Compare commits

..

3 Commits

Author SHA1 Message Date
Dave Richer
00d8b533f4 - mute gray more, mute more buttons
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-08-09 13:28:01 -04:00
Dave Richer
064ed1bb8b - Enhance Production Alert
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-08-08 12:16:56 -04:00
Dave Richer
efda254981 - Fix alert in table view
- (modify some docs)

Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-08-08 11:46:42 -04:00
9 changed files with 67 additions and 76 deletions

View File

@@ -31,3 +31,11 @@
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,3 +161,15 @@
.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 { ProductionListColumnAlertButton } from "../production-list-columns/production-list-columns.alert.component";
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 dayjs from "../../utils/day";
import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component";
const cardColor = (ssbuckets, totalHrs) => {
const bucket = ssbuckets.find((bucket) => bucket.gte <= totalHrs && (!bucket.lt || bucket.lt > totalHrs));
@@ -343,14 +343,7 @@ export default function ProductionBoardCard({ technician, card, bodyshop, cardSe
const headerContent = (
<div className="header-content-container">
<div className="inner-container">
<ProductionListColumnAlertButton
record={{
id: card.id,
production_vars: card?.metadata.production_vars,
refetch: card?.refetch
}}
key="alert"
/>
<ProductionAlert id={card.id} productionVars={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 } from "@ant-design/icons";
import { ExclamationCircleFilled, PlusCircleFilled } from "@ant-design/icons";
import { useMutation } from "@apollo/client";
import { Button, Dropdown } from "antd";
import React, { useCallback, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { Button, Popconfirm } from "antd";
import React, { useCallback } from "react";
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,23 +23,24 @@ const mapDispatchToProps = (dispatch) => ({
)
});
const ProductionListColumnAlertBase = ({ record, insertAuditTrail }) => {
const ProductionListColumnAlert = ({ id, productionVars, refetch, insertAuditTrail }) => {
const [updateAlert] = useMutation(UPDATE_JOB);
const { t } = useTranslation();
const handleAlertToggle = useCallback(() => {
logImEXEvent("production_toggle_alert");
const newAlertState = !!record.production_vars?.alert ? !record.production_vars.alert : true;
const newAlertState = !!productionVars?.alert ? !productionVars?.alert : true;
const finalProductionVars = {
...productionVars,
alert: newAlertState
};
updateAlert({
variables: {
jobId: record.id,
jobId: id,
job: {
production_vars: {
...record.production_vars,
alert: newAlertState
}
production_vars: finalProductionVars
}
}
}).catch((err) => {
@@ -47,55 +48,26 @@ const ProductionListColumnAlertBase = ({ record, insertAuditTrail }) => {
});
insertAuditTrail({
jobid: record.id,
jobid: id,
operation: AuditTrailMapping.alertToggle(newAlertState),
type: "alertToggle"
});
if (record.refetch) record.refetch();
}, [updateAlert, insertAuditTrail, record]);
if (refetch) refetch();
}, [updateAlert, insertAuditTrail, id, productionVars, refetch]);
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 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} />
);
return { handleAlertToggle, menuItems };
};
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>
);
});
export default connect(mapStateToProps, mapDispatchToProps)(ProductionListColumnAlert);

View File

@@ -2,19 +2,16 @@ 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 { ProductionListColumnAlertMenu } from "./production-list-columns.alert.component";
import ProductionListColumnAlert 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";
@@ -26,7 +23,10 @@ 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 ProductionListColumnTouchTime from "./prodution-list-columns.touchtime.component";
import { store } from "../../redux/store";
import { setModalContext } from "../../redux/modals/modals.actions";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
const r = ({ technician, state, activeStatuses, data, bodyshop, refetch, treatments }) => {
const { Enhanced_Payroll } = treatments;
@@ -349,7 +349,9 @@ 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) => <ProductionListColumnAlertMenu record={{ id: record.id, production_vars: record?.production_vars }} />
render: (text, record) => (
<ProductionListColumnAlert id={record.id} productionVars={record?.production_vars} refetch={refetch} />
)
},
{
title: i18n.t("production.labels.note"),
@@ -370,7 +372,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,6 +148,7 @@ export function ProductionListEmpAssignment({ insertAuditTrail, bodyshop, record
) : (
<PlusCircleFilled
style={iconStyle}
className="muted-button"
onClick={() => {
setAssignment({ operation: type });
setVisibility(true);

View File

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

View File

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

View File

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