mirror of
https://github.com/iflytek/skillhub.git
synced 2026-11-14 09:01:16 +00:00
fix(web): refresh removed owner state on resubmission
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
parent
1826fa6768
commit
87d922896b
3 changed files with 10 additions and 9 deletions
|
|
@ -5,11 +5,11 @@
|
|||
|
||||
## 2. 服务端与界面
|
||||
|
||||
- [ ] 统一当前所有者读取与成员维护权限,保留管理员独立授权。
|
||||
- [ ] 修正移除后写入口及旧旁路,补齐所有者列表、详情和受控下载读取。
|
||||
- [ ] 保留已有审核申请与现有账号停用/恢复行为。
|
||||
- [ ] 管理页面明确只读状态;如有契约变更,同步 OpenAPI 与生成类型。
|
||||
- [ ] 更新现有领域模型和用户文档中过时的成员移除/所有者权限说明,不新增转让或接管功能。
|
||||
- [x] 统一当前所有者读取与成员维护权限,保留管理员独立授权。
|
||||
- [x] 修正移除后写入口及旧旁路,补齐所有者列表、详情和受控下载读取。
|
||||
- [x] 保留已有审核申请与现有账号停用/恢复行为。
|
||||
- [x] 管理页面明确只读状态;如有契约变更,同步 OpenAPI 与生成类型。
|
||||
- [x] 更新现有领域模型和用户文档中过时的成员移除/所有者权限说明,不新增转让或接管功能。
|
||||
|
||||
## 3. 验证和交付
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|||
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
const api = vi.hoisted(() => ({ detail: vi.fn(), publish: vi.fn(), navigate: vi.fn() }))
|
||||
const api = vi.hoisted(() => ({ detail: vi.fn(), publish: vi.fn(), navigate: vi.fn(), search: {} as { namespace?: string; updateSkill?: string; resubmitSkill?: string; resubmitVersion?: string } }))
|
||||
vi.mock('@/api/client', async () => ({
|
||||
...await vi.importActual<typeof import('@/api/client')>('@/api/client'),
|
||||
fetchJson: api.detail,
|
||||
|
|
@ -14,7 +14,7 @@ vi.mock('@/shared/hooks/use-skill-queries', async () => ({
|
|||
previewSkillPackage: vi.fn().mockResolvedValue({ name: 'foo', displayName: 'Foo', version: '1.1' }),
|
||||
usePublishSkill: () => ({ mutateAsync: api.publish, isPending: false }),
|
||||
}))
|
||||
vi.mock('@tanstack/react-router', () => ({ useNavigate: () => api.navigate, useSearch: () => ({ namespace: 'team', updateSkill: 'foo' }) }))
|
||||
vi.mock('@tanstack/react-router', () => ({ useNavigate: () => api.navigate, useSearch: () => api.search }))
|
||||
vi.mock('react-i18next', async () => ({ ...await vi.importActual<typeof import('react-i18next')>('react-i18next'), useTranslation: () => ({ t: (key: string) => key }) }))
|
||||
vi.mock('@/shared/hooks/use-namespace-queries', () => ({ useMyNamespaces: () => ({ data: [{ slug: 'team', displayName: 'Team' }], isLoading: false }) }))
|
||||
vi.mock('@/features/publish/upload-zone', () => ({ UploadZone: ({ onFileSelect }: { onFileSelect: (file: File) => void }) => <button onClick={() => onFileSelect(new File(['zip'], 'skill.zip'))}>choose package</button> }))
|
||||
|
|
@ -27,8 +27,9 @@ import { toast } from '@/shared/lib/toast'
|
|||
|
||||
afterEach(() => { cleanup(); vi.clearAllMocks() })
|
||||
|
||||
describe('package rejection refreshes current update permissions', () => {
|
||||
describe.each(['update', 'resubmit'])('%s package rejection refreshes current permissions', mode => {
|
||||
it.each([true, false])('uses the server ownerReadOnly=%s response after a rejected package', async ownerReadOnly => {
|
||||
api.search = mode === 'update' ? { namespace: 'team', updateSkill: 'foo' } : { namespace: 'team', resubmitSkill: 'foo', resubmitVersion: '1.0' }
|
||||
const client = new QueryClient({ defaultOptions: { queries: { retry: false, staleTime: Infinity } } })
|
||||
api.detail.mockResolvedValueOnce({ ownerReadOnly: false }).mockResolvedValue({ ownerReadOnly })
|
||||
api.publish.mockRejectedValue(new ApiError('Localized package rejection', 400))
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ export function PublishPage() {
|
|||
} catch (error) {
|
||||
// A package rejection may also reflect changed membership. Re-read the
|
||||
// server state instead of inferring permissions from its localized message.
|
||||
if (isUpdate && !avatarOnly && error instanceof ApiError && error.status === 400) {
|
||||
if (updateSlug && !avatarOnly && error instanceof ApiError && error.status === 400) {
|
||||
await queryClient.invalidateQueries({ queryKey: getSkillDetailQueryKey(namespaceSlug, updateSlug ?? '') })
|
||||
}
|
||||
// Avatar-only updates call the API directly rather than a mutation.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue