@c-rex/components 0.1.36 → 0.1.38

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.
Files changed (95) hide show
  1. package/package.json +1 -18
  2. package/src/article/article-content.tsx +26 -35
  3. package/src/autocomplete.tsx +26 -5
  4. package/src/carousel/carousel.tsx +53 -52
  5. package/src/check-article-lang.tsx +8 -4
  6. package/src/favorites/bookmark-button.tsx +26 -11
  7. package/src/favorites/favorite-button.tsx +67 -21
  8. package/src/info/info-table.tsx +60 -38
  9. package/src/info/set-available-versions.tsx +19 -0
  10. package/src/navbar/language-switcher/content-language-switch.tsx +36 -36
  11. package/src/navbar/language-switcher/ui-language-switch.tsx +5 -6
  12. package/src/navbar/navbar.tsx +17 -8
  13. package/src/renditions/html.tsx +38 -31
  14. package/src/restriction-menu/restriction-menu-item.tsx +8 -5
  15. package/src/restriction-menu/restriction-menu.tsx +26 -25
  16. package/src/results/generic/table-result-list.tsx +1 -1
  17. package/src/results/utils.ts +9 -2
  18. package/src/stores/favorites-store.ts +21 -21
  19. package/src/stores/language-store.ts +2 -31
  20. package/src/article/article-action-bar.analysis.md +0 -15
  21. package/src/article/article-action-bar.stories.tsx +0 -15
  22. package/src/article/article-content.analysis.md +0 -15
  23. package/src/article/article-content.stories.tsx +0 -21
  24. package/src/autocomplete.analysis.md +0 -17
  25. package/src/breadcrumb.analysis.md +0 -15
  26. package/src/carousel/carousel.analysis.md +0 -17
  27. package/src/check-article-lang.analysis.md +0 -15
  28. package/src/directoryNodes/tree-of-content.analysis.md +0 -14
  29. package/src/directoryNodes/tree-of-content.stories.tsx +0 -22
  30. package/src/documents/result-list.analysis.md +0 -14
  31. package/src/documents/result-list.stories.tsx +0 -19
  32. package/src/favorites/bookmark-button.analysis.md +0 -17
  33. package/src/favorites/bookmark-button.stories.tsx +0 -19
  34. package/src/favorites/favorite-button.analysis.md +0 -18
  35. package/src/favorites/favorite-button.stories.tsx +0 -22
  36. package/src/icons/file-icon.analysis.md +0 -14
  37. package/src/icons/file-icon.stories.tsx +0 -19
  38. package/src/icons/flag-icon.analysis.md +0 -14
  39. package/src/icons/flag-icon.stories.tsx +0 -25
  40. package/src/icons/loading.analysis.md +0 -14
  41. package/src/icons/loading.stories.tsx +0 -21
  42. package/src/info/info-table.analysis.md +0 -15
  43. package/src/info/shared.analysis.md +0 -14
  44. package/src/info/stories/info-table.stories.tsx +0 -31
  45. package/src/info/stories/shared.stories.tsx +0 -24
  46. package/src/navbar/language-switcher/content-language-switch.analysis.md +0 -15
  47. package/src/navbar/language-switcher/shared.analysis.md +0 -14
  48. package/src/navbar/language-switcher/ui-language-switch.analysis.md +0 -15
  49. package/src/navbar/navbar.analysis.md +0 -14
  50. package/src/navbar/settings.analysis.md +0 -14
  51. package/src/navbar/sign-in-out-btns.analysis.md +0 -14
  52. package/src/navbar/stories/navbar.stories.tsx +0 -31
  53. package/src/navbar/stories/settings.stories.tsx +0 -15
  54. package/src/navbar/stories/sign-in-out-btns.stories.tsx +0 -15
  55. package/src/navbar/stories/user-menu.stories.tsx +0 -20
  56. package/src/navbar/user-menu.analysis.md +0 -14
  57. package/src/page-wrapper.analysis.md +0 -14
  58. package/src/render-article.analysis.md +0 -15
  59. package/src/renditions/file-download.analysis.md +0 -14
  60. package/src/renditions/file-download.stories.tsx +0 -19
  61. package/src/renditions/html.analysis.md +0 -17
  62. package/src/renditions/html.stories.tsx +0 -19
  63. package/src/renditions/image/container.analysis.md +0 -15
  64. package/src/renditions/image/container.stories.tsx +0 -19
  65. package/src/renditions/image/rendition.analysis.md +0 -14
  66. package/src/renditions/image/rendition.stories.tsx +0 -19
  67. package/src/restriction-menu/restriction-menu-container.analysis.md +0 -14
  68. package/src/restriction-menu/restriction-menu-item.analysis.md +0 -14
  69. package/src/restriction-menu/restriction-menu.analysis.md +0 -17
  70. package/src/results/analysis/cards.analysis.md +0 -14
  71. package/src/results/analysis/dialog-filter.analysis.md +0 -17
  72. package/src/results/analysis/empty.analysis.md +0 -14
  73. package/src/results/analysis/filter-navbar.analysis.md +0 -16
  74. package/src/results/analysis/pagination.analysis.md +0 -14
  75. package/src/results/analysis/table-with-images.analysis.md +0 -15
  76. package/src/results/analysis/table.analysis.md +0 -15
  77. package/src/results/filter-sidebar/index.analysis.md +0 -14
  78. package/src/results/generic/table-result-list.analysis.md +0 -15
  79. package/src/results/generic/table-result-list.stories.tsx +0 -21
  80. package/src/results/stories/cards.stories.tsx +0 -66
  81. package/src/results/stories/dialog-filter.stories.tsx +0 -20
  82. package/src/results/stories/empty.stories.tsx +0 -25
  83. package/src/results/stories/filter-navbar.stories.tsx +0 -19
  84. package/src/results/stories/filter-sidebar.stories.tsx +0 -20
  85. package/src/results/stories/pagination.stories.tsx +0 -24
  86. package/src/results/stories/table-with-images.stories.tsx +0 -19
  87. package/src/results/stories/table.stories.tsx +0 -78
  88. package/src/search-input.analysis.md +0 -15
  89. package/src/share-button.analysis.md +0 -19
  90. package/src/stories/autocomplete.stories.tsx +0 -20
  91. package/src/stories/breadcrumb.stories.tsx +0 -93
  92. package/src/stories/check-article-lang.stories.tsx +0 -22
  93. package/src/stories/render-article.stories.tsx +0 -19
  94. package/src/stories/search-input.stories.tsx +0 -21
  95. package/src/stories/share-button.stories.tsx +0 -15
