diff --git a/llmstack/client/src/components/Subscription.jsx b/llmstack/client/src/components/Subscription.jsx new file mode 100644 index 00000000000..3611df30864 --- /dev/null +++ b/llmstack/client/src/components/Subscription.jsx @@ -0,0 +1,95 @@ +import { useState } from "react"; + +import { Button, Paper, Typography, Stack } from "@mui/material"; + +import { organizationState, profileFlagsState } from "../data/atoms"; +import { useRecoilValue } from "recoil"; +import SubscriptionUpdateModal from "./SubscriptionUpdateModal"; + +function Subscription(props) { + const [subscriptionUpdateModalOpen, setSubscriptionUpdateModalOpen] = + useState(false); + const profileFlags = useRecoilValue(profileFlagsState); + const organization = useRecoilValue(organizationState); + + return ( + + + + Subscription + + ; + + + +

+ Logged in as {props.user_email}. You are + currently subscribed to  + + {profileFlags.IS_PRO_SUBSCRIBER + ? "Pro" + : profileFlags.IS_BASIC_SUBSCRIBER + ? "Basic" + : "Free"} + +  tier. Click on the Manage Subscription button below to + change your plan.  +
+
+ + Note: You will be redirected to Stripe payment portal to + complete the upgrade payment process. + +

+

+ Logged in as {props.user_email}. Your account + is managed by your organization,  + {organization?.name}. Please contact your admin + to manage your subscription. +

+
+
+
+ {subscriptionUpdateModalOpen && ( + { + setSubscriptionUpdateModalOpen(false); + }} + /> + )} +
+ {!profileFlags.IS_ORGANIZATION_MEMBER && ( + + )} +
+ ); +} + +export default Subscription; diff --git a/llmstack/client/src/components/SubscriptionUpdateModal.jsx b/llmstack/client/src/components/SubscriptionUpdateModal.jsx index eb93c49f64e..32c9b8f12ca 100644 --- a/llmstack/client/src/components/SubscriptionUpdateModal.jsx +++ b/llmstack/client/src/components/SubscriptionUpdateModal.jsx @@ -1,24 +1,27 @@ import { useEffect, useState } from "react"; import { - TextField, Button, - FormGroup, - InputLabel, - Paper, Stack, Dialog, DialogTitle, DialogContent, DialogActions, - MenuItem, - Select, + FormControl, + RadioGroup, + Card, + CardContent, + CardHeader, + Radio, + Typography, + Divider, } from "@mui/material"; + import { axios } from "../data/axios"; import { LoadingButton } from "@mui/lab"; import { enqueueSnackbar } from "notistack"; -const SubscriptionUpdateModal = ({ open, handleCloseCb, userEmail }) => { +const SubscriptionUpdateModal = ({ open, handleCloseCb }) => { const [subscriptionPrices, setSubscriptionPrices] = useState([]); const [subscription, setSubscription] = useState(""); const [updateButtonLoading, setUpdateButtonLoading] = useState(false); @@ -40,45 +43,65 @@ const SubscriptionUpdateModal = ({ open, handleCloseCb, userEmail }) => { return ( - {"Manage Subscription"} + {"Upgrade Subscription"} - - - - - - - Subscription - - - - + } + sx={{ padding: 0 }} + /> + + + + ${subscriptionPrice.unit_amount} /{" "} + {subscriptionPrice.recurring_interval} + + { + setSubscription(e.target.value); + }} + sx={{ + mb: 4, + }} + /> + + + + ))} + + - { }} variant="contained" > - Update + Checkout diff --git a/llmstack/client/src/pages/setting.jsx b/llmstack/client/src/pages/setting.jsx index 81559f65b62..5081060c645 100644 --- a/llmstack/client/src/pages/setting.jsx +++ b/llmstack/client/src/pages/setting.jsx @@ -19,7 +19,7 @@ import ContentCopy from "@mui/icons-material/ContentCopy"; import { useEffect, useState } from "react"; import { enqueueSnackbar } from "notistack"; import Connections from "../components/Connections"; -import SubscriptionUpdateModal from "../components/SubscriptionUpdateModal"; +import Subscription from "../components/Subscription"; import { fetchData, patchData } from "./dataUtil"; import { organizationState, profileFlagsState } from "../data/atoms"; import { useRecoilValue } from "recoil"; @@ -142,8 +142,6 @@ 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); @@ -336,98 +334,27 @@ const SettingPage = () => { - {process.env.REACT_APP_ENABLE_SUBSCRIPTION_MANAGEMENT === - "true" && ( - - Subscription -

- Logged in as {formData.user_email}. - You are currently subscribed to  - - {profileFlags.IS_PRO_SUBSCRIBER - ? "Pro" - : profileFlags.IS_BASIC_SUBSCRIBER - ? "Basic" - : "Free"} - -  tier. Click on the Manage Subscription button below to - change your plan.  -
-
- - Note: You will be needed to login with a link that is sent - to your email. - -

-

- Logged in as {formData.user_email}. Your - account is managed by your organization,  - {organization?.name}. Please contact your - admin to manage your subscription. -

-
- )} - {process.env.REACT_APP_ENABLE_SUBSCRIPTION_MANAGEMENT === - "true" && } - { + handleUpdate(updateKeys); + }} > - - {process.env.REACT_APP_ENABLE_SUBSCRIPTION_MANAGEMENT === - "true" && ( - - )} - + Update + + - + + + {process.env.REACT_APP_ENABLE_SUBSCRIPTION_MANAGEMENT === + "true" && } + )} - {subscriptionUpdateModalOpen && ( - { - setSubscriptionUpdateModalOpen(false); - }} - userEmail={formData.user_email} - /> - )} ); }; diff --git a/llmstack/processors/providers/promptly/http_api.py b/llmstack/processors/providers/promptly/http_api.py index b438c73ef70..662c764d381 100644 --- a/llmstack/processors/providers/promptly/http_api.py +++ b/llmstack/processors/providers/promptly/http_api.py @@ -156,7 +156,7 @@ def validate_input(cls, values): schema = {'type': 'object', 'properties': {}} required_fields = [] for parameter in values['parameters']: - param_name = f'{parameter.location}_{parameter.name}' + param_name = parameter.name schema['properties'][param_name] = { 'type': 'string', 'description': parameter.description} if parameter.required: @@ -164,7 +164,7 @@ def validate_input(cls, values): if values['request_body']: for parameter in values['request_body'].parameters: - param_name = f'body_{parameter.name}' + param_name = parameter.name schema['properties'][param_name] = { 'type': parameter.type, 'description': parameter.description} if parameter.required: @@ -214,17 +214,25 @@ def process(self): cookies = {} body_data = {} - for param_key in input_json: - if param_key.startswith('path_'): - path_params[param_key[5:]] = input_json[param_key] - elif param_key.startswith('query_'): - query_params[param_key[6:]] = input_json[param_key] - elif param_key.startswith('header_'): - headers[param_key[7:]] = input_json[param_key] - elif param_key.startswith('body_'): - body_data[param_key[5:]] = input_json[param_key] - elif param_key.startswith('cookie_'): - cookies[param_key[7:]] = input_json[param_key] + for parameter in self._config.parameters: + if parameter.name not in input_json: + continue + if parameter.location == ParameterLocation.PATH: + path_params[parameter.name] = input_json[parameter.name] + + if parameter.location == ParameterLocation.QUERY: + query_params[parameter.name] = input_json[parameter.name] + + if parameter.location == ParameterLocation.HEADER: + headers[parameter.name] = input_json[parameter.name] + + if parameter.location == ParameterLocation.COOKIE: + cookies[parameter.name] = input_json[parameter.name] + + for parameter in self._config.request_body.parameters: + if parameter.name not in input_json: + continue + body_data[parameter.name] = input_json[parameter.name] auth = None method = self._config.method