Skip to content

Commit

Permalink
feat: add pagination to trash page (#1494)
Browse files Browse the repository at this point in the history
* refactor: add margin

* feat: show paginated recycle bin

* feat: update tests

* refactor: remove features in recycled page

* refactor: apply PR requested changes

* refactor: apply PR requested changes
  • Loading branch information
pyphilia authored Oct 17, 2024
1 parent fa5af3a commit c3c5701
Show file tree
Hide file tree
Showing 22 changed files with 140 additions and 244 deletions.
1 change: 0 additions & 1 deletion cypress/e2e/item/trash/delete.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ describe('Delete Items', () => {
cy.wait('@deleteItems').then(({ request: { url } }) => {
expect(url).to.contain(id);
});
cy.wait('@getRecycledItems');
});

it('delete many items', () => {
Expand Down
1 change: 0 additions & 1 deletion cypress/e2e/item/trash/restore.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ describe('Restore Items', () => {
cy.wait('@restoreItems').then(({ request: { url } }) => {
expect(url).to.contain(id);
});
cy.wait('@getRecycledItems');
});

it('restore many items', () => {
Expand Down
50 changes: 0 additions & 50 deletions cypress/e2e/item/trash/viewTrash.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,14 @@ import {
PackedRecycledItemDataFactory,
} from '@graasp/sdk';

import { SortingOptions } from '@/components/table/types';
import { BUILDER } from '@/langs/constants';

import i18n, { BUILDER_NAMESPACE } from '../../../../src/config/i18n';
import { RECYCLE_BIN_PATH } from '../../../../src/config/paths';
import {
CREATE_ITEM_BUTTON_ID,
ITEM_SEARCH_INPUT_ID,
PREVENT_GUEST_MESSAGE_ID,
RECYCLED_ITEMS_ERROR_ALERT_ID,
RECYCLED_ITEMS_ROOT_CONTAINER,
SORTING_ORDERING_SELECTOR_ASC,
SORTING_ORDERING_SELECTOR_DESC,
SORTING_SELECT_SELECTOR,
buildItemCard,
} from '../../../../src/config/selectors';
import { CURRENT_USER } from '../../../fixtures/members';
Expand Down Expand Up @@ -62,55 +56,11 @@ describe('View trash', () => {
cy.visit(RECYCLE_BIN_PATH);
});

it('Empty search', () => {
i18n.changeLanguage(CURRENT_USER.extra.lang as string);
const searchText = 'mysearch';
cy.get(`#${ITEM_SEARCH_INPUT_ID}`).type(searchText);
const text = i18n.t(BUILDER.TRASH_NO_ITEM_SEARCH, {
search: searchText,
ns: BUILDER_NAMESPACE,
});
cy.get(`#${RECYCLED_ITEMS_ROOT_CONTAINER}`).should('contain', text);
});

it('New button should not exist', () => {
cy.get(`#${CREATE_ITEM_BUTTON_ID}`).should('not.exist');
});

it('check recycled item layout', () => {
for (const { item } of recycledItemData) {
cy.get(`#${buildItemCard(item.id)}`).should('be.visible');
}
});

it('Sorting & Ordering', () => {
cy.get(`${SORTING_SELECT_SELECTOR} input`).should(
'have.value',
SortingOptions.ItemUpdatedAt,
);
cy.get(SORTING_ORDERING_SELECTOR_DESC).should('be.visible');

cy.get(SORTING_SELECT_SELECTOR).click();
cy.get('li[data-value="item.name"]').click();

// check items are ordered by name
cy.get(`#${RECYCLED_ITEMS_ROOT_CONTAINER} h5`).then(($e) => {
recycledItemData.sort((a, b) => (a.item.name < b.item.name ? 1 : -1));
for (let idx = 0; idx < recycledItemData.length; idx += 1) {
expect($e[idx].innerText).to.eq(recycledItemData[idx].item.name);
}
});

// change ordering
cy.get(SORTING_ORDERING_SELECTOR_DESC).click();
cy.get(SORTING_ORDERING_SELECTOR_ASC).should('be.visible');
cy.get(`#${RECYCLED_ITEMS_ROOT_CONTAINER} h5`).then(($e) => {
recycledItemData.reverse();
for (let idx = 0; idx < recycledItemData.length; idx += 1) {
expect($e[idx].innerText).to.eq(recycledItemData[idx].item.name);
}
});
});
});

describe('Error Handling', () => {
Expand Down
7 changes: 2 additions & 5 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,11 @@ import {
mockGetMembersBy,
mockGetMembershipRequestsForItem,
mockGetOwnMembershipRequests,
mockGetOwnRecycledItemData,
mockGetParents,
mockGetPublicationStatus,
mockGetPublishItemInformations,
mockGetPublishItemsForMember,
mockGetRecycledItems,
mockGetSharedItems,
mockGetShortLinksItem,
mockImportH5p,
mockImportZip,
Expand Down Expand Up @@ -187,8 +186,6 @@ Cypress.Commands.add(

mockGetAccessibleItems(cachedItems);

mockGetSharedItems({ items: cachedItems, member: currentMember });

mockPostItem(cachedItems, postItemError);

mockDeleteItems(allItems, deleteItemsError);
Expand Down Expand Up @@ -282,7 +279,7 @@ Cypress.Commands.add(

mockRecycleItems(items, recycleItemsError);

mockGetRecycledItems(recycledItemData, getRecycledItemsError);
mockGetOwnRecycledItemData(recycledItemData, getRecycledItemsError);

mockRestoreItems(items, restoreItemsError);

Expand Down
54 changes: 22 additions & 32 deletions cypress/support/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { FAILURE_MESSAGES } from '@graasp/translations';
import { StatusCodes } from 'http-status-codes';
import { v4 as uuidv4, v4 } from 'uuid';

import { SETTINGS } from '../../src/config/constants';
import { ITEM_PAGE_SIZE, SETTINGS } from '../../src/config/constants';
import { getMemberById } from '../../src/utils/member';
import {
buildAppApiAccessTokenRoute,
Expand Down Expand Up @@ -69,16 +69,14 @@ const {
buildGetItemMembershipsForItemsRoute,
buildGetItemTagsRoute,
buildPostItemTagRoute,
buildPatchMemberRoute,
SHARED_ITEM_WITH_ROUTE,
buildPatchCurrentMemberRoute,
buildEditItemMembershipRoute,
buildDeleteItemMembershipRoute,
buildPostItemFlagRoute,
buildGetItemChatRoute,
buildExportItemChatRoute,
buildPostItemChatMessageRoute,
buildClearItemChatRoute,
GET_RECYCLED_ITEMS_DATA_ROUTE,
buildDeleteItemTagRoute,
buildDeleteItemsRoute,
buildGetMembersByIdRoute,
Expand Down Expand Up @@ -190,46 +188,38 @@ export const mockGetAccessibleItems = (items: ItemForTest[]): void => {
).as('getAccessibleItems');
};

export const mockGetRecycledItems = (
export const mockGetOwnRecycledItemData = (
recycledItemData: RecycledItemData[],
shouldThrowError: boolean,
): void => {
cy.intercept(
{
method: HttpMethod.Get,
url: `${API_HOST}/${GET_RECYCLED_ITEMS_DATA_ROUTE}`,
pathname: `/items/recycled`,
},
(req) => {
({ reply, url }) => {
if (shouldThrowError) {
req.reply({ statusCode: StatusCodes.BAD_REQUEST });
reply({ statusCode: StatusCodes.BAD_REQUEST });
return;
}

req.reply(recycledItemData);
},
).as('getRecycledItems');
};
const params = new URL(url).searchParams;

export const mockGetSharedItems = ({
items,
member,
}: {
items: ItemForTest[];
member?: Member;
}): void => {
cy.intercept(
{
method: HttpMethod.Get,
url: `${API_HOST}/${SHARED_ITEM_WITH_ROUTE}`,
},
(req) => {
if (!member) {
return req.reply({ statusCode: StatusCodes.UNAUTHORIZED });
}
const shared = items.filter(({ creator }) => creator?.id !== member.id);
return req.reply(shared);
const page = parseInt(params.get('page') ?? '1', 10);
const pageSize = parseInt(params.get('pageSize') ?? '10', 10);

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

reply({
data: result,
totalCount: recycledItemData.length,
pagination: { page: 1, pageSize: ITEM_PAGE_SIZE },
});
},
).as('getSharedItems');
).as('getOwnRecycledItemData');
};

export const mockPostItem = (
Expand Down Expand Up @@ -766,7 +756,7 @@ export const mockEditMember = (
cy.intercept(
{
method: HttpMethod.Patch,
url: new RegExp(`${API_HOST}/${buildPatchMemberRoute(ID_FORMAT)}`),
url: new RegExp(`${API_HOST}/${buildPatchCurrentMemberRoute()}`),
},
({ reply }) => {
if (shouldThrowError) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@emotion/styled": "11.13.0",
"@graasp/chatbox": "3.3.0",
"@graasp/map": "1.19.0",
"@graasp/query-client": "4.0.0",
"@graasp/query-client": "4.2.0",
"@graasp/sdk": "4.31.0",
"@graasp/stylis-plugin-rtl": "2.2.0",
"@graasp/translations": "1.39.0",
Expand Down
4 changes: 2 additions & 2 deletions src/components/common/DeleteButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState } from 'react';

import { PackedItem } from '@graasp/sdk';
import { DiscriminatedItem } from '@graasp/sdk';
import {
ActionButtonVariant,
ColorVariantsType,
Expand All @@ -13,7 +13,7 @@ import { BUILDER } from '../../langs/constants';
import DeleteItemDialog from '../main/DeleteItemDialog';

type Props = {
items: PackedItem[];
items: DiscriminatedItem[];
color?: ColorVariantsType;
id?: string;
type?: ActionButtonVariant;
Expand Down
4 changes: 2 additions & 2 deletions src/components/main/DeleteItemDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
DialogTitle,
} from '@mui/material';

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

import { useBuilderTranslation } from '../../config/i18n';
Expand All @@ -21,7 +21,7 @@ const descriptionId = 'alert-dialog-description';
type Props = {
open?: boolean;
handleClose: () => void;
items: PackedItem[];
items: DiscriminatedItem[];
onConfirm?: () => void;
};

Expand Down
6 changes: 3 additions & 3 deletions src/components/main/list/ItemsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const { useItem } = hooks;
export type ItemsTableProps = {
id?: string;
items?: PackedItem[];
showThumbnails?: boolean;
showThumbnail?: boolean;
canMove?: boolean;
enableMoveInBetween?: boolean;
onCardClick?: (id: DiscriminatedItem['id']) => void;
Expand All @@ -40,7 +40,7 @@ export type ItemsTableProps = {
const ItemsTable = ({
id: tableId = '',
items: rows = [],
showThumbnails = true,
showThumbnail = true,
canMove = true,
enableMoveInBetween = true,
selectedIds = [],
Expand Down Expand Up @@ -192,7 +192,7 @@ const ItemsTable = ({
isMovable={y.isMovable}
enableMoveInBetween={enableMoveInBetween}
itemsStatuses={itemsStatuses}
showThumbnails={showThumbnails}
showThumbnail={showThumbnail}
isSelected={isSelected(droppedEl)}
onThumbnailClick={() => {
if ('id' in droppedEl) {
Expand Down
8 changes: 5 additions & 3 deletions src/components/main/list/ItemsTableCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type Props = {
isDragging: boolean;
isOver: boolean;
isMovable: boolean;
showThumbnails: boolean;
showThumbnail: boolean;
itemsStatuses: ItemsStatuses;
enableMoveInBetween: boolean;
onClick?: (id: string) => void;
Expand All @@ -32,7 +32,7 @@ const ItemsTableCard = ({
isDragging,
isOver,
isMovable,
showThumbnails,
showThumbnail,
itemsStatuses,
enableMoveInBetween,
onClick,
Expand All @@ -51,6 +51,8 @@ const ItemsTableCard = ({
);
}

const thumbnailUrl = showThumbnail ? item.thumbnails?.medium : undefined;

return (
<Box px={1} onClick={() => onClick?.(item.id)}>
<ItemCard
Expand All @@ -61,7 +63,7 @@ const ItemsTableCard = ({
disabled={!isMovable && enableMoveInBetween}
isDragging={isDragging}
isSelected={isSelected}
showThumbnail={showThumbnails}
thumbnailUrl={thumbnailUrl}
menu={<ItemMenuContent item={item} />}
footer={
<Stack
Expand Down
Loading

0 comments on commit c3c5701

Please sign in to comment.