diff --git a/frontend/src/components/helpers/auth/RequireAuth.js b/frontend/src/components/helpers/auth/RequireAuth.js
index 48a6e7f7b..d98ba3c56 100644
--- a/frontend/src/components/helpers/auth/RequireAuth.js
+++ b/frontend/src/components/helpers/auth/RequireAuth.js
@@ -3,6 +3,7 @@ import { useEffect } from "react";
import {
getOrgNameFromPathname,
+ homePagePath,
onboardCompleted,
} from "../../../helpers/GetStaticData";
import { useSessionStore } from "../../../store/session-store";
@@ -53,7 +54,7 @@ const RequireAuth = () => {
if (isLlmWhisperer) {
navigateTo = `/llm-whisperer/${orgName}/playground`;
} else if (onboardCompleted(adapters)) {
- navigateTo = `/${orgName}/tools`;
+ navigateTo = `/${orgName}/${homePagePath}`;
}
if (
sessionDetails.role === "unstract_reviewer" ||
diff --git a/frontend/src/components/helpers/auth/RequireGuest.js b/frontend/src/components/helpers/auth/RequireGuest.js
index 00b1fa62c..a49c02035 100644
--- a/frontend/src/components/helpers/auth/RequireGuest.js
+++ b/frontend/src/components/helpers/auth/RequireGuest.js
@@ -1,6 +1,10 @@
import { Navigate, Outlet, useLocation } from "react-router-dom";
-import { publicRoutes, onboardCompleted } from "../../../helpers/GetStaticData";
+import {
+ publicRoutes,
+ onboardCompleted,
+ homePagePath,
+} from "../../../helpers/GetStaticData";
import { useSessionStore } from "../../../store/session-store";
let selectedProductStore;
let isLlmWhisperer;
@@ -28,7 +32,7 @@ const RequireGuest = () => {
if (isLlmWhisperer) {
navigateTo = `/llm-whisperer/${orgName}/playground`;
} else if (onboardCompleted(adapters)) {
- navigateTo = `/${orgName}/tools`;
+ navigateTo = `/${orgName}/${homePagePath}`;
}
if (
sessionDetails.role === "unstract_reviewer" ||
diff --git a/frontend/src/components/input-output/add-source/AddSource.jsx b/frontend/src/components/input-output/add-source/AddSource.jsx
index eb56d76a2..ddaff0a34 100644
--- a/frontend/src/components/input-output/add-source/AddSource.jsx
+++ b/frontend/src/components/input-output/add-source/AddSource.jsx
@@ -10,6 +10,22 @@ import { EmptyState } from "../../widgets/empty-state/EmptyState";
import { ConfigureDs } from "../configure-ds/ConfigureDs";
import { useExceptionHandler } from "../../../hooks/useExceptionHandler";
+let transformLlmWhispererJsonSchema;
+let LLMW_V2_ID;
+let PLAN_TYPES;
+let unstractSubscriptionPlanStore;
+try {
+ transformLlmWhispererJsonSchema =
+ require("../../../plugins/unstract-subscription/helper/transformLlmWhispererJsonSchema").transformLlmWhispererJsonSchema;
+ LLMW_V2_ID =
+ require("../../../plugins/unstract-subscription/helper/transformLlmWhispererJsonSchema").LLMW_V2_ID;
+ PLAN_TYPES =
+ require("../../../plugins/unstract-subscription/helper/constants").PLAN_TYPES;
+ unstractSubscriptionPlanStore = require("../../../plugins/store/unstract-subscription-plan-store");
+} catch (err) {
+ // Ignore if not available
+}
+
function AddSource({
selectedSourceId,
selectedSourceName,
@@ -32,6 +48,13 @@ function AddSource({
const axiosPrivate = useAxiosPrivate();
const handleException = useExceptionHandler();
+ let planType;
+ if (unstractSubscriptionPlanStore?.useUnstractSubscriptionPlanStore) {
+ planType = unstractSubscriptionPlanStore?.useUnstractSubscriptionPlanStore(
+ (state) => state?.unstractSubscriptionPlan?.planType
+ );
+ }
+
useEffect(() => {
if (!selectedSourceId) {
setSpec({});
@@ -56,7 +79,19 @@ function AddSource({
.then((res) => {
const data = res?.data;
setFormData(metadata || {});
- setSpec(data?.json_schema || {});
+
+ if (
+ LLMW_V2_ID &&
+ transformLlmWhispererJsonSchema &&
+ PLAN_TYPES &&
+ selectedSourceId === LLMW_V2_ID &&
+ planType === PLAN_TYPES?.PAID
+ ) {
+ setSpec(transformLlmWhispererJsonSchema(data?.json_schema || {}));
+ } else {
+ setSpec(data?.json_schema || {});
+ }
+
if (data?.oauth) {
setOAuthProvider(data?.python_social_auth_backend);
} else {
diff --git a/frontend/src/components/navigations/side-nav-bar/SideNavBar.jsx b/frontend/src/components/navigations/side-nav-bar/SideNavBar.jsx
index 0a1997d9d..2d58d5cd8 100644
--- a/frontend/src/components/navigations/side-nav-bar/SideNavBar.jsx
+++ b/frontend/src/components/navigations/side-nav-bar/SideNavBar.jsx
@@ -31,6 +31,14 @@ try {
// Plugin unavailable.
}
+let dashboardSideMenuItem;
+try {
+ dashboardSideMenuItem =
+ require("../../../plugins/unstract-subscription/helper/constants").dashboardSideMenuItem;
+} catch (err) {
+ // Plugin unavailable.
+}
+
const SideNavBar = ({ collapsed }) => {
const navigate = useNavigate();
const { sessionDetails } = useSessionStore();
@@ -40,7 +48,7 @@ const SideNavBar = ({ collapsed }) => {
menu = sideMenu.useSideMenu();
}
- const data = menu || [
+ const unstractMenuItems = [
{
id: 1,
mainTitle: "MANAGE",
@@ -155,6 +163,12 @@ const SideNavBar = ({ collapsed }) => {
},
];
+ if (dashboardSideMenuItem) {
+ unstractMenuItems[2].subMenu.push(dashboardSideMenuItem(orgName));
+ }
+
+ const data = menu || unstractMenuItems;
+
if (getMenuItem && flags?.app_deployment) {
data[0]?.subMenu?.splice(1, 0, getMenuItem?.default(orgName));
}
diff --git a/frontend/src/components/navigations/top-nav-bar/TopNavBar.jsx b/frontend/src/components/navigations/top-nav-bar/TopNavBar.jsx
index 7bbd63be8..2dd2d23ed 100644
--- a/frontend/src/components/navigations/top-nav-bar/TopNavBar.jsx
+++ b/frontend/src/components/navigations/top-nav-bar/TopNavBar.jsx
@@ -16,7 +16,7 @@ import {
FileProtectOutlined,
LikeOutlined,
} from "@ant-design/icons";
-import { useEffect, useState } from "react";
+import { useEffect, useState, useMemo, useCallback } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import axios from "axios";
import PropTypes from "prop-types";
@@ -24,6 +24,7 @@ import PropTypes from "prop-types";
import { UnstractLogo } from "../../../assets/index.js";
import {
getBaseUrl,
+ homePagePath,
onboardCompleted,
} from "../../../helpers/GetStaticData.js";
import useLogout from "../../../hooks/useLogout.js";
@@ -37,12 +38,13 @@ import { useExceptionHandler } from "../../../hooks/useExceptionHandler.jsx";
let TrialDaysInfo;
try {
TrialDaysInfo =
- require("../../../plugins/subscription/trial-helper/TrialDaysInfo.jsx").default;
+ require("../../../plugins/unstract-subscription/components/TrialDaysInfo.jsx").default;
} catch (err) {
// Plugin not found
}
-let selectedProduct;
+
let selectedProductStore;
+let selectedProduct;
try {
selectedProductStore = require("../../../plugins/llm-whisperer/store/select-product-store.js");
@@ -51,7 +53,6 @@ try {
}
let PlatformDropdown;
-
try {
PlatformDropdown =
require("../../../plugins/platform-dropdown/PlatformDropDown.jsx").PlatformDropdown;
@@ -59,12 +60,6 @@ try {
// Plugin not found
}
-try {
- selectedProductStore = require("../../../plugins/llm-whisperer/store/select-product-store.js");
-} catch {
- // Ignore if hook not available
-}
-
let WhispererLogo;
try {
WhispererLogo =
@@ -76,10 +71,9 @@ try {
function TopNavBar({ isSimpleLayout, topNavBarOptions }) {
const navigate = useNavigate();
const { sessionDetails } = useSessionStore();
- const { orgName, remainingTrialDays, allOrganization, orgId } =
- sessionDetails;
+ const { orgName, allOrganization, orgId } = sessionDetails;
const baseUrl = getBaseUrl();
- const onBoardUrl = baseUrl + `/${orgName}/onboard`;
+ const onBoardUrl = `${baseUrl}/${orgName}/onboard`;
const logout = useLogout();
const [showOnboardBanner, setShowOnboardBanner] = useState(false);
const [approverStatus, setApproverStatus] = useState(false);
@@ -97,27 +91,29 @@ function TopNavBar({ isSimpleLayout, topNavBarOptions }) {
const isUnstract = !(selectedProduct && selectedProduct !== "unstract");
+ // Check user role and whether the onboarding is incomplete
useEffect(() => {
- const isUnstractReviewer = sessionDetails.role === "unstract_reviewer";
- const isUnstractSupervisor = sessionDetails.role === "unstract_supervisor";
- const isUnstractAdmin = sessionDetails.role === "unstract_admin";
+ const { role } = sessionDetails;
+ const isReviewer = role === "unstract_reviewer";
+ const isSupervisor = role === "unstract_supervisor";
+ const isAdmin = role === "unstract_admin";
setShowOnboardBanner(
!onboardCompleted(sessionDetails?.adapters) &&
- !isUnstractReviewer &&
- !isUnstractSupervisor
+ !isReviewer &&
+ !isSupervisor
);
-
- setApproverStatus(isUnstractAdmin || isUnstractSupervisor);
- setReviewerStatus(isUnstractReviewer);
+ setApproverStatus(isAdmin || isSupervisor);
+ setReviewerStatus(isReviewer);
}, [sessionDetails]);
+ // Determine review page header
useEffect(() => {
- const checkReviewPage = location.pathname.split("review");
- if (checkReviewPage.length > 1) {
- if (checkReviewPage[1].includes("/approve")) {
+ const pathSegments = location.pathname.split("review");
+ if (pathSegments.length > 1) {
+ if (pathSegments[1].includes("/approve")) {
setReviewPageHeader("Approve");
- } else if (checkReviewPage[1].includes("/download_and_sync")) {
+ } else if (pathSegments[1].includes("/download_and_sync")) {
setReviewPageHeader("Download and syncmanager");
} else {
setReviewPageHeader("Review");
@@ -130,33 +126,8 @@ function TopNavBar({ isSimpleLayout, topNavBarOptions }) {
}
}, [location]);
- const cascadeOptions = allOrganization?.map((org) => {
- return {
- key: org?.id,
- label:
- org?.id === sessionDetails?.orgId ? (
-
- setAlertDetails({
- type: "error",
- content: `You are already in ${org?.display_name}`,
- })
- }
- >
- {org?.display_name}
-
- ) : (
- handleContinue(org?.id)}
- content={`Want to switch to ${org?.display_name} `}
- >
- {org?.display_name}
-
- ),
- };
- });
-
- const handleContinue = async (selectedOrg) => {
+ // Switch organization
+ const handleContinue = useCallback(async (selectedOrg) => {
const requestOptions = {
method: "POST",
url: `/api/v1/organization/${selectedOrg}/set`,
@@ -164,51 +135,89 @@ function TopNavBar({ isSimpleLayout, topNavBarOptions }) {
"X-CSRFToken": sessionDetails?.csrfToken,
},
};
- await axios(requestOptions)
- .then(() => {
- navigate("/");
- window.location.reload();
- })
- .catch((err) => {
- setAlertDetails(handleException(err));
+ try {
+ await axios(requestOptions);
+ navigate("/");
+ window.location.reload();
+ } catch (err) {
+ setAlertDetails(handleException(err));
+ }
+ }, []);
+
+ // Prepare org list for switching
+ const cascadeOptions = useMemo(() => {
+ return allOrganization?.map((org) => {
+ return {
+ key: org?.id,
+ label:
+ org?.id === sessionDetails?.orgId ? (
+
+ setAlertDetails({
+ type: "error",
+ content: `You are already in ${org?.display_name}`,
+ })
+ }
+ >
+ {org?.display_name}
+
+ ) : (
+ handleContinue(org?.id)}
+ content={`Want to switch to ${org?.display_name}?`}
+ >
+ {org?.display_name}
+
+ ),
+ };
+ });
+ }, [allOrganization, handleContinue]);
+
+ // Build dropdown menu items
+ const items = useMemo(() => {
+ const menuItems = [];
+
+ // Profile
+ if (isUnstract && !isSimpleLayout) {
+ menuItems.push({
+ key: "1",
+ label: (
+
+ ),
+ });
+ }
+
+ // Switch Organization
+ if (allOrganization?.length > 1) {
+ menuItems.push({
+ key: "3",
+ label: (
+
+
+ Switch Org
+
+
+ ),
});
- };
+ }
- // Profile Dropdown items
- const items = [
- isUnstract && {
- key: "1",
- label: (
-
- ),
- },
- allOrganization?.length > 1 && {
- key: "3",
- label: (
-
-
- {" "}
- Switch Org
-
-
- ),
- },
- isUnstract &&
- (reviewerStatus || approverStatus) && {
+ // Review
+ if (isUnstract && !isSimpleLayout && (reviewerStatus || approverStatus)) {
+ menuItems.push({
key: "4",
label: (
Review
),
- },
- isUnstract &&
- approverStatus && {
+ });
+ }
+
+ // Approve
+ if (isUnstract && !isSimpleLayout && approverStatus) {
+ menuItems.push({
key: "5",
label: (
Approve
),
- },
- isUnstract &&
- approverStatus && {
+ });
+
+ menuItems.push({
key: "6",
label: (
Download and Sync Manager
),
- },
- {
+ });
+ }
+
+ // Logout
+ menuItems.push({
key: "2",
label: (
),
- },
- ];
+ });
+
+ return menuItems.filter(Boolean); // remove any undefined items
+ }, [
+ isUnstract,
+ isSimpleLayout,
+ reviewerStatus,
+ approverStatus,
+ allOrganization,
+ cascadeOptions,
+ orgName,
+ orgId,
+ ]);
// Function to get the initials from the user name
- const getInitials = (name) => {
+ const getInitials = useCallback((name) => {
const names = name?.split(" ");
- const initials = names
+ return names
?.map((n) => n.charAt(0))
?.join("")
?.toUpperCase();
- return initials;
- };
+ }, []);
return (
{isUnstract ? (
-
+
+ navigate(`/${sessionDetails?.orgName}/${homePagePath}`)
+ }
+ />
) : (
WhispererLogo &&
)}
@@ -279,61 +309,55 @@ function TopNavBar({ isSimpleLayout, topNavBarOptions }) {
)}
{PlatformDropdown && }
- {!isSimpleLayout && (
- <>
-
- {isUnstract && showOnboardBanner && (
-
-
- Your setup process is incomplete. Now, that's a
- bummer!
-
-
- Complete it to start using Unstract
-
- >
- }
- showIcon
- />
- )}
-
-
-
-
- {topNavBarOptions}
- {isUnstract && TrialDaysInfo && (
-
- )}
-
-
- {sessionDetails?.picture ? (
-
- ) : (
-
- {getInitials(sessionDetails?.name)}
-
- )}
-
-
-
-
-
- >
+
+ {isSimpleLayout ? (
+
+ ) : (
+
+ {isUnstract && showOnboardBanner && (
+
+
+ Your setup process is incomplete. Now, that's a bummer!
+
+
+ Complete it to start using Unstract
+
+ >
+ }
+ showIcon
+ />
+ )}
+
)}
+
+
+
+
+ {topNavBarOptions}
+ {isUnstract && TrialDaysInfo && }
+
+
+ {sessionDetails?.picture ? (
+
+ ) : (
+
+ {getInitials(sessionDetails?.name)}
+
+ )}
+
+
+
+
+
);
}
diff --git a/frontend/src/components/onboard/OnBoard.jsx b/frontend/src/components/onboard/OnBoard.jsx
index 79f0afd1c..cf6a02534 100644
--- a/frontend/src/components/onboard/OnBoard.jsx
+++ b/frontend/src/components/onboard/OnBoard.jsx
@@ -8,7 +8,7 @@ import ConnectLLM from "../../assets/connect_llm.svg";
import ConnectVectorDb from "../../assets/connect_vector_db.svg";
import ConnectEmbedding from "../../assets/connect_embedding.svg";
import ConnectTextExtractor from "../../assets/connect_x2text.svg";
-import { onboardCompleted } from "../../helpers/GetStaticData.js";
+import { homePagePath, onboardCompleted } from "../../helpers/GetStaticData.js";
import { useSessionStore } from "../../store/session-store.js";
import { AddSourceModal } from "../input-output/add-source-modal/AddSourceModal.jsx";
import { CustomButton } from "../widgets/custom-button/CustomButton.jsx";
@@ -22,7 +22,7 @@ function OnBoard() {
const [openAddSourcesModal, setOpenAddSourcesModal] = useState(false);
const [editItemId, setEditItemId] = useState(null);
const [type, setType] = useState(null);
- const homePageUrl = `/${orgName}/tools`;
+ const homePageUrl = `/${orgName}/${homePagePath}`;
const [adaptersList, setAdaptersList] = useState(adapters || []);
useEffect(() => {
if (onboardCompleted(adaptersList)) {
diff --git a/frontend/src/components/rjsf-custom-widgets/alt-date-time-widget/AltDateTimeWidget.jsx b/frontend/src/components/rjsf-custom-widgets/alt-date-time-widget/AltDateTimeWidget.jsx
index 25112fa3b..3a20feb3a 100644
--- a/frontend/src/components/rjsf-custom-widgets/alt-date-time-widget/AltDateTimeWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/alt-date-time-widget/AltDateTimeWidget.jsx
@@ -11,6 +11,7 @@ const AltDateTimeWidget = ({
label,
schema,
required,
+ readonly,
}) => {
const description = schema?.description || "";
const handleDateChange = (date) => {
@@ -34,10 +35,12 @@ const AltDateTimeWidget = ({
id={id}
value={value ? moment(value) : null}
onChange={handleDateChange}
+ disabled={readonly}
/>
);
@@ -49,7 +52,8 @@ AltDateTimeWidget.propTypes = {
onChange: PropTypes.func.isRequired,
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
- required: PropTypes.bool,
+ required: PropTypes.bool.isRequired,
+ readonly: PropTypes.bool.isRequired,
};
export { AltDateTimeWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/alt-date-widget/AltDateWidget.jsx b/frontend/src/components/rjsf-custom-widgets/alt-date-widget/AltDateWidget.jsx
index 7c996c060..d683ed55d 100644
--- a/frontend/src/components/rjsf-custom-widgets/alt-date-widget/AltDateWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/alt-date-widget/AltDateWidget.jsx
@@ -4,7 +4,8 @@ import PropTypes from "prop-types";
import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidgetLayout.jsx";
-const AltDateWidget = ({ id, value, onChange, label, schema, required }) => {
+const AltDateWidget = (props) => {
+ const { id, value, onChange, label, schema, required, readonly } = props;
const description = schema?.description || "";
const handleDateChange = (date) => {
@@ -21,6 +22,7 @@ const AltDateWidget = ({ id, value, onChange, label, schema, required }) => {
id={id}
value={value ? moment(value) : null}
onChange={handleDateChange}
+ disabled={readonly}
/>
);
@@ -33,6 +35,7 @@ AltDateWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { AltDateWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/array-field/ArrayField.jsx b/frontend/src/components/rjsf-custom-widgets/array-field/ArrayField.jsx
index 434847c50..bc91174c7 100644
--- a/frontend/src/components/rjsf-custom-widgets/array-field/ArrayField.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/array-field/ArrayField.jsx
@@ -7,7 +7,7 @@ import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidget
import "./ArrayField.css";
const ArrayField = (props) => {
- const { schema, formData, onChange, required } = props;
+ const { schema, formData, onChange, required, readonly } = props;
const [dropdownList, setDropdownList] = useState([]);
const [options, setOptions] = useState([]);
@@ -54,6 +54,7 @@ const ArrayField = (props) => {
value={formData}
onChange={handleChange}
options={options}
+ disabled={readonly}
/>
);
@@ -65,6 +66,7 @@ ArrayField.propTypes = {
formData: PropTypes.array,
onChange: PropTypes.func.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { ArrayField };
diff --git a/frontend/src/components/rjsf-custom-widgets/checkbox-widget/CheckboxWidget.jsx b/frontend/src/components/rjsf-custom-widgets/checkbox-widget/CheckboxWidget.jsx
index 4ea6ba0b1..5d508cde4 100644
--- a/frontend/src/components/rjsf-custom-widgets/checkbox-widget/CheckboxWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/checkbox-widget/CheckboxWidget.jsx
@@ -1,8 +1,17 @@
import { Checkbox, Space, Typography } from "antd";
import PropTypes from "prop-types";
+
import "./CheckboxWidget.css";
import CustomMarkdown from "../../helpers/custom-markdown/CustomMarkdown";
-const CheckboxWidget = ({ id, value, onChange, label, schema, required }) => {
+const CheckboxWidget = ({
+ id,
+ value,
+ onChange,
+ label,
+ schema,
+ required,
+ readonly,
+}) => {
const description = schema?.description || "";
const handleCheckboxChange = (event) => {
onChange(event.target.checked);
@@ -10,7 +19,12 @@ const CheckboxWidget = ({ id, value, onChange, label, schema, required }) => {
return (
-
+
{required && * }
{label}
@@ -34,6 +48,7 @@ CheckboxWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { CheckboxWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/checkboxes-widget/CheckboxesWidget.jsx b/frontend/src/components/rjsf-custom-widgets/checkboxes-widget/CheckboxesWidget.jsx
index 76fbf0873..3fb43bb6f 100644
--- a/frontend/src/components/rjsf-custom-widgets/checkboxes-widget/CheckboxesWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/checkboxes-widget/CheckboxesWidget.jsx
@@ -11,6 +11,7 @@ const CheckboxesWidget = ({
label,
schema,
required,
+ readonly,
}) => {
const description = schema?.description || "";
const handleCheckboxChange = (optionValue) => {
@@ -35,6 +36,7 @@ const CheckboxesWidget = ({
key={option.value}
checked={value?.includes(option.value)}
onChange={() => handleCheckboxChange(option.value)}
+ disabled={readonly}
>
{option.label}
@@ -51,6 +53,7 @@ CheckboxesWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { CheckboxesWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/color-widget/ColorWidget.jsx b/frontend/src/components/rjsf-custom-widgets/color-widget/ColorWidget.jsx
index d6a1b4750..7bb0ea6db 100644
--- a/frontend/src/components/rjsf-custom-widgets/color-widget/ColorWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/color-widget/ColorWidget.jsx
@@ -3,7 +3,15 @@ import { Input } from "antd";
import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidgetLayout.jsx";
-const ColorWidget = ({ id, value, onChange, schema, label, required }) => {
+const ColorWidget = ({
+ id,
+ value,
+ onChange,
+ schema,
+ label,
+ required,
+ readonly,
+}) => {
const description = schema?.description || "";
const handleColorChange = (event) => {
@@ -16,7 +24,13 @@ const ColorWidget = ({ id, value, onChange, schema, label, required }) => {
description={description}
required={required}
>
-
+
);
};
@@ -28,6 +42,7 @@ ColorWidget.propTypes = {
schema: PropTypes.object.isRequired,
label: PropTypes.string.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { ColorWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/date-time-widget/DateTimeWidget.jsx b/frontend/src/components/rjsf-custom-widgets/date-time-widget/DateTimeWidget.jsx
index a3b2df307..74d28bc99 100644
--- a/frontend/src/components/rjsf-custom-widgets/date-time-widget/DateTimeWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/date-time-widget/DateTimeWidget.jsx
@@ -4,7 +4,15 @@ import PropTypes from "prop-types";
import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidgetLayout.jsx";
-const DateTimeWidget = ({ id, value, onChange, label, schema, required }) => {
+const DateTimeWidget = ({
+ id,
+ value,
+ onChange,
+ label,
+ schema,
+ required,
+ readonly,
+}) => {
const description = schema?.description || "";
const handleDateTimeChange = (dateTime) => {
onChange(dateTime?.toISOString());
@@ -21,6 +29,7 @@ const DateTimeWidget = ({ id, value, onChange, label, schema, required }) => {
id={id}
value={value ? moment(value) : null}
onChange={handleDateTimeChange}
+ disabled={readonly}
/>
);
@@ -33,6 +42,7 @@ DateTimeWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { DateTimeWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/date-widget/DateWidget.jsx b/frontend/src/components/rjsf-custom-widgets/date-widget/DateWidget.jsx
index 06ea0a494..5e4e5cd11 100644
--- a/frontend/src/components/rjsf-custom-widgets/date-widget/DateWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/date-widget/DateWidget.jsx
@@ -4,7 +4,15 @@ import PropTypes from "prop-types";
import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidgetLayout.jsx";
-const DateWidget = ({ id, value, onChange, label, schema, required }) => {
+const DateWidget = ({
+ id,
+ value,
+ onChange,
+ label,
+ schema,
+ required,
+ readonly,
+}) => {
const description = schema?.description || "";
const handleDateChange = (date) => {
onChange(date?.toISOString());
@@ -20,6 +28,7 @@ const DateWidget = ({ id, value, onChange, label, schema, required }) => {
id={id}
value={value ? moment(value) : null}
onChange={handleDateChange}
+ disabled={readonly}
/>
);
@@ -32,6 +41,7 @@ DateWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { DateWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/email-widget/EmailWidget.jsx b/frontend/src/components/rjsf-custom-widgets/email-widget/EmailWidget.jsx
index 711cb0b5d..183e0c0b7 100644
--- a/frontend/src/components/rjsf-custom-widgets/email-widget/EmailWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/email-widget/EmailWidget.jsx
@@ -3,7 +3,15 @@ import PropTypes from "prop-types";
import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidgetLayout.jsx";
-const EmailWidget = ({ id, value, onChange, label, schema, required }) => {
+const EmailWidget = ({
+ id,
+ value,
+ onChange,
+ label,
+ schema,
+ required,
+ readonly,
+}) => {
const description = schema?.description || "";
const handleEmailChange = (event) => {
onChange(event.target.value);
@@ -15,7 +23,13 @@ const EmailWidget = ({ id, value, onChange, label, schema, required }) => {
description={description}
required={required}
>
-
+
);
};
@@ -27,6 +41,7 @@ EmailWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { EmailWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/file-widget/FileWidget.jsx b/frontend/src/components/rjsf-custom-widgets/file-widget/FileWidget.jsx
index 4a43ed121..9a43dcaaa 100644
--- a/frontend/src/components/rjsf-custom-widgets/file-widget/FileWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/file-widget/FileWidget.jsx
@@ -4,7 +4,7 @@ import PropTypes from "prop-types";
import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidgetLayout.jsx";
-const FileWidget = ({ id, onChange, label, schema, required }) => {
+const FileWidget = ({ id, onChange, label, schema, required, readonly }) => {
const description = schema?.description || "";
const handleFileChange = (info) => {
if (info.file.status === "done") {
@@ -19,7 +19,7 @@ const FileWidget = ({ id, onChange, label, schema, required }) => {
description={description}
required={required}
>
-
+
}>Upload File
@@ -32,6 +32,7 @@ FileWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { FileWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/password-widget/PasswordWidget.jsx b/frontend/src/components/rjsf-custom-widgets/password-widget/PasswordWidget.jsx
index e7f8f53db..b21d5339a 100644
--- a/frontend/src/components/rjsf-custom-widgets/password-widget/PasswordWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/password-widget/PasswordWidget.jsx
@@ -3,7 +3,15 @@ import PropTypes from "prop-types";
import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidgetLayout.jsx";
-const PasswordWidget = ({ id, value, onChange, label, schema, required }) => {
+const PasswordWidget = ({
+ id,
+ value,
+ onChange,
+ label,
+ schema,
+ required,
+ readonly,
+}) => {
const description = schema?.description || "";
const handlePasswordChange = (event) => {
onChange(event.target.value);
@@ -15,7 +23,12 @@ const PasswordWidget = ({ id, value, onChange, label, schema, required }) => {
description={description}
required={required}
>
-
+
);
};
@@ -27,6 +40,7 @@ PasswordWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { PasswordWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/select-widget/SelectWidget.jsx b/frontend/src/components/rjsf-custom-widgets/select-widget/SelectWidget.jsx
index 49af88ee7..6540dfdab 100644
--- a/frontend/src/components/rjsf-custom-widgets/select-widget/SelectWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/select-widget/SelectWidget.jsx
@@ -1,10 +1,12 @@
import { Form, Select, Space, Typography } from "antd";
import PropTypes from "prop-types";
+
import CustomMarkdown from "../../helpers/custom-markdown/CustomMarkdown";
const { Option } = Select;
const SelectWidget = (props) => {
- const { id, value, options, onChange, label, schema, rawErrors } = props;
+ const { id, value, options, onChange, label, schema, rawErrors, readonly } =
+ props;
const description = schema?.description || "";
const handleSelectChange = (selectedValue) => {
@@ -22,6 +24,7 @@ const SelectWidget = (props) => {
value={value}
onChange={handleSelectChange}
showSearch
+ disabled={readonly}
>
{options?.enumOptions &&
options.enumOptions.map((option, index) => (
@@ -51,6 +54,7 @@ SelectWidget.propTypes = {
rawErrors: PropTypes.array,
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
+ readonly: PropTypes.bool.isRequired,
};
export { SelectWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/text-widget/TextWidget.jsx b/frontend/src/components/rjsf-custom-widgets/text-widget/TextWidget.jsx
index 6951b7c64..30017f32b 100644
--- a/frontend/src/components/rjsf-custom-widgets/text-widget/TextWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/text-widget/TextWidget.jsx
@@ -4,7 +4,7 @@ import PropTypes from "prop-types";
import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidgetLayout.jsx";
const TextWidget = (props) => {
- const { id, value, onChange, label, schema, required } = props;
+ const { id, value, onChange, label, schema, required, readonly } = props;
const description = schema?.description || "";
const handleTextChange = (event) => {
onChange(event.target.value);
@@ -16,7 +16,12 @@ const TextWidget = (props) => {
description={description}
required={required}
>
-
+
);
};
@@ -28,6 +33,7 @@ TextWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { TextWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/time-widget/TimeWidget.jsx b/frontend/src/components/rjsf-custom-widgets/time-widget/TimeWidget.jsx
index bad749ffa..81c371c76 100644
--- a/frontend/src/components/rjsf-custom-widgets/time-widget/TimeWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/time-widget/TimeWidget.jsx
@@ -4,7 +4,15 @@ import PropTypes from "prop-types";
import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidgetLayout.jsx";
-const TimeWidget = ({ id, value, onChange, label, schema, required }) => {
+const TimeWidget = ({
+ id,
+ value,
+ onChange,
+ label,
+ schema,
+ required,
+ readonly,
+}) => {
const description = schema?.description || "";
const handleTimeChange = (time) => {
onChange(time?.toISOString());
@@ -20,6 +28,7 @@ const TimeWidget = ({ id, value, onChange, label, schema, required }) => {
id={id}
value={value ? moment(value) : null}
onChange={handleTimeChange}
+ disabled={readonly}
/>
);
@@ -32,6 +41,7 @@ TimeWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { TimeWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/up-down-widget/UpDownWidget.jsx b/frontend/src/components/rjsf-custom-widgets/up-down-widget/UpDownWidget.jsx
index 23f0cf8e8..e33f8b0ae 100644
--- a/frontend/src/components/rjsf-custom-widgets/up-down-widget/UpDownWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/up-down-widget/UpDownWidget.jsx
@@ -3,7 +3,15 @@ import PropTypes from "prop-types";
import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidgetLayout.jsx";
-const UpDownWidget = ({ id, value, onChange, label, schema, required }) => {
+const UpDownWidget = ({
+ id,
+ value,
+ onChange,
+ label,
+ schema,
+ required,
+ readonly,
+}) => {
const description = schema?.description || "";
const handleNumberChange = (numberValue) => {
onChange(numberValue);
@@ -15,7 +23,12 @@ const UpDownWidget = ({ id, value, onChange, label, schema, required }) => {
description={description}
required={required}
>
-
+
);
};
@@ -27,6 +40,7 @@ UpDownWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { UpDownWidget };
diff --git a/frontend/src/components/rjsf-custom-widgets/url-widget/URLWidget.jsx b/frontend/src/components/rjsf-custom-widgets/url-widget/URLWidget.jsx
index ab1425713..4b501203e 100644
--- a/frontend/src/components/rjsf-custom-widgets/url-widget/URLWidget.jsx
+++ b/frontend/src/components/rjsf-custom-widgets/url-widget/URLWidget.jsx
@@ -1,9 +1,10 @@
import { Input } from "antd";
import PropTypes from "prop-types";
+
import { RjsfWidgetLayout } from "../../../layouts/rjsf-widget-layout/RjsfWidgetLayout";
const URLWidget = (props) => {
- const { id, value, onChange, label, schema, required } = props;
+ const { id, value, onChange, label, schema, required, readonly } = props;
const description = schema?.description || "";
const handleURLChange = (event) => {
onChange(event.target.value);
@@ -15,7 +16,13 @@ const URLWidget = (props) => {
description={description}
required={required}
>
-
+
);
};
@@ -27,6 +34,7 @@ URLWidget.propTypes = {
label: PropTypes.string.isRequired,
schema: PropTypes.object.isRequired,
required: PropTypes.bool,
+ readonly: PropTypes.bool.isRequired,
};
export { URLWidget };
diff --git a/frontend/src/components/settings/invite/InviteEditUser.jsx b/frontend/src/components/settings/invite/InviteEditUser.jsx
index e533063eb..f8d5e3fee 100644
--- a/frontend/src/components/settings/invite/InviteEditUser.jsx
+++ b/frontend/src/components/settings/invite/InviteEditUser.jsx
@@ -12,6 +12,7 @@ import { TopBar } from "../../widgets/top-bar/TopBar.jsx";
import "./InviteEditUser.css";
import { useExceptionHandler } from "../../../hooks/useExceptionHandler.jsx";
import usePostHogEvents from "../../../hooks/usePostHogEvents.js";
+import { homePagePath } from "../../../helpers/GetStaticData.js";
function InviteEditUser() {
const axiosPrivate = useAxiosPrivate();
@@ -145,7 +146,7 @@ function InviteEditUser() {
useEffect(() => {
if (!isInvite && !location.state) {
- navigate(`/${sessionDetails?.orgName}/tools`);
+ navigate(`/${sessionDetails?.orgName}/${homePagePath}`);
}
getUserRoles();
}, []);
diff --git a/frontend/src/components/widgets/spinner-loader/SpinnerLoader.css b/frontend/src/components/widgets/spinner-loader/SpinnerLoader.css
index 113372065..ba9d75887 100644
--- a/frontend/src/components/widgets/spinner-loader/SpinnerLoader.css
+++ b/frontend/src/components/widgets/spinner-loader/SpinnerLoader.css
@@ -1,23 +1,17 @@
/* Styles for SpinnerLoader */
-.spinner-loader-layout {
- display: flex;
- width: 100%;
- height: 100%;
-}
-
.spinner-loader-layout .ant-spin-dot-item {
- background-color: #FFB400 !important; /* Change the color of the first dot */
+ background-color: #ffb400 !important; /* Change the color of the first dot */
}
.spinner-loader-layout .ant-spin-dot-item:nth-child(2) {
- background-color: #00A6ED !important; /* Change the color of the second dot */
+ background-color: #00a6ed !important; /* Change the color of the second dot */
}
.spinner-loader-layout .ant-spin-dot-item:nth-child(3) {
- background-color: #7FB800 !important; /* Change the color of the third dot */
+ background-color: #7fb800 !important; /* Change the color of the third dot */
}
.spinner-loader-layout .ant-spin-dot-item:nth-child(4) {
- background-color: #FF4D6D !important; /* Change the color of the fourth dot */
+ background-color: #ff4d6d !important; /* Change the color of the fourth dot */
}
diff --git a/frontend/src/components/widgets/spinner-loader/SpinnerLoader.jsx b/frontend/src/components/widgets/spinner-loader/SpinnerLoader.jsx
index a7b290627..27d57bdc5 100644
--- a/frontend/src/components/widgets/spinner-loader/SpinnerLoader.jsx
+++ b/frontend/src/components/widgets/spinner-loader/SpinnerLoader.jsx
@@ -18,12 +18,14 @@ function SpinnerLoader({
align = "center",
}) {
return (
-
-
+
);
}
diff --git a/frontend/src/helpers/GetSessionData.js b/frontend/src/helpers/GetSessionData.js
index 5ee6b9291..baed64a49 100644
--- a/frontend/src/helpers/GetSessionData.js
+++ b/frontend/src/helpers/GetSessionData.js
@@ -20,7 +20,6 @@ function getSessionData(sessionData) {
isAdmin: sessionData.isAdmin,
adapters: sessionData?.adapters,
logEventsId: sessionData?.logEventsId,
- remainingTrialDays: sessionData?.remainingTrialDays,
allOrganization: sessionData?.allOrganization,
isPlatformAdmin: sessionData?.isPlatformAdmin,
loginOnboardingMessage: sessionData?.loginOnboardingMessage,
diff --git a/frontend/src/helpers/GetStaticData.js b/frontend/src/helpers/GetStaticData.js
index 1fcf4fece..e75e1e560 100644
--- a/frontend/src/helpers/GetStaticData.js
+++ b/frontend/src/helpers/GetStaticData.js
@@ -2,6 +2,14 @@ import moment from "moment";
import momentTz from "moment-timezone";
import { v4 as uuidv4 } from "uuid";
+let cloudHomePagePath;
+try {
+ cloudHomePagePath =
+ require("../plugins/unstract-subscription/helper/constants").cloudHomePagePath;
+} catch (err) {
+ // Ignore if plugin not available
+}
+
const THEME = {
DARK: "dark",
LIGHT: "light",
@@ -565,6 +573,10 @@ const generateCoverageKey = (promptId, profileId) => {
return `coverage_${promptId}_${profileId}`;
};
+const TRIAL_PLAN = "TRIAL";
+
+const homePagePath = cloudHomePagePath || "tools";
+
export {
CONNECTOR_TYPE_MAP,
O_AUTH_PROVIDERS,
@@ -616,4 +628,6 @@ export {
generateApiRunStatusId,
base64toBlobWithMime,
generateCoverageKey,
+ TRIAL_PLAN,
+ homePagePath,
};
diff --git a/frontend/src/hooks/useExceptionHandler.jsx b/frontend/src/hooks/useExceptionHandler.jsx
index c9472015c..94ceb071e 100644
--- a/frontend/src/hooks/useExceptionHandler.jsx
+++ b/frontend/src/hooks/useExceptionHandler.jsx
@@ -51,7 +51,7 @@ const useExceptionHandler = () => {
}
break;
case "subscription_error":
- navigate("/trial-expired");
+ navigate("/subscription-expired");
return {
title: title,
type: "error",
diff --git a/frontend/src/hooks/useRequestUrl.js b/frontend/src/hooks/useRequestUrl.js
new file mode 100644
index 000000000..1bb202f2f
--- /dev/null
+++ b/frontend/src/hooks/useRequestUrl.js
@@ -0,0 +1,16 @@
+import { useSessionStore } from "../store/session-store";
+
+const useRequestUrl = () => {
+ const { sessionDetails } = useSessionStore();
+
+ const getUrl = (url) => {
+ if (!url) return null;
+
+ const baseUrl = `/api/v1/${sessionDetails?.orgId}/`;
+ return baseUrl + url.replace(/^\//, "");
+ };
+
+ return { getUrl };
+};
+
+export default useRequestUrl;
diff --git a/frontend/src/hooks/useUserSession.js b/frontend/src/hooks/useUserSession.js
index de8782da2..0ba0d1956 100644
--- a/frontend/src/hooks/useUserSession.js
+++ b/frontend/src/hooks/useUserSession.js
@@ -24,7 +24,7 @@ const useUserSession = () => {
}
if (error?.response?.data?.type === "subscription_error") {
- navigate("/trial-expired");
+ navigate("/subscription-expired");
return;
}
diff --git a/frontend/src/index.css b/frontend/src/index.css
index 49221c103..65d62801d 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -15,6 +15,10 @@ body {
min-width: 1024px;
}
+.page-bg-2 {
+ background-color: var(--page-bg-2);
+}
+
.center {
display: grid;
width: inherit;
diff --git a/frontend/src/routes/Router.jsx b/frontend/src/routes/Router.jsx
index e2936ec54..08c9dd2cb 100644
--- a/frontend/src/routes/Router.jsx
+++ b/frontend/src/routes/Router.jsx
@@ -19,9 +19,9 @@ let SimplePromptStudioHelper;
let SimplePromptStudio;
let SpsLanding;
let SpsUpload;
-let TrialRoutes;
let PaymentSuccessful;
let SelectProduct;
+let UnstractSubscriptionEndPage;
try {
SimplePromptStudioHelper =
require("../plugins/simple-prompt-studio/SimplePromptStudioHelper.jsx").SimplePromptStudioHelper;
@@ -57,8 +57,8 @@ try {
}
try {
- TrialRoutes =
- require("../plugins/subscription/trial-page/TrialEndPage.jsx").TrialEndPage;
+ UnstractSubscriptionEndPage =
+ require("../plugins/unstract-subscription/pages/UnstractSubscriptionEndPage.jsx").UnstractSubscriptionEndPage;
} catch (err) {
// Do nothing, Not-found Page will be triggered.
}
@@ -116,14 +116,17 @@ function Router() {
{SelectProduct && (
} />
)}
- {TrialRoutes && (
-
} />
+ {UnstractSubscriptionEndPage && (
+
}
+ />
)}
{PaymentSuccessful && (
} />
)}
}>
-
{MainAppRoute}
+ {MainAppRoute}
{llmWhispererRouter && (
{llmWhispererRouter()}
)}
diff --git a/frontend/src/routes/useMainAppRoutes.js b/frontend/src/routes/useMainAppRoutes.js
index 039591f29..f77e96ad5 100644
--- a/frontend/src/routes/useMainAppRoutes.js
+++ b/frontend/src/routes/useMainAppRoutes.js
@@ -32,6 +32,9 @@ let PRODUCT_NAMES = {};
let ManualReviewPage;
let SimpleManualReviewPage;
let ReviewLayout;
+let UnstractUsagePage;
+let UnstractSubscriptionPage;
+let UnstractSubscriptionCheck;
try {
RequirePlatformAdmin =
@@ -62,7 +65,7 @@ try {
try {
OnboardProduct =
- require("../plugins/llm-whisperer/components/onboard-product/OnboardProduct.jsx").OnboardProduct;
+ require("../plugins/onboard-product/OnboardProduct.jsx").OnboardProduct;
PRODUCT_NAMES = require("../plugins/llm-whisperer/helper.js").PRODUCT_NAMES;
} catch (err) {
// Do nothing.
@@ -79,6 +82,17 @@ try {
// Do nothing, Not-found Page will be triggered.
}
+try {
+ UnstractSubscriptionPage =
+ require("../plugins/unstract-subscription/pages/UnstractSubscriptionPage.jsx").UnstractSubscriptionPage;
+ UnstractUsagePage =
+ require("../plugins/unstract-subscription/pages/UnstractUsagePage.jsx").UnstractUsagePage;
+ UnstractSubscriptionCheck =
+ require("../plugins/unstract-subscription/components/UnstractSubscriptionCheck.jsx").UnstractSubscriptionCheck;
+} catch (err) {
+ // Do nothing, Not-found Page will be triggered.
+}
+
function useMainAppRoutes() {
const routes = (
<>
@@ -91,6 +105,12 @@ function useMainAppRoutes() {
)}
}>
+ {UnstractUsagePage && (
+
} />
+ )}
+ {UnstractSubscriptionPage && (
+
} />
+ )}
} />
}
>
- {routes}
+
}>
+ {routes}
+
);
} else {