diff --git a/cypress/e2e/item/bookmarks/bookmarks.cy.ts b/cypress/e2e/item/bookmarks/bookmarks.cy.ts
index 2cbbdfc37..e86cb871b 100644
--- a/cypress/e2e/item/bookmarks/bookmarks.cy.ts
+++ b/cypress/e2e/item/bookmarks/bookmarks.cy.ts
@@ -3,6 +3,7 @@ import {
PackedItemBookmarkFactory,
} from '@graasp/sdk';
+import { SortingOptions } from '@/components/table/types';
import { BUILDER } from '@/langs/constants';
import i18n, { BUILDER_NAMESPACE } from '../../../../src/config/i18n';
@@ -12,6 +13,9 @@ import {
BOOKMARKED_ITEMS_ID,
CREATE_ITEM_BUTTON_ID,
ITEM_SEARCH_INPUT_ID,
+ SORTING_ORDERING_SELECTOR_ASC,
+ SORTING_ORDERING_SELECTOR_DESC,
+ SORTING_SELECT_SELECTOR,
buildItemCard,
} from '../../../../src/config/selectors';
import { CURRENT_USER } from '../../../fixtures/members';
@@ -56,11 +60,10 @@ describe('Bookmarked Item', () => {
bookmarkedItems: BOOKMARKED_ITEMS,
});
i18n.changeLanguage(CURRENT_USER.extra.lang as string);
- cy.visit(HOME_PATH);
+ cy.visit(BOOKMARKED_ITEMS_PATH);
});
it('Empty search', () => {
- cy.visit(BOOKMARKED_ITEMS_PATH);
i18n.changeLanguage(CURRENT_USER.extra.lang as string);
const searchText = 'mysearch';
cy.get(`#${ITEM_SEARCH_INPUT_ID}`).type(searchText);
@@ -72,19 +75,18 @@ describe('Bookmarked Item', () => {
});
it("New button doesn't exist", () => {
- cy.visit(BOOKMARKED_ITEMS_PATH);
cy.get(`#${CREATE_ITEM_BUTTON_ID}`).should('not.exist');
});
it('check bookmarked items view', () => {
- cy.visit(BOOKMARKED_ITEMS_PATH);
-
for (const { item } of BOOKMARKED_ITEMS) {
cy.get(`#${buildItemCard(item.id)}`).should('be.visible');
}
});
it('add item to bookmarks', () => {
+ cy.visit(HOME_PATH);
+
const item = NON_BOOKMARKED_ITEM;
addToBookmark(item.id);
@@ -103,6 +105,35 @@ describe('Bookmarked Item', () => {
expect(request.url).to.contain(itemId);
});
});
+
+ 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(`#${BOOKMARKED_ITEMS_ID} h5`).then(($e) => {
+ BOOKMARKED_ITEMS.sort((a, b) => (a.item.name < b.item.name ? 1 : -1));
+ for (let idx = 0; idx < BOOKMARKED_ITEMS.length; idx += 1) {
+ expect($e[idx].innerText).to.eq(BOOKMARKED_ITEMS[idx].item.name);
+ }
+ });
+
+ // change ordering
+ cy.get(SORTING_ORDERING_SELECTOR_DESC).click();
+ cy.get(SORTING_ORDERING_SELECTOR_ASC).should('be.visible');
+ cy.get(`#${BOOKMARKED_ITEMS_ID} h5`).then(($e) => {
+ BOOKMARKED_ITEMS.reverse();
+ for (let idx = 0; idx < BOOKMARKED_ITEMS.length; idx += 1) {
+ expect($e[idx].innerText).to.eq(BOOKMARKED_ITEMS[idx].item.name);
+ }
+ });
+ });
});
describe('Error Handling', () => {
diff --git a/cypress/e2e/item/home/home.cy.ts b/cypress/e2e/item/home/home.cy.ts
index 83317dc00..f02cdf1a5 100644
--- a/cypress/e2e/item/home/home.cy.ts
+++ b/cypress/e2e/item/home/home.cy.ts
@@ -3,6 +3,7 @@ import {
PackedLocalFileItemFactory,
} from '@graasp/sdk';
+import { SortingOptions } from '@/components/table/types';
import { ITEM_PAGE_SIZE } from '@/config/constants';
import i18n from '../../../../src/config/i18n';
@@ -13,6 +14,9 @@ import {
DROPZONE_SELECTOR,
HOME_LOAD_MORE_BUTTON_SELECTOR,
ITEM_SEARCH_INPUT_ID,
+ SORTING_ORDERING_SELECTOR_ASC,
+ SORTING_ORDERING_SELECTOR_DESC,
+ SORTING_SELECT_SELECTOR,
buildItemCard,
buildMapViewId,
} from '../../../../src/config/selectors';
@@ -84,6 +88,36 @@ describe('Home', () => {
});
});
+ it.only('Sorting & ordering', () => {
+ cy.get(`${SORTING_SELECT_SELECTOR} input`).should(
+ 'have.value',
+ SortingOptions.ItemUpdatedAt,
+ );
+ cy.get(SORTING_ORDERING_SELECTOR_DESC).should('be.visible');
+
+ // change sorting
+ cy.get(SORTING_SELECT_SELECTOR).click();
+ cy.get('li[data-value="item.name"]').click();
+ cy.wait(['@getAccessibleItems', '@getAccessibleItems']).then(
+ ([
+ _first,
+ {
+ request: { url },
+ },
+ ]) => {
+ expect(url).to.contain('item.name');
+ expect(url).to.contain('desc');
+ },
+ );
+
+ // change ordering
+ cy.get(SORTING_ORDERING_SELECTOR_DESC).click();
+ cy.get(SORTING_ORDERING_SELECTOR_ASC).should('be.visible');
+ cy.wait('@getAccessibleItems').then(({ request: { url } }) => {
+ expect(url).to.contain('asc');
+ });
+ });
+
describe('Search', () => {
it('Search should trigger refetch', () => {
const searchText = 'mysearch';
diff --git a/cypress/e2e/item/publish/viewPublished.cy.ts b/cypress/e2e/item/publish/viewPublished.cy.ts
index 3372c6715..e63089695 100644
--- a/cypress/e2e/item/publish/viewPublished.cy.ts
+++ b/cypress/e2e/item/publish/viewPublished.cy.ts
@@ -1,5 +1,6 @@
import { PackedFolderItemFactory } from '@graasp/sdk';
+import { SortingOptions } from '@/components/table/types';
import { BUILDER } from '@/langs/constants';
import i18n, { BUILDER_NAMESPACE } from '../../../../src/config/i18n';
@@ -9,6 +10,9 @@ import {
ITEM_SEARCH_INPUT_ID,
PUBLISHED_ITEMS_ERROR_ALERT_ID,
PUBLISHED_ITEMS_ID,
+ SORTING_ORDERING_SELECTOR_ASC,
+ SORTING_ORDERING_SELECTOR_DESC,
+ SORTING_SELECT_SELECTOR,
buildItemCard,
} from '../../../../src/config/selectors';
import { PublishedItemFactory } from '../../../fixtures/items';
@@ -66,6 +70,35 @@ describe('Published Items', () => {
cy.get(`#${buildItemCard(id)}`).should('be.visible');
}
});
+
+ it.only('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(`#${PUBLISHED_ITEMS_ID} h5`).then(($e) => {
+ items.sort((a, b) => (a.name < b.name ? 1 : -1));
+ for (let idx = 0; idx < items.length; idx += 1) {
+ expect($e[idx].innerText).to.eq(items[idx].name);
+ }
+ });
+
+ // change ordering
+ cy.get(SORTING_ORDERING_SELECTOR_DESC).click();
+ cy.get(SORTING_ORDERING_SELECTOR_ASC).should('be.visible');
+ cy.get(`#${PUBLISHED_ITEMS_ID} h5`).then(($e) => {
+ items.reverse();
+ for (let idx = 0; idx < items.length; idx += 1) {
+ expect($e[idx].innerText).to.eq(items[idx].name);
+ }
+ });
+ });
});
describe('Error Handling', () => {
diff --git a/cypress/e2e/item/trash/viewTrash.cy.ts b/cypress/e2e/item/trash/viewTrash.cy.ts
index f248df548..2778882ba 100644
--- a/cypress/e2e/item/trash/viewTrash.cy.ts
+++ b/cypress/e2e/item/trash/viewTrash.cy.ts
@@ -1,14 +1,18 @@
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 { HOME_PATH, RECYCLE_BIN_PATH } from '../../../../src/config/paths';
+import { RECYCLE_BIN_PATH } from '../../../../src/config/paths';
import {
CREATE_ITEM_BUTTON_ID,
ITEM_SEARCH_INPUT_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';
@@ -19,7 +23,7 @@ const recycledItemData = [
PackedRecycledItemDataFactory(),
];
-describe('Bookmarked Item', () => {
+describe('View trash', () => {
describe('Member has no recycled items', () => {
it('Show empty table', () => {
cy.setUpApi({
@@ -39,11 +43,10 @@ describe('Bookmarked Item', () => {
recycledItemData,
});
i18n.changeLanguage(CURRENT_USER.extra.lang as string);
- cy.visit(HOME_PATH);
+ cy.visit(RECYCLE_BIN_PATH);
});
it('Empty search', () => {
- cy.visit(RECYCLE_BIN_PATH);
i18n.changeLanguage(CURRENT_USER.extra.lang as string);
const searchText = 'mysearch';
cy.get(`#${ITEM_SEARCH_INPUT_ID}`).type(searchText);
@@ -55,17 +58,43 @@ describe('Bookmarked Item', () => {
});
it('New button should not exist', () => {
- cy.visit(RECYCLE_BIN_PATH);
cy.get(`#${CREATE_ITEM_BUTTON_ID}`).should('not.exist');
});
it('check recycled item layout', () => {
- cy.visit(RECYCLE_BIN_PATH);
-
for (const { item } of recycledItemData) {
cy.get(`#${buildItemCard(item.id)}`).should('be.visible');
}
});
+
+ it.only('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', () => {
diff --git a/cypress/e2e/item/view/viewFolder.cy.ts b/cypress/e2e/item/view/viewFolder.cy.ts
index e3bdcd4c8..2754b45af 100644
--- a/cypress/e2e/item/view/viewFolder.cy.ts
+++ b/cypress/e2e/item/view/viewFolder.cy.ts
@@ -1,12 +1,17 @@
import { PackedFolderItemFactory } from '@graasp/sdk';
+import { SortingOptionsForFolder } from '../../../../src/components/table/types';
import i18n from '../../../../src/config/i18n';
import { buildItemPath } from '../../../../src/config/paths';
import {
CREATE_ITEM_BUTTON_ID,
ITEM_SEARCH_INPUT_ID,
NAVIGATION_HOME_ID,
+ SORTING_ORDERING_SELECTOR_ASC,
+ SORTING_ORDERING_SELECTOR_DESC,
+ SORTING_SELECT_SELECTOR,
buildItemCard,
+ buildItemsTableId,
buildMapViewId,
} from '../../../../src/config/selectors';
import { ItemLayoutMode } from '../../../../src/enums';
@@ -18,9 +23,11 @@ const item1 = PackedFolderItemFactory();
const child1 = PackedFolderItemFactory({ parentItem });
const child2 = PackedFolderItemFactory({ parentItem });
-const children = [child1, child2];
+const child3 = PackedFolderItemFactory({ parentItem });
+const child4 = PackedFolderItemFactory({ parentItem });
+const children = [child1, child2, child3, child4];
-const items = [parentItem, item1, child1, child2];
+const items = [parentItem, item1, ...children];
describe('View Folder', () => {
it('View folder on map by default', () => {
@@ -89,9 +96,41 @@ describe('View Folder', () => {
cy.get(`#${ITEM_SEARCH_INPUT_ID}`).type(child1.name);
cy.get(`#${buildItemCard(child1.id)}`).should('be.visible');
});
+
+ it.only('Sorting & Ordering', () => {
+ const { id } = parentItem;
+ cy.visit(buildItemPath(id));
+
+ cy.get(`${SORTING_SELECT_SELECTOR} input`).should(
+ 'have.value',
+ SortingOptionsForFolder.Order,
+ );
+ cy.get(SORTING_ORDERING_SELECTOR_ASC).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(`#${buildItemsTableId(parentItem.id)} h5`).then(($e) => {
+ children.sort((a, b) => (a.name > b.name ? 1 : -1));
+ for (let idx = 0; idx < children.length; idx += 1) {
+ expect($e[idx].innerText).to.eq(children[idx].name);
+ }
+ });
+
+ // change ordering
+ cy.get(SORTING_ORDERING_SELECTOR_ASC).click();
+ cy.get(SORTING_ORDERING_SELECTOR_DESC).should('be.visible');
+ cy.get(`#${buildItemsTableId(parentItem.id)} h5`).then(($e) => {
+ children.reverse();
+ for (let idx = 0; idx < children.length; idx += 1) {
+ expect($e[idx].innerText).to.eq(children[idx].name);
+ }
+ });
+ });
});
-it('Layout mode', () => {
+it('Folder Layout mode', () => {
cy.setUpApi({
items: [parentItem, child1],
});
diff --git a/src/components/item/FolderContent.tsx b/src/components/item/FolderContent.tsx
index 0cf75cd21..46bd5cdb4 100644
--- a/src/components/item/FolderContent.tsx
+++ b/src/components/item/FolderContent.tsx
@@ -25,7 +25,8 @@ import ItemsTable from '../main/ItemsTable';
import NewItemButton from '../main/NewItemButton';
import { DesktopMap } from '../map/DesktopMap';
import SortingSelect from '../table/SortingSelect';
-import { SortingOptionsForFolder, useSorting } from '../table/useSorting';
+import { SortingOptionsForFolder } from '../table/types';
+import { useSorting } from '../table/useSorting';
import FolderDescription from './FolderDescription';
import { useItemSearch } from './ItemSearch';
import ModeButton from './header/ModeButton';
@@ -87,6 +88,7 @@ const FolderContent = ({ item }: { item: PackedItem }): JSX.Element => {
{itemSearch.input}
diff --git a/src/components/main/NewItemButton.tsx b/src/components/main/NewItemButton.tsx
index 6d48e4f85..f08ac5045 100644
--- a/src/components/main/NewItemButton.tsx
+++ b/src/components/main/NewItemButton.tsx
@@ -1,6 +1,7 @@
import { useState } from 'react';
import { Add as AddIcon } from '@mui/icons-material';
+import { ButtonProps } from '@mui/material';
import { DiscriminatedItem } from '@graasp/sdk';
import { Button } from '@graasp/ui';
@@ -12,9 +13,13 @@ import NewItemModal from './NewItemModal';
type Props = {
previousItemId?: DiscriminatedItem['id'];
+ size?: ButtonProps['size'];
};
-const NewItemButton = ({ previousItemId }: Props): JSX.Element => {
+const NewItemButton = ({
+ previousItemId,
+ size = 'small',
+}: Props): JSX.Element => {
const [open, setOpen] = useState(false);
const { t: translateBuilder } = useBuilderTranslation();
@@ -34,7 +39,7 @@ const NewItemButton = ({ previousItemId }: Props): JSX.Element => {
color="primary"
aria-label="add"
startIcon={}
- size="small"
+ size={size}
>
{translateBuilder(BUILDER.NEW_ITEM_BUTTON)}
diff --git a/src/components/pages/BookmarkedItemsScreen.tsx b/src/components/pages/BookmarkedItemsScreen.tsx
index 06672fe37..78e97406a 100644
--- a/src/components/pages/BookmarkedItemsScreen.tsx
+++ b/src/components/pages/BookmarkedItemsScreen.tsx
@@ -20,11 +20,8 @@ import { useItemSearch } from '../item/ItemSearch';
import ModeButton from '../item/header/ModeButton';
import ItemsTable from '../main/ItemsTable';
import SortingSelect from '../table/SortingSelect';
-import {
- SortingOptions,
- useSorting,
- useTranslatedSortingOptions,
-} from '../table/useSorting';
+import { SortingOptions } from '../table/types';
+import { useSorting, useTranslatedSortingOptions } from '../table/useSorting';
const BookmarkedItems = (): JSX.Element | null => {
const { t: translateBuilder } = useBuilderTranslation();
diff --git a/src/components/pages/HomeScreen.tsx b/src/components/pages/HomeScreen.tsx
index 575e8e4ec..fa3299530 100644
--- a/src/components/pages/HomeScreen.tsx
+++ b/src/components/pages/HomeScreen.tsx
@@ -33,7 +33,8 @@ import NewItemButton from '../main/NewItemButton';
import { DesktopMap } from '../map/DesktopMap';
import ShowOnlyMeButton from '../table/ShowOnlyMeButton';
import SortingSelect from '../table/SortingSelect';
-import { SortingOptions, useSorting } from '../table/useSorting';
+import { SortingOptions } from '../table/types';
+import { useSorting } from '../table/useSorting';
const HomeScreen = (): JSX.Element => {
const { t: translateBuilder } = useBuilderTranslation();
@@ -232,7 +233,7 @@ const HomeScreen = (): JSX.Element => {
spacing={1}
>
{itemSearch.input}
-
+
diff --git a/src/components/pages/PublishedItemsScreen.tsx b/src/components/pages/PublishedItemsScreen.tsx
index 33a9961ba..ff9aba080 100644
--- a/src/components/pages/PublishedItemsScreen.tsx
+++ b/src/components/pages/PublishedItemsScreen.tsx
@@ -21,11 +21,8 @@ import { useItemSearch } from '../item/ItemSearch';
import ModeButton from '../item/header/ModeButton';
import ItemsTable from '../main/ItemsTable';
import SortingSelect from '../table/SortingSelect';
-import {
- SortingOptions,
- useSorting,
- useTranslatedSortingOptions,
-} from '../table/useSorting';
+import { SortingOptions } from '../table/types';
+import { useSorting, useTranslatedSortingOptions } from '../table/useSorting';
const PublishedItemsScreen = (): JSX.Element | null => {
const { t: translateBuilder } = useBuilderTranslation();
diff --git a/src/components/pages/RecycledItemsScreen.tsx b/src/components/pages/RecycledItemsScreen.tsx
index 962660654..5f082f8f8 100644
--- a/src/components/pages/RecycledItemsScreen.tsx
+++ b/src/components/pages/RecycledItemsScreen.tsx
@@ -22,11 +22,8 @@ import { useItemSearch } from '../item/ItemSearch';
import ModeButton from '../item/header/ModeButton';
import ItemCard from '../table/ItemCard';
import SortingSelect from '../table/SortingSelect';
-import {
- SortingOptions,
- useSorting,
- useTranslatedSortingOptions,
-} from '../table/useSorting';
+import { SortingOptions } from '../table/types';
+import { useSorting, useTranslatedSortingOptions } from '../table/useSorting';
const RecycledItemsScreen = (): JSX.Element | null => {
const { t: translateBuilder } = useBuilderTranslation();
diff --git a/src/components/table/SortingSelect.tsx b/src/components/table/SortingSelect.tsx
index 8bfe138d7..9fdc78608 100644
--- a/src/components/table/SortingSelect.tsx
+++ b/src/components/table/SortingSelect.tsx
@@ -14,10 +14,11 @@ import {
import { ArrowDownNarrowWide, ArrowUpWideNarrow } from 'lucide-react';
import { useBuilderTranslation } from '@/config/i18n';
+import { SORTING_SELECT_SELECTOR_TEST_ID } from '@/config/selectors';
import { Ordering } from '@/enums';
import { BUILDER } from '@/langs/constants';
-import { AllSortingOptions, SortingOptions } from './useSorting';
+import { AllSortingOptions, SortingOptions } from './types';
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
@@ -63,6 +64,7 @@ export const SortingSelect = ({
{label}