Skip to content

Commit

Permalink
fix: fix copy modal
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia committed Apr 24, 2024
1 parent 546fc62 commit b9081ec
Show file tree
Hide file tree
Showing 25 changed files with 651 additions and 330 deletions.
69 changes: 68 additions & 1 deletion cypress/e2e/collection/summary.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,25 @@ import { DEFAULT_LANG } from '@graasp/translations';
import { buildCollectionRoute } from '../../../src/config/routes';
import {
CHILDREN_ITEMS_GRID_ID,
CHILD_CARD_COPY_BUTTON_ID,
ITEM_SUMMARY_TITLE_ID,
LIBRARY_ACTION_GROUP_BUTTON_ID,
LIBRARY_ACTION_GROUP_COPY_BUTTON_ID,
LIBRARY_ACTION_GROUP_POP_UP_BUTTONS_ID,
LIKE_COLLECTION_NOT_LOGGED_ID,
SUMMARY_AUTHOR_CONTAINER_ID,
SUMMARY_CREATED_AT_CONTAINER_ID,
SUMMARY_LAST_UPDATE_CONTAINER_ID,
TREE_MODAL_CONFIRM_BUTTON_ID,
buildContributorId,
} from '../../../src/config/selectors';
import { buildPublicAndPrivateEnvironments } from '../../fixtures/environment';
import { PUBLISHED_ITEMS } from '../../fixtures/items';
import { COMPLETE_MEMBERS, MEMBERS } from '../../fixtures/members';
import {
COMPLETE_MEMBERS,
CURRENT_USER,
MEMBERS,
} from '../../fixtures/members';

describe('Collection Summary', () => {
buildPublicAndPrivateEnvironments().forEach((environment) => {
Expand Down Expand Up @@ -114,4 +123,62 @@ describe('Collection Summary', () => {
});
});
});

describe('Signed out', () => {
it('should not show copy button', { defaultCommandTimeout: 10000 }, () => {
cy.setUpApi({ items: PUBLISHED_ITEMS });

const item = PUBLISHED_ITEMS[1];
cy.visit(buildCollectionRoute(item.id));

cy.get(`#${LIBRARY_ACTION_GROUP_BUTTON_ID}`).click();
cy.get(`#${LIBRARY_ACTION_GROUP_POP_UP_BUTTONS_ID}`)
.find('button')
.should('have.length', 2);
});
});

