Track HiveGrid Cloud planning reference
This commit is contained in:
1 parent
b3d5ea6764
commit
e341c5938a
5784 files changed
+1104929
-3
No files matched your search
@@ -0,0 +1,55 @@
|
||||
import type { KnowledgeBaseDto } from "../../dtos/KnowledgeBaseDto";
|
||||
import BreadcrumbSimple from "~/components/ui/breadcrumbs/BreadcrumbSimple";
|
||||
import type { KbArticleDto } from "~/modules/knowledgeBase/dtos/KbArticleDto";
|
||||
import type { KbCategoryDto } from "~/modules/knowledgeBase/dtos/KbCategoryDto";
|
||||
import KbArticleContent from "./KbArticleContent";
|
||||
import { useParams } from "react-router";
|
||||
import KnowledgeBaseUtils from "../../utils/KnowledgeBaseUtils";
|
||||
|
||||
export default function KbArticle({
|
||||
kb,
|
||||
category,
|
||||
item,
|
||||
userState,
|
||||
actions,
|
||||
withMenu = true,
|
||||
}: {
|
||||
kb: KnowledgeBaseDto;
|
||||
category: KbCategoryDto;
|
||||
item: KbArticleDto;
|
||||
userState: {
|
||||
hasThumbsUp: boolean;
|
||||
hasThumbsDown: boolean;
|
||||
};
|
||||
actions: {
|
||||
onThumbsUp: () => void;
|
||||
onThumbsDown: () => void;
|
||||
};
|
||||
withMenu?: boolean;
|
||||
}) {
|
||||
const params = useParams();
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{withMenu && (
|
||||
<BreadcrumbSimple
|
||||
menu={[
|
||||
// {
|
||||
// title: kb.title,
|
||||
// routePath: KnowledgeBaseUtils.getKbUrl({ kb, params }),
|
||||
// },
|
||||
{
|
||||
title: category.title,
|
||||
routePath: KnowledgeBaseUtils.getCategoryUrl({ kb, category, params }),
|
||||
},
|
||||
{
|
||||
title: item.title,
|
||||
routePath: item.href,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
|
||||
<KbArticleContent item={item} content={item.contentPublished} userState={userState} actions={actions} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
import { Link } from "react-router";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ThumbsDownIcon from "~/components/ui/icons/ThumbsDownIcon";
|
||||
import ThumbsDownIconFilled from "~/components/ui/icons/ThumbsDownIconFilled";
|
||||
import ThumbsUpIcon from "~/components/ui/icons/ThumbsUpIcon";
|
||||
import ThumbsUpIconFilled from "~/components/ui/icons/ThumbsUpIconFilled";
|
||||
import { KbArticleDto } from "~/modules/knowledgeBase/dtos/KbArticleDto";
|
||||
import { renderSanitizedMarkdown } from "~/utils/html-sanitizer";
|
||||
import { useLocaleFormatters } from "~/locale/format";
|
||||
|
||||
export default function KbArticleContent({
|
||||
item,
|
||||
content,
|
||||
actions,
|
||||
userState,
|
||||
}: {
|
||||
item: KbArticleDto;
|
||||
content: string;
|
||||
userState?: {
|
||||
hasThumbsUp: boolean;
|
||||
hasThumbsDown: boolean;
|
||||
};
|
||||
actions?: {
|
||||
onThumbsUp: () => void;
|
||||
onThumbsDown: () => void;
|
||||
};
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const formatters = useLocaleFormatters();
|
||||
return (
|
||||
<div>
|
||||
<div className="flex flex-col space-y-6">
|
||||
<div className="flex items-center space-x-8">
|
||||
<div className="flex w-full flex-col">
|
||||
<div className="flex items-center space-x-3">
|
||||
<h1 className="text-xl font-bold md:text-3xl">{item.title}</h1>
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-2 font-light">{item.description}</p>
|
||||
<div className="flex justify-between space-x-2">
|
||||
<li className="mt-5 flex items-center space-x-2">
|
||||
{item.createdByUser?.avatar && (
|
||||
<img
|
||||
src={item.createdByUser.avatar}
|
||||
alt={`${item.createdByUser.firstName} ${item.createdByUser.lastName}`}
|
||||
className="h-8 w-8 rounded-full"
|
||||
/>
|
||||
)}
|
||||
<div>
|
||||
{item.createdByUser && (
|
||||
<dl className="whitespace-no-wrap text-sm font-medium leading-5">
|
||||
<dt className="sr-only">{t("knowledgeBase.article.author")}</dt>
|
||||
<dd className="">
|
||||
<span className="text-muted-foreground font-normal">{t("shared.by")}</span> {item.createdByUser.firstName} {item.createdByUser.lastName}
|
||||
</dd>
|
||||
</dl>
|
||||
)}
|
||||
<dl className="whitespace-no-wrap text-xs leading-5">{formatters.relativeDate(item.createdAt)}</dl>
|
||||
</div>
|
||||
</li>
|
||||
{actions && (
|
||||
<div className="flex items-center space-x-2">
|
||||
<button type="button" onClick={actions.onThumbsUp} className="text-muted-foreground hover:text-foreground flex items-center space-x-2">
|
||||
{userState?.hasThumbsUp ? <ThumbsUpIconFilled className="h-4 w-4" /> : <ThumbsUpIcon className="h-4 w-4" />}
|
||||
</button>
|
||||
<button type="button" onClick={actions.onThumbsDown} className="text-muted-foreground hover:text-foreground flex items-center space-x-2">
|
||||
{userState?.hasThumbsDown ? <ThumbsDownIconFilled className="h-4 w-4" /> : <ThumbsDownIcon className="h-4 w-4" />}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-border border-b pt-6"></div>
|
||||
|
||||
<div className="grid gap-8 sm:grid-cols-12">
|
||||
<div className="overflow-auto sm:col-span-9">
|
||||
<div className="prose dark:prose-dark">
|
||||
<div dangerouslySetInnerHTML={{ __html: renderSanitizedMarkdown(content) }} />
|
||||
</div>
|
||||
</div>
|
||||
{item.relatedArticles.length > 0 && (
|
||||
<div className="space-y-3 py-5 sm:col-span-3">
|
||||
<div className="text-muted-foreground text-sm font-medium">{t("knowledgeBase.article.relatedArticles")}</div>
|
||||
<div className="space-y-2">
|
||||
{item.relatedArticles.map((x) => (
|
||||
<Link to={x.href} key={x.href} className="flex items-center space-x-2 hover:underline">
|
||||
<div className="text-sm">{x.title}</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Link } from "react-router";
|
||||
import RightIcon from "~/components/ui/icons/RightIcon";
|
||||
import clsx from "clsx";
|
||||
import ColorHoverUtils from "~/utils/shared/colors/ColorHoverUtils";
|
||||
import type { KnowledgeBaseDto } from "../../dtos/KnowledgeBaseDto";
|
||||
|
||||
export default function KbArticles({
|
||||
kb,
|
||||
items,
|
||||
}: {
|
||||
kb: KnowledgeBaseDto;
|
||||
items: {
|
||||
order: number;
|
||||
title: string;
|
||||
description: string;
|
||||
href: string;
|
||||
sectionId: string | null;
|
||||
}[];
|
||||
}) {
|
||||
return (
|
||||
<div className="rounded-md border border-border bg-background py-3">
|
||||
{items.map((item) => {
|
||||
return (
|
||||
<div key={item.title} className={clsx("group", ColorHoverUtils.getBorder500(kb.color))}>
|
||||
<Link to={item.href}>
|
||||
<div className="flex items-center justify-between space-x-2 px-6 py-3 hover:bg-secondary">
|
||||
<div className="">
|
||||
<div className={clsx(" text-muted-foreground group-hover:text-foreground")}>{item.title}</div>
|
||||
</div>
|
||||
<RightIcon className={clsx("h-5 w-5 shrink-0 text-muted-foreground group-hover:text-foreground")} />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import EmptyState from "~/components/ui/emptyState/EmptyState";
|
||||
import type { KbCategoryDto } from "../../dtos/KbCategoryDto";
|
||||
import type { KnowledgeBaseDto } from "../../dtos/KnowledgeBaseDto";
|
||||
import KbArticles from "./KbArticles";
|
||||
import KnowledgeBaseUtils from "../../utils/KnowledgeBaseUtils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function KbArticlesBySection({ kb, item }: { kb: KnowledgeBaseDto; item: KbCategoryDto }) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div>
|
||||
{item.articles.length === 0 ? (
|
||||
<EmptyState className="bg-background" captions={{ thereAreNo: t("knowledgeBase.article.empty") }} />
|
||||
) : (
|
||||
<div className="space-y-6">
|
||||
{KnowledgeBaseUtils.getCategoryArticlesBySections({ kb, category: item }).map((item, idx) => {
|
||||
return (
|
||||
<div key={idx} className="space-y-3">
|
||||
{item.section && (
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="text-xl font-bold">{item.section.title}</div>
|
||||
</div>
|
||||
)}
|
||||
<KbArticles kb={kb} items={item.articles} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import OrderListButtons from "~/components/ui/sort/OrderListButtons";
|
||||
import TableSimple from "~/components/ui/tables/TableSimple";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function KbSortArticles({
|
||||
items,
|
||||
}: {
|
||||
items: {
|
||||
id: string;
|
||||
order: number;
|
||||
title: string;
|
||||
}[];
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
<label className="text-muted-foreground block text-xs font-medium">{t("knowledgeBase.authoring.articles.title")}</label>
|
||||
<TableSimple
|
||||
items={items}
|
||||
headers={[
|
||||
{
|
||||
name: "order",
|
||||
title: "",
|
||||
value: (i, idx) => <OrderListButtons index={idx} items={items} editable={true} />,
|
||||
},
|
||||
{
|
||||
name: "title",
|
||||
title: t("shared.title"),
|
||||
value: (item) => item.title,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user