diff --git a/cypress/integration/item/copy/gridCopyItem.spec.js b/cypress/integration/item/copy/gridCopyItem.spec.js index 0d04bf54b..c225f3127 100644 --- a/cypress/integration/item/copy/gridCopyItem.spec.js +++ b/cypress/integration/item/copy/gridCopyItem.spec.js @@ -4,13 +4,13 @@ import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; import { buildItemCard, buildItemMenu, - ITEM_MENU_BUTTON_CLASS, + buildItemMenuButtonId, ITEM_MENU_COPY_BUTTON_CLASS, } from '../../../../src/config/selectors'; import { SAMPLE_ITEMS } from '../../../fixtures/items'; const copyItem = ({ id, toItemPath }) => { - const menuSelector = `#${buildItemCard(id)} .${ITEM_MENU_BUTTON_CLASS}`; + const menuSelector = `#${buildItemMenuButtonId(id)}`; cy.get(menuSelector).click(); cy.get(`#${buildItemMenu(id)} .${ITEM_MENU_COPY_BUTTON_CLASS}`).click(); cy.fillTreeModal(toItemPath); diff --git a/cypress/integration/item/copy/listCopyItem.spec.js b/cypress/integration/item/copy/listCopyItem.spec.js index 710219ebb..725ef8053 100644 --- a/cypress/integration/item/copy/listCopyItem.spec.js +++ b/cypress/integration/item/copy/listCopyItem.spec.js @@ -6,18 +6,16 @@ import { ITEM_LAYOUT_MODES } from '../../../../src/enums'; import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; import { - buildItemsTableRowId, + buildItemsTableRowIdAttribute, buildItemMenu, - ITEM_MENU_BUTTON_CLASS, ITEM_MENU_COPY_BUTTON_CLASS, + buildItemMenuButtonId, } from '../../../../src/config/selectors'; import { SAMPLE_ITEMS } from '../../../fixtures/items'; import { TABLE_ITEM_RENDER_TIME } from '../../../support/constants'; const copyItem = ({ id, toItemPath }) => { - const menuSelector = `#${buildItemsTableRowId( - id, - )} .${ITEM_MENU_BUTTON_CLASS}`; + const menuSelector = `#${buildItemMenuButtonId(id)}`; cy.wait(TABLE_ITEM_RENDER_TIME); cy.get(menuSelector).click(); cy.get(`#${buildItemMenu(id)} .${ITEM_MENU_COPY_BUTTON_CLASS}`).click(); @@ -38,11 +36,11 @@ describe('Copy Item in List', () => { copyItem({ id: copyItemId, toItemPath }); cy.wait('@copyItems').then(({ response: { body } }) => { - cy.get(`#${buildItemsTableRowId(copyItemId)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(copyItemId)).should('exist'); // check in new parent cy.goToItemInList(toItem); - cy.get(`#${buildItemsTableRowId(body[0].id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(body[0].id)).should('exist'); }); }); @@ -62,11 +60,11 @@ describe('Copy Item in List', () => { copyItem({ id: copyItemId, toItemPath }); cy.wait('@copyItems').then(({ response: { body } }) => { - cy.get(`#${buildItemsTableRowId(copyItemId)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(copyItemId)).should('exist'); // check in new parent cy.goToItemInList(toItem); - cy.get(`#${buildItemsTableRowId(body[0].id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(body[0].id)).should('exist'); }); }); @@ -85,11 +83,11 @@ describe('Copy Item in List', () => { copyItem({ id: copyItemId, toItemPath: ROOT_ID }); cy.wait('@copyItems').then(({ response: { body } }) => { - cy.get(`#${buildItemsTableRowId(copyItemId)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(copyItemId)).should('exist'); // check in new parent cy.goToHome(); - cy.get(`#${buildItemsTableRowId(body[0].id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(body[0].id)).should('exist'); }); }); @@ -111,8 +109,8 @@ describe('Copy Item in List', () => { cy.wait('@copyItems').then(({ response: { body } }) => { // check item is still existing in parent - cy.get(`#${buildItemsTableRowId(copyItemId)}`).should('exist'); - cy.get(`#${buildItemsTableRowId(body[0].id)}`).should('not.exist'); + cy.get(buildItemsTableRowIdAttribute(copyItemId)).should('exist'); + cy.get(buildItemsTableRowIdAttribute(body[0].id)).should('not.exist'); }); }); }); diff --git a/cypress/integration/item/copy/listCopyMultiple.spec.js b/cypress/integration/item/copy/listCopyMultiple.spec.js index 759b1446d..260c04eaf 100644 --- a/cypress/integration/item/copy/listCopyMultiple.spec.js +++ b/cypress/integration/item/copy/listCopyMultiple.spec.js @@ -6,27 +6,23 @@ import { ITEM_LAYOUT_MODES } from '../../../../src/enums'; import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; import { - buildItemsTableRowId, - ITEMS_TABLE_ROW_CHECKBOX_CLASS, + buildItemsTableRowIdAttribute, ITEMS_TABLE_COPY_SELECTED_ITEMS_ID, } from '../../../../src/config/selectors'; import { SAMPLE_ITEMS } from '../../../fixtures/items'; import { TABLE_ITEM_RENDER_TIME } from '../../../support/constants'; - - + const copyItems = ({ itemIds, toItemPath }) => { // check selected ids itemIds.forEach((id) => { cy.wait(TABLE_ITEM_RENDER_TIME); - cy.get( - `#${buildItemsTableRowId(id)} .${ITEMS_TABLE_ROW_CHECKBOX_CLASS}`, - ).click(); + cy.get(`${buildItemsTableRowIdAttribute(id)} input`).click(); }); cy.wait(TABLE_ITEM_RENDER_TIME); cy.get(`#${ITEMS_TABLE_COPY_SELECTED_ITEMS_ID}`).click(); cy.fillTreeModal(toItemPath); -}; +}; describe('Copy items in List', () => { it('Copy items on Home', () => { @@ -34,7 +30,7 @@ describe('Copy items in List', () => { cy.visit(HOME_PATH); if (DEFAULT_ITEM_LAYOUT_MODE !== ITEM_LAYOUT_MODES.LIST) { - cy.switchMode(ITEM_LAYOUT_MODES.LIST); + cy.switchMode(ITEM_LAYOUT_MODES.LIST); } const itemIds = [SAMPLE_ITEMS.items[0].id, SAMPLE_ITEMS.items[5].id]; @@ -42,14 +38,14 @@ describe('Copy items in List', () => { copyItems({ itemIds, toItemPath }); cy.wait('@copyItems').then(({ response: { body } }) => { - itemIds.forEach(id =>{ - cy.get(`#${buildItemsTableRowId(id)}`).should('exist'); + itemIds.forEach((id) => { + cy.get(`${buildItemsTableRowIdAttribute(id)}`).should('exist'); }); // check in new parent cy.goToItemInList(toItem); - body.forEach(item => { - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + body.forEach((item) => { + cy.get(`${buildItemsTableRowIdAttribute(item.id)}`).should('exist'); }); }); }); @@ -70,14 +66,14 @@ describe('Copy items in List', () => { copyItems({ itemIds, toItemPath }); cy.wait('@copyItems').then(({ response: { body } }) => { - itemIds.forEach(id => { - cy.get(`#${buildItemsTableRowId(id)}`).should('exist'); + itemIds.forEach((id) => { + cy.get(`${buildItemsTableRowIdAttribute(id)}`).should('exist'); }); // check in new parent cy.goToItemInList(toItem); - body.forEach(item => { - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + body.forEach((item) => { + cy.get(`${buildItemsTableRowIdAttribute(item.id)}`).should('exist'); }); }); }); @@ -94,17 +90,17 @@ describe('Copy items in List', () => { // copy const itemIds = [SAMPLE_ITEMS.items[2].id, SAMPLE_ITEMS.items[4].id]; - copyItems({itemIds, toItemPath: ROOT_ID }); + copyItems({ itemIds, toItemPath: ROOT_ID }); cy.wait('@copyItems').then(({ response: { body } }) => { - itemIds.forEach(id => { - cy.get(`#${buildItemsTableRowId(id)}`).should('exist'); + itemIds.forEach((id) => { + cy.get(`${buildItemsTableRowIdAttribute(id)}`).should('exist'); }); // check in new parent cy.goToHome(); - body.forEach(item => { - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + body.forEach((item) => { + cy.get(`${buildItemsTableRowIdAttribute(item.id)}`).should('exist'); }); }); }); @@ -112,7 +108,7 @@ describe('Copy items in List', () => { describe('Error handling', () => { it('error while copying item does not create in interface', () => { cy.setUpApi({ ...SAMPLE_ITEMS, copyItemError: true }); - const { id :start } = SAMPLE_ITEMS.items[0]; + const { id: start } = SAMPLE_ITEMS.items[0]; // go to children item cy.visit(buildItemPath(start)); @@ -127,11 +123,13 @@ describe('Copy items in List', () => { cy.wait('@copyItems').then(({ response: { body } }) => { // check item is still existing in parent - itemIds.forEach(id => { - cy.get(`#${buildItemsTableRowId(id)}`).should('exist'); + itemIds.forEach((id) => { + cy.get(`${buildItemsTableRowIdAttribute(id)}`).should('exist'); }); - body.forEach(item => { - cy.get(`#${buildItemsTableRowId(item.id)}`).should('not.exist'); + body.forEach((item) => { + cy.get(`${buildItemsTableRowIdAttribute(item.id)}`).should( + 'not.exist', + ); }); }); }); diff --git a/cypress/integration/item/create/createFolder.spec.js b/cypress/integration/item/create/createFolder.spec.js index e568dc917..a0ac6ccdb 100644 --- a/cypress/integration/item/create/createFolder.spec.js +++ b/cypress/integration/item/create/createFolder.spec.js @@ -1,7 +1,7 @@ import { DEFAULT_ITEM_LAYOUT_MODE } from '../../../../src/config/constants'; import { ITEM_LAYOUT_MODES } from '../../../../src/enums'; import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; -import { buildItemsTableRowId } from '../../../../src/config/selectors'; +import { buildItemsTableRowIdAttribute } from '../../../../src/config/selectors'; import { CREATED_ITEM, SAMPLE_ITEMS } from '../../../fixtures/items'; import { CREATE_ITEM_PAUSE } from '../../../support/constants'; import { createItem } from './utils'; @@ -95,7 +95,7 @@ describe('Create Folder', () => { cy.wait('@postItem').then(({ response: { body } }) => { // check item is created and displayed - cy.get(`#${buildItemsTableRowId(body.id)}`).should('not.exist'); + cy.get(buildItemsTableRowIdAttribute(body.id)).should('not.exist'); }); }); }); diff --git a/cypress/integration/item/create/createShortcut.spec.js b/cypress/integration/item/create/createShortcut.spec.js index a100ffe83..53ca7aaf6 100644 --- a/cypress/integration/item/create/createShortcut.spec.js +++ b/cypress/integration/item/create/createShortcut.spec.js @@ -3,10 +3,8 @@ import { ITEM_LAYOUT_MODES, ITEM_TYPES } from '../../../../src/enums'; import { ROOT_ID } from '../../../../src/config/constants'; import { HOME_PATH } from '../../../../src/config/paths'; import { - buildItemCard, buildItemMenu, - buildItemsTableRowId, - ITEM_MENU_BUTTON_CLASS, + buildItemMenuButtonId, ITEM_MENU_SHORTCUT_BUTTON_CLASS, } from '../../../../src/config/selectors'; import { buildShortcutExtra } from '../../../../src/utils/itemExtra'; @@ -19,15 +17,13 @@ const createShortcut = ({ id, toItemPath }) => { }; const createShortcutInGrid = ({ id, toItemPath }) => { - const menuSelector = `#${buildItemCard(id)} .${ITEM_MENU_BUTTON_CLASS}`; + const menuSelector = `#${buildItemMenuButtonId(id)}`; cy.get(menuSelector).click(); createShortcut({ id, toItemPath }); }; const createShortcutInList = ({ id, toItemPath }) => { - const menuSelector = `#${buildItemsTableRowId( - id, - )} .${ITEM_MENU_BUTTON_CLASS}`; + const menuSelector = `#${buildItemMenuButtonId(id)}`; cy.get(menuSelector).click(); createShortcut({ id, toItemPath }); }; diff --git a/cypress/integration/item/delete/listDeleteItem.spec.js b/cypress/integration/item/delete/listDeleteItem.spec.js index 1cce1b731..8a05ae1c4 100644 --- a/cypress/integration/item/delete/listDeleteItem.spec.js +++ b/cypress/integration/item/delete/listDeleteItem.spec.js @@ -2,16 +2,16 @@ import { DEFAULT_ITEM_LAYOUT_MODE } from '../../../../src/config/constants'; import { ITEM_LAYOUT_MODES } from '../../../../src/enums'; import { RECYCLE_BIN_PATH } from '../../../../src/config/paths'; import { - buildItemsTableRowId, + buildDeleteButtonId, + buildItemsTableRowIdAttribute, CONFIRM_DELETE_BUTTON_ID, - ITEM_DELETE_BUTTON_CLASS, } from '../../../../src/config/selectors'; import { DATABASE_WITH_RECYCLE_BIN } from '../../../fixtures/recycleBin'; import { TABLE_ITEM_RENDER_TIME } from '../../../support/constants'; const deleteItem = (id) => { cy.wait(TABLE_ITEM_RENDER_TIME); - cy.get(`#${buildItemsTableRowId(id)} .${ITEM_DELETE_BUTTON_CLASS}`).click(); + cy.get(`#${buildDeleteButtonId(id)}`).click(); cy.get(`#${CONFIRM_DELETE_BUTTON_ID}`).click(); }; @@ -51,7 +51,7 @@ describe('Delete Item in List', () => { cy.wait('@deleteItem').then(() => { // check item is still displayed - cy.get(`#${buildItemsTableRowId(id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(id)).should('exist'); }); }); }); diff --git a/cypress/integration/item/delete/listDeleteItems.spec.js b/cypress/integration/item/delete/listDeleteItems.spec.js index 7cb8e148c..9fe23f284 100644 --- a/cypress/integration/item/delete/listDeleteItems.spec.js +++ b/cypress/integration/item/delete/listDeleteItems.spec.js @@ -2,10 +2,9 @@ import { DEFAULT_ITEM_LAYOUT_MODE } from '../../../../src/config/constants'; import { ITEM_LAYOUT_MODES } from '../../../../src/enums'; import { RECYCLE_BIN_PATH } from '../../../../src/config/paths'; import { - buildItemsTableRowId, + buildItemsTableRowIdAttribute, CONFIRM_DELETE_BUTTON_ID, ITEMS_TABLE_DELETE_SELECTED_ITEMS_ID, - ITEMS_TABLE_ROW_CHECKBOX_CLASS, } from '../../../../src/config/selectors'; import { DATABASE_WITH_RECYCLE_BIN } from '../../../fixtures/recycleBin'; import { TABLE_ITEM_RENDER_TIME } from '../../../support/constants'; @@ -14,9 +13,7 @@ const deleteItems = (itemIds) => { // check selected ids itemIds.forEach((id) => { cy.wait(TABLE_ITEM_RENDER_TIME); - cy.get( - `#${buildItemsTableRowId(id)} .${ITEMS_TABLE_ROW_CHECKBOX_CLASS}`, - ).click(); + cy.get(`${buildItemsTableRowIdAttribute(id)} .ag-checkbox-input`).click(); }); cy.get(`#${ITEMS_TABLE_DELETE_SELECTED_ITEMS_ID}`).click(); @@ -63,7 +60,7 @@ describe('Delete Items in List', () => { cy.wait('@deleteItems').then(() => { // check items are still displayed for (const id of itemIds) { - cy.get(`#${buildItemsTableRowId(id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(id)).should('exist'); } }); }); diff --git a/cypress/integration/item/edit/utils.js b/cypress/integration/item/edit/utils.js index a230427c4..4944c0482 100644 --- a/cypress/integration/item/edit/utils.js +++ b/cypress/integration/item/edit/utils.js @@ -1,9 +1,6 @@ import { ITEM_TYPES, ITEM_LAYOUT_MODES } from '../../../../src/enums'; import { DEFAULT_ITEM_LAYOUT_MODE } from '../../../../src/config/constants'; import { - buildItemCard, - buildItemsTableRowId, - EDIT_ITEM_BUTTON_CLASS, TEXT_EDITOR_CLASS, buildSaveButtonId, buildEditButtonId, @@ -15,13 +12,13 @@ export const editItem = (payload, mode = DEFAULT_ITEM_LAYOUT_MODE) => { const { id, type } = payload; switch (mode) { case ITEM_LAYOUT_MODES.GRID: { - const button = `#${buildItemCard(id)} .${EDIT_ITEM_BUTTON_CLASS}`; + const button = `#${buildEditButtonId(id)}`; cy.get(button).click(); break; } case ITEM_LAYOUT_MODES.LIST: default: { - cy.get(`#${buildItemsTableRowId(id)} .${EDIT_ITEM_BUTTON_CLASS}`).click(); + cy.get(`#${buildEditButtonId(id)}`).click(); } } diff --git a/cypress/integration/item/favorite/favoriteItem.spec.js b/cypress/integration/item/favorite/favoriteItem.spec.js index 1b3417527..aca75985c 100644 --- a/cypress/integration/item/favorite/favoriteItem.spec.js +++ b/cypress/integration/item/favorite/favoriteItem.spec.js @@ -1,7 +1,7 @@ import { SAMPLE_ITEMS } from '../../../fixtures/items'; import { FAVORITE_ITEMS_PATH, HOME_PATH } from '../../../../src/config/paths'; import { - buildItemsTableRowId, + buildItemsTableRowIdAttribute, FAVORITE_ITEM_BUTTON_CLASS, FAVORITE_ITEMS_ERROR_ALERT_ID, CREATE_ITEM_BUTTON_ID, @@ -12,7 +12,7 @@ import { TABLE_ITEM_RENDER_TIME } from '../../../support/constants'; const toggleFavoriteButton = (itemId) => { cy.wait(TABLE_ITEM_RENDER_TIME); cy.get( - `#${buildItemsTableRowId(itemId)} .${FAVORITE_ITEM_BUTTON_CLASS}`, + `${buildItemsTableRowIdAttribute(itemId)} .${FAVORITE_ITEM_BUTTON_CLASS}`, ).click(); }; @@ -70,7 +70,7 @@ describe('Favorite Item', () => { const itemId = favoriteItems[0]; - cy.get(`#${buildItemsTableRowId(itemId)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(itemId)).should('exist'); }); }); diff --git a/cypress/integration/item/flag/flagItem.spec.js b/cypress/integration/item/flag/flagItem.spec.js index c172410f9..7f489cbd0 100644 --- a/cypress/integration/item/flag/flagItem.spec.js +++ b/cypress/integration/item/flag/flagItem.spec.js @@ -3,18 +3,16 @@ import { HOME_PATH } from '../../../../src/config/paths'; import { buildFlagListItemId, buildItemMenu, - buildItemsTableRowId, + buildItemMenuButtonId, FLAG_ITEM_BUTTON_ID, - ITEM_MENU_BUTTON_CLASS, ITEM_MENU_FLAG_BUTTON_CLASS, } from '../../../../src/config/selectors'; import { SAMPLE_FLAGS } from '../../../fixtures/flags'; +import { TABLE_ITEM_RENDER_TIME } from '../../../support/constants'; const openFlagItemModal = (itemId) => { - const menuSelector = `#${buildItemsTableRowId( - itemId, - )} .${ITEM_MENU_BUTTON_CLASS}`; - + const menuSelector = `#${buildItemMenuButtonId(itemId)}`; + cy.wait(TABLE_ITEM_RENDER_TIME); cy.get(menuSelector).click(); const menuFlagButton = cy.get( diff --git a/cypress/integration/item/move/gridMoveItem.spec.js b/cypress/integration/item/move/gridMoveItem.spec.js index c2355e864..3f1ee33ba 100644 --- a/cypress/integration/item/move/gridMoveItem.spec.js +++ b/cypress/integration/item/move/gridMoveItem.spec.js @@ -4,15 +4,13 @@ import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; import { buildItemCard, buildItemMenu, - ITEM_MENU_BUTTON_CLASS, + buildItemMenuButtonId, ITEM_MENU_MOVE_BUTTON_CLASS, } from '../../../../src/config/selectors'; import { SAMPLE_ITEMS } from '../../../fixtures/items'; const moveItem = ({ id: movedItemId, toItemPath }) => { - const menuSelector = `#${buildItemCard( - movedItemId, - )} .${ITEM_MENU_BUTTON_CLASS}`; + const menuSelector = `#${buildItemMenuButtonId(movedItemId)}`; cy.get(menuSelector).click(); cy.get( `#${buildItemMenu(movedItemId)} .${ITEM_MENU_MOVE_BUTTON_CLASS}`, diff --git a/cypress/integration/item/move/listMoveItem.spec.js b/cypress/integration/item/move/listMoveItem.spec.js index a37339b87..fefe8497d 100644 --- a/cypress/integration/item/move/listMoveItem.spec.js +++ b/cypress/integration/item/move/listMoveItem.spec.js @@ -5,18 +5,16 @@ import { import { ITEM_LAYOUT_MODES } from '../../../../src/enums'; import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; import { - buildItemsTableRowId, + buildItemsTableRowIdAttribute, buildItemMenu, - ITEM_MENU_BUTTON_CLASS, ITEM_MENU_MOVE_BUTTON_CLASS, + buildItemMenuButtonId, } from '../../../../src/config/selectors'; import { SAMPLE_ITEMS } from '../../../fixtures/items'; import { TABLE_ITEM_RENDER_TIME } from '../../../support/constants'; const moveItem = ({ id: movedItemId, toItemPath }) => { - const menuSelector = `#${buildItemsTableRowId( - movedItemId, - )} .${ITEM_MENU_BUTTON_CLASS}`; + const menuSelector = `#${buildItemMenuButtonId(movedItemId)}`; cy.wait(TABLE_ITEM_RENDER_TIME); cy.get(menuSelector).click(); cy.get( @@ -109,7 +107,7 @@ describe('Move Item in List', () => { cy.wait('@moveItems').then(() => { // check item is still there - cy.get(`#${buildItemsTableRowId(movedItem)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(movedItem)).should('exist'); }); }); }); diff --git a/cypress/integration/item/move/listMoveMultiple.spec.js b/cypress/integration/item/move/listMoveMultiple.spec.js index 042e3ef90..01247683e 100644 --- a/cypress/integration/item/move/listMoveMultiple.spec.js +++ b/cypress/integration/item/move/listMoveMultiple.spec.js @@ -1,31 +1,28 @@ import { - ROOT_ID, - DEFAULT_ITEM_LAYOUT_MODE, - } from '../../../../src/config/constants'; - import { ITEM_LAYOUT_MODES } from '../../../../src/enums'; - import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; - import { - buildItemsTableRowId, - ITEMS_TABLE_ROW_CHECKBOX_CLASS, - ITEMS_TABLE_MOVE_SELECTED_ITEMS_ID - } from '../../../../src/config/selectors'; - import { SAMPLE_ITEMS } from '../../../fixtures/items'; - import { TABLE_ITEM_RENDER_TIME } from '../../../support/constants'; - + ROOT_ID, + DEFAULT_ITEM_LAYOUT_MODE, +} from '../../../../src/config/constants'; +import { ITEM_LAYOUT_MODES } from '../../../../src/enums'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemsTableRowIdAttribute, + ITEMS_TABLE_MOVE_SELECTED_ITEMS_ID, +} from '../../../../src/config/selectors'; +import { SAMPLE_ITEMS } from '../../../fixtures/items'; +import { TABLE_ITEM_RENDER_TIME } from '../../../support/constants'; + const moveItems = ({ itemIds, toItemPath }) => { // check selected ids itemIds.forEach((id) => { cy.wait(TABLE_ITEM_RENDER_TIME); - cy.get( - `#${buildItemsTableRowId(id)} .${ITEMS_TABLE_ROW_CHECKBOX_CLASS}`, - ).click(); + cy.get(`${buildItemsTableRowIdAttribute(id)} input`).click(); }); cy.wait(TABLE_ITEM_RENDER_TIME); cy.get(`#${ITEMS_TABLE_MOVE_SELECTED_ITEMS_ID}`).click(); cy.fillTreeModal(toItemPath); }; - + describe('Move Items in List', () => { it('Move items on Home', () => { cy.setUpApi(SAMPLE_ITEMS); @@ -34,22 +31,22 @@ describe('Move Items in List', () => { if (DEFAULT_ITEM_LAYOUT_MODE !== ITEM_LAYOUT_MODES.LIST) { cy.switchMode(ITEM_LAYOUT_MODES.LIST); } - + // move const itemIds = [SAMPLE_ITEMS.items[0].id, SAMPLE_ITEMS.items[5].id]; const { id: toItem, path: toItemPath } = SAMPLE_ITEMS.items[1]; moveItems({ itemIds, toItemPath }); - + cy.wait('@moveItems').then(({ request: { url, body } }) => { - expect(body.parentId).to.equal(toItem); - itemIds.forEach(movedItem => expect(url).to.contain(movedItem)); + expect(body.parentId).to.equal(toItem); + itemIds.forEach((movedItem) => expect(url).to.contain(movedItem)); - itemIds.forEach(id => { - cy.get(`#${buildItemsTableRowId(id)}`).should('not.exist'); - }); + itemIds.forEach((id) => { + cy.get(`${buildItemsTableRowIdAttribute(id)}`).should('not.exist'); + }); }); }); - + it('Move items in item', () => { cy.setUpApi(SAMPLE_ITEMS); const { id: start } = SAMPLE_ITEMS.items[0]; @@ -68,9 +65,9 @@ describe('Move Items in List', () => { cy.wait('@moveItems').then(({ request: { body, url } }) => { expect(body.parentId).to.equal(toItem); - itemIds.forEach(movedItem => expect(url).to.contain(movedItem)); - itemIds.forEach(id => { - cy.get(`#${buildItemsTableRowId(id)}`).should('not.exist'); + itemIds.forEach((movedItem) => expect(url).to.contain(movedItem)); + itemIds.forEach((id) => { + cy.get(`${buildItemsTableRowIdAttribute(id)}`).should('not.exist'); }); }); }); @@ -93,14 +90,14 @@ describe('Move Items in List', () => { cy.wait('@moveItems').then(({ request: { body, url } }) => { expect(body.parentId).to.equal(undefined); - itemIds.forEach(movedItem => expect(url).to.contain(movedItem)); - - itemIds.forEach(id => { - cy.get(`#${buildItemsTableRowId(id)}`).should('not.exist'); + itemIds.forEach((movedItem) => expect(url).to.contain(movedItem)); + + itemIds.forEach((id) => { + cy.get(`${buildItemsTableRowIdAttribute(id)}`).should('not.exist'); }); }); }); - + describe('Error handling', () => { it('error while moving items does not create in interface', () => { cy.setUpApi({ ...SAMPLE_ITEMS, moveItemsError: true }); @@ -120,11 +117,10 @@ describe('Move Items in List', () => { cy.wait('@moveItems').then(() => { // check item is still there - itemIds.forEach(id => { - cy.get(`#${buildItemsTableRowId(id)}`).should('exist'); + itemIds.forEach((id) => { + cy.get(`${buildItemsTableRowIdAttribute(id)}`).should('exist'); }); }); }); }); }); - \ No newline at end of file diff --git a/cypress/integration/item/order/reorderItems.spec.js b/cypress/integration/item/order/reorderItems.spec.js index 6563a3d97..ab2f1b9e9 100644 --- a/cypress/integration/item/order/reorderItems.spec.js +++ b/cypress/integration/item/order/reorderItems.spec.js @@ -1,16 +1,13 @@ import { buildItemPath } from '../../../../src/config/paths'; -import { ITEM_REORDER_ITEMS, ORDERED_ITEMS } from '../../../fixtures/items'; -import { - buildItemsTableRowId, - ITEMS_TABLE_BODY, -} from '../../../../src/config/selectors'; +import { ITEM_REORDER_ITEMS } from '../../../fixtures/items'; +import { buildRowDraggerId } from '../../../../src/config/selectors'; import { TABLE_ITEM_RENDER_TIME, ROW_HEIGHT } from '../../../support/constants'; const reorderAndCheckItem = (id, currentPosition, newPosition) => { - const childEl = `#${buildItemsTableRowId(id)}`; + const dragIcon = `#${buildRowDraggerId(id)}`; cy.wait(TABLE_ITEM_RENDER_TIME); - cy.dragAndDrop(childEl, 0, (newPosition - currentPosition) * ROW_HEIGHT); + cy.dragAndDrop(dragIcon, 0, (newPosition - currentPosition) * ROW_HEIGHT); cy.wait('@editItem').then( ({ @@ -59,23 +56,4 @@ describe('Order Items', () => { reorderAndCheckItem(childId, currentPosition, newPosition); }); }); - - describe('Check Order', () => { - it('check item order in folder with non-existing item in ordering', () => { - cy.setUpApi({ - items: [ORDERED_ITEMS.parent, ...ORDERED_ITEMS.children], - }); - - cy.visit(buildItemPath(ORDERED_ITEMS.parent.id)); - - const tableBody = `#${ITEMS_TABLE_BODY}`; - - ORDERED_ITEMS.existingChildrenOrder.forEach((id, index) => { - cy.get(tableBody) - .children() - .eq(index) - .should('have.id', buildItemsTableRowId(id)); - }); - }); - }); }); diff --git a/cypress/integration/item/search/listItemSearch.spec.js b/cypress/integration/item/search/listItemSearch.spec.js index 97bfb767f..f51026dc5 100644 --- a/cypress/integration/item/search/listItemSearch.spec.js +++ b/cypress/integration/item/search/listItemSearch.spec.js @@ -1,6 +1,6 @@ import { buildItemPath } from '../../../../src/config/paths'; import { - buildItemsTableRowId, + buildItemsTableRowIdAttribute, ITEM_SEARCH_INPUT_ID, } from '../../../../src/config/selectors'; import { SAMPLE_ITEMS } from '../../../fixtures/items'; @@ -22,7 +22,7 @@ describe('Search Item in Table', () => { cy.wait('@getChildren').then(({ response: { body } }) => { // check item is created and displayed for (const item of body) { - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(item.id)).should('exist'); } }); @@ -31,8 +31,8 @@ describe('Search Item in Table', () => { .type(child3.name) .then(() => { // should find child3 but not child4 - cy.get(`#${buildItemsTableRowId(child3.id)}`).should('exist'); - cy.get(`#${buildItemsTableRowId(child4.id)}`).should('not.exist'); + cy.get(buildItemsTableRowIdAttribute(child3.id)).should('exist'); + cy.get(buildItemsTableRowIdAttribute(child4.id)).should('not.exist'); }); // erase search @@ -40,8 +40,8 @@ describe('Search Item in Table', () => { .clear() .then(() => { // should find all children again - cy.get(`#${buildItemsTableRowId(child3.id)}`).should('exist'); - cy.get(`#${buildItemsTableRowId(child4.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(child3.id)).should('exist'); + cy.get(buildItemsTableRowIdAttribute(child4.id)).should('exist'); }); }); }); diff --git a/cypress/integration/item/view/viewFile.spec.js b/cypress/integration/item/view/viewFile.spec.js index a4c153e1f..5510857ea 100644 --- a/cypress/integration/item/view/viewFile.spec.js +++ b/cypress/integration/item/view/viewFile.spec.js @@ -1,7 +1,7 @@ import { DEFAULT_ITEM_LAYOUT_MODE } from '../../../../src/config/constants'; import { ITEM_LAYOUT_MODES } from '../../../../src/enums'; import { HOME_PATH } from '../../../../src/config/paths'; -import { buildItemsTableRowId } from '../../../../src/config/selectors'; +import { buildItemsTableRowIdAttribute } from '../../../../src/config/selectors'; import { IMAGE_ITEM_DEFAULT, IMAGE_ITEM_S3, @@ -25,7 +25,9 @@ describe('Files', () => { }); it('image', () => { // item is displayed in table - cy.get(`#${buildItemsTableRowId(IMAGE_ITEM_DEFAULT.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(IMAGE_ITEM_DEFAULT.id)).should( + 'exist', + ); // item metadata cy.goToItemInList(IMAGE_ITEM_DEFAULT.id); @@ -34,7 +36,9 @@ describe('Files', () => { it('video', () => { // item is displayed in table - cy.get(`#${buildItemsTableRowId(VIDEO_ITEM_DEFAULT.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(VIDEO_ITEM_DEFAULT.id)).should( + 'exist', + ); // item metadata cy.goToItemInList(VIDEO_ITEM_DEFAULT.id); @@ -43,7 +47,9 @@ describe('Files', () => { it('pdf', () => { // item is displayed in table - cy.get(`#${buildItemsTableRowId(PDF_ITEM_DEFAULT.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(PDF_ITEM_DEFAULT.id)).should( + 'exist', + ); // item metadata cy.goToItemInList(PDF_ITEM_DEFAULT.id); @@ -63,7 +69,7 @@ describe('Files', () => { }); it('image', () => { // item is displayed in table - cy.get(`#${buildItemsTableRowId(IMAGE_ITEM_S3.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(IMAGE_ITEM_S3.id)).should('exist'); // item metadata cy.goToItemInList(IMAGE_ITEM_S3.id); @@ -72,7 +78,7 @@ describe('Files', () => { it('video', () => { // item is displayed in table - cy.get(`#${buildItemsTableRowId(VIDEO_ITEM_S3.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(VIDEO_ITEM_S3.id)).should('exist'); // item metadata cy.goToItemInList(VIDEO_ITEM_S3.id); @@ -81,7 +87,7 @@ describe('Files', () => { it('pdf', () => { // item is displayed in table - cy.get(`#${buildItemsTableRowId(PDF_ITEM_S3.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(PDF_ITEM_S3.id)).should('exist'); // item metadata cy.goToItemInList(PDF_ITEM_S3.id); diff --git a/cypress/integration/item/view/viewFolder.spec.js b/cypress/integration/item/view/viewFolder.spec.js index 5fc195e7f..1b3821f89 100644 --- a/cypress/integration/item/view/viewFolder.spec.js +++ b/cypress/integration/item/view/viewFolder.spec.js @@ -5,14 +5,14 @@ import { import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; import { buildItemCard, - buildItemsTableRowId, + buildItemsTableRowIdAttribute, ITEMS_GRID_ITEMS_PER_PAGE_SELECT_ID, ITEMS_GRID_ITEMS_PER_PAGE_SELECT_LABEL_ID, ITEMS_GRID_NO_ITEM_ID, ITEMS_GRID_PAGINATION_ID, - ITEMS_TABLE_EMPTY_ROW_ID, ITEM_SCREEN_ERROR_ALERT_ID, NAVIGATION_HOME_LINK_ID, + ITEMS_TABLE_ROW, } from '../../../../src/config/selectors'; import { ITEM_LAYOUT_MODES } from '../../../../src/enums'; import { IMAGE_ITEM_DEFAULT, VIDEO_ITEM_S3 } from '../../../fixtures/files'; @@ -195,7 +195,7 @@ describe('View Folder', () => { cy.wait('@getOwnItems').then(({ response: { body } }) => { // check item is created and displayed for (const item of body) { - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(item.id)).should('exist'); } }); @@ -207,7 +207,7 @@ describe('View Folder', () => { cy.wait('@getChildren').then(({ response: { body } }) => { // check item is created and displayed for (const item of body) { - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(item.id)).should('exist'); } }); @@ -216,7 +216,7 @@ describe('View Folder', () => { cy.goToItemInList(childChildId); // expect no children - cy.get(`#${ITEMS_TABLE_EMPTY_ROW_ID}`).should('exist'); + cy.get(ITEMS_TABLE_ROW).should('not.exist'); // return parent with navigation and should display children cy.goToItemWithNavigation(childId); @@ -224,7 +224,7 @@ describe('View Folder', () => { cy.wait('@getChildren').then(({ response: { body } }) => { // check item is created and displayed for (const item of body) { - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(item.id)).should('exist'); } }); }); @@ -247,7 +247,7 @@ describe('View Folder', () => { cy.wait('@getChildren').then(({ response: { body } }) => { // check item is created and displayed for (const item of body) { - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(item.id)).should('exist'); } }); @@ -258,7 +258,7 @@ describe('View Folder', () => { cy.wait('@getOwnItems').then(({ response: { body } }) => { // check item is created and displayed for (const item of body) { - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(item.id)).should('exist'); } }); }); diff --git a/cypress/integration/ws/item.spec.js b/cypress/integration/ws/item.spec.js index 2f939d480..91a1f4869 100644 --- a/cypress/integration/ws/item.spec.js +++ b/cypress/integration/ws/item.spec.js @@ -1,6 +1,6 @@ import { WebSocket } from '@graasp/websockets/test/mock-client'; import { buildItemPath, SHARED_ITEMS_PATH } from '../../../src/config/paths'; -import { buildItemsTableRowId } from '../../../src/config/selectors'; +import { buildItemsTableRowIdAttribute } from '../../../src/config/selectors'; import { SAMPLE_ITEMS } from '../../fixtures/items'; import { CURRENT_USER } from '../../fixtures/members'; import { WEBSOCKETS_DELAY_TIME } from '../../support/constants'; @@ -47,7 +47,7 @@ describe('Websocket interactions', () => { cy.wait(WEBSOCKETS_DELAY_TIME); // assert item is in list - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(item.id)).should('exist'); }); it('displays sharedWith delete update', () => { @@ -59,7 +59,7 @@ describe('Websocket interactions', () => { const item = items[0]; beforeWs(SHARED_ITEMS_PATH, { items }, client); - cy.get(`#${buildItemsTableRowId(item.id)}`).then(() => { + cy.get(buildItemsTableRowIdAttribute(item.id)).then(() => { // send mock sharedItem delete update client.receive({ realm: 'notif', @@ -76,7 +76,7 @@ describe('Websocket interactions', () => { cy.wait(WEBSOCKETS_DELAY_TIME); // assert item is not in list anymore - cy.get(`#${buildItemsTableRowId(item.id)}`).should('not.exist'); + cy.get(buildItemsTableRowIdAttribute(item.id)).should('not.exist'); }); }); @@ -90,7 +90,7 @@ describe('Websocket interactions', () => { cy.wait('@getChildren').then(({ response: { body } }) => { // check item is created and displayed for (const item of body) { - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(item.id)).should('exist'); } }); }); @@ -112,7 +112,7 @@ describe('Websocket interactions', () => { cy.wait(WEBSOCKETS_DELAY_TIME); // assert item is in list - cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + cy.get(buildItemsTableRowIdAttribute(item.id)).should('exist'); }); it('displays childItem delete update', () => { @@ -133,7 +133,7 @@ describe('Websocket interactions', () => { cy.wait(WEBSOCKETS_DELAY_TIME); // assert item is not in list - cy.get(`#${buildItemsTableRowId(item.id)}`).should('not.exist'); + cy.get(buildItemsTableRowIdAttribute(item.id)).should('not.exist'); }); }); }); diff --git a/cypress/support/commands/navigation.js b/cypress/support/commands/navigation.js index 8f473fdf0..454f556dd 100644 --- a/cypress/support/commands/navigation.js +++ b/cypress/support/commands/navigation.js @@ -1,6 +1,6 @@ import { buildItemLink, - buildItemsTableRowId, + buildItemsTableRowIdAttribute, buildNavigationLink, NAVIGATION_HIDDEN_PARENTS_ID, NAVIGATION_HOME_LINK_ID, @@ -14,7 +14,7 @@ Cypress.Commands.add('goToItemInGrid', (id) => { Cypress.Commands.add('goToItemInList', (id) => { cy.wait(NAVIGATE_PAUSE); - cy.get(`#${buildItemsTableRowId(id)}`, { + cy.get(buildItemsTableRowIdAttribute(id), { timeout: WAIT_FOR_ITEM_TABLE_ROW_TIME, }).click(); }); diff --git a/cypress/support/constants.js b/cypress/support/constants.js index 766fc9798..204529e66 100644 --- a/cypress/support/constants.js +++ b/cypress/support/constants.js @@ -1,7 +1,7 @@ export const CREATE_ITEM_PAUSE = 1000; export const EDIT_ITEM_PAUSE = 1000; export const ITEM_LOGIN_PAUSE = 1000; -export const NAVIGATE_PAUSE = 500; +export const NAVIGATE_PAUSE = 1000; export const PAGE_LOAD_WAITING_PAUSE = 3000; export const REQUEST_FAILURE_LOADING_TIME = 1500; export const TREE_VIEW_PAUSE = 2000; @@ -14,5 +14,5 @@ export const REQUEST_FAILURE_TIME = 2500; export const REDIRECTION_TIME = 500; export const CAPTION_EDIT_PAUSE = 2000; -export const ROW_HEIGHT = 93; +export const ROW_HEIGHT = 48; export const TABLE_ITEM_RENDER_TIME = 2000; diff --git a/package.json b/package.json index 8d0df1e83..0a0ea5782 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "@uppy/react": "1.11.3", "@uppy/tus": "1.8.5", "@uppy/xhr-upload": "1.7.0", + "ag-grid-community": "25.3.0", + "ag-grid-react": "25.3.0", "clsx": "1.1.1", "connected-react-router": "6.8.0", "dexie": "3.0.3", diff --git a/src/components/common/DraggableTableRow.js b/src/components/common/DraggableTableRow.js deleted file mode 100644 index d01653ec2..000000000 --- a/src/components/common/DraggableTableRow.js +++ /dev/null @@ -1,42 +0,0 @@ -import { Draggable } from 'react-beautiful-dnd'; -import { TableRow } from '@material-ui/core'; -import React from 'react'; - -const getItemStyle = (isDragging, draggableStyle) => ({ - ...draggableStyle, - - ...(isDragging && { - background: 'rgb(235,235,235)', - }), -}); - -const getVisibleChildren = (props, isDragging) => { - if (isDragging) { - // On drag, only the checkbox and item name will be shown in the row - const checkbox = props.children[0]; - const name = props.children[1][0]; - return [checkbox, name]; - } - return props.children; -}; - -const DraggableTableRow = (id, index) => (props) => ( - - {(provided, snapshot) => ( - - {getVisibleChildren(props, snapshot.isDragging)} - - )} - -); - -export default DraggableTableRow; diff --git a/src/components/common/DroppableTableBody.js b/src/components/common/DroppableTableBody.js deleted file mode 100644 index 10d72d808..000000000 --- a/src/components/common/DroppableTableBody.js +++ /dev/null @@ -1,25 +0,0 @@ -import { DragDropContext, Droppable } from 'react-beautiful-dnd'; -import { TableBody } from '@material-ui/core'; -import React from 'react'; - -const DroppableTableBody = (onDragEnd) => (props) => ( - - - {(provided) => ( - - {/* eslint-disable-next-line react/prop-types */} - {props.children} - {provided.placeholder} - - )} - - -); - -export default DroppableTableBody; diff --git a/src/components/common/EditButton.js b/src/components/common/EditButton.js index 2d372d6e2..72ece049d 100644 --- a/src/components/common/EditButton.js +++ b/src/components/common/EditButton.js @@ -4,7 +4,10 @@ import IconButton from '@material-ui/core/IconButton'; import EditIcon from '@material-ui/icons/Edit'; import { useTranslation } from 'react-i18next'; import Tooltip from '@material-ui/core/Tooltip'; -import { EDIT_ITEM_BUTTON_CLASS } from '../../config/selectors'; +import { + buildEditButtonId, + EDIT_ITEM_BUTTON_CLASS, +} from '../../config/selectors'; import { EditItemModalContext } from '../context/EditItemModalContext'; const EditButton = ({ item }) => { @@ -18,6 +21,7 @@ const EditButton = ({ item }) => { return ( { }; EditButton.propTypes = { - item: PropTypes.shape({}).isRequired, + item: PropTypes.shape({ id: PropTypes.string.isRequired }).isRequired, }; export default EditButton; diff --git a/src/components/item/ItemContent.js b/src/components/item/ItemContent.js index 067348f64..b2991d3cd 100644 --- a/src/components/item/ItemContent.js +++ b/src/components/item/ItemContent.js @@ -54,7 +54,9 @@ const ItemContent = ({ item, enableEdition }) => { const { data: user, isLoading: isLoadingUser } = useCurrentMember(); // display children - const { data: children, isLoading: isLoadingChildren } = useChildren(itemId); + const { data: children, isLoading: isLoadingChildren } = useChildren(itemId, { + ordered: true, + }); const id = item?.get(ITEM_KEYS.ID); const { data: content, isLoading: isLoadingFileContent } = useFileContent( diff --git a/src/components/item/ItemSearch.js b/src/components/item/ItemSearch.js index 98136a882..96251424c 100644 --- a/src/components/item/ItemSearch.js +++ b/src/components/item/ItemSearch.js @@ -107,7 +107,7 @@ const useItemSearch = (items) => { }; const results = items.filter((it) => - it.name.toLowerCase().includes(searchText), + it?.name?.toLowerCase().includes(searchText), ); const itemSearchInput = ( diff --git a/src/components/main/Item.js b/src/components/main/Item.js index af1ad37ac..89f3b02cc 100644 --- a/src/components/main/Item.js +++ b/src/components/main/Item.js @@ -9,7 +9,7 @@ import CardActions from '@material-ui/core/CardActions'; import Typography from '@material-ui/core/Typography'; import CustomCardHeader from './CustomCardHeader'; import { DESCRIPTION_MAX_LENGTH } from '../../config/constants'; -import { buildItemCard } from '../../config/selectors'; +import { buildDeleteButtonId, buildItemCard } from '../../config/selectors'; import EditButton from '../common/EditButton'; import DeleteButton from '../common/DeleteButton'; import { getItemImage } from '../../utils/item'; @@ -48,7 +48,7 @@ const Item = ({ item }) => { - + ); diff --git a/src/components/main/ItemMenu.js b/src/components/main/ItemMenu.js index d6d26e41a..4cce38aa8 100644 --- a/src/components/main/ItemMenu.js +++ b/src/components/main/ItemMenu.js @@ -7,6 +7,7 @@ import React, { useContext } from 'react'; import { useTranslation } from 'react-i18next'; import { buildItemMenu, + buildItemMenuButtonId, ITEM_MENU_BUTTON_CLASS, ITEM_MENU_COPY_BUTTON_CLASS, ITEM_MENU_FLAG_BUTTON_CLASS, @@ -58,7 +59,11 @@ const ItemMenu = ({ item }) => { return ( <> - + ({ root: { width: '100%', + '& .ag-checked::after': { + color: `${theme.palette.primary.main}!important`, + }, }, - paper: { - width: '100%', - marginBottom: theme.spacing(2), - }, - visuallyHidden: { - border: 0, - clip: 'rect(0 0 0 0)', - height: 1, - margin: -1, - overflow: 'hidden', - padding: 0, - position: 'absolute', - top: 20, - width: 1, - }, - selected: { - backgroundColor: `${lighten(theme.palette.primary.main, 0.85)} !important`, - }, - hover: { + row: { cursor: 'pointer', }, - iconAndName: { + dragCell: { + paddingLeft: '0!important', + paddingRight: '0!important', display: 'flex', alignItems: 'center', }, - itemName: { - paddingLeft: theme.spacing(1), + actionCell: { + paddingLeft: '0!important', + paddingRight: '0!important', + textAlign: 'right', }, })); -const computeReorderedIdList = (list, startIndex, endIndex) => { - const result = Array.from(list); - const [removed] = result.splice(startIndex, 1); - result.splice(endIndex, 0, removed); - - return result.map((i) => i.id); -}; - -const ItemsTable = ({ items: rows, tableTitle, id: tableId, headerElements }) => { +const ItemsTable = ({ + items: rows, + tableTitle, + id: tableId, + headerElements, +}) => { + const { t } = useTranslation(); + const { push } = useHistory(); + const classes = useStyles(); const { itemId } = useParams(); const { data: parentItem } = useItem(itemId); - const { data: member, isLoading: isMemberLoading } = hooks.useCurrentMember(); - const classes = useStyles(); - const { t } = useTranslation(); - const { push } = useHistory(); - const [order, setOrder] = React.useState(ORDERING.DESC); - const [orderBy, setOrderBy] = React.useState(USER_ITEM_ORDER); - const [selected, setSelected] = React.useState([]); - const [page, setPage] = React.useState(0); - const [rowsPerPage, setRowsPerPage] = React.useState( - ROWS_PER_PAGE_OPTIONS[0], - ); + const [gridApi, setGridApi] = useState(null); + const [selected, setSelected] = useState([]); const mutation = useMutation(MUTATION_KEYS.EDIT_ITEM); - useEffect(() => { - // remove deleted rows from selection - const newSelected = selected.filter( - (id) => rows.findIndex(({ id: thisId }) => thisId === id) >= 0, - ); - if (newSelected.length !== selected.length) { - setSelected(newSelected); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [rows]); - - const headCells = [ - { - id: 'name', - numeric: false, - label: t('Name'), - align: 'left', - }, - { - id: 'type', - numeric: false, - label: t('Type'), - align: 'right', - }, - { - id: 'createdAt', - numeric: false, - label: t('Created At'), - align: 'right', - type: ITEM_DATA_TYPES.DATE, - }, - { - id: 'updatedAt', - numeric: false, - label: t('Updated At'), - align: 'right', - type: ITEM_DATA_TYPES.DATE, - }, - { - id: 'actions', - numeric: false, - label: t('Actions'), - align: 'right', - }, - ]; - - // display empty rows to maintain the table height - const emptyRows = - rowsPerPage - Math.min(rowsPerPage, rows.size - page * rowsPerPage); - - // order and select rows to display given the current page and the number of entries displayed - const rowsToDisplay = getRowsForPage( - stableSort( - rows, - getComparator( - order, - orderBy, - getChildrenOrderFromFolderExtra(parentItem), - ), - ), - { page, rowsPerPage }, - ); - - if (isMemberLoading) { - return ; - } - - // transform rows' information into displayable information - const mappedRows = rowsToDisplay.map((item) => { + const mappedRows = rows.map((item) => { const { id, updatedAt, name, createdAt, type, extra } = item; - const nameAndIcon = ( - - - {name} - - ); - return { id, - name: nameAndIcon, + name, type, updatedAt, createdAt, extra, - actions: ( - <> - - - - - - ), }; }); - const handleRequestSort = (event, property) => { - const isAsc = orderBy === property && order === ORDERING.ASC; - setOrder(isAsc ? ORDERING.DESC : ORDERING.ASC); - setOrderBy(property); - }; + const isFolder = () => Boolean(itemId); + const isSearching = () => Boolean(itemSearch.text); + const canDrag = () => isFolder() && !isSearching(); - const handleSelectAllClick = (event) => { - const checked = - JSON.parse(event.target.dataset.indeterminate) || !event.target.checked; - if (!checked) { - const newSelecteds = mappedRows.map((n) => n.id).toJS(); - return setSelected(newSelecteds); - } - return setSelected([]); + const onGridReady = (params) => { + setGridApi(params.api); }; - const removeItemsFromSelected = (items) => { - const newSelected = selected.filter((id) => !items.includes(id)); - setSelected(newSelected); + const onSelectionChanged = () => { + setSelected(gridApi?.getSelectedRows().map((r) => r.id) ?? []); }; - const addItemsInSelected = (items) => { - const newSelected = selected.concat(items); - setSelected(newSelected); + const onRowDataChanged = () => { + onSelectionChanged(); }; - const handleClick = (event, id) => { - const checked = selected.indexOf(id) !== -1; - if (checked) { - removeItemsFromSelected([id]); - } else { - addItemsInSelected([id]); - } - }; + const getRowNodeId = (row) => buildItemsTableRowId(row.id); - const handleChangePage = (event, newPage) => { - setPage(newPage); - }; + const onCellClicked = ({ column: { colId }, data: item }) => { + if (colId !== 'actions') { + let targetId = item.id; - const handleChangeRowsPerPage = (event) => { - setRowsPerPage(parseInt(event.target.value, 10)); - setPage(0); + // redirect to target if shortcut + if (item.type === ITEM_TYPES.SHORTCUT) { + targetId = getShortcutTarget(item.extra); + } + push(buildItemPath(targetId)); + } }; - const handleOnClickRow = ({ id, type, extra }) => { - let targetId = id; + const getDisplayedRowIds = () => + gridApi.getModel().rowsToDisplay.map((r) => r.data.id); - // redirect to target if shortcut - if (type === ITEM_TYPES.SHORTCUT) { - targetId = getShortcutTarget(extra); - } - push(buildItemPath(targetId)); + const hasOrderChanged = () => { + const rowIds = getDisplayedRowIds(); + const childrenOrder = getChildrenOrderFromFolderExtra(parentItem); + + return ( + rowIds.length !== childrenOrder.length || + !childrenOrder.every((id, i) => id === rowIds[i]) + ); }; - // format entry data given type - const formatRowValue = ({ value, type }) => { - switch (type) { - case ITEM_DATA_TYPES.DATE: - return formatDate(value); - default: - return value; + const onDragEnd = () => { + if (canDrag() && hasOrderChanged()) { + mutation.mutate({ + id: itemId, + extra: { + folder: { + childrenOrder: getDisplayedRowIds(), + }, + }, + }); } }; - const onDragEnd = (result) => { - if (!result.destination) return; + const dateColumnFormatter = ({ value }) => formatDate(value); - mutation.mutate({ - id: itemId, - extra: { - folder: { - childrenOrder: computeReorderedIdList( - rowsToDisplay, - result.source.index, - result.destination.index, - ), - }, - }, - }); - }; + const dateComparator = (d1, d2) => new Date(d1) - new Date(d2); + + const textComparator = (text1, text2) => + text1.localeCompare(text2, undefined, { sensitivity: 'base' }); - const isSelected = (id) => selected.indexOf(id) !== -1; + const itemRowDragText = (params) => params.rowNode.data.name; return (
- - - - - - - {mappedRows.map((row, index) => { - const isItemSelected = isSelected(row.id); - const labelId = `enhanced-table-checkbox-${index}`; - - return ( - - - handleClick(event, row.id)} - color="primary" - /> - - {headCells.map(({ id: field, align, type }, idx) => ( - { - // do not navigate when clicking on actions - const shouldNavigate = idx !== headCells.length - 1; - if (shouldNavigate) { - handleOnClickRow(row); - } - }} - > - {formatRowValue({ value: row[field], type })} - - ))} - - ); - })} - {emptyRows > 0 && ( - - - - )} - -
-
- -
+ +
+ + + + + + + + +
); }; @@ -389,13 +240,17 @@ ItemsTable.propTypes = { items: PropTypes.instanceOf(List), tableTitle: PropTypes.string.isRequired, id: PropTypes.string, - headerElements: PropTypes.arrayOf(PropTypes.element) + headerElements: PropTypes.arrayOf(PropTypes.element), + itemSearch: PropTypes.shape({ + input: PropTypes.instanceOf(ItemSearchInput), + text: PropTypes.string, + }), }; ItemsTable.defaultProps = { id: '', items: List(), - headerElements: [] + headerElements: [], }; export default ItemsTable; diff --git a/src/components/table/ActionsCellRenderer.js b/src/components/table/ActionsCellRenderer.js new file mode 100644 index 000000000..d51d86651 --- /dev/null +++ b/src/components/table/ActionsCellRenderer.js @@ -0,0 +1,31 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import EditButton from '../common/EditButton'; +import ShareButton from '../common/ShareButton'; +import DeleteButton from '../common/DeleteButton'; +import { buildDeleteButtonId } from '../../config/selectors'; +import ItemMenu from '../main/ItemMenu'; +import { hooks } from '../../config/queryClient'; +import FavoriteButton from '../common/FavoriteButton'; + +const { useCurrentMember } = hooks; + +const ActionsCellRenderer = ({ data: item }) => { + const { data: member } = useCurrentMember(); + + return ( + <> + + + + + + + ); +}; + +ActionsCellRenderer.propTypes = { + data: PropTypes.shape({}).isRequired, +}; + +export default ActionsCellRenderer; diff --git a/src/components/table/DragCellRenderer.js b/src/components/table/DragCellRenderer.js new file mode 100644 index 000000000..94c1048e6 --- /dev/null +++ b/src/components/table/DragCellRenderer.js @@ -0,0 +1,41 @@ +import React, { useEffect, useRef } from 'react'; +import DragIndicatorIcon from '@material-ui/icons/DragIndicator'; +import PropTypes from 'prop-types'; +import { makeStyles } from '@material-ui/core/styles'; +import { DRAG_ICON_SIZE } from '../../config/constants'; +import { buildRowDraggerId } from '../../config/selectors'; + +const useStyles = makeStyles(() => ({ + dragIconContainer: { + display: 'flex', + }, + dragIcon: { + fontSize: DRAG_ICON_SIZE, + }, +})); + +const DragCellRenderer = ({ data: item, registerRowDragger }) => { + const classes = useStyles(); + const dragRef = useRef(null); + + useEffect(() => { + registerRowDragger(dragRef.current); + }); + + return ( +
+ +
+ ); +}; + +DragCellRenderer.propTypes = { + data: PropTypes.shape({}).isRequired, + registerRowDragger: PropTypes.func.isRequired, +}; + +export default DragCellRenderer; diff --git a/src/components/table/NameCellRenderer.js b/src/components/table/NameCellRenderer.js new file mode 100644 index 000000000..10637e1c7 --- /dev/null +++ b/src/components/table/NameCellRenderer.js @@ -0,0 +1,31 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import ItemIcon from '../main/ItemIcon'; + +const useStyles = makeStyles((theme) => ({ + nameCell: { + display: 'flex', + alignItems: 'center', + }, + name: { + marginLeft: theme.spacing(1), + }, +})); + +const NameCellRenderer = ({ data: item }) => { + const classes = useStyles(); + + return ( +
+ +
{item.name}
+
+ ); +}; + +NameCellRenderer.propTypes = { + data: PropTypes.shape({}).isRequired, +}; + +export default NameCellRenderer; diff --git a/src/config/constants.js b/src/config/constants.js index 030269093..7c680605a 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -161,3 +161,8 @@ export const ITEM_DEFAULT_HEIGHT = 500; export const GRAASP_LOGO_HEADER_HEIGHT = 40; export const PSEUDONIMIZED_USER_MAIL = '@graasp.org'; +export const ITEMS_TABLE_CONTAINER_HEIGHT = '60vh'; + +export const DRAG_ICON_SIZE = 18; + +export const ACTION_CELL_WIDTH = 230; diff --git a/src/config/selectors.js b/src/config/selectors.js index d9814faac..9e60cbf8e 100644 --- a/src/config/selectors.js +++ b/src/config/selectors.js @@ -35,7 +35,10 @@ export const SHARED_ITEMS_ID = 'sharedItems'; export const FAVORITE_ITEMS_ID = 'favoriteItems'; export const OWNED_ITEMS_ID = 'ownedItems'; export const ITEMS_TABLE_BODY = 'itemsTableBody'; +export const ITEMS_TABLE_ROW = '.ag-row'; export const buildItemsTableRowId = (id) => `itemsTableRow-${id}`; +export const buildItemsTableRowIdAttribute = (id) => + `[name="center"] [row-id="${buildItemsTableRowId(id)}"]`; export const ITEMS_TABLE_EMPTY_ROW_ID = 'itemsTableEmptyRow'; export const ITEMS_TABLE_DELETE_SELECTED_ITEMS_ID = 'itemsTableDeleteSelectedItems'; @@ -122,7 +125,10 @@ export const buildItemsGridPaginationButton = (page) => export const buildItemsGridPaginationButtonSelected = (page) => `${buildItemsGridPaginationButton(page)}.Mui-selected`; export const ITEM_HEADER_ID = 'itemHeader'; +export const buildRowDraggerId = (id) => `rowDragger-${id}`; export const buildShareButtonId = (id) => `shareButton-${id}`; +export const buildDeleteButtonId = (id) => `deleteButton-${id}`; +export const buildItemMenuButtonId = (id) => `itemMenuButton-${id}`; export const buildPerformButtonId = (id) => `performButton-${id}`; export const buildEditButtonId = (id) => `editButton-${id}`; export const buildSettingsButtonId = (id) => `settingsButton-${id}`; diff --git a/src/utils/item.js b/src/utils/item.js index 9d8304e0b..f7d4b3615 100644 --- a/src/utils/item.js +++ b/src/utils/item.js @@ -132,4 +132,4 @@ export const getErrorItemIds = (items) => items.filter((item) => item.statusCode).map((item) => item.data); export const getChildrenOrderFromFolderExtra = (item) => - item?.get('extra')?.folder?.childrenOrder; + item?.get('extra')?.folder?.childrenOrder ?? []; diff --git a/src/utils/table.js b/src/utils/table.js index ab4adccf1..a81bd348e 100644 --- a/src/utils/table.js +++ b/src/utils/table.js @@ -58,3 +58,6 @@ export const stableSort = (array, comparator) => { */ export const getRowsForPage = (table, { page, rowsPerPage }) => table.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage); + +export const userOrderComparator = (userOrder = []) => (a, b) => + userOrder.indexOf(a.id) - userOrder.indexOf(b.id); diff --git a/yarn.lock b/yarn.lock index 5921969a5..41c100d2a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2226,9 +2226,9 @@ __metadata: linkType: hard "@hapi/hoek@npm:^9.0.0": - version: 9.2.0 - resolution: "@hapi/hoek@npm:9.2.0" - checksum: 57103bb5074d24ffd876f559bac6b312f2f58fe0f21dbfb0b8941032cba4fd37d92249db366516e1f68e2033834b87001c1558f523b48130b21f823f1e35b91a + version: 9.2.1 + resolution: "@hapi/hoek@npm:9.2.1" + checksum: 6a439f672df5f12f1d08d56967b4cb364ce05d81e95e3c3c1b88c5a98b917ca91c70e78cc0b2b4219a760cceec1f22d6658bfc93a83670cecc1ce9ca2247ebd8 languageName: node linkType: hard @@ -2502,16 +2502,16 @@ __metadata: languageName: node linkType: hard -"@jest/types@npm:^27.1.1": - version: 27.1.1 - resolution: "@jest/types@npm:27.1.1" +"@jest/types@npm:^27.2.3": + version: 27.2.3 + resolution: "@jest/types@npm:27.2.3" dependencies: "@types/istanbul-lib-coverage": ^2.0.0 "@types/istanbul-reports": ^3.0.0 "@types/node": "*" "@types/yargs": ^16.0.0 chalk: ^4.0.0 - checksum: 917acbf05d96415cae05067f1f0c79a58112b086baf941b92f4fc989d75f632cf7c2a87eb679254609c96d24ed7e442ea5b387312651996ed95310f7003a43e2 + checksum: 578f6fe6a6b33558e6ac8f5fbca6c91448d04591ecac15d8204f86554b1fdaa4e78bd073d245622f030c5305a3cbf54e02c610c508fc857fb9a0f9cd643b24c7 languageName: node linkType: hard @@ -3251,9 +3251,9 @@ __metadata: linkType: hard "@types/prettier@npm:^2.0.0": - version: 2.4.0 - resolution: "@types/prettier@npm:2.4.0" - checksum: f7128dc36e68906c9316c7d284b29561c6aa294e9b04d860ab41ebb9734080fdcbbedb42dd1bfa45ed72f9b34e28233d8e2e98c715b31b333d31f77da3dcad01 + version: 2.4.1 + resolution: "@types/prettier@npm:2.4.1" + checksum: df330c2d6fe7c282839b0f17701e069a9c6c96d2ff54704e933a1b3c1b98844d963a7cb00c5629d173604892ceee802312bbaeb8a97f5da21e13db8f653b519e languageName: node linkType: hard @@ -3432,13 +3432,14 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^4.5.0": - version: 4.31.2 - resolution: "@typescript-eslint/eslint-plugin@npm:4.31.2" + version: 4.32.0 + resolution: "@typescript-eslint/eslint-plugin@npm:4.32.0" dependencies: - "@typescript-eslint/experimental-utils": 4.31.2 - "@typescript-eslint/scope-manager": 4.31.2 + "@typescript-eslint/experimental-utils": 4.32.0 + "@typescript-eslint/scope-manager": 4.32.0 debug: ^4.3.1 functional-red-black-tree: ^1.0.1 + ignore: ^5.1.8 regexpp: ^3.1.0 semver: ^7.3.5 tsutils: ^3.21.0 @@ -3448,23 +3449,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 5d0c2ff34d5a263d2c7e5455ae5844cd24f34eac013e7a1189a959d4edb3ce2312cf340bc78f9a346e64cc3a73e1c8bd9ed367a58ba8633acd04122ad7304b82 + checksum: f1e856f1f500ac7a06097536d0a5392f33f4a9f0750ffac90c30e40852524579715624ffa791b6fb601320d1d53135b4321b00d0554f6aea12fe55b65ccedd7b languageName: node linkType: hard -"@typescript-eslint/experimental-utils@npm:4.31.2, @typescript-eslint/experimental-utils@npm:^4.0.1": - version: 4.31.2 - resolution: "@typescript-eslint/experimental-utils@npm:4.31.2" +"@typescript-eslint/experimental-utils@npm:4.32.0, @typescript-eslint/experimental-utils@npm:^4.0.1": + version: 4.32.0 + resolution: "@typescript-eslint/experimental-utils@npm:4.32.0" dependencies: "@types/json-schema": ^7.0.7 - "@typescript-eslint/scope-manager": 4.31.2 - "@typescript-eslint/types": 4.31.2 - "@typescript-eslint/typescript-estree": 4.31.2 + "@typescript-eslint/scope-manager": 4.32.0 + "@typescript-eslint/types": 4.32.0 + "@typescript-eslint/typescript-estree": 4.32.0 eslint-scope: ^5.1.1 eslint-utils: ^3.0.0 peerDependencies: eslint: "*" - checksum: 0c251effbab00ee26eaaa78540b2988ff24550564e6dea9e31190c1d120e846afb3882394be4d65fac53008f6feb5abc66723826ed093d09c49c14374630b8fb + checksum: bad0072df9f7f7804a3bd9aeccfe6a0b117e47ad7f58d091674a276c84171be2c525c977c304d39c6d0cd31706a2d9a4f797466a505dda7985535cd3ad9b5830 languageName: node linkType: hard @@ -3484,29 +3485,29 @@ __metadata: linkType: hard "@typescript-eslint/parser@npm:^4.5.0": - version: 4.31.2 - resolution: "@typescript-eslint/parser@npm:4.31.2" + version: 4.32.0 + resolution: "@typescript-eslint/parser@npm:4.32.0" dependencies: - "@typescript-eslint/scope-manager": 4.31.2 - "@typescript-eslint/types": 4.31.2 - "@typescript-eslint/typescript-estree": 4.31.2 + "@typescript-eslint/scope-manager": 4.32.0 + "@typescript-eslint/types": 4.32.0 + "@typescript-eslint/typescript-estree": 4.32.0 debug: ^4.3.1 peerDependencies: eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 peerDependenciesMeta: typescript: optional: true - checksum: e0f83958483326942241838f672291a652ce30078c1a9faac0a99ff381c977c1e568bf0591593e3f5bd4e492fb7d91dbabde965ef5e3296e6f28de127db3107b + checksum: dd6a30fb04e56a13b53298c7d20cb3954cc6f220c599ba907b5029c2d36230a1d9850c8392d47a3b4c2760a39af5f6ff502a2eaa984a44f93142c83ac231d52d languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:4.31.2": - version: 4.31.2 - resolution: "@typescript-eslint/scope-manager@npm:4.31.2" +"@typescript-eslint/scope-manager@npm:4.32.0": + version: 4.32.0 + resolution: "@typescript-eslint/scope-manager@npm:4.32.0" dependencies: - "@typescript-eslint/types": 4.31.2 - "@typescript-eslint/visitor-keys": 4.31.2 - checksum: 5560dcbe0fbb629967071f88ab4767cb7e443f2a2008724e1dc0d974bf16cf89400180d3bf56206bf3e7d6c49ad3b22c72b8c465c826510979b4513dad3e6b2d + "@typescript-eslint/types": 4.32.0 + "@typescript-eslint/visitor-keys": 4.32.0 + checksum: 03510d080dee19588a09f41226c93fb67eafe132c2305da4dbcfaf3ccb333a6d1736f7b897d83c85545cb88f532c81849182b1c55cb7ca7ad9148aa5d4671ad2 languageName: node linkType: hard @@ -3517,10 +3518,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:4.31.2": - version: 4.31.2 - resolution: "@typescript-eslint/types@npm:4.31.2" - checksum: 361533ef9d921ead2e4aac9f097dd01468e84eca2d73157ec02c13fa164688fa1d58497a1a4519f00a5eb88d67efdea279ebc365328aa7371a0466b6ff8149bc +"@typescript-eslint/types@npm:4.32.0": + version: 4.32.0 + resolution: "@typescript-eslint/types@npm:4.32.0" + checksum: e93ce12ee3ee0fa1ac6f6e51f9aec8c4b7b603296dad2d5cb11790710de12fd7bf88fca0f8220e51f18e696aba8764e26ff960fa0cc1aef50055ee1e1e72c207 languageName: node linkType: hard @@ -3543,12 +3544,12 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:4.31.2": - version: 4.31.2 - resolution: "@typescript-eslint/typescript-estree@npm:4.31.2" +"@typescript-eslint/typescript-estree@npm:4.32.0": + version: 4.32.0 + resolution: "@typescript-eslint/typescript-estree@npm:4.32.0" dependencies: - "@typescript-eslint/types": 4.31.2 - "@typescript-eslint/visitor-keys": 4.31.2 + "@typescript-eslint/types": 4.32.0 + "@typescript-eslint/visitor-keys": 4.32.0 debug: ^4.3.1 globby: ^11.0.3 is-glob: ^4.0.1 @@ -3557,7 +3558,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 75df8e5341f581d3303b237b9b32bef3e63e87114d14ed5896c293f25ec253e6ef8489752cf78ca0fbfc3cf1d4deb122a22b92b57bfb845bc0fa41812a04e34c + checksum: 4525789cd27f4af333c9e2c221511b4ce8c50bd520b5c73958885b718f38d5c7349678286db8dc26de2ca61463651925d37e833456497e493c357acc3ea24b03 languageName: node linkType: hard @@ -3570,13 +3571,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:4.31.2": - version: 4.31.2 - resolution: "@typescript-eslint/visitor-keys@npm:4.31.2" +"@typescript-eslint/visitor-keys@npm:4.32.0": + version: 4.32.0 + resolution: "@typescript-eslint/visitor-keys@npm:4.32.0" dependencies: - "@typescript-eslint/types": 4.31.2 + "@typescript-eslint/types": 4.32.0 eslint-visitor-keys: ^2.0.0 - checksum: 5f3d16d3d282e9b4b02acd06e787e182e9afb9e0a1c42a19268d9f8e02895163ff81674281db27e4777cc239675d6be2abfab8129458f670fe0c17a0d19ad796 + checksum: 233bf479b6373bae2e61976ed1f2d0fb5c365203984e1233024a2677da0958fb3b19753b67047e8c9a9f4cec7603d1027d73b1302fef0d49c5e92be012d3d92e languageName: node linkType: hard @@ -4179,6 +4180,26 @@ __metadata: languageName: node linkType: hard +"ag-grid-community@npm:25.3.0": + version: 25.3.0 + resolution: "ag-grid-community@npm:25.3.0" + checksum: 9e7c60ab1c14b0964c5e10a0a5492a2c0ef90062778c1ffc8aecf9b4d68c434684e643765c81352e66c898fec5a12cc76eae7a0c5401c90a6ef39e2f2cc554b0 + languageName: node + linkType: hard + +"ag-grid-react@npm:25.3.0": + version: 25.3.0 + resolution: "ag-grid-react@npm:25.3.0" + dependencies: + prop-types: ^15.6.2 + peerDependencies: + ag-grid-community: ~25.3.0 + react: ^16.3.0 || ^17.0.0 + react-dom: ^16.3.0 || ^17.0.0 + checksum: e1489128163c42bab88de87c8f2cf2d3ef494819970908b897476371c9fab75b9eb2ee823b9b9a8ccbc15810eb24655c7903a0623cd4dcedfbf757b654fb1303 + languageName: node + linkType: hard + "agent-base@npm:6, agent-base@npm:^6.0.2": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -5838,11 +5859,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30000981, caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001125, caniuse-lite@npm:^1.0.30001259": - version: 1.0.30001260 - resolution: "caniuse-lite@npm:1.0.30001260" - dependencies: - nanocolors: ^0.1.0 - checksum: a3a61073204636e02bc3972bfdcd8b3c3a2fb56f29b5ffa95fad7e5a01e2eece2ed92f1246728185992618a04f9221cbd83ddd96d2ef68083353d55ffe660e29 + version: 1.0.30001261 + resolution: "caniuse-lite@npm:1.0.30001261" + checksum: d894662312ecbdd772f0a258c4a45cac93605247b127b25649052353e0b981abfd0b445f469650943b612adc236fd510ae61c1293f3e77c68af7411d1b66574a languageName: node linkType: hard @@ -8155,9 +8174,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.3.564, electron-to-chromium@npm:^1.3.846": - version: 1.3.850 - resolution: "electron-to-chromium@npm:1.3.850" - checksum: 55d4bea34359a69b5f42cb6d5c6ee7bb29c8d0d1dafd8adfc828f2a984fbe8db704703b16f4536f1f702f255c17798cc5a0c509f6375bc766c0253618aa00d9f + version: 1.3.853 + resolution: "electron-to-chromium@npm:1.3.853" + checksum: 9a71823087b480cf53423a5cb3fe39dd8e84386c3b39ff6f14e0c05c9bfad0504722e86c0c84779b9aab911e9a19677da8d6f5bd8370a66800934da843d18f3d languageName: node linkType: hard @@ -8333,8 +8352,8 @@ __metadata: linkType: hard "es-abstract@npm:^1.17.2, es-abstract@npm:^1.18.0-next.1, es-abstract@npm:^1.18.0-next.2, es-abstract@npm:^1.18.1, es-abstract@npm:^1.18.2": - version: 1.18.6 - resolution: "es-abstract@npm:1.18.6" + version: 1.18.7 + resolution: "es-abstract@npm:1.18.7" dependencies: call-bind: ^1.0.2 es-to-primitive: ^1.2.1 @@ -8354,7 +8373,7 @@ __metadata: string.prototype.trimend: ^1.0.4 string.prototype.trimstart: ^1.0.4 unbox-primitive: ^1.0.1 - checksum: 8903ed187a9f66a8b21385401770124b37ded75a9cd99c7ea22e709ca667e7b549f37dc8bf9bf458a6cdb908c95a16fed389e2871bb3a28bfaab46db555cb1f3 + checksum: ec466f4a236b1f511dc20ddf2518d6192e60c741e0cdd151c6de1dadecbc7af469bf5359c3d33237955f39b177f53349cf73eae196e092e5d12e73b4910c77a7 languageName: node linkType: hard @@ -8611,8 +8630,8 @@ __metadata: linkType: hard "eslint-plugin-jest@npm:^24.1.0": - version: 24.4.2 - resolution: "eslint-plugin-jest@npm:24.4.2" + version: 24.5.0 + resolution: "eslint-plugin-jest@npm:24.5.0" dependencies: "@typescript-eslint/experimental-utils": ^4.0.1 peerDependencies: @@ -8621,7 +8640,7 @@ __metadata: peerDependenciesMeta: "@typescript-eslint/eslint-plugin": optional: true - checksum: de00fa7464860a189841cf767eda6607ec53e8b839d2317f80561751580c3976a04af509f1b771808b56e88316ffc31309b9e58aeac7ac55ffdea8ed3f4626f1 + checksum: 6f7eacb7e3ba60a90d23d998c97dfa2eec46694b1c2102bf585bf0e60a5bb6b31f880d49a569813b70da45e6449b1db0dfad646c1204e2d27be8eca039bcbc63 languageName: node linkType: hard @@ -10221,6 +10240,8 @@ fsevents@^1.2.7: "@uppy/react": 1.11.3 "@uppy/tus": 1.8.5 "@uppy/xhr-upload": 1.7.0 + ag-grid-community: 25.3.0 + ag-grid-react: 25.3.0 clsx: 1.1.1 concurrently: 6.0.0 connected-react-router: 6.8.0 @@ -10920,7 +10941,7 @@ fsevents@^1.2.7: languageName: node linkType: hard -"ignore@npm:^5.1.4": +"ignore@npm:^5.1.4, ignore@npm:^5.1.8": version: 5.1.8 resolution: "ignore@npm:5.1.8" checksum: 967abadb61e2cb0e5c5e8c4e1686ab926f91bc1a4680d994b91947d3c65d04c3ae126dcdf67f08e0feeb8ff8407d453e641aeeddcc47a3a3cca359f283cf6121 @@ -11315,11 +11336,11 @@ fsevents@^1.2.7: linkType: hard "is-core-module@npm:^2.0.0, is-core-module@npm:^2.2.0, is-core-module@npm:^2.5.0, is-core-module@npm:^2.6.0": - version: 2.6.0 - resolution: "is-core-module@npm:2.6.0" + version: 2.7.0 + resolution: "is-core-module@npm:2.7.0" dependencies: has: ^1.0.3 - checksum: 183b3b96fed19822b13959876b0317e61fc2cb5ebcbc21639904c81f7ae328af57f8e18cc4750a9c4abebd686130c70d34a89521e57dbe002edfa4614507ce18 + checksum: 8ec6dc714438ef9dc4dae10c94d21bd5aa67244da7e85bd9e42f0fd298514181214f6bebe358a486477c1242458b170ad7a8c936be0be15d465862fa61d3d1c7 languageName: node linkType: hard @@ -11956,14 +11977,14 @@ fsevents@^1.2.7: linkType: hard "jest-diff@npm:^27.0.0": - version: 27.2.2 - resolution: "jest-diff@npm:27.2.2" + version: 27.2.3 + resolution: "jest-diff@npm:27.2.3" dependencies: chalk: ^4.0.0 diff-sequences: ^27.0.6 jest-get-type: ^27.0.6 - pretty-format: ^27.2.2 - checksum: 864f2337bde9a409b0c21c6d44d86c0aef1477422e24f52d58ad34792a1ee2303e512144ee3897a10fbe5846c731964d03b37e42a74bb28d331f42f155f93088 + pretty-format: ^27.2.3 + checksum: 0a9325c822f5bbd4132b35728e5a7339e60f26f690a1a1680115ac5e384c0aa39918601c259a67fb7c3391425c60e01b70103057c07b47516de6f87c914a80e2 languageName: node linkType: hard @@ -14067,7 +14088,7 @@ fsevents@^1.2.7: languageName: node linkType: hard -"nanocolors@npm:^0.1.0, nanocolors@npm:^0.1.5": +"nanocolors@npm:^0.1.5": version: 0.1.12 resolution: "nanocolors@npm:0.1.12" checksum: 2ce58f57006ddd1d2680d05fe21f54d858db8ba81bd13381598ddc546f7637e33c4407da2ea7da40ea1c96794250e7c14a4d00358b48eeae4d917d6a92bafe4c @@ -14075,9 +14096,9 @@ fsevents@^1.2.7: linkType: hard "nanocolors@npm:^0.2.2, nanocolors@npm:^0.2.8": - version: 0.2.10 - resolution: "nanocolors@npm:0.2.10" - checksum: 6c141b3c7beeb203a9461c07b5cc0efe178b465f83bbdac3822f35464778cb74577e4c3f5f673b8238c6db9a0471718ead0b3ca8b33581866168d5cbc3f390a0 + version: 0.2.12 + resolution: "nanocolors@npm:0.2.12" + checksum: a34a63dcca29eede3db41afd1421f130423fc99e73f6c89166f57815bbf0441f02a6112651b068acfd309707215f48eec15dd38e790a8225d6762503a7c175c6 languageName: node linkType: hard @@ -16246,15 +16267,15 @@ fsevents@^1.2.7: languageName: node linkType: hard -"pretty-format@npm:^27.0.0, pretty-format@npm:^27.2.2": - version: 27.2.2 - resolution: "pretty-format@npm:27.2.2" +"pretty-format@npm:^27.0.0, pretty-format@npm:^27.2.3": + version: 27.2.3 + resolution: "pretty-format@npm:27.2.3" dependencies: - "@jest/types": ^27.1.1 + "@jest/types": ^27.2.3 ansi-regex: ^5.0.1 ansi-styles: ^5.0.0 react-is: ^17.0.1 - checksum: 569c39c81e44d29c782d558d01a8ae33ae3e6a617b316527ef92b027298b9c5e71526d54c37f0804f5b17aab99704ad36aa7da817d552cf10ed34d51b646ee52 + checksum: 94b53feeb30ff63691297434674e5755e5b4e95cf242b26c86126d265c239e6b5a80d50bfd9cfbee4d4dff21f38cb3cdda3f035f84db8343e41116e1478d4bb3 languageName: node linkType: hard