diff --git a/client/package.json b/client/package.json index 7b92c7a49..eeafdb4e5 100644 --- a/client/package.json +++ b/client/package.json @@ -57,6 +57,7 @@ "redux-state-sync": "^3.1.2", "reselect": "^4.0.0", "sass": "^1.32.13", + "socket.io-client": "^4.1.2", "styled-components": "^5.3.0", "subscriptions-transport-ws": "^0.9.18", "web-vitals": "^1.1.2", diff --git a/client/src/components/job-detail-lines/job-lines.component.jsx b/client/src/components/job-detail-lines/job-lines.component.jsx index 346741d47..8ebc5d284 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -395,7 +395,7 @@ export function JobLinesComponent({ setState({ ...state, filteredInfo: { - part_type: ["PAN,PAL,PAA,PAP,PAS,PASL"], + part_type: ["PAN,PAC,PAR,PAL,PAA,PAM,PAP,PAS,PASL"], }, }); }} diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js index e4c429df8..5dfd68ccb 100644 --- a/client/src/graphql/bodyshop.queries.js +++ b/client/src/graphql/bodyshop.queries.js @@ -89,6 +89,7 @@ export const QUERY_BODYSHOP = gql` website jc_hourly_rates md_jobline_presets + cdk_dealerid employees { id active @@ -175,6 +176,7 @@ export const UPDATE_SHOP = gql` website jc_hourly_rates md_jobline_presets + cdk_dealerid employees { id first_name diff --git a/client/src/pages/cdk/cdk.container.jsx b/client/src/pages/cdk/cdk.container.jsx new file mode 100644 index 000000000..67b240e66 --- /dev/null +++ b/client/src/pages/cdk/cdk.container.jsx @@ -0,0 +1,128 @@ +import { Result, Timeline, Space, Tag, Divider, Button } from "antd"; +import React, { useEffect, useState } from "react"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { + setBreadcrumbs, + setSelectedHeader, +} from "../../redux/application/application.actions"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import { useTranslation } from "react-i18next"; +import SocketIO from "socket.io-client"; +import { auth } from "../../firebase/firebase.utils"; +import moment from "moment"; + +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop, +}); + +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), + setSelectedHeader: (key) => dispatch(setSelectedHeader(key)), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(CdkContainer); + +export const socket = SocketIO( + process.env.NODE_ENV === "production" + ? process.env.REACT_APP_AXIOS_BASE_API_URL + : window.location.origin, + { + path: "/ws", + // transports: ["websocket"], + auth: async (callback) => { + const token = auth.currentUser && (await auth.currentUser.getIdToken()); + callback({ token }); + }, + } +); + +export function CdkContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) { + const { t } = useTranslation(); + const [logs, setLogs] = useState([]); + useEffect(() => { + document.title = t("titles.cdk"); + setSelectedHeader("cdk"); + setBreadcrumbs([ + { + link: "/manage/cdk", + label: t("titles.bc.cdk"), + }, + ]); + }, [t, setBreadcrumbs, setSelectedHeader]); + + useEffect(() => { + socket.on("connected", () => { + console.log("Connected again."); + }); + + socket.on("log-event", (payload) => { + setLogs((logs) => { + return [...logs, payload]; + }); + }); + + socket.connect(); + + socket.emit("set-log-level", "TRACE"); + + return () => { + socket.removeAllListeners(); + socket.disconnect(); + }; + }, []); + + if (!bodyshop.cdk_dealerid) return ; + + return ( +
+ + + + + + {logs.map((log, idx) => ( + + + {log.level} + {moment(log.timestamp).format("MM/DD/YYYY HH:MM:ss")} + + {log.message} + + + ))} + +
+ ); +} + +function LogLevelHierarchy(level) { + switch (level) { + case "TRACE": + return "pink"; + case "DEBUG": + return "orange"; + case "INFO": + return "blue"; + case "WARNING": + return "yellow"; + case "ERROR": + return "red"; + default: + return 0; + } +} diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index dbf37cca1..1736f48ff 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -159,6 +159,7 @@ const EmailTest = lazy(() => import("../../components/email-test/email-test-component") ); const Dashboard = lazy(() => import("../dashboard/dashboard.container")); +const Cdk = lazy(() => import("../cdk/cdk.container")); const { Content, Footer } = Layout; @@ -367,6 +368,7 @@ export function Manage({ match, conflict, bodyshop }) { + ); diff --git a/client/src/redux/dms/dms.actions.js b/client/src/redux/dms/dms.actions.js new file mode 100644 index 000000000..5b602fa88 --- /dev/null +++ b/client/src/redux/dms/dms.actions.js @@ -0,0 +1,6 @@ +import DmsActions from "./dms.types"; + +export const endLoading = (options) => ({ + // type: DmsActions.END_LOADING, + payload: options, +}); diff --git a/client/src/redux/dms/dms.reducer.js b/client/src/redux/dms/dms.reducer.js new file mode 100644 index 000000000..32b41ff24 --- /dev/null +++ b/client/src/redux/dms/dms.reducer.js @@ -0,0 +1,20 @@ +import DmsActionTypes from "./dms.types"; + +const INITIAL_STATE = { + eventLog: [], +}; + +const dmsReducer = (state = INITIAL_STATE, action) => { + switch (action.type) { + // case ApplicationActionTypes.SET_SELECTED_HEADER: + // return { + // ...state, + // selectedHeader: action.payload, + // }; + + default: + return state; + } +}; + +export default dmsReducer; diff --git a/client/src/redux/dms/dms.sagas.js b/client/src/redux/dms/dms.sagas.js new file mode 100644 index 000000000..a4467d0ba --- /dev/null +++ b/client/src/redux/dms/dms.sagas.js @@ -0,0 +1,14 @@ +import { all, call } from "redux-saga/effects"; +//import DmsActionTypes from "./dms.types"; + +export function* onCalculateScheduleLoad() { + // yield takeLatest( + // DmsActionTypes.CALCULATE_SCHEDULE_LOAD, + // calculateScheduleLoad + // ); +} +export function* calculateScheduleLoad({ payload: end }) {} + +export function* dmsSagas() { + yield all([call()]); +} diff --git a/client/src/redux/dms/dms.selectors.js b/client/src/redux/dms/dms.selectors.js new file mode 100644 index 000000000..e708c3485 --- /dev/null +++ b/client/src/redux/dms/dms.selectors.js @@ -0,0 +1,8 @@ +import { createSelector } from "reselect"; + +const selectDms = (state) => state.dms; + +export const selectEventLog = createSelector( + [selectDms], + (dms) => dms.eventLog +); diff --git a/client/src/redux/dms/dms.types.js b/client/src/redux/dms/dms.types.js new file mode 100644 index 000000000..ffbda242f --- /dev/null +++ b/client/src/redux/dms/dms.types.js @@ -0,0 +1,4 @@ +const DmsActionTypes = { + ADD_EVENT: "ADD_EVENT", +}; +export default DmsActionTypes; diff --git a/client/yarn.lock b/client/yarn.lock index 7be04d553..86d239f03 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -2271,6 +2271,11 @@ dependencies: "@babel/types" "^7.3.0" +"@types/component-emitter@^1.2.10": + version "1.2.10" + resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.10.tgz#ef5b1589b9f16544642e473db5ea5639107ef3ea" + integrity sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg== + "@types/d3-path@^1": version "1.0.9" resolved "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.9.tgz" @@ -3480,7 +3485,7 @@ babylon@^6.18.0: resolved "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== -backo2@^1.0.2: +backo2@^1.0.2, backo2@~1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz" integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= @@ -3490,6 +3495,11 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-arraybuffer@0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz#9818c79e059b1355f97e0428a017c838e90ba812" + integrity sha1-mBjHngWbE1X5fgQooBfIOOkLqBI= + base64-js@^1.0.2: version "1.5.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" @@ -4194,7 +4204,7 @@ commondir@^1.0.1: resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -component-emitter@^1.2.1: +component-emitter@^1.2.1, component-emitter@~1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== @@ -4838,7 +4848,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@~4.3.1: version "4.3.1" resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== @@ -5272,6 +5282,28 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" +engine.io-client@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-5.1.1.tgz#f5c3aaaef1bdc9443aac6ffde48b3b2fb2dc56fc" + integrity sha512-jPFpw2HLL0lhZ2KY0BpZhIJdleQcUO9W1xkIpo0h3d6s+5D6+EV/xgQw9qWOmymszv2WXef/6KUUehyxEKomlQ== + dependencies: + base64-arraybuffer "0.1.4" + component-emitter "~1.3.0" + debug "~4.3.1" + engine.io-parser "~4.0.1" + has-cors "1.1.0" + parseqs "0.0.6" + parseuri "0.0.6" + ws "~7.4.2" + yeast "0.1.2" + +engine.io-parser@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-4.0.2.tgz#e41d0b3fb66f7bf4a3671d2038a154024edb501e" + integrity sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg== + dependencies: + base64-arraybuffer "0.1.4" + enhanced-resolve@^4.3.0: version "4.5.0" resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz" @@ -6394,6 +6426,11 @@ has-bigints@^1.0.1: resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +has-cors@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" + integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" @@ -9172,6 +9209,16 @@ parse5@6.0.1: resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +parseqs@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.6.tgz#8e4bb5a19d1cdc844a08ac974d34e273afa670d5" + integrity sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w== + +parseuri@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.6.tgz#e1496e829e3ac2ff47f39a4dd044b32823c4a25a" + integrity sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow== + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" @@ -11940,6 +11987,28 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +socket.io-client@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.1.2.tgz#95ad7113318ea01fba0860237b96d71e1b1fd2eb" + integrity sha512-RDpWJP4DQT1XeexmeDyDkm0vrFc0+bUsHDKiVGaNISJvJonhQQOMqV9Vwfg0ZpPJ27LCdan7iqTI92FRSOkFWQ== + dependencies: + "@types/component-emitter" "^1.2.10" + backo2 "~1.0.2" + component-emitter "~1.3.0" + debug "~4.3.1" + engine.io-client "~5.1.1" + parseuri "0.0.6" + socket.io-parser "~4.0.4" + +socket.io-parser@~4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.4.tgz#9ea21b0d61508d18196ef04a2c6b9ab630f4c2b0" + integrity sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g== + dependencies: + "@types/component-emitter" "^1.2.10" + component-emitter "~1.3.0" + debug "~4.3.1" + sockjs-client@^1.5.0: version "1.5.1" resolved "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.1.tgz" @@ -13702,7 +13771,7 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -"ws@^5.2.0 || ^6.0.0 || ^7.0.0", ws@^7.4.5: +"ws@^5.2.0 || ^6.0.0 || ^7.0.0", ws@^7.4.5, ws@~7.4.2: version "7.4.6" resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== @@ -13826,6 +13895,11 @@ yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yeast@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" + integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" diff --git a/hasura/migrations/1624310782649_alter_table_public_bodyshops_add_column_cdk_dealerid/down.yaml b/hasura/migrations/1624310782649_alter_table_public_bodyshops_add_column_cdk_dealerid/down.yaml new file mode 100644 index 000000000..ac0260950 --- /dev/null +++ b/hasura/migrations/1624310782649_alter_table_public_bodyshops_add_column_cdk_dealerid/down.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."bodyshops" DROP COLUMN "cdk_dealerid"; + type: run_sql diff --git a/hasura/migrations/1624310782649_alter_table_public_bodyshops_add_column_cdk_dealerid/up.yaml b/hasura/migrations/1624310782649_alter_table_public_bodyshops_add_column_cdk_dealerid/up.yaml new file mode 100644 index 000000000..56b9e04b1 --- /dev/null +++ b/hasura/migrations/1624310782649_alter_table_public_bodyshops_add_column_cdk_dealerid/up.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."bodyshops" ADD COLUMN "cdk_dealerid" text NULL; + type: run_sql diff --git a/hasura/migrations/1624310795238_update_permission_user_public_table_bodyshops/down.yaml b/hasura/migrations/1624310795238_update_permission_user_public_table_bodyshops/down.yaml new file mode 100644 index 000000000..fae9999b1 --- /dev/null +++ b/hasura/migrations/1624310795238_update_permission_user_public_table_bodyshops/down.yaml @@ -0,0 +1,85 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - accountingconfig + - address1 + - address2 + - appt_alt_transport + - appt_colors + - appt_length + - bill_tax_rates + - city + - country + - created_at + - default_adjustment_rate + - deliverchecklist + - email + - enforce_class + - enforce_referral + - federal_tax_id + - id + - imexshopid + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - jc_hourly_rates + - jobsizelimit + - logo_img_path + - md_categories + - md_ccc_rates + - md_classes + - md_hour_split + - md_ins_cos + - md_jobline_presets + - md_labor_rates + - md_messaging_presets + - md_notes_presets + - md_order_statuses + - md_parts_locations + - md_payment_types + - md_rbac + - md_referral_sources + - md_responsibility_centers + - md_ro_statuses + - messagingservicesid + - phone + - prodtargethrs + - production_config + - region_config + - schedule_end_time + - schedule_start_time + - scoreboard_target + - shopname + - shoprates + - speedprint + - ssbuckets + - state + - state_tax_id + - stripe_acct_id + - sub_status + - target_touchtime + - template_header + - textid + - updated_at + - use_fippa + - website + - workingdays + - zip_post + computed_fields: [] + filter: + associations: + user: + authid: + _eq: X-Hasura-User-Id + role: user + table: + name: bodyshops + schema: public + type: create_select_permission diff --git a/hasura/migrations/1624310795238_update_permission_user_public_table_bodyshops/up.yaml b/hasura/migrations/1624310795238_update_permission_user_public_table_bodyshops/up.yaml new file mode 100644 index 000000000..330d7d1af --- /dev/null +++ b/hasura/migrations/1624310795238_update_permission_user_public_table_bodyshops/up.yaml @@ -0,0 +1,86 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - accountingconfig + - address1 + - address2 + - appt_alt_transport + - appt_colors + - appt_length + - bill_tax_rates + - cdk_dealerid + - city + - country + - created_at + - default_adjustment_rate + - deliverchecklist + - email + - enforce_class + - enforce_referral + - federal_tax_id + - id + - imexshopid + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - jc_hourly_rates + - jobsizelimit + - logo_img_path + - md_categories + - md_ccc_rates + - md_classes + - md_hour_split + - md_ins_cos + - md_jobline_presets + - md_labor_rates + - md_messaging_presets + - md_notes_presets + - md_order_statuses + - md_parts_locations + - md_payment_types + - md_rbac + - md_referral_sources + - md_responsibility_centers + - md_ro_statuses + - messagingservicesid + - phone + - prodtargethrs + - production_config + - region_config + - schedule_end_time + - schedule_start_time + - scoreboard_target + - shopname + - shoprates + - speedprint + - ssbuckets + - state + - state_tax_id + - stripe_acct_id + - sub_status + - target_touchtime + - template_header + - textid + - updated_at + - use_fippa + - website + - workingdays + - zip_post + computed_fields: [] + filter: + associations: + user: + authid: + _eq: X-Hasura-User-Id + role: user + table: + name: bodyshops + schema: public + type: create_select_permission diff --git a/hasura/migrations/metadata.yaml b/hasura/migrations/metadata.yaml index f9bb3e114..3a4f43614 100644 --- a/hasura/migrations/metadata.yaml +++ b/hasura/migrations/metadata.yaml @@ -757,6 +757,7 @@ tables: - appt_colors - appt_length - bill_tax_rates + - cdk_dealerid - city - country - created_at diff --git a/package.json b/package.json index 9dbe66bb1..7026cc986 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "node-mailjet": "^3.3.1", "nodemailer": "^6.6.0", "phone": "^2.4.20", + "socket.io": "^4.1.2", "stripe": "^8.148.0", "twilio": "^3.62.0", "xmlbuilder2": "^2.4.1" diff --git a/server.js b/server.js index 8f37796a6..a26bc207a 100644 --- a/server.js +++ b/server.js @@ -148,16 +148,14 @@ app.get("/", async function (req, res) { res.status(200).send("Access Forbidden."); }); -if (process.env.NODE_ENV === "production") { - app.listen(port, (error) => { - if (error) throw error; - console.log("AWS - [PRODUCTION] Server running on port " + port); - }); -} else { - app.listen(port, (error) => { - if (error) throw error; - console.log( - `[${process.env.NODE_ENV}] Non Secured Server running on port ` + port - ); - }); -} +const http = require("http"); +const server = http.createServer(app); +const { Server } = require("socket.io"); +const io = new Server(server, { path: "/ws" }); + +server.listen(port, (error) => { + if (error) throw error; + console.log(`[${process.env.NODE_ENV}] Server running on port ${port}`); +}); +exports.io = io; +require("./server/cdk/cdk"); diff --git a/server/cdk/cdk-job-export.js b/server/cdk/cdk-job-export.js new file mode 100644 index 000000000..ecaf4d288 --- /dev/null +++ b/server/cdk/cdk-job-export.js @@ -0,0 +1,34 @@ +const path = require("path"); +require("dotenv").config({ + path: path.resolve( + process.cwd(), + `.env.${process.env.NODE_ENV || "development"}` + ), +}); +const GraphQLClient = require("graphql-request").GraphQLClient; +const queries = require("../graphql-client/queries"); + +const CdkBase = require("./cdk"); + +exports.default = async function (socket, jobid) { + CdkBase.createLogEvent( + socket, + "DEBUG", + `Received Job export request for id ${jobid}` + ); + const JobData = await QueryJobData(socket, jobid); +}; + +async function QueryJobData(socket, jobid) { + CdkBase.createLogEvent(socket, "DEBUG", `Querying job data for id ${jobid}`); + const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {}); + const result = await client + .setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` }) + .request(queries.QUERY_JOBS_FOR_CDK_EXPORT, { id: jobid }); + CdkBase.createLogEvent( + socket, + "TRACE", + `Job data query result ${JSON.stringify(result)}` + ); + return result; +} diff --git a/server/cdk/cdk.js b/server/cdk/cdk.js new file mode 100644 index 000000000..6846609eb --- /dev/null +++ b/server/cdk/cdk.js @@ -0,0 +1,86 @@ +const path = require("path"); +const _ = require("lodash"); +require("dotenv").config({ + path: path.resolve( + process.cwd(), + `.env.${process.env.NODE_ENV || "development"}` + ), +}); + +const { io } = require("../../server"); +const { admin } = require("../firebase/firebase-handler"); +const CdkJobExport = require("./cdk-job-export").default; + +io.use(function (socket, next) { + try { + if (socket.handshake.auth.token) { + admin + .auth() + .verifyIdToken(socket.handshake.auth.token) + .then((user) => { + socket.user = user; + next(); + }) + .catch((error) => { + next(new Error("Authentication error", JSON.stringify(error))); + }); + } else { + next(new Error("Authentication error - no authorization token.")); + } + } catch (error) { + console.log("Uncaught connection error:::", error); + next(new Error(`Authentication error ${error}`)); + } +}); + +io.on("connection", (socket) => { + socket.log_level = "DEBUG"; + createLogEvent(socket, "DEBUG", `Connected and Authenticated.`); + + socket.on("set-log-level", (level) => { + socket.log_level = level; + createLogEvent(socket, "DEBUG", `Updated log level to ${level}`); + }); + + socket.on("export-job", (jobid) => { + CdkJobExport(socket, jobid); + }); + + socket.on("disconnect", () => { + createLogEvent(socket, "DEBUG", `User disconnected.`); + }); +}); + +function createLogEvent(socket, level, message) { + if (LogLevelHierarchy(socket.log_level) >= LogLevelHierarchy(level)) { + console.log( + `[CDK LOG EVENT] ${level} - ${new Date()} - ${socket.user.email} - ${ + socket.id + } - ${message}` + ); + socket.emit("log-event", { + timestamp: new Date(), + level, + message, + }); + } +} + +function LogLevelHierarchy(level) { + switch (level) { + case "TRACE": + return 5; + case "DEBUG": + return 4; + case "INFO": + return 3; + case "WARNING": + return 2; + case "ERROR": + return 1; + default: + return 3; + } +} + +exports.createLogEvent = createLogEvent; diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index f5f4e837d..7d14d6325 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -116,6 +116,80 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) { } `; +exports.QUERY_JOBS_FOR_CDK_EXPORT = ` +query QUERY_JOBS_FOR_CDK_EXPORT($id: uuid!) { + jobs_by_pk(id: $id) { + id + job_totals + date_invoiced + ro_number + clm_total + clm_no + invoice_allocation + ownerid + ownr_ln + ownr_fn + ownr_addr1 + ownr_addr2 + ownr_zip + ownr_city + ownr_st + ins_co_nm + job_totals + rate_la1 + rate_la2 + rate_la3 + rate_la4 + rate_laa + rate_lab + rate_lad + rate_lae + rate_laf + rate_lag + rate_lam + rate_lar + rate_las + rate_lau + rate_ma2s + rate_ma2t + rate_ma3s + rate_mabl + rate_macs + rate_mahw + rate_mapa + rate_mash + rate_matd + class + ca_bc_pvrt + ca_customer_gst + bodyshop { + id + md_responsibility_centers + accountingconfig + cdk_dealerid + } + owner { + accountingid + } + joblines(where:{removed: {_eq:false}}) { + id + line_desc + part_type + act_price + mod_lb_hrs + mod_lbr_ty + part_qty + op_code_desc + profitcenter_labor + profitcenter_part + db_ref + prt_dsmk_p + } + } + +} + `; + exports.QUERY_BILLS_FOR_PAYABLES_EXPORT = ` query QUERY_BILLS_FOR_PAYABLES_EXPORT($bills: [uuid!]!) { bills(where: {id: {_in: $bills}}) { diff --git a/yarn.lock b/yarn.lock index 9ec5af81c..e4e1b080c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -296,6 +296,11 @@ "@types/connect" "*" "@types/node" "*" +"@types/component-emitter@^1.2.10": + version "1.2.10" + resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.10.tgz#ef5b1589b9f16544642e473db5ea5639107ef3ea" + integrity sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg== + "@types/concat-stream@^1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.0.tgz#394dbe0bb5fee46b38d896735e8b68ef2390d00d" @@ -310,6 +315,16 @@ dependencies: "@types/node" "*" +"@types/cookie@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.0.tgz#14f854c0f93d326e39da6e3b6f34f7d37513d108" + integrity sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg== + +"@types/cors@^2.8.8": + version "2.8.10" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.10.tgz#61cc8469849e5bcdd0c7044122265c39cec10cf4" + integrity sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ== + "@types/express-jwt@0.0.42": version "0.0.42" resolved "https://registry.yarnpkg.com/@types/express-jwt/-/express-jwt-0.0.42.tgz#4f04e1fadf9d18725950dc041808a4a4adf7f5ae" @@ -371,6 +386,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.37.tgz#a3dd8da4eb84a996c36e331df98d82abd76b516e" integrity sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw== +"@types/node@>=10.0.0": + version "15.12.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.4.tgz#e1cf817d70a1e118e81922c4ff6683ce9d422e26" + integrity sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA== + "@types/node@^13.7.0": version "13.13.48" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.48.tgz#46a3df718aed5217277f2395a682e055a487e341" @@ -411,7 +431,7 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -accepts@~1.3.5, accepts@~1.3.7: +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== @@ -582,11 +602,21 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base64-arraybuffer@0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz#9818c79e059b1355f97e0428a017c838e90ba812" + integrity sha1-mBjHngWbE1X5fgQooBfIOOkLqBI= + base64-js@^1.0.2, base64-js@^1.3.0: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +base64id@2.0.0, base64id@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" + integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + batch@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" @@ -811,7 +841,7 @@ combined-stream@^1.0.6, combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -component-emitter@^1.2.0, component-emitter@^1.3.0: +component-emitter@^1.2.0, component-emitter@^1.3.0, component-emitter@~1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== @@ -907,6 +937,11 @@ cookie@0.4.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== +cookie@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + cookiejar@^2.1.0, cookiejar@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" @@ -922,7 +957,7 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cors@2.8.5: +cors@2.8.5, cors@~2.8.5: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== @@ -1026,7 +1061,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== @@ -1219,6 +1254,26 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" +engine.io-parser@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-4.0.2.tgz#e41d0b3fb66f7bf4a3671d2038a154024edb501e" + integrity sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg== + dependencies: + base64-arraybuffer "0.1.4" + +engine.io@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-5.1.1.tgz#a1f97e51ddf10cbd4db8b5ff4b165aad3760cdd3" + integrity sha512-aMWot7H5aC8L4/T8qMYbLdvKlZOdJTH54FxfdFunTGvhMx1BHkJOntWArsVfgAZVwAO9LC2sryPWRcEeUzCe5w== + dependencies: + accepts "~1.3.4" + base64id "2.0.0" + cookie "~0.4.1" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~4.0.0" + ws "~7.4.2" + enquirer@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -3362,6 +3417,35 @@ snakeize@^0.1.0: resolved "https://registry.yarnpkg.com/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d" integrity sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0= +socket.io-adapter@~2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.3.1.tgz#a442720cb09a4823cfb81287dda1f9b52d4ccdb2" + integrity sha512-8cVkRxI8Nt2wadkY6u60Y4rpW3ejA1rxgcK2JuyIhmF+RMNpTy1QRtkHIDUOf3B4HlQwakMsWbKftMv/71VMmw== + +socket.io-parser@~4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.4.tgz#9ea21b0d61508d18196ef04a2c6b9ab630f4c2b0" + integrity sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g== + dependencies: + "@types/component-emitter" "^1.2.10" + component-emitter "~1.3.0" + debug "~4.3.1" + +socket.io@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.1.2.tgz#f90f9002a8d550efe2aa1d320deebb9a45b83233" + integrity sha512-xK0SD1C7hFrh9+bYoYCdVt+ncixkSLKtNLCax5aEy1o3r5PaO5yQhVb97exIe67cE7lAK+EpyMytXWTWmyZY8w== + dependencies: + "@types/cookie" "^0.4.0" + "@types/cors" "^2.8.8" + "@types/node" ">=10.0.0" + accepts "~1.3.4" + base64id "~2.0.0" + debug "~4.3.1" + engine.io "~5.1.0" + socket.io-adapter "~2.3.0" + socket.io-parser "~4.0.3" + socks-proxy-agent@5, socks-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz#7c0f364e7b1cf4a7a437e71253bed72e9004be60" @@ -3949,6 +4033,11 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +ws@~7.4.2: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + xdg-basedir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"