4.8 KiB
4.8 KiB
type, title, description, tags, timestamp
| type | title | description | tags | timestamp | |||||
|---|---|---|---|---|---|---|---|---|---|
| guide | Blog Publishing and Reading | How administrators create, edit, publish, and delete Markdown posts and how users read published posts. |
|
2026-07-23T10:12:24Z |
User views
Published posts are available in two places:
| View | Access | Expected content |
|---|---|---|
/login |
Unauthenticated users | The landing-page blog section lists published posts below the Login button. |
/blog |
Signed-in users | The Blog page loads and lists all published posts. |
Both views use BlogPresenterComponent to show the post title, publication date, and sanitized Markdown body. Draft posts never appear in either public list. The /blog page shows Loading blog posts… while loading, No announcements yet. when no posts are published, and an error message if loading fails.
Admin workflow
- Sign in as an administrator.
- Open Admin, then select Blog, or navigate directly to
/admin/blog. - Confirm the page displays a table with Title, Status, Created, Updated, Published, and Actions columns. If no posts exist, it displays
No posts yet.. - Click + New post.
- Enter a required title and an optional Markdown body. The live preview updates beside the editor.
- Click Save draft to keep the post hidden from users, or Publish to expose it in
/blogand on/login. - Confirm a success banner displays
Draft saved.orPost published., and the refreshed table contains the post with the correct status badge.
Editing and deleting
- Click the pencil action on a row to open the prefilled Edit post modal. It shows created, updated, and publication timestamps where available.
- Saving as draft changes the status to Draft and hides the post from public lists. Republishing preserves the post's original publication timestamp.
- Click the trash action to open Delete post. The confirmation includes the title and warns that deletion cannot be undone.
- Click Delete to remove the post. The table refreshes and displays
Post deleted.. Click Cancel or the modal backdrop to leave the post unchanged.
Validation and expected errors
| Input or operation | Expected behavior |
|---|---|
| Empty or whitespace-only title | Title is required; save and publish remain unavailable. |
| Title over 200 characters | Title must be at most 200 characters. |
| Markdown body over 200,000 characters | Body must be at most 200000 characters. |
| API list failure | An error banner replaces the table state. |
| Create or update failure | The form stays open and displays the server message. |
| Delete failure | The confirmation stays open and displays the server message. |
Architecture map
| Layer | File | Responsibility |
|---|---|---|
| Routes | frontend/src/app/app.routes.ts |
Registers authenticated /blog and admin-only /admin/blog. |
| Admin page | frontend/src/app/features/admin/blog/blog.component.ts |
Loads all posts and coordinates create, edit, publish, draft, and delete operations. |
| Admin form | frontend/src/app/features/admin/blog/blog-form-modal.component.ts |
Reactive title/body editor with sanitized live Markdown preview. |
| Admin form logic | frontend/src/app/features/admin/blog/blog-form.pure.ts |
Validation, form synchronization, request cleanup, and status labels. |
| Delete confirmation | frontend/src/app/features/admin/blog/blog-delete-modal.component.ts |
Confirms destructive deletion and displays failures. |
| User page | frontend/src/app/features/blog/blog.page.ts |
Loads published posts and selects loading, error, empty, or list state. |
| Shared presenter | frontend/src/app/features/blog/blog-presenter.component.ts |
Renders a published post consistently on /blog and /login. |
| HTTP client | frontend/src/app/core/services/blog.service.ts |
Calls public list and admin CRUD endpoints. |
| Backend wiring | backend/src/modules/blog/blog.module.ts |
Registers public and admin controllers and services with the blog repository. |
| Admin API | backend/src/modules/blog/admin-blog.controller.ts |
Registers guarded CRUD routes under /api/v1/admin/blog/posts. |
| Persistence logic | backend/src/modules/blog/admin-blog.service.ts |
Queries and mutates blog_post rows and controls publication timestamps. |
The Angular client uses HTTP JSON calls. Existing auth and CSRF interceptors attach the administrator JWT and CSRF token to unsafe requests. The backend controller is protected by AdminGuard and @Roles('admin'), then delegates to AdminBlogService, which uses the TypeORM BlogPostEntity repository.