fix(acadenice): unwrap server response envelope in 4 client services — Patch 024

The server applies a global TransformHttpResponseInterceptor that wraps
every response body in { data, success, status }. Native Docmost client
services use the api axios instance whose interceptor already unwraps
once, so callers see r.data === payload directly.

The acadenice client services use axios directly (no interceptor), so
r.data === { data, success, status } envelope. Calling templates.map()
on the envelope crashed <TemplatePickerModal> with 'templates.map is
not a function' — exact symptom Corentin hit (white screen on click).

Patched 4 services to read r.data.data: templates, sync-blocks,
slash-commands, clipper. The notifications service already uses the api
instance so it was untouched.

A future refactor should migrate all 4 to the shared api instance for
consistency and to inherit auth/redirect handling.

Patch 024.
This commit is contained in:
Corentin JOGUET 2026-05-08 12:41:18 +02:00
parent 5f7bce9b02
commit e027ae9357
4 changed files with 17 additions and 17 deletions

View file

@ -24,13 +24,13 @@ export interface CreateTokenResponse {
export const clipperClient = {
listTokens(): Promise<ClipperTokenInfo[]> {
return axios.get<ClipperTokenInfo[]>(`${BASE}/tokens`).then((r) => r.data);
return axios.get<ClipperTokenInfo[]>(`${BASE}/tokens`).then((r) => r.data.data);
},
createToken(payload: CreateTokenPayload): Promise<CreateTokenResponse> {
return axios
.post<CreateTokenResponse>(`${BASE}/tokens`, payload)
.then((r) => r.data);
.then((r) => r.data.data);
},
revokeToken(tokenId: string): Promise<void> {

View file

@ -39,21 +39,21 @@ const BASE = '/api/acadenice/slash-commands';
export const slashCommandsClient = {
list(): Promise<SlashCommandDto[]> {
return axios.get<SlashCommandDto[]>(BASE).then((r) => r.data);
return axios.get<SlashCommandDto[]>(BASE).then((r) => r.data.data);
},
get(id: string): Promise<SlashCommandDto> {
return axios.get<SlashCommandDto>(`${BASE}/${id}`).then((r) => r.data);
return axios.get<SlashCommandDto>(`${BASE}/${id}`).then((r) => r.data.data);
},
create(payload: CreateSlashCommandPayload): Promise<SlashCommandDto> {
return axios.post<SlashCommandDto>(BASE, payload).then((r) => r.data);
return axios.post<SlashCommandDto>(BASE, payload).then((r) => r.data.data);
},
update(id: string, payload: UpdateSlashCommandPayload): Promise<SlashCommandDto> {
return axios
.patch<SlashCommandDto>(`${BASE}/${id}`, payload)
.then((r) => r.data);
.then((r) => r.data.data);
},
delete(id: string): Promise<void> {
@ -63,6 +63,6 @@ export const slashCommandsClient = {
toggle(id: string, isEnabled: boolean): Promise<SlashCommandDto> {
return axios
.patch<SlashCommandDto>(`${BASE}/${id}`, { isEnabled })
.then((r) => r.data);
.then((r) => r.data.data);
},
};

View file

@ -21,15 +21,15 @@ const BASE = '/api/acadenice/sync-blocks';
export const syncBlocksClient = {
create(content: Record<string, unknown> = {}): Promise<SyncBlockDto> {
return axios.post<SyncBlockDto>(BASE, { content }).then((r) => r.data);
return axios.post<SyncBlockDto>(BASE, { content }).then((r) => r.data.data);
},
get(id: string): Promise<SyncBlockDto> {
return axios.get<SyncBlockDto>(`${BASE}/${id}`).then((r) => r.data);
return axios.get<SyncBlockDto>(`${BASE}/${id}`).then((r) => r.data.data);
},
update(id: string, content: Record<string, unknown>): Promise<SyncBlockDto> {
return axios.patch<SyncBlockDto>(`${BASE}/${id}`, { content }).then((r) => r.data);
return axios.patch<SyncBlockDto>(`${BASE}/${id}`, { content }).then((r) => r.data.data);
},
delete(id: string): Promise<void> {
@ -37,6 +37,6 @@ export const syncBlocksClient = {
},
usages(id: string): Promise<SyncBlockUsageDto[]> {
return axios.get<SyncBlockUsageDto[]>(`${BASE}/${id}/usages`).then((r) => r.data);
return axios.get<SyncBlockUsageDto[]>(`${BASE}/${id}/usages`).then((r) => r.data.data);
},
};

View file

@ -42,19 +42,19 @@ export const templatesClient = {
list(opts: { category?: string; search?: string } = {}): Promise<TemplateDto[]> {
return axios
.get<TemplateDto[]>(BASE, { params: opts })
.then((r) => r.data);
.then((r) => r.data.data);
},
get(id: string): Promise<TemplateDto> {
return axios.get<TemplateDto>(`${BASE}/${id}`).then((r) => r.data);
return axios.get<TemplateDto>(`${BASE}/${id}`).then((r) => r.data.data);
},
create(payload: CreateTemplatePayload): Promise<TemplateDto> {
return axios.post<TemplateDto>(BASE, payload).then((r) => r.data);
return axios.post<TemplateDto>(BASE, payload).then((r) => r.data.data);
},
update(id: string, payload: UpdateTemplatePayload): Promise<TemplateDto> {
return axios.patch<TemplateDto>(`${BASE}/${id}`, payload).then((r) => r.data);
return axios.patch<TemplateDto>(`${BASE}/${id}`, payload).then((r) => r.data.data);
},
delete(id: string): Promise<void> {
@ -67,10 +67,10 @@ export const templatesClient = {
): Promise<{ pageId: string; slugId: string }> {
return axios
.post<{ pageId: string; slugId: string }>(`${BASE}/${id}/instantiate`, payload)
.then((r) => r.data);
.then((r) => r.data.data);
},
setDefault(id: string): Promise<TemplateDto> {
return axios.patch<TemplateDto>(`${BASE}/${id}/default`).then((r) => r.data);
return axios.patch<TemplateDto>(`${BASE}/${id}/default`).then((r) => r.data.data);
},
};