@c-rex/components 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c-rex/components",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "files": [
5
5
  "src"
6
6
  ],
@@ -56,6 +56,18 @@
56
56
  "./dialog-filter": {
57
57
  "types": "./src/dialog-filter.tsx",
58
58
  "import": "./src/dialog-filter.tsx"
59
+ },
60
+ "./check-article-lang": {
61
+ "types": "./src/check-article-lang.tsx",
62
+ "import": "./src/check-article-lang.tsx"
63
+ },
64
+ "./cookies": {
65
+ "types": "./src/cookies.tsx",
66
+ "import": "./src/cookies.tsx"
67
+ },
68
+ "./page-wrapper": {
69
+ "types": "./src/page-wrapper.tsx",
70
+ "import": "./src/page-wrapper.tsx"
59
71
  }
60
72
  },
61
73
  "scripts": {
@@ -102,6 +114,7 @@
102
114
  "nuqs": "^2.4.3",
103
115
  "react": "^18",
104
116
  "react-dom": "^18",
117
+ "react-icons": "^5.5.0",
105
118
  "tailwindcss-animate": "^1.0.7"
106
119
  },
107
120
  "eslintConfig": {
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { useState } from "react";
3
+ import React, { useState } from "react";
4
4
  import type { ComponentProps } from "react";
5
5
  import Image from "next/image";
6
6
  import { cn } from "@c-rex/utils";
@@ -0,0 +1,43 @@
1
+ "use client"
2
+
3
+ import { SidebarAvailableVersionsInterface } from "@c-rex/interfaces";
4
+ import { FC, useEffect, useRef } from "react";
5
+ import { toast } from "sonner"
6
+
7
+ interface Props {
8
+ availableVersions: SidebarAvailableVersionsInterface[]
9
+ contentLanguage: string
10
+ }
11
+
12
+ export const CheckArticleLangToast: FC<Props> = ({
13
+ availableVersions,
14
+ contentLanguage,
15
+ }) => {
16
+ const hasRun = useRef(false)
17
+
18
+ useEffect(() => {
19
+ if (hasRun.current) return
20
+ hasRun.current = true
21
+
22
+ const activeArticle = availableVersions.filter((item) => item.active)[0]
23
+ if (activeArticle == undefined || activeArticle.lang == contentLanguage) return
24
+
25
+ const articleAvailable = availableVersions.find((item) => item.lang === contentLanguage)
26
+ if (articleAvailable == undefined) return
27
+
28
+ showToast(articleAvailable.lang, articleAvailable.link)
29
+ }, [])
30
+
31
+ const showToast = (lang: string, link: string) => {
32
+ toast(`Read ${lang} version`, {
33
+ description: `This article is also available in ${lang}`,
34
+ action: {
35
+ label: `Open ${lang} version`,
36
+ onClick: () => window.location.href = link,
37
+ },
38
+ duration: 10000,
39
+ })
40
+ }
41
+
42
+ return null
43
+ }
@@ -0,0 +1,50 @@
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
+ };
@@ -11,7 +11,7 @@ import {
11
11
  } from "@c-rex/ui/dialog"
12
12
  import { Checkbox } from "@c-rex/ui/checkbox"
13
13
  import { Label } from "@c-rex/ui/label"
14
- import { useQueryState } from "nuqs"
14
+ import { parseAsInteger, parseAsString, useQueryStates } from "nuqs"
15
15
  import { useTranslations } from "next-intl"
16
16
 
