diff --git a/client/src/App/App.container.jsx b/client/src/App/App.container.jsx index 58b35ff7c..148ed0fe0 100644 --- a/client/src/App/App.container.jsx +++ b/client/src/App/App.container.jsx @@ -30,6 +30,7 @@ class AppContainer extends Component { const wsLink = new WebSocketLink({ uri: process.env.REACT_APP_GRAPHQL_ENDPOINT_WS, options: { + lazy: true, reconnect: true, connectionParams: () => { const token = localStorage.getItem("token"); @@ -49,7 +50,11 @@ class AppContainer extends Component { ({ query }) => { const definition = getMainDefinition(query); console.log( - "##Intercepted GQL Transaction##" + definition.operation, + "##Intercepted GQL Transaction : " + + definition.operation + + "|" + + definition.name.value + + "##", query ); return ( diff --git a/client/src/App/App.js b/client/src/App/App.js index ec1fd98d4..543b9209d 100644 --- a/client/src/App/App.js +++ b/client/src/App/App.js @@ -13,20 +13,17 @@ import SignInPage from "../pages/sign-in/sign-in.page"; import Unauthorized from "../pages/unauthorized/unauthorized.component"; import { auth } from "../firebase/firebase.utils"; - +import { UPSERT_USER } from "../graphql/user.queries"; import { GET_CURRENT_USER } from "../graphql/local.queries"; import LoadingSpinner from "../components/loading-spinner/loading-spinner.component"; import AlertComponent from "../components/alert/alert.component"; -import SignOut from "../components/sign-out/sign-out.component"; - -import { UPSERT_USER } from "../graphql/user.queries"; export default () => { const apolloClient = useApolloClient(); useEffect(() => { //Run the auth code only on the first render. - const unsubscribeFromAuth = auth.onAuthStateChanged(async user => { + const unsubscribeFromAuth = auth.onIdTokenChanged(async user => { if (user) { let token; token = await user.getIdToken(); @@ -85,7 +82,6 @@ export default () => { return ; return (
- diff --git a/client/src/components/global-search/global-search.component.jsx b/client/src/components/global-search/global-search.component.jsx new file mode 100644 index 000000000..7b9042fda --- /dev/null +++ b/client/src/components/global-search/global-search.component.jsx @@ -0,0 +1,80 @@ +import React from "react"; +import { Icon, Button, Input, AutoComplete } from "antd"; + +const { Option } = AutoComplete; + +function onSelect(value) { + console.log("onSelect", value); +} + +function getRandomInt(max, min = 0) { + return Math.floor(Math.random() * (max - min + 1)) + min; // eslint-disable-line no-mixed-operators +} + +function searchResult(query) { + return new Array(getRandomInt(5)) + .join(".") + .split(".") + .map((item, idx) => ({ + query, + category: `${query}${idx}`, + count: getRandomInt(200, 100) + })); +} + +function renderOption(item) { + return ( + + ); +} + +export default class GlobalSearch extends React.Component { + state = { + dataSource: [] + }; + + handleSearch = value => { + this.setState({ + dataSource: value ? searchResult(value) : [] + }); + }; + + render() { + const { dataSource } = this.state; + return ( +
+ + + + + } + /> + +
+ ); + } +} diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index d864afc0b..74fc26e47 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -8,38 +8,56 @@ import { GET_LANDING_NAV_ITEMS, GET_NAV_ITEMS } from "../../graphql/metadata.queries"; +import { GET_CURRENT_SELECTED_NAV_ITEM } from "../../graphql/local.queries"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import AlertComponent from "../alert/alert.component"; +import ManageSignInButton from "../manage-sign-in-button/manage-sign-in-button.component"; +import { useApolloClient } from "@apollo/react-hooks"; +import GlobalSearch from "../global-search/global-search.component"; -export default ({ landingHeader }) => { - let HookNavItems; +export default ({ landingHeader, signedIn }) => { + const apolloClient = useApolloClient(); + const hookSelectedNavItem = useQuery(GET_CURRENT_SELECTED_NAV_ITEM); + let hookNavItems; if (landingHeader) { - HookNavItems = useQuery(GET_LANDING_NAV_ITEMS); + hookNavItems = useQuery(GET_LANDING_NAV_ITEMS, { + fetchPolicy: "network-only" + }); } else { - HookNavItems = useQuery(GET_NAV_ITEMS); + hookNavItems = useQuery(GET_NAV_ITEMS, { + fetchPolicy: "network-only" + }); } const handleClick = e => { - console.log("click ", e); - // this.setState({ - // current: e.key - // }); + apolloClient.writeData({ data: { selectedNavItem: e.key } }); }; - if (HookNavItems.loading) return ; - if (HookNavItems.error) - return ; + if (hookNavItems.loading || hookSelectedNavItem.loading) + return ; + if (hookNavItems.error) + return ; + if (hookSelectedNavItem.error) + return console.log( + "Unable to load Selected Navigation Item.", + hookSelectedNavItem.error + ); + + const { selectedNavItem } = hookSelectedNavItem.data; + const navItems = JSON.parse(hookNavItems.data.masterdata_by_pk.value); - const navItems = JSON.parse(HookNavItems.data.masterdata_by_pk.value); return ( + + + {navItems.map(navItem => ( @@ -48,11 +66,16 @@ export default ({ landingHeader }) => { ))} + {!landingHeader ? ( - ) : null} + ) : ( + + + + )} ); }; diff --git a/client/src/components/manage-sign-in-button/manage-sign-in-button.component.jsx b/client/src/components/manage-sign-in-button/manage-sign-in-button.component.jsx new file mode 100644 index 000000000..dca1ad63f --- /dev/null +++ b/client/src/components/manage-sign-in-button/manage-sign-in-button.component.jsx @@ -0,0 +1,33 @@ +import React from "react"; +import { useQuery } from "react-apollo"; +import { Link } from "react-router-dom"; +import { GET_CURRENT_USER } from "../../graphql/local.queries"; +import { Icon } from "antd"; + +export default function ManageSignInButton() { + const { + loading, + error, + data: { currentUser } + } = useQuery(GET_CURRENT_USER); + + if (loading) return "MSI Loading"; + if (error) return error.message; + console.log("currentUser", currentUser); + return currentUser ? ( +
+ {" "} + + + Manage + +
+ ) : ( +
+ + + Sign In + +
+ ); +} diff --git a/client/src/graphql/local.queries.js b/client/src/graphql/local.queries.js index b5f469097..d0c4298c0 100644 --- a/client/src/graphql/local.queries.js +++ b/client/src/graphql/local.queries.js @@ -9,7 +9,7 @@ export const SET_CURRENT_USER = gql` `; export const GET_CURRENT_USER = gql` - { + query GET_CURRENT_USER { currentUser @client { email displayName @@ -20,6 +20,12 @@ export const GET_CURRENT_USER = gql` } `; +export const GET_CURRENT_SELECTED_NAV_ITEM = gql` + query GET_CURRENT_SELECTED_NAV_ITEM { + selectedNavItem @client + } +`; + export const GET_WHITE_BOARD_LEFT_SIDER_VISIBLE = gql` { whiteBoardLeftSiderVisible @client diff --git a/client/src/pages/jobs/jobs.page.jsx b/client/src/pages/jobs/jobs.page.jsx index 8c4864d4d..1134c8e22 100644 --- a/client/src/pages/jobs/jobs.page.jsx +++ b/client/src/pages/jobs/jobs.page.jsx @@ -1,18 +1,16 @@ -import React from "react"; -import { useQuery, useSubscription } from "@apollo/react-hooks"; +import React, { useState } from "react"; +import { useSubscription } from "@apollo/react-hooks"; import AlertComponent from "../../components/alert/alert.component"; //import { GET_ALL_OPEN_JOBS } from "../../graphql/jobs.queries"; import { Table, Divider, Icon } from "antd"; +import { alphaSort } from "../../utils/sorters"; -import { - GET_ALL_OPEN_JOBS, - SUBSCRIPTION_ALL_OPEN_JOBS -} from "../../graphql/jobs.queries"; +import { SUBSCRIPTION_ALL_OPEN_JOBS } from "../../graphql/jobs.queries"; +//import { columns } from "./jobs.page.metadata"; export default function JobsPage() { - // const { loading, error, data } = useQuery(GET_ALL_OPEN_JOBS, { - // fetchPolicy: "network-only" - // }); + const [sortedInfo, setSortedInfo] = useState({}); + const { loading, error, data } = useSubscription(SUBSCRIPTION_ALL_OPEN_JOBS, { fetchPolicy: "network-only" }); @@ -21,7 +19,10 @@ export default function JobsPage() { { title: "RO #", dataIndex: "ro_number", - key: "ro_number" + key: "ro_number", + sorter: (a, b) => alphaSort(a, b), + sortOrder: sortedInfo.columnKey === "ro_number" && sortedInfo.order, + ellipsis: true }, { title: "Est. #", @@ -31,7 +32,10 @@ export default function JobsPage() { { title: "Status", dataIndex: "status", - key: "status" + key: "status", + sorter: (a, b) => alphaSort(a, b), + sortOrder: sortedInfo.columnKey === "status" && sortedInfo.order, + ellipsis: true }, { title: "Customer", @@ -67,22 +71,25 @@ export default function JobsPage() { key: "action", render: (text, record) => ( - Action 一 {record.ro_number} + Action 一 {record.ro_number} - Delete - - More actions - + More actions ) } ]; - if (error) { - console.log("error", error); - return ; - } + const handleChange = (pagination, filters, sorter) => { + console.log("Various parameters", pagination, filters, sorter); + // this.setState({ + // filteredInfo: filters, + // sortedInfo: sorter, + // }); + setSortedInfo(sorter); + }; + + if (error) return ; return (
@@ -92,6 +99,7 @@ export default function JobsPage() { columns={columns.map(item => ({ ...item }))} rowKey="id" dataSource={data ? data.jobs : null} + onChange={handleChange} />
); diff --git a/client/src/pages/jobs/jobs.page.metadata.jsx b/client/src/pages/jobs/jobs.page.metadata.jsx new file mode 100644 index 000000000..cc5886629 --- /dev/null +++ b/client/src/pages/jobs/jobs.page.metadata.jsx @@ -0,0 +1,64 @@ +import React from "react"; +import { Divider, Icon } from "antd"; + +export const columns = [ + { + title: "RO #", + dataIndex: "ro_number", + key: "ro_number", + sorter: (a, b) => a.ro_number > b.ro_number, + sortOrder: sortedInfo.columnKey === "ro_number" && sortedInfo.order, + ellipsis: true + }, + { + title: "Est. #", + dataIndex: "est_number", + key: "est_number" + }, + { + title: "Status", + dataIndex: "status", + key: "status" + }, + { + title: "Customer", + dataIndex: "customer", + key: "customer", + render: (text, record) => { + return record.owner ? ( +
+ {record.owner.first_name} {record.owner.last_name} +
+ ) : ( + "No Customer" + ); + } + }, + { + title: "Vehicle", + dataIndex: "vehicle", + key: "vehicle", + render: (text, record) => { + return record.vehicle ? ( +
+ {record.vehicle.v_model_yr} {record.vehicle.v_make_desc}{" "} + {record.vehicle.v_model_desc} +
+ ) : ( + "No Vehicle" + ); + } + }, + { + title: "Action", + key: "action", + render: (text, record) => ( + + Action 一 {record.ro_number} + + + More actions + + ) + } +]; diff --git a/client/src/utils/sorters.js b/client/src/utils/sorters.js new file mode 100644 index 000000000..6010a29a7 --- /dev/null +++ b/client/src/utils/sorters.js @@ -0,0 +1,9 @@ +export function alphaSort(a, b) { + if (a > b) { + return false; + } + if (b > a) { + return true; + } + return true; +}