- Clear stage (progress update), moving branches to verify some outputs.

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-06-19 14:06:39 -04:00
parent b0a5f2d998
commit 36f7b7a1a1
5 changed files with 119 additions and 91 deletions

View File

@@ -3,7 +3,7 @@ import { useApolloClient } from "@apollo/client";
import Board from "../../components/trello-board/index"; import Board from "../../components/trello-board/index";
import { Button, Grid, notification, Skeleton, Space, Statistic } from "antd"; import { Button, Grid, notification, Skeleton, Space, Statistic } from "antd";
import { PageHeader } from "@ant-design/pro-layout"; import { PageHeader } from "@ant-design/pro-layout";
import React, { useEffect, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Sticky, StickyContainer } from "react-sticky"; import { Sticky, StickyContainer } from "react-sticky";
@@ -71,14 +71,11 @@ export function ProductionBoardKanbanComponent({
); );
let idx = 0; let idx = 0;
const newCardIndexMappings = {};
// Build Board Lanes Data // Build Board Lanes Data
boardData.lanes = boardData.lanes.map((lane, laneIndex) => { boardData.lanes = boardData.lanes.map((lane, laneIndex) => {
const cardsWithIndex = lane.cards.map((card, cardIndex) => { const cardsWithIndex = lane.cards.map((card, cardIndex) => {
const cardWithIndex = { ...card, idx, lane: lane.id, cardIndex, laneIndex }; const cardWithIndex = { ...card, idx, lane: lane.id, cardIndex, laneIndex };
newCardIndexMappings[idx] = { laneIndex, cardIndex };
idx++; idx++;
return cardWithIndex; return cardWithIndex;
}); });
@@ -130,21 +127,10 @@ export function ProductionBoardKanbanComponent({
const sourceLane = boardLanes.lanes[Number.parseInt(source.droppableId)]; const sourceLane = boardLanes.lanes[Number.parseInt(source.droppableId)];
const sourceCard = getCardByID(boardLanes, draggableId); const sourceCard = getCardByID(boardLanes, draggableId);
console.dir({
sameColumnTransfer,
targetLane,
sourceLane,
sourceCard,
destination
});
const movedCardWillBeFirst = destination.index === 0; const movedCardWillBeFirst = destination.index === 0;
const movedCardWillBeLast = destination.index > targetLane.cards.length - 1; const movedCardWillBeLast = destination.index > targetLane.cards.length - 1;
const movedCardIsFirstNewCard = movedCardWillBeFirst && movedCardWillBeLast; const movedCardIsFirstNewCard = movedCardWillBeFirst && movedCardWillBeLast;
console.log("movedCardWillBeFirst, movedCardWillBeLast");
console.dir({ movedCardWillBeFirst, movedCardWillBeLast, movedCardIsFirstNewCard });
const lastCardInTargetLane = targetLane.cards[targetLane.cards.length - 1]; const lastCardInTargetLane = targetLane.cards[targetLane.cards.length - 1];
const oldChildCard = sourceLane.cards[destination.index + 1]; const oldChildCard = sourceLane.cards[destination.index + 1];
@@ -162,13 +148,6 @@ export function ProductionBoardKanbanComponent({
const oldChildCardNewParent = oldChildCard ? sourceCard.metadata.kanbanparent : null; const oldChildCardNewParent = oldChildCard ? sourceCard.metadata.kanbanparent : null;
console.dir({
lastCardInTargetLane,
oldChildCard,
newChildCard,
oldChildCardNewParent
});
let movedCardNewKanbanParent; let movedCardNewKanbanParent;
if (movedCardWillBeFirst) { if (movedCardWillBeFirst) {
movedCardNewKanbanParent = "-1"; movedCardNewKanbanParent = "-1";
@@ -217,14 +196,28 @@ export function ProductionBoardKanbanComponent({
} }
}; };
const totalHrs = data const totalHrs = useMemo(
.reduce( () =>
(acc, val) => acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0) + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0), data
0 .reduce(
) (acc, val) =>
.toFixed(1); acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0) + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0),
const totalLAB = data.reduce((acc, val) => acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1); 0
const totalLAR = data.reduce((acc, val) => acc + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1); )
.toFixed(1),
[data]
);
const totalLAB = useMemo(
() => data.reduce((acc, val) => acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1),
[data]
);
const totalLAR = useMemo(
() => data.reduce((acc, val) => acc + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1),
[data]
);
const selectedBreakpoint = Object.entries(Grid.useBreakpoint()) const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
.filter((screen) => !!screen[1]) .filter((screen) => !!screen[1])
.slice(-1)[0]; .slice(-1)[0];
@@ -353,7 +346,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(ProductionBoardKanba
const Container = styled.div` const Container = styled.div`
.react-trello-card-skeleton, .react-trello-card-skeleton,
.react-trel lo-card, .react-trello-card,
.react-trello-card-adder-form { .react-trello-card-adder-form {
box-sizing: border-box; box-sizing: border-box;
max-width: ${(props) => props.width}px; max-width: ${(props) => props.width}px;

View File

@@ -8,6 +8,7 @@ import isEqual from "lodash/isEqual";
import Lane from "./Lane"; import Lane from "./Lane";
import { PopoverWrapper } from "react-popopo"; import { PopoverWrapper } from "react-popopo";
import * as actions from "../../../redux/trello/trello.actions.js"; import * as actions from "../../../redux/trello/trello.actions.js";
import { isFunction } from "lodash";
/** /**
* BoardContainer is a React component that represents a Trello-like board. * BoardContainer is a React component that represents a Trello-like board.
@@ -234,11 +235,34 @@ const BoardContainer = ({
] ]
); );
const onLaneDrag = ({ draggableId, type, source, reason, mode, destination, combine }) => {
if (!type || type !== "lane" || !source || !destination) return;
dispatch(
actions.moveCardAcrossLanes({
fromLaneId: Number.parseInt(source.droppableId),
toLaneId: Number.parseInt(destination.droppableId),
cardId: draggableId,
index: destination.index
})
);
// onCardMoveAcrossLanes(payload.laneId, laneId, payload.id, addedIndex);
};
const combinedDragEnd = (...params) => {
// Early Gate
if (!params || !params[0]) return;
onLaneDrag(params[0]);
if (isFunction(onDragEnd)) {
onDragEnd(params[0]);
}
};
return ( return (
<components.BoardWrapper style={style} orientation={orientation} draggable={false}> <components.BoardWrapper style={style} orientation={orientation} draggable={false}>
<PopoverWrapper> <PopoverWrapper>
<DragDropContext <DragDropContext
onDragEnd={onDragEnd} onDragEnd={combinedDragEnd}
onDragUpdate={onDragUpdate} onDragUpdate={onDragUpdate}
onDragStart={onDragStart} onDragStart={onDragStart}
onBeforeDragStart={onBeforeDragStart} onBeforeDragStart={onBeforeDragStart}

View File

@@ -32,7 +32,6 @@ import { Droppable, Draggable } from "../dnd/lib/index.js";
* @param {boolean} props.draggable - Whether the lane is draggable * @param {boolean} props.draggable - Whether the lane is draggable
* @param {boolean} props.collapsibleLanes - Whether the lanes are collapsible * @param {boolean} props.collapsibleLanes - Whether the lanes are collapsible
* @param {boolean} props.droppable - Whether the lane is droppable * @param {boolean} props.droppable - Whether the lane is droppable
* @param {Function} props.onCardMoveAcrossLanes - Callback function when a card is moved across lanes
* @param {Function} props.onCardClick - Callback function when a card is clicked * @param {Function} props.onCardClick - Callback function when a card is clicked
* @param {Function} props.onBeforeCardDelete - Callback function before a card is deleted * @param {Function} props.onBeforeCardDelete - Callback function before a card is deleted
* @param {Function} props.onCardDelete - Callback function when a card is deleted * @param {Function} props.onCardDelete - Callback function when a card is deleted
@@ -75,7 +74,6 @@ function Lane({
draggable = false, draggable = false,
collapsibleLanes = false, collapsibleLanes = false,
droppable = true, droppable = true,
onCardMoveAcrossLanes = () => {},
onCardClick = () => {}, onCardClick = () => {},
onBeforeCardDelete = () => {}, onBeforeCardDelete = () => {},
onCardDelete = () => {}, onCardDelete = () => {},
@@ -206,29 +204,6 @@ function Lane({
return droppable && sourceContainerOptions.groupName === groupName; return droppable && sourceContainerOptions.groupName === groupName;
}; };
const onDragEnd = (laneId, result) => {
const { addedIndex, payload } = result;
if (isDraggingOver) {
setIsDraggingOver(false);
}
if (addedIndex != null) {
const newCard = { ...cloneDeep(payload), laneId };
const response = handleDragEnd ? handleDragEnd(payload.id, payload.laneId, laneId, addedIndex, newCard) : true;
if (response === undefined || !!response) {
actions.moveCardAcrossLanes({
fromLaneId: payload.laneId,
toLaneId: laneId,
cardId: payload.id,
index: addedIndex
});
onCardMoveAcrossLanes(payload.laneId, laneId, payload.id, addedIndex);
}
return response;
}
};
const updateCard = (updatedCard) => { const updateCard = (updatedCard) => {
actions.updateCard({ laneId: id, card: updatedCard }); actions.updateCard({ laneId: id, card: updatedCard });
onCardUpdate(id, updatedCard); onCardUpdate(id, updatedCard);
@@ -396,7 +371,6 @@ Lane.propTypes = {
draggable: PropTypes.bool, draggable: PropTypes.bool,
collapsibleLanes: PropTypes.bool, collapsibleLanes: PropTypes.bool,
droppable: PropTypes.bool, droppable: PropTypes.bool,
onCardMoveAcrossLanes: PropTypes.func,
onCardClick: PropTypes.func, onCardClick: PropTypes.func,
onBeforeCardDelete: PropTypes.func, onBeforeCardDelete: PropTypes.func,
onCardDelete: PropTypes.func, onCardDelete: PropTypes.func,

View File

@@ -1,7 +1,7 @@
import update from "immutability-helper"; import update from "immutability-helper";
import cloneDeep from "lodash/cloneDeep";
const updateLanes = (state, lanes) => update(state, { lanes: { $set: lanes } }); const updateLanes = (state, lanes) => update(state, { lanes: { $set: lanes } });
const updateLaneCards = (lane, cards) => update(lane, { cards: { $set: cards } }); const updateLaneCards = (lane, cards) => update(lane, { cards: { $set: cards } });
const LaneHelper = { const LaneHelper = {
@@ -53,42 +53,78 @@ const LaneHelper = {
return updateLanes(state, newLanes); return updateLanes(state, newLanes);
}, },
// TODO: Unverified, needs to be hoisted.
removeCardFromLane: (state, { laneId, cardId }) => { removeCardFromLane: (state, { laneId, cardId }) => {
const lanes = state.lanes.map((lane) => { // Clone the state to avoid mutation
if (lane.id === laneId) { const newLanes = cloneDeep(state.lanes);
const newCards = lane.cards.filter((card) => card.id !== cardId);
return updateLaneCards(lane, newCards); // Find the lane from which the card will be removed
} else { const lane = newLanes.find((lane) => lane.id === laneId);
return lane;
} // Find the card in the lane
const cardIndex = lane.cards.findIndex((card) => card.id === cardId);
if (cardIndex === -1) {
throw new Error("Card not found in the lane");
}
// Remove the card from the lane
lane.cards.splice(cardIndex, 1);
let idx = 0;
// Update the lane and card indexes for all lanes
newLanes.forEach((lane, laneIndex) => {
lane.cards.forEach((card, cardIndex) => {
card.idx = idx;
card.laneIndex = laneIndex;
card.cardIndex = cardIndex;
card.laneId = lane.id;
idx++;
});
});
return update(state, {
lanes: { $set: newLanes }
}); });
return updateLanes(state, lanes);
}, },
moveCardAcrossLanes: (state, ...params) => { // TODO: This has been updated to new DND Lib, verified.
console.log("state"); moveCardAcrossLanes: (state, { fromLaneId, toLaneId, cardId, index }) => {
console.dir(state); // Clone the state to avoid mutation
console.log("params"); const newLanes = cloneDeep(state.lanes);
console.dir(params);
// let cardToMove = null; // Find the source and destination lanes using the lane indices
// const interimLanes = state.lanes.map((lane) => { const fromLane = newLanes[fromLaneId];
// if (lane.id === fromLaneId) { const toLane = newLanes[toLaneId];
// cardToMove = lane.cards.find((card) => card.id === cardId);
// const newCards = lane.cards.filter((card) => card.id !== cardId); // Find the card in the source lane
// return updateLaneCards(lane, newCards); const cardIndex = fromLane.cards.findIndex((card) => card.id === cardId);
// } else { if (cardIndex === -1) {
// return lane; throw new Error("Card not found in the source lane");
// } }
// });
// return LaneHelper.appendCardToLane( // Remove the card from the source lane
// { ...state, lanes: interimLanes }, const [card] = fromLane.cards.splice(cardIndex, 1);
// {
// laneId: toLaneId, // Insert the card into the destination lane at the specified index
// card: cardToMove, toLane.cards.splice(index, 0, card);
// index: index
// } let idx = 0;
// );
return state; // Update the lane and card indexes for all lanes
newLanes.forEach((lane, laneIndex) => {
lane.cards.forEach((card, cardIndex) => {
card.idx = idx;
card.laneIndex = laneIndex;
card.cardIndex = cardIndex;
card.laneId = lane.id;
idx++;
});
});
return update(state, {
lanes: { $set: newLanes }
});
}, },
updateCardsForLane: (state, { laneId, cards }) => { updateCardsForLane: (state, { laneId, cards }) => {

View File

@@ -7,6 +7,7 @@ const getBoardWrapperStyles = (props) => {
} }
if (props.orientation === "horizontal") { if (props.orientation === "horizontal") {
// TODO: The white-space: nowrap; would be a good place to offer further customization // TODO: The white-space: nowrap; would be a good place to offer further customization
// This will be put in the lane settings and marked as 'Horizontal Wrapping'
return ` return `
display: flex; display: flex;
flex-direction: row; flex-direction: row;