@c-rex/templates 0.1.2 → 0.1.4
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 +11 -5
- package/src/articles/blog/page.tsx +69 -0
- package/src/articles/documents/page.tsx +13 -48
- package/src/articles/topics/page.tsx +21 -0
- package/src/articles/utils.ts +75 -0
- package/src/articles/wrapper.tsx +169 -0
- package/src/home/layout.tsx +43 -74
- package/src/home/page.tsx +22 -21
- package/src/layout.tsx +18 -14
- package/src/articles/info/page.tsx +0 -50
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c-rex/templates",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"src"
|
|
@@ -18,9 +18,13 @@
|
|
|
18
18
|
"types": "./src/home/page.tsx",
|
|
19
19
|
"import": "./src/home/page.tsx"
|
|
20
20
|
},
|
|
21
|
-
"./articles/
|
|
22
|
-
"types": "./src/articles/
|
|
23
|
-
"import": "./src/articles/
|
|
21
|
+
"./articles/topics/page": {
|
|
22
|
+
"types": "./src/articles/topics/page.tsx",
|
|
23
|
+
"import": "./src/articles/topics/page.tsx"
|
|
24
|
+
},
|
|
25
|
+
"./articles/blog/page": {
|
|
26
|
+
"types": "./src/articles/blog/page.tsx",
|
|
27
|
+
"import": "./src/articles/blog/page.tsx"
|
|
24
28
|
},
|
|
25
29
|
"./articles/documents/page": {
|
|
26
30
|
"types": "./src/articles/documents/page.tsx",
|
|
@@ -52,12 +56,14 @@
|
|
|
52
56
|
"@c-rex/services": "*",
|
|
53
57
|
"@c-rex/ui": "*",
|
|
54
58
|
"@c-rex/utils": "*",
|
|
59
|
+
"cheerio": "^1.1.0",
|
|
55
60
|
"i18next": "^25.1.3",
|
|
56
61
|
"next": "^14",
|
|
57
62
|
"next-intl": "^4.1.0",
|
|
58
63
|
"nuqs": "^2.4.3",
|
|
59
64
|
"react": "^18",
|
|
60
65
|
"react-dom": "^18",
|
|
61
|
-
"react-i18next": "^15.5.1"
|
|
66
|
+
"react-i18next": "^15.5.1",
|
|
67
|
+
"sonner": "^2.0.5"
|
|
62
68
|
}
|
|
63
69
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { getPrimaryInfo } from "../utils";
|
|
3
|
+
import { TOPICS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
4
|
+
import { PageWrapper } from "@c-rex/components/page-wrapper";
|
|
5
|
+
import { Breadcrumb } from "@c-rex/components/breadcrumb";
|
|
6
|
+
import * as cheerio from 'cheerio'
|
|
7
|
+
import { Metadata } from "next";
|
|
8
|
+
import { RenderArticle } from "@c-rex/components/render-article";
|
|
9
|
+
|
|
10
|
+
const extractHtmlContent = (htmlString: string) => {
|
|
11
|
+
const $ = cheerio.load(htmlString)
|
|
12
|
+
|
|
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
|
+
|
|
27
|
+
export const generateMetadata = async (
|
|
28
|
+
{ params }: { params: { id: string } }
|
|
29
|
+
): Promise<Metadata> => {
|
|
30
|
+
const { htmlContent, title } = await getPrimaryInfo(params.id, TOPICS_TYPE_AND_LINK);
|
|
31
|
+
const { metaTags } = extractHtmlContent(htmlContent)
|
|
32
|
+
|
|
33
|
+
const other: Record<string, string[]> = {}
|
|
34
|
+
|
|
35
|
+
for (const { name, content } of metaTags) {
|
|
36
|
+
if (Object.keys(other).includes(name)) {
|
|
37
|
+
other[name]?.push(content)
|
|
38
|
+
} else {
|
|
39
|
+
other[name] = [content]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return { ...other, title }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const BlogPageTemplate = async ({ params }: { params: { id: string } }) => {
|
|
47
|
+
const { htmlContent, title, lang } = await getPrimaryInfo(params.id, TOPICS_TYPE_AND_LINK);
|
|
48
|
+
const { articleHtml } = extractHtmlContent(htmlContent)
|
|
49
|
+
|
|
50
|
+
const breadcrumbItems = [{
|
|
51
|
+
link: "/",
|
|
52
|
+
label: title,
|
|
53
|
+
id: "home",
|
|
54
|
+
active: false,
|
|
55
|
+
children: [],
|
|
56
|
+
}]
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<PageWrapper title="">
|
|
60
|
+
<div className="container flex flex-col">
|
|
61
|
+
<header className="flex h-16 shrink-0 items-center justify-between">
|
|
62
|
+
<Breadcrumb items={breadcrumbItems} lang={lang} />
|
|
63
|
+
</header>
|
|
64
|
+
|
|
65
|
+
<RenderArticle htmlContent={articleHtml} contentLang={lang} />
|
|
66
|
+
</div>
|
|
67
|
+
</PageWrapper>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
@@ -1,56 +1,21 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { getPrimaryInfo } from "../utils";
|
|
3
|
+
import { ArticleWrapper } from "../wrapper";
|
|
4
|
+
import { PageWrapper } from "@c-rex/components/page-wrapper";
|
|
5
|
+
import { DOCUMENTS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
6
6
|
|
|
7
7
|
export const DocumentsPageTemplate = async ({ params }: { params: { id: string } }) => {
|
|
8
|
-
const {
|
|
9
|
-
|
|
10
|
-
const availableVersions = availableVersionsAux.map((item) => {
|
|
11
|
-
return {
|
|
12
|
-
link: `/documents/${item.shortId}`,
|
|
13
|
-
...item,
|
|
14
|
-
}
|
|
15
|
-
})
|
|
8
|
+
const { htmlContent, title, lang } = await getPrimaryInfo(params.id, DOCUMENTS_TYPE_AND_LINK);
|
|
16
9
|
|
|
17
10
|
return (
|
|
18
|
-
<
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
variant="floating"
|
|
26
|
-
collapsible="icon"
|
|
11
|
+
<PageWrapper title={title}>
|
|
12
|
+
<ArticleWrapper
|
|
13
|
+
title={title}
|
|
14
|
+
htmlContent={htmlContent}
|
|
15
|
+
lang={lang}
|
|
16
|
+
id={params.id}
|
|
17
|
+
type={DOCUMENTS_TYPE_AND_LINK}
|
|
27
18
|
/>
|
|
28
|
-
|
|
29
|
-
<div className="container flex flex-col">
|
|
30
|
-
<header className="flex h-16 shrink-0 items-center justify-between">
|
|
31
|
-
<div className="flex shrink-0 items-center">
|
|
32
|
-
<Breadcrumb items={[
|
|
33
|
-
{
|
|
34
|
-
link: "/",
|
|
35
|
-
label: title,
|
|
36
|
-
id: "title",
|
|
37
|
-
active: false,
|
|
38
|
-
children: [],
|
|
39
|
-
}
|
|
40
|
-
]} />
|
|
41
|
-
</div>
|
|
42
|
-
</header>
|
|
43
|
-
|
|
44
|
-
<div style={{ width: '100%', height: '90.6vh' }}>
|
|
45
|
-
<iframe
|
|
46
|
-
width="100%"
|
|
47
|
-
height="100%"
|
|
48
|
-
style={{ border: 'none' }}
|
|
49
|
-
src={documentURL}
|
|
50
|
-
/>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
</SidebarInset>
|
|
54
|
-
</SidebarProvider>
|
|
19
|
+
</PageWrapper>
|
|
55
20
|
);
|
|
56
21
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { getPrimaryInfo } from "../utils";
|
|
3
|
+
import { TOPICS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
4
|
+
import { ArticleWrapper } from "../wrapper";
|
|
5
|
+
import { PageWrapper } from "@c-rex/components/page-wrapper";
|
|
6
|
+
|
|
7
|
+
export const TopicsPageTemplate = async ({ params }: { params: { id: string } }) => {
|
|
8
|
+
const { htmlContent, title, lang } = await getPrimaryInfo(params.id, TOPICS_TYPE_AND_LINK);
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<PageWrapper title={title}>
|
|
12
|
+
<ArticleWrapper
|
|
13
|
+
title={title}
|
|
14
|
+
lang={lang}
|
|
15
|
+
htmlContent={htmlContent}
|
|
16
|
+
id={params.id}
|
|
17
|
+
type={TOPICS_TYPE_AND_LINK}
|
|
18
|
+
/>
|
|
19
|
+
</PageWrapper>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use server"
|
|
2
|
+
|
|
3
|
+
import { DirectoryNodesService, InformationUnitsService, RenditionsService } from "@c-rex/services";
|
|
4
|
+
import { DOCUMENTS_TYPE_AND_LINK, TOPICS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
5
|
+
import { DirectoryNodes } from "@c-rex/interfaces";
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* Get primary info for a given information unit
|
|
9
|
+
* @param id: string
|
|
10
|
+
* @param type: string
|
|
11
|
+
* @returns { htmlContent: string, title: string }
|
|
12
|
+
*/
|
|
13
|
+
export const getPrimaryInfo = async (id: string, type: string): Promise<{
|
|
14
|
+
htmlContent: string,
|
|
15
|
+
title: string,
|
|
16
|
+
lang: string
|
|
17
|
+
}> => {
|
|
18
|
+
const renditionService = new RenditionsService();
|
|
19
|
+
const informationService = new InformationUnitsService();
|
|
20
|
+
const informationUnitsItem = await informationService.getItem({ id });
|
|
21
|
+
|
|
22
|
+
let title = informationUnitsItem.labels[0]?.value
|
|
23
|
+
const lang = informationUnitsItem.languages[0];
|
|
24
|
+
const rootNode = await getRootNode(informationUnitsItem.directoryNodes);
|
|
25
|
+
let htmlContent = ""
|
|
26
|
+
|
|
27
|
+
if (rootNode != null) {
|
|
28
|
+
title = rootNode.informationUnits[0]?.labels[0]?.value;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (type == TOPICS_TYPE_AND_LINK) {
|
|
32
|
+
htmlContent = await renditionService.getHTMLRendition({ renditions: informationUnitsItem.renditions });
|
|
33
|
+
} else if (rootNode != null && type == DOCUMENTS_TYPE_AND_LINK) {
|
|
34
|
+
const directoryId = rootNode.childNodes[0]?.shortId as string;
|
|
35
|
+
const service = new DirectoryNodesService();
|
|
36
|
+
const response = await service.getItem(directoryId);
|
|
37
|
+
const infoId = response.informationUnits[0]?.shortId;
|
|
38
|
+
|
|
39
|
+
const childInformationUnit = await informationService.getItem({ id: infoId as string });
|
|
40
|
+
htmlContent = await renditionService.getHTMLRendition({ renditions: childInformationUnit.renditions });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
htmlContent,
|
|
45
|
+
title: title as string,
|
|
46
|
+
lang: lang as string,
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const getRootNode = async (directoryNodes: DirectoryNodes[]): Promise<DirectoryNodes | null> => {
|
|
51
|
+
const service = new DirectoryNodesService();
|
|
52
|
+
|
|
53
|
+
if (directoryNodes.length == 0 || directoryNodes[0] == undefined) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let id = directoryNodes[0].shortId;
|
|
58
|
+
let response = await service.getItem(id);
|
|
59
|
+
|
|
60
|
+
while (response.parents != undefined) {
|
|
61
|
+
|
|
62
|
+
const hasInfo = (response.informationUnits != undefined) && (response.informationUnits[0] != undefined);
|
|
63
|
+
const hasLabel = (response.labels != undefined) && (response.labels[0] != undefined);
|
|
64
|
+
const hasParent = (response.parents != undefined) && (response.parents[0] != undefined);
|
|
65
|
+
|
|
66
|
+
if (!hasInfo || !hasLabel || !hasParent) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
id = response.parents[0]?.shortId as string;
|
|
71
|
+
response = await service.getItem(id);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return response;
|
|
75
|
+
};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import React, { useEffect, useState } from "react";
|
|
4
|
+
import { SidebarInset, SidebarProvider } from "@c-rex/ui/sidebar";
|
|
5
|
+
import { AppSidebar } from "@c-rex/components/sidebar";
|
|
6
|
+
import { CheckArticleLangToast } from "@c-rex/components/check-article-lang";
|
|
7
|
+
import { Breadcrumb } from "@c-rex/components/breadcrumb";
|
|
8
|
+
import { RenderArticle } from "@c-rex/components/render-article";
|
|
9
|
+
import { CloudDownload, Eye } from "lucide-react";
|
|
10
|
+
import { informationUnitsItems, informationUnitsResponse, SidebarAvailableVersionsInterface, TreeOfContent } from "@c-rex/interfaces";
|
|
11
|
+
import { DOCUMENTS_TYPE_AND_LINK, TOPICS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
12
|
+
import { call, generateBreadcrumbItems, generateTreeOfContent } from "@c-rex/utils";
|
|
13
|
+
import { DropdownMenu } from "@c-rex/components/dropdown-menu";
|
|
14
|
+
import { FileRenditionType } from "@c-rex/types";
|
|
15
|
+
|
|
16
|
+
type Props = {
|
|
17
|
+
htmlContent: string,
|
|
18
|
+
title: string,
|
|
19
|
+
id: string,
|
|
20
|
+
type: string,
|
|
21
|
+
lang: string,
|
|
22
|
+
}
|
|
23
|
+
type filesRenditions = {
|
|
24
|
+
filesToDownload: FileRenditionType[],
|
|
25
|
+
filesToOpen: FileRenditionType[]
|
|
26
|
+
}
|
|
27
|
+
const loadArticleData = async (id: string, type: string, title: string) => {
|
|
28
|
+
const informationUnitsItem = await call<informationUnitsItems>('InformationUnitsService.getItem', { id: id });
|
|
29
|
+
|
|
30
|
+
const { rootNode, result: treeOfContent } = await generateTreeOfContent(informationUnitsItem.directoryNodes);
|
|
31
|
+
|
|
32
|
+
const articleLanguage = informationUnitsItem.languages[0]
|
|
33
|
+
const versionOf = informationUnitsItem.versionOf.shortId
|
|
34
|
+
|
|
35
|
+
const versions = await call<informationUnitsResponse>("InformationUnitsService.getList", {
|
|
36
|
+
filters: [`versionOf.shortId=${versionOf}`],
|
|
37
|
+
fields: ["renditions", "class", "languages", "labels"],
|
|
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 });
|
|
54
|
+
let rootNodeInfoID = "";
|
|
55
|
+
let breadcrumbItems: TreeOfContent[] = [];
|
|
56
|
+
|
|
57
|
+
if (rootNode != null) {
|
|
58
|
+
rootNodeInfoID = rootNode.informationUnits[0]?.shortId as string;
|
|
59
|
+
|
|
60
|
+
const childInformationUnit = await call<informationUnitsItems>('InformationUnitsService.getItem', { id: rootNodeInfoID });
|
|
61
|
+
documents = await call<filesRenditions>("RenditionsService.getFileRenditions", { renditions: childInformationUnit.renditions });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (type == TOPICS_TYPE_AND_LINK) {
|
|
65
|
+
breadcrumbItems = generateBreadcrumbItems(treeOfContent);
|
|
66
|
+
} else if (rootNode != null && type == DOCUMENTS_TYPE_AND_LINK) {
|
|
67
|
+
if ((treeOfContent !== null && treeOfContent !== undefined) && (treeOfContent[0] !== undefined)) {
|
|
68
|
+
treeOfContent[0].active = true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
breadcrumbItems = [{
|
|
72
|
+
link: "/",
|
|
73
|
+
label: title,
|
|
74
|
+
id: "title",
|
|
75
|
+
active: false,
|
|
76
|
+
children: [],
|
|
77
|
+
}]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
treeOfContent,
|
|
82
|
+
breadcrumbItems,
|
|
83
|
+
availableVersions,
|
|
84
|
+
documents,
|
|
85
|
+
articleLanguage
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const ArticleWrapper = ({ htmlContent, title, id, type, lang }: Props) => {
|
|
90
|
+
const [loading, setLoading] = useState<boolean>(true)
|
|
91
|
+
const [availableVersions, setAvailableVersions] = useState<SidebarAvailableVersionsInterface[]>([])
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
//set available versions on confgi context so will be possible to get the link when change contant language
|
|
95
|
+
const [breadcrumbItems, setBreadcrumbItems] = useState<TreeOfContent[]>([])
|
|
96
|
+
const [treeOfContent, setTreeOfContent] = useState<TreeOfContent[]>([])
|
|
97
|
+
const [documents, setDocuments] = useState<{
|
|
98
|
+
filesToDownload: {
|
|
99
|
+
format: string;
|
|
100
|
+
link: string;
|
|
101
|
+
}[],
|
|
102
|
+
filesToOpen: {
|
|
103
|
+
format: string,
|
|
104
|
+
link: string,
|
|
105
|
+
}[]
|
|
106
|
+
}>({
|
|
107
|
+
filesToDownload: [],
|
|
108
|
+
filesToOpen: [],
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
const fetchData = async () => {
|
|
113
|
+
|
|
114
|
+
const {
|
|
115
|
+
availableVersions,
|
|
116
|
+
treeOfContent,
|
|
117
|
+
documents,
|
|
118
|
+
breadcrumbItems,
|
|
119
|
+
} = await loadArticleData(id, type, title)
|
|
120
|
+
|
|
121
|
+
setAvailableVersions(availableVersions)
|
|
122
|
+
setTreeOfContent(treeOfContent)
|
|
123
|
+
setDocuments(documents)
|
|
124
|
+
setBreadcrumbItems(breadcrumbItems)
|
|
125
|
+
setLoading(false)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fetchData();
|
|
129
|
+
}, [])
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<SidebarProvider>
|
|
133
|
+
<title>{title}</title>
|
|
134
|
+
|
|
135
|
+
<CheckArticleLangToast availableVersions={availableVersions} />
|
|
136
|
+
|
|
137
|
+
<AppSidebar
|
|
138
|
+
lang={lang}
|
|
139
|
+
data={treeOfContent}
|
|
140
|
+
availableVersions={availableVersions}
|
|
141
|
+
loading={loading}
|
|
142
|
+
/>
|
|
143
|
+
<SidebarInset>
|
|
144
|
+
<div className="container flex flex-col">
|
|
145
|
+
<header className="flex h-16 shrink-0 items-center justify-between">
|
|
146
|
+
<Breadcrumb items={breadcrumbItems} loading={loading} lang={lang} />
|
|
147
|
+
|
|
148
|
+
<div className="flex">
|
|
149
|
+
{documents.filesToDownload.length > 0 && (
|
|
150
|
+
<DropdownMenu
|
|
151
|
+
items={documents.filesToDownload}
|
|
152
|
+
icon={<CloudDownload />}
|
|
153
|
+
/>
|
|
154
|
+
)}
|
|
155
|
+
{documents.filesToOpen.length > 0 && (
|
|
156
|
+
<DropdownMenu
|
|
157
|
+
items={documents.filesToOpen}
|
|
158
|
+
icon={<Eye />}
|
|
159
|
+
/>
|
|
160
|
+
)}
|
|
161
|
+
</div>
|
|
162
|
+
</header>
|
|
163
|
+
|
|
164
|
+
<RenderArticle htmlContent={htmlContent} contentLang={lang} />
|
|
165
|
+
</div>
|
|
166
|
+
</SidebarInset>
|
|
167
|
+
</SidebarProvider>
|
|
168
|
+
);
|
|
169
|
+
};
|
package/src/home/layout.tsx
CHANGED
|
@@ -1,87 +1,56 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
import { InformationUnitsService
|
|
4
|
-
import { getConfigs, getCookie } from "@c-rex/utils/next-cookies";
|
|
2
|
+
import { informationUnitsResponse } from "@c-rex/interfaces";
|
|
3
|
+
import { InformationUnitsService } from "@c-rex/services";
|
|
5
4
|
import { HomePage } from "./page";
|
|
6
|
-
import {
|
|
5
|
+
import { PageWrapper } from "@c-rex/components/page-wrapper";
|
|
7
6
|
|
|
8
|
-
interface SearchParams {
|
|
9
|
-
search?: string;
|
|
10
|
-
page?: string;
|
|
11
|
-
language?: string;
|
|
12
|
-
}
|
|
13
7
|
interface HomeProps {
|
|
14
|
-
searchParams:
|
|
8
|
+
searchParams: {
|
|
9
|
+
search?: string;
|
|
10
|
+
page?: string;
|
|
11
|
+
language?: string;
|
|
12
|
+
};
|
|
15
13
|
}
|
|
16
14
|
|
|
17
|
-
const
|
|
18
|
-
search,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
page: 0,
|
|
28
|
-
selectedLanguage: [],
|
|
29
|
-
availableLanguages: [],
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const pageAux = Number(page);
|
|
35
|
-
const configs = await getConfigs();
|
|
36
|
-
const searchValue = search as string;
|
|
37
|
-
const languageService = new LanguageService(configs.languageSwitcher.endpoint);
|
|
38
|
-
const availableLanguagesAndCountries = await languageService.getLanguagesAndCountries();
|
|
39
|
-
|
|
40
|
-
let data = { items: [] } as unknown as informationUnits;
|
|
15
|
+
export const HomeLayout = async ({ searchParams }: HomeProps) => {
|
|
16
|
+
const { search, page, language } = searchParams;
|
|
17
|
+
|
|
18
|
+
let data = {
|
|
19
|
+
items: [],
|
|
20
|
+
pageInfo: {
|
|
21
|
+
pageCount: 0,
|
|
22
|
+
pageNumber: 0
|
|
23
|
+
}
|
|
24
|
+
} as unknown as informationUnitsResponse;
|
|
41
25
|
let selectedLanguages: string[] = [];
|
|
42
26
|
|
|
43
|
-
if (
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
searchValue: searchValue,
|
|
63
|
-
page: pageAux,
|
|
64
|
-
selectedLanguages: selectedLanguages,
|
|
65
|
-
availableLanguages: availableLanguagesAndCountries,
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export const HomeLayout = async ({ searchParams }: HomeProps) => {
|
|
71
|
-
const { data, filters: { selectedLanguages, availableLanguages } } = await loadData(searchParams);
|
|
72
|
-
const jsonConfigs = await getCookie(SDK_CONFIG_KEY);
|
|
73
|
-
if (!jsonConfigs) {
|
|
74
|
-
return null;
|
|
27
|
+
if (search !== undefined) {
|
|
28
|
+
const pageAux = Number(page);
|
|
29
|
+
const searchValue = search;
|
|
30
|
+
|
|
31
|
+
if (language != undefined) {
|
|
32
|
+
const aux = language;
|
|
33
|
+
selectedLanguages = aux.split(",");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (searchValue) {
|
|
37
|
+
const service = new InformationUnitsService();
|
|
38
|
+
|
|
39
|
+
data = await service.getList({
|
|
40
|
+
queries: searchValue.split(" ").join(","),
|
|
41
|
+
page: pageAux,
|
|
42
|
+
fields: ["renditions", "class", "languages", "labels"],
|
|
43
|
+
languages: selectedLanguages
|
|
44
|
+
});
|
|
45
|
+
}
|
|
75
46
|
}
|
|
76
47
|
|
|
77
|
-
const configs: ConfigInterface = JSON.parse(jsonConfigs);
|
|
78
|
-
|
|
79
48
|
return (
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
49
|
+
<PageWrapper title="">
|
|
50
|
+
<HomePage
|
|
51
|
+
data={data}
|
|
52
|
+
selectedLanguages={selectedLanguages}
|
|
53
|
+
/>
|
|
54
|
+
</PageWrapper>
|
|
86
55
|
);
|
|
87
56
|
};
|
package/src/home/page.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import React, { FC } from "react";
|
|
4
|
-
import {
|
|
4
|
+
import { informationUnitsResponse } from "@c-rex/interfaces";
|
|
5
5
|
import { call } from "@c-rex/utils";
|
|
6
6
|
import { Button } from "@c-rex/ui/button";
|
|
7
7
|
import { AutoComplete } from "@c-rex/components/autocomplete";
|
|
@@ -9,22 +9,17 @@ 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
|
|
12
|
+
import { getCookie } from "@c-rex/utils";
|
|
13
13
|
import { CONTENT_LANG_KEY } from "@c-rex/constants";
|
|
14
|
+
import { useAppConfig } from "@c-rex/contexts/config-provider";
|
|
14
15
|
|
|
15
16
|
interface HomePageProps {
|
|
16
|
-
data:
|
|
17
|
+
data: informationUnitsResponse;
|
|
17
18
|
selectedLanguages: string[];
|
|
18
|
-
availableLanguages: any;
|
|
19
|
-
configs: ConfigInterface
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
export const HomePage: FC<HomePageProps> = ({
|
|
23
|
-
|
|
24
|
-
selectedLanguages,
|
|
25
|
-
availableLanguages,
|
|
26
|
-
configs
|
|
27
|
-
}) => {
|
|
21
|
+
export const HomePage: FC<HomePageProps> = ({ data, selectedLanguages }) => {
|
|
22
|
+
const { configs, availableLanguagesAndCountries: availableLanguages, contentLang } = useAppConfig()
|
|
28
23
|
const t = useTranslations();
|
|
29
24
|
const [params, setParams] = useQueryStates({
|
|
30
25
|
search: {
|
|
@@ -44,18 +39,21 @@ export const HomePage: FC<HomePageProps> = ({
|
|
|
44
39
|
const { search } = params;
|
|
45
40
|
|
|
46
41
|
const onSearch = (value: string): Promise<string[]> => {
|
|
47
|
-
return call(
|
|
42
|
+
return call("InformationUnitsService.getSuggestions", { query: value, language: contentLang });
|
|
48
43
|
}
|
|
49
44
|
|
|
50
45
|
const onSelect = (value: string) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
46
|
+
//show loading
|
|
47
|
+
getCookie(CONTENT_LANG_KEY)
|
|
48
|
+
.then((cookie) => cookie.value)
|
|
49
|
+
.then((cookie) => {
|
|
50
|
+
setParams({
|
|
51
|
+
search: value,
|
|
52
|
+
operator: "OR",
|
|
53
|
+
page: 1,
|
|
54
|
+
language: cookie,
|
|
55
|
+
});
|
|
57
56
|
});
|
|
58
|
-
});
|
|
59
57
|
};
|
|
60
58
|
|
|
61
59
|
return (
|
|
@@ -71,7 +69,6 @@ export const HomePage: FC<HomePageProps> = ({
|
|
|
71
69
|
<div className="col-span-12 sm:col-span-3 md:col-span-2">
|
|
72
70
|
<div className="flex justify-end">
|
|
73
71
|
<DialogFilter
|
|
74
|
-
|
|
75
72
|
startSelectedLanguages={selectedLanguages}
|
|
76
73
|
availableLanguages={availableLanguages}
|
|
77
74
|
trigger={(
|
|
@@ -82,7 +79,11 @@ export const HomePage: FC<HomePageProps> = ({
|
|
|
82
79
|
</div>
|
|
83
80
|
</div>
|
|
84
81
|
|
|
85
|
-
<ResultList
|
|
82
|
+
<ResultList
|
|
83
|
+
configs={configs}
|
|
84
|
+
items={data.items}
|
|
85
|
+
pagination={data.pageInfo}
|
|
86
|
+
/>
|
|
86
87
|
</div>
|
|
87
88
|
);
|
|
88
89
|
};
|
package/src/layout.tsx
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { NavBar } from "@c-rex/components/navbar";
|
|
3
2
|
import { NextIntlClientProvider } from 'next-intl';
|
|
4
3
|
import { getLocale } from "next-intl/server";
|
|
4
|
+
import { Toaster } from "@c-rex/ui/sonner"
|
|
5
|
+
import { AppConfigProvider } from "@c-rex/contexts/config-provider";
|
|
6
|
+
import { NuqsAdapter } from 'nuqs/adapters/next/app'
|
|
5
7
|
|
|
6
8
|
interface DefaultRootLayoutProps {
|
|
7
9
|
children: React.ReactNode;
|
|
@@ -11,18 +13,20 @@ export const DefaultRootLayout = async ({ children }: DefaultRootLayoutProps) =>
|
|
|
11
13
|
const locale = await getLocale();
|
|
12
14
|
|
|
13
15
|
return (
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
<
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
<NuqsAdapter>
|
|
17
|
+
<html lang={locale} suppressHydrationWarning>
|
|
18
|
+
<head />
|
|
19
|
+
<body className="min-h-screen bg-background font-sans antialiased">
|
|
20
|
+
<div className="items-center flex flex-col">
|
|
21
|
+
<NextIntlClientProvider>
|
|
22
|
+
<AppConfigProvider>
|
|
23
|
+
<Toaster />
|
|
24
|
+
{children}
|
|
25
|
+
</AppConfigProvider>
|
|
26
|
+
</NextIntlClientProvider>
|
|
27
|
+
</div>
|
|
28
|
+
</body>
|
|
29
|
+
</html>
|
|
30
|
+
</NuqsAdapter>
|
|
27
31
|
);
|
|
28
32
|
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { SidebarInset, SidebarProvider } from "@c-rex/ui/sidebar";
|
|
3
|
-
import { AppSidebar } from "@c-rex/components/sidebar";
|
|
4
|
-
import { Breadcrumb } from "@c-rex/components/breadcrumb";
|
|
5
|
-
import { loadArticleData } from "@c-rex/utils";
|
|
6
|
-
|
|
7
|
-
export const InfoPageTemplate = async ({ params }: { params: { id: string } }) => {
|
|
8
|
-
const {
|
|
9
|
-
availableVersions: availableVersionsAux,
|
|
10
|
-
title,
|
|
11
|
-
treeOfContent,
|
|
12
|
-
breadcrumbItems,
|
|
13
|
-
htmlContent
|
|
14
|
-
} = await loadArticleData(params.id)
|
|
15
|
-
|
|
16
|
-
const availableVersions = availableVersionsAux.map((item) => {
|
|
17
|
-
return {
|
|
18
|
-
link: `/topics/${item.shortId}`,
|
|
19
|
-
...item,
|
|
20
|
-
}
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<SidebarProvider>
|
|
25
|
-
<title>{title}</title>
|
|
26
|
-
|
|
27
|
-
<AppSidebar
|
|
28
|
-
data={treeOfContent}
|
|
29
|
-
availableVersions={availableVersions}
|
|
30
|
-
className="top-20"
|
|
31
|
-
side="right"
|
|
32
|
-
variant="floating"
|
|
33
|
-
collapsible="icon"
|
|
34
|
-
/>
|
|
35
|
-
<SidebarInset>
|
|
36
|
-
<div className="container flex flex-col">
|
|
37
|
-
<header className="flex h-16 shrink-0 items-center justify-between">
|
|
38
|
-
<div className="flex shrink-0 items-center">
|
|
39
|
-
<Breadcrumb items={breadcrumbItems} />
|
|
40
|
-
</div>
|
|
41
|
-
</header>
|
|
42
|
-
|
|
43
|
-
<div
|
|
44
|
-
dangerouslySetInnerHTML={{ __html: htmlContent }}
|
|
45
|
-
/>
|
|
46
|
-
</div>
|
|
47
|
-
</SidebarInset>
|
|
48
|
-
</SidebarProvider>
|
|
49
|
-
);
|
|
50
|
-
};
|