Co-authored-by: Joel <iamjoel007@gmail.com>tags/0.5.3
| from .workspace import account, members, model_providers, models, tool_providers, workspace | from .workspace import account, members, model_providers, models, tool_providers, workspace | ||||
| # Import billing controllers | # Import billing controllers | ||||
| from .billing import billing | from .billing import billing | ||||
| # Import operation controllers | |||||
| from .operation import operation |
| from services.feature_service import FeatureService | from services.feature_service import FeatureService | ||||
| from . import api | from . import api | ||||
| from .wraps import cloud_utm_record | |||||
| class FeatureApi(Resource): | class FeatureApi(Resource): | ||||
| @cloud_utm_record | |||||
| def get(self): | def get(self): | ||||
| return FeatureService.get_features(current_user.current_tenant_id).dict() | return FeatureService.get_features(current_user.current_tenant_id).dict() | ||||
| from flask_login import current_user | |||||
| from flask_restful import Resource, reqparse | |||||
| from controllers.console import api | |||||
| from controllers.console.setup import setup_required | |||||
| from controllers.console.wraps import account_initialization_required, only_edition_cloud | |||||
| from libs.login import login_required | |||||
| from services.operation_service import OperationService | |||||
| class TenantUtm(Resource): | |||||
| @setup_required | |||||
| @login_required | |||||
| @account_initialization_required | |||||
| @only_edition_cloud | |||||
| def post(self): | |||||
| parser = reqparse.RequestParser() | |||||
| parser.add_argument('utm_source', type=str, required=True) | |||||
| parser.add_argument('utm_medium', type=str, required=True) | |||||
| parser.add_argument('utm_campaign', type=str, required=False, default='') | |||||
| parser.add_argument('utm_content', type=str, required=False, default='') | |||||
| parser.add_argument('utm_term', type=str, required=False, default='') | |||||
| args = parser.parse_args() | |||||
| return OperationService.record_utm(current_user.current_tenant_id, args) | |||||
| api.add_resource(TenantUtm, '/operation/utm') |
| # -*- coding:utf-8 -*- | # -*- coding:utf-8 -*- | ||||
| import json | |||||
| from functools import wraps | from functools import wraps | ||||
| from flask import request | |||||
| from controllers.console.workspace.error import AccountNotInitializedError | from controllers.console.workspace.error import AccountNotInitializedError | ||||
| from flask import abort, current_app | from flask import abort, current_app | ||||
| from flask_login import current_user | from flask_login import current_user | ||||
| from services.feature_service import FeatureService | from services.feature_service import FeatureService | ||||
| from services.operation_service import OperationService | |||||
| def account_initialization_required(view): | def account_initialization_required(view): | ||||
| return decorated | return decorated | ||||
| return interceptor | return interceptor | ||||
| def cloud_utm_record(view): | |||||
| @wraps(view) | |||||
| def decorated(*args, **kwargs): | |||||
| try: | |||||
| features = FeatureService.get_features(current_user.current_tenant_id) | |||||
| if features.billing.enabled: | |||||
| utm_info = request.cookies.get('utm_info') | |||||
| if utm_info: | |||||
| utm_info = json.loads(utm_info) | |||||
| OperationService.record_utm(current_user.current_tenant_id, utm_info) | |||||
| except Exception as e: | |||||
| pass | |||||
| return view(*args, **kwargs) | |||||
| return decorated |
| return response.json() | return response.json() | ||||
| @classmethod | @classmethod | ||||
| def record_utm(cls, tenant_id, args): | |||||
| def record_utm(cls, tenant_id: str, utm_info: dict): | |||||
| params = { | params = { | ||||
| 'tenant_id': tenant_id, | 'tenant_id': tenant_id, | ||||
| 'utm_source': args['utm_source'], | |||||
| 'utm_medium': args['utm_medium'], | |||||
| 'utm_campaign': args['utm_campaign'], | |||||
| 'utm_content': args['utm_content'], | |||||
| 'utm_term': args['utm_term'] | |||||
| 'utm_source': utm_info.get('utm_source', ''), | |||||
| 'utm_medium': utm_info.get('utm_medium', ''), | |||||
| 'utm_campaign': utm_info.get('utm_campaign', ''), | |||||
| 'utm_content': utm_info.get('utm_content', ''), | |||||
| 'utm_term': utm_info.get('utm_term', '') | |||||
| } | } | ||||
| return cls._send_request('POST', '/tenant_utms', params=params) | return cls._send_request('POST', '/tenant_utms', params=params) |
| const searchParams = useSearchParams() | const searchParams = useSearchParams() | ||||
| const consoleToken = searchParams.get('console_token') | const consoleToken = searchParams.get('console_token') | ||||
| const consoleTokenFromLocalStorage = localStorage?.getItem('console_token') | const consoleTokenFromLocalStorage = localStorage?.getItem('console_token') | ||||
| const utm = { | |||||
| utm_source: searchParams.get('utm_source') || '', | |||||
| utm_medium: searchParams.get('utm_medium') || '', | |||||
| utm_campaign: searchParams.get('utm_campaign') || '', | |||||
| utm_content: searchParams.get('utm_content') || '', | |||||
| utm_term: searchParams.get('utm_term') || '', | |||||
| } | |||||
| localStorage?.setItem('utm', JSON.stringify(utm)) | |||||
| const [init, setInit] = useState(false) | const [init, setInit] = useState(false) | ||||
| useEffect(() => { | useEffect(() => { |
| fetchModelList, | fetchModelList, | ||||
| fetchModelProviders, | fetchModelProviders, | ||||
| fetchSupportRetrievalMethods, | fetchSupportRetrievalMethods, | ||||
| operationUtm, | |||||
| } from '@/service/common' | } from '@/service/common' | ||||
| import { | import { | ||||
| ModelFeatureEnum, | ModelFeatureEnum, | ||||
| const [isFetchedPlan, setIsFetchedPlan] = useState(false) | const [isFetchedPlan, setIsFetchedPlan] = useState(false) | ||||
| const [enableBilling, setEnableBilling] = useState(true) | const [enableBilling, setEnableBilling] = useState(true) | ||||
| const [enableReplaceWebAppLogo, setEnableReplaceWebAppLogo] = useState(false) | const [enableReplaceWebAppLogo, setEnableReplaceWebAppLogo] = useState(false) | ||||
| const handleOperateUtm = () => { | |||||
| let utm | |||||
| try { | |||||
| utm = JSON.parse(localStorage?.getItem('utm') || '{}') | |||||
| } | |||||
| catch (e) { | |||||
| utm = { | |||||
| utm_source: '', | |||||
| utm_medium: '', | |||||
| utm_campaign: '', | |||||
| utm_content: '', | |||||
| utm_term: '', | |||||
| } | |||||
| } | |||||
| if (utm.utm_source || utm.utm_medium || utm.utm_campaign || utm.utm_content || utm.utm_term) | |||||
| operationUtm({ url: '/operation/utm', body: utm }) | |||||
| } | |||||
| const fetchPlan = async () => { | const fetchPlan = async () => { | ||||
| const data = await fetchCurrentPlanInfo() | const data = await fetchCurrentPlanInfo() | ||||
| const enabled = data.billing.enabled | const enabled = data.billing.enabled | ||||
| setEnableReplaceWebAppLogo(data.can_replace_logo) | setEnableReplaceWebAppLogo(data.can_replace_logo) | ||||
| if (enabled) { | if (enabled) { | ||||
| setPlan(parseCurrentPlan(data)) | setPlan(parseCurrentPlan(data)) | ||||
| handleOperateUtm() | |||||
| setIsFetchedPlan(true) | setIsFetchedPlan(true) | ||||
| } | } | ||||
| } | } |
| text: string | text: string | ||||
| } | } | ||||
| ) => Promise<ModerateResponse> | ) => Promise<ModerateResponse> | ||||
| export type Utm = { | |||||
| utm_source?: string | |||||
| utm_medium?: string | |||||
| utm_campaign?: string | |||||
| utm_term?: string | |||||
| utm_content?: string | |||||
| } |
| ProviderAzureToken, | ProviderAzureToken, | ||||
| SetupStatusResponse, | SetupStatusResponse, | ||||
| UserProfileOriginResponse, | UserProfileOriginResponse, | ||||
| Utm, | |||||
| } from '@/models/common' | } from '@/models/common' | ||||
| import type { | import type { | ||||
| UpdateOpenAIKeyResponse, | UpdateOpenAIKeyResponse, | ||||
| export const fetchSupportRetrievalMethods: Fetcher<RetrievalMethodsRes, string> = (url) => { | export const fetchSupportRetrievalMethods: Fetcher<RetrievalMethodsRes, string> = (url) => { | ||||
| return get<RetrievalMethodsRes>(url) | return get<RetrievalMethodsRes>(url) | ||||
| } | } | ||||
| export const operationUtm: Fetcher<CommonResponse, { url: string; body: Utm }> = ({ url, body }) => { | |||||
| return post(url, { body }) as Promise<CommonResponse> | |||||
| } |