@@ -20,40 +20,79 @@ import { Flag } from "../icons/flag-icon";
20
20
  import { Button } from "@c-rex/ui/button";
21
21
  import { FileIcon } from "../icons/file-icon";
22
22
  import { BookmarkButton } from "../favorites/bookmark-button";
23
- import { InformationUnitsGetAll } from "../generated/server-components";
23
+ import { informationUnitsGetAllServer } from "@c-rex/services/server-requests";
24
24
  import { getTranslations } from "next-intl/server";
25
25
  import { EN_LANG } from "@c-rex/constants";
26
26
  import { getFileRenditions } from "../results/utils";
27
27
  import Link from "next/link";
28
28
  import { processDataToLabelValuePairs } from "@c-rex/utils";
29
+ import { AvailableVersionsInterface } from "@c-rex/interfaces";
30
+ import { SetAvailableVersions } from "./set-available-versions";
29
31
 
30
32
  type Props = {
31
33
  title: string;
32
- linkPath: "topics" | "documents";
34
+ linkPattern: string;
33
35
  data: InformationUnitModel;
34
36
  excludeKeys?: string[];
35
37
  showBookmarkButton?: boolean;
38
+ saveVersionsInContext?: boolean;
36
39
  }
37
40
 
38
41
  export const InfoTable: FC<Props> = async ({
39
42
  title,
40
43
  data,
41
- linkPath = "topics",
44
+ linkPattern,
42
45
  showBookmarkButton = false,
46
+ saveVersionsInContext = false
43
47
  }) => {
44
- const t = await getTranslations();
48
+ const versionBaseShortId = data.versionOf?.shortId ?? null;
49
+ const [t, informationUnits] = await Promise.all([
50
+ getTranslations(),
51
+ versionBaseShortId
52
+ ? informationUnitsGetAllServer({
53
+ Restrict: [`versionOf.shortId=${versionBaseShortId}`],
54
+ Fields: ["renditions", "class", "languages", "labels"],
55
+ })
56
+ : Promise.resolve({ items: [] }),
57
+ ])
45
58
  const files = getFileRenditions({ renditions: data.renditions! });
59
+ const versionsByShortId = new Map<string, { shortId: string; language: string }>();
60
+
61
+ if (data.shortId && data.languages?.[0]) {
62
+ versionsByShortId.set(data.shortId, {
63
+ shortId: data.shortId,
64
+ language: data.languages[0],
65
+ });
66
+ }
67
+
68
+ informationUnits.items.forEach((item) => {
69
+ if (!item.shortId || !item.languages?.[0]) return;
70
+ versionsByShortId.set(item.shortId, {
71
+ shortId: item.shortId,
72
+ language: item.languages[0],
73
+ });
74
+ });
75
+
76
+ const availableVersions = Array.from(versionsByShortId.values())
77
+ .map((item) => ({
78
+ shortId: item.shortId,
79
+ active: item.shortId === data.shortId,
80
+ lang: item.language,
81
+ country: item.language.split("-")[1] ?? item.language,
82
+ link: linkPattern.replace("{shortId}", item.shortId),
83
+ }))
84
+ .sort((a, b) => a.lang.localeCompare(b.lang)) as AvailableVersionsInterface[];
46
85
 
47
86
  return (
48
87
  <Card className="p-0 !pt-4">
49
88
  <CardHeader>
50
89
  <CardTitle className="text-lg flex justify-between items-end">
51
90
  {title}
52
-
53
91
  {showBookmarkButton && <BookmarkButton shortId={data.shortId!} />}
54
92
  </CardTitle>
55
93
  </CardHeader>
56
94
  <CardContent className="space-y-3 !p-0">
95
+ {saveVersionsInContext && <SetAvailableVersions versions={availableVersions} />}
57
96
  <Table>
58
97
  <TableBody>
59
98
  {processDataToLabelValuePairs(data).map((item) => (
@@ -67,39 +106,22 @@ export const InfoTable: FC<Props> = async ({
67
106
  </TableRow>
68
107
  ))}
69
108
 
70
- {/*check if has versionOF */}
71
- <InformationUnitsGetAll
72
- queryParams={{
73
- Restrict: [`versionOf.shortId=${data.versionOf?.shortId}`],
74
- Fields: ["renditions", "class", "languages", "labels"]
75
- }}
76
- render={(data, error) => {
77
- if (error) {
78
- return JSON.stringify(error);
79
- }
80
-
81
- return (
82
- <TableRow className="min-h-12">
83
- <TableCell className="font-medium w-28 pl-4">
84
- <h4 className="text-sm font-medium">{t("availableIn")}</h4>
85
- </TableCell>
86
- <TableCell className="text-xs text-muted-foreground flex items-center gap-2 min-h-12">
87
- {data.items.map((item) => {
88
- const language = item.languages?.[0] ?? "NO LANGUAGE";
89
- const country = language.split("-")[1]!;
90
- return (
91
- <span className="w-8 block border" key={item.shortId}>
92
- <Link href={`/${linkPath}/${item.shortId}/content`} title={language}>
93
- <Flag countryCode={country} />
94
- </Link>
95
- </span>
96
- )
97
- })}
98
- </TableCell>
99
- </TableRow>
100
- )
101
- }}
102
- />
109
+ <TableRow className="min-h-12">
110
+ <TableCell className="font-medium w-28 pl-4">
111
+ <h4 className="text-sm font-medium">{t("availableIn")}</h4>
112
+ </TableCell>
113
+ <TableCell className="text-xs text-muted-foreground flex items-center gap-2 min-h-12">
114
+ {availableVersions.map((item) => {
115
+ return (
116
+ <span className="w-8 block border" key={item.shortId}>
117
+ <Link href={item.link} title={item.lang}>
118
+ <Flag countryCode={item.country} />
119
+ </Link>
120
+ </span>
121
+ )
122
+ })}
123
+ </TableCell>
124
+ </TableRow>
103
125
 
104
126
  {Object.keys(files).length > 0 && (
105
127
  <TableRow className="min-h-12">
@@ -0,0 +1,19 @@
1
+ "use client";
2
+
3
+ import { useEffect } from "react";
4
+ import { AvailableVersionsInterface } from "@c-rex/interfaces";
5
+ import { useAppConfig } from "@c-rex/contexts/config-provider";
6
+
7
+ type Props = {
8
+ versions: AvailableVersionsInterface[];
9
+ };
10
+
11
+ export const SetAvailableVersions = ({ versions }: Props) => {
12
+ const { setAvailableVersions } = useAppConfig();
13
+
14
+ useEffect(() => {
15
+ setAvailableVersions(versions);
16
+ }, [setAvailableVersions, versions]);
17
+
18
+ return null;
19
+ };
@@ -1,8 +1,7 @@
1
1
  "use client";
2
2
 
3
- import { startTransition } from "react";
3
+ import { startTransition, useCallback, useMemo } from "react";
4
4
  import { SharedLanguageSwitch } from "./shared";
5
- import { BLOG_TYPE_AND_LINK, DOCUMENTS_TYPE_AND_LINK, TOPICS_TYPE_AND_LINK } from "@c-rex/constants";
6
5
  import { useQueryState } from "nuqs"
7
6
  import { useAppConfig } from "@c-rex/contexts/config-provider";
8
7
  import { useTranslations } from "next-intl";
@@ -16,26 +15,36 @@ type Props = {
16
15
 
17
16
  export const ContentLanguageSwitch = ({ contentLangDefault }: Props) => {
18
17
  const t = useTranslations();
19
- const contentLang = useSearchSettingsStore.getState().language || contentLangDefault;
20
- const updatePreferences = useSearchSettingsStore.getState().updatePreferences;
21
-
18
+ const contentLang = useSearchSettingsStore((state) => state.language) || contentLangDefault;
19
+ const updatePreferences = useSearchSettingsStore((state) => state.updatePreferences);
20
+ const availableLanguages = useLanguageStore((state) => state.availableLanguages);
22
21
  const { availableVersions } = useAppConfig()
23
22
 
24
- const availableLanguagesAndCountries = () => {
25
- const aux = useLanguageStore.getState().availableLanguages;
26
- let result = aux.map(item => ({ ...item, link: "#" }))
27
- if (availableVersions == null) return result
28
23
 
29
- result = aux.map(item => {
30
- const availableVersion = availableVersions.find(version => version.lang === item.value)
24
+ const normalizeLang = (lang: string) => lang.trim().toLowerCase();
25
+
26
+ const findVersionByLocale = useCallback((locale: string) => {
27
+ if (!availableVersions || availableVersions.length === 0) return undefined;
28
+ const normalizedLocale = normalizeLang(locale);
29
+
30
+ return availableVersions.find((item) => normalizeLang(item.lang) === normalizedLocale)
31
+ ?? availableVersions.find((item) => {
32
+ const langCode = normalizeLang(item.lang).split("-")[0];
33
+ const localeCode = normalizedLocale.split("-")[0];
34
+ return langCode === localeCode;
35
+ });
36
+ }, [availableVersions]);
37
+
38
+ const availableLanguagesAndCountries = useMemo(() => {
39
+ return availableLanguages.map((item) => {
40
+ const availableVersion = findVersionByLocale(item.value);
31
41
  return {
32
42
  ...item,
33
- link: availableVersion?.link ?? "#"
34
- }
35
- })
43
+ link: availableVersion?.link ?? "#",
44
+ };
45
+ });
46
+ }, [availableLanguages, availableVersions]);
36
47
 
37
- return result;
38
- }
39
48
  const [queryLanguage, setContentLanguage] = useQueryState('language', {
40
49
  history: 'push',
41
50
  shallow: false,
@@ -44,34 +53,25 @@ export const ContentLanguageSwitch = ({ contentLangDefault }: Props) => {
44
53
  const changeContentLanguage = (locale: string) => {
45
54
  startTransition(() => {
46
55
  updatePreferences({ language: locale })
47
-
48
56
  if (queryLanguage != null) {
49
57
  setContentLanguage(locale)
58
+ return;
50
59
  }
51
60
 
52
- //TODO en: needs to be fixed as it's not working
53
-
54
61
  const currentPath = window.location.pathname;
55
- const isTopicOrBlogOrDocument = (
56
- currentPath.includes(TOPICS_TYPE_AND_LINK) ||
57
- currentPath.includes(BLOG_TYPE_AND_LINK) ||
58
- currentPath.includes(DOCUMENTS_TYPE_AND_LINK)
59
- )
62
+ const isArticlePage = currentPath.includes("/pages");
63
+ if (!isArticlePage) {
64
+ window.location.reload();
65
+ return;
66
+ };
60
67
 
61
- if (!isTopicOrBlogOrDocument) {
62
- setTimeout(() => window.location.reload(), 5);
68
+ const targetVersion = findVersionByLocale(locale);
69
+ if (targetVersion?.link) {
70
+ window.location.href = targetVersion.link;
63
71
  return;
64
72
  }
65
73
 
66
- if (availableVersions !== null) {
67
- const filteredList = availableVersions.filter((item) => item.lang === locale)
68
-
69
- if (filteredList.length > 0 && filteredList[0]) {
70
- window.location.href = filteredList[0].link as string;
71
- } else {
72
- articleNotAvailableToast()
73
- }
74
- }
74
+ articleNotAvailableToast()
75
75
  });
76
76
  };
77
77
 
@@ -84,7 +84,7 @@ export const ContentLanguageSwitch = ({ contentLangDefault }: Props) => {
84
84
 
85
85
  return (
86
86
  <SharedLanguageSwitch
87
- availableLanguagesAndCountries={availableLanguagesAndCountries()}
87
+ availableLanguagesAndCountries={availableLanguagesAndCountries}
88
88
  changeLanguage={changeContentLanguage}
89
89
  selected={contentLang}
90
90
  />
@@ -5,11 +5,12 @@ import { SharedLanguageSwitch } from "./shared";
5
5
  import { UI_LANG_KEY, UI_LANG_OPTIONS } from "@c-rex/constants";
6
6
  import { getCountryCodeByLang, } from "@c-rex/utils";
7
7
  import { setCookie } from "@c-rex/utils/cookies";
8
- import { useLanguageStore } from "../../stores/language-store";
8
+ import { useLocale } from "next-intl";
9
+ import { useRouter } from "next/navigation";
9
10
 
10
11
  export const UILanguageSwitch: FC = () => {
11
- const uiLang = useLanguageStore((state) => state.uiLang);
12
- const setUiLang = useLanguageStore.getState().setUiLang;
12
+ const uiLang = useLocale().toLowerCase();
13
+ const router = useRouter();
13
14
  const UILanguages = UI_LANG_OPTIONS.map((lang) => {
14
15
  const langCode = lang.split("-")[0] as string;
15
16
  return {
@@ -21,10 +22,8 @@ export const UILanguageSwitch: FC = () => {
21
22
 
22
23
  const setUILanguage = (locale: string) => {
23
24
  startTransition(() => {
24
- setUiLang(locale)
25
25
  setCookie(UI_LANG_KEY, locale, { httpOnly: false });
26
-
27
- //window.location.reload()
26
+ router.refresh();
28
27
  });
29
28
  }
30
29
 
@@ -1,4 +1,4 @@
1
- import { ComponentProps, FC } from "react";
1
+ import { FC } from "react";
2
2
  import Link from "next/link";
3
3
  import { SignInBtn } from "./sign-in-out-btns";
4
4
  import { getServerSession } from "next-auth";
@@ -30,7 +30,7 @@ export const NavBar: FC<NavBarProps> = async ({
30
30
  showInput,
31
31
  autocompleteType,
32
32
  onSelectPath,
33
- showMenu = false,
33
+ showMenu = true,
34
34
  ...props
35
35
  }) => {
36
36
  const t = await getTranslations();
@@ -75,27 +75,32 @@ export const NavBar: FC<NavBarProps> = async ({
75
75
  </Button>
76
76
  }
77
77
  >
78
- <Button asChild variant="link">
78
+ <Button asChild variant="link" className="flex justify-start">
79
+ <Link href="/">
80
+ {t('navigation.home')}
81
+ </Link>
82
+ </Button>
83
+ <Button asChild variant="link" className="flex justify-start">
79
84
  <Link href="/documents">
80
85
  {t('navigation.documents')}
81
86
  </Link>
82
87
  </Button>
83
- <Button asChild variant="link">
88
+ <Button asChild variant="link" className="flex justify-start">
84
89
  <Link href="/topics">
85
90
  {t('navigation.topics')}
86
91
  </Link>
87
92
  </Button>
88
- <Button asChild variant="link">
93
+ <Button asChild variant="link" className="flex justify-start">
89
94
  <Link href="/fragments">
90
95
  {t('navigation.fragments')}
91
96
  </Link>
92
97
  </Button>
93
- <Button asChild variant="link">
98
+ <Button asChild variant="link" className="flex justify-start">
94
99
  <Link href="/packages">
95
100
  {t('navigation.packages')}
96
101
  </Link>
97
102
  </Button>
98
- <Button asChild variant="link">
103
+ <Button asChild variant="link" className="flex justify-start">
99
104
  <Link href="/information-units">
100
105
  {t('navigation.informationUnits')}
101
106
  </Link>
@@ -113,7 +118,11 @@ export const NavBar: FC<NavBarProps> = async ({
113
118
  <div className="flex gap-2">
114
119
  {willShowInput &&
115
120
  <div className="hidden sm:flex flex-1 items-center px-3 border rounded-full h-8 c-rex-search-bar">
116
- <SearchInput autocompleteType={autocompleteType} onSelectPath={onSelectPath} {...props} />
121
+ <SearchInput
122
+ autocompleteType={autocompleteType}
123
+ onSelectPath={onSelectPath}
124
+ {...props}
125
+ />
117
126
  </div>
118
127
  }
119
128
 
@@ -1,11 +1,14 @@
1
1
  import { FC, JSX } from "react";
2
2
  import * as cheerio from "cheerio"
3
- import { FragmentsGetAll } from "../generated/server-components";
3
+ import { RenditionModel } from "@c-rex/interfaces";
4
+ import { fragmentsGetAllServer } from "@c-rex/services/server-requests";
5
+ import { call } from "@c-rex/utils";
4
6
 
5
7
  interface HtmlRenditionProps {
6
8
  htmlFormats?: string[]
7
9
  shortId: string,
8
- render?: (html: string) => JSX.Element
10
+ render?: (html: string) => JSX.Element,
11
+ renditions?: RenditionModel[] | null
9
12
  }
10
13
 
11
14
  const defaultRender = (html: string) => {
@@ -14,45 +17,49 @@ const defaultRender = (html: string) => {
14
17
  return <div dangerouslySetInnerHTML={{ __html: articleHtml }} />;
15
18
  }
16
19
 
17
- export const HtmlRendition: FC<HtmlRenditionProps> = ({
20
+ export const HtmlRendition: FC<HtmlRenditionProps> = async ({
18
21
  shortId,
19
22
  htmlFormats = ["application/xhtml+xml", "application/html", "text/html"],
20
- render
23
+ render = defaultRender,
24
+ renditions
21
25
  }) => {
22
26
  const empty = <div>No rendition available</div>;
23
27
 
24
- return (
25
- <FragmentsGetAll
26
- queryParams={{
27
- Fields: ["titles", "renditions"],
28
- Embed: ["renditions"],
29
- PageSize: 1,
30
- Links: true,
31
- Restrict: [
32
- `informationUnits=${shortId}`,
33
- ...htmlFormats.map(format => `renditions.format=${format}`)
34
- ],
28
+ if (renditions == undefined) {
29
+ const result = await fragmentsGetAllServer({
30
+ Fields: ["titles", "renditions"],
31
+ Embed: ["renditions"],
32
+ PageSize: 1,
33
+ Links: true,
34
+ Restrict: [
35
+ `informationUnits=${shortId}`,
36
+ ...htmlFormats.map(format => `renditions.format=${format}`)
37
+ ],
38
+ })
35
39
 
36
- }}
37
- render={async (data, error) => {
38
- if (error) {
39
- return <div>Error loading content</div>;
40
- }
40
+ renditions = result.items?.[0]?.renditions;
41
+ }
41
42
 
42
- const renditions = data?.items?.[0]?.renditions;
43
+ if (renditions == null || renditions.length == 0) return empty;
44
+ renditions = renditions.filter(rendition => htmlFormats.includes(rendition.format!));
43
45
 
44
- if (renditions == null || renditions.length == 0) return empty;
45
- if (renditions.length == 0 || renditions[0] == undefined || renditions[0].links == undefined) return empty;
46
+ if (renditions.length == 0 || renditions[0] == undefined || renditions[0].links == undefined) return empty;
46
47
 
47
- const filteredLinks = renditions[0].links.filter((item) => item.rel == "view");
48
+ const filteredLinks = renditions[0].links.filter((item) => item.rel == "view");
48
49
 
49
- if (filteredLinks.length == 0 || filteredLinks[0] == undefined || filteredLinks[0].href == undefined) return empty;
50
+ if (filteredLinks.length == 0 || filteredLinks[0] == undefined || filteredLinks[0].href == undefined) return empty;
50
51
 
51
- const url = filteredLinks[0].href;
52
- const html = await fetch(url).then(res => res.text());
52
+ const url = filteredLinks[0].href;
53
+ try {
53
54
 
54
- return render ? render(html) : defaultRender(html);
55
- }}
56
- />
57
- )
55
+ const html = await fetch(url).then(res => res.text());
56
+ return render(html);
57
+ } catch (error) {
58
+ call("CrexLogger.log", {
59
+ level: "error",
60
+ message: `HtmlRendition error: ${error}`
61
+ });
62
+
63
+ return empty;
64
+ }
58
65
  }
@@ -77,23 +77,26 @@ export const RestrictionDropdownItem: FC<Props> = ({
77
77
  shortId,
78
78
  label,
79
79
  restrictField,
80
+ selected = false,
80
81
  }) => {
81
82
  const [restrict, setRestrict] = useQueryState("restrict", {
82
83
  shallow: false,
83
84
  history: "push",
84
85
  });
85
86
 
86
- const { restrictionValue } = getRestrictionValue({
87
+ const { restrictionValue, shouldRemoveRestrictParam } = getRestrictionValue({
87
88
  shortId,
88
89
  restrictField,
90
+ selected,
89
91
  currentRestrict: restrict,
90
92
  });
91
93
 
92
94
  return (
93
95
  <Button
94
- variant="ghost"
95
- onClick={() => setRestrict(restrictionValue)}
96
- className="text-left text-wrap !h-auto w-full !justify-start cursor-pointer"
96
+ variant={selected ? "default" : "ghost"}
97
+ onClick={() => shouldRemoveRestrictParam ? setRestrict(null) : setRestrict(restrictionValue)}
98
+ rounded="full"
99
+ className="text-left text-wrap !h-auto min-h-10 w-full !justify-start cursor-pointer"
97
100
  >
98
101
  {label}
99
102
  </Button>
@@ -141,4 +144,4 @@ function getRestrictionValue({
141
144
  const restrictionValue = shouldRemoveRestrictParam ? null : restrictParam
142
145
 
143
146
  return { restrictionValue, shouldRemoveRestrictParam };
144
- }
147
+ }
@@ -5,17 +5,15 @@ import {
5
5
  NavigationMenu,
6
6
  NavigationMenuList,
7
7
  NavigationMenuItem,
8
+ NavigationMenuTrigger,
9
+ NavigationMenuContent,
8
10
  } from "@c-rex/ui/navigation-menu";
9
- import { Button } from "@c-rex/ui/button";
10
- import { ChevronDown } from "lucide-react";
11
- import { DropdownHoverItem } from "@c-rex/ui/dropdown-hover-item";
12
11
  import { RestrictionDropdownItem, RestrictionNavigationItem } from "./restriction-menu-item";
13
12
  import { parseAsString, useQueryStates } from "nuqs";
14
13
  import { InformationSubjectModel } from "@c-rex/interfaces";
15
- import { useTranslations } from 'next-intl'
14
+ import { useLocale, useTranslations } from 'next-intl'
16
15
  import { cn, getLabelByLang } from "@c-rex/utils";
17
16
  import { useRestrictionStore } from "../stores/restriction-store";
18
- import { useLanguageStore } from "../stores/language-store";
19
17
  import { useBreakpoint } from "@c-rex/ui/hooks";
20
18
  import { DEVICE_OPTIONS } from "@c-rex/constants";
21
19
 
@@ -53,7 +51,7 @@ export const RestrictionMenu: FC<Props> = ({
53
51
 
54
52
  const restrictionValues = useMemo(() => params.restrict?.split(`${restrictField}=`)[1]?.split(",") || [], [params.restrict, restrictField]);
55
53
 
56
- const uiLang = useLanguageStore.getState().uiLang;
54
+ const uiLang = useLocale();
57
55
  const lang = uiLang?.split("-")[0] ?? "";
58
56
 
59
57
  useEffect(() => {
@@ -110,13 +108,13 @@ export const RestrictionMenu: FC<Props> = ({
110
108
  }, [sortedItems, visibleCount]);
111
109
 
112
110
  return (
113
- <NavigationMenu className="max-w-full w-full c-rex-restriction-menu">
111
+ <NavigationMenu viewport={false} className="max-w-full w-full c-rex-restriction-menu">
114
112
  <NavigationMenuList className={cn("w-full", navigationMenuListClassName)}>
115
113
 
116
114
 
117
115
  <RestrictionNavigationItem
118
116
  removeRestrictParam
119
- label="All"
117
+ label={t('all')}
120
118
  selected={restrictionValues.length === 0}
121
119
  />
122
120
 
@@ -131,23 +129,26 @@ export const RestrictionMenu: FC<Props> = ({
131
129
  ))}
132
130
 
133
131
  <NavigationMenuItem>
134
- <DropdownHoverItem
135
- label={
136
- <Button variant="outline" rounded="full">
137
- More <ChevronDown className="size-4" />
138
- </Button>
139
- }
140
- >
141
- {hiddenItems.map((item) => (
142
- <RestrictionDropdownItem
143
- key={item.shortId}
144
- shortId={item.shortId!}
145
- restrictField={restrictField as string}
146
- label={getLabelByLang(item.labels, lang)}
147
- selected={restrictionValues.includes(item.shortId!)}
148
- />
149
- ))}
150
- </DropdownHoverItem>
132
+ <NavigationMenuTrigger>
133
+ {t('more')}
134
+ </NavigationMenuTrigger>
135
+ <NavigationMenuContent className="w-96 sm:w-[] md:w-[700px] lg:w-[65rem]">
136
+ <ul className="grid gap-1 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-4">
137
+ {hiddenItems.map((item) => (
138
+ <li
139
+ key={item.shortId}
140
+ className="flex items-center"
141
+ >
142
+ <RestrictionDropdownItem
143
+ shortId={item.shortId!}
144
+ restrictField={restrictField as string}
145
+ label={getLabelByLang(item.labels, lang)}
146
+ selected={restrictionValues.includes(item.shortId!)}
147
+ />
148
+ </li>
149
+ ))}
150
+ </ul>
151
+ </NavigationMenuContent>
151
152
  </NavigationMenuItem>
152
153
  </NavigationMenuList>
153
154
  </NavigationMenu>
@@ -58,7 +58,7 @@ export const GenericTableResultList: FC<Props> = async ({
58
58
  }
59
59
 
60
60
  const params = generateQueryParams(queryParams)
61
- const link = linkPattern.replace("{id}", item.shortId!) + (params.length > 0 ? `?${params}` : "")
61
+ const link = linkPattern.replace("{shortId}", item.shortId!) + (params.length > 0 ? `?${params}` : "")
62
62
 
63
63
  return (
64
64
  <div
@@ -1,13 +1,20 @@
1
1
  import { RenditionModel } from "@c-rex/interfaces";
2
2
  import { DocumentsType } from "@c-rex/types";
3
3
 
4
- export const getFileRenditions = ({ renditions }: { renditions: RenditionModel[] }): DocumentsType => {
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 => {
5
12
  if (renditions == undefined || renditions.length == 0) {
6
13
  return {} as DocumentsType;
7
14
  }
8
15
 
9
16
  const filteredRenditions = renditions.filter(
10
- (item) => item.format != "application/xhtml+xml" && item.format != "application/json" && item.format != "application/llm+xml"
17
+ (item) => !ignoreFormat.includes(item.format!)
11
18
  );
12
19
 
13
20
  if (filteredRenditions.length == 0 || filteredRenditions[0] == undefined) {