From dd65d03d3383f32de617f2baafac6503efb88ede Mon Sep 17 00:00:00 2001
From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com>
Date: Tue, 4 Jun 2024 11:12:24 +0530
Subject: [PATCH 001/307] [WEB-1184] feat: issue bulk operations (#4674)
* feat: issue bulk operations
* style: bulk operations action bar
* chore: remove edition separation
---
.../components/admin-sidebar/help-section.tsx | 13 +-
web/components/gantt-chart/blocks/block.tsx | 22 +-
.../gantt-chart/blocks/blocks-list.tsx | 11 +-
.../gantt-chart/chart/main-content.tsx | 97 ++++---
web/components/gantt-chart/chart/root.tsx | 3 +
web/components/gantt-chart/constants.ts | 2 +
web/components/gantt-chart/root.tsx | 3 +
.../gantt-chart/sidebar/cycles/block.tsx | 2 +-
.../gantt-chart/sidebar/issues/block.tsx | 64 +++--
.../gantt-chart/sidebar/issues/sidebar.tsx | 12 +-
.../gantt-chart/sidebar/modules/block.tsx | 2 +-
web/components/gantt-chart/sidebar/root.tsx | 53 +++-
.../issues/bulk-operations/index.ts | 2 +
.../issues/bulk-operations/root.tsx | 19 ++
.../issues/bulk-operations/upgrade-banner.tsx | 32 +++
web/components/issues/index.ts | 1 +
.../issue-layouts/gantt/base-gantt-root.tsx | 1 +
.../issue-layouts/list/base-list-root.tsx | 21 +-
.../issues/issue-layouts/list/block-root.tsx | 9 +-
.../issues/issue-layouts/list/block.tsx | 86 +++++--
.../issues/issue-layouts/list/blocks-list.tsx | 46 ++--
.../issues/issue-layouts/list/default.tsx | 102 +++++---
.../list/headers/group-by-card.tsx | 237 ++++++++++--------
.../issues/issue-layouts/list/list-group.tsx | 9 +-
.../spreadsheet/columns/assignee-column.tsx | 4 +-
.../spreadsheet/columns/attachment-column.tsx | 4 +-
.../spreadsheet/columns/created-on-column.tsx | 5 +-
.../spreadsheet/columns/cycle-column.tsx | 15 +-
.../spreadsheet/columns/due-date-column.tsx | 13 +-
.../spreadsheet/columns/estimate-column.tsx | 6 +-
.../spreadsheet/columns/label-column.tsx | 8 +-
.../spreadsheet/columns/link-column.tsx | 4 +-
.../spreadsheet/columns/module-column.tsx | 15 +-
.../spreadsheet/columns/priority-column.tsx | 4 +-
.../spreadsheet/columns/start-date-column.tsx | 4 +-
.../spreadsheet/columns/state-column.tsx | 4 +-
.../spreadsheet/columns/sub-issue-column.tsx | 2 +-
.../spreadsheet/columns/updated-on-column.tsx | 5 +-
.../spreadsheet/issue-column.tsx | 13 +-
.../issue-layouts/spreadsheet/issue-row.tsx | 108 +++++---
.../spreadsheet/spreadsheet-header.tsx | 57 ++++-
.../spreadsheet/spreadsheet-table.tsx | 6 +
.../spreadsheet/spreadsheet-view.tsx | 68 +++--
web/components/workspace/help-section.tsx | 13 +-
web/constants/common.ts | 2 +
web/constants/spreadsheet.ts | 14 +-
46 files changed, 817 insertions(+), 406 deletions(-)
create mode 100644 web/components/issues/bulk-operations/index.ts
create mode 100644 web/components/issues/bulk-operations/root.tsx
create mode 100644 web/components/issues/bulk-operations/upgrade-banner.tsx
diff --git a/admin/components/admin-sidebar/help-section.tsx b/admin/components/admin-sidebar/help-section.tsx
index 56ccbcd8446..38edd06fc23 100644
--- a/admin/components/admin-sidebar/help-section.tsx
+++ b/admin/components/admin-sidebar/help-section.tsx
@@ -5,9 +5,11 @@ import { observer } from "mobx-react-lite";
import Link from "next/link";
import { ExternalLink, FileText, HelpCircle, MoveLeft } from "lucide-react";
import { Transition } from "@headlessui/react";
+// ui
import { DiscordIcon, GithubIcon, Tooltip } from "@plane/ui";
+// helpers
+import { WEB_BASE_URL, cn } from "@/helpers/common.helper";
// hooks
-import { WEB_BASE_URL } from "@/helpers/common.helper";
import { useTheme } from "@/hooks/store";
// assets
import packageJson from "package.json";
@@ -42,9 +44,12 @@ export const HelpSection: FC = observer(() => {
return (
diff --git a/web/components/gantt-chart/blocks/block.tsx b/web/components/gantt-chart/blocks/block.tsx
index 0897b6b39ea..a33a0fd9f34 100644
--- a/web/components/gantt-chart/blocks/block.tsx
+++ b/web/components/gantt-chart/blocks/block.tsx
@@ -1,15 +1,16 @@
import { observer } from "mobx-react";
-// hooks
-// components
// helpers
import { cn } from "@/helpers/common.helper";
import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper";
+// hooks
import { useIssueDetail } from "@/hooks/store";
-// types
+import { TSelectionHelper } from "@/hooks/use-multiple-select";
// constants
import { BLOCK_HEIGHT } from "../constants";
+// components
import { ChartAddBlock, ChartDraggable } from "../helpers";
import { useGanttChart } from "../hooks";
+// types
import { IBlockUpdateData, IGanttBlock } from "../types";
type Props = {
@@ -21,6 +22,7 @@ type Props = {
enableBlockMove: boolean;
enableAddBlock: boolean;
ganttContainerRef: React.RefObject;
+ selectionHelpers: TSelectionHelper;
};
export const GanttChartBlock: React.FC = observer((props) => {
@@ -33,6 +35,7 @@ export const GanttChartBlock: React.FC = observer((props) => {
enableBlockMove,
enableAddBlock,
ganttContainerRef,
+ selectionHelpers,
} = props;
// store hooks
const { updateActiveBlockId, isBlockActive } = useGanttChart();
@@ -70,6 +73,10 @@ export const GanttChartBlock: React.FC = observer((props) => {
});
};
+ const isBlockSelected = selectionHelpers.getIsEntitySelected(block.id);
+ const isBlockFocused = selectionHelpers.getIsEntityActive(block.id);
+ const isBlockHoveredOn = isBlockActive(block.id);
+
return (
= observer((props) => {
>
updateActiveBlockId(block.id)}
onMouseLeave={() => updateActiveBlockId(null)}
diff --git a/web/components/gantt-chart/blocks/blocks-list.tsx b/web/components/gantt-chart/blocks/blocks-list.tsx
index 8eb1d877252..6fd22b254e9 100644
--- a/web/components/gantt-chart/blocks/blocks-list.tsx
+++ b/web/components/gantt-chart/blocks/blocks-list.tsx
@@ -1,10 +1,12 @@
import { FC } from "react";
-// components
+// hooks
+import { TSelectionHelper } from "@/hooks/use-multiple-select";
+// constants
import { HEADER_HEIGHT } from "../constants";
+// types
import { IBlockUpdateData, IGanttBlock } from "../types";
+// components
import { GanttChartBlock } from "./block";
-// types
-// constants
export type GanttChartBlocksProps = {
itemsContainerWidth: number;
@@ -17,6 +19,7 @@ export type GanttChartBlocksProps = {
enableAddBlock: boolean;
ganttContainerRef: React.RefObject
;
showAllBlocks: boolean;
+ selectionHelpers: TSelectionHelper;
};
export const GanttChartBlocksList: FC = (props) => {
@@ -31,6 +34,7 @@ export const GanttChartBlocksList: FC = (props) => {
enableAddBlock,
ganttContainerRef,
showAllBlocks,
+ selectionHelpers,
} = props;
return (
@@ -56,6 +60,7 @@ export const GanttChartBlocksList: FC = (props) => {
enableBlockMove={enableBlockMove}
enableAddBlock={enableAddBlock}
ganttContainerRef={ganttContainerRef}
+ selectionHelpers={selectionHelpers}
/>
);
})}
diff --git a/web/components/gantt-chart/chart/main-content.tsx b/web/components/gantt-chart/chart/main-content.tsx
index 2f5abc8863a..e3b97223790 100644
--- a/web/components/gantt-chart/chart/main-content.tsx
+++ b/web/components/gantt-chart/chart/main-content.tsx
@@ -2,8 +2,8 @@ import { useEffect, useRef } 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";
-// hooks
// components
+import { MultipleSelectGroup } from "@/components/core";
import {
BiWeekChartView,
DayChartView,
@@ -18,8 +18,12 @@ import {
WeekChartView,
YearChartView,
} from "@/components/gantt-chart";
+import { IssueBulkOperationsRoot } from "@/components/issues";
// helpers
import { cn } from "@/helpers/common.helper";
+// constants
+import { GANTT_SELECT_GROUP } from "../constants";
+// hooks
import { useGanttChart } from "../hooks/use-gantt-chart";
type Props = {
@@ -33,6 +37,7 @@ type Props = {
enableBlockRightResize: boolean;
enableReorder: boolean;
enableAddBlock: boolean;
+ enableSelection: boolean;
itemsContainerWidth: number;
showAllBlocks: boolean;
sidebarToRender: (props: any) => React.ReactNode;
@@ -53,6 +58,7 @@ export const GanttChartMainContent: React.FC = observer((props) => {
enableBlockRightResize,
enableReorder,
enableAddBlock,
+ enableSelection,
itemsContainerWidth,
showAllBlocks,
sidebarToRender,
@@ -107,43 +113,58 @@ export const GanttChartMainContent: React.FC = observer((props) => {
const ActiveChartView = CHART_VIEW_COMPONENTS[currentView];
return (
- block.id) ?? [],
+ }}
>
-
-
-
- {currentViewData && (
-
- )}
-
-
+ {(helpers) => (
+ <>
+
+
+
+
+ {currentViewData && (
+
+ )}
+
+
+
+ >
+ )}
+
);
});
diff --git a/web/components/gantt-chart/chart/root.tsx b/web/components/gantt-chart/chart/root.tsx
index 395e0771cd5..d961047e939 100644
--- a/web/components/gantt-chart/chart/root.tsx
+++ b/web/components/gantt-chart/chart/root.tsx
@@ -32,6 +32,7 @@ type ChartViewRootProps = {
enableBlockMove: boolean;
enableReorder: boolean;
enableAddBlock: boolean;
+ enableSelection: boolean;
bottomSpacing: boolean;
showAllBlocks: boolean;
quickAdd?: React.JSX.Element | undefined;
@@ -51,6 +52,7 @@ export const ChartViewRoot: FC = observer((props) => {
enableBlockMove,
enableReorder,
enableAddBlock,
+ enableSelection,
bottomSpacing,
showAllBlocks,
quickAdd,
@@ -184,6 +186,7 @@ export const ChartViewRoot: FC = observer((props) => {
enableBlockRightResize={enableBlockRightResize}
enableReorder={enableReorder}
enableAddBlock={enableAddBlock}
+ enableSelection={enableSelection}
itemsContainerWidth={itemsContainerWidth}
showAllBlocks={showAllBlocks}
sidebarToRender={sidebarToRender}
diff --git a/web/components/gantt-chart/constants.ts b/web/components/gantt-chart/constants.ts
index 958985cf166..52167a49844 100644
--- a/web/components/gantt-chart/constants.ts
+++ b/web/components/gantt-chart/constants.ts
@@ -3,3 +3,5 @@ export const BLOCK_HEIGHT = 44;
export const HEADER_HEIGHT = 60;
export const SIDEBAR_WIDTH = 360;
+
+export const GANTT_SELECT_GROUP = "gantt-issues";
diff --git a/web/components/gantt-chart/root.tsx b/web/components/gantt-chart/root.tsx
index 10c1c0d98de..267dfe5c584 100644
--- a/web/components/gantt-chart/root.tsx
+++ b/web/components/gantt-chart/root.tsx
@@ -18,6 +18,7 @@ type GanttChartRootProps = {
enableBlockMove?: boolean;
enableReorder?: boolean;
enableAddBlock?: boolean;
+ enableSelection?: boolean;
bottomSpacing?: boolean;
showAllBlocks?: boolean;
};
@@ -36,6 +37,7 @@ export const GanttChartRoot: FC = (props) => {
enableBlockMove = false,
enableReorder = false,
enableAddBlock = false,
+ enableSelection = false,
bottomSpacing = false,
showAllBlocks = false,
quickAdd,
@@ -56,6 +58,7 @@ export const GanttChartRoot: FC = (props) => {
enableBlockMove={enableBlockMove}
enableReorder={enableReorder}
enableAddBlock={enableAddBlock}
+ enableSelection={enableSelection}
bottomSpacing={bottomSpacing}
showAllBlocks={showAllBlocks}
quickAdd={quickAdd}
diff --git a/web/components/gantt-chart/sidebar/cycles/block.tsx b/web/components/gantt-chart/sidebar/cycles/block.tsx
index 1119e2e9ca9..7922e86a62d 100644
--- a/web/components/gantt-chart/sidebar/cycles/block.tsx
+++ b/web/components/gantt-chart/sidebar/cycles/block.tsx
@@ -38,7 +38,7 @@ export const CyclesSidebarBlock: React.FC = observer((props) => {