diff --git a/src/App/App.jsx b/src/App/App.jsx index 7b4aed7..62a3607 100644 --- a/src/App/App.jsx +++ b/src/App/App.jsx @@ -1,5 +1,5 @@ import { ApolloProvider } from "@apollo/client"; -import { ConfigProvider } from "antd"; +import { ConfigProvider, theme } from "antd"; import enLocale from "antd/es/locale/en_US"; import React, { useEffect } from "react"; import { connect } from "react-redux"; @@ -11,18 +11,19 @@ import client from "../graphql/GraphQLClient"; import ipcTypes from "../ipc.types"; import "../ipc/ipc-renderer-handler"; import { checkUserSession } from "../redux/user/user.actions"; -import { selectCurrentUser } from "../redux/user/user.selectors"; +import { selectCurrentUser, selectDarkMode } from "../redux/user/user.selectors"; import "./App.styles.scss"; const { ipcRenderer } = window; const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, + darkMode: selectDarkMode }); const mapDispatchToProps = (dispatch) => ({ - checkUserSession: () => dispatch(checkUserSession()), + checkUserSession: () => dispatch(checkUserSession()) }); -export function App({ currentUser, checkUserSession }) { +export function App({ currentUser, checkUserSession, darkMode }) { useEffect(() => { checkUserSession(); }, [checkUserSession]); @@ -42,6 +43,9 @@ export function App({ currentUser, checkUserSession }) { diff --git a/src/components/molecules/jobs-list-item/jobs-list-item.molecule.jsx b/src/components/molecules/jobs-list-item/jobs-list-item.molecule.jsx index 0ab6928..18a17cf 100644 --- a/src/components/molecules/jobs-list-item/jobs-list-item.molecule.jsx +++ b/src/components/molecules/jobs-list-item/jobs-list-item.molecule.jsx @@ -33,6 +33,7 @@ export function JobsListItemMolecule({ selectedJobId, setSelectedJobId, item, re
Refresh All
); + return ( handleSelect(item.id)}> diff --git a/src/components/molecules/jobs-list-item/jobs-list-item.styles.scss b/src/components/molecules/jobs-list-item/jobs-list-item.styles.scss index e484b5a..e085d73 100644 --- a/src/components/molecules/jobs-list-item/jobs-list-item.styles.scss +++ b/src/components/molecules/jobs-list-item/jobs-list-item.styles.scss @@ -1,7 +1,7 @@ .jobs-list-item { padding: 0rem !important; margin: 0; - border: 0.4rem solid #f0f0f0 !important; + padding: 0.4rem !important; .jobs-list-item-content { &-selected { border-left: 3px solid #1890ff; @@ -13,7 +13,7 @@ //padding: 0.5rem; width: 100%; } - background-color: #f0f0f0; + // background-color: #f0f0f0; cursor: pointer; // &:hover { // background-color: #e6f7ff; diff --git a/src/components/organisms/jobs-detail/jobs-detail.organism.styles.scss b/src/components/organisms/jobs-detail/jobs-detail.organism.styles.scss index a1f9c80..4c31f91 100644 --- a/src/components/organisms/jobs-detail/jobs-detail.organism.styles.scss +++ b/src/components/organisms/jobs-detail/jobs-detail.organism.styles.scss @@ -1,7 +1,7 @@ .jobs-detail-container { height: 100%; overflow-y: auto; - background-color: rgb(244, 244, 244); + //background-color: rgb(244, 244, 244); & > * { margin: 0.7rem; } diff --git a/src/components/organisms/jobs-list-latest/jobs-list-latest.organism.jsx b/src/components/organisms/jobs-list-latest/jobs-list-latest.organism.jsx index 9772d10..4f27fe2 100644 --- a/src/components/organisms/jobs-list-latest/jobs-list-latest.organism.jsx +++ b/src/components/organisms/jobs-list-latest/jobs-list-latest.organism.jsx @@ -1,5 +1,5 @@ import { useQuery } from "@apollo/client"; -import { List } from "antd"; +import { Button, List } from "antd"; import React, { useState } from "react"; import InfiniteScroll from "react-infinite-scroller"; import { QUERY_ALL_JOBS_PAGINATED } from "../../../graphql/jobs.queries"; @@ -10,23 +10,20 @@ const limit = 20; export default function JobsTableOrganism() { const [state, setState] = useState({ hasMore: true }); - const { loading, error, data, refetch, fetchMore } = useQuery( - QUERY_ALL_JOBS_PAGINATED, - { - variables: { - offset: 0, - limit: limit, - order: [{ updated_at: "desc" }], - }, + const { loading, error, data, refetch, fetchMore } = useQuery(QUERY_ALL_JOBS_PAGINATED, { + variables: { + offset: 0, + limit: limit, + order: [{ updated_at: "desc" }] } - ); + }); const handleInfiniteOnLoad = async (page) => { console.log("Fetching more records!", page, fetchMore); if (fetchMore) { await fetchMore({ variables: { - offset: limit * page, + offset: limit * page }, updateQuery: (prev, { fetchMoreResult }) => { @@ -37,19 +34,16 @@ export default function JobsTableOrganism() { } const newCache = Object.assign({}, prev, { - jobs: [...prev.jobs, ...fetchMoreResult.jobs], + jobs: [...prev.jobs, ...fetchMoreResult.jobs] }); - if ( - newCache.jobs.length >= - (data && data.jobs_aggregate.aggregate.count) - ) { + if (newCache.jobs.length >= (data && data.jobs_aggregate.aggregate.count)) { console.log("No more results."); setState({ ...state, hasMore: false }); } return newCache; - }, + } }); // if (data.jobs.length >= data.jobs_aggregate.aggregate.count) { // console.log("No more results."); @@ -58,16 +52,13 @@ export default function JobsTableOrganism() { } }; - if (error) - return ( - - ); + if (error) return ; return (
+
( - - )} + dataSource={ + data + ? [ + //{ isRefresh: true }, + ...data.jobs + ] + : [] + } + renderItem={(item) => } >
- {`${data ? data.jobs.length : 0} jobs loaded. ${ - data ? data.jobs_aggregate.aggregate.count : 0 - } total jobs.`} + {`${data ? data.jobs.length : 0} jobs loaded. ${data ? data.jobs_aggregate.aggregate.count : 0} total jobs.`}
); diff --git a/src/components/organisms/sider-menu/sider-menu.organism.jsx b/src/components/organisms/sider-menu/sider-menu.organism.jsx index 9960a14..34b2490 100644 --- a/src/components/organisms/sider-menu/sider-menu.organism.jsx +++ b/src/components/organisms/sider-menu/sider-menu.organism.jsx @@ -4,24 +4,48 @@ import { CloseOutlined, FileAddFilled, LogoutOutlined, + MoonOutlined, PieChartOutlined, SettingFilled, - AlertOutlined + SunOutlined } from "@ant-design/icons"; import { Menu } from "antd"; import React from "react"; import { Link, useLocation } from "react-router-dom"; +import { createStructuredSelector } from "reselect"; import ipcTypes from "../../../ipc.types"; +import { selectDarkMode } from "../../../redux/user/user.selectors"; import SiderSignOut from "../../molecules/sider-sign-out/sider-sign-out.molecule"; +import { connect } from "react-redux"; +import { toggleDarkMode } from "../../../redux/user/user.actions"; const { ipcRenderer } = window; -export default function SiderMenuOrganism() { +const mapStateToProps = createStructuredSelector({ + darkMode: selectDarkMode +}); +const mapDispatchToProps = (dispatch) => ({ + toggleDarkMode: () => dispatch(toggleDarkMode()) +}); + +export function SiderMenuOrganism({ darkMode, toggleDarkMode }) { const { pathname } = useLocation(); return ( { + switch (e.key) { + case "darkmode": + toggleDarkMode(); + break; + case "quit": + ipcRenderer.send(ipcTypes.quit); + break; + default: + break; + } + }} mode="inline" items={[ { @@ -58,17 +82,13 @@ export default function SiderMenuOrganism() { { key: "quit", icon: , - label: ( - { - ipcRenderer.send(ipcTypes.quit); - }} - > - Quit - - ) + label: "Quit" }, - + { + key: "darkmode", + icon: darkMode ? : , + label: darkMode ? "Light Mode" : "Dark Mode" + } // ...(process.env.NODE_ENV !== "production" // ? [ // { @@ -82,3 +102,5 @@ export default function SiderMenuOrganism() { /> ); } + +export default connect(mapStateToProps, mapDispatchToProps)(SiderMenuOrganism); diff --git a/src/components/pages/audit/audit.page.styles.scss b/src/components/pages/audit/audit.page.styles.scss index 8f1cb5b..e4d6ab2 100644 --- a/src/components/pages/audit/audit.page.styles.scss +++ b/src/components/pages/audit/audit.page.styles.scss @@ -1,7 +1,7 @@ .audit-container { height: 100%; overflow-y: auto; - background-color: rgb(244, 244, 244); + //background-color: rgb(244, 244, 244); & > * { padding: 1rem; } diff --git a/src/components/pages/reporting/reporting.page.styles.scss b/src/components/pages/reporting/reporting.page.styles.scss index 882bad5..f1bdba2 100644 --- a/src/components/pages/reporting/reporting.page.styles.scss +++ b/src/components/pages/reporting/reporting.page.styles.scss @@ -1,7 +1,7 @@ .reporting-container { height: 100%; overflow-y: auto; - background-color: rgb(244, 244, 244); + //background-color: rgb(244, 244, 244); & > .reporting-cards > * { padding: 1rem; } diff --git a/src/components/pages/routes/routes.page.jsx b/src/components/pages/routes/routes.page.jsx index 4c3c1a6..73d7c19 100644 --- a/src/components/pages/routes/routes.page.jsx +++ b/src/components/pages/routes/routes.page.jsx @@ -4,7 +4,7 @@ import { connect } from "react-redux"; import { Routes } from "react-router-dom"; import { Route } from "react-router-dom"; import { createStructuredSelector } from "reselect"; -import { selectBodyshop } from "../../../redux/user/user.selectors"; +import { selectBodyshop, selectDarkMode } from "../../../redux/user/user.selectors"; import ErrorResultAtom from "../../atoms/error-result/error-result.atom"; import ReleaseNotes from "../../molecules/release-notes/release-notes.molecule"; import NotificationModalOrganism from "../../organisms/notification-modal/notification-modal.organism"; @@ -17,10 +17,10 @@ import SettingsPage from "../settings/settings.page"; import AuditPage from "../audit/audit.page"; import AdminPage from "../admin/admin.page"; -const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop }); +const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, darkMode: selectDarkMode }); const mapDispatchToProps = (dispatch) => ({}); -export function RoutesPage({ bodyshop }) { +export function RoutesPage({ bodyshop, darkMode }) { if (bodyshop === false) return ( - + + - + diff --git a/src/redux/user/user.actions.js b/src/redux/user/user.actions.js index 86806df..2aeb89d 100644 --- a/src/redux/user/user.actions.js +++ b/src/redux/user/user.actions.js @@ -2,97 +2,101 @@ import UserActionTypes from "./user.types"; export const signInSuccess = (user) => ({ type: UserActionTypes.SIGN_IN_SUCCESS, - payload: user, + payload: user }); export const signInFailure = (errorMsg) => ({ type: UserActionTypes.SIGN_IN_FAILURE, - payload: errorMsg, + payload: errorMsg }); export const emailSignInStart = (emailAndPassword) => ({ type: UserActionTypes.EMAIL_SIGN_IN_START, - payload: emailAndPassword, + payload: emailAndPassword }); export const checkUserSession = () => ({ - type: UserActionTypes.CHECK_USER_SESSION, + type: UserActionTypes.CHECK_USER_SESSION }); export const signOutStart = () => ({ - type: UserActionTypes.SIGN_OUT_START, + type: UserActionTypes.SIGN_OUT_START }); export const signOutSuccess = () => ({ - type: UserActionTypes.SIGN_OUT_SUCCESS, + type: UserActionTypes.SIGN_OUT_SUCCESS }); export const signOutFailure = (error) => ({ type: UserActionTypes.SIGN_OUT_FAILURE, - payload: error, + payload: error }); export const unauthorizedUser = () => ({ - type: UserActionTypes.UNAUTHORIZED_USER, + type: UserActionTypes.UNAUTHORIZED_USER }); export const setUserLanguage = (language) => ({ type: UserActionTypes.SET_USER_LANGUAGE, - payload: language, + payload: language }); export const updateUserDetails = (userDetails) => ({ type: UserActionTypes.UPDATE_USER_DETAILS, - payload: userDetails, + payload: userDetails }); export const updateUserDetailsSuccess = (userDetails) => ({ type: UserActionTypes.UPDATE_USER_DETAILS_SUCCESS, - payload: userDetails, + payload: userDetails }); export const setBodyshop = (bodyshop) => ({ type: UserActionTypes.SET_SHOP_DETAILS, - payload: bodyshop, + payload: bodyshop }); export const setTargets = (targets) => ({ type: UserActionTypes.SET_TARGETS, - payload: targets, + payload: targets }); export const setLocalFingerprint = (fingerprint) => ({ type: UserActionTypes.SET_LOCAL_FINGERPRINT, - payload: fingerprint, + payload: fingerprint }); export const sendPasswordReset = (email) => ({ type: UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START, - payload: email, + payload: email }); export const sendPasswordResetFailure = (error) => ({ type: UserActionTypes.SEND_PASSWORD_RESET_EMAIL_FAILURE, - payload: error, + payload: error }); export const sendPasswordResetSuccess = () => ({ - type: UserActionTypes.SEND_PASSWORD_RESET_EMAIL_SUCCESS, + type: UserActionTypes.SEND_PASSWORD_RESET_EMAIL_SUCCESS }); export const validatePasswordResetStart = (emailAndPin) => ({ type: UserActionTypes.VALIDATE_PASSWORD_RESET_START, - payload: emailAndPin, + payload: emailAndPin }); export const validatePasswordResetSuccess = () => ({ - type: UserActionTypes.VALIDATE_PASSWORD_RESET_SUCCESS, + type: UserActionTypes.VALIDATE_PASSWORD_RESET_SUCCESS }); export const validatePasswordResetFailure = (error) => ({ type: UserActionTypes.VALIDATE_PASSWORD_RESET_FAILURE, - payload: error, + payload: error }); export const setNotification = (notificationObject) => ({ type: UserActionTypes.SET_NOTIFICATIONS, - payload: notificationObject, + payload: notificationObject }); export const checkForNotification = () => ({ - type: UserActionTypes.CHECK_FOR_NOTIFICATION, + type: UserActionTypes.CHECK_FOR_NOTIFICATION +}); + +export const toggleDarkMode = () => ({ + type: UserActionTypes.TOGGLE_DARK_MODE }); diff --git a/src/redux/user/user.reducer.js b/src/redux/user/user.reducer.js index 3556742..c2ea19f 100644 --- a/src/redux/user/user.reducer.js +++ b/src/redux/user/user.reducer.js @@ -2,7 +2,7 @@ import UserActionTypes from "./user.types"; const INITIAL_STATE = { currentUser: { - authorized: null, + authorized: null //language: "en-US" }, bodyshop: null, @@ -13,10 +13,11 @@ const INITIAL_STATE = { passwordreset: { email: null, error: null, - success: false, + success: false }, loginLoading: false, notifications: null, + darkMode: false }; const userReducer = (state = INITIAL_STATE, action) => { @@ -37,8 +38,8 @@ const userReducer = (state = INITIAL_STATE, action) => { passwordreset: { email: action.payload, error: null, - success: false, - }, + success: false + } }; case UserActionTypes.VALIDATE_PASSWORD_RESET_FAILURE: case UserActionTypes.SEND_PASSWORD_RESET_EMAIL_FAILURE: @@ -47,48 +48,52 @@ const userReducer = (state = INITIAL_STATE, action) => { case UserActionTypes.SEND_PASSWORD_RESET_EMAIL_SUCCESS: return { ...state, - passwordreset: { ...state.passwordreset, success: true }, + passwordreset: { ...state.passwordreset, success: true } }; case UserActionTypes.SIGN_IN_SUCCESS: return { ...state, currentUser: action.payload, loginLoading: false, - error: null, + error: null }; case UserActionTypes.SIGN_OUT_SUCCESS: return { ...state, currentUser: { authorized: false }, - error: null, + error: null }; case UserActionTypes.UNAUTHORIZED_USER: return { ...state, error: null, - currentUser: { authorized: false }, + currentUser: { authorized: false } }; case UserActionTypes.SET_USER_LANGUAGE: return { ...state, - language: action.payload, + language: action.payload }; case UserActionTypes.UPDATE_USER_DETAILS_SUCCESS: return { ...state, currentUser: { ...state.currentUser, - ...action.payload, //Spread current user details in. - }, + ...action.payload //Spread current user details in. + } + }; + case UserActionTypes.TOGGLE_DARK_MODE: + return { + ...state, + darkMode: !state.darkMode }; - case UserActionTypes.SIGN_IN_FAILURE: case UserActionTypes.SIGN_OUT_FAILURE: case UserActionTypes.EMAIL_SIGN_UP_FAILURE: return { ...state, error: action.payload, - loginLoading: false, + loginLoading: false }; case UserActionTypes.EMAIL_SIGN_IN_START: return { ...state, loginLoading: true }; diff --git a/src/redux/user/user.selectors.js b/src/redux/user/user.selectors.js index b93be58..be78786 100644 --- a/src/redux/user/user.selectors.js +++ b/src/redux/user/user.selectors.js @@ -2,31 +2,14 @@ import { createSelector } from "reselect"; const selectUser = (state) => state.user; -export const selectCurrentUser = createSelector( - [selectUser], - (user) => user.currentUser -); +export const selectCurrentUser = createSelector([selectUser], (user) => user.currentUser); -export const selectSignInError = createSelector( - [selectUser], - (user) => user.error -); +export const selectSignInError = createSelector([selectUser], (user) => user.error); -export const selectPasswordReset = createSelector( - [selectUser], - (user) => user.passwordreset -); +export const selectPasswordReset = createSelector([selectUser], (user) => user.passwordreset); -export const selectBodyshop = createSelector( - [selectUser], - (user) => user.bodyshop -); +export const selectBodyshop = createSelector([selectUser], (user) => user.bodyshop); -export const selectLoginLoading = createSelector( - [selectUser], - (user) => user.loginLoading -); -export const selectNotifications = createSelector( - [selectUser], - (user) => user.notifications -); +export const selectLoginLoading = createSelector([selectUser], (user) => user.loginLoading); +export const selectNotifications = createSelector([selectUser], (user) => user.notifications); +export const selectDarkMode = createSelector([selectUser], (user) => user.darkMode); diff --git a/src/redux/user/user.types.js b/src/redux/user/user.types.js index 54b5486..a8e173c 100644 --- a/src/redux/user/user.types.js +++ b/src/redux/user/user.types.js @@ -30,5 +30,6 @@ const UserActionTypes = { CHECK_FOR_NOTIFICATION: "CHECK_FOR_NOTIFICATION", SET_NOTIFICATIONS: "SET_NOTIFICATIONS", SET_TARGETS: "SET_TARGETS", + TOGGLE_DARK_MODE: "TOGGLE_DARK_MODE" }; export default UserActionTypes;