feat(schema-workflow): Phase 1b — SchemaDraftDrawer with status-aware actions
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useQuery, queryOptions } from '@tanstack/react-query'
|
||||
import axios from 'axios'
|
||||
import {
|
||||
apiClient,
|
||||
type AuditFilters,
|
||||
@@ -6,6 +7,8 @@ import {
|
||||
type CascadePlan,
|
||||
type ChangelogDiff,
|
||||
type ChangelogResponse,
|
||||
type SchemaDraft,
|
||||
type SchemaReviewQueuePage,
|
||||
type DictionaryDefinition,
|
||||
type DictionaryDetail,
|
||||
type DlqPage,
|
||||
@@ -192,6 +195,100 @@ export const useChangelogDiff = (
|
||||
enabled: Boolean(dictionaryName) && Boolean(entryId),
|
||||
})
|
||||
|
||||
// === Schema workflow drafts (Phase 1a) ================================
|
||||
|
||||
/**
|
||||
* Active schema draft на словаре, если есть. Backend возвращает 404
|
||||
* {@code no_active_draft} когда нет non-terminal draft'а — мы маппим
|
||||
* это в null чтобы UI рендерил «no draft» state без error toast'а.
|
||||
*
|
||||
* <p>refetchInterval=20s — banner должен быстро отражать «отправили
|
||||
* на ревью» / «approved» transition от другого пользователя.
|
||||
*/
|
||||
export const dictActiveSchemaDraftQuery = (dictName: string) =>
|
||||
queryOptions({
|
||||
queryKey: ['schema-draft-active', dictName] as const,
|
||||
queryFn: async (): Promise<SchemaDraft | null> => {
|
||||
try {
|
||||
const { data } = await apiClient.get<SchemaDraft>(
|
||||
`/dictionaries/${dictName}/drafts/active`,
|
||||
)
|
||||
return data
|
||||
} catch (err) {
|
||||
// 404 no_active_draft — это not-an-error, отдаём null.
|
||||
if (axios.isAxiosError(err) && err.response?.status === 404) {
|
||||
return null
|
||||
}
|
||||
throw err
|
||||
}
|
||||
},
|
||||
refetchInterval: 20_000,
|
||||
})
|
||||
|
||||
export const useDictActiveSchemaDraft = (dictName: string | undefined) =>
|
||||
useQuery({
|
||||
...dictActiveSchemaDraftQuery(dictName ?? ''),
|
||||
enabled: Boolean(dictName),
|
||||
})
|
||||
|
||||
/** History всех schema drafts на словаре (для admin audit / settings tab). */
|
||||
export const dictSchemaDraftsQuery = (dictName: string) =>
|
||||
queryOptions({
|
||||
queryKey: ['schema-drafts', dictName] as const,
|
||||
queryFn: async (): Promise<SchemaDraft[]> => {
|
||||
const { data } = await apiClient.get<SchemaDraft[]>(
|
||||
`/dictionaries/${dictName}/drafts`,
|
||||
)
|
||||
return data
|
||||
},
|
||||
})
|
||||
|
||||
export const useDictSchemaDrafts = (dictName: string | undefined) =>
|
||||
useQuery({
|
||||
...dictSchemaDraftsQuery(dictName ?? ''),
|
||||
enabled: Boolean(dictName),
|
||||
})
|
||||
|
||||
/** Single draft drill-in (decision modal, deep-link). */
|
||||
export const schemaDraftQuery = (dictName: string, draftId: string) =>
|
||||
queryOptions({
|
||||
queryKey: ['schema-draft', dictName, draftId] as const,
|
||||
queryFn: async (): Promise<SchemaDraft> => {
|
||||
const { data } = await apiClient.get<SchemaDraft>(
|
||||
`/dictionaries/${dictName}/drafts/${draftId}`,
|
||||
)
|
||||
return data
|
||||
},
|
||||
})
|
||||
|
||||
export const useSchemaDraft = (
|
||||
dictName: string | undefined,
|
||||
draftId: string | undefined,
|
||||
) =>
|
||||
useQuery({
|
||||
...schemaDraftQuery(dictName ?? '', draftId ?? ''),
|
||||
enabled: Boolean(dictName) && Boolean(draftId),
|
||||
})
|
||||
|
||||
/**
|
||||
* Global pool queue для approvers — все review_pending drafts.
|
||||
* Backend response: {items, page, size, total}.
|
||||
*/
|
||||
export const schemaReviewQueueQuery = (page = 0, size = 50) =>
|
||||
queryOptions({
|
||||
queryKey: ['schema-review-queue', page, size] as const,
|
||||
queryFn: async (): Promise<SchemaReviewQueuePage> => {
|
||||
const { data } = await apiClient.get<SchemaReviewQueuePage>(
|
||||
'/admin/schema-reviews/pending',
|
||||
{ params: { page, size } },
|
||||
)
|
||||
return data
|
||||
},
|
||||
})
|
||||
|
||||
export const useSchemaReviewQueue = (page = 0, size = 50) =>
|
||||
useQuery(schemaReviewQueueQuery(page, size))
|
||||
|
||||
export const recordRawQuery = (dictionaryName: string, businessKey: string) =>
|
||||
queryOptions({
|
||||
queryKey: ['record-raw', dictionaryName, businessKey] as const,
|
||||
|
||||
Reference in New Issue
Block a user