From 6050eea2c47b312b043214454ecd81d17348f25f Mon Sep 17 00:00:00 2001 From: gakshita Date: Wed, 8 Jan 2025 15:13:30 +0530 Subject: [PATCH 1/9] fix: added delete sticky confirmation modal --- .../editor/sticky-editor/editor.tsx | 2 +- web/core/components/stickies/delete-modal.tsx | 44 ++++++++++++++++ .../components/stickies/sticky/inputs.tsx | 2 +- web/core/components/stickies/sticky/root.tsx | 51 ++++++++++++------- 4 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 web/core/components/stickies/delete-modal.tsx diff --git a/web/core/components/editor/sticky-editor/editor.tsx b/web/core/components/editor/sticky-editor/editor.tsx index a56fc119b91..3dad67477f7 100644 --- a/web/core/components/editor/sticky-editor/editor.tsx +++ b/web/core/components/editor/sticky-editor/editor.tsx @@ -29,7 +29,7 @@ interface StickyEditorWrapperProps uploadFile: (file: File) => Promise; parentClassName?: string; handleColorChange: (data: Partial) => Promise; - handleDelete: () => Promise; + handleDelete: () => void; } export const StickyEditor = React.forwardRef((props, ref) => { diff --git a/web/core/components/stickies/delete-modal.tsx b/web/core/components/stickies/delete-modal.tsx new file mode 100644 index 00000000000..3b0857b56ef --- /dev/null +++ b/web/core/components/stickies/delete-modal.tsx @@ -0,0 +1,44 @@ +"use client"; + +import { useState } from "react"; +import { observer } from "mobx-react"; +// ui +import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui"; + +interface IStickyDelete { + isOpen: boolean; + handleSubmit: () => void; + handleClose: () => void; +} + +export const StickyDeleteModal: React.FC = observer((props) => { + const { isOpen, handleClose, handleSubmit } = props; + // states + const [loader, setLoader] = useState(false); + + const formSubmit = async () => { + await handleSubmit(); + setLoader(true); + try { + } catch (error) { + setToast({ + type: TOAST_TYPE.ERROR, + title: "Warning!", + message: "Something went wrong please try again later.", + }); + } + + setLoader(false); + }; + + return ( + Are you sure you want to delete the sticky? } + /> + ); +}); diff --git a/web/core/components/stickies/sticky/inputs.tsx b/web/core/components/stickies/sticky/inputs.tsx index 3dd97c9c061..8e36fd0b8db 100644 --- a/web/core/components/stickies/sticky/inputs.tsx +++ b/web/core/components/stickies/sticky/inputs.tsx @@ -13,7 +13,7 @@ type TProps = { handleUpdate: DebouncedFunc<(payload: Partial) => Promise>; stickyId: string | undefined; handleChange: (data: Partial) => Promise; - handleDelete: () => Promise; + handleDelete: () => void; }; export const StickyInput = (props: TProps) => { const { stickyData, workspaceSlug, handleUpdate, stickyId, handleDelete, handleChange } = props; diff --git a/web/core/components/stickies/sticky/root.tsx b/web/core/components/stickies/sticky/root.tsx index a9b26ae5ffb..d7c8fe70ddc 100644 --- a/web/core/components/stickies/sticky/root.tsx +++ b/web/core/components/stickies/sticky/root.tsx @@ -1,4 +1,4 @@ -import { useCallback } from "react"; +import { useCallback, useState } from "react"; import { debounce } from "lodash"; import { observer } from "mobx-react"; import { Minimize2 } from "lucide-react"; @@ -6,6 +6,7 @@ import { TSticky } from "@plane/types"; import { cn } from "@plane/utils"; import { useSticky } from "@/hooks/use-stickies"; import { STICKY_COLORS } from "../../editor/sticky-editor/color-pallete"; +import { StickyDeleteModal } from "../delete-modal"; import { StickyInput } from "./inputs"; import { useStickyOperations } from "./use-operations"; @@ -17,6 +18,8 @@ type TProps = { }; export const StickyNote = observer((props: TProps) => { const { onClose, workspaceSlug, className = "", stickyId } = props; + //state + const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); // hooks const { stickyOperations } = useStickyOperations({ workspaceSlug }); const { stickies } = useSticky(); @@ -49,24 +52,34 @@ export const StickyNote = observer((props: TProps) => { }; return ( -
- {onClose && ( - - )} - {/* inputs */} - + setIsDeleteModalOpen(false)} /> -
+
+ {onClose && ( + + )} + {/* inputs */} + { + if (!stickyId) return; + setIsDeleteModalOpen(true); + }} + handleChange={handleChange} + /> +
+ ); }); From de9d05a534d9d3928392ccf8adc76a4b9c022366 Mon Sep 17 00:00:00 2001 From: gakshita Date: Wed, 8 Jan 2025 15:29:35 +0530 Subject: [PATCH 2/9] fix: prevented quick links reordering --- .../home/widgets/manage/widget-item.tsx | 83 +++++++++++-------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/web/core/components/home/widgets/manage/widget-item.tsx b/web/core/components/home/widgets/manage/widget-item.tsx index 453a96588c0..d7d8da2bd79 100644 --- a/web/core/components/home/widgets/manage/widget-item.tsx +++ b/web/core/components/home/widgets/manage/widget-item.tsx @@ -17,6 +17,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { createRoot } from "react-dom/client"; // ui +import { Lock } from "lucide-react"; import { InstructionType, TWidgetEntityData } from "@plane/types"; // components import { DropIndicator, ToggleSwitch } from "@plane/ui"; @@ -53,6 +54,46 @@ export const WidgetItem: FC = observer((props) => { if (!element) return; const initialData = { id: widget.key, isGroup: false }; + const dropTargets = dropTargetForElements({ + element, + canDrop: ({ source }) => { + if (widget.key === "quick_links") return false; + return getCanDrop(source, widget); + }, + onDragStart: () => { + setIsDragging(true); + }, + getData: ({ input, element }) => { + const blockedStates: InstructionType[] = ["make-child"]; + if (!isLastChild) { + blockedStates.push("reorder-below"); + } + + return attachInstruction(initialData, { + input, + element, + currentLevel: 1, + indentPerLevel: 0, + mode: isLastChild ? "last-in-group" : "standard", + block: blockedStates, + }); + }, + onDrag: ({ self, source, location }) => { + const instruction = getInstructionFromPayload(self, source, location); + setInstruction(instruction); + }, + onDragLeave: () => { + setInstruction(undefined); + }, + onDrop: ({ self, source, location }) => { + setInstruction(undefined); + handleDrop(self, source, location); + }, + }); + + if (widget.key === "quick_links") { + return dropTargets; + } return combine( draggable({ element, @@ -76,46 +117,14 @@ export const WidgetItem: FC = observer((props) => { }); }, }), - dropTargetForElements({ - element, - canDrop: ({ source }) => getCanDrop(source, widget), - onDragStart: () => { - setIsDragging(true); - }, - getData: ({ input, element }) => { - const blockedStates: InstructionType[] = ["make-child"]; - if (!isLastChild) { - blockedStates.push("reorder-below"); - } - - return attachInstruction(initialData, { - input, - element, - currentLevel: 1, - indentPerLevel: 0, - mode: isLastChild ? "last-in-group" : "standard", - block: blockedStates, - }); - }, - onDrag: ({ self, source, location }) => { - const instruction = getInstructionFromPayload(self, source, location); - setInstruction(instruction); - }, - onDragLeave: () => { - setInstruction(undefined); - }, - onDrop: ({ self, source, location }) => { - setInstruction(undefined); - handleDrop(self, source, location); - }, - }) + dropTargets ); // eslint-disable-next-line react-hooks/exhaustive-deps }, [elementRef?.current, isDragging, isLastChild, widget.key]); return (
- + {widget.key !== "quick_links" && }{" "}
= observer((props) => { )} >
- + {widget.key === "quick_links" ? ( + + ) : ( + + )}
{widget.key.replaceAll("_", " ")}
Date: Wed, 8 Jan 2025 16:14:47 +0530 Subject: [PATCH 3/9] fix: quick links css --- .../components/core/content-overflow-HOC.tsx | 111 ++++++++++++++++++ .../components/home/widgets/links/links.tsx | 64 +++------- .../components/home/widgets/links/root.tsx | 20 +++- .../home/widgets/loaders/quick-links.tsx | 2 +- 4 files changed, 145 insertions(+), 52 deletions(-) create mode 100644 web/core/components/core/content-overflow-HOC.tsx diff --git a/web/core/components/core/content-overflow-HOC.tsx b/web/core/components/core/content-overflow-HOC.tsx new file mode 100644 index 00000000000..fc3fcf455d9 --- /dev/null +++ b/web/core/components/core/content-overflow-HOC.tsx @@ -0,0 +1,111 @@ +import { ReactNode, useEffect, useRef, useState } from "react"; +import { observer } from "mobx-react"; +import { cn } from "@plane/utils"; + +interface IContentOverflowWrapper { + children: ReactNode; + maxHeight?: number; + gradientColor?: string; + buttonClassName?: string; + containerClassName?: string; + fallback?: ReactNode; +} + +export const ContentOverflowWrapper = observer((props: IContentOverflowWrapper) => { + const { + children, + maxHeight = 625, + buttonClassName = "text-sm font-medium text-custom-primary-100", + containerClassName, + fallback = null, + } = props; + + // states + const [containerHeight, setContainerHeight] = useState(0); + const [showAll, setShowAll] = useState(false); + + // refs + const contentRef = useRef(null); + + useEffect(() => { + if (!contentRef?.current) return; + + const updateHeight = () => { + if (contentRef.current) { + const height = contentRef.current.getBoundingClientRect().height; + setContainerHeight(height); + } + }; + + // Initial height measurement + updateHeight(); + + // Create ResizeObserver for size changes + const resizeObserver = new ResizeObserver(updateHeight); + resizeObserver.observe(contentRef.current); + + // Create MutationObserver for content changes + const mutationObserver = new MutationObserver((mutations) => { + const shouldUpdate = mutations.some( + (mutation) => + mutation.type === "childList" || + (mutation.type === "attributes" && (mutation.attributeName === "style" || mutation.attributeName === "class")) + ); + + if (shouldUpdate) { + updateHeight(); + } + }); + + mutationObserver.observe(contentRef.current, { + childList: true, + subtree: true, + attributes: true, + attributeFilter: ["style", "class"], + }); + + return () => { + resizeObserver.disconnect(); + mutationObserver.disconnect(); + }; + }, [contentRef?.current]); + + if (!children) return fallback; + + return ( +
+
{children}
+ + {containerHeight > maxHeight && ( +
+ +
+ )} +
+ ); +}); diff --git a/web/core/components/home/widgets/links/links.tsx b/web/core/components/home/widgets/links/links.tsx index 194b1dfc121..5c35cca5498 100644 --- a/web/core/components/home/widgets/links/links.tsx +++ b/web/core/components/home/widgets/links/links.tsx @@ -1,9 +1,9 @@ -import { FC, useEffect, useState } from "react"; +import { FC } from "react"; import { observer } from "mobx-react"; // computed +import { ContentOverflowWrapper } from "@/components/core/content-overflow-HOC"; import { useHome } from "@/hooks/store/use-home"; import { EWidgetKeys, WidgetLoader } from "../loaders"; -import { AddLink } from "./action"; import { ProjectLinkDetail } from "./link-detail"; import { TLinkOperations } from "./use-links"; @@ -17,61 +17,29 @@ export type TProjectLinkList = { export const ProjectLinkList: FC = observer((props) => { // props const { linkOperations, workspaceSlug } = props; - // states - const [columnCount, setColumnCount] = useState(4); - const [showAll, setShowAll] = useState(false); // hooks const { - quickLinks: { getLinksByWorkspaceId, toggleLinkModal }, + quickLinks: { getLinksByWorkspaceId }, } = useHome(); const links = getLinksByWorkspaceId(workspaceSlug); - useEffect(() => { - const updateColumnCount = () => { - if (window.matchMedia("(min-width: 1024px)").matches) { - setColumnCount(4); // lg screens - } else if (window.matchMedia("(min-width: 768px)").matches) { - setColumnCount(3); // md screens - } else if (window.matchMedia("(min-width: 640px)").matches) { - setColumnCount(2); // sm screens - } else { - setColumnCount(1); // mobile - } - }; - - // Initial check - updateColumnCount(); - - // Add event listener for window resize - window.addEventListener("resize", updateColumnCount); - - // Cleanup - return () => window.removeEventListener("resize", updateColumnCount); - }, []); - if (links === undefined) return ; return ( -
-
- {links && - links.length > 0 && - (showAll ? links : links.slice(0, 2 * columnCount - 1)).map((linkId) => ( - - ))} - - {/* Add new link */} - toggleLinkModal(true)} /> + } + buttonClassName="bg-custom-background-90/20" + > +
+
+ {links && + links.length > 0 && + links.map((linkId) => )} +
- {links.length > 2 * columnCount - 1 && ( - - )} -
+ ); }); diff --git a/web/core/components/home/widgets/links/root.tsx b/web/core/components/home/widgets/links/root.tsx index f7b6f007cc2..504a7cf1680 100644 --- a/web/core/components/home/widgets/links/root.tsx +++ b/web/core/components/home/widgets/links/root.tsx @@ -1,5 +1,6 @@ import { observer } from "mobx-react"; import useSWR from "swr"; +import { Plus } from "lucide-react"; import { THomeWidgetProps } from "@plane/types"; import { useHome } from "@/hooks/store/use-home"; import { LinkCreateUpdateModal } from "./create-update-link-modal"; @@ -31,9 +32,22 @@ export const DashboardQuickLinks = observer((props: THomeWidgetProps) => { preloadedData={linkData} setLinkData={setLinkData} /> -
- {/* rendering links */} - +
+
+
Quick links
+ +
+
+ {/* rendering links */} + +
); diff --git a/web/core/components/home/widgets/loaders/quick-links.tsx b/web/core/components/home/widgets/loaders/quick-links.tsx index e4b8deafcb8..3037bf39c72 100644 --- a/web/core/components/home/widgets/loaders/quick-links.tsx +++ b/web/core/components/home/widgets/loaders/quick-links.tsx @@ -5,7 +5,7 @@ import range from "lodash/range"; import { Loader } from "@plane/ui"; export const QuickLinksWidgetLoader = () => ( - + {range(4).map((index) => ( ))} From f6dfabb4b8bfef8ed4ac82275845e3e3aa24114b Mon Sep 17 00:00:00 2001 From: gakshita Date: Wed, 8 Jan 2025 16:23:00 +0530 Subject: [PATCH 4/9] fix: minor css --- web/core/components/home/widgets/links/links.tsx | 2 +- .../components/home/widgets/loaders/recent-activity.tsx | 2 +- web/core/components/home/widgets/recents/index.tsx | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/web/core/components/home/widgets/links/links.tsx b/web/core/components/home/widgets/links/links.tsx index 5c35cca5498..c855b1419ac 100644 --- a/web/core/components/home/widgets/links/links.tsx +++ b/web/core/components/home/widgets/links/links.tsx @@ -34,7 +34,7 @@ export const ProjectLinkList: FC = observer((props) => { buttonClassName="bg-custom-background-90/20" >
-
+
{links && links.length > 0 && links.map((linkId) => )} diff --git a/web/core/components/home/widgets/loaders/recent-activity.tsx b/web/core/components/home/widgets/loaders/recent-activity.tsx index 2f78db64a0a..741ef29ebf1 100644 --- a/web/core/components/home/widgets/loaders/recent-activity.tsx +++ b/web/core/components/home/widgets/loaders/recent-activity.tsx @@ -6,7 +6,7 @@ import { Loader } from "@plane/ui"; export const RecentActivityWidgetLoader = () => ( - {range(7).map((index) => ( + {range(5).map((index) => (
diff --git a/web/core/components/home/widgets/recents/index.tsx b/web/core/components/home/widgets/recents/index.tsx index 8eaecca7708..dfc550f1761 100644 --- a/web/core/components/home/widgets/recents/index.tsx +++ b/web/core/components/home/widgets/recents/index.tsx @@ -72,20 +72,20 @@ export const RecentActivityWidget: React.FC = observer((props)
Recents
-
+
); return ( -
+
Recents
-
+
{isLoading && } {!isLoading && recents?.length > 0 && From 96795fc6d4ffdb5fb02927a050b5a74f341b20f3 Mon Sep 17 00:00:00 2001 From: gakshita Date: Wed, 8 Jan 2025 17:47:50 +0530 Subject: [PATCH 5/9] fix: empty states --- .../home/widgets/empty-states/issues.tsx | 21 --------------- .../home/widgets/empty-states/links.tsx | 27 +++++++++++++++++++ .../home/widgets/empty-states/recents.tsx | 15 +++++++++++ .../components/home/widgets/links/links.tsx | 4 ++- .../components/home/widgets/recents/index.tsx | 8 +++--- web/core/components/stickies/empty.tsx | 21 +++++++-------- 6 files changed, 58 insertions(+), 38 deletions(-) delete mode 100644 web/core/components/home/widgets/empty-states/issues.tsx create mode 100644 web/core/components/home/widgets/empty-states/links.tsx create mode 100644 web/core/components/home/widgets/empty-states/recents.tsx diff --git a/web/core/components/home/widgets/empty-states/issues.tsx b/web/core/components/home/widgets/empty-states/issues.tsx deleted file mode 100644 index fc4548d67ab..00000000000 --- a/web/core/components/home/widgets/empty-states/issues.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import Image from "next/image"; -import { useTheme } from "next-themes"; -import UpcomingIssuesDark from "@/public/empty-state/dashboard/dark/upcoming-issues.svg"; -import UpcomingIssuesLight from "@/public/empty-state/dashboard/light/upcoming-issues.svg"; - -export const IssuesEmptyState = () => { - // next-themes - const { resolvedTheme } = useTheme(); - - const image = resolvedTheme === "dark" ? UpcomingIssuesDark : UpcomingIssuesLight; - - // TODO: update empty state logic to use a general component - return ( -
-
- Assigned issues -
-

No activity to display

-
- ); -}; diff --git a/web/core/components/home/widgets/empty-states/links.tsx b/web/core/components/home/widgets/empty-states/links.tsx new file mode 100644 index 00000000000..00e91274ca3 --- /dev/null +++ b/web/core/components/home/widgets/empty-states/links.tsx @@ -0,0 +1,27 @@ +import { Link2, Plus } from "lucide-react"; +import { Button } from "@plane/ui"; + +type TProps = { + handleCreate: () => void; +}; +export const LinksEmptyState = (props: TProps) => { + const { handleCreate } = props; + return ( +
+
+
+ +
+
No quick links yet
+
+ Add any links you need for quick access to your work.{" "} +
+ +
+
+ ); +}; diff --git a/web/core/components/home/widgets/empty-states/recents.tsx b/web/core/components/home/widgets/empty-states/recents.tsx new file mode 100644 index 00000000000..5306584fd05 --- /dev/null +++ b/web/core/components/home/widgets/empty-states/recents.tsx @@ -0,0 +1,15 @@ +import { History } from "lucide-react"; + +export const RecentsEmptyState = () => ( +
+
+
+ +
+
No recent items yet
+
You don’t have any recent items yet.
+
+
+); diff --git a/web/core/components/home/widgets/links/links.tsx b/web/core/components/home/widgets/links/links.tsx index c855b1419ac..85feab84040 100644 --- a/web/core/components/home/widgets/links/links.tsx +++ b/web/core/components/home/widgets/links/links.tsx @@ -3,6 +3,7 @@ import { observer } from "mobx-react"; // computed import { ContentOverflowWrapper } from "@/components/core/content-overflow-HOC"; import { useHome } from "@/hooks/store/use-home"; +import { LinksEmptyState } from "../empty-states/links"; import { EWidgetKeys, WidgetLoader } from "../loaders"; import { ProjectLinkDetail } from "./link-detail"; import { TLinkOperations } from "./use-links"; @@ -19,13 +20,14 @@ export const ProjectLinkList: FC = observer((props) => { const { linkOperations, workspaceSlug } = props; // hooks const { - quickLinks: { getLinksByWorkspaceId }, + quickLinks: { getLinksByWorkspaceId, toggleLinkModal }, } = useHome(); const links = getLinksByWorkspaceId(workspaceSlug); if (links === undefined) return ; + if (links.length === 0) return toggleLinkModal(true)} />; return ( = observer((props) if (!isLoading && recents?.length === 0) return (
-
+
Recents
-
- +
+
); diff --git a/web/core/components/stickies/empty.tsx b/web/core/components/stickies/empty.tsx index 4413ab570f9..4a407a96957 100644 --- a/web/core/components/stickies/empty.tsx +++ b/web/core/components/stickies/empty.tsx @@ -1,4 +1,5 @@ -import { Plus, StickyNote as StickyIcon, X } from "lucide-react"; +import { Plus, StickyNote as StickyIcon } from "lucide-react"; +import { Button } from "@plane/ui"; type TProps = { handleCreate: () => void; @@ -7,22 +8,18 @@ type TProps = { export const EmptyState = (props: TProps) => { const { handleCreate, creatingSticky } = props; return ( -
+
- +
-
No stickies yet
-
+
No stickies yet
+
All your stickies in this workspace will appear here.
- +
); From 57ac82bbbf71396e7b60fc13454dd59aae65dd21 Mon Sep 17 00:00:00 2001 From: sangeethailango Date: Wed, 8 Jan 2025 18:16:45 +0530 Subject: [PATCH 6/9] Filter quick_tutorial and new_at_plane --- apiserver/plane/app/views/workspace/preference.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apiserver/plane/app/views/workspace/preference.py b/apiserver/plane/app/views/workspace/preference.py index 4d6d9456224..e3da9184da2 100644 --- a/apiserver/plane/app/views/workspace/preference.py +++ b/apiserver/plane/app/views/workspace/preference.py @@ -31,7 +31,11 @@ def get(self, request, slug): create_preference_keys = [] - keys = [key for key, _ in WorkspaceHomePreference.HomeWidgetKeys.choices] + keys = [ + key + for key, _ in WorkspaceHomePreference.HomeWidgetKeys.choices + if key not in ["quick_tutorial", "new_at_plane"] + ] sort_order_counter = 1 From 5bafee27a448ea9e0d3edba383766989e6c01ec5 Mon Sep 17 00:00:00 2001 From: gakshita Date: Wed, 8 Jan 2025 19:21:03 +0530 Subject: [PATCH 7/9] fix: stickies search backend change --- apiserver/plane/app/views/workspace/sticky.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apiserver/plane/app/views/workspace/sticky.py b/apiserver/plane/app/views/workspace/sticky.py index d0b78aaf4a6..552d59f9259 100644 --- a/apiserver/plane/app/views/workspace/sticky.py +++ b/apiserver/plane/app/views/workspace/sticky.py @@ -39,13 +39,18 @@ def create(self, request, slug): allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE" ) def list(self, request, slug): + query = request.query_params.get("query", False) + stickies = self.get_queryset() + if query: + stickies = stickies.filter(name__icontains=query) + return self.paginate( request=request, - queryset=(self.get_queryset()), + queryset=(stickies), on_results=lambda stickies: StickySerializer(stickies, many=True).data, default_per_page=20, ) - + @allow_permission(allowed_roles=[], creator=True, model=Sticky, level="WORKSPACE") def partial_update(self, request, *args, **kwargs): return super().partial_update(request, *args, **kwargs) From 831662f43ce3801075da6b5dfaade514edf28851 Mon Sep 17 00:00:00 2001 From: gakshita Date: Wed, 8 Jan 2025 20:18:15 +0530 Subject: [PATCH 8/9] fix: stickies editor enhanced --- .../home/widgets/manage/widget-item.tsx | 83 ++++++++----------- .../components/stickies/stickies-layout.tsx | 67 ++------------- 2 files changed, 44 insertions(+), 106 deletions(-) diff --git a/web/core/components/home/widgets/manage/widget-item.tsx b/web/core/components/home/widgets/manage/widget-item.tsx index d7d8da2bd79..453a96588c0 100644 --- a/web/core/components/home/widgets/manage/widget-item.tsx +++ b/web/core/components/home/widgets/manage/widget-item.tsx @@ -17,7 +17,6 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { createRoot } from "react-dom/client"; // ui -import { Lock } from "lucide-react"; import { InstructionType, TWidgetEntityData } from "@plane/types"; // components import { DropIndicator, ToggleSwitch } from "@plane/ui"; @@ -54,46 +53,6 @@ export const WidgetItem: FC = observer((props) => { if (!element) return; const initialData = { id: widget.key, isGroup: false }; - const dropTargets = dropTargetForElements({ - element, - canDrop: ({ source }) => { - if (widget.key === "quick_links") return false; - return getCanDrop(source, widget); - }, - onDragStart: () => { - setIsDragging(true); - }, - getData: ({ input, element }) => { - const blockedStates: InstructionType[] = ["make-child"]; - if (!isLastChild) { - blockedStates.push("reorder-below"); - } - - return attachInstruction(initialData, { - input, - element, - currentLevel: 1, - indentPerLevel: 0, - mode: isLastChild ? "last-in-group" : "standard", - block: blockedStates, - }); - }, - onDrag: ({ self, source, location }) => { - const instruction = getInstructionFromPayload(self, source, location); - setInstruction(instruction); - }, - onDragLeave: () => { - setInstruction(undefined); - }, - onDrop: ({ self, source, location }) => { - setInstruction(undefined); - handleDrop(self, source, location); - }, - }); - - if (widget.key === "quick_links") { - return dropTargets; - } return combine( draggable({ element, @@ -117,14 +76,46 @@ export const WidgetItem: FC = observer((props) => { }); }, }), - dropTargets + dropTargetForElements({ + element, + canDrop: ({ source }) => getCanDrop(source, widget), + onDragStart: () => { + setIsDragging(true); + }, + getData: ({ input, element }) => { + const blockedStates: InstructionType[] = ["make-child"]; + if (!isLastChild) { + blockedStates.push("reorder-below"); + } + + return attachInstruction(initialData, { + input, + element, + currentLevel: 1, + indentPerLevel: 0, + mode: isLastChild ? "last-in-group" : "standard", + block: blockedStates, + }); + }, + onDrag: ({ self, source, location }) => { + const instruction = getInstructionFromPayload(self, source, location); + setInstruction(instruction); + }, + onDragLeave: () => { + setInstruction(undefined); + }, + onDrop: ({ self, source, location }) => { + setInstruction(undefined); + handleDrop(self, source, location); + }, + }) ); // eslint-disable-next-line react-hooks/exhaustive-deps }, [elementRef?.current, isDragging, isLastChild, widget.key]); return (
- {widget.key !== "quick_links" && }{" "} +
= observer((props) => { )} >
- {widget.key === "quick_links" ? ( - - ) : ( - - )} +
{widget.key.replaceAll("_", " ")}
{ const masonryRef = useRef(null); const containerRef = useRef(null); // states - const [containerHeight, setContainerHeight] = useState(0); - const [showAllStickies, setShowAllStickies] = useState(false); const [intersectionElement, setIntersectionElement] = useState(null); // router const { workspaceSlug } = useParams(); @@ -59,44 +58,6 @@ export const StickyAll = observer((props: TProps) => { } }, [fetchingWorkspaceStickies, workspaceStickies, toggleShowNewSticky]); - // Update this useEffect to correctly track height - useEffect(() => { - if (!masonryRef?.current) return; - - const updateHeight = () => { - if (masonryRef.current) { - const height = masonryRef.current.getBoundingClientRect().height; - setContainerHeight(parseInt(height.toString())); - } - }; - - // Initial height measurement - updateHeight(); - - // Create ResizeObserver - const resizeObserver = new ResizeObserver(() => { - updateHeight(); - }); - - resizeObserver.observe(masonryRef.current); - - // Also update height when Masonry content changes - const mutationObserver = new MutationObserver(() => { - updateHeight(); - }); - - mutationObserver.observe(masonryRef.current, { - childList: true, - subtree: true, - attributes: true, - }); - - return () => { - resizeObserver.disconnect(); - mutationObserver.disconnect(); - }; - }, [masonryRef?.current]); - useIntersectionObserver(containerRef, fetchingWorkspaceStickies ? null : intersectionElement, incrementPage, "20%"); if (fetchingWorkspaceStickies && workspaceStickies.length === 0) { @@ -145,26 +106,16 @@ export const StickyAll = observer((props: TProps) => { ); return ( -
-
+
+ } + buttonClassName="bg-custom-background-90/20" + > {/* @ts-expect-error type mismatch here */} {childElements} -
- {containerHeight > 632.9 && ( -
- -
- )} +
); }); From 756fe858a0b67817e5b8410cd42af7848ce88e2d Mon Sep 17 00:00:00 2001 From: gakshita Date: Thu, 9 Jan 2025 14:05:13 +0530 Subject: [PATCH 9/9] fix: sticky delete function --- web/core/components/stickies/delete-modal.tsx | 8 ++++---- web/core/components/stickies/stickies-layout.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/web/core/components/stickies/delete-modal.tsx b/web/core/components/stickies/delete-modal.tsx index 3b0857b56ef..2d26a53dedc 100644 --- a/web/core/components/stickies/delete-modal.tsx +++ b/web/core/components/stickies/delete-modal.tsx @@ -17,18 +17,18 @@ export const StickyDeleteModal: React.FC = observer((props) => { const [loader, setLoader] = useState(false); const formSubmit = async () => { - await handleSubmit(); - setLoader(true); try { + setLoader(true); + await handleSubmit(); } catch (error) { setToast({ type: TOAST_TYPE.ERROR, title: "Warning!", message: "Something went wrong please try again later.", }); + } finally { + setLoader(false); } - - setLoader(false); }; return ( diff --git a/web/core/components/stickies/stickies-layout.tsx b/web/core/components/stickies/stickies-layout.tsx index 644e5a984f7..5cd2f83efcd 100644 --- a/web/core/components/stickies/stickies-layout.tsx +++ b/web/core/components/stickies/stickies-layout.tsx @@ -7,11 +7,11 @@ import { Loader } from "@plane/ui"; import { cn } from "@plane/utils"; import { useIntersectionObserver } from "@/hooks/use-intersection-observer"; import { useSticky } from "@/hooks/use-stickies"; +import { ContentOverflowWrapper } from "../core/content-overflow-HOC"; import { STICKY_COLORS } from "../editor/sticky-editor/color-pallete"; import { EmptyState } from "./empty"; import { StickyNote } from "./sticky"; import { useStickyOperations } from "./sticky/use-operations"; -import { ContentOverflowWrapper } from "../core/content-overflow-HOC"; const PER_PAGE = 10;