292 lines
10 KiB
TypeScript
292 lines
10 KiB
TypeScript
import type { KnowledgeBase, KnowledgeBaseArticle } from "@toolctrl/db/prisma-browser";
|
|
import {
|
|
createKnowledgeBaseArticle,
|
|
getKbArticleBySlug,
|
|
getKnowledgeBaseArticlesForTemplateExport,
|
|
updateKnowledgeBaseArticle,
|
|
} from "../db/kbArticles.db.server";
|
|
import {
|
|
createKnowledgeBaseCategory,
|
|
getKbCategoryBySlug,
|
|
getKnowledgeBaseCategoriesForTemplateExport,
|
|
updateKnowledgeBaseCategory,
|
|
} from "../db/kbCategories.db.server";
|
|
import { createKnowledgeBase, getAllKnowledgeBases, getKnowledgeBaseBySlug, updateKnowledgeBase } from "../db/knowledgeBase.db.server";
|
|
import { KbNavLinkDto } from "../dtos/KbNavLinkDto";
|
|
import { KnowledgeBasesTemplateDto } from "../dtos/KnowledgeBasesTemplateDto";
|
|
import { KnowledgeBaseCategoryWithDetails } from "../helpers/KbCategoryModelHelper";
|
|
import { createKnowledgeBaseCategorySection, updateKnowledgeBaseCategorySection } from "../db/kbCategorySections.db.server";
|
|
import { adminGetAllUsersNames } from "~/utils/db/users.db.server";
|
|
|
|
async function getTemplate(): Promise<KnowledgeBasesTemplateDto> {
|
|
const template: KnowledgeBasesTemplateDto = {
|
|
knowledgeBases: [],
|
|
categories: [],
|
|
articles: [],
|
|
};
|
|
const allKbs = await getAllKnowledgeBases();
|
|
const categoriesByKnowledgeBaseId = groupByKnowledgeBaseId(
|
|
await getKnowledgeBaseCategoriesForTemplateExport({ knowledgeBaseIds: allKbs.map((kb) => kb.id) })
|
|
);
|
|
const articlesByKnowledgeBaseId = groupByKnowledgeBaseId(await getKnowledgeBaseArticlesForTemplateExport({ knowledgeBaseIds: allKbs.map((kb) => kb.id) }));
|
|
for (const kb of allKbs) {
|
|
template.knowledgeBases.push({
|
|
basePath: kb.basePath,
|
|
slug: kb.slug,
|
|
title: kb.title,
|
|
description: kb.description,
|
|
defaultLanguage: kb.defaultLanguage,
|
|
layout: kb.layout,
|
|
color: kb.color,
|
|
enabled: kb.enabled,
|
|
languages: JSON.parse(kb.languages) as string[],
|
|
links: JSON.parse(kb.links) as KbNavLinkDto[],
|
|
logo: kb.logo,
|
|
seoImage: kb.seoImage,
|
|
});
|
|
const allCategories = categoriesByKnowledgeBaseId.get(kb.id) ?? [];
|
|
for (const category of allCategories) {
|
|
template.categories.push({
|
|
knowledgeBaseSlug: kb.slug,
|
|
slug: category.slug,
|
|
order: category.order,
|
|
title: category.title,
|
|
description: category.description,
|
|
icon: category.icon,
|
|
language: category.language,
|
|
seoImage: category.seoImage,
|
|
sections: category.sections.map((section) => ({
|
|
order: section.order,
|
|
title: section.title,
|
|
description: section.description,
|
|
})),
|
|
});
|
|
}
|
|
const allArticles = articlesByKnowledgeBaseId.get(kb.id) ?? [];
|
|
for (const article of allArticles) {
|
|
template.articles.push({
|
|
knowledgeBaseSlug: kb.slug,
|
|
categorySlug: article.category?.slug ?? null,
|
|
categorySectionOrder: article.section?.order ?? null,
|
|
slug: article.slug,
|
|
title: article.title,
|
|
description: article.description,
|
|
order: article.order,
|
|
contentDraft: article.contentDraft,
|
|
contentPublished: article.contentPublished,
|
|
contentPublishedAsText: article.contentPublishedAsText,
|
|
contentType: article.contentType,
|
|
language: article.language,
|
|
featuredOrder: article.featuredOrder,
|
|
seoImage: article.seoImage,
|
|
publishedAt: article.publishedAt ? article.publishedAt.toISOString() : null,
|
|
createdByUserEmail: article.createdByUser?.email ?? null,
|
|
relatedArticles: article.relatedArticles.map(({ relatedArticle }) => ({
|
|
slug: relatedArticle.slug,
|
|
})),
|
|
});
|
|
}
|
|
}
|
|
return template;
|
|
}
|
|
|
|
function groupByKnowledgeBaseId<T extends { knowledgeBaseId: string }>(items: T[]) {
|
|
const grouped = new Map<string, T[]>();
|
|
for (const item of items) {
|
|
const current = grouped.get(item.knowledgeBaseId);
|
|
if (current) {
|
|
current.push(item);
|
|
} else {
|
|
grouped.set(item.knowledgeBaseId, [item]);
|
|
}
|
|
}
|
|
return grouped;
|
|
}
|
|
|
|
async function importKbs({ template, currentUserId }: { template: KnowledgeBasesTemplateDto; currentUserId: string }) {
|
|
let created = {
|
|
kbs: 0,
|
|
categories: 0,
|
|
sections: 0,
|
|
articles: 0,
|
|
};
|
|
let updated = {
|
|
kbs: 0,
|
|
categories: 0,
|
|
sections: 0,
|
|
articles: 0,
|
|
};
|
|
const allUsers = await adminGetAllUsersNames();
|
|
for (const kb of template.knowledgeBases) {
|
|
if (!kb.basePath) {
|
|
kb.basePath = "/";
|
|
}
|
|
let existing: KnowledgeBase | null = await getKnowledgeBaseBySlug(kb.slug);
|
|
if (existing) {
|
|
await updateKnowledgeBase(existing.id, {
|
|
basePath: kb.basePath,
|
|
slug: kb.slug,
|
|
title: kb.title,
|
|
description: kb.description,
|
|
defaultLanguage: kb.defaultLanguage,
|
|
layout: kb.layout,
|
|
color: kb.color,
|
|
enabled: kb.enabled,
|
|
languages: JSON.stringify(kb.languages),
|
|
links: JSON.stringify(kb.links),
|
|
logo: kb.logo,
|
|
seoImage: kb.seoImage,
|
|
});
|
|
updated.kbs++;
|
|
} else {
|
|
existing = await createKnowledgeBase({
|
|
basePath: kb.basePath,
|
|
slug: kb.slug,
|
|
title: kb.title,
|
|
description: kb.description,
|
|
defaultLanguage: kb.defaultLanguage,
|
|
layout: kb.layout,
|
|
color: kb.color,
|
|
enabled: kb.enabled,
|
|
languages: JSON.stringify(kb.languages),
|
|
links: JSON.stringify(kb.links),
|
|
logo: kb.logo,
|
|
seoImage: kb.seoImage,
|
|
});
|
|
created.kbs++;
|
|
}
|
|
|
|
for (const category of template.categories.filter((c) => c.knowledgeBaseSlug === kb.slug)) {
|
|
let existingCategory: KnowledgeBaseCategoryWithDetails | null = await getKbCategoryBySlug({
|
|
knowledgeBaseId: existing.id,
|
|
slug: category.slug,
|
|
language: category.language,
|
|
});
|
|
if (existingCategory) {
|
|
await updateKnowledgeBaseCategory(existingCategory.id, {
|
|
title: category.title,
|
|
order: category.order,
|
|
description: category.description,
|
|
icon: category.icon,
|
|
language: category.language,
|
|
seoImage: category.seoImage,
|
|
});
|
|
updated.categories++;
|
|
} else {
|
|
existingCategory = await createKnowledgeBaseCategory({
|
|
knowledgeBaseId: existing.id,
|
|
slug: category.slug,
|
|
title: category.title,
|
|
order: category.order,
|
|
description: category.description,
|
|
icon: category.icon,
|
|
language: category.language,
|
|
seoImage: category.seoImage,
|
|
});
|
|
created.categories++;
|
|
}
|
|
|
|
for (const section of category.sections) {
|
|
let existingSection: { id: string; order: number; title: string; description: string } | null = null;
|
|
if (existingCategory) {
|
|
existingSection = existingCategory.sections.find((s) => s.order === section.order) ?? null;
|
|
}
|
|
if (existingSection) {
|
|
await updateKnowledgeBaseCategorySection(existingSection.id, {
|
|
title: section.title,
|
|
description: section.description,
|
|
});
|
|
updated.sections++;
|
|
} else {
|
|
await createKnowledgeBaseCategorySection({
|
|
categoryId: existingCategory?.id ?? null,
|
|
order: section.order,
|
|
title: section.title,
|
|
description: section.description,
|
|
});
|
|
created.sections++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const article of template.articles.filter((a) => a.knowledgeBaseSlug === kb.slug)) {
|
|
let existingArticle: KnowledgeBaseArticle | null = await getKbArticleBySlug({
|
|
knowledgeBaseId: existing.id,
|
|
slug: article.slug,
|
|
language: article.language,
|
|
});
|
|
let category: KnowledgeBaseCategoryWithDetails | null = null;
|
|
let sectionId: string | null = null;
|
|
if (article.categorySlug) {
|
|
category = await getKbCategoryBySlug({
|
|
knowledgeBaseId: existing.id,
|
|
slug: article.categorySlug,
|
|
language: article.language,
|
|
});
|
|
if (category && article.categorySectionOrder) {
|
|
const section = category.sections.find((s) => s.order === article.categorySectionOrder);
|
|
if (section) {
|
|
sectionId = section.id;
|
|
}
|
|
}
|
|
}
|
|
let createdByUserId = currentUserId;
|
|
if (article.createdByUserEmail) {
|
|
const user = allUsers.find((f) => f.email === article.createdByUserEmail);
|
|
if (user) {
|
|
createdByUserId = user.id;
|
|
}
|
|
}
|
|
if (existingArticle) {
|
|
await updateKnowledgeBaseArticle(existingArticle.id, {
|
|
categoryId: category?.id ?? null,
|
|
sectionId: sectionId,
|
|
slug: article.slug,
|
|
title: article.title,
|
|
description: article.description,
|
|
order: article.order,
|
|
contentDraft: article.contentDraft,
|
|
contentPublished: article.contentPublished,
|
|
contentPublishedAsText: article.contentPublishedAsText,
|
|
contentType: article.contentType,
|
|
language: article.language,
|
|
featuredOrder: article.featuredOrder,
|
|
createdByUserId,
|
|
seoImage: article.seoImage,
|
|
publishedAt: article.publishedAt ? new Date(article.publishedAt) : null,
|
|
});
|
|
updated.articles++;
|
|
} else {
|
|
existingArticle = await createKnowledgeBaseArticle({
|
|
knowledgeBaseId: existing.id,
|
|
categoryId: category?.id ?? null,
|
|
sectionId: sectionId,
|
|
slug: article.slug,
|
|
title: article.title,
|
|
description: article.description,
|
|
order: article.order,
|
|
contentDraft: article.contentDraft,
|
|
contentPublished: article.contentPublished,
|
|
contentPublishedAsText: article.contentPublishedAsText,
|
|
contentType: article.contentType,
|
|
language: article.language,
|
|
featuredOrder: article.featuredOrder,
|
|
createdByUserId,
|
|
seoImage: article.seoImage,
|
|
publishedAt: article.publishedAt ? new Date(article.publishedAt) : null,
|
|
});
|
|
created.articles++;
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
created,
|
|
updated,
|
|
};
|
|
}
|
|
|
|
export default {
|
|
getTemplate,
|
|
importKbs,
|
|
};
|