From d8ab3e00873fd97069c1513e8832d7997b04938e Mon Sep 17 00:00:00 2001 From: rahulramesha <71900764+rahulramesha@users.noreply.github.com> Date: Thu, 9 May 2024 15:51:49 +0530 Subject: [PATCH 1/6] [WEB-1139] chore: Calendar pragmatic dnd (#4410) * replace Pragmatic DND for calendar * remove unnecessary check --- .../calendar/base-calendar-root.tsx | 103 +++++----- .../issue-layouts/calendar/calendar.tsx | 30 ++- .../issue-layouts/calendar/day-tile.tsx | 112 ++++++---- .../calendar/issue-block-root.tsx | 41 +++- .../issue-layouts/calendar/issue-block.tsx | 192 +++++++++--------- .../issue-layouts/calendar/issue-blocks.tsx | 67 +++--- .../issues/issue-layouts/calendar/utils.ts | 37 +--- .../issue-layouts/calendar/week-days.tsx | 7 + web/hooks/use-draggable-portal.ts | 31 --- 9 files changed, 334 insertions(+), 286 deletions(-) delete mode 100644 web/hooks/use-draggable-portal.ts diff --git a/web/components/issues/issue-layouts/calendar/base-calendar-root.tsx b/web/components/issues/issue-layouts/calendar/base-calendar-root.tsx index ad9903747c..946ae0ed49 100644 --- a/web/components/issues/issue-layouts/calendar/base-calendar-root.tsx +++ b/web/components/issues/issue-layouts/calendar/base-calendar-root.tsx @@ -1,6 +1,5 @@ import { FC } from "react"; -import { DragDropContext, DropResult } from "@hello-pangea/dnd"; -import { observer } from "mobx-react"; +import { observer } from "mobx-react-lite"; import { useRouter } from "next/router"; import { TGroupedIssues } from "@plane/types"; // components @@ -51,67 +50,59 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => { const groupedIssueIds = (issues.groupedIssueIds ?? {}) as TGroupedIssues; - const onDragEnd = async (result: DropResult) => { - if (!result) return; + const handleDragAndDrop = async ( + issueId: string | undefined, + sourceDate: string | undefined, + destinationDate: string | undefined + ) => { + if (!issueId || !destinationDate || !sourceDate) return; - // return if not dropped on the correct place - if (!result.destination) return; - - // return if dropped on the same date - if (result.destination.droppableId === result.source.droppableId) return; - - if (handleDragDrop) { - await handleDragDrop( - result.source, - result.destination, - workspaceSlug?.toString(), - projectId?.toString(), - issueMap, - groupedIssueIds, - updateIssue - ).catch((err) => { - setToast({ - title: "Error!", - type: TOAST_TYPE.ERROR, - message: err?.detail ?? "Failed to perform this action", - }); + await handleDragDrop( + issueId, + sourceDate, + destinationDate, + workspaceSlug?.toString(), + projectId?.toString(), + updateIssue + ).catch((err) => { + setToast({ + title: "Error!", + type: TOAST_TYPE.ERROR, + message: err?.detail ?? "Failed to perform this action", }); - } + }); }; return ( <>
- - ( - removeIssue(issue.project_id, issue.id)} - handleUpdate={async (data) => updateIssue && updateIssue(issue.project_id, issue.id, data)} - handleRemoveFromView={async () => - removeIssueFromView && removeIssueFromView(issue.project_id, issue.id) - } - handleArchive={async () => archiveIssue && archiveIssue(issue.project_id, issue.id)} - handleRestore={async () => restoreIssue && restoreIssue(issue.project_id, issue.id)} - readOnly={!isEditingAllowed || isCompletedCycle} - placements={placement} - /> - )} - addIssuesToView={addIssuesToView} - quickAddCallback={issues.quickAddIssue} - viewId={viewId} - readOnly={!isEditingAllowed || isCompletedCycle} - updateFilters={updateFilters} - /> - + ( + removeIssue(issue.project_id, issue.id)} + handleUpdate={async (data) => updateIssue && updateIssue(issue.project_id, issue.id, data)} + handleRemoveFromView={async () => removeIssueFromView && removeIssueFromView(issue.project_id, issue.id)} + handleArchive={async () => archiveIssue && archiveIssue(issue.project_id, issue.id)} + handleRestore={async () => restoreIssue && restoreIssue(issue.project_id, issue.id)} + readOnly={!isEditingAllowed || isCompletedCycle} + placements={placement} + /> + )} + addIssuesToView={addIssuesToView} + quickAddCallback={issues.quickAddIssue} + viewId={viewId} + readOnly={!isEditingAllowed || isCompletedCycle} + updateFilters={updateFilters} + handleDragAndDrop={handleDragAndDrop} + />
); diff --git a/web/components/issues/issue-layouts/calendar/calendar.tsx b/web/components/issues/issue-layouts/calendar/calendar.tsx index c4110bc13f..a120c78d99 100644 --- a/web/components/issues/issue-layouts/calendar/calendar.tsx +++ b/web/components/issues/issue-layouts/calendar/calendar.tsx @@ -1,4 +1,6 @@ -import { useState } from "react"; +import { useEffect, useRef, useState } from "react"; +import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; +import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element"; import { observer } from "mobx-react-lite"; // types import type { @@ -40,6 +42,11 @@ type Props = { layout: "month" | "week" | undefined; showWeekends: boolean; quickActions: TRenderQuickActions; + handleDragAndDrop: ( + issueId: string | undefined, + sourceDate: string | undefined, + destinationDate: string | undefined + ) => Promise; quickAddCallback?: ( workspaceSlug: string, projectId: string, @@ -63,6 +70,7 @@ export const CalendarChart: React.FC = observer((props) => { groupedIssueIds, layout, showWeekends, + handleDragAndDrop, quickActions, quickAddCallback, addIssuesToView, @@ -72,6 +80,8 @@ export const CalendarChart: React.FC = observer((props) => { } = props; // states const [selectedDate, setSelectedDate] = useState(new Date()); + //refs + const scrollableContainerRef = useRef(null); // store hooks const { issues: { viewFlags }, @@ -91,6 +101,19 @@ export const CalendarChart: React.FC = observer((props) => { const formattedDatePayload = renderFormattedPayloadDate(selectedDate) ?? undefined; + // Enable Auto Scroll for calendar + useEffect(() => { + const element = scrollableContainerRef.current; + + if (!element) return; + + return combine( + autoScrollForElements({ + element, + }) + ); + }, [scrollableContainerRef?.current]); + if (!calendarPayload || !formattedDatePayload) return (
@@ -112,6 +135,7 @@ export const CalendarChart: React.FC = observer((props) => { className={cn("flex w-full flex-col overflow-y-auto md:h-full", { "vertical-scrollbar scrollbar-lg": windowWidth > 768, })} + ref={scrollableContainerRef} >
@@ -123,6 +147,7 @@ export const CalendarChart: React.FC = observer((props) => { selectedDate={selectedDate} setSelectedDate={setSelectedDate} issuesFilterStore={issuesFilterStore} + handleDragAndDrop={handleDragAndDrop} key={weekIndex} week={week} issues={issues} @@ -143,6 +168,7 @@ export const CalendarChart: React.FC = observer((props) => { selectedDate={selectedDate} setSelectedDate={setSelectedDate} issuesFilterStore={issuesFilterStore} + handleDragAndDrop={handleDragAndDrop} week={issueCalendarView.allDaysOfActiveWeek} issues={issues} groupedIssueIds={groupedIssueIds} @@ -175,6 +201,8 @@ export const CalendarChart: React.FC = observer((props) => { addIssuesToView={addIssuesToView} viewId={viewId} readOnly={readOnly} + isMonthLayout={false} + showAllIssues isDragDisabled isMobileView /> diff --git a/web/components/issues/issue-layouts/calendar/day-tile.tsx b/web/components/issues/issue-layouts/calendar/day-tile.tsx index 8f162869a2..7dfcfdcac9 100644 --- a/web/components/issues/issue-layouts/calendar/day-tile.tsx +++ b/web/components/issues/issue-layouts/calendar/day-tile.tsx @@ -1,10 +1,13 @@ -import { Droppable } from "@hello-pangea/dnd"; +import { useEffect, useRef, useState } from "react"; +import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; +import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { observer } from "mobx-react-lite"; // types import { TGroupedIssues, TIssue, TIssueMap } from "@plane/types"; // components import { CalendarIssueBlocks, ICalendarDate } from "@/components/issues"; -// constants +import { highlightIssueOnDrop } from "@/components/issues/issue-layouts/utils"; +// helpers import { MONTHS_LIST } from "@/constants/calendar"; // helpers import { cn } from "@/helpers/common.helper"; @@ -24,6 +27,11 @@ type Props = { quickActions: TRenderQuickActions; enableQuickIssueCreate?: boolean; disableIssueCreation?: boolean; + handleDragAndDrop: ( + issueId: string | undefined, + sourceDate: string | undefined, + destinationDate: string | undefined + ) => Promise; quickAddCallback?: ( workspaceSlug: string, projectId: string, @@ -51,12 +59,46 @@ export const CalendarDayTile: React.FC = observer((props) => { viewId, readOnly = false, selectedDate, + handleDragAndDrop, setSelectedDate, } = props; + const [isDraggingOver, setIsDraggingOver] = useState(false); + const [showAllIssues, setShowAllIssues] = useState(false); + const calendarLayout = issuesFilterStore?.issueFilters?.displayFilters?.calendar?.layout ?? "month"; const formattedDatePayload = renderFormattedPayloadDate(date.date); + + const dayTileRef = useRef(null); + + useEffect(() => { + const element = dayTileRef.current; + + if (!element) return; + + return combine( + dropTargetForElements({ + element, + getData: () => ({ date: formattedDatePayload }), + onDragEnter: () => { + setIsDraggingOver(true); + }, + onDragLeave: () => { + setIsDraggingOver(false); + }, + onDrop: ({ source, self }) => { + setIsDraggingOver(false); + const sourceData = source?.data as { id: string; date: string } | undefined; + const destinationData = self?.data as { date: string } | undefined; + handleDragAndDrop(sourceData?.id, sourceData?.date, destinationData?.date); + setShowAllIssues(true); + highlightIssueOnDrop(source?.element?.id, false); + }, + }) + ); + }, [dayTileRef?.current, formattedDatePayload]); + if (!formattedDatePayload) return null; const issueIdList = groupedIssueIds ? groupedIssueIds[formattedDatePayload] : null; @@ -65,13 +107,19 @@ export const CalendarDayTile: React.FC = observer((props) => { const isToday = date.date.toDateString() === new Date().toDateString(); const isSelectedDate = date.date.toDateString() == selectedDate.toDateString(); + const isWeekend = date.date.getDay() === 0 || date.date.getDay() === 6; + const isMonthLayout = calendarLayout === "month"; + + const normalBackground = isWeekend ? "bg-custom-background-90" : "bg-custom-background-100"; + const draggingOverBackground = isWeekend ? "bg-custom-background-80" : "bg-custom-background-90"; + return ( <> -
+
{/* header */}
= observer((props) => {
{/* content */} -
- - {(provided, snapshot) => ( -
- - {provided.placeholder} -
- )} -
+
+
+ +
{/* Mobile view content */}
setSelectedDate(date.date)} className={cn( - "mx-auto flex h-full w-full cursor-pointer flex-col items-center justify-start py-2.5 text-sm font-medium md:hidden", + "text-sm py-2.5 h-full w-full font-medium mx-auto flex flex-col justify-start items-center md:hidden cursor-pointer opacity-80", { - "bg-custom-background-100": date.date.getDay() !== 0 && date.date.getDay() !== 6, + "bg-custom-background-100": !isWeekend, } )} > diff --git a/web/components/issues/issue-layouts/calendar/issue-block-root.tsx b/web/components/issues/issue-layouts/calendar/issue-block-root.tsx index efedcf50ba..df0d03845a 100644 --- a/web/components/issues/issue-layouts/calendar/issue-block-root.tsx +++ b/web/components/issues/issue-layouts/calendar/issue-block-root.tsx @@ -1,23 +1,54 @@ -import React from "react"; +import React, { useEffect, useRef, useState } from "react"; +import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; +import { draggable } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; // components import { TIssueMap } from "@plane/types"; import { CalendarIssueBlock } from "@/components/issues"; +import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { TRenderQuickActions } from "../list/list-view-types"; +import { HIGHLIGHT_CLASS } from "../utils"; // types type Props = { issues: TIssueMap | undefined; issueId: string; quickActions: TRenderQuickActions; - isDragging?: boolean; + isDragDisabled: boolean; }; export const CalendarIssueBlockRoot: React.FC = (props) => { - const { issues, issueId, quickActions, isDragging } = props; + const { issues, issueId, quickActions, isDragDisabled } = props; - if (!issues?.[issueId]) return null; + const issueRef = useRef(null); + const [isDragging, setIsDragging] = useState(false); const issue = issues?.[issueId]; - return ; + useEffect(() => { + const element = issueRef.current; + + if (!element) return; + + return combine( + draggable({ + element, + canDrag: () => !isDragDisabled, + getInitialData: () => ({ id: issue?.id, date: issue?.target_date }), + onDragStart: () => { + setIsDragging(true); + }, + onDrop: () => { + setIsDragging(false); + }, + }) + ); + }, [issueRef?.current, issue]); + + useOutsideClickDetector(issueRef, () => { + issueRef?.current?.classList?.remove(HIGHLIGHT_CLASS); + }); + + if (!issue) return null; + + return ; }; diff --git a/web/components/issues/issue-layouts/calendar/issue-block.tsx b/web/components/issues/issue-layouts/calendar/issue-block.tsx index 01d7615f3a..b9cf59d0a4 100644 --- a/web/components/issues/issue-layouts/calendar/issue-block.tsx +++ b/web/components/issues/issue-layouts/calendar/issue-block.tsx @@ -1,4 +1,5 @@ -import { useState, useRef } from "react"; +/* eslint-disable react/display-name */ +import { useState, useRef, forwardRef } from "react"; import { observer } from "mobx-react"; import { MoreHorizontal } from "lucide-react"; import { TIssue } from "@plane/types"; @@ -19,106 +20,111 @@ type Props = { isDragging?: boolean; }; -export const CalendarIssueBlock: React.FC = observer((props) => { - const { issue, quickActions, isDragging = false } = props; - // states - const [isMenuActive, setIsMenuActive] = useState(false); - // refs - const blockRef = useRef(null); - const menuActionRef = useRef(null); - // hooks - const { workspaceSlug, projectId } = useAppRouter(); - const { getProjectIdentifierById } = useProject(); - const { getProjectStates } = useProjectState(); - const { getIsIssuePeeked, setPeekIssue } = useIssueDetail(); - const { isMobile } = usePlatformOS(); +export const CalendarIssueBlock = observer( + forwardRef((props, ref) => { + const { issue, quickActions, isDragging = false } = props; + // states + const [isMenuActive, setIsMenuActive] = useState(false); + // refs + const blockRef = useRef(null); + const menuActionRef = useRef(null); + // hooks + const { workspaceSlug, projectId } = useAppRouter(); + const { getProjectIdentifierById } = useProject(); + const { getProjectStates } = useProjectState(); + const { getIsIssuePeeked, setPeekIssue } = useIssueDetail(); + const { isMobile } = usePlatformOS(); - const stateColor = getProjectStates(issue?.project_id)?.find((state) => state?.id == issue?.state_id)?.color || ""; + const stateColor = getProjectStates(issue?.project_id)?.find((state) => state?.id == issue?.state_id)?.color || ""; - const handleIssuePeekOverview = (issue: TIssue) => - workspaceSlug && - issue && - issue.project_id && - issue.id && - !getIsIssuePeeked(issue.id) && - setPeekIssue({ workspaceSlug, projectId: issue.project_id, issueId: issue.id }); + const handleIssuePeekOverview = (issue: TIssue) => + workspaceSlug && + issue && + issue.project_id && + issue.id && + !getIsIssuePeeked(issue.id) && + setPeekIssue({ workspaceSlug, projectId: issue.project_id, issueId: issue.id }); - useOutsideClickDetector(menuActionRef, () => setIsMenuActive(false)); + useOutsideClickDetector(menuActionRef, () => setIsMenuActive(false)); - const customActionButton = ( -
setIsMenuActive(!isMenuActive)} - > - -
- ); + const customActionButton = ( +
setIsMenuActive(!isMenuActive)} + > + +
+ ); - const isMenuActionRefAboveScreenBottom = - menuActionRef?.current && menuActionRef?.current?.getBoundingClientRect().bottom < window.innerHeight - 220; + const isMenuActionRefAboveScreenBottom = + menuActionRef?.current && menuActionRef?.current?.getBoundingClientRect().bottom < window.innerHeight - 220; - const placement = isMenuActionRefAboveScreenBottom ? "bottom-end" : "top-end"; + const placement = isMenuActionRefAboveScreenBottom ? "bottom-end" : "top-end"; - return ( - handleIssuePeekOverview(issue)} - className="w-full cursor-pointer text-sm text-custom-text-100" - disabled={!!issue?.tempId} - > - <> - {issue?.tempId !== undefined && ( -
- )} - -
handleIssuePeekOverview(issue)} + className="block w-full text-sm text-custom-text-100 rounded border-b md:border-[1px] border-custom-border-200 hover:border-custom-border-400" + disabled={!!issue?.tempId} + ref={ref} + > + <> + {issue?.tempId !== undefined && ( +
)} - > -
- -
- {getProjectIdentifierById(issue?.project_id)}-{issue.sequence_id} -
- -
{issue.name}
-
-
+
{ - e.preventDefault(); - e.stopPropagation(); - }} + ref={blockRef} + className={cn( + "group/calendar-block flex h-10 md:h-8 w-full items-center justify-between gap-1.5 rounded md:px-1 px-4 py-1.5 ", + { + "bg-custom-background-90 shadow-custom-shadow-rg border-custom-primary-100": isDragging, + "bg-custom-background-100 hover:bg-custom-background-90": !isDragging, + "border border-custom-primary-70 hover:border-custom-primary-70": getIsIssuePeeked(issue.id), + } + )} > - {quickActions({ - issue, - parentRef: blockRef, - customActionButton, - placement, - })} +
+ +
+ {getProjectIdentifierById(issue?.project_id)}-{issue.sequence_id} +
+ +
{issue.name}
+
+
+
{ + e.preventDefault(); + e.stopPropagation(); + }} + > + {quickActions({ + issue, + parentRef: blockRef, + customActionButton, + placement, + })} +
-
- - - ); -}); + + + ); + }) +); + +CalendarIssueBlock.displayName = "CalendarIssueBlock"; diff --git a/web/components/issues/issue-layouts/calendar/issue-blocks.tsx b/web/components/issues/issue-layouts/calendar/issue-blocks.tsx index 86cecdf201..c04241953e 100644 --- a/web/components/issues/issue-layouts/calendar/issue-blocks.tsx +++ b/web/components/issues/issue-layouts/calendar/issue-blocks.tsx @@ -1,5 +1,4 @@ -import { useState } from "react"; -import { Draggable } from "@hello-pangea/dnd"; +import { Dispatch, SetStateAction } from "react"; import { observer } from "mobx-react-lite"; // types import { TIssue, TIssueMap } from "@plane/types"; @@ -14,6 +13,9 @@ type Props = { date: Date; issues: TIssueMap | undefined; issueIdList: string[] | null; + showAllIssues: boolean; + setShowAllIssues?: Dispatch>; + isMonthLayout: boolean; quickActions: TRenderQuickActions; isDragDisabled?: boolean; enableQuickIssueCreate?: boolean; @@ -35,6 +37,8 @@ export const CalendarIssueBlocks: React.FC = observer((props) => { date, issues, issueIdList, + showAllIssues, + setShowAllIssues, quickActions, isDragDisabled = false, enableQuickIssueCreate, @@ -43,10 +47,9 @@ export const CalendarIssueBlocks: React.FC = observer((props) => { addIssuesToView, viewId, readOnly, + isMonthLayout, isMobileView = false, } = props; - // states - const [showAllIssues, setShowAllIssues] = useState(false); const formattedDatePayload = renderFormattedPayloadDate(date); const totalIssues = issueIdList?.length ?? 0; @@ -55,30 +58,27 @@ export const CalendarIssueBlocks: React.FC = observer((props) => { return ( <> - {issueIdList?.slice(0, showAllIssues || isMobileView ? issueIdList.length : 4).map((issueId, index) => - !isMobileView ? ( - - {(provided, snapshot) => ( -
- -
- )} -
- ) : ( - - ) + {issueIdList?.slice(0, showAllIssues || !isMonthLayout ? issueIdList.length : 4).map((issueId) => ( +
+ +
+ ))} + {totalIssues > 4 && isMonthLayout && ( +
+ +
)} - {enableQuickIssueCreate && !disableIssueCreation && !readOnly && (
= observer((props) => { quickAddCallback={quickAddCallback} addIssuesToView={addIssuesToView} viewId={viewId} - onOpen={() => setShowAllIssues(true)} + onOpen={() => setShowAllIssues && setShowAllIssues(true)} />
)} - {totalIssues > 4 && ( -
- -
- )} ); }); diff --git a/web/components/issues/issue-layouts/calendar/utils.ts b/web/components/issues/issue-layouts/calendar/utils.ts index fd96ff6476..acba413f89 100644 --- a/web/components/issues/issue-layouts/calendar/utils.ts +++ b/web/components/issues/issue-layouts/calendar/utils.ts @@ -1,36 +1,21 @@ -import { DraggableLocation } from "@hello-pangea/dnd"; -import { TGroupedIssues, IIssueMap, TIssue } from "@plane/types"; +import { TIssue } from "@plane/types"; export const handleDragDrop = async ( - source: DraggableLocation, - destination: DraggableLocation, + issueId: string, + sourceDate: string, + destinationDate: string, workspaceSlug: string | undefined, projectId: string | undefined, - issueMap: IIssueMap, - issueWithIds: TGroupedIssues, updateIssue?: (projectId: string, issueId: string, data: Partial) => Promise ) => { - if (!issueMap || !issueWithIds || !workspaceSlug || !projectId || !updateIssue) return; + if (!workspaceSlug || !projectId || !updateIssue) return; - const sourceColumnId = source?.droppableId || null; - const destinationColumnId = destination?.droppableId || null; + if (sourceDate === destinationDate) return; - if (!workspaceSlug || !projectId || !sourceColumnId || !destinationColumnId) return; + const updatedIssue = { + id: issueId, + target_date: destinationDate, + }; - if (sourceColumnId === destinationColumnId) return; - - // horizontal - if (sourceColumnId != destinationColumnId) { - const sourceIssues = issueWithIds[sourceColumnId] || []; - - const [removed] = sourceIssues.splice(source.index, 1); - const removedIssueDetail = issueMap[removed]; - - const updatedIssue = { - id: removedIssueDetail?.id, - target_date: destinationColumnId, - }; - - return await updateIssue(projectId, updatedIssue.id, updatedIssue); - } + return await updateIssue(projectId, updatedIssue.id, updatedIssue); }; diff --git a/web/components/issues/issue-layouts/calendar/week-days.tsx b/web/components/issues/issue-layouts/calendar/week-days.tsx index 0ac4d30b09..9cd107bbd2 100644 --- a/web/components/issues/issue-layouts/calendar/week-days.tsx +++ b/web/components/issues/issue-layouts/calendar/week-days.tsx @@ -20,6 +20,11 @@ type Props = { quickActions: TRenderQuickActions; enableQuickIssueCreate?: boolean; disableIssueCreation?: boolean; + handleDragAndDrop: ( + issueId: string | undefined, + sourceDate: string | undefined, + destinationDate: string | undefined + ) => Promise; quickAddCallback?: ( workspaceSlug: string, projectId: string, @@ -38,6 +43,7 @@ export const CalendarWeekDays: React.FC = observer((props) => { issuesFilterStore, issues, groupedIssueIds, + handleDragAndDrop, week, quickActions, enableQuickIssueCreate, @@ -80,6 +86,7 @@ export const CalendarWeekDays: React.FC = observer((props) => { addIssuesToView={addIssuesToView} viewId={viewId} readOnly={readOnly} + handleDragAndDrop={handleDragAndDrop} /> ); })} diff --git a/web/hooks/use-draggable-portal.ts b/web/hooks/use-draggable-portal.ts deleted file mode 100644 index 325f8b2680..0000000000 --- a/web/hooks/use-draggable-portal.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { useEffect, useRef } from "react"; -import { DraggableProvided, DraggableStateSnapshot } from "@hello-pangea/dnd"; -import { createPortal } from "react-dom"; - -const useDraggableInPortal = () => { - const self = useRef(); - - useEffect(() => { - const div = document.createElement("div"); - div.style.position = "absolute"; - div.style.pointerEvents = "none"; - div.style.top = "0"; - div.style.width = "100%"; - div.style.height = "100%"; - self.current = div; - document.body.appendChild(div); - return () => { - document.body.removeChild(div); - }; - }, [self.current]); - - return (render: any) => (provided: DraggableProvided, snapshot: DraggableStateSnapshot) => { - const element = render(provided, snapshot); - if (self.current && snapshot?.isDragging) { - return createPortal(element, self.current); - } - return element; - }; -}; - -export default useDraggableInPortal; From 3a66986785754b4bb70cadc06c20cfaaa5a75ffe Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Thu, 9 May 2024 15:52:17 +0530 Subject: [PATCH 2/6] [WEB-1256] fix: accept image as a valid comment (#4409) * fix: accept image as a valid comment * fix: update space app helper function --- space/helpers/string.helper.ts | 2 +- web/helpers/string.helper.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/space/helpers/string.helper.ts b/space/helpers/string.helper.ts index b44974d250..525a9fc99d 100644 --- a/space/helpers/string.helper.ts +++ b/space/helpers/string.helper.ts @@ -52,7 +52,7 @@ export const checkEmailValidity = (email: string): boolean => { export const isEmptyHtmlString = (htmlString: string) => { // Remove HTML tags using regex - const cleanText = DOMPurify.sanitize(htmlString, { ALLOWED_TAGS: [] }); + const cleanText = DOMPurify.sanitize(htmlString, { ALLOWED_TAGS: ["img"] }); // Trim the string and check if it's empty return cleanText.trim() === ""; }; diff --git a/web/helpers/string.helper.ts b/web/helpers/string.helper.ts index 558c888834..51feb46561 100644 --- a/web/helpers/string.helper.ts +++ b/web/helpers/string.helper.ts @@ -174,10 +174,10 @@ export const getFetchKeysForIssueMutation = (options: { const ganttFetchKey = cycleId ? { ganttFetchKey: CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), ganttParams) } : moduleId - ? { ganttFetchKey: MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), ganttParams) } - : viewId - ? { ganttFetchKey: VIEW_ISSUES(viewId.toString(), viewGanttParams) } - : { ganttFetchKey: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId?.toString() ?? "", ganttParams) }; + ? { ganttFetchKey: MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), ganttParams) } + : viewId + ? { ganttFetchKey: VIEW_ISSUES(viewId.toString(), viewGanttParams) } + : { ganttFetchKey: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId?.toString() ?? "", ganttParams) }; return { ...ganttFetchKey, @@ -230,7 +230,7 @@ export const checkEmailValidity = (email: string): boolean => { export const isEmptyHtmlString = (htmlString: string) => { // Remove HTML tags using regex - const cleanText = DOMPurify.sanitize(htmlString, { ALLOWED_TAGS: [] }); + const cleanText = DOMPurify.sanitize(htmlString, { ALLOWED_TAGS: ["img"] }); // Trim the string and check if it's empty return cleanText.trim() === ""; }; From 11cd9f57d7a6ea498554d0548d9963a7831f7ddf Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Thu, 9 May 2024 15:52:56 +0530 Subject: [PATCH 3/6] chore: applied filters update view button alignment improvement (#4407) --- .../applied-filters/roots/archived-issue.tsx | 2 +- .../filters/applied-filters/roots/cycle-root.tsx | 2 +- .../filters/applied-filters/roots/draft-issue.tsx | 2 +- .../filters/applied-filters/roots/module-root.tsx | 2 +- .../applied-filters/roots/project-root.tsx | 2 +- .../applied-filters/roots/project-view-root.tsx | 15 ++++++--------- 6 files changed, 11 insertions(+), 14 deletions(-) diff --git a/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx b/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx index 8c3a6dc65e..fa89757216 100644 --- a/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx +++ b/web/components/issues/issue-layouts/filters/applied-filters/roots/archived-issue.tsx @@ -68,7 +68,7 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => { if (Object.keys(appliedFilters).length === 0) return null; return ( -
+
{ if (Object.keys(appliedFilters).length === 0 || !workspaceSlug || !projectId) return null; return ( -
+
{ if (Object.keys(appliedFilters).length === 0) return null; return ( -
+
{ if (!workspaceSlug || !projectId || Object.keys(appliedFilters).length === 0) return null; return ( -
+
{ if (Object.keys(appliedFilters).length === 0) return null; return ( -
+
{ }; return ( -
+
{ /> {!areFiltersEqual && ( - <> -
-
- -
- +
+ +
)}
); From 41093efbb79cf9816d542c7b2870b1d49751d58c Mon Sep 17 00:00:00 2001 From: sriram veeraghanta Date: Thu, 9 May 2024 16:01:23 +0530 Subject: [PATCH 4/6] fix: adding harbour env variables in workflow --- .github/workflows/build-branch-ee.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-branch-ee.yml b/.github/workflows/build-branch-ee.yml index c768c96d3f..833810cd3b 100644 --- a/.github/workflows/build-branch-ee.yml +++ b/.github/workflows/build-branch-ee.yml @@ -113,11 +113,16 @@ jobs: - name: Set Admin Docker Tag run: | if [ "${{ github.event_name }}" == "release" ]; then - TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-admin:stable,${{ secrets.DOCKERHUB_USERNAME }}/plane-admin:${{ github.event.release.tag_name }} + TAG=${{ secrets.DOCKERHUB_USERNAME }}/admin-enterprise:stable + TAG=${TAG},${{ secrets.DOCKERHUB_USERNAME }}/admin-enterprise:${{ github.event.release.tag_name }} + TAG=${TAG},${{ vars.HARBOR_REGISTRY }}/${{ vars.HARBOR_PROJECT }}/admin-enterprise:stable + TAG=${TAG},${{ vars.HARBOR_REGISTRY }}/${{ vars.HARBOR_PROJECT }}/admin-enterprise:${{ github.event.release.tag_name }} elif [ "${{ env.TARGET_BRANCH }}" == "master" ]; then - TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-admin:latest + TAG=${{ secrets.DOCKERHUB_USERNAME }}/admin-enterprise:latest + TAG=${TAG},${{ vars.HARBOR_REGISTRY }}/${{ vars.HARBOR_PROJECT }}/admin-enterprise:latest else TAG=${{ env.ADMIN_TAG }} + TAG=${TAG},${{ vars.HARBOR_REGISTRY }}/${{ vars.HARBOR_PROJECT }}/admin-enterprise:${{ needs.branch_build_setup.outputs.gh_branch_name }} fi echo "ADMIN_TAG=${TAG}" >> $GITHUB_ENV @@ -127,6 +132,13 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Login to Harbor + uses: docker/login-action@v3 + with: + username: ${{ secrets.HARBOR_USERNAME }} + password: ${{ secrets.HARBOR_TOKEN }} + registry: ${{ vars.HARBOR_REGISTRY }} + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: From 335bf88af14f5e64a164e7dc37c68464d095e867 Mon Sep 17 00:00:00 2001 From: Manish Gupta <59428681+mguptahub@users.noreply.github.com> Date: Thu, 9 May 2024 16:45:52 +0530 Subject: [PATCH 5/6] cli-install fixes for god-mode (#224) --- deploy/cli-install/Caddyfile | 4 ++++ deploy/cli-install/docker-compose-caddy.yml | 12 ++++++++++++ deploy/cli-install/docker-compose.yml | 12 ++++++++++++ 3 files changed, 28 insertions(+) diff --git a/deploy/cli-install/Caddyfile b/deploy/cli-install/Caddyfile index 2ab9d05032..1079e1d2eb 100644 --- a/deploy/cli-install/Caddyfile +++ b/deploy/cli-install/Caddyfile @@ -10,8 +10,12 @@ reverse_proxy /spaces/* space:3000 + reverse_proxy /god-mode/* admin:3000 + reverse_proxy /api/* api:8000 + reverse_proxy /auth/* api:8000 + reverse_proxy /{$BUCKET_NAME}/* plane-minio:9000 reverse_proxy /* web:3000 diff --git a/deploy/cli-install/docker-compose-caddy.yml b/deploy/cli-install/docker-compose-caddy.yml index d9c424ee9d..82c2a7d7c7 100644 --- a/deploy/cli-install/docker-compose-caddy.yml +++ b/deploy/cli-install/docker-compose-caddy.yml @@ -46,6 +46,18 @@ x-app-env: &app-env - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880} services: + + admin: + <<: *app-env + image: registry.plane.tools/plane/admin-enterprise:${APP_RELEASE_VERSION} + restart: unless-stopped + command: node admin/server.js admin + deploy: + replicas: ${ADMIN_REPLICAS:-1} + depends_on: + - api + - web + web: <<: *app-env image: registry.plane.tools/plane/web-enterprise:${APP_RELEASE_VERSION} diff --git a/deploy/cli-install/docker-compose.yml b/deploy/cli-install/docker-compose.yml index 845f7e3ca2..c0dd06f53d 100644 --- a/deploy/cli-install/docker-compose.yml +++ b/deploy/cli-install/docker-compose.yml @@ -37,6 +37,18 @@ x-app-env: &app-env - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880} services: + + admin: + <<: *app-env + image: registry.plane.tools/plane/admin-enterprise:${APP_RELEASE_VERSION} + restart: unless-stopped + command: node admin/server.js admin + deploy: + replicas: ${ADMIN_REPLICAS:-1} + depends_on: + - api + - web + web: <<: *app-env image: registry.plane.tools/plane/web-enterprise:${APP_RELEASE_VERSION} From 89976c47a9a0398272b38587b5cab9a23e1d1dc7 Mon Sep 17 00:00:00 2001 From: Manish Gupta <59428681+mguptahub@users.noreply.github.com> Date: Thu, 9 May 2024 16:46:34 +0530 Subject: [PATCH 6/6] upload action fixed (#222) --- .github/workflows/build-branch-ee.yml | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-branch-ee.yml b/.github/workflows/build-branch-ee.yml index 833810cd3b..1c0f1c628c 100644 --- a/.github/workflows/build-branch-ee.yml +++ b/.github/workflows/build-branch-ee.yml @@ -424,18 +424,8 @@ jobs: runs-on: ubuntu-latest needs: [ - branch_build_setup, - branch_build_push_web, - branch_build_push_space, - branch_build_push_apiserver, - branch_build_push_proxy, - branch_build_push_admin, + branch_build_setup ] - container: - image: docker:20.10.7 - credentials: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} env: ARTIFACT_SUFFIX: ${{ needs.branch_build_setup.outputs.artifact_s3_suffix }} AWS_ACCESS_KEY_ID: ${{ secrets.SELF_HOST_BUCKET_ACCESS_KEY }} @@ -448,8 +438,15 @@ jobs: - name: Upload artifacts run: | - apk update - apk add --no-cache aws-cli + CPU_ARCH=$(uname -m) + if [ "${CPU_ARCH}" == "x86_64" ] || [ "${CPU_ARCH}" == "amd64" ]; then + CPU_ARCH="x86_64" + elif [ "${CPU_ARCH}" == "aarch64" ] || [ "${CPU_ARCH}" == "arm64" ]; then + CPU_ARCH="aarch64" + fi + curl "https://awscli.amazonaws.com/awscli-exe-linux-${CPU_ARCH}.zip" -o "awscliv2.zip" + unzip -q awscliv2.zip + ./aws/install mkdir -p ~/${{ env.ARTIFACT_SUFFIX }}