Merged in release/2024-08-30 (pull request #1673)

Release/2024 08 30
This commit is contained in:
Allan Carr
2024-08-30 20:34:21 +00:00
9 changed files with 147 additions and 93 deletions

View File

@@ -1,23 +1,23 @@
import React, { useEffect, useMemo, useRef, useState } from "react"; import { SyncOutlined } from "@ant-design/icons";
import { Button, Dropdown, Input, Space, Statistic, Table } from "antd";
import { PageHeader } from "@ant-design/pro-layout"; import { PageHeader } from "@ant-design/pro-layout";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
import { Button, Dropdown, Input, Space, Statistic, Table } from "antd";
import _ from "lodash";
import React, { useEffect, useMemo, useRef, useState } from "react";
import ReactDragListView from "react-drag-listview"; import ReactDragListView from "react-drag-listview";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectTechnician } from "../../redux/tech/tech.selectors"; import { selectTechnician } from "../../redux/tech/tech.selectors";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors"; import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import Prompt from "../../utils/prompt.js";
import AlertComponent from "../alert/alert.component.jsx";
import ProductionListColumnsAdd from "../production-list-columns/production-list-columns.add.component"; import ProductionListColumnsAdd from "../production-list-columns/production-list-columns.add.component";
import ProductionListColumns from "../production-list-columns/production-list-columns.data"; import ProductionListColumns from "../production-list-columns/production-list-columns.data";
import ProductionListDetail from "../production-list-detail/production-list-detail.component"; import ProductionListDetail from "../production-list-detail/production-list-detail.component";
import { ProductionListConfigManager } from "./production-list-config-manager.component.jsx";
import ProductionListPrint from "./production-list-print.component"; import ProductionListPrint from "./production-list-print.component";
import ResizeableTitle from "./production-list-table.resizeable.component"; import ResizeableTitle from "./production-list-table.resizeable.component";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
import { SyncOutlined } from "@ant-design/icons";
import Prompt from "../../utils/prompt.js";
import _ from "lodash";
import AlertComponent from "../alert/alert.component.jsx";
import { ProductionListConfigManager } from "./production-list-config-manager.component.jsx";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -43,7 +43,7 @@ export function ProductionListTable({ loading, data, refetch, bodyshop, technici
const initialStateRef = useRef( const initialStateRef = useRef(
(bodyshop.production_config && (bodyshop.production_config &&
bodyshop.production_config.find((p) => p.name === defaultView)?.columns.tableState) || bodyshop.production_config.find((p) => p.name === defaultView)?.columns.tableState) ||
bodyshop.production_config[0]?.columns.tableState || { (bodyshop.production_config && bodyshop.production_config[0]?.columns.tableState) || {
sortedInfo: {}, sortedInfo: {},
filteredInfo: { text: "" } filteredInfo: { text: "" }
} }

View File

@@ -1,5 +1,4 @@
import { Button, Card, DatePicker, Form, Popover, Radio, Space } from "antd"; import { Button, Card, DatePicker, Form, Popover, Radio, Space } from "antd";
import dayjs from "../../utils/day";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -7,10 +6,12 @@ import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.utils"; import { logImEXEvent } from "../../firebase/firebase.utils";
import { selectTechnician } from "../../redux/tech/tech.selectors"; import { selectTechnician } from "../../redux/tech/tech.selectors";
import DatePIckerRanges from "../../utils/DatePickerRanges"; import DatePIckerRanges from "../../utils/DatePickerRanges";
import dayjs from "../../utils/day";
import { GenerateDocument } from "../../utils/RenderTemplate"; import { GenerateDocument } from "../../utils/RenderTemplate";
import { TemplateList } from "../../utils/TemplateConstants"; import { TemplateList } from "../../utils/TemplateConstants";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectTechnician,
technician: selectTechnician technician: selectTechnician
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
@@ -18,7 +19,7 @@ const mapDispatchToProps = (dispatch) => ({
}); });
export default connect(mapStateToProps, mapDispatchToProps)(TechJobPrintTickets); export default connect(mapStateToProps, mapDispatchToProps)(TechJobPrintTickets);
export function TechJobPrintTickets({ technician, event, attendacePrint }) { export function TechJobPrintTickets({ bodyshop, technician, event, attendacePrint }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@@ -57,7 +58,8 @@ export function TechJobPrintTickets({ technician, event, attendacePrint }) {
subject: subject:
attendacePrint === true ? Templates.attendance_employee.subject : Templates.timetickets_employee.subject attendacePrint === true ? Templates.attendance_employee.subject : Templates.timetickets_employee.subject
}, },
values.sendby // === "email" ? "e" : "p" values.sendby,
bodyshop
); );
} catch (error) { } catch (error) {
console.log(error); console.log(error);

View File

@@ -1,6 +1,6 @@
import { EditFilled, SyncOutlined } from "@ant-design/icons"; import { EditFilled, SyncOutlined } from "@ant-design/icons";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
import { Button, Card, Checkbox, Space, Table } from "antd"; import { Button, Card, Checkbox, Space, Table } from "antd";
import dayjs from "../../utils/day";
import React, { useMemo, useState } from "react"; import React, { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -10,10 +10,10 @@ import { setModalContext } from "../../redux/modals/modals.actions";
import { selectAuthLevel, selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors"; import { selectAuthLevel, selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter"; import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter";
import { onlyUnique } from "../../utils/arrayHelper"; import { onlyUnique } from "../../utils/arrayHelper";
import dayjs from "../../utils/day";
import { alphaSort, dateSort } from "../../utils/sorters"; import { alphaSort, dateSort } from "../../utils/sorters";
import RbacWrapper, { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component"; import RbacWrapper, { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component";
import TimeTicketEnterButton from "../time-ticket-enter-button/time-ticket-enter-button.component"; import TimeTicketEnterButton from "../time-ticket-enter-button/time-ticket-enter-button.component";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -165,7 +165,7 @@ export function TimeTicketList({
key: "memo", key: "memo",
sorter: (a, b) => alphaSort(a.memo, b.memo), sorter: (a, b) => alphaSort(a.memo, b.memo),
sortOrder: state.sortedInfo.columnKey === "memo" && state.sortedInfo.order, sortOrder: state.sortedInfo.columnKey === "memo" && state.sortedInfo.order,
render: (text, record) => (record.clockon || record.clockoff ? t(record.memo) : record.memo) render: (text, record) => (record.memo.startsWith("timetickets.labels") ? t(record.memo) : record.memo)
}, },
...(Enhanced_Payroll.treatment === "on" ...(Enhanced_Payroll.treatment === "on"
? [ ? [
@@ -206,76 +206,98 @@ export function TimeTicketList({
return null; return null;
} }
} }
}, }
]), ]),
{ {
title: t("timetickets.fields.created_by"), title: t("timetickets.fields.created_by"),
dataIndex: "created_by", dataIndex: "created_by",
key: "created_by", key: "created_by",
sorter: (a, b) => alphaSort(a.created_by, b.created_by), sorter: (a, b) => alphaSort(a.created_by, b.created_by),
sortOrder: state.sortedInfo.columnKey === "created_by" && state.sortedInfo.order, sortOrder: state.sortedInfo.columnKey === "created_by" && state.sortedInfo.order,
render: (text, record) => record.created_by render: (text, record) => record.created_by
}, },
// { // {
// title: "Pay", // title: "Pay",
// dataIndex: "pay", // dataIndex: "pay",
// key: "pay", // key: "pay",
// render: (text, record) => // render: (text, record) =>
// Dinero({ amount: Math.round(record.rate * 100) }) // Dinero({ amount: Math.round(record.rate * 100) })
// .multiply(record.flat_rate ? record.productivehrs : record.actualhrs) // .multiply(record.flat_rate ? record.productivehrs : record.actualhrs)
// .toFormat("$0.00"), // .toFormat("$0.00"),
// }, // },
{ {
title: t("general.labels.actions"), title: t("general.labels.actions"),
dataIndex: "actions", dataIndex: "actions",
key: "actions", key: "actions",
render: (text, record) => ( render: (text, record) => (
<Space wrap> <Space wrap>
{techConsole && ( {techConsole && (
<TimeTicketEnterButton <TimeTicketEnterButton
actions={{ refetch }} actions={{ refetch }}
context={{ id: record.id, timeticket: record }} context={{ id: record.id, timeticket: record }}
disabled={!record.job || disabled} disabled={!record.job || disabled}
> >
<EditFilled /> <EditFilled />
</TimeTicketEnterButton> </TimeTicketEnterButton>
)} )}
{!techConsole && ( {!techConsole && (
<RbacWrapper <RbacWrapper
action="timetickets:edit" action="timetickets:edit"
noauth={() => { noauth={() => {
return <div />; return <div />;
}} }}
> >
<TimeTicketEnterButton <TimeTicketEnterButton
actions={{ refetch }} actions={{ refetch }}
context={{ context={{
id: record.id, id: record.id,
timeticket: record timeticket: record
}} }}
disabled={ disabled={
HasRbacAccess({ record.ciecacode
bodyshop, ? record.committed_at
authLevel: authLevel, ? HasRbacAccess({
action: "timetickets:editcommitted" bodyshop,
}) && authLevel: authLevel,
HasRbacAccess({ action: "timetickets:editcommitted"
bodyshop, }) &&
authLevel: authLevel, HasRbacAccess({
action: "timetickets:shiftedit" bodyshop,
}) authLevel: authLevel,
action: "timetickets:edit"
})
: HasRbacAccess({
bodyshop,
authLevel: authLevel,
action: "timetickets:edit"
})
: record.committed_at
? HasRbacAccess({
bodyshop,
authLevel: authLevel,
action: "timetickets:editcommitted"
}) &&
HasRbacAccess({
bodyshop,
authLevel: authLevel,
action: "timetickets:shiftedit"
})
: HasRbacAccess({
bodyshop,
authLevel: authLevel,
action: "timetickets:shiftedit"
})
? disabled ? disabled
: !record.jobid : !record.jobid
} }
> >
<EditFilled /> <EditFilled />
</TimeTicketEnterButton> </TimeTicketEnterButton>
</RbacWrapper> </RbacWrapper>
)} )}
</Space> </Space>
) )
} }
]; ];
const handleTableChange = (pagination, filters, sorter) => { const handleTableChange = (pagination, filters, sorter) => {

View File

@@ -1,4 +1,5 @@
import { useLazyQuery } from "@apollo/client"; import { useLazyQuery } from "@apollo/client";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
import { Form, Input, InputNumber, Select, Switch } from "antd"; import { Form, Input, InputNumber, Select, Switch } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -7,8 +8,10 @@ import { createStructuredSelector } from "reselect";
import { GET_LINE_TICKET_BY_PK } from "../../graphql/jobs-lines.queries"; import { GET_LINE_TICKET_BY_PK } from "../../graphql/jobs-lines.queries";
import { selectAuthLevel, selectBodyshop } from "../../redux/user/user.selectors"; import { selectAuthLevel, selectBodyshop } from "../../redux/user/user.selectors";
import EmployeeSearchSelect from "../employee-search-select/employee-search-select.component"; import EmployeeSearchSelect from "../employee-search-select/employee-search-select.component";
import FormDateTimePicker from "../form-date-time-picker/form-date-time-picker.component"; import {
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component"; default as DateTimePicker,
default as FormDateTimePicker
} from "../form-date-time-picker/form-date-time-picker.component";
import JobSearchSelect from "../job-search-select/job-search-select.component"; import JobSearchSelect from "../job-search-select/job-search-select.component";
import LaborAllocationsTable from "../labor-allocations-table/labor-allocations-table.component"; import LaborAllocationsTable from "../labor-allocations-table/labor-allocations-table.component";
import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility"; import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility";
@@ -16,7 +19,6 @@ import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component"; import { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component";
import TimeTicketList from "../time-ticket-list/time-ticket-list.component"; import TimeTicketList from "../time-ticket-list/time-ticket-list.component";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -69,13 +71,7 @@ export function TimeTicketModalComponent({
}; };
const MemoInput = ({ value, ...props }) => { const MemoInput = ({ value, ...props }) => {
return ( return <Input value={value?.startsWith("timetickets.labels") ? t(value) : value} {...props} />;
<Input
value={value?.startsWith("timetickets.") ? t(value) : value}
{...props}
disabled={value?.startsWith("timetickets.") || disabled}
/>
);
}; };
return ( return (

View File

@@ -39,7 +39,7 @@ export default function TimeTicketShiftActive({ timetickets, refetch, isTechCons
renderItem={(ticket) => ( renderItem={(ticket) => (
<List.Item> <List.Item>
<Card <Card
title={t(ticket.memo)} title={ticket.memo.startsWith("timetickets.labels") ? t(ticket.memo) : ticket.memo}
actions={[ actions={[
<TechClockOffButton <TechClockOffButton
jobId={ticket.jobid} jobId={ticket.jobid}

View File

@@ -1,3 +1,19 @@
- name: AutoHouse Data Pump
webhook: '{{HASURA_API_URL}}/data/ah'
schedule: 0 6 * * *
include_in_metadata: true
payload: {}
headers:
- name: x-imex-auth
value_from_env: DATAPUMP_AUTH
- name: Claimscorp Data Pump
webhook: '{{HASURA_API_URL}}/data/cc'
schedule: 30 6 * * *
include_in_metadata: true
payload: {}
headers:
- name: x-imex-auth
value: DATAPUMP_AUTH
- name: Kaizen Data Pump - name: Kaizen Data Pump
webhook: '{{HASURA_API_URL}}/data/kaizen' webhook: '{{HASURA_API_URL}}/data/kaizen'
schedule: 30 5 * * * schedule: 30 5 * * *

View File

@@ -31,6 +31,12 @@ const ftpSetup = {
}; };
exports.default = async (req, res) => { exports.default = async (req, res) => {
// Only process if in production environment.
if (process.env.NODE_ENV !== "production") {
res.sendStatus(403);
return;
}
//Query for the List of Bodyshop Clients. //Query for the List of Bodyshop Clients.
logger.log("autohouse-start", "DEBUG", "api", null, null); logger.log("autohouse-start", "DEBUG", "api", null, null);
const { bodyshops } = await client.request(queries.GET_AUTOHOUSE_SHOPS); const { bodyshops } = await client.request(queries.GET_AUTOHOUSE_SHOPS);

View File

@@ -31,6 +31,12 @@ const ftpSetup = {
}; };
exports.default = async (req, res) => { exports.default = async (req, res) => {
// Only process if in production environment.
if (process.env.NODE_ENV !== "production") {
res.sendStatus(403);
return;
}
//Query for the List of Bodyshop Clients. //Query for the List of Bodyshop Clients.
logger.log("claimscorp-start", "DEBUG", "api", null, null); logger.log("claimscorp-start", "DEBUG", "api", null, null);
const { bodyshops } = await client.request(queries.GET_CLAIMSCORP_SHOPS); const { bodyshops } = await client.request(queries.GET_CLAIMSCORP_SHOPS);

View File

@@ -31,6 +31,12 @@ const ftpSetup = {
}; };
exports.default = async (req, res) => { exports.default = async (req, res) => {
// Only process if in production environment.
if (process.env.NODE_ENV !== "production") {
res.sendStatus(403);
return;
}
//Query for the List of Bodyshop Clients. //Query for the List of Bodyshop Clients.
logger.log("kaizen-start", "DEBUG", "api", null, null); logger.log("kaizen-start", "DEBUG", "api", null, null);
const kaizenShopsIDs = ["SUMMIT", "STRATHMORE", "SUNRIDGE", "SHAW"]; const kaizenShopsIDs = ["SUMMIT", "STRATHMORE", "SUNRIDGE", "SHAW"];