@c-rex/components 0.1.3 → 0.1.5
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 +8 -4
- package/src/autocomplete.tsx +39 -30
- package/src/blog-card.tsx +38 -41
- package/src/breadcrumb.tsx +3 -2
- package/src/check-article-lang.tsx +26 -19
- package/src/navbar/language-switcher/content-language-switch.tsx +17 -24
- package/src/navbar/language-switcher/ui-language-switch.tsx +9 -19
- package/src/navbar/navbar.tsx +4 -9
- package/src/render-article.tsx +16 -0
- package/src/result-list.tsx +2 -2
- package/src/result-view/blog.tsx +4 -16
- package/src/result-view/table.tsx +4 -5
- package/src/sidebar.tsx +10 -4
- package/src/cookies.tsx +0 -50
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c-rex/components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"files": [
|
|
5
5
|
"src"
|
|
6
6
|
],
|
|
@@ -49,6 +49,10 @@
|
|
|
49
49
|
"types": "./src/result-view/table.tsx",
|
|
50
50
|
"import": "./src/result-view/table.tsx"
|
|
51
51
|
},
|
|
52
|
+
"./dropdown-menu": {
|
|
53
|
+
"types": "./src/result-view/dropdown-menu.tsx",
|
|
54
|
+
"import": "./src/result-view/dropdown-menu.tsx"
|
|
55
|
+
},
|
|
52
56
|
"./sidebar": {
|
|
53
57
|
"types": "./src/sidebar.tsx",
|
|
54
58
|
"import": "./src/sidebar.tsx"
|
|
@@ -61,9 +65,9 @@
|
|
|
61
65
|
"types": "./src/check-article-lang.tsx",
|
|
62
66
|
"import": "./src/check-article-lang.tsx"
|
|
63
67
|
},
|
|
64
|
-
"./
|
|
65
|
-
"types": "./src/
|
|
66
|
-
"import": "./src/
|
|
68
|
+
"./render-article": {
|
|
69
|
+
"types": "./src/render-article.tsx",
|
|
70
|
+
"import": "./src/render-article.tsx"
|
|
67
71
|
},
|
|
68
72
|
"./page-wrapper": {
|
|
69
73
|
"types": "./src/page-wrapper.tsx",
|
package/src/autocomplete.tsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Command as CommandPrimitive } from "cmdk";
|
|
3
|
-
import { Check } from "lucide-react";
|
|
4
3
|
import { useEffect, useState } from "react";
|
|
5
4
|
import { Input } from "@c-rex/ui/input";
|
|
6
5
|
import {
|
|
@@ -30,11 +29,20 @@ export const AutoComplete = ({
|
|
|
30
29
|
const [query, setQuery] = useState(initialValue);
|
|
31
30
|
const [suggestions, setSuggestions] = useState<string[]>([]);
|
|
32
31
|
const [open, setOpen] = useState(false);
|
|
32
|
+
const [loading, setLoading] = useState(false);
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
setQuery(initialValue);
|
|
36
|
+
}, [initialValue]);
|
|
33
37
|
|
|
34
38
|
useEffect(() => {
|
|
35
39
|
const debounceFetch = setTimeout(() => {
|
|
36
40
|
if (query) {
|
|
37
|
-
|
|
41
|
+
setLoading(true)
|
|
42
|
+
onSearch(query).then(suggestions => {
|
|
43
|
+
setSuggestions(suggestions)
|
|
44
|
+
setLoading(false)
|
|
45
|
+
});
|
|
38
46
|
} else {
|
|
39
47
|
setSuggestions([]);
|
|
40
48
|
}
|
|
@@ -46,7 +54,7 @@ export const AutoComplete = ({
|
|
|
46
54
|
return (
|
|
47
55
|
<div className="flex items-center">
|
|
48
56
|
<Popover open={open} onOpenChange={setOpen}>
|
|
49
|
-
<Command shouldFilter={
|
|
57
|
+
<Command shouldFilter={!loading} >
|
|
50
58
|
<PopoverAnchor asChild>
|
|
51
59
|
<CommandPrimitive.Input
|
|
52
60
|
asChild
|
|
@@ -56,12 +64,10 @@ export const AutoComplete = ({
|
|
|
56
64
|
onMouseDown={() => setOpen(false)}
|
|
57
65
|
onFocus={() => setOpen(true)}
|
|
58
66
|
>
|
|
59
|
-
<Input />
|
|
67
|
+
<Input value={query} />
|
|
60
68
|
</CommandPrimitive.Input>
|
|
61
69
|
</PopoverAnchor>
|
|
62
70
|
|
|
63
|
-
{!open && <CommandList aria-hidden="true" className="hidden" />}
|
|
64
|
-
|
|
65
71
|
<PopoverContent
|
|
66
72
|
asChild
|
|
67
73
|
onOpenAutoFocus={(e) => e.preventDefault()}
|
|
@@ -75,34 +81,37 @@ export const AutoComplete = ({
|
|
|
75
81
|
}}
|
|
76
82
|
className="w-[--radix-popover-trigger-width] p-0"
|
|
77
83
|
>
|
|
78
|
-
<CommandList
|
|
79
|
-
{
|
|
84
|
+
<CommandList
|
|
85
|
+
key={query}
|
|
86
|
+
>
|
|
87
|
+
{loading ? (
|
|
80
88
|
<CommandPrimitive.Loading>
|
|
81
|
-
<div className="
|
|
82
|
-
<
|
|
89
|
+
<div className="flex items-center justify-center py-4">
|
|
90
|
+
<div className="animate-spin rounded-full h-6 w-6 border-2 border-gray-300 border-t-gray-950" />
|
|
83
91
|
</div>
|
|
84
92
|
</CommandPrimitive.Loading>
|
|
85
|
-
)*/}
|
|
86
|
-
|
|
87
|
-
{suggestions.length > 0 ? (
|
|
88
|
-
<CommandGroup>
|
|
89
|
-
{suggestions.map((option) => (
|
|
90
|
-
<CommandItem
|
|
91
|
-
key={option}
|
|
92
|
-
value={option}
|
|
93
|
-
onMouseDown={(e) => e.preventDefault()}
|
|
94
|
-
onSelect={(inputValue) => {
|
|
95
|
-
setOpen(false);
|
|
96
|
-
onSelect(inputValue ?? "");
|
|
97
|
-
}}
|
|
98
|
-
>
|
|
99
|
-
<Check className="mr-2 h-4 w-4 opacity-0" />
|
|
100
|
-
{option}
|
|
101
|
-
</CommandItem>
|
|
102
|
-
))}
|
|
103
|
-
</CommandGroup>
|
|
104
93
|
) : (
|
|
105
|
-
|
|
94
|
+
<>
|
|
95
|
+
{suggestions.length > 0 ? (
|
|
96
|
+
<CommandGroup>
|
|
97
|
+
{suggestions.map((option) => (
|
|
98
|
+
<CommandItem
|
|
99
|
+
key={option}
|
|
100
|
+
value={option}
|
|
101
|
+
onMouseDown={(e) => e.preventDefault()}
|
|
102
|
+
onSelect={(inputValue) => {
|
|
103
|
+
setOpen(false);
|
|
104
|
+
onSelect(inputValue);
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
107
|
+
{option}
|
|
108
|
+
</CommandItem>
|
|
109
|
+
))}
|
|
110
|
+
</CommandGroup>
|
|
111
|
+
) : (
|
|
112
|
+
<CommandEmpty>No suggestions.</CommandEmpty>
|
|
113
|
+
)}
|
|
114
|
+
</>
|
|
106
115
|
)}
|
|
107
116
|
</CommandList>
|
|
108
117
|
</PopoverContent>
|
package/src/blog-card.tsx
CHANGED
|
@@ -1,58 +1,52 @@
|
|
|
1
1
|
import Link from "next/link";
|
|
2
|
-
import React from "react";
|
|
3
2
|
import { cn } from "@c-rex/utils";
|
|
4
3
|
import { BlurImage } from "./blur-image";
|
|
5
4
|
import { useTranslations } from "next-intl";
|
|
5
|
+
import { informationUnitsResponseItem } from "@c-rex/interfaces";
|
|
6
6
|
|
|
7
7
|
interface BlogCardProp {
|
|
8
|
-
|
|
9
|
-
title: string;
|
|
10
|
-
blurDataURL: string;
|
|
11
|
-
image: string;
|
|
12
|
-
description: string;
|
|
13
|
-
authors: string;
|
|
14
|
-
_id: string;
|
|
15
|
-
date: string;
|
|
16
|
-
slug: string;
|
|
17
|
-
};
|
|
8
|
+
item: informationUnitsResponseItem;
|
|
18
9
|
priority?: boolean;
|
|
19
10
|
horizontal?: boolean;
|
|
20
11
|
}
|
|
21
12
|
|
|
22
13
|
export const BlogCard = ({
|
|
23
|
-
|
|
14
|
+
item,
|
|
24
15
|
priority,
|
|
25
16
|
horizontal = false,
|
|
26
17
|
}: BlogCardProp) => {
|
|
27
18
|
const t = useTranslations("results")
|
|
19
|
+
const image = "/img/blog-post-1.webp"
|
|
20
|
+
const blurDataURL = "/img/blog-post-1.webp"
|
|
28
21
|
|
|
29
22
|
return (
|
|
30
23
|
<article
|
|
31
24
|
className={cn(
|
|
32
|
-
"group relative",
|
|
25
|
+
"group relative", `c-rex_result_${item.type.toLowerCase()}`,
|
|
33
26
|
horizontal
|
|
34
27
|
? "grid grid-cols-1 gap-3 md:grid-cols-2 md:gap-6"
|
|
35
28
|
: "flex flex-col space-y-2",
|
|
29
|
+
item.disabled ? "c-rex_result_item_disabled" : ""
|
|
36
30
|
)}
|
|
37
31
|
>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
32
|
+
|
|
33
|
+
<div className="w-full overflow-hidden rounded-xl border">
|
|
34
|
+
<BlurImage
|
|
35
|
+
alt={item.title}
|
|
36
|
+
blurDataURL={blurDataURL}
|
|
37
|
+
className={cn(
|
|
38
|
+
"size-full object-cover object-center",
|
|
39
|
+
horizontal ? "lg:h-72" : null,
|
|
40
|
+
)}
|
|
41
|
+
width={800}
|
|
42
|
+
height={400}
|
|
43
|
+
priority={priority}
|
|
44
|
+
placeholder="blur"
|
|
45
|
+
src={image}
|
|
46
|
+
sizes="(max-width: 768px) 750px, 600px"
|
|
47
|
+
/>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
56
50
|
<div
|
|
57
51
|
className={cn(
|
|
58
52
|
"flex flex-1 flex-col",
|
|
@@ -61,31 +55,34 @@ export const BlogCard = ({
|
|
|
61
55
|
>
|
|
62
56
|
<div className="w-full">
|
|
63
57
|
<h2 className="my-1.5 line-clamp-2 font-heading text-2xl">
|
|
64
|
-
{
|
|
58
|
+
{item.title}
|
|
65
59
|
</h2>
|
|
66
|
-
{
|
|
60
|
+
{item.type && (
|
|
67
61
|
<p className="line-clamp-2 text-muted-foreground">
|
|
68
|
-
{
|
|
62
|
+
{item.type}
|
|
69
63
|
</p>
|
|
70
64
|
)}
|
|
71
65
|
</div>
|
|
72
66
|
{/*
|
|
73
67
|
<div className="mt-4 flex items-center space-x-3">
|
|
74
68
|
<div className="flex items-center -space-x-2">
|
|
75
|
-
{
|
|
76
|
-
<p className="text-sm text-muted-foreground">{
|
|
69
|
+
{item.authors && (
|
|
70
|
+
<p className="text-sm text-muted-foreground">{item.authors}</p>
|
|
77
71
|
)}
|
|
78
72
|
</div>
|
|
79
73
|
|
|
80
|
-
{
|
|
81
|
-
<p className="text-sm text-muted-foreground">{
|
|
74
|
+
{item.date && (
|
|
75
|
+
<p className="text-sm text-muted-foreground">{item.date}</p>
|
|
82
76
|
)}
|
|
83
77
|
</div>
|
|
84
78
|
*/}
|
|
85
79
|
</div>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
80
|
+
|
|
81
|
+
{!item.disabled && (
|
|
82
|
+
<Link href={item.link} className="absolute inset-0">
|
|
83
|
+
<span className="sr-only">{t("viewArticle")}</span>
|
|
84
|
+
</Link>
|
|
85
|
+
)}
|
|
89
86
|
</article>
|
|
90
87
|
);
|
|
91
88
|
};
|
package/src/breadcrumb.tsx
CHANGED
|
@@ -13,10 +13,11 @@ import { useTranslations } from 'next-intl';
|
|
|
13
13
|
|
|
14
14
|
interface BreadcrumbProps {
|
|
15
15
|
items: TreeOfContent[];
|
|
16
|
+
lang: string;
|
|
16
17
|
loading?: boolean;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
export const Breadcrumb: FC<BreadcrumbProps> = ({ items, loading }) => {
|
|
20
|
+
export const Breadcrumb: FC<BreadcrumbProps> = ({ items, loading, lang }) => {
|
|
20
21
|
const t = useTranslations("breadcrumbs");
|
|
21
22
|
if (!items) {
|
|
22
23
|
return null;
|
|
@@ -61,7 +62,7 @@ export const Breadcrumb: FC<BreadcrumbProps> = ({ items, loading }) => {
|
|
|
61
62
|
};
|
|
62
63
|
|
|
63
64
|
return (
|
|
64
|
-
<BreadcrumbComponent>
|
|
65
|
+
<BreadcrumbComponent lang={lang}>
|
|
65
66
|
<BreadcrumbList>
|
|
66
67
|
{newItemList.map((item, index) => {
|
|
67
68
|
const isLast = index === newItemList.length - 1;
|
|
@@ -1,43 +1,50 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
+
import { FC, useEffect } from "react";
|
|
4
|
+
import { useAppConfig } from "@c-rex/contexts/config-provider";
|
|
3
5
|
import { SidebarAvailableVersionsInterface } from "@c-rex/interfaces";
|
|
4
|
-
import { FC, useEffect, useRef } from "react";
|
|
5
6
|
import { toast } from "sonner"
|
|
7
|
+
import { useTranslations } from "next-intl"
|
|
6
8
|
|
|
7
9
|
interface Props {
|
|
8
10
|
availableVersions: SidebarAvailableVersionsInterface[]
|
|
9
|
-
contentLanguage: string
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
export const CheckArticleLangToast: FC<Props> = ({
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}) => {
|
|
16
|
-
const hasRun = useRef(false)
|
|
13
|
+
export const CheckArticleLangToast: FC<Props> = ({ availableVersions }) => {
|
|
14
|
+
const t = useTranslations();
|
|
15
|
+
const { contentLang, setAvailableVersions } = useAppConfig()
|
|
17
16
|
|
|
18
17
|
useEffect(() => {
|
|
19
|
-
|
|
20
|
-
hasRun.current = true
|
|
18
|
+
setAvailableVersions(availableVersions)
|
|
21
19
|
|
|
22
20
|
const activeArticle = availableVersions.filter((item) => item.active)[0]
|
|
23
|
-
if (activeArticle == undefined || activeArticle.lang ==
|
|
24
|
-
|
|
25
|
-
const articleAvailable = availableVersions.find((item) => item.lang ===
|
|
26
|
-
if (articleAvailable == undefined)
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
if (activeArticle == undefined || activeArticle.lang == contentLang) return
|
|
22
|
+
|
|
23
|
+
const articleAvailable = availableVersions.find((item) => item.lang === contentLang)
|
|
24
|
+
if (articleAvailable == undefined) {
|
|
25
|
+
articleNotAvailableToast()
|
|
26
|
+
} else {
|
|
27
|
+
articleAvailableInToast(articleAvailable.lang, articleAvailable.link)
|
|
28
|
+
}
|
|
29
29
|
}, [])
|
|
30
30
|
|
|
31
|
-
const
|
|
32
|
-
toast(
|
|
33
|
-
description:
|
|
31
|
+
const articleAvailableInToast = (lang: string, link: string) => {
|
|
32
|
+
toast(t('toast.read', { lang }), {
|
|
33
|
+
description: t('toast.description', { lang }),
|
|
34
34
|
action: {
|
|
35
|
-
label:
|
|
35
|
+
label: t('toast.label', { lang }),
|
|
36
36
|
onClick: () => window.location.href = link,
|
|
37
37
|
},
|
|
38
38
|
duration: 10000,
|
|
39
39
|
})
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
const articleNotAvailableToast = () => {
|
|
43
|
+
toast(t('sorry'), {
|
|
44
|
+
description: t('toast.articleNotAvailable'),
|
|
45
|
+
duration: 10000,
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
42
49
|
return null
|
|
43
50
|
}
|
|
@@ -1,42 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
"use client"
|
|
2
2
|
|
|
3
|
-
import React, {
|
|
4
|
-
import { LanguageAndCountries } from "@c-rex/interfaces";
|
|
3
|
+
import React, { startTransition } from "react";
|
|
5
4
|
import { SharedLanguageSwitch } from "./shared";
|
|
6
|
-
import { setCookie } from "@c-rex/utils
|
|
5
|
+
import { getFromCookieString, setCookie } from "@c-rex/utils";
|
|
7
6
|
import { CONTENT_LANG_KEY } from "@c-rex/constants";
|
|
8
7
|
import { useQueryState } from "nuqs"
|
|
9
|
-
import {
|
|
8
|
+
import { useAppConfig } from "@c-rex/contexts/config-provider";
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
availableLanguagesAndCountries
|
|
13
|
-
|
|
14
|
-
export const ContentLanguageSwitch: FC<ContentLanguageSwitchProps> = ({ availableLanguagesAndCountries }) => {
|
|
15
|
-
const [selected, setSelected] = useState("");
|
|
10
|
+
export const ContentLanguageSwitch = () => {
|
|
11
|
+
const { availableLanguagesAndCountries, setContentLang, availableVersions } = useAppConfig()
|
|
12
|
+
const contentLang = getFromCookieString(document.cookie, CONTENT_LANG_KEY)
|
|
16
13
|
const [queryLanguage, setContentLanguage] = useQueryState('language', {
|
|
17
14
|
history: 'push',
|
|
18
15
|
shallow: false,
|
|
19
16
|
})
|
|
20
17
|
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
const get = async () => {
|
|
23
|
-
const uiLang = await getCookieInFront(CONTENT_LANG_KEY)
|
|
24
|
-
|
|
25
|
-
if (uiLang.value != null) {
|
|
26
|
-
setSelected(uiLang.value)
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
get()
|
|
31
|
-
}, [])
|
|
32
|
-
|
|
33
18
|
const changeContentLanguage = (locale: string) => {
|
|
34
19
|
startTransition(() => {
|
|
35
20
|
setCookie(CONTENT_LANG_KEY, locale)
|
|
36
|
-
|
|
21
|
+
setContentLang(locale)
|
|
37
22
|
if (queryLanguage != null) {
|
|
38
23
|
setContentLanguage(locale)
|
|
39
24
|
}
|
|
25
|
+
|
|
26
|
+
if (availableVersions !== null) {
|
|
27
|
+
const filteredList = availableVersions.filter((item) => item.lang === locale)
|
|
28
|
+
|
|
29
|
+
if (filteredList.length > 0 && filteredList[0]) {
|
|
30
|
+
window.location.href = filteredList[0].link as string;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
40
33
|
});
|
|
41
34
|
};
|
|
42
35
|
|
|
@@ -44,7 +37,7 @@ export const ContentLanguageSwitch: FC<ContentLanguageSwitchProps> = ({ availabl
|
|
|
44
37
|
<SharedLanguageSwitch
|
|
45
38
|
availableLanguagesAndCountries={availableLanguagesAndCountries}
|
|
46
39
|
changeLanguage={changeContentLanguage}
|
|
47
|
-
selected={
|
|
40
|
+
selected={contentLang}
|
|
48
41
|
/>
|
|
49
42
|
);
|
|
50
43
|
};
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import React, { FC, startTransition
|
|
3
|
+
import React, { FC, startTransition } from "react";
|
|
4
4
|
import { SharedLanguageSwitch } from "./shared";
|
|
5
|
-
import { setCookie } from "@c-rex/utils/next-cookies";
|
|
6
5
|
import { UI_LANG_KEY, UI_LANG_OPTIONS } from "@c-rex/constants";
|
|
7
|
-
import {
|
|
6
|
+
import { getCountryCodeByLang, getFromCookieString, setCookie } from "@c-rex/utils";
|
|
7
|
+
import { useAppConfig } from "@c-rex/contexts/config-provider";
|
|
8
8
|
|
|
9
9
|
export const UILanguageSwitch: FC = () => {
|
|
10
|
+
const { setUiLang } = useAppConfig()
|
|
11
|
+
const uiLang = getFromCookieString(document.cookie, UI_LANG_KEY).toLowerCase()
|
|
10
12
|
const UILanguages = UI_LANG_OPTIONS.map((lang) => {
|
|
11
|
-
|
|
12
13
|
const langCode = lang.split("-")[0] as string;
|
|
13
14
|
return {
|
|
14
15
|
value: lang,
|
|
@@ -17,23 +18,12 @@ export const UILanguageSwitch: FC = () => {
|
|
|
17
18
|
};
|
|
18
19
|
})
|
|
19
20
|
|
|
20
|
-
const [selected, setSelected] = useState("");
|
|
21
|
-
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
const get = async () => {
|
|
24
|
-
const uiLang = await getCookieInFront(UI_LANG_KEY)
|
|
25
|
-
|
|
26
|
-
if (uiLang.value != null) {
|
|
27
|
-
setSelected(uiLang.value.toLowerCase())
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
get()
|
|
32
|
-
}, [])
|
|
33
|
-
|
|
34
21
|
const setUILanguage = (locale: string) => {
|
|
35
22
|
startTransition(() => {
|
|
36
23
|
setCookie(UI_LANG_KEY, locale)
|
|
24
|
+
setUiLang(locale)
|
|
25
|
+
|
|
26
|
+
window.location.reload()
|
|
37
27
|
});
|
|
38
28
|
}
|
|
39
29
|
|
|
@@ -41,7 +31,7 @@ export const UILanguageSwitch: FC = () => {
|
|
|
41
31
|
<SharedLanguageSwitch
|
|
42
32
|
availableLanguagesAndCountries={UILanguages}
|
|
43
33
|
changeLanguage={setUILanguage}
|
|
44
|
-
selected={
|
|
34
|
+
selected={uiLang}
|
|
45
35
|
/>
|
|
46
36
|
);
|
|
47
37
|
};
|
package/src/navbar/navbar.tsx
CHANGED
|
@@ -13,15 +13,12 @@ import {
|
|
|
13
13
|
DropdownMenuSubTrigger,
|
|
14
14
|
DropdownMenuTrigger,
|
|
15
15
|
} from "@c-rex/ui/dropdown-menu"
|
|
16
|
-
import {
|
|
16
|
+
import { Settings } from "lucide-react";
|
|
17
17
|
import { ContentLanguageSwitch } from "./language-switcher/content-language-switch";
|
|
18
18
|
import { getTranslations } from "next-intl/server";
|
|
19
19
|
import { UILanguageSwitch } from "./language-switcher/ui-language-switch";
|
|
20
|
-
import { Input } from "@c-rex/ui/input";
|
|
21
20
|
import { getServerSession } from "next-auth";
|
|
22
21
|
import { getConfigs } from "@c-rex/utils/next-cookies";
|
|
23
|
-
import { LanguageService } from "@c-rex/services";
|
|
24
|
-
|
|
25
22
|
|
|
26
23
|
interface NavBarProps {
|
|
27
24
|
title: string;
|
|
@@ -30,8 +27,6 @@ interface NavBarProps {
|
|
|
30
27
|
export const NavBar: FC<NavBarProps> = async ({ title }) => {
|
|
31
28
|
const t = await getTranslations();
|
|
32
29
|
const configs = await getConfigs();
|
|
33
|
-
const languageService = new LanguageService(configs.languageSwitcher.endpoint);
|
|
34
|
-
const availableLanguagesAndCountries = await languageService.getLanguagesAndCountries();
|
|
35
30
|
|
|
36
31
|
let session: any;
|
|
37
32
|
if (configs.OIDC.user.enabled) {
|
|
@@ -59,10 +54,12 @@ export const NavBar: FC<NavBarProps> = async ({ title }) => {
|
|
|
59
54
|
</div>
|
|
60
55
|
|
|
61
56
|
<div className="flex items-center space-x-3">
|
|
57
|
+
{/*
|
|
62
58
|
<div className="flex items-center px-3 border rounded-full h-8">
|
|
63
59
|
<Search className="h-4 w-4 shrink-0 opacity-50" />
|
|
64
60
|
<Input variant="embedded" placeholder="Search" />
|
|
65
61
|
</div>
|
|
62
|
+
*/}
|
|
66
63
|
|
|
67
64
|
{configs.OIDC.user.enabled && (
|
|
68
65
|
<>
|
|
@@ -93,9 +90,7 @@ export const NavBar: FC<NavBarProps> = async ({ title }) => {
|
|
|
93
90
|
|
|
94
91
|
<DropdownMenuPortal>
|
|
95
92
|
<DropdownMenuSubContent>
|
|
96
|
-
<ContentLanguageSwitch
|
|
97
|
-
availableLanguagesAndCountries={availableLanguagesAndCountries}
|
|
98
|
-
/>
|
|
93
|
+
<ContentLanguageSwitch />
|
|
99
94
|
</DropdownMenuSubContent>
|
|
100
95
|
</DropdownMenuPortal>
|
|
101
96
|
</DropdownMenuSub>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
type Props = {
|
|
4
|
+
htmlContent: string,
|
|
5
|
+
contentLang: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const RenderArticle = ({ htmlContent, contentLang }: Props) => {
|
|
9
|
+
return (
|
|
10
|
+
<main
|
|
11
|
+
lang={contentLang}
|
|
12
|
+
className="pb-4"
|
|
13
|
+
dangerouslySetInnerHTML={{ __html: htmlContent }}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
package/src/result-list.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React, { FC } from "react";
|
|
2
|
-
import { ConfigInterface, DefaultPageInfo,
|
|
2
|
+
import { ConfigInterface, DefaultPageInfo, informationUnitsResponseItem, } from "@c-rex/interfaces";
|
|
3
3
|
import { Empty } from "./empty";
|
|
4
4
|
import BlogView from './result-view/blog';
|
|
5
5
|
import TableView from './result-view/table';
|
|
6
6
|
import { Pagination } from "./pagination";
|
|
7
7
|
|
|
8
8
|
interface ResultListProps {
|
|
9
|
-
items:
|
|
9
|
+
items: informationUnitsResponseItem[];
|
|
10
10
|
configs: ConfigInterface;
|
|
11
11
|
pagination: DefaultPageInfo;
|
|
12
12
|
}
|
package/src/result-view/blog.tsx
CHANGED
|
@@ -1,30 +1,18 @@
|
|
|
1
1
|
import React, { FC } from "react";
|
|
2
2
|
import { BlogCard } from "../blog-card";
|
|
3
|
-
import {
|
|
3
|
+
import { informationUnitsResponseItem } from "@c-rex/interfaces";
|
|
4
4
|
|
|
5
5
|
interface BlogViewProps {
|
|
6
|
-
items:
|
|
6
|
+
items: informationUnitsResponseItem[];
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
const BlogView: FC<BlogViewProps> = ({ items }) => {
|
|
10
|
-
|
|
11
10
|
return (
|
|
12
11
|
<div className="grid gap-8 md:grid-cols-2 md:gap-x-6 md:gap-y-10 xl:grid-cols-3">
|
|
13
12
|
{items.map((item, index) => {
|
|
13
|
+
|
|
14
14
|
return (
|
|
15
|
-
<BlogCard
|
|
16
|
-
key={index}
|
|
17
|
-
data={{
|
|
18
|
-
title: item.title,
|
|
19
|
-
blurDataURL: "/img/blog-post-1.webp",
|
|
20
|
-
image: "/img/blog-post-1.webp",
|
|
21
|
-
description: item.type,
|
|
22
|
-
authors: "item.authors",
|
|
23
|
-
_id: "item._id",
|
|
24
|
-
date: "item.date",
|
|
25
|
-
slug: item.link,
|
|
26
|
-
}}
|
|
27
|
-
/>
|
|
15
|
+
<BlogCard key={index} item={item} />
|
|
28
16
|
);
|
|
29
17
|
})}
|
|
30
18
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { FC } from "react";
|
|
2
2
|
import {
|
|
3
3
|
Table,
|
|
4
4
|
TableBody,
|
|
@@ -6,18 +6,17 @@ import {
|
|
|
6
6
|
TableHeader,
|
|
7
7
|
TableRow,
|
|
8
8
|
} from "@c-rex/ui/table";
|
|
9
|
-
import {
|
|
9
|
+
import { informationUnitsResponseItem } from "@c-rex/interfaces";
|
|
10
10
|
import { useTranslations } from "next-intl";
|
|
11
11
|
import { Ban, CloudDownload, CloudOff, Eye, EyeOff } from "lucide-react";
|
|
12
12
|
import { DropdownMenu } from "./dropdown-menu";
|
|
13
13
|
|
|
14
14
|
interface TableViewProps {
|
|
15
|
-
items:
|
|
15
|
+
items: informationUnitsResponseItem[];
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
const TableView: FC<TableViewProps> = ({ items }) => {
|
|
19
19
|
const t = useTranslations("results")
|
|
20
|
-
|
|
21
20
|
return (
|
|
22
21
|
<div className="rounded-md border">
|
|
23
22
|
<Table>
|
|
@@ -31,7 +30,7 @@ const TableView: FC<TableViewProps> = ({ items }) => {
|
|
|
31
30
|
</TableHeader>
|
|
32
31
|
<TableBody>
|
|
33
32
|
{items.map((item, index) => {
|
|
34
|
-
const clazz = `h-12 c-rex_result_row c-rex_result_${item.type.toLowerCase()} ${item.disabled ? "c-
|
|
33
|
+
const clazz = `h-12 c-rex_result_row c-rex_result_${item.type.toLowerCase()} ${item.disabled ? "c-rex_result_item_disabled" : ""}`
|
|
35
34
|
|
|
36
35
|
return (
|
|
37
36
|
<TableRow key={index} className={clazz}>
|
package/src/sidebar.tsx
CHANGED
|
@@ -26,7 +26,7 @@ interface SidebarProps extends ComponentProps<typeof Sidebar> {
|
|
|
26
26
|
availableVersions: SidebarAvailableVersionsInterface[]
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export function AppSidebar({ data, availableVersions, loading, className, ...props }: SidebarProps) {
|
|
29
|
+
export function AppSidebar({ data, availableVersions, loading, className, lang, ...props }: SidebarProps) {
|
|
30
30
|
const t = useTranslations();
|
|
31
31
|
|
|
32
32
|
const getFlagIcon = (countryCode: string): JSX.Element | null => {
|
|
@@ -40,7 +40,7 @@ export function AppSidebar({ data, availableVersions, loading, className, ...pro
|
|
|
40
40
|
const tableOfContentGroup = (): JSX.Element | null => {
|
|
41
41
|
if (loading) {
|
|
42
42
|
return (
|
|
43
|
-
|
|
43
|
+
<SidebarGroup className="pt-4">
|
|
44
44
|
<Skeleton className="w-auto h-10 mb-2" />
|
|
45
45
|
<Skeleton className="w-auto h-10 mb-2" />
|
|
46
46
|
<Skeleton className="w-auto h-10 mb-2 ml-8" />
|
|
@@ -48,14 +48,20 @@ export function AppSidebar({ data, availableVersions, loading, className, ...pro
|
|
|
48
48
|
<Skeleton className="w-auto h-10 mb-2 ml-8" />
|
|
49
49
|
<Skeleton className="w-auto h-10 mb-2 ml-8" />
|
|
50
50
|
<Skeleton className="w-auto h-10 mb-2" />
|
|
51
|
-
|
|
51
|
+
</SidebarGroup>
|
|
52
52
|
)
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
if (data.length == 0) return null;
|
|
56
56
|
|
|
57
|
+
const langProp = {} as any
|
|
58
|
+
|
|
59
|
+
if (lang) {
|
|
60
|
+
langProp.lang = lang
|
|
61
|
+
}
|
|
62
|
+
|
|
57
63
|
return (
|
|
58
|
-
<SidebarGroup>
|
|
64
|
+
<SidebarGroup {...langProp}>
|
|
59
65
|
<SidebarMenu>
|
|
60
66
|
{data.map((item) => (
|
|
61
67
|
<SidebarMenuItem key={item.id}>
|
package/src/cookies.tsx
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import { FC, useEffect } from "react";
|
|
4
|
-
import { CONTENT_LANG_KEY, UI_LANG_KEY, UI_LANG_OPTIONS } from "@c-rex/constants";
|
|
5
|
-
import { getCookieInFront } from "@c-rex/utils";
|
|
6
|
-
import { setCookie } from "@c-rex/utils/next-cookies";
|
|
7
|
-
import { ConfigInterface, LanguageAndCountries } from "@c-rex/interfaces";
|
|
8
|
-
|
|
9
|
-
type Props = {
|
|
10
|
-
configs: ConfigInterface;
|
|
11
|
-
availableLanguages: LanguageAndCountries[];
|
|
12
|
-
}
|
|
13
|
-
export const SetCookies: FC<Props> = ({ configs, availableLanguages }) => {
|
|
14
|
-
const manageUILanguage = async (configs: ConfigInterface): Promise<void> => {
|
|
15
|
-
const hasUILangCookie = await getCookieInFront(UI_LANG_KEY);
|
|
16
|
-
|
|
17
|
-
if (hasUILangCookie.value === null) {
|
|
18
|
-
const browserLang = navigator.language;
|
|
19
|
-
|
|
20
|
-
const locale = UI_LANG_OPTIONS.includes(browserLang.toLowerCase())
|
|
21
|
-
? browserLang
|
|
22
|
-
: configs.languageSwitcher.default;
|
|
23
|
-
|
|
24
|
-
setCookie(UI_LANG_KEY, locale);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const manageContentLanguage = async (configs: ConfigInterface, availableLanguages: LanguageAndCountries[]): Promise<void> => {
|
|
29
|
-
const hasContentLangCookie = await getCookieInFront(CONTENT_LANG_KEY);
|
|
30
|
-
|
|
31
|
-
if (hasContentLangCookie.value === null) {
|
|
32
|
-
const browserLang = navigator.language;
|
|
33
|
-
const hasLang = availableLanguages.some((item) => item.value === browserLang);
|
|
34
|
-
|
|
35
|
-
const locale = hasLang
|
|
36
|
-
? browserLang
|
|
37
|
-
: configs.languageSwitcher.default;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
setCookie(CONTENT_LANG_KEY, locale);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
manageUILanguage(configs);
|
|
46
|
-
manageContentLanguage(configs, availableLanguages);
|
|
47
|
-
}, [])
|
|
48
|
-
|
|
49
|
-
return null;
|
|
50
|
-
};
|