Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add new folder button #1593

Merged
merged 2 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions cypress/e2e/map/map.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// /map is used by the mobile application to display the map and have access to its feature
import { MAP_ITEMS_PATH } from '@/config/paths';
import {
CREATE_ITEM_FOLDER_ID,
FOLDER_FORM_DESCRIPTION_ID,
buildMapViewId,
} from '@/config/selectors';

describe('Map', () => {
it('open create folder modal on Home', () => {
cy.setUpApi();
cy.visit(`${MAP_ITEMS_PATH}?enableGeolocation=false`);

// home id
cy.get(`#${buildMapViewId(undefined)}`).should('be.visible');

// select a country
cy.get(`#${buildMapViewId(undefined)} input`).click();
cy.get(`#${buildMapViewId(undefined)} [role="presentation"]`).click();

// open location button
cy.get(`#${buildMapViewId(undefined)}`).click();
cy.get(`#${buildMapViewId(undefined)} img[role="button"]`).click();
cy.get(`[data-testid="AddLocationAltIcon"]`).click();

// open folder form
cy.get(`#${CREATE_ITEM_FOLDER_ID}`).click();
cy.get(`#${FOLDER_FORM_DESCRIPTION_ID}`).should('be.visible');
});
});
4 changes: 3 additions & 1 deletion cypress/support/createUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from '@graasp/sdk';

