@c-rex/templates 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/articles/blog/page.tsx +23 -37
- package/src/articles/documents/page.tsx +2 -2
- package/src/articles/topics/page.tsx +33 -3
- package/src/articles/utils.ts +64 -6
- package/src/articles/wrapper.tsx +13 -36
- package/src/home/page.tsx +11 -13
package/package.json
CHANGED
|
@@ -1,33 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { TOPICS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
1
|
+
import { extractHtmlContent, getInfoWithCache, getPrimaryInfo } from "../utils";
|
|
2
|
+
import { BLOG_TYPE_AND_LINK } from "@c-rex/constants";
|
|
4
3
|
import { PageWrapper } from "@c-rex/components/page-wrapper";
|
|
5
|
-
import { Breadcrumb } from "@c-rex/components/breadcrumb";
|
|
6
|
-
import * as cheerio from 'cheerio'
|
|
7
4
|
import { Metadata } from "next";
|
|
8
5
|
import { RenderArticle } from "@c-rex/components/render-article";
|
|
6
|
+
import { AppSidebar } from "@c-rex/components/sidebar";
|
|
7
|
+
import { SidebarInset, SidebarProvider } from "@c-rex/ui/sidebar";
|
|
8
|
+
import { CheckArticleLangToast } from "@c-rex/components/check-article-lang";
|
|
9
9
|
|
|
10
|
-
const
|
|
11
|
-
const $ = cheerio.load(htmlString)
|
|
10
|
+
const infoCache = new Map<string, Awaited<ReturnType<typeof getPrimaryInfo>>>();
|
|
12
11
|
|
|
13
|
-
const metaTags = $('meta').map((_, el) => {
|
|
14
|
-
const name = $(el).attr('name')
|
|
15
|
-
const content = $(el).attr('content')
|
|
16
|
-
return name && content ? { name, content } : null
|
|
17
|
-
}).get().filter(Boolean)
|
|
18
|
-
|
|
19
|
-
const articleHtml = $('body').html() || ''
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
metaTags,
|
|
23
|
-
articleHtml,
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
12
|
|
|
27
13
|
export const generateMetadata = async (
|
|
28
14
|
{ params }: { params: { id: string } }
|
|
29
15
|
): Promise<Metadata> => {
|
|
30
|
-
const { htmlContent, title } = await
|
|
16
|
+
const { htmlContent, title } = await getInfoWithCache(params.id, BLOG_TYPE_AND_LINK, infoCache);
|
|
31
17
|
const { metaTags } = extractHtmlContent(htmlContent)
|
|
32
18
|
|
|
33
19
|
const other: Record<string, string[]> = {}
|
|
@@ -44,26 +30,26 @@ export const generateMetadata = async (
|
|
|
44
30
|
}
|
|
45
31
|
|
|
46
32
|
export const BlogPageTemplate = async ({ params }: { params: { id: string } }) => {
|
|
47
|
-
const { htmlContent,
|
|
33
|
+
const { htmlContent, lang, availableVersions } = await getInfoWithCache(params.id, BLOG_TYPE_AND_LINK, infoCache);
|
|
48
34
|
const { articleHtml } = extractHtmlContent(htmlContent)
|
|
49
35
|
|
|
50
|
-
const breadcrumbItems = [{
|
|
51
|
-
link: "/",
|
|
52
|
-
label: title,
|
|
53
|
-
id: "home",
|
|
54
|
-
active: false,
|
|
55
|
-
children: [],
|
|
56
|
-
}]
|
|
57
|
-
|
|
58
36
|
return (
|
|
59
37
|
<PageWrapper title="">
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
38
|
+
<SidebarProvider>
|
|
39
|
+
|
|
40
|
+
<CheckArticleLangToast availableVersions={availableVersions} />
|
|
41
|
+
|
|
42
|
+
<AppSidebar
|
|
43
|
+
lang={lang}
|
|
44
|
+
data={[]}
|
|
45
|
+
availableVersions={availableVersions}
|
|
46
|
+
/>
|
|
47
|
+
<SidebarInset>
|
|
48
|
+
<div className="container flex flex-col">
|
|
49
|
+
<RenderArticle htmlContent={articleHtml} contentLang={lang} />
|
|
50
|
+
</div>
|
|
51
|
+
</SidebarInset>
|
|
52
|
+
</SidebarProvider>
|
|
67
53
|
</PageWrapper>
|
|
68
54
|
);
|
|
69
55
|
};
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
import { getPrimaryInfo } from "../utils";
|
|
3
2
|
import { ArticleWrapper } from "../wrapper";
|
|
4
3
|
import { PageWrapper } from "@c-rex/components/page-wrapper";
|
|
5
4
|
import { DOCUMENTS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
6
5
|
|
|
7
6
|
export const DocumentsPageTemplate = async ({ params }: { params: { id: string } }) => {
|
|
8
|
-
const { htmlContent, title, lang } = await getPrimaryInfo(params.id, DOCUMENTS_TYPE_AND_LINK);
|
|
7
|
+
const { htmlContent, title, lang, availableVersions } = await getPrimaryInfo(params.id, DOCUMENTS_TYPE_AND_LINK);
|
|
9
8
|
|
|
10
9
|
return (
|
|
11
10
|
<PageWrapper title={title}>
|
|
12
11
|
<ArticleWrapper
|
|
13
12
|
title={title}
|
|
13
|
+
availableVersions={availableVersions}
|
|
14
14
|
htmlContent={htmlContent}
|
|
15
15
|
lang={lang}
|
|
16
16
|
id={params.id}
|
|
@@ -1,18 +1,48 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { getPrimaryInfo } from "../utils";
|
|
2
|
+
import { extractHtmlContent, getInfoWithCache, getPrimaryInfo } from "../utils";
|
|
3
3
|
import { TOPICS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
4
4
|
import { ArticleWrapper } from "../wrapper";
|
|
5
5
|
import { PageWrapper } from "@c-rex/components/page-wrapper";
|
|
6
|
+
import { Metadata } from "next";
|
|
7
|
+
|
|
8
|
+
const infoCache = new Map<string, Awaited<ReturnType<typeof getPrimaryInfo>>>();
|
|
9
|
+
|
|
10
|
+
export const generateMetadata = async (
|
|
11
|
+
{ params }: { params: { id: string } }
|
|
12
|
+
): Promise<Metadata> => {
|
|
13
|
+
const { htmlContent, title } = await getInfoWithCache(params.id, TOPICS_TYPE_AND_LINK, infoCache);
|
|
14
|
+
const { metaTags } = extractHtmlContent(htmlContent)
|
|
15
|
+
|
|
16
|
+
const other: Record<string, string[]> = {}
|
|
17
|
+
|
|
18
|
+
for (const { name, content } of metaTags) {
|
|
19
|
+
if (Object.keys(other).includes(name)) {
|
|
20
|
+
other[name]?.push(content)
|
|
21
|
+
} else {
|
|
22
|
+
other[name] = [content]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return { ...other, title }
|
|
27
|
+
}
|
|
6
28
|
|
|
7
29
|
export const TopicsPageTemplate = async ({ params }: { params: { id: string } }) => {
|
|
8
|
-
const {
|
|
30
|
+
const {
|
|
31
|
+
htmlContent,
|
|
32
|
+
title,
|
|
33
|
+
lang,
|
|
34
|
+
availableVersions
|
|
35
|
+
} = await getInfoWithCache(params.id, TOPICS_TYPE_AND_LINK, infoCache);
|
|
36
|
+
|
|
37
|
+
const { articleHtml } = extractHtmlContent(htmlContent)
|
|
9
38
|
|
|
10
39
|
return (
|
|
11
40
|
<PageWrapper title={title}>
|
|
12
41
|
<ArticleWrapper
|
|
13
42
|
title={title}
|
|
14
43
|
lang={lang}
|
|
15
|
-
|
|
44
|
+
availableVersions={availableVersions}
|
|
45
|
+
htmlContent={articleHtml}
|
|
16
46
|
id={params.id}
|
|
17
47
|
type={TOPICS_TYPE_AND_LINK}
|
|
18
48
|
/>
|
package/src/articles/utils.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { DirectoryNodesService, InformationUnitsService, RenditionsService } from "@c-rex/services";
|
|
2
2
|
import { DOCUMENTS_TYPE_AND_LINK, TOPICS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
3
|
-
import { DirectoryNodes } from "@c-rex/interfaces";
|
|
3
|
+
import { DirectoryNodes, SidebarAvailableVersionsInterface } from "@c-rex/interfaces";
|
|
4
|
+
import * as cheerio from 'cheerio'
|
|
5
|
+
import { BLOG_TYPE_AND_LINK } from "@c-rex/constants";
|
|
4
6
|
|
|
5
7
|
/*
|
|
6
8
|
* Get primary info for a given information unit
|
|
@@ -11,7 +13,8 @@ import { DirectoryNodes } from "@c-rex/interfaces";
|
|
|
11
13
|
export const getPrimaryInfo = async (id: string, type: string): Promise<{
|
|
12
14
|
htmlContent: string,
|
|
13
15
|
title: string,
|
|
14
|
-
lang: string
|
|
16
|
+
lang: string,
|
|
17
|
+
availableVersions: SidebarAvailableVersionsInterface[]
|
|
15
18
|
}> => {
|
|
16
19
|
const renditionService = new RenditionsService();
|
|
17
20
|
const informationService = new InformationUnitsService();
|
|
@@ -19,29 +22,59 @@ export const getPrimaryInfo = async (id: string, type: string): Promise<{
|
|
|
19
22
|
|
|
20
23
|
let title = informationUnitsItem.labels[0]?.value
|
|
21
24
|
const lang = informationUnitsItem.languages[0];
|
|
22
|
-
const
|
|
25
|
+
const versionOf = informationUnitsItem.versionOf.shortId
|
|
26
|
+
|
|
27
|
+
const [versions, rootNode] = await Promise.all([
|
|
28
|
+
informationService.getList({
|
|
29
|
+
filters: [`versionOf.shortId=${versionOf}`],
|
|
30
|
+
fields: ["renditions", "class", "languages", "labels"],
|
|
31
|
+
}),
|
|
32
|
+
getRootNode(informationUnitsItem.directoryNodes),
|
|
33
|
+
])
|
|
34
|
+
|
|
23
35
|
let htmlContent = ""
|
|
24
36
|
|
|
25
37
|
if (rootNode != null) {
|
|
26
38
|
title = rootNode.informationUnits[0]?.labels[0]?.value;
|
|
27
39
|
}
|
|
28
40
|
|
|
29
|
-
if (type
|
|
41
|
+
if ([TOPICS_TYPE_AND_LINK, BLOG_TYPE_AND_LINK].includes(type)) {
|
|
30
42
|
htmlContent = await renditionService.getHTMLRendition({ renditions: informationUnitsItem.renditions });
|
|
43
|
+
|
|
31
44
|
} else if (rootNode != null && type == DOCUMENTS_TYPE_AND_LINK) {
|
|
32
|
-
|
|
45
|
+
|
|
33
46
|
const service = new DirectoryNodesService();
|
|
47
|
+
|
|
48
|
+
const directoryId = rootNode.childNodes[0]?.shortId as string;
|
|
49
|
+
|
|
34
50
|
const response = await service.getItem(directoryId);
|
|
35
51
|
const infoId = response.informationUnits[0]?.shortId;
|
|
36
52
|
|
|
37
53
|
const childInformationUnit = await informationService.getItem({ id: infoId as string });
|
|
54
|
+
|
|
38
55
|
htmlContent = await renditionService.getHTMLRendition({ renditions: childInformationUnit.renditions });
|
|
39
56
|
}
|
|
40
57
|
|
|
58
|
+
const availableVersions = versions.items.map((item) => {
|
|
59
|
+
return {
|
|
60
|
+
shortId: item.shortId,
|
|
61
|
+
link: `/${type}/${item.shortId}`,
|
|
62
|
+
lang: item.language,
|
|
63
|
+
country: item.language.split("-")[1],
|
|
64
|
+
active: item.language === lang,
|
|
65
|
+
}
|
|
66
|
+
}).sort((a, b) => {
|
|
67
|
+
if (a.lang < b.lang) return -1;
|
|
68
|
+
if (a.lang > b.lang) return 1;
|
|
69
|
+
return 0;
|
|
70
|
+
})
|
|
71
|
+
.filter(item => item.lang.toLocaleLowerCase() !== "pl-pl") as SidebarAvailableVersionsInterface[];
|
|
72
|
+
|
|
41
73
|
return {
|
|
42
74
|
htmlContent,
|
|
43
75
|
title: title as string,
|
|
44
76
|
lang: lang as string,
|
|
77
|
+
availableVersions
|
|
45
78
|
}
|
|
46
79
|
}
|
|
47
80
|
|
|
@@ -70,4 +103,29 @@ export const getRootNode = async (directoryNodes: DirectoryNodes[]): Promise<Dir
|
|
|
70
103
|
}
|
|
71
104
|
|
|
72
105
|
return response;
|
|
73
|
-
};
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export const getInfoWithCache = async (id: string, type: string, infoCache: any): Promise<Awaited<ReturnType<typeof getPrimaryInfo>>> => {
|
|
109
|
+
if (!infoCache.has(id)) {
|
|
110
|
+
const info = await getPrimaryInfo(id, type);
|
|
111
|
+
infoCache.set(id, info);
|
|
112
|
+
}
|
|
113
|
+
return infoCache.get(id)!;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export const extractHtmlContent = (htmlString: string) => {
|
|
117
|
+
const $ = cheerio.load(htmlString)
|
|
118
|
+
|
|
119
|
+
const metaTags = $('meta').map((_, el) => {
|
|
120
|
+
const name = $(el).attr('name')
|
|
121
|
+
const content = $(el).attr('content')
|
|
122
|
+
return name && content ? { name, content } : null
|
|
123
|
+
}).get().filter(Boolean)
|
|
124
|
+
|
|
125
|
+
const articleHtml = $('main').html() || ''
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
metaTags,
|
|
129
|
+
articleHtml,
|
|
130
|
+
}
|
|
131
|
+
}
|
package/src/articles/wrapper.tsx
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
4
|
import { SidebarInset, SidebarProvider } from "@c-rex/ui/sidebar";
|
|
5
5
|
import { AppSidebar } from "@c-rex/components/sidebar";
|
|
6
6
|
import { CheckArticleLangToast } from "@c-rex/components/check-article-lang";
|
|
7
7
|
import { Breadcrumb } from "@c-rex/components/breadcrumb";
|
|
8
8
|
import { RenderArticle } from "@c-rex/components/render-article";
|
|
9
9
|
import { CloudDownload, Eye } from "lucide-react";
|
|
10
|
-
import { informationUnitsItems,
|
|
10
|
+
import { informationUnitsItems, SidebarAvailableVersionsInterface, TreeOfContent } from "@c-rex/interfaces";
|
|
11
11
|
import { DOCUMENTS_TYPE_AND_LINK, TOPICS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
12
|
-
import { call, generateBreadcrumbItems, generateTreeOfContent } from "@c-rex/utils";
|
|
12
|
+
import { call, generateBreadcrumbItems, generateTreeOfContent, getFileRenditions } from "@c-rex/utils";
|
|
13
13
|
import { DropdownMenu } from "@c-rex/components/dropdown-menu";
|
|
14
14
|
import { FileRenditionType } from "@c-rex/types";
|
|
15
15
|
|
|
@@ -19,38 +19,19 @@ type Props = {
|
|
|
19
19
|
id: string,
|
|
20
20
|
type: string,
|
|
21
21
|
lang: string,
|
|
22
|
+
availableVersions: SidebarAvailableVersionsInterface[],
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
-
filesToDownload: FileRenditionType[],
|
|
25
|
-
filesToOpen: FileRenditionType[]
|
|
26
|
-
}
|
|
24
|
+
|
|
27
25
|
const loadArticleData = async (id: string, type: string, title: string) => {
|
|
28
26
|
const informationUnitsItem = await call<informationUnitsItems>('InformationUnitsService.getItem', { id: id });
|
|
29
|
-
|
|
30
27
|
const { rootNode, result: treeOfContent } = await generateTreeOfContent(informationUnitsItem.directoryNodes);
|
|
31
28
|
|
|
32
29
|
const articleLanguage = informationUnitsItem.languages[0]
|
|
33
|
-
const versionOf = informationUnitsItem.versionOf.shortId
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
const availableVersions = versions.items.map((item) => {
|
|
40
|
-
return {
|
|
41
|
-
shortId: item.shortId,
|
|
42
|
-
link: `/${type}/${item.shortId}`,
|
|
43
|
-
lang: item.language,
|
|
44
|
-
country: item.language.split("-")[1],
|
|
45
|
-
active: item.language === articleLanguage,
|
|
46
|
-
}
|
|
47
|
-
}).sort((a, b) => {
|
|
48
|
-
if (a.lang < b.lang) return -1;
|
|
49
|
-
if (a.lang > b.lang) return 1;
|
|
50
|
-
return 0;
|
|
51
|
-
}) as SidebarAvailableVersionsInterface[];
|
|
52
|
-
|
|
53
|
-
let documents = await call<filesRenditions>("RenditionsService.getFileRenditions", { renditions: informationUnitsItem.renditions });
|
|
31
|
+
let documents: {
|
|
32
|
+
filesToDownload: FileRenditionType[];
|
|
33
|
+
filesToOpen: FileRenditionType[];
|
|
34
|
+
}
|
|
54
35
|
let rootNodeInfoID = "";
|
|
55
36
|
let breadcrumbItems: TreeOfContent[] = [];
|
|
56
37
|
|
|
@@ -58,7 +39,9 @@ const loadArticleData = async (id: string, type: string, title: string) => {
|
|
|
58
39
|
rootNodeInfoID = rootNode.informationUnits[0]?.shortId as string;
|
|
59
40
|
|
|
60
41
|
const childInformationUnit = await call<informationUnitsItems>('InformationUnitsService.getItem', { id: rootNodeInfoID });
|
|
61
|
-
documents =
|
|
42
|
+
documents = getFileRenditions({ renditions: childInformationUnit.renditions });
|
|
43
|
+
} else {
|
|
44
|
+
documents = getFileRenditions({ renditions: informationUnitsItem.renditions });
|
|
62
45
|
}
|
|
63
46
|
|
|
64
47
|
if (type == TOPICS_TYPE_AND_LINK) {
|
|
@@ -80,16 +63,13 @@ const loadArticleData = async (id: string, type: string, title: string) => {
|
|
|
80
63
|
return {
|
|
81
64
|
treeOfContent,
|
|
82
65
|
breadcrumbItems,
|
|
83
|
-
availableVersions,
|
|
84
66
|
documents,
|
|
85
67
|
articleLanguage
|
|
86
68
|
}
|
|
87
69
|
};
|
|
88
70
|
|
|
89
|
-
export const ArticleWrapper = ({ htmlContent, title, id, type, lang }: Props) => {
|
|
71
|
+
export const ArticleWrapper = ({ htmlContent, title, id, type, lang, availableVersions }: Props) => {
|
|
90
72
|
const [loading, setLoading] = useState<boolean>(true)
|
|
91
|
-
const [availableVersions, setAvailableVersions] = useState<SidebarAvailableVersionsInterface[]>([])
|
|
92
|
-
|
|
93
73
|
|
|
94
74
|
//set available versions on confgi context so will be possible to get the link when change contant language
|
|
95
75
|
const [breadcrumbItems, setBreadcrumbItems] = useState<TreeOfContent[]>([])
|
|
@@ -110,15 +90,12 @@ export const ArticleWrapper = ({ htmlContent, title, id, type, lang }: Props) =>
|
|
|
110
90
|
|
|
111
91
|
useEffect(() => {
|
|
112
92
|
const fetchData = async () => {
|
|
113
|
-
|
|
114
93
|
const {
|
|
115
|
-
availableVersions,
|
|
116
94
|
treeOfContent,
|
|
117
95
|
documents,
|
|
118
96
|
breadcrumbItems,
|
|
119
97
|
} = await loadArticleData(id, type, title)
|
|
120
98
|
|
|
121
|
-
setAvailableVersions(availableVersions)
|
|
122
99
|
setTreeOfContent(treeOfContent)
|
|
123
100
|
setDocuments(documents)
|
|
124
101
|
setBreadcrumbItems(breadcrumbItems)
|
package/src/home/page.tsx
CHANGED
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { FC } from "react";
|
|
4
4
|
import { informationUnitsResponse } from "@c-rex/interfaces";
|
|
5
|
-
import { call } from "@c-rex/utils";
|
|
5
|
+
import { call, getFromCookieString } from "@c-rex/utils";
|
|
6
6
|
import { Button } from "@c-rex/ui/button";
|
|
7
7
|
import { AutoComplete } from "@c-rex/components/autocomplete";
|
|
8
8
|
import { ResultList } from "@c-rex/components/result-list";
|
|
9
9
|
import { useTranslations } from 'next-intl'
|
|
10
10
|
import { parseAsInteger, parseAsString, useQueryStates } from 'nuqs'
|
|
11
11
|
import { DialogFilter } from "@c-rex/components/dialog-filter";
|
|
12
|
-
import { getCookie } from "@c-rex/utils";
|
|
13
12
|
import { CONTENT_LANG_KEY } from "@c-rex/constants";
|
|
14
13
|
import { useAppConfig } from "@c-rex/contexts/config-provider";
|
|
15
14
|
|
|
@@ -39,21 +38,20 @@ export const HomePage: FC<HomePageProps> = ({ data, selectedLanguages }) => {
|
|
|
39
38
|
const { search } = params;
|
|
40
39
|
|
|
41
40
|
const onSearch = (value: string): Promise<string[]> => {
|
|
42
|
-
return call("InformationUnitsService.getSuggestions", { query: value, language: contentLang });
|
|
41
|
+
return call<string[]>("InformationUnitsService.getSuggestions", { query: value, language: contentLang });
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
const onSelect = (value: string) => {
|
|
46
45
|
//show loading
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
});
|
|
46
|
+
|
|
47
|
+
const cookie = getFromCookieString(document.cookie, CONTENT_LANG_KEY)
|
|
48
|
+
|
|
49
|
+
setParams({
|
|
50
|
+
search: value,
|
|
51
|
+
operator: "OR",
|
|
52
|
+
page: 1,
|
|
53
|
+
language: cookie,
|
|
54
|
+
});
|
|
57
55
|
};
|
|
58
56
|
|
|
59
57
|
return (
|