From 77d31575920eefc90ed4df09d7e2ff646c3b289f Mon Sep 17 00:00:00 2001
From: QuentinHsu
Date: Thu, 4 Jun 2026 17:22:50 +0800
Subject: [PATCH] fix(model-pricing): commit visual pricing drafts on save
- Commit the open visual editor draft before saving model pricing settings
- Show unsaved draft differences against persisted model pricing values
- Move model pricing actions into the editor toolbar and refine the visual editor layout
---
.../models/model-pricing-sheet.tsx | 452 +++++++---------
.../models/model-ratio-form.tsx | 51 +-
.../models/model-ratio-visual-editor.tsx | 511 +++++++++++-------
.../models/ratio-settings-card.tsx | 8 +
web/default/src/i18n/locales/en.json | 2 +
web/default/src/i18n/locales/fr.json | 2 +
web/default/src/i18n/locales/ja.json | 2 +
web/default/src/i18n/locales/ru.json | 2 +
web/default/src/i18n/locales/vi.json | 2 +
web/default/src/i18n/locales/zh.json | 2 +
10 files changed, 561 insertions(+), 473 deletions(-)
diff --git a/web/default/src/features/system-settings/models/model-pricing-sheet.tsx b/web/default/src/features/system-settings/models/model-pricing-sheet.tsx
index f35afb80..ab0ac72e 100644
--- a/web/default/src/features/system-settings/models/model-pricing-sheet.tsx
+++ b/web/default/src/features/system-settings/models/model-pricing-sheet.tsx
@@ -27,17 +27,10 @@ import {
import * as z from 'zod'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
-import { AlertTriangle, ChevronDown } from 'lucide-react'
+import { AlertTriangle } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import { cn } from '@/lib/utils'
import { Alert, AlertDescription } from '@/components/ui/alert'
-import { Badge } from '@/components/ui/badge'
-import { Button } from '@/components/ui/button'
-import {
- Collapsible,
- CollapsibleContent,
- CollapsibleTrigger,
-} from '@/components/ui/collapsible'
import {
Field,
FieldDescription,
@@ -63,15 +56,11 @@ import {
Sheet,
SheetContent,
SheetDescription,
- SheetFooter,
SheetHeader,
SheetTitle,
} from '@/components/ui/sheet'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
-import {
- sideDrawerContentClassName,
- sideDrawerFooterClassName,
-} from '@/components/drawer-layout'
+import { sideDrawerContentClassName } from '@/components/drawer-layout'
import { combineBillingExpr } from '@/features/pricing/lib/billing-expr'
import {
SettingsControlGroup,
@@ -124,10 +113,7 @@ export type ModelRatioData = {
type ModelPricingSheetProps = {
open: boolean
onOpenChange: (open: boolean) => void
- onSave: (data: ModelRatioData) => void
- onCancel?: () => void
editData?: ModelRatioData | null
- selectedTargetCount?: number
}
type ModelPricingEditorPanelProps = Omit<
@@ -284,20 +270,6 @@ function createInitialLaneState(data?: ModelRatioData | null) {
}
}
-function getModeLabel(mode: PricingMode) {
- if (mode === 'per-request') return 'Per-request'
- if (mode === 'tiered_expr') return 'Expression'
- return 'Per-token'
-}
-
-function getModeBadgeVariant(
- mode: PricingMode
-): 'default' | 'secondary' | 'outline' {
- if (mode === 'per-request') return 'secondary'
- if (mode === 'tiered_expr') return 'default'
- return 'outline'
-}
-
function buildPreviewRows(
values: ModelPricingFormValues,
mode: PricingMode,
@@ -391,10 +363,7 @@ function buildPreviewRows(
export const ModelPricingSheet = forwardRef<
ModelPricingEditorPanelHandle,
ModelPricingSheetProps
->(function ModelPricingSheet(
- { open, onOpenChange, onSave, onCancel, editData, selectedTargetCount = 0 },
- ref
-) {
+>(function ModelPricingSheet({ open, onOpenChange, editData }, ref) {
const { t } = useTranslation()
const title = editData ? t('Edit model pricing') : t('Add model pricing')
const description = editData?.name || t('New model')
@@ -411,13 +380,7 @@ export const ModelPricingSheet = forwardRef<
{
- onCancel?.()
- onOpenChange(false)
- }}
className='h-full rounded-none border-0'
/>
@@ -428,10 +391,7 @@ export const ModelPricingSheet = forwardRef<
export const ModelPricingEditorPanel = forwardRef<
ModelPricingEditorPanelHandle,
ModelPricingEditorPanelProps
->(function ModelPricingEditorPanel(
- { onSave, editData, selectedTargetCount = 0, onCancel, className },
- ref
-) {
+>(function ModelPricingEditorPanel({ editData, className }, ref) {
const { t } = useTranslation()
const [pricingMode, setPricingMode] = useState('per-token')
const [promptPrice, setPromptPrice] = useState('')
@@ -443,7 +403,6 @@ export const ModelPricingEditorPanel = forwardRef<
})
const [billingExpr, setBillingExpr] = useState('')
const [requestRuleExpr, setRequestRuleExpr] = useState('')
- const [previewOpen, setPreviewOpen] = useState(true)
const isEditMode = !!editData
const form = useForm({
@@ -505,7 +464,6 @@ export const ModelPricingEditorPanel = forwardRef<
setPromptPrice(nextLaneState.promptPrice)
setLanePrices(nextLaneState.prices)
setLaneEnabled(nextLaneState.enabled)
- setPreviewOpen(true)
}, [editData, form])
const setFormValue = (field: keyof ModelPricingFormValues, value: string) => {
@@ -763,15 +721,6 @@ export const ModelPricingEditorPanel = forwardRef<
[form, validatePricingValues, buildSubmitData]
)
- const handleSubmit = (values: ModelPricingFormValues) => {
- if (!validatePricingValues()) return
-
- const data = buildSubmitData(values)
- onSave(data)
- form.reset()
- onCancel?.()
- }
-
const activeName = watchedValues.name || editData?.name || t('New model')
return (
@@ -791,232 +740,197 @@ export const ModelPricingEditorPanel = forwardRef<
{activeName}
-
- {t(getModeLabel(pricingMode))}
-