osaet/frontend/admin/src/app/admin-api.service.ts
yarnom f0b50d13ea feat: add admin publishing workflow and yar theme
Add Go/Postgres admin APIs, Angular admin UI, manual build flow, asset uploads, markdown import/export, configurable slug generation, and the Yar reading theme. Exclude local docs and generated development artifacts from version control.
2026-06-01 15:48:04 +08:00

117 lines
2.8 KiB
TypeScript

import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import {
AssetResponse,
BuildJobResponse,
LoginResponse,
DeletePostResponse,
PostInput,
PostResponse,
PostStatus,
PostsResponse,
SlugResponse
} from './models';
@Injectable({ providedIn: 'root' })
export class AdminApiService {
private readonly http = inject(HttpClient);
private readonly baseUrl = '/api/admin';
me() {
return this.http.get<{ user: LoginResponse['user'] }>(`${this.baseUrl}/me`, {
withCredentials: true
});
}
login(username: string, password: string) {
return this.http.post<LoginResponse>(
`${this.baseUrl}/login`,
{ username, password },
{ withCredentials: true }
);
}
logout() {
return this.http.post<{ ok: boolean }>(`${this.baseUrl}/logout`, {}, { withCredentials: true });
}
listPosts(status: PostStatus | '', limit?: number, offset?: number) {
let params = new HttpParams();
if (status) {
params = params.set('status', status);
}
if (limit) {
params = params.set('limit', String(limit));
}
if (offset) {
params = params.set('offset', String(offset));
}
return this.http.get<PostsResponse>(`${this.baseUrl}/posts`, {
params,
withCredentials: true
});
}
getPost(id: string) {
return this.http.get<PostResponse>(`${this.baseUrl}/posts/${id}`, {
withCredentials: true
});
}
createPost(input: PostInput) {
return this.http.post<PostResponse>(`${this.baseUrl}/posts`, input, {
withCredentials: true
});
}
updatePost(id: string, input: PostInput) {
return this.http.put<PostResponse>(`${this.baseUrl}/posts/${id}`, input, {
withCredentials: true
});
}
deletePost(id: string) {
return this.http.delete<DeletePostResponse>(`${this.baseUrl}/posts/${id}`, {
withCredentials: true
});
}
publishPost(id: string) {
return this.http.post<PostResponse & BuildJobResponse>(
`${this.baseUrl}/posts/${id}/publish`,
{},
{ withCredentials: true }
);
}
buildPost(id: string) {
return this.http.post<BuildJobResponse>(
`${this.baseUrl}/posts/${id}/build`,
{},
{ withCredentials: true }
);
}
getBuildJob(id: string) {
return this.http.get<BuildJobResponse>(`${this.baseUrl}/build-jobs/${id}`, {
withCredentials: true
});
}
uploadAsset(file: File) {
const body = new FormData();
body.append('file', file);
return this.http.post<AssetResponse>(`${this.baseUrl}/assets`, body, {
withCredentials: true
});
}
generateSlug(title: string, summary: string, postId?: string) {
return this.http.post<SlugResponse>(
`${this.baseUrl}/slug`,
{ title, summary, postId },
{ withCredentials: true }
);
}
}