Compare commits

..

1 Commits

Author SHA1 Message Date
Allan Carr
9f354f5e36 IO-2869 Production Board Alert
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-08-07 15:42:22 -07:00
9 changed files with 76 additions and 67 deletions

View File

@@ -31,11 +31,3 @@
These allow users to turn fields on or off, turning them all off will show the card in the most minimal form
### Statistics
- The statistics section allows users to see accumulations of both jobs on the board, and jobs in production.
- you can click a statistic to turn it on and off, and drag and drop the statistics to rearrange them
### Filters
- Allows you to set, and persist filters for estimators and insurance companies

View File

@@ -161,15 +161,3 @@
.rowWithColor > td {
background-color: var(--bgColor) !important;
}
.muted-button {
color: lightgray;
border: none;
background: none;
cursor: pointer;
font-size: 16px; /* Adjust as needed */
}
.muted-button:hover {
color: darkgrey;
}

View File

@@ -6,20 +6,20 @@ import {
PauseCircleOutlined
} from "@ant-design/icons";
import { Card, Col, Row, Space, Tooltip } from "antd";
import Dinero from "dinero.js";
import React, { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import Dinero from "dinero.js";
import ProductionAlert from "../production-list-columns/production-list-columns.alert.component";
import { ProductionListColumnAlertButton } 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 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";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
const cardColor = (ssbuckets, totalHrs) => {
const bucket = ssbuckets.find((bucket) => bucket.gte <= totalHrs && (!bucket.lt || bucket.lt > totalHrs));
@@ -343,7 +343,14 @@ export default function ProductionBoardCard({ technician, card, bodyshop, cardSe
const headerContent = (
<div className="header-content-container">
<div className="inner-container">
<ProductionAlert id={card.id} productionVars={metadata?.production_vars} refetch={card?.refetch} key="alert" />
<ProductionListColumnAlertButton
record={{
id: card.id,
production_vars: card?.metadata.production_vars,
refetch: card?.refetch
}}
key="alert"
/>
{metadata?.suspended && <PauseCircleOutlined className="circle-outline" key="suspended" />}
{metadata?.iouparent && (
<EllipsesToolTip

View File

@@ -1,14 +1,14 @@
import { ExclamationCircleFilled, PlusCircleFilled } from "@ant-design/icons";
import { ExclamationCircleFilled } from "@ant-design/icons";
import { useMutation } from "@apollo/client";
import { Button, Popconfirm } from "antd";
import React, { useCallback } from "react";
import { Button, Dropdown } from "antd";
import React, { useCallback, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import { useTranslation } from "react-i18next";
const mapStateToProps = createStructuredSelector({});
@@ -23,24 +23,23 @@ const mapDispatchToProps = (dispatch) => ({
)
});
const ProductionListColumnAlert = ({ id, productionVars, refetch, insertAuditTrail }) => {
const ProductionListColumnAlertBase = ({ record, insertAuditTrail }) => {
const [updateAlert] = useMutation(UPDATE_JOB);
const { t } = useTranslation();
const handleAlertToggle = useCallback(() => {
logImEXEvent("production_toggle_alert");
const newAlertState = !!productionVars?.alert ? !productionVars?.alert : true;
const finalProductionVars = {
...productionVars,
alert: newAlertState
};
const newAlertState = !!record.production_vars?.alert ? !record.production_vars.alert : true;
updateAlert({
variables: {
jobId: id,
jobId: record.id,
job: {
production_vars: finalProductionVars
production_vars: {
...record.production_vars,
alert: newAlertState
}
}
}
}).catch((err) => {
@@ -48,26 +47,55 @@ const ProductionListColumnAlert = ({ id, productionVars, refetch, insertAuditTra
});
insertAuditTrail({
jobid: id,
jobid: record.id,
operation: AuditTrailMapping.alertToggle(newAlertState),
type: "alertToggle"
});
if (refetch) refetch();
}, [updateAlert, insertAuditTrail, id, productionVars, refetch]);
if (record.refetch) record.refetch();
}, [updateAlert, insertAuditTrail, record]);
return productionVars?.alert ? (
<Popconfirm
title={t("general.actions.remove_alert")}
onConfirm={handleAlertToggle}
okText={t("general.labels.yes")}
cancelText={t("general.labels.no")}
>
<Button className="production-alert" icon={<ExclamationCircleFilled />} />
</Popconfirm>
) : (
<Button className="muted-button" icon={<PlusCircleFilled />} onClick={handleAlertToggle} />
const menuItems = useMemo(
() => [
{
key: "toggleAlert",
label:
record.production_vars && record.production_vars.alert
? t("production.labels.alertoff")
: t("production.labels.alerton"),
onClick: handleAlertToggle
}
],
[record.production_vars, t, handleAlertToggle]
);
return { handleAlertToggle, menuItems };
};
export default connect(mapStateToProps, mapDispatchToProps)(ProductionListColumnAlert);
export const ProductionListColumnAlertButton = connect(
mapStateToProps,
mapDispatchToProps
)(({ record, insertAuditTrail }) => {
const { handleAlertToggle } = ProductionListColumnAlertBase({ record, insertAuditTrail });
if (!record.production_vars?.alert) return null;
return <Button className="production-alert" icon={<ExclamationCircleFilled />} onClick={handleAlertToggle} />;
});
export const ProductionListColumnAlertMenu = connect(
mapStateToProps,
mapDispatchToProps
)(({ record, insertAuditTrail }) => {
const { menuItems } = ProductionListColumnAlertBase({ record, insertAuditTrail });
return (
<Dropdown menu={{ items: menuItems }} trigger={["contextMenu"]}>
<div style={{ height: "19px" }}>
{record.production_vars && record.production_vars.alert ? (
<ExclamationCircleFilled className="production-alert" />
) : null}
</div>
</Dropdown>
);
});

View File

@@ -2,16 +2,19 @@ import { BranchesOutlined, PauseCircleOutlined } from "@ant-design/icons";
import { Checkbox, Space, Tooltip } from "antd";
import i18n from "i18next";
import { Link } from "react-router-dom";
import { setModalContext } from "../../redux/modals/modals.actions";
import { store } from "../../redux/store";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { TimeFormatter } from "../../utils/DateFormatter";
import PhoneFormatter from "../../utils/PhoneFormatter";
import { onlyUnique } from "../../utils/arrayHelper";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
import { alphaSort, dateSort, statusSort } from "../../utils/sorters";
import JobAltTransportChange from "../job-at-change/job-at-change.component";
import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component";
import OwnerNameDisplay, { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
import ProductionListColumnAlert from "./production-list-columns.alert.component";
import { ProductionListColumnAlertMenu } from "./production-list-columns.alert.component";
import ProductionListColumnBodyPriority from "./production-list-columns.bodypriority.component";
import ProductionListColumnComment from "./production-list-columns.comment.component";
import ProductionListDate from "./production-list-columns.date.component";
@@ -23,10 +26,7 @@ import ProductionListColumnPartsReceived from "./production-list-columns.partsre
import ProductionListColumnNote from "./production-list-columns.productionnote.component";
import ProductionListColumnCategory from "./production-list-columns.status.category";
import ProductionListColumnStatus from "./production-list-columns.status.component";
import ProductionListColumnTouchTime from "./prodution-list-columns.touchtime.component";
import { store } from "../../redux/store";
import { setModalContext } from "../../redux/modals/modals.actions";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatments }) => {
const { Enhanced_Payroll } = treatments;
@@ -349,9 +349,7 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme
key: "alert",
sorter: (a, b) => Number(a.production_vars?.alert || false) - Number(b.production_vars?.alert || false),
sortOrder: state.sortedInfo.columnKey === "alert" && state.sortedInfo.order,
render: (text, record) => (
<ProductionListColumnAlert id={record.id} productionVars={record?.production_vars} refetch={refetch} />
)
render: (text, record) => <ProductionListColumnAlertMenu record={{ id: record.id, production_vars: record?.production_vars }} />
},
{
title: i18n.t("production.labels.note"),
@@ -372,7 +370,7 @@ const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatme
dataIndex: "tt",
key: "tt",
render: (text, record) => {
return <ProductionListColumnTouchTime job={record} />;
return <ProductionlistColumnTouchTime job={record} />;
}
},
{

View File

@@ -148,7 +148,6 @@ export function ProductionListEmpAssignment({ insertAuditTrail, bodyshop, record
) : (
<PlusCircleFilled
style={iconStyle}
className="muted-button"
onClick={() => {
setAssignment({ operation: type });
setVisibility(true);

View File

@@ -1160,8 +1160,7 @@
"submit": "Submit",
"tryagain": "Try Again",
"view": "View",
"viewreleasenotes": "See What's Changed",
"remove_alert": "Are you sure you want to dismiss the alert?"
"viewreleasenotes": "See What's Changed"
},
"errors": {
"fcm": "You must allow notification permissions to have real time messaging. Click to try again.",

View File

@@ -1160,8 +1160,7 @@
"submit": "",
"tryagain": "",
"view": "",
"viewreleasenotes": "",
"remove_alert": ""
"viewreleasenotes": ""
},
"errors": {
"fcm": "",

View File

@@ -1160,8 +1160,7 @@
"submit": "",
"tryagain": "",
"view": "",
"viewreleasenotes": "",
"remove_alert": ""
"viewreleasenotes": ""
},
"errors": {
"fcm": "",