Fix OAuth token import and table filters

This commit is contained in:
fawney19
2026-05-01 02:14:49 +08:00
parent 9570e5c2c1
commit 4fc7cecf30
54 changed files with 3160 additions and 727 deletions

View File

@@ -37,6 +37,8 @@ describe('poolManagementState', () => {
status: 'cooldown',
page: 5,
pageSize: 20,
sortBy: 'last_used_at',
sortOrder: 'asc',
},
storage,
)
@@ -48,6 +50,8 @@ describe('poolManagementState', () => {
status: 'inactive',
page: '3',
pageSize: '100',
sortBy: 'imported_at',
sortOrder: 'desc',
},
storage,
)
@@ -58,6 +62,8 @@ describe('poolManagementState', () => {
status: 'inactive',
page: 3,
pageSize: 100,
sortBy: 'imported_at',
sortOrder: 'desc',
})
})
@@ -69,6 +75,8 @@ describe('poolManagementState', () => {
status: 'active',
page: 2,
pageSize: 50,
sortBy: 'last_used_at',
sortOrder: 'asc',
},
storage,
)
@@ -81,6 +89,8 @@ describe('poolManagementState', () => {
status: 'active',
page: 2,
pageSize: 50,
sortBy: 'last_used_at',
sortOrder: 'asc',
})
})
@@ -92,6 +102,8 @@ describe('poolManagementState', () => {
status: 'all',
page: 1,
pageSize: 50,
sortBy: null,
sortOrder: 'desc',
}),
).toEqual({
providerId: 'provider-d',
@@ -99,6 +111,25 @@ describe('poolManagementState', () => {
status: undefined,
page: undefined,
pageSize: undefined,
sortBy: undefined,
sortOrder: undefined,
})
})
it('keeps sortable column state in query patch', () => {
expect(
buildPoolManagementQueryPatch({
providerId: 'provider-e',
search: '',
status: 'all',
page: 1,
pageSize: 50,
sortBy: 'last_used_at',
sortOrder: 'asc',
}),
).toMatchObject({
sortBy: 'last_used_at',
sortOrder: 'asc',
})
})

View File

@@ -54,4 +54,14 @@ describe('poolMobilePresentation', () => {
overflow: [],
})
})
it('can show a disabled refresh action even when refresh is not available', () => {
expect(
splitPoolMobileActions({
canDownloadOrCopy: true,
canRefreshToken: false,
showRefreshToken: true,
}).primary,
).toContain('refresh_token')
})
})

View File

@@ -1,4 +1,6 @@
export type PoolManagementStatus = 'all' | 'active' | 'cooldown' | 'inactive'
export type PoolManagementSortBy = 'imported_at' | 'last_used_at'
export type PoolManagementSortOrder = 'asc' | 'desc'
export interface PoolManagementViewState {
providerId: string | null
@@ -6,6 +8,8 @@ export interface PoolManagementViewState {
status: PoolManagementStatus
page: number
pageSize: number
sortBy: PoolManagementSortBy | null
sortOrder: PoolManagementSortOrder
}
export interface PoolManagementStateSource {
@@ -14,6 +18,8 @@ export interface PoolManagementStateSource {
status?: string
page?: string
pageSize?: string
sortBy?: string
sortOrder?: string
}
export interface StorageLike {
@@ -30,6 +36,8 @@ export const DEFAULT_POOL_MANAGEMENT_VIEW_STATE: PoolManagementViewState = {
status: 'all',
page: 1,
pageSize: 50,
sortBy: null,
sortOrder: 'desc',
}
function normalizeProviderId(value: unknown): string | null {
@@ -56,6 +64,17 @@ function normalizePositiveInteger(value: unknown, fallback: number): number {
return normalized
}
function normalizeSortBy(value: unknown): PoolManagementSortBy | null {
if (value === 'imported_at' || value === 'last_used_at') {
return value
}
return null
}
function normalizeSortOrder(value: unknown): PoolManagementSortOrder {
return value === 'asc' ? 'asc' : 'desc'
}
function normalizeViewState(input: Partial<PoolManagementViewState>): PoolManagementViewState {
return {
providerId: normalizeProviderId(input.providerId),
@@ -63,6 +82,8 @@ function normalizeViewState(input: Partial<PoolManagementViewState>): PoolManage
status: normalizeStatus(input.status),
page: normalizePositiveInteger(input.page, DEFAULT_POOL_MANAGEMENT_VIEW_STATE.page),
pageSize: normalizePositiveInteger(input.pageSize, DEFAULT_POOL_MANAGEMENT_VIEW_STATE.pageSize),
sortBy: normalizeSortBy(input.sortBy),
sortOrder: normalizeSortOrder(input.sortOrder),
}
}
@@ -91,6 +112,8 @@ export function readPoolManagementViewState(
status: source.status ?? stored.status,
page: source.page ?? stored.page,
pageSize: source.pageSize ?? stored.pageSize,
sortBy: source.sortBy ?? stored.sortBy,
sortOrder: source.sortOrder ?? stored.sortOrder,
})
}
@@ -125,6 +148,8 @@ export function buildPoolManagementQueryPatch(
normalized.pageSize === DEFAULT_POOL_MANAGEMENT_VIEW_STATE.pageSize
? undefined
: String(normalized.pageSize),
sortBy: normalized.sortBy || undefined,
sortOrder: normalized.sortBy ? normalized.sortOrder : undefined,
}
}

View File

@@ -32,6 +32,7 @@ export type PoolMobileActionId =
export interface PoolMobileActionInput {
canDownloadOrCopy?: boolean
canRefreshToken?: boolean
showRefreshToken?: boolean
canClearCooldown?: boolean
canRecoverHealth?: boolean
hasProxy?: boolean
@@ -62,9 +63,11 @@ export function splitPoolMobileActions(input: PoolMobileActionInput): {
primary: PoolMobileActionId[]
overflow: PoolMobileActionId[]
} {
const showRefreshToken = input.showRefreshToken ?? input.canRefreshToken
if (input.canDownloadOrCopy) {
const primary: PoolMobileActionId[] = ['copy_or_download']
if (input.canRefreshToken) {
if (showRefreshToken) {
primary.push('refresh_token')
}
if (input.canClearCooldown) {
@@ -86,7 +89,7 @@ export function splitPoolMobileActions(input: PoolMobileActionInput): {
}
const primary: PoolMobileActionId[] = []
if (input.canRefreshToken) {
if (showRefreshToken) {
primary.push('refresh_token')
}
if (input.canClearCooldown) {