Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions web/default/src/components/data-table/core/data-table-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,4 @@ function DataTableRowInner<TData>({
)
}

export const DataTableRow = React.memo(DataTableRowInner, (prev, next) => {
// Skip re-render when only the getColumnClassName reference changed but the
// row identity and selection state are the same — callers rarely stabilize
// this callback, so excluding it from comparison avoids unnecessary renders.
return (
prev.row === next.row &&
prev.className === next.className &&
prev.row.getIsSelected() === next.row.getIsSelected()
)
}) as typeof DataTableRowInner
export const DataTableRow = DataTableRowInner

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

经过多次排查,这里的缓存会导致同步渠道中的复选框无法被选中,底层数据已经选中但是UI不会得到更新,尝试通过添加更新的逻辑条件,会导致更新选中状态时页面闪烁。

2 changes: 1 addition & 1 deletion web/default/src/components/layout/components/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ export function Footer(props: FooterProps) {
{displayColumns.map((column, index) => (
<div key={index}>
<p className='text-muted-foreground/50 mb-3 text-xs font-medium tracking-wider uppercase'>
{t(column.title)}
{column.title}
</p>
<ul className='space-y-2.5'>
{column.links.map((link, linkIndex) => (
Expand Down
10 changes: 5 additions & 5 deletions web/default/src/components/layout/components/public-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export function PublicHeader(props: PublicHeaderProps) {
}
setAuthPromptSecondsLeft(AUTH_PROMPT_SECONDS)
setAuthPromptTarget({
title: t(link.title),
title: link.title,
href: link.href,
})
return
Expand Down Expand Up @@ -231,7 +231,7 @@ export function PublicHeader(props: PublicHeaderProps) {
link.disabled && 'pointer-events-none opacity-50'
)}
>
{t(link.title)}
{link.title}
</a>
)
}
Expand All @@ -249,7 +249,7 @@ export function PublicHeader(props: PublicHeaderProps) {
link.disabled && 'pointer-events-none opacity-50'
)}
>
{t(link.title)}
{link.title}
</Link>
)
})}
Expand Down Expand Up @@ -372,7 +372,7 @@ export function PublicHeader(props: PublicHeaderProps) {
className={linkClassName}
style={transitionStyle}
>
{t(link.title)}
{link.title}
</a>
)
}
Expand All @@ -385,7 +385,7 @@ export function PublicHeader(props: PublicHeaderProps) {
className={linkClassName}
style={transitionStyle}
>
{t(link.title)}
{link.title}
</Link>
)
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,17 +203,15 @@ export const ModelRatioForm = memo(function ModelRatioForm({
<RotateCcw data-icon='inline-start' />
{t('Reset prices')}
</Button>
{editMode === 'json' && (
<Button
type='button'
size='sm'
onClick={handleSave}
disabled={isSaving}
>
<Save data-icon='inline-start' />
{isSaving ? t('Saving...') : t('Save model prices')}
</Button>
)}
<Button
type='button'
size='sm'
onClick={handleSave}
disabled={isSaving}
>
<Save data-icon='inline-start' />
{isSaving ? t('Saving...') : t('Save model prices')}
</Button>
<Button variant='outline' size='sm' onClick={toggleEditMode}>
{editMode === 'visual' ? (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.

For commercial licensing, please contact support@quantumnous.com
*/
import { useState } from 'react'
import { type ColumnDef } from '@tanstack/react-table'
import { Pencil, Trash2 } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Checkbox } from '@/components/ui/checkbox'
import { DataTableColumnHeader } from '@/components/data-table'
import { StatusBadge } from '@/components/status-badge'
import { ConfirmDialog } from '@/components/confirm-dialog'
import {
getModeLabel,
getModeVariant,
Expand All @@ -38,10 +40,54 @@ const filterBySelectedValues = (
return filterValue.includes(String(rowValue))
}

type Translate = (key: string, options?: Record<string, unknown>) => string

type BuildModelRatioColumnsOptions = {
onDelete: (name: string) => void
onEdit: (model: ModelRow) => void
t: (key: string) => string
t: Translate
}

function DeleteButton({
modelName,
onDelete,
t,
}: {
modelName: string
onDelete: (name: string) => void
t: Translate
}) {
const [confirmOpen, setConfirmOpen] = useState(false)

return (
<>
<Button
variant='ghost'
size='sm'
onClick={(e) => {
e.stopPropagation()
setConfirmOpen(true)
}}
>
<Trash2 />
</Button>
Comment on lines +64 to +73

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add accessible names to icon-only action buttons.

At Line 64 and Line 194, the icon-only delete/edit buttons have no accessible name. Add aria-label (localized) so assistive tech users can discover and operate these controls.

Proposed fix
       <Button
         variant='ghost'
         size='sm'
+        aria-label={t('Delete model pricing')}
         onClick={(e) => {
           e.stopPropagation()
           setConfirmOpen(true)
         }}
       >
         <Trash2 />
       </Button>
@@
           <Button
             variant='ghost'
             size='sm'
+            aria-label={t('Edit model pricing')}
             onClick={(e) => {
               e.stopPropagation()
               onEdit(row.original)
             }}
           >
             <Pencil />
           </Button>

As per coding guidelines: “Ensure keyboard operability and logical focus order; use ARIA attributes when necessary (aria-label, aria-expanded, aria-hidden)…”.

Also applies to: 194-203

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@web/default/src/features/system-settings/models/model-ratio-table-columns.tsx`
around lines 64 - 73, The Button component at lines 64-73 containing only the
Trash2 icon lacks an accessible name for screen reader users. Add a localized
aria-label attribute to this delete button to provide an accessible description.
The same issue also applies to the edit/action button at lines 194-203, which
similarly needs an aria-label attribute added. Both icon-only buttons should
include aria-label with appropriate localized text describing their actions to
comply with accessibility guidelines.

Source: Coding guidelines

<ConfirmDialog
open={confirmOpen}
onOpenChange={setConfirmOpen}
title={t('Delete model pricing')}
desc={t(
'Are you sure you want to delete pricing for "{{name}}"? This action cannot be undone.',
{ name: modelName }
)}
confirmText={t('Delete')}
destructive
handleConfirm={() => {
onDelete(modelName)
setConfirmOpen(false)
}}
Comment on lines +84 to +87
/>
</>
)
}

export function buildModelRatioColumns({
Expand Down Expand Up @@ -148,17 +194,18 @@ export function buildModelRatioColumns({
<Button
variant='ghost'
size='sm'
onClick={() => onEdit(row.original)}
onClick={(e) => {
e.stopPropagation()
onEdit(row.original)
}}
>
<Pencil />
</Button>
<Button
variant='ghost'
size='sm'
onClick={() => onDelete(row.original.name)}
>
<Trash2 />
</Button>
<DeleteButton
modelName={row.original.name}
onDelete={onDelete}
t={t}
/>
</div>
),
enableHiding: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ const ModelRatioVisualEditorComponent = forwardRef<
.map((name) => {
const saved = savedByName.get(name)
const draft = draftByName.get(name)
const displayed = saved ?? draft
const displayed = draft ?? saved
const savedSignature = getSnapshotSignature(saved)
const draftSignature = getSnapshotSignature(draft)

Expand All @@ -225,6 +225,7 @@ const ModelRatioVisualEditorComponent = forwardRef<
isDraftNew: Boolean(!saved && draft),
}
})
.filter((row) => !row.isDraftDeleted)
.sort((a, b) => a.name.localeCompare(b.name))
}, [
savedModelPrice,
Expand Down
2 changes: 2 additions & 0 deletions web/default/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@
"Are you sure you want to delete {{count}} model(s)? This action cannot be undone.": "Are you sure you want to delete {{count}} model(s)? This action cannot be undone.",
"Are you sure you want to delete all auto-disabled keys? This action cannot be undone.": "Are you sure you want to delete all auto-disabled keys? This action cannot be undone.",
"Are you sure you want to delete deployment \"{{name}}\"? This action cannot be undone.": "Are you sure you want to delete deployment \"{{name}}\"? This action cannot be undone.",
"Are you sure you want to delete pricing for \"{{name}}\"? This action cannot be undone.": "Are you sure you want to delete pricing for \"{{name}}\"? This action cannot be undone.",
"Are you sure you want to delete this key? This action cannot be undone.": "Are you sure you want to delete this key? This action cannot be undone.",
"Are you sure you want to disable all enabled keys?": "Are you sure you want to disable all enabled keys?",
"Are you sure you want to enable all keys?": "Are you sure you want to enable all keys?",
Expand Down Expand Up @@ -1160,6 +1161,7 @@
"Delete logs": "Delete logs",
"Delete mapping": "Delete mapping",
"Delete Model": "Delete Model",
"Delete model pricing": "Delete model pricing",
"Delete Models?": "Delete Models?",
"Delete Provider": "Delete Provider",
"Delete Request Header": "Delete Request Header",
Expand Down
2 changes: 2 additions & 0 deletions web/default/src/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@
"Are you sure you want to delete {{count}} model(s)? This action cannot be undone.": "Êtes-vous sûr de vouloir supprimer {{count}} modèle(s) ? Cette action ne peut pas être annulée.",
"Are you sure you want to delete all auto-disabled keys? This action cannot be undone.": "Êtes-vous sûr de vouloir supprimer toutes les clés automatiquement désactivées ? Cette action ne peut pas être annulée.",
"Are you sure you want to delete deployment \"{{name}}\"? This action cannot be undone.": "Êtes-vous sûr de vouloir supprimer le déploiement \"{{name}}\" ? Cette action est irréversible.",
"Are you sure you want to delete pricing for \"{{name}}\"? This action cannot be undone.": "Êtes-vous sûr de vouloir supprimer la tarification pour \"{{name}}\" ? Cette action est irréversible.",
"Are you sure you want to delete this key? This action cannot be undone.": "Êtes-vous sûr de vouloir supprimer cette clé ? Cette action ne peut pas être annulée.",
"Are you sure you want to disable all enabled keys?": "Êtes-vous sûr de vouloir désactiver toutes les clés activées ?",
"Are you sure you want to enable all keys?": "Êtes-vous sûr de vouloir activer toutes les clés ?",
Expand Down Expand Up @@ -1160,6 +1161,7 @@
"Delete logs": "Supprimer les journaux",
"Delete mapping": "Supprimer le mappage",
"Delete Model": "Supprimer le modèle",
"Delete model pricing": "Supprimer la tarification du modèle",
"Delete Models?": "Supprimer les modèles ?",
"Delete Provider": "Supprimer le fournisseur",
"Delete Request Header": "Supprimer un en-tête de requête",
Expand Down
2 changes: 2 additions & 0 deletions web/default/src/i18n/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@
"Are you sure you want to delete {{count}} model(s)? This action cannot be undone.": "{{count}} 個のモデルを削除してもよろしいですか?この操作は元に戻せません。",
"Are you sure you want to delete all auto-disabled keys? This action cannot be undone.": "すべての自動無効化されたキーを削除してもよろしいですか?この操作は元に戻せません。",
"Are you sure you want to delete deployment \"{{name}}\"? This action cannot be undone.": "デプロイ \"{{name}}\" を削除してもよろしいですか?この操作は元に戻せません。",
"Are you sure you want to delete pricing for \"{{name}}\"? This action cannot be undone.": "モデル \"{{name}}\" の価格を削除してもよろしいですか?この操作は元に戻せません。",
"Are you sure you want to delete this key? This action cannot be undone.": "このキーを削除してもよろしいですか?この操作は元に戻せません。",
"Are you sure you want to disable all enabled keys?": "すべての有効なキーを無効にすることをよろしいですか?",
"Are you sure you want to enable all keys?": "すべてのキーを有効にすることをよろしいですか?",
Expand Down Expand Up @@ -1160,6 +1161,7 @@
"Delete logs": "ログを削除",
"Delete mapping": "マッピングを削除",
"Delete Model": "モデルを削除",
"Delete model pricing": "モデル価格を削除",
"Delete Models?": "モデルを削除しますか?",
"Delete Provider": "プロバイダーを削除",
"Delete Request Header": "リクエストヘッダーを削除",
Expand Down
2 changes: 2 additions & 0 deletions web/default/src/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@
"Are you sure you want to delete {{count}} model(s)? This action cannot be undone.": "Вы уверены, что хотите удалить {{count}} модел(ей)? Это действие нельзя отменить.",
"Are you sure you want to delete all auto-disabled keys? This action cannot be undone.": "Вы уверены, что хотите удалить все автоматически отключённые ключи? Это действие нельзя отменить.",
"Are you sure you want to delete deployment \"{{name}}\"? This action cannot be undone.": "Вы уверены, что хотите удалить развертывание \"{{name}}\"? Это действие нельзя отменить.",
"Are you sure you want to delete pricing for \"{{name}}\"? This action cannot be undone.": "Вы уверены, что хотите удалить цену для \"{{name}}\"? Это действие нельзя отменить.",
"Are you sure you want to delete this key? This action cannot be undone.": "Вы уверены, что хотите удалить этот ключ? Это действие нельзя отменить.",
"Are you sure you want to disable all enabled keys?": "Вы уверены, что хотите отключить все включённые ключи?",
"Are you sure you want to enable all keys?": "Вы уверены, что хотите включить все ключи?",
Expand Down Expand Up @@ -1160,6 +1161,7 @@
"Delete logs": "Удалить логи",
"Delete mapping": "Удалить сопоставление",
"Delete Model": "Удалить модель",
"Delete model pricing": "Удалить цену модели",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use the same Russian pricing term here.

Add model pricing and Edit model pricing already use «тариф», but this new key says «цена модели». Keeping the wording consistent will make the pricing UI read more naturally.

💡 Suggested wording
-    "Delete model pricing": "Удалить цену модели",
+    "Delete model pricing": "Удалить тариф модели",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Delete model pricing": "Удалить цену модели",
"Delete model pricing": "Удалить тариф модели",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/default/src/i18n/locales/ru.json` at line 1164, The Russian translation
for the "Delete model pricing" key uses inconsistent terminology. The related
keys "Add model pricing" and "Edit model pricing" already use the term «тариф»
(tariff/plan), but this new key uses «цена модели» (model price). Replace «цена
модели» with «тариф» in the translation value for "Delete model pricing" to
maintain consistent terminology across all pricing-related strings in the
Russian locale file.

"Delete Models?": "Удалить модели?",
"Delete Provider": "Удалить провайдер",
"Delete Request Header": "Удалить заголовок запроса",
Expand Down
2 changes: 2 additions & 0 deletions web/default/src/i18n/locales/vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@
"Are you sure you want to delete {{count}} model(s)? This action cannot be undone.": "Bạn có chắc muốn xóa {{count}} mô hình không? Hành động này không thể hoàn tác.",
"Are you sure you want to delete all auto-disabled keys? This action cannot be undone.": "Bạn có chắc chắn muốn xóa tất cả các khóa bị tắt tự động? Hành động này không thể hoàn tác.",
"Are you sure you want to delete deployment \"{{name}}\"? This action cannot be undone.": "Bạn có chắc muốn xóa triển khai \"{{name}}\" không? Hành động này không thể hoàn tác.",
"Are you sure you want to delete pricing for \"{{name}}\"? This action cannot be undone.": "Bạn có chắc muốn xóa giá cho \"{{name}}\" không? Hành động này không thể hoàn tác.",
"Are you sure you want to delete this key? This action cannot be undone.": "Bạn có chắc chắn muốn xóa khóa này? Hành động này không thể hoàn tác.",
"Are you sure you want to disable all enabled keys?": "Bạn có chắc chắn muốn vô hiệu hóa tất cả các khóa đang bật không?",
"Are you sure you want to enable all keys?": "Bạn có chắc chắn muốn bật tất cả các khóa không?",
Expand Down Expand Up @@ -1160,6 +1161,7 @@
"Delete logs": "Xóa nhật ký",
"Delete mapping": "Xóa ánh xạ",
"Delete Model": "Xóa Mô hình",
"Delete model pricing": "Xóa giá mô hình",
"Delete Models?": "Xóa mô hình?",
"Delete Provider": "Xóa nhà cung cấp",
"Delete Request Header": "Xóa header yêu cầu",
Expand Down
2 changes: 2 additions & 0 deletions web/default/src/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@
"Are you sure you want to delete {{count}} model(s)? This action cannot be undone.": "您确定要删除 {{count}} 个模型吗?此操作无法撤销。",
"Are you sure you want to delete all auto-disabled keys? This action cannot be undone.": "您确定要删除所有自动禁用的密钥吗?此操作无法撤销。",
"Are you sure you want to delete deployment \"{{name}}\"? This action cannot be undone.": "确定要删除部署 \"{{name}}\" 吗?此操作不可撤销。",
"Are you sure you want to delete pricing for \"{{name}}\"? This action cannot be undone.": "确定要删除模型 \"{{name}}\" 的定价吗?此操作不可撤销。",
"Are you sure you want to delete this key? This action cannot be undone.": "您确定要删除此密钥吗?此操作无法撤销。",
"Are you sure you want to disable all enabled keys?": "您确定要禁用所有已启用的密钥吗?",
"Are you sure you want to enable all keys?": "您确定要启用所有密钥吗?",
Expand Down Expand Up @@ -1160,6 +1161,7 @@
"Delete logs": "删除日志",
"Delete mapping": "删除映射",
"Delete Model": "删除模型",
"Delete model pricing": "删除模型定价",
"Delete Models?": "删除模型?",
"Delete Provider": "删除提供商",
"Delete Request Header": "删除请求头",
Expand Down