From ae07f71e76b4255aff67a1bed4a1743081570a9a Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 1 Apr 2024 14:45:55 -0400 Subject: [PATCH] - Progress Commit Signed-off-by: Dave Richer --- .../bills-list-table.component.jsx | 50 ++++++++---- .../job-lines-expander.component.jsx | 15 +++- .../job-detail-lines/job-lines.component.jsx | 17 +++- .../jobs-list-paginated.component.jsx | 1 - .../jobs-list/jobs-list.component.jsx | 6 +- .../parts-order-list-table.component.jsx | 79 ++++++++++++------- .../task-list/task-list.component.jsx | 39 +++++++-- .../task-list/task-list.container.jsx | 7 +- .../task-upsert-modal.component.jsx | 2 +- client/src/graphql/bills.queries.js | 4 + client/src/graphql/jobs.queries.js | 10 +++ client/src/graphql/tasks.queries.js | 12 +++ .../jobs-detail.page.component.jsx | 14 ++-- .../src/pages/tasks/tasks.page.component.jsx | 2 +- client/src/translations/en_us/common.json | 15 +++- client/src/translations/es/common.json | 14 +++- client/src/translations/fr/common.json | 14 +++- 17 files changed, 223 insertions(+), 78 deletions(-) diff --git a/client/src/components/bills-list-table/bills-list-table.component.jsx b/client/src/components/bills-list-table/bills-list-table.component.jsx index 5db868406..ad764f1e1 100644 --- a/client/src/components/bills-list-table/bills-list-table.component.jsx +++ b/client/src/components/bills-list-table/bills-list-table.component.jsx @@ -1,29 +1,35 @@ -import { EditFilled, SyncOutlined } from "@ant-design/icons"; -import { Button, Card, Checkbox, Input, Space, Table } from "antd"; -import React, { useState } from "react"; -import { useTranslation } from "react-i18next"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { selectJobReadOnly } from "../../redux/application/application.selectors"; -import { setModalContext } from "../../redux/modals/modals.actions"; -import { selectBodyshop } from "../../redux/user/user.selectors"; +import {EditFilled, SyncOutlined} from "@ant-design/icons"; +import {Button, Card, Checkbox, Input, Space, Table} from "antd"; +import React, {useState} from "react"; +import {useTranslation} from "react-i18next"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; +import {selectJobReadOnly} from "../../redux/application/application.selectors"; +import {setModalContext} from "../../redux/modals/modals.actions"; +import {selectBodyshop, selectCurrentUser} from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; -import { DateFormatter } from "../../utils/DateFormatter"; -import { alphaSort, dateSort } from "../../utils/sorters"; -import { TemplateList } from "../../utils/TemplateConstants"; +import {DateFormatter} from "../../utils/DateFormatter"; +import {alphaSort, dateSort} from "../../utils/sorters"; +import {TemplateList} from "../../utils/TemplateConstants"; import BillDeleteButton from "../bill-delete-button/bill-delete-button.component"; import BillDetailEditReturnComponent from "../bill-detail-edit/bill-detail-edit-return.component"; import PrintWrapperComponent from "../print-wrapper/print-wrapper.component"; +import {FaTasks} from "react-icons/fa"; const mapStateToProps = createStructuredSelector({ jobRO: selectJobReadOnly, - bodyshop: selectBodyshop + bodyshop: selectBodyshop, + currentUser: selectCurrentUser }); const mapDispatchToProps = (dispatch) => ({ setPartsOrderContext: (context) => dispatch(setModalContext({ context: context, modal: "partsOrder" })), setBillEnterContext: (context) => dispatch(setModalContext({ context: context, modal: "billEnter" })), - setReconciliationContext: (context) => dispatch(setModalContext({ context: context, modal: "reconciliation" })) + setReconciliationContext: (context) => dispatch(setModalContext({ + context: context, + modal: "reconciliation" + })), + setTaskUpsertContext: (context) => dispatch(setModalContext({context, modal: 'taskUpsert'})), }); export function BillsListTableComponent({ @@ -34,7 +40,9 @@ export function BillsListTableComponent({ handleOnRowClick, setPartsOrderContext, setBillEnterContext, - setReconciliationContext + setReconciliationContext, + setTaskUpsertContext, + currentUser, }) { const { t } = useTranslation(); @@ -48,6 +56,8 @@ export function BillsListTableComponent({ const Templates = TemplateList("bill"); const bills = billsQuery.data ? billsQuery.data.bills : []; const { refetch } = billsQuery; + + const recordActions = (record, showView = false) => ( {showView && ( @@ -55,6 +65,16 @@ export function BillsListTableComponent({ )} + ({ //setUserLanguage: language => dispatch(setUserLanguage(language)) }); export default connect(mapStateToProps, mapDispatchToProps)(JobLinesExpander); -export function JobLinesExpander({ jobline, jobid, bodyshop }) { +export function JobLinesExpander({ jobline, jobid, bodyshop, currentUser }) { const { t } = useTranslation(); const { loading, error, data } = useQuery(GET_JOB_LINE_ORDERS, { fetchPolicy: "network-only", @@ -128,6 +134,9 @@ export function JobLinesExpander({ jobline, jobid, bodyshop }) { } /> + + + ); } diff --git a/client/src/components/job-detail-lines/job-lines.component.jsx b/client/src/components/job-detail-lines/job-lines.component.jsx index 8dfa60132..fc209d210 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -42,6 +42,7 @@ import JobSendPartPriceChangeComponent from "../job-send-parts-price-change/job- import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container"; import JobLinesExpander from "./job-lines-expander.component"; import JobLinesPartPriceChange from "./job-lines-part-price-change.component"; +import {FaTasks} from "react-icons/fa"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -52,7 +53,8 @@ const mapStateToProps = createStructuredSelector({ const mapDispatchToProps = (dispatch) => ({ setJobLineEditContext: (context) => dispatch(setModalContext({ context: context, modal: "jobLineEdit" })), setPartsOrderContext: (context) => dispatch(setModalContext({ context: context, modal: "partsOrder" })), - setBillEnterContext: (context) => dispatch(setModalContext({ context: context, modal: "billEnter" })) + setBillEnterContext: (context) => dispatch(setModalContext({ context: context, modal: "billEnter" })), + setTaskUpsertContext: (context) => dispatch(setModalContext({context, modal: 'taskUpsert'})), }); export function JobLinesComponent({ @@ -67,7 +69,8 @@ export function JobLinesComponent({ job, setJobLineEditContext, form, - setBillEnterContext + setBillEnterContext, + setTaskUpsertContext }) { const [deleteJobLine] = useMutation(DELETE_JOB_LINE_BY_PK); const { @@ -331,6 +334,16 @@ export function JobLinesComponent({ > + - + ), - }, - ]; + } + ); const [state, setState] = useState({ sortedInfo: {}, @@ -190,6 +205,7 @@ function TaskListComponent({ setTaskUpsertContext({ actions: {}, context: { + jobid: parentJobId, [relationshipType]: relationshipId, }, }); @@ -219,6 +235,15 @@ function TaskListComponent({ const tasksExtra = useCallback(() => { return ( + {!onlyMine && ( + handleSwitchChange('mine', value)} + /> +)} } unCheckedChildren={} @@ -242,7 +267,7 @@ function TaskListComponent({ ); - }, [refetch, deleted, completed]); + }, [refetch, deleted, completed, mine]); return ( ); } diff --git a/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx b/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx index b84d15579..a00741d77 100644 --- a/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx +++ b/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx @@ -187,7 +187,7 @@ export function TaskUpsertModalComponent({ }, ]} > - {bodyshop.employees.filter(x => x.active).map((employee) => ( {employee.first_name} {employee.last_name} diff --git a/client/src/graphql/bills.queries.js b/client/src/graphql/bills.queries.js index 355a123dd..49bbaebbc 100644 --- a/client/src/graphql/bills.queries.js +++ b/client/src/graphql/bills.queries.js @@ -59,6 +59,10 @@ export const QUERY_BILLS_BY_JOBID = gql` name email } + tasks { + id + due_date + } order_date deliver_by return diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index 92e490316..3e340152b 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -100,6 +100,11 @@ export const QUERY_ALL_ACTIVE_JOBS = gql` suspended est_ct_fn est_ct_ln + tasks_aggregate(where: { completed: { _eq: false }, deleted: { _eq: false } }) { + aggregate { + count + } + } } } `; @@ -499,6 +504,11 @@ export const QUERY_JOB_COSTING_DETAILS = gql` export const GET_JOB_BY_PK = gql` query GET_JOB_BY_PK($id: uuid!) { jobs_by_pk(id: $id) { + tasks_aggregate(where: { completed: { _eq: false }, deleted: { _eq: false } }) { + aggregate { + count + } + } actual_completion actual_delivery actual_in diff --git a/client/src/graphql/tasks.queries.js b/client/src/graphql/tasks.queries.js index 525cc4ae0..615a04963 100644 --- a/client/src/graphql/tasks.queries.js +++ b/client/src/graphql/tasks.queries.js @@ -97,6 +97,7 @@ export const QUERY_JOBLINE_TASKS_PAGINATED = gql` $bodyshop: uuid! $deleted: Boolean $completed: Boolean + $assigned_to: String $order: [tasks_order_by!]! ) { tasks( @@ -107,6 +108,7 @@ export const QUERY_JOBLINE_TASKS_PAGINATED = gql` joblineid: {_eq: $joblineid}, bodyshopid: {_eq: $bodyshop}, deleted: {_eq: $deleted}, + assigned_to: {_eq: $assigned_to}, completed: {_eq: $completed} } ) { @@ -117,6 +119,7 @@ export const QUERY_JOBLINE_TASKS_PAGINATED = gql` joblineid: {_eq: $joblineid}, bodyshopid: {_eq: $bodyshop}, deleted: {_eq: $deleted}, + assigned_to: {_eq: $assigned_to}, completed: {_eq: $completed} } ) { @@ -137,6 +140,7 @@ export const QUERY_PARTSORDER_TASKS_PAGINATED = gql` $bodyshop: uuid! $deleted: Boolean $completed: Boolean + $assigned_to: String $order: [tasks_order_by!]! ) { tasks( @@ -147,6 +151,7 @@ export const QUERY_PARTSORDER_TASKS_PAGINATED = gql` partsorderid: {_eq: $partsorderid}, bodyshopid: {_eq: $bodyshop}, deleted: {_eq: $deleted}, + assigned_to: {_eq: $assigned_to}, completed: {_eq: $completed} } ) { @@ -157,6 +162,7 @@ export const QUERY_PARTSORDER_TASKS_PAGINATED = gql` partsorderid: {_eq: $partsorderid}, bodyshopid: {_eq: $bodyshop}, deleted: {_eq: $deleted}, + assigned_to: {_eq: $assigned_to}, completed: {_eq: $completed} } ) { @@ -177,6 +183,7 @@ export const QUERY_BILL_TASKS_PAGINATED = gql` $bodyshop: uuid! $deleted: Boolean $completed: Boolean + $assigned_to: String $order: [tasks_order_by!]! ) { tasks( @@ -187,6 +194,7 @@ export const QUERY_BILL_TASKS_PAGINATED = gql` billid: {_eq: $billid}, bodyshopid: {_eq: $bodyshop}, deleted: {_eq: $deleted}, + assigned_to: {_eq: $assigned_to}, completed: {_eq: $completed} } ) { @@ -197,6 +205,7 @@ export const QUERY_BILL_TASKS_PAGINATED = gql` billid: {_eq: $billid}, bodyshopid: {_eq: $bodyshop}, deleted: {_eq: $deleted}, + assigned_to: {_eq: $assigned_to}, completed: {_eq: $completed} } ) { @@ -217,6 +226,7 @@ export const QUERY_JOB_TASKS_PAGINATED = gql` $bodyshop: uuid! $deleted: Boolean $completed: Boolean + $assigned_to: String $order: [tasks_order_by!]! ) { tasks( @@ -227,6 +237,7 @@ export const QUERY_JOB_TASKS_PAGINATED = gql` jobid: {_eq: $jobid}, bodyshopid: {_eq: $bodyshop}, deleted: {_eq: $deleted}, + assigned_to: {_eq: $assigned_to}, completed: {_eq: $completed} } ) { @@ -237,6 +248,7 @@ export const QUERY_JOB_TASKS_PAGINATED = gql` jobid: {_eq: $jobid}, bodyshopid: {_eq: $bodyshop}, deleted: {_eq: $deleted}, + assigned_to: {_eq: $assigned_to}, completed: {_eq: $completed} } ) { diff --git a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx index ca42fb86f..423287a8a 100644 --- a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx +++ b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx @@ -8,7 +8,7 @@ import Icon, { SyncOutlined, ToolFilled } from "@ant-design/icons"; -import {Button, Divider, Form, notification, Space, Tabs} from "antd"; +import {Badge, Button, Divider, Form, notification, Space, Tabs} from "antd"; import {PageHeader} from "@ant-design/pro-layout"; import Axios from "axios"; @@ -55,7 +55,7 @@ import ScheduleJobModalContainer import {insertAuditTrail} from "../../redux/application/application.actions"; import {selectJobReadOnly} from "../../redux/application/application.selectors"; import {setModalContext} from "../../redux/modals/modals.actions"; -import {selectBodyshop} from "../../redux/user/user.selectors"; +import {selectBodyshop, selectCurrentUser} from "../../redux/user/user.selectors"; import AuditTrailMapping from "../../utils/AuditTrailMappings"; import UndefinedToNull from "../../utils/undefinedtonull"; import _ from "lodash"; @@ -69,7 +69,8 @@ import {QUERY_JOB_TASKS_PAGINATED} from "../../graphql/tasks.queries.js"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, - jobRO: selectJobReadOnly + jobRO: selectJobReadOnly, + currentUser: selectCurrentUser }); const mapDispatchToProps = (dispatch) => ({ setPrintCenterContext: (context) => dispatch(setModalContext({ @@ -90,6 +91,7 @@ export function JobsDetailPage({ job, mutationUpdateJob, handleSubmit, + currentUser, insertAuditTrail, refetch }) { @@ -391,8 +393,10 @@ export function JobsDetailPage({ { key: 'tasks', icon: , - label: t("menus.jobsdetail.tasks"), - children: + label: + {t("jobs.labels.tasks")}{job.tasks_aggregate.aggregate.count > 0 && } + , + children: }, ]} /> diff --git a/client/src/pages/tasks/tasks.page.component.jsx b/client/src/pages/tasks/tasks.page.component.jsx index 34cff9fc3..b3758f48a 100644 --- a/client/src/pages/tasks/tasks.page.component.jsx +++ b/client/src/pages/tasks/tasks.page.component.jsx @@ -6,7 +6,7 @@ export default function TasksPageComponent({bodyshop, currentUser}) { return (
-
); diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 82eca9aeb..d1c14f89b 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -1524,7 +1524,8 @@ "voiding": "Error voiding Job. {{error}}" }, "fields": { - "actual_completion": "Actual Completion", + "active_tasks": "Active Tasks", + "actual_completion": "Actual Completion", "actual_delivery": "Actual Delivery", "actual_in": "Actual In", "adjustment_bottom_line": "Adjustments", @@ -1840,7 +1841,8 @@ "appointmentconfirmation": "Send confirmation to customer?", "associationwarning": "Any changes to associations will require updating the data from the new parent record to the Job.", "audit": "Audit Trail", - "available": "Available", + "tasks": "Tasks", + "available": "Available", "availablejobs": "Available Jobs", "ca_bc_pvrt": { "days": "Days", @@ -2121,6 +2123,7 @@ }, "titles": { "job_tasks": "Job Tasks", + "mine": "My Tasks", "my_tasks": "My Tasks", "completed": "Completed Tasks", "deleted": "Deleted Tasks" @@ -2130,14 +2133,17 @@ "complete": "Complete", "delete": "Delete", "edit": "Edit", - "refresh": "Refresh" + "refresh": "Refresh", + "myTasks": "Mine", + "allTasks": "All" }, "placeholders": { "description": "Enter a description", "jobid": "Select a Job", "joblineid": "Select a Job Line", "partsorderid": "Select a Parts Order", - "billid": "Select a Bill" + "billid": "Select a Bill", + "assigned_to": "Select an Employee" }, "fields": { "priorities": { @@ -3127,6 +3133,7 @@ } }, "titles": { + "tasks": "Tasks", "accounting-payables": "Payables | {{app}}", "accounting-payments": "Payments | {{app}}", "accounting-receivables": "Receivables | {{app}}", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 75b7c323a..8d412e06b 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -1524,6 +1524,7 @@ "voiding": "" }, "fields": { + "active_tasks": "", "actual_completion": "Realización real", "actual_delivery": "Entrega real", "actual_in": "Real en", @@ -1840,7 +1841,8 @@ "appointmentconfirmation": "¿Enviar confirmación al cliente?", "associationwarning": "", "audit": "", - "available": "", + "tasks": "", + "available": "", "availablejobs": "", "ca_bc_pvrt": { "days": "", @@ -2120,6 +2122,8 @@ "edit": "" }, "titles": { + "job_tasks": "", + "ny_tasks": "", "completed": "", "deleted": "" }, @@ -2128,14 +2132,17 @@ "complete": "", "delete": "", "edit": "", - "refresh":"" + "refresh":"", + "myTasks": "", + "allTasks": "" }, "placeholders": { "description": "", "jobid": "", "joblineid": "", "partsorderid": "", - "billid": "" + "billid": "", + "assigned_to": "" }, "fields": { "priorities": { @@ -3125,6 +3132,7 @@ } }, "titles": { + "tasks": "", "accounting-payables": "", "accounting-payments": "", "accounting-receivables": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index fa57f97f4..e39928eb3 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -1524,6 +1524,7 @@ "voiding": "" }, "fields": { + "active_tasks": "", "actual_completion": "Achèvement réel", "actual_delivery": "Livraison réelle", "actual_in": "En réel", @@ -1840,7 +1841,8 @@ "appointmentconfirmation": "Envoyer une confirmation au client?", "associationwarning": "", "audit": "", - "available": "", + "tasks": "", + "available": "", "availablejobs": "", "ca_bc_pvrt": { "days": "", @@ -2120,6 +2122,8 @@ "edit": "" }, "titles": { + "job_tasks": "", + "ny_tasks": "", "completed": "", "deleted": "" }, @@ -2128,14 +2132,17 @@ "complete": "", "delete": "", "edit": "", - "refresh":"" + "refresh":"", + "myTasks": "", + "allTasks": "" }, "placeholders": { "description": "", "jobid": "", "joblineid": "", "partsorderid": "", - "billid": "" + "billid": "", + "assigned_to": "" }, "fields": { "priorities": { @@ -3129,6 +3136,7 @@ "accounting-payments": "", "accounting-receivables": "", "app": "", + "tasks": "", "bc": { "tasks": "", "accounting-payables": "",