@c-rex/templates 0.1.7 → 0.1.9
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 +25 -17
- package/src/{articles/blog → blog/article}/page.tsx +5 -5
- package/src/{articles → blog/article}/utils.ts +28 -17
- package/src/blog/home/layout.tsx +59 -0
- package/src/blog/home/page.tsx +323 -0
- package/src/doc/articles/documents.tsx +38 -0
- package/src/{articles/topics/page.tsx → doc/articles/topics.tsx} +10 -6
- package/src/doc/articles/utils.ts +142 -0
- package/src/{articles → doc/articles}/wrapper.tsx +13 -7
- package/src/doc/home/layout.tsx +59 -0
- package/src/doc/home/page.tsx +324 -0
- package/src/articles/documents/page.tsx +0 -21
- package/src/home/layout.tsx +0 -56
- package/src/home/page.tsx +0 -87
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { DirectoryNodesService, InformationUnitsService, RenditionsService } from "@c-rex/services";
|
|
2
|
+
import { DOCUMENTS_TYPE_AND_LINK, TOPICS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
3
|
+
import { DirectoryNodes, informationUnitsResponseItem, SidebarAvailableVersionsInterface } from "@c-rex/interfaces";
|
|
4
|
+
import * as cheerio from 'cheerio'
|
|
5
|
+
import { BLOG_TYPE_AND_LINK } from "@c-rex/constants";
|
|
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
|
+
articleLang: string,
|
|
17
|
+
packageId: string,
|
|
18
|
+
documentLang: string,
|
|
19
|
+
availableVersions: SidebarAvailableVersionsInterface[]
|
|
20
|
+
}> => {
|
|
21
|
+
const renditionService = new RenditionsService();
|
|
22
|
+
const informationService = new InformationUnitsService();
|
|
23
|
+
const informationUnitsItem = await informationService.getItem({ id });
|
|
24
|
+
|
|
25
|
+
let title = informationUnitsItem.labels[0]?.value
|
|
26
|
+
const versionOf = informationUnitsItem.versionOf.shortId
|
|
27
|
+
let documentLang = ""
|
|
28
|
+
const articleLang = informationUnitsItem.languages[0];
|
|
29
|
+
|
|
30
|
+
const promiseList: any = [
|
|
31
|
+
informationService.getList({
|
|
32
|
+
restrict: [`versionOf.shortId=${versionOf}`],
|
|
33
|
+
fields: ["renditions", "class", "languages", "labels"],
|
|
34
|
+
}),
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
const rootNode = await getRootNode(informationUnitsItem.directoryNodes)
|
|
38
|
+
|
|
39
|
+
if (rootNode != null) {
|
|
40
|
+
title = rootNode.informationUnits[0]?.labels[0]?.value;
|
|
41
|
+
documentLang = rootNode.informationUnits[0]?.labels[0]?.language as string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if ([TOPICS_TYPE_AND_LINK, BLOG_TYPE_AND_LINK].includes(type)) {
|
|
45
|
+
promiseList.push(
|
|
46
|
+
renditionService.getHTMLRendition({ renditions: informationUnitsItem.renditions })
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
} else if (rootNode != null && type == DOCUMENTS_TYPE_AND_LINK) {
|
|
50
|
+
|
|
51
|
+
const service = new DirectoryNodesService();
|
|
52
|
+
|
|
53
|
+
const directoryId = rootNode.childNodes[0]?.shortId as string;
|
|
54
|
+
|
|
55
|
+
const response = await service.getItem(directoryId);
|
|
56
|
+
|
|
57
|
+
const infoId = response.informationUnits[0]?.shortId;
|
|
58
|
+
|
|
59
|
+
const childInformationUnit = await informationService.getItem({ id: infoId as string });
|
|
60
|
+
|
|
61
|
+
promiseList.push(
|
|
62
|
+
renditionService.getHTMLRendition({ renditions: childInformationUnit.renditions })
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const [versions, htmlContent] = await Promise.all(promiseList)
|
|
67
|
+
|
|
68
|
+
const availableVersions = versions.items.map((item: informationUnitsResponseItem) => {
|
|
69
|
+
return {
|
|
70
|
+
shortId: item.shortId,
|
|
71
|
+
link: `/${type}/${item.shortId}`,
|
|
72
|
+
lang: item.language,
|
|
73
|
+
country: item.language.split("-")[1],
|
|
74
|
+
active: item.language === articleLang,
|
|
75
|
+
}
|
|
76
|
+
}).sort((a: SidebarAvailableVersionsInterface, b: SidebarAvailableVersionsInterface) => {
|
|
77
|
+
if (a.lang < b.lang) return -1;
|
|
78
|
+
if (a.lang > b.lang) return 1;
|
|
79
|
+
return 0;
|
|
80
|
+
}) as SidebarAvailableVersionsInterface[];
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
htmlContent,
|
|
84
|
+
packageId: informationUnitsItem.packages[0]?.shortId as string,
|
|
85
|
+
title: title as string,
|
|
86
|
+
articleLang: articleLang as string,
|
|
87
|
+
documentLang: documentLang as string,
|
|
88
|
+
availableVersions,
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const getRootNode = async (directoryNodes: DirectoryNodes[]): Promise<DirectoryNodes | null> => {
|
|
93
|
+
const service = new DirectoryNodesService();
|
|
94
|
+
|
|
95
|
+
if (directoryNodes.length == 0 || directoryNodes[0] == undefined) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let id = directoryNodes[0].shortId;
|
|
100
|
+
let response = await service.getItem(id);
|
|
101
|
+
|
|
102
|
+
while (response.parents != undefined) {
|
|
103
|
+
|
|
104
|
+
const hasInfo = (response.informationUnits != undefined) && (response.informationUnits[0] != undefined);
|
|
105
|
+
const hasLabel = (response.labels != undefined) && (response.labels[0] != undefined);
|
|
106
|
+
const hasParent = (response.parents != undefined) && (response.parents[0] != undefined);
|
|
107
|
+
|
|
108
|
+
if (!hasInfo || !hasLabel || !hasParent) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
id = response.parents[0]?.shortId as string;
|
|
113
|
+
response = await service.getItem(id);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return response;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export const getInfoWithCache = async (id: string, type: string, infoCache: any): Promise<Awaited<ReturnType<typeof getPrimaryInfo>>> => {
|
|
120
|
+
if (!infoCache.has(id)) {
|
|
121
|
+
const info = await getPrimaryInfo(id, type);
|
|
122
|
+
infoCache.set(id, info);
|
|
123
|
+
}
|
|
124
|
+
return infoCache.get(id)!;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const extractHtmlContent = (htmlString: string) => {
|
|
128
|
+
const $ = cheerio.load(htmlString)
|
|
129
|
+
|
|
130
|
+
const metaTags = $('meta').map((_, el) => {
|
|
131
|
+
const name = $(el).attr('name')
|
|
132
|
+
const content = $(el).attr('content')
|
|
133
|
+
return name && content ? { name, content } : null
|
|
134
|
+
}).get().filter(Boolean)
|
|
135
|
+
|
|
136
|
+
const articleHtml = $('main').html() || ''
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
metaTags,
|
|
140
|
+
articleHtml,
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -12,14 +12,17 @@ import { DOCUMENTS_TYPE_AND_LINK, TOPICS_TYPE_AND_LINK } from "@c-rex/constants"
|
|
|
12
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
|
+
import { useAppConfig } from "@c-rex/contexts/config-provider";
|
|
15
16
|
|
|
16
17
|
type Props = {
|
|
17
18
|
htmlContent: string,
|
|
18
19
|
title: string,
|
|
19
20
|
id: string,
|
|
20
21
|
type: string,
|
|
21
|
-
|
|
22
|
+
documentLang: string,
|
|
23
|
+
articleLang: string,
|
|
22
24
|
availableVersions: SidebarAvailableVersionsInterface[],
|
|
25
|
+
packageId: string,
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
const loadArticleData = async (id: string, type: string, title: string) => {
|
|
@@ -68,10 +71,10 @@ const loadArticleData = async (id: string, type: string, title: string) => {
|
|
|
68
71
|
}
|
|
69
72
|
};
|
|
70
73
|
|
|
71
|
-
export const ArticleWrapper = ({ htmlContent, title, id, type,
|
|
74
|
+
export const ArticleWrapper = ({ htmlContent, title, id, type, documentLang, articleLang, availableVersions, packageId }: Props) => {
|
|
75
|
+
console.log(availableVersions)
|
|
76
|
+
const { setPackageID, setArticleLang } = useAppConfig()
|
|
72
77
|
const [loading, setLoading] = useState<boolean>(true)
|
|
73
|
-
|
|
74
|
-
//set available versions on confgi context so will be possible to get the link when change contant language
|
|
75
78
|
const [breadcrumbItems, setBreadcrumbItems] = useState<TreeOfContent[]>([])
|
|
76
79
|
const [treeOfContent, setTreeOfContent] = useState<TreeOfContent[]>([])
|
|
77
80
|
const [documents, setDocuments] = useState<{
|
|
@@ -89,6 +92,9 @@ export const ArticleWrapper = ({ htmlContent, title, id, type, lang, availableVe
|
|
|
89
92
|
})
|
|
90
93
|
|
|
91
94
|
useEffect(() => {
|
|
95
|
+
setPackageID(packageId)
|
|
96
|
+
setArticleLang(articleLang)
|
|
97
|
+
|
|
92
98
|
const fetchData = async () => {
|
|
93
99
|
const {
|
|
94
100
|
treeOfContent,
|
|
@@ -112,7 +118,7 @@ export const ArticleWrapper = ({ htmlContent, title, id, type, lang, availableVe
|
|
|
112
118
|
<CheckArticleLangToast availableVersions={availableVersions} />
|
|
113
119
|
|
|
114
120
|
<AppSidebar
|
|
115
|
-
lang={
|
|
121
|
+
lang={documentLang}
|
|
116
122
|
data={treeOfContent}
|
|
117
123
|
availableVersions={availableVersions}
|
|
118
124
|
loading={loading}
|
|
@@ -120,7 +126,7 @@ export const ArticleWrapper = ({ htmlContent, title, id, type, lang, availableVe
|
|
|
120
126
|
<SidebarInset>
|
|
121
127
|
<div className="container flex flex-col">
|
|
122
128
|
<header className="flex h-16 shrink-0 items-center justify-between">
|
|
123
|
-
<Breadcrumb items={breadcrumbItems} loading={loading} lang={
|
|
129
|
+
<Breadcrumb items={breadcrumbItems} loading={loading} lang={documentLang} />
|
|
124
130
|
|
|
125
131
|
<div className="flex">
|
|
126
132
|
{documents.filesToDownload.length > 0 && (
|
|
@@ -138,7 +144,7 @@ export const ArticleWrapper = ({ htmlContent, title, id, type, lang, availableVe
|
|
|
138
144
|
</div>
|
|
139
145
|
</header>
|
|
140
146
|
|
|
141
|
-
<RenderArticle htmlContent={htmlContent} contentLang={
|
|
147
|
+
<RenderArticle htmlContent={htmlContent} contentLang={articleLang} />
|
|
142
148
|
</div>
|
|
143
149
|
</SidebarInset>
|
|
144
150
|
</SidebarProvider>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { informationUnitsResponse } from "@c-rex/interfaces";
|
|
2
|
+
import { InformationUnitsService } from "@c-rex/services";
|
|
3
|
+
import { HomePage } from "./page";
|
|
4
|
+
import { PageWrapper } from "@c-rex/components/page-wrapper";
|
|
5
|
+
import { WildCardType } from "@c-rex/types";
|
|
6
|
+
|
|
7
|
+
interface HomeProps {
|
|
8
|
+
searchParams: {
|
|
9
|
+
search?: string;
|
|
10
|
+
page: string;
|
|
11
|
+
language: string;
|
|
12
|
+
wildcard: string;
|
|
13
|
+
operator: string;
|
|
14
|
+
like: string;
|
|
15
|
+
packages?: string;
|
|
16
|
+
filter?: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const HomeLayout = async ({ searchParams }: HomeProps) => {
|
|
21
|
+
const { search, page, language, wildcard, operator, like, packages, filter } = searchParams;
|
|
22
|
+
|
|
23
|
+
let data = {
|
|
24
|
+
items: [],
|
|
25
|
+
pageInfo: {
|
|
26
|
+
pageCount: 0,
|
|
27
|
+
pageNumber: 0
|
|
28
|
+
}
|
|
29
|
+
} as unknown as informationUnitsResponse;
|
|
30
|
+
|
|
31
|
+
if (search !== undefined) {
|
|
32
|
+
|
|
33
|
+
const filters: string[] = filter?.split(",") || []
|
|
34
|
+
const restrict: string[] = []
|
|
35
|
+
|
|
36
|
+
if (packages && packages.length > 0) {
|
|
37
|
+
restrict.push(`packages.shortId=${packages}`)
|
|
38
|
+
}
|
|
39
|
+
const service = new InformationUnitsService();
|
|
40
|
+
|
|
41
|
+
data = await service.getList({
|
|
42
|
+
queries: search,
|
|
43
|
+
page: Number(page),
|
|
44
|
+
fields: ["renditions", "class", "languages", "labels"],
|
|
45
|
+
languages: language.split(","),
|
|
46
|
+
wildcard: wildcard as WildCardType,
|
|
47
|
+
restrict: restrict,
|
|
48
|
+
operator: operator,
|
|
49
|
+
like: Boolean(like === "true"),
|
|
50
|
+
filters: filters
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<PageWrapper title="" pageType="HOME">
|
|
56
|
+
<HomePage data={data} />
|
|
57
|
+
</PageWrapper>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React, { FC, useEffect, useState } from "react";
|
|
4
|
+
import { Trash2, X } from "lucide-react"
|
|
5
|
+
import { useTranslations } from 'next-intl'
|
|
6
|
+
import { parseAsBoolean, parseAsInteger, parseAsString, useQueryStates } from 'nuqs'
|
|
7
|
+
import { informationUnitsResponse } from "@c-rex/interfaces";
|
|
8
|
+
import { Button } from "@c-rex/ui/button";
|
|
9
|
+
import { Badge } from "@c-rex/ui/badge";
|
|
10
|
+
import {
|
|
11
|
+
SidebarContent,
|
|
12
|
+
SidebarGroup,
|
|
13
|
+
SidebarGroupContent,
|
|
14
|
+
SidebarGroupLabel,
|
|
15
|
+
SidebarHeader,
|
|
16
|
+
SidebarMenu,
|
|
17
|
+
SidebarMenuSub,
|
|
18
|
+
SidebarMenuSubButton,
|
|
19
|
+
SidebarMenuSubItem
|
|
20
|
+
} from "@c-rex/ui/sidebar";
|
|
21
|
+
import { ResultList } from "@c-rex/components/result-list";
|
|
22
|
+
import { DialogFilter } from "@c-rex/components/dialog-filter";
|
|
23
|
+
import { useAppConfig } from "@c-rex/contexts/config-provider";
|
|
24
|
+
import { AutoComplete } from "@c-rex/components/autocomplete";
|
|
25
|
+
import { OPERATOR_OPTIONS, WILD_CARD_OPTIONS } from "@c-rex/constants";
|
|
26
|
+
import { Loading } from "@c-rex/components/loading";
|
|
27
|
+
|
|
28
|
+
interface HomePageProps {
|
|
29
|
+
data: informationUnitsResponse;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type filterModel = {
|
|
33
|
+
key: string
|
|
34
|
+
name?: string
|
|
35
|
+
value: string
|
|
36
|
+
default?: string | boolean | null
|
|
37
|
+
removable: boolean
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const HomePage: FC<HomePageProps> = ({ data }) => {
|
|
41
|
+
const t = useTranslations();
|
|
42
|
+
const { configs } = useAppConfig()
|
|
43
|
+
|
|
44
|
+
const [tags, setTags] = useState<{ [key: string]: any[] }>(data.tags || {});
|
|
45
|
+
const [filters, setFilters] = useState<filterModel[] | null>(null)
|
|
46
|
+
const [disabled, setDisabled] = useState<boolean>(false)
|
|
47
|
+
const [loading, setLoading] = useState<boolean>(true)
|
|
48
|
+
const [params, setParams] = useQueryStates({
|
|
49
|
+
language: parseAsString,
|
|
50
|
+
page: parseAsInteger,
|
|
51
|
+
wildcard: parseAsString,
|
|
52
|
+
operator: parseAsString,
|
|
53
|
+
packages: parseAsString,
|
|
54
|
+
filter: parseAsString,
|
|
55
|
+
like: parseAsBoolean,
|
|
56
|
+
search: {
|
|
57
|
+
defaultValue: "",
|
|
58
|
+
parse(value) {
|
|
59
|
+
return value
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
}, {
|
|
63
|
+
history: 'push',
|
|
64
|
+
shallow: false,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (params.search.length > 0) {
|
|
69
|
+
setDisabled(false)
|
|
70
|
+
generateFiltersObj()
|
|
71
|
+
} else {
|
|
72
|
+
setDisabled(true)
|
|
73
|
+
setFilters(null)
|
|
74
|
+
}
|
|
75
|
+
}, [params])
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
const newTags = { ...data.tags }
|
|
79
|
+
|
|
80
|
+
if (params.filter !== null) {
|
|
81
|
+
const splittedParam = params.filter.split(",")
|
|
82
|
+
|
|
83
|
+
splittedParam.forEach((item) => {
|
|
84
|
+
const aux = item.split(".shortId=")
|
|
85
|
+
const name = aux[0] as string
|
|
86
|
+
const shortId = aux[1] as string
|
|
87
|
+
|
|
88
|
+
if (!Object.keys(newTags).includes(name)) {
|
|
89
|
+
newTags[name] = []
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
newTags[name].forEach((el: any) => {
|
|
93
|
+
if (el.shortId == shortId) {
|
|
94
|
+
el.active = true
|
|
95
|
+
} else {
|
|
96
|
+
el.active = false
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (params.packages !== null && newTags["packages"]) {
|
|
103
|
+
newTags["packages"].forEach((el: any) => {
|
|
104
|
+
if (el.shortId == params.packages) {
|
|
105
|
+
el.active = true
|
|
106
|
+
} else {
|
|
107
|
+
el.active = false
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
setTags(newTags)
|
|
113
|
+
setLoading(false)
|
|
114
|
+
}, [data])
|
|
115
|
+
|
|
116
|
+
const generateFiltersObj = () => {
|
|
117
|
+
const filters: filterModel[] = [{
|
|
118
|
+
key: "operator",
|
|
119
|
+
name: t("filter.operator"),
|
|
120
|
+
value: `${params?.operator !== OPERATOR_OPTIONS.OR}`,
|
|
121
|
+
default: OPERATOR_OPTIONS.OR,
|
|
122
|
+
removable: params?.operator !== OPERATOR_OPTIONS.OR
|
|
123
|
+
}, {
|
|
124
|
+
key: "like",
|
|
125
|
+
name: t("filter.like"),
|
|
126
|
+
value: `${params.like}`,
|
|
127
|
+
default: false,
|
|
128
|
+
removable: params?.like as boolean
|
|
129
|
+
}, {
|
|
130
|
+
key: "wildcard",
|
|
131
|
+
value: params.wildcard as string,
|
|
132
|
+
default: WILD_CARD_OPTIONS.NONE,
|
|
133
|
+
removable: params?.wildcard !== WILD_CARD_OPTIONS.NONE
|
|
134
|
+
}]
|
|
135
|
+
|
|
136
|
+
const languages = params.language?.split(",")
|
|
137
|
+
languages?.forEach((item) => {
|
|
138
|
+
const aux = languages?.filter(langItem => langItem !== item)
|
|
139
|
+
filters.push({ key: "language", value: item, removable: languages.length > 1, default: aux.join(",") })
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
if (params.filter !== null) {
|
|
143
|
+
const splittedParam = params.filter.split(",")
|
|
144
|
+
|
|
145
|
+
splittedParam.forEach((item, index) => {
|
|
146
|
+
const aux = item.split(".shortId=")
|
|
147
|
+
const name = aux[0] as string
|
|
148
|
+
const shortId = aux[1] as string
|
|
149
|
+
|
|
150
|
+
const defaultValue = [...splittedParam]
|
|
151
|
+
defaultValue.splice(index, 1)
|
|
152
|
+
|
|
153
|
+
if (!Object.keys(tags).includes(name) || !tags[name]) return;
|
|
154
|
+
|
|
155
|
+
const tag = tags[name].find(el => el.shortId === shortId)
|
|
156
|
+
if (!tag) return;
|
|
157
|
+
|
|
158
|
+
const value = defaultValue.length == 0 ? null : defaultValue.join(",")
|
|
159
|
+
|
|
160
|
+
filters.push({ key: "filter", name: t(`filter.tags.${name}`), value: tag.label, removable: true, default: value })
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (params.packages !== null && tags["packages"]) {
|
|
165
|
+
const packageTag = tags["packages"]?.find(el => el.shortId === params.packages)
|
|
166
|
+
filters.push({
|
|
167
|
+
key: "packages",
|
|
168
|
+
name: t("filter.tags.packages"),
|
|
169
|
+
value: packageTag.label,
|
|
170
|
+
removable: true,
|
|
171
|
+
default: null
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
Object.keys(params)
|
|
176
|
+
.filter(item => !["page", "search", "language", "operator", "like", "wildcard", "filter", "packages"].includes(item))
|
|
177
|
+
.forEach(item => {
|
|
178
|
+
if (params[item as keyof typeof params] === null || params[item as keyof typeof params] === undefined) return;
|
|
179
|
+
const value = params[item as keyof typeof params] as string
|
|
180
|
+
filters.push({ key: item, value: value, removable: true, default: null })
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
setFilters(filters)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const updateFilterParam = (key: string, item: any) => {
|
|
187
|
+
setLoading(true)
|
|
188
|
+
if (key === "packages") {
|
|
189
|
+
setParams({ packages: item.shortId })
|
|
190
|
+
return;
|
|
191
|
+
} else {
|
|
192
|
+
const value = `${key}.shortId=${item.shortId}`
|
|
193
|
+
let aux = value
|
|
194
|
+
|
|
195
|
+
if (params.filter != null) {
|
|
196
|
+
const splittedParam = params.filter.split(",")
|
|
197
|
+
const finalValue = [...splittedParam]
|
|
198
|
+
|
|
199
|
+
const hasParams = params.filter.includes(key)
|
|
200
|
+
|
|
201
|
+
if (hasParams) {
|
|
202
|
+
let mainIndex = -1
|
|
203
|
+
|
|
204
|
+
splittedParam.forEach((el, index) => {
|
|
205
|
+
if (el.includes(key)) {
|
|
206
|
+
mainIndex = index
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
finalValue[mainIndex] = value
|
|
210
|
+
} else {
|
|
211
|
+
finalValue.push(value)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
aux = finalValue.join(",")
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
setParams({ filter: aux })
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
return (
|
|
222
|
+
<div className="container">
|
|
223
|
+
{loading && <Loading opacity={true} />}
|
|
224
|
+
|
|
225
|
+
<div className="grid grid-cols-12 gap-4 py-6">
|
|
226
|
+
<div className="col-span-12 sm:col-span-10 md:col-span-10">
|
|
227
|
+
<AutoComplete
|
|
228
|
+
embedded={false}
|
|
229
|
+
initialValue={params.search}
|
|
230
|
+
searchByPackage={false}
|
|
231
|
+
/>
|
|
232
|
+
</div>
|
|
233
|
+
<div className="col-span-12 sm:col-span-2 md:col-span-2">
|
|
234
|
+
<div className="flex justify-end">
|
|
235
|
+
<DialogFilter
|
|
236
|
+
setLoading={setLoading}
|
|
237
|
+
trigger={(
|
|
238
|
+
<Button variant="default" disabled={disabled}>{t("filter.filters")}</Button>
|
|
239
|
+
)}
|
|
240
|
+
/>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
|
|
245
|
+
{filters != null && filters.length > 0 && (
|
|
246
|
+
<div className="pb-4 flex justify-between">
|
|
247
|
+
<div>
|
|
248
|
+
|
|
249
|
+
{filters?.map((item) => (
|
|
250
|
+
<Badge key={`${item.key}-${item?.value}`} variant="outline" className="mr-2 mb-2 h-6">
|
|
251
|
+
{item?.name ? item.name : item.key}: {item.value}
|
|
252
|
+
{item.removable && (
|
|
253
|
+
<Button size="xs" variant="ghost" onClick={() => {
|
|
254
|
+
setLoading(true)
|
|
255
|
+
setParams({ [item.key]: item?.default })
|
|
256
|
+
}}>
|
|
257
|
+
<X className="h-2" />
|
|
258
|
+
</Button>
|
|
259
|
+
)}
|
|
260
|
+
</Badge>
|
|
261
|
+
))}
|
|
262
|
+
|
|
263
|
+
</div>
|
|
264
|
+
<Button
|
|
265
|
+
size="sm"
|
|
266
|
+
variant="outline"
|
|
267
|
+
disabled={params.filter === null}
|
|
268
|
+
onClick={() => {
|
|
269
|
+
setLoading(true)
|
|
270
|
+
setParams({ filter: null, packages: null })
|
|
271
|
+
}}
|
|
272
|
+
>
|
|
273
|
+
{t("filter.clearFilters")}
|
|
274
|
+
<Trash2 className="h-2" />
|
|
275
|
+
</Button>
|
|
276
|
+
</div>
|
|
277
|
+
)}
|
|
278
|
+
|
|
279
|
+
<div className="flex flex-row gap-6 pb-6">
|
|
280
|
+
{data.items.length > 0 && (
|
|
281
|
+
<div className="w-80 bg-sidebar rounded-md border pb-4">
|
|
282
|
+
<SidebarHeader className="text-center font-bold">
|
|
283
|
+
Search Filters
|
|
284
|
+
</SidebarHeader>
|
|
285
|
+
<SidebarContent>
|
|
286
|
+
{Object.entries(tags).map(([key, value]: any) => (
|
|
287
|
+
<SidebarGroup key={key} className="py-0">
|
|
288
|
+
<SidebarGroupLabel>
|
|
289
|
+
{t(`filter.tags.${key}`)}
|
|
290
|
+
</SidebarGroupLabel>
|
|
291
|
+
<SidebarGroupContent>
|
|
292
|
+
<SidebarMenu>
|
|
293
|
+
<SidebarMenuSub>
|
|
294
|
+
{value.map((item: any) => (
|
|
295
|
+
<SidebarMenuSubItem key={item.shortId}>
|
|
296
|
+
<SidebarMenuSubButton
|
|
297
|
+
className="cursor-pointer"
|
|
298
|
+
isActive={item.active}
|
|
299
|
+
onClick={() => updateFilterParam(key, item)}
|
|
300
|
+
>
|
|
301
|
+
{item.label} ({item.hits}/{item.total})
|
|
302
|
+
</SidebarMenuSubButton>
|
|
303
|
+
</SidebarMenuSubItem>
|
|
304
|
+
))}
|
|
305
|
+
</SidebarMenuSub>
|
|
306
|
+
</SidebarMenu>
|
|
307
|
+
</SidebarGroupContent>
|
|
308
|
+
</SidebarGroup>
|
|
309
|
+
))}
|
|
310
|
+
</SidebarContent>
|
|
311
|
+
</div>
|
|
312
|
+
)}
|
|
313
|
+
|
|
314
|
+
<div className="flex-1">
|
|
315
|
+
<ResultList
|
|
316
|
+
configs={configs}
|
|
317
|
+
items={data.items}
|
|
318
|
+
pagination={data.pageInfo}
|
|
319
|
+
/>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
);
|
|
324
|
+
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { getPrimaryInfo } from "../utils";
|
|
2
|
-
import { ArticleWrapper } from "../wrapper";
|
|
3
|
-
import { PageWrapper } from "@c-rex/components/page-wrapper";
|
|
4
|
-
import { DOCUMENTS_TYPE_AND_LINK } from "@c-rex/constants";
|
|
5
|
-
|
|
6
|
-
export const DocumentsPageTemplate = async ({ params }: { params: { id: string } }) => {
|
|
7
|
-
const { htmlContent, title, lang, availableVersions } = await getPrimaryInfo(params.id, DOCUMENTS_TYPE_AND_LINK);
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<PageWrapper title={title}>
|
|
11
|
-
<ArticleWrapper
|
|
12
|
-
title={title}
|
|
13
|
-
availableVersions={availableVersions}
|
|
14
|
-
htmlContent={htmlContent}
|
|
15
|
-
lang={lang}
|
|
16
|
-
id={params.id}
|
|
17
|
-
type={DOCUMENTS_TYPE_AND_LINK}
|
|
18
|
-
/>
|
|
19
|
-
</PageWrapper>
|
|
20
|
-
);
|
|
21
|
-
};
|
package/src/home/layout.tsx
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { informationUnitsResponse } from "@c-rex/interfaces";
|
|
3
|
-
import { InformationUnitsService } from "@c-rex/services";
|
|
4
|
-
import { HomePage } from "./page";
|
|
5
|
-
import { PageWrapper } from "@c-rex/components/page-wrapper";
|
|
6
|
-
|
|
7
|
-
interface HomeProps {
|
|
8
|
-
searchParams: {
|
|
9
|
-
search?: string;
|
|
10
|
-
page?: string;
|
|
11
|
-
language?: string;
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
|
|
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;
|
|
25
|
-
let selectedLanguages: string[] = [];
|
|
26
|
-
|
|
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
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<PageWrapper title="">
|
|
50
|
-
<HomePage
|
|
51
|
-
data={data}
|
|
52
|
-
selectedLanguages={selectedLanguages}
|
|
53
|
-
/>
|
|
54
|
-
</PageWrapper>
|
|
55
|
-
);
|
|
56
|
-
};
|