Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
9100e15e
authored
Jun 19, 2026
by
CaIon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add channel sensitive info toggle
parent
4206d7fd
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
129 additions
and
37 deletions
+129
-37
web/default/src/components/data-table/toolbar/toolbar.tsx
+16
-4
web/default/src/features/channels/components/channel-card.tsx
+15
-2
web/default/src/features/channels/components/channels-columns.tsx
+35
-15
web/default/src/features/channels/components/channels-provider.tsx
+5
-0
web/default/src/features/channels/components/channels-table.tsx
+46
-13
web/default/src/features/channels/components/dialogs/codex-usage-dialog.tsx
+12
-3
No files found.
web/default/src/components/data-table/toolbar/toolbar.tsx
View file @
9100e15e
...
@@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
...
@@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
*/
*/
import
*
as
React
from
'react'
import
*
as
React
from
'react'
import
{
useState
,
type
ReactNode
}
from
'react'
import
{
useState
,
type
ReactNode
}
from
'react'
import
{
type
Table
}
from
'@tanstack/react-table'
import
type
{
Table
}
from
'@tanstack/react-table'
import
{
useDebounce
}
from
'@/hooks'
import
{
useDebounce
}
from
'@/hooks'
import
{
ChevronDown
,
Loader2
,
X
as
Cross2Icon
}
from
'lucide-react'
import
{
ChevronDown
,
Loader2
,
X
as
Cross2Icon
}
from
'lucide-react'
import
{
useTranslation
}
from
'react-i18next'
import
{
useTranslation
}
from
'react-i18next'
...
@@ -77,6 +77,11 @@ export type DataTableToolbarProps<TData> = {
...
@@ -77,6 +77,11 @@ export type DataTableToolbarProps<TData> = {
*/
*/
additionalSearch
?:
ReactNode
additionalSearch
?:
ReactNode
/**
/**
* Extra controls displayed immediately after the filter chips, before the
* right-aligned action cluster.
*/
afterFilters
?:
ReactNode
/**
* Whether non-table filters (e.g. `additionalSearch` or `expandable`
* Whether non-table filters (e.g. `additionalSearch` or `expandable`
* inputs) are currently active. Controls Reset button visibility
* inputs) are currently active. Controls Reset button visibility
* when no column filters are set.
* when no column filters are set.
...
@@ -282,11 +287,15 @@ export function DataTableToolbar<TData>(props: DataTableToolbarProps<TData>) {
...
@@ -282,11 +287,15 @@ export function DataTableToolbar<TData>(props: DataTableToolbarProps<TData>) {
// Reset: outline text-only for form mode (always visible, disabled when
// Reset: outline text-only for form mode (always visible, disabled when
// nothing to reset); ghost text + X for filter-as-you-type mode (only
// nothing to reset); ghost text + X for filter-as-you-type mode (only
// visible when active filters exist).
// visible when active filters exist).
const
resetButton
=
hasSearch
?
(
let
resetButton
:
ReactNode
=
null
if
(
hasSearch
)
{
resetButton
=
(
<
Button
variant=
'outline'
onClick=
{
handleReset
}
disabled=
{
!
isFiltered
}
>
<
Button
variant=
'outline'
onClick=
{
handleReset
}
disabled=
{
!
isFiltered
}
>
{
t
(
'Reset'
)
}
{
t
(
'Reset'
)
}
</
Button
>
</
Button
>
)
:
isFiltered
?
(
)
}
else
if
(
isFiltered
)
{
resetButton
=
(
<
Button
<
Button
variant=
'ghost'
variant=
'ghost'
onClick=
{
handleReset
}
onClick=
{
handleReset
}
...
@@ -295,7 +304,8 @@ export function DataTableToolbar<TData>(props: DataTableToolbarProps<TData>) {
...
@@ -295,7 +304,8 @@ export function DataTableToolbar<TData>(props: DataTableToolbarProps<TData>) {
{
t
(
'Reset'
)
}
{
t
(
'Reset'
)
}
<
Cross2Icon
/>
<
Cross2Icon
/>
</
Button
>
</
Button
>
)
:
null
)
}
const
searchButton
=
hasSearch
?
(
const
searchButton
=
hasSearch
?
(
<
Button
onClick=
{
props
.
onSearch
}
disabled=
{
props
.
searchLoading
}
>
<
Button
onClick=
{
props
.
onSearch
}
disabled=
{
props
.
searchLoading
}
>
...
@@ -341,6 +351,7 @@ export function DataTableToolbar<TData>(props: DataTableToolbarProps<TData>) {
...
@@ -341,6 +351,7 @@ export function DataTableToolbar<TData>(props: DataTableToolbarProps<TData>) {
{
props
.
customSearch
!==
undefined
?
props
.
customSearch
:
searchInput
}
{
props
.
customSearch
!==
undefined
?
props
.
customSearch
:
searchInput
}
{
props
.
additionalSearch
}
{
props
.
additionalSearch
}
{
filterChips
}
{
filterChips
}
{
props
.
afterFilters
}
<
div
className=
'ms-auto flex shrink-0 items-center gap-1.5 sm:gap-2'
>
<
div
className=
'ms-auto flex shrink-0 items-center gap-1.5 sm:gap-2'
>
{
expandToggle
}
{
expandToggle
}
</
div
>
</
div
>
...
@@ -376,6 +387,7 @@ export function DataTableToolbar<TData>(props: DataTableToolbarProps<TData>) {
...
@@ -376,6 +387,7 @@ export function DataTableToolbar<TData>(props: DataTableToolbarProps<TData>) {
{
props
.
customSearch
!==
undefined
?
props
.
customSearch
:
searchInput
}
{
props
.
customSearch
!==
undefined
?
props
.
customSearch
:
searchInput
}
{
props
.
additionalSearch
}
{
props
.
additionalSearch
}
{
filterChips
}
{
filterChips
}
{
props
.
afterFilters
}
{
expanded
&&
hasExpandable
&&
props
.
expandable
}
{
expanded
&&
hasExpandable
&&
props
.
expandable
}
<
div
className=
'ms-auto flex shrink-0 items-center gap-1.5 sm:gap-2'
>
<
div
className=
'ms-auto flex shrink-0 items-center gap-1.5 sm:gap-2'
>
...
...
web/default/src/features/channels/components/channel-card.tsx
View file @
9100e15e
...
@@ -24,6 +24,9 @@ import { CHANNEL_STATUS } from '../constants'
...
@@ -24,6 +24,9 @@ import { CHANNEL_STATUS } from '../constants'
import
{
isTagAggregateRow
,
parseGroupsList
}
from
'../lib'
import
{
isTagAggregateRow
,
parseGroupsList
}
from
'../lib'
import
type
{
Channel
}
from
'../types'
import
type
{
Channel
}
from
'../types'
import
{
ChannelRowActionsLayoutContext
}
from
'./channel-row-actions-context'
import
{
ChannelRowActionsLayoutContext
}
from
'./channel-row-actions-context'
import
{
useChannels
}
from
'./channels-provider'
const
SENSITIVE_MASK
=
'••••'
/**
/**
* Bespoke channel card for the card view. Reuses every column's existing cell
* Bespoke channel card for the card view. Reuses every column's existing cell
...
@@ -35,6 +38,7 @@ import { ChannelRowActionsLayoutContext } from './channel-row-actions-context'
...
@@ -35,6 +38,7 @@ import { ChannelRowActionsLayoutContext } from './channel-row-actions-context'
*/
*/
export
function
ChannelCard
({
row
}:
{
row
:
Row
<
Channel
>
})
{
export
function
ChannelCard
({
row
}:
{
row
:
Row
<
Channel
>
})
{
const
{
t
}
=
useTranslation
()
const
{
t
}
=
useTranslation
()
const
{
sensitiveVisible
}
=
useChannels
()
const
isTagRow
=
isTagAggregateRow
(
row
.
original
)
const
isTagRow
=
isTagAggregateRow
(
row
.
original
)
const
cells
=
row
.
getAllCells
()
const
cells
=
row
.
getAllCells
()
...
@@ -99,7 +103,11 @@ export function ChannelCard({ row }: { row: Row<Channel> }) {
...
@@ -99,7 +103,11 @@ export function ChannelCard({ row }: { row: Row<Channel> }) {
{
/* Left column */
}
{
/* Left column */
}
<
div
className=
'flex min-w-0 flex-1 flex-col gap-3 overflow-hidden'
>
<
div
className=
'flex min-w-0 flex-1 flex-col gap-3 overflow-hidden'
>
<
div
className=
'min-w-0 text-sm'
>
<
div
className=
'min-w-0 text-sm'
>
{
!
isTagRow
&&
<
div
className=
{
labelClass
}
>
#
{
row
.
original
.
id
}
</
div
>
}
{
!
isTagRow
&&
(
<
div
className=
{
labelClass
}
>
#
{
sensitiveVisible
?
row
.
original
.
id
:
SENSITIVE_MASK
}
</
div
>
)
}
{
nameCell
}
{
nameCell
}
</
div
>
</
div
>
<
div
className=
'min-w-0'
>
<
div
className=
'min-w-0'
>
...
@@ -138,7 +146,12 @@ export function ChannelCard({ row }: { row: Row<Channel> }) {
...
@@ -138,7 +146,12 @@ export function ChannelCard({ row }: { row: Row<Channel> }) {
{
groups
.
length
>
0
?
(
{
groups
.
length
>
0
?
(
<
div
className=
'-ml-1.5 flex flex-wrap gap-1'
>
<
div
className=
'-ml-1.5 flex flex-wrap gap-1'
>
{
groups
.
map
((
g
)
=>
(
{
groups
.
map
((
g
)
=>
(
<
GroupBadge
key=
{
g
}
group=
{
g
}
size=
'sm'
/>
<
GroupBadge
key=
{
g
}
group=
{
g
}
label=
{
sensitiveVisible
?
undefined
:
SENSITIVE_MASK
}
size=
'sm'
/>
))
}
))
}
</
div
>
</
div
>
)
:
(
)
:
(
...
...
web/default/src/features/channels/components/channels-columns.tsx
View file @
9100e15e
...
@@ -285,6 +285,7 @@ function WeightCell({ channel }: { channel: Channel }) {
...
@@ -285,6 +285,7 @@ function WeightCell({ channel }: { channel: Channel }) {
* notation (e.g. "$28万"); the precise value stays available in the tooltip.
* notation (e.g. "$28万"); the precise value stays available in the tooltip.
*/
*/
const
MAX_INLINE_BALANCE_CHARS
=
8
const
MAX_INLINE_BALANCE_CHARS
=
8
const
SENSITIVE_MASK
=
'••••'
/**
/**
* Balance cell component with click to update
* Balance cell component with click to update
...
@@ -292,6 +293,7 @@ const MAX_INLINE_BALANCE_CHARS = 8
...
@@ -292,6 +293,7 @@ const MAX_INLINE_BALANCE_CHARS = 8
function
BalanceCell
({
channel
}:
{
channel
:
Channel
})
{
function
BalanceCell
({
channel
}:
{
channel
:
Channel
})
{
const
{
t
,
i18n
}
=
useTranslation
()
const
{
t
,
i18n
}
=
useTranslation
()
const
queryClient
=
useQueryClient
()
const
queryClient
=
useQueryClient
()
const
{
sensitiveVisible
}
=
useChannels
()
const
isTagRow
=
isTagAggregateRow
(
channel
)
const
isTagRow
=
isTagAggregateRow
(
channel
)
const
balance
=
channel
.
balance
||
0
const
balance
=
channel
.
balance
||
0
const
usedQuota
=
channel
.
used_quota
||
0
const
usedQuota
=
channel
.
used_quota
||
0
...
@@ -320,6 +322,8 @@ function BalanceCell({ channel }: { channel: Channel }) {
...
@@ -320,6 +322,8 @@ function BalanceCell({ channel }: { channel: Channel }) {
:
remainingFull
:
remainingFull
const
usedLabel
=
`
${
t
(
'Used:'
)}
${
usedFull
}
`
const
usedLabel
=
`
${
t
(
'Used:'
)}
${
usedFull
}
`
const
remainingLabel
=
`
${
t
(
'Remaining:'
)}
${
remainingFull
}
`
const
remainingLabel
=
`
${
t
(
'Remaining:'
)}
${
remainingFull
}
`
const
maskedUsedLabel
=
`
${
t
(
'Used:'
)}
${
SENSITIVE_MASK
}
`
const
maskedRemainingLabel
=
`
${
t
(
'Remaining:'
)}
${
SENSITIVE_MASK
}
`
// Tag row: only show cumulative used quota
// Tag row: only show cumulative used quota
if
(
isTagRow
)
{
if
(
isTagRow
)
{
...
@@ -329,7 +333,11 @@ function BalanceCell({ channel }: { channel: Channel }) {
...
@@ -329,7 +333,11 @@ function BalanceCell({ channel }: { channel: Channel }) {
<
TooltipTrigger
<
TooltipTrigger
render=
{
render=
{
<
StatusBadge
<
StatusBadge
label=
{
`${t('Used:')} ${usedDisplay}`
}
label=
{
sensitiveVisible
?
`${t('Used:')} ${usedDisplay}`
:
maskedUsedLabel
}
variant=
'neutral'
variant=
'neutral'
size=
'sm'
size=
'sm'
copyable=
{
false
}
copyable=
{
false
}
...
@@ -339,7 +347,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
...
@@ -339,7 +347,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
}
}
/>
/>
<
TooltipContent
>
<
TooltipContent
>
<
p
>
{
u
sedLabel
}
</
p
>
<
p
>
{
sensitiveVisible
?
usedLabel
:
maskedU
sedLabel
}
</
p
>
</
TooltipContent
>
</
TooltipContent
>
</
Tooltip
>
</
Tooltip
>
</
TooltipProvider
>
</
TooltipProvider
>
...
@@ -376,12 +384,20 @@ function BalanceCell({ channel }: { channel: Channel }) {
...
@@ -376,12 +384,20 @@ function BalanceCell({ channel }: { channel: Channel }) {
await
handleUpdateChannelBalance
(
channel
.
id
,
queryClient
)
await
handleUpdateChannelBalance
(
channel
.
id
,
queryClient
)
setIsUpdating
(
false
)
setIsUpdating
(
false
)
}
}
let
remainingBadgeLabel
=
remainingDisplay
let
remainingBadgeLabel
=
sensitiveVisible
if
(
isUpdating
)
{
?
remainingDisplay
:
SENSITIVE_MASK
if
(
sensitiveVisible
&&
isUpdating
)
{
remainingBadgeLabel
=
t
(
'Updating...'
)
remainingBadgeLabel
=
t
(
'Updating...'
)
}
else
if
(
channel
.
type
===
57
)
{
}
else
if
(
sensitiveVisible
&&
channel
.
type
===
57
)
{
remainingBadgeLabel
=
t
(
'Account Info'
)
remainingBadgeLabel
=
t
(
'Account Info'
)
}
}
let
remainingTooltipLabel
=
remainingLabel
if
(
!
sensitiveVisible
)
{
remainingTooltipLabel
=
maskedRemainingLabel
}
else
if
(
channel
.
type
===
57
)
{
remainingTooltipLabel
=
t
(
'Click to view Codex usage'
)
}
let
remainingBadgeVariant
:
StatusBadgeProps
[
'variant'
]
=
variant
let
remainingBadgeVariant
:
StatusBadgeProps
[
'variant'
]
=
variant
if
(
channel
.
type
===
57
)
{
if
(
channel
.
type
===
57
)
{
remainingBadgeVariant
=
'info'
remainingBadgeVariant
=
'info'
...
@@ -396,7 +412,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
...
@@ -396,7 +412,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
<
TooltipTrigger
<
TooltipTrigger
render=
{
render=
{
<
StatusBadge
<
StatusBadge
label=
{
usedDisplay
}
label=
{
sensitiveVisible
?
usedDisplay
:
SENSITIVE_MASK
}
variant=
'neutral'
variant=
'neutral'
size=
'sm'
size=
'sm'
copyable=
{
false
}
copyable=
{
false
}
...
@@ -406,7 +422,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
...
@@ -406,7 +422,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
}
}
/>
/>
<
TooltipContent
>
<
TooltipContent
>
<
p
>
{
u
sedLabel
}
</
p
>
<
p
>
{
sensitiveVisible
?
usedLabel
:
maskedU
sedLabel
}
</
p
>
</
TooltipContent
>
</
TooltipContent
>
</
Tooltip
>
</
Tooltip
>
<
Tooltip
>
<
Tooltip
>
...
@@ -424,11 +440,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
...
@@ -424,11 +440,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
}
}
/>
/>
<
TooltipContent
>
<
TooltipContent
>
<
p
>
<
p
>
{
remainingTooltipLabel
}
</
p
>
{
channel
.
type
===
57
?
t
(
'Click to view Codex usage'
)
:
remainingLabel
}
</
p
>
{
channel
.
type
!==
57
&&
<
p
>
{
t
(
'Click to update balance'
)
}
</
p
>
}
{
channel
.
type
!==
57
&&
<
p
>
{
t
(
'Click to update balance'
)
}
</
p
>
}
</
TooltipContent
>
</
TooltipContent
>
</
Tooltip
>
</
Tooltip
>
...
@@ -439,6 +451,8 @@ function BalanceCell({ channel }: { channel: Channel }) {
...
@@ -439,6 +451,8 @@ function BalanceCell({ channel }: { channel: Channel }) {
onOpenChange=
{
setCodexUsageOpen
}
onOpenChange=
{
setCodexUsageOpen
}
channelName=
{
channel
.
name
}
channelName=
{
channel
.
name
}
channelId=
{
channel
.
id
}
channelId=
{
channel
.
id
}
channelDisplayName=
{
sensitiveVisible
?
undefined
:
SENSITIVE_MASK
}
channelDisplayId=
{
sensitiveVisible
?
undefined
:
SENSITIVE_MASK
}
response=
{
codexUsageResponse
}
response=
{
codexUsageResponse
}
onRefresh=
{
async
()
=>
{
onRefresh=
{
async
()
=>
{
if
(
isUpdating
)
{
if
(
isUpdating
)
{
...
@@ -472,6 +486,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
...
@@ -472,6 +486,7 @@ function BalanceCell({ channel }: { channel: Channel }) {
*/
*/
export
function
useChannelsColumns
():
ColumnDef
<
Channel
>
[]
{
export
function
useChannelsColumns
():
ColumnDef
<
Channel
>
[]
{
const
{
t
,
i18n
}
=
useTranslation
()
const
{
t
,
i18n
}
=
useTranslation
()
const
{
sensitiveVisible
}
=
useChannels
()
const
locale
=
i18n
.
resolvedLanguage
||
i18n
.
language
const
locale
=
i18n
.
resolvedLanguage
||
i18n
.
language
return
[
return
[
// Checkbox column
// Checkbox column
...
@@ -513,7 +528,7 @@ export function useChannelsColumns(): ColumnDef<Channel>[] {
...
@@ -513,7 +528,7 @@ export function useChannelsColumns(): ColumnDef<Channel>[] {
meta
:
{
mobileHidden
:
true
},
meta
:
{
mobileHidden
:
true
},
cell
:
({
row
})
=>
{
cell
:
({
row
})
=>
{
const
id
=
row
.
getValue
(
'id'
)
as
number
const
id
=
row
.
getValue
(
'id'
)
as
number
return
<
TableId
value=
{
id
}
/>
return
<
TableId
value=
{
sensitiveVisible
?
id
:
SENSITIVE_MASK
}
/>
},
},
size
:
80
,
size
:
80
,
},
},
...
@@ -570,7 +585,7 @@ export function useChannelsColumns(): ColumnDef<Channel>[] {
...
@@ -570,7 +585,7 @@ export function useChannelsColumns(): ColumnDef<Channel>[] {
<
div
className=
'flex flex-col gap-1'
>
<
div
className=
'flex flex-col gap-1'
>
<
div
className=
'flex items-center gap-1.5'
>
<
div
className=
'flex items-center gap-1.5'
>
<
TruncatedText
<
TruncatedText
text=
{
name
}
text=
{
sensitiveVisible
?
name
:
SENSITIVE_MASK
}
className=
'font-medium'
className=
'font-medium'
maxWidth=
'max-w-[180px]'
maxWidth=
'max-w-[180px]'
/>
/>
...
@@ -929,7 +944,12 @@ export function useChannelsColumns(): ColumnDef<Channel>[] {
...
@@ -929,7 +944,12 @@ export function useChannelsColumns(): ColumnDef<Channel>[] {
return
(
return
(
<
BadgeListCell
<
BadgeListCell
items=
{
groupArray
.
map
((
g
)
=>
(
items=
{
groupArray
.
map
((
g
)
=>
(
<
GroupBadge
key=
{
g
}
group=
{
g
}
size=
'sm'
/>
<
GroupBadge
key=
{
g
}
group=
{
g
}
label=
{
sensitiveVisible
?
undefined
:
SENSITIVE_MASK
}
size=
'sm'
/>
))
}
))
}
/>
/>
)
)
...
...
web/default/src/features/channels/components/channels-provider.tsx
View file @
9100e15e
...
@@ -53,6 +53,8 @@ type ChannelsContextType = {
...
@@ -53,6 +53,8 @@ type ChannelsContextType = {
setEnableTagMode
:
(
enabled
:
boolean
)
=>
void
setEnableTagMode
:
(
enabled
:
boolean
)
=>
void
idSort
:
boolean
idSort
:
boolean
setIdSort
:
(
enabled
:
boolean
)
=>
void
setIdSort
:
(
enabled
:
boolean
)
=>
void
sensitiveVisible
:
boolean
setSensitiveVisible
:
(
visible
:
boolean
)
=>
void
upstream
:
UpstreamUpdateState
upstream
:
UpstreamUpdateState
}
}
...
@@ -78,6 +80,7 @@ export function ChannelsProvider({ children }: { children: React.ReactNode }) {
...
@@ -78,6 +80,7 @@ export function ChannelsProvider({ children }: { children: React.ReactNode }) {
const
[
idSort
,
setIdSort
]
=
useState
(()
=>
{
const
[
idSort
,
setIdSort
]
=
useState
(()
=>
{
return
localStorage
.
getItem
(
'channels-id-sort'
)
===
'true'
return
localStorage
.
getItem
(
'channels-id-sort'
)
===
'true'
})
})
const
[
sensitiveVisible
,
setSensitiveVisible
]
=
useState
(
true
)
const
queryClient
=
useQueryClient
()
const
queryClient
=
useQueryClient
()
const
refreshChannels
=
useCallback
(
async
()
=>
{
const
refreshChannels
=
useCallback
(
async
()
=>
{
...
@@ -98,6 +101,8 @@ export function ChannelsProvider({ children }: { children: React.ReactNode }) {
...
@@ -98,6 +101,8 @@ export function ChannelsProvider({ children }: { children: React.ReactNode }) {
setEnableTagMode
,
setEnableTagMode
,
idSort
,
idSort
,
setIdSort
,
setIdSort
,
sensitiveVisible
,
setSensitiveVisible
,
upstream
,
upstream
,
}
}
}
}
>
>
...
...
web/default/src/features/channels/components/channels-table.tsx
View file @
9100e15e
...
@@ -19,17 +19,20 @@ For commercial licensing, please contact support@quantumnous.com
...
@@ -19,17 +19,20 @@ For commercial licensing, please contact support@quantumnous.com
import
{
useState
,
useMemo
}
from
'react'
import
{
useState
,
useMemo
}
from
'react'
import
{
useQuery
}
from
'@tanstack/react-query'
import
{
useQuery
}
from
'@tanstack/react-query'
import
{
getRouteApi
}
from
'@tanstack/react-router'
import
{
getRouteApi
}
from
'@tanstack/react-router'
import
{
import
type
{
OnChangeFn
,
SortingState
,
Row
}
from
'@tanstack/react-table'
type
OnChangeFn
,
import
{
Eye
,
EyeOff
}
from
'lucide-react'
type
SortingState
,
type
Row
,
}
from
'@tanstack/react-table'
import
{
useMediaQuery
}
from
'@/hooks'
import
{
useMediaQuery
}
from
'@/hooks'
import
{
useTranslation
}
from
'react-i18next'
import
{
useTranslation
}
from
'react-i18next'
import
{
getLobeIcon
}
from
'@/lib/lobe-icon'
import
{
getLobeIcon
}
from
'@/lib/lobe-icon'
import
{
useTableUrlState
}
from
'@/hooks/use-table-url-state'
import
{
useTableUrlState
}
from
'@/hooks/use-table-url-state'
import
{
Button
}
from
'@/components/ui/button'
import
{
Input
}
from
'@/components/ui/input'
import
{
Input
}
from
'@/components/ui/input'
import
{
import
{
Tooltip
,
TooltipContent
,
TooltipTrigger
,
}
from
'@/components/ui/tooltip'
import
{
DISABLED_ROW_DESKTOP
,
DISABLED_ROW_DESKTOP
,
DISABLED_ROW_MOBILE
,
DISABLED_ROW_MOBILE
,
DataTablePage
,
DataTablePage
,
...
@@ -77,7 +80,12 @@ function isDisabledChannelRow(channel: Channel) {
...
@@ -77,7 +80,12 @@ function isDisabledChannelRow(channel: Channel) {
export
function
ChannelsTable
()
{
export
function
ChannelsTable
()
{
const
{
t
}
=
useTranslation
()
const
{
t
}
=
useTranslation
()
const
{
enableTagMode
,
idSort
}
=
useChannels
()
const
{
enableTagMode
,
idSort
,
sensitiveVisible
,
setSensitiveVisible
,
}
=
useChannels
()
const
isMobile
=
useMediaQuery
(
'(max-width: 640px)'
)
const
isMobile
=
useMediaQuery
(
'(max-width: 640px)'
)
// Table state
// Table state
...
@@ -343,7 +351,10 @@ export function ChannelsTable() {
...
@@ -343,7 +351,10 @@ export function ChannelsTable() {
const
groupFilterOptions
=
[
const
groupFilterOptions
=
[
{
label
:
t
(
'All Groups'
),
value
:
'all'
},
{
label
:
t
(
'All Groups'
),
value
:
'all'
},
...
groupOptions
,
...
groupOptions
.
map
((
option
)
=>
({
...
option
,
label
:
sensitiveVisible
?
option
.
label
:
'••••'
,
})),
]
]
return
(
return
(
...
@@ -398,14 +409,36 @@ export function ChannelsTable() {
...
@@ -398,14 +409,36 @@ export function ChannelsTable() {
singleSelect
:
true
,
singleSelect
:
true
,
},
},
],
],
afterFilters
:
(
<
Tooltip
>
<
TooltipTrigger
render=
{
<
Button
variant=
'ghost'
size=
'icon'
onClick=
{
()
=>
setSensitiveVisible
(
!
sensitiveVisible
)
}
aria
-
label=
{
sensitiveVisible
?
t
(
'Hide'
)
:
t
(
'Show'
)
}
className=
'text-muted-foreground hover:text-foreground size-8'
/>
}
>
{
sensitiveVisible
?
<
Eye
/>
:
<
EyeOff
/>
}
</
TooltipTrigger
>
<
TooltipContent
>
{
sensitiveVisible
?
t
(
'Hide'
)
:
t
(
'Show'
)
}
</
TooltipContent
>
</
Tooltip
>
),
}
}
}
}
getRowClassName=
{
(
row
,
{
isMobile
})
=>
getRowClassName=
{
(
row
,
{
isMobile
})
=>
{
isDisabledChannelRow
(
row
.
original
)
if
(
!
isDisabledChannelRow
(
row
.
original
))
{
?
isMobile
return
undefined
?
DISABLED_ROW_MOBILE
:
DISABLED_ROW_DESKTOP
:
undefined
}
}
if
(
isMobile
)
{
return
DISABLED_ROW_MOBILE
}
return
DISABLED_ROW_DESKTOP
}
}
bulkActions=
{
<
DataTableBulkActions
table=
{
table
}
/>
}
bulkActions=
{
<
DataTableBulkActions
table=
{
table
}
/>
}
/>
/>
)
)
...
...
web/default/src/features/channels/components/dialogs/codex-usage-dialog.tsx
View file @
9100e15e
...
@@ -139,6 +139,8 @@ type CodexUsageDialogProps = {
...
@@ -139,6 +139,8 @@ type CodexUsageDialogProps = {
onOpenChange
:
(
open
:
boolean
)
=>
void
onOpenChange
:
(
open
:
boolean
)
=>
void
channelName
?:
string
channelName
?:
string
channelId
?:
number
channelId
?:
number
channelDisplayName
?:
string
channelDisplayId
?:
string
response
:
CodexUsageDialogData
|
null
response
:
CodexUsageDialogData
|
null
onRefresh
?:
()
=>
void
|
Promise
<
void
>
onRefresh
?:
()
=>
void
|
Promise
<
void
>
isRefreshing
?:
boolean
isRefreshing
?:
boolean
...
@@ -885,6 +887,8 @@ export function CodexUsageDialog({
...
@@ -885,6 +887,8 @@ export function CodexUsageDialog({
onOpenChange
,
onOpenChange
,
channelName
,
channelName
,
channelId
,
channelId
,
channelDisplayName
,
channelDisplayId
,
response
,
response
,
onRefresh
,
onRefresh
,
isRefreshing
,
isRefreshing
,
...
@@ -931,9 +935,14 @@ export function CodexUsageDialog({
...
@@ -931,9 +935,14 @@ export function CodexUsageDialog({
?
String
(
resetCredits
)
?
String
(
resetCredits
)
:
'-'
:
'-'
const
canResetCodexUsage
=
Number
(
resetCredits
)
>
0
const
canResetCodexUsage
=
Number
(
resetCredits
)
>
0
const
channelLabel
=
`
${
channelName
||
'-'
}${
const
channelLabelName
=
channelDisplayName
??
channelName
??
'-'
channelId
?
` (#
${
channelId
}
)`
:
''
let
channelLabelId
=
''
}
`
if
(
channelDisplayId
!=
null
)
{
channelLabelId
=
` (#
${
channelDisplayId
}
)`
}
else
if
(
channelId
)
{
channelLabelId
=
` (#
${
channelId
}
)`
}
const
channelLabel
=
`
${
channelLabelName
}${
channelLabelId
}
`
const
{
fiveHourWindow
,
weeklyWindow
}
=
resolveRateLimitWindows
(
payload
)
const
{
fiveHourWindow
,
weeklyWindow
}
=
resolveRateLimitWindows
(
payload
)
const
errorMessage
=
const
errorMessage
=
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment