@c-rex/components 0.1.37 → 0.1.39
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/README.md +73 -73
- package/package.json +250 -235
- package/src/article/article-action-bar.tsx +110 -110
- package/src/article/article-content.tsx +18 -46
- package/src/autocomplete.tsx +201 -201
- package/src/breadcrumb.tsx +124 -124
- package/src/carousel/carousel.tsx +353 -352
- package/src/check-article-lang.tsx +47 -43
- package/src/directoryNodes/directory-tree-context.tsx +388 -0
- package/src/directoryNodes/tree-of-content.tsx +68 -67
- package/src/documents/result-list.tsx +124 -127
- package/src/favorites/bookmark-button.tsx +97 -79
- package/src/favorites/favorite-button.tsx +137 -74
- package/src/footer/footer-shell.tsx +52 -0
- package/src/footer/footer.tsx +7 -0
- package/src/footer/legal-links-block.tsx +25 -0
- package/src/footer/organization-contact-block.tsx +94 -0
- package/src/footer/social-links-block.tsx +38 -0
- package/src/footer/types.ts +10 -0
- package/src/footer/vcard-footer.tsx +72 -0
- package/src/generated/client-components.tsx +1366 -1350
- package/src/generated/create-client-request.tsx +116 -113
- package/src/generated/create-server-request.tsx +70 -61
- package/src/generated/create-suggestions-request.tsx +55 -55
- package/src/generated/server-components.tsx +1056 -1056
- package/src/generated/suggestions.tsx +302 -299
- package/src/icons/file-icon.tsx +8 -8
- package/src/icons/flag-icon.tsx +15 -15
- package/src/icons/loading.tsx +11 -11
- package/src/icons/social-icon.tsx +24 -0
- package/src/info/info-card.tsx +43 -0
- package/src/info/{info-table.tsx → information-unit-metadata-grid.tsx} +157 -146
- package/src/info/shared.tsx +49 -25
- package/src/navbar/language-switcher/content-language-switch.tsx +92 -92
- package/src/navbar/language-switcher/shared.tsx +33 -33
- package/src/navbar/language-switcher/ui-language-switch.tsx +37 -38
- package/src/navbar/navbar.tsx +157 -148
- package/src/navbar/settings.tsx +62 -62
- package/src/navbar/sign-in-out-btns.tsx +35 -35
- package/src/navbar/user-menu.tsx +60 -60
- package/src/page-wrapper.tsx +54 -31
- package/src/render-article.module.css +155 -0
- package/src/render-article.tsx +75 -68
- package/src/renditions/file-download.tsx +83 -83
- package/src/renditions/html.tsx +64 -64
- package/src/renditions/image/container.tsx +54 -54
- package/src/renditions/image/rendition.tsx +55 -55
- package/src/restriction-menu/restriction-menu-container.tsx +117 -53
- package/src/restriction-menu/restriction-menu-item.tsx +155 -147
- package/src/restriction-menu/restriction-menu.tsx +341 -157
- package/src/results/dialog-filter.tsx +166 -166
- package/src/results/empty.tsx +15 -15
- package/src/results/filter-navbar.tsx +294 -261
- package/src/results/filter-sidebar/__tests__/utils.test.ts +129 -0
- package/src/results/filter-sidebar/index.tsx +270 -126
- package/src/results/filter-sidebar/utils.ts +196 -164
- package/src/results/generic/table-result-list.tsx +97 -99
- package/src/results/{table-with-images.tsx → information-unit-search-results-card-list.tsx} +125 -127
- package/src/results/{cards.tsx → information-unit-search-results-cards.tsx} +99 -99
- package/src/results/{table.tsx → information-unit-search-results-table.tsx} +104 -104
- package/src/results/pagination.tsx +81 -81
- package/src/results/summary.ts +30 -0
- package/src/results/utils.ts +54 -47
- package/src/search-input.tsx +70 -70
- package/src/share-button.tsx +49 -49
- package/src/stores/favorites-store.ts +88 -88
- package/src/stores/highlight-store.ts +15 -15
- package/src/stores/language-store.ts +14 -43
- package/src/stores/restriction-store.ts +11 -11
- package/src/stores/search-settings-store.ts +68 -64
- package/src/article/article-action-bar.analysis.md +0 -15
- package/src/article/article-action-bar.stories.tsx +0 -15
- package/src/article/article-content.analysis.md +0 -15
- package/src/article/article-content.stories.tsx +0 -21
- package/src/autocomplete.analysis.md +0 -17
- package/src/breadcrumb.analysis.md +0 -15
- package/src/carousel/carousel.analysis.md +0 -17
- package/src/check-article-lang.analysis.md +0 -15
- package/src/directoryNodes/tree-of-content.analysis.md +0 -14
- package/src/directoryNodes/tree-of-content.stories.tsx +0 -22
- package/src/documents/result-list.analysis.md +0 -14
- package/src/documents/result-list.stories.tsx +0 -19
- package/src/favorites/bookmark-button.analysis.md +0 -17
- package/src/favorites/bookmark-button.stories.tsx +0 -19
- package/src/favorites/favorite-button.analysis.md +0 -18
- package/src/favorites/favorite-button.stories.tsx +0 -22
- package/src/icons/file-icon.analysis.md +0 -14
- package/src/icons/file-icon.stories.tsx +0 -19
- package/src/icons/flag-icon.analysis.md +0 -14
- package/src/icons/flag-icon.stories.tsx +0 -25
- package/src/icons/loading.analysis.md +0 -14
- package/src/icons/loading.stories.tsx +0 -21
- package/src/info/info-table.analysis.md +0 -15
- package/src/info/shared.analysis.md +0 -14
- package/src/info/stories/info-table.stories.tsx +0 -31
- package/src/info/stories/shared.stories.tsx +0 -24
- package/src/navbar/language-switcher/content-language-switch.analysis.md +0 -15
- package/src/navbar/language-switcher/shared.analysis.md +0 -14
- package/src/navbar/language-switcher/ui-language-switch.analysis.md +0 -15
- package/src/navbar/navbar.analysis.md +0 -14
- package/src/navbar/settings.analysis.md +0 -14
- package/src/navbar/sign-in-out-btns.analysis.md +0 -14
- package/src/navbar/stories/navbar.stories.tsx +0 -31
- package/src/navbar/stories/settings.stories.tsx +0 -15
- package/src/navbar/stories/sign-in-out-btns.stories.tsx +0 -15
- package/src/navbar/stories/user-menu.stories.tsx +0 -20
- package/src/navbar/user-menu.analysis.md +0 -14
- package/src/page-wrapper.analysis.md +0 -14
- package/src/render-article.analysis.md +0 -15
- package/src/renditions/file-download.analysis.md +0 -14
- package/src/renditions/file-download.stories.tsx +0 -19
- package/src/renditions/html.analysis.md +0 -17
- package/src/renditions/html.stories.tsx +0 -19
- package/src/renditions/image/container.analysis.md +0 -15
- package/src/renditions/image/container.stories.tsx +0 -19
- package/src/renditions/image/rendition.analysis.md +0 -14
- package/src/renditions/image/rendition.stories.tsx +0 -19
- package/src/restriction-menu/restriction-menu-container.analysis.md +0 -14
- package/src/restriction-menu/restriction-menu-item.analysis.md +0 -14
- package/src/restriction-menu/restriction-menu.analysis.md +0 -17
- package/src/results/analysis/cards.analysis.md +0 -14
- package/src/results/analysis/dialog-filter.analysis.md +0 -17
- package/src/results/analysis/empty.analysis.md +0 -14
- package/src/results/analysis/filter-navbar.analysis.md +0 -16
- package/src/results/analysis/pagination.analysis.md +0 -14
- package/src/results/analysis/table-with-images.analysis.md +0 -15
- package/src/results/analysis/table.analysis.md +0 -15
- package/src/results/filter-sidebar/index.analysis.md +0 -14
- package/src/results/generic/table-result-list.analysis.md +0 -15
- package/src/results/generic/table-result-list.stories.tsx +0 -21
- package/src/results/stories/cards.stories.tsx +0 -66
- package/src/results/stories/dialog-filter.stories.tsx +0 -20
- package/src/results/stories/empty.stories.tsx +0 -25
- package/src/results/stories/filter-navbar.stories.tsx +0 -19
- package/src/results/stories/filter-sidebar.stories.tsx +0 -20
- package/src/results/stories/pagination.stories.tsx +0 -24
- package/src/results/stories/table-with-images.stories.tsx +0 -19
- package/src/results/stories/table.stories.tsx +0 -78
- package/src/search-input.analysis.md +0 -15
- package/src/share-button.analysis.md +0 -19
- package/src/stories/autocomplete.stories.tsx +0 -20
- package/src/stories/breadcrumb.stories.tsx +0 -93
- package/src/stories/check-article-lang.stories.tsx +0 -22
- package/src/stories/render-article.stories.tsx +0 -19
- package/src/stories/search-input.stories.tsx +0 -21
- package/src/stories/share-button.stories.tsx +0 -15
|
@@ -1,104 +1,104 @@
|
|
|
1
|
-
import { FC } from "react";
|
|
2
|
-
import { informationUnitsResponseItem } from "@c-rex/interfaces";
|
|
3
|
-
import { useTranslations } from "next-intl";
|
|
4
|
-
import { CloudDownload, Eye } from "lucide-react";
|
|
5
|
-
import { FaFilePdf } from "react-icons/fa6";
|
|
6
|
-
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@c-rex/ui/dropdown-menu";
|
|
7
|
-
import { cn } from "@c-rex/utils";
|
|
8
|
-
import { Flag } from "../icons/flag-icon";
|
|
9
|
-
import { Badge } from "@c-rex/ui/badge";
|
|
10
|
-
import { useQueryState } from "nuqs";
|
|
11
|
-
|
|
12
|
-
interface
|
|
13
|
-
items: informationUnitsResponseItem[];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const IconsToFileExtension: Record<string, React.ReactNode> = {
|
|
17
|
-
"application/pdf": <FaFilePdf className="h-6 w-6" />,
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const t = useTranslations("results")
|
|
22
|
-
const [query] = useQueryState("search");
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<div className="rounded-md border mb-6 last:border-b-0">
|
|
27
|
-
<div className="font-bold text-sm p-2 border-b items-center flex-wrap hidden md:flex">
|
|
28
|
-
<div className="w-1/2 md:w-2/5 p-2">{t("title")}</div>
|
|
29
|
-
<div className="w-1/2 md:w-1/5 p-2 flex justify-center">{t("language")}</div>
|
|
30
|
-
<div className="w-1/2 md:w-1/5 p-2">{t("type")}</div>
|
|
31
|
-
<div className="w-1/2 md:w-1/5 p-2 flex justify-center">{t("files")}</div>
|
|
32
|
-
</div>
|
|
33
|
-
|
|
34
|
-
{items.map((item) => (
|
|
35
|
-
<div
|
|
36
|
-
className={cn(
|
|
37
|
-
"min-h-12 c-rex-result-item flex flex-wrap items-center",
|
|
38
|
-
`c-rex-result-${item.type.toLowerCase()}`,
|
|
39
|
-
item.disabled && "c-rex-result-item-disabled",
|
|
40
|
-
"border-b"
|
|
41
|
-
)}
|
|
42
|
-
key={item.shortId}
|
|
43
|
-
>
|
|
44
|
-
<div className="w-4/5 md:w-2/5 p-2">
|
|
45
|
-
{item.disabled ? (item.title) : (<a href={`${item.link}?q=${query}`}>{item.title}</a>)}
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
<div className="w-1/5 md:w-1/5 flex justify-center p-2">
|
|
49
|
-
<span className="w-8 inline-block">
|
|
50
|
-
{item.language.split("-").length > 1 && (
|
|
51
|
-
<Flag countryCode={item.language.split("-")[1] as string} />
|
|
52
|
-
)}
|
|
53
|
-
</span>
|
|
54
|
-
</div>
|
|
55
|
-
|
|
56
|
-
<div className="w-4/5 md:w-1/5 p-2">
|
|
57
|
-
<Badge variant="secondary">
|
|
58
|
-
{item.type}
|
|
59
|
-
</Badge>
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
<div className="w-1/5 flex justify-center p-2">
|
|
63
|
-
{(item.disabled || (Object.keys(item.files).length === 0)) ? (
|
|
64
|
-
null // remove null rendering
|
|
65
|
-
) : (
|
|
66
|
-
<>
|
|
67
|
-
{Object.keys(item.files).map((fileKey) => {
|
|
68
|
-
|
|
69
|
-
if (!item.files[fileKey]) {
|
|
70
|
-
return null
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<DropdownMenu key={fileKey}>
|
|
75
|
-
<DropdownMenuTrigger className="mx-2">
|
|
76
|
-
{IconsToFileExtension[fileKey]}
|
|
77
|
-
</DropdownMenuTrigger>
|
|
78
|
-
<DropdownMenuContent>
|
|
79
|
-
<DropdownMenuItem>
|
|
80
|
-
<a href={item.files[fileKey].view} target="_blank" rel="noreferrer" className="flex items-center">
|
|
81
|
-
<Eye className="mr-2" /> Open {/*TODO: use i18n functions*/}
|
|
82
|
-
</a>
|
|
83
|
-
</DropdownMenuItem>
|
|
84
|
-
<DropdownMenuItem>
|
|
85
|
-
<a href={item.files[fileKey].download} target="_blank" rel="noreferrer" className="flex items-center">
|
|
86
|
-
<CloudDownload className="mr-2" /> Download {/*TODO: use i18n functions*/}
|
|
87
|
-
</a>
|
|
88
|
-
</DropdownMenuItem>
|
|
89
|
-
</DropdownMenuContent>
|
|
90
|
-
</DropdownMenu>
|
|
91
|
-
)
|
|
92
|
-
})}
|
|
93
|
-
</>
|
|
94
|
-
)}
|
|
95
|
-
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
</div>
|
|
99
|
-
))}
|
|
100
|
-
</div>
|
|
101
|
-
);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
export default
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { informationUnitsResponseItem } from "@c-rex/interfaces";
|
|
3
|
+
import { useTranslations } from "next-intl";
|
|
4
|
+
import { CloudDownload, Eye } from "lucide-react";
|
|
5
|
+
import { FaFilePdf } from "react-icons/fa6";
|
|
6
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@c-rex/ui/dropdown-menu";
|
|
7
|
+
import { cn } from "@c-rex/utils";
|
|
8
|
+
import { Flag } from "../icons/flag-icon";
|
|
9
|
+
import { Badge } from "@c-rex/ui/badge";
|
|
10
|
+
import { useQueryState } from "nuqs";
|
|
11
|
+
|
|
12
|
+
interface InformationUnitSearchResultsTableProps {
|
|
13
|
+
items: informationUnitsResponseItem[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const IconsToFileExtension: Record<string, React.ReactNode> = {
|
|
17
|
+
"application/pdf": <FaFilePdf className="h-6 w-6" />,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const InformationUnitSearchResultsTable: FC<InformationUnitSearchResultsTableProps> = ({ items }) => {
|
|
21
|
+
const t = useTranslations("results")
|
|
22
|
+
const [query] = useQueryState("search");
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div className="rounded-md border mb-6 last:border-b-0">
|
|
27
|
+
<div className="font-bold text-sm p-2 border-b items-center flex-wrap hidden md:flex">
|
|
28
|
+
<div className="w-1/2 md:w-2/5 p-2">{t("title")}</div>
|
|
29
|
+
<div className="w-1/2 md:w-1/5 p-2 flex justify-center">{t("language")}</div>
|
|
30
|
+
<div className="w-1/2 md:w-1/5 p-2">{t("type")}</div>
|
|
31
|
+
<div className="w-1/2 md:w-1/5 p-2 flex justify-center">{t("files")}</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
{items.map((item) => (
|
|
35
|
+
<div
|
|
36
|
+
className={cn(
|
|
37
|
+
"min-h-12 c-rex-result-item flex flex-wrap items-center",
|
|
38
|
+
`c-rex-result-${item.type.toLowerCase()}`,
|
|
39
|
+
item.disabled && "c-rex-result-item-disabled",
|
|
40
|
+
"border-b"
|
|
41
|
+
)}
|
|
42
|
+
key={item.shortId}
|
|
43
|
+
>
|
|
44
|
+
<div className="w-4/5 md:w-2/5 p-2">
|
|
45
|
+
{item.disabled ? (item.title) : (<a href={`${item.link}?q=${query}`}>{item.title}</a>)}
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div className="w-1/5 md:w-1/5 flex justify-center p-2">
|
|
49
|
+
<span className="w-8 inline-block">
|
|
50
|
+
{item.language.split("-").length > 1 && (
|
|
51
|
+
<Flag countryCode={item.language.split("-")[1] as string} />
|
|
52
|
+
)}
|
|
53
|
+
</span>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div className="w-4/5 md:w-1/5 p-2">
|
|
57
|
+
<Badge variant="secondary">
|
|
58
|
+
{item.type}
|
|
59
|
+
</Badge>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div className="w-1/5 flex justify-center p-2">
|
|
63
|
+
{(item.disabled || (Object.keys(item.files).length === 0)) ? (
|
|
64
|
+
null // remove null rendering
|
|
65
|
+
) : (
|
|
66
|
+
<>
|
|
67
|
+
{Object.keys(item.files).map((fileKey) => {
|
|
68
|
+
|
|
69
|
+
if (!item.files[fileKey]) {
|
|
70
|
+
return null
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<DropdownMenu key={fileKey}>
|
|
75
|
+
<DropdownMenuTrigger className="mx-2">
|
|
76
|
+
{IconsToFileExtension[fileKey]}
|
|
77
|
+
</DropdownMenuTrigger>
|
|
78
|
+
<DropdownMenuContent>
|
|
79
|
+
<DropdownMenuItem>
|
|
80
|
+
<a href={item.files[fileKey].view} target="_blank" rel="noreferrer" className="flex items-center">
|
|
81
|
+
<Eye className="mr-2" /> Open {/*TODO: use i18n functions*/}
|
|
82
|
+
</a>
|
|
83
|
+
</DropdownMenuItem>
|
|
84
|
+
<DropdownMenuItem>
|
|
85
|
+
<a href={item.files[fileKey].download} target="_blank" rel="noreferrer" className="flex items-center">
|
|
86
|
+
<CloudDownload className="mr-2" /> Download {/*TODO: use i18n functions*/}
|
|
87
|
+
</a>
|
|
88
|
+
</DropdownMenuItem>
|
|
89
|
+
</DropdownMenuContent>
|
|
90
|
+
</DropdownMenu>
|
|
91
|
+
)
|
|
92
|
+
})}
|
|
93
|
+
</>
|
|
94
|
+
)}
|
|
95
|
+
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
</div>
|
|
99
|
+
))}
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export default InformationUnitSearchResultsTable;
|
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import { FC, MouseEvent } from "react";
|
|
4
|
-
import {
|
|
5
|
-
Pagination as PaginationUI,
|
|
6
|
-
PaginationContent,
|
|
7
|
-
PaginationItem,
|
|
8
|
-
PaginationLink,
|
|
9
|
-
PaginationNext,
|
|
10
|
-
PaginationPrevious,
|
|
11
|
-
} from "@c-rex/ui/pagination"
|
|
12
|
-
import { parseAsInteger, useQueryState } from "nuqs";
|
|
13
|
-
import { ResultContainerPageInfoModel } from "@c-rex/interfaces";
|
|
14
|
-
|
|
15
|
-
interface PaginationProps {
|
|
16
|
-
pageInfo: ResultContainerPageInfoModel;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export const Pagination: FC<PaginationProps> = ({ pageInfo }) => {
|
|
20
|
-
const disabledClass = "opacity-50 pointer-events-none";
|
|
21
|
-
|
|
22
|
-
const [, setPage] = useQueryState('page',
|
|
23
|
-
parseAsInteger.withOptions({
|
|
24
|
-
history: 'push',
|
|
25
|
-
shallow: false,
|
|
26
|
-
})
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
const onChangePage = (event: MouseEvent<HTMLAnchorElement>, pageNumber: number) => {
|
|
30
|
-
event.preventDefault();
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
pageNumber < 1
|
|
34
|
-
|| (pageInfo.pageCount !== undefined && pageNumber > pageInfo.pageCount)
|
|
35
|
-
|| pageNumber === pageInfo.pageNumber
|
|
36
|
-
) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
void setPage(pageNumber);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<PaginationUI className="py-4">
|
|
45
|
-
<PaginationContent>
|
|
46
|
-
<PaginationItem>
|
|
47
|
-
<PaginationPrevious
|
|
48
|
-
href="#"
|
|
49
|
-
className={pageInfo.pageNumber === 1 ? disabledClass : ""}
|
|
50
|
-
onClick={(event) => onChangePage(event, pageInfo.pageNumber! - 1)}
|
|
51
|
-
/>
|
|
52
|
-
</PaginationItem>
|
|
53
|
-
|
|
54
|
-
{Array.from({ length: pageInfo.pageCount || 1 }, (_, index) => index + 1).map((page) => (
|
|
55
|
-
<PaginationItem key={page}>
|
|
56
|
-
<PaginationLink
|
|
57
|
-
href="#"
|
|
58
|
-
isActive={page === pageInfo.pageNumber}
|
|
59
|
-
onClick={(event) => onChangePage(event, page)}
|
|
60
|
-
>
|
|
61
|
-
{page}
|
|
62
|
-
</PaginationLink>
|
|
63
|
-
</PaginationItem>
|
|
64
|
-
))}
|
|
65
|
-
|
|
66
|
-
{/*
|
|
67
|
-
<PaginationItem>
|
|
68
|
-
<PaginationEllipsis />
|
|
69
|
-
</PaginationItem>
|
|
70
|
-
*/}
|
|
71
|
-
<PaginationItem>
|
|
72
|
-
<PaginationNext
|
|
73
|
-
href="#"
|
|
74
|
-
onClick={(event) => onChangePage(event, pageInfo.pageNumber! + 1)}
|
|
75
|
-
className={pageInfo.pageNumber === pageInfo.pageCount ? disabledClass : ""}
|
|
76
|
-
/>
|
|
77
|
-
</PaginationItem>
|
|
78
|
-
</PaginationContent>
|
|
79
|
-
</PaginationUI>
|
|
80
|
-
)
|
|
81
|
-
}
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { FC, MouseEvent } from "react";
|
|
4
|
+
import {
|
|
5
|
+
Pagination as PaginationUI,
|
|
6
|
+
PaginationContent,
|
|
7
|
+
PaginationItem,
|
|
8
|
+
PaginationLink,
|
|
9
|
+
PaginationNext,
|
|
10
|
+
PaginationPrevious,
|
|
11
|
+
} from "@c-rex/ui/pagination"
|
|
12
|
+
import { parseAsInteger, useQueryState } from "nuqs";
|
|
13
|
+
import { ResultContainerPageInfoModel } from "@c-rex/interfaces";
|
|
14
|
+
|
|
15
|
+
interface PaginationProps {
|
|
16
|
+
pageInfo: ResultContainerPageInfoModel;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const Pagination: FC<PaginationProps> = ({ pageInfo }) => {
|
|
20
|
+
const disabledClass = "opacity-50 pointer-events-none";
|
|
21
|
+
|
|
22
|
+
const [, setPage] = useQueryState('page',
|
|
23
|
+
parseAsInteger.withOptions({
|
|
24
|
+
history: 'push',
|
|
25
|
+
shallow: false,
|
|
26
|
+
})
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
const onChangePage = (event: MouseEvent<HTMLAnchorElement>, pageNumber: number) => {
|
|
30
|
+
event.preventDefault();
|
|
31
|
+
|
|
32
|
+
if (
|
|
33
|
+
pageNumber < 1
|
|
34
|
+
|| (pageInfo.pageCount !== undefined && pageNumber > pageInfo.pageCount)
|
|
35
|
+
|| pageNumber === pageInfo.pageNumber
|
|
36
|
+
) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void setPage(pageNumber);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<PaginationUI className="py-4">
|
|
45
|
+
<PaginationContent>
|
|
46
|
+
<PaginationItem>
|
|
47
|
+
<PaginationPrevious
|
|
48
|
+
href="#"
|
|
49
|
+
className={pageInfo.pageNumber === 1 ? disabledClass : ""}
|
|
50
|
+
onClick={(event) => onChangePage(event, pageInfo.pageNumber! - 1)}
|
|
51
|
+
/>
|
|
52
|
+
</PaginationItem>
|
|
53
|
+
|
|
54
|
+
{Array.from({ length: pageInfo.pageCount || 1 }, (_, index) => index + 1).map((page) => (
|
|
55
|
+
<PaginationItem key={page}>
|
|
56
|
+
<PaginationLink
|
|
57
|
+
href="#"
|
|
58
|
+
isActive={page === pageInfo.pageNumber}
|
|
59
|
+
onClick={(event) => onChangePage(event, page)}
|
|
60
|
+
>
|
|
61
|
+
{page}
|
|
62
|
+
</PaginationLink>
|
|
63
|
+
</PaginationItem>
|
|
64
|
+
))}
|
|
65
|
+
|
|
66
|
+
{/*
|
|
67
|
+
<PaginationItem>
|
|
68
|
+
<PaginationEllipsis />
|
|
69
|
+
</PaginationItem>
|
|
70
|
+
*/}
|
|
71
|
+
<PaginationItem>
|
|
72
|
+
<PaginationNext
|
|
73
|
+
href="#"
|
|
74
|
+
onClick={(event) => onChangePage(event, pageInfo.pageNumber! + 1)}
|
|
75
|
+
className={pageInfo.pageNumber === pageInfo.pageCount ? disabledClass : ""}
|
|
76
|
+
/>
|
|
77
|
+
</PaginationItem>
|
|
78
|
+
</PaginationContent>
|
|
79
|
+
</PaginationUI>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { CommonItemsModel } from "@c-rex/interfaces";
|
|
2
|
+
import { ResultTypes } from "@c-rex/types";
|
|
3
|
+
import { extractCountryCodeFromLanguage, getLanguage, getTitle, getType, getVersions } from "@c-rex/utils";
|
|
4
|
+
|
|
5
|
+
export type ResultItemSummary = {
|
|
6
|
+
title: string;
|
|
7
|
+
itemType: ResultTypes;
|
|
8
|
+
language: string;
|
|
9
|
+
countryCode: string;
|
|
10
|
+
multipleVersions: string[];
|
|
11
|
+
packageId: string | null;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const getResultItemSummary = (item: CommonItemsModel): ResultItemSummary => {
|
|
15
|
+
const title = getTitle(item.titles, item.labels);
|
|
16
|
+
const itemType = (getType(item.class) || "TOPIC") as ResultTypes;
|
|
17
|
+
const language = getLanguage(item.languages);
|
|
18
|
+
const countryCode = extractCountryCodeFromLanguage(language);
|
|
19
|
+
const multipleVersions = getVersions(item.versionOf);
|
|
20
|
+
const packageId = item.packages && item.packages.length > 0 ? item.packages[0]?.shortId || null : null;
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
title,
|
|
24
|
+
itemType,
|
|
25
|
+
language,
|
|
26
|
+
countryCode,
|
|
27
|
+
multipleVersions,
|
|
28
|
+
packageId,
|
|
29
|
+
};
|
|
30
|
+
};
|
package/src/results/utils.ts
CHANGED
|
@@ -1,47 +1,54 @@
|
|
|
1
|
-
import { RenditionModel } from "@c-rex/interfaces";
|
|
2
|
-
import { DocumentsType } from "@c-rex/types";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
1
|
+
import { RenditionModel } from "@c-rex/interfaces";
|
|
2
|
+
import { DocumentsType } from "@c-rex/types";
|
|
3
|
+
|
|
4
|
+
type Props = {
|
|
5
|
+
renditions: RenditionModel[];
|
|
6
|
+
ignoreFormat?: string[];
|
|
7
|
+
}
|
|
8
|
+
export const getFileRenditions = ({
|
|
9
|
+
renditions,
|
|
10
|
+
ignoreFormat = ["application/xhtml+xml", "application/json", "application/llm+xml", "text/html"]
|
|
11
|
+
}: Props): DocumentsType => {
|
|
12
|
+
if (renditions == undefined || renditions.length == 0) {
|
|
13
|
+
return {} as DocumentsType;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const filteredRenditions = renditions.filter(
|
|
17
|
+
(item) => !ignoreFormat.includes(item.format!)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
if (filteredRenditions.length == 0 || filteredRenditions[0] == undefined) {
|
|
21
|
+
return {} as DocumentsType;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const result: {
|
|
25
|
+
[key: string]: {
|
|
26
|
+
view: string;
|
|
27
|
+
download: string;
|
|
28
|
+
}
|
|
29
|
+
} = {}
|
|
30
|
+
|
|
31
|
+
filteredRenditions.forEach((item) => {
|
|
32
|
+
const key = item.format!
|
|
33
|
+
|
|
34
|
+
if (result[key] == undefined) {
|
|
35
|
+
result[key] = {
|
|
36
|
+
view: "",
|
|
37
|
+
download: ""
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const download = item.links?.filter((link) => link.rel == "download")[0]?.href
|
|
41
|
+
const view = item.links?.filter((link) => link.rel == "view")[0]?.href
|
|
42
|
+
|
|
43
|
+
if (download != null && download != undefined) {
|
|
44
|
+
result[key].download = download
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (view != null && view != undefined) {
|
|
48
|
+
result[key].view = view
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
return result
|
|
53
|
+
}
|
|
54
|
+
|
package/src/search-input.tsx
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import { FC, useEffect, useState } from "react";
|
|
4
|
-
import { FileCheck, FileX, Search } from "lucide-react";
|
|
5
|
-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@c-rex/ui/tooltip";
|
|
6
|
-
import * as AutocompleteOptions from "./generated/suggestions";
|
|
7
|
-
import { useQueryState } from "nuqs";
|
|
8
|
-
|
|
9
|
-
type PlacedOn = "NAVBAR" | "BODY"
|
|
10
|
-
type Props = {
|
|
11
|
-
showPkgFilter: boolean
|
|
12
|
-
placedOn?: PlacedOn
|
|
13
|
-
onSelectPath: string;
|
|
14
|
-
autocompleteType: keyof typeof AutocompleteOptions;
|
|
15
|
-
//these two props are only used when showPkgFilter is false and has some values to override the default behavior
|
|
16
|
-
alternativeAutocompleteType?: keyof typeof AutocompleteOptions;
|
|
17
|
-
alternativeOnSelectPath?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const SearchInput: FC<Props> = ({
|
|
21
|
-
showPkgFilter,
|
|
22
|
-
autocompleteType,
|
|
23
|
-
onSelectPath,
|
|
24
|
-
alternativeAutocompleteType,
|
|
25
|
-
alternativeOnSelectPath
|
|
26
|
-
}) => {
|
|
27
|
-
const [pkg] = useQueryState("package");
|
|
28
|
-
const [checked, setChecked] = useState<boolean>(true);
|
|
29
|
-
const [autocompleteComponentName, setAutocompleteComponentName] = useState<keyof typeof AutocompleteOptions>(autocompleteType);
|
|
30
|
-
|
|
31
|
-
const AutocompleteComponent = AutocompleteOptions[autocompleteComponentName] as FC<any>;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
if (checked) {
|
|
36
|
-
setAutocompleteComponentName(autocompleteType);
|
|
37
|
-
} else if (alternativeAutocompleteType) {
|
|
38
|
-
setAutocompleteComponentName(alternativeAutocompleteType);
|
|
39
|
-
}
|
|
40
|
-
}, [checked]);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<>
|
|
45
|
-
<Search className="shrink-0 opacity-50" />
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<AutocompleteComponent
|
|
49
|
-
onSelectParams={
|
|
50
|
-
(pkg && checked && showPkgFilter) ? [{ key: "packages", value: pkg }] : []
|
|
51
|
-
}
|
|
52
|
-
onSelectPath={checked ? onSelectPath : alternativeOnSelectPath}
|
|
53
|
-
embedded
|
|
54
|
-
/>
|
|
55
|
-
|
|
56
|
-
{showPkgFilter && <>
|
|
57
|
-
<TooltipProvider>
|
|
58
|
-
<Tooltip delayDuration={100}>
|
|
59
|
-
<TooltipTrigger onClick={() => setChecked(!checked)}>
|
|
60
|
-
{checked ? <FileCheck className="opacity-50" /> : <FileX className="opacity-50" />}
|
|
61
|
-
</TooltipTrigger>
|
|
62
|
-
|
|
63
|
-
<TooltipContent>
|
|
64
|
-
If checked will search only in this document
|
|
65
|
-
</TooltipContent>
|
|
66
|
-
</Tooltip>
|
|
67
|
-
</TooltipProvider>
|
|
68
|
-
</>}
|
|
69
|
-
</>
|
|
70
|
-
);
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { FC, useEffect, useState } from "react";
|
|
4
|
+
import { FileCheck, FileX, Search } from "lucide-react";
|
|
5
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@c-rex/ui/tooltip";
|
|
6
|
+
import * as AutocompleteOptions from "./generated/suggestions";
|
|
7
|
+
import { useQueryState } from "nuqs";
|
|
8
|
+
|
|
9
|
+
type PlacedOn = "NAVBAR" | "BODY"
|
|
10
|
+
type Props = {
|
|
11
|
+
showPkgFilter: boolean
|
|
12
|
+
placedOn?: PlacedOn
|
|
13
|
+
onSelectPath: string;
|
|
14
|
+
autocompleteType: keyof typeof AutocompleteOptions;
|
|
15
|
+
//these two props are only used when showPkgFilter is false and has some values to override the default behavior
|
|
16
|
+
alternativeAutocompleteType?: keyof typeof AutocompleteOptions;
|
|
17
|
+
alternativeOnSelectPath?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const SearchInput: FC<Props> = ({
|
|
21
|
+
showPkgFilter,
|
|
22
|
+
autocompleteType,
|
|
23
|
+
onSelectPath,
|
|
24
|
+
alternativeAutocompleteType,
|
|
25
|
+
alternativeOnSelectPath
|
|
26
|
+
}) => {
|
|
27
|
+
const [pkg] = useQueryState("package");
|
|
28
|
+
const [checked, setChecked] = useState<boolean>(true);
|
|
29
|
+
const [autocompleteComponentName, setAutocompleteComponentName] = useState<keyof typeof AutocompleteOptions>(autocompleteType);
|
|
30
|
+
|
|
31
|
+
const AutocompleteComponent = AutocompleteOptions[autocompleteComponentName] as FC<any>;
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (checked) {
|
|
36
|
+
setAutocompleteComponentName(autocompleteType);
|
|
37
|
+
} else if (alternativeAutocompleteType) {
|
|
38
|
+
setAutocompleteComponentName(alternativeAutocompleteType);
|
|
39
|
+
}
|
|
40
|
+
}, [checked]);
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<>
|
|
45
|
+
<Search className="shrink-0 opacity-50" />
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
<AutocompleteComponent
|
|
49
|
+
onSelectParams={
|
|
50
|
+
(pkg && checked && showPkgFilter) ? [{ key: "packages", value: pkg }] : []
|
|
51
|
+
}
|
|
52
|
+
onSelectPath={checked ? onSelectPath : alternativeOnSelectPath}
|
|
53
|
+
embedded
|
|
54
|
+
/>
|
|
55
|
+
|
|
56
|
+
{showPkgFilter && <>
|
|
57
|
+
<TooltipProvider>
|
|
58
|
+
<Tooltip delayDuration={100}>
|
|
59
|
+
<TooltipTrigger onClick={() => setChecked(!checked)}>
|
|
60
|
+
{checked ? <FileCheck className="opacity-50" /> : <FileX className="opacity-50" />}
|
|
61
|
+
</TooltipTrigger>
|
|
62
|
+
|
|
63
|
+
<TooltipContent>
|
|
64
|
+
If checked will search only in this document
|
|
65
|
+
</TooltipContent>
|
|
66
|
+
</Tooltip>
|
|
67
|
+
</TooltipProvider>
|
|
68
|
+
</>}
|
|
69
|
+
</>
|
|
70
|
+
);
|
|
71
71
|
};
|