import {
ADD_FOLDER_BUTTON_CY,
CREATE_ITEM_APP_ID,
CREATE_ITEM_BUTTON_ID,
CREATE_ITEM_CLOSE_BUTTON_ID,
Expand All @@ -16,6 +17,7 @@ import {
DASHBOARD_UPLOADER_ID,
H5P_DASHBOARD_UPLOADER_ID,
ZIP_DASHBOARD_UPLOADER_ID,
buildDataCyWrapper,
} from '../../src/config/selectors';
import { InternalItemType } from '../../src/config/types';
import { ZIPInternalItem } from '../fixtures/files';
Expand Down Expand Up @@ -43,7 +45,7 @@ export const createFolder = (
payload: { name?: string; description?: string },
options?: { confirm?: boolean },
): void => {
cy.get(`#${CREATE_ITEM_BUTTON_ID}`).click({ force: true });
cy.get(buildDataCyWrapper(ADD_FOLDER_BUTTON_CY)).click({ force: true });
cy.fillFolderModal(payload, options);
};

Expand Down
32 changes: 25 additions & 7 deletions src/components/item/FolderContent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { useEffect } from 'react';
import { useOutletContext } from 'react-router-dom';

import { Alert, Box, Stack, Typography } from '@mui/material';
import {
Alert,
Box,
Stack,
Typography,
useMediaQuery,
useTheme,
} from '@mui/material';

import {
PackedItem,
Expand Down Expand Up @@ -43,6 +50,7 @@ import { useSorting } from '../table/useSorting';
import FolderDescription from './FolderDescription';
import FolderToolbar from './FolderSelectionToolbar';
import { useItemSearch } from './ItemSearch';
import { NewFolderButton } from './form/folder/NewFolderButton';
import ModeButton from './header/ModeButton';

type Props = {
Expand Down Expand Up @@ -132,6 +140,8 @@ const Content = ({
* Helper component to render typed folder items
*/
const FolderContent = ({ item }: { item: PackedItem }): JSX.Element => {
const theme = useTheme();
const isMd = useMediaQuery(theme.breakpoints.up('md'));
const { t: translateEnums } = useEnumsTranslation();
const { itemTypes } = useFilterItemsContext();
const { t: translateBuilder } = useBuilderTranslation();
Expand Down Expand Up @@ -185,12 +195,20 @@ const FolderContent = ({ item }: { item: PackedItem }): JSX.Element => {
>
{itemSearch.input}
{canWrite && (
<NewItemButton
key="newButton"
size="medium"
// add new items at the end of the list
previousItemId={children[children.length - 1]?.id}
/>
<>
<NewFolderButton
type={isMd ? 'button' : 'icon'}
// add new items at the end of the list
previousItemId={children[children.length - 1]?.id}
/>
<NewItemButton
type={isMd ? 'button' : 'icon'}
key="newButton"
size="medium"
// add new items at the end of the list
previousItemId={children[children.length - 1]?.id}
/>
</>
)}
</Stack>
</Stack>
Expand Down
3 changes: 2 additions & 1 deletion src/components/item/form/folder/FolderCreateForm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useParams } from 'react-router';

import {
Box,
Expand Down Expand Up @@ -40,10 +41,10 @@ type FolderCreateFormProps = {

export function FolderCreateForm({
onClose,
parentId,
geolocation,
previousItemId,
}: FolderCreateFormProps): JSX.Element {
const { itemId: parentId } = useParams();
const { t: translateBuilder } = useBuilderTranslation();
const { t: translateCommon } = useCommonTranslation();
const methods = useForm<Inputs>();
Expand Down
75 changes: 75 additions & 0 deletions src/components/item/form/folder/NewFolderButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { ButtonProps, Dialog, IconButton, useTheme } from '@mui/material';

import { DiscriminatedItem, ItemGeolocation } from '@graasp/sdk';
import { Button } from '@graasp/ui';

import { FolderPlus } from 'lucide-react';

import useModalStatus from '@/components/hooks/useModalStatus';
import { useBuilderTranslation } from '@/config/i18n';
import { ADD_FOLDER_BUTTON_CY } from '@/config/selectors';
import { BUILDER } from '@/langs/constants';

import { FolderCreateForm } from './FolderCreateForm';

type Props = {
previousItemId?: DiscriminatedItem['id'];
parentId?: DiscriminatedItem['id'];
geolocation?: Pick<ItemGeolocation, 'lat' | 'lng'>;
size?: ButtonProps['size'];
type?: 'button' | 'icon';
};

export const NewFolderButton = ({
previousItemId,
parentId,
geolocation,
size = 'medium',
type = 'button',
}: Props): JSX.Element => {
const { t: translateBuilder } = useBuilderTranslation();
const theme = useTheme();
const { isOpen, openModal, closeModal } = useModalStatus();

const handleClickOpen = () => {
openModal();
};

return (
<>
{type === 'icon' ? (
<IconButton
onClick={handleClickOpen}
color="secondary"
sx={{
background: theme.palette.primary.main,
'&:hover': { background: 'grey' },
}}
data-umami-event="new-folder-icon-button"
>
<FolderPlus color="white" />
</IconButton>
) : (
<Button
dataCy={ADD_FOLDER_BUTTON_CY}
onClick={handleClickOpen}
color="primary"
aria-label="add-folder"
startIcon={<FolderPlus />}
size={size}
data-umami-event="new-folder-button"
>
{translateBuilder(BUILDER.CREATE_FOLDER_BUTTON_TEXT)}
</Button>
)}
<Dialog open={isOpen} onClose={closeModal} maxWidth="md" fullWidth>
<FolderCreateForm
onClose={closeModal}
previousItemId={previousItemId}
parentId={parentId}
geolocation={geolocation}
/>
</Dialog>
</>
);
};
2 changes: 1 addition & 1 deletion src/components/main/NewItemModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const NewItemModal = ({
const { t: translateCommon } = useCommonTranslation();

const [selectedItemType, setSelectedItemType] = useState<NewItemTabType>(
ItemType.FOLDER,
ItemType.LOCAL_FILE,
);

const { itemId: parentId } = useParams();
Expand Down
12 changes: 11 additions & 1 deletion src/components/pages/home/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ import {
Button as MuiButton,
Stack,
Typography,
useMediaQuery,
useTheme,
} from '@mui/material';

import { Button } from '@graasp/ui';

import { NewFolderButton } from '@/components/item/form/folder/NewFolderButton';
import LoadingScreen from '@/components/layout/LoadingScreen';
import {
SelectionContextProvider,
Expand Down Expand Up @@ -211,6 +214,8 @@ const HomeScreenContent = ({ searchText }: { searchText: string }) => {
const HomeScreen = (): JSX.Element => {
const { t: translateBuilder } = useBuilderTranslation();
const { data: currentMember } = hooks.useCurrentMember();
const theme = useTheme();
const isMd = useMediaQuery(theme.breakpoints.up('md'));

const itemSearch = useItemSearch();

Expand All @@ -226,7 +231,12 @@ const HomeScreen = (): JSX.Element => {
spacing={1}
>
{itemSearch.input}
<NewItemButton key="newButton" size="medium" />
<NewFolderButton type={isMd ? 'button' : 'icon'} />
<NewItemButton
key="newButton"
size="medium"
type={isMd ? 'button' : 'icon'}
/>
</Stack>
}
>
Expand Down
3 changes: 2 additions & 1 deletion src/config/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const buildFileItemId = (id: string): string => `file-${id}`;
export const ITEM_PANEL_ID = 'itemPanelMetadata';
export const ITEM_PANEL_NAME_ID = 'itemPanelName';
export const ITEM_PANEL_TABLE_ID = 'itemPanelTable';
export const CREATE_ITEM_FOLDER_ID = 'createItemSpace';
export const CREATE_ITEM_FOLDER_ID = 'createItemFolder';
export const CREATE_ITEM_LINK_ID = 'createItemLink';
export const CREATE_ITEM_FILE_ID = 'createItemFile';
export const ITEM_FORM_LINK_INPUT_ID = 'itemFormLinkInput';
Expand Down Expand Up @@ -452,3 +452,4 @@ export const MEMBERSHIP_REQUEST_REJECT_BUTTON_SELECTOR =
export const ENROLL_BUTTON_SELECTOR = 'enrollButton';
export const VISIBILITY_HIDDEN_ALERT_ID = 'visibilityHiddenAlert';
export const SHARE_ITEM_CANCEL_BUTTON_CY = 'shareItemCancelButton';
export const ADD_FOLDER_BUTTON_CY = 'addFolder';
1 change: 1 addition & 0 deletions src/langs/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -613,4 +613,5 @@ export const BUILDER = {
DELETE_GUESTS_MODAL_DELETE_BUTTON: 'DELETE_GUESTS_MODAL_DELETE_BUTTON',
DELETE_GUESTS_MODAL_CONTENT: 'DELETE_GUESTS_MODAL_CONTENT',
DELETE_ITEM_LOGIN_SCHEMA_ALERT_TEXT: 'DELETE_ITEM_LOGIN_SCHEMA_ALERT_TEXT',
CREATE_FOLDER_BUTTON_TEXT: 'CREATE_FOLDER_BUTTON_TEXT',
};
3 changes: 2 additions & 1 deletion src/langs/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -510,5 +510,6 @@
"DELETE_GUESTS_MODAL_TITLE_other": "Confirm deletion of {{count}} disabled reader(s)",
"DELETE_GUESTS_MODAL_CONTENT": "I confirm deleting <1>permanently</1> the following readers and their data:",
"DELETE_GUESTS_MODAL_DELETE_BUTTON": "Delete permanently",
"ADD_TAG_OPTION_BUTTON_TEXT": "Add {{value}}"
"ADD_TAG_OPTION_BUTTON_TEXT": "Add {{value}}",
"CREATE_FOLDER_BUTTON_TEXT": "Create Folder"
}
3 changes: 2 additions & 1 deletion src/langs/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -503,5 +503,6 @@
"TRASH_COUNT_other": "Il y a {{count}} éléments dans la poubelle.",
"ITEM_NAME_CANNOT_BE_EMPTY": "L'élément a besoin d'un nom.",
"LINK_INVALID_MESSAGE": "Le lien est invalide.",
"DOCUMENT_EMPTY_MESSAGE": "Le contenu ne peut pas être vide."
"DOCUMENT_EMPTY_MESSAGE": "Le contenu ne peut pas être vide.",
"CREATE_FOLDER_BUTTON_TEXT": "Nouveau Dossier"
}
Loading