diff --git a/deployment.md b/deployment.md new file mode 100644 index 0000000..43f5fd3 --- /dev/null +++ b/deployment.md @@ -0,0 +1,5 @@ +Deployment: + +Change version to 2.11.2 +Update VARS to HASURA_GRAPHQL_V1_BOOLEAN_NULL_COLLAPSE = true + diff --git a/electron/analytics.js b/electron/analytics.js index 2a45eb7..e011d99 100644 --- a/electron/analytics.js +++ b/electron/analytics.js @@ -1,34 +1,34 @@ const { ipcMain } = require("electron"); -const { app } = require("electron"); +//const { app } = require("electron"); const log = require("electron-log"); -const Nucleus = require("nucleus-nodejs"); +//const Nucleus = require("nucleus-nodejs"); const { default: ipcTypes } = require("../src/ipc.types"); -Nucleus.init("5f91b569b95bac34eefdb63a", { - disableInDev: true, - debug: false, - version: app.getVersion(), -}); +// Nucleus.init("5f91b569b95bac34eefdb63a", { +// disableInDev: true, +// debug: false, +// version: app.getVersion(), +// }); -Nucleus.setProps({ - version: app.getVersion(), -}); +// Nucleus.setProps({ +// version: app.getVersion(), +// }); -Nucleus.onError = (type, err) => { - log.error(err); - // type will either be uncaughtException, unhandledRejection or windowError -}; +// Nucleus.onError = (type, err) => { +// log.error(err); +// // type will either be uncaughtException, unhandledRejection or windowError +// }; ipcMain.on(ipcTypes.app.toMain.setUserName, (event, userName) => { - Nucleus.setUserId(userName); - Nucleus.appStarted(); +// Nucleus.setUserId(userName); +// Nucleus.appStarted(); }); ipcMain.on(ipcTypes.app.toMain.track, (e, args) => { log.log("NUCLEUS Event", args); - const { event, ...eventDetails } = args; + // const { event, ...eventDetails } = args; try { - Nucleus.track(event, eventDetails); + //// Nucleus.track(event, eventDetails); } catch (error) { log.error(error); } diff --git a/electron/decoder/decoder.js b/electron/decoder/decoder.js index b7fa4b9..86404ca 100644 --- a/electron/decoder/decoder.js +++ b/electron/decoder/decoder.js @@ -8,7 +8,7 @@ const ipcTypes = require("../../src/ipc.types"); const { NewNotification, } = require("../notification-wrapper/notification-wrapper"); -const Nucleus = require("nucleus-nodejs"); +//const Nucleus = require("nucleus-nodejs"); async function ImportJob(path) { const b = BrowserWindow.getAllWindows()[0]; @@ -27,7 +27,7 @@ async function ImportJob(path) { }); } else { log.info(`Ignored job. ${newJob.ERROR}`); - Nucleus.track("IGNORE_JOB", { reason: newJob.ERROR }); + // Nucleus.track("IGNORE_JOB", { reason: newJob.ERROR }); NewNotification({ title: "Job Ignored", body: newJob.ERROR, diff --git a/electron/file-scan/file-scan-ipc.js b/electron/file-scan/file-scan-ipc.js index f388001..f584988 100644 --- a/electron/file-scan/file-scan-ipc.js +++ b/electron/file-scan/file-scan-ipc.js @@ -1,5 +1,5 @@ const { ipcMain } = require("electron"); -const Nucleus = require("nucleus-nodejs"); +//const Nucleus = require("nucleus-nodejs"); const ipcTypes = require("../../src/ipc.types"); const { ImportJob } = require("../decoder/decoder"); const { GetListOfEstimates, DeleteAllEms } = require("./file-scan"); @@ -18,7 +18,7 @@ ipcMain.on( ipcMain.on( ipcTypes.default.fileScan.toMain.importJob, async (event, filePath) => { - Nucleus.track("IMPORT_JOB_FROM_SCAN"); + // Nucleus.track("IMPORT_JOB_FROM_SCAN"); await ImportJob(filePath); } ); @@ -26,7 +26,7 @@ ipcMain.on( ipcMain.on( ipcTypes.default.fileScan.toMain.deleteAllEms, async (event, filePath) => { - Nucleus.track("DELETE_ALLEMS"); + // Nucleus.track("DELETE_ALLEMS"); await DeleteAllEms(); const ret = await GetListOfEstimates(); event.reply( diff --git a/electron/file-scan/file-scan.js b/electron/file-scan/file-scan.js index c7328e5..b021eb8 100644 --- a/electron/file-scan/file-scan.js +++ b/electron/file-scan/file-scan.js @@ -3,13 +3,11 @@ const fs = require("fs"); const { store } = require("../electron-store"); const log = require("electron-log"); const fsPromises = fs.promises; -const _ = require("lodash"); const { DecodeEstimate } = require("../decoder/decoder"); -const Nucleus = require("nucleus-nodejs"); -const { format } = require("path"); +//const Nucleus = require("nucleus-nodejs"); async function GetListOfEstimates() { - Nucleus.track("SCAN_ALL_ESTIMATES"); + // Nucleus.track("SCAN_ALL_ESTIMATES"); log.info("Scanning all local estimates.."); const ListOfEnvFiles = await GetEnvFiles(); const ListOfSummarizedEstimates = await ReadAllEstimates(ListOfEnvFiles); diff --git a/electron/file-watcher/file-watcher.js b/electron/file-watcher/file-watcher.js index 6964e04..2780299 100644 --- a/electron/file-watcher/file-watcher.js +++ b/electron/file-watcher/file-watcher.js @@ -8,7 +8,7 @@ const { NewNotification, } = require("../notification-wrapper/notification-wrapper"); const log = require("electron-log"); -const Nucleus = require("nucleus-nodejs"); +//const Nucleus = require("nucleus-nodejs"); var watcher; async function StartWatcher() { @@ -71,7 +71,7 @@ async function StartWatcher() { log.error("Error in Watcher", error); const b = BrowserWindow.getFocusedWindow(); b.webContents.send(ipcTypes.default.fileWatcher.toRenderer.error, error); - Nucleus.track("WATCHER_ERROR", error); + // Nucleus.track("WATCHER_ERROR", error); }) .on("ready", onWatcherReady) .on("raw", function (event, path, details) { diff --git a/electron/main.js b/electron/main.js index 6dffe9f..7c45c60 100644 --- a/electron/main.js +++ b/electron/main.js @@ -15,7 +15,7 @@ const { store } = require("./electron-store"); const { autoUpdater } = require("electron-updater"); const log = require("electron-log"); -const Nucleus = require("nucleus-nodejs"); +//const Nucleus = require("nucleus-nodejs"); require("./ipc-main-handler"); require("./analytics"); @@ -299,12 +299,12 @@ ipcMain.on(ipcTypes.app.toMain.checkForUpdates, (event, args) => { }); ipcMain.on(ipcTypes.app.toMain.downloadUpdates, (event, args) => { - Nucleus.track("DOWNLOAD_UPDATE_FROM_RENDERER"); + //Nucleus.track("DOWNLOAD_UPDATE_FROM_RENDERER"); autoUpdater.downloadUpdate(); }); ipcMain.on(ipcTypes.app.toMain.installUpdates, (event, args) => { - Nucleus.track("INSTALL_UPDATE_FROM_RENDERER"); + //Nucleus.track("INSTALL_UPDATE_FROM_RENDERER"); const isSilent = true; const isForceRunAfter = true; autoUpdater.quitAndInstall(isSilent, isForceRunAfter); @@ -316,7 +316,7 @@ autoUpdater.on("download-progress", (ev) => { }); autoUpdater.on("update-downloaded", (ev, info) => { - Nucleus.track("UPDATE_DOWNLOADED", ev); + //Nucleus.track("UPDATE_DOWNLOADED", ev); // if (process.env.NODE_ENV === "production") { mainWindow.webContents.send(ipcTypes.app.toRenderer.downloadProgress, { ...ev, diff --git a/hasura/metadata/databases/default/tables/public_bodyshops.yaml b/hasura/metadata/databases/default/tables/public_bodyshops.yaml index 412f510..4296d9d 100644 --- a/hasura/metadata/databases/default/tables/public_bodyshops.yaml +++ b/hasura/metadata/databases/default/tables/public_bodyshops.yaml @@ -16,6 +16,13 @@ array_relationships: table: name: jobs schema: public + - name: notifications + using: + foreign_key_constraint_on: + column: bodyshopid + table: + name: notifications + schema: public select_permissions: - role: user permission: diff --git a/hasura/metadata/databases/default/tables/public_notifications.yaml b/hasura/metadata/databases/default/tables/public_notifications.yaml new file mode 100644 index 0000000..b1bb0d9 --- /dev/null +++ b/hasura/metadata/databases/default/tables/public_notifications.yaml @@ -0,0 +1,43 @@ +table: + name: notifications + schema: public +object_relationships: + - name: bodyshop + using: + foreign_key_constraint_on: bodyshopid +select_permissions: + - role: user + permission: + columns: + - acceptedat + - acceptedby + - bodyshopid + - created_at + - effectivedate + - html + - id + - requiresconfirmation + - requiresconfirmationby + - updated_at + filter: + bodyshop: + associations: + user: + authid: + _eq: X-Hasura-User-Id +update_permissions: + - role: user + permission: + columns: + - acceptedat + - acceptedby + filter: + _and: + - bodyshop: + associations: + user: + authid: + _eq: X-Hasura-User-Id + - acceptedat: + _is_null: true + check: null diff --git a/hasura/metadata/databases/default/tables/tables.yaml b/hasura/metadata/databases/default/tables/tables.yaml index 42b6c18..154b182 100644 --- a/hasura/metadata/databases/default/tables/tables.yaml +++ b/hasura/metadata/databases/default/tables/tables.yaml @@ -3,5 +3,6 @@ - "!include public_groupings.yaml" - "!include public_joblines.yaml" - "!include public_jobs.yaml" +- "!include public_notifications.yaml" - "!include public_users.yaml" - "!include public_veh_groups.yaml" diff --git a/hasura/migrations/1602633863978_create_table_public_users/up.sql b/hasura/migrations/1602633863978_create_table_public_users/up.sql new file mode 100644 index 0000000..c73e743 --- /dev/null +++ b/hasura/migrations/1602633863978_create_table_public_users/up.sql @@ -0,0 +1,35 @@ + +CREATE TABLE "public"."users"("email" text NOT NULL, "authid" text NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("email") ); +CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() +RETURNS TRIGGER AS $$ +DECLARE + _new record; +BEGIN + _new := NEW; + _new."updated_at" = NOW(); + RETURN _new; +END; +$$ LANGUAGE plpgsql; +CREATE TRIGGER "set_public_users_updated_at" +BEFORE UPDATE ON "public"."users" +FOR EACH ROW +EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); +COMMENT ON TRIGGER "set_public_users_updated_at" ON "public"."users" +IS 'trigger to set value of column "updated_at" to current timestamp on row update'; +CREATE TABLE "public"."users"("email" text NOT NULL, "authid" text NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("email") ); +CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() +RETURNS TRIGGER AS $$ +DECLARE + _new record; +BEGIN + _new := NEW; + _new."updated_at" = NOW(); + RETURN _new; +END; +$$ LANGUAGE plpgsql; +CREATE TRIGGER "set_public_users_updated_at" +BEFORE UPDATE ON "public"."users" +FOR EACH ROW +EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); +COMMENT ON TRIGGER "set_public_users_updated_at" ON "public"."users" +IS 'trigger to set value of column "updated_at" to current timestamp on row update'; \ No newline at end of file diff --git a/hasura/migrations/default/1663277904884_create_table_public_notifications/down.sql b/hasura/migrations/default/1663277904884_create_table_public_notifications/down.sql new file mode 100644 index 0000000..6fc4e30 --- /dev/null +++ b/hasura/migrations/default/1663277904884_create_table_public_notifications/down.sql @@ -0,0 +1 @@ +DROP TABLE "public"."notifications"; diff --git a/hasura/migrations/default/1663277904884_create_table_public_notifications/up.sql b/hasura/migrations/default/1663277904884_create_table_public_notifications/up.sql new file mode 100644 index 0000000..75423c3 --- /dev/null +++ b/hasura/migrations/default/1663277904884_create_table_public_notifications/up.sql @@ -0,0 +1,17 @@ +CREATE TABLE "public"."notifications" ("id" serial NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), "bodyshopid" uuid, "effectivedate" timestamptz NOT NULL, "html" text NOT NULL, "acceptedat" timestamptz, "acceptedby" text, "requiresaacceptance" text NOT NULL DEFAULT 'false', PRIMARY KEY ("id") , FOREIGN KEY ("bodyshopid") REFERENCES "public"."bodyshops"("id") ON UPDATE restrict ON DELETE restrict); +CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() +RETURNS TRIGGER AS $$ +DECLARE + _new record; +BEGIN + _new := NEW; + _new."updated_at" = NOW(); + RETURN _new; +END; +$$ LANGUAGE plpgsql; +CREATE TRIGGER "set_public_notifications_updated_at" +BEFORE UPDATE ON "public"."notifications" +FOR EACH ROW +EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); +COMMENT ON TRIGGER "set_public_notifications_updated_at" ON "public"."notifications" +IS 'trigger to set value of column "updated_at" to current timestamp on row update'; diff --git a/hasura/migrations/default/1663278102853_alter_table_public_notifications_drop_column_requiresaacceptance/down.sql b/hasura/migrations/default/1663278102853_alter_table_public_notifications_drop_column_requiresaacceptance/down.sql new file mode 100644 index 0000000..d6f67d7 --- /dev/null +++ b/hasura/migrations/default/1663278102853_alter_table_public_notifications_drop_column_requiresaacceptance/down.sql @@ -0,0 +1,3 @@ +alter table "public"."notifications" alter column "requiresaacceptance" set default ''false'::text'; +alter table "public"."notifications" alter column "requiresaacceptance" drop not null; +alter table "public"."notifications" add column "requiresaacceptance" text; diff --git a/hasura/migrations/default/1663278102853_alter_table_public_notifications_drop_column_requiresaacceptance/up.sql b/hasura/migrations/default/1663278102853_alter_table_public_notifications_drop_column_requiresaacceptance/up.sql new file mode 100644 index 0000000..c1c5f36 --- /dev/null +++ b/hasura/migrations/default/1663278102853_alter_table_public_notifications_drop_column_requiresaacceptance/up.sql @@ -0,0 +1 @@ +alter table "public"."notifications" drop column "requiresaacceptance" cascade; diff --git a/hasura/migrations/default/1663278122231_alter_table_public_notifications_add_column_requiresconfirmation/down.sql b/hasura/migrations/default/1663278122231_alter_table_public_notifications_add_column_requiresconfirmation/down.sql new file mode 100644 index 0000000..e8faa06 --- /dev/null +++ b/hasura/migrations/default/1663278122231_alter_table_public_notifications_add_column_requiresconfirmation/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."notifications" add column "requiresconfirmation" boolean +-- not null default 'false'; diff --git a/hasura/migrations/default/1663278122231_alter_table_public_notifications_add_column_requiresconfirmation/up.sql b/hasura/migrations/default/1663278122231_alter_table_public_notifications_add_column_requiresconfirmation/up.sql new file mode 100644 index 0000000..fb48de3 --- /dev/null +++ b/hasura/migrations/default/1663278122231_alter_table_public_notifications_add_column_requiresconfirmation/up.sql @@ -0,0 +1,2 @@ +alter table "public"."notifications" add column "requiresconfirmation" boolean + not null default 'false'; diff --git a/hasura/migrations/default/1663278170291_alter_table_public_notifications_add_column_requiresconfirmationby/down.sql b/hasura/migrations/default/1663278170291_alter_table_public_notifications_add_column_requiresconfirmationby/down.sql new file mode 100644 index 0000000..5e46737 --- /dev/null +++ b/hasura/migrations/default/1663278170291_alter_table_public_notifications_add_column_requiresconfirmationby/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."notifications" add column "requiresconfirmationby" timestamptz +-- null; diff --git a/hasura/migrations/default/1663278170291_alter_table_public_notifications_add_column_requiresconfirmationby/up.sql b/hasura/migrations/default/1663278170291_alter_table_public_notifications_add_column_requiresconfirmationby/up.sql new file mode 100644 index 0000000..58fed55 --- /dev/null +++ b/hasura/migrations/default/1663278170291_alter_table_public_notifications_add_column_requiresconfirmationby/up.sql @@ -0,0 +1,2 @@ +alter table "public"."notifications" add column "requiresconfirmationby" timestamptz + null; diff --git a/src/components/molecules/notification-display/notification-display.molecule.jsx b/src/components/molecules/notification-display/notification-display.molecule.jsx new file mode 100644 index 0000000..dacd528 --- /dev/null +++ b/src/components/molecules/notification-display/notification-display.molecule.jsx @@ -0,0 +1,70 @@ +import { useMutation } from "@apollo/client"; +import { Button, Card, Form, Input, Space } from "antd"; +import React from "react"; +import { useState } from "react"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { ACCEPT_NOTIFICATION } from "../../../graphql/notification.queries"; +import { checkForNotification } from "../../../redux/user/user.actions"; +const mapStateToProps = createStructuredSelector({ + //currentUser: selectCurrentUser +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) + checkForNotification: () => dispatch(checkForNotification()), +}); +export default connect( + mapStateToProps, + mapDispatchToProps +)(NotificationDisplayMolecule); + +export function NotificationDisplayMolecule({ + notification, + checkForNotification, +}) { + const [acceptNotification] = useMutation(ACCEPT_NOTIFICATION); + const [loading, setLoading] = useState(false); + const handleConfirm = async (values) => { + console.log("form submit", notification, values); + setLoading(true); + await acceptNotification({ + variables: { + id: notification.id, + notification: { acceptedby: values.acceptedby, acceptedat: new Date() }, + }, + }); + checkForNotification(); + setLoading(false); + }; + const handleDismiss = async () => {}; + const [form] = Form.useForm(); + return ( + +
+ {notification.requiresconfirmation ? ( +
+ + + + + + +
+ ) : ( + + )} + + ); +} diff --git a/src/components/organisms/notification-modal/notification-modal.organism.jsx b/src/components/organisms/notification-modal/notification-modal.organism.jsx new file mode 100644 index 0000000..5676e0c --- /dev/null +++ b/src/components/organisms/notification-modal/notification-modal.organism.jsx @@ -0,0 +1,30 @@ +import { Modal } from "antd"; +import React from "react"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectNotifications } from "../../../redux/user/user.selectors"; +import NotificationDisplayMolecule from "../../molecules/notification-display/notification-display.molecule"; +const mapStateToProps = createStructuredSelector({ + //currentUser: selectCurrentUser + notifications: selectNotifications, +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) +}); +export default connect(mapStateToProps, mapDispatchToProps)(NotificationModal); + +export function NotificationModal({ notifications }) { + if (!notifications || notifications.length === 0) return null; + return ( + 0} + closable={false} + footer={null} + > + {notifications && + notifications.map((n) => ( + + ))} + + ); +} diff --git a/src/components/pages/routes/routes.page.jsx b/src/components/pages/routes/routes.page.jsx index 9c9e24c..e6fb3f8 100644 --- a/src/components/pages/routes/routes.page.jsx +++ b/src/components/pages/routes/routes.page.jsx @@ -7,6 +7,7 @@ import { createStructuredSelector } from "reselect"; import { selectBodyshop } 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"; import SiderMenuOrganism from "../../organisms/sider-menu/sider-menu.organism"; import UpdateManagerOrganism from "../../organisms/update-manager/update-manager.organism"; import JobsPage from "../jobs/jobs.page"; @@ -37,6 +38,7 @@ export function RoutesPage({ bodyshop }) { + } /> } /> diff --git a/src/graphql/bodyshop.queries.js b/src/graphql/bodyshop.queries.js index e66da44..8ab325c 100644 --- a/src/graphql/bodyshop.queries.js +++ b/src/graphql/bodyshop.queries.js @@ -16,7 +16,7 @@ export const UPDATE_SHOP = gql` mutation UPDATE_SHOP($id: uuid, $shop: bodyshops_set_input!) { update_bodyshops(where: { id: { _eq: $id } }, _set: $shop) { returning { - id + id shopname targets accepted_ins_co @@ -26,3 +26,18 @@ export const UPDATE_SHOP = gql` } } `; + +export const QUERY_NOTIFICATIONS = gql` + query QUERY_NOTIFICATIONS($now: timestamptz) { + notifications( + where: { acceptedat: { _is_null: true }, effectivedate: { _lte: $now } } + ) { + effectivedate + html + id + requiresconfirmation + requiresconfirmationby + updated_at + } + } +`; diff --git a/src/graphql/notification.queries.js b/src/graphql/notification.queries.js new file mode 100644 index 0000000..2a948a7 --- /dev/null +++ b/src/graphql/notification.queries.js @@ -0,0 +1,18 @@ +import gql from "graphql-tag"; + +export const ACCEPT_NOTIFICATION = gql` + mutation ACCEPT_NOTIFICATION( + $id: Int! + $notification: notifications_set_input + ) { + update_notifications_by_pk(pk_columns: { id: $id }, _set: $notification) { + html + id + requiresconfirmation + requiresconfirmationby + updated_at + acceptedat + effectivedate + } + } +`; diff --git a/src/ipc/suvs.json b/src/ipc/suvs.json index 494cd73..eba4efb 100644 --- a/src/ipc/suvs.json +++ b/src/ipc/suvs.json @@ -150,6 +150,7 @@ "UPLANDER", "YUKON", "YUKON DENALI", + "YUKON XL", "EQUINOX LS", "EQUINOX LT", "EQUINOX PREMIER", @@ -164,6 +165,7 @@ "RAV4 XLE HYBRID", "HIGHLANDER", "4RUNNER", + "SEQUOIA", "PATHFINDER SE", "PATHFINDER SL", diff --git a/src/redux/user/user.actions.js b/src/redux/user/user.actions.js index ba06e36..db83b3e 100644 --- a/src/redux/user/user.actions.js +++ b/src/redux/user/user.actions.js @@ -85,3 +85,10 @@ export const validatePasswordResetFailure = (error) => ({ payload: error, }); +export const setNotification = (notificationObject) => ({ + type: UserActionTypes.SET_NOTIFICATIONS, + payload: notificationObject, +}); +export const checkForNotification = () => ({ + type: UserActionTypes.CHECK_FOR_NOTIFICATION, +}); diff --git a/src/redux/user/user.reducer.js b/src/redux/user/user.reducer.js index 840eeb2..0c46460 100644 --- a/src/redux/user/user.reducer.js +++ b/src/redux/user/user.reducer.js @@ -15,10 +15,13 @@ const INITIAL_STATE = { success: false, }, loginLoading: false, + notifications: null, }; const userReducer = (state = INITIAL_STATE, action) => { switch (action.type) { + case UserActionTypes.SET_NOTIFICATIONS: + return { ...state, notifications: action.payload }; case UserActionTypes.SET_SHOP_DETAILS: return { ...state, bodyshop: action.payload }; case UserActionTypes.SET_LOCAL_FINGERPRINT: diff --git a/src/redux/user/user.sagas.js b/src/redux/user/user.sagas.js index f3a8e6c..c5f46fe 100644 --- a/src/redux/user/user.sagas.js +++ b/src/redux/user/user.sagas.js @@ -1,12 +1,16 @@ -import { message } from "antd"; +import { message, notification } from "antd"; +import moment from "moment"; //import LogRocket from "logrocket"; -import { all, call, put, takeLatest } from "redux-saga/effects"; +import { all, call, put, takeLatest, delay } from "redux-saga/effects"; import { auth, getCurrentUser, updateCurrentUser, } from "../../firebase/firebase.utils"; -import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries"; +import { + QUERY_BODYSHOP, + QUERY_NOTIFICATIONS, +} from "../../graphql/bodyshop.queries"; import client from "../../graphql/GraphQLClient"; import { UPSERT_USER } from "../../graphql/user.queries"; import ipcTypes from "../../ipc.types"; @@ -20,6 +24,8 @@ import { signOutSuccess, unauthorizedUser, updateUserDetailsSuccess, + checkForNotification, + setNotification, } from "./user.actions"; import UserActionTypes from "./user.types"; @@ -144,6 +150,8 @@ export function* signInSuccessSaga({ payload }) { ipcRenderer.send(ipcTypes.default.fileWatcher.toMain.start, { startup: true, }); + yield put(checkForNotification()); + //Check for notifications, and continue to check. } else { console.log("No bodyshop has been associated."); yield put(setBodyshop(false)); @@ -153,6 +161,27 @@ export function* signInSuccessSaga({ payload }) { // yield logImEXEvent("redux_sign_in_success"); } +export function* onCheckForNotification() { + yield takeLatest( + UserActionTypes.CHECK_FOR_NOTIFICATION, + checkForNotificationSaga + ); +} +export function* checkForNotificationSaga() { + const { + data: { notifications }, + } = yield client.query({ + query: QUERY_NOTIFICATIONS, + variables: { now: moment() }, + }); + + if (notifications) { + yield put(setNotification(notifications)); + } + yield delay(4 * 60 * 60 * 1000); + yield put(checkForNotification()); +} + export function* onSendPasswordResetStart() { yield takeLatest( UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START, @@ -181,6 +210,7 @@ export function* userSagas() { call(onUpdateUserDetails), call(onSignInSuccess), call(onSendPasswordResetStart), + call(onCheckForNotification), ]); } diff --git a/src/redux/user/user.selectors.js b/src/redux/user/user.selectors.js index 79180d8..b93be58 100644 --- a/src/redux/user/user.selectors.js +++ b/src/redux/user/user.selectors.js @@ -26,3 +26,7 @@ export const selectLoginLoading = createSelector( [selectUser], (user) => user.loginLoading ); +export const selectNotifications = createSelector( + [selectUser], + (user) => user.notifications +); diff --git a/src/redux/user/user.types.js b/src/redux/user/user.types.js index 1ee363c..a007723 100644 --- a/src/redux/user/user.types.js +++ b/src/redux/user/user.types.js @@ -27,5 +27,7 @@ const UserActionTypes = { VALIDATE_PASSWORD_RESET_SUCCESS: "VALIDATE_PASSWORD_RESET_SUCCESS", VALIDATE_PASSWORD_RESET_FAILURE: "VALIDATE_PASSWORD_RESET_FAILURE", SET_AUTH_LEVEL: "SET_AUTH_LEVEL", + CHECK_FOR_NOTIFICATION: "CHECK_FOR_NOTIFICATION", + SET_NOTIFICATIONS: "SET_NOTIFICATIONS", }; -export default UserActionTypes; +export default UserActionTypes;