refactoring
This commit is contained in:
@@ -18,8 +18,8 @@
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.board-during-dnd {
|
||||
background-color: var(--color-gray-10);
|
||||
.no-transition {
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
.board::after {
|
||||
|
||||
@@ -5,31 +5,30 @@ import { IconEdit, IconPlus, IconTrash } from "@tabler/icons-react";
|
||||
import classNames from "classnames";
|
||||
import styles from "./Board.module.scss";
|
||||
import useStatus from "../../Statuses/Status/hooks/useStatus.tsx";
|
||||
import { useDndContext } from "../../../../pages/CardsPage/contexts/DndContext.tsx";
|
||||
import DragState from "../../../../pages/CardsPage/enums/DragState.ts";
|
||||
import { useBoardsContext } from "../../../../contexts/BoardsContext.tsx";
|
||||
|
||||
|
||||
type Props = {
|
||||
board: BoardSchema;
|
||||
selectedBoard: BoardSchema | null;
|
||||
setSelectedBoard: (board: BoardSchema) => void;
|
||||
onEditBoardClick: (board: BoardSchema) => void;
|
||||
onDeleteBoardClick: (board: BoardSchema) => void;
|
||||
isBoardDragEnded: boolean;
|
||||
refetch: () => void;
|
||||
}
|
||||
|
||||
const Board = ({
|
||||
board,
|
||||
selectedBoard,
|
||||
setSelectedBoard,
|
||||
onEditBoardClick,
|
||||
onDeleteBoardClick,
|
||||
isBoardDragEnded,
|
||||
refetch,
|
||||
}: Props) => {
|
||||
const Board = ({ board }: Props) => {
|
||||
const {
|
||||
selectedBoard,
|
||||
setSelectedBoard,
|
||||
onEditBoardClick,
|
||||
onDeleteBoardClick,
|
||||
} = useBoardsContext();
|
||||
|
||||
const { dragState } = useDndContext();
|
||||
|
||||
const { showContextMenu } = useContextMenu();
|
||||
|
||||
const { onCreateStatusClick } = useStatus({ refetch });
|
||||
const { onCreateStatusClick } = useStatus();
|
||||
|
||||
const isDropDisabled = dragState !== DragState.DRAG_BOARD;
|
||||
|
||||
const contextMenu = (board: BoardSchema) => showContextMenu([
|
||||
{
|
||||
@@ -54,16 +53,22 @@ const Board = ({
|
||||
|
||||
return (
|
||||
<Droppable
|
||||
droppableId={board.id.toString()}
|
||||
droppableId={"board-" + board.id.toString()}
|
||||
direction={"horizontal"}
|
||||
isDropDisabled={isDropDisabled}
|
||||
>
|
||||
{provided => (
|
||||
<div
|
||||
{...provided.droppableProps}
|
||||
ref={provided.innerRef}
|
||||
onMouseEnter={() => {
|
||||
if (dragState === DragState.DRAG_CARD) {
|
||||
setSelectedBoard(board);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Draggable
|
||||
draggableId={board.id.toString()}
|
||||
draggableId={"board-" + board.id.toString()}
|
||||
index={board.ordinalNumber}
|
||||
>
|
||||
{(provided) => (
|
||||
@@ -77,7 +82,6 @@ const Board = ({
|
||||
board.id === selectedBoard?.id ?
|
||||
styles["selected-board"] :
|
||||
styles["board"],
|
||||
!isBoardDragEnded && styles["board-during-dnd"],
|
||||
)}
|
||||
|
||||
onClick={() => setSelectedBoard(board)}
|
||||
|
||||
@@ -1,88 +1,66 @@
|
||||
import { Box, Center, Group, Stack } from "@mantine/core";
|
||||
import { DragDropContext } from "@hello-pangea/dnd";
|
||||
import { BoardSchema, CardSummary } from "../../../../client";
|
||||
import { BoardSchema } from "../../../../client";
|
||||
import { IconPlus } from "@tabler/icons-react";
|
||||
import useBoards from "./hooks/useBoards.tsx";
|
||||
import Statuses from "../../Statuses/Statuses/Statuses.tsx";
|
||||
import Board from "../Board/Board.tsx";
|
||||
import useBoardsDnd from "./hooks/useBoardsDnd.tsx";
|
||||
import PrefillCardsWithExcelDrawer
|
||||
from "../../../../pages/CardsPage/drawers/PrefillCardWithExcelDrawer/PrefillCardsWithExcelDrawer.tsx";
|
||||
import { useDndContext } from "../../../../pages/CardsPage/contexts/DndContext.tsx";
|
||||
import { useBoardsContext } from "../../../../contexts/BoardsContext.tsx";
|
||||
|
||||
|
||||
type Props = {
|
||||
summariesRaw: CardSummary[];
|
||||
refetchSummaries: () => void;
|
||||
boards: BoardSchema[];
|
||||
refetchBoards: () => void;
|
||||
}
|
||||
|
||||
const Boards = (props: Props) => {
|
||||
const Boards = () => {
|
||||
const {
|
||||
boards,
|
||||
selectedBoard,
|
||||
setSelectedBoard,
|
||||
onCreateBoardClick,
|
||||
onEditBoardClick,
|
||||
onDeleteBoardClick,
|
||||
} = useBoards(props);
|
||||
} = useBoardsContext();
|
||||
|
||||
const {
|
||||
onBoardDragEnd,
|
||||
isBoardDragEnded,
|
||||
setIsBoardDragEnded,
|
||||
} = useBoardsDnd(props);
|
||||
onDragEnd,
|
||||
onDragStart,
|
||||
} = useDndContext();
|
||||
|
||||
const getBoardsTabs = () => {
|
||||
return (
|
||||
<DragDropContext
|
||||
onDragStart={() => {
|
||||
setIsBoardDragEnded(false);
|
||||
}}
|
||||
onDragEnd={onBoardDragEnd}
|
||||
<Group
|
||||
mx={"3%"}
|
||||
mb={"md"}
|
||||
gap={0}
|
||||
align={"end"}
|
||||
wrap={"nowrap"}
|
||||
>
|
||||
<Group
|
||||
mx={"3%"}
|
||||
mb={"md"}
|
||||
gap={0}
|
||||
align={"end"}
|
||||
wrap={"nowrap"}
|
||||
{boards.map((board: BoardSchema) => (
|
||||
<Board
|
||||
key={board.id}
|
||||
board={board}
|
||||
/>
|
||||
))}
|
||||
<Center
|
||||
px={"md"}
|
||||
py={"xs"}
|
||||
style={{ cursor: "pointer", borderBottom: "solid gray 1px" }}
|
||||
onClick={onCreateBoardClick}
|
||||
>
|
||||
{props.boards.map((board: BoardSchema) => (
|
||||
<Board
|
||||
key={board.id}
|
||||
|
||||
board={board}
|
||||
selectedBoard={selectedBoard}
|
||||
setSelectedBoard={setSelectedBoard}
|
||||
onEditBoardClick={onEditBoardClick}
|
||||
onDeleteBoardClick={onDeleteBoardClick}
|
||||
isBoardDragEnded={isBoardDragEnded}
|
||||
refetch={props.refetchBoards}
|
||||
/>
|
||||
))}
|
||||
<Center
|
||||
px={"md"}
|
||||
py={"xs"}
|
||||
style={{ cursor: "pointer", borderBottom: "solid gray 1px" }}
|
||||
onClick={onCreateBoardClick}
|
||||
>
|
||||
<IconPlus />
|
||||
</Center>
|
||||
<Box w={"100%"} style={{ borderBottom: "solid gray 1px" }}></Box>
|
||||
</Group>
|
||||
</DragDropContext>
|
||||
<IconPlus />
|
||||
</Center>
|
||||
<Box w={"100%"} style={{ borderBottom: "solid gray 1px" }}></Box>
|
||||
</Group>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
{getBoardsTabs()}
|
||||
<Statuses
|
||||
selectedBoard={selectedBoard}
|
||||
{...props}
|
||||
/>
|
||||
<PrefillCardsWithExcelDrawer board={selectedBoard} />
|
||||
</Stack>
|
||||
<DragDropContext
|
||||
onDragStart={onDragStart}
|
||||
onDragEnd={onDragEnd}
|
||||
>
|
||||
<Stack>
|
||||
{getBoardsTabs()}
|
||||
<Statuses />
|
||||
<PrefillCardsWithExcelDrawer board={selectedBoard} />
|
||||
</Stack>
|
||||
</DragDropContext>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { BoardSchema, BoardService } from "../../../../../client";
|
||||
import { modals } from "@mantine/modals";
|
||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
||||
import { useProjectsContext } from "../../../../../contexts/ProjectsContext.tsx";
|
||||
|
||||
type Props = {
|
||||
boards: BoardSchema[];
|
||||
refetchBoards: () => void;
|
||||
}
|
||||
|
||||
const useBoards = ({ boards, refetchBoards }: Props) => {
|
||||
const [selectedBoard, setSelectedBoard] = useState<BoardSchema | null>(null);
|
||||
const { selectedProject: project } = useProjectsContext();
|
||||
|
||||
useEffect(() => {
|
||||
if (boards.length > 0 && selectedBoard === null) {
|
||||
setSelectedBoard(boards[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedBoard) {
|
||||
// Update selected board after changing all boards
|
||||
let newBoard = boards.find(board => board.id === selectedBoard.id);
|
||||
|
||||
if (!newBoard && boards.length > 0) {
|
||||
newBoard = boards[0];
|
||||
}
|
||||
setSelectedBoard(newBoard ?? null);
|
||||
}
|
||||
}, [boards]);
|
||||
|
||||
const onEditBoardClick = (board: BoardSchema) => {
|
||||
if (!project) return;
|
||||
modals.openContextModal({
|
||||
modal: "boardModal",
|
||||
title: "Редактирование доски",
|
||||
withCloseButton: false,
|
||||
innerProps: {
|
||||
projectId: project.id,
|
||||
board,
|
||||
refetchBoards,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const onCreateBoardClick = () => {
|
||||
if (!project) return;
|
||||
modals.openContextModal({
|
||||
modal: "boardModal",
|
||||
title: "Добавление доски",
|
||||
withCloseButton: false,
|
||||
innerProps: {
|
||||
projectId: project.id,
|
||||
refetchBoards,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const onDeleteBoardClick = (board: BoardSchema) => {
|
||||
if (!board) return;
|
||||
BoardService.deleteBoard({
|
||||
boardId: board.id,
|
||||
})
|
||||
.then(({ ok, message }) => {
|
||||
if (!ok) {
|
||||
notifications.error({ message });
|
||||
return;
|
||||
}
|
||||
refetchBoards();
|
||||
})
|
||||
.catch(err => console.log(err));
|
||||
};
|
||||
|
||||
return {
|
||||
selectedBoard,
|
||||
setSelectedBoard,
|
||||
onCreateBoardClick,
|
||||
onEditBoardClick,
|
||||
onDeleteBoardClick,
|
||||
};
|
||||
};
|
||||
|
||||
export default useBoards;
|
||||
@@ -1,16 +1,14 @@
|
||||
import { DropResult } from "@hello-pangea/dnd";
|
||||
import { BoardSchema, BoardService } from "../../../../../client";
|
||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
||||
import { useState } from "react";
|
||||
import { useBoardsContext } from "../../../../../contexts/BoardsContext.tsx";
|
||||
|
||||
|
||||
type Props = {
|
||||
boards: BoardSchema[];
|
||||
refetchBoards: () => void;
|
||||
}
|
||||
|
||||
const useBoardsDnd = ({ boards, refetchBoards }: Props) => {
|
||||
const [isBoardDragEnded, setIsBoardDragEnded] = useState(true);
|
||||
const useBoardsDnd = () => {
|
||||
const {
|
||||
boards,
|
||||
refetchBoards,
|
||||
} = useBoardsContext();
|
||||
|
||||
const updateBoardOrder = (board: BoardSchema, newOrdinalNumber: number) => {
|
||||
BoardService.updateBoardOrder({
|
||||
@@ -18,22 +16,21 @@ const useBoardsDnd = ({ boards, refetchBoards }: Props) => {
|
||||
projectId: board.projectId,
|
||||
boardId: board.id,
|
||||
newOrdinalNumber,
|
||||
}
|
||||
},
|
||||
})
|
||||
.then(({ ok, message }) => {
|
||||
if (!ok) notifications.error({ message });
|
||||
refetchBoards();
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
const onBoardDragEnd = async (result: DropResult) => {
|
||||
setIsBoardDragEnded(true);
|
||||
|
||||
// If there is no changes
|
||||
if (!result.destination || result.destination == result.source) return;
|
||||
|
||||
// Checking for valid cardId
|
||||
const boardId = parseInt(result.draggableId);
|
||||
const boardIdStr = result.draggableId.replace("board-", "");
|
||||
const boardId = parseInt(boardIdStr);
|
||||
if (isNaN(boardId)) return;
|
||||
|
||||
// Checking for valid card
|
||||
@@ -45,8 +42,6 @@ const useBoardsDnd = ({ boards, refetchBoards }: Props) => {
|
||||
|
||||
return {
|
||||
onBoardDragEnd,
|
||||
isBoardDragEnded,
|
||||
setIsBoardDragEnded,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ export const CardsDndColumn: FC<Props> = ({
|
||||
}) => {
|
||||
const { selectedProject } = useProjectsContext();
|
||||
const isCreatingDealFromFileEnabled = isModuleInProject(Modules.SERVICES_AND_PRODUCTS, selectedProject);
|
||||
const isDropDisabled = dragState === DragState.DRAG_STATUS;
|
||||
const isDropDisabled = dragState !== DragState.DRAG_CARD;
|
||||
const droppableId = status.id.toString();
|
||||
|
||||
const isGroup = (obj: GroupWithCards | CardSummary): obj is GroupWithCards => {
|
||||
|
||||
@@ -9,7 +9,7 @@ type Props = {
|
||||
}
|
||||
|
||||
const CardsDndFooter = ({ dragState }: Props) => {
|
||||
const isDealDragEnded = dragState === DragState.DRAG_ENDED;
|
||||
const isDealDragEnded = dragState !== DragState.DRAG_CARD;
|
||||
|
||||
return (
|
||||
<Flex
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import styles from "../../../../pages/CardsPage/ui/CardsPage.module.css";
|
||||
import { Divider, Stack, Text, Title } from "@mantine/core";
|
||||
import getColumnColor from "../../Cards/CardsDndColumn/utils/getColumnColor.ts";
|
||||
import { BoardSchema, CardSummary, StatusSchema } from "../../../../client";
|
||||
import { CardSummary, StatusSchema } from "../../../../client";
|
||||
import { getPluralForm } from "../../../../shared/lib/utils.ts";
|
||||
import { sum } from "lodash";
|
||||
import { Draggable, Droppable } from "@hello-pangea/dnd";
|
||||
@@ -11,20 +11,23 @@ import { IconEdit, IconTrash } from "@tabler/icons-react";
|
||||
import useStatus from "./hooks/useStatus.tsx";
|
||||
import isModuleInProject, { Modules } from "../../../../modules/utils/isModuleInProject.ts";
|
||||
import { useEqualHeightsContext } from "./contexts/EqualHeightContext.tsx";
|
||||
import { useBoardsContext } from "../../../../contexts/BoardsContext.tsx";
|
||||
|
||||
|
||||
type Props = {
|
||||
status: StatusSchema;
|
||||
board: BoardSchema | null;
|
||||
index: number;
|
||||
summaries: CardSummary[];
|
||||
dragState: DragState;
|
||||
refetch: () => void;
|
||||
}
|
||||
|
||||
const Status = ({ summaries, status, board, dragState, index, refetch }: Props) => {
|
||||
const isDropDisabled = dragState === DragState.DRAG_CARD;
|
||||
const isServicesAndProductsIncluded = isModuleInProject(Modules.SERVICES_AND_PRODUCTS, board?.project);
|
||||
const Status = ({ summaries, status, dragState, index }: Props) => {
|
||||
const {
|
||||
selectedBoard,
|
||||
} = useBoardsContext();
|
||||
|
||||
const isDropDisabled = dragState !== DragState.DRAG_STATUS;
|
||||
const isServicesAndProductsIncluded = isModuleInProject(Modules.SERVICES_AND_PRODUCTS, selectedBoard?.project);
|
||||
|
||||
const {
|
||||
divRefs,
|
||||
@@ -33,7 +36,7 @@ const Status = ({ summaries, status, board, dragState, index, refetch }: Props)
|
||||
const {
|
||||
onEditStatusClick,
|
||||
onDeleteStatusClick,
|
||||
} = useStatus({ refetch });
|
||||
} = useStatus();
|
||||
|
||||
const getDealsText = () => {
|
||||
const pluralForm = getPluralForm(
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { BoardSchema, StatusSchema, StatusService } from "../../../../../client";
|
||||
import { modals } from "@mantine/modals";
|
||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
||||
import { useBoardsContext } from "../../../../../contexts/BoardsContext.tsx";
|
||||
|
||||
|
||||
type Props = {
|
||||
refetch: () => void;
|
||||
}
|
||||
const useStatus = () => {
|
||||
const {
|
||||
refetchBoards: refetch,
|
||||
} = useBoardsContext();
|
||||
|
||||
const useStatus = ({ refetch }: Props) => {
|
||||
const onEditStatusClick = (status: StatusSchema) => {
|
||||
modals.openContextModal({
|
||||
modal: "statusModal",
|
||||
|
||||
@@ -1,38 +1,21 @@
|
||||
import { BoardSchema, CardSummary, StatusSchema } from "../../../../client";
|
||||
import { StatusSchema } from "../../../../client";
|
||||
import CardsDndColumn from "../../Cards/CardsDndColumn/CardsDndColumn.tsx";
|
||||
import styles from "../../../../pages/CardsPage/ui/CardsPage.module.css";
|
||||
import CardsDndFooter from "../../Cards/CardsDndFooter/CardsDndFooter.tsx";
|
||||
import { Flex, rem, Stack } from "@mantine/core";
|
||||
import { DragDropContext } from "@hello-pangea/dnd";
|
||||
import useDnd from "../../../../pages/CardsPage/hooks/useDnd.tsx";
|
||||
import Status from "../Status/Status.tsx";
|
||||
import { EqualHeightsContextProvider } from "../Status/contexts/EqualHeightContext.tsx";
|
||||
import { useBoardsContext } from "../../../../contexts/BoardsContext.tsx";
|
||||
import { useDndContext } from "../../../../pages/CardsPage/contexts/DndContext.tsx";
|
||||
|
||||
|
||||
type Props = {
|
||||
selectedBoard: BoardSchema | null;
|
||||
summariesRaw: CardSummary[];
|
||||
refetchSummaries: () => void;
|
||||
refetchBoards: () => void;
|
||||
}
|
||||
const Statuses = () => {
|
||||
const { selectedBoard } = useBoardsContext();
|
||||
|
||||
const Statuses = ({
|
||||
selectedBoard,
|
||||
summariesRaw,
|
||||
refetchSummaries,
|
||||
refetchBoards,
|
||||
}: Props) => {
|
||||
const {
|
||||
summaries,
|
||||
dragState,
|
||||
onDragStart,
|
||||
onDragEnd,
|
||||
} = useDnd({
|
||||
selectedBoard,
|
||||
summariesRaw,
|
||||
refetchSummaries,
|
||||
refetchBoards,
|
||||
});
|
||||
} = useDndContext();
|
||||
|
||||
const statusDndColumn = (status: StatusSchema, index: number) => {
|
||||
const filteredSummaries = summaries.filter(
|
||||
@@ -45,9 +28,7 @@ const Statuses = ({
|
||||
summaries={filteredSummaries}
|
||||
index={index}
|
||||
status={status}
|
||||
board={selectedBoard}
|
||||
dragState={dragState}
|
||||
refetch={refetchBoards}
|
||||
/>
|
||||
<CardsDndColumn
|
||||
withCreateButton={index === 0}
|
||||
@@ -64,26 +45,21 @@ const Statuses = ({
|
||||
.sort((a, b) => a.ordinalNumber - b.ordinalNumber) ?? [];
|
||||
|
||||
return (
|
||||
<DragDropContext
|
||||
onDragStart={onDragStart}
|
||||
onDragEnd={onDragEnd}
|
||||
>
|
||||
<EqualHeightsContextProvider statuses={statuses}>
|
||||
<Flex
|
||||
justify={"space-between"}
|
||||
direction={"column"}
|
||||
>
|
||||
<Flex className={styles["statuses"]}>
|
||||
{selectedBoard &&
|
||||
statuses.map(((status: StatusSchema, index: number) => {
|
||||
return statusDndColumn(status, index);
|
||||
}))
|
||||
}
|
||||
</Flex>
|
||||
<CardsDndFooter dragState={dragState} />
|
||||
<EqualHeightsContextProvider statuses={statuses}>
|
||||
<Flex
|
||||
justify={"space-between"}
|
||||
direction={"column"}
|
||||
>
|
||||
<Flex className={styles["statuses"]}>
|
||||
{selectedBoard &&
|
||||
statuses.map(((status: StatusSchema, index: number) => {
|
||||
return statusDndColumn(status, index);
|
||||
}))
|
||||
}
|
||||
</Flex>
|
||||
</EqualHeightsContextProvider>
|
||||
</DragDropContext>
|
||||
<CardsDndFooter dragState={dragState} />
|
||||
</Flex>
|
||||
</EqualHeightsContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { DropResult } from "@hello-pangea/dnd";
|
||||
import { BoardSchema, StatusSchema, StatusService } from "../../../../../client";
|
||||
import { StatusSchema, StatusService } from "../../../../../client";
|
||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
||||
import { useBoardsContext } from "../../../../../contexts/BoardsContext.tsx";
|
||||
|
||||
type Props = {
|
||||
board: BoardSchema | null;
|
||||
refetch: () => void;
|
||||
}
|
||||
|
||||
const useStatusesDnd = ({ refetch, board }: Props) => {
|
||||
const useStatusesDnd = () => {
|
||||
const {
|
||||
refetchBoards,
|
||||
selectedBoard: board,
|
||||
} = useBoardsContext();
|
||||
|
||||
const updateStatusOrder = (status: StatusSchema, newOrdinalNumber: number) => {
|
||||
if (!board) return;
|
||||
|
||||
@@ -20,7 +22,7 @@ const useStatusesDnd = ({ refetch, board }: Props) => {
|
||||
})
|
||||
.then(({ ok, message }) => {
|
||||
if (!ok) notifications.error({ message });
|
||||
refetch();
|
||||
refetchBoards();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user