describe('Signed in', () => {
beforeEach(() => {
cy.setUpApi({ currentMember: CURRENT_USER, items: PUBLISHED_ITEMS });
});

it('copy current item and child', { defaultCommandTimeout: 10000 }, () => {
cy.intercept({
method: 'POST',
url: '/items/copy*',
}).as('copy');

const item = PUBLISHED_ITEMS[0];
cy.visit(buildCollectionRoute(item.id));

// copy parent item on home
cy.get(`#${LIBRARY_ACTION_GROUP_BUTTON_ID}`).click();
cy.get(`#${LIBRARY_ACTION_GROUP_COPY_BUTTON_ID}`).click();

cy.get(`#${TREE_MODAL_CONFIRM_BUTTON_ID}`).should('be.disabled');
cy.get(`button`).contains('My Graasp').click();
cy.get(`#${TREE_MODAL_CONFIRM_BUTTON_ID}`).click();

cy.wait('@copy').then(({ request: { url, body } }) => {
expect(url).to.contain(item.id);
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
expect(body.to).to.be.undefined;
});

// copy child item on home
const child = PUBLISHED_ITEMS[2];
cy.get(`#${CHILD_CARD_COPY_BUTTON_ID}`).click();

cy.get(`#${TREE_MODAL_CONFIRM_BUTTON_ID}`).should('be.disabled');
cy.get(`button`).contains('My Graasp').click();
cy.get(`#${TREE_MODAL_CONFIRM_BUTTON_ID}`).click();

cy.wait('@copy').then(({ request: { url, body } }) => {
expect(url).to.contain(child.id);
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
expect(body.to).to.be.undefined;
});
});
});
});
4 changes: 2 additions & 2 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ITEM_LIKES } from '../fixtures/itemLikes';
import { PUBLISHED_ITEMS } from '../fixtures/items';
import { MEMBERS } from '../fixtures/members';
import {
mockGetAccessibleItems,
mockGetAvatarUrl,
mockGetCategories,
mockGetChildren,
Expand All @@ -15,7 +16,6 @@ import {
mockGetLikedItems,
mockGetMember,
mockGetMembers,
mockGetOwnItems,
mockGetPublishItemInformations,
mockSearch,
mockSignInRedirection,
Expand All @@ -42,7 +42,7 @@ Cypress.Commands.add(
} = {}) => {
const cachedMembers = JSON.parse(JSON.stringify(members));

mockGetOwnItems({ items, currentMember });
mockGetAccessibleItems(items);

mockGetChildren({ items, currentMember });

Expand Down
40 changes: 20 additions & 20 deletions cypress/support/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ const {
SIGN_OUT_ROUTE,
buildGetMembersRoute,
buildGetCategoriesRoute,
GET_OWN_ITEMS_ROUTE,
SEARCH_PUBLISHED_ITEMS_ROUTE,
} = API_ROUTES;

Expand Down Expand Up @@ -70,29 +69,30 @@ export const redirectionReply = {
body: null,
};

export const mockGetOwnItems = ({
items,
currentMember,
}: {
items: MockItem[];
currentMember?: MockMember;
}) => {
export const mockGetAccessibleItems = (items: MockItem[]): void => {
cy.intercept(
{
method: DEFAULT_GET.method,
url: `${API_HOST}/${GET_OWN_ITEMS_ROUTE}`,
method: HttpMethod.Get,
pathname: `/${ITEMS_ROUTE}/accessible`,
},
({ reply }) => {
if (!currentMember) {
return reply({ statusCode: StatusCodes.UNAUTHORIZED, body: null });
}
const own = items.filter(
({ creator, path }) =>
creator?.id === currentMember.id && !path.includes('.'),
);
return reply(own);
({ url, reply }) => {
const params = new URL(url).searchParams;

const page = parseInt(params.get('page') ?? '1', 10);
const pageSize = parseInt(params.get('pageSize') ?? '10', 10);

// as { page: number; pageSize: number };

// warning: we don't check memberships
const root = items.filter((i) => !i.path.includes('.'));

// todo: filter

const result = root.slice((page - 1) * pageSize, page * pageSize);

reply({ data: result, totalCount: root.length });
},
).as('getOwnItems');
).as('getAccessibleItems');
};

export const mockGetCurrentMember = (
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"@graasp/query-client": "3.4.1",
"@graasp/sdk": "4.4.0",
"@graasp/translations": "1.25.3",
"@graasp/ui": "4.15.0",
"@graasp/ui": "github:graasp/graasp-ui#row-menu",
"@mui/icons-material": "5.15.14",
"@mui/lab": "5.0.0-alpha.169",
"@mui/material": "5.15.14",
Expand Down
10 changes: 7 additions & 3 deletions src/components/collection/ChildrenCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import { ItemIcon, Thumbnail } from '@graasp/ui';
import { COLLECTION_CARD_BORDER_RADIUS } from '../../config/cssStyles';
import { useLibraryTranslation } from '../../config/i18n';
import { buildCollectionRoute } from '../../config/routes';
import { CHILD_CARD_COPY_BUTTON_ID } from '../../config/selectors';
import LIBRARY from '../../langs/constants';
import { QueryClientContext } from '../QueryClientContext';
import CopyButton from './CopyButton';
import CopyLinkButton from './CopyLinkButton';
import DownloadButton from './DownloadButton';

Expand Down Expand Up @@ -73,9 +75,9 @@ export const SubItemCard: React.FC<SubItemCardProps> = ({
thumbnail,
subtext,
}) => {
// const { hooks } = useContext(QueryClientContext);
const { hooks } = useContext(QueryClientContext);

// const { data: member } = hooks.useCurrentMember();
const { data: member } = hooks.useCurrentMember();

const { name, id } = item;

Expand All @@ -87,7 +89,9 @@ export const SubItemCard: React.FC<SubItemCardProps> = ({
href={link}
actions={
<>
{/* {member?.id && <CopyButton id={id} />} */}
{member?.id && (
<CopyButton id={CHILD_CARD_COPY_BUTTON_ID} itemId={id} />
)}
<CopyLinkButton itemId={item.id} />
<DownloadButton id={id} />
</>
Expand Down
5 changes: 3 additions & 2 deletions src/components/collection/CollectionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { QueryClientContext } from '../QueryClientContext';
import CardMediaComponent from '../common/CardMediaComponent';
import { StyledCard } from '../common/StyledCard';
import ContentDescription from './ContentDescription';
import CopyButton from './CopyButton';
import CopyLinkButton from './CopyLinkButton';
import DownloadButton from './DownloadButton';

Expand Down Expand Up @@ -117,7 +118,7 @@ export const CollectionCard = ({ collection, showIsContentTag }: Props) => {
} = collection;
const { t } = useLibraryTranslation();
const { hooks } = useContext(QueryClientContext);
// const { data: member } = hooks.useCurrentMember();
const { data: member } = hooks.useCurrentMember();
const { data: authorAvatarUrl, isLoading: isLoadingAvatar } =
hooks.useAvatarUrl({
id: creator?.id,
Expand Down Expand Up @@ -204,7 +205,7 @@ export const CollectionCard = ({ collection, showIsContentTag }: Props) => {
</Stack>
<Box>
<DownloadButton id={id} />
{/* {member?.id && <CopyButton id={id} />} */}
{member?.id && <CopyButton itemId={id} />}
<CopyLinkButton itemId={collection.id} />
</Box>
</CardActions>
Expand Down
30 changes: 15 additions & 15 deletions src/components/collection/CopyButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@ import IconButton from '@mui/material/IconButton';
import Tooltip from '@mui/material/Tooltip';

import { useLibraryTranslation } from '../../config/i18n';
import {
TREE_MODAL_MY_ITEMS_ID,
TREE_MODAL_SHARED_ITEMS_ID,
} from '../../config/selectors';
import LIBRARY from '../../langs/constants';
import { QueryClientContext } from '../QueryClientContext';
import TreeModal from './TreeModal';
import ItemSelectionModal from './copyModal/ItemSelectionModal';

export const useCopyAction = (id?: string) => {
const { t } = useLibraryTranslation();
Expand All @@ -36,29 +32,31 @@ export const useCopyAction = (id?: string) => {
}

// todo: set notifier for copy
const copy = ({ to }: { to: string }) => {
const copy = (to: string | undefined) => {
// remove loading icon on callback
// do not set parent if it is root
const payload: Parameters<typeof copyItems>[0] = {
ids: [id],
};

// if the location to copy the item is MyItems or SharedItems root, then set the payload.to argument to be undefined
payload.to = [TREE_MODAL_MY_ITEMS_ID, TREE_MODAL_SHARED_ITEMS_ID].includes(
to,
)
? undefined
: to;
payload.to = to;

copyItems(payload);
};

const treeModal = user?.id && id && (
<TreeModal
<ItemSelectionModal
title={t(LIBRARY.COPY_BUTTON_MODAL_TITLE)}
open={showTreeModal}
onClose={() => setShowTreeModal(false)}
onConfirm={copy}
itemId={id}
buttonText={() => t(LIBRARY.COPY_MODAL_SUBMIT_BUTTON)}
isDisabled={(items, item) => {
// cannot copy inside itself
return items.some((i) => item.path.includes(i.path));
}}
/>
);

Expand All @@ -70,13 +68,14 @@ export const useCopyAction = (id?: string) => {
};

type Props = {
id: string;
itemId: string;
id?: string;
};

const CopyButton = ({ id }: Props) => {
const CopyButton = ({ id, itemId }: Props) => {
const { t } = useLibraryTranslation();

const { treeModal, isCopying, startCopy } = useCopyAction(id);
const { treeModal, isCopying, startCopy } = useCopyAction(itemId);

const renderButton = () => {
if (isCopying) {
Expand All @@ -92,6 +91,7 @@ const CopyButton = ({ id }: Props) => {
return (
<Tooltip title={t(LIBRARY.COPY_BUTTON_TOOLTIP)}>
<IconButton
id={id}
onClick={startCopy}
aria-label={t(LIBRARY.COPY_BUTTON_TOOLTIP)}
>
Expand Down
Loading

0 comments on commit b9081ec

Please sign in to comment.