feat: read the profile's topics from Studio, and add working-copy deletion
Two things an author could not control from Studio. The profile's "주요 관심 주제" was four strings in the JSX. Creating or removing a topic in Studio changed nothing, and correcting the list meant a rebuild and a redeploy. It now renders the published topic list. The old literal opened with "Backend Architecture", which no record in the catalogue actually carries — the profile was advertising a topic that did not exist, and nothing could have caught that while the list lived in the markup. The working-copy list gained a delete control. It routes by kind because the contract and the storage both do: Case and Reference share one table split by type, Question is its own. Decision has no delete — its lifecycle is accept, reject, supersede, which records what happened rather than erasing it — so the control does not appear for it. The list summary carries no version, so deletion reads the working copy first and uses the version it finds. A stale version from a list left open should fail as a conflict, not delete whatever is there now.
This commit is contained in:
@@ -10,7 +10,10 @@ import {
|
||||
type Release,
|
||||
type HomeFocusItem,
|
||||
} from "./public-content.ts";
|
||||
import type { PublicContentQueries } from "../../application/ports/public-content-queries.ts";
|
||||
import type {
|
||||
PublicContentQueries,
|
||||
PublicTopic,
|
||||
} from "../../application/ports/public-content-queries.ts";
|
||||
|
||||
export type RecordFilters = {
|
||||
kind?: RecordKind;
|
||||
@@ -98,6 +101,24 @@ export function getProjectActivity(projectSlug: string): ProjectActivity[] {
|
||||
return [...(getProject(projectSlug)?.activity ?? [])];
|
||||
}
|
||||
|
||||
/**
|
||||
* 정적 카탈로그에는 주제 테이블이 없다 — 기록마다 붙은 주제 이름이 있을 뿐이다. 그것을 모아
|
||||
* 세면 백엔드의 `listPublicTopics` 와 같은 모양이 되고, 이 어댑터의 목적(백엔드 없이 화면을
|
||||
* 그린다)에도 맞는다.
|
||||
*/
|
||||
export function listTopics(): PublicTopic[] {
|
||||
const counts = new Map<string, { name: string; slug: string; recordCount: number }>();
|
||||
for (const record of listRecords()) {
|
||||
if (!record.topic) continue;
|
||||
const existing = counts.get(record.topicSlug);
|
||||
if (existing) existing.recordCount += 1;
|
||||
else counts.set(record.topicSlug, { name: record.topic, slug: record.topicSlug, recordCount: 1 });
|
||||
}
|
||||
return [...counts.values()]
|
||||
.sort((left, right) => right.recordCount - left.recordCount || (left.name < right.name ? -1 : 1))
|
||||
.map((entry) => Object.freeze(entry));
|
||||
}
|
||||
|
||||
export function getHomeFocusItems(): HomeFocusItem[] {
|
||||
const project = getProject("backend-skeleton");
|
||||
const question = getRecord("QUESTION", "validate-edge-token-again");
|
||||
@@ -240,6 +261,9 @@ export const publicContentQueries = Object.freeze({
|
||||
async getProjectActivity(projectSlug: string) {
|
||||
return getProjectActivity(projectSlug);
|
||||
},
|
||||
async listTopics() {
|
||||
return listTopics();
|
||||
},
|
||||
async getHomeFocusItems() {
|
||||
return getHomeFocusItems();
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user