@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c-rex/templates",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src"
@@ -1,33 +1,19 @@
1
- import React from "react";
2
- import { getPrimaryInfo } from "../utils";
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 extractHtmlContent = (htmlString: string) => {
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 getPrimaryInfo(params.id, TOPICS_TYPE_AND_LINK);
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, title, lang } = await getPrimaryInfo(params.id, TOPICS_TYPE_AND_LINK);
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
- <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>
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 { htmlContent, title, lang } = await getPrimaryInfo(params.id, TOPICS_TYPE_AND_LINK);
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
- htmlContent={htmlContent}
44
+ availableVersions={availableVersions}
45
+ htmlContent={articleHtml}
16
46
  id={params.id}
17
47
  type={TOPICS_TYPE_AND_LINK}
18
48
  />
@@ -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 rootNode = await getRootNode(informationUnitsItem.directoryNodes);
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 == TOPICS_TYPE_AND_LINK) {
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
- const directoryId = rootNode.childNodes[0]?.shortId as string;
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
+ }
@@ -1,15 +1,15 @@
1
1
  "use client"
2
2
 
3
- import React, { useEffect, useState } from "react";
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, informationUnitsResponse, SidebarAvailableVersionsInterface, TreeOfContent } from "@c-rex/interfaces";
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
- type filesRenditions = {
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
- 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 });
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 = await call<filesRenditions>("RenditionsService.getFileRenditions", { renditions: childInformationUnit.renditions });
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
- 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
- });
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 (