From a7d4f0b04bb102d899203b31f793439f9d5cabe6 Mon Sep 17 00:00:00 2001 From: Vignesh Aigal Date: Fri, 22 Dec 2023 12:41:19 -0800 Subject: [PATCH 1/4] Update settings page to support updating subscription --- llmstack/client/src/pages/setting.jsx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/llmstack/client/src/pages/setting.jsx b/llmstack/client/src/pages/setting.jsx index 1fadb1e07ed..cb51793df51 100644 --- a/llmstack/client/src/pages/setting.jsx +++ b/llmstack/client/src/pages/setting.jsx @@ -11,7 +11,15 @@ import { InputLabel, Paper, Stack, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + MenuItem, + Select, } from "@mui/material"; +import { LoadingButton } from "@mui/lab"; + import { styled } from "@mui/material/styles"; import FileUpload from "@mui/icons-material/FileUpload"; import ContentCopy from "@mui/icons-material/ContentCopy"; @@ -21,6 +29,7 @@ import Connections from "../components/Connections"; import { fetchData, patchData } from "./dataUtil"; import { organizationState, profileFlagsState } from "../data/atoms"; import { useRecoilValue } from "recoil"; +import { axios } from "../data/axios"; import "../index.css"; import ThemedJsonForm from "../components/ThemedJsonForm"; import validator from "@rjsf/validator-ajv8"; @@ -169,6 +178,13 @@ const SettingPage = () => { setLoading(false); }, ); + + const searchParams = new URLSearchParams(window.location.search); + if (searchParams.get("showNotification")) { + enqueueSnackbar(searchParams.get("notificationMessage") || "", { + variant: searchParams.get("notificationType") || "info", + }); + } }, []); const handleUpdate = (update_keys) => { @@ -411,6 +427,15 @@ const SettingPage = () => { )} + {subscriptionUpdateModalOpen && ( + { + setSubscriptionUpdateModalOpen(false); + }} + userEmail={formData.user_email} + /> + )} ); }; From c5ce8c73a1c50146373f5cd3c988b1371fe67eeb Mon Sep 17 00:00:00 2001 From: Vignesh Aigal Date: Tue, 2 Jan 2024 15:03:23 -0800 Subject: [PATCH 2/4] Update --- .../components/SubscriptionUpdateModal.jsx | 117 ++++++++++++++++++ llmstack/client/src/pages/setting.jsx | 9 +- 2 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 llmstack/client/src/components/SubscriptionUpdateModal.jsx diff --git a/llmstack/client/src/components/SubscriptionUpdateModal.jsx b/llmstack/client/src/components/SubscriptionUpdateModal.jsx new file mode 100644 index 00000000000..eb93c49f64e --- /dev/null +++ b/llmstack/client/src/components/SubscriptionUpdateModal.jsx @@ -0,0 +1,117 @@ +import { useEffect, useState } from "react"; + +import { + TextField, + Button, + FormGroup, + InputLabel, + Paper, + Stack, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + MenuItem, + Select, +} from "@mui/material"; +import { axios } from "../data/axios"; +import { LoadingButton } from "@mui/lab"; +import { enqueueSnackbar } from "notistack"; + +const SubscriptionUpdateModal = ({ open, handleCloseCb, userEmail }) => { + const [subscriptionPrices, setSubscriptionPrices] = useState([]); + const [subscription, setSubscription] = useState(""); + const [updateButtonLoading, setUpdateButtonLoading] = useState(false); + const [updateButtonDisabled, setUpdateButtonDisabled] = useState(false); + const [cancelButtonDisabled, setCancelButtonDisabled] = useState(false); + + useEffect(() => { + axios() + .get("/api/subscriptions/prices") + .then((res) => { + setSubscriptionPrices(res.data.prices || []); + }) + .catch((err) => { + enqueueSnackbar("Error loading subscription prices", { + variant: "error", + }); + }); + }, []); + + return ( + + {"Manage Subscription"} + + + + + + + + Subscription + + + + + + + + { + setCancelButtonDisabled(true); + setUpdateButtonDisabled(true); + setUpdateButtonLoading(true); + axios() + .post("/api/subscriptions/checkout", { + price_id: subscription, + }) + .then((res) => { + enqueueSnackbar("Loading Checkout Page", { + variant: "success", + }); + window.location.href = res.data.checkout_session_url; + }) + .catch((err) => {}) + .finally(() => { + setCancelButtonDisabled(false); + setUpdateButtonDisabled(false); + setUpdateButtonLoading(false); + }); + }} + variant="contained" + > + Update + + + + ); +}; + +export default SubscriptionUpdateModal; diff --git a/llmstack/client/src/pages/setting.jsx b/llmstack/client/src/pages/setting.jsx index cb51793df51..f907f303046 100644 --- a/llmstack/client/src/pages/setting.jsx +++ b/llmstack/client/src/pages/setting.jsx @@ -11,13 +11,8 @@ import { InputLabel, Paper, Stack, - Dialog, - DialogTitle, - DialogContent, - DialogActions, - MenuItem, - Select, } from "@mui/material"; + import { LoadingButton } from "@mui/lab"; import { styled } from "@mui/material/styles"; @@ -26,6 +21,8 @@ import ContentCopy from "@mui/icons-material/ContentCopy"; import { useEffect, useState } from "react"; import { enqueueSnackbar } from "notistack"; import Connections from "../components/Connections"; +import SecretTextField from "../components/form/SecretTextField"; +import SubscriptionUpdateModal from "../components/SubscriptionUpdateModal"; import { fetchData, patchData } from "./dataUtil"; import { organizationState, profileFlagsState } from "../data/atoms"; import { useRecoilValue } from "recoil"; From 91aef3bdf0b4eebf233b580a86673973331a3eea Mon Sep 17 00:00:00 2001 From: Vignesh Aigal Date: Tue, 2 Jan 2024 15:19:17 -0800 Subject: [PATCH 3/4] Fix merge issues --- llmstack/client/src/pages/setting.jsx | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/llmstack/client/src/pages/setting.jsx b/llmstack/client/src/pages/setting.jsx index f907f303046..e10e814276c 100644 --- a/llmstack/client/src/pages/setting.jsx +++ b/llmstack/client/src/pages/setting.jsx @@ -13,20 +13,16 @@ import { Stack, } from "@mui/material"; -import { LoadingButton } from "@mui/lab"; - import { styled } from "@mui/material/styles"; import FileUpload from "@mui/icons-material/FileUpload"; import ContentCopy from "@mui/icons-material/ContentCopy"; import { useEffect, useState } from "react"; import { enqueueSnackbar } from "notistack"; import Connections from "../components/Connections"; -import SecretTextField from "../components/form/SecretTextField"; import SubscriptionUpdateModal from "../components/SubscriptionUpdateModal"; import { fetchData, patchData } from "./dataUtil"; import { organizationState, profileFlagsState } from "../data/atoms"; import { useRecoilValue } from "recoil"; -import { axios } from "../data/axios"; import "../index.css"; import ThemedJsonForm from "../components/ThemedJsonForm"; import validator from "@rjsf/validator-ajv8"; @@ -146,6 +142,8 @@ const SettingPage = () => { logo: "", }); const [loading, setLoading] = useState(true); + const [subscriptionUpdateModalOpen, setSubscriptionUpdateModalOpen] = + useState(false); const [updateKeys, setUpdateKeys] = useState(new Set()); const profileFlags = useRecoilValue(profileFlagsState); const organization = useRecoilValue(organizationState); @@ -399,18 +397,9 @@ const SettingPage = () => { {process.env.REACT_APP_ENABLE_SUBSCRIPTION_MANAGEMENT === "true" && (