Added additional translations.
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
"antd": "^3.26.0",
|
"antd": "^3.26.0",
|
||||||
"apollo-boost": "^0.4.4",
|
"apollo-boost": "^0.4.4",
|
||||||
"apollo-link-context": "^1.0.19",
|
"apollo-link-context": "^1.0.19",
|
||||||
|
"apollo-link-error": "^1.1.12",
|
||||||
"apollo-link-logger": "^1.2.3",
|
"apollo-link-logger": "^1.2.3",
|
||||||
"apollo-link-ws": "^1.0.19",
|
"apollo-link-ws": "^1.0.19",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { ApolloProvider } from "react-apollo";
|
|||||||
import { persistCache } from "apollo-cache-persist";
|
import { persistCache } from "apollo-cache-persist";
|
||||||
import initialState from "../graphql/initial-state";
|
import initialState from "../graphql/initial-state";
|
||||||
import { shouldRefreshToken, refreshToken } from "../graphql/middleware";
|
import { shouldRefreshToken, refreshToken } from "../graphql/middleware";
|
||||||
|
import errorLink from "../graphql/apollo-error-handling";
|
||||||
|
|
||||||
class AppContainer extends Component {
|
class AppContainer extends Component {
|
||||||
state = {
|
state = {
|
||||||
@@ -72,9 +73,9 @@ class AppContainer extends Component {
|
|||||||
const token = localStorage.getItem("token");
|
const token = localStorage.getItem("token");
|
||||||
// return the headers to the context so httpLink can read them
|
// return the headers to the context so httpLink can read them
|
||||||
if (token) {
|
if (token) {
|
||||||
if (shouldRefreshToken) {
|
// if (shouldRefreshToken) {
|
||||||
refreshToken();
|
// refreshToken();
|
||||||
}
|
// }
|
||||||
|
|
||||||
return {
|
return {
|
||||||
headers: {
|
headers: {
|
||||||
@@ -91,7 +92,7 @@ class AppContainer extends Component {
|
|||||||
if (process.env.NODE_ENV === "development") {
|
if (process.env.NODE_ENV === "development") {
|
||||||
middlewares.push(apolloLogger);
|
middlewares.push(apolloLogger);
|
||||||
}
|
}
|
||||||
middlewares.push(authLink.concat(link));
|
middlewares.push(errorLink.concat(authLink.concat(link)));
|
||||||
|
|
||||||
const cache = new InMemoryCache();
|
const cache = new InMemoryCache();
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ export default () => {
|
|||||||
localStorage.setItem("token", token);
|
localStorage.setItem("token", token);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
window.sessionStorage.setItem(`lastTokenRefreshTime`, now);
|
window.sessionStorage.setItem(`lastTokenRefreshTime`, now);
|
||||||
|
// window.sessionStorage.setItem("user", user);
|
||||||
|
|
||||||
apolloClient
|
apolloClient
|
||||||
.mutate({
|
.mutate({
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import {
|
|||||||
Descriptions,
|
Descriptions,
|
||||||
Tag,
|
Tag,
|
||||||
notification,
|
notification,
|
||||||
Avatar
|
Avatar,
|
||||||
|
Layout
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
import { useMutation } from "@apollo/react-hooks";
|
import { useMutation } from "@apollo/react-hooks";
|
||||||
@@ -20,15 +21,16 @@ import FormItemPhone from "../form-items-formatted/phone-form-item.component";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import CarImage from "../../assets/car.svg";
|
import CarImage from "../../assets/car.svg";
|
||||||
|
|
||||||
|
const { Content } = Layout;
|
||||||
const formItemLayout = {
|
const formItemLayout = {
|
||||||
labelCol: {
|
// labelCol: {
|
||||||
xs: { span: 24 },
|
// xs: { span: 12 },
|
||||||
sm: { span: 5 }
|
// sm: { span: 5 }
|
||||||
},
|
// },
|
||||||
wrapperCol: {
|
// wrapperCol: {
|
||||||
xs: { span: 24 },
|
// xs: { span: 24 },
|
||||||
sm: { span: 12 }
|
// sm: { span: 12 }
|
||||||
}
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
function JobTombstone({ job, ...otherProps }) {
|
function JobTombstone({ job, ...otherProps }) {
|
||||||
@@ -77,108 +79,110 @@ function JobTombstone({ job, ...otherProps }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form onSubmit={handleSubmit} {...formItemLayout}>
|
<Content>
|
||||||
<PageHeader
|
<Form onSubmit={handleSubmit} {...formItemLayout}>
|
||||||
style={{
|
<PageHeader
|
||||||
border: "1px solid rgb(235, 237, 240)"
|
style={{
|
||||||
}}
|
border: "1px solid rgb(235, 237, 240)"
|
||||||
title={tombstoneTitle}
|
}}
|
||||||
subTitle={
|
title={tombstoneTitle}
|
||||||
jobContext.owner
|
subTitle={
|
||||||
? (jobContext.owner?.first_name ?? "") +
|
jobContext.owner
|
||||||
" " +
|
? (jobContext.owner?.first_name ?? "") +
|
||||||
(jobContext.owner?.last_name ?? "")
|
" " +
|
||||||
: t("jobs.labels.no_owner")
|
(jobContext.owner?.last_name ?? "")
|
||||||
}
|
: t("jobs.labels.no_owner")
|
||||||
tags={<Tag color='blue'>{jobContext?.job_status?.name}</Tag>}
|
}
|
||||||
extra={[
|
tags={<Tag color='blue'>{jobContext?.job_status?.name}</Tag>}
|
||||||
<Form.Item key='1'>
|
extra={[
|
||||||
<Button type='primary' htmlType='submit'>
|
<Form.Item key='1'>
|
||||||
{t("general.labels.save")}
|
<Button type='primary' htmlType='submit'>
|
||||||
</Button>
|
{t("general.labels.save")}
|
||||||
</Form.Item>
|
</Button>
|
||||||
]}>
|
</Form.Item>
|
||||||
<Descriptions size='small' column={5}>
|
]}>
|
||||||
<Descriptions.Item label={t("jobs.labels.vehicle_info")}>
|
<Descriptions size='small' column={5}>
|
||||||
<Link to={`/manage/vehicles/${jobContext.vehicle?.id}`}>
|
<Descriptions.Item label={t("jobs.labels.vehicle_info")}>
|
||||||
{jobContext.vehicle?.v_model_yr ?? t("general.labels.na")}{" "}
|
<Link to={`/manage/vehicles/${jobContext.vehicle?.id}`}>
|
||||||
{jobContext.vehicle?.v_make_desc ?? t("general.labels.na")}{" "}
|
{jobContext.vehicle?.v_model_yr ?? t("general.labels.na")}{" "}
|
||||||
{jobContext.vehicle?.v_model_desc ?? t("general.labels.na")} |{" "}
|
{jobContext.vehicle?.v_make_desc ?? t("general.labels.na")}{" "}
|
||||||
{jobContext.vehicle?.plate_no ?? t("general.labels.na")}
|
{jobContext.vehicle?.v_model_desc ?? t("general.labels.na")} |{" "}
|
||||||
</Link>
|
{jobContext.vehicle?.plate_no ?? t("general.labels.na")}
|
||||||
</Descriptions.Item>
|
</Link>
|
||||||
|
</Descriptions.Item>
|
||||||
|
|
||||||
<Descriptions.Item label={t("jobs.fields.est_number")}>
|
<Descriptions.Item label={t("jobs.fields.est_number")}>
|
||||||
{jobContext.est_number}
|
{jobContext.est_number}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
|
|
||||||
<Descriptions.Item label={t("jobs.fields.claim_total")}>
|
<Descriptions.Item label={t("jobs.fields.claim_total")}>
|
||||||
$ {jobContext.claim_total?.toFixed(2)}
|
$ {jobContext.claim_total?.toFixed(2)}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
|
|
||||||
<Descriptions.Item label={t("jobs.fields.deductible")}>
|
<Descriptions.Item label={t("jobs.fields.deductible")}>
|
||||||
$ {jobContext.deductible?.toFixed(2)}
|
$ {jobContext.deductible?.toFixed(2)}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
</Descriptions>
|
</Descriptions>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Typography.Title level={4}>Information</Typography.Title>
|
<Typography.Title level={4}>Information</Typography.Title>
|
||||||
{
|
{
|
||||||
// <Form.Item label='Estimate #'>
|
// <Form.Item label='Estimate #'>
|
||||||
// {getFieldDecorator("est_number", {
|
// {getFieldDecorator("est_number", {
|
||||||
// initialValue: jobContext.est_number
|
// initialValue: jobContext.est_number
|
||||||
// })(<Input name='est_number' readOnly onChange={handleChange} />)}
|
// })(<Input name='est_number' readOnly onChange={handleChange} />)}
|
||||||
// </Form.Item>
|
// </Form.Item>
|
||||||
}
|
}
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Typography.Title level={4}>Insurance Information</Typography.Title>
|
<Typography.Title level={4}>Insurance Information</Typography.Title>
|
||||||
<Form.Item label='Insurance Company'>
|
<Form.Item label='Insurance Company'>
|
||||||
{getFieldDecorator("est_co_nm", {
|
{getFieldDecorator("est_co_nm", {
|
||||||
initialValue: jobContext.est_co_nm
|
initialValue: jobContext.est_co_nm
|
||||||
})(<Input name='est_co_nm' onChange={handleChange} />)}
|
})(<Input name='est_co_nm' onChange={handleChange} />)}
|
||||||
</Form.Item>
|
|
||||||
<Col span={8}>
|
|
||||||
<Form.Item label='Estimator Last Name'>
|
|
||||||
{getFieldDecorator("est_ct_ln", {
|
|
||||||
initialValue: jobContext.est_ct_ln
|
|
||||||
})(<Input name='est_ct_ln' onChange={handleChange} />)}
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label='Estimator First Name'>
|
<Col span={8}>
|
||||||
{getFieldDecorator("est_ct_fn", {
|
<Form.Item label='Estimator Last Name'>
|
||||||
initialValue: jobContext.est_ct_fn
|
{getFieldDecorator("est_ct_ln", {
|
||||||
})(<Input name='est_ct_fn' onChange={handleChange} />)}
|
initialValue: jobContext.est_ct_ln
|
||||||
</Form.Item>
|
})(<Input name='est_ct_ln' onChange={handleChange} />)}
|
||||||
</Col>
|
</Form.Item>
|
||||||
<Col span={8}>
|
<Form.Item label='Estimator First Name'>
|
||||||
<Form.Item label='Estimator Phone #'>
|
{getFieldDecorator("est_ct_fn", {
|
||||||
{getFieldDecorator("est_ph1", {
|
initialValue: jobContext.est_ct_fn
|
||||||
initialValue: jobContext.est_ph1
|
})(<Input name='est_ct_fn' onChange={handleChange} />)}
|
||||||
})(
|
</Form.Item>
|
||||||
<FormItemPhone
|
</Col>
|
||||||
customInput={Input}
|
<Col span={8}>
|
||||||
name='est_ph1'
|
<Form.Item label='Estimator Phone #'>
|
||||||
onValueChange={handleChange}
|
{getFieldDecorator("est_ph1", {
|
||||||
/>
|
initialValue: jobContext.est_ph1
|
||||||
)}
|
})(
|
||||||
</Form.Item>
|
<FormItemPhone
|
||||||
<Form.Item label='Estimator Email'>
|
customInput={Input}
|
||||||
{getFieldDecorator("est_ea", {
|
name='est_ph1'
|
||||||
initialValue: jobContext.est_ea,
|
onValueChange={handleChange}
|
||||||
rules: [
|
/>
|
||||||
{
|
)}
|
||||||
type: "email",
|
</Form.Item>
|
||||||
message: "This is not a valid email address."
|
<Form.Item label='Estimator Email'>
|
||||||
}
|
{getFieldDecorator("est_ea", {
|
||||||
]
|
initialValue: jobContext.est_ea,
|
||||||
})(<Input name='est_ea' onChange={handleChange} />)}
|
rules: [
|
||||||
</Form.Item>
|
{
|
||||||
</Col>
|
type: "email",
|
||||||
</Row>
|
message: "This is not a valid email address."
|
||||||
</Form>
|
}
|
||||||
|
]
|
||||||
|
})(<Input name='est_ea' onChange={handleChange} />)}
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Form>
|
||||||
|
</Content>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Form.create({ name: "JobTombstone" })(JobTombstone);
|
export default Form.create({ name: "JobTombstone" })(JobTombstone);
|
||||||
58
client/src/graphql/apollo-error-handling.js
Normal file
58
client/src/graphql/apollo-error-handling.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { onError } from "apollo-link-error";
|
||||||
|
import { Observable } from "apollo-link";
|
||||||
|
import { auth } from "../firebase/firebase.utils";
|
||||||
|
//https://stackoverflow.com/questions/57163454/refreshing-a-token-with-apollo-client-firebase-auth
|
||||||
|
const errorLink = onError(
|
||||||
|
({ graphQLErrors, networkError, operation, forward }) => {
|
||||||
|
let access_token = window.localStorage.getItem("token");
|
||||||
|
if (graphQLErrors) {
|
||||||
|
// User access token has expired
|
||||||
|
if (graphQLErrors[0].message.includes("JWTExpired")) {
|
||||||
|
if (access_token && access_token !== "undefined") {
|
||||||
|
// Let's refresh token through async request
|
||||||
|
return new Observable(observer => {
|
||||||
|
auth.currentUser
|
||||||
|
.getIdToken(true)
|
||||||
|
.then(function(idToken) {
|
||||||
|
if (!idToken) {
|
||||||
|
window.localStorage.removeItem("token");
|
||||||
|
return console.log("Refresh token has expired");
|
||||||
|
}
|
||||||
|
|
||||||
|
window.localStorage.setItem("token", idToken);
|
||||||
|
|
||||||
|
// reset the headers
|
||||||
|
operation.setContext(({ headers = {} }) => ({
|
||||||
|
headers: {
|
||||||
|
// Re-add old headers
|
||||||
|
...headers,
|
||||||
|
// Switch out old access token for new one
|
||||||
|
authorization: idToken ? `Bearer ${idToken}` : ""
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
const subscriber = {
|
||||||
|
next: observer.next.bind(observer),
|
||||||
|
error: observer.error.bind(observer),
|
||||||
|
complete: observer.complete.bind(observer)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Retry last failed request
|
||||||
|
forward(operation).subscribe(subscriber);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// No refresh or client token available, we force user to login
|
||||||
|
observer.error(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkError) {
|
||||||
|
console.log(`[Network error]: ${networkError}`);
|
||||||
|
//props.history.push("/network-error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default errorLink;
|
||||||
@@ -20,6 +20,7 @@ export function shouldRefreshToken(minutesBeforeShouldRefresh = 45) {
|
|||||||
return aboutToExpire;
|
return aboutToExpire;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function refreshToken() {
|
export async function refreshToken() {
|
||||||
try {
|
try {
|
||||||
if (auth.user) {
|
if (auth.user) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from "react";
|
import React, { useEffect } from "react";
|
||||||
import { useSubscription } from "@apollo/react-hooks";
|
import { useSubscription } from "@apollo/react-hooks";
|
||||||
import SpinComponent from "../../components/loading-spinner/loading-spinner.component";
|
import SpinComponent from "../../components/loading-spinner/loading-spinner.component";
|
||||||
import AlertComponent from "../../components/alert/alert.component";
|
import AlertComponent from "../../components/alert/alert.component";
|
||||||
@@ -6,15 +6,26 @@ import JobTombstone from "../../components/job-tombstone/job-tombstone.component
|
|||||||
import { GET_JOB_BY_PK } from "../../graphql/jobs.queries";
|
import { GET_JOB_BY_PK } from "../../graphql/jobs.queries";
|
||||||
import { Tabs, Icon, Row } from "antd";
|
import { Tabs, Icon, Row } from "antd";
|
||||||
import JobLinesContainer from "../../components/job-lines/job-lines.container.component";
|
import JobLinesContainer from "../../components/job-lines/job-lines.container.component";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function JobsDetailPage({ match }) {
|
function JobsDetailPage({ match }) {
|
||||||
const { jobId } = match.params;
|
const { jobId } = match.params;
|
||||||
|
const { t } = useTranslation();
|
||||||
const { loading, error, data } = useSubscription(GET_JOB_BY_PK, {
|
const { loading, error, data } = useSubscription(GET_JOB_BY_PK, {
|
||||||
variables: { id: jobId },
|
variables: { id: jobId },
|
||||||
fetchPolicy: "network-only"
|
fetchPolicy: "network-only"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.title = loading
|
||||||
|
? "..."
|
||||||
|
: t("titles.jobsdetail", {
|
||||||
|
ro_number: data.jobs_by_pk.ro_number
|
||||||
|
});
|
||||||
|
}, [loading]);
|
||||||
|
|
||||||
if (loading) return <SpinComponent />;
|
if (loading) return <SpinComponent />;
|
||||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
if (error) return <AlertComponent message={error.message} type='error' />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -22,38 +33,35 @@ function JobsDetailPage({ match }) {
|
|||||||
<JobTombstone job={data.jobs_by_pk} />
|
<JobTombstone job={data.jobs_by_pk} />
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Tabs defaultActiveKey="lines">
|
<Tabs defaultActiveKey='lines'>
|
||||||
<Tabs.TabPane
|
<Tabs.TabPane
|
||||||
tab={
|
tab={
|
||||||
<span>
|
<span>
|
||||||
<Icon type="bars" />
|
<Icon type='bars' />
|
||||||
Lines
|
Lines
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
key="lines"
|
key='lines'>
|
||||||
>
|
|
||||||
<JobLinesContainer match={match} />
|
<JobLinesContainer match={match} />
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane
|
<Tabs.TabPane
|
||||||
tab={
|
tab={
|
||||||
<span>
|
<span>
|
||||||
<Icon type="dollar" />
|
<Icon type='dollar' />
|
||||||
Rates
|
Rates
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
key="rates"
|
key='rates'>
|
||||||
>
|
|
||||||
Estimate Rates
|
Estimate Rates
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane
|
<Tabs.TabPane
|
||||||
tab={
|
tab={
|
||||||
<span>
|
<span>
|
||||||
<Icon type="tool1" />
|
<Icon type='tool1' />
|
||||||
Parts
|
Parts
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
key="parts"
|
key='parts'>
|
||||||
>
|
|
||||||
Estimate Parts
|
Estimate Parts
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -3,16 +3,17 @@ import { useSubscription } from "@apollo/react-hooks";
|
|||||||
import AlertComponent from "../../components/alert/alert.component";
|
import AlertComponent from "../../components/alert/alert.component";
|
||||||
import { Col } from "antd";
|
import { Col } from "antd";
|
||||||
import { SUBSCRIPTION_ALL_OPEN_JOBS } from "../../graphql/jobs.queries";
|
import { SUBSCRIPTION_ALL_OPEN_JOBS } from "../../graphql/jobs.queries";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import JobsList from "../../components/jobs-list/jobs-list.component";
|
import JobsList from "../../components/jobs-list/jobs-list.component";
|
||||||
|
|
||||||
export default function JobsPage() {
|
export default function JobsPage() {
|
||||||
const { loading, error, data } = useSubscription(SUBSCRIPTION_ALL_OPEN_JOBS, {
|
const { loading, error, data } = useSubscription(SUBSCRIPTION_ALL_OPEN_JOBS, {
|
||||||
fetchPolicy: "network-only"
|
fetchPolicy: "network-only"
|
||||||
});
|
});
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = "new title";
|
document.title = t("titles.jobs");
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (error) return <AlertComponent message={error.message} />;
|
if (error) return <AlertComponent message={error.message} />;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { lazy, Suspense } from "react";
|
import React, { lazy, Suspense, useEffect } from "react";
|
||||||
import { Route } from "react-router";
|
import { Route } from "react-router";
|
||||||
import { Layout, BackTop } from "antd";
|
import { Layout, BackTop } from "antd";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
//Component Imports
|
//Component Imports
|
||||||
import HeaderContainer from "../../components/header/header.container";
|
import HeaderContainer from "../../components/header/header.container";
|
||||||
@@ -14,6 +15,12 @@ const JobsDetailPage = lazy(() => import("../jobs-detail/jobs-detail.page"));
|
|||||||
const { Header, Content, Footer } = Layout;
|
const { Header, Content, Footer } = Layout;
|
||||||
//This page will handle all routing for the entire application.
|
//This page will handle all routing for the entire application.
|
||||||
export default function Manage({ match }) {
|
export default function Manage({ match }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.title = t("titles.app");
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<Header>
|
<Header>
|
||||||
@@ -23,8 +30,7 @@ export default function Manage({ match }) {
|
|||||||
<Content>
|
<Content>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<Suspense
|
<Suspense
|
||||||
fallback={<div>TODO: Suspended Loading in Manage Page...</div>}
|
fallback={<div>TODO: Suspended Loading in Manage Page...</div>}>
|
||||||
>
|
|
||||||
<Route exact path={`${match.path}`} component={WhiteBoardPage} />
|
<Route exact path={`${match.path}`} component={WhiteBoardPage} />
|
||||||
|
|
||||||
<Route exact path={`${match.path}/jobs`} component={JobsPage} />
|
<Route exact path={`${match.path}/jobs`} component={JobsPage} />
|
||||||
|
|||||||
@@ -13,6 +13,11 @@
|
|||||||
"save": "Save"
|
"save": "Save"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"titles": {
|
||||||
|
"app": "Bodyshop by ImEX Systems",
|
||||||
|
"jobs": "All Jobs | $t(titles.app)",
|
||||||
|
"jobsdetail": "Job {{ro_number}} | $t(titles.app)"
|
||||||
|
},
|
||||||
|
|
||||||
"jobs": {
|
"jobs": {
|
||||||
"labels": {
|
"labels": {
|
||||||
|
|||||||
@@ -2313,7 +2313,7 @@ apollo-link-context@^1.0.19:
|
|||||||
apollo-link "^1.2.13"
|
apollo-link "^1.2.13"
|
||||||
tslib "^1.9.3"
|
tslib "^1.9.3"
|
||||||
|
|
||||||
apollo-link-error@^1.0.3:
|
apollo-link-error@^1.0.3, apollo-link-error@^1.1.12:
|
||||||
version "1.1.12"
|
version "1.1.12"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-link-error/-/apollo-link-error-1.1.12.tgz#e24487bb3c30af0654047611cda87038afbacbf9"
|
resolved "https://registry.yarnpkg.com/apollo-link-error/-/apollo-link-error-1.1.12.tgz#e24487bb3c30af0654047611cda87038afbacbf9"
|
||||||
integrity sha512-psNmHyuy3valGikt/XHJfe0pKJnRX19tLLs6P6EHRxg+6q6JMXNVLYPaQBkL0FkwdTCB0cbFJAGRYCBviG8TDA==
|
integrity sha512-psNmHyuy3valGikt/XHJfe0pKJnRX19tLLs6P6EHRxg+6q6JMXNVLYPaQBkL0FkwdTCB0cbFJAGRYCBviG8TDA==
|
||||||
|
|||||||
Reference in New Issue
Block a user