Merge remote-tracking branch 'origin/master-AIO' into feature/IO-2776-cdk-fortellis
# Conflicts: # client/src/components/dms-post-form/dms-post-form.component.jsx # package-lock.json # package.json # server/web-sockets/redisSocketEvents.js
This commit is contained in:
@@ -2,7 +2,7 @@ import { EditFilled, SyncOutlined } from "@ant-design/icons";
|
||||
import { Button, Card, Checkbox, Input, Space, Table, Typography } from "antd";
|
||||
import axios from "axios";
|
||||
import queryString from "query-string";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||
@@ -13,8 +13,9 @@ import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import { DateFormatter } from "../../utils/DateFormatter";
|
||||
import { TemplateList } from "../../utils/TemplateConstants";
|
||||
import { alphaSort, dateSort } from "../../utils/sorters";
|
||||
import { pageLimit } from "../../utils/config";
|
||||
import { alphaSort, dateSort } from "../../utils/sorters";
|
||||
import useLocalStorage from "../../utils/useLocalStorage";
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setPartsOrderContext: (context) => dispatch(setModalContext({ context: context, modal: "partsOrder" })),
|
||||
@@ -27,7 +28,7 @@ export function BillsListPage({ loading, data, refetch, total, setPartsOrderCont
|
||||
const [searchLoading, setSearchLoading] = useState(false);
|
||||
const { page } = search;
|
||||
const history = useNavigate();
|
||||
const [state, setState] = useState({
|
||||
const [state, setState] = useLocalStorage("bills_list_sort", {
|
||||
sortedInfo: {},
|
||||
filteredInfo: { text: "" }
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//import {useMutation, useQuery } from "@apollo/client";
|
||||
import { Button, Form, Layout, Result, Typography } from "antd";
|
||||
import axios from "axios";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { useParams } from "react-router-dom";
|
||||
@@ -16,7 +16,8 @@ import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({});
|
||||
|
||||
const mapDispatchToProps = () => ({});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(CsiContainerPage);
|
||||
|
||||
@@ -28,7 +29,6 @@ export function CsiContainerPage({ currentUser }) {
|
||||
loading: false,
|
||||
submitted: false
|
||||
});
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const getAxiosData = useCallback(async () => {
|
||||
@@ -39,7 +39,6 @@ export function CsiContainerPage({ currentUser }) {
|
||||
console.log("Unable to attach to crisp instance. ");
|
||||
}
|
||||
setSubmitting((prevSubmitting) => ({ ...prevSubmitting, loading: true }));
|
||||
|
||||
const response = await axios.post("/csi/lookup", {
|
||||
surveyId
|
||||
});
|
||||
@@ -91,7 +90,7 @@ export function CsiContainerPage({ currentUser }) {
|
||||
setSubmitting({ ...submitting, loading: true, submitting: true });
|
||||
const result = await axios.post("/csi/submit", { surveyId, values });
|
||||
console.log("result", result);
|
||||
if (!!!result.errors && result.data.update_csi.affected_rows > 0) {
|
||||
if (!result.errors && result.data.update_csi.affected_rows > 0) {
|
||||
setSubmitting({ ...submitting, loading: false, submitted: true });
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -110,7 +109,7 @@ export function CsiContainerPage({ currentUser }) {
|
||||
<Layout style={{ display: "flex", flexDirection: "column" }}>
|
||||
<Layout.Content
|
||||
style={{
|
||||
backgroundColor: "#fff",
|
||||
backgroundColor: "var(--content-bg)",
|
||||
margin: "2em 4em",
|
||||
padding: "2em",
|
||||
overflowY: "auto",
|
||||
@@ -139,7 +138,6 @@ export function CsiContainerPage({ currentUser }) {
|
||||
relateddata: { bodyshop, job },
|
||||
csiquestion: { config: csiquestions }
|
||||
} = axiosResponse.csi_by_pk;
|
||||
|
||||
return (
|
||||
<Layout style={{ display: "flex", flexDirection: "column" }}>
|
||||
<div
|
||||
@@ -184,13 +182,11 @@ export function CsiContainerPage({ currentUser }) {
|
||||
})}
|
||||
</Typography.Paragraph>
|
||||
</div>
|
||||
|
||||
{submitting.error ? <AlertComponent message={submitting.error} type="error" /> : null}
|
||||
|
||||
{submitting.submitted ? (
|
||||
<Layout.Content
|
||||
style={{
|
||||
backgroundColor: "#fff",
|
||||
backgroundColor: "var(--content-bg)",
|
||||
margin: "2em 4em",
|
||||
padding: "2em",
|
||||
overflowY: "auto"
|
||||
@@ -201,7 +197,7 @@ export function CsiContainerPage({ currentUser }) {
|
||||
) : (
|
||||
<Layout.Content
|
||||
style={{
|
||||
backgroundColor: "#fff",
|
||||
backgroundColor: "var(--content-bg)",
|
||||
margin: "2em 4em",
|
||||
padding: "2em",
|
||||
overflowY: "auto"
|
||||
|
||||
42
client/src/pages/feature-request/feature-request.page.jsx
Normal file
42
client/src/pages/feature-request/feature-request.page.jsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import axios from "axios";
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
||||
setSelectedHeader: (key) => dispatch(setSelectedHeader(key))
|
||||
});
|
||||
|
||||
export function FeedbackPage({ setBreadcrumbs, setSelectedHeader }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
document.title = t("titles.feature-request", {
|
||||
app: InstanceRenderManager({
|
||||
imex: "$t(titles.imexonline)",
|
||||
rome: "$t(titles.romeonline)"
|
||||
})
|
||||
});
|
||||
setBreadcrumbs([{ link: "/manage/feature-request", label: t("titles.bc.feature-request") }]);
|
||||
}, [t, setBreadcrumbs, setSelectedHeader]);
|
||||
|
||||
useEffect(() => {
|
||||
async function RenderCanny() {
|
||||
const ssoToken = await axios.post("/sso/canny");
|
||||
window.Canny("render", {
|
||||
boardToken: "bba97b06-70db-0334-dee7-8108d73ef614",
|
||||
basePath: `/manage/feature-request`, // See step 2
|
||||
ssoToken: ssoToken.data, // See step 3,
|
||||
theme: "light" // options: light [default], dark, auto
|
||||
});
|
||||
}
|
||||
RenderCanny();
|
||||
}, []);
|
||||
|
||||
return <div data-canny />;
|
||||
}
|
||||
|
||||
export default connect(null, mapDispatchToProps)(FeedbackPage);
|
||||
@@ -271,7 +271,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, set
|
||||
{
|
||||
required: true
|
||||
},
|
||||
({ getFieldValue }) => ({
|
||||
() => ({
|
||||
validator(_, value) {
|
||||
if (!bodyshop.cdk_dealerid) return Promise.resolve();
|
||||
if (!value || dayjs(value).isSameOrAfter(dayjs(), "day")) {
|
||||
@@ -280,7 +280,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, set
|
||||
return Promise.reject(new Error(t("jobs.labels.dms.invoicedatefuture")));
|
||||
}
|
||||
}),
|
||||
({ getFieldValue }) => ({
|
||||
() => ({
|
||||
validator(_, value) {
|
||||
if (ClosingPeriod.treatment === "on" && bodyshop.accountingconfig.ClosingPeriod) {
|
||||
if (
|
||||
@@ -369,8 +369,8 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, set
|
||||
<Form.List
|
||||
name={["qb_multiple_payers"]}
|
||||
rules={[
|
||||
({ getFieldValue }) => ({
|
||||
validator(_, value) {
|
||||
() => ({
|
||||
validator() {
|
||||
let totalAllocated = Dinero();
|
||||
|
||||
const payers = form.getFieldValue("qb_multiple_payers");
|
||||
@@ -492,7 +492,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, set
|
||||
<Statistic
|
||||
title={t("jobs.labels.pimraryamountpayable")}
|
||||
valueStyle={{
|
||||
color: discrep.getAmount() > 0 ? "green" : "red"
|
||||
color: discrep.getAmount() >= 0 ? "green" : "red"
|
||||
}}
|
||||
value={discrep.toFormat()}
|
||||
/>
|
||||
|
||||
@@ -114,7 +114,6 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
||||
if (!!!job.ownerid) {
|
||||
ownerData = job.owner.data;
|
||||
ownerData.shopid = bodyshop.id;
|
||||
delete ownerData.allow_text_message;
|
||||
delete ownerData.preferred_contact;
|
||||
delete job.ownerid;
|
||||
} else {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Badge, Button, Divider, Form, Space, Tabs } from "antd";
|
||||
import Axios from "axios";
|
||||
import _ from "lodash";
|
||||
import queryString from "query-string";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FaHardHat, FaRegStickyNote, FaShieldAlt, FaTasks } from "react-icons/fa";
|
||||
import { connect } from "react-redux";
|
||||
@@ -28,6 +28,7 @@ import JobLineUpsertModalContainer from "../../components/job-lines-upsert-modal
|
||||
import JobProfileDataWarning from "../../components/job-profile-data-warning/job-profile-data-warning.component";
|
||||
import JobReconciliationModal from "../../components/job-reconciliation-modal/job-reconciliation.modal.container";
|
||||
import JobSyncButton from "../../components/job-sync-button/job-sync-button.component";
|
||||
import JobWatcherToggleContainer from "../../components/job-watcher-toggle/job-watcher-toggle.container.jsx";
|
||||
import JobsChangeStatus from "../../components/jobs-change-status/jobs-change-status.component";
|
||||
import JobsConvertButton from "../../components/jobs-convert-button/jobs-convert-button.component";
|
||||
import JobsDetailDatesComponent from "../../components/jobs-detail-dates/jobs-detail-dates.component";
|
||||
@@ -45,6 +46,8 @@ import LockWrapperComponent from "../../components/lock-wrapper/lock-wrapper.com
|
||||
import NoteUpsertModalComponent from "../../components/note-upsert-modal/note-upsert-modal.container";
|
||||
import ScheduleJobModalContainer from "../../components/schedule-job-modal/schedule-job-modal.container";
|
||||
import TaskListContainer from "../../components/task-list/task-list.container.jsx";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
import { QUERY_PARTS_BILLS_BY_JOBID } from "../../graphql/bills.queries.js";
|
||||
import { QUERY_JOB_TASKS_PAGINATED } from "../../graphql/tasks.queries.js";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
@@ -55,9 +58,6 @@ import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import { DateTimeFormat } from "../../utils/DateFormatter";
|
||||
import dayjs from "../../utils/day";
|
||||
import UndefinedToNull from "../../utils/undefinedtonull";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
|
||||
import JobWatcherToggleContainer from "../../components/job-watcher-toggle/job-watcher-toggle.container.jsx";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -322,11 +322,11 @@ export function JobsDetailPage({
|
||||
>
|
||||
<PageHeader
|
||||
// onBack={() => window.history.back()}
|
||||
|
||||
id="job-detail-header"
|
||||
title={
|
||||
<Space>
|
||||
{scenarioNotificationsOn && <JobWatcherToggleContainer job={job} />}
|
||||
{job.ro_number || t("general.labels.na")}
|
||||
<span id="job-ro_number">{job.ro_number || t("general.labels.na")}</span>
|
||||
</Space>
|
||||
}
|
||||
extra={menuExtra}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { FloatButton, Layout, Spin } from "antd";
|
||||
import { Button, FloatButton, Layout, Space, Spin } from "antd";
|
||||
import { AlertOutlined, BulbOutlined } from "@ant-design/icons";
|
||||
|
||||
// import preval from "preval.macro";
|
||||
import React, { lazy, Suspense, useEffect, useState } from "react";
|
||||
@@ -19,7 +20,6 @@ import LoadingSpinner from "../../components/loading-spinner/loading-spinner.com
|
||||
import PartnerPingComponent from "../../components/partner-ping/partner-ping.component";
|
||||
import PrintCenterModalContainer from "../../components/print-center-modal/print-center-modal.container";
|
||||
import ShopSubStatusComponent from "../../components/shop-sub-status/shop-sub-status.component";
|
||||
import { requestForToken } from "../../firebase/firebase.utils";
|
||||
import { selectBodyshop, selectInstanceConflict } from "../../redux/user/user.selectors";
|
||||
import UpdateAlert from "../../components/update-alert/update-alert.component";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr.js";
|
||||
@@ -56,6 +56,7 @@ const ContractCreatePage = lazy(() => import("../contract-create/contract-create
|
||||
const ContractDetailPage = lazy(() => import("../contract-detail/contract-detail.page.container"));
|
||||
const ContractsList = lazy(() => import("../contracts/contracts.page.container"));
|
||||
const BillsListPage = lazy(() => import("../bills/bills.page.container"));
|
||||
const FeatureRequestPage = lazy(() => import("../feature-request/feature-request.page.jsx"));
|
||||
|
||||
const JobCostingModal = lazy(() => import("../../components/job-costing-modal/job-costing-modal.container"));
|
||||
const ReportCenterModal = lazy(() => import("../../components/report-center-modal/report-center-modal.container"));
|
||||
@@ -180,15 +181,12 @@ export function Manage({ conflict, bodyshop, alerts, setAlerts }) {
|
||||
});
|
||||
}
|
||||
}, [alerts, displayedAlertIds, notification]);
|
||||
|
||||
useEffect(() => {
|
||||
const widgetId = InstanceRenderManager({
|
||||
imex: "IABVNO4scRKY11XBQkNr",
|
||||
rome: "mQdqARMzkZRUVugJ6TdS"
|
||||
});
|
||||
window.noticeable.render("widget", widgetId);
|
||||
requestForToken().catch((error) => {
|
||||
console.error(`Unable to request for token.`, error);
|
||||
window.Canny("initChangelog", {
|
||||
appID: "680bd2c7ee501290377f6686",
|
||||
position: "top",
|
||||
align: "left",
|
||||
theme: "light" // options: light [default], dark, auto
|
||||
});
|
||||
}, []);
|
||||
|
||||
@@ -480,6 +478,8 @@ export function Manage({ conflict, bodyshop, alerts, setAlerts }) {
|
||||
// element={<ShopTemplates />}
|
||||
// />
|
||||
}
|
||||
<Route path="/feature-request/*" index element={<FeatureRequestPage />} />
|
||||
|
||||
<Route
|
||||
path="/shop/vendors"
|
||||
element={
|
||||
@@ -669,7 +669,12 @@ export function Manage({ conflict, bodyshop, alerts, setAlerts }) {
|
||||
margin: "1rem 0rem"
|
||||
}}
|
||||
>
|
||||
<div style={{ display: "flex" }}>
|
||||
<Link to="/manage/feature-request">
|
||||
<Button icon={<BulbOutlined />} type="text">
|
||||
{t("general.labels.feature-request")}
|
||||
</Button>
|
||||
</Link>
|
||||
<Space>
|
||||
<WssStatusDisplayComponent />
|
||||
<div onClick={broadcastMessage}>
|
||||
{`${InstanceRenderManager({
|
||||
@@ -677,8 +682,10 @@ export function Manage({ conflict, bodyshop, alerts, setAlerts }) {
|
||||
rome: t("titles.romeonline")
|
||||
})} - ${import.meta.env.VITE_APP_GIT_SHA_DATE}`}
|
||||
</div>
|
||||
<div id="noticeable-widget" style={{ marginLeft: "1rem" }} />
|
||||
</div>
|
||||
<Button icon={<AlertOutlined />} data-canny-changelog type="text">
|
||||
{t("general.labels.changelog")}
|
||||
</Button>
|
||||
</Space>
|
||||
<Link to="/disclaimer" target="_blank" style={{ color: "#ccc" }}>
|
||||
Disclaimer & Notices
|
||||
</Link>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import ScheduleCalendarContainer from "../../components/schedule-calendar/schedule-calendar.container";
|
||||
|
||||
export default function SchedulePageComponent() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Icon, { FieldTimeOutlined } from "@ant-design/icons";
|
||||
import { Card, Tabs } from "antd";
|
||||
import queryString from "query-string";
|
||||
import React, { useEffect } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FaShieldAlt } from "react-icons/fa";
|
||||
import { connect } from "react-redux";
|
||||
@@ -78,7 +78,7 @@ export function ScoreboardContainer({ setBreadcrumbs, setSelectedHeader }) {
|
||||
<RbacWrapper action="scoreboard:view">
|
||||
<Tabs
|
||||
activeKey={tab || "sb"}
|
||||
destroyInactiveTabPane
|
||||
destroyOnHidden
|
||||
onChange={(key) => {
|
||||
searchParams.tab = key;
|
||||
history({
|
||||
|
||||
@@ -10,10 +10,10 @@ import ShopCsiConfig from "../../components/shop-csi-config/shop-csi-config.comp
|
||||
import ShopEmployeesContainer from "../../components/shop-employees/shop-employees.container";
|
||||
import ShopInfoContainer from "../../components/shop-info/shop-info.container";
|
||||
import ShopInfoUsersComponent from "../../components/shop-users/shop-users.component";
|
||||
import ShopInfoConsentComponent from "../../components/shop-info/shop-info.consent.component";
|
||||
import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
|
||||
import { HasFeatureAccess } from "../../components/feature-wrapper/feature-wrapper.component";
|
||||
import ShopTeamsContainer from "../../components/shop-teams/shop-teams.container";
|
||||
|
||||
@@ -91,6 +91,16 @@ export function ShopPage({ bodyshop, setSelectedHeader, setBreadcrumbs }) {
|
||||
children: <ShopCsiConfig />
|
||||
});
|
||||
}
|
||||
|
||||
if (bodyshop.messagingservicesid) {
|
||||
// Add Consent Settings tab
|
||||
items.push({
|
||||
key: "consent",
|
||||
label: t("bodyshop.labels.consent_settings"),
|
||||
children: <ShopInfoConsentComponent bodyshop={bodyshop} />
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<RbacWrapper action="shop:config">
|
||||
<Tabs activeKey={search.tab} onChange={(key) => history({ search: `?tab=${key}` })} items={items} />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import TasksPageComponent from "./tasks.page.component";
|
||||
import queryString from "query-string";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import TasksPageComponent from "./tasks.page.component";
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import TaskListContainer from "../../components/task-list/task-list.container.jsx";
|
||||
import { QUERY_ALL_TASKS_PAGINATED, QUERY_MY_TASKS_PAGINATED } from "../../graphql/tasks.queries.js";
|
||||
import taskPageTypes from "./taskPageTypes.jsx";
|
||||
@@ -10,7 +9,7 @@ const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({});
|
||||
const mapDispatchToProps = () => ({});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TasksPageComponent);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.tech-content-container {
|
||||
overflow-y: visible;
|
||||
padding: 1rem;
|
||||
background: #fff;
|
||||
background: var(--tech-content-bg);
|
||||
}
|
||||
|
||||
.tech-layout-container {
|
||||
|
||||
Reference in New Issue
Block a user