Compare commits

..

3 Commits

Author SHA1 Message Date
Allan Carr
49816d5d43 IO-3607 Employee Drop Down Inactive filter
Signed-off-by: Allan Carr <allan@imexsystems.ca>
2026-03-09 16:28:10 -07:00
Dave Richer
b9b3e2c2aa Merged in hotfix/2026-03-09 (pull request #3109)
hotfix/2026-03-09 - Eula
2026-03-09 17:00:49 +00:00
Dave
7e5363f911 hotfix/2026-03-09 - Eula 2026-03-09 12:33:20 -04:00
8 changed files with 44 additions and 64 deletions

View File

@@ -41,7 +41,7 @@ export function EmailOverlayComponent({ emailConfig, form, selectedMediaState, b
const emailsToMenu = { const emailsToMenu = {
items: [ items: [
...bodyshop.employees ...bodyshop.employees
.filter((e) => e.user_email) .filter((e) => e.user_email && e.active === true)
.map((e, idx) => ({ .map((e, idx) => ({
key: idx, key: idx,
label: `${e.first_name} ${e.last_name}`, label: `${e.first_name} ${e.last_name}`,
@@ -59,7 +59,7 @@ export function EmailOverlayComponent({ emailConfig, form, selectedMediaState, b
const menuCC = { const menuCC = {
items: [ items: [
...bodyshop.employees ...bodyshop.employees
.filter((e) => e.user_email) .filter((e) => e.user_email && e.active === true)
.map((e, idx) => ({ .map((e, idx) => ({
key: idx, key: idx,
label: `${e.first_name} ${e.last_name}`, label: `${e.first_name} ${e.last_name}`,

View File

@@ -25,6 +25,7 @@ const Eula = ({ currentEula, currentUser, acceptEula }) => {
const handleScroll = useCallback( const handleScroll = useCallback(
(e) => { (e) => {
if (!e.target) return;
const bottom = e.target.scrollHeight - 100 <= e.target.scrollTop + e.target.clientHeight; const bottom = e.target.scrollHeight - 100 <= e.target.scrollTop + e.target.clientHeight;
if (bottom && !hasEverScrolledToBottom) { if (bottom && !hasEverScrolledToBottom) {
setHasEverScrolledToBottom(true); setHasEverScrolledToBottom(true);
@@ -36,7 +37,9 @@ const Eula = ({ currentEula, currentUser, acceptEula }) => {
); );
useEffect(() => { useEffect(() => {
handleScroll({ target: markdownCardRef.current }); if (markdownCardRef.current) {
handleScroll({ target: markdownCardRef.current });
}
}, [handleScroll]); }, [handleScroll]);
const handleChange = useCallback(() => { const handleChange = useCallback(() => {

View File

@@ -33,7 +33,7 @@ import JobLinesBillRefernece from "../job-lines-bill-reference/job-lines-bill-re
import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react"; import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react";
import _ from "lodash"; import _ from "lodash";
import { FaTasks } from "react-icons/fa"; import { FaTasks } from "react-icons/fa";
import { selectAuthLevel, selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import dayjs from "../../utils/day"; import dayjs from "../../utils/day";
import InstanceRenderManager from "../../utils/instanceRenderMgr"; import InstanceRenderManager from "../../utils/instanceRenderMgr";
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
@@ -49,7 +49,6 @@ import JobLinesPartPriceChange from "./job-lines-part-price-change.component";
import JobLinesExpanderSimple from "./jobs-lines-expander-simple.component"; import JobLinesExpanderSimple from "./jobs-lines-expander-simple.component";
import { logImEXEvent } from "../../firebase/firebase.utils"; import { logImEXEvent } from "../../firebase/firebase.utils";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component.jsx";
const UPDATE_JOB_LINES_LOCATION_BULK = gql` const UPDATE_JOB_LINES_LOCATION_BULK = gql`
mutation UPDATE_JOB_LINES_LOCATION_BULK($ids: [uuid!]!, $location: String!) { mutation UPDATE_JOB_LINES_LOCATION_BULK($ids: [uuid!]!, $location: String!) {
@@ -67,8 +66,7 @@ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
jobRO: selectJobReadOnly, jobRO: selectJobReadOnly,
technician: selectTechnician, technician: selectTechnician,
isPartsEntry: selectIsPartsEntry, isPartsEntry: selectIsPartsEntry
authLevel: selectAuthLevel
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
@@ -96,8 +94,7 @@ export function JobLinesComponent({
setTaskUpsertContext, setTaskUpsertContext,
billsQuery, billsQuery,
handlePartsOrderOnRowClick, handlePartsOrderOnRowClick,
isPartsEntry, isPartsEntry
authLevel
}) { }) {
const [deleteJobLine] = useMutation(DELETE_JOB_LINE_BY_PK); const [deleteJobLine] = useMutation(DELETE_JOB_LINE_BY_PK);
const [bulkUpdateLocations] = useMutation(UPDATE_JOB_LINES_LOCATION_BULK); const [bulkUpdateLocations] = useMutation(UPDATE_JOB_LINES_LOCATION_BULK);
@@ -389,20 +386,18 @@ export function JobLinesComponent({
key: "actions", key: "actions",
render: (text, record) => ( render: (text, record) => (
<Space> <Space>
{(record.manual_line || jobIsPrivate) && {(record.manual_line || jobIsPrivate) && !technician && (
!technician && <Button
HasRbacAccess({ bodyshop, authLevel, action: "jobs:manual-line" }) && ( disabled={jobRO}
<Button onClick={() => {
disabled={jobRO} setJobLineEditContext({
onClick={() => { actions: { refetch: refetch, submit: form && form.submit },
setJobLineEditContext({ context: { ...record, jobid: job.id }
actions: { refetch: refetch, submit: form && form.submit }, });
context: { ...record, jobid: job.id } }}
}); icon={<EditFilled />}
}} />
icon={<EditFilled />} )}
/>
)}
<Button <Button
title={t("tasks.buttons.create")} title={t("tasks.buttons.create")}
onClick={() => { onClick={() => {
@@ -415,30 +410,29 @@ export function JobLinesComponent({
}} }}
icon={<FaTasks />} icon={<FaTasks />}
/> />
{(record.manual_line || jobIsPrivate) &&
!technician && {(record.manual_line || jobIsPrivate) && !technician && (
HasRbacAccess({ bodyshop, authLevel, action: "jobs:manual-line" }) && ( <Button
<Button disabled={jobRO}
disabled={jobRO} onClick={async () => {
onClick={async () => { await deleteJobLine({
await deleteJobLine({ variables: { joblineId: record.id },
variables: { joblineId: record.id }, update(cache) {
update(cache) { cache.modify({
cache.modify({ fields: {
fields: { joblines(existingJobLines, { readField }) {
joblines(existingJobLines, { readField }) { return existingJobLines.filter((jlRef) => record.id !== readField("id", jlRef));
return existingJobLines.filter((jlRef) => record.id !== readField("id", jlRef));
}
} }
}); }
} });
}); }
await axios.post("/job/totalsssu", { id: job.id }); });
if (refetch) refetch(); await axios.post("/job/totalsssu", { id: job.id });
}} if (refetch) refetch();
icon={<DeleteFilled />} }}
/> icon={<DeleteFilled />}
)} />
)}
</Space> </Space>
) )
} }
@@ -663,7 +657,7 @@ export function JobLinesComponent({
<Button id="repair-data-mark-button">{t("jobs.actions.mark")}</Button> <Button id="repair-data-mark-button">{t("jobs.actions.mark")}</Button>
</Dropdown> </Dropdown>
{!isPartsEntry && HasRbacAccess({ bodyshop, authLevel, action: "jobs:manual-line" }) && ( {!isPartsEntry && (
<Button <Button
disabled={jobRO || technician} disabled={jobRO || technician}
onClick={() => { onClick={() => {

View File

@@ -26,7 +26,6 @@ const ret = {
"jobs:partsqueue": 4, "jobs:partsqueue": 4,
"jobs:checklist-view": 2, "jobs:checklist-view": 2,
"jobs:list-ready": 1, "jobs:list-ready": 1,
"jobs:manual-line": 1,
"jobs:void": 5, "jobs:void": 5,
"bills:enter": 2, "bills:enter": 2,

View File

@@ -435,19 +435,6 @@ export function ShopInfoRbacComponent({ bodyshop }) {
> >
<InputNumber /> <InputNumber />
</Form.Item>, </Form.Item>,
<Form.Item
key="jobs:manual-line"
label={t("bodyshop.fields.rbac.jobs.manual-line")}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
name={["md_rbac", "jobs:manual-line"]}
>
<InputNumber />
</Form.Item>,
<Form.Item <Form.Item
key="jobs:partsqueue" key="jobs:partsqueue"
label={t("bodyshop.fields.rbac.jobs.partsqueue")} label={t("bodyshop.fields.rbac.jobs.partsqueue")}

View File

@@ -519,7 +519,6 @@
"list-active": "Jobs -> List Active", "list-active": "Jobs -> List Active",
"list-all": "Jobs -> List All", "list-all": "Jobs -> List All",
"list-ready": "Jobs -> List Ready", "list-ready": "Jobs -> List Ready",
"manual-line": "Jobs -> Manual Line",
"partsqueue": "Jobs -> Parts Queue", "partsqueue": "Jobs -> Parts Queue",
"void": "Jobs -> Void" "void": "Jobs -> Void"
}, },

View File

@@ -519,7 +519,6 @@
"list-active": "", "list-active": "",
"list-all": "", "list-all": "",
"list-ready": "", "list-ready": "",
"manual-line": "",
"partsqueue": "", "partsqueue": "",
"void": "" "void": ""
}, },

View File

@@ -519,7 +519,6 @@
"list-active": "", "list-active": "",
"list-all": "", "list-all": "",
"list-ready": "", "list-ready": "",
"manual-line": "",
"partsqueue": "", "partsqueue": "",
"void": "" "void": ""
}, },