Refactored job line edit modal to use redux so that it can be an independent form. Created general modals reducer to manage all modals.
This commit is contained in:
@@ -15,107 +15,168 @@ export default ({
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
//TODO Add
|
||||
|
||||
return (
|
||||
<Row type='flex' justify='space-around' align='middle'>
|
||||
<Row type="flex" justify="space-around" align="middle">
|
||||
{logo ? (
|
||||
<Col span={4}>
|
||||
<img alt='Shop Logo' src={logo} style={{ height: "40px" }} />
|
||||
<Col span={3}>
|
||||
<img alt="Shop Logo" src={logo} style={{ height: "40px" }} />
|
||||
</Col>
|
||||
) : null}
|
||||
<Col span={14}>
|
||||
<Menu
|
||||
theme='dark'
|
||||
className='header'
|
||||
selectedKeys={selectedNavItem}
|
||||
mode='horizontal'
|
||||
onClick={handleMenuClick}>
|
||||
<Menu.Item key='home'>
|
||||
<Link to='/manage'>
|
||||
<Icon type='home' />
|
||||
{t("menus.header.home")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu title={t("menus.header.jobs")}>
|
||||
<Menu.Item key='schedule'>
|
||||
<Link to='/manage/schedule'>
|
||||
<Icon type='calendar' />
|
||||
{t("menus.header.schedule")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key='activejobs'>
|
||||
<Link to='/manage/jobs'>{t("menus.header.activejobs")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key='availablejobs'>
|
||||
<Link to='/manage/available'>
|
||||
{t("menus.header.availablejobs")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
{landingHeader ? (
|
||||
<Menu
|
||||
theme="dark"
|
||||
className="header"
|
||||
selectedKeys={selectedNavItem}
|
||||
mode="horizontal"
|
||||
onClick={handleMenuClick}
|
||||
>
|
||||
<ManageSignInButton />
|
||||
|
||||
<Menu.SubMenu title={t("menus.header.customers")}>
|
||||
<Menu.Item key='owners'>
|
||||
<Link to='/manage/owners'>
|
||||
<Icon type='team' />
|
||||
{t("menus.header.owners")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key='vehicles'>
|
||||
<Link to='/manage/vehicles'>
|
||||
<Icon type='car' />
|
||||
{t("menus.header.vehicles")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu title={t("menus.header.shop")}>
|
||||
<Menu.Item key='shop'>
|
||||
<Link to='/manage/shop'>{t("menus.header.shop_config")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key='shop-vendors'>
|
||||
<Link to='/manage/shop/vendors'>
|
||||
{t("menus.header.shop_vendors")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<div>
|
||||
<Avatar
|
||||
size='medium'
|
||||
alt='Avatar'
|
||||
src={currentUser.photoURL ? currentUser.photoURL : UserImage}
|
||||
style={{ margin: "10px" }}
|
||||
/>
|
||||
{currentUser.displayName || t("general.labels.unknown")}
|
||||
</div>
|
||||
}>
|
||||
<Menu.Item onClick={signOutStart()}>
|
||||
{t("user.actions.signout")}
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<Link to='/manage/profile'>{t("menus.currentuser.profile")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<Icon type='global' />
|
||||
<span>{t("menus.currentuser.languageselector")}</span>
|
||||
</span>
|
||||
}>
|
||||
<Menu.Item actiontype='lang-select' key='en_us'>
|
||||
{t("general.languages.english")}
|
||||
<div>
|
||||
<Avatar
|
||||
size="medium"
|
||||
alt="Avatar"
|
||||
src={
|
||||
currentUser.photoURL ? currentUser.photoURL : UserImage
|
||||
}
|
||||
style={{ margin: "10px" }}
|
||||
/>
|
||||
{currentUser.displayName || t("general.labels.unknown")}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Menu.Item onClick={signOutStart()}>
|
||||
{t("user.actions.signout")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype='lang-select' key='fr'>
|
||||
{t("general.languages.french")}
|
||||
<Menu.Item>
|
||||
<Link to="/manage/profile">
|
||||
{t("menus.currentuser.profile")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype='lang-select' key='es'>
|
||||
{t("general.languages.spanish")}
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<Icon type="global" />
|
||||
<span>{t("menus.currentuser.languageselector")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item actiontype="lang-select" key="en_us">
|
||||
{t("general.languages.english")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="fr">
|
||||
{t("general.languages.french")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="es">
|
||||
{t("general.languages.spanish")}
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
) : (
|
||||
<Menu
|
||||
theme="dark"
|
||||
className="header"
|
||||
selectedKeys={selectedNavItem}
|
||||
mode="horizontal"
|
||||
onClick={handleMenuClick}
|
||||
>
|
||||
<Menu.Item key="home">
|
||||
<Link to="/manage">
|
||||
<Icon type="home" />
|
||||
{t("menus.header.home")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu title={t("menus.header.jobs")}>
|
||||
<Menu.Item key="schedule">
|
||||
<Link to="/manage/schedule">
|
||||
<Icon type="calendar" />
|
||||
{t("menus.header.schedule")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="activejobs">
|
||||
<Link to="/manage/jobs">{t("menus.header.activejobs")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="availablejobs">
|
||||
<Link to="/manage/available">
|
||||
{t("menus.header.availablejobs")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
<Menu.SubMenu title={t("menus.header.customers")}>
|
||||
<Menu.Item key="owners">
|
||||
<Link to="/manage/owners">
|
||||
<Icon type="team" />
|
||||
{t("menus.header.owners")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="vehicles">
|
||||
<Link to="/manage/vehicles">
|
||||
<Icon type="car" />
|
||||
{t("menus.header.vehicles")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu title={t("menus.header.shop")}>
|
||||
<Menu.Item key="shop">
|
||||
<Link to="/manage/shop">{t("menus.header.shop_config")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="shop-vendors">
|
||||
<Link to="/manage/shop/vendors">
|
||||
{t("menus.header.shop_vendors")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<div>
|
||||
<Avatar
|
||||
size="medium"
|
||||
alt="Avatar"
|
||||
src={
|
||||
currentUser.photoURL ? currentUser.photoURL : UserImage
|
||||
}
|
||||
style={{ margin: "10px" }}
|
||||
/>
|
||||
{currentUser.displayName || t("general.labels.unknown")}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Menu.Item onClick={signOutStart()}>
|
||||
{t("user.actions.signout")}
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<Link to="/manage/profile">
|
||||
{t("menus.currentuser.profile")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<Icon type="global" />
|
||||
<span>{t("menus.currentuser.languageselector")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item actiontype="lang-select" key="en_us">
|
||||
{t("general.languages.english")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="fr">
|
||||
{t("general.languages.french")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="es">
|
||||
{t("general.languages.spanish")}
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
)}
|
||||
</Col>
|
||||
<Col span={4}>{!landingHeader ? null : <ManageSignInButton />}</Col>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { Button, Input, Table } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import { alphaSort } from "../../utils/sorters";
|
||||
import { Link } from "react-router-dom";
|
||||
//import EditableCell from "./job-lines-cell.component";
|
||||
import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container";
|
||||
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
|
||||
import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container";
|
||||
import JobLineUpsertModalContainer from "../job-lines-upsert-modal/job-lines-upsert-modal.container";
|
||||
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
|
||||
|
||||
export default function JobLinesComponent({
|
||||
loading,
|
||||
refetch,
|
||||
@@ -18,8 +17,7 @@ export default function JobLinesComponent({
|
||||
setSelectedLines,
|
||||
partsOrderModalVisible,
|
||||
jobId,
|
||||
editLineModalVisible,
|
||||
lineToEdit
|
||||
setJobLineEditContext
|
||||
}) {
|
||||
const [state, setState] = useState({
|
||||
sortedInfo: {}
|
||||
@@ -145,9 +143,8 @@ export default function JobLinesComponent({
|
||||
{record.allocations && record.allocations.length > 0
|
||||
? record.allocations.map(item => (
|
||||
<div
|
||||
key={
|
||||
item.id
|
||||
}>{`${item.employee.first_name} ${item.employee.last_name} (${item.hours})`}</div>
|
||||
key={item.id}
|
||||
>{`${item.employee.first_name} ${item.employee.last_name} (${item.hours})`}</div>
|
||||
))
|
||||
: null}
|
||||
<AllocationsAssignmentContainer
|
||||
@@ -167,9 +164,14 @@ export default function JobLinesComponent({
|
||||
<span>
|
||||
<Button
|
||||
onClick={() => {
|
||||
lineToEdit[1](record);
|
||||
editLineModalVisible[1](true);
|
||||
}}>
|
||||
setJobLineEditContext({
|
||||
actions: { refetch: refetch },
|
||||
context: record
|
||||
});
|
||||
//lineToEdit[1](record);
|
||||
//editLineModalVisible[1](true);
|
||||
}}
|
||||
>
|
||||
{t("general.actions.edit")}
|
||||
</Button>
|
||||
</span>
|
||||
@@ -201,14 +203,6 @@ export default function JobLinesComponent({
|
||||
jobId={jobId}
|
||||
/>
|
||||
|
||||
<JobLineUpsertModalContainer
|
||||
jobId={jobId}
|
||||
visible={editLineModalVisible[0]}
|
||||
changeVisibility={editLineModalVisible[1]}
|
||||
refetch={refetch}
|
||||
existingLine={lineToEdit[0]}
|
||||
/>
|
||||
|
||||
<Table
|
||||
title={() => {
|
||||
return (
|
||||
@@ -222,7 +216,8 @@ export default function JobLinesComponent({
|
||||
/>
|
||||
<Button
|
||||
disabled={selectedLines.length > 0 ? false : true}
|
||||
onClick={() => setPartsModalVisible(true)}>
|
||||
onClick={() => setPartsModalVisible(true)}
|
||||
>
|
||||
{t("parts.actions.order")}
|
||||
</Button>
|
||||
<AllocationsBulkAssignmentContainer
|
||||
@@ -234,7 +229,7 @@ export default function JobLinesComponent({
|
||||
}}
|
||||
{...formItemLayout}
|
||||
loading={loading}
|
||||
size='small'
|
||||
size="small"
|
||||
expandedRowRender={record => (
|
||||
<div style={{ margin: 0 }}>
|
||||
<strong>{t("parts_orders.labels.orderhistory")}</strong>
|
||||
@@ -252,11 +247,14 @@ export default function JobLinesComponent({
|
||||
pagination={{ position: "top", defaultPageSize: 25 }}
|
||||
rowSelection={{
|
||||
// selectedRowKeys: selectedLines,
|
||||
onSelectAll: (selected, selectedRows, changeRows) => {
|
||||
setSelectedLines(selectedRows);
|
||||
},
|
||||
onSelect: (record, selected, selectedRows, nativeEvent) =>
|
||||
setSelectedLines(selectedRows)
|
||||
}}
|
||||
columns={columns.map(item => ({ ...item }))}
|
||||
rowKey='id'
|
||||
rowKey="id"
|
||||
dataSource={jobLines}
|
||||
onChange={handleTableChange}
|
||||
/>
|
||||
|
||||
@@ -5,9 +5,16 @@ import { GET_JOB_LINES_BY_PK } from "../../graphql/jobs-lines.queries";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import JobLinesComponent from "./job-lines.component";
|
||||
|
||||
//export default Form.create({ name: "JobsDetailJobLines" })(
|
||||
|
||||
export default function JobLinesContainer({ jobId }) {
|
||||
import { connect } from "react-redux";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
setJobLineEditContext: context =>
|
||||
dispatch(setModalContext({ context: context, modal: "jobLineEdit" }))
|
||||
});
|
||||
export default connect(
|
||||
null,
|
||||
mapDispatchToProps
|
||||
)(function JobLinesContainer({ jobId, setJobLineEditContext }) {
|
||||
const { loading, error, data, refetch } = useQuery(GET_JOB_LINES_BY_PK, {
|
||||
variables: { id: jobId },
|
||||
fetchPolicy: "network-only"
|
||||
@@ -16,10 +23,8 @@ export default function JobLinesContainer({ jobId }) {
|
||||
const [searchText, setSearchText] = useState("");
|
||||
const [selectedLines, setSelectedLines] = useState([]);
|
||||
const partsOrderModalVisible = useState(false);
|
||||
const editLineModalVisible = useState(false);
|
||||
const lineToEdit = useState({});
|
||||
|
||||
if (error) return <AlertComponent message={error.message} type='error' />;
|
||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||
|
||||
return (
|
||||
<JobLinesComponent
|
||||
@@ -61,9 +66,7 @@ export default function JobLinesContainer({ jobId }) {
|
||||
setSelectedLines={setSelectedLines}
|
||||
partsOrderModalVisible={partsOrderModalVisible}
|
||||
jobId={jobId}
|
||||
editLineModalVisible={editLineModalVisible}
|
||||
lineToEdit={lineToEdit}
|
||||
setJobLineEditContext={setJobLineEditContext}
|
||||
/>
|
||||
);
|
||||
}
|
||||
//);
|
||||
});
|
||||
|
||||
@@ -1,31 +1,33 @@
|
||||
import { Input, Modal } from "antd";
|
||||
import { Modal, Form } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function JobLinesUpsertModalComponent({
|
||||
visible,
|
||||
changeVisibility,
|
||||
lineState,
|
||||
setLineState,
|
||||
updateExistingLine,
|
||||
insertNewLine
|
||||
jobLine,
|
||||
handleOk,
|
||||
handleCancel,
|
||||
handleSubmit,
|
||||
form
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const handleChange = e => {
|
||||
setLineState({ ...lineState, [e.target.name]: e.target.value });
|
||||
};
|
||||
//const { getFieldDecorator, isFieldsTouched, resetFields } = form;
|
||||
console.log("jobLine", jobLine);
|
||||
return (
|
||||
<Modal
|
||||
title={lineState.id ? t("joblines.label.edit") : t("joblines.label.new")}
|
||||
title={
|
||||
jobLine && jobLine.id
|
||||
? t("joblines.labels.edit")
|
||||
: t("joblines.labels.new")
|
||||
}
|
||||
visible={visible}
|
||||
okText={t("general.labels.save")}
|
||||
onOk={() => {
|
||||
lineState.id ? updateExistingLine() : insertNewLine();
|
||||
}}
|
||||
onCancel={() => {
|
||||
changeVisibility(false);
|
||||
}}>
|
||||
<Input.TextArea rows={8} value={lineState.text} onChange={handleChange} />
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<Form onSubmit={handleSubmit} autoComplete={"off"}>
|
||||
{JSON.stringify(jobLine)}
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,71 +1,102 @@
|
||||
import { notification } from "antd";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Form, notification } from "antd";
|
||||
import React from "react";
|
||||
import { useMutation } from "react-apollo";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import {
|
||||
INSERT_NEW_JOB_LINE,
|
||||
UPDATE_JOB_LINE
|
||||
} from "../../graphql/jobs-lines.queries";
|
||||
import { toggleModalVisible } from "../../redux/modals/modals.actions";
|
||||
import { selectJobLineEditModal } from "../../redux/modals/modals.selectors";
|
||||
import JobLinesUpdsertModal from "./job-lines-upsert-modal.component";
|
||||
|
||||
export default function JobLinesUpsertModalContainer({
|
||||
jobId,
|
||||
visible,
|
||||
changeVisibility,
|
||||
refetch,
|
||||
existingLine
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobLineEditModal: selectJobLineEditModal
|
||||
});
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
toggleModalVisible: () => dispatch(toggleModalVisible("jobLineEdit"))
|
||||
});
|
||||
|
||||
function JobLinesUpsertModalContainer({
|
||||
jobLineEditModal,
|
||||
toggleModalVisible,
|
||||
form
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [insertJobLine] = useMutation(INSERT_NEW_JOB_LINE);
|
||||
const [updateJobLine] = useMutation(UPDATE_JOB_LINE);
|
||||
|
||||
const [lineState, setLineState] = useState({});
|
||||
const handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
|
||||
useEffect(() => {
|
||||
//Required to prevent infinite looping.
|
||||
if (existingLine) {
|
||||
setLineState(existingLine);
|
||||
}
|
||||
}, [existingLine]);
|
||||
|
||||
const insertNewLine = () => {
|
||||
insertJobLine({
|
||||
variables: {
|
||||
lineInput: [{ ...lineState, jobid: jobId }]
|
||||
form.validateFieldsAndScroll((err, values) => {
|
||||
if (err) {
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.validationtitle"),
|
||||
description: t("jobs.errors.validation")
|
||||
});
|
||||
}
|
||||
if (!err) {
|
||||
if (true) {
|
||||
insertJobLine({
|
||||
variables: {
|
||||
//lineInput: [{ ...lineState, jobid: jobId }]
|
||||
}
|
||||
}).then(r => {
|
||||
if (jobLineEditModal.actions.refetch)
|
||||
jobLineEditModal.actions.refetch();
|
||||
toggleModalVisible();
|
||||
notification["success"]({
|
||||
message: t("joblines.successes.create")
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (false) {
|
||||
//Required, otherwise unable to spread in new note prop.
|
||||
//delete lineState.__typename;
|
||||
updateJobLine({
|
||||
variables: {
|
||||
//lineId: lineState.id,
|
||||
//line: lineState
|
||||
}
|
||||
}).then(r => {
|
||||
notification["success"]({
|
||||
message: t("joblines.successes.updated")
|
||||
});
|
||||
});
|
||||
if (jobLineEditModal.actions.refetch)
|
||||
jobLineEditModal.actions.refetch();
|
||||
toggleModalVisible();
|
||||
}
|
||||
}
|
||||
}).then(r => {
|
||||
refetch();
|
||||
changeVisibility(!visible);
|
||||
notification["success"]({
|
||||
message: t("joblines.successes.create")
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const updateExistingLine = () => {
|
||||
//Required, otherwise unable to spread in new note prop.
|
||||
delete lineState.__typename;
|
||||
updateJobLine({
|
||||
variables: {
|
||||
lineId: lineState.id,
|
||||
line: lineState
|
||||
}
|
||||
}).then(r => {
|
||||
notification["success"]({
|
||||
message: t("joblines.successes.updated")
|
||||
});
|
||||
});
|
||||
refetch();
|
||||
changeVisibility(!visible);
|
||||
const handleOk = () => {
|
||||
//lineState.id ? updateExistingLine() : insertNewLine();
|
||||
};
|
||||
const handleCancel = () => {
|
||||
toggleModalVisible();
|
||||
};
|
||||
|
||||
return (
|
||||
<JobLinesUpdsertModal
|
||||
visible={visible}
|
||||
changeVisibility={changeVisibility}
|
||||
updateExistingLine={updateExistingLine}
|
||||
insertNewLine={insertNewLine}
|
||||
lineState={lineState}
|
||||
setLineState={setLineState}
|
||||
visible={jobLineEditModal.visible}
|
||||
jobLine={jobLineEditModal.context}
|
||||
handleSubmit={handleSubmit}
|
||||
handleOk={handleOk}
|
||||
handleCancel={handleCancel}
|
||||
form={form}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(
|
||||
Form.create({ name: "JobsDetailPageContainer" })(JobLinesUpsertModalContainer)
|
||||
);
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { Form, Icon, Tabs } from "antd";
|
||||
import React, { useContext } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FaHardHat, FaInfo, FaRegStickyNote, FaShieldAlt } from "react-icons/fa";
|
||||
import {
|
||||
FaHardHat,
|
||||
FaInfo,
|
||||
FaRegStickyNote,
|
||||
FaShieldAlt
|
||||
} from "react-icons/fa";
|
||||
import ResetForm from "../../components/form-items-formatted/reset-form-item.component";
|
||||
import JobsLinesContainer from "../../components/job-detail-lines/job-lines.container";
|
||||
import JobsDetailClaims from "../../components/jobs-detail-claims/jobs-detail-claims.component";
|
||||
@@ -13,6 +18,7 @@ import JobsDocumentsContainer from "../../components/jobs-documents/jobs-documen
|
||||
import JobNotesContainer from "../../components/jobs-notes/jobs-notes.container";
|
||||
import ScheduleJobModalContainer from "../../components/schedule-job-modal/schedule-job-modal.container";
|
||||
import JobDetailFormContext from "./jobs-detail.page.context";
|
||||
import JobLineUpsertModalContainer from "../../components/job-lines-upsert-modal/job-lines-upsert-modal.container";
|
||||
|
||||
export default function JobsDetailPage({
|
||||
job,
|
||||
@@ -46,6 +52,8 @@ export default function JobsDetailPage({
|
||||
refetch={refetch}
|
||||
/>
|
||||
|
||||
<JobLineUpsertModalContainer />
|
||||
|
||||
<Form onSubmit={handleSubmit} {...formItemLayout} autoComplete={"off"}>
|
||||
<JobsDetailHeader
|
||||
job={job}
|
||||
|
||||
12
client/src/redux/modals/modals.actions.js
Normal file
12
client/src/redux/modals/modals.actions.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import ModalsActionTypes from "./modals.types";
|
||||
|
||||
export const toggleModalVisible = modalName => ({
|
||||
type: ModalsActionTypes.TOGGLE_MODAL_VISIBLE,
|
||||
payload: modalName
|
||||
});
|
||||
|
||||
//Modal Context: {context (context object), modal(name of modal)}
|
||||
export const setModalContext = modalContext => ({
|
||||
type: ModalsActionTypes.SET_MODAL_CONTEXT,
|
||||
payload: modalContext
|
||||
});
|
||||
37
client/src/redux/modals/modals.reducer.js
Normal file
37
client/src/redux/modals/modals.reducer.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import ModalsActionTypes from "./modals.types";
|
||||
|
||||
const INITIAL_STATE = {
|
||||
jobLineEdit: {
|
||||
visible: false,
|
||||
context: null,
|
||||
actions: {
|
||||
refetch: null
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const modalsReducer = (state = INITIAL_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case ModalsActionTypes.TOGGLE_MODAL_VISIBLE:
|
||||
return {
|
||||
...state,
|
||||
[action.payload]: {
|
||||
...state[action.payload],
|
||||
visible: !state[action.payload].visible
|
||||
}
|
||||
};
|
||||
case ModalsActionTypes.SET_MODAL_CONTEXT:
|
||||
return {
|
||||
...state,
|
||||
[action.payload.modal]: {
|
||||
...state[action.payload.modal],
|
||||
...action.payload.context,
|
||||
visible: true
|
||||
}
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default modalsReducer;
|
||||
24
client/src/redux/modals/modals.sagas.js
Normal file
24
client/src/redux/modals/modals.sagas.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import { all } from "redux-saga/effects";
|
||||
|
||||
// export function* onSendEmail() {
|
||||
// yield takeLatest(EmailActionTypes.SEND_EMAIL, sendEmail);
|
||||
// }
|
||||
// export function* sendEmail(payload) {
|
||||
// try {
|
||||
// console.log("Sending thta email", payload);
|
||||
// axios.post("/sendemail", payload).then(response => {
|
||||
// console.log(JSON.stringify(response));
|
||||
// put(sendEmailSuccess());
|
||||
// });
|
||||
// } catch (error) {
|
||||
// console.log("Error in sendEmail saga.");
|
||||
// yield put(sendEmailFailure(error.message));
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
export function* modalsSagas() {
|
||||
yield all([
|
||||
//call(onSendEmail),
|
||||
]);
|
||||
}
|
||||
9
client/src/redux/modals/modals.selectors.js
Normal file
9
client/src/redux/modals/modals.selectors.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createSelector } from "reselect";
|
||||
|
||||
const selectModals = state => state.modals;
|
||||
|
||||
export const selectJobLineEditModal = createSelector(
|
||||
[selectModals],
|
||||
modals => modals.jobLineEdit
|
||||
);
|
||||
|
||||
5
client/src/redux/modals/modals.types.js
Normal file
5
client/src/redux/modals/modals.types.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const ModalActionTypes = {
|
||||
TOGGLE_MODAL_VISIBLE: "TOGGLE_MODAL_VISIBLE",
|
||||
SET_MODAL_CONTEXT: "SET_JOBLINEEDIT_CONTEXT"
|
||||
};
|
||||
export default ModalActionTypes;
|
||||
@@ -5,18 +5,19 @@ import storage from "redux-persist/lib/storage";
|
||||
import userReducer from "./user/user.reducer";
|
||||
import messagingReducer from "./messaging/messaging.reducer";
|
||||
import emailReducer from "./email/email.reducer";
|
||||
|
||||
import modalsReducer from './modals/modals.reducer'
|
||||
const persistConfig = {
|
||||
key: "root",
|
||||
storage,
|
||||
//whitelist: ["user"]
|
||||
blacklist: ["user", "email", "messaging"]
|
||||
blacklist: ["user", "email", "messaging", "modals"]
|
||||
};
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
user: userReducer,
|
||||
messaging: messagingReducer,
|
||||
email: emailReducer
|
||||
email: emailReducer,
|
||||
modals: modalsReducer
|
||||
});
|
||||
|
||||
export default persistReducer(persistConfig, rootReducer);
|
||||
|
||||
@@ -3,6 +3,8 @@ import { all, call } from "redux-saga/effects";
|
||||
import { userSagas } from "./user/user.sagas";
|
||||
import { messagingSagas } from "./messaging/messaging.sagas";
|
||||
import { emailSagas } from "./email/email.sagas";
|
||||
import { modalsSagas } from "./modals/modals.sagas";
|
||||
export default function* rootSaga() {
|
||||
yield all([call(userSagas), call(messagingSagas), call(emailSagas)]);
|
||||
yield all([call(userSagas), call(messagingSagas), call(emailSagas),
|
||||
call(modalsSagas)]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user