Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.

Commit 1413356

Browse files
authored
refactor(admin): migrate data layer to V2 API response contract (#1045)
* fix(admin): smoke-test driven API alignment for v2 migration - posts/notes/drafts: switch list sort params to wire-format sort_by/sort_order (snake_case enums) to match server's createPagerSchema; previous camelCase + numeric -1/1 was rejected - manage-posts/notes list views: pass the new sort keys through - webhook create: always send `secret: ''` when the form leaves it blank; server's WebhookSchema requires `z.string()` and the admin form intentionally treats the field as optional - docs/superpowers: capture in-progress React migration specs (status, layout shell, data flow, datatable, list filter bar, recovery banner, rightpane quick edit) so they survive across machines * feat(admin): opt out of implicit response translation via x-skip-translation Admin always edits/manages original records; no admin endpoint consumes translated payloads. Send `x-skip-translation: 1` on every outbound request (shared $api instance plus the raw agent-chat SSE fetch) so the backend ignores browser-implicit Accept-Language and NEXT_LOCALE cookie. Explicit `?lang=xx` query and `x-lang` header remain respected for business filters (enrichment per-locale rows, search index).
1 parent 0bef9b8 commit 1413356

26 files changed

Lines changed: 3880 additions & 116 deletions

apps/admin/src/api/drafts.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import type {
88

99
import { request } from '~/utils/request'
1010

11+
export type DraftSortOrder = 'asc' | 'desc'
12+
1113
export interface GetDraftsParams {
1214
page?: number
1315
size?: number
1416
refType?: DraftRefType
1517
hasRef?: boolean
16-
sortBy?: string
17-
sortOrder?: 1 | -1
18+
sort_by?: string
19+
sort_order?: DraftSortOrder
1820
}
1921

2022
export interface CreateDraftData {

apps/admin/src/api/notes.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,22 @@ import type { NoteModel } from '~/models/note'
33

44
import { request } from '~/utils/request'
55

6+
export type NoteSortKey =
7+
| 'title'
8+
| 'createdAt'
9+
| 'modifiedAt'
10+
| 'weather'
11+
| 'mood'
12+
export type SortOrder = 'asc' | 'desc'
13+
614
export interface GetNotesParams {
715
page?: number
816
size?: number
9-
sortBy?: string
10-
sortOrder?: number
17+
sort_by?: NoteSortKey
18+
sort_order?: SortOrder
19+
/**
20+
* @deprecated backend dropped db_query in v12.10.x pager refactor; param is silently ignored
21+
*/
1122
db_query?: Record<string, boolean>
1223
}
1324

apps/admin/src/api/posts.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ import type { PostModel } from '~/models/post'
33

44
import { request } from '~/utils/request'
55

6+
export type PostSortKey = 'createdAt' | 'modifiedAt' | 'pinAt'
7+
export type SortOrder = 'asc' | 'desc'
8+
69
export interface GetPostsParams {
710
page?: number
811
size?: number
9-
sortBy?: string
10-
sortOrder?: number
12+
sort_by?: PostSortKey
13+
sort_order?: SortOrder
1114
categoryIds?: string[]
1215
}
1316

apps/admin/src/components/editor/rich/agent-chat/composables/use-agent-loop.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ function createAdminTransport(providerId: string): TransportAdapter {
4646
return async (messages, tools, model, signal) => {
4747
const response = await fetch(`${API_URL}/ai/agent/chat`, {
4848
method: 'POST',
49-
headers: { 'Content-Type': 'application/json' },
49+
headers: {
50+
'Content-Type': 'application/json',
51+
'x-skip-translation': '1',
52+
},
5053
credentials: 'include',
5154
body: JSON.stringify({ model, messages, tools, providerId }),
5255
signal,

apps/admin/src/utils/request.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export const $api = ofetch.create({
4040
onRequest({ options }) {
4141
const headers = new Headers(options.headers)
4242
headers.set('x-uuid', _uuid)
43+
headers.set('x-skip-translation', '1')
4344

4445
// GET 请求添加时间戳防缓存
4546
if (options.method?.toUpperCase() === 'GET') {

apps/admin/src/views/extra-features/webhook/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,13 @@ export default defineComponent({
160160
data: submitData,
161161
})
162162
} else {
163-
createMutation.mutate(data as any)
163+
// Server requires `secret` as a string; admin form leaves it optional.
164+
// Default to "" when the user did not provide one so creation succeeds.
165+
const createPayload: Partial<WebhookModel> = {
166+
...data,
167+
secret: data.secret ?? '',
168+
}
169+
createMutation.mutate(createPayload as any)
164170
}
165171
}
166172

apps/admin/src/views/manage-notes/list.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { NButton, NEllipsis, NInput, NPopconfirm, NSpace } from 'naive-ui'
1414
import { computed, defineComponent, reactive, ref, watchEffect } from 'vue'
1515
import { RouterLink } from 'vue-router'
1616
import { toast } from 'vue-sonner'
17+
import type { NoteSortKey } from '~/api/notes'
1718
import type { NoteModel } from '~/models/note'
1819
import type { TableColumns } from 'naive-ui/lib/data-table/src/interface'
1920
import type { PropType } from 'vue'
@@ -225,8 +226,12 @@ export const ManageNoteListView = defineComponent({
225226
return notesApi.getList({
226227
page: params.page,
227228
size: params.size,
228-
sortBy: params.sortBy || undefined,
229-
sortOrder: params.sortOrder || undefined,
229+
...(params.sortBy
230+
? {
231+
sort_by: params.sortBy as NoteSortKey,
232+
sort_order: params.sortOrder === 1 ? 'asc' : 'desc',
233+
}
234+
: {}),
230235
db_query: params.filters?.dbQuery,
231236
}) as Promise<any>
232237
},

apps/admin/src/views/manage-posts/list.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
} from 'vue'
2020
import { RouterLink } from 'vue-router'
2121
import { toast } from 'vue-sonner'
22+
import type { PostSortKey } from '~/api/posts'
2223
import type {
2324
FilterOption,
2425
FilterState,
@@ -206,8 +207,8 @@ export const ManagePostListView = defineComponent({
206207
categoryIds: params.filters?.categoryIds,
207208
...(params.sortBy
208209
? {
209-
sortBy: params.sortBy,
210-
sortOrder: params.sortOrder,
210+
sort_by: params.sortBy as PostSortKey,
211+
sort_order: params.sortOrder === 1 ? 'asc' : 'desc',
211212
}
212213
: {}),
213214
})

docs/superpowers/specs/2026-05-06-react-migration/00-roadmap.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ docs/superpowers/specs/2026-05-06-react-migration/
2020
├── 05-data-layer.md ← request.ts port, TanStack Query patterns, socket.io hook
2121
├── 06-routing-auth.md ← react-router tree, ProtectedRoute, better-auth + passkey
2222
├── 07-layouts-patterns.md ← AppShell, Sidebar, MasterDetailLayout, header-action injection
23-
├── 08-form-system.md ← react-hook-form + zod, ConfigForm DSL port
23+
├── 08-form-system.md ← @tanstack/react-form + zod (Standard Schema), ConfigForm DSL port
2424
├── 09-editors.md ← haklex direct-mount, monaco, codemirror, xterm, draft system
2525
├── 10-charts-misc.md ← G2 hook, kbar swap, shiki/marked, diffs, excalidraw, confetti
2626
├── 11-views-migration.md ← 21 views in batches; preconditions + acceptance per batch
@@ -43,7 +43,7 @@ docs/superpowers/specs/2026-05-06-react-migration/
4343
| UI primitives | Base UI (`@base-ui-components/react`) | headless; pairs with css.ts |
4444
| Styling | css.ts (`@vanilla-extract/css` + vite plugin) | Compile-time CSS; tokens live as TS exports |
4545
| Design system | Linear dark-canvas (per pasted DESIGN.md) | Lavender accent, four-step surface ladder, no second chromatic accent |
46-
| Forms | `react-hook-form` + `zod` | `zod` already in source repo |
46+
| Forms | `@tanstack/react-form` + `zod` (Standard Schema) | aligns with TanStack Query/Table; zod already in source repo; library swap landed 2026-05-10 |
4747
| Animation | `motion` | User-specified |
4848
| Icons | `lucide-react` | 1:1 swap from `lucide-vue-next` |
4949
| Toast | `sonner` | 1:1 swap from `vue-sonner` |

docs/superpowers/specs/2026-05-06-react-migration/01-repo-skeleton.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,7 @@ admin-react/
143143
"lucide-react": "latest",
144144
"sonner": "^1.7.0",
145145
"kbar": "^0.1.0",
146-
"react-hook-form": "^7.53.0",
147-
"@hookform/resolvers": "^3.9.0",
146+
"@tanstack/react-form": "^1.29.3",
148147
"zod": "4.3.6",
149148
"ofetch": "1.5.1",
150149
"better-auth": "1.4.18",

0 commit comments

Comments
 (0)