Merged in hotfix/2025-08-22 (pull request #2508)
DO NOT MERGE Hotfix/2025 08 22
This commit is contained in:
@@ -14,3 +14,5 @@ VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
|||||||
VITE_APP_INSTANCE=IMEX
|
VITE_APP_INSTANCE=IMEX
|
||||||
TEST_USERNAME="test@imex.dev"
|
TEST_USERNAME="test@imex.dev"
|
||||||
TEST_PASSWORD="test123"
|
TEST_PASSWORD="test123"
|
||||||
|
VITE_PUBLIC_POSTHOG_KEY=phc_xtLmBIu0rjWwExY73Oj5DTH1bGbwq1G1Y8jnlTceien
|
||||||
|
VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
|
||||||
@@ -16,3 +16,5 @@ VITE_APP_COUNTRY=USA
|
|||||||
VITE_APP_INSTANCE=ROME
|
VITE_APP_INSTANCE=ROME
|
||||||
TEST_USERNAME="test@imex.dev"
|
TEST_USERNAME="test@imex.dev"
|
||||||
TEST_PASSWORD="test123"
|
TEST_PASSWORD="test123"
|
||||||
|
VITE_PUBLIC_POSTHOG_KEY=phc_xtLmBIu0rjWwExY73Oj5DTH1bGbwq1G1Y8jnlTceien
|
||||||
|
VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
|
||||||
@@ -13,3 +13,5 @@ VITE_APP_AXIOS_BASE_API_URL=https://api.imex.online/
|
|||||||
VITE_APP_REPORTS_SERVER_URL=https://reports.imex.online
|
VITE_APP_REPORTS_SERVER_URL=https://reports.imex.online
|
||||||
VITE_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
VITE_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
||||||
VITE_APP_INSTANCE=IMEX
|
VITE_APP_INSTANCE=IMEX
|
||||||
|
VITE_PUBLIC_POSTHOG_KEY=phc_xtLmBIu0rjWwExY73Oj5DTH1bGbwq1G1Y8jnlTceien
|
||||||
|
VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
|
||||||
@@ -13,3 +13,5 @@ VITE_APP_AXIOS_BASE_API_URL=https://api.romeonline.io/
|
|||||||
VITE_APP_REPORTS_SERVER_URL=https://reports.romeonline.io
|
VITE_APP_REPORTS_SERVER_URL=https://reports.romeonline.io
|
||||||
VITE_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
VITE_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
||||||
VITE_APP_INSTANCE=ROME
|
VITE_APP_INSTANCE=ROME
|
||||||
|
VITE_PUBLIC_POSTHOG_KEY=phc_xtLmBIu0rjWwExY73Oj5DTH1bGbwq1G1Y8jnlTceien
|
||||||
|
VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
|
||||||
@@ -13,3 +13,5 @@ VITE_APP_REPORTS_SERVER_URL=https://reports.test.imex.online
|
|||||||
VITE_APP_IS_TEST=true
|
VITE_APP_IS_TEST=true
|
||||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||||
VITE_APP_INSTANCE=IMEX
|
VITE_APP_INSTANCE=IMEX
|
||||||
|
VITE_PUBLIC_POSTHOG_KEY=phc_xtLmBIu0rjWwExY73Oj5DTH1bGbwq1G1Y8jnlTceien
|
||||||
|
VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
|
||||||
@@ -13,3 +13,5 @@ VITE_APP_REPORTS_SERVER_URL=https://reports.test.romeonline.io
|
|||||||
VITE_APP_IS_TEST=true
|
VITE_APP_IS_TEST=true
|
||||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||||
VITE_APP_INSTANCE=ROME
|
VITE_APP_INSTANCE=ROME
|
||||||
|
VITE_PUBLIC_POSTHOG_KEY=phc_xtLmBIu0rjWwExY73Oj5DTH1bGbwq1G1Y8jnlTceien
|
||||||
|
VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
|
||||||
2115
client/package-lock.json
generated
2115
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,7 @@
|
|||||||
"proxy": "http://localhost:4000",
|
"proxy": "http://localhost:4000",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/pro-layout": "^7.22.4",
|
"@ant-design/pro-layout": "^7.22.4",
|
||||||
|
"@amplitude/analytics-browser": "^2.23.1",
|
||||||
"@apollo/client": "^3.13.6",
|
"@apollo/client": "^3.13.6",
|
||||||
"@emotion/is-prop-valid": "^1.3.1",
|
"@emotion/is-prop-valid": "^1.3.1",
|
||||||
"@fingerprintjs/fingerprintjs": "^4.6.1",
|
"@fingerprintjs/fingerprintjs": "^4.6.1",
|
||||||
@@ -48,6 +49,7 @@
|
|||||||
"normalize-url": "^8.0.2",
|
"normalize-url": "^8.0.2",
|
||||||
"object-hash": "^3.0.0",
|
"object-hash": "^3.0.0",
|
||||||
"phone": "^3.1.59",
|
"phone": "^3.1.59",
|
||||||
|
"posthog-js": "^1.260.2",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"query-string": "^9.2.0",
|
"query-string": "^9.2.0",
|
||||||
"raf-schd": "^4.0.3",
|
"raf-schd": "^4.0.3",
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { ApolloProvider } from "@apollo/client";
|
import { ApolloProvider } from "@apollo/client";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import { SplitFactoryProvider, useSplitClient } from "@splitsoftware/splitio-react";
|
import { SplitFactoryProvider, useSplitClient } from "@splitsoftware/splitio-react";
|
||||||
import { ConfigProvider } from "antd";
|
import { ConfigProvider } from "antd";
|
||||||
import enLocale from "antd/es/locale/en_US";
|
import enLocale from "antd/es/locale/en_US";
|
||||||
import { useEffect, useMemo } from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
|
import { CookiesProvider } from "react-cookie";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect, useSelector } from "react-redux";
|
import { connect, useSelector } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
|
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
|
||||||
|
import { setDarkMode } from "../redux/application/application.actions";
|
||||||
|
import { selectDarkMode } from "../redux/application/application.selectors";
|
||||||
|
import { selectCurrentUser } from "../redux/user/user.selectors.js";
|
||||||
import client from "../utils/GraphQLClient";
|
import client from "../utils/GraphQLClient";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
import * as Sentry from "@sentry/react";
|
|
||||||
import getTheme from "./themeProvider";
|
import getTheme from "./themeProvider";
|
||||||
import { CookiesProvider } from "react-cookie";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectCurrentUser } from "../redux/user/user.selectors.js";
|
|
||||||
import { selectDarkMode } from "../redux/application/application.selectors";
|
|
||||||
import { setDarkMode } from "../redux/application/application.actions";
|
|
||||||
|
|
||||||
// Base Split configuration
|
// Base Split configuration
|
||||||
const config = {
|
const config = {
|
||||||
@@ -86,7 +86,7 @@ function AppContainer({ currentUser, setDarkMode }) {
|
|||||||
theme={theme}
|
theme={theme}
|
||||||
form={{
|
form={{
|
||||||
validateMessages: {
|
validateMessages: {
|
||||||
required: t("general.validation.required", { label: "{{label}}" })
|
required: t("general.validation.required", { label: "${label}" })
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { getAuth, updatePassword, updateProfile } from "@firebase/auth";
|
|||||||
import { getFirestore } from "@firebase/firestore";
|
import { getFirestore } from "@firebase/firestore";
|
||||||
import { getMessaging, getToken, onMessage } from "@firebase/messaging";
|
import { getMessaging, getToken, onMessage } from "@firebase/messaging";
|
||||||
import { store } from "../redux/store";
|
import { store } from "../redux/store";
|
||||||
|
import * as amplitude from '@amplitude/analytics-browser';
|
||||||
|
import posthog from 'posthog-js'
|
||||||
|
|
||||||
const config = JSON.parse(import.meta.env.VITE_APP_FIREBASE_CONFIG);
|
const config = JSON.parse(import.meta.env.VITE_APP_FIREBASE_CONFIG);
|
||||||
initializeApp(config);
|
initializeApp(config);
|
||||||
@@ -71,25 +73,33 @@ onMessage(messaging, (payload) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const logImEXEvent = (eventName, additionalParams, stateProp = null) => {
|
export const logImEXEvent = (eventName, additionalParams, stateProp = null) => {
|
||||||
const state = stateProp || store.getState();
|
try {
|
||||||
const eventParams = {
|
|
||||||
shop: (state.user && state.user.bodyshop && state.user.bodyshop.shopname) || null,
|
const state = stateProp || store.getState();
|
||||||
user: (state.user && state.user.currentUser && state.user.currentUser.email) || null,
|
const eventParams = {
|
||||||
...additionalParams
|
shop: (state.user && state.user.bodyshop && state.user.bodyshop.shopname) || null,
|
||||||
};
|
user: (state.user && state.user.currentUser && state.user.currentUser.email) || null,
|
||||||
// axios.post("/ioevent", {
|
...additionalParams
|
||||||
// useremail: (state.user && state.user.currentUser && state.user.currentUser.email) || null,
|
};
|
||||||
// bodyshopid: (state.user && state.user.bodyshop && state.user.bodyshop.id) || null,
|
// axios.post("/ioevent", {
|
||||||
// operationName: eventName,
|
// useremail: (state.user && state.user.currentUser && state.user.currentUser.email) || null,
|
||||||
// variables: additionalParams,
|
// bodyshopid: (state.user && state.user.bodyshop && state.user.bodyshop.id) || null,
|
||||||
// dbevent: false,
|
// operationName: eventName,
|
||||||
// env: `master-AIO|${import.meta.env.VITE_APP_GIT_SHA_DATE}`
|
// variables: additionalParams,
|
||||||
// });
|
// dbevent: false,
|
||||||
// console.log(
|
// env: `master-AIO|${import.meta.env.VITE_APP_GIT_SHA_DATE}`
|
||||||
// "%c[Analytics]",
|
// });
|
||||||
// "background-color: green ;font-weight:bold;",
|
// console.log(
|
||||||
// eventName,
|
// "%c[Analytics]",
|
||||||
// eventParams
|
// "background-color: green ;font-weight:bold;",
|
||||||
// );
|
// eventName,
|
||||||
logEvent(analytics, eventName, eventParams);
|
// eventParams
|
||||||
|
// );
|
||||||
|
logEvent(analytics, eventName, eventParams);
|
||||||
|
amplitude.track(eventName, eventParams);
|
||||||
|
posthog.capture(eventName, eventParams);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
//If it fails, just keep going.
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import { persistor, store } from "./redux/store";
|
|||||||
import reportWebVitals from "./reportWebVitals";
|
import reportWebVitals from "./reportWebVitals";
|
||||||
import "./translations/i18n";
|
import "./translations/i18n";
|
||||||
import "./utils/CleanAxios";
|
import "./utils/CleanAxios";
|
||||||
|
import * as amplitude from "@amplitude/analytics-browser";
|
||||||
|
import { PostHogProvider } from "posthog-js/react";
|
||||||
|
|
||||||
window.global ||= window;
|
window.global ||= window;
|
||||||
|
|
||||||
@@ -23,10 +25,10 @@ registerSW({ immediate: true });
|
|||||||
// Dinero.globalLocale = "en-CA";
|
// Dinero.globalLocale = "en-CA";
|
||||||
Dinero.globalRoundingMode = "HALF_EVEN";
|
Dinero.globalRoundingMode = "HALF_EVEN";
|
||||||
|
|
||||||
|
amplitude.init("6228a598e57cd66875cfd41604f1f891", {});
|
||||||
const sentryCreateBrowserRouter = Sentry.wrapCreateBrowserRouterV6(createBrowserRouter);
|
const sentryCreateBrowserRouter = Sentry.wrapCreateBrowserRouterV6(createBrowserRouter);
|
||||||
|
|
||||||
const router = sentryCreateBrowserRouter(createRoutesFromElements(<Route path="*" element={<AppContainer />} />));
|
const router = sentryCreateBrowserRouter(createRoutesFromElements(<Route path="*" element={<AppContainer />} />));
|
||||||
|
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
let styles =
|
let styles =
|
||||||
"font-weight: bold; font-size: 50px;color: red; 6px 6px 0 rgb(226,91,14) , 9px 9px 0 rgb(245,221,8) , 12px 12px 0 rgb(5,148,68) ";
|
"font-weight: bold; font-size: 50px;color: red; 6px 6px 0 rgb(226,91,14) , 9px 9px 0 rgb(245,221,8) , 12px 12px 0 rgb(5,148,68) ";
|
||||||
@@ -37,7 +39,12 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<PersistGate loading={<LoadingSpinner message="Restoring your settings..." />} persistor={persistor}>
|
<PersistGate loading={<LoadingSpinner message="Restoring your settings..." />} persistor={persistor}>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<RouterProvider router={router} />
|
<PostHogProvider
|
||||||
|
apiKey={import.meta.env.VITE_PUBLIC_POSTHOG_KEY}
|
||||||
|
options={{ autocapture: false, capture_exceptions: true }}
|
||||||
|
>
|
||||||
|
<RouterProvider router={router} />
|
||||||
|
</PostHogProvider>
|
||||||
</Provider>
|
</Provider>
|
||||||
</PersistGate>
|
</PersistGate>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ import {
|
|||||||
validatePasswordResetSuccess
|
validatePasswordResetSuccess
|
||||||
} from "./user.actions";
|
} from "./user.actions";
|
||||||
import UserActionTypes from "./user.types";
|
import UserActionTypes from "./user.types";
|
||||||
|
import * as amplitude from "@amplitude/analytics-browser";
|
||||||
|
import posthog from "posthog-js";
|
||||||
|
|
||||||
const fpPromise = FingerprintJS.load();
|
const fpPromise = FingerprintJS.load();
|
||||||
|
|
||||||
@@ -82,8 +84,6 @@ export function* onCheckUserSession() {
|
|||||||
|
|
||||||
export function* isUserAuthenticated() {
|
export function* isUserAuthenticated() {
|
||||||
try {
|
try {
|
||||||
logImEXEvent("redux_auth_check");
|
|
||||||
|
|
||||||
const user = yield getCurrentUser();
|
const user = yield getCurrentUser();
|
||||||
if (!user) {
|
if (!user) {
|
||||||
yield put(unauthorizedUser());
|
yield put(unauthorizedUser());
|
||||||
@@ -91,6 +91,8 @@ export function* isUserAuthenticated() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LogRocket.identify(user.email);
|
LogRocket.identify(user.email);
|
||||||
|
amplitude.setUserId(user.email);
|
||||||
|
posthog.identify(user.email);
|
||||||
|
|
||||||
const eulaQuery = yield client.query({
|
const eulaQuery = yield client.query({
|
||||||
query: QUERY_EULA,
|
query: QUERY_EULA,
|
||||||
@@ -136,7 +138,8 @@ export function* signOutStart() {
|
|||||||
imexshopid: state.user.bodyshop.imexshopid,
|
imexshopid: state.user.bodyshop.imexshopid,
|
||||||
type: "messaging"
|
type: "messaging"
|
||||||
});
|
});
|
||||||
} catch (error) {
|
amplitude.reset();
|
||||||
|
} catch {
|
||||||
console.log("No FCM token. Skipping unsubscribe.");
|
console.log("No FCM token. Skipping unsubscribe.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +164,7 @@ export function* updateUserDetails(userDetails) {
|
|||||||
type: "success",
|
type: "success",
|
||||||
message: i18next.t("profile.successes.updated")
|
message: i18next.t("profile.successes.updated")
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch {
|
||||||
//yield put(signOutFailure(error.message));
|
//yield put(signOutFailure(error.message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,7 +271,7 @@ export function* signInSuccessSaga({ payload }) {
|
|||||||
|
|
||||||
setUserId(analytics, payload.email);
|
setUserId(analytics, payload.email);
|
||||||
setUserProperties(analytics, payload);
|
setUserProperties(analytics, payload);
|
||||||
yield logImEXEvent("redux_sign_in_success");
|
yield;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* onSendPasswordResetStart() {
|
export function* onSendPasswordResetStart() {
|
||||||
@@ -335,6 +338,7 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
amplitude.setGroup("Shop", payload.shopname);
|
||||||
window.$crisp.push(["set", "user:company", [payload.shopname]]);
|
window.$crisp.push(["set", "user:company", [payload.shopname]]);
|
||||||
window.$crisp.push(["set", "session:segments", [[`region:${payload.region_config}`]]]);
|
window.$crisp.push(["set", "session:segments", [[`region:${payload.region_config}`]]]);
|
||||||
if (authRecord[0] && authRecord[0].user.validemail) {
|
if (authRecord[0] && authRecord[0].user.validemail) {
|
||||||
|
|||||||
@@ -73,37 +73,23 @@ const processCanvasRequest = async (req, res) => {
|
|||||||
// Default width and height
|
// Default width and height
|
||||||
const width = isNumber(w) && w > 0 ? w : 500;
|
const width = isNumber(w) && w > 0 ? w : 500;
|
||||||
const height = isNumber(h) && h > 0 ? h : 275;
|
const height = isNumber(h) && h > 0 ? h : 275;
|
||||||
|
|
||||||
const configuration = getChartConfiguration(keys, values, override);
|
const configuration = getChartConfiguration(keys, values, override);
|
||||||
|
|
||||||
let canvas = null;
|
|
||||||
let ctx = null;
|
|
||||||
let chart = null;
|
let chart = null;
|
||||||
let chartImage = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Create the canvas
|
const canvas = new Canvas(width, height);
|
||||||
canvas = new Canvas(width, height);
|
const ctx = canvas.getContext("2d");
|
||||||
ctx = canvas.getContext("2d");
|
|
||||||
|
|
||||||
// Render the chart
|
|
||||||
chart = new Chart(ctx, configuration);
|
chart = new Chart(ctx, configuration);
|
||||||
|
|
||||||
// Generate and send the image
|
const chartImage = (await canvas.toBuffer("image/png")).toString("base64");
|
||||||
chartImage = (await canvas.toBuffer("image/png")).toString("base64");
|
|
||||||
res.status(200).send(`data:image/png;base64,${chartImage}`);
|
res.status(200).send(`data:image/png;base64,${chartImage}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Log the error and send the response
|
|
||||||
logger.log("canvas-error", "error", "jsr", null, { error: error.message });
|
logger.log("canvas-error", "error", "jsr", null, { error: error.message });
|
||||||
res.status(500).send("Failed to generate canvas.");
|
res.status(500).send("Error generating canvas");
|
||||||
} finally {
|
} finally {
|
||||||
// Cleanup resources
|
chart?.destroy();
|
||||||
if (chart) {
|
|
||||||
chart.destroy();
|
|
||||||
}
|
|
||||||
ctx = null;
|
|
||||||
canvas = null;
|
|
||||||
chartImage = null;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,15 +104,18 @@ const enqueueRequest = (req, res) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const processNextInQueue = async () => {
|
const processNextInQueue = async () => {
|
||||||
while (requestQueue.length > 0) {
|
try {
|
||||||
const { req, res } = requestQueue.shift();
|
while (requestQueue.length > 0) {
|
||||||
try {
|
const { req, res } = requestQueue.shift();
|
||||||
await processCanvasRequest(req, res);
|
try {
|
||||||
} catch (err) {
|
await processCanvasRequest(req, res);
|
||||||
console.error("canvas-queue-error", "error", "jsr", null, { error: err.message });
|
} catch (err) {
|
||||||
|
console.error("canvas-queue-error", "error", "jsr", null, { error: err.message });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
isProcessing = false;
|
||||||
}
|
}
|
||||||
isProcessing = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.canvastest = function (req, res) {
|
exports.canvastest = function (req, res) {
|
||||||
@@ -134,7 +123,10 @@ exports.canvastest = function (req, res) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
exports.canvas = async (req, res) => {
|
exports.canvas = async (req, res) => {
|
||||||
if (isProcessing || !enqueueRequest(req, res)) return;
|
if (!enqueueRequest(req, res)) return;
|
||||||
isProcessing = true;
|
|
||||||
processNextInQueue().catch((err) => console.error("canvas-processing-error", { error: err.message }));
|
if (!isProcessing) {
|
||||||
|
isProcessing = true;
|
||||||
|
processNextInQueue().catch((err) => console.error("canvas-processing-error", { error: err.message }));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user