- Checkpoint (Major Bug Fixed)
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -6,7 +6,7 @@ import {
|
|||||||
PauseCircleOutlined
|
PauseCircleOutlined
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { Card, Col, Row, Space, Tooltip } from "antd";
|
import { Card, Col, Row, Space, Tooltip } from "antd";
|
||||||
import React, { useMemo } from "react";
|
import React, { useMemo, useCallback } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||||
@@ -26,14 +26,7 @@ import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.c
|
|||||||
*/
|
*/
|
||||||
const cardColor = (ssbuckets, totalHrs) => {
|
const cardColor = (ssbuckets, totalHrs) => {
|
||||||
const bucket = ssbuckets.find((bucket) => bucket.gte <= totalHrs && (!bucket.lt || bucket.lt > 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 };
|
||||||
let color = { r: 255, g: 255, b: 255 };
|
|
||||||
|
|
||||||
if (bucket && bucket.color) {
|
|
||||||
color = bucket.color.rgb || bucket.color;
|
|
||||||
}
|
|
||||||
|
|
||||||
return color;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,31 +49,32 @@ const getContrastYIQ = (bgColor) =>
|
|||||||
export default function ProductionBoardCard({ technician, card, bodyshop, cardSettings }) {
|
export default function ProductionBoardCard({ technician, card, bodyshop, cardSettings }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
let employee_body, employee_prep, employee_refinish, employee_csr;
|
|
||||||
|
|
||||||
// Destructure metadata
|
|
||||||
const { metadata } = card;
|
const { metadata } = card;
|
||||||
|
|
||||||
if (metadata?.employee_body) {
|
const employee_body = useMemo(
|
||||||
employee_body = bodyshop.employees.find((e) => e.id === metadata.employee_body);
|
() => metadata?.employee_body && bodyshop.employees.find((e) => e.id === metadata.employee_body),
|
||||||
}
|
[metadata?.employee_body, bodyshop.employees]
|
||||||
if (metadata?.employee_prep) {
|
);
|
||||||
employee_prep = bodyshop.employees.find((e) => e.id === metadata.employee_prep);
|
const employee_prep = useMemo(
|
||||||
}
|
() => metadata?.employee_prep && bodyshop.employees.find((e) => e.id === metadata.employee_prep),
|
||||||
if (metadata?.employee_refinish) {
|
[metadata?.employee_prep, bodyshop.employees]
|
||||||
employee_refinish = bodyshop.employees.find((e) => e.id === metadata.employee_refinish);
|
);
|
||||||
}
|
const employee_refinish = useMemo(
|
||||||
if (metadata?.employee_csr) {
|
() => metadata?.employee_refinish && bodyshop.employees.find((e) => e.id === metadata.employee_refinish),
|
||||||
employee_csr = bodyshop.employees.find((e) => e.id === metadata.employee_csr);
|
[metadata?.employee_refinish, bodyshop.employees]
|
||||||
}
|
);
|
||||||
// if (metadata.?employee_csr) {
|
const employee_csr = useMemo(
|
||||||
// employee_csr = bodyshop.employees.find((e) => e.id === metadata.employee_csr);
|
() => metadata?.employee_csr && bodyshop.employees.find((e) => e.id === metadata.employee_csr),
|
||||||
// }
|
[metadata?.employee_csr, bodyshop.employees]
|
||||||
|
);
|
||||||
|
|
||||||
const pastDueAlert =
|
const pastDueAlert = useMemo(() => {
|
||||||
!!metadata?.scheduled_completion &&
|
if (!metadata?.scheduled_completion) return null;
|
||||||
((dayjs().isSameOrAfter(dayjs(metadata.scheduled_completion), "day") && "production-completion-past") ||
|
const completionDate = dayjs(metadata.scheduled_completion);
|
||||||
(dayjs().add(1, "day").isSame(dayjs(metadata.scheduled_completion), "day") && "production-completion-soon"));
|
if (dayjs().isSameOrAfter(completionDate, "day")) return "production-completion-past";
|
||||||
|
if (dayjs().add(1, "day").isSame(completionDate, "day")) return "production-completion-soon";
|
||||||
|
return null;
|
||||||
|
}, [metadata?.scheduled_completion]);
|
||||||
|
|
||||||
const totalHrs = useMemo(() => {
|
const totalHrs = useMemo(() => {
|
||||||
return metadata?.labhrs && metadata?.larhrs
|
return metadata?.labhrs && metadata?.larhrs
|
||||||
@@ -125,9 +119,9 @@ export default function ProductionBoardCard({ technician, card, bodyshop, cardSe
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Row>
|
<Row>
|
||||||
{cardSettings && cardSettings.ownr_nm && (
|
{cardSettings?.ownr_nm && (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
{cardSettings && cardSettings.compact ? (
|
{cardSettings.compact ? (
|
||||||
<div className="ellipses">{`${metadata.ownr_ln || ""} ${metadata.ownr_co_nm || ""}`}</div>
|
<div className="ellipses">{`${metadata.ownr_ln || ""} ${metadata.ownr_co_nm || ""}`}</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="ellipses">
|
<div className="ellipses">
|
||||||
@@ -136,97 +130,79 @@ export default function ProductionBoardCard({ technician, card, bodyshop, cardSe
|
|||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
{cardSettings && cardSettings.model_info && (
|
{cardSettings?.model_info && (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<div className="ellipses">{`${metadata.v_model_yr || ""} ${
|
<div className="ellipses">{`${metadata.v_model_yr || ""} ${metadata.v_make_desc || ""} ${metadata.v_model_desc || ""}`}</div>
|
||||||
metadata.v_make_desc || ""
|
|
||||||
} ${metadata.v_model_desc || ""}`}</div>
|
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
|
{cardSettings?.ins_co_nm && metadata.ins_co_nm && (
|
||||||
{cardSettings && cardSettings.ins_co_nm && metadata.ins_co_nm && (
|
<Col span={cardSettings.compact ? 24 : 12}>
|
||||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>
|
|
||||||
<div className="ellipses">{metadata.ins_co_nm || ""}</div>
|
<div className="ellipses">{metadata.ins_co_nm || ""}</div>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
{cardSettings && cardSettings.clm_no && metadata.clm_no && (
|
{cardSettings?.clm_no && metadata.clm_no && (
|
||||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>
|
<Col span={cardSettings.compact ? 24 : 12}>
|
||||||
<div className="ellipses">{metadata.clm_no || ""}</div>
|
<div className="ellipses">{metadata.clm_no || ""}</div>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
|
{cardSettings?.employeeassignments && (
|
||||||
{cardSettings && cardSettings.employeeassignments && (
|
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Row>
|
<Row>
|
||||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`B: ${
|
<Col span={cardSettings.compact ? 24 : 12}>{`B: ${
|
||||||
employee_body ? `${employee_body.first_name.substr(0, 3)} ${employee_body.last_name.charAt(0)}` : ""
|
employee_body ? `${employee_body.first_name.substr(0, 3)} ${employee_body.last_name.charAt(0)}` : ""
|
||||||
} ${metadata.labhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</Col>
|
} ${metadata.labhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</Col>
|
||||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`P: ${
|
<Col span={cardSettings.compact ? 24 : 12}>{`P: ${
|
||||||
employee_prep ? `${employee_prep.first_name.substr(0, 3)} ${employee_prep.last_name.charAt(0)}` : ""
|
employee_prep ? `${employee_prep.first_name.substr(0, 3)} ${employee_prep.last_name.charAt(0)}` : ""
|
||||||
}`}</Col>
|
}`}</Col>
|
||||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`R: ${
|
<Col span={cardSettings.compact ? 24 : 12}>{`R: ${
|
||||||
employee_refinish
|
employee_refinish
|
||||||
? `${employee_refinish.first_name.substr(0, 3)} ${employee_refinish.last_name.charAt(0)}`
|
? `${employee_refinish.first_name.substr(0, 3)} ${employee_refinish.last_name.charAt(0)}`
|
||||||
: ""
|
: ""
|
||||||
} ${metadata.larhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</Col>
|
} ${metadata.larhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</Col>
|
||||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`C: ${
|
<Col span={cardSettings.compact ? 24 : 12}>{`C: ${
|
||||||
employee_csr ? `${employee_csr.first_name} ${employee_csr.last_name}` : ""
|
employee_csr ? `${employee_csr.first_name} ${employee_csr.last_name}` : ""
|
||||||
}`}</Col>
|
}`}</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
{/* {cardSettings && cardSettings.laborhrs && (
|
{cardSettings?.actual_in && metadata.actual_in && (
|
||||||
<Col span={24}>
|
<Col span={cardSettings.compact ? 24 : 12}>
|
||||||
<Row>
|
|
||||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`B: ${
|
|
||||||
metadata.labhrs.aggregate.sum.mod_lb_hrs || "?"
|
|
||||||
} hrs`}</Col>
|
|
||||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`R: ${
|
|
||||||
metadata.larhrs.aggregate.sum.mod_lb_hrs || "?"
|
|
||||||
} hrs`}</Col>
|
|
||||||
</Row>
|
|
||||||
</Col>
|
|
||||||
)} */}
|
|
||||||
{cardSettings && cardSettings.actual_in && metadata.actual_in && (
|
|
||||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>
|
|
||||||
<Space>
|
<Space>
|
||||||
<DownloadOutlined />
|
<DownloadOutlined />
|
||||||
<DateTimeFormatter format="MM/DD">{metadata.actual_in}</DateTimeFormatter>
|
<DateTimeFormatter format="MM/DD">{metadata.actual_in}</DateTimeFormatter>
|
||||||
</Space>
|
</Space>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
{cardSettings && cardSettings.scheduled_completion && metadata.scheduled_completion && (
|
{cardSettings?.scheduled_completion && metadata.scheduled_completion && (
|
||||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>
|
<Col span={cardSettings.compact ? 24 : 12}>
|
||||||
<Space className={pastDueAlert}>
|
<Space className={pastDueAlert}>
|
||||||
<CalendarOutlined />
|
<CalendarOutlined />
|
||||||
<DateTimeFormatter format="MM/DD">{metadata.scheduled_completion}</DateTimeFormatter>
|
<DateTimeFormatter format="MM/DD">{metadata.scheduled_completion}</DateTimeFormatter>
|
||||||
</Space>
|
</Space>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
{cardSettings && cardSettings.ats && metadata.alt_transport && (
|
{cardSettings?.ats && metadata.alt_transport && (
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<div>{metadata.alt_transport || ""}</div>
|
<div>{metadata.alt_transport || ""}</div>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
{cardSettings && cardSettings.sublets && (
|
{cardSettings?.sublets && (
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<ProductionSubletsManageComponent subletJobLines={metadata.subletLines} />
|
<ProductionSubletsManageComponent subletJobLines={metadata.subletLines} />
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
{cardSettings && cardSettings.production_note && (
|
{cardSettings?.production_note && (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
{cardSettings && cardSettings.production_note && (
|
<ProductionListColumnProductionNote
|
||||||
<ProductionListColumnProductionNote
|
record={{
|
||||||
record={{
|
production_vars: card?.metadata.production_vars,
|
||||||
production_vars: card?.metadata.production_vars,
|
id: card?.id,
|
||||||
id: card?.id,
|
refetch: card?.refetch
|
||||||
refetch: card?.refetch
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
{cardSettings && cardSettings.partsstatus && (
|
{cardSettings?.partsstatus && (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<JobPartsQueueCount parts={metadata.joblines_status} />
|
<JobPartsQueueCount parts={metadata.joblines_status} />
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { groupBy } from "lodash";
|
import { groupBy } from "lodash";
|
||||||
import fakeData from "./testData/board600.json";
|
import fakeData from "./testData/board1200.json";
|
||||||
|
|
||||||
const sortByParentId = (arr) => {
|
const sortByParentId = (arr) => {
|
||||||
// return arr.reduce((accumulator, currentValue) => {
|
// return arr.reduce((accumulator, currentValue) => {
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ const Lane = ({
|
|||||||
|
|
||||||
const Card = React.memo(({ provided, item: card, isDragging }) => {
|
const Card = React.memo(({ provided, item: card, isDragging }) => {
|
||||||
const onDeleteCard = () => removeCard(card.id);
|
const onDeleteCard = () => removeCard(card.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
{...provided.draggableProps}
|
{...provided.draggableProps}
|
||||||
@@ -209,11 +210,18 @@ const Lane = ({
|
|||||||
* @param item
|
* @param item
|
||||||
* @returns {React.JSX.Element}
|
* @returns {React.JSX.Element}
|
||||||
*/
|
*/
|
||||||
const renderDraggable = (index, item) => (
|
const renderDraggable = (index, item) => {
|
||||||
<Draggable draggableId={item.id} index={index} key={item.id}>
|
if (!item) {
|
||||||
{(provided, snapshot) => <Card provided={provided} item={item} isDragging={snapshot.isDragging} />}
|
console.log("null Item");
|
||||||
</Draggable>
|
return null;
|
||||||
);
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Draggable draggableId={item.id} index={index} key={item.id}>
|
||||||
|
{(provided, snapshot) => <Card provided={provided} item={item} isDragging={snapshot.isDragging} />}
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const renderAddCardLink = useCallback(
|
const renderAddCardLink = useCallback(
|
||||||
() => editable && !addCardMode && <components.AddCardLink onClick={showEditableCard} laneId={id} />,
|
() => editable && !addCardMode && <components.AddCardLink onClick={showEditableCard} laneId={id} />,
|
||||||
@@ -231,44 +239,13 @@ const Lane = ({
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flex: 1,
|
flex: 1,
|
||||||
whiteSpace: "wrap"
|
whiteSpace: "nowrap"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Components for the grid layout
|
|
||||||
* @type {{Item: (function({children: *, [p: string]: *}): *), List: React.ForwardRefExoticComponent<React.PropsWithoutRef<{readonly children?: *, readonly style?: *}> & React.RefAttributes<unknown>>}}
|
|
||||||
*/
|
|
||||||
const gridComponents = {
|
|
||||||
List: forwardRef(({ style, children, ...props }, ref) => (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexWrap: "wrap",
|
|
||||||
...style
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)),
|
|
||||||
Item: ({ children, ...props }) => (
|
|
||||||
<div
|
|
||||||
{...props}
|
|
||||||
style={{
|
|
||||||
alignContent: "stretch",
|
|
||||||
boxSizing: "border-box"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the droppable component with the provided cards and the provided props from react-beautiful-dnd
|
* Render the droppable component with the provided cards and the provided props from react-beautiful-dnd
|
||||||
* @param provided
|
* @param provided
|
||||||
@@ -291,7 +268,35 @@ const Lane = ({
|
|||||||
scrollerRef: provided.innerRef,
|
scrollerRef: provided.innerRef,
|
||||||
listClassName: "grid-container",
|
listClassName: "grid-container",
|
||||||
itemClassName: "grid-item",
|
itemClassName: "grid-item",
|
||||||
components: gridComponents,
|
components: {
|
||||||
|
List: forwardRef(({ style, children, ...props }, ref) => (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
...style
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)),
|
||||||
|
Item: ({ children, ...props }) => (
|
||||||
|
<div
|
||||||
|
{...props}
|
||||||
|
style={{
|
||||||
|
width: 252, // TODO: THIS IS THE LINE THAT CONTROLS IT ALL
|
||||||
|
display: "flex",
|
||||||
|
flex: "none",
|
||||||
|
alignContent: "stretch",
|
||||||
|
boxSizing: "border-box"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
itemContent: (index, item) => <ItemWrapper>{renderDraggable(index, item)}</ItemWrapper>
|
itemContent: (index, item) => <ItemWrapper>{renderDraggable(index, item)}</ItemWrapper>
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
@@ -306,16 +311,18 @@ const Lane = ({
|
|||||||
};
|
};
|
||||||
const finalComponentProps = collapsed ? {} : componentProps;
|
const finalComponentProps = collapsed ? {} : componentProps;
|
||||||
return (
|
return (
|
||||||
<div
|
<div>
|
||||||
{...provided.droppableProps}
|
<div
|
||||||
ref={provided.innerRef}
|
{...provided.droppableProps}
|
||||||
className={allClassNames}
|
ref={provided.innerRef}
|
||||||
style={{ ...provided.droppableProps.style }}
|
className={allClassNames}
|
||||||
>
|
style={{ ...provided.droppableProps.style }}
|
||||||
<FinalComponent {...finalComponentProps} />
|
>
|
||||||
|
<FinalComponent {...finalComponentProps} />
|
||||||
|
{provided.placeholder}
|
||||||
|
</div>
|
||||||
{renderAddCardLink()}
|
{renderAddCardLink()}
|
||||||
{renderNewCardForm()}
|
{renderNewCardForm()}
|
||||||
{provided.placeholder}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ export const StyleVertical = styled.div`
|
|||||||
|
|
||||||
.react-trello-card {
|
.react-trello-card {
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
min-width: 120px;
|
width: auto;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-trello-board {
|
.react-trello-board {
|
||||||
|
|||||||
Reference in New Issue
Block a user