diff --git a/CHANGELOG.md b/CHANGELOG.md
index b544febf..5aab3e34 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ and this project adheres to
- ๐๏ธ(yjs-server) organize yjs server #528
- โป๏ธ(frontend) better separation collaboration process #528
- ๐(frontend) updating the header and leftpanel for responsive #421
+- ๐(frontend) update DocsGrid component #431
## [1.10.0] - 2024-12-17
diff --git a/src/frontend/apps/impress/src/components/Card.tsx b/src/frontend/apps/impress/src/components/Card.tsx
index 95122594..5e3d5ed7 100644
--- a/src/frontend/apps/impress/src/components/Card.tsx
+++ b/src/frontend/apps/impress/src/components/Card.tsx
@@ -17,8 +17,7 @@ export const Card = ({
$background="white"
$radius="4px"
$css={css`
- box-shadow: 2px 2px 5px ${colorsTokens()['greyscale-300']};
- border: 1px solid ${colorsTokens()['card-border']};
+ border: 1px solid ${colorsTokens()['greyscale-200']};
${$css}
`}
{...props}
diff --git a/src/frontend/apps/impress/src/components/Icon.tsx b/src/frontend/apps/impress/src/components/Icon.tsx
index cdda0bbe..b5d44381 100644
--- a/src/frontend/apps/impress/src/components/Icon.tsx
+++ b/src/frontend/apps/impress/src/components/Icon.tsx
@@ -1,12 +1,15 @@
import { Text, TextType } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
-type IconProps = {
+type IconProps = TextType & {
iconName: string;
- className?: string;
};
-export const Icon = ({ iconName, className }: IconProps) => {
- return {iconName};
+export const Icon = ({ iconName, ...textProps }: IconProps) => {
+ return (
+
+ {iconName}
+
+ );
};
interface IconBGProps extends TextType {
diff --git a/src/frontend/apps/impress/src/components/Text.tsx b/src/frontend/apps/impress/src/components/Text.tsx
index 7982d1b4..2764f74c 100644
--- a/src/frontend/apps/impress/src/components/Text.tsx
+++ b/src/frontend/apps/impress/src/components/Text.tsx
@@ -33,6 +33,7 @@ export interface TextProps extends BoxProps {
| 'greyscale';
$variation?:
| 'text'
+ | '000'
| '100'
| '200'
| '300'
@@ -41,7 +42,8 @@ export interface TextProps extends BoxProps {
| '600'
| '700'
| '800'
- | '900';
+ | '900'
+ | '1000';
}
export type TextType = ComponentPropsWithRef;
diff --git a/src/frontend/apps/impress/src/cunningham/useCunninghamTheme.tsx b/src/frontend/apps/impress/src/cunningham/useCunninghamTheme.tsx
index 0de4513e..3bc853a2 100644
--- a/src/frontend/apps/impress/src/cunningham/useCunninghamTheme.tsx
+++ b/src/frontend/apps/impress/src/cunningham/useCunninghamTheme.tsx
@@ -5,6 +5,7 @@ import { tokens } from './cunningham-tokens';
type Tokens = typeof tokens.themes.default & Partial;
type ColorsTokens = Tokens['theme']['colors'];
+type FontSizesTokens = Tokens['theme']['font']['sizes'];
type SpacingsTokens = Tokens['theme']['spacings'];
type ComponentTokens = Tokens['components'];
export type Theme = keyof typeof tokens.themes;
@@ -14,6 +15,7 @@ interface AuthStore {
setTheme: (theme: Theme) => void;
themeTokens: () => Partial;
colorsTokens: () => Partial;
+ fontSizesTokens: () => Partial;
spacingsTokens: () => Partial;
componentTokens: () => ComponentTokens;
}
@@ -31,6 +33,7 @@ export const useCunninghamTheme = create((set, get) => {
colorsTokens: () => currentTheme().theme.colors,
componentTokens: () => currentTheme().components,
spacingsTokens: () => currentTheme().theme.spacings,
+ fontSizesTokens: () => currentTheme().theme.font.sizes,
setTheme: (theme: Theme) => {
set({ theme });
},
diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/api/useDocs.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/api/useDocs.tsx
index 9487684e..f3339aa1 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-management/api/useDocs.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-management/api/useDocs.tsx
@@ -1,6 +1,12 @@
import { UseQueryOptions, useQuery } from '@tanstack/react-query';
-import { APIError, APIList, errorCauses, fetchAPI } from '@/api';
+import {
+ APIError,
+ APIList,
+ errorCauses,
+ fetchAPI,
+ useAPIInfiniteQuery,
+} from '@/api';
import { Doc } from '../types';
@@ -52,3 +58,7 @@ export function useDocs(
...queryConfig,
});
}
+
+export const useInfiniteDocs = (params: DocsParams) => {
+ return useAPIInfiniteQuery(KEY_LIST_DOC, getDocs, params);
+};
diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/api/useRemoveDoc.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/api/useRemoveDoc.tsx
index 21c70ced..c64ee3b2 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-management/api/useRemoveDoc.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-management/api/useRemoveDoc.tsx
@@ -30,7 +30,7 @@ export const useRemoveDoc = (options?: UseRemoveDocOptions) => {
mutationFn: removeDoc,
...options,
onSuccess: (data, variables, context) => {
- void queryClient.resetQueries({
+ void queryClient.invalidateQueries({
queryKey: [KEY_LIST_DOC],
});
if (options?.onSuccess) {
diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/assets/pinned-document.svg b/src/frontend/apps/impress/src/features/docs/doc-management/assets/pinned-document.svg
new file mode 100644
index 00000000..cccfed37
--- /dev/null
+++ b/src/frontend/apps/impress/src/features/docs/doc-management/assets/pinned-document.svg
@@ -0,0 +1,9 @@
+
diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/assets/simple-document.svg b/src/frontend/apps/impress/src/features/docs/doc-management/assets/simple-document.svg
new file mode 100644
index 00000000..ad4cfcef
--- /dev/null
+++ b/src/frontend/apps/impress/src/features/docs/doc-management/assets/simple-document.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGrid.tsx b/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGrid.tsx
index 50069ee3..2f8536c1 100644
--- a/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGrid.tsx
+++ b/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGrid.tsx
@@ -1,220 +1,92 @@
-import {
- Column,
- DataGrid,
- SortModel,
- usePagination,
-} from '@openfun/cunningham-react';
-import React, { useEffect, useState } from 'react';
+import { Button, Loader } from '@openfun/cunningham-react';
import { useTranslation } from 'react-i18next';
-import { createGlobalStyle } from 'styled-components';
+import { InView } from 'react-intersection-observer';
-import { Card, StyledLink, Text, TextErrors } from '@/components';
-import { useCunninghamTheme } from '@/cunningham';
-import {
- Doc,
- DocsOrdering,
- LinkReach,
- currentDocRole,
- isDocsOrdering,
- useDocs,
- useTrans,
-} from '@/features/docs/doc-management';
-import { useDate } from '@/hook/';
+import { Box, Card, Text } from '@/components';
import { useResponsiveStore } from '@/stores';
-import { PAGE_SIZE } from '../conf';
+import { useInfiniteDocs } from '../../doc-management';
-import { DocsGridActions } from './DocsGridActions';
-
-const DocsGridStyle = createGlobalStyle`
- & .c__datagrid thead{
- position: sticky;
- top: 0;
- background: #fff;
- z-index: 1;
- }
- & .c__pagination__goto{
- display:none;
- }
-`;
-
-type SortModelItem = {
- field: string;
- sort: 'asc' | 'desc' | null;
-};
-
-function formatSortModel(sortModel: SortModelItem): DocsOrdering | undefined {
- const { field, sort } = sortModel;
- const orderingField = sort === 'desc' ? `-${field}` : field;
-
- if (isDocsOrdering(orderingField)) {
- return orderingField;
- }
-}
+import { DocsGridItem } from './DocsGridItem';
export const DocsGrid = () => {
- const { colorsTokens } = useCunninghamTheme();
- const { transRole } = useTrans();
const { t } = useTranslation();
- const { formatDate } = useDate();
- const pagination = usePagination({
- pageSize: PAGE_SIZE,
- });
- const [sortModel, setSortModel] = useState([
- {
- field: 'updated_at',
- sort: 'desc',
- },
- ]);
- const { page, pageSize, setPagesCount } = pagination;
- const [docs, setDocs] = useState([]);
- const { isMobile } = useResponsiveStore();
- const ordering = sortModel.length ? formatSortModel(sortModel[0]) : undefined;
+ const { isDesktop } = useResponsiveStore();
- const { data, isLoading, error } = useDocs({
- page,
- ordering,
- });
+ const { data, isFetching, isLoading, fetchNextPage, hasNextPage } =
+ useInfiniteDocs({
+ page: 1,
+ });
+ const loading = isFetching || isLoading;
- useEffect(() => {
- if (isLoading) {
+ const loadMore = (inView: boolean) => {
+ if (!inView || loading) {
return;
}
-
- setDocs(data?.results || []);
- }, [data?.results, t, isLoading]);
-
- useEffect(() => {
- setPagesCount(data?.count ? Math.ceil(data.count / pageSize) : 0);
- }, [data?.count, pageSize, setPagesCount]);
-
- const columns: Column[] = [
- {
- headerName: '',
- id: 'visibility',
- size: 95,
- renderCell: ({ row }) => {
- return (
- row.link_reach === LinkReach.PUBLIC && (
-
-
- {t('Public')}
-
-
- )
- );
- },
- },
- {
- headerName: t('Document name'),
- field: 'title',
- renderCell: ({ row }) => {
- return (
-
-
- {row.title}
-
-
- );
- },
- },
- {
- headerName: t('Created at'),
- field: 'created_at',
- renderCell: ({ row }) => {
- return (
-
- {formatDate(row.created_at)}
-
- );
- },
- },
- {
- headerName: t('Updated at'),
- field: 'updated_at',
- renderCell: ({ row }) => {
- return (
-
- {formatDate(row.updated_at)}
-
- );
- },
- },
- {
- headerName: t('Your role'),
- id: 'your_role',
- renderCell: ({ row }) => {
- return (
-
-
- {transRole(currentDocRole(row.abilities))}
-
-
- );
- },
- },
- {
- headerName: t('Members'),
- id: 'users_number',
- renderCell: ({ row }) => {
- return (
-
- {row.nb_accesses}
-
- );
- },
- },
- {
- id: 'column-actions',
- renderCell: ({ row }) => {
- return ;
- },
- },
- ];
-
- // Inverse columns for mobile to have the most important information first
- if (isMobile) {
- const tmpCol = columns[0];
- columns[0] = columns[1];
- columns[1] = tmpCol;
- }
+ void fetchNextPage();
+ };
return (
-
-
+
- {t('Documents')}
+ {t('All docs')}
- {error && }
+
+
+
+
+ {t('Name')}
+
+
+ {isDesktop && (
+
+
+ {t('Updated at')}
+
+
+ )}
-
+
+
+ {/* Body */}
+ {data?.pages.map((currentPage) => {
+ return currentPage.results.map((doc) => (
+
+ ));
+ })}
+
+
+ {loading && (
+
+
+
+ )}
+ {hasNextPage && !loading && (
+
+ {!isFetching && hasNextPage && (
+
+ )}
+
+ )}
);
};
diff --git a/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridActions.tsx b/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridActions.tsx
index 6a57a2fb..76ed43d8 100644
--- a/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridActions.tsx
+++ b/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridActions.tsx
@@ -1,5 +1,5 @@
import { Button } from '@openfun/cunningham-react';
-import React, { useState } from 'react';
+import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Doc, ModalRemoveDoc } from '@/features/docs/doc-management';
@@ -19,7 +19,10 @@ export const DocsGridActions = ({ doc }: DocsGridActionsProps) => {
return (
<>