feat : dont conflit with other editor
This commit is contained in:
+14
-13
@@ -40,6 +40,7 @@ import {
|
||||
} from "@/lib/guides/schemas";
|
||||
import { processCatalogSync } from "@/lib/catalog/sync";
|
||||
import { normalizeExtraRichText } from "@/lib/rich-text";
|
||||
import type { AdminEditorScope } from "@/lib/events/invalidation";
|
||||
|
||||
const DEFAULT_SECTIONS = [
|
||||
{ kind: "weapon", slug: "weapon", title: "Weapons", sortOrder: 0 },
|
||||
@@ -55,13 +56,13 @@ export class GuideVersionConflictError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
async function emitGuideEvents(tx: Parameters<Parameters<ReturnType<typeof getDb>["transaction"]>[0]>[0], guideId: string, version: number, directoryChanged = false) {
|
||||
async function emitGuideEvents(tx: Parameters<Parameters<ReturnType<typeof getDb>["transaction"]>[0]>[0], guideId: string, version: number, directoryChanged = false, scope?: AdminEditorScope) {
|
||||
await tx.insert(outboxEvents).values([
|
||||
...(directoryChanged
|
||||
? [{ topic: "directory", aggregateId: guideId, eventType: "directory.updated", payload: { id: guideId, version } }]
|
||||
: []),
|
||||
{ topic: `page:${guideId}`, aggregateId: guideId, eventType: "page.updated", payload: { id: guideId, version } },
|
||||
{ topic: "admin", aggregateId: guideId, eventType: "admin.updated", payload: { id: guideId, version } },
|
||||
{ topic: "admin", aggregateId: guideId, eventType: "admin.updated", payload: { id: guideId, version, ...(scope ? { scope } : {}) } },
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -101,14 +102,14 @@ export async function createGuide(input: unknown) {
|
||||
});
|
||||
}
|
||||
|
||||
async function advanceGuideVersion(tx: Parameters<Parameters<ReturnType<typeof getDb>["transaction"]>[0]>[0], guideId: string, expectedVersion: number, directoryChanged = false) {
|
||||
async function advanceGuideVersion(tx: Parameters<Parameters<ReturnType<typeof getDb>["transaction"]>[0]>[0], guideId: string, expectedVersion: number, directoryChanged = false, scope?: AdminEditorScope) {
|
||||
const [guide] = await tx.update(guides).set({ version: expectedVersion + 1 }).where(and(eq(guides.id, guideId), eq(guides.version, expectedVersion), sql`${guides.trashedAt} is null`)).returning();
|
||||
if (!guide) {
|
||||
const [current] = await tx.select({ version: guides.version }).from(guides).where(eq(guides.id, guideId)).limit(1);
|
||||
if (current) throw new GuideVersionConflictError(current.version);
|
||||
throw new Error("ไม่พบ Guide");
|
||||
}
|
||||
await emitGuideEvents(tx, guide.id, guide.version, directoryChanged);
|
||||
await emitGuideEvents(tx, guide.id, guide.version, directoryChanged, scope);
|
||||
return guide;
|
||||
}
|
||||
|
||||
@@ -117,7 +118,7 @@ export async function saveWeapons(guideId: string, input: unknown) {
|
||||
const [guide] = await getDb().select().from(guides).where(eq(guides.id, guideId)).limit(1);
|
||||
if (!guide) throw new Error("ไม่พบ Guide");
|
||||
return getDb().transaction(async (tx) => {
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion);
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion, false, "weapon");
|
||||
await tx.update(guideSections).set({ note: data.note }).where(and(eq(guideSections.guideId, guideId), eq(guideSections.slug, "weapon")));
|
||||
await tx.delete(weaponConditions).where(eq(weaponConditions.guideId, guideId));
|
||||
for (const [sortOrder, group] of data.groups.entries()) {
|
||||
@@ -153,7 +154,7 @@ export async function updateGuideBasics(guideId: string, input: unknown) {
|
||||
: [];
|
||||
if (bleedingMedia.length !== bleedingMediaIds.length) throw new Error("ไม่พบภาพ Bleeding ที่อัปโหลดแล้ว");
|
||||
}
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion, true);
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion, true, "overview");
|
||||
await tx.update(guides).set({
|
||||
overview: data.overview,
|
||||
coverMediaId: data.coverMediaId,
|
||||
@@ -206,7 +207,7 @@ export async function saveArtifacts(guideId: string, input: unknown) {
|
||||
const [guide] = await getDb().select().from(guides).where(eq(guides.id, guideId)).limit(1);
|
||||
if (!guide) throw new Error("ไม่พบ Guide");
|
||||
return getDb().transaction(async (tx) => {
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion);
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion, false, "artifact");
|
||||
await tx.delete(artifactGroups).where(eq(artifactGroups.guideId, guideId));
|
||||
for (const [sortOrder, group] of data.groups.entries()) {
|
||||
const [created] = await tx.insert(artifactGroups).values({ guideId, name: group.name, sortOrder }).returning();
|
||||
@@ -220,7 +221,7 @@ export async function saveArtifacts(guideId: string, input: unknown) {
|
||||
export async function saveConstellations(guideId: string, input: unknown) {
|
||||
const data = constellationSectionSchema.parse(input);
|
||||
return getDb().transaction(async (tx) => {
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion);
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion, false, "constellations");
|
||||
await tx.update(guideSections).set({ note: data.note }).where(and(eq(guideSections.guideId, guideId), eq(guideSections.slug, "constellations")));
|
||||
await tx.delete(constellationConditions).where(eq(constellationConditions.guideId, guideId));
|
||||
for (const [sortOrder, group] of data.groups.entries()) {
|
||||
@@ -255,7 +256,7 @@ export async function saveTeams(guideId: string, input: unknown) {
|
||||
}
|
||||
}
|
||||
return getDb().transaction(async (tx) => {
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion);
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion, false, "team");
|
||||
await tx.delete(teamConditions).where(eq(teamConditions.guideId, guideId));
|
||||
for (const [groupOrder, group] of data.groups.entries()) {
|
||||
const [condition] = await tx.insert(teamConditions).values({ guideId, name: group.name, note: group.note, sortOrder: groupOrder }).returning();
|
||||
@@ -271,7 +272,7 @@ export async function saveTeams(guideId: string, input: unknown) {
|
||||
export async function saveExtraSections(guideId: string, input: unknown) {
|
||||
const data = extraSectionSchema.parse(input);
|
||||
return getDb().transaction(async (tx) => {
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion);
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion, false, "extras:list");
|
||||
await tx.delete(guideSections).where(and(eq(guideSections.guideId, guideId), eq(guideSections.kind, "extra")));
|
||||
for (const [sortOrder, section] of data.sections.entries()) {
|
||||
const [createdSection] = await tx.insert(guideSections).values({ guideId, kind: "extra", slug: `extra-${sortOrder + 1}`, title: section.title, enabled: true, sortOrder: 4 + sortOrder }).returning();
|
||||
@@ -323,7 +324,7 @@ export async function createExtraSection(guideId: string, input: unknown) {
|
||||
})
|
||||
.returning();
|
||||
await tx.insert(extraSections).values({ sectionId: section.id });
|
||||
await emitGuideEvents(tx, guideId, updated.version);
|
||||
await emitGuideEvents(tx, guideId, updated.version, false, "extras:list");
|
||||
return { ...section, version: updated.version };
|
||||
});
|
||||
}
|
||||
@@ -346,7 +347,7 @@ export async function saveExtraSection(
|
||||
.limit(1);
|
||||
if (!target) throw new Error("ไม่พบ Extra section");
|
||||
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion);
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion, false, `extra:${sectionId}`);
|
||||
await tx
|
||||
.update(guideSections)
|
||||
.set({ title: data.section.title })
|
||||
@@ -406,7 +407,7 @@ export async function reorderExtraSections(guideId: string, input: unknown) {
|
||||
throw new Error("รายการ Extra sections ไม่ตรงกับข้อมูลล่าสุด");
|
||||
}
|
||||
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion);
|
||||
const updated = await advanceGuideVersion(tx, guideId, data.expectedVersion, false, "extras:list");
|
||||
for (const [index, sectionId] of data.sectionIds.entries()) {
|
||||
await tx
|
||||
.update(guideSections)
|
||||
|
||||
Reference in New Issue
Block a user