17
17
  interface DialogFilterProps {
@@ -27,10 +27,13 @@ export const DialogFilter: FC<DialogFilterProps> = ({
27
27
  }) => {
28
28
  const t = useTranslations();
29
29
 
30
- const [_, setContentLanguage] = useQueryState('language', {
30
+ const [params, setParams] = useQueryStates({
31
+ language: parseAsString,
32
+ page: parseAsInteger,
33
+ }, {
31
34
  history: 'push',
32
35
  shallow: false,
33
- })
36
+ });
34
37
 
35
38
  const [languages, setLanguages] = useState(availableLanguages.map((item: any) => {
36
39
  const checked = startSelectedLanguages.includes(item.value)
@@ -50,7 +53,11 @@ export const DialogFilter: FC<DialogFilterProps> = ({
50
53
 
51
54
  const apply = () => {
52
55
  const selectedLanguages = languages.filter((item: any) => item.checked).map((item: any) => item.value).join(',')
53
- setContentLanguage(selectedLanguages)
56
+
57
+ setParams({
58
+ page: 1,
59
+ language: selectedLanguages,
60
+ });
54
61
  }
55
62
 
56
63
  return (
@@ -1,27 +1,42 @@
1
1
  'use client'
2
2
 
3
- import React, { FC, startTransition } from "react";
3
+ import React, { FC, startTransition, useEffect, useState } from "react";
4
4
  import { LanguageAndCountries } from "@c-rex/interfaces";
5
5
  import { SharedLanguageSwitch } from "./shared";
6
6
  import { setCookie } from "@c-rex/utils/next-cookies";
7
- import { CONTENT_LANG_KEY, DEFAULT_UI_LANG } from "@c-rex/constants";
7
+ import { CONTENT_LANG_KEY } from "@c-rex/constants";
8
8
  import { useQueryState } from "nuqs"
9
+ import { getCookieInFront } from "@c-rex/utils";
9
10
 
10
11
  interface ContentLanguageSwitchProps {
11
12
  availableLanguagesAndCountries: LanguageAndCountries[];
12
13
  }
13
14
  export const ContentLanguageSwitch: FC<ContentLanguageSwitchProps> = ({ availableLanguagesAndCountries }) => {
14
-
15
- const [contentLanguage, setContentLanguage] = useQueryState('language', {
15
+ const [selected, setSelected] = useState("");
16
+ const [queryLanguage, setContentLanguage] = useQueryState('language', {
16
17
  history: 'push',
17
18
  shallow: false,
18
- defaultValue: DEFAULT_UI_LANG
19
19
  })
20
20
 
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
+
21
33
  const changeContentLanguage = (locale: string) => {
22
34
  startTransition(() => {
23
35
  setCookie(CONTENT_LANG_KEY, locale)
24
- setContentLanguage(locale)
36
+
37
+ if (queryLanguage != null) {
38
+ setContentLanguage(locale)
39
+ }
25
40
  });
26
41
  };
27
42
 
@@ -29,7 +44,7 @@ export const ContentLanguageSwitch: FC<ContentLanguageSwitchProps> = ({ availabl
29
44
  <SharedLanguageSwitch
30
45
  availableLanguagesAndCountries={availableLanguagesAndCountries}
31
46
  changeLanguage={changeContentLanguage}
32
- selected={contentLanguage}
47
+ selected={selected}
33
48
  />
34
49
  );
35
50
  };
@@ -23,8 +23,8 @@ export const SharedLanguageSwitch: FC<SharedLanguageSwitchProps> = ({ availableL
23
23
  {availableLanguagesAndCountries.map(item => {
24
24
  return (
25
25
  <DropdownMenuRadioItem key={item.value} value={item.value}>
26
- <span>{item.lang.toUpperCase()}</span>
27
26
  {getFlagIcon(item.country)}
27
+ <span>{item.lang.toUpperCase()}</span>
28
28
  </DropdownMenuRadioItem>
29
29
  )
30
30
  })}
@@ -1,26 +1,35 @@
1
1
  "use client"
2
2
 
3
3
  import React, { FC, startTransition, useEffect, useState } from "react";
4
- import { LanguageAndCountries } from "@c-rex/interfaces";
5
4
  import { SharedLanguageSwitch } from "./shared";
6
5
  import { setCookie } from "@c-rex/utils/next-cookies";
7
- import { DEFAULT_UI_LANG, UI_LANG_KEY } from "@c-rex/constants";
6
+ import { UI_LANG_KEY, UI_LANG_OPTIONS } from "@c-rex/constants";
7
+ import { getCookieInFront, getCountryCodeByLang } from "@c-rex/utils";
8
8
 
9
- interface UILanguageSwitchProps {
10
- availableLanguagesAndCountries: LanguageAndCountries[];
11
- }
12
- export const UILanguageSwitch: FC<UILanguageSwitchProps> = ({ availableLanguagesAndCountries }) => {
13
- const [selected, setSelected] = useState(DEFAULT_UI_LANG);
9
+ export const UILanguageSwitch: FC = () => {
10
+ const UILanguages = UI_LANG_OPTIONS.map((lang) => {
11
+
12
+ const langCode = lang.split("-")[0] as string;
13
+ return {
14
+ value: lang,
15
+ lang: langCode,
16
+ country: getCountryCodeByLang(langCode)
17
+ };
18
+ })
19
+
20
+ const [selected, setSelected] = useState("");
14
21
 
15
22
  useEffect(() => {
16
- const allCookies = document.cookie
17
- const uiLang = allCookies
18
- .split('; ')
19
- .find(row => row.startsWith(`${UI_LANG_KEY}=`))
20
- ?.split('=')[1]
21
- setSelected(uiLang as string)
22
- }, [])
23
+ const get = async () => {
24
+ const uiLang = await getCookieInFront(UI_LANG_KEY)
23
25
 
26
+ if (uiLang.value != null) {
27
+ setSelected(uiLang.value.toLowerCase())
28
+ return
29
+ }
30
+ }
31
+ get()
32
+ }, [])
24
33
 
25
34
  const setUILanguage = (locale: string) => {
26
35
  startTransition(() => {
@@ -30,7 +39,7 @@ export const UILanguageSwitch: FC<UILanguageSwitchProps> = ({ availableLanguages
30
39
 
31
40
  return (
32
41
  <SharedLanguageSwitch
33
- availableLanguagesAndCountries={availableLanguagesAndCountries}
42
+ availableLanguagesAndCountries={UILanguages}
34
43
  changeLanguage={setUILanguage}
35
44
  selected={selected}
36
45
  />
@@ -2,9 +2,6 @@ import React, { FC } from "react";
2
2
  import Link from "next/link";
3
3
  import Image from "next/image";
4
4
  import { SignOut, SignInBtn } from "./sign-in-out-btns";
5
- import { getServerSession } from "next-auth";
6
- import { getCookie } from '@c-rex/utils/next-cookies';
7
- import { ConfigInterface } from "@c-rex/interfaces";
8
5
  import {
9
6
  DropdownMenu,
10
7
  DropdownMenuContent,
@@ -16,47 +13,36 @@ import {
16
13
  DropdownMenuSubTrigger,
17
14
  DropdownMenuTrigger,
18
15
  } from "@c-rex/ui/dropdown-menu"
19
- import { SDK_CONFIG_KEY, UI_LANG_OPTIONS } from "@c-rex/constants";
20
- import { LanguageService } from "@c-rex/services";
21
- import { Settings } from "lucide-react";
16
+ import { Search, Settings } from "lucide-react";
22
17
  import { ContentLanguageSwitch } from "./language-switcher/content-language-switch";
23
18
  import { getTranslations } from "next-intl/server";
24
- import { getCountryCodeByLang } from "@c-rex/utils";
25
19
  import { UILanguageSwitch } from "./language-switcher/ui-language-switch";
20
+ import { Input } from "@c-rex/ui/input";
21
+ import { getServerSession } from "next-auth";
22
+ import { getConfigs } from "@c-rex/utils/next-cookies";
23
+ import { LanguageService } from "@c-rex/services";
24
+
26
25
 
27
26
  interface NavBarProps {
28
- scroll?: boolean;
29
- large?: boolean;
27
+ title: string;
30
28
  }
31
29
 
32
- export const NavBar: FC<NavBarProps> = async () => {
30
+ export const NavBar: FC<NavBarProps> = async ({ title }) => {
33
31
  const t = await getTranslations();
34
- let session;
35
-
36
- const jsonConfigs = await getCookie(SDK_CONFIG_KEY);
37
- if (!jsonConfigs) {
38
- return null;
39
- }
40
-
41
- const configs: ConfigInterface = JSON.parse(jsonConfigs);
42
- const service = new LanguageService(configs.languageSwitcher.endpoint);
43
- const contentLanguages = await service.getLanguagesAndCountries();
32
+ const configs = await getConfigs();
33
+ const languageService = new LanguageService(configs.languageSwitcher.endpoint);
34
+ const availableLanguagesAndCountries = await languageService.getLanguagesAndCountries();
44
35
 
36
+ let session: any;
45
37
  if (configs.OIDC.user.enabled) {
46
38
  session = await getServerSession();
47
39
  }
48
40
 
49
- const UILanguages = UI_LANG_OPTIONS.map((lang) => ({
50
- value: lang,
51
- lang: lang,
52
- country: getCountryCodeByLang(lang)
53
- }));
54
-
55
41
  return (
56
- <header className="sticky top-0 z-40 flex w-full bg-background/60 backdrop-blur-xl transition-all bg-transparent border-b justify-center py-4">
57
- <div className="container flex justify-between">
58
- <div className="flex gap-6 md:gap-10">
59
- <Link href="/" className="flex items-center space-x-1.5">
42
+ <header className="sticky top-0 z-40 flex w-full backdrop-blur-xl transition-all bg-transparent border-b justify-center py-4">
43
+ <div className="w-full px-4 flex justify-between">
44
+ <div className="flex">
45
+ <Link href="/" className="flex items-center justify-center space-x-1.5 w-60">
60
46
  <Image
61
47
  src="/img/logo.png"
62
48
  alt="C-rex Logo"
@@ -64,10 +50,20 @@ export const NavBar: FC<NavBarProps> = async () => {
64
50
  height={50}
65
51
  />
66
52
  </Link>
67
- {configs.projectName}
53
+
54
+ {title.length > 0 && (
55
+ <div className="flex items-center">
56
+ <h1 className="px-4 text-3xl font-bold tracking-tight text-balance">{title}</h1>
57
+ </div>
58
+ )}
68
59
  </div>
69
60
 
70
61
  <div className="flex items-center space-x-3">
62
+ <div className="flex items-center px-3 border rounded-full h-8">
63
+ <Search className="h-4 w-4 shrink-0 opacity-50" />
64
+ <Input variant="embedded" placeholder="Search" />
65
+ </div>
66
+
71
67
  {configs.OIDC.user.enabled && (
72
68
  <>
73
69
  {session ? (
@@ -86,7 +82,7 @@ export const NavBar: FC<NavBarProps> = async () => {
86
82
  <DropdownMenuTrigger>
87
83
  <Settings />
88
84
  </DropdownMenuTrigger>
89
- <DropdownMenuContent>
85
+ <DropdownMenuContent align="start" sideOffset={20} alignOffset={20}>
90
86
  <DropdownMenuLabel>{t("accountSettings.accountSettings")}</DropdownMenuLabel>
91
87
  <DropdownMenuSeparator />
92
88
 
@@ -98,7 +94,7 @@ export const NavBar: FC<NavBarProps> = async () => {
98
94
  <DropdownMenuPortal>
99
95
  <DropdownMenuSubContent>
100
96
  <ContentLanguageSwitch
101
- availableLanguagesAndCountries={contentLanguages}
97
+ availableLanguagesAndCountries={availableLanguagesAndCountries}
102
98
  />
103
99
  </DropdownMenuSubContent>
104
100
  </DropdownMenuPortal>
@@ -112,9 +108,7 @@ export const NavBar: FC<NavBarProps> = async () => {
112
108
 
113
109
  <DropdownMenuPortal>
114
110
  <DropdownMenuSubContent>
115
- <UILanguageSwitch
116
- availableLanguagesAndCountries={UILanguages}
117
- />
111
+ <UILanguageSwitch />
118
112
  </DropdownMenuSubContent>
119
113
  </DropdownMenuPortal>
120
114
  </DropdownMenuSub>
@@ -0,0 +1,16 @@
1
+ import React from "react";
2
+ import { NavBar } from './navbar/navbar';
3
+
4
+ type Props = {
5
+ children: React.ReactNode;
6
+ title: string;
7
+ }
8
+
9
+ export const PageWrapper = ({ children, title }: Props) => {
10
+ return (
11
+ <>
12
+ <NavBar title={title} />
13
+ {children}
14
+ </>
15
+ );
16
+ }
@@ -0,0 +1,65 @@
1
+ import React, { FC } from "react";
2
+ import {
3
+ Pagination as PaginationUI,
4
+ PaginationContent,
5
+ PaginationItem,
6
+ PaginationLink,
7
+ PaginationNext,
8
+ PaginationPrevious,
9
+ } from "@c-rex/ui/pagination"
10
+ import { parseAsInteger, useQueryState } from "nuqs";
11
+
12
+ interface PaginationProps {
13
+ totalPages: number;
14
+ currentPage: number;
15
+ }
16
+
17
+ export const Pagination: FC<PaginationProps> = ({ totalPages, currentPage }) => {
18
+ const disabledClass = "opacity-50 pointer-events-none";
19
+
20
+ const [_, setPage] = useQueryState('page',
21
+ parseAsInteger.withOptions({
22
+ history: 'push',
23
+ shallow: false,
24
+ })
25
+ )
26
+
27
+ return (
28
+ <PaginationUI className="py-4">
29
+ <PaginationContent>
30
+ <PaginationItem>
31
+ <PaginationPrevious
32
+ href="#"
33
+ className={currentPage === 1 ? disabledClass : ""}
34
+ onClick={() => setPage(currentPage - 1)}
35
+ />
36
+ </PaginationItem>
37
+
38
+ {Array.from({ length: totalPages }, (_, index) => index + 1).map((page) => (
39
+ <PaginationItem key={page}>
40
+ <PaginationLink
41
+ href="#"
42
+ isActive={page === currentPage}
43
+ onClick={() => setPage(page)}
44
+ >
45
+ {page}
46
+ </PaginationLink>
47
+ </PaginationItem>
48
+ ))}
49
+
50
+ {/*
51
+ <PaginationItem>
52
+ <PaginationEllipsis />
53
+ </PaginationItem>
54
+ */}
55
+ <PaginationItem>
56
+ <PaginationNext
57
+ href="#"
58
+ onClick={() => setPage(currentPage + 1)}
59
+ className={currentPage === totalPages ? disabledClass : ""}
60
+ />
61
+ </PaginationItem>
62
+ </PaginationContent>
63
+ </PaginationUI>
64
+ )
65
+ }
@@ -1,72 +1,37 @@
1
1
  import React, { FC } from "react";
2
- import { ConfigInterface, informationUnitsItems, Labels } from "@c-rex/interfaces";
2
+ import { ConfigInterface, DefaultPageInfo, informationUnitsResponseItems, } 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
- import { useLocale } from "next-intl";
7
- import { DEFAULT_UI_LANG, RESULT_TYPES } from "@c-rex/constants";
6
+ import { Pagination } from "./pagination";
8
7
 
9
8
  interface ResultListProps {
10
- items: informationUnitsItems[];
11
- configs: ConfigInterface
9
+ items: informationUnitsResponseItems[];
10
+ configs: ConfigInterface;
11
+ pagination: DefaultPageInfo;
12
12
  }
13
13
 
14
- export const ResultList: FC<ResultListProps> = ({ items, configs }) => {
15
- const locale = useLocale();
16
- const ViewComponent = configs.resultViewStyle == "table" ? TableView : BlogView;
17
-
18
- const getTitle = (labels: Labels[]): string => {
19
- if (labels === undefined) {
20
- return "";
21
- }
22
- return labels.map((item) => item.value).join();
23
- };
24
-
25
- const getType = (labels: Labels[]): { localeLabel: string, comparableLabel: string } => {
26
- const localeLabel = labels.find((item) => item.language === locale);
27
- const comparableLabel = labels.find((item) => item.language === DEFAULT_UI_LANG);
28
-
29
- if (!localeLabel || !comparableLabel) {
30
- return {
31
- localeLabel: "",
32
- comparableLabel: ""
33
- }
34
- }
35
-
36
- return {
37
- localeLabel: localeLabel.value,
38
- comparableLabel: comparableLabel.value
39
- }
40
- }
41
-
42
- const handleByType = (type: string, shortId: string) => {
43
- switch (type) {
44
- case RESULT_TYPES.TOPIC:
45
- window.location.href = `/topics/${shortId}`;
46
- break;
47
- case RESULT_TYPES.DOCUMENT:
48
- //should check if its a pdf or not
49
- // if pdf then open in new tab
50
- // else download the file
51
- window.open(`/documents/${shortId}`, '_blank');
52
- break;
53
- }
54
- }
14
+ export const ResultList: FC<ResultListProps> = ({ items, configs, pagination }: ResultListProps) => {
15
+ const ViewComponent = configs.results.resultViewStyle == "table" ? TableView : BlogView;
55
16
 
56
17
  return (
57
- <div>
18
+ <>
58
19
  {
59
20
  items.length == 0 ? (
60
21
  <Empty />
61
22
  ) : (
62
- <ViewComponent
63
- items={items}
64
- getTitle={getTitle}
65
- getType={getType}
66
- handleByType={handleByType}
67
- />
23
+ <>
24
+ <ViewComponent
25
+ items={items}
26
+ />
27
+
28
+ <Pagination
29
+ totalPages={pagination.pageCount}
30
+ currentPage={pagination.pageNumber}
31
+ />
32
+ </>
68
33
  )
69
34
  }
70
- </div>
35
+ </>
71
36
  );
72
37
  };
@@ -1,14 +1,12 @@
1
1
  import React, { FC } from "react";
2
2
  import { BlogCard } from "../blog-card";
3
- import { informationUnitsItems, Labels } from "@c-rex/interfaces";
3
+ import { informationUnitsResponseItems } from "@c-rex/interfaces";
4
4
 
5
5
  interface BlogViewProps {
6
- items: informationUnitsItems[];
7
- getType: (labels: Labels[]) => { localeLabel: string, comparableLabel: string };
8
- getTitle: (labels: Labels[]) => string;
6
+ items: informationUnitsResponseItems[];
9
7
  }
10
8
 
11
- const BlogView: FC<BlogViewProps> = ({ items, getTitle, getType }) => {
9
+ const BlogView: FC<BlogViewProps> = ({ items }) => {
12
10
 
13
11
  return (
14
12
  <div className="grid gap-8 md:grid-cols-2 md:gap-x-6 md:gap-y-10 xl:grid-cols-3">
@@ -17,14 +15,14 @@ const BlogView: FC<BlogViewProps> = ({ items, getTitle, getType }) => {
17
15
  <BlogCard
18
16
  key={index}
19
17
  data={{
20
- title: getTitle(item.labels),
18
+ title: item.title,
21
19
  blurDataURL: "/img/blog-post-1.webp",
22
20
  image: "/img/blog-post-1.webp",
23
- description: getType(item.class.labels).localeLabel,
21
+ description: item.type,
24
22
  authors: "item.authors",
25
23
  _id: "item._id",
26
24
  date: "item.date",
27
- slug: `info/${item.shortId}`,
25
+ slug: item.link,
28
26
  }}
29
27
  />
30
28
  );
@@ -0,0 +1,39 @@
1
+ import React, { FC, JSX } from "react";
2
+ import {
3
+ DropdownMenu as DropdownMenuComp,
4
+ DropdownMenuContent,
5
+ DropdownMenuItem,
6
+ DropdownMenuTrigger,
7
+ } from "@c-rex/ui/dropdown-menu";
8
+
9
+ interface DropdownMenuProps {
10
+ items: {
11
+ format: string;
12
+ link: string;
13
+ }[];
14
+ icon: JSX.Element;
15
+ }
16
+
17
+ export const DropdownMenu: FC<DropdownMenuProps> = ({
18
+ items, icon
19
+ }) => {
20
+
21
+ return (
22
+ <DropdownMenuComp>
23
+ <DropdownMenuTrigger className="mx-2">
24
+ {icon}
25
+ </DropdownMenuTrigger>
26
+ <DropdownMenuContent>
27
+ {items.map((file, index) => {
28
+ return (
29
+ <DropdownMenuItem key={index}>
30
+ <a href={file.link} target="_blank" rel="noreferrer">
31
+ {file.format}
32
+ </a>
33
+ </DropdownMenuItem>
34
+ )
35
+ })}
36
+ </DropdownMenuContent>
37
+ </DropdownMenuComp>
38
+ );
39
+ };
@@ -6,17 +6,16 @@ import {
6
6
  TableHeader,
7
7
  TableRow,
8
8
  } from "@c-rex/ui/table";
9
- import { informationUnitsItems, Labels } from "@c-rex/interfaces";
9
+ import { informationUnitsResponseItems } from "@c-rex/interfaces";
10
10
  import { useTranslations } from "next-intl";
11
+ import { Ban, CloudDownload, CloudOff, Eye, EyeOff } from "lucide-react";
12
+ import { DropdownMenu } from "./dropdown-menu";
11
13
 
12
14
  interface TableViewProps {
13
- items: informationUnitsItems[];
14
- getType: (labels: Labels[]) => { localeLabel: string, comparableLabel: string };
15
- getTitle: (labels: Labels[]) => string;
16
- handleByType: any;
15
+ items: informationUnitsResponseItems[];
17
16
  }
18
17
 
19
- const TableView: FC<TableViewProps> = ({ items, getType, getTitle, handleByType }) => {
18
+ const TableView: FC<TableViewProps> = ({ items }) => {
20
19
  const t = useTranslations("results")
21
20
 
22
21
  return (
@@ -27,25 +26,51 @@ const TableView: FC<TableViewProps> = ({ items, getType, getTitle, handleByType
27
26
  <TableCell>{t("title")}</TableCell>
28
27
  <TableCell>{t("type")}</TableCell>
29
28
  <TableCell>{t("language")}</TableCell>
29
+ <TableCell>{t("files")}</TableCell>
30
30
  </TableRow>
31
31
  </TableHeader>
32
32
  <TableBody>
33
- {items.map((item: informationUnitsItems, index: number) => {
34
- const type = getType(item.class.labels);
35
- let lang = "";
36
-
37
- if (item.languages.length > 0) {
38
- lang = item.languages[0] as string;
39
- lang = lang.split("-")[0] as string;
40
- }
33
+ {items.map((item, index) => {
34
+ const clazz = `h-12 c-rex_result_row c-rex_result_${item.type.toLowerCase()} ${item.disabled ? "c-rex_result_row_disabled" : ""}`
41
35
 
42
36
  return (
43
- <TableRow key={index}>
44
- <TableCell className="cursor-pointer" onClick={() => handleByType(type.comparableLabel.toUpperCase(), item.shortId)}>
45
- {getTitle(item.labels)}
37
+ <TableRow key={index} className={clazz}>
38
+ <TableCell className="h-12 c-rex_result_cell">
39
+ {item.disabled ? (item.title) : (<a href={item.link}>{item.title}</a>)}
40
+ </TableCell>
41
+ <TableCell>{item.type}</TableCell>
42
+ <TableCell>{item.language}</TableCell>
43
+ <TableCell>
44
+ {(item.disabled || (item.filesToDownload.length == 0 && item.filesToOpen.length == 0)) ? (
45
+ <button disabled className="mx-2">
46
+ <Ban />
47
+ </button>
48
+ ) : (
49
+ <>
50
+ {item.filesToDownload.length == 0 ? (
51
+ <button disabled className="mx-2">
52
+ <CloudOff />
53
+ </button>
54
+ ) : (
55
+ <DropdownMenu
56
+ items={item.filesToDownload}
57
+ icon={<CloudDownload />}
58
+ />
59
+ )}
60
+
61
+ {item.filesToOpen.length == 0 ? (
62
+ <button disabled className="mx-2">
63
+ <EyeOff />
64
+ </button>
65
+ ) : (
66
+ <DropdownMenu
67
+ items={item.filesToOpen}
68
+ icon={<Eye />}
69
+ />
70
+ )}
71
+ </>
72
+ )}
46
73
  </TableCell>
47
- <TableCell>{type.localeLabel}</TableCell>
48
- <TableCell>{lang.toUpperCase()}</TableCell>
49
74
  </TableRow>
50
75
  )
51
76
  })}
package/src/sidebar.tsx CHANGED
@@ -4,6 +4,7 @@ import React, { ComponentProps, JSX } from "react";
4
4
  import {
5
5
  Sidebar,
6
6
  SidebarContent,
7
+ SidebarFooter,
7
8
  SidebarGroup,
8
9
  SidebarGroupLabel,
9
10
  SidebarMenu,
@@ -12,12 +13,12 @@ import {
12
13
  SidebarMenuSub,
13
14
  SidebarMenuSubButton,
14
15
  SidebarMenuSubItem,
15
- SidebarRail
16
16
  } from "@c-rex/ui/sidebar";
17
17
  import { Skeleton } from "@c-rex/ui/skeleton";
18
18
  import { SidebarAvailableVersionsInterface, TreeOfContent } from "@c-rex/interfaces";
19
19
  import * as Flags from 'country-flag-icons/react/3x2';
20
20
  import { useTranslations } from "next-intl";
21
+ import { cn } from "@c-rex/utils";
21
22
 
22
23
  interface SidebarProps extends ComponentProps<typeof Sidebar> {
23
24
  data: TreeOfContent[];
@@ -25,7 +26,7 @@ interface SidebarProps extends ComponentProps<typeof Sidebar> {
25
26
  availableVersions: SidebarAvailableVersionsInterface[]
26
27
  }
27
28
 
28
- export function AppSidebar({ data, availableVersions, loading, ...props }: SidebarProps) {
29
+ export function AppSidebar({ data, availableVersions, loading, className, ...props }: SidebarProps) {
29
30
  const t = useTranslations();
30
31
 
31
32
  const getFlagIcon = (countryCode: string): JSX.Element | null => {
@@ -54,8 +55,7 @@ export function AppSidebar({ data, availableVersions, loading, ...props }: Sideb
54
55
  if (data.length == 0) return null;
55
56
 
56
57
  return (
57
- <SidebarGroup className="my-4">
58
- <SidebarGroupLabel>{t("tableOfContent")}:</SidebarGroupLabel>
58
+ <SidebarGroup>
59
59
  <SidebarMenu>
60
60
  {data.map((item) => (
61
61
  <SidebarMenuItem key={item.id}>
@@ -93,10 +93,10 @@ export function AppSidebar({ data, availableVersions, loading, ...props }: Sideb
93
93
  if (availableVersions.length == 0) return null;
94
94
 
95
95
  return (
96
- <SidebarGroup>
96
+ <>
97
97
  <SidebarGroupLabel>{t("availableIn")}:</SidebarGroupLabel>
98
98
  <SidebarMenu>
99
- {availableVersions.map((item: any) => {
99
+ {availableVersions.map((item) => {
100
100
  return (
101
101
  <SidebarMenuItem key={item.shortId}>
102
102
  <SidebarMenuButton asChild isActive={item.active}>
@@ -108,18 +108,19 @@ export function AppSidebar({ data, availableVersions, loading, ...props }: Sideb
108
108
  )
109
109
  })}
110
110
  </SidebarMenu>
111
- </SidebarGroup>
111
+ </>
112
112
  )
113
113
 
114
114
  }
115
115
 
116
116
  return (
117
- <Sidebar collapsible="icon" {...props}>
117
+ <Sidebar className={cn(className, "pt-20")} {...props}>
118
118
  <SidebarContent>
119
119
  {tableOfContentGroup()}
120
- {availableVersionsGroup()}
121
120
  </SidebarContent>
122
- <SidebarRail />
121
+ <SidebarFooter>
122
+ {availableVersionsGroup()}
123
+ </SidebarFooter>
123
124
  </Sidebar>
124
125
  );
125
126
  }