WIP on several user stories. BOD-10 BOD-52

This commit is contained in:
Patrick Fic
2020-03-23 17:40:48 -07:00
parent f04ba766ad
commit 7d33484294
10 changed files with 63 additions and 94 deletions

View File

@@ -1,3 +1,4 @@
import { ApolloProvider } from "@apollo/react-common";
import { ApolloLink } from "apollo-boost";
import { InMemoryCache } from "apollo-cache-inmemory";
import ApolloClient from "apollo-client";
@@ -8,22 +9,13 @@ import apolloLogger from "apollo-link-logger";
import { WebSocketLink } from "apollo-link-ws";
import { getMainDefinition } from "apollo-utilities";
import React, { Component } from "react";
import { ApolloProvider } from "react-apollo";
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
import SpinnerComponent from "../components/loading-spinner/loading-spinner.component";
//import { shouldRefreshToken, refreshToken } from "../graphql/middleware";
import errorLink from "../graphql/apollo-error-handling";
import App from "./App";
import { connect } from "react-redux";
import {
endLoading,
startLoading
} from "../redux/application/application.actions";
const mapDispatchToProps = dispatch => ({
startLoading: () => dispatch(startLoading()),
endLoading: () => dispatch(endLoading())
});
class AppContainer extends Component {
export default class AppContainer extends Component {
state = {
client: null,
loaded: false
@@ -92,23 +84,6 @@ class AppContainer extends Component {
middlewares.push(apolloLogger);
}
//New
// const startLoad = new ApolloLink((operation, forward) => {
// console.log("Starting", operation);
// this.props.startLoading();
// return forward(operation);
// });
// const endLoad = new ApolloLink((operation, forward) => {
// return forward(operation).map(response => {
// console.log("Completed", operation);
// this.props.endLoading();
// return response;
// });
// });
// middlewares.push(startLoad, endLoad);
//End new
middlewares.push(errorLink.concat(authLink.concat(link)));
const cache = new InMemoryCache();
@@ -130,15 +105,14 @@ class AppContainer extends Component {
render() {
const { client, loaded } = this.state;
if (!loaded) {
return <SpinnerComponent />;
return <SpinnerComponent message='Connecting to Bodyshop.app Database' />;
}
return (
<ApolloProvider client={client}>
<GlobalLoadingBar />
<App />
</ApolloProvider>
);
}
}
export default connect(null, mapDispatchToProps)(AppContainer);

View File

@@ -26,6 +26,7 @@ const mapStateToProps = createStructuredSelector({
const mapDispatchToProps = dispatch => ({
checkUserSession: () => dispatch(checkUserSession())
});
export default connect(
mapStateToProps,
mapDispatchToProps
@@ -34,6 +35,7 @@ export default connect(
checkUserSession();
return () => {};
}, [checkUserSession]);
const { t } = useTranslation();
if (currentUser && currentUser.language)
i18next.changeLanguage(currentUser.language, (err, t) => {
@@ -49,14 +51,13 @@ export default connect(
<div>
<Switch>
<ErrorBoundary>
<Suspense fallback={<LoadingSpinner />}>
<Suspense fallback={<LoadingSpinner message='In Suspense.' />}>
<Route exact path='/' component={LandingPage} />
<Route exact path='/unauthorized' component={Unauthorized} />
<Route exact path='/signin' component={SignInPage} />
<PrivateRoute
//isAuthorized={HookCurrentUser.data.currentUser ? true : false}
isAuthorized={currentUser.authorized}
path='/manage'
component={ManagePage}

View File

@@ -1,8 +1,8 @@
import { useNProgress } from "@tanem/react-nprogress";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectLoading } from "../../redux/application/application.selectors";
import { useNProgress } from "@tanem/react-nprogress";
const mapStateToProps = createStructuredSelector({
loading: selectLoading
@@ -11,6 +11,7 @@ const mapStateToProps = createStructuredSelector({
export default connect(mapStateToProps, null)(GlobalLoadingHeader);
function GlobalLoadingHeader({ loading }) {
const { animationDuration, isFinished, progress } = useNProgress({
isAnimating: loading
});
@@ -20,8 +21,7 @@ function GlobalLoadingHeader({ loading }) {
opacity: isFinished ? 0 : 1,
pointerEvents: "none",
transition: `opacity ${animationDuration}ms linear`
}}
>
}}>
<div
style={{
background: "#29d",
@@ -33,8 +33,7 @@ function GlobalLoadingHeader({ loading }) {
transition: `margin-left ${animationDuration}ms linear`,
width: "100%",
zIndex: 1031
}}
>
}}>
<div
style={{
boxShadow: "0 0 10px #29d, 0 0 5px #29d",

View File

@@ -3,78 +3,69 @@ import React from "react";
import { useTranslation } from "react-i18next";
import FormItemEmail from "../form-items-formatted/email-form-item.component";
import FormItemPhone from "../form-items-formatted/phone-form-item.component";
import ResetForm from "../form-items-formatted/reset-form-item.component";
export default function OwnerDetailFormComponent({ form }) {
const { t } = useTranslation();
const { isFieldsTouched, resetFields, getFieldValue } = form;
console.log("isFieldsTouched([], true)", isFieldsTouched([], true));
const { getFieldValue } = form;
return (
<div>
<button onClick={() => alert(getFieldValue("ownr_ea"))}>YY</button>
{isFieldsTouched([], true) ? (
<ResetForm resetFields={resetFields} />
) : null}
<Button type="primary" key="submit" htmlType="submit">
<Button type='primary' key='submit' htmlType='submit'>
{t("general.actions.save")}
</Button>
<Row>
<Col span={8}>
<Form.Item label={t("owners.fields.ownr_ln")} name="ownr_ln">
<Form.Item label={t("owners.fields.ownr_ln")} name='ownr_ln'>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_fn")} name="ownr_fn">
<Form.Item label={t("owners.fields.ownr_fn")} name='ownr_fn'>
<Input />
</Form.Item>
<Form.Item
label={t("owners.fields.allow_text_message")}
name="allow_text_message"
valuePropName="checked"
>
name='allow_text_message'
valuePropName='checked'>
<Switch />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_addr1")} name="ownr_addr1">
<Form.Item label={t("owners.fields.ownr_addr1")} name='ownr_addr1'>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_addr2")} name="ownr_addr2">
<Form.Item label={t("owners.fields.ownr_addr2")} name='ownr_addr2'>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_city")} name="ownr_city">
<Form.Item label={t("owners.fields.ownr_city")} name='ownr_city'>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_ctry")} name="ownr_ctry">
<Form.Item label={t("owners.fields.ownr_ctry")} name='ownr_ctry'>
<Input />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label={t("owners.fields.ownr_ea")}
name="ownr_ea"
name='ownr_ea'
rules={[
{
type: "email",
message: "This is not a valid email address."
}
]}
>
]}>
<FormItemEmail email={getFieldValue("ownr_ea")} />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_ph1")} name="ownr_ph1">
<Form.Item label={t("owners.fields.ownr_ph1")} name='ownr_ph1'>
<FormItemPhone customInput={Input} />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_st")} name="ownr_st">
<Form.Item label={t("owners.fields.ownr_st")} name='ownr_st'>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_zip")} name="ownr_zip">
<Form.Item label={t("owners.fields.ownr_zip")} name='ownr_zip'>
<Input />
</Form.Item>
<Form.Item
label={t("owners.fields.preferred_contact")}
name="preferred_contact"
>
name='preferred_contact'>
<Input />
</Form.Item>
<Form.Item label={t("owners.fields.ownr_title")} name="ownr_title">
<Form.Item label={t("owners.fields.ownr_title")} name='ownr_title'>
<Input />
</Form.Item>
</Col>

View File

@@ -65,6 +65,7 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
<OwnerDetailUpdateJobsComponent
selectedJobs={selectedJobs}
owner={owner}
disabled={selectedJobs.length === 0}
/>
</div>
)}
@@ -73,10 +74,10 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
rowKey='id'
dataSource={owner.jobs}
rowSelection={{
onSelect: props => {
setSelectedJobs([...selectedJobs, props.id]);
onSelect: (record, selected, selectedRows) => {
setSelectedJobs(selectedRows ? selectedRows.map(i => i.id) : []);
},
// type: "radio",
selectedRowKeys: selectedJobs,
getCheckboxProps: record => ({
disabled: bodyshop.md_ro_statuses.open_statuses

View File

@@ -6,7 +6,8 @@ import { UPDATE_JOBS } from "../../graphql/jobs.queries";
export default function OwnerDetailUpdateJobsComponent({
owner,
selectedJobs
selectedJobs,
disabled
}) {
const { t } = useTranslation();
const [updateJobs] = useMutation(UPDATE_JOBS);
@@ -32,6 +33,10 @@ export default function OwnerDetailUpdateJobsComponent({
}
});
};
return <Button onClick={handlecClick}>{t("owners.actions.update")}</Button>;
console.log("disabled", disabled);
return (
<Button disabled={disabled} onClick={handlecClick}>
{t("owners.actions.update")}
</Button>
);
}

View File

@@ -63,13 +63,20 @@ function JobsCreateContainer({ bodyshop }) {
let ownerData;
if (!!job.owner) {
ownerData = job.owner.data;
ownerData.shopid = bodyshop.id;
delete ownerData.allow_text_message;
delete ownerData.preferred_contact;
delete job.ownerid;
} else {
ownerData = RemoteOwnerData.data.owners_by_pk;
delete ownerData.id;
delete ownerData.__typename;
}
if (!!job.vehicle) {
delete job.vehicleid;
job.vehicle.data.shopid = bodyshop.id;
}
job = { ...job, ...ownerData };
runInsertJob(job);
};

View File

@@ -43,9 +43,7 @@ const ShopVendorPageContainer = lazy(() =>
const EmailOverlayContainer = lazy(() =>
import("../../components/email-overlay/email-overlay.container.jsx")
);
const GlobalLoadingBar = lazy(() =>
import("../../components/global-loading-bar/global-loading-bar.component")
);
const JobsCreateContainerPage = lazy(() =>
import("../jobs-create/jobs-create.container")
);
@@ -66,16 +64,13 @@ export default function Manage({ match }) {
</Header>
<Layout>
<Content
className="content-container"
style={{ padding: "0em 4em 4em" }}
>
<GlobalLoadingBar />
className='content-container'
style={{ padding: "0em 4em 4em" }}>
<ErrorBoundary>
<Suspense
fallback={
<LoadingSpinner message={t("general.labels.loadingapp")} />
}
>
}>
<EmailOverlayContainer />
<Route exact path={`${match.path}`} component={ManageRootPage} />
<Route exact path={`${match.path}/jobs`} component={JobsPage} />

View File

@@ -1,20 +1,16 @@
import { useQuery } from "@apollo/react-hooks";
import { notification } from "antd";
import React, { useEffect } from "react";
import { useQuery } from "@apollo/react-hooks";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries";
import { setBodyshop } from "../../redux/user/user.actions";
import {
selectBodyshop,
selectCurrentUser
} from "../../redux/user/user.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import ManagePage from "./manage.page.component";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
bodyshop: selectBodyshop
});
@@ -22,13 +18,11 @@ const mapDispatchToProps = dispatch => ({
setBodyshop: bs => dispatch(setBodyshop(bs))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(function ManagePageContainer({ match, setBodyshop, bodyshop }) {
function ManagePageContainer({ match, setBodyshop, bodyshop }) {
const { error, data } = useQuery(QUERY_BODYSHOP, {
fetchPolicy: "network-only"
});
const { t } = useTranslation();
if (error) {
notification["error"]({ message: t("bodyshop.errors.loading") });
@@ -36,10 +30,14 @@ export default connect(
useEffect(() => {
if (data) setBodyshop(data.bodyshops[0]);
return () => {};
}, [data, setBodyshop]);
if (!bodyshop)
return <LoadingSpinner message={t("general.labels.loadingshop")} />;
return <ManagePage match={match} />;
});
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ManagePageContainer);

View File

@@ -12203,8 +12203,6 @@ rxjs@^6.5.3:
version "6.5.4"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c"
integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==
dependencies:
tslib "^1.9.0"
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"