\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n {/* calls handleUpdateOrder() in EditOrderStatusContainer.js */}\r\n \r\n
\r\n \r\n );\r\n};\r\n\r\nexport default orderStatusFormComponent;","import React, {Fragment} from 'react';\r\nimport {Modal, ModalHeader, ModalBody} from 'reactstrap';\r\nimport OrderStatusFormComponent from '../OrderStatusForm/orderStatusFormComponent';\r\nimport VendorLookupContainer from '../../../VendorLookup/VendorLookupContainer';\r\nimport {Rnd} from 'react-rnd';\r\n\r\nconst editOrderStatusModalComponent = props => {\r\n const {modalOpen, vendorLookUpMode, orderInfo} = props;\r\n const modalClassName = 'modal-lg';\r\n const modalTitle = vendorLookUpMode ? 'Clinic Lookup' : 'Update Order';\r\n const vendorLookUpWrapperClassName = !vendorLookUpMode ? 'd-none' : '';\r\n const orderStatusFormWrapperClassName = vendorLookUpMode ? 'd-none' : '';\r\n return (\r\n
\r\n \r\n \r\n {modalTitle}\r\n \r\n \r\n \r\n
\r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n )\r\n};\r\n\r\nexport default editOrderStatusModalComponent;","import React, {Component} from 'react';\r\nimport moment from 'moment';\r\nimport PropTypes from 'prop-types';\r\nimport _ from 'lodash';\r\n\r\nimport EditOrderStatusModalComponent from \"./editOrderStatusModalComponent\";\r\n\r\nexport class EditOrderStatusModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n orderInfo: {},\r\n vendorLookUpMode: false\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n const walkIn = this.props.clinic && this.props.clinic.walkIn ? this.props.clinic.walkIn : false;\r\n const orderInfo = {\r\n orderStatusId: this.props.orderStatusId || -1,\r\n orderStatus: this.props.orderStatus || '',\r\n appointmentDate: this.props.clinic ? walkIn ? moment(this.props.clinic.appointment) : moment(this.props.clinic.appointment) : null,\r\n vendorId: this.props.clinic ? this.props.clinic.vendorId : null,\r\n vendor: this.props.clinic ? this.props.clinic.name : '',\r\n walkIn\r\n };\r\n this.setState({orderInfo});//the vendor id field shows for cme members, also the documents are hidden by default for them\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n let newState = {};\r\n if (!_.isEqual(this.props.clinic, prevProps.clinic)) {\r\n newState.clinic = this.props.clinic;\r\n }\r\n if (this.props.orderStatusId !== prevProps.orderStatusId) {\r\n newState.orderStatusId = this.props.orderStatusId;\r\n }\r\n if (this.props.orderStatus !== prevProps.orderStatus) {\r\n newState.orderStatus = this.props.orderStatus;\r\n }\r\n if (Object.keys(newState).length > 0) {\r\n this.setState({...newState});\r\n }\r\n }\r\n\r\n handleAppointmentDateChange = date => {\r\n const orderInfo = {...this.state.orderInfo};\r\n orderInfo.appointmentDate = date;\r\n this.setState({orderInfo});\r\n };\r\n\r\n /**\r\n * Fired from child when a new status is selected to send back to this state\r\n * @param statusInfo\r\n */\r\n handleOrderStatusChange = statusInfo => {\r\n const orderInfo = {...this.state.orderInfo};\r\n orderInfo.orderStatusId = statusInfo.selectedOrderStatusId;\r\n orderInfo.orderStatus = statusInfo.selectedOrderStatus;\r\n this.setState({orderInfo});\r\n };\r\n\r\n /**\r\n * Event handler for opening the Vendor Lookup container\r\n */\r\n handleVendorLookup = e => {\r\n e.preventDefault();\r\n this.setState({vendorLookUpMode: true});\r\n };\r\n\r\n /**\r\n * Event handler from retrieving selected vendor from Vendor Lookup\r\n */\r\n handleConfirmVendorSelection = vendorChanges => {\r\n const orderInfo = {...this.state.orderInfo};\r\n orderInfo.vendorId = vendorChanges.vendorId;\r\n orderInfo.vendor = vendorChanges.vendorName;\r\n orderInfo.address1 = vendorChanges.address1;\r\n orderInfo.address2 = vendorChanges.address2;\r\n orderInfo.city = vendorChanges.city;\r\n orderInfo.phone = vendorChanges.phone;\r\n orderInfo.state = vendorChanges.state;\r\n orderInfo.zip = vendorChanges.zip;\r\n this.setState({\r\n vendorLookUpMode: false,\r\n orderInfo\r\n });\r\n };\r\n\r\n handleCancelVendorSelection = e => {\r\n e.preventDefault();\r\n this.setState({vendorLookUpMode: false});\r\n };\r\n\r\n /**\r\n * Passes back updated state to parent controller to update order status in DQit and Mongo\r\n */\r\n handleUpdateOrder = e => {\r\n e.preventDefault();\r\n this.props.handleUpdateOrder(this.state.orderInfo);\r\n };\r\n\r\n handleCheckboxChange = e => {\r\n const orderInfo = {...this.state.orderInfo};\r\n orderInfo.walkIn = e.target.checked;\r\n this.setState({orderInfo});\r\n };\r\n\r\n render() {\r\n return
\r\n }\r\n}\r\n\r\nEditOrderStatusModalContainer.propTypes = {\r\n handleUpdateOrder: PropTypes.func.isRequired,\r\n handleCancelEditOrder: PropTypes.func.isRequired\r\n};\r\n\r\nexport default EditOrderStatusModalContainer;","import React, {Component, Fragment} from 'react';\r\nimport axios from 'axios';\r\nimport moment from 'moment';\r\nimport PropTypes from 'prop-types';\r\nimport EditOrderStatusModal from \"./components/EditOrderStatusModal/EditOrderStatusModalContainer\";\r\nimport ordersService from \"../../../services/ordersService\";\r\nimport async from 'async';\r\nimport classNames from 'classnames';\r\n\r\n/**\r\n * Edit Order Status Container\r\n * Purpose: Render a font awesome Edit icon that opens a modal window (Edit Order Status Modal Container)\r\n * Take note of the required PropTypes when implementing this component\r\n */\r\nexport class EditOrderStatusContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n editMode: false\r\n }\r\n }\r\n\r\n\r\n componentDidMount() {\r\n this.cancelSource = axios.CancelToken.source();\r\n }\r\n\r\n componentWillUnmount() {\r\n this.cancelSource.cancel('userCanceled');\r\n }\r\n\r\n /**\r\n * Click event handler for Edit button (fa-edit)\r\n * @param e\r\n */\r\n handleEditOrderClick = e => {\r\n e.preventDefault();\r\n this.setState({editMode: true});\r\n };\r\n\r\n /**\r\n * Button click event handler for canceling the editing dialog\r\n * Simply sets 'editMode' to 'false' in component state which will cause the editing dialog to close\r\n */\r\n handleCancelEditOrder = e => {\r\n e.preventDefault();\r\n this.setState({editMode: false});\r\n };\r\n\r\n handleUpdateOrder = (updatedOrderInfo) => {\r\n const {clinic, orderStatusId, medicalExamOrderId, orderId, userEmail} = this.props;\r\n // list of changes to update in DQit (SQL), initialized with default root values / properties\r\n let orderStatusChanges = {\r\n medicalExamOrderId,\r\n userEmail,\r\n walkIn: updatedOrderInfo.walkIn,\r\n updateLog: {},\r\n orderSource: clinic.orderSource\r\n };\r\n\r\n //check for differences between values at initialization vs when the Edit Order Status dialog is closed\r\n if (clinic.vendorId !== updatedOrderInfo.vendorId) {\r\n orderStatusChanges.updateLog.updateVendor = {\r\n vendorId: updatedOrderInfo.vendorId,\r\n name: updatedOrderInfo.vendor,\r\n address1: updatedOrderInfo.address1,\r\n address2: updatedOrderInfo.address2,\r\n city: updatedOrderInfo.city,\r\n state: updatedOrderInfo.state,\r\n zip: updatedOrderInfo.zip,\r\n phone: updatedOrderInfo.phone,\r\n auditMessage: `Vendor Changed to ${updatedOrderInfo.vendor}`\r\n };\r\n }\r\n if (moment(clinic.appointment).format(updatedOrderInfo.walkIn ? 'M/D/YYYY' : 'M/D/YYYY h:mm a') !== moment(updatedOrderInfo.appointmentDate).format(updatedOrderInfo.walkIn ? 'M/D/YYYY' : 'M/D/YYYY h:mm a')\r\n || (updatedOrderInfo.walkIn !== clinic.walkIn)) {\r\n orderStatusChanges.updateLog.updateAppointment = {\r\n appointment: updatedOrderInfo.walkIn ? moment(updatedOrderInfo.appointmentDate).format('YYYY-MM-DD') : moment(updatedOrderInfo.appointmentDate).format('YYYY-MM-DD HH:mm'),\r\n auditMessage: `Appointment Date Set to ${moment(updatedOrderInfo.appointmentDate).format(updatedOrderInfo.walkIn ? 'YYYY-MM-DD' : 'M/D/YYYY h:mm a')}`\r\n };\r\n }\r\n\r\n if (updatedOrderInfo.orderStatusId > -1 && orderStatusId !== updatedOrderInfo.orderStatusId) {\r\n orderStatusChanges.updateLog.updateStatus = {\r\n orderStatus: updatedOrderInfo.orderStatus,\r\n orderStatusId: updatedOrderInfo.orderStatusId,\r\n auditMessage: `Status changed to ${updatedOrderInfo.orderStatus}`\r\n };\r\n }\r\n\r\n //process updates if we have something to update in DQit (update log keys > 0)\r\n if (Object.keys(orderStatusChanges.updateLog).length > 0) {\r\n this.processBatchStatusUpdates(orderId, orderStatusChanges);\r\n }\r\n\r\n // close the modal\r\n this.setState({editMode: false});\r\n };\r\n\r\n /**\r\n * Process patch of status updates to DQit Db.\r\n * @param orderId - the Order Id (not the Medical Exam Order id)\r\n * @param orderStatusChanges - object of changes to be passed up to the sever\r\n */\r\n processBatchStatusUpdates = (orderId, orderStatusChanges) => {\r\n ordersService.updateOrder(orderId, orderStatusChanges, this.cancelSource.token)\r\n .then(response => {\r\n const updateResponses = response;\r\n\r\n if (this.props.onOrderChangedCallback) {\r\n this.props.onOrderChangedCallback(orderId, null);\r\n return;\r\n }\r\n // what we are sending to mongo\r\n let cmeValuesToUpdate = {};\r\n\r\n // only sync data we know was updated successfully in DQit\r\n // loop through response data and build a CME update object\r\n Object.keys(updateResponses).forEach(key => {\r\n // where 'key' is: updateVendor, updateAppointment, updateStatus\r\n // use \"update key\" to pull response status (what came back in response.data)\r\n const hasError = updateResponses[key].hasError; // check response object for error\r\n if (!hasError) {\r\n // pull the updated values for specific key\r\n const updatedValues = this.mapStatusChange(key, orderStatusChanges.updateLog[key]);\r\n cmeValuesToUpdate = {...cmeValuesToUpdate, ...updatedValues};\r\n }\r\n });\r\n this.syncLocalData(cmeValuesToUpdate);\r\n })\r\n .catch(err => {\r\n console.log(err);\r\n if (this.props.onOrderChangedCallback) {\r\n this.props.onOrderChangedCallback(null, err);\r\n }\r\n });\r\n };\r\n\r\n mapStatusChange = (updateKey, updateValues) => {\r\n switch (updateKey) {\r\n case 'updateVendor':\r\n return {\r\n 'clinic.vendorId': updateValues.vendorId,\r\n 'clinic.name': updateValues.name,\r\n 'clinic.address1': updateValues.address1,\r\n 'clinic.address2': updateValues.address2,\r\n 'clinic.city': updateValues.city,\r\n 'clinic.state': updateValues.state,\r\n 'clinic.zip': updateValues.zip,\r\n 'clinic.phone': updateValues.phone\r\n };\r\n case 'updateAppointment':\r\n return {\r\n 'clinic.appointment': updateValues.appointment\r\n };\r\n case 'updateStatus':\r\n return {\r\n 'orderStatusId': updateValues.orderStatusId,\r\n 'orderStatus': updateValues.orderStatus\r\n };\r\n default:\r\n return {}\r\n }\r\n };\r\n\r\n /**\r\n * Sync local MongoDb record with status change updates successfully updates w\r\n * @param cme\r\n */\r\n syncLocalData = cme => {\r\n // if component is not associated to a cmeId in Mongo immediately fire reload refresh events\r\n if (!this.props.cmeId || this.props.cmeId === '') {\r\n if (this.props.reloadPage) {\r\n this.props.reloadPage();\r\n }\r\n if (this.props.refreshAuditTrail) {\r\n this.props.refreshAuditTrail();\r\n }\r\n return;\r\n }\r\n async.parallel([\r\n done => {\r\n axios\r\n .patch(`/v1/cmes/${this.props.cmeId}`, cme, {cancelToken: this.cancelSource.token})\r\n .then(() => {\r\n done();\r\n })\r\n .catch(err => {\r\n done(err);\r\n });\r\n },\r\n done => {\r\n const variables = {};\r\n if (cme.hasOwnProperty('clinic.appointment')) {\r\n variables.appointmentDate = cme['clinic.appointment'];\r\n }\r\n if (cme.hasOwnProperty('clinic.name')) {\r\n variables.clinicName = cme['clinic.name'];\r\n }\r\n axios\r\n .patch(`/v1/processes/cmeProcess/tasks/${this.props.taskId}`,\r\n {variables}, {cancelToken: this.cancelSource.token})\r\n .then(() => {\r\n done();\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n done(err);\r\n });\r\n }\r\n ], err => {\r\n if (err) {\r\n console.log(err);\r\n } else {\r\n this.props.reloadPage();\r\n this.props.refreshAuditTrail();\r\n }\r\n }\r\n );\r\n\r\n\r\n };\r\n\r\n render() {\r\n const {clinic, orderStatusId, orderStatus, hidePadding} = this.props;\r\n return (\r\n
\r\n \r\n {this.state.editMode &&\r\n }\r\n \r\n )\r\n }\r\n}\r\n\r\nEditOrderStatusContainer.propTypes = {\r\n cmeId: PropTypes.string,\r\n clinic: PropTypes.object.isRequired,\r\n orderStatusId: PropTypes.number.isRequired,\r\n orderStatus: PropTypes.string.isRequired,\r\n medicalExamOrderId: PropTypes.number.isRequired,\r\n orderId: PropTypes.number.isRequired,\r\n userEmail: PropTypes.string.isRequired,\r\n reloadPage: PropTypes.func.isRequired,\r\n refreshAuditTrail: PropTypes.func\r\n};\r\n\r\nexport default EditOrderStatusContainer;","import React from 'react';\r\nimport Select from 'react-select';\r\n\r\nconst clientSiteSelectorComponent = props => {\r\n let clientOptions = props.displaySites\r\n .map(client => ({\r\n value: client._id,\r\n label: client.name,\r\n levelNumber: client.levelNumber\r\n })).sort(function (a, b) {\r\n if ( a.levelNumber === 1 ) return -1;\r\n if ( b.levelNumber === 1 ) return 1; \r\n return a.label.localeCompare(b.label);\r\n });\r\n \r\n if (props.selectAll) {\r\n clientOptions.unshift({value: 'allSites', label: 'All Sites', mongoId: 'allSites', legacyClientId: 'allSites'});\r\n }\r\n let selectedValue = null;\r\n if (props.allSitesSelected) {\r\n selectedValue = clientOptions.find(co => co.value === 'allSites');\r\n } else {\r\n if (props.multiSelect) {\r\n selectedValue = clientOptions.filter(co => props.selectedSites.map(ss => ss._id).includes(co.value));\r\n } else {\r\n if (props.selectedSite && Object.keys(props.selectedSite).length > 0) {\r\n selectedValue = clientOptions.find(co => co.value === props.selectedSite._id);\r\n }\r\n }\r\n }\r\n\r\n if (props.hideSelect || clientOptions.length === 0) {\r\n return null;\r\n }\r\n return (\r\n
\r\n );\r\n};\r\n\r\nexport default clientSiteSelectorComponent;","// =======================================================================================\r\n// Vaccines Reports Tables\r\n// =======================================================================================\r\nconst SET_VACCINE_EVENT_REPORT_TABLE_PAGE_INDEX = 'SET_VACCINE_EVENT_REPORT_TABLE_PAGE_INDEX';\r\nconst SET_VACCINE_EVENT_REPORT_PAGE_SIZE = 'SET_VACCINE_EVENT_REPORT_PAGE_SIZE';\r\nconst SET_VACCINE_EVENT_REPORT_SORTING = 'SET_VACCINE_EVENT_REPORT_SORTING';\r\nconst SET_VACCINE_EVENT_REPORT_FILTERING = 'SET_VACCINE_EVENT_REPORT_FILTERING';\r\nconst SET_VACCINE_EVENT_REPORT_RECENT = 'SET_VACCINE_EVENT_REPORT_RECENT';\r\nconst SET_VACCINE_TEST_REPORT_TABLE_PAGE_INDEX = 'SET_VACCINE_TEST_REPORT_TABLE_PAGE_INDEX';\r\nconst SET_VACCINE_TEST_REPORT_PAGE_SIZE = 'SET_VACCINE_TEST_REPORT_PAGE_SIZE';\r\nconst SET_VACCINE_TEST_REPORT_SORTING = 'SET_VACCINE_TEST_REPORT_SORTING';\r\nconst SET_VACCINE_TEST_REPORT_FILTERING = 'SET_VACCINE_TEST_REPORT_FILTERING';\r\nconst SET_VACCINE_TEST_REPORT_RECENT = 'SET_VACCINE_TEST_REPORT_RECENT';\r\n\r\nexport default {\r\n // Vaccine reports tables\r\n SET_VACCINE_EVENT_REPORT_TABLE_PAGE_INDEX,\r\n SET_VACCINE_EVENT_REPORT_PAGE_SIZE,\r\n SET_VACCINE_EVENT_REPORT_SORTING,\r\n SET_VACCINE_EVENT_REPORT_FILTERING,\r\n SET_VACCINE_EVENT_REPORT_RECENT,\r\n SET_VACCINE_TEST_REPORT_TABLE_PAGE_INDEX,\r\n SET_VACCINE_TEST_REPORT_PAGE_SIZE,\r\n SET_VACCINE_TEST_REPORT_SORTING,\r\n SET_VACCINE_TEST_REPORT_FILTERING,\r\n SET_VACCINE_TEST_REPORT_RECENT\r\n};","import types from './types';\r\nimport {combineReducers} from 'redux';\r\n\r\n// =======================================================================================\r\n// Vaccines Reports Tables\r\n// =======================================================================================\r\nconst tableSettingsDefaultState = {\r\n testsTable: {\r\n sorting: [{ id: 'colTestDate', desc: true }],\r\n filtering: [],\r\n pageIndex: 0,\r\n pageSize: 10,\r\n recentOnly: false\r\n },\r\n eventsTable: {\r\n sorting: [{ id: 'colEventDate', desc: true }],\r\n filtering: [],\r\n pageIndex: 0,\r\n pageSize: 10,\r\n recentOnly: false\r\n }\r\n};\r\n\r\nconst vaccineReportsTableSettingsReducer = (state = tableSettingsDefaultState, action) => {\r\n\r\n switch (action.type) {\r\n case types.SET_VACCINE_EVENT_REPORT_TABLE_PAGE_INDEX: \r\n return {\r\n ...state,\r\n eventsTable: {\r\n ...state.eventsTable,\r\n pageIndex: action.payload.pageIndex\r\n }\r\n }\r\n case types.SET_VACCINE_EVENT_REPORT_PAGE_SIZE:\r\n return {\r\n ...state,\r\n eventsTable: {\r\n ...state.eventsTable,\r\n pageIndex: action.payload.pageIndex,\r\n pageSize: action.payload.pageSize\r\n }\r\n }\r\n\r\n case types.SET_VACCINE_EVENT_REPORT_SORTING:\r\n return {\r\n ...state,\r\n eventsTable: {\r\n ...state.eventsTable,\r\n sorting: [{\r\n id: action.payload.columnId,\r\n desc: action.payload.desc\r\n }]\r\n }\r\n }\r\n\r\n case types.SET_VACCINE_EVENT_REPORT_FILTERING:\r\n return {\r\n ...state,\r\n eventsTable: {\r\n ...state.eventsTable,\r\n filtering: action.payload.filterArray\r\n }\r\n }\r\n\r\n case types.SET_VACCINE_EVENT_REPORT_RECENT:\r\n return {\r\n ...state,\r\n eventsTable: {\r\n ...state.eventsTable,\r\n recentOnly: action.payload.recent\r\n }\r\n }\r\n\r\n case types.SET_VACCINE_TEST_REPORT_TABLE_PAGE_INDEX: \r\n return {\r\n ...state,\r\n testsTable: {\r\n ...state.testsTable,\r\n pageIndex: action.payload.pageIndex\r\n }\r\n }\r\n\r\n case types.SET_VACCINE_TEST_REPORT_PAGE_SIZE:\r\n return {\r\n ...state,\r\n testsTable: {\r\n ...state.testsTable,\r\n pageIndex: action.payload.pageIndex,\r\n pageSize: action.payload.pageSize\r\n }\r\n }\r\n\r\n case types.SET_VACCINE_TEST_REPORT_SORTING:\r\n return {\r\n ...state,\r\n testsTable: {\r\n ...state.testsTable,\r\n sorting: [{\r\n id: action.payload.columnId,\r\n desc: action.payload.desc\r\n }]\r\n }\r\n }\r\n\r\n case types.SET_VACCINE_TEST_REPORT_FILTERING:\r\n return {\r\n ...state,\r\n testsTable: {\r\n ...state.testsTable,\r\n filtering: action.payload.filterArray\r\n }\r\n }\r\n\r\n case types.SET_VACCINE_TEST_REPORT_RECENT:\r\n return {\r\n ...state,\r\n testsTable: {\r\n ...state.testsTable,\r\n recentOnly: action.payload.recent\r\n }\r\n }\r\n\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst tableSettingsReducers = combineReducers({\r\n vaccineReportsTables: vaccineReportsTableSettingsReducer\r\n});\r\n\r\nexport default tableSettingsReducers;","import types from './types';\r\n\r\n// =======================================================================================\r\n// Vaccines Reports Tables\r\n// =======================================================================================\r\n// Events table\r\nconst setVaccEventReportTableIndex = (table, pageIndex) => ({\r\n type: types.SET_VACCINE_EVENT_REPORT_TABLE_PAGE_INDEX,\r\n payload: {table, pageIndex}\r\n});\r\n\r\nconst setVaccEventReportTablePageSize = (table, pageIndex, pageSize) => ({\r\n type: types.SET_VACCINE_EVENT_REPORT_PAGE_SIZE,\r\n payload: {table, pageIndex, pageSize}\r\n});\r\n\r\nconst setVaccEventReportTableSorting = (table, columnId, desc) => ({\r\n type: types.SET_VACCINE_EVENT_REPORT_SORTING,\r\n payload: {table, columnId, desc}\r\n});\r\n\r\nconst setVaccEventReportTableFiltering = (table, filterArray) => ({\r\n type: types.SET_VACCINE_EVENT_REPORT_FILTERING,\r\n payload: {table, filterArray}\r\n});\r\n\r\nconst setVaccEventReportRecent = (recent) => ({\r\n type: types.SET_VACCINE_EVENT_REPORT_RECENT,\r\n payload: {recent}\r\n});\r\n// Tests Table\r\nconst setVaccTestReportTableIndex = (table, pageIndex) => ({\r\n type: types.SET_VACCINE_TEST_REPORT_TABLE_PAGE_INDEX,\r\n payload: {table, pageIndex}\r\n});\r\n\r\nconst setVaccTestReportTablePageSize = (table, pageIndex, pageSize) => ({\r\n type: types.SET_VACCINE_TEST_REPORT_PAGE_SIZE,\r\n payload: {table, pageIndex, pageSize}\r\n});\r\n\r\nconst setVaccTestReportTableSorting = (table, columnId, desc) => ({\r\n type: types.SET_VACCINE_TEST_REPORT_SORTING,\r\n payload: {table, columnId, desc}\r\n});\r\n\r\nconst setVaccTestReportTableFiltering = (table, filterArray) => ({\r\n type: types.SET_VACCINE_TEST_REPORT_FILTERING,\r\n payload: {table, filterArray}\r\n});\r\n\r\nconst setVaccTestReportRecent = (recent) => ({\r\n type: types.SET_VACCINE_TEST_REPORT_RECENT,\r\n payload: {recent}\r\n});\r\n\r\nexport default {\r\n // Vaccines Reports Tables\r\n setVaccEventReportTableIndex,\r\n setVaccEventReportTablePageSize,\r\n setVaccEventReportTableSorting,\r\n setVaccEventReportTableFiltering,\r\n setVaccEventReportRecent,\r\n setVaccTestReportTableIndex,\r\n setVaccTestReportTablePageSize,\r\n setVaccTestReportTableSorting,\r\n setVaccTestReportTableFiltering,\r\n setVaccTestReportRecent\r\n};","import actions from './actions';\r\n\r\n// We could just call these table dispatches directly, but I think this is technically best practice\r\n// =======================================================================================\r\n// Vaccines Reports Tables\r\n// =======================================================================================\r\n// event table\r\nconst updateVaccEventReportTablePageIndex = (table, pageIndex) => (dispatch) => {\r\n dispatch(actions.setVaccEventReportTableIndex(table, pageIndex));\r\n}\r\n\r\nconst updateVaccEventReportTablePageSize = (table, pageIndex, pageSize) => (dispatch) => {\r\n dispatch(actions.setVaccEventReportTablePageSize(table, pageIndex, pageSize));\r\n}\r\n\r\nconst updateVaccEventReportTableTableSorting = (table, columnId, desc) => (dispatch) => {\r\n dispatch(actions.setVaccEventReportTableSorting(table, columnId, desc));\r\n}\r\n\r\nconst updateVaccEventReportTableTableFiltering = (table, filterArray) => (dispatch) => {\r\n dispatch(actions.setVaccEventReportTableFiltering(table, filterArray));\r\n}\r\n\r\nconst updateVaccEventReportTableTableRecent = (recent) => (dispatch) => {\r\n dispatch(actions.setVaccEventReportRecent(recent));\r\n}\r\n// test table\r\nconst updateVaccTestReportTablePageIndex = (table, pageIndex) => (dispatch) => {\r\n dispatch(actions.setVaccTestReportTableIndex(table, pageIndex));\r\n}\r\n\r\nconst updateVaccTestReportTablePageSize = (table, pageIndex, pageSize) => (dispatch) => {\r\n dispatch(actions.setVaccTestReportTablePageSize(table, pageIndex, pageSize));\r\n}\r\n\r\nconst updateVaccTestReportTableTableSorting = (table, columnId, desc) => (dispatch) => {\r\n dispatch(actions.setVaccTestReportTableSorting(table, columnId, desc));\r\n}\r\n\r\nconst updateVaccTestReportTableTableFiltering = (table, filterArray) => (dispatch) => {\r\n dispatch(actions.setVaccTestReportTableFiltering(table, filterArray));\r\n}\r\n\r\nconst updateVaccTestReportTableTableRecent = (recent) => (dispatch) => {\r\n dispatch(actions.setVaccTestReportRecent(recent));\r\n}\r\n\r\nexport default {\r\n // Vaccines Reports Tables\r\n updateVaccEventReportTablePageIndex,\r\n updateVaccEventReportTablePageSize,\r\n updateVaccEventReportTableTableSorting,\r\n updateVaccEventReportTableTableFiltering,\r\n updateVaccEventReportTableTableRecent,\r\n updateVaccTestReportTablePageIndex,\r\n updateVaccTestReportTablePageSize,\r\n updateVaccTestReportTableTableSorting,\r\n updateVaccTestReportTableTableFiltering,\r\n updateVaccTestReportTableTableRecent\r\n};","import tableSettingsReducers from './reducers';\r\n\r\nexport {default as tableOperations} from './operations';\r\nexport {default as tableTypes} from './types';\r\n\r\nexport default tableSettingsReducers;","// Step 3\r\nconst selectionFrequenciesList = [\r\n {value: 2, label: 'Semi-annually (twice a year)'},\r\n {value: 4, label: 'Quarterly (4x per year)'},\r\n {value: 6, label: 'Bi-monthly (6x per year)'},\r\n {value: 12, label: 'Monthly (12x per year)'}\r\n]\r\n\r\nexport default {\r\n selectionFrequenciesList\r\n}","import React from 'react';\r\nimport stringUtils from '../../../../utils/stringUtils';\r\n\r\nconst SocialSecurityNumberDisplayComponent = ({ssn, redact, isHidden}) => {\r\n if (!ssn) {\r\n return null;\r\n }\r\n\r\n const ssnString = stringUtils.formatSSNOverride(ssn, redact, isHidden);\r\n return
{ssnString}
;\r\n};\r\n\r\nexport default SocialSecurityNumberDisplayComponent;","import types from './types';\r\n\r\nconst setSSNMask = selection => ({\r\n type: types.SET_SSNMASK,\r\n payload: selection\r\n})\r\n\r\nconst setSidebar = options => ({\r\n type: types.SET_SIDEBAR,\r\n payload: options\r\n});\r\n\r\n/**\r\n * Action to show the Loading Panel and increase the instance count by 1\r\n * @returns {{type: string, payload: number}}\r\n */\r\nconst showLoadingPanel = () => ({\r\n type: types.LAYOUT_SHOW_LOADING_PANEL,\r\n payload: 1\r\n});\r\n\r\n/**\r\n * Action to hide the Loading Panel and decrease the instance count by 1\r\n * @returns {{type: string, payload: number}}\r\n */\r\nconst hideLoadingPanel = () => ({\r\n type: types.LAYOUT_HIDE_LOADING_PANEL,\r\n payload: -1\r\n});\r\n\r\nconst resetLoadingPanel = () => ({\r\n type: types.LAYOUT_RESET_LOADING_PANEL,\r\n payload: 0\r\n});\r\n\r\nconst addUserOption = (pathname, id, option) => ({\r\n type: types.USER_OPTIONS_ADD,\r\n payload: {pathname, id, option}\r\n});\r\n\r\nconst clearUserOptions = () => ({\r\n type: types.USER_OPTIONS_CLEAR,\r\n payload: {}\r\n});\r\n\r\nconst setBroadcast = broadcastItems => ({\r\n type: types.SET_BROADCAST,\r\n payload: broadcastItems\r\n});\r\n\r\nexport default {\r\n setSidebar,\r\n showLoadingPanel,\r\n hideLoadingPanel,\r\n resetLoadingPanel,\r\n addUserOption,\r\n clearUserOptions,\r\n setSSNMask,\r\n setBroadcast\r\n};","import axios from 'axios';\r\nimport actions from './actions';\r\n\r\nconst setSidebar = actions.setSidebar;\r\n\r\nconst showLoadingPanel = actions.showLoadingPanel;\r\n\r\nconst hideLoadingPanel = actions.hideLoadingPanel;\r\n\r\nconst resetLoadingPanel = actions.resetLoadingPanel;\r\n\r\nconst addUserOption = actions.addUserOption;\r\n\r\nconst clearUserOptions = actions.clearUserOptions;\r\n\r\nconst setSSNMask = actions.setSSNMask;\r\n\r\nconst loadBroadcastItems = () => dispatch => {\r\n axios.get('/v1/settings/texts?collection=Broadcast')\r\n .then(res => {\r\n dispatch(actions.setBroadcast(res.data.map(standardText => standardText.text)));\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n dispatch(actions.setBroadcast([]));\r\n });\r\n};\r\n\r\nexport default {\r\n setSidebar,\r\n showLoadingPanel,\r\n hideLoadingPanel,\r\n resetLoadingPanel,\r\n addUserOption,\r\n clearUserOptions,\r\n setSSNMask,\r\n loadBroadcastItems\r\n};","import types from './types';\r\nimport {combineReducers} from 'redux';\r\n\r\nconst sidebarInitialState = {isOpen: true};\r\n\r\nconst ssnMaskInitialState = {isMasked: true};\r\n\r\nconst ssnMaskReducer = (state = ssnMaskInitialState, action) => {\r\n switch (action.type) {\r\n case types.SET_SSNMASK:\r\n return {\r\n ...state,\r\n isMasked: action.payload\r\n };\r\n default:\r\n return state;\r\n }\r\n}\r\n\r\nconst sidebarReducer = (state = sidebarInitialState, action) => {\r\n switch (action.type) {\r\n case types.SET_SIDEBAR:\r\n return {\r\n ...state,\r\n ...action.payload\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst loadingPanelInitialState = {\r\n instances: 0\r\n};\r\n\r\nconst loadingPanelReducer = (state = loadingPanelInitialState, action) => {\r\n switch (action.type) {\r\n case types.LAYOUT_SHOW_LOADING_PANEL:\r\n return {\r\n ...state,\r\n instances: state.instances + action.payload\r\n };\r\n case types.LAYOUT_HIDE_LOADING_PANEL:\r\n return {\r\n ...state,\r\n instances: Math.max(0, state.instances + action.payload)\r\n };\r\n case types.LAYOUT_RESET_LOADING_PANEL:\r\n return {\r\n ...state,\r\n instances: action.payload\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst currentUserOptionsReducer = (state = {}, action) => {\r\n switch (action.type) {\r\n case types.USER_OPTIONS_ADD:\r\n const currentOptions = {...state};\r\n if (!currentOptions[action.payload.pathname]) {\r\n currentOptions[action.payload.pathname] = {};\r\n }\r\n currentOptions[action.payload.pathname][action.payload.id] = action.payload.option;\r\n return {\r\n ...currentOptions\r\n };\r\n case types.USER_OPTIONS_CLEAR:\r\n return action.payload;\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\n\r\nconst broadcastReducer = (state = {}, action) => {\r\n switch (action.type) {\r\n case types.SET_BROADCAST:\r\n return action.payload;\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst layoutReducers = combineReducers({\r\n sidebar: sidebarReducer,\r\n loadingPanel: loadingPanelReducer,\r\n currentUserOptions: currentUserOptionsReducer,\r\n ssnMask: ssnMaskReducer,\r\n broadcast: broadcastReducer\r\n});\r\n\r\nexport default layoutReducers;","import reducer from './reducers';\r\n\r\nexport {default as layoutOperations} from './operations';\r\nexport {default as layoutTypes} from './types';\r\n\r\nexport default reducer;","import React from 'react';\r\nimport ReactTable from \"react-table\";\r\nimport PageMessage from '../../PageMessage/pageMessageComponent';\r\nimport CBReactTablePagination from '../../CBReactTablePagination/CBReactTablePagination';\r\nimport moment from 'moment';\r\n\r\nconst documentListPaneComponent = props => {\r\n\r\n let tableColumns = [\r\n {\r\n id: 'colItem',\r\n Header: 'Document',\r\n accessor: 'item',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n Header: 'Date',\r\n accessor: 'docDate',\r\n id: 'colDocDate',\r\n headerClassName: 'text-left',\r\n sortable: true,\r\n Cell: ({value}) => value ? moment.utc(value).format('M/D/YYYY') : ''\r\n },\r\n {\r\n Header: 'Expires',\r\n accessor: 'expireDate',\r\n id: 'colExpireDate',\r\n headerClassName: 'text-left',\r\n sortable: true,\r\n Cell: ({value}) => value ? moment.utc(value).format('M/D/YYYY') : ''\r\n },\r\n {\r\n id: 'colUploader',\r\n Header: 'Uploaded By',\r\n accessor: 'uploader',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colDateUploaded',\r\n Header: 'Received',\r\n accessor: 'uploadDate',\r\n sortable: true,\r\n Cell: ({value}) => value ? moment.utc(value).format('M/D/YYYY') : '',\r\n headerClassName: 'text-left'\r\n }\r\n ];\r\n\r\n\r\n if (props.employeeInfo) {\r\n tableColumns = [{\r\n id: 'colReportTitle',\r\n Header: (
{`CME Documents for ${props.employeeInfo.firstName} ${props.employeeInfo.lastName}`}),\r\n columns: tableColumns\r\n }];\r\n }\r\n\r\n const maxRows = 5;\r\n const dataLength = props.data ? props.data.length : 0;\r\n let defaultPageSize = dataLength <= maxRows ? dataLength : maxRows;\r\n if (defaultPageSize === 0) {\r\n defaultPageSize = 3;\r\n }\r\n\r\n return (\r\n
\r\n }\r\n showPagination={dataLength > defaultPageSize}\r\n PaginationComponent={CBReactTablePagination}\r\n getTrProps={\r\n (state, rowInfo, column) => {\r\n if (!rowInfo) return {};\r\n if (!rowInfo.original) return {};\r\n return {\r\n className: rowInfo.original.selected ? 'selected' : ''\r\n }\r\n }\r\n }\r\n getTdProps={(state, rowInfo, column, instance) => {\r\n return {\r\n onClick: (e, handleOriginal) => {\r\n if (!rowInfo) return;\r\n if (!rowInfo.original) return;\r\n if (column.cellClassName && column.cellClassName.includes('prevent-click')) {\r\n return;\r\n }\r\n if (props.clickRowHandler) {\r\n props.clickRowHandler(rowInfo.original);\r\n }\r\n if (handleOriginal) {\r\n handleOriginal();\r\n }\r\n }\r\n };\r\n }}\r\n />\r\n );\r\n};\r\n\r\nexport default documentListPaneComponent;","import types from './types';\r\n\r\nconst initialState = [];\r\n\r\nconst alertsReducer = (state = initialState, action) => {\r\n switch (action.type) {\r\n case types.ADD_ALERT:\r\n return [\r\n ...state,\r\n {\r\n text: action.payload.text,\r\n style: action.payload.style,\r\n id: action.payload.id\r\n }\r\n ];\r\n\r\n case types.REMOVE_ALERT:\r\n return state.filter(a => a.id !== action.payload.id);\r\n\r\n case types.CLEAR_ALERTS:\r\n return [];\r\n\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nexport default alertsReducer;","import reducer from './reducers';\r\n\r\nexport {default as alertsOperations} from \"./operations\";\r\nexport {default as alertsTypes} from \"./types\";\r\n\r\nexport default reducer;","import types from './types';\r\n\r\nconst setRosterView = (rosterView, auditId) => ({\r\n type: types.DQF_SET_ROSTER_VIEW,\r\n payload: {rosterView, auditId}\r\n});\r\n\r\nconst setRandomsRosterView = rosterView => ({\r\n type: types.DQF_SET_RANDOMS_ROSTER_VIEW,\r\n payload: { rosterView }\r\n});\r\n\r\nconst setRandomsPoolRosterView = rosterView => ({\r\n type: types.DQF_SET_RANDOMS_POOL_ROSTER_VIEW,\r\n payload: { rosterView }\r\n});\r\n\r\nconst setSortedFilteredRoster = roster => ({\r\n type: types.DQF_SET_SORTED_FILTERED_ROSTER,\r\n payload: roster\r\n});\r\n\r\nconst setRosterSelectedLocation = location => ({\r\n type: types.DQF_SET_ROSTER_SELECTED_LOCATION,\r\n payload: location\r\n});\r\n\r\nconst setFilteredExcelData = excelData => ({\r\n type: types.DQF_SET_FILTERED_EXCEL_DATA,\r\n payload: excelData\r\n});\r\n\r\nconst searchResults = (query, results, redirectTo) => ({\r\n type: types.DQF_SEARCH_EMPLOYEES,\r\n payload: {\r\n query,\r\n results,\r\n redirectTo\r\n }\r\n});\r\n\r\n/**\r\n * Set the notifications list in redux\r\n * @param notificationsData - (array) notifications\r\n * @returns {{type: string, payload: *}}\r\n */\r\nconst setNotificationsList = notificationsData => ({\r\n type: types.DQF_NOTIFICATIONS_SET_LIST,\r\n payload: notificationsData\r\n});\r\n\r\n/**\r\n * SEt the flag indicating whether notifications are loading\r\n * @param loading\r\n * @returns {{payload: *, type: string}}\r\n */\r\nconst setNotificationsLoading = loading => ({\r\n type: types.DQF_NOTIFICATIONS_SET_LOADING,\r\n payload: loading\r\n});\r\n\r\n/**\r\n * Set the pending changes in redux to be processed on save\r\n * @param changeLog - (object) list of pending changes: {contactId: notificationType: notificationValue, etc...}\r\n * @returns {{type: string, payload: {pendingChanges: *}}}\r\n */\r\nconst notificationsChanged = changeLog => ({\r\n type: types.DQF_NOTIFICATIONS_CHANGED,\r\n payload: {pendingChanges: changeLog}\r\n});\r\n\r\n/**\r\n * Set whether the notifications manager should be in edit mode\r\n * @param isEditing - (bool)\r\n * @param fromCancel - (bool) edit mode to view mode caused by a Cancel operation (from the caller)\r\n * @returns {{type: string, payload: {isEditing: *, canceled: boolean}}}\r\n */\r\nconst setNotificationsEditing = (isEditing, fromCancel) => ({\r\n type: types.DQF_NOTIFICATIONS_SET_EDITING,\r\n payload: {isEditing, canceled: fromCancel ? fromCancel : false}\r\n});\r\n\r\n/**\r\n * Filter the notifications list by filter / query string\r\n * @param filterBy - (string) query string\r\n * @returns {{type: string, payload: {filterBy: *}}}\r\n */\r\nconst setNotificationsFilterBy = filterBy => ({\r\n type: types.DQF_NOTIFICATIONS_SET_FILTER_BY,\r\n payload: {filterBy}\r\n});\r\n\r\n/**\r\n * Update the notifications list with the processed / saved notifications changes\r\n * @param changeLog - (object) list of changes: {contactId: notificationType: notificationValue, etc...}\r\n * @returns {{type: string, payload: *}}\r\n */\r\nconst applyChanges = changeLog => ({\r\n type: types.DQF_NOTIFICATIONS_APPLY_CHANGES,\r\n payload: changeLog\r\n});\r\n\r\nconst setSitesSelected = (selectedSites = [], displaySite = {}) => {\r\n return ({\r\n type: types.DQF_SITES_SET_SELECTED,\r\n payload: {selectedSites, displaySite}\r\n })\r\n};\r\n\r\nconst setSiteTree = siteTree => {\r\n return ({\r\n type: types.DQF_SITES_SET_SITE_TREE,\r\n payload: siteTree\r\n })\r\n};\r\n\r\nconst setSelectedHierarchySites = sites => ({\r\n type: types.DQF_SET_SELECTED_HIERARCHY_SITES,\r\n payload: sites\r\n});\r\n\r\n/**\r\n * Update the Session Client in dqf.sites\r\n * @param sessionClient\r\n * @returns {{type: string, payload: *}}\r\n */\r\nconst setSessionClient = sessionClient => ({\r\n type: types.DQF_SITES_SET_SESSION_CLIENT,\r\n payload: sessionClient\r\n});\r\n\r\nconst setDisplayIncludeChildren = displayIncludeChildren => ({\r\n type: types.DQF_SET_DISPLAY_INCLUDE_CHILDREN,\r\n payload: displayIncludeChildren\r\n});\r\n\r\nconst setAutoSelectSite = site => ({\r\n type: types.DQF_SET_AUTO_SELECT_SITE,\r\n payload: site\r\n});\r\n\r\nconst setSitesSelectorEnabled = enabled => ({\r\n type: types.DQF_SET_SITES_SELECTOR_ENABLED,\r\n payload: enabled\r\n});\r\n\r\nconst setAlertCounts = alertCounts => ({\r\n type: types.DQF_SET_ALERT_COUNTS,\r\n payload: alertCounts\r\n});\r\n\r\nconst setAlertsValues = alertsValues => ({\r\n type: types.DQF_SET_ALERTS_VALUES,\r\n payload: alertsValues\r\n});\r\n\r\nconst setDocumentTabsSingleOrMulti = documentTabsSingleOrMulti => ({\r\n type: types.DQF_SET_DOCUMENT_TABS_SINGLE_OR_MULTI,\r\n payload: documentTabsSingleOrMulti\r\n});\r\n\r\nconst setUnscoredMVRs = items => ({\r\n type: types.DQF_SET_UNSCORED_MVRS,\r\n payload: items\r\n});\r\n\r\nexport default {\r\n setRosterView,\r\n setRandomsRosterView,\r\n setRandomsPoolRosterView,\r\n setSortedFilteredRoster,\r\n setRosterSelectedLocation,\r\n searchResults,\r\n setNotificationsLoading,\r\n setNotificationsList,\r\n notificationsChanged,\r\n setNotificationsEditing,\r\n setNotificationsFilterBy,\r\n applyChanges,\r\n setSitesSelected,\r\n setSiteTree,\r\n setSelectedHierarchySites,\r\n setSessionClient,\r\n setDisplayIncludeChildren,\r\n setAutoSelectSite,\r\n setSitesSelectorEnabled,\r\n setAlertCounts,\r\n setFilteredExcelData,\r\n setAlertsValues,\r\n setDocumentTabsSingleOrMulti,\r\n setUnscoredMVRs\r\n}","import axios from 'axios';\r\n\r\nimport actions from './actions';\r\nimport {layoutOperations} from \"../layout\";\r\nimport { defaultEmployeeRosterState } from './reducers';\r\nimport idConstants from '../../config/idConstants';\r\n\r\nconst setRosterView = actions.setRosterView;\r\nconst setRandomsRosterView = actions.setRandomsRosterView;\r\nconst setRandomsPoolRosterView = actions.setRandomsPoolRosterView;\r\nconst setRosterSelectedLocation = actions.setRosterSelectedLocation;\r\nconst setSortedFilteredRoster = actions.setSortedFilteredRoster;\r\nconst setFilteredExcelData = actions.setFilteredExcelData;\r\n\r\nconst resetRosterViews = () => dispatch => {\r\n dispatch(setRosterView(defaultEmployeeRosterState.rosterView));\r\n dispatch(setRandomsRosterView(defaultEmployeeRosterState.randomsRosterView));\r\n dispatch(setRandomsPoolRosterView(defaultEmployeeRosterState.randomsPoolRosterView));\r\n};\r\n\r\nconst _getCSADetailValue = (basics, current) => {\r\n let display = 'ALL';\r\n current.types.forEach((type) => {\r\n if (!Object.values(type).every((value) => value)) {\r\n display = 'SOME'\r\n }\r\n });\r\n return display;\r\n};\r\n\r\nconst _combineContactAndCSANotificationsList = notificationsData => {\r\n let contactNotifications = notificationsData ? notificationsData.contacts || [] : [];\r\n const csaNotificationsList = notificationsData ? notificationsData.csaNotifications || [] : [];\r\n const basics = notificationsData ? notificationsData.basics || [] : [];\r\n const notificationTypes = idConstants.notificationTypes;\r\n\r\n const csaResultArray = csaNotificationsList.reduce((accumulator, record) => {\r\n const contactMatch = accumulator.filter((contact) => contact.email === record.email && contact.clientId === record.clientId);\r\n let contact;\r\n if (contactMatch === null || contactMatch.length === 0) {\r\n const typesArray = notificationTypes.map((type) => {\r\n const notificationTypeData = {typeName: type.name, typeId: type.typeId};\r\n basics.forEach((basic) => {\r\n notificationTypeData[basic.BasName] = false\r\n });\r\n return notificationTypeData\r\n });\r\n accumulator.push({\r\n email: record.email,\r\n clientId: record.clientId,\r\n clientName: record.clientName,\r\n UID: record.UID,\r\n types: typesArray\r\n });\r\n contact = accumulator[accumulator.length - 1];\r\n } else {\r\n contact = contactMatch[0];\r\n }\r\n const index = contact.types.findIndex((type) => type.typeId === record.notifyTypeId);\r\n if (index !== -1) {\r\n contact.types[index][record.basicName] = true; //flip the flag for this type of notification\r\n }\r\n if (!contact.csaDetail && (record.notifyTypeId === 2 ||\r\n record.notifyTypeId === 3 ||\r\n record.notifyTypeId === 4)) {\r\n contact.csaDetail = true;\r\n } else if (!contact.csaScores && record.notifyTypeId === 5) {\r\n contact.csaScores = true;\r\n }\r\n return accumulator;\r\n }, []);\r\n\r\n csaResultArray.forEach((csaContact) => {\r\n const index = contactNotifications.findIndex(contact => contact.clientId === csaContact.clientId && contact.email === csaContact.email);\r\n if (csaContact.csaDetail) {//there are some csa detail subscriptions so determine if we have them all.\r\n csaContact.csaDetail = _getCSADetailValue(basics, csaContact);\r\n }\r\n if (index !== -1) {//there is a matching contact notification, so we will append the csa notification data to that one\r\n contactNotifications[index].types = csaContact.types;\r\n contactNotifications[index].csaDetail = csaContact.csaDetail || null;\r\n contactNotifications[index].csaScores = csaContact.csaScores || null;\r\n } else {\r\n contactNotifications.push(csaContact); //there is no matching contact notification, so just add this to the end\r\n }\r\n });\r\n\r\n return contactNotifications;\r\n};\r\n\r\n\r\n/**\r\n * Make axios call with provided query\r\n * @param query - query\r\n * @param siteList - list of user sites\r\n * @param showLoadingPanel (bool) - show loading panel (defaulted to true)\r\n * @returns {Function} - dispatches searchResults action with query, results, and redirect link\r\n */\r\nconst searchEmployees = (query, siteList, isConcordeUser, showLoadingPanel = true) => dispatch => {\r\n if (showLoadingPanel) {\r\n dispatch(layoutOperations.showLoadingPanel());\r\n }\r\n axios\r\n .get(`/v1/employees?search=${query}&sites=${siteList}&isConcordeUser=${isConcordeUser}`)\r\n .then(res => {\r\n if (showLoadingPanel) {\r\n dispatch(layoutOperations.hideLoadingPanel());\r\n }\r\n const results = res.data;\r\n let redirectTo = '/manage/employeesearch';\r\n if (results.length === 1 && (!isConcordeUser || (isConcordeUser && results[0].importedClient))) {\r\n redirectTo = `/manage/employees/${results[0].employeeId}`;\r\n }\r\n dispatch(actions.searchResults(query, results, redirectTo));\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n if (showLoadingPanel) {\r\n dispatch(layoutOperations.hideLoadingPanel());\r\n }\r\n })\r\n};\r\n\r\nconst notificationsChanged = actions.notificationsChanged;\r\n\r\nconst setNotificationsEditing = actions.setNotificationsEditing;\r\n\r\nconst setNotificationsFilterBy = actions.setNotificationsFilterBy;\r\n\r\nconst setNotificationsList = notificationsData => dispatch => {\r\n dispatch(actions.setNotificationsList(_combineContactAndCSANotificationsList(notificationsData)));\r\n};\r\n\r\n/***\r\n * Get notifications data from list of user Sites\r\n * @param sites - (array) list of user sites\r\n * @returns {Function}\r\n */\r\nconst getNotificationsData = sites => dispatch => {\r\n dispatch(layoutOperations.showLoadingPanel());\r\n dispatch(actions.setNotificationsLoading(true));\r\n axios.get(`/v1/clients?notificationsFor=${sites.map(site => site.legacyClientId).join(',')}`)\r\n .then(response => {\r\n if (response.status === 200) {\r\n const notificationsData = response.data;\r\n //format different types of notifications into one list\r\n dispatch(actions.setNotificationsList(_combineContactAndCSANotificationsList(notificationsData)));\r\n dispatch(actions.setNotificationsLoading(false));\r\n dispatch(layoutOperations.hideLoadingPanel());\r\n }\r\n })\r\n .catch(err => {\r\n dispatch(actions.setNotificationsLoading(false));\r\n dispatch(layoutOperations.hideLoadingPanel());\r\n console.error('failed to load contact information');\r\n });\r\n};\r\n\r\n/**\r\n * Get notifications data from an email address\r\n * @param email - (string) notification email address\r\n * @returns {Function}\r\n */\r\nconst getNotificationsDataForUser = email => dispatch => {\r\n axios.get(`/v1/clients/0/notifications/${email}`)\r\n .then(response => {\r\n const notificationsData = response.data;\r\n dispatch(actions.setNotificationsList(_combineContactAndCSANotificationsList(notificationsData)))\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n};\r\n\r\n/**\r\n * Save (patch) 1-n notification changes in SQL\r\n * @param changeLog - (object) list of changes to processes: {contactId: notificationType: notificationValue, etc...}\r\n * @returns {Function}\r\n */\r\nconst saveNotifications = (changeLog, userId) => dispatch => {\r\n dispatch(layoutOperations.showLoadingPanel());\r\n axios\r\n .patch(`/v1/clients/0/notifications?forUser=${userId}`, changeLog)\r\n .then(() => {\r\n dispatch(actions.applyChanges(changeLog));\r\n dispatch(actions.notificationsChanged({}));\r\n dispatch(actions.setNotificationsEditing(false));\r\n dispatch(layoutOperations.hideLoadingPanel());\r\n })\r\n .catch(err => {\r\n dispatch(layoutOperations.hideLoadingPanel());\r\n console.error(err);\r\n });\r\n};\r\n\r\n\r\n// sites\r\n\r\nconst setSiteTree = actions.setSiteTree;\r\n\r\nconst setSessionClient = actions.setSessionClient;\r\n\r\nconst setDisplayIncludeChildren = actions.setDisplayIncludeChildren;\r\n\r\nconst setSelectedSites = actions.setSitesSelected;\r\n\r\nconst setSelectedHierarchySites = actions.setSelectedHierarchySites;\r\n\r\nconst setAutoSelectSite = actions.setAutoSelectSite;\r\n\r\nconst setSitesSelectorEnabled = actions.setSitesSelectorEnabled;\r\n\r\nconst setAlertCounts = actions.setAlertCounts;\r\n\r\nconst setAlertsValues = actions.setAlertsValues;\r\n\r\nconst setDocumentTabsSingleOrMulti = actions.setDocumentTabsSingleOrMulti;\r\n\r\nconst getUnscoredMVRs = () => async dispatch => {\r\n try {\r\n const res = await axios.get('/v1/mvrscoring/unscored')\r\n dispatch(actions.setUnscoredMVRs(res.data));\r\n } catch (err) {\r\n console.error(err);\r\n }\r\n};\r\n\r\nexport default {\r\n setRosterView,\r\n setRandomsRosterView,\r\n setRandomsPoolRosterView,\r\n resetRosterViews,\r\n setRosterSelectedLocation,\r\n setSortedFilteredRoster,\r\n searchEmployees,\r\n notificationsChanged,\r\n setNotificationsEditing,\r\n getNotificationsData,\r\n getNotificationsDataForUser,\r\n setNotificationsList,\r\n saveNotifications,\r\n setNotificationsFilterBy,\r\n setSelectedSites,\r\n setSiteTree,\r\n setSessionClient,\r\n setDisplayIncludeChildren,\r\n setSelectedHierarchySites,\r\n setAutoSelectSite,\r\n setSitesSelectorEnabled,\r\n setAlertCounts,\r\n setFilteredExcelData,\r\n setAlertsValues,\r\n setDocumentTabsSingleOrMulti,\r\n getUnscoredMVRs\r\n}","import reducer from './reducers';\r\n\r\nexport { default as dqfOperations } from \"./operations\";\r\nexport { default as dqfTypes } from \"./types\";\r\n\r\nexport default reducer;","import React from 'react'\r\nimport {NavLink} from 'react-router-dom';\r\n\r\nconst footerComponent = props => {\r\n const {apiVersion} = props;\r\n return (\r\n \r\n )\r\n};\r\n\r\nexport default footerComponent;","const SHOW_MODAL = 'modal/SHOW_MODAL';\r\nconst HIDE_MODAL = 'modal/HIDE_MODAL';\r\n\r\nexport default {\r\n SHOW_MODAL,\r\n HIDE_MODAL\r\n};","import types from './types';\r\n\r\nconst initialState = {\r\n displayModal: null, //indicates which modal to display. as a string\r\n info: null, //the data that is required by the specified modal\r\n refreshData: false, //a flag to indicate if data may need to be refreshed on the original page\r\n dialogAccepted: false //a flag to indicate if the user clicked on the accept button\r\n};\r\n\r\nconst modalReducer = (state = initialState, action) => {\r\n let displayModal, info, refreshData, responseInfo;\r\n switch (action.type) {\r\n case types.SHOW_MODAL:\r\n displayModal = action.payload.displayModal;\r\n refreshData = false;\r\n info = action.payload.info;\r\n return {\r\n ...state,\r\n refreshData,\r\n displayModal,\r\n info\r\n };\r\n case types.HIDE_MODAL:\r\n displayModal = info = null;\r\n refreshData = action.payload.refreshData;\r\n responseInfo = action.payload.responseInfo;\r\n return {\r\n ...state,\r\n displayModal,\r\n info,\r\n refreshData,\r\n responseInfo\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nexport default modalReducer;","import types from './types';\r\n\r\nconst showModal = (displayModal, info) => ({\r\n type: types.SHOW_MODAL,\r\n payload: {\r\n displayModal,\r\n info\r\n }\r\n});\r\n\r\nconst hideModal = (refreshData, responseInfo) => ({\r\n type: types.HIDE_MODAL,\r\n payload: {\r\n refreshData,\r\n responseInfo\r\n }\r\n});\r\n\r\nexport default {\r\n showModal,\r\n hideModal\r\n}","import actions from './actions';\r\n\r\nconst showModal = (displayModal, info) => dispatch => {\r\n dispatch(actions.showModal(displayModal, info));\r\n};\r\n\r\nconst hideModal = (refreshData, responseInfo) => dispatch => {\r\n dispatch(actions.hideModal(refreshData, responseInfo));\r\n};\r\n\r\nexport default {\r\n showModal,\r\n hideModal\r\n}\r\n","import reducer from './reducers';\r\n\r\nexport { default as modalOperations } from \"./operations\";\r\nexport { default as modalTypes } from \"./types\";\r\n\r\nexport default reducer;","import packageJson from '../../package.json';\r\n\r\n// Setting a global variable `clientVersion` to the version number from package.json.\r\n// This makes the version number accessible globally in the application.\r\nglobal.clientVersion = packageJson.version;","const SET_SIDEBAR = 'SET_SIDEBAR';\r\n\r\nconst LAYOUT_SHOW_LOADING_PANEL = 'LAYOUT_SHOW_LOADING_PANEL';\r\nconst LAYOUT_HIDE_LOADING_PANEL = 'LAYOUT_HIDE_LOADING_PANEL';\r\nconst LAYOUT_RESET_LOADING_PANEL = 'LAYOUT_RESET_LOADING_PANEL';\r\n\r\nconst USER_OPTIONS_ADD = 'USER_OPTIONS_ADD';\r\nconst USER_OPTIONS_CLEAR = 'USER_OPTIONS_CLEAR';\r\nconst SET_SSNMASK = 'SET_SSNMASK';\r\n\r\nconst SET_BROADCAST = 'SET_BROADCAST';\r\n\r\n\r\nexport default {\r\n SET_SIDEBAR,\r\n LAYOUT_SHOW_LOADING_PANEL,\r\n LAYOUT_HIDE_LOADING_PANEL,\r\n LAYOUT_RESET_LOADING_PANEL,\r\n USER_OPTIONS_ADD,\r\n USER_OPTIONS_CLEAR,\r\n SET_SSNMASK,\r\n SET_BROADCAST\r\n};","import moment from 'moment';\r\n\r\nconst saveObjectToLocalStorage = (key, value) => {\r\n localStorage.setItem(key, JSON.stringify(value));\r\n};\r\n\r\nconst getObjectFromLocalStorage = key => {\r\n const value = localStorage.getItem(key);\r\n if (value) {\r\n return JSON.parse(value);\r\n } else\r\n return {};\r\n};\r\n\r\nconst setCookie = (key, value) => {\r\n document.cookie = `${key}=${value};path=/;expires=;`;\r\n};\r\n\r\nconst getCookie = key => {\r\n let decodedCookie = decodeURIComponent(document.cookie);\r\n const cookies = decodedCookie.split(';');\r\n for (let cookie of cookies) {\r\n const currentCookie = cookie.split('=');\r\n if (currentCookie[0].trim() === key) {\r\n return currentCookie[1];\r\n }\r\n }\r\n return null;\r\n};\r\n\r\nconst deleteCookie = key => {\r\n document.cookie = `${key}=;path=/;expires=${moment.utc(new Date()).format('ddd, DD-MMM-YYYY h:mm:ss a')};`;\r\n};\r\n\r\nexport {\r\n saveObjectToLocalStorage,\r\n getObjectFromLocalStorage,\r\n setCookie,\r\n getCookie,\r\n deleteCookie\r\n};","const hasPermission = (user, permissionToCheck) => {\r\n return user.permissions && user.permissions.includes(permissionToCheck);\r\n};\r\n\r\nconst hasAnyPermissions = (user, permissionGroupToCheck) => {\r\n if (!permissionGroupToCheck) return false;\r\n return Object.values(permissionGroupToCheck).some(permission => hasPermission(user, permission));\r\n};\r\n\r\nconst whichPermissions = (user, permissionGroupToCheck) => {\r\n if (!permissionGroupToCheck) return [];\r\n return Object.values(permissionGroupToCheck).filter(permission => hasPermission(user, permission));\r\n};\r\n\r\nexport {\r\n hasPermission,\r\n hasAnyPermissions,\r\n whichPermissions\r\n};","const allStepsDefaultState = {\r\n criticalErrorEncountered: false,\r\n currentStep: 0,\r\n haveFetchedDataForWizard: false, // whether we've fetched the data we need to complete the wizard\r\n okToProceedToNextStep: false,\r\n poolToEdit: null,\r\n showRandomsPoolWizard: false,\r\n steps: [\r\n {title: 'Location(s)', status: 'process'},\r\n {title: 'Filters', status: 'wait'},\r\n {title: '% ages and frequency', status: 'wait'},\r\n {title: 'YTD totals (optional)', status: 'wait'},\r\n {title: '# of Employees', status: 'wait'}\r\n ]\r\n}\r\n\r\nexport default allStepsDefaultState;","import _ from 'lodash';\r\n\r\nimport types from './types';\r\nimport allStepsDefaultState from './defaultState';\r\n\r\nconst randomsPoolCreationWizardAllStepsReducer = (state = allStepsDefaultState, action) => {\r\n let currentStep = state.currentStep;\r\n const stepsCopy = _.cloneDeep(state.steps);\r\n\r\n switch (action.type) {\r\n // =======================================================================================\r\n // Randoms Pool Creation Wizard - All Steps\r\n // =======================================================================================\r\n case types.INCREMENT_CURRENT_STEP_BY_1:\r\n // the status updates are needed for the rc-steps library to correctly show what step the user is on.\r\n stepsCopy[currentStep].status = 'finish';\r\n stepsCopy[currentStep + 1].status = 'process';\r\n return {\r\n ...state,\r\n currentStep: currentStep += 1,\r\n okToProceedToNextStep: false, // When users move on to the next step we'll need to re-check if they can proceed to the step after that\r\n steps: stepsCopy\r\n }\r\n\r\n case types.DECREMENT_CURRENT_STEP_BY_1:\r\n // the status updates are needed for the rc-steps library to correctly show what step the user is on.\r\n stepsCopy[currentStep].status = 'wait';\r\n stepsCopy[currentStep - 1].status = 'process';\r\n return {\r\n ...state,\r\n currentStep: currentStep -= 1,\r\n steps: stepsCopy\r\n }\r\n\r\n case types.RESET_ALL_STEPS_GLOBAL_STATE:\r\n return allStepsDefaultState;\r\n\r\n case types.SET_POOL_TO_EDIT:\r\n return {\r\n ...state,\r\n poolToEdit: action.payload,\r\n showRandomsPoolWizard: true\r\n }\r\n\r\n case types.SET_RANDOMS_POOL_WIZARD_CRITICAL_ERROR:\r\n return {\r\n ...state,\r\n criticalErrorEncountered: true\r\n }\r\n\r\n case types.SET_RANDOMS_POOL_WIZARD_HAVE_FETCHED_DATA:\r\n return {\r\n ...state,\r\n haveFetchedDataForWizard: true\r\n }\r\n\r\n case types.SET_RANDOMS_POOL_WIZARD_OK_TO_PROCEED:\r\n return {\r\n ...state,\r\n okToProceedToNextStep: action.payload\r\n }\r\n\r\n case types.SET_SHOW_RANDOMS_POOL_WIZARD:\r\n return {\r\n ...state,\r\n showRandomsPoolWizard: action.payload\r\n }\r\n\r\n default:\r\n return state;\r\n }\r\n}\r\n\r\nexport default randomsPoolCreationWizardAllStepsReducer;","const step1DefaultState = {\r\n dotListForDropdown: [],\r\n locationSearchQuery: '',\r\n selection: null,\r\n byDOTNumberSelectionValues: [],\r\n byLocationNameSelectionValues: []\r\n};\r\n\r\nexport default step1DefaultState;","import types from './types';\r\nimport step1DefaultState from './defaultState';\r\n\r\nconst randomsPoolCreationWizardStep1Reducer = (state = step1DefaultState, action) => {\r\n switch (action.type) {\r\n // =======================================================================================\r\n // Randoms Pool Creation Wizard - Step 1\r\n // =======================================================================================\r\n case types.RESET_STEP_1_GLOBAL_STATE: \r\n return step1DefaultState\r\n\r\n case types.SET_STEP1_BY_DOT_NUMBER_SELECTION_VALUES: \r\n return {\r\n ...state,\r\n byDOTNumberSelectionValues: action.payload,\r\n }\r\n\r\n case types.SET_STEP1_BY_LOCATION_NAME_SELECTION_VALUES: \r\n return {\r\n ...state,\r\n byLocationNameSelectionValues: action.payload,\r\n }\r\n\r\n case types.SET_STEP1_DOT_LIST_FOR_DROPDOWN: \r\n return {\r\n ...state,\r\n dotListForDropdown: action.payload,\r\n }\r\n\r\n case types.SET_STEP1_FOR_EDITING: \r\n return {\r\n ...state,\r\n ...action.payload\r\n }\r\n\r\n case types.SET_STEP1_LOCATION_SEARCH_QUERY: \r\n return {\r\n ...state,\r\n locationSearchQuery: action.payload\r\n }\r\n\r\n case types.SET_STEP1_SELECTION: \r\n return {\r\n ...state,\r\n selection: action.payload,\r\n // we always want to reset the properties below when the user chooses a new selection\r\n locationSearchQuery: '',\r\n byDOTNumberSelectionValues: [],\r\n byLocationNameSelectionValues: []\r\n }\r\n\r\n default:\r\n return state;\r\n }\r\n}\r\n\r\nexport default randomsPoolCreationWizardStep1Reducer;","const step2DefaultState = {\r\n byEmploymentStatus: false,\r\n byEmploymentStatusSelectionValues: [],\r\n byJobTitle: false,\r\n byJobTitleSelectionValues: [],\r\n bySafetyCode: false,\r\n bySafetyCodeSelectionValues: [],\r\n // there is no 'safetyCodeValuesForDropdown' property here. This is intentional. The safety code dropdown values come from from the 'safetyCodes.json' file.\r\n employmentStatusValuesForDropdown: [],\r\n jobTitleValuesForDropdown: []\r\n};\r\n\r\nexport default step2DefaultState;","import types from './types';\r\nimport step2DefaultState from './defaultState';\r\n\r\nconst randomsPoolCreationWizardStep2Reducer = (state = step2DefaultState, action) => {\r\n switch (action.type) {\r\n // =======================================================================================\r\n // Randoms Pool Creation Wizard - Step 2\r\n // =======================================================================================\r\n case types.RESET_STEP_2_GLOBAL_STATE: \r\n return step2DefaultState\r\n \r\n // By Employment Status\r\n case types.SET_STEP2_EMPLOYMENT_STATUS_CHECKBOX: \r\n return {\r\n ...state,\r\n byEmploymentStatus: action.payload,\r\n }\r\n\r\n case types.SET_STEP2_EMPLOYMENT_STATUS_VALUES_FOR_DROPDOWN: \r\n return {\r\n ...state,\r\n employmentStatusValuesForDropdown: action.payload\r\n }\r\n\r\n case types.SET_STEP2_BY_EMPLOYMENT_STATUS_SELECTION_VALUES: \r\n return {\r\n ...state,\r\n byEmploymentStatusSelectionValues: action.payload\r\n }\r\n\r\n case types.SET_STEP2_FOR_EDITING: \r\n return {\r\n ...state,\r\n ...action.payload\r\n }\r\n\r\n // By Job Titles\r\n case types.SET_STEP2_JOB_TITLE_CHECKBOX: \r\n return {\r\n ...state,\r\n byJobTitle: action.payload,\r\n }\r\n \r\n case types.SET_STEP2_BY_JOB_TITLE_SELECTION_VALUES: \r\n return {\r\n ...state,\r\n byJobTitleSelectionValues: action.payload\r\n }\r\n\r\n case types.SET_STEP2_JOB_TITLE_VALUES_FOR_DROPDOWN: \r\n return {\r\n ...state,\r\n jobTitleValuesForDropdown: action.payload\r\n }\r\n\r\n // By Safety Codes\r\n case types.SET_STEP2_SAFETY_CODE_CHECKBOX: \r\n return {\r\n ...state,\r\n bySafetyCode: action.payload,\r\n }\r\n\r\n case types.SET_STEP2_BY_SAFETY_CODE_SELECTION_VALUES: \r\n return {\r\n ...state,\r\n bySafetyCodeSelectionValues: action.payload\r\n }\r\n\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nexport default randomsPoolCreationWizardStep2Reducer;","import constants from '../helperFiles/constants';\r\n\r\nconst step3DefaultState = {\r\n existingPoolNames: null,\r\n testingAuthoritiesAndRates: {},\r\n testingAuthoritiesList: [],\r\n testingAuthoritySelected: '',\r\n percentageDrug: '',\r\n percentageAlcohol: '',\r\n poolNameAlreadyExists: false,\r\n selectionFrequenciesList: constants.selectionFrequenciesList,\r\n selectionFrequencySelected: {value: 4, label: 'Quarterly'},\r\n poolName: '',\r\n}\r\n\r\nexport default step3DefaultState;","import types from './types';\r\nimport step3DefaultState from './defaultState';\r\n\r\nconst randomsPoolCreationWizardStep2Reducer = (state = step3DefaultState, action) => {\r\n switch (action.type) {\r\n // =======================================================================================\r\n // Randoms Pool Creation Wizard - Step 3\r\n // =======================================================================================\r\n case types.RESET_STEP_3_GLOBAL_STATE: \r\n return step3DefaultState\r\n\r\n case types.SET_STEP3_DEFAULT_RANDOMS_TESTING_RATES: \r\n const {\r\n testingAuthoritiesAndRates,\r\n testingAuthoritiesList,\r\n testingAuthoritySelected,\r\n percentageDrug,\r\n percentageAlcohol,\r\n poolName\r\n } = action.payload;\r\n\r\n return {\r\n ...state,\r\n testingAuthoritiesAndRates,\r\n testingAuthoritiesList,\r\n testingAuthoritySelected,\r\n percentageDrug,\r\n percentageAlcohol,\r\n poolName\r\n }\r\n\r\n case types.SET_STEP3_EXISTING_POOL_NAMES: \r\n return {\r\n ...state,\r\n existingPoolNames: action.payload\r\n }\r\n\r\n case types.SET_STEP3_FOR_EDITING: \r\n return {\r\n ...state,\r\n ...action.payload\r\n }\r\n\r\n case types.SET_STEP3_FREQUENCY_SELECTION: \r\n return {\r\n ...state,\r\n selectionFrequencySelected: action.payload\r\n }\r\n\r\n case types.SET_STEP3_PERCENTAGE_ALCOHOL: \r\n return {\r\n ...state,\r\n percentageAlcohol: action.payload\r\n }\r\n\r\n case types.SET_STEP3_PERCENTAGE_DRUG: \r\n return {\r\n ...state,\r\n percentageDrug: action.payload\r\n }\r\n\r\n case types.SET_STEP3_POOL_NAME: \r\n return {\r\n ...state,\r\n poolName: action.payload\r\n }\r\n\r\n case types.SET_STEP3_POOL_NAME_ALREADY_EXISTS: \r\n return {\r\n ...state,\r\n poolNameAlreadyExists: action.payload\r\n }\r\n\r\n case types.SET_STEP3_TESTING_AUTHORITY_SELECTION: \r\n return {\r\n ...state,\r\n testingAuthoritySelected: action.payload,\r\n // the values below serve as both the default values and the minimum values for the drug % and alcohol % inputs\r\n percentageDrug: action.payload.drug,\r\n percentageAlcohol: action.payload.alcohol\r\n }\r\n\r\n default:\r\n return state;\r\n }\r\n}\r\n\r\nexport default randomsPoolCreationWizardStep2Reducer;\r\n","const step4DefaultState = {\r\n ytdAvgPoolRosterSize: 0,\r\n numberSelectedDrug: 0,\r\n numberTestedDrug: 0,\r\n numberSelectedAlcohol: 0,\r\n numberTestedAlcohol: 0\r\n}\r\n\r\nexport default step4DefaultState;","import types from './types';\r\nimport step4DefaultState from './defaultState';\r\n\r\nconst randomsPoolCreationWizardStep4Reducer = (state = step4DefaultState, action) => {\r\n switch (action.type) {\r\n case types.RESET_STEP_4_GLOBAL_STATE: \r\n return step4DefaultState;\r\n\r\n case types.SET_STEP4_AVG_POOL_ROSTER_SIZE: \r\n return {\r\n ...state,\r\n ytdAvgPoolRosterSize: action.payload\r\n }\r\n\r\n case types.SET_STEP4_FOR_EDITING: \r\n return {\r\n ...state,\r\n ...action.payload\r\n }\r\n\r\n case types.SET_STEP4_NUM_SELECTED_DRUG: \r\n return {\r\n ...state,\r\n numberSelectedDrug: action.payload\r\n }\r\n\r\n case types.SET_STEP4_NUM_TESTED_DRUG: \r\n return {\r\n ...state,\r\n numberTestedDrug: action.payload\r\n }\r\n\r\n case types.SET_STEP4_NUM_SELECTED_ALCOHOL: \r\n return {\r\n ...state,\r\n numberSelectedAlcohol: action.payload\r\n }\r\n\r\n case types.SET_STEP4_NUM_TESTED_ALCOHOL: \r\n return {\r\n ...state,\r\n numberTestedAlcohol: action.payload\r\n }\r\n\r\n default:\r\n return state;\r\n }\r\n}\r\n\r\nexport default randomsPoolCreationWizardStep4Reducer;","const step5DefaultState = {\r\n employeesInPool: 0,\r\n};\r\n\r\nexport default step5DefaultState;","import types from './types';\r\nimport step5DefaultState from './defaultState';\r\n\r\nconst randomsPoolCreationWizardStep5Reducer = (state = step5DefaultState, action) => {\r\n switch (action.type) {\r\n case types.RESET_STEP_5_GLOBAL_STATE: \r\n return step5DefaultState;\r\n\r\n case types.SET_STEP5_EMPLOYEES_IN_POOL: {\r\n return {\r\n ...state,\r\n employeesInPool: action.payload\r\n }\r\n }\r\n\r\n default:\r\n return state;\r\n }\r\n}\r\n\r\nexport default randomsPoolCreationWizardStep5Reducer;","import { combineReducers } from 'redux';\r\n\r\nimport randomsPoolCreationWizardAllStepsReducer from './AllSteps/reducers';\r\nimport randomsPoolCreationWizardStep1Reducer from './Step1/reducers';\r\nimport randomsPoolCreationWizardStep2Reducer from './Step2/reducers';\r\nimport randomsPoolCreationWizardStep3Reducer from './Step3/reducers';\r\nimport randomsPoolCreationWizardStep4Reducer from './Step4/reducers';\r\nimport randomsPoolCreationWizardStep5Reducer from './Step5/reducers';\r\n\r\n// This will allow us to export this reducer specific to the Randoms Pool Creation Wizard in ./index.js.\r\nconst randomsPoolCreationWizardReducers = combineReducers({\r\n allSteps: randomsPoolCreationWizardAllStepsReducer,\r\n step1: randomsPoolCreationWizardStep1Reducer,\r\n step2: randomsPoolCreationWizardStep2Reducer,\r\n step3: randomsPoolCreationWizardStep3Reducer,\r\n step4: randomsPoolCreationWizardStep4Reducer,\r\n step5: randomsPoolCreationWizardStep5Reducer\r\n})\r\n\r\nexport default randomsPoolCreationWizardReducers;","import { combineReducers } from 'redux';\r\n\r\nimport randomsPoolCreationWizardReducers from './randomsPoolCreationWizard/reducers'\r\n\r\n// COMBINE ALL OF OUR RANDOMS REDUCERS HERE IN THIS FILE\r\nconst randomsReducers = combineReducers({\r\n randomsPoolCreationWizard: randomsPoolCreationWizardReducers\r\n // next property for different randoms functionality here...\r\n // next property for different randoms functionality here...\r\n // etc.\r\n});\r\n\r\nexport default randomsReducers;","import {combineReducers} from 'redux';\r\nimport layout from './layout';\r\nimport alerts from './alerts';\r\nimport cme from './cme';\r\nimport userSession from './userSession';\r\nimport auth from './auth';\r\nimport dqf from './dqf';\r\nimport dqInternal from './dqInternal';\r\nimport breadcrumb from './breadcrumb';\r\nimport modal from './modal';\r\nimport concorde from './concorde';\r\nimport tableSettings from './tablesettings';\r\nimport randoms from './randomsPage/reducers';\r\n\r\nexport default combineReducers({\r\n layout,\r\n alerts,\r\n cme,\r\n userSession,\r\n auth,\r\n dqf,\r\n dqInternal,\r\n breadcrumb,\r\n modal,\r\n concorde,\r\n tableSettings,\r\n randoms\r\n});","import {createStore, applyMiddleware} from 'redux';\r\nimport thunk from 'redux-thunk';\r\nimport {composeWithDevTools} from 'redux-devtools-extension';\r\n\r\nimport rootReducer from './ducks/index';\r\n\r\nconst initialState = {};\r\nconst middleware = [thunk];\r\n\r\nconst store = createStore(\r\n rootReducer,\r\n initialState,\r\n composeWithDevTools(\r\n applyMiddleware(...middleware)\r\n )\r\n);\r\n\r\nexport default store;","import React, {Component} from \"react\";\r\n\r\nexport default function asyncComponent(importComponent) {\r\n class AsyncComponent extends Component {\r\n constructor(props) {\r\n super(props);\r\n \r\n this.state = {\r\n component: null\r\n };\r\n }\r\n\r\n async componentDidMount() {\r\n const {default: component} = await importComponent();\r\n\r\n this.setState({\r\n component: component\r\n });\r\n }\r\n\r\n render() {\r\n const C = this.state.component;\r\n\r\n return C ?
: null;\r\n }\r\n }\r\n\r\n return AsyncComponent;\r\n}","import React from 'react'\r\n\r\nconst NotFound = props => {\r\n return (\r\n
\r\n
Sorry, this page does not exist
\r\n
\r\n )\r\n};\r\n\r\nexport default NotFound;","import permissions from './config/permissions';\r\nimport asyncComponent from './AsyncComponent';\r\n\r\nimport NotFound from './components/general/not-found/NotFound';\r\nimport React from 'react';\r\n\r\nconst Home = asyncComponent(() => import('./components/home/HomeContainer'));\r\nconst TermsOfService = asyncComponent(() => import('./components/general/termsOfService/TermsOfServiceContainer'));\r\nconst PrivacyPolicy = asyncComponent(() => import('./components/general/privacyPolicy/PrivacyPolicyContainer'));\r\nconst Login = asyncComponent(() => import( './components/general/auth/Login/LoginContainer'));\r\nconst Profile = asyncComponent(() => import('./components/general/profile/ProfileContainer'));\r\nconst ChangePassword = asyncComponent(() => import('./components/general/auth/ChangePassword/ChangePassword'));\r\nconst AddClient = asyncComponent(() => import('./components/Concorde/AddClient/AddClientContainer'));\r\nconst CoverSheetInfo = asyncComponent(() => import('./components/Concorde/DQInternal/CoverSheetInfo/CoverSheetInfoContainer'));\r\n\r\nconst CustomerCareReps = asyncComponent(() => import('./components/Concorde/CustomerCareReps/CustomerCareRepsContainer'));\r\nconst AddCCRep = asyncComponent(() => import('./components/Concorde/CustomerCareReps/components/AddEditCCRep/AddEditCCRepContainer'));\r\nconst CCRepDetail = asyncComponent(() => import('./components/Concorde/CustomerCareReps/components/CCRepDetail/CCRepDetailContainer'));\r\n\r\nconst RandomsDashboard = asyncComponent(() => import('./components/randoms/Dashboard/RandomsDashboard'));\r\nconst PoolCreation = asyncComponent(() => import('./components/randoms/Dashboard/PoolCreation'));\r\nconst PoolReporting = asyncComponent(() => import('./components/randoms/Dashboard/PoolReporting/PoolReportingContainer'));\r\nconst PoolDrilldown = asyncComponent(() => import('./components/randoms/Dashboard/PoolReporting/poolDrilldownContainer/PoolDrilldownContainer'));\r\nconst TestingRates = asyncComponent(() => import('./components/randoms/Dashboard/TestingRates'));\r\n\r\nconst CMESupervisorDashboard = asyncComponent(() => import('./components/cme/CMESupervisorDashboard/cmeSupervisorDashboard'));\r\nconst CMEWorklists = asyncComponent(() => import('./components/cme/CMEWorklists/CMEWorklistsContainer'));\r\nconst CMEWork = asyncComponent(() => import('./components/cme/CMEWork/CMEWork'));\r\nconst CMEChaseList = asyncComponent(() => import('./components/cme/CMEChaseList/CMEChaseListContainer'));\r\nconst CMEChaseDetail = asyncComponent(() => import('./components/cme/CMEChaseList/components/CMEChaseDetail/CMEChaseDetailContainer'));\r\n\r\nconst DQInternalWorklists = asyncComponent(() => import('./components/Concorde/DQInternal/DQInternalWorklistsContainer'));\r\nconst DQInternalMatch = asyncComponent(() => import('./components/Concorde/DQInternal/SearchAndMatchForm/DQInternalSearchAndMatchFormContainer'));\r\nconst DQInternalReview = asyncComponent(() => import('./components/Concorde/DQInternal/Review/DQInternalReviewContainer'));\r\nconst DQInternalGetExternalDocsWorklist = asyncComponent(() => import('./components/Concorde/DQInternal/GetExternalDocsWorklist/GetExternalDocsWorklistContainer'));\r\nconst DQInternalGetExternalDocs = asyncComponent(() => import('./components/Concorde/DQInternal/GetExternalDocs/DQInternalGetExternalDocsContainer'));\r\nconst WaitingForCoversheetWorklist = asyncComponent(() => import('./components/Concorde/DQInternal/WaitingForCoversheetWorklist/WaitingForCoversheetWorklistContainer'));\r\nconst DQSupervisorDashboard = asyncComponent(() => import('./components/Concorde/DQInternal/SupervisorDashboard/DQSupervisorDashboardContainer'));\r\n\r\nconst EmployeeSearch = asyncComponent(() => import('./components/dqf/employees/common/EmployeeSearch/EmployeeSearchContainer'));\r\nconst EmployeeSearchResults = asyncComponent(() => import('./components/dqf/employees/EmployeeSearchResults/EmployeeSearchResultsContainer'));\r\n\r\nconst Compliance = asyncComponent(() => import('./components/dqf/compliance/ComplianceContainer'));\r\nconst DocumentAlerts = asyncComponent(() => import('./components/dqf/manage/alerts/components/documentAlerts/DocumentAlertsContainer'));\r\nconst DocReviewAlerts = asyncComponent(() => import('./components/dqf/manage/alerts/components/docReviewAlerts/DocReviewAlertsContainer'));\r\nconst MVRScoring = asyncComponent(() => import('./components/dqf/manage/alerts/components/MVRScoring/MVRScoring'));\r\nconst ApplicantAlerts = asyncComponent(() => import('./components/dqf/manage/alerts/components/applicantAlerts/ApplicantAlertsContainer'));\r\nconst StaleApplicantAlerts = asyncComponent(() => import('./components/dqf/manage/alerts/components/staleApplicantAlerts/StaleApplicantAlertsContainer'));\r\nconst CSAAlerts = asyncComponent(() => import('./components/dqf/manage/alerts/components/csaAlerts/CSAAlertsContainer'));\r\nconst DACAlerts = asyncComponent(() => import('./components/dqf/manage/alerts/components/dacAlerts/DACAlertsContainer'));\r\nconst RandomAlerts = asyncComponent(() => import('./components/dqf/manage/alerts/components/randomAlerts/RandomAlertsContainer'));\r\nconst OnboardingAlerts = asyncComponent(() => import('./components/dqf/manage/alerts/components/onboardingAlerts/OnboardingAlertsContainer'));\r\nconst ClearinghouseQueryAlerts = asyncComponent(() => import('./components/dqf/manage/alerts/components/clearinghouseQueryAlerts/ClearinghouseQueryAlerts'));\r\nconst EmployeeList = asyncComponent(() => import('./components/dqf/employees/EmployeeList/EmployeeListContainer'));\r\nconst EmployeeDetail = asyncComponent(() => import('./components/dqf/employees/EmployeeDetail/EmployeeDetailContainer'));\r\nconst AddEmployee = asyncComponent(() => import('./components/dqf/employees/AddEmployee/AddEmployeeContainer'));\r\nconst UploadRosterUpdates = asyncComponent(() => import('./components/dqf/employees/UploadRosterUpdates/UploadRosterUpdatesContainer'));\r\nconst UploadDocument = asyncComponent(() => import('./components/dqf/employees/UploadDocument/UploadDocumentContainer'));\r\nconst MissingDocumentWizard = asyncComponent(() => import('./components/dqf/employees/MissingDocumentWizard/MissingDocumentWizardContainer'));\r\nconst MergeEmployees = asyncComponent(() => import('./components/dqf/employees/EmployeeDetail/components/MergeEmployees/MergeEmployeesContainer'));\r\nconst OrderList = asyncComponent(() => import('./components/dqf/manage/Orders/OrdersAdminContainer'));\r\nconst OrderDetail = asyncComponent(() => import('./components/dqf/manage/Orders/OrderDetail/OrderDetailContainer'));\r\nconst Reports = asyncComponent(() => import('./components/dqf/manage/reports/Reports/ReportsContainer'));\r\nconst Report = asyncComponent(() => import('./components/dqf/manage/reports/Reports/Report/ReportContainer'));\r\nconst ContactUs = asyncComponent(() => import('./components/dqf/ContactUs/ContactUsComponent'));\r\nconst SiteLocations = asyncComponent(() => import('./components/dqf/manage/admin/SiteLocations/SiteLocationsContainer'));\r\nconst SiteLocationDetail = asyncComponent(() => import('./components/dqf/manage/admin/SiteLocationDetail/SiteLocationDetailContainer'));\r\nconst FileSetup = asyncComponent(() => import('./components/dqf/manage/admin/SiteLocationDetail/FileSetup/FileSetupContainer'));\r\nconst ManageUsers = asyncComponent(() => import('./components/common/user/UserList/UserListContainer'));\r\nconst UserDetail = asyncComponent(() => import('./components/common/user/UserDetail/UserDetailContainer'));\r\nconst Contact = asyncComponent(() => import('./components/dqf/manage/admin/ContactsNotifications/ContactNotificationsContainer'));\r\nconst Signup = asyncComponent(() => import('./components/general/auth/Signup/SignupContainer'));\r\nconst ResetPassword = asyncComponent(() => import('./components/general/auth/ResetPassword/ResetPassword'));\r\nconst ForgotPassword = asyncComponent(() => import('./components/general/auth/ForgotPassword/ForgotPassword'));\r\n\r\nconst CMESearchResults = asyncComponent(() => import(\"./components/cme/CMESearchResults/CMESearchResultsContainer\"));\r\nconst AddUser = asyncComponent(() => import(\"./components/dqf/manage/admin/AddUser/AddUserContainer\"));\r\nconst AddLocation = asyncComponent(() => import(\"./components/dqf/manage/admin/AddLocation/NewLocationContainer\"));\r\nconst AddContact = asyncComponent(() => import(\"./components/dqf/manage/admin/AddNotification/AddNotificationContainer\"));\r\nconst NotificationList = asyncComponent(() => import(\"./components/dqf/manage/admin/Notifications/NotificationListContainer\"));\r\nconst Clients = asyncComponent(() => import(\"./components/Concorde/Clients/ClientsContainer\"));\r\nconst ClientDetail = asyncComponent(() => import('./components/Concorde/Clients/components/ClientDetail/ClientDetailContainer'));\r\nconst AuditorLogin = asyncComponent(() => import(\"./components/general/auth/AuditorLogin/AuditorLoginContainer\"));\r\nconst DriverAnnual = asyncComponent(() => import('./components/dqf/DriverAnnual/DriverAnnualContainer'));\r\nconst ViolationsForm = asyncComponent(() => import(\"./components/dqf/DriverAnnual/ViolationsForm/ViolationsFormContainer\"));\r\nconst OnboardingEmployee = asyncComponent(() => import(\"./components/dqf/OnboardingEmployee/OnboardingEmployeeContainer\"));\r\n// const ElectronicDOTApplication = asyncComponent(() => import('./components/dqf/ElectronicDOTApplication/ElectronicDOTApplicationContainer'));\r\nconst ApplicantScreening = asyncComponent(() => import('./components/applicants/ApplicantScreening/ApplicantScreeningContainer/ApplicantScreeningContainer'));\r\nconst ImportEmployeeProfilePhotos = asyncComponent(() => import('./components/Concorde/ImportEmployeeProfilePhotos/ImportEmployeeProfilePhotosContainer'));\r\nconst JumpList = asyncComponent(() => import(\"./components/dqf/common/JumpList/JumpListContainer\"));\r\nconst SupervisorReview = asyncComponent(() => import(\"./components/dqf/DriverAnnual/SupervisorReview/SupervisorReviewContainer\"));\r\n\r\nconst DrugTestResults = asyncComponent(() => import('./components/DrugTestResults/DrugTestResultsContainer'));\r\nconst BATReview = asyncComponent(() => import('./components/BAT/BATReview/BATReview'));\r\n\r\nconst BackgroundCheckReportCopyRequests = asyncComponent(() => import('./components/applicants/BackgroundCheckReportCopyRequests/BackgroundCheckReportCopyRequestsContainer'));\r\n\r\n/**\r\n * This object defines all of the routes in the app. It is used to generate the menu, the breadcrumbs,\r\n * and the main page content.\r\n *\r\n * It is an array; each entry should contain the following properties:\r\n * - text: the text to display (leave blank if setting the text via Redux)\r\n * - path: the path element for the route (incremental by default; see next property)\r\n * - absolutePath: true if the path property is ABSOLUTE rather than incremental (default: false)\r\n * - inMenu: true if the route should be shown in the menu (default is false)\r\n * - menuHeading: true if the entry is a menu heading (default is false)\r\n *\r\n * An entry that is a menu heading may contain the following (optional) property,\r\n * to render a component just below the menu section heading (for example, an employee search):\r\n * - component: the React component to render in the menu\r\n *\r\n * Otherwise, the entry is interpreted as a route and it may also contain the following (optional) properties:\r\n * - badgeCalculator: a method that can be called to calculate a badge number to show next to the menu link\r\n * - badgeCalculatorArguments: a list of argument names corresponding to Redux object to pass to the badge calculator\r\n * - showBreadcrumbs: true if the breadcrumbs should be shown when this route is active\r\n * - component: the React component to link to (for the main page)\r\n * - exact: true if the Route must match the path exactly in order for the menu link to be \"active\"\r\n * - permission: the permission that a user must have in order to access the route (and see the menu link)\r\n * - needClient: if true, and user is a Concorde user, disable the entry if a client is not selected\r\n * - isConcordeUser: if true, the entry will only be shown if the user is a Concorde user (in addition to the permissions required)\r\n * - protected: true if the user needs to be logged in (but does not need any specific permission) to access the route\r\n *\r\n * It is also possible for a menu entry to invoke a modal instead of going to a page. For that option, do not set a\r\n * path or a component (set them to null); instead, set the following:\r\n * - modal: the name of the modal to display via Redux (see /src/components/common/Modal/modalComponent.js)\r\n *\r\n * Note that a menu heading does not have a permission setting; it will be shown in the menu ONLY if one or more\r\n * of its \"child\" entries is shown (based on permissions).\r\n *\r\n * Also note that the \"tail\" of the breadcrumbs can be set via Redux; to allow this to happen, do NOT\r\n * set the text property.\r\n */\r\nconst routes = [\r\n {\r\n text: 'Home',\r\n path: '/',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: Home,\r\n exact: true\r\n },\r\n {\r\n text: 'Terms of Service',\r\n path: '/termsOfService',\r\n component: TermsOfService,\r\n showBreadcrumbs: true\r\n },\r\n {\r\n text: 'Privacy Policy',\r\n path: '/privacyPolicy',\r\n component: PrivacyPolicy,\r\n showBreadcrumbs: true\r\n },\r\n {\r\n text: 'Driver Annual Certification',\r\n path: '/driverannual/:dacId',\r\n inMenu: false,\r\n showBreadcrumbs: false,\r\n component: DriverAnnual\r\n },\r\n {\r\n text: 'Employee Onboarding',\r\n path: '/onboardingEmployee/:onboardingId',\r\n inMenu: false,\r\n showBreadcrumbs: false,\r\n component: OnboardingEmployee\r\n },\r\n {\r\n path: '/login',\r\n component: Login\r\n },\r\n {\r\n path: '/signup/:token',\r\n component: Signup\r\n },\r\n {\r\n path: '/auditor/:auditorToken',\r\n component: AuditorLogin\r\n },\r\n {\r\n path: '/resetPassword/:token',\r\n component: ResetPassword\r\n },\r\n {\r\n path: '/forgotPassword',\r\n component: ForgotPassword\r\n },\r\n {\r\n path: '/additionalinfo/:dqItemId',\r\n component: CoverSheetInfo\r\n },\r\n {\r\n text: 'User Profile',\r\n path: '/user/profile',\r\n showBreadcrumbs: true,\r\n component: Profile,\r\n protected: true,\r\n routes: [\r\n {\r\n text: 'Change Password',\r\n path: '/user/changepassword',\r\n absolutePath: true,\r\n showBreadcrumbs: true,\r\n component: ChangePassword,\r\n protected: true\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Clients',\r\n path: '/clients',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: Clients,\r\n permission: permissions.customerCare.viewClients,\r\n routes: [\r\n {\r\n text: 'Add Client',\r\n path: '/action/addClient',\r\n showBreadcrumbs: true,\r\n component: AddClient,\r\n permission: permissions.admin.addClient\r\n },\r\n {\r\n path: '/:clientId',\r\n showBreadcrumbs: true,\r\n component: ClientDetail,\r\n permission: permissions.customerCare.viewClients\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Customer Care Reps',\r\n path: '/customercarereps',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: CustomerCareReps,\r\n permission: permissions.admin.viewCCRs,\r\n routes: [\r\n {\r\n path: '/action/addccrep',\r\n text: 'Create Customer Care Rep',\r\n showBreadcrumbs: true,\r\n component: AddCCRep,\r\n permission: permissions.admin.addCCR\r\n },\r\n {\r\n path: '/detail/:repId',\r\n showBreadcrumbs: true,\r\n component: CCRepDetail,\r\n permission: permissions.admin.viewCCRs,\r\n routes: [\r\n {\r\n path: '/edit',\r\n text: 'Edit',\r\n showBreadcrumbs: true,\r\n component: AddCCRep,\r\n permission: permissions.admin.configureCCR\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Internal User Management',\r\n path: '/concordeUsers',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: ManageUsers,\r\n permission: permissions.admin.viewUsers,\r\n routes: [\r\n {\r\n path: '/action/adduser',\r\n text: 'Add User',\r\n showBreadcrumbs: true,\r\n component: AddUser,\r\n permission: permissions.client.addUser\r\n },\r\n {\r\n path: '/:userId',\r\n showBreadcrumbs: true,\r\n component: UserDetail,\r\n permission: permissions.admin.viewInternalUser\r\n }\r\n ]\r\n },\r\n {\r\n text: '',\r\n path: '/cme',\r\n inMenu: true,\r\n menuHeading: true,\r\n routes: [\r\n {\r\n text: 'CME Supervisor Dashboard',\r\n path: '/dashboard',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: CMESupervisorDashboard,\r\n exact: true,\r\n permission: permissions.cme.dashboard\r\n },\r\n {\r\n text:
CME Tool
,\r\n path: null,\r\n modal: 'CMEResearch',\r\n inMenu: true,\r\n component: null,\r\n exact: true,\r\n permission: permissions.cme.research\r\n },\r\n {\r\n text: 'CME Worklists',\r\n path: '/workflow',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: CMEWorklists,\r\n permission: permissions.cme.worklists,\r\n routes: [\r\n {\r\n path: '/:processInstanceId',\r\n showBreadcrumbs: true,\r\n component: CMEWork,\r\n permission: permissions.cme.worklists\r\n },\r\n {\r\n path: '/detail/:cmeId',\r\n showBreadcrumbs: true,\r\n component: CMEWork,\r\n permission: permissions.cme.viewDetail\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Chase List',\r\n path: '/chase',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: CMEChaseList,\r\n permission: permissions.cme.chaseList,\r\n routes: [\r\n {\r\n path: '/:medicalExamOrderId/:orderId',\r\n showBreadcrumbs: true,\r\n component: CMEChaseDetail,\r\n permission: permissions.cme.chaseList\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Customer Care Intervention',\r\n path: '/customercare',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: CMEWorklists,\r\n exact: true,\r\n permission: permissions.cme.customerCareIntervention,\r\n badgeCalculatorArguments: ['auth', 'cme'],\r\n badgeCalculator: ({auth, cme}) => {\r\n let badgeNumber = 0;\r\n if (auth && auth.user && cme.taskLists && cme.taskLists.taskListData && cme.taskLists.taskListData.length > 0) {\r\n badgeNumber = cme.taskLists.taskListData.filter(task => task.customerCareRep === auth.user.email && task.needsCCIntervention).length;\r\n }\r\n return badgeNumber;\r\n },\r\n routes: [\r\n {\r\n path: '/:processInstanceId',\r\n showBreadcrumbs: true,\r\n component: CMEWork,\r\n permission: permissions.cme.customerCareIntervention\r\n }\r\n ]\r\n },\r\n {\r\n text: 'CME Search Results',\r\n path: '/results',\r\n showBreadcrumbs: true,\r\n component: CMESearchResults,\r\n permission: permissions.cme.search\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Document Alerts',\r\n path: '/alerts/documentAlerts',\r\n showBreadcrumbs: true,\r\n component: DocumentAlerts,\r\n permission: permissions.client.viewAlerts\r\n },\r\n {\r\n text: 'MVR Alerts',\r\n path: '/alerts/docReviewAlerts',\r\n showBreadcrumbs: true,\r\n component: DocReviewAlerts,\r\n permission: permissions.client.viewAlerts\r\n },\r\n {\r\n text: 'MVR Scoring',\r\n path: '/alerts/MVRScoring',\r\n showBreadcrumbs: true,\r\n component: MVRScoring,\r\n permission: permissions.client.viewAlerts\r\n },\r\n {\r\n text: 'Applicants Pending More than 60 Days',\r\n path: '/alerts/staleApplicants',\r\n showBreadcrumbs: true,\r\n component: StaleApplicantAlerts,\r\n permission: permissions.client.viewAlerts\r\n },\r\n {\r\n text: 'CSA Alerts',\r\n path: '/alerts/csaAlerts',\r\n showBreadcrumbs: true,\r\n component: CSAAlerts,\r\n permission: permissions.client.viewAlerts\r\n },\r\n {\r\n text: 'Driver Annual Certifications',\r\n path: '/alerts/dacAlerts',\r\n showBreadcrumbs: true,\r\n component: DACAlerts,\r\n permission: permissions.client.viewAlerts\r\n },\r\n {\r\n text: 'Open Randoms',\r\n path: '/alerts/randomAlerts',\r\n showBreadcrumbs: true,\r\n component: RandomAlerts,\r\n permission: permissions.client.viewAlerts\r\n },\r\n {\r\n text: 'Open Onboarding Employees',\r\n path: '/alerts/onboardingEmployees',\r\n showBreadcrumbs: true,\r\n component: OnboardingAlerts,\r\n permission: permissions.client.viewAlerts\r\n },\r\n {\r\n text: 'Applications and Background Checks',\r\n path: '/alerts/applicants',\r\n showBreadcrumbs: true,\r\n component: ApplicantAlerts,\r\n permission: permissions.client.viewAlerts\r\n },\r\n {\r\n text: 'Clearinghouse Queries',\r\n path: '/alerts/clearinghouseQueryAlerts',\r\n showBreadcrumbs: true,\r\n component: ClearinghouseQueryAlerts,\r\n permission: permissions.servicesClearinghouse.orderClearinghouseQueries\r\n },\r\n {\r\n text: '',\r\n path: '/dqInternal',\r\n inMenu: true,\r\n menuHeading: true,\r\n routes: [\r\n {\r\n text: 'DQ Worklists',\r\n path: '/workflow',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: DQInternalWorklists,\r\n permission: permissions.dq.worklists,\r\n routes: [\r\n {\r\n path: '/match/:processInstanceId',\r\n showBreadcrumbs: true,\r\n component: DQInternalMatch,\r\n permission: permissions.dq.searchAndMatch\r\n },\r\n {\r\n path: '/review/:processInstanceId',\r\n showBreadcrumbs: true,\r\n component: DQInternalReview,\r\n permission: permissions.dq.review\r\n },\r\n {\r\n text: 'Get External Files',\r\n path: '/getexternaldocs',\r\n showBreadcrumbs: true,\r\n component: DQInternalGetExternalDocsWorklist,\r\n permission: permissions.dq.getExternalDocs,\r\n routes: [\r\n {\r\n path: '/:processInstanceId',\r\n showBreadcrumbs: true,\r\n component: DQInternalGetExternalDocs,\r\n permission: permissions.dq.getExternalDocs\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Waiting for Cover Sheet',\r\n path: '/waitingforcoversheet',\r\n showBreadcrumbs: true,\r\n component: WaitingForCoversheetWorklist,\r\n permission: permissions.dq.review\r\n }\r\n ]\r\n },\r\n {\r\n text: 'DQ Supervisor Dashboard',\r\n path: '/dashboard',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: DQSupervisorDashboard,\r\n exact: true,\r\n permission: permissions.dq.dashboard\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Background Check Report Copy Requests',\r\n path: '/backgroundcheckreportcopyrequests',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: BackgroundCheckReportCopyRequests,\r\n permission: permissions.client.viewEmployeeDataReports,\r\n isConcordeUser: true\r\n },\r\n {\r\n text: '',\r\n path: '/manage',\r\n inMenu: true,\r\n menuHeading: true,\r\n sectionComponents: [\r\n {component: EmployeeSearch, permission: permissions.client.viewEmployee},\r\n {component: JumpList, permission: permissions.client.viewEmployee}\r\n ],\r\n routes: [\r\n {\r\n text: 'Roster',\r\n path: '/employees',\r\n inMenu: true,\r\n needClient: true,\r\n showBreadcrumbs: true,\r\n component: EmployeeList,\r\n permission: permissions.client.viewRoster,\r\n routes: [\r\n {\r\n path: '/:employeeId',\r\n showBreadcrumbs: true,\r\n component: EmployeeDetail,\r\n permission: permissions.client.viewEmployee,\r\n routes: [\r\n {\r\n text: 'Upload a Document',\r\n path: '/upload',\r\n showBreadcrumbs: true,\r\n component: UploadDocument,\r\n permission: permissions.client.uploadDocuments\r\n },\r\n {\r\n text: 'Missing Document Wizard',\r\n path: '/missing',\r\n showBreadcrumbs: true,\r\n component: MissingDocumentWizard,\r\n permission: permissions.client.uploadDocuments\r\n },\r\n {\r\n text: 'Merge Employees',\r\n path: '/merge',\r\n showBreadcrumbs: true,\r\n component: MergeEmployees,\r\n permission: permissions.client.mergeEmployees\r\n }\r\n ]\r\n },\r\n {\r\n //this needs to be located here as opposed to the routes array above for '/:employeeId' b/c of issues with the breadcrumbs if placed there\r\n path: '/:employeeId/tab/:tabToOpen',\r\n showBreadcrumbs: true,\r\n component: EmployeeDetail,\r\n permission: permissions.client.viewEmployee\r\n },\r\n {\r\n text: 'Add a New Employee',\r\n path: '/add/:clientId',\r\n showBreadcrumbs: true,\r\n component: AddEmployee,\r\n permission: permissions.client.addEmployee\r\n },\r\n {\r\n text: 'Upload Roster Updates',\r\n path: '/roster/update',\r\n showBreadcrumbs: true,\r\n component: UploadRosterUpdates,\r\n permission: permissions.client.uploadRosterUpdates\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Employee Search Results',\r\n path: '/employeesearch',\r\n showBreadcrumbs: true,\r\n component: EmployeeSearchResults,\r\n permission: permissions.client.viewEmployee\r\n },\r\n {\r\n text: 'Applicants',\r\n path: '/alerts/applicants',\r\n inMenu: true,\r\n needClient: true,\r\n showBreadcrumbs: true,\r\n component: ApplicantAlerts,\r\n permission: permissions.client.viewApplicants\r\n },\r\n {\r\n text: 'Compliance',\r\n path: '/compliance',\r\n inMenu: true,\r\n needClient: true,\r\n showBreadcrumbs: true,\r\n component: Compliance,\r\n permission: permissions.client.viewAlerts\r\n },\r\n {\r\n text: 'Orders',\r\n path: '/orders',\r\n inMenu: true,\r\n needClient: true,\r\n showBreadcrumbs: true,\r\n component: OrderList,\r\n permission: permissions.client.viewOrders,\r\n routes: [\r\n {\r\n path: '/:orderId',\r\n showBreadcrumbs: true,\r\n component: OrderDetail,\r\n permission: permissions.client.viewOrders\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Reports',\r\n path: '/reports',\r\n inMenu: true,\r\n needClient: true,\r\n showBreadcrumbs: true,\r\n component: Reports,\r\n permission: permissions.client.viewEmployeeDataReports,\r\n routes: [\r\n {\r\n path: '/:reportName',\r\n showBreadcrumbs: true,\r\n component: Report,\r\n permission: permissions.client.viewEmployeeDataReports\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Locations',\r\n path: '/admin/locations',\r\n inMenu: true,\r\n needClient: true,\r\n showBreadcrumbs: true,\r\n component: SiteLocations,\r\n permission: permissions.client.viewLocation,\r\n routes: [\r\n {\r\n path: '/action/addlocation',\r\n showBreadcrumbs: true,\r\n component: AddLocation,\r\n permission: permissions.client.addLocation\r\n },\r\n {\r\n path: '/:clientId',\r\n showBreadcrumbs: true,\r\n component: SiteLocationDetail,\r\n permission: permissions.client.viewLocation,\r\n routes: [\r\n {\r\n text: 'File Setup',\r\n path: '/fileSetup',\r\n showBreadcrumbs: true,\r\n component: FileSetup,\r\n permission: permissions.client.viewLocation\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Users',\r\n path: '/admin/users',\r\n inMenu: true,\r\n needClient: true,\r\n showBreadcrumbs: true,\r\n component: ManageUsers,\r\n permission: permissions.client.viewUsers,\r\n routes: [\r\n {\r\n path: '/action/adduser',\r\n text: 'Add User',\r\n showBreadcrumbs: true,\r\n component: AddUser,\r\n permission: permissions.client.addUser\r\n },\r\n {\r\n path: '/:userId',\r\n showBreadcrumbs: true,\r\n component: UserDetail,\r\n permission: permissions.client.configureUser\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Notifications',\r\n path: '/admin/notifications',\r\n inMenu: true,\r\n needClient: true,\r\n showBreadcrumbs: true,\r\n component: NotificationList,\r\n permission: permissions.client.configureNotifications,\r\n routes: [\r\n {\r\n path: '/:email',\r\n showBreadcrumbs: true,\r\n component: Contact,\r\n permission: permissions.client.configureNotifications\r\n },\r\n {\r\n path: '/action/addcontact',\r\n showBreadcrumbs: true,\r\n component: AddContact,\r\n permission: permissions.client.configureNotifications\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Driver Annual Certification',\r\n path: '/driverannual/:dacId',\r\n inMenu: false,\r\n showBreadcrumbs: true,\r\n component: ViolationsForm\r\n },\r\n {\r\n text: 'Review Driver Annual Certification',\r\n path: '/driverannual/review/:dacId',\r\n inMenu: false,\r\n showBreadcrumbs: true,\r\n component: SupervisorReview,\r\n permissions: permissions.client.viewAlerts\r\n },\r\n {\r\n text: 'Employee Onboarding',\r\n path: '/onboardingEmployee/:onboardingId',\r\n inMenu: false,\r\n showBreadcrumbs: true,\r\n component: OnboardingEmployee\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Drug Testing',\r\n path: '/drugtesting',\r\n inMenu: true,\r\n menuHeading: true,\r\n routes: [\r\n {\r\n text: 'Drug Test Results',\r\n path: '/drugtestresults',\r\n inMenu: true,\r\n needClient: true,\r\n showBreadcrumbs: true,\r\n component: DrugTestResults,\r\n permission: permissions.client.viewOrders\r\n },\r\n {\r\n text: 'BAT Review',\r\n path: '/batreview',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: BATReview,\r\n permission: permissions.customerCare.assumeClient\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Randoms',\r\n path: '/randoms',\r\n inMenu: true,\r\n menuHeading: true,\r\n routes: [\r\n {\r\n text: 'Roster Management',\r\n path: '/roster',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: RandomsDashboard,\r\n permission: permissions.servicesRandoms.viewSelections\r\n },\r\n {\r\n text: 'Pool Management/Creation',\r\n path: '/poolmanagement',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: PoolCreation,\r\n permission: permissions.servicesRandoms.viewConfigurePools\r\n },\r\n {\r\n text: 'Compliance/Reporting',\r\n path: '/poolreporting',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: PoolReporting,\r\n permission: permissions.servicesRandoms.viewSelections,\r\n routes: [\r\n {\r\n path: '/:clientId/:poolId',\r\n showBreadcrumbs: true,\r\n component: PoolDrilldown,\r\n permission: permissions.servicesRandoms.viewSelections\r\n }\r\n ]\r\n },\r\n {\r\n text: 'View Testing Rates',\r\n path: '/testingrates',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: TestingRates,\r\n permission: permissions.servicesRandoms.viewConfigurePools\r\n }\r\n ]\r\n },\r\n {\r\n text: 'Applicant Screening',\r\n path: '/application/:applicantId',\r\n inMenu: false,\r\n showBreadcrumbs: true,\r\n component: ApplicantScreening\r\n },\r\n {\r\n text: 'Import Employee Profile Photos',\r\n path: '/importPhotos',\r\n showBreadcrumbs: true,\r\n component: ImportEmployeeProfilePhotos,\r\n permission: permissions.admin.superAdmin,\r\n isConcordeUser: true\r\n },\r\n {\r\n text: 'Score MVRs Manually',\r\n path: '/scoremvrs',\r\n inMenu: true,\r\n showBreadcrumbs: true,\r\n component: MVRScoring,\r\n permission: permissions.dq.scoreMVRsManually,\r\n isConcordeUser: true,\r\n badgeCalculatorArguments: ['auth', 'dqf'],\r\n badgeCalculator: ({auth, dqf}) => {\r\n let badgeNumber = 0;\r\n if (auth && auth.user && dqf && dqf.unscoredMVRs && dqf.unscoredMVRs.length > 0) {\r\n badgeNumber = dqf.unscoredMVRs.length;\r\n }\r\n return badgeNumber;\r\n },\r\n },\r\n {\r\n text: '',\r\n path: '',\r\n inMenu: true,\r\n externalOnly: true,\r\n menuHeading: true,\r\n routes: [\r\n {\r\n text: 'Contact Us',\r\n path: '/contact',\r\n showBreadcrumbs: true,\r\n component: ContactUs\r\n }\r\n ]\r\n },\r\n {\r\n path: '*',\r\n protected: true,\r\n component: NotFound\r\n }\r\n];\r\n\r\nexport default routes;","import React, {Component} from 'react';\r\nimport {connect} from 'react-redux';\r\nimport classNames from 'classnames';\r\nimport {CSSTransition} from 'react-transition-group';\r\n\r\nimport {alertsOperations} from \"../../../../ducks/alerts\";\r\n\r\nexport class AlertMessageComponent extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n currentCount: 10,\r\n showing: false\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n const intervalId = setInterval(this.timer, 1000);\r\n this.setState({\r\n intervalId,\r\n showing: true\r\n });\r\n }\r\n\r\n componentWillUnmount() {\r\n clearInterval(this.state.intervalId);\r\n }\r\n\r\n timer = () => {\r\n this.setState({currentCount: this.state.currentCount - 1});\r\n if (this.state.currentCount === 0) {\r\n this.setState({showing: false});\r\n }\r\n };\r\n\r\n handleRemoveAlert = e => {\r\n e.preventDefault();\r\n this.setState({showing: false});\r\n };\r\n\r\n handleAlertExited = () => {\r\n this.props.removeAlert(this.props.id);\r\n };\r\n\r\n handleKeepAlive = () => {\r\n clearInterval(this.state.intervalId);\r\n };\r\n\r\n render() {\r\n return (\r\n\r\n
\r\n \r\n
\r\n
\r\n
\r\n
{this.props.text}
\r\n
\r\n
\r\n \r\n )\r\n }\r\n}\r\n\r\nconst mapDispatchToProps = {\r\n removeAlert: alertsOperations.removeAlert\r\n};\r\n\r\nexport default connect(null, mapDispatchToProps)(AlertMessageComponent);\r\n","import React, {Component} from 'react';\r\nimport {connect} from \"react-redux\";\r\n\r\nimport AlertMessage from './components/AlertMessageComponent';\r\n\r\nexport class AlertsComponent extends Component {\r\n render() {\r\n const {alerts} = this.props;\r\n const alertMessages = alerts.reverse().map(a => {\r\n return
\r\n });\r\n\r\n return (\r\n
\r\n {alertMessages}\r\n
\r\n )\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n alerts: state.alerts\r\n});\r\n\r\nexport default connect(mapStateToProps)(AlertsComponent);\r\n","import React from 'react';\r\nimport {Route, Redirect} from 'react-router-dom';\r\nimport {connect} from 'react-redux';\r\nimport PropTypes from 'prop-types';\r\n\r\nimport {alertsOperations} from '../../../ducks/alerts';\r\nimport {sessionOperations} from '../../../ducks/userSession';\r\n\r\nconst ProtectedRoute = (props) => {\r\n const {component: Component, auth, permission, addAlert, ...rest} = props;\r\n\r\n if (!auth.isAuthenticated && props.userSession.status === 'ACTIVE') {\r\n return null;\r\n }\r\n // If user is not authenticated . . .\r\n if (!auth.isAuthenticated) {\r\n // Tell the user he needs to login to reach the page (e.g. if he clicked a link in an email)\r\n if (props.userSession.status === 'INITIAL') {\r\n addAlert('To proceed to the requested page, please log in', 'warning');\r\n }\r\n // . . . redirect to the login page\r\n return (\r\n
\r\n \r\n }\r\n />\r\n );\r\n }\r\n\r\n // if a permission is required to access the route and the user.permissions object is null, wait until the permissions are fetched from the server\r\n if (permission && !auth.user.permissions) {\r\n return null;\r\n }\r\n\r\n // If user is logged in but has no permission for the requested page, tell the user and redirect to the home page\r\n if (permission && auth.user.permissions.indexOf(permission) === -1) {\r\n addAlert('You do not have permission to access the page that you requested, and have been redirected to your \\'Home\\' page. If you require access, please contact your system administrator.', 'warning');\r\n return (\r\n \r\n \r\n }\r\n />\r\n );\r\n }\r\n\r\n // All is well; user is logged in and has permission. Go to the page.\r\n return (\r\n \r\n \r\n }\r\n />\r\n );\r\n};\r\n\r\nProtectedRoute.propTypes = {\r\n auth: PropTypes.object.isRequired,\r\n permission: PropTypes.string,\r\n viewOnly: PropTypes.bool\r\n};\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n userSession: state.userSession\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n addAlert: alertsOperations.addAlert,\r\n setSessionStatus: sessionOperations.setSessionStatus\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(ProtectedRoute);\r\n","import React, {Component, Fragment} from 'react';\r\nimport {withRouter} from 'react-router-dom';\r\nimport {connect} from 'react-redux';\r\nimport moment from 'moment';\r\nimport {Modal, ModalHeader, ModalBody, ModalFooter, Button} from 'reactstrap';\r\nimport {sessionOperations} from '../../../ducks/userSession/index';\r\nimport {authOperations} from '../../../ducks/auth/index';\r\nimport axios from 'axios';\r\n\r\nexport class UserSessionContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n intervalId: null,\r\n warningIntervalId: null,\r\n warningDurationMS: 0,\r\n warningModalOpen: false,\r\n durationDisplay: ''\r\n }\r\n }\r\n\r\n componentDidMount() {\r\n this.cancelSource = axios.CancelToken.source();\r\n if (!this.state.intervalId && this.props.userSession.status === 'ACTIVE') {\r\n this.startSessionTimer();\r\n }\r\n }\r\n\r\n componentWillUnmount() {\r\n this.cancelSource.cancel('userCanceled');\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n if (this.props.userSession.status !== prevProps.userSession.status) {\r\n if (this.props.userSession.status === 'ACTIVE' && prevProps.userSession.status !== 'ACTIVE') {\r\n this.startSessionTimer();\r\n }\r\n if (this.props.userSession.status !== 'ACTIVE' && prevProps.userSession.status === 'ACTIVE') {\r\n this.stopSessionTimer();\r\n }\r\n }\r\n }\r\n\r\n startSessionTimer = () => {\r\n this.sessionTimerTick(); //for tick 0 to n (interval)\r\n const intervalId = setInterval(this.sessionTimerTick, 30000);\r\n this.setState({intervalId});\r\n };\r\n\r\n stopSessionTimer = () => {\r\n clearInterval(this.state.intervalId);\r\n this.setState({intervalId: null});\r\n };\r\n\r\n sessionTimerTick = () => {\r\n if (!this.state.warningModalOpen) {\r\n const now = moment(Date.now());\r\n const expireAt = this.props.userSession.expireAt;\r\n const warnAt = this.props.userSession.warnAt;\r\n if (warnAt <= now) {\r\n const warningDurationMS = expireAt.diff(warnAt);\r\n this.setState({warningDurationMS});\r\n this.startWarningTimer();\r\n }\r\n }\r\n };\r\n\r\n userLogoff = () => {\r\n this.props.setSessionStatus('EXITED');\r\n this.props.logoutUser();\r\n };\r\n\r\n expireUserSession = () => {\r\n this.props.setSessionStatus('EXPIRED');\r\n this.props.autoLogoutUser();\r\n };\r\n\r\n startWarningTimer = () => {\r\n this.warningTick(); // tick 0\r\n const warningIntervalId = setInterval(this.warningTick, 1000);\r\n this.setState({warningIntervalId, warningModalOpen: true});\r\n };\r\n\r\n stopWarningTimer = () => {\r\n clearInterval(this.state.warningIntervalId);\r\n this.setState({\r\n warningModalOpen: false,\r\n warningIntervalId: null,\r\n warningDurationMS: 0,\r\n durationDisplay: ''\r\n });\r\n };\r\n\r\n warningTick = () => {\r\n let {warningDurationMS} = this.state;\r\n warningDurationMS = warningDurationMS - 1000;\r\n const durationDisplay = moment(moment.duration(warningDurationMS)._data).format('mm:ss');\r\n this.setState({warningDurationMS, durationDisplay});\r\n if (warningDurationMS < 1000) {\r\n this.stopWarningTimer();\r\n this.expireUserSession();\r\n }\r\n };\r\n\r\n handleStayLoggedOn = e => {\r\n e.preventDefault();\r\n this.props.setSessionStatus('ACTIVE');\r\n this.stopWarningTimer();\r\n //make an axios call in order to refresh the bearer token\r\n axios.get(`/v1/settings/lists?collections=employmentStatus`, {cancelToken: this.cancelSource.token})\r\n .then(response => {\r\n }).catch(err => {\r\n });\r\n };\r\n\r\n handleLogOff = e => {\r\n this.props.history.push('/');\r\n this.stopWarningTimer();\r\n this.userLogoff();\r\n };\r\n\r\n render() {\r\n return (\r\n \r\n \r\n Your session is about to expire due to inactivity\r\n \r\n You will be logged out in {this.state.durationDisplay}. Do\r\n you you want to stay logged on?
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n userSession: state.userSession,\r\n auth: state.auth\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n setSessionStatus: sessionOperations.setSessionStatus,\r\n logoutUser: authOperations.logoutUser,\r\n autoLogoutUser: authOperations.autoLogoutUser\r\n};\r\n\r\nexport default withRouter(connect(mapStateToProps, mapDispatchToProps)(UserSessionContainer));\r\n","import React from 'react';\r\nimport {FormGroup, Label, Input} from 'reactstrap';\r\n\r\nconst toggleMaskComponent = (props) => {\r\n return (\r\n \r\n Mask SSN\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n )\r\n}\r\nexport default toggleMaskComponent;","import React, {Component, Fragment} from 'react';\r\nimport ToggleMaskComponent from './toggleMaskComponent.jsx';\r\nimport {withRouter} from 'react-router-dom';\r\nimport {connect} from 'react-redux';\r\nimport {layoutOperations} from '../../../../ducks/layout/';\r\nimport {hasPermission} from '../../../../utils/permissions';\r\nimport permissions from '../../../../config/permissions';\r\n\r\nexport class ToggleMaskContainer extends Component{\r\n\r\n onChangeMask = (e) => {\r\n e.target.value === 'off' ? this.props.setSSNMask(false) : this.props.setSSNMask(true)\r\n }\r\n render(){\r\n return(\r\n \r\n {hasPermission(this.props.auth.user, permissions.client.viewPII)\r\n ? \r\n : null\r\n }\r\n \r\n )\r\n }\r\n\r\n}\r\n\r\n\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n ssnMask: state.layout.ssnMasked,\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n setSSNMask: layoutOperations.setSSNMask,\r\n};\r\n\r\nexport default withRouter(connect(mapStateToProps, mapDispatchToProps)(ToggleMaskContainer));","import React from 'react';\r\nimport {Link} from \"react-router-dom\";\r\nimport {connect} from 'react-redux';\r\nimport ToggleMaskContainer from './ToggleMaskContainer';\r\n\r\nconst authenticatedLinksComponent = props => {\r\n const {isAuditor, onLogoutClicked, auth: {user}} = props;\r\n return (\r\n \r\n {!user.isConcordeUser &&\r\n
\r\n \r\n Contact Us \r\n \r\n
\r\n }\r\n
\r\n
\r\n )\r\n};\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n});\r\n\r\nexport default connect(mapStateToProps)(authenticatedLinksComponent);","import React from 'react';\r\nimport Select from 'react-select';\r\n\r\nconst ccrClientSelectorComponent = props => {\r\n const clientOptions = props.sites.map(s => ({\r\n value: s._id,\r\n label: s.name\r\n }));\r\n const selectedOption = clientOptions.find(co => co.value === props.selectedClient) || null;\r\n return (\r\n \r\n )\r\n};\r\n\r\nexport default ccrClientSelectorComponent;","import React, { Component } from 'react';\r\nimport { connect } from 'react-redux';\r\nimport _ from \"lodash\";\r\nimport CCRClientSelectorComponent from './ccrClientSelectorComponent';\r\nimport { authOperations } from \"../../../ducks/auth\";\r\nimport { dqfOperations } from \"../../../ducks/dqf\";\r\nimport { concordeOperations } from '../../../ducks/concorde';\r\n\r\nexport class CCRClientSelectorContainer extends Component {\r\n componentDidMount() {\r\n this.props.getClientList();\r\n };\r\n\r\n /**\r\n * Event handler for when the CCR Sites Selector value is changed\r\n * @param selectedClient\r\n */\r\n handleClientChanged = selectedClient => {\r\n // dqfOperations reset dqf.sites\r\n this.props.setSelectedSites();\r\n this.props.setSiteTree({});\r\n this.props.setSessionClient(selectedClient.value);\r\n this.props.resetRosterViews();\r\n // authOperations: update values in auth.user\r\n this.props.getClientAndSites(selectedClient.value, true);\r\n if (this.props.onClientChanged) {\r\n this.props.onClientChanged(selectedClient);\r\n }\r\n };\r\n\r\n render() {\r\n return (\r\n \r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n dqf: state.dqf,\r\n clientList: state.concorde.clientList\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n getClientAndSites: authOperations.getClientAndSites,\r\n setSelectedSites: dqfOperations.setSelectedSites,\r\n setSiteTree: dqfOperations.setSiteTree,\r\n setSessionClient: dqfOperations.setSessionClient,\r\n resetRosterViews: dqfOperations.resetRosterViews,\r\n getClientList: concordeOperations.getClientList\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(CCRClientSelectorContainer);","import React from 'react';\r\n\r\nimport SelectorMode from '../SitesSelector/components/ClientSiteSelector/clientSiteSelectorComponent';\r\n\r\nconst simpleSitesSelectorComponent = props => {\r\n return (\r\n \r\n );\r\n};\r\n\r\nexport default simpleSitesSelectorComponent;","import React, {Component} from 'react';\r\nimport {connect} from 'react-redux';\r\nimport _ from 'lodash';\r\n\r\nimport SimpleSitesSelectorComponent from './simpleSitesSelectorComponent';\r\nimport {dqfOperations} from \"../../../ducks/dqf\";\r\n\r\n\r\nexport class SimpleSitesSelectorContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n selectedSite: {},\r\n selectedSites: [],\r\n placeholder: 'Select Location', // placeholder text in select mode\r\n onlySite: null, // is always set internally\r\n autoSelectSite: null, // set in mounting once\r\n showHierarchySearchBox: true\r\n }\r\n }\r\n\r\n componentDidMount() {\r\n\r\n const newState = {onlySite: null, autoSelectSite: null};\r\n\r\n if (this.props.sites.displaySite) {\r\n // reset the 'selected site' and 'selected sites' in Redux if the displayValue in Redux is equal to 'allSites'\r\n // and the implementation doesn't support the 'selectAll' option\r\n if (this.props.sites.displaySite._id === 'allSites' && !this.props.selectAll) {\r\n this.props.setSelectedSites([], {});\r\n } else {\r\n // otherwise, the selectedSite is can be set equal to the displaySite stored in Redux\r\n newState.selectedSite = this.props.sites.displaySite;\r\n }\r\n }\r\n\r\n if (this.props.displaySites && this.props.displaySites.length === 1) {\r\n newState.onlySite = this.props.displaySites[0];\r\n }\r\n\r\n newState.autoSelectSite = this.props.autoSelectSite || null;\r\n\r\n // set the 'selected site' with the provided value for autoSelectSite or the onlySite possible\r\n if (newState.autoSelectSite || newState.onlySite) {\r\n const autoSite = newState.autoSelectSite || newState.onlySite;\r\n newState.selectedSite = autoSite;\r\n const autoClickedSite = {value: autoSite._id, label: autoSite.name};\r\n this.setSitesForFlatSingleSelect(autoClickedSite, true);\r\n }\r\n\r\n this.setState({...newState});\r\n }\r\n\r\n shouldComponentUpdate(nextProps, nextState) {\r\n return this.props.sites.sessionClient !== nextProps.sites.sessionClient ||\r\n !_.isEqual(this.props.sites.displaySite, nextProps.sites.displaySite) ||\r\n !_.isEqual(this.props.displaySites, nextProps.displaySites) ||\r\n !_.isEqual(this.props.autoSelectSite, nextProps.autoSelectSite) ||\r\n !_.isEqual(this.state.selectedSite, nextState.selectedSite) || this.props.selectIsDisabled !== nextProps.selectIsDisabled;\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n const newState = {};\r\n let requiresReSelection = false;\r\n let sessionClientChanged = this.props.sites.sessionClient !== prevProps.sites.sessionClient;\r\n let reduxDisplaySiteChanged = !_.isEqual(this.props.sites.displaySite, prevProps.sites.displaySite);\r\n let displaySitesChanged = !_.isEqual(this.props.displaySites, prevProps.displaySites);\r\n let autoSelectSiteChanged = !_.isEqual(this.props.autoSelectSite, prevProps.autoSelectSite);\r\n\r\n if (autoSelectSiteChanged) {\r\n newState.autoSelectSite = this.props.autoSelectSite;\r\n requiresReSelection = true;\r\n }\r\n if (displaySitesChanged) {\r\n const isATT = this.props.sites.siteTree.legacyClientId === 513;\r\n newState.displaySites = this.props.displaySites.filter(site => isATT || !site.deactivated);\r\n newState.onlySite = newState.displaySites && newState.displaySites.length === 1 ? newState.displaySites[0] : null;\r\n requiresReSelection = true;\r\n }\r\n if (reduxDisplaySiteChanged && this.props.sites.displaySite && Object.keys(this.props.sites.displaySite).length > 0) {\r\n newState.selectedSite = this.props.sites.displaySite;\r\n }\r\n // note: a client selection change *should* always be an independent update from other prop changes passed into\r\n // the component. if that changes it possible 're selection' logic needs to be applied to the truthy condition\r\n\r\n if (!sessionClientChanged && requiresReSelection) {\r\n const onlySite = newState.onlySite || this.state.onlySite; // the updated 'onlySite' takes priority over the property in state\r\n const autoSelectSite = newState.autoSelectSite || this.state.autoSelectSite; // the updated 'autoSelectSite' takes priority over the priority in state\r\n const autoAssignSite = autoSelectSite || onlySite; // if both exist take the autSelectSite as that is defined by the user\r\n if (autoAssignSite) {\r\n newState.selectedSite = autoSelectSite;\r\n this.setSitesForFlatSingleSelect({\r\n value: autoAssignSite._id,\r\n label: autoAssignSite.name\r\n }, true);\r\n }\r\n }\r\n\r\n if (Object.keys(newState).length > 0) {\r\n this.setState({...newState});\r\n }\r\n\r\n }\r\n\r\n componentWillUnmount() {\r\n this.props.setAutoSelectSite(null);\r\n this.props.setSelectedHierarchySites([]);\r\n }\r\n\r\n /**\r\n * Event handler for when sites are selected in Flat Mode\r\n * @param selection - (array or object) react-select selected sites\r\n * multi select: e: [ value, name ]\r\n * single select - e: { value, name }\r\n */\r\n handleFlatModeSitesChanged = selection => {\r\n this.setSitesForFlatMode(selection);\r\n };\r\n\r\n setSitesForFlatMode = (selection) => {\r\n this.setSitesForFlatSingleSelect(selection);\r\n };\r\n\r\n setSitesForFlatSingleSelect = (site, broadcastOnly = false) => {\r\n const selectedSite = {_id: site.value, name: site.label};\r\n const selectedSites = [selectedSite];\r\n\r\n if (broadcastOnly) {\r\n this.broadcastChanges(selectedSites, selectedSite);\r\n } else {\r\n this.broadcastChangesAndSetState(selectedSites, selectedSite, false);\r\n }\r\n };\r\n\r\n broadcastChanges = (selectedSites, displaySite) => {\r\n this.props.setSelectedSites(selectedSites, displaySite);\r\n // We also separately record the selected site, so that it cab be reinstated on all pages that display a roster. This needs\r\n // to be done in case a user has \"drilled down\" to a driver at a child site, and then wants to return to the parent site\r\n // when viewing the roster again. We set it HERE because this component is ONLY used in the page header, to select a location.\r\n this.props.setRosterSelectedLocation(displaySite);\r\n // do we have a onSitesChangedProp to fire?\r\n if (this.props.onSitesChanged) {\r\n if (selectedSites.length > 0) {\r\n this.props.onSitesChanged(selectedSites, displaySite); // fire event handler if we found at least on site in withChildren mode\r\n }\r\n\r\n }\r\n };\r\n\r\n broadcastChangesAndSetState = (selectedSites, displaySite, allSitesSelected) => {\r\n this.broadcastChanges(selectedSites, displaySite);\r\n this.setState({\r\n selectedSites,\r\n selectedSite: displaySite,\r\n allSitesSelected\r\n })\r\n };\r\n\r\n render() {\r\n const isATT = this.props.sites.siteTree.legacyClientId === 513;\r\n return (\r\n isATT || !site.deactivated)}\r\n selectedSites={this.props.sites.selectedSites}\r\n selectedSite={this.state.selectedSite}\r\n selectAll={this.props.selectAll}\r\n allSitesSelected={this.state.allSitesSelected}\r\n hideSelect={!!(this.state.onlySite)}\r\n selectIsDisabled={!!this.props.selectIsDisabled}\r\n onSitesChanged={this.handleFlatModeSitesChanged}\r\n />\r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n sites: state.dqf ? state.dqf.sites : {}\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n setSelectedSites: dqfOperations.setSelectedSites,\r\n setSelectedHierarchySites: dqfOperations.setSelectedHierarchySites,\r\n setRosterSelectedLocation: dqfOperations.setRosterSelectedLocation,\r\n setAutoSelectSite: dqfOperations.setAutoSelectSite\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(SimpleSitesSelectorContainer);","import React, {Component} from 'react';\r\nimport {connect} from 'react-redux';\r\nimport {Link, withRouter} from 'react-router-dom'\r\nimport _ from 'lodash';\r\nimport classNames from 'classnames';\r\nimport Ticker from 'react-ticker';\r\nimport AuthenticatedLinks from './components/authenticatedLinksComponent';\r\nimport CCRClientSelectorContainer from \"../../Concorde/CCRClientSelector/CCRClientSelectorContainer\";\r\nimport SitesSelector from \"../../common/SimpleSitesSelector/SimpleSitesSelectorContainer\";\r\nimport {authOperations} from '../../../ducks/auth';\r\nimport {layoutOperations} from \"../../../ducks/layout\";\r\nimport {dqfOperations} from \"../../../ducks/dqf\";\r\nimport permissions from '../../../config/permissions';\r\nimport {hasPermission} from '../../../utils/permissions'\r\nimport {concordeClient} from '../../../config/concordeClient';\r\nimport {UncontrolledTooltip} from 'reactstrap';\r\nimport routes from '../../../routes';\r\n\r\nexport class HeaderComponent extends Component {\r\n\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n pauseTicker: false\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n // ignore call for ccr on mount -- ccr needs to select their session client from the list 'component did update'\r\n if (this.props.auth.isAuthenticated && !hasPermission(this.props.auth.user, permissions.customerCare.assumeClient)) {\r\n this.props.getSiteTreeForClient(this.props.auth.user.client._id, this.props.auth.user && this.props.auth.user.permissions ? this.props.auth.user.permissions.includes(permissions.customerCare.assumeClient) : false);\r\n }\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n if (this.props.location.pathname !== prevProps.location.pathname) {\r\n this.props.setSitesSelectorEnabled(false);\r\n }\r\n\r\n // non authenticated => authenticated\r\n if (this.props.auth.isAuthenticated && this.props.auth.isAuthenticated !== prevProps.auth.isAuthenticated) {\r\n this.props.getSiteTreeForClient(this.props.auth.user.client._id, this.props.auth.user && this.props.auth.user.permissions ? this.props.auth.user.permissions.includes(permissions.customerCare.assumeClient) : false);\r\n }\r\n\r\n // new client is selected in the CCR Client Selector\r\n //commenting this out because the set sites for user method is called and the sites and tree are now one call\r\n /*if (this.props.auth.isAuthenticated && hasPermission(this.props.auth.user, permissions.customerCare.assumeClient) && this.props.dqf.sites.sessionClient !== prevProps.dqf.sites.sessionClient) {\r\n this.props.getSiteTreeForClient(this.props.dqf.sites.sessionClient);\r\n }*/\r\n }\r\n\r\n handleLogoutClicked = () => {\r\n // NOTE -- do not do e.preventDefault() here. We want the logout link to go to the home page prior to logout so that\r\n // the next login will go to the home page (not the page the user was last on). Logout should wipe the slate clean :-).\r\n this.props.logoutUser();\r\n };\r\n\r\n handleToggleMenu = e => {\r\n e.preventDefault();\r\n this.props.setSidebar({isOpen: !(this.props.layout.sidebar.isOpen)});\r\n };\r\n\r\n // Recursive function to find the route that matches a path\r\n _findMatchingRoute = (routeTree, path) => {\r\n let currentRoute = null;\r\n let i = 0;\r\n while (!currentRoute && i < routeTree.length) {\r\n const route = routeTree[i];\r\n if (path === route.fullPath) {\r\n currentRoute = route;\r\n } else if (route.routes && route.routes.length > 0 && path.startsWith(route.fullPath)) {\r\n currentRoute = this._findMatchingRoute(route.routes, path);\r\n }\r\n i++;\r\n }\r\n return currentRoute;\r\n };\r\n\r\n handleCCRClientChanged = () => {\r\n this.props.setAlertCounts(null);\r\n // Look for an exact match of the path (the URL) in the list of all routes\r\n const currentRoute = this._findMatchingRoute(routes, this.props.location.pathname);\r\n // If there is no exact match, we are on a \"detail\" page (locaton, employee, etc.)\r\n // so we need to redirect to the home page because the client changed (otherwise,\r\n // we stay on the current page and it will update with the correct data).\r\n if (!currentRoute) {\r\n this.props.history.push('/');\r\n }\r\n };\r\n\r\n handleClickTicker = () => {\r\n this.setState({pauseTicker: !this.state.pauseTicker});\r\n };\r\n\r\n render() {\r\n const {isAuthenticated, user} = this.props.auth;\r\n const isAuditor = !!user.auditorToken;\r\n const showHideIndicator = this.props.layout.sidebar.isOpen ? 'hide' : 'show';\r\n return (\r\n \r\n )\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n dqf: state.dqf,\r\n layout: state.layout\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n logoutUser: authOperations.logoutUser,\r\n setSidebar: layoutOperations.setSidebar,\r\n getSiteTreeForClient: authOperations.getSitesForUser,\r\n setSitesSelectorEnabled: dqfOperations.setSitesSelectorEnabled,\r\n setAlertCounts: dqfOperations.setAlertCounts\r\n};\r\n\r\nexport default withRouter(connect(mapStateToProps, mapDispatchToProps)(HeaderComponent));","import React, {Fragment} from 'react';\r\nimport classNames from 'classnames';\r\nimport MenuEntry from '../MenuEntry/MenuEntryContainer';\r\n\r\nconst menuHeadingComponent = ({path, text, components, routes, expanded, needClient, onClick}) => {\r\n return (\r\n \r\n {!!text &&\r\n \r\n {text}\r\n
\r\n }\r\n {(!text || expanded) &&\r\n \r\n {components}\r\n {routes.map((route, index) => {\r\n return (\r\n \r\n );\r\n })}\r\n \r\n }\r\n \r\n );\r\n};\r\n\r\nexport default menuHeadingComponent;","import React, {Component} from 'react';\r\nimport {withRouter} from 'react-router-dom';\r\nimport {connect} from 'react-redux';\r\nimport {hasPermission} from '../../../../../utils/permissions';\r\nimport MenuHeadingComponent from './menuHeadingComponent';\r\n\r\nexport class MenuHeadingContainer extends Component {\r\n\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n hidden: false,\r\n needClient: false,\r\n expanded: false\r\n }\r\n }\r\n\r\n checkNeedClient = () => {\r\n // See if Concorde user is logged in and no client selected in session\r\n const needClient = this.props.section.needClient && this.props.auth.user.isConcordeUser && !this.props.dqf.sites.sessionClient;\r\n this.setState({needClient});\r\n };\r\n\r\n componentDidMount() {\r\n // Do nothing if it's an \"invisible\" menu heading\r\n if (!this.props.section.text) {\r\n return;\r\n }\r\n if (this.props.auth.user.isConcordeUser) {\r\n this.checkNeedClient();\r\n }\r\n }\r\n\r\n componentDidUpdate(prevProps) {\r\n // Do nothing if it's an \"invisible\" menu heading\r\n if (!this.props.section.text) {\r\n return;\r\n }\r\n // If the user is a Concorde user and the session client changed, check if need client\r\n if (this.props.auth.user.isConcordeUser && prevProps.dqf.sites.sessionClient !== this.props.dqf.sites.sessionClient) {\r\n this.checkNeedClient();\r\n }\r\n // If the active route changed and the menu section is expanded, and the route is not in our section, collapse\r\n if (prevProps.location.pathname !== this.props.location.pathname && this.state.expanded && !this.props.location.pathname.startsWith(this.props.section.path)) {\r\n this.setState({expanded: false});\r\n }\r\n }\r\n\r\n handleClick = () => {\r\n if (this.state.needClient || this.state.expanded || !this.props.section.routes || this.props.section.routes.length === 0) {\r\n return;\r\n }\r\n // Find the first route that the user has permiossion for\r\n const route = this.props.section.routes.find(route => route.inMenu && (!route.permission || hasPermission(this.props.auth.user, route.permission)));\r\n if (!route) {\r\n return;\r\n }\r\n this.setState({expanded: true}, () => this.props.history.push(route.fullPath));\r\n };\r\n\r\n render() {\r\n // If the section heading has a permission, make sure the user has it\r\n if (this.props.section.permission && !hasPermission(this.props.auth.user, this.props.section.permission)) {\r\n return null;\r\n }\r\n // If the section has section components, make sure the user has the permissions\r\n let sectionComponents = null;\r\n if (this.props.section.sectionComponents) {\r\n sectionComponents = this.props.section.sectionComponents.reduce((sectionComponents, sectionComponent, index) => {\r\n if (!sectionComponent.permission || hasPermission(this.props.auth.user, sectionComponent.permission)) {\r\n sectionComponents.push();\r\n }\r\n return sectionComponents;\r\n }, []);\r\n }\r\n // See if the user has permission for any of the routes in the section\r\n let hasAnyPermission = false;\r\n if (this.props.section.routes) {\r\n this.props.section.routes.forEach(route => {\r\n if (route.inMenu && (!route.permission || hasPermission(this.props.auth.user, route.permission))) {\r\n hasAnyPermission = true;\r\n }\r\n });\r\n }\r\n // If user has no permission, do not render\r\n if (!hasAnyPermission) {\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n );\r\n }\r\n\r\n};\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n dqf: state.dqf\r\n});\r\n\r\nexport default withRouter(connect(mapStateToProps, null)(MenuHeadingContainer));","import React from 'react';\r\nimport {NavLink} from 'react-router-dom';\r\nimport classNames from 'classnames';\r\n\r\nconst menuEntryComponent = ({path, entry, badgeNumber, needClient, onShowModal, indent}) => {\r\n if (!!entry.modal) {\r\n return (\r\n onShowModal(entry.modal)}\r\n >\r\n \r\n {entry.text}\r\n \r\n {(badgeNumber !== null) && {badgeNumber}}\r\n \r\n );\r\n }\r\n return (\r\n \r\n \r\n {entry.text}\r\n \r\n {(badgeNumber !== null) && {badgeNumber}}\r\n \r\n );\r\n};\r\n\r\nexport default menuEntryComponent;","import React, {Component} from 'react';\r\nimport {withRouter} from 'react-router-dom';\r\nimport {connect} from 'react-redux';\r\nimport MenuHeading from '../MenuHeading/MenuHeadingContainer';\r\nimport MenuEntryComponent from './menuEntryComponent';\r\nimport {modalOperations} from '../../../../../ducks/modal';\r\n\r\nclass MenuEntryContainer extends Component {\r\n\r\n handleShowModal = modal => {\r\n this.props.showModal(modal);\r\n };\r\n\r\n render() {\r\n const {path, entry} = this.props;\r\n // Only render if the entry belongs in the menu\r\n if (!entry.inMenu) {\r\n return null;\r\n }\r\n // If this entry is a menu heading, use the heading component\r\n if (entry.menuHeading) {\r\n return (\r\n \r\n );\r\n }\r\n const user = this.props.reduxState.auth.user;\r\n // If user does not have permission, do not render\r\n if (entry.permission && user.permissions.indexOf(entry.permission) === -1) {\r\n return null;\r\n }\r\n if (entry.isConcordeUser && !user.isConcordeUser) {\r\n return null;\r\n }\r\n // See if Concorde user is logged in and no client selected in session\r\n const sessionClient = this.props.reduxState.dqf.sites.sessionClient;\r\n const needClient = entry.needClient && user.isConcordeUser && !sessionClient;\r\n let badgeNumber = null;\r\n if (entry.badgeCalculator) {\r\n // Go through the list of arguments needed by the badge calculator, and copy them from the Redux state into an object\r\n const badgeCalculatorArguments = (entry.badgeCalculatorArguments || []).reduce((argAcccumulator, argument) => {\r\n argAcccumulator[argument] = this.props.reduxState[argument];\r\n return argAcccumulator;\r\n }, {});\r\n badgeNumber = entry.badgeCalculator(badgeCalculatorArguments);\r\n }\r\n return (\r\n \r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n reduxState: state\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n showModal: modalOperations.showModal\r\n};\r\n\r\nexport default withRouter(connect(mapStateToProps, mapDispatchToProps)(MenuEntryContainer));","import React from 'react';\r\nimport MenuEntry from './components/MenuEntry/MenuEntryContainer';\r\n\r\nconst sidebarComponent = props => {\r\n return (\r\n \r\n );\r\n};\r\n\r\nexport default sidebarComponent;","import React, {Component} from 'react';\r\nimport {withRouter} from 'react-router-dom';\r\nimport {connect} from 'react-redux';\r\nimport {subscribeToTaskListChange} from \"../../../utils/sockets/workflow\";\r\nimport {cmeOperations} from \"../../../ducks/cme\";\r\nimport {dqInternalOperations} from \"../../../ducks/dqInternal\";\r\nimport {sessionOperations} from \"../../../ducks/userSession\";\r\n\r\nimport routes from '../../../routes';\r\nimport SidebarComponent from './sidebarComponent';\r\nimport permissions from '../../../config/permissions';\r\nimport openSocket from 'socket.io-client';\r\n\r\nclass SidebarContainer extends Component {\r\n\r\n componentDidMount() {\r\n //subscribe to socket\r\n if (window.env.ENABLE_SOCKET_IO === true && \r\n (this.props.auth.user.permissions.includes(permissions.cme.searchAndMatch) \r\n || this.props.auth.user.permissions.includes(permissions.cme.review) \r\n || this.props.auth.user.permissions.includes(permissions.cme.secondReview) \r\n || this.props.auth.user.permissions.includes(permissions.cme.finalReview))\r\n ) {\r\n const socket2 = openSocket.connect();\r\n this.props.setUserSocket(socket2);\r\n subscribeToTaskListChange(socket2, socket => this.props.setCMETaskListFromSocket(socket.taskList));\r\n this.props.getCMETaskList();\r\n }\r\n if (this.props.auth.user.permissions.includes(permissions.dq.worklists)) {\r\n this.props.getDQTaskList(this.props.auth.user, true);\r\n }\r\n }\r\n\r\n componentWillUnmount() {\r\n if (this.props.userSession.socket) {\r\n this.props.userSession.socket.disconnect();\r\n }\r\n }\r\n\r\n render() {\r\n if (!!this.props.auth.user.auditorToken) {\r\n return null;\r\n }\r\n let routeList = routes;\r\n if (this.props.auth.user.isConcordeUser) {\r\n routeList = routeList.filter((route) => !route.externalOnly);\r\n }\r\n return \r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n userSession: state.userSession\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n getCMETaskList: cmeOperations.getCMETaskList,\r\n setCMETaskListFromSocket: cmeOperations.setCMETaskListFromSocket,\r\n getDQTaskList: dqInternalOperations.getDQTaskList,\r\n setUserSocket: sessionOperations.setSocket\r\n};\r\n\r\nexport default withRouter(connect(mapStateToProps, mapDispatchToProps)(SidebarContainer));","function subscribeToTaskListChange(socket, cb) {\r\n socket.on('update-cme-task-list-data', taskData => {\r\n cb(taskData);\r\n });\r\n}\r\n\r\nfunction subscribeToDQTaskListChange(socket, cb) {\r\n socket.on('update-dq-task-list-data', taskData => {\r\n cb(taskData);\r\n });\r\n}\r\n\r\nexport {subscribeToTaskListChange, subscribeToDQTaskListChange}","import React from 'react';\r\nimport {Link} from 'react-router-dom';\r\nimport {Breadcrumb, BreadcrumbItem} from 'reactstrap';\r\n\r\nconst breadcrumbsComponent = (props) => {\r\n const {route} = props;\r\n // Don't render a breadcrumb for the Home page\r\n if (route.path === '/' || !props.userAuthenticated) {\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n Home\r\n {route.breadcrumbs.map((breadcrumb, breadcrumbIndex) => {\r\n if (breadcrumbIndex === route.breadcrumbs.length - 1) {\r\n // If it's the \"tail\" of the breadcrumbs, render it as the active one\r\n return (\r\n \r\n {breadcrumb.text}\r\n \r\n );\r\n } else if (!!breadcrumb.text) {\r\n // Prior to the \"tail\" render each breadcrumb with a link (but only if it's not empty;\r\n // if empty, it's an invisible menu header used to group children under a path)\r\n return (\r\n \r\n \r\n {breadcrumb.text}\r\n \r\n \r\n );\r\n } else {\r\n return '';\r\n }\r\n })}\r\n \r\n );\r\n};\r\n\r\nexport default breadcrumbsComponent;","import React, {Component} from 'react';\r\nimport {withRouter, Route} from 'react-router-dom';\r\nimport {connect} from 'react-redux';\r\nimport routes from '../../../routes';\r\n\r\nimport BreadcrumbsComponent from './breadcrumbsComponent';\r\n\r\nclass BreadcrumbsContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n pathMap: {}\r\n }\r\n }\r\n\r\n /**\r\n * Recursively traverse all the routes, and build the breadcrumbs for each route. As each route is processed,\r\n * add it to the global routeList.\r\n *\r\n * @param pathList\r\n * @param breadcrumbs\r\n * @param routes\r\n * @private\r\n */\r\n _buildRouteBreadcrumbs = (pathList, breadcrumbs, routes) => {\r\n routes.forEach(route => {\r\n const newPathList = pathList.slice(0);\r\n newPathList.push(route.path);\r\n route.fullPath = newPathList.join('');\r\n const newBreadcrumbs = breadcrumbs.slice(0);\r\n const mappedPath = this.state.pathMap[route.absolutePath ? route.path : route.fullPath];\r\n let url = mappedPath ? mappedPath.url : route.absolutePath ? route.path : route.fullPath;\r\n if (route.menuHeading && route.routes && route.routes.length > 0) {\r\n url += route.routes[0].path;\r\n }\r\n const text = mappedPath ? mappedPath.text : route.text;\r\n newBreadcrumbs.push({text, url});\r\n route.breadcrumbs = newBreadcrumbs;\r\n this.routeList.push(route);\r\n // Process this route's \"children\"\r\n if (route.hasOwnProperty('routes')) {\r\n this._buildRouteBreadcrumbs(newPathList, newBreadcrumbs, route.routes);\r\n }\r\n });\r\n };\r\n\r\n static getDerivedStateFromProps(nextProps, prevState) {\r\n if (nextProps.breadcrumb.pathMap !== prevState.pathMap) {\r\n return {pathMap: nextProps.breadcrumb.pathMap};\r\n }\r\n return null;\r\n }\r\n\r\n render() {\r\n // Generate the breadcrumbs for the routes\r\n this.routeList = [];\r\n this._buildRouteBreadcrumbs([], [], routes);\r\n // Now produce an exact Route for each breadcrumb trail\r\n return (\r\n \r\n {this.routeList.map(route => {\r\n if (!route.showBreadcrumbs) {\r\n return null;\r\n }\r\n return (\r\n {\r\n return (\r\n \r\n );\r\n }} key={`${route.absolutePath ? route.path : route.fullPath}_${route.text}`}/>\r\n )\r\n })}\r\n
\r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n breadcrumb: state.breadcrumb,\r\n auth: state.auth\r\n});\r\n\r\nexport default withRouter(connect(mapStateToProps)(BreadcrumbsContainer));","import React, {Component} from 'react';\r\nimport axios from 'axios';\r\n\r\nimport FooterComponent from './footerComponent';\r\n\r\nexport class FooterContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n apiVersion: ''\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n this.getApiVersion();\r\n }\r\n\r\n getApiVersion = () => {\r\n axios.get('/v1')\r\n .then(response => {\r\n this.setState({apiVersion: response.data.version});\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n };\r\n\r\n render() {\r\n const {apiVersion} = this.state;\r\n return (\r\n \r\n );\r\n }\r\n\r\n}\r\n\r\nexport default FooterContainer;","import React from 'react';\r\nimport Select from 'react-select';\r\n\r\nconst transferDQFileComponent = props => {\r\n const targetSiteOptions = props.allowedTargetSites.map(site => ({value: site.legacyClientId, label: site.name}));\r\n targetSiteOptions.sort((a, b) => a.label.localeCompare(b.label));\r\n const jobTitleOptions = props.jobTitles.map(jobTitle => ({value: jobTitle.jobTitleId, label: jobTitle.jobTitle}));\r\n jobTitleOptions.sort((a, b) => a.label.localeCompare(b.label));\r\n const employmentStatusOptions = props.employmentStatuses.map(status => ({\r\n value: status.employmentStatusId,\r\n label: status.status\r\n }));\r\n employmentStatusOptions.sort((a, b) => a.label.localeCompare(b.label));\r\n const {currentSite} = props;\r\n return (\r\n <>\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n >\r\n );\r\n};\r\n\r\nexport default transferDQFileComponent;","import React, {Component} from 'react';\r\nimport {connect} from \"react-redux\";\r\nimport {Modal, ModalHeader, ModalBody, ModalFooter} from 'reactstrap';\r\nimport TransferDQFile from './transferDQFileComponent';\r\nimport axios from \"axios\";\r\nimport {alertsOperations} from '../../../../../../ducks/alerts';\r\nimport {modalOperations} from \"../../../../../../ducks/modal\";\r\nimport {Rnd} from \"react-rnd\";\r\nimport _ from 'lodash';\r\nimport {layoutOperations} from '../../../../../../ducks/layout';\r\n\r\nclass TransferEmployeeModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {};\r\n }\r\n\r\n componentDidMount() {\r\n this.cancelSource = axios.CancelToken.source();\r\n this.loadData();\r\n }\r\n\r\n componentWillUnmount() {\r\n this.cancelSource.cancel('userCanceled');\r\n this.props.resetLoadingPanel();\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n if (!_.isEqual(this.props.employeeInfo, prevProps.employeeInfo)) {\r\n this.loadData();\r\n }\r\n }\r\n\r\n loadData = () => {\r\n //the props are coming in on the info prop of the modal container, so map them to the ones we need\r\n this.setState({\r\n employeeInfo: this.props.info.employeeInfo,\r\n dropDownLists: this.props.info.dropDownLists,\r\n selectedTargetSite: this.props.info.selectedTargetSite,\r\n selectedJobTitle: this.props.info.selectedJobTitle,\r\n selectedEmploymentStatus: this.props.info.selectedEmploymentStatus\r\n });\r\n };\r\n\r\n handleTransferSelect = (propertyName, value) => {\r\n this.setState({[propertyName]: value});\r\n };\r\n\r\n performTransfer = () => {\r\n const employeeId = this.state.employeeInfo.employeeId;\r\n const {selectedTargetSite, selectedJobTitle, selectedEmploymentStatus} = this.state;\r\n this.props.showLoadingPanel();\r\n this.setState({transferInProgress: true}, () => {\r\n axios.patch(`/v1/employees/${employeeId}`, {\r\n transfer: {\r\n oldClientId: this.state.employeeInfo.legacyClientId,\r\n newClientId: selectedTargetSite.value,\r\n jobTitleId: selectedJobTitle.value,\r\n employmentStatusId: selectedEmploymentStatus.value\r\n }\r\n }, {cancelToken: this.cancelSource.token})\r\n .then(result => {\r\n this.props.hideLoadingPanel();\r\n this.props.hideModal(true);\r\n this.props.addAlert('The driver file was successfully transferred');\r\n if (result?.data?.length) {\r\n this.props.addAlert(result.data, 'info');\r\n }\r\n })\r\n .catch(err => {\r\n this.props.hideLoadingPanel();\r\n this.props.hideModal(true);\r\n this.props.addAlert('The transfer completed with issues. Please contact customer service.', 'danger');\r\n console.error(err);\r\n });\r\n });\r\n };\r\n\r\n cancelTransfer = () => {\r\n this.props.hideModal(false);\r\n };\r\n\r\n render() {\r\n const {\r\n employeeInfo, dropDownLists, selectedTargetSite, selectedJobTitle,\r\n selectedEmploymentStatus, transferInProgress\r\n } = this.state;\r\n\r\n if (!employeeInfo) {\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n \r\n Transfer {employeeInfo.firstName} {employeeInfo.lastName} to\r\n Another Work\r\n Location\r\n \r\n site.legacyClientId !== employeeInfo.legacyClientId && !site.deactivated)}\r\n selectedSite={selectedTargetSite}\r\n handleSelect={this.handleTransferSelect}\r\n jobTitles={dropDownLists.jobTitles}\r\n selectedJobTitle={selectedJobTitle}\r\n employmentStatuses={dropDownLists.employmentStatus}\r\n selectedEmploymentStatus={selectedEmploymentStatus}\r\n />\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n hideModal: modalOperations.hideModal,\r\n addAlert: alertsOperations.addAlert,\r\n showLoadingPanel: layoutOperations.showLoadingPanel,\r\n hideLoadingPanel: layoutOperations.hideLoadingPanel,\r\n resetLoadingPanel: layoutOperations.resetLoadingPanel\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(TransferEmployeeModalContainer);","import React, {Fragment} from 'react';\r\nimport Select from 'react-select';\r\n\r\nconst copySettingsModalComponent = props => {\r\n const targetSiteOptions = props.allowedTargetSites.map(site => ({value: site.legacyClientId, label: site.name}));\r\n targetSiteOptions.sort((a, b) => a.label.localeCompare(b.label));\r\n const {currentSite, selectedTargetSite} = props;\r\n return (\r\n \r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n \r\n );\r\n};\r\n\r\nexport default copySettingsModalComponent;","import React, {Component} from 'react';\r\nimport {connect} from \"react-redux\";\r\nimport {Modal, ModalHeader, ModalBody, ModalFooter} from 'reactstrap';\r\nimport axios from \"axios\";\r\nimport {modalOperations} from \"../../../../../../../ducks/modal\";\r\nimport CopySettingsModal from './copySettingsModalComponent'\r\nimport {alertsOperations} from \"../../../../../../../ducks/alerts\";\r\nimport _ from \"lodash\";\r\nimport {Rnd} from \"react-rnd\";\r\nimport {layoutOperations} from '../../../../../../../ducks/layout';\r\nimport clientsService from '../../../../../../../services/clientsService/clientsService';\r\n\r\nclass CopySettingsModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n //the props are coming in on the info prop of the modal container, so map them to the ones we need\r\n this.state = {\r\n legacyClientId: parseInt(props.info.legacyClientId, 10),\r\n clientId: props.info.mongoId,\r\n checkboxes: {},\r\n fullClient: null\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n if (this.state.clientId) {\r\n this.loadFullClient(this.state.clientId);\r\n }\r\n this.cancelSource = axios.CancelToken.source();\r\n }\r\n\r\n componentWillUnmount() {\r\n this.cancelSource.cancel('userCanceled');\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapShot) {\r\n if (!this.props.auth.user || !this.props.auth.user.sites) {\r\n return;\r\n }\r\n if (!prevProps.auth.user || !prevProps.auth.user.sites ||\r\n !_.isEqual(this.props.auth.user.sites, prevProps.auth.user.sites)) {\r\n this.loadFullClient(this.props.info.mongoId);\r\n this.setState({legacyClientId: parseInt(this.props.info.legacyClientId, 10), clientId: this.props.info.mongoId});\r\n }\r\n if (prevProps.info.legacyClientId !== this.props.info.legacyClientId) {\r\n this.loadFullClient(this.props.info.mongoId);\r\n this.setState({legacyClientId: parseInt(this.props.info.legacyClientId, 10), clientId: this.props.info.mongoId});\r\n }\r\n }\r\n\r\n loadFullClient = (mongoId) => {\r\n this.props.showLoadingPanel();\r\n clientsService.getClient(mongoId)\r\n .then((result) => {\r\n this.setState({fullClient: result});\r\n this.props.hideLoadingPanel();\r\n })\r\n .catch(() => {\r\n this.props.addAlert('Failed to load the full client', 'danger');\r\n this.props.hideLoadingPanel();\r\n })\r\n }\r\n\r\n handleCopySelect = (propertyName, value) => {\r\n this.setState({[propertyName]: value});\r\n };\r\n\r\n handleCheckBoxChange = (e) => {\r\n const {checkboxes} = this.state;\r\n checkboxes[e.target.name] = e.target.checked;\r\n this.setState({checkboxes});\r\n };\r\n\r\n\r\n cancelCopy = () => {\r\n this.props.hideModal(false);\r\n };\r\n\r\n performCopy = (e) => {\r\n e.preventDefault();\r\n const {checkboxes} = this.state; \r\n let fields = !!checkboxes.docTypes ? ['docTypes'] : [];\r\n if (!!checkboxes.users) {\r\n fields.push('users');\r\n }\r\n if (!!checkboxes.notifications) {\r\n fields.push('notifications');\r\n }\r\n if (!!checkboxes.medcardsubmissions) {\r\n fields.push('medcardsubmissions');\r\n }\r\n if (!!checkboxes.drivermonitoring) {\r\n fields.push('drivermonitoring');\r\n }\r\n this.props.showLoadingPanel();\r\n clientsService.copySettingsFromLocation(this.state.clientId, this.state.selectedTargetSite.value, fields, this.cancelSource.token)\r\n .then(result => {\r\n this.props.hideModal(true);\r\n this.props.addAlert('The settings were created successfully.', 'success');\r\n this.props.hideLoadingPanel();\r\n })\r\n .catch(err => {\r\n this.props.hideModal(true);\r\n this.props.addAlert('The settings were not copied.' + err.response.data, 'danger');\r\n this.props.hideLoadingPanel();\r\n console.log(err);\r\n });\r\n };\r\n\r\n render() {\r\n const {\r\n legacyClientId, selectedTargetSite, checkboxes, fullClient\r\n } = this.state;\r\n\r\n const currentSiteList = this.props.auth.user.sites.filter(site => site.legacyClientId === legacyClientId);\r\n const currentSite = currentSiteList && currentSiteList.length > 0 ? currentSiteList[0] : null;\r\n if (!currentSite || !currentSite.parent) {\r\n this.props.hideModal(false);\r\n this.props.addAlert('You cannot copy to this location', 'danger');\r\n return null;\r\n }\r\n\r\n if (!fullClient) {\r\n return null;\r\n }\r\n const allowedTargetSites = this.props.auth.user.sites.filter(site =>\r\n ((fullClient.parent && fullClient.parent.children.includes(site._id))\r\n || fullClient.parent._id === site._id)\r\n && site._id !== fullClient._id\r\n );\r\n\r\n const copyEnabled = this.state.selectedTargetSite && (this.state.checkboxes.notifications || \r\n this.state.checkboxes.users || \r\n this.state.checkboxes.docTypes ||\r\n this.state.checkboxes.medcardsubmissions ||\r\n this.state.checkboxes.drivermonitoring\r\n );\r\n\r\n return (\r\n \r\n \r\n Copy Settings from Another Location\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n )\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n hideModal: modalOperations.hideModal,\r\n addAlert: alertsOperations.addAlert,\r\n showLoadingPanel: layoutOperations.showLoadingPanel,\r\n hideLoadingPanel: layoutOperations.hideLoadingPanel\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(CopySettingsModalContainer);","import React, {Component} from 'react';\r\nimport {connect} from \"react-redux\";\r\nimport {Modal, ModalHeader, ModalBody, ModalFooter, Progress} from 'reactstrap';\r\nimport axios from \"axios\";\r\nimport {modalOperations} from \"../../../../../../../ducks/modal\";\r\nimport _ from \"lodash\";\r\nimport {Rnd} from \"react-rnd\";\r\nimport async from 'async';\r\n\r\nclass PushSettingsModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n //the props are coming in on the info prop of the modal container, so map them to the ones we need\r\n this.state = {\r\n legacyClientId: parseInt(props.info.legacyClientId, 10),\r\n clientId: props.info.mongoId,\r\n checkboxes: {}\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n this.cancelSource = axios.CancelToken.source();\r\n this.startSettingsPush();\r\n }\r\n\r\n componentWillUnmount() {\r\n this.cancelSource.cancel('userCanceled');\r\n }\r\n\r\n _siteList = [];\r\n\r\n componentDidUpdate(prevProps, prevState, snapShot) {\r\n if (!this.props.auth.user || !this.props.auth.user.sites) {\r\n return;\r\n }\r\n if (!prevProps.auth.user || !prevProps.auth.user.sites ||\r\n !_.isEqual(this.props.auth.user.sites, prevProps.auth.user.sites)) {\r\n this.setState({\r\n legacyClientId: parseInt(this.props.info.legacyClientId, 10),\r\n clientId: this.props.info.mongoId\r\n }, () => {\r\n this.startSettingsPush()\r\n });\r\n }\r\n if (prevProps.info.legacyClientId !== this.props.info.legacyClientId) {\r\n this.setState({\r\n legacyClientId: parseInt(this.props.info.legacyClientId, 10),\r\n clientId: this.props.info.mongoId\r\n }, () => {\r\n this.startSettingsPush()\r\n });\r\n }\r\n }\r\n\r\n getListOfChildren = (subTree, include) => {\r\n subTree.children.forEach((child) => {\r\n if (include) {\r\n this._siteList.push({\r\n legacyClientId: child.legacyClientId,\r\n id: child._id,\r\n name: child.name\r\n });\r\n this.getListOfChildren(child, true);\r\n } else {\r\n this.getListOfChildren(child, child._id === this.state.clientId);\r\n }\r\n });\r\n };\r\n\r\n startSettingsPush = () => {\r\n //get all the children.\r\n this._siteList = [];\r\n this.getListOfChildren(this.props.dqf.sites.siteTree, this.props.dqf.sites.siteTree._id === this.state.clientId);\r\n const siteCount = this._siteList.length;\r\n this.setState({siteCount, progress: 0, siteList: this._siteList}, () => {\r\n this.pushSettings(this._siteList, siteCount);\r\n });\r\n };\r\n\r\n pushSettings = (sitesToPushSettingsToList, siteCount) => {\r\n const errorList = [];\r\n async.eachOfSeries(sitesToPushSettingsToList, (site, e, cb) => {\r\n axios.patch(`/v1/clients/${site.id}?settingsFrom=${this.state.legacyClientId}&fields=docTypes,medcardsubmissions,drivermonitoring&legacy=true`, {}, {cancelToken: this.cancelSource.token})\r\n .then(() => {\r\n const progress = Math.floor(((e + 1) / siteCount) * 100);\r\n this.setState({progress});\r\n return cb(null);\r\n })\r\n .catch(err => {\r\n console.log(err);\r\n // Depending on where we generate an error on the backend, the 'response' property can have an 'errorText' property, an 'error' property, a 'message' property, or none of the above\r\n let errorMsg, detailedErrorMessage;\r\n if(err.response && err.response.data){\r\n if(err.response.data.errorText){ \r\n errorMsg = err.response.data.errorText;\r\n } else if(err.response.data.error){\r\n errorMsg = err.response.data.error;\r\n } else {\r\n errorMsg = 'Unknown error while completing settings copy';\r\n };\r\n if(err.response.data.message){ \r\n detailedErrorMessage = err.response.data.message;\r\n };\r\n } else {\r\n errorMsg = 'Unknown error while completing settings copy';\r\n };\r\n errorList.push({legacyClientId: site.legacyClientId, id: site.id, error: errorMsg, detailedErrorMessage, name: site.name});\r\n const progress = Math.floor(((e + 1) / siteCount) * 100);\r\n this.setState({progress});\r\n return cb(null);\r\n });\r\n }, err => {\r\n this.setState({complete: true, errorList});\r\n });\r\n };\r\n\r\n retrySettingsPush = () => {\r\n this.setState({progress: 0, siteList: this.state.errorList, siteCount: this.state.errorList.length, complete: false}, () => {\r\n this.pushSettings(this.state.errorList, this.state.errorList.length);\r\n });\r\n };\r\n\r\n finishCopy = () => {\r\n this.setState({\r\n complete: null,\r\n errorList: null,\r\n progress: null,\r\n siteCount: null,\r\n siteList: []\r\n });\r\n this.props.hideModal(true, {refreshData: true});\r\n };\r\n\r\n\r\n render() {\r\n const {\r\n progress, siteList, siteCount, errorList, complete\r\n } = this.state;\r\n\r\n if (!siteList) {\r\n return null;\r\n }\r\n return (\r\n \r\n \r\n \r\n Push{progress || progress === 0 ? 'ing' : ''} settings to the {siteList.length} child location{siteCount > 1 && 's'} \r\n \r\n \r\n {(progress || progress === 0) && !complete ?\r\n <>\r\n Progress: {progress}% of {siteCount} location{siteCount > 1 ? 's' : ''}
\r\n \r\n \r\n {complete &&\r\n <> \r\n {this.state.errorList && this.state.errorList.length > 0 && }\r\n \r\n >}\r\n \r\n \r\n \r\n )\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n dqf: state.dqf\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n hideModal: modalOperations.hideModal\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(PushSettingsModalContainer);","import React, {Fragment} from 'react';\r\nimport Select from 'react-select';\r\nimport StateSelect from '../../../../../common/StateSelect/StateSelect';\r\nimport DateInputWrapper from '../../../../../common/DateWrapper/DateInputWrapperContainer';\r\nimport moment from 'moment';\r\nimport classNames from 'classnames';\r\n\r\nimport LicenseNumberFormatOverride\r\n from '../../../../../common/DriverLicenseNumberFormatOverride/driverLicenseNumberFormatOverrideComponent';\r\n\r\nconst orderMVRModalComponent = props => {\r\n\r\n const licenseClasses = props.licenseClassList ? props.licenseClassList.map(c => ({\r\n value: c.licenseClassId,\r\n label: c.code\r\n })) : [];\r\n\r\n return (\r\n \r\n \r\n {props.message}\r\n
\r\n \r\n
\r\n
\r\n props.onDateChange(e, \"dob\")}\r\n name=\"dob\"\r\n id=\"dob\"\r\n autoComplete=\"new-password\"\r\n className={!props.employeeInfo.dob ? \"is-invalid form-control-sm form-control\" : \"form-control-sm form-control\"}\r\n dropdownMode={'scroll'}\r\n />\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n {props.licenseFormatInvalid &&\r\n \r\n }\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n props.onSelectChange(e, \"state\")}\r\n />\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n );\r\n};\r\n\r\nexport default orderMVRModalComponent;","import React, {Component} from 'react';\r\nimport {connect} from \"react-redux\";\r\nimport {Modal, ModalHeader, ModalBody, ModalFooter} from 'reactstrap';\r\nimport OrderMVR from './orderMVRModalComponent';\r\nimport axios from \"axios\";\r\nimport {alertsOperations} from '../../../../../../ducks/alerts';\r\nimport {modalOperations} from \"../../../../../../ducks/modal\";\r\nimport validator from '@civteam/cc-driver-license-validator';\r\nimport moment from 'moment';\r\nimport _ from 'lodash';\r\nimport {Rnd} from \"react-rnd\";\r\nimport settingsAPI from '../../../../../../services/settings';\r\n\r\nclass OrderMVRModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n //the props are coming in on the info prop of the modal container, so map them to the ones we need\r\n this.state = {};\r\n }\r\n\r\n componentDidMount() {\r\n this.cancelSource = axios.CancelToken.source();\r\n this.loadData();\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n if (!_.isEqual(this.props.info, prevProps.info)) {\r\n this.loadData();\r\n }\r\n }\r\n\r\n componentWillUnmount() {\r\n this.cancelSource.cancel('userCanceled');\r\n }\r\n\r\n loadData = async () => {\r\n let driversLicenseFormatRules;\r\n try {\r\n driversLicenseFormatRules = await settingsAPI.getDriversLicenseFormatRules(this.cancelSource.token);\r\n } catch (err) {\r\n console.error(err);\r\n }\r\n this.setState({\r\n employeeInfo: this.props.info.employeeInfo,\r\n message: this.props.info.message,\r\n licenseClassList: this.props.info.licenseClassList,\r\n licenseFormatInvalid: this.props.info.licenseFormatInvalid,\r\n driversLicenseFormatRules\r\n });\r\n };\r\n\r\n revalidateDriverLicenseInfo = (state, license) => {\r\n const dlState = state && state.trim().length > 0 ? state : null;\r\n const dlNum = license && license.trim().length > 0 ? license : null;\r\n if (dlState && dlNum && !this.state.overrideLicenseValidation) {\r\n const licenseFormatInvalid = !validator.validateLicenseNumber(dlNum, dlState, this.state.driversLicenseFormatRules);\r\n this.setState({licenseFormatInvalid});\r\n }\r\n };\r\n\r\n /**\r\n * on change handler for all of the editable fields uses the id to edit the field in the employeeInfo object\r\n * that corresponds to this item\r\n * @param e\r\n */\r\n handleChange = e => {\r\n const employeeInfo = _.cloneDeep(this.state.employeeInfo);\r\n employeeInfo[e.target.name] = e.target.value;\r\n if (e.target.name === 'license') {\r\n this.revalidateDriverLicenseInfo(employeeInfo.state, employeeInfo.license);\r\n }\r\n this.setState({employeeInfo});\r\n };\r\n\r\n /**\r\n * the change handler for the date field, uses the passed in name parameter to determine which field to update\r\n * @param date\r\n * @param name\r\n */\r\n handleDateChange = (date, name) => {\r\n const employeeInfo = _.cloneDeep(this.state.employeeInfo);\r\n employeeInfo[name] = date ? moment(date) : null;\r\n this.setState({employeeInfo});\r\n };\r\n\r\n /**\r\n * the change handler for the select fields, uses the passed in name parameter to determine which field to update\r\n * @param e\r\n * @param name\r\n */\r\n handleSelectChange = (e, name) => {\r\n const selectedItem = e ? e.value : -1;\r\n const employeeInfo = _.cloneDeep(this.state.employeeInfo);\r\n employeeInfo[name] = selectedItem;\r\n if (name === 'state') {\r\n // for 'state' we want an empty string if the input is cleared out\r\n employeeInfo[name] = selectedItem || '';\r\n this.revalidateDriverLicenseInfo(employeeInfo.state, employeeInfo.license);\r\n }\r\n this.setState({employeeInfo});\r\n };\r\n\r\n\r\n /**\r\n * validateMVRInfo - before ordering an mvr, verify that the fields are valid\r\n * @returns {{message: string, validData: boolean}}\r\n */\r\n validateMVRInfo = (employeeInfo) => {\r\n let validData = true;\r\n let message = '';\r\n let licenseFormatInvalid = false;\r\n const dlState = employeeInfo.state && employeeInfo.state.trim().length > 0 ? employeeInfo.state : null;\r\n const dlNum = employeeInfo.license && employeeInfo.license.trim().length > 0 ? employeeInfo.license : null;\r\n\r\n if (!dlState || !dlNum || !employeeInfo.dob || !employeeInfo.licenseClassId) {\r\n validData = false;\r\n message = 'You must fill in all of the required fields.'\r\n }\r\n if (dlState && dlNum) {\r\n if (!this.state.overrideLicenseValidation && !validator.validateLicenseNumber(dlNum, dlState, this.state.driversLicenseFormatRules)) {\r\n validData = false;\r\n licenseFormatInvalid = true;\r\n message = `You must update the driver's license information. The number ${dlNum} is invalid for ${dlState}`;\r\n }\r\n }\r\n return {message, validData, licenseFormatInvalid};\r\n };\r\n\r\n placeOrder = async () => {\r\n const {employeeInfo} = this.state;\r\n const {validData, message, licenseFormatInvalid} = this.validateMVRInfo(employeeInfo);\r\n if (validData) {\r\n await this.setStateAsync({orderPlaced: true});\r\n const updates = {\r\n dob: employeeInfo.dob,\r\n license: employeeInfo.license,\r\n state: employeeInfo.state,\r\n licenseClassId: employeeInfo.licenseClassId\r\n };\r\n axios.patch(`/v1/employees/${employeeInfo.employeeId}`, updates, {cancelToken: this.cancelSource.token})\r\n .then(() => {\r\n this.props.addAlert('Employee information updated successfully');\r\n const info = {\r\n employeeInfo: this.state.employeeInfo,\r\n refreshData: true,\r\n employeeId: this.state.employeeInfo.employeeId //employee id is needed separately for the dac order mvr buttons\r\n };\r\n this.props.showModal('verification', info);\r\n })\r\n .catch(err => {\r\n this.props.addAlert('Employee information could not be updated.', 'danger');\r\n });\r\n } else {\r\n this.props.addAlert(message, 'danger');\r\n this.setState({message, licenseFormatInvalid});\r\n }\r\n };\r\n\r\n cancelOrderPlacement = () => {\r\n this.props.hideModal(false);\r\n };\r\n\r\n handleOverrideValidation = e => {\r\n const employeeInfo = {...this.state.employeeInfo};\r\n this.setState({overrideLicenseValidation: e.target.checked}, () => {\r\n this.revalidateDriverLicenseInfo(employeeInfo.state, employeeInfo.license)\r\n });\r\n };\r\n\r\n setStateAsync = state => {\r\n return new Promise(resolve => {\r\n this.setState({...state}, () => resolve())\r\n });\r\n };\r\n\r\n\r\n render() {\r\n const {\r\n employeeInfo, message, licenseClassList, licenseFormatInvalid\r\n } = this.state;\r\n\r\n if (!employeeInfo) {\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n \r\n Update Information\r\n for {employeeInfo.firstName} {employeeInfo.lastName} \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n hideModal: modalOperations.hideModal,\r\n addAlert: alertsOperations.addAlert,\r\n showModal: modalOperations.showModal\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(OrderMVRModalContainer);","import React, {Fragment} from 'react';\r\n\r\nconst orderMVRModalComponent = props => {\r\n return (\r\n \r\n {props.content}\r\n \r\n );\r\n};\r\n\r\nexport default orderMVRModalComponent;","import React, {Component, Fragment} from 'react';\r\nimport {connect} from \"react-redux\";\r\nimport {Modal, ModalHeader, ModalBody, ModalFooter} from 'reactstrap';\r\nimport VerificationModal from './verificationOfFCRAModalComponent';\r\nimport axios from \"axios\";\r\nimport {alertsOperations} from '../../../../ducks/alerts';\r\nimport {modalOperations} from \"../../../../ducks/modal\";\r\nimport ReactHtmlParser from 'react-html-parser';\r\nimport {Rnd} from \"react-rnd\";\r\n\r\nclass VerificationOfFCRAModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n //the props are coming in on the info prop of the modal container, so map them to the ones we need\r\n this.state = {\r\n refreshData: props.info && props.info.refreshData ? props.info.refreshData : false,\r\n content: null\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n this.cancelSource = axios.CancelToken.source();\r\n axios.get(`/v1/settings/documents/verification`, {cancelToken: this.cancelSource.token})\r\n .then(response => {\r\n this.setState({content: {ReactHtmlParser(response.data.contents)}
})\r\n }).catch(err => {\r\n console.log(err);\r\n this.props.addAlert('The verification content could not be loaded.', 'danger');\r\n });\r\n }\r\n\r\n componentWillUnmount() {\r\n this.cancelSource.cancel('userCanceled');\r\n }\r\n\r\n\r\n acceptVerification = async () => {\r\n if (this.state.accepted) {\r\n return; // prevent calling hide modal prop twice\r\n }\r\n await this.setStateAsync({accepted: true});\r\n this.props.hideModal(true, {dialogAccepted: true, info: this.props.info});\r\n };\r\n\r\n cancelVerification = () => {\r\n this.props.hideModal(true);\r\n };\r\n\r\n setStateAsync = state => {\r\n return new Promise(resolve => {\r\n this.setState({...state}, () => resolve())\r\n });\r\n };\r\n\r\n render() {\r\n const {content} = this.state;\r\n if (!content) {\r\n return null;\r\n }\r\n return (\r\n \r\n \r\n \r\n You must verify your consent under the Fair Credit Reporting\r\n Act\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n )\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n hideModal: modalOperations.hideModal,\r\n addAlert: alertsOperations.addAlert\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(VerificationOfFCRAModalContainer);","import React, {Fragment} from 'react';\r\nimport StateSelect from '../../../../../../../common/StateSelect/StateSelect';\r\nimport DateInputWrapper from '../../../../../../../common/DateWrapper/DateInputWrapperContainer';\r\nimport moment from 'moment';\r\n\r\nconst addAccidentModalComponent = props => {\r\n\r\n return (\r\n \r\n \r\n
\r\n
\r\n props.onDateChange(e, \"date\")}\r\n name=\"date\"\r\n id=\"date\"\r\n autoComplete=\"new-password\"\r\n className={props.showFieldValidation && !props.accidentInfo.date ? \"is-invalid form-control-sm form-control\" : \"form-control-sm form-control\"}\r\n dropdownMode={'scroll'}\r\n />\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n props.onSelectChange(e, \"state\")}\r\n />\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n );\r\n};\r\n\r\nexport default addAccidentModalComponent;","import React, {Component} from 'react';\r\nimport {connect} from \"react-redux\";\r\nimport {Modal, ModalHeader, ModalBody, ModalFooter} from 'reactstrap';\r\nimport axios from \"axios\";\r\nimport {alertsOperations} from '../../../../../../../../ducks/alerts/index';\r\nimport {modalOperations} from \"../../../../../../../../ducks/modal/index\";\r\nimport moment from 'moment';\r\nimport _ from 'lodash';\r\nimport {Rnd} from \"react-rnd\";\r\n\r\nimport AddAccidentModal from './addAccidentModalComponent';\r\nimport ConfirmActionModal from '../../../../../../../common/ConfirmActionModal/ConfirmActionModal';\r\n\r\nclass AddAccidentModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n //the props are coming in on the info prop of the modal container, so map them to the ones we need\r\n this.state = {\r\n accidentInfo: {}\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n this.cancelSource = axios.CancelToken.source();\r\n this.setState({\r\n accidentInfo: {\r\n legacyClientId: this.props.info.legacyClientId\r\n },\r\n employeeId: this.props.info.employeeId\r\n });\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n if (prevProps.info.employeeId !== this.props.info.employeeId) {\r\n this.setState({employeeId: this.props.info.employeeId});\r\n }\r\n }\r\n\r\n componentWillUnmount() {\r\n this.cancelSource.cancel('userCanceled');\r\n }\r\n\r\n /**\r\n * on change handler for all of the editable fields\r\n * @param e\r\n */\r\n handleChange = e => {\r\n const accidentInfo = _.cloneDeep(this.state.accidentInfo);\r\n let showConfirmModal = false;\r\n if (e.target.id === 'cited') {\r\n if (e.target.checked) {\r\n showConfirmModal = true;\r\n } else {\r\n accidentInfo[e.target.id] = e.target.checked\r\n }\r\n } else if (e.target.id === 'hazmat') {//the checkboxes\r\n accidentInfo[e.target.id] = e.target.checked;\r\n } else {\r\n accidentInfo[e.target.name] = e.target.value;\r\n }\r\n\r\n this.setState({accidentInfo, showConfirmModal});\r\n };\r\n\r\n /**\r\n * the change handler for the date field, uses the passed in name parameter to determine which field to update\r\n * @param date\r\n * @param name\r\n */\r\n handleDateChange = (date, name) => {\r\n const accidentInfo = _.cloneDeep(this.state.accidentInfo);\r\n accidentInfo[name] = date ? moment(date) : null;\r\n this.setState({accidentInfo});\r\n };\r\n\r\n /**\r\n * the change handler for the select fields, uses the passed in name parameter to determine which field to update\r\n * @param e\r\n * @param name\r\n */\r\n handleSelectChange = (e, name) => {\r\n const selectedItem = e ? e.value : -1;\r\n const accidentInfo = _.cloneDeep(this.state.accidentInfo);\r\n accidentInfo[name] = selectedItem;\r\n if (name === 'state') {\r\n // for 'state' we want an empty string if the input is cleared out\r\n accidentInfo[name] = selectedItem || '';\r\n }\r\n this.setState({accidentInfo});\r\n };\r\n\r\n addAccident = () => {\r\n const {dataIsValid, message} = this.validData();\r\n if (!dataIsValid) {\r\n this.setState({showFieldValidation: true});\r\n this.props.addAlert(message, 'danger');\r\n } else {\r\n const {accidentInfo} = this.state;\r\n accidentInfo.fatalities = parseInt(accidentInfo.fatalities, 10);\r\n accidentInfo.disabled = parseInt(accidentInfo.disabled, 10);\r\n accidentInfo.injuries = parseInt(accidentInfo.injuries, 10);\r\n accidentInfo.addedBy = this.props.auth && this.props.auth.user ? this.props.auth.user.email : '';\r\n axios.post(`/v1/employees/${this.state.employeeId}/accidents`, accidentInfo, {cancelToken: this.cancelSource.token})\r\n .then(result => {\r\n this.props.addAlert('Accident Added successfully');\r\n this.setState({showFieldValidation: false});\r\n this.props.hideModal(true);\r\n }).catch(err => {\r\n //dispatch errors?\r\n console.log('error adding accident');\r\n this.props.addAlert('Error Adding Accident', 'danger');\r\n });\r\n }\r\n };\r\n\r\n validData = () => {\r\n const {accidentInfo} = this.state;\r\n if (!accidentInfo.fatalities || !accidentInfo.disabled || !accidentInfo.injuries) {\r\n return {dataIsValid: false, message: 'You must fill in all required fields.'};\r\n }\r\n if (!accidentInfo.state || !accidentInfo.city || !accidentInfo.date) {\r\n return {dataIsValid: false, message: 'You must fill in all required fields.'};\r\n }\r\n if (isNaN(accidentInfo.fatalities) || isNaN(accidentInfo.disabled) || isNaN(accidentInfo.injuries)) {\r\n return {dataIsValid: false, message: 'Number of fatalities, disabled vehicles and injuries must be numbers'};\r\n }\r\n return {dataIsValid: true, message: ''};\r\n };\r\n\r\n cancelAdd = () => {\r\n this.props.hideModal(false);\r\n };\r\n\r\n handleModalConfirmClick = () => {\r\n const accidentInfo = _.cloneDeep(this.state.accidentInfo);\r\n accidentInfo.cited = true;\r\n this.setState({accidentInfo, showConfirmModal: false});\r\n };\r\n\r\n render() {\r\n const {accidentInfo, showConfirmModal, showFieldValidation} = this.state;\r\n\r\n return (showConfirmModal ? \r\n : \r\n \r\n Add Accident \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n hideModal: modalOperations.hideModal,\r\n addAlert: alertsOperations.addAlert,\r\n showModal: modalOperations.showModal\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(AddAccidentModalContainer);","import React, {Fragment} from 'react';\r\nimport Select from 'react-select';\r\n\r\nconst dotNumberModalComponent = props => {\r\n\r\n //const dotList = props.dotList.map((item) => item);\r\n return (\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n \r\n );\r\n};\r\n\r\nexport default dotNumberModalComponent;","import React, {Component, Fragment} from 'react';\r\nimport {connect} from \"react-redux\";\r\nimport {Modal, ModalHeader, ModalBody, ModalFooter} from 'reactstrap';\r\nimport axios from \"axios\";\r\nimport {modalOperations} from \"../../../../../../../../../ducks/modal/index\";\r\nimport DOTNumberModal from './dotNumberModalComponent'\r\nimport {alertsOperations} from \"../../../../../../../../../ducks/alerts/index\";\r\nimport _ from \"lodash\";\r\nimport {Rnd} from 'react-rnd';\r\n\r\nclass DOTNumberModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n //the props are coming in on the info prop of the modal container, so map them to the ones we need\r\n this.state = {};\r\n }\r\n\r\n componentDidMount() {\r\n this.showDOTModal();\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n if (this.props.info.selectedClientId !== prevProps.info.selectedClientId) {\r\n this.showDOTModal();\r\n }\r\n }\r\n\r\n showDOTModal = () => {\r\n axios.get(`/v1/clients/${this.props.info.selectedClientId}/children?source=legacy&includeParent=true&forUser=${this.props.auth.user._id}`)\r\n .then(response => {\r\n const dotListWithDupes = response.data.filter((item) => {\r\n return item.DOTNumber && item.DOTNumber !== ''\r\n }).map((item) => {\r\n return {value: item.DOTNumber, label: item.DOTNumber}\r\n });\r\n const dotList = _.uniqBy(dotListWithDupes, (item) => {\r\n return item.value.trim();\r\n });\r\n if (dotList && dotList.length === 1) {\r\n this.props.hideModal(false, [dotList[0].value]); //if there is only one location, dont' show the modal\r\n } else if (dotList && dotList.length === 0) {\r\n this.props.addAlert('There are no DOT numbers associated with this location.', 'danger');\r\n this.props.hideModal(false, []);\r\n } else {\r\n this.setState({dotList: dotList});\r\n }\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n };\r\n\r\n selectNumbers = () => {\r\n if (this.state.selectedItems && this.state.selectedItems.length > 0) {\r\n this.props.hideModal(false, this.state.selectedItems.map((item) => item.value));\r\n } else {\r\n this.props.hideModal(false, []);\r\n }\r\n\r\n };\r\n\r\n handleDOTListChange = (options) => {\r\n this.setState({selectedItems: options});\r\n };\r\n\r\n render() {\r\n\r\n const {dotList} = this.state;\r\n if (!dotList) {\r\n return null;\r\n }\r\n return (\r\n \r\n \r\n \r\n Select DOT Number(s) to run report for\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n )\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n hideModal: modalOperations.hideModal,\r\n addAlert: alertsOperations.addAlert\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(DOTNumberModalContainer);","import React, {Fragment} from 'react';\r\nimport {UncontrolledTooltip} from 'reactstrap';\r\n\r\nconst drugAlcoholQuestionModalComponent = props => {\r\n\r\n return (\r\n \r\n \r\n
\r\n
\r\n 1. Did the employee have alcohol tests with a result of 0.04 or higher?\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n 2. Did the Employee complete a DOT negative return-to-duty test result as prescribed by a Substance\r\n Abuse Professional (SAP) (49 CFR Part 40 or 382)? Did the Employee complete a DOT negative return-to-duty\r\n test result as prescribed by a Substance Abuse Professional (SAP) (49 CFR Part 40 or 382)?\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
- Note: this is not return to duty from extended leave or other\r\n reasons not prescribed by a SAP.\r\n
\r\n
\r\n
\r\n 3. Did the Employee refuse to take an alcohol test pursuant to 49 CFR 40.261?\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n 4. Did the employee refuse a drug test, with the situation specifically listed below: (Must check one\r\n that applies)\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n {props.showQ4Details &&
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
}\r\n
\r\n
\r\n 5. Has the driver successfully completed all follow-up tests as prescribed in the SAP report in\r\n accordance with §§ 40.307, 40.309, and 40.311 of this title. (if so final SAP report must be uploaded)\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n 6. Has the Employee had the any of the following violations of which the employer obtains \r\n actual knowledge, as defined at § 382.107, of: \r\n (Must check all that\r\n apply)\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n {props.showQ6Details &&
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n props.onChecklistChange(e)}\r\n />\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
}\r\n
\r\n DOT Notices within the regulations:\r\n
\r\n
\r\n 49CFR Part 382.705(e): Reporting truthfully and accurately. Every person or entity with access must report\r\n truthfully and accurately to the Clearinghouse and is expressly prohibited from reporting information he or\r\n she knows or should know is false or inaccurate.\r\n
\r\n
\r\n 49CFR Part 382.705(c) C/TPAs. Any employer may designate a C/TPA to perform the employer requirements in\r\n paragraph (b) of this section. Regardless of whether it uses a C/TPA to perform its requirements, the\r\n employer retains ultimate responsibility for compliance with this section. Exception: An employer does not\r\n retain responsibility where the C/TPA is designated to comply with employer requirements as described in\r\n paragraph (b)(6) [owner-operator] of this section.\r\n
\r\n
\r\n \r\n Actual knowledge for the purpose of subpart B of this part, means actual knowledge by an employer that a\r\n driver has used alcohol or controlled substances based on the employer's direct observation of the employee,\r\n information provided by the driver's previous employer(s), a traffic citation for driving a CMV while under\r\n the influence of alcohol or controlled substances or an employee's admission of alcohol or controlled\r\n substance use, except as provided in §382.121. Direct observation as used in this definition means observation\r\n of alcohol or controlled substances use and does not include observation of employee behavior or physical\r\n characteristics sufficient to warrant reasonable suspicion testing under §382.307. As used in this section,\r\n “traffic citation” means a ticket, complaint, or other document charging driving a CMV while under the\r\n influence of alcohol or controlled substances.\r\n \r\n {props.showQ6Details && \r\n No driver shall use alcohol while performing safety-sensitive functions. No employer having actual knowledge\r\n that a driver is using alcohol while performing safety-sensitive functions shall permit the driver to perform\r\n or continue to perform safety-sensitive functions\r\n \r\n \r\n No driver shall perform safety-sensitive functions within four hours after using alcohol. No employer having\r\n actual knowledge that a driver has used alcohol within four hours shall permit a driver to perform or\r\n continue\r\n to perform safety-sensitive functions.\r\n \r\n \r\n No driver required to take a post-accident alcohol test under §382.303 shall use alcohol for eight hours\r\n following the accident, or until he/she undergoes a post-accident alcohol test, whichever occurs first.\r\n \r\n \r\n (a) No driver shall report for duty or remain on duty requiring the performance of safety sensitive\r\n functions\r\n when the driver uses any drug or substance identified in 21 CFR 1308.11 Schedule I.\r\n (b) No driver shall report for duty or remain on duty requiring the performance of safety-sensitive\r\n functions\r\n when the driver uses any non-Schedule I drug or substance that is identified in the other Schedules in 21\r\n CFR\r\n part 1308 except when the use is pursuant to the instructions of a licensed medical practitioner, as defined\r\n in §382.107, who is familiar with the driver's medical history and has advised the driver that the substance\r\n will not adversely affect the driver's ability to safely operate a commercial motor vehicle.\r\n (c) No employer having actual knowledge that a driver has used a controlled substance shall permit the\r\n driver\r\n to perform or continue to perform a safety-sensitive function.\r\n (d) An employer may require a driver to inform the employer of any therapeutic drug use.\r\n }\r\n \r\n );\r\n};\r\n\r\nexport default drugAlcoholQuestionModalComponent;","import React, {Fragment} from 'react';\r\nimport Dropzone from 'react-dropzone';\r\nimport classNames from 'classnames';\r\n\r\nconst multiFileUploadComponent = ({\r\n className,\r\n onFileSelect,\r\n fileList\r\n }) => {\r\n\r\n return (\r\n \r\n {fileList && fileList.length > 0 &&\r\n \r\n
Files Currently Marked for Upload
\r\n
\r\n {fileList.map((file, index) => {\r\n return
{file.name}
\r\n })\r\n }\r\n
\r\n
}\r\n \r\n
\r\n
\r\n
\r\n {({getRootProps, getInputProps, isDragActive}) => {\r\n return \r\n
\r\n
\r\n {isDragActive\r\n ?
Drop file here...
\r\n :\r\n
Drag a PDF file and drop it here, or click here to select\r\n a\r\n file
\r\n }\r\n
\r\n
\r\n }}\r\n \r\n
\r\n
\r\n
\r\n \r\n );\r\n};\r\n\r\nexport default multiFileUploadComponent;","import React, {Fragment} from 'react';\r\nimport {UncontrolledTooltip} from 'reactstrap';\r\nimport MultiFileUploadContainer from './multiFileUploadComponent';\r\n\r\nconst drugAlcoholUploadModalComponent = props => {\r\n\r\n return (\r\n \r\n {(props.checklist.q1 || props.checklist.q2 || props.checklist.q5) &&\r\n \r\n
The information required to be reported under all questions listed\r\n above must include, as applicable:\r\n
\r\n
\r\n
\r\n
(i)
\r\n
Reason for the test;
\r\n
\r\n
\r\n
(ii)
\r\n
Driver's name, date of birth, and CDL number and State of\r\n issuance;\r\n
\r\n
\r\n
\r\n
(iii)
\r\n
Employer name, address, and USDOT number;
\r\n
\r\n
\r\n
(iv)
\r\n
Date of the test;
\r\n
\r\n
\r\n
(v)
\r\n
Date the result was reported; and
\r\n
\r\n
\r\n
(vi)
\r\n
Test result. The test result must be one of the following:
\r\n
\r\n
\r\n
\r\n
(A)
\r\n
Negative (only required for return-to-duty tests administered in\r\n accordance with § 382.309);\r\n
\r\n
\r\n
\r\n
(B)
\r\n
Positive; or
\r\n
\r\n
\r\n
(C)
\r\n
Refusal to take a test.(see directly below for additional\r\n documentation requirements).\r\n
\r\n
\r\n
\r\n
\r\n
\r\n }\r\n {(props.checklist.q3 || props.checklist.q4) &&\r\n \r\n
For each report of a REFUSAL violation of 49 CFR 40.261(a)(1) or\r\n 40.191(a)(1), the employer must report the following information:\r\n
\r\n
\r\n
\r\n
(i)
\r\n
Documentation, including, but not limited to, electronic mail or\r\n other contemporaneous record of the time and date the driver was notified to appear at a testing site;\r\n and the time, date and testing site location at which the employee was directed to appear, or an\r\n affidavit providing evidence of such notification;\r\n
\r\n
\r\n
\r\n
(ii)
\r\n
Documentation, including, but not limited to, electronic mail or\r\n other correspondence, or an affidavit, indicating the date the employee was terminated or resigned (if\r\n applicable);\r\n
\r\n
\r\n
\r\n
(iii)
\r\n
Documentation, including, but not limited to, electronic mail or\r\n other correspondence, or an affidavit, showing that the C/TPA reporting the violation was designated\r\n as a service agent for an employer who employs himself/herself as a driver pursuant to paragraph (b)\r\n (6) (Owner-Operators) of this section when the reported refusal occurred (if applicable); and\r\n
\r\n
\r\n
\r\n
(iv)
\r\n
Documentation, including a certificate of service or other evidence\r\n [i.e. mail, email, affidavit of discussion, memorandum], showing that the employer provided the\r\n employee with all documentation reported under paragraph (b)(3) (REFUSALS) of this section.\r\n
\r\n
\r\n
\r\n
\r\n }\r\n {props.checklist.q6 &&\r\n \r\n
\r\n
For each of the actual knowledge violations as\r\n listed in the question above, the employer must report the following information:\r\n
\r\n
\r\n
\r\n
(i)
\r\n
Driver's name, date of birth, CDL number and State of issuance\r\n
\r\n
\r\n
\r\n
(ii)
\r\n
Employer name, address, and USDOT number, if applicable;
\r\n
\r\n
\r\n
(iii)
\r\n
Date the employer obtained actual knowledge of\r\n the violation;\r\n
\r\n
\r\n
\r\n
(iv)
\r\n
Witnesses to the violation, if any, including contact\r\n information;\r\n
\r\n
\r\n
\r\n
(v)
\r\n
Description of the violation;\r\n
\r\n
\r\n
\r\n
(vi)
\r\n
Evidence supporting each fact alleged in the description of the\r\n violation required under paragraph (b)(4) of this section, which may include, but is not limited to,\r\n affidavits, photographs, video or audio recordings, employee statements (other than admissions\r\n pursuant to § 382.121), correspondence, or other documentation; and\r\n
\r\n
\r\n
\r\n
(vii)
\r\n
A certificate of service or other evidence showing that the\r\n employer provided the employee with all information reported under paragraph (b)(4) of this section.\r\n
\r\n
\r\n
\r\n
\r\n
\r\n }\r\n {props.docType ? : Client Not Configured for Drug and Alcohol Document\r\n Uploads
}\r\n {props.checklist.q6 &&\r\n \r\n Actual knowledge for the purpose of subpart B of this part, means actual knowledge by an employer that a\r\n driver has used alcohol or controlled substances based on the employer's direct observation of the employee,\r\n information provided by the driver's previous employer(s), a traffic citation for driving a CMV while under\r\n the influence of alcohol or controlled substances or an employee's admission of alcohol or controlled\r\n substance use, except as provided in §382.121. Direct observation as used in this definition means\r\n observation\r\n of alcohol or controlled substances use and does not include observation of employee behavior or physical\r\n characteristics sufficient to warrant reasonable suspicion testing under §382.307. As used in this section,\r\n “traffic citation” means a ticket, complaint, or other document charging driving a CMV while under the\r\n influence of alcohol or controlled substances.\r\n }\r\n \r\n );\r\n};\r\n\r\nexport default drugAlcoholUploadModalComponent;","import React, {Component, Fragment} from 'react';\r\nimport {connect} from \"react-redux\";\r\nimport {Modal, ModalHeader, ModalBody, ModalFooter} from 'reactstrap';\r\nimport axios from \"axios\";\r\nimport {modalOperations} from \"../../../../../../../../ducks/modal\";\r\nimport DrugAlcoholQuestionModal from './drugAlcoholQuestionModalComponent';\r\nimport DrugAlcoholUploadModalComponent from './drugAlcoholUploadModalComponent';\r\nimport {alertsOperations} from \"../../../../../../../../ducks/alerts\";\r\nimport _ from 'lodash';\r\nimport async from 'async';\r\nimport {Rnd} from \"react-rnd\";\r\nimport ConfirmActionModal from '../../../../../../../common/ConfirmActionModal/ConfirmActionModal';\r\nimport {layoutOperations} from '../../../../../../../../ducks/layout';\r\n\r\nclass DrugAlcoholQuestionModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n cancelConfirmationPrompt: false,\r\n showQ4Details: false,\r\n showQ6Details: false,\r\n disableSave: true,\r\n q4ReasonsRed: false,\r\n q6ViolationsRed: false,\r\n isUploading: false,\r\n hasFMCSAService: false,\r\n fileList: [],\r\n checklist: {}\r\n };\r\n }\r\n\r\n componentWillUnmount() {\r\n this.cancelSource.cancel('userCanceled');\r\n }\r\n\r\n componentDidMount() {\r\n this.cancelSource = axios.CancelToken.source();\r\n const hasFMCSAService = this.props.auth.user.client.services.some(service => service.name === 'FMCSA-Clearinghouse')\r\n this.setState({hasFMCSAService});\r\n }\r\n\r\n //six questions. question 4 has 10 possible sub part responses, question 6 has 4 possible sub part responses\r\n _questionList = [\"q1\", \"q2\", \"q3\", \"q4\", \"q5\", \"q6\", \"q61\", \"q62\", \"q63\", \"q64\",\r\n \"q41\", \"q42\", \"q43\", \"q44\", \"q45\", \"q46\", \"q47\", \"q48\", \"q49\", \"q410\"];\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n if (this.props.auth.user.client.legacyClientId !== prevProps.auth.user.client.legacyClientId) {\r\n this.setState({hasFMCSAService: this.props.auth.user.client.services.some(service => service.name === 'FMCSA-Clearinghouse')})\r\n }\r\n }\r\n\r\n //If the wizard is at the uploading step then do the upload and submit, otherwise move to the upload step.\r\n handleSaveClick = () => {\r\n if (this.state.isUploading) {\r\n //this is the upload screen, so upload and submitQuestions\r\n this.props.showLoadingPanel();\r\n this.handleUpload().then(() => {\r\n this.submitQuestions().then((response) => {\r\n this.props.hideModal(response, []);\r\n this.props.hideLoadingPanel();\r\n }).catch(err => {\r\n this.props.hideLoadingPanel();\r\n });\r\n }).catch(err => {\r\n this.props.hideLoadingPanel();\r\n });\r\n } else {\r\n //there should only be one service and bucket in the doc list - the one that pertains to drug and alcohol, but we\r\n //need to drill down to the actual document level to get the doc type information\r\n const docType = this.props.info.documentList && this.props.info.documentList.length > 0 && this.props.info.documentList[0].children && this.props.info.documentList[0].children.length > 0\r\n && this.props.info.documentList[0].children[0].children && this.props.info.documentList[0].children[0].children.length > 0 ? this.props.info.documentList[0].children[0].children[0] : null;\r\n this.setState({isUploading: true, docType});\r\n }\r\n };\r\n\r\n //submit the changes.\r\n submitQuestions = () => {\r\n return new Promise(resolve => {\r\n\r\n if (this.nothingChecked()) {\r\n return resolve(false);\r\n }\r\n //take the checklist information and make it into an array that just holds the numbers of the questions that the\r\n //user answered yes to, that is what the database expects\r\n const positiveQuestionList = [];\r\n Object.keys(this.state.checklist).forEach((theKey) => {\r\n if (this.state.checklist[theKey]) {\r\n positiveQuestionList.push(parseInt(theKey.substring(1)));//trim off the q and just put the number into the array\r\n }\r\n });\r\n axios.put(`/v1/employees/${this.props.info.employeeId}/drugAlcoholInfo?forUser=${this.props.auth.user._id}`, {\r\n positiveQuestionList\r\n }, {cancelToken: this.cancelSource.token})\r\n .then(() => {\r\n this.props.addAlert('Drug and alcohol questionnaire information saved successfully');\r\n return resolve(true);\r\n })\r\n .catch(err => {\r\n console.log('failed to update employee', err);\r\n this.props.addAlert('Drug and alcohol questionnaire information could not be saved.', 'danger');\r\n return resolve(false);\r\n });\r\n });\r\n };\r\n\r\n /*\r\n check if anything was marked yes yet\r\n */\r\n nothingChecked = () => {\r\n const {checklist} = this.state;\r\n let nothingChecked = true;\r\n this._questionList.forEach((field) => {\r\n nothingChecked = nothingChecked && !checklist[field];\r\n });\r\n return nothingChecked;\r\n };\r\n\r\n handleChecklistChange = e => {\r\n const checklist = _.cloneDeep(this.state.checklist);\r\n checklist[e.target.id] = !checklist[e.target.id];\r\n let {showQ4Details, showQ6Details} = this.state;\r\n if (e.target.name === 'q6') {\r\n if (showQ6Details) { //if we were showing the sub fields and it was just turned off, reset the sub fields\r\n this._questionList.forEach((field) => {\r\n if (field.charAt(1) === '6') {\r\n checklist[field] = false;\r\n }\r\n });\r\n }\r\n showQ6Details = !showQ6Details;\r\n }\r\n if (e.target.name === 'q4') {\r\n if (showQ4Details) { //if we were showing the sub fields and it was just turned off, reset the sub fields\r\n this._questionList.forEach((field) => {\r\n if (field.charAt(1) === '4') {\r\n checklist[field] = false;\r\n }\r\n });\r\n }\r\n showQ4Details = !showQ4Details;\r\n }\r\n this.validate(checklist);\r\n this.setState({checklist, showQ4Details, showQ6Details});\r\n };\r\n\r\n validate = (checklist) => {\r\n //if q4 but no reason\r\n const q4ReasonsRed = checklist.q4 && !checklist.q41 && !checklist.q42\r\n && !checklist.q43 && !checklist.q44 && !checklist.q45\r\n && !checklist.q46 && !checklist.q47 && !checklist.q48\r\n && !checklist.q49 && !checklist.q410;\r\n //if q6 but no violation\r\n const q6ViolationsRed = checklist.q6 && !checklist.q61 && !checklist.q62\r\n && !checklist.q63 && !checklist.q64;\r\n const noneSelected = !checklist.q1 && !checklist.q2 && !checklist.q3 && !checklist.q4 && !checklist.q5 && !checklist.q6;\r\n this.setState({disableSave: q4ReasonsRed || q6ViolationsRed || noneSelected, q4ReasonsRed, q6ViolationsRed})\r\n };\r\n\r\n handleCancel = e => {\r\n this.setState({cancelConfirmationPrompt: true});\r\n };\r\n\r\n handleConfirmCancel = e => {\r\n this.props.hideModal(true);\r\n this.setState({\r\n cancelConfirmationPrompt: false,\r\n isUploading: false,\r\n fileList: [],\r\n showQ4Details: false,\r\n showQ6Detail: false,\r\n checklist: {}\r\n });\r\n };\r\n\r\n handleCancelCancel = e => {\r\n this.setState({cancelConfirmationPrompt: false});\r\n };\r\n\r\n //When the user chooses to go back to the questionnaire, clear the fileList\r\n handleGoBack = e => {\r\n this.setState({isUploading: false, fileList: []})\r\n };\r\n\r\n //when a new file, or group of files is dropped into the drop zone, add it to the list to be uploaded.\r\n handleFileSelect = acceptedFiles => {\r\n const fileList = this.state.fileList.concat(acceptedFiles);\r\n this.setState({fileList});\r\n };\r\n\r\n //loop through the list of files to be uploaded and upload each one.\r\n handleUpload = () => {\r\n return new Promise(resolve => {\r\n const docType = _.cloneDeep(this.state.docType);\r\n if (!docType.docTypeId) {\r\n const docTypesFound = this.props.info.availableDocTypes.filter(dt => dt.docCategoryId === docType.categoryId);\r\n if (docTypesFound.length === 1) {\r\n docType.docTypeId = docTypesFound[0].docTypeId;\r\n }\r\n }\r\n\r\n async.eachSeries(this.state.fileList, (file, cb) => {\r\n const data = new FormData();\r\n data.append('document', file);\r\n data.append('docCategoryId', docType.categoryId);\r\n data.append('docTypeId', docType.docTypeId);\r\n data.append('uploadedBy', `web_${this.props.auth.user.firstName}${this.props.auth.user.lastName}`);\r\n data.append('docDate', new Date());\r\n axios\r\n .post(`/v1/employees/${this.props.info.employeeId}/documents`, data, {cancelToken: this.cancelSource.token})\r\n .then(() => { //alert success and clear fields\r\n cb();\r\n })\r\n .catch(err => {\r\n cb(err);\r\n });\r\n },\r\n err => {\r\n if (err) {\r\n console.error(err);\r\n this.props.addAlert(`Failed to upload ${this.state.fileList.length > 1 ? 'one or more documents' : 'the document'}`, 'danger');\r\n resolve();\r\n } else {\r\n if (this.state.fileList.length > 0) {\r\n this.props.addAlert(`Saved document${this.state.fileList.length > 1 ? 's' : ''} successfully`);\r\n }\r\n this.setState({\r\n fileList: [],\r\n docType: null,\r\n changesPresent: false\r\n });\r\n resolve();\r\n }\r\n });\r\n });\r\n };\r\n\r\n render() {\r\n const {\r\n checklist, cancelConfirmationPrompt, showQ4Details, showQ6Details,\r\n disableSave, q4ReasonsRed, q6ViolationsRed, hasFMCSAService,\r\n isUploading, docType, fileList\r\n } = this.state;\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n Drug and Alcohol Questionnaire\r\n - {this.props.info.employeeInfo.firstName} {this.props.info.employeeInfo.lastName}
\r\n {!isUploading && Only click yes to questions that apply to this Driver}\r\n {isUploading && docType && Uploading Documents of Type: {docType ? docType.item : ''}}\r\n \r\n \r\n {!isUploading && }\r\n {isUploading && }\r\n \r\n \r\n {!isUploading &&\r\n }\r\n {isUploading &&\r\n }\r\n \r\n {isUploading && Once\r\n you save, a yes answer cannot be changed!\r\n }\r\n \r\n
\r\n \r\n \r\n \r\n {cancelConfirmationPrompt &&\r\n }\r\n \r\n )\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n hideModal: modalOperations.hideModal,\r\n addAlert: alertsOperations.addAlert,\r\n showLoadingPanel: layoutOperations.showLoadingPanel,\r\n hideLoadingPanel: layoutOperations.hideLoadingPanel\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(DrugAlcoholQuestionModalContainer);","import React, {Fragment} from 'react';\r\nimport ReactTable from 'react-table';\r\nimport PageMessage from '../../../common/PageMessage/pageMessageComponent';\r\n\r\nconst csaNotificationsModalComponent = props => {\r\n const data = props.data || {};\r\n const basics = props.basics || [];\r\n\r\n const tableColumns = basics.map((basic) => {\r\n return {\r\n Header: x => {\r\n return (\r\n \r\n {basic.BasicID === 4 ? 'Drug & Alcohol' : basic.BasFullName}\r\n {props.editMode &&\r\n \r\n props.onSelectAll(e, basic.BasName)}\r\n checked={props.toggleAllCheckStatuses[basic.BasName] === data.length}\r\n ref={input => {\r\n if (input) {\r\n input.indeterminate = props.toggleAllCheckStatuses[basic.BasName] > 0 && props.toggleAllCheckStatuses[basic.BasName] < data.length;\r\n }\r\n }}\r\n />
}\r\n \r\n );\r\n },\r\n id: basic.BasName,\r\n Cell: ({original}) => {\r\n if (props.editMode) {\r\n return props.onNotificationChange(e, basic.BasName, original.typeName)}\r\n />\r\n }\r\n if (original[basic.BasName]) {\r\n return \r\n }\r\n return null;\r\n },\r\n headerClassName: 'text-center table-cell-wrap',\r\n className: 'text-center',\r\n sortable: false,\r\n width: 85\r\n }\r\n });\r\n tableColumns.unshift({\r\n id: 'colNotificationType',\r\n Header: x => {\r\n return Notification Type\r\n },\r\n Cell: ({original}) => {\r\n return {props.editMode &&\r\n props.onSelectAllType(e, original.typeName)}\r\n checked={props.toggleAllCheckStatuses[original.typeName] === basics.length}\r\n ref={input => {\r\n if (input) {\r\n input.indeterminate = props.toggleAllCheckStatuses[original.typeName] > 0 && props.toggleAllCheckStatuses[original.typeName] < basics.length;\r\n }\r\n }}\r\n />} {original.typeName}
\r\n },\r\n headerClassName: 'text-center table-cell-wrap'\r\n });\r\n\r\n\r\n return \r\n }\r\n />\r\n
\r\n};\r\n\r\nexport default csaNotificationsModalComponent;","import React, {Component} from 'react';\r\nimport {connect} from \"react-redux\";\r\nimport {Modal, ModalBody, ModalFooter, ModalHeader} from 'reactstrap';\r\nimport CSANotificationsModal from './csaNotificationsModalComponent';\r\nimport {alertsOperations} from '../../../../ducks/alerts';\r\nimport {modalOperations} from \"../../../../ducks/modal\";\r\nimport {Rnd} from \"react-rnd\";\r\nimport _ from 'lodash';\r\n\r\nclass CSANotificationsModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n //the props are coming in on the info prop of the modal container, so map them to the ones we need\r\n this.state = {\r\n modalDisplayInfo: props.info && props.info.modalDisplayInfo ? props.info.modalDisplayInfo : null,\r\n basics: props.info && props.info.basics ? props.info.basics : [],\r\n editMode: (props.info && props.info.editMode) || false\r\n };\r\n }\r\n\r\n handleHideCSADetailModal = () => {\r\n this.props.hideModal(true);\r\n };\r\n\r\n handleSaveCSADetail = () => {\r\n this.props.hideModal(true, {modalDisplayInfo: this.state.modalDisplayInfo});\r\n };\r\n\r\n handleSelectAll = (e, basic) => {\r\n const modalDisplayInfo = _.cloneDeep(this.state.modalDisplayInfo);\r\n modalDisplayInfo.types.forEach((type) => type[basic] = e.target.checked);\r\n this.setState({modalDisplayInfo});\r\n };\r\n\r\n handleSelectAllType = (e, typeName) => {\r\n const modalDisplayInfo = _.cloneDeep(this.state.modalDisplayInfo);\r\n const typeToChange = modalDisplayInfo.types.findIndex((type) => type.typeName === typeName);\r\n this.state.basics.forEach((basic) => {\r\n modalDisplayInfo.types[typeToChange][basic.BasName] = e.target.checked\r\n });\r\n this.setState({modalDisplayInfo});\r\n };\r\n\r\n handleNotificationChange = (e, basic, type) => {\r\n const modalDisplayInfo = _.cloneDeep(this.state.modalDisplayInfo);\r\n const index = modalDisplayInfo.types.findIndex((item) =>\r\n item.typeName === type);\r\n modalDisplayInfo.types[index][basic] = !modalDisplayInfo.types[index][basic];\r\n this.setState({modalDisplayInfo});\r\n };\r\n\r\n render() {\r\n const {modalDisplayInfo, basics, editMode} = this.state;\r\n if (!modalDisplayInfo) {\r\n return null;\r\n }\r\n let title = 'CSA Detail Notifications';\r\n let subtitle = '';\r\n if (modalDisplayInfo.hasOwnProperty('email')) {\r\n title += ` - ${modalDisplayInfo.email}`;\r\n subtitle = `Location: ${modalDisplayInfo.clientName}`\r\n } else {\r\n title += ` - (for ALL recipients!)`;\r\n }\r\n const toggleAllCheckStatuses = {};\r\n basics.forEach((basic) => {\r\n toggleAllCheckStatuses[basic.BasName] = modalDisplayInfo.types.filter((type) => type[basic.BasName]).length;\r\n });\r\n modalDisplayInfo.types.forEach((type) => {\r\n toggleAllCheckStatuses[type.typeName] = Object.values(type).filter((value) => value === true).length;\r\n });\r\n\r\n return (\r\n \r\n \r\n {title}\r\n \r\n \r\n
\r\n {subtitle}\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n {editMode &&\r\n \r\n }\r\n \r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n hideModal: modalOperations.hideModal,\r\n addAlert: alertsOperations.addAlert\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(CSANotificationsModalContainer);","import React, {Component, Fragment} from 'react';\r\nimport {connect} from \"react-redux\";\r\nimport {Modal, ModalHeader, ModalBody, ModalFooter} from 'reactstrap';\r\nimport axios from \"axios\";\r\nimport {alertsOperations} from '../../../../../ducks/alerts';\r\nimport {modalOperations} from \"../../../../../ducks/modal\";\r\nimport {withRouter} from 'react-router-dom';\r\nimport {Rnd} from \"react-rnd\";\r\nimport _ from 'lodash';\r\nimport Select from 'react-select';\r\nimport async from 'async';\r\nimport settingsAPI from '../../../../../services/settings';\r\nimport {Progress} from 'reactstrap';\r\n\r\nclass BulkTransferEmployeeModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n selectedTargetSite: {},\r\n employmentStatusList: []\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n this.cancelSource = axios.CancelToken.source();\r\n settingsAPI\r\n .getEmploymentStatus(this.cancelSource.token)\r\n .then(employmentStatusList => {\r\n this.setState({employmentStatusList});\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n });\r\n this.loadData();\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n if (!_.isEqual(this.props.employeeList, prevProps.employeeList)) {\r\n this.loadData();\r\n }\r\n }\r\n\r\n componentWillUnmount() {\r\n this.cancelSource.cancel('userCanceled');\r\n }\r\n\r\n loadData = () => {\r\n //the props are coming in on the info prop of the modal container, so map them to the ones we need\r\n this.setState({\r\n employeeList: this.props.info.employeeList\r\n });\r\n };\r\n\r\n handleTransferSelect = (propertyName, value) => {\r\n this.setState({[propertyName]: value});\r\n };\r\n\r\n performTransfer = () => {\r\n const {selectedTargetSite, employeeList, employmentStatusList} = this.state;\r\n const errorList = [];\r\n const skippedList = [];\r\n const userCount = employeeList.length;\r\n let progress = 0;\r\n this.setState({userCount, progress});\r\n\r\n async.eachOfSeries(employeeList, (employee, e, cb) => {\r\n const employmentStatus = employmentStatusList.filter((status) => status.status === employee.employmentStatus);\r\n if (employmentStatus.length === 0) {\r\n errorList.push({\r\n employeeId: employee.employeeId,\r\n employeeName: employee.employeeName,\r\n error: 'employment status could not be matched'\r\n });\r\n cb(null);\r\n }\r\n if (employee.employerId === selectedTargetSite.value) {\r\n //this one doesn't need to be done. so add to the skipped list\r\n skippedList.push({employeeId: employee.employeeId, employeeName: employee.employeeName});\r\n }\r\n axios.patch(`/v1/employees/${employee.employeeId}`, {\r\n transfer: {\r\n newClientId: selectedTargetSite.value,\r\n oldClientId: employee.employerId,\r\n jobTitleId: employee.jobTitleId,\r\n employmentStatusId: employmentStatus[0].employmentStatusId\r\n }\r\n }, {cancelToken: this.cancelSource.token})\r\n .then(result => {\r\n const progress = Math.floor(((e + 1) / userCount) * 100);\r\n this.setState({progress});\r\n return cb(null);\r\n })\r\n .catch(err => {\r\n console.log(err);\r\n const errorMsg = err.response && err.response.data ? err.response.data.errorText : 'error completing transfer';\r\n errorList.push({employeeId: employee.employeeId, error: errorMsg, employeeName: employee.employeeName});\r\n const progress = Math.floor(((e + 1) / userCount) * 100);\r\n this.setState({progress});\r\n return cb(null);\r\n });\r\n }, err => {\r\n this.setState({complete: true, errorList, skippedList});\r\n });\r\n };\r\n\r\n cancelTransfer = () => {\r\n this.props.hideModal(false);\r\n };\r\n\r\n finishTransfer = () => {\r\n this.setState({\r\n complete: null,\r\n errorList: null,\r\n skippedList: null,\r\n progress: null,\r\n userCount: null,\r\n selectedTargetSite: {},\r\n employmentStatusList: []\r\n });\r\n this.props.hideModal(true, {refreshData: true});\r\n };\r\n\r\n render() {\r\n const {\r\n employeeList, selectedTargetSite, progress, userCount, errorList, skippedList, complete\r\n } = this.state;\r\n\r\n const targetSiteOptions = this.props.auth.user.sites.map(site => ({\r\n value: site.legacyClientId,\r\n label: site.name\r\n }));\r\n targetSiteOptions.sort((a, b) => a.label.localeCompare(b.label));\r\n if (!employeeList) {\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n Transfer{progress || progress === 0 ? 'ring' : ''} the {employeeList.length} selected\r\n employee{employeeList.length > 1 ? 's' : ''} to\r\n {progress || progress === 0 ? ' ' + selectedTargetSite.label : ' another work location'} \r\n \r\n {(progress || progress === 0) && !complete ?\r\n \r\n Progress: {progress}% of {userCount} user{userCount > 1 ? 's' : ''}
\r\n \r\n :\r\n (complete) ?\r\n \r\n {errorList.length === 0 && skippedList.length === 0 && 'Transfer completed successfully'}
\r\n {errorList.length > 0 && \r\n
The\r\n following {errorList.length} employee transfers completed\r\n with errors:\r\n
\r\n
{errorList.map((skipped) => skipped.employeeName).join(', ')}
\r\n
}\r\n {skippedList.length > 0 && \r\n
0 && errorList.length > 0 ? 'border-top mt-1' : ''}>The\r\n following {skippedList.length} employee{skippedList.length > 1 ? `s were ` : ` was`} skipped\r\n because they are already working at the\r\n destination location:\r\n
\r\n
{skippedList.map((skipped) => skipped.employeeName).join(', ')}
\r\n
}\r\n \r\n :\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n }\r\n \r\n \r\n {complete &&\r\n \r\n \r\n }\r\n {!progress && progress !== 0 &&\r\n \r\n \r\n \r\n }\r\n \r\n \r\n \r\n \r\n )\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n hideModal: modalOperations.hideModal,\r\n addAlert: alertsOperations.addAlert\r\n};\r\n\r\nexport default withRouter(connect(mapStateToProps, mapDispatchToProps)(BulkTransferEmployeeModalContainer));","import React from 'react';\r\nimport moment from 'moment';\r\nimport ReactTable from 'react-table';\r\nimport CBReactTablePagination from '../../../common/CBReactTablePagination/CBReactTablePagination';\r\nimport PageMessage from '../../../common/PageMessage/pageMessageComponent';\r\nimport SocialSecurityNumberDisplayContainer\r\n from '../../../common/SocialSecurityNumber/SocialSecurityNumberDisplay/SocialSecurityNumberDisplayContainer';\r\n\r\nconst cmeResearchResultsComponent = props => {\r\n const results = props.results || [];\r\n\r\n const employeeColumns = [\r\n {\r\n id: 'colReportTitle',\r\n Header: ({'Employee Results'}),\r\n columns: [\r\n {\r\n id: 'colId',\r\n Header: '#',\r\n accessor: 'employeeId',\r\n className: 'text-left',\r\n headerClassName: 'text-left',\r\n show: false\r\n },\r\n {\r\n id: 'colName',\r\n Header: 'Employee Name',\r\n Cell: ({original}) => `${original.firstName} ${original.lastName}`,\r\n accessor: 'LastName',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colEmployerName',\r\n Header: 'Employer Name',\r\n accessor: 'employerName',\r\n className: 'text-left',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colDOB',\r\n Header: 'DOB',\r\n accessor: 'dob',\r\n Cell: ({value}) => value ? moment(value).utc().format('M/D/YYYY') : '',\r\n className: 'text-left',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colSSN',\r\n Header: 'SSN',\r\n accessor: 'ssn',\r\n className: 'text-left',\r\n headerClassName: 'text-left',\r\n Cell: ({value}) => {\r\n return (\r\n \r\n );\r\n }\r\n },\r\n {\r\n id: 'colLicense',\r\n Header: 'License',\r\n accessor: 'licence',\r\n className: 'text-left',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colJobTitle',\r\n Header: 'Job Title',\r\n accessor: 'jobTitle',\r\n className: 'text-left',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colStatus',\r\n Header: 'Status',\r\n accessor: 'employmentStatus',\r\n className: 'text-left',\r\n headerClassName: 'text-left'\r\n }\r\n ]\r\n }];\r\n\r\n const maxRows = 5;\r\n const dataLength = results ? results.length : 0;\r\n let defaultPageSize = dataLength <= maxRows ? dataLength : maxRows;\r\n if (defaultPageSize === 0) {\r\n defaultPageSize = 3;\r\n }\r\n\r\n return (\r\n \r\n
defaultPageSize}\r\n PaginationComponent={CBReactTablePagination}\r\n noDataText={\r\n !results\r\n ? \r\n : results.length === 0 &&\r\n \r\n }\r\n filterable={false}\r\n getTrProps={\r\n (state, rowInfo, column) => {\r\n if (!rowInfo) return {};\r\n if (!rowInfo.original) return {};\r\n return {\r\n className: rowInfo.original.selected ? 'selected' : ''\r\n }\r\n }\r\n }\r\n getTdProps={(state, rowInfo, column, instance) => {\r\n return {\r\n onClick: (e, handleOriginal) => {\r\n // If it's an icon, don't trigger the row click (the icon has its own onClick)\r\n if (!rowInfo) return;\r\n if (!rowInfo.original) return;\r\n props.selectionChanged(e, rowInfo.original);\r\n if (handleOriginal) {\r\n handleOriginal();\r\n }\r\n }\r\n };\r\n }}\r\n />\r\n \r\n )\r\n};\r\n\r\nexport default cmeResearchResultsComponent;","import React, {Fragment} from 'react';\r\nimport moment from \"moment\";\r\nimport ReactTable from 'react-table';\r\nimport PageMessage from '../../../common/PageMessage/pageMessageComponent';\r\n\r\nconst cmeResearchAuditTrailComponent = props => {\r\n\r\n const tableColumns = [\r\n {\r\n id: 'colReportTitle',\r\n Header: ({'Audit Trail'}),\r\n columns: [\r\n {\r\n id: 'colDate',\r\n Header: 'Date',\r\n Cell: ({value}) => value ? moment(value).format('M/D/YYYY h:mm a') : '',\r\n accessor: 'AuditTime',\r\n headerClassName: 'text-left',\r\n width: 170\r\n },\r\n {\r\n id: 'colUserName',\r\n Header: 'UserName',\r\n accessor: 'UserName',\r\n headerClassName: 'text-left',\r\n width: 180\r\n },\r\n {\r\n id: 'colMessage',\r\n Header: 'Message',\r\n accessor: 'Message',\r\n headerClassName: 'text-left'\r\n }\r\n ]\r\n }];\r\n\r\n const maxRows = 20;\r\n const dataLength = props.data ? props.data.length : 0;\r\n let defaultPageSize = dataLength <= maxRows ? dataLength : maxRows;\r\n if (defaultPageSize === 0) {\r\n defaultPageSize = 3;\r\n }\r\n\r\n return (\r\n \r\n defaultPageSize}\r\n noDataText={\r\n \r\n }\r\n />\r\n \r\n )\r\n};\r\n\r\nexport default cmeResearchAuditTrailComponent;","import React from 'react';\r\nimport moment from 'moment';\r\nimport SocialSecurityNumberDisplayContainer\r\n from \"../../../common/SocialSecurityNumber/SocialSecurityNumberDisplay/SocialSecurityNumberDisplayContainer\";\r\n\r\nconst cmeResearchEmployeeInfoComponent = props => {\r\n\r\n return (\r\n \r\n
\r\n
\r\n
Employee Id:
\r\n
\r\n {props.employeeInfo.employeeId}\r\n \r\n
\r\n
\r\n
\r\n
\r\n
Name:
\r\n
\r\n {props.employeeInfo.firstName} {props.employeeInfo.lastName}\r\n \r\n
\r\n
\r\n
\r\n
\r\n
SSN:
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n
Work Id:
\r\n
\r\n {props.employeeInfo.workId}\r\n \r\n
\r\n
\r\n
\r\n
\r\n
Date of Birth:
\r\n
\r\n {props.employeeInfo.dob ? moment(props.employeeInfo.dob).utc().format('M/D/YYYY') : ''}\r\n \r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default cmeResearchEmployeeInfoComponent;","import React, {Fragment} from 'react';\r\nimport moment from \"moment\";\r\nimport ReactTable from 'react-table';\r\nimport CBReactTablePagination from '../../../common/CBReactTablePagination/CBReactTablePagination';\r\nimport PageMessage from '../../../common/PageMessage/pageMessageComponent';\r\nimport {UncontrolledTooltip} from 'reactstrap';\r\nimport EditOrderStatus from '../../../common/EditOrderStatus/EditOrderStatusContainer';\r\n\r\nconst cmeResearchOrdersComponent = props => {\r\n\r\n const maxRows = 10;\r\n let defaultPageSize = props.results.length <= maxRows ? props.results.length : maxRows;\r\n if (defaultPageSize === 0) {\r\n defaultPageSize = 3;\r\n }\r\n\r\n const tableColumns = [\r\n {\r\n id: 'colReportTitle',\r\n Header: ({`Orders for ${props.employeeInfo.firstName} ${props.employeeInfo.lastName}`}),\r\n columns: [\r\n {\r\n id: 'colOrderDateTime',\r\n Header: 'Order Date',\r\n Cell: ({value}) => value ? moment.utc(value).format('M/D/YYYY') : '',\r\n accessor: 'OrderDate',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colEmployerName',\r\n Header: 'Employer',\r\n accessor: 'EmployerName',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colEmploymentStatus',\r\n Header: 'Status',\r\n accessor: 'EmploymentStatus',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colAppointmentDateTime',\r\n Header: 'Appointment',\r\n Cell: ({value}) => value ? moment.utc(value).format('M/D/YYYY h:mm a') : '',\r\n accessor: 'AppointmentDateTime',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colOrderStatus',\r\n Header: 'Order Status',\r\n accessor: 'OrderStatus',\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colIcon',\r\n Header: '',\r\n accessor: '',\r\n headerClassName: 'text-left',\r\n width: 38,\r\n className: 'd-flex justify-content-center align-items-center',\r\n Cell: ({original}) => {\r\n return (\r\n \r\n \r\n Change appointment information for {original.FirstName} {original.LastName}\r\n \r\n \r\n \r\n );\r\n }\r\n },\r\n {\r\n id: 'colClinic',\r\n Header: 'Clinic',\r\n accessor: d => `${d.VendorName} ${d.VendorAddress} ${d.VendorCity} ${d.VendorState} ${d.VendorZip}`,\r\n headerClassName: 'text-left'\r\n },\r\n {\r\n id: 'colVendorPhone',\r\n Header: 'Clinic Phone',\r\n accessor: 'VendorPhone',\r\n headerClassName: 'text-left'\r\n }\r\n ]\r\n }];\r\n\r\n return (\r\n \r\n defaultPageSize}\r\n PaginationComponent={CBReactTablePagination}\r\n noDataText={\r\n \r\n }\r\n getTrProps={\r\n (state, rowInfo, column) => {\r\n if (!rowInfo) return {};\r\n if (!rowInfo.original) return {};\r\n return {\r\n className: rowInfo.original.selected ? 'selected' : ''\r\n }\r\n }\r\n }\r\n getTdProps={(state, rowInfo, column, instance) => {\r\n return {\r\n onClick: (e, handleOriginal) => {\r\n if (!rowInfo) return;\r\n const item = rowInfo.original;\r\n props.handleItemSelected(item.OrderID);\r\n if (handleOriginal) {\r\n handleOriginal();\r\n }\r\n }\r\n };\r\n }}\r\n />\r\n \r\n )\r\n};\r\n\r\nexport default cmeResearchOrdersComponent;","import React from 'react';\r\nimport {Modal, ModalBody, ModalFooter, ModalHeader, UncontrolledTooltip} from 'reactstrap';\r\nimport {Rnd} from 'react-rnd';\r\nimport SearchComponent from '../../common/SearchField/searchComponent';\r\nimport CMEResearchResultsComponent from './components/cmeResearchResultsComponent';\r\nimport CMEResearchAuditTrailComponent from './components/cmeResearchAuditTrailComponent'\r\nimport CMEResearchEmployeeInfoComponent from './components/cmeResearchEmployeeInfoComponent';\r\nimport CMEResearchOrdersComponent from './components/cmeResearchOrdersComponent';\r\nimport DocumentListPane from '../../common/DocumentListViewer/components/documentListPaneComponent';\r\nimport PDFViewer from '../../common/PDF/PDFViewer';\r\n\r\nconst cmeResearchModalComponent = props => {\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n
CME Tool
\r\n
\r\n \r\n
\r\n
\r\n \r\n {(props.searchResults || props.orderResults) && \r\n {props.employeeInfo && \r\n }\r\n {props.searchResults &&
}\r\n {props.orderResults && !props.showDocuments &&\r\n \r\n
\r\n {props.auditTrail &&
\r\n
\r\n \r\n
\r\n \r\n \r\n \r\n Add a new message to the audit trail\r\n \r\n
\r\n
\r\n }\r\n
}\r\n {props.showDocuments &&\r\n \r\n
\r\n \r\n
\r\n {props.selectedDocumentId &&\r\n
{\r\n }}\r\n rotatePage={() => {\r\n }}\r\n allowEdit={true}\r\n /> }\r\n
}\r\n }\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default cmeResearchModalComponent;","import React, {Component} from 'react';\r\nimport {connect} from 'react-redux';\r\nimport CMEResearchModalComponent from './cmeResearchModalComponent';\r\nimport {modalOperations} from '../../../ducks/modal';\r\nimport axios from 'axios';\r\nimport {layoutOperations} from '../../../ducks/layout';\r\nimport {alertsOperations} from '../../../ducks/alerts';\r\nimport ordersService from '../../../services/ordersService'\r\nimport _ from 'lodash';\r\nimport employeeService from '../../../services/employeeService';\r\nimport async from 'async';\r\n\r\nexport class CMEResearchModalContainer extends Component {\r\n\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n showDocuments: false\r\n };\r\n\r\n }\r\n\r\n componentDidMount() {\r\n this.cancelSource = axios.CancelToken.source();\r\n }\r\n\r\n componentWillUnmount() {\r\n this.cancelSource.cancel('userCanceled');\r\n }\r\n\r\n handleHideModal = () => {\r\n this.props.hideModal(true);\r\n };\r\n\r\n handleSearchButtonClick = e => {\r\n e.preventDefault();\r\n if (!this.state.searchQuery) {\r\n this.props.addAlert('You must enter search criteria.', 'danger');\r\n return;\r\n }\r\n if (this.state.searchQuery && this.state.searchQuery.length > 0) {\r\n this.props.showLoadingPanel();\r\n axios\r\n .get(`/v1/employees?search=${this.state.searchQuery}&isConcordeUser=true&exactMatch=true`)\r\n .then(res => {\r\n const searchResults = res ? res.data : [];\r\n if (searchResults.length === 1) { //if there is only one result, auto select it.\r\n this.selectionChanged(null, searchResults[0]);\r\n } else {\r\n this.setState({\r\n searchResults, employeeId: null, orderId: null, employeeInfo: null, orderResults: null\r\n });\r\n }\r\n this.props.hideLoadingPanel();\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n this.props.hideLoadingPanel();\r\n });\r\n }\r\n };\r\n\r\n handleSearchInputChanged = e => {\r\n e.preventDefault();\r\n this.setState({searchQuery: e.target.value});\r\n };\r\n\r\n //employee selection changed\r\n selectionChanged = (e, rowInfo) => {\r\n if (e) {\r\n e.preventDefault();\r\n }\r\n //search for orders and documents\r\n this.props.showLoadingPanel();\r\n this.setState({\r\n employeeId: rowInfo.employeeId,\r\n searchResults: null,\r\n employeeInfo: rowInfo,\r\n selectedDocumentId: null\r\n });\r\n\r\n async.parallel([\r\n done => {\r\n employeeService.getCMEDocuments(rowInfo.employeeId, this.cancelSource.token)\r\n .then(docList => {\r\n const sortedArray = docList.sort((a, b) => {\r\n if (a.docDate < b.docDate) {\r\n return -1;\r\n }\r\n if (a.docDate > b.docDate) {\r\n return 1;\r\n }\r\n // a must be equal to b\r\n return 0;\r\n });\r\n this.setState({docList: sortedArray});\r\n done();\r\n })\r\n .catch(err => {\r\n if (err !== 'userCanceled') {\r\n console.error(err);\r\n }\r\n done(err);\r\n });\r\n },\r\n done => {\r\n ordersService.searchOrders(`employmentId=${rowInfo.employeeId}`, this.cancelSource.token)\r\n .then((results) => {\r\n const orderResults = results && results.orderResults ? results.orderResults : [];\r\n this.setState({orderResults});\r\n done();\r\n }).catch(err => {\r\n console.error(err);\r\n this.setState({orderResults: []});\r\n done(err);\r\n });\r\n }\r\n ], err => {\r\n this.props.hideLoadingPanel();\r\n }\r\n );\r\n };\r\n\r\n orderSelectionChanged = (selectedOrder) => {\r\n //we are selecting the order now, not the employee\r\n const orderResults = _.cloneDeep(this.state.orderResults);\r\n if (this.state.orderId) {//if there is one selected already\r\n //unselect it\r\n const index = orderResults.findIndex((result) => result.selected);\r\n if (index !== -1) {\r\n orderResults[index].selected = false;\r\n }\r\n }\r\n const index = orderResults.findIndex((result) => result.OrderID === selectedOrder);\r\n if (index === -1) {\r\n this.props.addAlert('Order is not valid. Audit trail could not be loaded', 'danger');\r\n return;\r\n }\r\n orderResults[index].selected = true;\r\n ordersService.getAuditTrail(selectedOrder, this.cancelSource.token)\r\n .then(auditTrail => {\r\n this.setState({orderId: selectedOrder, orderResults, auditTrail});\r\n })\r\n .catch(err => {\r\n if (!axios.isCancel(err)) {\r\n console.error(err);\r\n }\r\n });\r\n };\r\n\r\n documentListClickRowHandler = (original) => {\r\n const docList = _.cloneDeep(this.state.docList);\r\n if (this.state.selectedDocumentId) {//if there is one selected already\r\n //unselect it\r\n const index = docList.findIndex((result) => result.selected);\r\n if (index !== -1) {\r\n docList[index].selected = false;\r\n }\r\n }\r\n\r\n const index = docList.findIndex((result) => result.imageId === original.imageId);\r\n if (index === -1) {\r\n this.props.addAlert('Document is not valid and could not be loaded', 'danger');\r\n return;\r\n }\r\n docList[index].selected = true;\r\n this.setState({selectedDocumentId: original.imageId, docList});\r\n };\r\n\r\n handleShowDocuments = () => {\r\n this.setState({showDocuments: !this.state.showDocuments})\r\n };\r\n\r\n //this is blank because it's a required property that is used elsewhere to basically reload the page, but we don't need it here\r\n handleOrderChanged = () => {\r\n };\r\n\r\n handleOrderChangedCallback = (orderId, error) => {\r\n if (error) {\r\n this.props.addAlert('The order update did not complete.', 'danger');\r\n }\r\n ordersService.searchOrders(`employmentId=${this.state.employeeId}`, this.cancelSource.token)\r\n .then((results) => {\r\n const orderResults = results && results.orderResults ? results.orderResults : [];\r\n this.setState({orderResults});\r\n }).catch(err => {\r\n console.error(err);\r\n this.setState({orderResults: []});\r\n });\r\n if (this.state.auditTrail) {\r\n ordersService.getAuditTrail(this.state.orderId, this.cancelSource.token)\r\n .then(auditTrail => {\r\n this.setState({auditTrail});\r\n })\r\n .catch(err => {\r\n if (!axios.isCancel(err)) {\r\n console.error(err);\r\n }\r\n });\r\n }\r\n };\r\n\r\n handleChangeMessageText = (e) => {\r\n this.setState({newMessageText: e.target.value})\r\n };\r\n\r\n handleAddMessage = (e) => {\r\n e.preventDefault();\r\n ordersService.addAuditTrail(this.state.orderId, this.state.newMessageText, this.cancelSource.token)\r\n .then(() => {\r\n this.props.addAlert('Message successfully added');\r\n ordersService.getAuditTrail(this.state.orderId, this.cancelSource.token)\r\n .then(auditTrail => {\r\n this.setState({auditTrail, newMessageText: ''});\r\n })\r\n .catch(err => {\r\n if (!axios.isCancel(err)) {\r\n console.error(err);\r\n }\r\n });\r\n }).catch(err => {\r\n console.error(err);\r\n this.props.addAlert('The message could not be added.', 'danger');\r\n });\r\n };\r\n\r\n render() {\r\n return (\r\n \r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n hideModal: modalOperations.hideModal,\r\n showLoadingPanel: layoutOperations.showLoadingPanel,\r\n hideLoadingPanel: layoutOperations.hideLoadingPanel,\r\n addAlert: alertsOperations.addAlert\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(CMEResearchModalContainer);","import React, {Fragment} from 'react';\r\nimport TransferEmployeeModalContainer\r\n from '../../dqf/employees/EmployeeDetail/components/TransferEmployeeModal/TransferEmployeeModalContainer';\r\nimport CopySettingsModalContainer\r\n from '../../dqf/manage/admin/SiteLocationDetail/components/CopySettingsModal/CopySettingsModalContainer';\r\nimport PushSettingsModalContainer\r\n from '../../dqf/manage/admin/SiteLocationDetail/components/PushSettingsModal/PushSettingsModalContainer';\r\n\r\nimport OrderMVRModalContainer from '../../dqf/employees/EmployeeDetail/components/OrderMVRModal/OrderMVRModalContainer';\r\nimport VerificationOfFCRAContainer from '../../dqf/common/VerificationOfFCRAModal/VerificationOfFCRAModalContainer'\r\nimport AddAccidentModalContainer\r\n from '../../dqf/employees/EmployeeDetail/components/EmployeeAccidents/components/AddAccidentModal/AddAccidentModalContainer';\r\nimport DOTNumberModal\r\n from '../../dqf/manage/reports/Reports/Report/components/common/DOTNumberModal/DOTNumberModalContainer';\r\nimport DrugAlcoholQuestionModal\r\n from '../../dqf/employees/EmployeeDetail/components/EmployeeDrugAndAlcohol/components/DrugAlcoholQuestionModal/DrugAlcoholQuestionModalContainer';\r\nimport CSANotificationsModal from '../../dqf/common/CSANotificationsModal/CSANotificationsModalContainer';\r\nimport BulkTransferEmployeeModal from '../../dqf/employees/EmployeeList/components/BulkTransferEmployeeModalContainer';\r\nimport CMEResearchModal from '../../cme/CMEResearchModal/CMEResearchModalContainer';\r\n\r\nconst modalComponent = props => {\r\n let modal = null; //start with null so we don't display anything unless we are told to\r\n\r\n switch (props.displayModal) {\r\n case 'transfer': //if the displayModal value is transfer then display the transferEmployeeModal\r\n modal = ;\r\n break;\r\n case 'copySettings':\r\n modal = ;\r\n break;\r\n case 'pushSettings':\r\n modal = ;\r\n break;\r\n case 'orderMVR':\r\n modal = ;\r\n break;\r\n case 'verification':\r\n modal = ;\r\n break;\r\n case 'addAccident':\r\n modal = ;\r\n break;\r\n case 'dotNumberModal':\r\n modal = ;\r\n break;\r\n case 'drugAlcoholQuestionModal':\r\n modal = ;\r\n break;\r\n case 'csaNotificationsModal':\r\n modal = ;\r\n break;\r\n case 'bulkTransfer':\r\n modal = ;\r\n break;\r\n case 'CMEResearch':\r\n modal = ;\r\n break;\r\n default:\r\n break;\r\n }\r\n\r\n return (\r\n {modal}\r\n );\r\n};\r\n\r\nexport default modalComponent;","import React, {Component} from 'react';\r\nimport ModalComponent from './modalComponent';\r\nimport {connect} from \"react-redux\";\r\n\r\nclass ModalContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {};\r\n }\r\n\r\n static getDerivedStateFromProps(nextProps, prevState) {\r\n if (nextProps.modal.displayModal !== prevState.displayModal) {\r\n return {displayModal: nextProps.modal.displayModal, info: nextProps.modal.info};\r\n }\r\n return null;\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n
\r\n )\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n modal: state.modal\r\n});\r\n\r\nexport default connect(mapStateToProps)(ModalContainer);\r\n","import React from 'react';\r\nimport classes from './LoadingPanel.module.css';\r\n\r\nconst loadingPanelComponent = props => {\r\n return(\r\n \r\n
\r\n

\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default loadingPanelComponent;","import React, {Component} from 'react';\r\nimport {connect} from 'react-redux';\r\n\r\nimport LoadingPanelComponent from './loadingPanelComponent';\r\n\r\nexport class LoadingPanelContainer extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n spinning: false\r\n }\r\n }\r\n\r\n componentDidMount() {\r\n this.setState({spinning: this.props.layout.loadingPanel.instances > 0});\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n if (this.props.layout.loadingPanel.instances !== prevProps.layout.loadingPanel.instances) {\r\n this.setState({spinning: this.props.layout.loadingPanel.instances > 0});\r\n }\r\n }\r\n\r\n render() {\r\n return (\r\n this.state.spinning ? : null\r\n );\r\n }\r\n\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n layout: state.layout\r\n});\r\n\r\nexport default connect(mapStateToProps)(LoadingPanelContainer);","// Importing the setClientVersion module for its side effects only.\r\n//This runs the module's global code, but doesn't actually import any values.\r\n// The setClientVersion module sets a global variable `clientVersion` to the version number from package.json.\r\nimport './utils/setClientVersion'\r\nimport React, {Component} from 'react';\r\nimport {connect} from 'react-redux';\r\nimport {Route, Switch, BrowserRouter} from 'react-router-dom';\r\nimport classNames from 'classnames';\r\n\r\nimport {getCookie} from './utils/storageUtils';\r\nimport routes from './routes';\r\n\r\n// hoc\r\nimport Alerts from './components/common/Alerts/AlertsComponent';\r\nimport ProtectedRoute from './components/common/ProtectedRoute/ProtectedRoute';\r\nimport UserSession from './components/common/UserSession/UserSessionContainer';\r\n\r\n// layout\r\nimport Header from './components/layout/Header/HeaderComponent';\r\nimport Sidebar from './components/layout/Sidebar/SidebarContainer';\r\nimport Breadcrumbs from './components/layout/Breadcrumbs/BreadcrumbsContainer';\r\nimport Footer from './components/layout/Footer/FooterContainer';\r\nimport ModalContainer from \"./components/common/Modal/ModalContainer\";\r\nimport LoadingPanel from \"./components/common/LoadingPanel/LoadingPanelContainer\";\r\n\r\nimport {layoutOperations} from './ducks/layout';\r\nimport {dqfOperations} from './ducks/dqf';\r\nimport concordeSettings from './config/concordeClient';\r\nimport permissions from './config/permissions';\r\nimport {hasPermission} from './utils/permissions';\r\n\r\nexport class App extends Component {\r\n\r\n // Load the broadcast items from the server, and do it again every 600 seconds (10 minutes)\r\n _loadBroadcastItems = () => {\r\n // Only do it if there's a refreshToken cookie (if there's not, there's no user logged in!)\r\n if (!!getCookie('refreshToken')) {\r\n this.props.loadBroadcastItems();\r\n if (hasPermission(this.props.auth.user, permissions.dq.scoreMVRsManually)) {\r\n this.props.getUnscoredMVRs();\r\n }\r\n }\r\n setTimeout(this._loadBroadcastItems, 600000); // 10 * 60 * 1000ms\r\n };\r\n\r\n /**\r\n * Load Matomo (a web analytics application)\r\n */\r\n _loadMatomoAnalytics = () => {\r\n var _mtm = window._mtm = window._mtm || [];\r\n _mtm.push({'mtm.startTime': (new Date().getTime()), 'event': 'mtm.Start'});\r\n (function() {\r\n var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];\r\n g.async=true;\r\n g.src=window.env.MATOMO_TAG_MANAGER_CONTAINER_URL;\r\n s.parentNode.insertBefore(g,s);\r\n })();\r\n }\r\n\r\n componentDidMount() {\r\n this._loadBroadcastItems();\r\n this._loadMatomoAnalytics();\r\n }\r\n\r\n /**\r\n * Recursively traverse all the routes, and build the full path for each route. As each route is processed,\r\n * add it to the global routeList.\r\n *\r\n * @param basePath\r\n * @param routes\r\n * @param isConcordeUser\r\n * @private\r\n */\r\n _buildRouteFullPaths = (basePath, routes, isConcordeUser) => {\r\n routes.forEach(route => {\r\n const path = basePath + route.path || '';\r\n // If the route is just a menu heading, we don't need a Route for it\r\n if (!route.menuHeading) {\r\n route.fullPath = path;\r\n this.routeList.push(route);\r\n }\r\n if (isConcordeUser && route.externalOnly) { //if it's a concorde user and this is the contact us route then skip it\r\n return;\r\n }\r\n // Process this route's \"children\"\r\n if (route.hasOwnProperty('routes')) {\r\n this._buildRouteFullPaths(path, route.routes, isConcordeUser);\r\n }\r\n });\r\n };\r\n\r\n render() {\r\n const {isAuthenticated} = this.props.auth;\r\n const isNonUserPseudoUser = isAuthenticated && this.props.auth.user.email === 'nonuserpseudouser';\r\n const {layout} = this.props;\r\n const showSidebar = isAuthenticated && !isNonUserPseudoUser && layout.sidebar.isOpen && this.props.auth.user.permissions && !this.props.auth.user.auditorToken;\r\n const isConcordeUser = (this.props.auth.user.client && this.props.auth.user.client.legacyClientId === concordeSettings.concordeClient.legacyClientId) ||\r\n (hasPermission(this.props.auth.user, permissions.customerCare.assumeClient));\r\n // Generate the full paths for the routes\r\n this.routeList = [];\r\n this._buildRouteFullPaths('', routes, isConcordeUser);\r\n\r\n return (\r\n \r\n <>\r\n \r\n \r\n
\r\n {isAuthenticated && !isNonUserPseudoUser &&\r\n
\r\n }\r\n
\r\n
\r\n {showSidebar &&
}\r\n
\r\n
\r\n
\r\n \r\n \r\n {/* Create a Route for each route in the list*/}\r\n {this.routeList.map(route => {\r\n if (route.permission || route.protected) {\r\n // The route requires a specific permission or simply requires that the user\r\n // be logged in, so use our ProtectedRoute component\r\n return (\r\n \r\n );\r\n } else {\r\n // The route is not protected, so use the standard React Route component\r\n return (\r\n \r\n );\r\n }\r\n })}\r\n \r\n \r\n
\r\n
\r\n {isAuthenticated && !isNonUserPseudoUser &&\r\n
\r\n }\r\n
\r\n >\r\n \r\n );\r\n }\r\n}\r\n\r\nconst mapStateToProps = state => ({\r\n auth: state.auth,\r\n layout: state.layout\r\n});\r\n\r\nconst mapDispatchToProps = {\r\n loadBroadcastItems: layoutOperations.loadBroadcastItems,\r\n getUnscoredMVRs: dqfOperations.getUnscoredMVRs\r\n};\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(App);","import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport {Provider} from 'react-redux';\r\nimport jwt_decode from 'jwt-decode';\r\n\r\nimport store from './store';\r\nimport setAuthToken from './utils/setAuthToken';\r\nimport {getCookie, setCookie} from './utils/storageUtils';\r\nimport {authOperations} from './ducks/auth/index';\r\nimport {sessionOperations} from \"./ducks/userSession\";\r\nimport {alertsOperations} from './ducks/alerts';\r\nimport {layoutOperations} from './ducks/layout';\r\n\r\nimport App from './App';\r\nimport \"react-datepicker/dist/react-datepicker-cssmodules.css\";\r\nimport \"react-datepicker/dist/react-datepicker.css\";\r\nimport 'react-sortable-tree/style.css';\r\n\r\n//the service worker was causing issues with requiring users to clear their cookies before logging in\r\n//import registerServiceWorker from './registerServiceWorker';\r\nimport axios from \"axios\";\r\n\r\nconst jwtToken = getCookie('jwtToken');\r\nif (jwtToken && jwtToken.length > 0) { // exists and not an empty string\r\n setAuthToken(jwtToken);\r\n const decoded = jwt_decode(jwtToken);\r\n store.dispatch(authOperations.getFullCurrentUser(decoded._id));\r\n store.dispatch(sessionOperations.setSessionStatus('ACTIVE'));\r\n}\r\n\r\n/***** Start of code for intercepting axios calls, detecting 401 errors, refreshing the bearer token, and retrying *****/\r\n\r\n// If multiple requests fail due to bearer token expiration, we don't want to generate multiple server request\r\n// to refresh the token. So, use a flag and keep a list of the requests that need to be re-submitted once\r\n// the token has been refreshed.\r\nlet isAlreadyRefreshingToken = false;\r\nlet subscribersToRetry = [];\r\n\r\n// Add a retry subscriber. The callback() will accept the new token and insert it into the original request\r\n// before re-submitting the request to the server.\r\nconst addRetrySubscriber = callback => {\r\n subscribersToRetry.push(callback);\r\n};\r\n\r\n// When the bearer token is refreshed after a server error, loop through all subscribers and reset the subscriber list\r\nconst retryAllSubscribersWithNewToken = token => {\r\n // console.log(subscribersToRetry.length, 'subscribers to retry');\r\n subscribersToRetry = subscribersToRetry.filter(callback => callback(token));\r\n // console.log(subscribersToRetry.length, 'subscribers remain');\r\n};\r\n\r\n// Intercept all responses so that we can check for a 401 (unauthorized) error. this is safer than checking the\r\n// token expiration in a request interceptor, because that approach could lead to a \"race\" condition (we think the\r\n// token is still valid, but after checking it, it actually expires before the server receives it)\r\naxios\r\n.interceptors\r\n.response\r\n.use(\r\n response => {\r\n if (response.config.headers.Authorization && !response.headers['no-auth-refresh']) {\r\n //console.log('session status active: ' + response.config.url);\r\n store.dispatch(sessionOperations.setSessionStatus('ACTIVE'));\r\n }\r\n return response;\r\n },\r\n error => {\r\n const {config, response, message} = error;\r\n const originalRequest = config;\r\n let status, data;\r\n if (response) { // Sometimes there's no response object; double-destructuring doesn't always work!\r\n status = response.status;\r\n data = response.data;\r\n }\r\n if ((!response && !axios.isCancel(error) && message !== 'Network Error') || (status === 401 && data === 'Unauthorized')) {\r\n // Since the request failed and needs to be retried, we have to return a new Promise. The Promise\r\n // will resolve after we resubmit the request (which will happen after we get the new token)\r\n const retryPromise = new Promise((resolve, reject) => {\r\n // Push an asynchronous function onto the retry list; it will accept the new token, stuff it into\r\n // the original API request, and retry the original request with the new token.\r\n addRetrySubscriber(token => {\r\n originalRequest.headers.Authorization = token;\r\n axios(originalRequest)\r\n .then(resolve)\r\n .catch(reject);\r\n });\r\n });\r\n // If multiple requests failed (e.g., from components on the same page), it's only necessary to issue ONE\r\n // request for a new token.\r\n const refreshToken = getCookie('refreshToken');\r\n if (response) {\r\n console.log('in error url: ' + response.config.url + ' isalreadyrefreshing: ' + isAlreadyRefreshingToken.toString());\r\n } else {\r\n console.log('in error no response, isalreadyrefreshing: ' + isAlreadyRefreshingToken.toString());\r\n }\r\n\r\n if (!isAlreadyRefreshingToken && !!refreshToken) {\r\n isAlreadyRefreshingToken = true;\r\n axios.get('/v1/auth/token', {headers: {Authorization: refreshToken}})\r\n .then(({data}) => {\r\n setCookie('jwtToken', data.token);\r\n setCookie('refreshToken', data.refreshToken);\r\n setAuthToken(data.token);\r\n // WE PROBABLY DON'T NEED THE FOLLOWING TWO LINES . . .\r\n // const decoded = jwt_decode(data.token);\r\n // store.dispatch(authOperations.getFullCurrentUser(decoded._id, true));\r\n isAlreadyRefreshingToken = false;\r\n // Now that we've got the new token, retry all of the subscribers (the requests that failed)\r\n retryAllSubscribersWithNewToken(data.token);\r\n })\r\n .catch(err => {\r\n isAlreadyRefreshingToken = false;\r\n console.error('Error generating refresh token!', err);\r\n store.dispatch(alertsOperations.addAlert('We apologize but we are unable to proceed due to a user authentication error - try logging out and back in', 'danger'));\r\n store.dispatch(layoutOperations.resetLoadingPanel());\r\n return Promise.reject(error);\r\n });\r\n }\r\n // Return the Promise that we created above\r\n return retryPromise;\r\n }\r\n\r\n // If the API request failed for any reason other than 401 (unauthorized), reject the Promise and return the error.\r\n return Promise.reject(error);\r\n }\r\n);\r\n\r\n/***** End of code for intercepting axios calls, detecting 401 errors, refreshing the bearer token, and retrying *****/\r\n\r\nReactDOM.render((\r\n \r\n \r\n \r\n), document.getElementById('root'));\r\n//the service worker was causing issues with requiring users to clear their cookies before logging in\r\n//registerServiceWorker();","const SET_SESSION_STATUS = 'SET_SESSION_STATUS';\r\nconst SET_SESSION_CONFIG = 'SET_SESSION_CONFIG';\r\nconst SET_SOCKET = 'SET_SOCKET';\r\nexport default {\r\n SET_SESSION_STATUS,\r\n SET_SESSION_CONFIG,\r\n SET_SOCKET\r\n}","import moment from 'moment';\r\nimport userSession from '../../config/userSession';\r\nimport types from './types';\r\n\r\nconst sessionReducer = (state = { status: 'INITIAL', expireAt: null, config: { ...userSession } }, action) => {\r\n switch (action.type) {\r\n case types.SET_SESSION_STATUS:\r\n const now = moment(Date.now());\r\n //console.log(`${action.payload} timeout: ${moment(now).add(state.config.timeout, 'minutes')} warn before: ${moment(now).add(state.config.timeout - state.config.warnBefore, 'minutes')}`);\r\n return {\r\n ...state,\r\n status: action.payload,\r\n expireAt: action.payload === 'ACTIVE' ? moment(now).add(state.config.timeout, 'minutes') : null,\r\n warnAt: action.payload === 'ACTIVE' ? moment(now).add(state.config.timeout - state.config.warnBefore, 'minutes') : null\r\n };\r\n case types.SET_SESSION_CONFIG:\r\n return {\r\n ...state,\r\n config: action.payload\r\n };\r\n case types.SET_SOCKET:\r\n return {\r\n ...state,\r\n socket: action.payload\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nexport default sessionReducer;\r\n","import actions from './actions';\r\n\r\nconst setSessionStatus = actions.setSessionStatus;\r\n\r\nconst setSocket = actions.setSocket;\r\n\r\n\r\nexport default {\r\n setSessionStatus,\r\n setSocket\r\n}","import types from './types';\r\n\r\nconst setSessionStatus = status => ({\r\n type: types.SET_SESSION_STATUS,\r\n payload: status\r\n});\r\n\r\nconst setSocket = socket => ({\r\n type: types.SET_SOCKET,\r\n payload: socket\r\n});\r\n\r\nexport default {\r\n setSessionStatus,\r\n setSocket\r\n}","import reducer from './reducers';\r\n\r\nexport {default as sessionOperations} from './operations';\r\nexport {default as sessionTypes} from './types';\r\n\r\nexport default reducer;","const SET_CURRENT_USER = 'SET_CURRENT_USER';\r\nconst SET_PASSWORD_POLICY = 'SET_PASSWORD_POLICY';\r\nconst GET_SITES_FOR_USER = 'auth/GET_SITES_FOR_USER';\r\nconst GET_CLIENT_FOR_USER = 'auth/GET_CLIENT_FOR_USER';\r\nconst USER_SET_JUMP_LIST = 'USER_SET_JUMP_LIST';\r\nconst SET_TRUE_IDENTITY = 'SET_TRUE_IDENTITY';\r\nconst SET_USER_PERMISSIONS = 'SET_USER_PERMISSIONS';\r\nconst SET_IMPERSONATING_USER_ID = 'SET_IMPERSONATING_USER_ID';\r\nconst SET_IMPERSONATE_MODE = 'SET_IMPERSONATE_MODE';\r\n\r\nexport default {\r\n SET_CURRENT_USER,\r\n SET_PASSWORD_POLICY,\r\n GET_SITES_FOR_USER,\r\n GET_CLIENT_FOR_USER,\r\n USER_SET_JUMP_LIST,\r\n SET_TRUE_IDENTITY,\r\n SET_USER_PERMISSIONS,\r\n SET_IMPERSONATING_USER_ID,\r\n SET_IMPERSONATE_MODE\r\n};","import types from './types';\r\nimport _ from 'lodash';\r\nimport concordeSettings from '../../config/concordeClient.json';\r\n\r\nconst initialState = {\r\n isAuthenticated: false,\r\n user: {},\r\n trueIdentity: {}, // maybe it's ccrTrueIdentity with the 'ccr'\r\n impersonatingDisplayName: null,\r\n impersonatingUserId: null // the only thing we are not changing in the user object is the user Id\r\n};\r\n\r\nconst authReducer = (state = initialState, action) => {\r\n switch (action.type) {\r\n case types.SET_CURRENT_USER:\r\n if (action.payload.preserveState) {\r\n // If preserveState is true, we got here from a token refresh or a profile update so . . .\r\n // we need to keep the client and sites (in case the user is an internal user who selected a client)\r\n if (!!state.impersonatingUserId) {\r\n // . . . but if the user was impersonating another user, don't lose that! -- just re-set the \"true identity\"\r\n return {\r\n ...state,\r\n trueIdentity: {\r\n ...action.payload.userData,\r\n isConcordeUser: action.payload.userData.client && action.payload.userData.client.legacyClientId === concordeSettings.concordeClient.legacyClientId\r\n }\r\n };\r\n } else {\r\n return {\r\n ...state,\r\n user: {\r\n ...action.payload.userData,\r\n isConcordeUser: action.payload.userData.client && action.payload.userData.client.legacyClientId === concordeSettings.concordeClient.legacyClientId,\r\n client: state.user.client,\r\n sites: state.user.sites\r\n }\r\n };\r\n }\r\n } else if (Object.keys(action.payload.userData).length === 0) {\r\n // If clearing the user data (user logged out), also clear the impersonation settings here\r\n return {\r\n ...state,\r\n user: {},\r\n isAuthenticated: false,\r\n trueIdentity: null,\r\n impersonatingUserId: null,\r\n impersonatingDisplayName: null\r\n };\r\n } else {\r\n return {\r\n ...state,\r\n isAuthenticated: true,\r\n user: {\r\n ...action.payload.userData,\r\n isConcordeUser: action.payload.userData.client && action.payload.userData.client.legacyClientId === concordeSettings.concordeClient.legacyClientId\r\n }\r\n };\r\n }\r\n case types.GET_SITES_FOR_USER:\r\n return {\r\n ...state,\r\n user: {\r\n ...state.user,\r\n sites: [...action.payload]\r\n }\r\n };\r\n case types.GET_CLIENT_FOR_USER:\r\n return {\r\n ...state,\r\n user: {\r\n ...state.user,\r\n client: action.payload\r\n }\r\n };\r\n case types.USER_SET_JUMP_LIST:\r\n return {\r\n ...state,\r\n user: {\r\n ...state.user,\r\n jumpList: action.payload\r\n }\r\n };\r\n case types.SET_TRUE_IDENTITY:\r\n const user = _.cloneDeep(state.user);\r\n user.isConcordeUser = !action.payload;\r\n return {\r\n ...state,\r\n user,\r\n trueIdentity: action.payload\r\n };\r\n case types.SET_USER_PERMISSIONS:\r\n return {\r\n ...state,\r\n user: {\r\n ...state.user,\r\n permissions: [...action.payload]\r\n }\r\n };\r\n case types.SET_IMPERSONATING_USER_ID:\r\n return {\r\n ...state,\r\n impersonatingUserId: action.payload.impersonatingUserId,\r\n impersonatingDisplayName: action.payload.impersonatingDisplayName\r\n };\r\n case types.SET_IMPERSONATE_MODE:\r\n const newProps = _.cloneDeep(action.payload);\r\n return {\r\n ...state,\r\n user: {\r\n ...state.user,\r\n ...newProps\r\n }\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nexport default authReducer;","import types from './types';\r\n\r\nconst setCurrentUser = (userData, preserveState) => ({\r\n type: types.SET_CURRENT_USER,\r\n payload: {userData, preserveState}\r\n});\r\n\r\n/**\r\n * Update the Sites in the auth.user object\r\n * @param sites (array) - list of sites\r\n * @returns {{type: string, payload: *}}\r\n */\r\nconst setUserSites = sites => ({\r\n type: types.GET_SITES_FOR_USER,\r\n payload: sites\r\n});\r\n\r\n/**\r\n * Update the Client in the auth.user object\r\n * @param client (object) - mongo client object\r\n * @returns {{type: string, payload: *}}\r\n */\r\nconst setClientForUser = client => ({\r\n type: types.GET_CLIENT_FOR_USER,\r\n payload: client\r\n});\r\n\r\nconst setUserPermissions = permissions => ({\r\n type: types.SET_USER_PERMISSIONS,\r\n payload: permissions\r\n});\r\n\r\nconst setTrueIdentity = identity => ({\r\n type: types.SET_TRUE_IDENTITY,\r\n payload: identity\r\n});\r\n\r\nconst setImpersonatingUser = (impersonatingUserId, impersonatingDisplayName) => ({\r\n type: types.SET_IMPERSONATING_USER_ID,\r\n payload: {impersonatingUserId, impersonatingDisplayName}\r\n});\r\n\r\nconst setImpersonateMode = user => ({\r\n type: types.SET_IMPERSONATE_MODE,\r\n payload: user\r\n});\r\n\r\nconst setJumpList = jumpList => ({\r\n type: types.USER_SET_JUMP_LIST,\r\n payload: jumpList\r\n});\r\n\r\nexport default {\r\n setCurrentUser,\r\n setUserSites,\r\n setClientForUser,\r\n setJumpList,\r\n setTrueIdentity,\r\n setUserPermissions,\r\n setImpersonatingUser,\r\n setImpersonateMode\r\n};","import axios from 'axios';\r\n\r\nimport actions from './actions';\r\nimport setAuthToken from \"../../utils/setAuthToken\";\r\nimport {getCookie, deleteCookie} from \"../../utils/storageUtils\";\r\nimport clientService from '../../services/clientsService/clientsService';\r\nimport {sessionOperations} from \"../userSession\";\r\nimport {dqfOperations} from \"../dqf\";\r\nimport {layoutOperations} from \"../layout\";\r\n\r\nconst setTrueIdentity = actions.setTrueIdentity;\r\n\r\nconst setImpersonatingUser = actions.setImpersonatingUser; // store who is being impersonated\r\n\r\nconst setImpersonateMode = actions.setImpersonateMode; // essentially \"start\" / \"restore\"\r\n\r\nconst setCurrentUser = (userData, preserveState = false) => dispatch => {\r\n dispatch(actions.setCurrentUser(userData, preserveState));\r\n};\r\n\r\nconst getFullCurrentUser = (userId, preserveState = false) => dispatch => {\r\n axios\r\n .get(`/v1/users/${userId}`)\r\n .then(res => dispatch(actions.setCurrentUser(res.data, preserveState)))\r\n .catch(err => console.error(err));\r\n};\r\n\r\n/**\r\n * Process a logout (manual or auto-logout)\r\n * @param status - 'EXITED' or 'EXPIRED'\r\n * @private\r\n */\r\nconst _logout = (status, dispatch) => {\r\n axios.post(`/v1/auth/logout/${getCookie('refreshToken')}`)\r\n .then()\r\n .catch(console.error);\r\n dispatch(sessionOperations.setSessionStatus(status));\r\n deleteCookie('jwtToken');\r\n deleteCookie('refreshToken');\r\n setAuthToken(false);\r\n dispatch(actions.setCurrentUser({}));\r\n // reset site tree and site selections in dqf.sites\r\n dispatch(dqfOperations.setSiteTree({}));\r\n dispatch(dqfOperations.setSelectedSites([], {}));\r\n dispatch(dqfOperations.setSessionClient(''));\r\n // reset roster views\r\n dispatch(dqfOperations.resetRosterViews());\r\n // reset alert counts\r\n dispatch(dqfOperations.setAlertCounts(null));\r\n dispatch(layoutOperations.clearUserOptions());\r\n // reset document view option to \"multi\"\r\n dispatch(dqfOperations.setDocumentTabsSingleOrMulti('multi'));\r\n};\r\n\r\nconst logoutUser = () => dispatch => {\r\n _logout('EXITED', dispatch);\r\n};\r\n\r\nconst autoLogoutUser = () => dispatch => {\r\n _logout('EXPIRED', dispatch);\r\n};\r\n\r\nconst _getAllChildrenSites = client => {\r\n const sites = [];\r\n for (let childSite of client.children) {\r\n sites.push(childSite);\r\n if (childSite.children && childSite.children.length > 0) {\r\n sites.push(..._getAllChildrenSites(childSite));\r\n }\r\n }\r\n return sites;\r\n};\r\n\r\n/**\r\n * Operation to get list of Sites for given clientId\r\n * @param clientId (string) - mongoId for client\r\n * @param isConcorde\r\n * @returns {Function}\r\n */\r\nconst getSitesForUser = (clientId, isConcorde = false) => dispatch => {\r\n if (!clientId) {\r\n return;\r\n }\r\n axios.get(`/v1/clients?descendantsOf=${clientId}`)\r\n .then(response => {\r\n if (response.status === 200) {\r\n if (response.data.length > 0) {\r\n dispatch(dqfOperations.setSiteTree(response.data[0]));\r\n const siteList = _getAllChildrenSites(response.data[0]);\r\n siteList.unshift(response.data[0]);\r\n if (isConcorde) {\r\n dispatch(actions.setUserSites(siteList));\r\n }\r\n }\r\n }\r\n })\r\n .catch(err => {\r\n console.log(err);\r\n })\r\n};\r\n\r\n/**\r\n * Operation to get Client for given clientId\r\n * @param clientId (string) - mongoId for client\r\n * @returns {Function}\r\n */\r\nconst getClientForUser = clientId => dispatch => {\r\n axios.get(`/v1/clients/${clientId}`)\r\n .then(response => {\r\n if (response.status === 200) {\r\n // Pull out the client's \"displayIncludeChildren\" setting\r\n // so that it can be dispatched to the DQF Redux store separately\r\n const {displayIncludeChildren, ...client} = response.data;\r\n dispatch(actions.setClientForUser(client));\r\n dispatch(dqfOperations.setDisplayIncludeChildren(displayIncludeChildren));\r\n // Also need to clear the roster's saved location\r\n dispatch(dqfOperations.setRosterSelectedLocation(null));\r\n }\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n })\r\n};\r\n\r\n/**\r\n * Get Client and Sites for provided clientId\r\n * Dispatches both getClientForUser and getSitesForUser operations\r\n * @param clientId (string) - mongoId for client\r\n * @returns {Function}\r\n */\r\nconst getClientAndSites = (clientId, isConcorde = false) => dispatch => {\r\n dispatch(actions.setUserSites([]));\r\n dispatch(getClientForUser(clientId));\r\n dispatch(getSitesForUser(clientId, isConcorde));\r\n};\r\n\r\nconst getJumpList = userId => dispatch => {\r\n axios.get(`/v1/users/${userId}/jumplist`)\r\n .then(res => {\r\n if (res.status === 200) {\r\n dispatch(actions.setJumpList(res.data));\r\n }\r\n })\r\n .catch(err => console.error(err));\r\n};\r\n\r\nconst clearJumpList = userId => dispatch => {\r\n axios.delete(`/v1/users/${userId}/jumplist`)\r\n .then(res => {\r\n if (res.status === 204) {\r\n dispatch(actions.setJumpList([]));\r\n }\r\n })\r\n .catch(err => console.error(err));\r\n};\r\n\r\nconst addToEmployeeJumpList = (userId, jumpListRecord) => dispatch => {\r\n axios.post(`/v1/users/${userId}/jumplist`, jumpListRecord)\r\n .then(res => {\r\n if (res.status === 201) {\r\n dispatch(actions.setJumpList(res.data));\r\n }\r\n })\r\n .catch(err => console.error(err));\r\n};\r\n\r\nconst removeEmployeeFromJumpList = (userId, employeeId) => dispatch => {\r\n axios.delete(`/v1/users/${userId}/jumplist/${employeeId}`)\r\n .then(res => {\r\n if (res.status === 201) {\r\n dispatch(actions.setJumpList(res.data));\r\n }\r\n })\r\n .catch(err => console.error(err));\r\n};\r\n\r\nconst getTopLevelClientAndSetAssumedClientAndSites = childLocationId => dispatch => {\r\n clientService.getTopLevelClient(childLocationId)\r\n .then(topLevelClient => {\r\n // first set the CCR Client Selector\r\n dispatch(dqfOperations.setSessionClient(topLevelClient._id));\r\n // change the 'auth.user.client' object\r\n dispatch(actions.setClientForUser(topLevelClient));\r\n // change the 'auth.user.sites' array\r\n dispatch(getSitesForUser(topLevelClient._id, true));\r\n })\r\n .catch(err => console.log(err));\r\n};\r\n\r\nconst startImpersonateMode = (trueIdentity, impersonateUser) => dispatch => {\r\n dispatch(setTrueIdentity(trueIdentity)); // store ccr true identity\r\n dispatch(setImpersonateMode(impersonateUser));\r\n dispatch(dqfOperations.setSelectedSites(impersonateUser.sites, {}));\r\n dispatch(setImpersonatingUser(impersonateUser._id, `${impersonateUser.firstName} ${impersonateUser.lastName}`));\r\n};\r\n\r\nconst stopImpersonateMode = ccrUser => dispatch => {\r\n dispatch(setTrueIdentity({}));\r\n dispatch(setImpersonateMode(ccrUser));\r\n dispatch(dqfOperations.setSelectedSites(ccrUser.sites, {}));\r\n dispatch(setImpersonatingUser(null, null));\r\n};\r\n\r\nexport default {\r\n setCurrentUser,\r\n getFullCurrentUser,\r\n logoutUser,\r\n autoLogoutUser,\r\n getClientForUser,\r\n getClientAndSites,\r\n getJumpList,\r\n clearJumpList,\r\n addToEmployeeJumpList,\r\n getTopLevelClientAndSetAssumedClientAndSites,\r\n startImpersonateMode,\r\n stopImpersonateMode,\r\n getSitesForUser,\r\n removeEmployeeFromJumpList\r\n};\r\n","import reducer from './reducers';\r\n\r\nexport {default as authOperations} from \"./operations\";\r\nexport {default as authTypes} from \"./types\";\r\n\r\nexport default reducer;","import React from 'react';\r\n\r\n/**\r\n * Display a message on the page, in a inside a Bootstrap card.\r\n * Props can include the following, to style the
:\r\n * - color the Bootstrap text color (success, info, etc.)\r\n * - bgColor the Bootstrap background color (success, info, etc.)\r\n * - innerClassName additional classNames for the
\r\n * Props can also include the following to style the card:\r\n * - className any arbitrary className(s) to add to the container card\r\n * The message is passed as the child, and can be plain text or a component.\r\n */\r\nconst pageMessageComponent = props => {\r\n const bgColor = `bg-${props.bgColor || 'white'}`;\r\n const textColor = `text-${props.color || 'black'}`;\r\n return
\r\n
\r\n
\r\n {props.children || props.text}\r\n
\r\n
\r\n
\r\n};\r\n\r\nexport default pageMessageComponent;","const RESET_STEP_2_GLOBAL_STATE = 'RESET_STEP_2_GLOBAL_STATE';\r\n// Employment Status\r\nconst SET_STEP2_BY_EMPLOYMENT_STATUS_SELECTION_VALUES = 'SET_STEP2_BY_EMPLOYMENT_STATUS_SELECTION_VALUES';\r\nconst SET_STEP2_EMPLOYMENT_STATUS_CHECKBOX = 'SET_STEP2_EMPLOYMENT_STATUS_CHECKBOX';\r\nconst SET_STEP2_EMPLOYMENT_STATUS_VALUES_FOR_DROPDOWN = 'SET_STEP2_EMPLOYMENT_STATUS_VALUES_FOR_DROPDOWN';\r\nconst SET_STEP2_FOR_EDITING = 'SET_STEP2_FOR_EDITING';\r\n\r\n// Job Titles\r\nconst SET_STEP2_BY_JOB_TITLE_SELECTION_VALUES = 'SET_STEP2_BY_JOB_TITLE_SELECTION_VALUES';\r\nconst SET_STEP2_JOB_TITLE_CHECKBOX = 'SET_STEP2_JOB_TITLE_CHECKBOX';\r\nconst SET_STEP2_JOB_TITLE_VALUES_FOR_DROPDOWN = 'SET_STEP2_JOB_TITLE_VALUES_FOR_DROPDOWN';\r\n// Safety Codes\r\nconst SET_STEP2_BY_SAFETY_CODE_SELECTION_VALUES = 'SET_STEP2_BY_SAFETY_CODE_SELECTION_VALUES';\r\nconst SET_STEP2_SAFETY_CODE_CHECKBOX = 'SET_STEP2_SAFETY_CODE_CHECKBOX';\r\n\r\nexport default {\r\n RESET_STEP_2_GLOBAL_STATE,\r\n SET_STEP2_BY_EMPLOYMENT_STATUS_SELECTION_VALUES,\r\n SET_STEP2_EMPLOYMENT_STATUS_CHECKBOX,\r\n SET_STEP2_EMPLOYMENT_STATUS_VALUES_FOR_DROPDOWN,\r\n SET_STEP2_FOR_EDITING,\r\n SET_STEP2_BY_JOB_TITLE_SELECTION_VALUES,\r\n SET_STEP2_JOB_TITLE_CHECKBOX,\r\n SET_STEP2_JOB_TITLE_VALUES_FOR_DROPDOWN,\r\n SET_STEP2_BY_SAFETY_CODE_SELECTION_VALUES,\r\n SET_STEP2_SAFETY_CODE_CHECKBOX\r\n}","const RESET_STEP_3_GLOBAL_STATE = 'RESET_STEP_3_GLOBAL_STATE';\r\nconst SET_STEP3_DEFAULT_RANDOMS_TESTING_RATES = 'SET_STEP3_DEFAULT_RANDOMS_TESTING_RATES';\r\nconst SET_STEP3_EXISTING_POOL_NAMES = 'SET_STEP3_EXISTING_POOL_NAMES';\r\nconst SET_STEP3_FOR_EDITING = 'SET_STEP3_FOR_EDITING';\r\nconst SET_STEP3_FREQUENCY_SELECTION = 'SET_STEP3_FREQUENCY_SELECTION';\r\nconst SET_STEP3_PERCENTAGE_ALCOHOL = 'SET_STEP3_PERCENTAGE_ALCOHOL';\r\nconst SET_STEP3_PERCENTAGE_DRUG = 'SET_STEP3_PERCENTAGE_DRUG';\r\nconst SET_STEP3_POOL_NAME = 'SET_STEP3_POOL_NAME';\r\nconst SET_STEP3_POOL_NAME_ALREADY_EXISTS = 'SET_STEP3_POOL_NAME_ALREADY_EXISTS';\r\nconst SET_STEP3_TESTING_AUTHORITY_SELECTION = 'SET_STEP3_TESTING_AUTHORITY_SELECTION';\r\n\r\nexport default {\r\n RESET_STEP_3_GLOBAL_STATE,\r\n SET_STEP3_DEFAULT_RANDOMS_TESTING_RATES,\r\n SET_STEP3_EXISTING_POOL_NAMES,\r\n SET_STEP3_FOR_EDITING,\r\n SET_STEP3_FREQUENCY_SELECTION,\r\n SET_STEP3_PERCENTAGE_ALCOHOL,\r\n SET_STEP3_PERCENTAGE_DRUG,\r\n SET_STEP3_POOL_NAME,\r\n SET_STEP3_POOL_NAME_ALREADY_EXISTS,\r\n SET_STEP3_TESTING_AUTHORITY_SELECTION\r\n}","const ADD_ALERT = 'ADD_ALERT';\r\nconst REMOVE_ALERT = 'REMOVE_ALERT';\r\nconst CLEAR_ALERTS = 'CLEAR_ALERT';\r\n\r\nexport default {\r\n ADD_ALERT,\r\n REMOVE_ALERT,\r\n CLEAR_ALERTS\r\n};","import axios from 'axios';\r\nimport moment from 'moment';\r\n\r\nconst sendAuthorizationEmail = (orderId, orderType, email, employerName, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.post(`/v1/authorizations/${orderId}/email`, {orderType, email, employerName}, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => reject(err));\r\n });\r\n};\r\n\r\nconst getOpenOrders = (selectedSites, forEmployee, onlyPhysicals, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/orders?sites=${selectedSites}&openOrders=true${forEmployee}${onlyPhysicals ? '&onlyPhysicals' : ''}`, {cancelToken})\r\n .then(response => {\r\n return resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error('Failed to get employee open orders', err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getPreviousOrders = (selectedSites, forEmployee, startDate, endDate, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/orders?sites=${selectedSites}${forEmployee ? `&forEmployee=${forEmployee}` : `&startDate=${startDate}&endDate=${endDate}`}`, {cancelToken})\r\n .then(response => {\r\n return resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error('Failed to get previous orders', err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\n/**\r\n * Get drug tests for an employee from IMS\r\n * @param {string} legacyEmployeeId - The employee's legacy ID from MongoDB the corresponds to the IMS Utility API ID\r\n * @param {Object} cancelToken - Axios cancel token\r\n */\r\nconst getDrugTestsForEmployee = async (legacyEmployeeId, cancelToken = null) => {\r\n try {\r\n const drugTests = await axios.get(`/v1/orders/getDrugTestsForEmployee/${legacyEmployeeId}`, {cancelToken});\r\n return drugTests;\r\n } catch (err) {\r\n console.error('Failed to get drug tests for employee', err);\r\n throw err;\r\n }\r\n};\r\n\r\n/**\r\n * Reopens drug order in IMS\r\n * @param {String} orderId - the order ID from IMS\r\n * @param {Object} cancelToken - the axios cancel token\r\n * @returns \r\n */\r\nconst reopenOrder = async (orderId, cancelToken = null) => {\r\n try {\r\n const reopenedOrder = await axios.patch(`/v1/orders/${orderId}/reopen`, {cancelToken});\r\n return reopenedOrder;\r\n } catch (err) {\r\n console.error('Failed to reopen order', err);\r\n throw err;\r\n }\r\n}\r\n\r\n\r\nconst searchOrders = (queryString, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/orders?${queryString}`, {cancelToken})\r\n .then(response => {\r\n if (!response.data.hasOwnProperty(\"orderResults\")) {\r\n return resolve(response.data);\r\n }\r\n return resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error('Failed to get orders', err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\n\r\nconst updateOrder = (orderId, orderStatusChanges, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios\r\n .patch(`/v1/orders/${orderId}`, orderStatusChanges, {cancelToken})\r\n .then(response => {\r\n return resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error('Failed to update order', err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst cancelOrder = (order, email, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n const orderUpdates = {\r\n \"orderId\": order.orderId,\r\n \"medicalExamOrderId\": order.orderId,\r\n \"userEmail\": email,\r\n \"orderType\": order.orderType,\r\n \"updateLog\": {\r\n \"updateStatus\": {\r\n \"orderStatus\": \"Canceled\",\r\n \"orderStatusId\": 6,\r\n \"auditMessage\": \"Status changed to Canceled\"\r\n }\r\n },\r\n \"orderSource\": order.orderSource\r\n };\r\n axios\r\n .patch(`/v1/orders/${order.orderId}`, orderUpdates, {cancelToken})\r\n .then(response => {\r\n return resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error('Failed to update order', err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getAuditTrail = (orderId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n if (!orderId) {\r\n return resolve([]);\r\n }\r\n axios.get(`/v1/orders/${orderId}/auditTrail`, {cancelToken})\r\n .then(response => {\r\n let auditTrail = response.data;\r\n for (let i = 0; i < auditTrail.length; i++) {\r\n auditTrail[i].AuditTime = moment(auditTrail[i].AuditTime).format('M/D/YYYY h:mm a')\r\n }\r\n return resolve(auditTrail);\r\n })\r\n .catch(err => {\r\n if (!axios.isCancel(err)) {\r\n return reject(err);\r\n }\r\n });\r\n });\r\n};\r\n\r\nconst addAuditTrail = (orderId, message, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.post(`/v1/orders/${orderId}/auditTrail`, {message}, {cancelToken})\r\n .then(response => {\r\n return resolve();\r\n })\r\n .catch(err => {\r\n return reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst refreshMVR = (MVRId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.patch(`/v1/orders/${MVRId}/refreshmvr`, {}, {cancelToken})\r\n .then(response => resolve())\r\n .catch(reject)\r\n });\r\n};\r\n\r\n\r\n\r\n// CME = Certified Medical Exam\r\nconst CME = {\r\n /**\r\n * Get CME (Certified Medical Exam) orders\r\n * @param {*} queryString \r\n * @param {*} cancelToken \r\n * @returns \r\n */\r\n getOrders (queryString, cancelToken = null) {\r\n return new Promise((resolve, reject) => {\r\n \r\n const url = `/v1/orders/cme?${queryString}`;\r\n\r\n axios.get(url, {cancelToken})\r\n .then(response => {\r\n return resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error('Failed to get orders', err);\r\n reject(err);\r\n });\r\n });\r\n }\r\n}\r\n\r\n\r\nexport default {\r\n sendAuthorizationEmail,\r\n getOpenOrders,\r\n updateOrder,\r\n cancelOrder,\r\n getPreviousOrders,\r\n getDrugTestsForEmployee,\r\n reopenOrder,\r\n searchOrders,\r\n getAuditTrail,\r\n addAuditTrail,\r\n refreshMVR,\r\n CME\r\n};","const INCREMENT_CURRENT_STEP_BY_1 = 'INCREMENT_CURRENT_STEP_BY_1';\r\nconst DECREMENT_CURRENT_STEP_BY_1 = 'DECREMENT_CURRENT_STEP_BY_1';\r\nconst RESET_ALL_STEPS_GLOBAL_STATE = 'RESET_ALL_STEPS_GLOBAL_STATE';\r\nconst SET_POOL_TO_EDIT = 'SET_POOL_TO_EDIT';\r\nconst SET_RANDOMS_POOL_WIZARD_CRITICAL_ERROR = 'SET_RANDOMS_POOL_WIZARD_CRITICAL_ERROR';\r\nconst SET_RANDOMS_POOL_WIZARD_HAVE_FETCHED_DATA = 'SET_RANDOMS_POOL_WIZARD_HAVE_FETCHED_DATA';\r\nconst SET_RANDOMS_POOL_WIZARD_OK_TO_PROCEED = 'SET_RANDOMS_POOL_WIZARD_OK_TO_PROCEED';\r\nconst SET_SHOW_RANDOMS_POOL_WIZARD = 'SET_SHOW_RANDOMS_POOL_WIZARD';\r\n\r\nexport default {\r\n INCREMENT_CURRENT_STEP_BY_1,\r\n DECREMENT_CURRENT_STEP_BY_1,\r\n RESET_ALL_STEPS_GLOBAL_STATE,\r\n SET_POOL_TO_EDIT,\r\n SET_RANDOMS_POOL_WIZARD_CRITICAL_ERROR,\r\n SET_RANDOMS_POOL_WIZARD_HAVE_FETCHED_DATA,\r\n SET_RANDOMS_POOL_WIZARD_OK_TO_PROCEED,\r\n SET_SHOW_RANDOMS_POOL_WIZARD\r\n}","import React, {Component} from 'react';\r\nimport classNames from 'classnames';\r\nimport _ from 'lodash';\r\n\r\nconst defaultButton = props => (\r\n \r\n);\r\n\r\nexport default class CBReactTablePagination extends Component {\r\n constructor(props) {\r\n super();\r\n this.getSafePage = this.getSafePage.bind(this);\r\n this.changePage = this.changePage.bind(this);\r\n this.applyPage = this.applyPage.bind(this);\r\n\r\n this.state = {\r\n page: props.page\r\n };\r\n }\r\n\r\n componentDidMount() {\r\n this.updateCurrentRows(this.props);\r\n }\r\n\r\n componentDidUpdate(prevProps, prevState, snapshot) {\r\n if (!_.isEqual(prevProps.page, this.props.page) || !_.isEqual(prevProps.sortedData, this.props.sortedData)) {\r\n if (!_.isEqual(prevProps.page, this.props.page)) {\r\n this.setState({page: this.props.page});\r\n }\r\n this.updateCurrentRows(this.props);\r\n }\r\n }\r\n\r\n updateCurrentRows(props) {\r\n if (typeof props.sortedData !== 'undefined' //use props.data for unfiltered (all) rows\r\n && typeof props.page !== 'undefined'\r\n && typeof props.pageSize !== 'undefined'\r\n ) {\r\n const rowCount = props.sortedData.length; //use props.data.length for unfiltered (all) rows\r\n this.setState({\r\n rowCount,\r\n rowMin: props.page * props.pageSize + 1,\r\n rowMax: Math.min((props.page + 1) * props.pageSize, rowCount)\r\n });\r\n }\r\n }\r\n\r\n getSafePage(page) {\r\n if (isNaN(page)) {\r\n page = this.props.page\r\n }\r\n return Math.min(Math.max(page, 0), this.props.pages - 1);\r\n }\r\n\r\n changePage(page) {\r\n page = this.getSafePage(page);\r\n this.setState({page});\r\n if (this.props.page !== page) {\r\n this.props.onPageChange(page);\r\n }\r\n\r\n this.updateCurrentRows(page);\r\n }\r\n\r\n applyPage(e) {\r\n if (e) {\r\n e.preventDefault();\r\n }\r\n const page = this.state.page;\r\n this.changePage(page === '' ? this.props.page : page);\r\n }\r\n\r\n render() {\r\n const {\r\n // Computed\r\n pages,\r\n // Props\r\n page,\r\n showPageSizeOptions,\r\n pageSizeOptions,\r\n pageSize,\r\n showPageJump,\r\n canPrevious,\r\n canNext,\r\n onPageSizeChange,\r\n className,\r\n PreviousComponent = defaultButton,\r\n NextComponent = defaultButton\r\n } = this.props;\r\n\r\n return (\r\n \r\n
\r\n
{\r\n if (!canPrevious) return;\r\n this.changePage(page - 1);\r\n }}\r\n disabled={!canPrevious}\r\n >\r\n {this.props.previousText}\r\n \r\n
\r\n
\r\n
\r\n {this.props.pageText}{' '}\r\n {showPageJump\r\n ?\r\n \r\n {\r\n const val = e.target.value;\r\n const page = val - 1;\r\n if (val === '') {\r\n return this.setState({page: val});\r\n }\r\n this.setState({page: this.getSafePage(page)});\r\n }}\r\n value={this.state.page === '' ? '' : this.state.page + 1}\r\n onBlur={this.applyPage}\r\n onKeyPress={e => {\r\n if (e.which === 13 || e.keyCode === 13) {\r\n this.applyPage();\r\n }\r\n }}\r\n />\r\n
\r\n :\r\n \r\n {page + 1}\r\n \r\n }\r\n {' '}\r\n {this.props.ofText}{' '}\r\n {pages || 1}\r\n \r\n {(typeof this.state.rowCount !== 'undefined' && this.state.rowCount > 0)\r\n ?\r\n
\r\n {\"Showing \"}\r\n {this.state.rowMin}\r\n {\" - \"}\r\n {this.state.rowMax}\r\n {\" of \"}\r\n {this.state.rowCount}\r\n {\" total rows\"}\r\n \r\n : ''\r\n }\r\n {showPageSizeOptions &&\r\n
\r\n \r\n \r\n }\r\n
\r\n
\r\n {\r\n if (!canNext) return;\r\n this.changePage(page + 1);\r\n }}\r\n disabled={!canNext}\r\n >\r\n {this.props.nextText}\r\n \r\n
\r\n
\r\n )\r\n }\r\n}","// Step 1\r\nconst SET_STEP1_BY_DOT_NUMBER_SELECTION_VALUES = 'SET_STEP1_BY_DOT_NUMBER_SELECTION_VALUES';\r\nconst SET_STEP1_BY_LOCATION_NAME_SELECTION_VALUES = 'SET_STEP1_BY_LOCATION_NAME_SELECTION_VALUES';\r\nconst RESET_STEP_1_GLOBAL_STATE = 'RESET_STEP_1_GLOBAL_STATE';\r\nconst SET_STEP1_DOT_LIST_FOR_DROPDOWN = 'SET_STEP1_DOT_LIST_FOR_DROPDOWN';\r\nconst SET_STEP1_FOR_EDITING = 'SET_STEP1_FOR_EDITING';\r\nconst SET_STEP1_LOCATION_SEARCH_QUERY = 'SET_STEP1_LOCATION_SEARCH_QUERY';\r\nconst SET_STEP1_SELECTION = 'SET_STEP1_SELECTION';\r\n\r\nexport default {\r\n SET_STEP1_BY_DOT_NUMBER_SELECTION_VALUES,\r\n SET_STEP1_BY_LOCATION_NAME_SELECTION_VALUES,\r\n RESET_STEP_1_GLOBAL_STATE,\r\n SET_STEP1_DOT_LIST_FOR_DROPDOWN,\r\n SET_STEP1_FOR_EDITING,\r\n SET_STEP1_LOCATION_SEARCH_QUERY,\r\n SET_STEP1_SELECTION,\r\n}","const RESET_STEP_4_GLOBAL_STATE = 'RESET_STEP_4_GLOBAL_STATE';\r\nconst SET_STEP4_AVG_POOL_ROSTER_SIZE = 'SET_STEP4_AVG_POOL_ROSTER_SIZE';\r\nconst SET_STEP4_FOR_EDITING = 'SET_STEP4_FOR_EDITING';\r\nconst SET_STEP4_NUM_SELECTED_DRUG = 'SET_STEP4_NUM_SELECTED_DRUG';\r\nconst SET_STEP4_NUM_TESTED_DRUG = 'SET_STEP4_NUM_TESTED_DRUG';\r\nconst SET_STEP4_NUM_SELECTED_ALCOHOL = 'SET_STEP4_NUM_SELECTED_ALCOHOL';\r\nconst SET_STEP4_NUM_TESTED_ALCOHOL = 'SET_STEP4_NUM_TESTED_ALCOHOL';\r\n\r\nexport default {\r\n RESET_STEP_4_GLOBAL_STATE,\r\n SET_STEP4_AVG_POOL_ROSTER_SIZE,\r\n SET_STEP4_FOR_EDITING,\r\n SET_STEP4_NUM_SELECTED_DRUG,\r\n SET_STEP4_NUM_TESTED_DRUG,\r\n SET_STEP4_NUM_SELECTED_ALCOHOL,\r\n SET_STEP4_NUM_TESTED_ALCOHOL\r\n}","import axios from \"axios\";\r\n\r\nconst setAuthToken = token => {\r\n if (token) {\r\n axios.defaults.headers.common['Authorization'] = token;\r\n } else {\r\n delete axios.defaults.headers.common['Authorization'];\r\n }\r\n};\r\n\r\nexport default setAuthToken;","import React, {Component} from 'react';\r\nimport DatePicker from 'react-datepicker';\r\nimport _ from 'lodash';\r\nimport {alertsOperations} from '../../../ducks/alerts';\r\nimport {connect} from 'react-redux';\r\n\r\n/**\r\n * must have either id or key.\r\n */\r\nclass DateInputWrapperContainer extends Component {\r\n\r\n handleDatePickerChange = date => {\r\n if (date && (!date.isValid() || date.isBefore('1900-01-01') || !date.isBefore('2100-01-01'))) {\r\n this.props.addAlert(`The date that you entered (${date ? date.format('M/D/YYYY') : ''}) is invalid. Please enter a valid date between 1900 and 2099`, 'danger');\r\n this.props.onChangeHandler(null);\r\n } else {\r\n this.props.onChangeHandler(date);\r\n }\r\n };\r\n\r\n render() {\r\n const other = _.omit(this.props, ['keyName', 'id', 'onChangeHandler']);\r\n return (\r\n \r\n );\r\n }\r\n\r\n}\r\n\r\nconst mapDispatchToProps = {\r\n addAlert: alertsOperations.addAlert\r\n};\r\n\r\nexport default connect(null, mapDispatchToProps)(DateInputWrapperContainer);","import {combineReducers} from 'redux';\r\nimport moment from 'moment';\r\nimport uuid from 'uuid/v1';\r\nimport _ from 'lodash';\r\n\r\nimport types from './types';\r\n\r\nconst excelDataReducer = (state = {}, action) => {\r\n switch (action.type) {\r\n case types.DQF_SET_FILTERED_EXCEL_DATA:\r\n return {\r\n ...state,\r\n filteredExcelData: action.payload\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nexport const defaultEmployeeRosterState = {\r\n rosterView: 'ACTIVE_EMPLOYEES',\r\n randomsRosterView: 'RANDOMS_SELECTED_EMPLOYEES',\r\n randomsPoolRosterView: 'ALL_EMPLOYEES',\r\n sortedFilteredEmployeeIds: []\r\n};\r\n\r\nconst employeeRosterReducer = (state = defaultEmployeeRosterState, action) => {\r\n switch (action.type) {\r\n case types.DQF_SET_ROSTER_VIEW:\r\n return {\r\n ...state,\r\n rosterView: action.payload.rosterView,\r\n auditId: action.payload.auditId\r\n };\r\n case types.DQF_SET_RANDOMS_ROSTER_VIEW:\r\n return {\r\n ...state,\r\n randomsRosterView: action.payload.rosterView,\r\n };\r\n case types.DQF_SET_RANDOMS_POOL_ROSTER_VIEW:\r\n return {\r\n ...state,\r\n randomsPoolRosterView: action.payload.rosterView,\r\n };\r\n case types.DQF_SET_SORTED_FILTERED_ROSTER:\r\n return {\r\n ...state,\r\n sortedFilteredEmployeeIds: action.payload\r\n };\r\n case types.DQF_SET_ROSTER_SELECTED_LOCATION:\r\n return {\r\n ...state,\r\n selectedLocation: action.payload\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst employeeSearchReducer = (state = {query: '', results: []}, action) => {\r\n const now = moment(Date.now());\r\n switch (action.type) {\r\n case types.DQF_SEARCH_EMPLOYEES:\r\n return {\r\n ...state,\r\n query: action.payload.query,\r\n results: action.payload.results,\r\n timestamp: now,\r\n redirectTo: action.payload.redirectTo\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst notificationsDefaultState = {\r\n loading: false,\r\n list: [],\r\n filterBy: '',\r\n pendingChanges: {},\r\n editing: false,\r\n managerKey: uuid()\r\n};\r\n\r\nconst notificationsReducer = (state = notificationsDefaultState, action) => {\r\n switch (action.type) {\r\n case types.DQF_SET_SORTED_FILTERED_ROSTER:\r\n return {\r\n ...state\r\n };\r\n case types.DQF_NOTIFICATIONS_SET_LOADING:\r\n return {\r\n ...state,\r\n loading: action.payload\r\n };\r\n case types.DQF_NOTIFICATIONS_SET_LIST:\r\n return {\r\n ...state,\r\n list: action.payload\r\n };\r\n case types.DQF_NOTIFICATIONS_APPLY_CHANGES:\r\n const changeLog = action.payload;\r\n const currentList = _.cloneDeep(state.list);\r\n // for each contact\r\n Object.keys(changeLog).forEach(contactId => {\r\n const notificationToUpdate = currentList.find(cl => cl.contactId === parseInt(contactId, 10));\r\n // for each (contact) notification change\r\n Object.keys(changeLog[contactId]).forEach(notificationChange => {\r\n if (notificationChange === 'csaScores') {//csa notifications are handled differently\r\n notificationToUpdate[notificationChange] = changeLog[contactId][notificationChange].csaScores;\r\n } else if (notificationChange === 'csaDetails') {\r\n notificationToUpdate.types = changeLog[contactId][notificationChange].types;\r\n let allOn = true;\r\n let allOff = true;\r\n // Start by assuming they're all on, AND they're all off; obviously one or both of these assumptions is inccorrect\r\n notificationToUpdate.types.forEach((type) => {\r\n // Check each type to see if they're all on or they're all off (skip over the properties for type id and type name)\r\n if (allOn || allOff) {\r\n if (Object.entries(type).some(([key, value]) => key !== 'typeId' && key !== 'typeName' && !!value)) {\r\n // At least one in this type is on, so they can't all be off\r\n allOff = false;\r\n }\r\n if (Object.entries(type).some(([key, value]) => key !== 'typeId' && key !== 'typeName' && !value)) {\r\n // At least one in this type is off, so they can't all be on\r\n allOn = false;\r\n }\r\n }\r\n });\r\n notificationToUpdate.csaDetail = allOn ? 'ALL' : allOff ? '' : 'SOME';\r\n delete notificationToUpdate.csaDetails;\r\n } else {\r\n notificationToUpdate[notificationChange] = changeLog[contactId][notificationChange];\r\n }\r\n });\r\n });\r\n return {\r\n ...state,\r\n list: currentList\r\n };\r\n case types.DQF_NOTIFICATIONS_CHANGED:\r\n return {\r\n ...state,\r\n pendingChanges: action.payload.pendingChanges\r\n };\r\n case types.DQF_NOTIFICATIONS_SET_EDITING:\r\n const currentState = state;\r\n const newState = action.payload;\r\n let managerKey = currentState.managerKey;\r\n let pendingChanges = {...currentState.pendingChanges};\r\n if (!newState.editing && newState.canceled && Object.keys(pendingChanges).length > 0) {\r\n managerKey = uuid();\r\n pendingChanges = {};\r\n }\r\n return {\r\n ...currentState,\r\n managerKey,\r\n pendingChanges,\r\n editing: action.payload.isEditing\r\n };\r\n case types.DQF_NOTIFICATIONS_SET_FILTER_BY:\r\n return {\r\n ...state,\r\n filterBy: action.payload.filterBy\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst sitesReducer = (state = {\r\n sessionClient: '',\r\n selectedSites: [],\r\n siteTree: {},\r\n displaySite: {},\r\n selectedHierarchySites: [],\r\n autoSelectSite: null,\r\n sitesSelectorEnabled: false\r\n}, action) => {\r\n switch (action.type) {\r\n case types.DQF_SITES_SET_SELECTED:\r\n return {\r\n ...state,\r\n selectedSites: action.payload.selectedSites,\r\n displaySite: action.payload.displaySite\r\n };\r\n case types.DQF_SITES_SET_SITE_TREE:\r\n return {\r\n ...state,\r\n siteTree: action.payload\r\n };\r\n case types.DQF_SITES_SET_SESSION_CLIENT:\r\n return {\r\n ...state,\r\n sessionClient: action.payload\r\n };\r\n case types.DQF_SET_SELECTED_HIERARCHY_SITES:\r\n return {\r\n ...state,\r\n selectedHierarchySites: action.payload\r\n };\r\n case types.DQF_SET_AUTO_SELECT_SITE:\r\n return {\r\n ...state,\r\n autoSelectSite: action.payload\r\n };\r\n case types.DQF_SET_SITES_SELECTOR_ENABLED:\r\n return {\r\n ...state,\r\n sitesSelectorEnabled: action.payload\r\n };\r\n case types.DQF_SITES_SET_DISPLAY_INCLUDE_CHILDREN:\r\n return {\r\n ...state,\r\n displayIncludeChildren: action.payload\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst alertCountsReducer = (state = {}, action) => {\r\n switch (action.type) {\r\n case types.DQF_SET_ALERT_COUNTS:\r\n return action.payload;\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst alertValuesReducer = (state = {}, action) => {\r\n switch (action.type) {\r\n case types.DQF_SET_ALERTS_VALUES:\r\n return action.payload;\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst displayIncludeChildrenReducer = (state = {}, action) => {\r\n switch (action.type) {\r\n case types.DQF_SET_DISPLAY_INCLUDE_CHILDREN:\r\n return action.payload;\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst documentTabsSingleOrMultiReducer = (state = 'multi', action) => {\r\n switch (action.type) {\r\n case types.DQF_SET_DOCUMENT_TABS_SINGLE_OR_MULTI:\r\n return action.payload;\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst unscoredMVRsReducer = (state = [], action) => {\r\n switch (action.type) {\r\n case types.DQF_SET_UNSCORED_MVRS:\r\n return action.payload;\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst reducer = combineReducers({\r\n excelData: excelDataReducer,\r\n employeeRoster: employeeRosterReducer,\r\n employeeSearch: employeeSearchReducer,\r\n notifications: notificationsReducer,\r\n sites: sitesReducer,\r\n alertCounts: alertCountsReducer,\r\n alertsValues: alertValuesReducer,\r\n displayIncludeChildren: displayIncludeChildrenReducer,\r\n documentTabsSingleOrMulti: documentTabsSingleOrMultiReducer,\r\n unscoredMVRs: unscoredMVRsReducer\r\n});\r\n\r\nexport default reducer;","import axios from 'axios';\r\nimport { stringify } from 'querystring';\r\nimport { apiService } from '../apiService/apiService';\r\n\r\nconst getClientList = (cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients?filters=topLevel`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getClient = (clientId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getClientByLegacyId = (clientId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}?source=legacy`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\n\r\nconst getTopLevelClient = (childClientId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients?familyOf=${childClientId}`, {cancelToken})\r\n .then(response => {\r\n if (response.status !== 200 || response.data.length !== 1) {\r\n return reject('Unexpected response from server looking up parent location');\r\n }\r\n return resolve(response.data[0]);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\n// NOTE: this method is dangerous because if the object passed is missing any\r\n// of the following information: (name, primaryAddress, contacts, notes, deactivated, employeeIdentifier) these fields will\r\n// null out the existing values. Right now only the Client Detail page is using this method and is providing\r\n// the full client object so all information is retained.\r\n// todo: create dynamic patch method only modify what is provided\r\nconst updateClient = (client, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios\r\n .put(`/v1/clients/${client._id}`, {\r\n name: client.name,\r\n primaryAddress: client.primaryAddress,\r\n contacts: client.contacts,\r\n notes: client.notes,\r\n deactivated: client.deactivated,\r\n employeeIdentifier: client.employeeIdentifier\r\n }, {cancelToken})\r\n .then(response => {\r\n resolve();\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst patchClient = (clientId, clientChanges, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n if (!clientId) {\r\n return reject(new Error('Client id is required'));\r\n }\r\n if (!clientChanges || Object.keys(clientChanges).length === 0) {\r\n return reject(new Error('Patch body is required'));\r\n }\r\n axios\r\n .patch(`/v1/clients/${clientId}`, clientChanges, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 201) {\r\n return reject(new Error('Unexpected response from server updating client'));\r\n }\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n })\r\n};\r\n\r\nconst setNotes = (clientId, notes, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios\r\n .put(`/v1/clients/${clientId}/notes`, {notes}, {cancelToken})\r\n .then(response => {\r\n resolve();\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst setServices = (clientId, services, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios\r\n .put(`/v1/clients/${clientId}/services`, {services}, {cancelToken})\r\n .then(response => {\r\n resolve();\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst uploadLogo = (clientId, logo, cancelToken = null) => {\r\n const data = new FormData();\r\n data.append('image', logo);\r\n return new Promise((resolve, reject) => {\r\n axios\r\n .post(`/v1/clients/${clientId}/logo`, data, {cancelToken})\r\n .then(result => resolve(result.data))\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getNonImportedLegacyClientList = (cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get('/v1/clients?source=legacy&filters=topLevel,nonImported', {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getClientSummary = (clientId, sites, isRandoms, cancelToken) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/employees?summary=true&sites=${sites}${isRandoms ? '&isRandoms' : ''}`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getFastTestResultsForClient = (clientId, sites, startDate, endDate, cancelToken) => {\r\n let url = `/v1/clients/${clientId}/fasttest?sites=${sites}`;\r\n if (!!startDate) {\r\n url += `&startDate=${startDate.format('YYYY-MM-DD')}T00:00:00`;\r\n }\r\n if (!!endDate) {\r\n url += `&endDate=${endDate.format('YYYY-MM-DD')}T23:59:59`;\r\n }\r\n return new Promise((resolve, reject) => {\r\n axios.get(url, {cancelToken})\r\n .then(response => resolve(response.data))\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getRandomsPoolsForClient = (clientId, cancelToken) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/pools`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\n/**\r\n * getRandomsPoolsByClient\r\n * @param {string} clientId\r\n * @param {Object} [summary]\r\n * @param {true|Object|String|Array } summary - true for default summary fields or\r\n * choose the fields returned from RandomPools Schema using https://mongoosejs.com/docs/5.x/docs/api.html#query_Query-select.\r\n * @returns RandomPools[]\r\n */\r\nconst getRandomsPoolsByClient = (clientId, summary) => apiService({\r\n url: `/v1/clients/${clientId}/pools?${stringify({ summary })}`\r\n});\r\n\r\nconst getClientComplianceSummary = (clientId, cancelToken) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/compliance`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getClientAudits = (clientId, cancelToken) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/audits`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getActiveEmployeesBySite = (clientId, sites, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/employees?active=true&sites=${sites}`, {cancelToken}\r\n )\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getAlerts = (clientId, sites, alertTypes, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/alerts?alertTypes=${alertTypes.join(',')}&sites=${sites}&summary&problemsAndWarningsOnly=true`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getDocReviewAlerts = (clientId, sites, cancelToken, mvrOrEPN) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/alerts?alertTypes=${mvrOrEPN}&sites=${sites}`, {cancelToken})\r\n .then(response => {\r\n resolve(mvrOrEPN === 'MVR' ? response.data.mvrAlerts : response.data.epnAlerts);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getStaleApplicantAlerts = (clientId, sites, cancelToken) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/alerts?alertTypes=staleApplicants&sites=${sites}`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data.staleApplicantAlerts);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getCSAAlerts = (clientId, sites, cancelToken) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/alerts?alertTypes=CSA&sites=${sites}`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getDACAlerts = (clientId, sites, cancelToken) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/alerts?alertTypes=DAC&sites=${sites}`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data.dacStatus);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getDocumentAlerts = (clientId, sites, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/alerts?alertTypes=documents&sites=${sites}`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getMissingDocuments = (clientId, sites, allEmployees, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/alerts?alertTypes=missingDocuments&sites=${sites}&allEmployees=${allEmployees}`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data.docAlerts);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getMissingAndExpiredDocuments = (\r\n clientId,\r\n sites,\r\n applicant,\r\n employee,\r\n inactive,\r\n terminated,\r\n missing,\r\n expired,\r\n expiredDays,\r\n expiring,\r\n expiringDays,\r\n cancelToken = null\r\n) => {\r\n const employmentStatuses = [];\r\n if (applicant) {\r\n employmentStatuses.push('Applicant');\r\n }\r\n if (employee) {\r\n employmentStatuses.push('Employee');\r\n }\r\n if (inactive) {\r\n employmentStatuses.push('Inactive');\r\n }\r\n if (terminated) {\r\n employmentStatuses.push('Terminated');\r\n }\r\n const docStatuses = [];\r\n if (missing) {\r\n docStatuses.push('missing');\r\n }\r\n if (expired) {\r\n docStatuses.push('expired');\r\n }\r\n if (expiring) {\r\n docStatuses.push('expiring');\r\n }\r\n return new Promise((resolve, reject) => {\r\n axios.get(\r\n // We need to pass allEmployees=true so that it gets them all from the sproc; then we also pass the list of\r\n // statuses that we really care about, so that they are filtered from the sproc results at the server.\r\n // Also pass the list of docSTatuses that we want, as well as expiredDays and expiringDays\r\n // -- and let the server do all the filtering.\r\n `/v1/clients/${clientId}/alerts?alertTypes=missingDocuments&sites=${sites}&allEmployees=true&employmentStatuses=${employmentStatuses}&docStatuses=${docStatuses}&expiredDays=${expiredDays}&expiringDays=${expiringDays}`,\r\n {cancelToken}\r\n )\r\n .then(response => {\r\n resolve(response.data.docAlerts);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n }\r\n );\r\n};\r\n\r\nconst getCSAReportData = (clientId, forUser, sites, reportType, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n let url = `/v1/clients/${clientId}/csa?forUser=${forUser}&reportType=${reportType}`;\r\n if (reportType === 'csaLocation') {\r\n url += `&selectedClientId=${sites}`\r\n } else {\r\n url += `&selectedDOTIds=${sites.join(',')}`;\r\n }\r\n axios.get(url, {cancelToken})\r\n .then(response => {\r\n const results = response.data.results || [];\r\n resolve(results);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\n// this is misleading: 'sites' is either sites or dotNums?\r\nconst getCrashReportData = (clientId, forUser, sites, reportType, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n let url = `/v1/clients/${clientId}/crashes?forUser=${forUser}&reportType=${reportType}`;\r\n if (reportType === 'crashLocation') {\r\n url += `&selectedClientId=${sites}`\r\n } else {\r\n url += `&selectedDOTIds=${sites.join(',')}`;\r\n }\r\n axios.get(url, {cancelToken})\r\n .then(response => {\r\n const results = response.data.results || [];\r\n resolve(results);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\n/**\r\n * Get Med Cards for a single client location or include child locations\r\n * @param {string} legacyClientId - The legacy ID of the client\r\n * @param {Array} [selectedSites=null] - An array of selected site IDs (optional)\r\n * @param {object} [cancelToken=null] - Axios cancel token for request cancellation (optional)\r\n * @returns {Promise>} - The response data from the API\r\n * @property {string} response[].companyName - The name of the company associated with the med card\r\n * @property {string} response[].locationName - The name of the location associated with the med card\r\n * @property {string} response[].employeeName - The name of the employee holding the med card\r\n * @property {string} response[].ssn - The Social Security Number of the employee\r\n * @property {string} response[].documentBucketName - The type of document (Medical Examiners Certificate)\r\n * @property {string} response[].docDate - The date the document was issued, formatted as an ISO 8601 string\r\n * @property {string} response[].expirationDate - The expiration date of the document, formatted as an ISO 8601 string\r\n */\r\nconst getReportOfAllMedCardsByLocation = async ({clientId, isIncludeChildren, cancelToken = null}) => {\r\n try {\r\n const url = `/v1/clients/medCards`;\r\n const requestBody = {\r\n clientId,\r\n isIncludeChildren,\r\n };\r\n const response = await axios.post(url, requestBody, { cancelToken });\r\n return response.data;\r\n } catch (err) {\r\n console.error('Error fetching med cards:', err);\r\n throw err;\r\n }\r\n};\r\n\r\nconst getEmployeesDOTReportData = (clientId, forUser, sites, reportType, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n let url = `/v1/clients/${clientId}/employeesByDot?reportType=employeesDOT`;\r\n url += `&selectedDOTIds=${sites.join(',')}`;\r\n axios.get(url, {cancelToken})\r\n .then(response => {\r\n const results = response.data || [];\r\n resolve(results);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getAccidentReportData = (clientId, forUser, sites, reportType, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n let url = `/v1/clients/${clientId}/accidents?forUser=${forUser}&reportType=${reportType}`;\r\n if (reportType === 'accidentLocation') {\r\n url += `&selectedClientId=${sites}`\r\n } else {\r\n url += `&selectedDOTIds=${sites.join(',')}`;\r\n }\r\n axios.get(url, {cancelToken})\r\n .then(response => {\r\n const results = response.data.results || [];\r\n resolve(results);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getDrugAlcoholReportData = (clientId, forUser, sites, reportType, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n let url = `/v1/clients/${clientId}/drugAlcohol?forUser=${forUser}&reportType=${reportType}`;\r\n if (reportType === 'daLocation') {\r\n url += `&selectedClientId=${sites}`\r\n } else {\r\n url += `&selectedDOTIds=${sites.join(',')}`;\r\n }\r\n axios.get(url, {cancelToken})\r\n .then(response => {\r\n const results = response.data.results || [];\r\n resolve(results);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\n// TODO: remove this\r\nconst addRandomPool = (clientId, pools, topLevel, includeChildren, configuring = false, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n if (!clientId) {\r\n return reject(new Error('The client id is required'));\r\n }\r\n if (!pools || Object.keys(pools).length === 0) {\r\n return reject(new Error('The random pool is required'));\r\n }\r\n axios.post(`/v1/clients/${clientId}/pools?topLevel=${topLevel}&includeChildren=${includeChildren}&configuring=${configuring}`, pools, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 201 && res.status !== 200) {\r\n return reject(new Error('Unexpected response from server when adding new randoms pool to client'));\r\n }\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst addEZComplianceRandomsPool = (clientId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n if (!clientId) {\r\n return reject(new Error('The client id is required'));\r\n }\r\n axios.post(`/v1/clients/${clientId}/pools?ezCompliance=true&topLevel=true`, {}, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 201) {\r\n return reject(new Error('Unexpected response from server when adding new randoms pool to client'));\r\n }\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst removeEZComplianceRandomsPool = (clientId, poolId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n if (!poolId || !clientId) {\r\n return reject(new Error('pool id and client id is required'));\r\n }\r\n axios.delete(`/v1/clients/${clientId}/pools/${poolId}?ezCompliance=true&topLevel=true`, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 204) {\r\n return reject(new Error('Unexpected response from server when deleting provided randoms pool'));\r\n }\r\n resolve();\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst updateRandomPool = (pool, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n if (!pool || !pool._id) {\r\n return reject(new Error('pool is required'));\r\n }\r\n axios.patch(`/v1/clients/0/pools/${pool._id}`, pool, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 204) {\r\n return reject(new Error('Unexpected response from server when updating provided randoms pool'));\r\n }\r\n resolve();\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst deleteRandomPool = (clientId, poolId, topLevel, includeChildren = false, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n if (!poolId || !clientId) {\r\n return reject(new Error('pool id and client id is required'));\r\n }\r\n axios.delete(`/v1/clients/${clientId}/pools/${poolId}?topLevel=${topLevel}&includeChildren=${includeChildren}`, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 204) {\r\n return reject(new Error('Unexpected response from server when deleting provided randoms pool'));\r\n }\r\n resolve();\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst createRandomsPool = (clientId, poolDefinition, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n if (!clientId) {\r\n return reject(new Error('The client id is required'));\r\n }\r\n if (!poolDefinition) {\r\n return reject(new Error('The pool definition is required'));\r\n }\r\n axios.post(`/v1/clients/${clientId}/pools`, poolDefinition, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 204) {\r\n return reject(new Error('Unexpected response from server when creating randoms pool'));\r\n }\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst modifyRandomsPool = (clientId, poolDefinition, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n if (!clientId) {\r\n return reject(new Error('The client id is required'));\r\n }\r\n if (!poolDefinition) {\r\n return reject(new Error('The pool definition is required'));\r\n }\r\n axios.patch(`/v1/clients/${clientId}/pools/${poolDefinition._id}`, poolDefinition, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 204) {\r\n return reject(new Error('Unexpected response from server when updating provided randoms pool'));\r\n }\r\n resolve();\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getPools = (clientId, availablePools = false, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/pools?availablePools=${availablePools}`, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 200) {\r\n return reject(new Error('Unexpected response from server'));\r\n }\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getEmployeesForPool = (pool, clientId, sites, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.post(`/v1/clients/${clientId}/pools/employeeList?sites=${sites}`, pool, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 201) {\r\n return reject(new Error('Unexpected response from server'));\r\n }\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getLocationsForPool = (pool, clientId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.post(`/v1/clients/${clientId}/pools/locationList`, pool, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 201) {\r\n return reject(new Error('Unexpected response from server'));\r\n }\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getUsersForClient = (clientId, forPermission = null, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n if (!clientId) {\r\n return reject(new Error('Invalid parameters. Unable to make request.'));\r\n }\r\n let url = `/v1/clients/${clientId}/users`;\r\n if (forPermission) {\r\n url += `?forPermission=${forPermission}`\r\n }\r\n axios.get(url, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 200) {\r\n return reject(new Error('Unexpected error from server'));\r\n }\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getJobTitleProgramsForClient = (legacyClientId, cancelToken) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${legacyClientId}/jobTitles?includePrograms=true&legacyClientId=${legacyClientId}`, {cancelToken})\r\n .then(response => {\r\n resolve(response);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst addJobTitleToClient = (selectedJobTitle, legacyClientId, newJobTitleName, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n if (!legacyClientId) {\r\n return reject(new Error('The client id is required'));\r\n }\r\n if (!newJobTitleName && !selectedJobTitle) {\r\n return reject(new Error('The job title is required to be specified'));\r\n }\r\n let jobTitleId = -1;\r\n let jobTitleName = newJobTitleName;\r\n if (selectedJobTitle) {\r\n jobTitleId = selectedJobTitle.value;\r\n jobTitleName = selectedJobTitle.name;\r\n }\r\n axios.post(`/v1/clients/${legacyClientId}/jobTitles/${jobTitleId}?jobTitle=${jobTitleName}${newJobTitleName ? '&isNew=true' : ''}`, {}, {cancelToken})\r\n .then(res => {\r\n if (res.status !== 201 && res.status !== 200) {\r\n return reject(new Error('Unexpected response from server when adding new job title to client'));\r\n }\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst updateClientHierarchy = (clientId, legacyClientId, LCodes, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.patch(`/v1/clients/${clientId}/hierarchy`, {legacyClientId, LCodes}, {cancelToken})\r\n .then(res => {\r\n resolve();\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst calculateRandomSelection = (clientId, poolId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/pools/${poolId}/selections/calculation`, {cancelToken})\r\n .then(res => {\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst makeRandomSelection = (clientId, poolId, numToSelectDrug, numToSelectAlcohol, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.post(`/v1/clients/${clientId}/pools/${poolId}/selections?drug=${numToSelectDrug}&alcohol=${numToSelectAlcohol}`, {}, {cancelToken})\r\n .then(res => {\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst extendRandomSelection = (clientId, poolId, selectionId, numToSelectDrug, numToSelectAlcohol, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.patch(`/v1/clients/${clientId}/pools/${poolId}/selections/${selectionId}`, {numToSelectDrug, numToSelectAlcohol}, {cancelToken})\r\n .then(res => {\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst makeRandomAlternateSelection = (clientId, poolId, alternateValue, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.post(`/v1/clients/${clientId}/pools/${poolId}/selections${!!alternateValue ? '?alternateNumber=' + alternateValue : ''}`, {}, {cancelToken})\r\n .then(res => {\r\n resolve(res.data);\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getPreviousRandomsPoolSelections = (clientId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/pools/selections/previous`, {cancelToken})\r\n .then(result => {\r\n resolve(result.data)\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\n\r\n// getAlternates indicates to get the alternate list instead of the selection\r\n// getSnapshot indicates to get the whole roster snapshot not just the selection\r\nconst getRandomSelection = ({clientId, poolId, selectionId, getAlternates = false, getSnapshot = false, isInternalUser, impersonatingUserId, cancelToken = null}) => {\r\n return new Promise((resolve, reject) => {\r\n const optionString = `${'?'}${getAlternates ? 'alternates&' : ''}${getSnapshot ? 'snapshot&' : ''}${isInternalUser ? 'isInternalUser=true&' : ''}${impersonatingUserId ? `impersonatingUserId=${impersonatingUserId}` : ''}`;\r\n axios.get(`/v1/clients/${clientId}/pools/${poolId}/selections/${selectionId}${optionString}`, {cancelToken})\r\n .then(result => {\r\n resolve(result.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getDocTypesForClient = (clientId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/docTypes`, {cancelToken})\r\n .then(response => {\r\n resolve(response);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst searchForDrugTestMatch = (clientId, searchData, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.post(`/v1/clients/${clientId}/drugTestMatch`, {searchData}, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst saveDrugTestMatch = (clientId, employeeId, specimenReferenceId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.post(`/v1/clients/${clientId}/drugTestMatch/${specimenReferenceId}?employeeId=${employeeId}`, {}, {cancelToken})\r\n .then(response => {\r\n resolve();\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst updateDrugTestMatch = (clientId, employeeId, specimenReferenceId, data, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.patch(`/v1/clients/${clientId}/drugTestMatch/${specimenReferenceId}?employeeId=${employeeId}`, data, {cancelToken})\r\n .then(response => {\r\n resolve();\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\n\r\nconst getSelectionsForEmployee = (clientId, employeeId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/selections/${employeeId}`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst emailRandomSelection = (clientId, poolId, selectionId, emailList, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.post(`/v1/clients/${clientId}/pools/${poolId}/selections/${selectionId}/email`, {emailList}, {cancelToken})\r\n .then(result => resolve(result.data))\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst copySettingsFromLocation = (clientId, clientFrom, fields, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.patch(`/v1/clients/${clientId}?settingsFrom=${clientFrom}&fields=${fields.join()}&legacy=true`, {}, {cancelToken})\r\n .then(result => resolve())\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getEmployeeCount = (clientId, jobTitleId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/employees/count?jobTitleId=${jobTitleId}`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst deleteJobTitleTransferEmployees = (clientId, deleteJobTitleId, transferJobTitle, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.patch(`/v1/clients/${clientId}/removeJobTitle?deleteJobTitleId=${deleteJobTitleId}&transferJobTitle=${transferJobTitle}`, {cancelToken})\r\n .then(() => resolve())\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getClientMVRScoreDefs = (clientId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/MVRScoreDefs`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getClientMVRScoringRules = (clientId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/MVRScoringRules`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getClientMVRScoringReasons = (clientId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/MVRScoringReasons`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst searchByDOTNumber = (DOTNumber, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients?source=legacy&dotnumber=${DOTNumber}`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getClientLocations = (clientId, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients?descendantsOf=${clientId}&filters=active&source=legacy&aliases=true&flatten=true`, {cancelToken})\r\n .then(response => resolve(response.data))\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst updateLocationAliases = (integrationTypeId, aliases, cancelToken = null) => {\r\n return new Promise((resolve, reject) => {\r\n axios.patch(`/v1/clients/aliases/${integrationTypeId}`, aliases, {cancelToken})\r\n .then(response => {\r\n resolve();\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nconst getClearinghouseQueryAlerts = (clientId, sites, problemsAndWarningsOnly, cancelToken) => {\r\n return new Promise((resolve, reject) => {\r\n axios.get(`/v1/clients/${clientId}/alerts?alertTypes=clearinghouseQueries&sites=${sites}&problemsAndWarningsOnly=${problemsAndWarningsOnly}`, {cancelToken})\r\n .then(response => {\r\n resolve(response.data.clearinghouseQueryAlerts);\r\n })\r\n .catch(err => {\r\n if (axios.isCancel(err)) {\r\n return reject(err.message);\r\n }\r\n console.error(err);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\n// TODO - move this to Concorde API\r\nconst getAllJobTitlesForAClient = async (clientMongoId) => {\r\n const { data } = await axios.get(`/v1/clients/${clientMongoId}/jobTitles?forCompleteHierarchy=true`)\r\n return data;\r\n}\r\n\r\nexport default {\r\n getAllJobTitlesForAClient,\r\n getClientList,\r\n getClient,\r\n getClientByLegacyId,\r\n getTopLevelClient,\r\n updateClient,\r\n setNotes,\r\n setServices,\r\n uploadLogo,\r\n getNonImportedLegacyClientList,\r\n getClientSummary,\r\n getClientComplianceSummary,\r\n getClientAudits,\r\n getActiveEmployeesBySite,\r\n getAlerts,\r\n getDocReviewAlerts,\r\n getStaleApplicantAlerts,\r\n getCSAAlerts,\r\n getDACAlerts,\r\n getDocumentAlerts,\r\n getMissingDocuments,\r\n getMissingAndExpiredDocuments,\r\n getCSAReportData,\r\n getCrashReportData,\r\n getReportOfAllMedCardsByLocation,\r\n getAccidentReportData,\r\n getDrugAlcoholReportData,\r\n addRandomPool, // TODO: remove this\r\n getEmployeesForPool,\r\n getLocationsForPool,\r\n updateRandomPool,\r\n deleteRandomPool,\r\n createRandomsPool,\r\n modifyRandomsPool,\r\n addEZComplianceRandomsPool,\r\n removeEZComplianceRandomsPool,\r\n patchClient,\r\n getPools,\r\n getUsersForClient,\r\n getJobTitleProgramsForClient,\r\n addJobTitleToClient,\r\n getEmployeesDOTReportData,\r\n getFastTestResultsForClient,\r\n getRandomsPoolsForClient,\r\n getRandomsPoolsByClient,\r\n updateClientHierarchy,\r\n calculateRandomSelection,\r\n makeRandomSelection,\r\n extendRandomSelection,\r\n makeRandomAlternateSelection,\r\n getPreviousRandomsPoolSelections,\r\n getRandomSelection,\r\n getDocTypesForClient,\r\n searchForDrugTestMatch,\r\n saveDrugTestMatch,\r\n updateDrugTestMatch,\r\n getSelectionsForEmployee,\r\n emailRandomSelection,\r\n copySettingsFromLocation,\r\n getEmployeeCount,\r\n deleteJobTitleTransferEmployees,\r\n getClientMVRScoreDefs,\r\n getClientMVRScoringRules,\r\n getClientMVRScoringReasons,\r\n searchByDOTNumber,\r\n getClientLocations,\r\n updateLocationAliases,\r\n getClearinghouseQueryAlerts\r\n};","import axios from 'axios';\r\n\r\nexport const apiService = (params = {}) => {\r\n const source = axios.CancelToken.source();\r\n\r\n const promise = axios.request({ ...params, cancelToken: source.token });\r\n\r\n const cancel = () => source.cancel();\r\n\r\n return { promise, cancel };\r\n};\r\n","const SET_CME_SEARCH_QUERY = 'SET_CME_SEARCH_QUERY';\r\nconst SET_CME_SEARCH_RESULTS = 'SET_CME_SEARCH_RESULTS';\r\nconst SET_CME_TASKLIST = 'SET_CME_TASKLIST';\r\nconst SET_CME_FETCHING_RESULTS = 'SET_CME_FETCHING_RESULTS';\r\nconst RESET_CME_SEARCH = 'RESET_CME_SEARCH';\r\nconst SET_CUSTOMER_CARE_INTERVENTION_ITEMS = 'SET_CUSTOMER_CARE_INTERVENTION_ITEMS';\r\n\r\nexport default {\r\n SET_CME_SEARCH_QUERY,\r\n SET_CME_SEARCH_RESULTS,\r\n SET_CME_TASKLIST,\r\n SET_CME_FETCHING_RESULTS,\r\n RESET_CME_SEARCH,\r\n SET_CUSTOMER_CARE_INTERVENTION_ITEMS\r\n};","import types from './types';\r\nimport {combineReducers} from 'redux';\r\n\r\nconst searchDefaultState = {\r\n query: '',\r\n results: [],\r\n fetching: false\r\n};\r\n\r\nconst taskListsDefaultState = {\r\n taskListData: [],\r\n taskListInitialized: false\r\n};\r\n\r\nconst customerCareInterventionItemsDefaultState = {\r\n customerCareInterventionItems: []\r\n};\r\n\r\nconst cmeSearchReducer = (state = searchDefaultState, action) => {\r\n switch (action.type) {\r\n case types.SET_CME_SEARCH_QUERY:\r\n return {\r\n ...state,\r\n query: action.payload,\r\n fetching: true\r\n };\r\n case types.SET_CME_SEARCH_RESULTS:\r\n return {\r\n ...state,\r\n results: action.payload.searchResults,\r\n status: action.payload.status\r\n };\r\n case types.SET_CME_FETCHING_RESULTS:\r\n return {\r\n ...state,\r\n fetching: action.payload\r\n };\r\n case types.RESET_CME_SEARCH:\r\n return {\r\n ...state,\r\n query: '',\r\n results: [],\r\n fetching: false\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst cmeTaskListsReducer = (state = taskListsDefaultState, action) => {\r\n switch (action.type) {\r\n case types.SET_CME_TASKLIST:\r\n return {\r\n ...state,\r\n taskListData: action.payload,\r\n taskListInitialized: true\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst cmeCustomerCareInterventionItemsReducer = (state = customerCareInterventionItemsDefaultState, action) => {\r\n switch (action.type) {\r\n case types.SET_CUSTOMER_CARE_INTERVENTION_ITEMS:\r\n return {\r\n ...state,\r\n customerCareInterventionItems: action.payload\r\n };\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst cmeReducers = combineReducers({\r\n search: cmeSearchReducer,\r\n taskLists: cmeTaskListsReducer,\r\n customerCareIntervention: cmeCustomerCareInterventionItemsReducer\r\n});\r\n\r\nexport default cmeReducers;","import types from './types';\r\n\r\nconst setCMESearchQuery = query => ({\r\n type: types.SET_CME_SEARCH_QUERY,\r\n payload: query\r\n});\r\n\r\nconst resetCMESearch = () => ({\r\n type: types.RESET_CME_SEARCH,\r\n payload: null\r\n});\r\n\r\nconst setCMESearchResults = (searchResults, status = 200) => ({\r\n type: types.SET_CME_SEARCH_RESULTS,\r\n payload: {searchResults, status}\r\n});\r\n\r\nconst setCMESearchFetching = fetching => ({\r\n type: types.SET_CME_FETCHING_RESULTS,\r\n payload: fetching\r\n});\r\n\r\nconst setCMETaskList = taskList => ({\r\n type: types.SET_CME_TASKLIST,\r\n payload: taskList\r\n});\r\n\r\nconst setCustomerCareInterventionItems = items => ({\r\n type: types.SET_CUSTOMER_CARE_INTERVENTION_ITEMS,\r\n payload: items\r\n});\r\n\r\nexport default {\r\n setCMESearchQuery,\r\n setCMESearchResults,\r\n setCMESearchFetching,\r\n setCMETaskList,\r\n resetCMESearch,\r\n setCustomerCareInterventionItems\r\n};","import actions from './actions';\r\nimport axios from \"axios\";\r\nimport moment from \"moment\";\r\n\r\nconst getCMESearchResults = (query) => dispatch => {\r\n dispatch(actions.setCMESearchQuery(query)); // store the \"search query\" in redux state\r\n dispatch(actions.setCMESearchResults([])); // clear anything prior (helps in the GUI / client to do this)\r\n axios\r\n .get(`/v1/cmes?search=${query}`)\r\n .then(response => {\r\n if (response.data && response.data.length > 0) {\r\n response.data.forEach((cme) => {\r\n if (cme && cme.clinic && cme.clinic.appointment) {\r\n cme.clinic.appointment = moment.utc(cme.clinic.appointment).format('YYYY-MM-DD H:mm');\r\n }\r\n })\r\n }\r\n dispatch(actions.setCMESearchResults(response.data)); // set the results in redux state\r\n dispatch(actions.setCMESearchFetching(false));\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n dispatch(actions.setCMESearchResults([], err.response.status)); // reset to an empty array on error i.e. \"no results\"\r\n dispatch(actions.setCMESearchFetching(false));\r\n });\r\n};\r\n\r\nconst getCMETaskList = () => dispatch => {\r\n axios\r\n .get('/v1/processes/cmeProcess/tasks')\r\n .then(res => {\r\n dispatch(actions.setCMETaskList(mapCamundaVariables(res.data)));\r\n })\r\n .catch(err => console.error(err));\r\n};\r\n\r\nconst resetCMESearch = actions.resetCMESearch;\r\n\r\nconst setCMETaskListFromSocket = taskList => dispatch => {\r\n dispatch(actions.setCMETaskList(mapCamundaVariables(taskList)));\r\n};\r\n\r\n/**\r\n * Create property for each Camunda Variable on the root / parent object.\r\n * After all variables are mapped to the root task object the variables collection is deleted\r\n */\r\nconst mapCamundaVariables = taskList => {\r\n for (const [, camTask] of Object.entries(taskList)) {\r\n if (camTask.variables) {\r\n camTask.variables.forEach(v => {\r\n let variableValue = v.value;\r\n if (v.type === 'Date' && v.value) {\r\n variableValue = moment(v.value);\r\n }\r\n // todo: this can't stay. ideally the variable type should be Date in camunda\r\n if (v.name === 'appointmentDate' && v.value) {\r\n variableValue = moment(v.value);\r\n }\r\n if (v.name === 'received') {\r\n camTask.daysInQueue = moment(Date.now()).diff(moment(v.value), 'days');\r\n }\r\n camTask[v.name] = variableValue;\r\n });\r\n delete camTask.variables;\r\n }\r\n }\r\n return Object.keys(taskList).map(key => taskList[key]);\r\n};\r\n\r\nconst setCustomerCareInterventionItems = actions.setCustomerCareInterventionItems;\r\n\r\nexport default {\r\n getCMESearchResults,\r\n getCMETaskList,\r\n setCMETaskListFromSocket,\r\n resetCMESearch,\r\n setCustomerCareInterventionItems\r\n};","import reducer from './reducers';\r\n\r\nexport {default as cmeOperations} from './operations';\r\nexport {default as cmeTypes} from './types';\r\n\r\nexport default reducer;","import React from 'react';\r\nimport {Modal, ModalHeader, ModalBody, ModalFooter, Button} from 'reactstrap';\r\nimport {Rnd} from \"react-rnd\";\r\nimport { useSelector } from 'react-redux';\r\n\r\n\r\nconst ConfirmActionModal = ({showModal = true, modalHeaderText, modalBodyText, confirmText, cancelText, onConfirm, onCancel, hideCancel}) => {\r\n const loading = useSelector((state) => state.layout.loadingPanel.instances);\r\n return (\r\n \r\n \r\n \r\n {modalHeaderText}\r\n \r\n \r\n {modalBodyText}\r\n \r\n \r\n \r\n {!hideCancel && \r\n \r\n }\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default ConfirmActionModal;","import React, {PureComponent} from 'react';\r\nimport Select from 'react-select';\r\nimport _ from 'lodash';\r\nimport states from '../../../config/statesAndProvinces.json';\r\n\r\nexport default class StateSelect extends PureComponent {\r\n render() {\r\n\r\n const displayMode = this.props.displayMode || 'fancy';\r\n if (displayMode.toLowerCase() === 'fancy') {\r\n const stateOptions = _.sortBy(states, ['abbreviation']).map(s => ({\r\n label: s.country === 'Canada' ? {s.abbreviation} ({s.name})
: `${s.abbreviation} (${s.name})`,\r\n value: s.abbreviation\r\n }));\r\n return (\r\n