From 19dfec2a34cc6bad0b0757cb62b35a94ba7d02a2 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 21 May 2024 17:12:48 -0400 Subject: [PATCH] Board Container and Lane, the last remaining class components are now functional components utilizing up to date react stuff, defaultProps deprecation fixed (rolled into function decleration) Signed-off-by: Dave Richer --- .../controllers/BoardContainer.jsx | 201 +++++++++-------- .../trello-board/controllers/Lane.jsx | 204 ++++++++++-------- 2 files changed, 220 insertions(+), 185 deletions(-) diff --git a/client/src/components/trello-board/controllers/BoardContainer.jsx b/client/src/components/trello-board/controllers/BoardContainer.jsx index daa30cf7d..7761d2f23 100644 --- a/client/src/components/trello-board/controllers/BoardContainer.jsx +++ b/client/src/components/trello-board/controllers/BoardContainer.jsx @@ -9,42 +9,42 @@ import Lane from "./Lane"; import { PopoverWrapper } from "react-popopo"; import * as actions from "../../../redux/trello/trello.actions.js"; -const BoardContainer = (props) => { +const BoardContainer = ({ + id, + components, + data, + draggable = false, + laneDraggable = true, + laneDragClass = "react_trello_dragLaneClass", + laneDropClass = "react_trello_dragLaneDropClass", + style, + onDataChange = () => {}, + onCardAdd = () => {}, + onCardUpdate = () => {}, + onCardClick = () => {}, + onBeforeCardDelete = () => {}, + onCardDelete = () => {}, + onLaneScroll = () => {}, + onLaneClick = () => {}, + onLaneAdd = () => {}, + onLaneDelete = () => {}, + onLaneUpdate = () => {}, + editable = false, + canAddLanes = false, + laneStyle, + onCardMoveAcrossLanes = () => {}, + orientation = "horizontal", + eventBusHandle, + handleLaneDragStart = () => {}, + handleLaneDragEnd = () => {}, + reducerData, + cardStyle, + ...otherProps +}) => { const [addLaneMode, setAddLaneMode] = useState(false); - const { - id, - components, - data, - draggable, - laneDraggable, - laneDragClass, - laneDropClass, - style, - onDataChange, - onCardAdd, - onCardUpdate, - onCardClick, - onBeforeCardDelete, - onCardDelete, - onLaneScroll, - onLaneClick, - onLaneAdd, - onLaneDelete, - onLaneUpdate, - editable, - canAddLanes, - laneStyle, - onCardMoveAcrossLanes, - orientation, - eventBusHandle, - handleLaneDragStart, - handleLaneDragEnd, - ...otherProps - } = props; - const dispatch = useDispatch(); - const reducerData = useSelector((state) => (state.trello.lanes ? state.trello : {})); + const currentReducerData = useSelector((state) => (state.trello.lanes ? state.trello : {})); const groupName = `TrelloBoard${id}`; @@ -91,10 +91,10 @@ const BoardContainer = (props) => { }, [data, eventBusHandle, dispatch, wireEventBus]); useEffect(() => { - if (!isEqual(reducerData, props.reducerData)) { - onDataChange(reducerData); + if (!isEqual(currentReducerData, reducerData)) { + onDataChange(currentReducerData); } - }, [reducerData, props.reducerData, onDataChange]); + }, [currentReducerData, reducerData, onDataChange]); const onDragStart = useCallback( ({ payload }) => { @@ -115,16 +115,16 @@ const BoardContainer = (props) => { const getCardDetails = useCallback( (laneId, cardIndex) => { - return reducerData.lanes.find((lane) => lane.id === laneId).cards[cardIndex]; + return currentReducerData.lanes.find((lane) => lane.id === laneId).cards[cardIndex]; }, - [reducerData] + [currentReducerData] ); const getLaneDetails = useCallback( (index) => { - return reducerData.lanes[index]; + return currentReducerData.lanes[index]; }, - [reducerData] + [currentReducerData] ); const hideEditableLane = () => { @@ -141,31 +141,65 @@ const BoardContainer = (props) => { onLaneAdd(params); }; - const passThroughProps = pick(props, [ - "onCardMoveAcrossLanes", - "onLaneScroll", - "onLaneDelete", - "onLaneUpdate", - "onCardClick", - "onBeforeCardDelete", - "onCardDelete", - "onCardAdd", - "onCardUpdate", - "onLaneClick", - "laneSortFunction", - "draggable", - "laneDraggable", - "cardDraggable", - "collapsibleLanes", - "canAddLanes", - "hideCardDeleteIcon", - "tagStyle", - "handleDragStart", - "handleDragEnd", - "cardDragClass", - "editLaneTitle", - "orientation" - ]); + const passThroughProps = pick( + { + id, + components, + data, + draggable, + laneDraggable, + laneDragClass, + laneDropClass, + style, + onDataChange, + onCardAdd, + onCardUpdate, + onCardClick, + onBeforeCardDelete, + onCardDelete, + onLaneScroll, + onLaneClick, + onLaneAdd, + onLaneDelete, + onLaneUpdate, + editable, + canAddLanes, + laneStyle, + onCardMoveAcrossLanes, + orientation, + eventBusHandle, + handleLaneDragStart, + handleLaneDragEnd, + reducerData, + cardStyle, + ...otherProps + }, + [ + "onCardMoveAcrossLanes", + "onLaneScroll", + "onLaneDelete", + "onLaneUpdate", + "onCardClick", + "onBeforeCardDelete", + "onCardDelete", + "onCardAdd", + "onCardUpdate", + "onLaneClick", + "laneSortFunction", + "draggable", + "laneDraggable", + "cardDraggable", + "collapsibleLanes", + "canAddLanes", + "hideCardDeleteIcon", + "tagStyle", + "handleDragStart", + "handleDragEnd", + "cardDragClass", + "editLaneTitle", + "orientation" + ] + ); return ( @@ -180,8 +214,8 @@ const BoardContainer = (props) => { getChildPayload={(index) => getLaneDetails(index)} groupName={groupName} > - {reducerData.lanes.map((lane, index) => { - const { id, droppable, ...otherProps } = lane; + {currentReducerData.lanes.map((lane, index) => { + const { id, droppable, ...laneOtherProps } = lane; const laneToRender = ( { droppable={droppable === undefined ? true : droppable} style={laneStyle || lane.style || {}} labelStyle={lane.labelStyle || {}} - cardStyle={props.cardStyle || lane.cardStyle} + cardStyle={cardStyle || lane.cardStyle} editable={editable && !lane.disallowAddingCard} - {...otherProps} + {...laneOtherProps} {...passThroughProps} /> ); @@ -251,32 +285,9 @@ BoardContainer.propTypes = { cardDragClass: PropTypes.string, laneDragClass: PropTypes.string, laneDropClass: PropTypes.string, - onCardMoveAcrossLanes: PropTypes.func.isRequired, - orientation: PropTypes.string -}; - -BoardContainer.defaultProps = { - onDataChange: () => {}, - handleDragStart: () => {}, - handleDragEnd: () => {}, - handleLaneDragStart: () => {}, - handleLaneDragEnd: () => {}, - onCardUpdate: () => {}, - onLaneAdd: () => {}, - onLaneDelete: () => {}, - onCardMoveAcrossLanes: () => {}, - onLaneUpdate: () => {}, - editable: false, - canAddLanes: false, - hideCardDeleteIcon: false, - draggable: false, - collapsibleLanes: false, - laneDraggable: true, - cardDraggable: true, - cardDragClass: "react_trello_dragClass", - laneDragClass: "react_trello_dragLaneClass", - laneDropClass: "react_trello_dragLaneDropClass", - orientation: "horizontal" + onCardMoveAcrossLanes: PropTypes.func, + orientation: PropTypes.string, + cardStyle: PropTypes.object }; export default BoardContainer; diff --git a/client/src/components/trello-board/controllers/Lane.jsx b/client/src/components/trello-board/controllers/Lane.jsx index af821fe42..db875358d 100644 --- a/client/src/components/trello-board/controllers/Lane.jsx +++ b/client/src/components/trello-board/controllers/Lane.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useRef, useCallback, useMemo } from "react"; +import React, { useCallback, useEffect, useRef, useState } from "react"; import classNames from "classnames"; import PropTypes from "prop-types"; import { bindActionCreators } from "redux"; @@ -12,39 +12,51 @@ import Draggable from "../dnd/Draggable.jsx"; import * as actions from "../../../redux/trello/trello.actions.js"; -const defaultProps = { - style: {}, - titleStyle: {}, - labelStyle: {}, - label: undefined, - editable: false, - onLaneUpdate: () => {}, - onCardAdd: () => {}, - onCardUpdate: () => {}, - onCardDelete: () => {}, - onBeforeCardDelete: () => {}, - onLaneDelete: () => {}, - onLaneClick: () => {}, - onLaneScroll: () => {}, - onCardClick: () => {}, - onCardMoveAcrossLanes: () => {}, - draggable: false, - laneDraggable: false, - cardDraggable: true, - collapsibleLanes: false, - droppable: true, - canAddLanes: false, - hideCardDeleteIcon: false, - components: {}, - handleDragStart: () => {}, - handleDragEnd: () => {}, - orientation: "vertical" -}; - -const Lane = (internalProps) => { - const props = useMemo(() => ({ ...defaultProps, ...internalProps }), [internalProps]); +function Lane({ + actions, + id, + boardId, + title, + index, + laneSortFunction, + style = {}, + cardStyle = {}, + tagStyle = {}, + titleStyle = {}, + labelStyle = {}, + cards, + label, + draggable = false, + collapsibleLanes = false, + droppable = true, + onCardMoveAcrossLanes = () => {}, + onCardClick = () => {}, + onBeforeCardDelete = () => {}, + onCardDelete = () => {}, + onCardAdd = () => {}, + onCardUpdate = () => {}, + onLaneDelete = () => {}, + onLaneUpdate = () => {}, + onLaneClick = () => {}, + onLaneScroll = () => {}, + editable = false, + laneDraggable = false, + cardDraggable = true, + cardDragClass, + cardDropClass, + canAddLanes = false, + hideCardDeleteIcon = false, + components = {}, + getCardDetails, + handleDragStart = () => {}, + handleDragEnd = () => {}, + orientation = "vertical", + className, + currentPage, + ...otherProps +}) { const [loading, setLoading] = useState(false); - const [currentPage, setCurrentPage] = useState(props.currentPage); + const [currentPageFinal, setCurrentPageFinal] = useState(currentPage); const [addCardMode, setAddCardMode] = useState(false); const [collapsed, setCollapsed] = useState(false); const [isDraggingOver, setIsDraggingOver] = useState(false); @@ -52,23 +64,22 @@ const Lane = (internalProps) => { const laneRef = useRef(null); useEffect(() => { - if (!isEqual(props.cards, currentPage)) { - setCurrentPage(props.currentPage); + if (!isEqual(cards, currentPageFinal)) { + setCurrentPageFinal(currentPage); } - }, [props.cards, props.currentPage, currentPage]); + }, [cards, currentPage, currentPageFinal]); const handleScroll = useCallback( (evt) => { const node = evt.target; const elemScrollPosition = node.scrollHeight - node.scrollTop - node.clientHeight; - const { onLaneScroll } = props; if (elemScrollPosition < 1 && onLaneScroll && !loading) { - const nextPage = currentPage + 1; + const nextPage = currentPageFinal + 1; setLoading(true); - onLaneScroll(nextPage, props.id).then((moreCards) => { + onLaneScroll(nextPage, id).then((moreCards) => { if ((moreCards || []).length > 0) { - props.actions.paginateLane({ - laneId: props.id, + actions.paginateLane({ + laneId: id, newCards: moreCards, nextPage: nextPage }); @@ -77,7 +88,7 @@ const Lane = (internalProps) => { }); } }, - [currentPage, loading, props] + [currentPageFinal, loading, onLaneScroll, id, actions] ); useEffect(() => { @@ -99,19 +110,18 @@ const Lane = (internalProps) => { }; const removeCard = (cardId) => { - if (props.onBeforeCardDelete && typeof props.onBeforeCardDelete === "function") { - props.onBeforeCardDelete(() => { - props.onCardDelete && props.onCardDelete(cardId, props.id); - props.actions.removeCard({ laneId: props.id, cardId: cardId }); + if (onBeforeCardDelete && typeof onBeforeCardDelete === "function") { + onBeforeCardDelete(() => { + onCardDelete && onCardDelete(cardId, id); + actions.removeCard({ laneId: id, cardId: cardId }); }); } else { - props.onCardDelete && props.onCardDelete(cardId, props.id); - props.actions.removeCard({ laneId: props.id, cardId: cardId }); + onCardDelete && onCardDelete(cardId, id); + actions.removeCard({ laneId: id, cardId: cardId }); } }; const handleCardClick = (e, card) => { - const { onCardClick } = props; onCardClick && onCardClick(card.id, card.metadata, card.laneId); e.stopPropagation(); }; @@ -125,25 +135,23 @@ const Lane = (internalProps) => { }; const addNewCard = (params) => { - const laneId = props.id; - const id = v1(); + const laneId = id; + const newCardId = v1(); hideEditableCard(); - let card = { id, ...params }; - props.actions.addCard({ laneId, card }); - props.onCardAdd(card, laneId); + let card = { id: newCardId, ...params }; + actions.addCard({ laneId, card }); + onCardAdd(card, laneId); }; const onDragStart = ({ payload }) => { - const { handleDragStart } = props; handleDragStart && handleDragStart(payload.id, payload.laneId); }; const shouldAcceptDrop = (sourceContainerOptions) => { - return props.droppable && sourceContainerOptions.groupName === groupName; + return droppable && sourceContainerOptions.groupName === groupName; }; const onDragEnd = (laneId, result) => { - const { handleDragEnd } = props; const { addedIndex, payload } = result; if (isDraggingOver) { @@ -154,56 +162,40 @@ const Lane = (internalProps) => { const newCard = { ...cloneDeep(payload), laneId }; const response = handleDragEnd ? handleDragEnd(payload.id, payload.laneId, laneId, addedIndex, newCard) : true; if (response === undefined || !!response) { - props.actions.moveCardAcrossLanes({ + actions.moveCardAcrossLanes({ fromLaneId: payload.laneId, toLaneId: laneId, cardId: payload.id, index: addedIndex }); - props.onCardMoveAcrossLanes(payload.laneId, laneId, payload.id, addedIndex); + onCardMoveAcrossLanes(payload.laneId, laneId, payload.id, addedIndex); } return response; } }; const updateCard = (updatedCard) => { - props.actions.updateCard({ laneId: props.id, card: updatedCard }); - props.onCardUpdate(props.id, updatedCard); + actions.updateCard({ laneId: id, card: updatedCard }); + onCardUpdate(id, updatedCard); }; const removeLane = () => { - const { id } = props; - props.actions.removeLane({ laneId: id }); - props.onLaneDelete(id); + actions.removeLane({ laneId: id }); + onLaneDelete(id); }; const updateTitle = (value) => { - props.actions.updateLane({ id: props.id, title: value }); - props.onLaneUpdate(props.id, { title: value }); + actions.updateLane({ id, title: value }); + onLaneUpdate(id, { title: value }); }; const toggleLaneCollapsed = () => { - props.collapsibleLanes && setCollapsed(!collapsed); + collapsibleLanes && setCollapsed(!collapsed); }; - const groupName = `TrelloBoard${props.boardId}Lane`; + const groupName = `TrelloBoard${boardId}Lane`; const renderDragContainer = (isDraggingOver) => { - const { - id, - cards, - laneSortFunction, - editable, - hideCardDeleteIcon, - cardDraggable, - cardDragClass, - cardDropClass, - tagStyle, - cardStyle, - components, - orientation - } = props; - const stableCards = collapsed ? [] : cards; const cardList = sortCards(stableCards, laneSortFunction).map((card, idx) => { @@ -243,7 +235,7 @@ const Lane = (internalProps) => { onDragEnter={() => setIsDraggingOver(true)} onDragLeave={() => setIsDraggingOver(false)} shouldAcceptDrop={shouldAcceptDrop} - getChildPayload={(index) => props.getCardDetails(id, index)} + getChildPayload={(index) => getCardDetails(id, index)} > {cardList} @@ -254,7 +246,6 @@ const Lane = (internalProps) => { }; const renderHeader = (pickedProps) => { - const { components } = props; return ( { ); }; - const { id, cards, collapsibleLanes, components, onLaneClick, orientation, ...otherProps } = props; - const allClassNames = classNames("react-trello-lane", collapsed ? "lane-collapsed" : "", props.className || ""); + const allClassNames = classNames("react-trello-lane", collapsed ? "lane-collapsed" : "", className || ""); const showFooter = collapsibleLanes && cards.length > 0; - // Removed the ...otherProps spread from the components.Section + const passedProps = { + actions, + id, + boardId, + title, + index, + laneSortFunction, + style, + cardStyle, + tagStyle, + titleStyle, + labelStyle, + cards, + label, + draggable, + collapsibleLanes, + droppable, + editable, + laneDraggable, + cardDraggable, + cardDragClass, + cardDropClass, + canAddLanes, + hideCardDeleteIcon, + components, + getCardDetails, + handleDragStart, + handleDragEnd, + orientation, + className, + currentPage, + ...otherProps + }; + return ( { draggable={false} className={allClassNames} orientation={orientation} + {...passedProps} > - {renderHeader({ id, cards, ...otherProps })} + {renderHeader({ id, cards, ...passedProps })} {renderDragContainer(isDraggingOver)} {loading && } {showFooter && } ); -}; +} Lane.propTypes = { actions: PropTypes.object,