diff --git a/src/locales/en/enums.json b/src/locales/en/enums.json index bd2926844..cba0a1983 100644 --- a/src/locales/en/enums.json +++ b/src/locales/en/enums.json @@ -58,5 +58,9 @@ "uncollapse-item": "un-collapse item", "member-login": "member login", "ask-reset-password": "request password reset", - "reset-password": "password reset" + "reset-password": "password reset", + + "level": "Level", + "discipline": "Discipline", + "resource-type": "Resource Type" } diff --git a/src/modules/builder/components/App.tsx b/src/modules/builder/components/App.tsx deleted file mode 100644 index 1e01deb03..000000000 --- a/src/modules/builder/components/App.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { Trans } from 'react-i18next'; - -import { buildSignInPath, saveUrlForRedirection } from '@graasp/sdk'; -import { - CustomInitialLoader, - PreventGuestWrapper, - SignedInWrapper, -} from '@graasp/ui'; - -import { DOMAIN, GRAASP_AUTH_HOST } from '@/config/env'; -import { useBuilderTranslation } from '@/config/i18n'; -import { PREVENT_GUEST_MESSAGE_ID } from '@/config/selectors'; -import { BUILDER } from '@/langs/constants'; - -import { - BOOKMARKED_ITEMS_PATH, - HOME_PATH, - ITEM_PUBLISH_PATH, - ITEM_SETTINGS_PATH, - ITEM_SHARE_PATH, - PUBLISHED_ITEMS_PATH, - buildItemPath, -} from '../config/paths'; -import { hooks, mutations } from '../config/queryClient'; -import BookmarkedItemsScreen from './pages/BookmarkedItemsScreen'; -import PublishedItemsScreen from './pages/PublishedItemsScreen'; -import ItemPageLayout from './pages/item/ItemPageLayout'; -import ItemScreen from './pages/item/ItemScreen'; -import ItemSettingsPage from './pages/item/ItemSettingsPage'; -import ItemSharingPage from './pages/item/ItemSharingPage'; -import LibrarySettingsPage from './pages/item/LibrarySettingsPage'; -import ItemAccessWrapper from './pages/item/accessWrapper/ItemAccessWrapper'; - -const { useItemFeedbackUpdates, useCurrentMember } = hooks; - -const App = (): JSX.Element => { - const { t: translateBuilder } = useTranslation(NS.Builder); - const { mutate: signOut } = mutations.useSignOut(); - const { pathname } = useLocation(); - const { data: currentAccount, isLoading } = useCurrentMember(); - - // registers the item updates through websockets - useItemFeedbackUpdates?.(currentAccount?.id); - - if (isLoading) { - return ; - } - - return ( - - {/* pages with personal info */} - { - // save current url for later redirection after sign in - saveUrlForRedirection(pathname, DOMAIN); - }} - > - signOut()} - errorText={translateBuilder(BUILDER.ERROR_MESSAGE)} - text={ - }} - /> - } - > - - - - } - > - } - /> - } /> - - - {/* item pages - can be public */} - }> - } /> - }> - } /> - } /> - } /> - - - - ); -}; - -export default App; diff --git a/src/modules/builder/components/input/MultiSelectTagChipInput.tsx b/src/modules/builder/components/input/MultiSelectTagChipInput.tsx index 19265f3f1..85e4d0028 100644 --- a/src/modules/builder/components/input/MultiSelectTagChipInput.tsx +++ b/src/modules/builder/components/input/MultiSelectTagChipInput.tsx @@ -1,3 +1,5 @@ +import { useTranslation } from 'react-i18next'; + import { Autocomplete, AutocompleteRenderGetTagProps, @@ -12,7 +14,7 @@ import { import { DiscriminatedItem, TagCategory } from '@graasp/sdk'; -import { useBuilderTranslation, useEnumsTranslation } from '@/config/i18n'; +import { NS } from '@/config/constants'; import { hooks } from '@/config/queryClient'; import { MULTI_SELECT_CHIP_CONTAINER_ID, @@ -34,7 +36,7 @@ export const MultiSelectTagChipInput = ({ helpertext, }: Props): JSX.Element | null => { const { t } = useTranslation(NS.Builder); - const { t: translateEnums } = useEnumsTranslation(); + const { t: translateEnums } = useTranslation(NS.Enums); const { currentValue, error, @@ -62,7 +64,6 @@ export const MultiSelectTagChipInput = ({ data-cy={buildMultiSelectChipsSelector(index)} variant="outlined" label={option} - // eslint-disable-next-line react/jsx-props-no-spreading {...getTagProps({ index })} onDelete={() => { const tagId = tagsPerCategory?.[tagCategory].find( @@ -80,7 +81,6 @@ export const MultiSelectTagChipInput = ({ const renderInput = (params: AutocompleteRenderInputParams) => ( { const { t } = useTranslation(NS.Builder); const { computeStatusFor } = useDataSyncContext(); const { isOpen, openModal, closeModal } = useModalStatus(); + const { color } = useButtonColor('warning'); const { mutate: updateItem, @@ -69,7 +71,7 @@ export const EditItemDescription = ({ item }: Props): JSX.Element => { - + ) : null; @@ -85,7 +87,7 @@ export const EditItemDescription = ({ item }: Props): JSX.Element => { const descriptionContent = ( {noDescriptionToolTip} diff --git a/src/modules/builder/components/item/publish/PublicVisibilityModal.tsx b/src/modules/builder/components/item/publish/PublicVisibilityModal.tsx index cdf5ac9ac..bf9f31dc7 100644 --- a/src/modules/builder/components/item/publish/PublicVisibilityModal.tsx +++ b/src/modules/builder/components/item/publish/PublicVisibilityModal.tsx @@ -1,3 +1,5 @@ +import { useTranslation } from 'react-i18next'; + import { Button, Dialog, @@ -9,10 +11,11 @@ import { import { PackedItem } from '@graasp/sdk'; -import { SETTINGS } from '@/config/constants'; -import { useBuilderTranslation } from '@/config/i18n'; +import { NS } from '@/config/constants'; import { PUBLIC_VISIBILITY_MODAL_VALIDATE_BUTTON } from '@/config/selectors'; -import { BUILDER } from '@/langs/constants'; + +import { SETTINGS } from '~builder/config/constants'; +import { BUILDER } from '~builder/langs/constants'; import useVisibility from '../../hooks/useVisibility'; diff --git a/src/modules/builder/components/item/publish/customizedTags/PublishCustomizedTags.tsx b/src/modules/builder/components/item/publish/customizedTags/PublishCustomizedTags.tsx index dd1d24cae..ba6865131 100644 --- a/src/modules/builder/components/item/publish/customizedTags/PublishCustomizedTags.tsx +++ b/src/modules/builder/components/item/publish/customizedTags/PublishCustomizedTags.tsx @@ -1,14 +1,16 @@ import { useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; import WarningIcon from '@mui/icons-material/Warning'; import { Tooltip } from '@mui/material'; import { DiscriminatedItem } from '@graasp/sdk'; +import { useButtonColor } from '@graasp/ui'; -import { useDataSyncContext } from '@/components/context/DataSyncContext'; -import { WARNING_COLOR } from '@/config/constants'; -import { useBuilderTranslation } from '@/config/i18n'; -import { BUILDER } from '@/langs/constants'; +import { NS } from '@/config/constants'; + +import { useDataSyncContext } from '~builder/components/context/DataSyncContext'; +import { BUILDER } from '~builder/langs/constants'; import CustomizedTags from './CustomizedTags'; import { useTagsManager } from './useTagsManager'; @@ -33,6 +35,7 @@ export const PublishCustomizedTags = ({ }); const { computeStatusFor } = useDataSyncContext(); const showWarning = !tags?.length; + const { color } = useButtonColor('warning'); useEffect( () => computeStatusFor(SYNC_STATUS_KEY, { isLoading, isSuccess, isError }), @@ -45,7 +48,7 @@ export const PublishCustomizedTags = ({ {showWarning && ( - + )} diff --git a/src/modules/builder/components/item/publish/customizedTags/useTagsManager.tsx b/src/modules/builder/components/item/publish/customizedTags/useTagsManager.tsx index f193e79a3..a31c10972 100644 --- a/src/modules/builder/components/item/publish/customizedTags/useTagsManager.tsx +++ b/src/modules/builder/components/item/publish/customizedTags/useTagsManager.tsx @@ -1,12 +1,12 @@ import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { DiscriminatedItem, Tag, TagCategory } from '@graasp/sdk'; import groupBy from 'lodash.groupby'; -import { useBuilderTranslation } from '@/config/i18n'; +import { NS } from '@/config/constants'; import { hooks, mutations } from '@/config/queryClient'; -import { BUILDER } from '@/langs/constants'; const EMPTY_STRING = ''; type Props = { @@ -65,7 +65,7 @@ export const useTagsManager = ({ itemId }: Props): UseMultiSelectChipInput => { const validateData = (tag: Pick) => { if (valueExist(tag)) { - setError(t(BUILDER.CHIPS_ALREADY_EXIST, { element: tag.name })); + setError(t('CHIPS_ALREADY_EXIST', { element: tag.name })); return false; } setError(undefined); diff --git a/src/modules/builder/components/item/publish/publicationButtons/PublishedChildrenButton.tsx b/src/modules/builder/components/item/publish/publicationButtons/PublishedChildrenButton.tsx index d39f3e359..6e1e84524 100644 --- a/src/modules/builder/components/item/publish/publicationButtons/PublishedChildrenButton.tsx +++ b/src/modules/builder/components/item/publish/publicationButtons/PublishedChildrenButton.tsx @@ -1,14 +1,15 @@ +import { useTranslation } from 'react-i18next'; + import { Alert } from '@mui/material'; -import { useBuilderTranslation } from '@/config/i18n'; -import { BUILDER } from '@/langs/constants'; +import { NS } from '@/config/constants'; export const PublishedChildrenButton = (): JSX.Element => { const { t } = useTranslation(NS.Builder); return ( - {t(BUILDER.LIBRARY_SETTINGS_CHILD_PUBLISHED_STATUS)} + {t('LIBRARY_SETTINGS_CHILD_PUBLISHED_STATUS')} ); }; diff --git a/src/modules/builder/components/item/settings/ItemMetadataContent.tsx b/src/modules/builder/components/item/settings/ItemMetadataContent.tsx index eee69a026..cfd4ab8c1 100644 --- a/src/modules/builder/components/item/settings/ItemMetadataContent.tsx +++ b/src/modules/builder/components/item/settings/ItemMetadataContent.tsx @@ -1,3 +1,5 @@ +import { useTranslation } from 'react-i18next'; + import { Box } from '@mui/material'; import Table from '@mui/material/Table'; import TableBody from '@mui/material/TableBody'; @@ -13,23 +15,22 @@ import { getFileExtra, getS3FileExtra, } from '@graasp/sdk'; -import { COMMON } from '@graasp/translations'; -import { hooks } from '../../../config/queryClient'; -import { - ITEM_PANEL_NAME_ID, - ITEM_PANEL_TABLE_ID, -} from '../../../config/selectors'; +import { NS } from '@/config/constants'; +import { hooks } from '@/config/queryClient'; +import { ITEM_PANEL_NAME_ID, ITEM_PANEL_TABLE_ID } from '@/config/selectors'; + +import { useOutletContext } from '~builder/contexts/OutletContext'; + import { BUILDER } from '../../../langs/constants'; -import { OutletType } from '../../pages/item/type'; import LanguageSelect from './LanguageSelect'; const { useMember } = hooks; const ItemMetadataContent = (): JSX.Element => { - const { t: translateBuilder } = useTranslation(NS.Builder); - const { t: translateCommon } = useCommonTranslation(); - const { item } = useOutletContext(); + const { t: translateBuilder, i18n } = useTranslation(NS.Builder); + const { t: translateCommon } = useTranslation(NS.Common); + const { item } = useOutletContext(); const { data: creator } = useMember(item?.creator?.id); @@ -102,7 +103,7 @@ const ItemMetadataContent = (): JSX.Element => { {formatDate(item.createdAt, { locale: i18n.language, - defaultValue: translateCommon(COMMON.UNKNOWN_DATE), + defaultValue: translateCommon('UNKNOWN_DATE'), })} @@ -113,7 +114,7 @@ const ItemMetadataContent = (): JSX.Element => { {formatDate(item.updatedAt, { locale: i18n.language, - defaultValue: translateCommon(COMMON.UNKNOWN_DATE), + defaultValue: translateCommon('UNKNOWN_DATE'), })} diff --git a/src/modules/builder/components/pages/BookmarkedItemsScreen.tsx b/src/modules/builder/components/pages/BookmarkedItemsScreen.tsx index 2678245d9..89ca8d206 100644 --- a/src/modules/builder/components/pages/BookmarkedItemsScreen.tsx +++ b/src/modules/builder/components/pages/BookmarkedItemsScreen.tsx @@ -1,13 +1,16 @@ -import { Alert, Stack } from '@mui/material'; +import { useTranslation } from 'react-i18next'; -import { Ordering } from '@/enums'; +import { Alert, Stack } from '@mui/material'; -import { useBuilderTranslation } from '../../config/i18n'; -import { hooks } from '../../config/queryClient'; +import { NS } from '@/config/constants'; +import { hooks } from '@/config/queryClient'; import { BOOKMARKED_ITEMS_ERROR_ALERT_ID, BOOKMARKED_ITEMS_ID, -} from '../../config/selectors'; +} from '@/config/selectors'; + +import { Ordering } from '~builder/enums'; + import { BUILDER } from '../../langs/constants'; import ErrorAlert from '../common/ErrorAlert'; import SelectTypes from '../common/SelectTypes'; @@ -17,11 +20,11 @@ import ModeButton from '../item/header/ModeButton'; import LoadingScreen from '../layout/LoadingScreen'; import ItemsTable from '../main/list/ItemsTable'; import SortingSelect from '../table/SortingSelect'; -import { SortingOptions } from '../table/types'; +import { SortingOptions, SortingOptionsType } from '../table/types'; import { useSorting, useTranslatedSortingOptions } from '../table/useSorting'; -import PageWrapper from './BuilderPageLayout'; +import { BuilderPageLayout } from './BuilderPageLayout'; -const BookmarkedItems = ({ +const BookmarkedItemsContent = ({ searchText, }: { searchText: string; @@ -35,7 +38,7 @@ const BookmarkedItems = ({ const { shouldDisplayItem } = useFilterItemsContext(); const { sortBy, setSortBy, ordering, setOrdering, sortFn } = - useSorting({ + useSorting({ sortBy: SortingOptions.ItemUpdatedAt, ordering: Ordering.DESC, }); @@ -111,12 +114,12 @@ const BookmarkedItems = ({ ); }; -const BookmarkedItemsWrapper = (): JSX.Element => { +export function BookmarkedItemsScreen() { const { t } = useTranslation(NS.Builder); const itemSearch = useItemSearch(); return ( - { } > - - + + ); -}; - -export default BookmarkedItemsWrapper; +} diff --git a/src/modules/builder/components/pages/PublishedItemsScreen.tsx b/src/modules/builder/components/pages/PublishedItemsScreen.tsx index d7c5f19e7..6ba1a553f 100644 --- a/src/modules/builder/components/pages/PublishedItemsScreen.tsx +++ b/src/modules/builder/components/pages/PublishedItemsScreen.tsx @@ -1,13 +1,16 @@ -import { Alert, Stack } from '@mui/material'; +import { useTranslation } from 'react-i18next'; -import { Ordering } from '@/enums'; +import { Alert, Stack } from '@mui/material'; -import { useBuilderTranslation } from '../../config/i18n'; -import { hooks } from '../../config/queryClient'; +import { NS } from '@/config/constants'; +import { hooks } from '@/config/queryClient'; import { PUBLISHED_ITEMS_ERROR_ALERT_ID, PUBLISHED_ITEMS_ID, -} from '../../config/selectors'; +} from '@/config/selectors'; + +import { Ordering } from '~builder/enums'; + import { BUILDER } from '../../langs/constants'; import ErrorAlert from '../common/ErrorAlert'; import SelectTypes from '../common/SelectTypes'; @@ -17,9 +20,9 @@ import ModeButton from '../item/header/ModeButton'; import LoadingScreen from '../layout/LoadingScreen'; import ItemsTable from '../main/list/ItemsTable'; import SortingSelect from '../table/SortingSelect'; -import { SortingOptions } from '../table/types'; +import { SortingOptions, SortingOptionsType } from '../table/types'; import { useSorting, useTranslatedSortingOptions } from '../table/useSorting'; -import PageWrapper from './BuilderPageLayout'; +import { BuilderPageLayout } from './BuilderPageLayout'; const PublishedItemsScreenContent = ({ searchText, @@ -36,7 +39,7 @@ const PublishedItemsScreenContent = ({ const options = useTranslatedSortingOptions(); const { shouldDisplayItem } = useFilterItemsContext(); const { sortBy, setSortBy, ordering, setOrdering, sortFn } = - useSorting({ + useSorting({ sortBy: SortingOptions.ItemUpdatedAt, ordering: Ordering.DESC, }); @@ -112,7 +115,7 @@ const PublishedItemsScreen = (): JSX.Element | null => { const { input, text } = useItemSearch(); return ( - { } > - + ); }; diff --git a/src/modules/builder/components/pages/item/ItemInformationPage.tsx b/src/modules/builder/components/pages/item/ItemInformationPage.tsx index f873d6c0e..bb539f364 100644 --- a/src/modules/builder/components/pages/item/ItemInformationPage.tsx +++ b/src/modules/builder/components/pages/item/ItemInformationPage.tsx @@ -1,6 +1,5 @@ import ItemMetadataContent from '~builder/components/item/settings/ItemMetadataContent'; -// eslint-disable-next-line arrow-body-style const ItemInformationPage = (): JSX.Element => { // anyone can see this page return ; diff --git a/src/modules/builder/components/pages/item/accessWrapper/EnrollContent.tsx b/src/modules/builder/components/pages/item/accessWrapper/EnrollContent.tsx index 71275362e..84fc4757b 100644 --- a/src/modules/builder/components/pages/item/accessWrapper/EnrollContent.tsx +++ b/src/modules/builder/components/pages/item/accessWrapper/EnrollContent.tsx @@ -1,3 +1,5 @@ +import { useTranslation } from 'react-i18next'; + import { Stack, Typography } from '@mui/material'; import { DiscriminatedItem } from '@graasp/sdk'; @@ -5,10 +7,11 @@ import { Button } from '@graasp/ui'; import { CircleUser } from 'lucide-react'; -import { useBuilderTranslation } from '@/config/i18n'; +import { NS } from '@/config/constants'; import { mutations } from '@/config/queryClient'; import { ENROLL_BUTTON_SELECTOR } from '@/config/selectors'; -import { BUILDER } from '@/langs/constants'; + +import { BUILDER } from '~builder/langs/constants'; type Props = { itemId: DiscriminatedItem['id'] }; diff --git a/src/modules/builder/components/pages/item/accessWrapper/RequestAccessContent.tsx b/src/modules/builder/components/pages/item/accessWrapper/RequestAccessContent.tsx index 20c3bef99..b26a20420 100644 --- a/src/modules/builder/components/pages/item/accessWrapper/RequestAccessContent.tsx +++ b/src/modules/builder/components/pages/item/accessWrapper/RequestAccessContent.tsx @@ -1,3 +1,5 @@ +import { useTranslation } from 'react-i18next'; + import { LoadingButton } from '@mui/lab'; import { Stack, Typography } from '@mui/material'; @@ -9,13 +11,14 @@ import { import { Check, Lock } from 'lucide-react'; -import { useBuilderTranslation } from '@/config/i18n'; +import { NS } from '@/config/constants'; import { hooks, mutations } from '@/config/queryClient'; import { MEMBERSHIP_REQUEST_PENDING_SCREEN_SELECTOR, REQUEST_MEMBERSHIP_BUTTON_ID, } from '@/config/selectors'; -import { BUILDER } from '@/langs/constants'; + +import { BUILDER } from '~builder/langs/constants'; type Props = { member: Member; diff --git a/src/modules/builder/components/thumbnails/ThumbnailCrop.hook.tsx b/src/modules/builder/components/thumbnails/ThumbnailCrop.hook.tsx index dbe61ebb9..6ebb00790 100644 --- a/src/modules/builder/components/thumbnails/ThumbnailCrop.hook.tsx +++ b/src/modules/builder/components/thumbnails/ThumbnailCrop.hook.tsx @@ -27,6 +27,7 @@ export const useThumbnailCrop = ({ const [croppedUrl, setCroppedUrl] = useState(); const [fileSource, setFileSource] = useState(); + // eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect useEffect(() => setCroppedUrl(currentThumbnail), [currentThumbnail]); const resetCroppedUrl = () => setCroppedUrl(undefined); diff --git a/src/modules/builder/components/thumbnails/ThumbnailUploader.hook.tsx b/src/modules/builder/components/thumbnails/ThumbnailUploader.hook.tsx index 54a9eef4e..5ee7c4197 100644 --- a/src/modules/builder/components/thumbnails/ThumbnailUploader.hook.tsx +++ b/src/modules/builder/components/thumbnails/ThumbnailUploader.hook.tsx @@ -58,11 +58,12 @@ export const useThumbnailUploader = ({ })); useEffect(() => { + // eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect setItemThumbnail((prev) => ({ url: thumbnailUrl, // As we set hasThumbnail = true during the upload, // we only update it if the previous state is false, - // meaning that no upload occured and the item doesn't have a thumbnail. + // meaning that no upload occurred and the item doesn't have a thumbnail. // This solve some flickering of the warning tooltip after the upload. hasThumbnail: prev.hasThumbnail || Boolean(thumbnailUrl), })); diff --git a/src/modules/builder/cypress/support/server.ts b/src/modules/builder/cypress/support/server.ts index 538322fd7..e004041f3 100644 --- a/src/modules/builder/cypress/support/server.ts +++ b/src/modules/builder/cypress/support/server.ts @@ -106,7 +106,6 @@ const checkMembership = ({ }: { item: ItemForTest; currentMember: Member; - // eslint-disable-next-line arrow-body-style }) => { // todo: public // TODO!!! diff --git a/src/modules/builder/utils/useDebounce.ts b/src/modules/builder/utils/useDebounce.ts index 22c5893af..d4e7fd894 100644 --- a/src/modules/builder/utils/useDebounce.ts +++ b/src/modules/builder/utils/useDebounce.ts @@ -18,9 +18,11 @@ export const useDebouncedCallback = ( const [isDebounced, setIsDebounced] = useState(false); const debounceSetSend = useMemo(() => { + // eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect setIsDebounced(true); return debounce(() => { callback(); + // eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect setIsDebounced(false); }, debounceDelayMS); }, [callback, debounceDelayMS]); diff --git a/src/routes/builder/_layout/bookmarks.tsx b/src/routes/builder/_layout/bookmarks.tsx index 25fd94305..1a451af4e 100644 --- a/src/routes/builder/_layout/bookmarks.tsx +++ b/src/routes/builder/_layout/bookmarks.tsx @@ -1,9 +1,11 @@ import { createFileRoute } from '@tanstack/react-router'; +import { BookmarkedItemsScreen } from '~builder/components/pages/BookmarkedItemsScreen'; + export const Route = createFileRoute('/builder/_layout/bookmarks')({ component: RouteComponent, }); function RouteComponent() { - return
Hello "/builder/_layout/bookmarks"!
; + return ; } diff --git a/src/routes/builder/_layout/published.tsx b/src/routes/builder/_layout/published.tsx index ed5f34ff3..1a6e918ea 100644 --- a/src/routes/builder/_layout/published.tsx +++ b/src/routes/builder/_layout/published.tsx @@ -1,9 +1,11 @@ import { createFileRoute } from '@tanstack/react-router'; +import PublishedItemsScreen from '~builder/components/pages/PublishedItemsScreen'; + export const Route = createFileRoute('/builder/_layout/published')({ component: RouteComponent, }); function RouteComponent() { - return
Hello "/builder/_layout/published"!
; + return ; }