diff --git a/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx b/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx index 88bd2ec7e..99fbc4f99 100644 --- a/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx +++ b/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx @@ -6,49 +6,31 @@ import { PauseCircleOutlined } from "@ant-design/icons"; import { Card, Col, Row, Space, Tooltip } from "antd"; -import React, { useMemo, useCallback } from "react"; +import React, { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; import { DateTimeFormatter } from "../../utils/DateFormatter"; + import ProductionAlert from "../production-list-columns/production-list-columns.alert.component"; import ProductionListColumnProductionNote from "../production-list-columns/production-list-columns.productionnote.component"; import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component"; + import "./production-board-card.styles.scss"; import dayjs from "../../utils/day"; + import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component"; -/** - * Get the color of the card based on the total hours - * @param ssbuckets - * @param totalHrs - * @returns {{r: number, b: number, g: number}} - */ const cardColor = (ssbuckets, totalHrs) => { const bucket = ssbuckets.find((bucket) => bucket.gte <= totalHrs && (!bucket.lt || bucket.lt > totalHrs)); return bucket && bucket.color ? bucket.color.rgb || bucket.color : { r: 255, g: 255, b: 255 }; }; -/** - * Get the contrast color based on the background color - * @param bgColor - * @returns {string} - */ const getContrastYIQ = (bgColor) => (bgColor.r * 299 + bgColor.g * 587 + bgColor.b * 114) / 1000 >= 128 ? "black" : "white"; -/** - * Production Board Card component - * @param technician - * @param card - * @param bodyshop - * @param cardSettings - * @returns {Element} - * @constructor - */ export default function ProductionBoardCard({ technician, card, bodyshop, cardSettings }) { const { t } = useTranslation(); - const { metadata } = card; const employee_body = useMemo( @@ -90,9 +72,8 @@ export default function ProductionBoardCard({ technician, card, bodyshop, cardSe className="react-trello-card" size="small" style={{ - backgroundColor: - cardSettings && cardSettings.cardcolor && `rgba(${bgColor.r},${bgColor.g},${bgColor.b},${bgColor.a})`, - color: cardSettings && cardSettings.cardcolor && contrastYIQ, + backgroundColor: cardSettings?.cardcolor && `rgba(${bgColor.r},${bgColor.g},${bgColor.b},${bgColor.a})`, + color: cardSettings?.cardcolor && contrastYIQ, maxWidth: "250px", margin: "5px" }} diff --git a/client/src/components/production-board-kanban/production-board-kanban.component.jsx b/client/src/components/production-board-kanban/production-board-kanban.component.jsx index bffcf77f2..0d8172585 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.component.jsx +++ b/client/src/components/production-board-kanban/production-board-kanban.component.jsx @@ -3,7 +3,7 @@ import { useApolloClient } from "@apollo/client"; import Board from "../../components/trello-board/index"; import { Button, notification, Skeleton, Space, Statistic } from "antd"; import { PageHeader } from "@ant-design/pro-layout"; -import React, { useEffect, useMemo, useState } from "react"; +import React, { useEffect, useMemo, useState, useCallback } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -49,13 +49,11 @@ export function ProductionBoardKanbanComponent({ associationSettings }) { const [boardLanes, setBoardLanes] = useState({ lanes: [] }); - const [filter, setFilter] = useState({ search: "", employeeId: null }); const [loading, setLoading] = useState(true); const [isMoving, setIsMoving] = useState(false); const orientation = associationSettings?.kanban_settings?.orientation ? "vertical" : "horizontal"; - const { t } = useTranslation(); useEffect(() => { @@ -65,13 +63,12 @@ export function ProductionBoardKanbanComponent({ }, [associationSettings]); useEffect(() => { - const newBoardData = createFakeBoardData( + const newBoardData = createBoardData( [...bodyshop.md_ro_statuses.production_statuses, ...(bodyshop.md_ro_statuses.additional_board_statuses || [])], data, filter ); - // Build Board Lanes Data newBoardData.lanes = newBoardData.lanes.map((lane) => ({ ...lane, title: `${lane.title} (${lane.cards.length})` @@ -89,13 +86,7 @@ export function ProductionBoardKanbanComponent({ const client = useApolloClient(); - /** - * Get Card By ID - * @param data - * @param cardId - * @returns {*|any|null} - */ - const getCardByID = (data, cardId) => { + const getCardByID = useCallback((data, cardId) => { for (const lane of data.lanes) { for (const card of lane.cards) { if (card.id === cardId) { @@ -104,88 +95,90 @@ export function ProductionBoardKanbanComponent({ } } return null; - }; + }, []); - const onDragEnd = async ({ type, source, destination, draggableId }) => { - logImEXEvent("kanban_drag_end"); + const onDragEnd = useCallback( + async ({ type, source, destination, draggableId }) => { + logImEXEvent("kanban_drag_end"); - // Early gate, also if the card is already moving bail - if (!type || type !== "lane" || !source || !destination || isMoving) return; + if (!type || type !== "lane" || !source || !destination || isMoving) return; - setIsMoving(true); + setIsMoving(true); - const targetLane = boardLanes.lanes.find((lane) => lane.id === destination.droppableId); - const sourceLane = boardLanes.lanes.find((lane) => lane.id === source.droppableId); + const targetLane = boardLanes.lanes.find((lane) => lane.id === destination.droppableId); + const sourceLane = boardLanes.lanes.find((lane) => lane.id === source.droppableId); - const sameColumnTransfer = source.droppableId === destination.droppableId; - const sourceCard = getCardByID(boardLanes, draggableId); + const sameColumnTransfer = source.droppableId === destination.droppableId; + const sourceCard = getCardByID(boardLanes, draggableId); - const movedCardWillBeFirst = destination.index === 0; - const movedCardWillBeLast = destination.index > targetLane.cards.length - 1; + const movedCardWillBeFirst = destination.index === 0; + const movedCardWillBeLast = destination.index > targetLane.cards.length - 1; - 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]; - const newChildCard = movedCardWillBeLast - ? null - : targetLane.cards[ - sameColumnTransfer - ? destination.index - destination.index > 0 - ? destination.index - : destination.index + 1 - : destination.index - ]; + const newChildCard = movedCardWillBeLast + ? null + : targetLane.cards[ + sameColumnTransfer + ? destination.index - destination.index > 0 + ? destination.index + : destination.index + 1 + : destination.index + ]; - const oldChildCardNewParent = oldChildCard ? sourceCard.metadata.kanbanparent : null; + const oldChildCardNewParent = oldChildCard ? sourceCard.metadata.kanbanparent : null; - let movedCardNewKanbanParent; - if (movedCardWillBeFirst) { - movedCardNewKanbanParent = "-1"; - } else if (movedCardWillBeLast) { - movedCardNewKanbanParent = lastCardInTargetLane.id; - } else if (!!newChildCard) { - movedCardNewKanbanParent = newChildCard.metadata.kanbanparent; - } else { - console.log("==> !!!!!!Couldn't find a parent.!!!! <=="); - } - const newChildCardNewParent = newChildCard ? draggableId : null; - try { - const update = await client.mutate({ - mutation: generate_UPDATE_JOB_KANBAN( - oldChildCard ? oldChildCard.id : null, - oldChildCardNewParent, - draggableId, - movedCardNewKanbanParent, - targetLane.id, - newChildCard ? newChildCard.id : null, - newChildCardNewParent - ) - }); + let movedCardNewKanbanParent; + if (movedCardWillBeFirst) { + movedCardNewKanbanParent = "-1"; + } else if (movedCardWillBeLast) { + movedCardNewKanbanParent = lastCardInTargetLane.id; + } else if (!!newChildCard) { + movedCardNewKanbanParent = newChildCard.metadata.kanbanparent; + } else { + console.log("==> !!!!!!Couldn't find a parent.!!!! <=="); + } + const newChildCardNewParent = newChildCard ? draggableId : null; + try { + const update = await client.mutate({ + mutation: generate_UPDATE_JOB_KANBAN( + oldChildCard ? oldChildCard.id : null, + oldChildCardNewParent, + draggableId, + movedCardNewKanbanParent, + targetLane.id, + newChildCard ? newChildCard.id : null, + newChildCardNewParent + ) + }); - insertAuditTrail({ - jobid: draggableId, - operation: AuditTrailMapping.jobstatuschange(targetLane.id), - type: "jobstatuschange" - }); + insertAuditTrail({ + jobid: draggableId, + operation: AuditTrailMapping.jobstatuschange(targetLane.id), + type: "jobstatuschange" + }); - if (update.errors) { + if (update.errors) { + notification["error"]({ + message: t("production.errors.boardupdate", { + message: JSON.stringify(update.errors) + }) + }); + } + } catch (error) { notification["error"]({ message: t("production.errors.boardupdate", { - message: JSON.stringify(update.errors) + message: error.message }) }); + } finally { + setIsMoving(false); } - } catch (error) { - notification["error"]({ - message: t("production.errors.boardupdate", { - message: error.message - }) - }); - } finally { - setIsMoving(false); - } - }; + }, + [boardLanes, client, getCardByID, insertAuditTrail, isMoving, t] + ); const totalHrs = useMemo( () => @@ -209,36 +202,45 @@ export function ProductionBoardKanbanComponent({ [data] ); - const Header = ({ title }) => ( -