From 45eeea4f07cd7151a111be2eb3d647c39f4af1f4 Mon Sep 17 00:00:00 2001 From: spaenleh Date: Thu, 1 Feb 2024 08:22:11 +0100 Subject: [PATCH 1/7] fix: udpate main component and refactor --- package.json | 4 +- src/App.tsx | 10 +- src/config/queryClient.ts | 3 - src/contexts/ItemContext.tsx | 10 +- src/langs/constants.ts | 2 + src/langs/en.json | 4 +- src/modules/item/ItemForbiddenScreen.tsx | 64 +++++----- src/modules/item/MainScreen.tsx | 61 ++++------ src/modules/layout/PageWrapper.tsx | 103 +++++++++++++++++ src/modules/main/ItemGrid.tsx | 6 +- src/modules/navigation/HomeNavigation.tsx | 72 ++++++++++++ .../{item => navigation}/ItemNavigation.tsx | 7 +- src/modules/{ => navigation}/tree/Node.tsx | 0 .../{ => navigation}/tree/TreeView.tsx | 0 src/modules/pages/HomePage.tsx | 109 ++---------------- src/modules/pages/ItemPage.tsx | 19 ++- src/modules/rightPanel/SideContent.tsx | 6 +- src/modules/userSwitch/UserSwitchWrapper.tsx | 2 +- yarn.lock | 40 ++++--- 19 files changed, 295 insertions(+), 227 deletions(-) create mode 100644 src/modules/layout/PageWrapper.tsx create mode 100644 src/modules/navigation/HomeNavigation.tsx rename src/modules/{item => navigation}/ItemNavigation.tsx (90%) rename src/modules/{ => navigation}/tree/Node.tsx (100%) rename src/modules/{ => navigation}/tree/TreeView.tsx (100%) diff --git a/package.json b/package.json index 49a489bb..4cfc517c 100644 --- a/package.json +++ b/package.json @@ -36,10 +36,10 @@ "@emotion/react": "11.11.1", "@emotion/styled": "11.11.0", "@graasp/chatbox": "3.0.3", - "@graasp/query-client": "2.2.3", + "@graasp/query-client": "github:graasp/graasp-query-client#allow-descendents-id-to-be-undefined", "@graasp/sdk": "3.5.0", "@graasp/translations": "1.21.1", - "@graasp/ui": "4.4.0", + "@graasp/ui": "4.5.0", "@mui/icons-material": "5.14.19", "@mui/lab": "5.0.0-alpha.151", "@mui/material": "5.14.19", diff --git a/src/App.tsx b/src/App.tsx index 56aae2aa..90fbd4ad 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -17,6 +17,8 @@ import { useCurrentMemberContext } from '@/contexts/CurrentMemberContext'; import HomePage from '@/modules/pages/HomePage'; import ItemPage from '@/modules/pages/ItemPage'; +import PageWrapper from './modules/layout/PageWrapper'; + export const App = (): JSX.Element => { const location = useLocation(); const [searchParams, setSearchParams] = useSearchParams(); @@ -50,9 +52,11 @@ export const App = (): JSX.Element => { return ( - } /> - } /> - } /> + }> + } /> + } /> + } /> + ); }; diff --git a/src/config/queryClient.ts b/src/config/queryClient.ts index 2d7930df..91899fa8 100644 --- a/src/config/queryClient.ts +++ b/src/config/queryClient.ts @@ -20,9 +20,6 @@ const { enableWebsocket: true, defaultQueryOptions: { keepPreviousData: true, - // avoid refetching when same data are closely fetched - staleTime: 1000, // ms - cacheTime: 1000, // ms }, }); export { diff --git a/src/contexts/ItemContext.tsx b/src/contexts/ItemContext.tsx index 9e02d1b4..fe80c978 100644 --- a/src/contexts/ItemContext.tsx +++ b/src/contexts/ItemContext.tsx @@ -5,12 +5,12 @@ import { DiscriminatedItem } from '@graasp/sdk'; import { hooks } from '@/config/queryClient'; type Props = { - rootId: string; + rootId?: string; children: JSX.Element | JSX.Element[]; }; type ItemContextType = { - rootId: string; + rootId?: string; focusedItemId?: string; setFocusedItemId: (id: string) => void; rootItem?: DiscriminatedItem; @@ -24,7 +24,9 @@ type ItemContextType = { const ItemContext = React.createContext({ rootId: '', focusedItemId: '', - setFocusedItemId: () => null, + setFocusedItemId: (id: string) => { + console.error(`Called setFocusedItemId(${id}) without a matching Provider`); + }, isRootItemLoading: true, isRootItemError: false, isDescendantsLoading: true, @@ -42,7 +44,7 @@ const ItemContextProvider = ({ children, rootId }: Props): JSX.Element => { data: descendants, isLoading: isDescendantsLoading, isError: isDescendantsError, - } = hooks.useDescendants({ id: rootId, enabled: true }); + } = hooks.useDescendants({ id: rootId || '', enabled: true }); const value = useMemo( () => ({ diff --git a/src/langs/constants.ts b/src/langs/constants.ts index 2a796b62..787a331e 100644 --- a/src/langs/constants.ts +++ b/src/langs/constants.ts @@ -10,4 +10,6 @@ export const PLAYER = { HIDDEN_WRAPPER_TOOLTIP: 'HIDDEN_WRAPPER_TOOLTIP', SHOW_MORE: 'SHOW_MORE', RECENT_ITEMS_TITLE: 'RECENT_ITEMS_TITLE', + DRAWER_ARIAL_LABEL: 'DRAWER_ARIAL_LABEL', + ERROR_FETCHING_ITEM: 'ERROR_FETCHING_ITEM', }; diff --git a/src/langs/en.json b/src/langs/en.json index 394f9363..57230451 100644 --- a/src/langs/en.json +++ b/src/langs/en.json @@ -8,5 +8,7 @@ "LOAD_MORE": "Load more", "HIDDEN_WRAPPER_TOOLTIP": "This element is hidden, you can see it because you have admin or write access, users with read access won't see it", "SHOW_MORE": "Show More...", - "RECENT_ITEMS_TITLE": "Most Recent Items" + "RECENT_ITEMS_TITLE": "Most Recent Items", + "DRAWER_ARIAL_LABEL": "Open drawer", + "ERROR_FETCHING_ITEM": "There was an error fetching the requested item" } diff --git a/src/modules/item/ItemForbiddenScreen.tsx b/src/modules/item/ItemForbiddenScreen.tsx index 075132f1..f94e61a6 100644 --- a/src/modules/item/ItemForbiddenScreen.tsx +++ b/src/modules/item/ItemForbiddenScreen.tsx @@ -5,13 +5,10 @@ import AccountCircleIcon from '@mui/icons-material/AccountCircle'; import BlockIcon from '@mui/icons-material/Block'; import { IconButton, Stack, Typography } from '@mui/material'; -import { Context } from '@graasp/sdk'; import { AUTH } from '@graasp/translations'; -import { Button, Main } from '@graasp/ui'; +import { Button } from '@graasp/ui'; import { useAuthTranslation } from '@/config/i18n'; -import HeaderNavigation from '@/modules/header/HeaderNavigation'; -import HeaderRightContent from '@/modules/header/HeaderRightContent'; import UserSwitchWrapper from '@/modules/userSwitch/UserSwitchWrapper'; const ItemForbiddenScreen: FC = () => { @@ -25,40 +22,33 @@ const ItemForbiddenScreen: FC = () => { ); return ( -
} - headerRightContent={} + - - - - - - { - // todo: add translations - t('You cannot access this item') - } - - - { - // todo: add translations - t( - 'Your current account does not have the rights to access this item.', - ) - } - - - -
+ + + + + { + // todo: add translations + t('You cannot access this item') + } + + + { + // todo: add translations + t( + 'Your current account does not have the rights to access this item.', + ) + } + + + ); }; diff --git a/src/modules/item/MainScreen.tsx b/src/modules/item/MainScreen.tsx index 7d9d2670..800c1129 100644 --- a/src/modules/item/MainScreen.tsx +++ b/src/modules/item/MainScreen.tsx @@ -1,71 +1,50 @@ -import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useParams } from 'react-router-dom'; import { Alert, Skeleton, Typography } from '@mui/material'; -import { Context } from '@graasp/sdk'; -import { Main, useMobileView } from '@graasp/ui'; - import { ROOT_ID_PATH } from '@/config/paths'; import { hooks } from '@/config/queryClient'; import { useItemContext } from '@/contexts/ItemContext'; import { LayoutContextProvider } from '@/contexts/LayoutContext'; -import HeaderNavigation from '@/modules/header/HeaderNavigation'; -import HeaderRightContent from '@/modules/header/HeaderRightContent'; +import { PLAYER } from '@/langs/constants'; import SideContent from '@/modules/rightPanel/SideContent'; import Item from './Item'; -import ItemNavigation from './ItemNavigation'; - -const MainScreen = (): JSX.Element => { - const { isMobile } = useMobileView(); +const MainScreen = (): JSX.Element | null => { const rootId = useParams()[ROOT_ID_PATH]; const { focusedItemId } = useItemContext(); const mainId = focusedItemId || rootId; const { data: item, isLoading, isError } = hooks.useItem(mainId); const { t } = useTranslation(); - const [topItemName, setTopItemName] = useState(''); - const [isFirstItem, setIsFirstItem] = useState(true); - if (isLoading) { - return ; - } - - if (!item || isError) { - // todo: add this to translations - return {t('This item does not exist')}; - } - - if (isFirstItem) { - setTopItemName(item.name); - setIsFirstItem(false); - } - - const content = !rootId ? ( + const content = rootId ? ( + + ) : ( {t('No item defined.')} - ) : ( - ); - return ( -
} - headerLeftContent={ - - } - headerRightContent={} - > + if (item) { + return ( -
- ); + ); + } + + if (isLoading) { + return ; + } + + if (isError) { + // todo: add this to translations + return {t(PLAYER.ERROR_FETCHING_ITEM)}; + } + + return null; }; export default MainScreen; diff --git a/src/modules/layout/PageWrapper.tsx b/src/modules/layout/PageWrapper.tsx new file mode 100644 index 00000000..b91cbb17 --- /dev/null +++ b/src/modules/layout/PageWrapper.tsx @@ -0,0 +1,103 @@ +import { Link, Outlet, useParams } from 'react-router-dom'; + +import { Typography, styled } from '@mui/material'; + +import { Context } from '@graasp/sdk'; +import { + Main, + Platform, + PlatformSwitch, + defaultHostsMapper, + usePlatformNavigation, +} from '@graasp/ui'; + +import { + GRAASP_ANALYTICS_HOST, + GRAASP_BUILDER_HOST, + GRAASP_LIBRARY_HOST, +} from '@/config/env'; +import { usePlayerTranslation } from '@/config/i18n'; +import { HOME_PATH } from '@/config/paths'; +import { hooks } from '@/config/queryClient'; +import { + APP_NAVIGATION_PLATFORM_SWITCH_BUTTON_IDS, + APP_NAVIGATION_PLATFORM_SWITCH_ID, +} from '@/config/selectors'; +import { ItemContextProvider } from '@/contexts/ItemContext'; +import { PLAYER } from '@/langs/constants'; + +import HomeNavigation from '../navigation/HomeNavigation'; +import ItemNavigation from '../navigation/ItemNavigation'; +import UserSwitchWrapper from '../userSwitch/UserSwitchWrapper'; + +// small converter for HOST_MAP into a usePlatformNavigation mapper +export const platformsHostsMap = defaultHostsMapper({ + [Platform.Builder]: GRAASP_BUILDER_HOST, + [Platform.Library]: GRAASP_LIBRARY_HOST, + [Platform.Analytics]: GRAASP_ANALYTICS_HOST, +}); + +const StyledLink = styled(Link)(() => ({ + textDecoration: 'none', + color: 'inherit', + display: 'flex', + alignItems: 'center', +})); + +const LinkComponent = ({ + children, +}: { + children: JSX.Element; +}): JSX.Element => {children}; + +const PageWrapper = (): JSX.Element => { + const { t } = usePlayerTranslation(); + + const { rootId } = useParams(); + const { data: item } = hooks.useItem(); + const getNavigationEvents = usePlatformNavigation(platformsHostsMap, rootId); + + const platformProps = { + [Platform.Builder]: { + id: APP_NAVIGATION_PLATFORM_SWITCH_BUTTON_IDS[Platform.Builder], + ...getNavigationEvents(Platform.Builder), + }, + [Platform.Player]: { + id: APP_NAVIGATION_PLATFORM_SWITCH_BUTTON_IDS[Platform.Player], + href: '/', + }, + [Platform.Library]: { + id: APP_NAVIGATION_PLATFORM_SWITCH_BUTTON_IDS[Platform.Library], + ...getNavigationEvents(Platform.Library), + }, + [Platform.Analytics]: { + id: APP_NAVIGATION_PLATFORM_SWITCH_BUTTON_IDS[Platform.Analytics], + ...getNavigationEvents(Platform.Analytics), + }, + }; + + return ( + +
: } + drawerOpenAriaLabel={t(PLAYER.DRAWER_ARIAL_LABEL)} + LinkComponent={LinkComponent} + PlatformComponent={ + + } + headerLeftContent={{item?.name}} + headerRightContent={} + > + +
+
+ ); +}; +export default PageWrapper; diff --git a/src/modules/main/ItemGrid.tsx b/src/modules/main/ItemGrid.tsx index 3af95e8b..9294c57c 100644 --- a/src/modules/main/ItemGrid.tsx +++ b/src/modules/main/ItemGrid.tsx @@ -1,4 +1,4 @@ -import { Grid, Typography } from '@mui/material'; +import { Box, Grid, Typography } from '@mui/material'; import { DiscriminatedItem } from '@graasp/sdk'; @@ -20,7 +20,7 @@ const ItemGrid = ({ isLoading, items, title }: Props): JSX.Element | null => { return null; } return ( - <> + {title} @@ -31,7 +31,7 @@ const ItemGrid = ({ isLoading, items, title }: Props): JSX.Element | null => { ))} - + ); }; diff --git a/src/modules/navigation/HomeNavigation.tsx b/src/modules/navigation/HomeNavigation.tsx new file mode 100644 index 00000000..bb91c218 --- /dev/null +++ b/src/modules/navigation/HomeNavigation.tsx @@ -0,0 +1,72 @@ +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; + +import { Box, Button, Skeleton } from '@mui/material'; + +import { DiscriminatedItem } from '@graasp/sdk'; +import { MainMenu } from '@graasp/ui'; + +import { usePlayerTranslation } from '@/config/i18n'; +import { buildMainPath } from '@/config/paths'; +import { hooks } from '@/config/queryClient'; +import { MY_ITEMS_ID, SHOW_MORE_ITEMS_ID } from '@/config/selectors'; +import { PLAYER } from '@/langs/constants'; + +import TreeView from './tree/TreeView'; + +const PAGE_SIZE = 20; + +const HomeNavigation = (): JSX.Element | null => { + const { t } = usePlayerTranslation(); + + const navigate = useNavigate(); + + const [page, setPage] = useState(1); + const [allItems, setAllItems] = useState([]); + + const { data: accessibleItems, isLoading: isLoadingAccessibleItems } = + hooks.useAccessibleItems({}, { page, pageSize: PAGE_SIZE }); + + const allPagesItems = allItems.concat(accessibleItems?.data ?? []); + + if (allPagesItems) { + return ( + + + { + if (payload !== 'own') { + navigate(buildMainPath({ rootId: payload })); + } + }} + /> + + {accessibleItems?.totalCount && + page * PAGE_SIZE < accessibleItems.totalCount && ( + + )} + + ); + } + + if (isLoadingAccessibleItems) { + return ; + } + + return null; +}; +export default HomeNavigation; diff --git a/src/modules/item/ItemNavigation.tsx b/src/modules/navigation/ItemNavigation.tsx similarity index 90% rename from src/modules/item/ItemNavigation.tsx rename to src/modules/navigation/ItemNavigation.tsx index 2a6909cd..6bbe8944 100644 --- a/src/modules/item/ItemNavigation.tsx +++ b/src/modules/navigation/ItemNavigation.tsx @@ -10,12 +10,12 @@ import { ROOT_ID_PATH } from '@/config/paths'; import { hooks } from '@/config/queryClient'; import { MAIN_MENU_ID, TREE_VIEW_ID } from '@/config/selectors'; import { useItemContext } from '@/contexts/ItemContext'; -import TreeView from '@/modules/tree/TreeView'; +import TreeView from '@/modules/navigation/tree/TreeView'; import { isHidden } from '@/utils/item'; const { useItem, useDescendants, useItemsTags } = hooks; -const ItemNavigation = (): JSX.Element | null => { +const DrawerNavigation = (): JSX.Element | null => { const rootId = useParams()[ROOT_ID_PATH]; const { t: translateMessage } = useMessagesTranslation(); @@ -47,7 +47,6 @@ const ItemNavigation = (): JSX.Element | null => { if (isSuccess) return ( -
{ return null; }; -export default ItemNavigation; +export default DrawerNavigation; diff --git a/src/modules/tree/Node.tsx b/src/modules/navigation/tree/Node.tsx similarity index 100% rename from src/modules/tree/Node.tsx rename to src/modules/navigation/tree/Node.tsx diff --git a/src/modules/tree/TreeView.tsx b/src/modules/navigation/tree/TreeView.tsx similarity index 100% rename from src/modules/tree/TreeView.tsx rename to src/modules/navigation/tree/TreeView.tsx diff --git a/src/modules/pages/HomePage.tsx b/src/modules/pages/HomePage.tsx index d49aa760..cbe2d4aa 100644 --- a/src/modules/pages/HomePage.tsx +++ b/src/modules/pages/HomePage.tsx @@ -1,29 +1,12 @@ import { useState } from 'react'; -import { useNavigate } from 'react-router'; -import { Divider, Skeleton, Stack, styled } from '@mui/material'; - -import { Context, DiscriminatedItem } from '@graasp/sdk'; -import { Button, Main, MainMenu } from '@graasp/ui'; +import { Pagination, Stack } from '@mui/material'; import { usePlayerTranslation } from '@/config/i18n'; -import { buildMainPath } from '@/config/paths'; import { hooks } from '@/config/queryClient'; -import { - HOME_NAVIGATION_STACK_ID, - MY_ITEMS_ID, - SHOW_MORE_ITEMS_ID, -} from '@/config/selectors'; import { PLAYER } from '@/langs/constants'; import PlayerCookiesBanner from '@/modules/cookies/PlayerCookiesBanner'; -import HeaderNavigation from '@/modules/header/HeaderNavigation'; -import HeaderRightContent from '@/modules/header/HeaderRightContent'; import ItemGrid from '@/modules/main/ItemGrid'; -import TreeView from '@/modules/tree/TreeView'; - -const StyledDivider = styled(Divider)(({ theme }) => ({ - margin: theme.spacing(2, 0), -})); const { useAccessibleItems } = hooks; @@ -31,98 +14,26 @@ const PAGE_SIZE = 20; const HomePage = (): JSX.Element => { const { t } = usePlayerTranslation(); - const navigate = useNavigate(); const [page, setPage] = useState(1); - const [allItems, setAllItems] = useState([]); const { data: accessibleItems, isLoading: isLoadingAccessibleItems } = useAccessibleItems({}, { page, pageSize: PAGE_SIZE }); - const allPagesItems = allItems.concat(accessibleItems?.data ?? []); - - const renderContent = () => ( - }> + return ( + + setPage(newPage)} /> - - ); - - const renderOwnItemsMenu = () => { - const rootOwnId = 'own'; - - if (isLoadingAccessibleItems) { - return ; - } - - if (!accessibleItems?.data?.length) { - return null; - } - - return ( - - { - if (payload !== rootOwnId) { - navigate(buildMainPath({ rootId: payload })); - } - }} - /> - - ); - }; - - const showMoreButton = - accessibleItems?.totalCount && - page * PAGE_SIZE < accessibleItems.totalCount ? ( - - ) : ( - // todo: this should be null, but Main component does not allow it, because the typing there is dumb - // replace with null once Main accepts null as valid components - // eslint-disable-next-line react/jsx-no-useless-fragment - <> - ); - - return ( -
-
- } - > - {renderOwnItemsMenu()} - - - } - headerLeftContent={} - headerRightContent={} - > - {renderContent()} - {showMoreButton} -
+
); }; diff --git a/src/modules/pages/ItemPage.tsx b/src/modules/pages/ItemPage.tsx index aef0e359..d4772856 100644 --- a/src/modules/pages/ItemPage.tsx +++ b/src/modules/pages/ItemPage.tsx @@ -4,7 +4,6 @@ import { ItemLoginAuthorization } from '@graasp/ui'; import { HOME_PATH, ROOT_ID_PATH } from '@/config/paths'; import { hooks, mutations } from '@/config/queryClient'; -import { ItemContextProvider } from '@/contexts/ItemContext'; import PlayerCookiesBanner from '@/modules/cookies/PlayerCookiesBanner'; import ItemForbiddenScreen from '../item/ItemForbiddenScreen'; @@ -12,16 +11,12 @@ import MainScreen from '../item/MainScreen'; const { useItem, useItemLoginSchemaType, useCurrentMember } = hooks; -const ItemScreenWrapper = (rootId: string) => { - const ItemScreen = (): JSX.Element => ( - - - - - ); - - return ItemScreen; -}; +const ItemScreenWrapper = () => ( + <> + + + +); const { usePostItemLogin } = mutations; @@ -47,7 +42,7 @@ const ItemPage = (): JSX.Element | null => { useItem, ForbiddenContent, useItemLoginSchemaType, - })(ItemScreenWrapper(rootId)); + })(ItemScreenWrapper); return ; }; diff --git a/src/modules/rightPanel/SideContent.tsx b/src/modules/rightPanel/SideContent.tsx index 605d84ce..157d2ae8 100644 --- a/src/modules/rightPanel/SideContent.tsx +++ b/src/modules/rightPanel/SideContent.tsx @@ -58,7 +58,7 @@ type Props = { content: JSX.Element; }; -const SideContent = ({ content, item }: Props): JSX.Element => { +const SideContent = ({ content, item }: Props): JSX.Element | null => { const { descendants, rootId } = useItemContext(); const { @@ -72,6 +72,10 @@ const SideContent = ({ content, item }: Props): JSX.Element => { const settings = item.settings ?? {}; const isFolder = item.type === ItemType.FOLDER; + if (!rootId) { + return null; + } + /* This removes the parents that are higher than the perform root element Ex: if we are in item 6 and the root is 3, when splitting the path we get [ 1, 2, 3, 4, 5, 6 ]. However the student cannot go higher than element 3, so we remove the element before 3, this diff --git a/src/modules/userSwitch/UserSwitchWrapper.tsx b/src/modules/userSwitch/UserSwitchWrapper.tsx index c767b9ab..a540c4eb 100644 --- a/src/modules/userSwitch/UserSwitchWrapper.tsx +++ b/src/modules/userSwitch/UserSwitchWrapper.tsx @@ -25,7 +25,7 @@ type Props = { const UserSwitchWrapper = ({ ButtonContent, - preserveUrl = false, + preserveUrl = true, }: Props): JSX.Element => { const { data: member, isLoading = true } = useCurrentMemberContext(); const { mutate: useSignOutMutation } = useSignOut(); diff --git a/yarn.lock b/yarn.lock index 254b0820..fdaae0f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1283,21 +1283,22 @@ __metadata: languageName: node linkType: hard -"@graasp/query-client@npm:2.2.3": - version: 2.2.3 - resolution: "@graasp/query-client@npm:2.2.3" +"@graasp/query-client@github:graasp/graasp-query-client#allow-descendents-id-to-be-undefined": + version: 2.4.1 + resolution: "@graasp/query-client@https://github.com/graasp/graasp-query-client.git#commit=17bfec081fc025d6f52d419024565aa31f0a4e93" dependencies: - "@graasp/sdk": "npm:3.4.1" - "@graasp/translations": "npm:1.22.1" + "@graasp/sdk": "npm:3.6.0" + "@graasp/translations": "npm:1.23.0" axios: "npm:0.27.2" crypto-js: "npm:4.2.0" + date-fns: "npm:3.3.1" http-status-codes: "npm:2.3.0" qs: "npm:6.11.2" react-query: "npm:3.39.3" uuid: "npm:9.0.1" peerDependencies: react: ^17.0.0 || ^18.0.0 - checksum: cf7d3ebc8b7098b0c8b2d04d71ed56ff8004d5e892ac12bdb7cb088bdb25db559795e2fb73400410b748a09a17b06e1d3c83f28e02f8a6805669c349a13535fe + checksum: 054c0682559cec0aaba6e1c61e38d99628451bfa6d231cb31979121f5288bbf9799f28a4a3113ce0f6acab59d80930b2019b855bae2299aa82d8d7d69381d24e languageName: node linkType: hard @@ -1322,12 +1323,12 @@ __metadata: languageName: node linkType: hard -"@graasp/translations@npm:1.22.1": - version: 1.22.1 - resolution: "@graasp/translations@npm:1.22.1" +"@graasp/translations@npm:1.23.0": + version: 1.23.0 + resolution: "@graasp/translations@npm:1.23.0" dependencies: i18next: "npm:23.7.16" - checksum: 29043007a9926ff54236101c41ceb92eead09d8ce99edf46943790171f3275fb2cc1acd552bfa605247c42b4866bbf1f83dd889da3f571d388eca5f2dd598e17 + checksum: dc0d605b520a28deb1ad3054323dc4b71f709b79adf5924552c602f3c3ed2fa7c3c8538a3015c86c8db05867159df4b2f6ad18583766b2b97c8dd850952d29e2 languageName: node linkType: hard @@ -1340,9 +1341,9 @@ __metadata: languageName: node linkType: hard -"@graasp/ui@npm:4.4.0": - version: 4.4.0 - resolution: "@graasp/ui@npm:4.4.0" +"@graasp/ui@npm:4.5.0": + version: 4.5.0 + resolution: "@graasp/ui@npm:4.5.0" dependencies: "@graasp/sdk": "npm:3.5.0" http-status-codes: "npm:2.3.0" @@ -1376,7 +1377,7 @@ __metadata: optional: true ag-grid-react: optional: true - checksum: 2b037daec606f5de34079a36560991efc9ebe044b26f472a272ca480e21083109304a978a2fbe74a23de1e70de19d2e814e434f7665a828bbdaa5ef93538a65f + checksum: eecd53f0d9d7824c526179b84db29ff303c70f0405d19ad74fc48c5b4966ed47620da06fdda981bfc7ed70eba08d02d1bc9f3e3a958ec430c556fa6b191f5878 languageName: node linkType: hard @@ -4134,6 +4135,13 @@ __metadata: languageName: node linkType: hard +"date-fns@npm:3.3.1": + version: 3.3.1 + resolution: "date-fns@npm:3.3.1" + checksum: 98231936765dfb6fc6897676319b500a06a39f051b2c3ecbdd541a07ce9b1344b770277b8bfb1049fb7a2f70bf365ac8e6f1e2bb452b10e1a8101d518ca7f95d + languageName: node + linkType: hard + "date-fns@npm:^2.30.0": version: 2.30.0 resolution: "date-fns@npm:2.30.0" @@ -5649,10 +5657,10 @@ __metadata: "@emotion/react": "npm:11.11.1" "@emotion/styled": "npm:11.11.0" "@graasp/chatbox": "npm:3.0.3" - "@graasp/query-client": "npm:2.2.3" + "@graasp/query-client": "github:graasp/graasp-query-client#allow-descendents-id-to-be-undefined" "@graasp/sdk": "npm:3.5.0" "@graasp/translations": "npm:1.21.1" - "@graasp/ui": "npm:4.4.0" + "@graasp/ui": "npm:4.5.0" "@mui/icons-material": "npm:5.14.19" "@mui/lab": "npm:5.0.0-alpha.151" "@mui/material": "npm:5.14.19" From 1582f86aa712f78ae54048f986717f6061285b4d Mon Sep 17 00:00:00 2001 From: spaenleh Date: Thu, 1 Feb 2024 08:30:44 +0100 Subject: [PATCH 2/7] fix: use latest version of query-client --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 4cfc517c..fd545ee1 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@emotion/react": "11.11.1", "@emotion/styled": "11.11.0", "@graasp/chatbox": "3.0.3", - "@graasp/query-client": "github:graasp/graasp-query-client#allow-descendents-id-to-be-undefined", + "@graasp/query-client": "2.4.2", "@graasp/sdk": "3.5.0", "@graasp/translations": "1.21.1", "@graasp/ui": "4.5.0", diff --git a/yarn.lock b/yarn.lock index fdaae0f5..d0415a8c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1283,9 +1283,9 @@ __metadata: languageName: node linkType: hard -"@graasp/query-client@github:graasp/graasp-query-client#allow-descendents-id-to-be-undefined": - version: 2.4.1 - resolution: "@graasp/query-client@https://github.com/graasp/graasp-query-client.git#commit=17bfec081fc025d6f52d419024565aa31f0a4e93" +"@graasp/query-client@npm:2.4.2": + version: 2.4.2 + resolution: "@graasp/query-client@npm:2.4.2" dependencies: "@graasp/sdk": "npm:3.6.0" "@graasp/translations": "npm:1.23.0" @@ -1298,7 +1298,7 @@ __metadata: uuid: "npm:9.0.1" peerDependencies: react: ^17.0.0 || ^18.0.0 - checksum: 054c0682559cec0aaba6e1c61e38d99628451bfa6d231cb31979121f5288bbf9799f28a4a3113ce0f6acab59d80930b2019b855bae2299aa82d8d7d69381d24e + checksum: cfe0b679fd574b487a97ef1e764f40a056be732cbb44393aabda55ea4eba3ee83d823d45945973eb974aa41ec903b67326749e9c1cfbcdfc246638864ce4cf81 languageName: node linkType: hard @@ -5657,7 +5657,7 @@ __metadata: "@emotion/react": "npm:11.11.1" "@emotion/styled": "npm:11.11.0" "@graasp/chatbox": "npm:3.0.3" - "@graasp/query-client": "github:graasp/graasp-query-client#allow-descendents-id-to-be-undefined" + "@graasp/query-client": "npm:2.4.2" "@graasp/sdk": "npm:3.5.0" "@graasp/translations": "npm:1.21.1" "@graasp/ui": "npm:4.5.0" From 6ebfe92146d7abe441b83050ad876728c324a600 Mon Sep 17 00:00:00 2001 From: spaenleh Date: Thu, 1 Feb 2024 12:21:35 +0100 Subject: [PATCH 3/7] fix: navigation test --- cypress/e2e/navigation.cy.ts | 17 ++++++++++++----- cypress/support/integrationUtils.ts | 3 ++- src/Root.tsx | 8 +++++++- src/config/selectors.ts | 4 ++++ src/modules/pages/HomePage.tsx | 11 ++++++++++- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/cypress/e2e/navigation.cy.ts b/cypress/e2e/navigation.cy.ts index 8a511df6..9461dd58 100644 --- a/cypress/e2e/navigation.cy.ts +++ b/cypress/e2e/navigation.cy.ts @@ -1,7 +1,11 @@ import { PermissionLevel } from '@graasp/sdk'; import { buildMainPath } from '@/config/paths'; -import { SHOW_MORE_ITEMS_ID, buildTreeItemClass } from '@/config/selectors'; +import { + HOME_PAGE_PAGINATION_ID, + buildHomePaginationId, + buildTreeItemClass, +} from '@/config/selectors'; import { FOLDER_WITH_SUBFOLDER_ITEM, @@ -27,8 +31,8 @@ describe('Navigation', () => { cy.visit('/'); cy.wait(['@getCurrentMember', '@getAccessibleItems']); - - cy.get(`#${SHOW_MORE_ITEMS_ID}`).click(); + cy.get(`#${HOME_PAGE_PAGINATION_ID}`).scrollIntoView().should('be.visible'); + cy.get(`#${buildHomePaginationId(2)}`).click(); }); it('Expand folder when navigating', () => { @@ -38,8 +42,11 @@ describe('Navigation', () => { const child = FOLDER_WITH_SUBFOLDER_ITEM.items[1]; const childOfChild = FOLDER_WITH_SUBFOLDER_ITEM.items[3]; - cy.get(`.${buildTreeItemClass(child.id)}`).click(); - cy.get(`.${buildTreeItemClass(childOfChild.id)}`).should('be.visible'); + // we need to to use the `:visible` meta selector because there are 2 navigations (one for mobile hidden, and one for desktop) + cy.get(`.${buildTreeItemClass(child.id)}:visible`).click(); + cy.get(`.${buildTreeItemClass(childOfChild.id)}:visible`).should( + 'be.visible', + ); }); it('show all folders for partial order', () => { diff --git a/cypress/support/integrationUtils.ts b/cypress/support/integrationUtils.ts index a250e946..71dba7ed 100644 --- a/cypress/support/integrationUtils.ts +++ b/cypress/support/integrationUtils.ts @@ -138,7 +138,8 @@ export const expectFolderLayout = ({ .filter(({ type }) => type === ItemType.FOLDER) .forEach(({ id }) => { // click in mainmenu - cy.get(`.${buildTreeItemClass(id)}`).click(); + // there are two because of th two menus + cy.get(`.${buildTreeItemClass(id)}:visible`).click(); expectFolderLayout({ rootId: id, items }); }); diff --git a/src/Root.tsx b/src/Root.tsx index bdd1574d..3582cce0 100644 --- a/src/Root.tsx +++ b/src/Root.tsx @@ -5,6 +5,10 @@ import { ToastContainer } from 'react-toastify'; import { CssBaseline, GlobalStyles } from '@mui/material'; import { ThemeProvider } from '@mui/material/styles'; +// todo: set locale based on member local using +// https://mui.com/material-ui/customization/theming/#api +// and https://mui.com/material-ui/guides/localization/#locale-text +// with the deepMerge util function import { theme } from '@graasp/ui'; import { SHOW_NOTIFICATIONS } from '@/config/env'; @@ -36,7 +40,9 @@ const Root = (): JSX.Element => ( - {import.meta.env.DEV && } + {import.meta.env.DEV && import.meta.env.MODE !== 'test' && ( + + )} ); diff --git a/src/config/selectors.ts b/src/config/selectors.ts index 80b6484c..57649677 100644 --- a/src/config/selectors.ts +++ b/src/config/selectors.ts @@ -48,6 +48,10 @@ export const OWN_ITEMS_GRID_ID = 'ownItemsGrid'; export const buildMemberAvatarClass = (id?: string): string => `memberAvatar-${id}`; +export const HOME_PAGE_PAGINATION_ID = 'honmePagePagination'; +export const buildHomePaginationId = (page: number | null): string => + `homePagination-${page}`; + export const APP_NAVIGATION_PLATFORM_SWITCH_ID = 'appNavigationPlatformSwitch'; export const APP_NAVIGATION_PLATFORM_SWITCH_BUTTON_IDS = { [Platform.Builder]: 'appNavigationPlatformSwitchButtonBuilder', diff --git a/src/modules/pages/HomePage.tsx b/src/modules/pages/HomePage.tsx index cbe2d4aa..bbb744d2 100644 --- a/src/modules/pages/HomePage.tsx +++ b/src/modules/pages/HomePage.tsx @@ -1,9 +1,13 @@ import { useState } from 'react'; -import { Pagination, Stack } from '@mui/material'; +import { Pagination, PaginationItem, Stack } from '@mui/material'; import { usePlayerTranslation } from '@/config/i18n'; import { hooks } from '@/config/queryClient'; +import { + HOME_PAGE_PAGINATION_ID, + buildHomePaginationId, +} from '@/config/selectors'; import { PLAYER } from '@/langs/constants'; import PlayerCookiesBanner from '@/modules/cookies/PlayerCookiesBanner'; import ItemGrid from '@/modules/main/ItemGrid'; @@ -28,8 +32,13 @@ const HomePage = (): JSX.Element => { items={accessibleItems?.data} /> ( + // eslint-disable-next-line react/jsx-props-no-spreading + + )} onChange={(_, newPage) => setPage(newPage)} /> From fada69dde1a30a7a93f0ee8c6110a45d20a61c06 Mon Sep 17 00:00:00 2001 From: spaenleh Date: Thu, 1 Feb 2024 12:25:20 +0100 Subject: [PATCH 4/7] fix: main test with scrollView --- cypress/support/integrationUtils.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cypress/support/integrationUtils.ts b/cypress/support/integrationUtils.ts index 71dba7ed..a1d9f783 100644 --- a/cypress/support/integrationUtils.ts +++ b/cypress/support/integrationUtils.ts @@ -44,10 +44,14 @@ export const expectLinkViewScreenLayout = ({ if (!html) { if (settings?.showLinkButton ?? DEFAULT_LINK_SHOW_BUTTON) { - cy.get('[data-testid="OpenInNewIcon"]').should('be.visible'); + cy.get('[data-testid="OpenInNewIcon"]') + .scrollIntoView() + .should('be.visible'); } else { // button should not be shown when the setting is false - cy.get('[data-testid="OpenInNewIcon"]').should('not.exist'); + cy.get('[data-testid="OpenInNewIcon"]') + .scrollIntoView() + .should('not.exist'); } } }; From a2971656eb069c9a8431a04c4f4a2e3499e79712 Mon Sep 17 00:00:00 2001 From: spaenleh Date: Thu, 1 Feb 2024 14:02:10 +0100 Subject: [PATCH 5/7] fix: sonar cloud issues --- src/contexts/ItemContext.tsx | 2 +- src/modules/navigation/ItemNavigation.tsx | 2 +- src/modules/navigation/tree/TreeView.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/contexts/ItemContext.tsx b/src/contexts/ItemContext.tsx index fe80c978..1c361961 100644 --- a/src/contexts/ItemContext.tsx +++ b/src/contexts/ItemContext.tsx @@ -44,7 +44,7 @@ const ItemContextProvider = ({ children, rootId }: Props): JSX.Element => { data: descendants, isLoading: isDescendantsLoading, isError: isDescendantsError, - } = hooks.useDescendants({ id: rootId || '', enabled: true }); + } = hooks.useDescendants({ id: rootId ?? '', enabled: true }); const value = useMemo( () => ({ diff --git a/src/modules/navigation/ItemNavigation.tsx b/src/modules/navigation/ItemNavigation.tsx index 6bbe8944..7cb26ade 100644 --- a/src/modules/navigation/ItemNavigation.tsx +++ b/src/modules/navigation/ItemNavigation.tsx @@ -21,7 +21,7 @@ const DrawerNavigation = (): JSX.Element | null => { const { t: translateMessage } = useMessagesTranslation(); const { setFocusedItemId } = useItemContext(); - const { data: descendants } = useDescendants({ id: rootId || '' }); + const { data: descendants } = useDescendants({ id: rootId ?? '' }); const { data: itemsTags } = useItemsTags(descendants?.map(({ id }) => id)); const { diff --git a/src/modules/navigation/tree/TreeView.tsx b/src/modules/navigation/tree/TreeView.tsx index 73887cb4..2db7603b 100644 --- a/src/modules/navigation/tree/TreeView.tsx +++ b/src/modules/navigation/tree/TreeView.tsx @@ -81,7 +81,7 @@ const TreeView = ({ /> ); - const tree = Object.values(getItemTree(itemsToShow || [], rootItems)); + const tree = Object.values(getItemTree(itemsToShow ?? [], rootItems)); return ( Date: Fri, 2 Feb 2024 10:52:28 +0100 Subject: [PATCH 6/7] fix: add translations --- src/langs/constants.ts | 2 ++ src/langs/en.json | 4 +++- src/modules/item/ItemForbiddenScreen.tsx | 13 +++---------- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/langs/constants.ts b/src/langs/constants.ts index 787a331e..9f1d30a5 100644 --- a/src/langs/constants.ts +++ b/src/langs/constants.ts @@ -12,4 +12,6 @@ export const PLAYER = { RECENT_ITEMS_TITLE: 'RECENT_ITEMS_TITLE', DRAWER_ARIAL_LABEL: 'DRAWER_ARIAL_LABEL', ERROR_FETCHING_ITEM: 'ERROR_FETCHING_ITEM', + ERROR_ACCESSING_ITEM: 'ERROR_ACCESSING_ITEM', + ERROR_ACCESSING_ITEM_HELPER: 'ERROR_ACCESSING_ITEM_HELPER', }; diff --git a/src/langs/en.json b/src/langs/en.json index 57230451..1b8834bd 100644 --- a/src/langs/en.json +++ b/src/langs/en.json @@ -10,5 +10,7 @@ "SHOW_MORE": "Show More...", "RECENT_ITEMS_TITLE": "Most Recent Items", "DRAWER_ARIAL_LABEL": "Open drawer", - "ERROR_FETCHING_ITEM": "There was an error fetching the requested item" + "ERROR_FETCHING_ITEM": "There was an error fetching the requested item", + "ERROR_ACCESSING_ITEM": "You cannot access this item", + "ERROR_ACCESSING_ITEM_HELPER": "Your current account does not have the rights to access this item." } diff --git a/src/modules/item/ItemForbiddenScreen.tsx b/src/modules/item/ItemForbiddenScreen.tsx index f94e61a6..5b141919 100644 --- a/src/modules/item/ItemForbiddenScreen.tsx +++ b/src/modules/item/ItemForbiddenScreen.tsx @@ -9,6 +9,7 @@ import { AUTH } from '@graasp/translations'; import { Button } from '@graasp/ui'; import { useAuthTranslation } from '@/config/i18n'; +import { PLAYER } from '@/langs/constants'; import UserSwitchWrapper from '@/modules/userSwitch/UserSwitchWrapper'; const ItemForbiddenScreen: FC = () => { @@ -34,18 +35,10 @@ const ItemForbiddenScreen: FC = () => { - { - // todo: add translations - t('You cannot access this item') - } + {t(PLAYER.ERROR_ACCESSING_ITEM)} - { - // todo: add translations - t( - 'Your current account does not have the rights to access this item.', - ) - } + {t(PLAYER.ERROR_ACCESSING_ITEM_HELPER)} From e5471181e3433c7e6108f9d57094008e02a80cef Mon Sep 17 00:00:00 2001 From: spaenleh Date: Fri, 2 Feb 2024 10:54:53 +0100 Subject: [PATCH 7/7] fix: typos and add comments --- src/config/selectors.ts | 2 +- src/modules/pages/HomePage.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/selectors.ts b/src/config/selectors.ts index 57649677..1da6a6af 100644 --- a/src/config/selectors.ts +++ b/src/config/selectors.ts @@ -48,7 +48,7 @@ export const OWN_ITEMS_GRID_ID = 'ownItemsGrid'; export const buildMemberAvatarClass = (id?: string): string => `memberAvatar-${id}`; -export const HOME_PAGE_PAGINATION_ID = 'honmePagePagination'; +export const HOME_PAGE_PAGINATION_ID = 'homePagePagination'; export const buildHomePaginationId = (page: number | null): string => `homePagination-${page}`; diff --git a/src/modules/pages/HomePage.tsx b/src/modules/pages/HomePage.tsx index bbb744d2..85309d06 100644 --- a/src/modules/pages/HomePage.tsx +++ b/src/modules/pages/HomePage.tsx @@ -35,6 +35,7 @@ const HomePage = (): JSX.Element => { id={HOME_PAGE_PAGINATION_ID} count={Math.floor((accessibleItems?.totalCount ?? 0) / PAGE_SIZE) + 1} page={page} + // use the render prop to add a unique id that we can use for tests renderItem={(props) => ( // eslint-disable-next-line react/jsx-props-no-spreading