Skip to content

Commit

Permalink
Change link/unlink behaviour to directly apply changes without showin…
Browse files Browse the repository at this point in the history
…g modal or message (#2523)

* Change unlink behavior to not show the summary modal and close the unlink modal after success
* Change link behavior to not show the alert after each successful link operation
  • Loading branch information
KenyShah24 authored Sep 4, 2024
1 parent bd66eec commit cedfb0e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 107 deletions.
123 changes: 57 additions & 66 deletions src/components/record/related-table-actions.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,48 @@
import { MouseEvent, useState, useRef, useLayoutEffect } from 'react';
import { MouseEvent, useLayoutEffect, useRef, useState } from 'react';

// components
import DisplayValue from '@isrd-isi-edu/chaise/src/components/display-value';
import ChaiseTooltip from '@isrd-isi-edu/chaise/src/components/tooltip';
import RecordsetModal from '@isrd-isi-edu/chaise/src/components/modals/recordset-modal';
import DeleteConfirmationModal, { DeleteConfirmationModalTypes } from '@isrd-isi-edu/chaise/src/components/modals/delete-confirmation-modal';
import RecordsetModal from '@isrd-isi-edu/chaise/src/components/modals/recordset-modal';
import ChaiseTooltip from '@isrd-isi-edu/chaise/src/components/tooltip';
import Dropdown from 'react-bootstrap/Dropdown';
// hooks
import useRecord from '@isrd-isi-edu/chaise/src/hooks/record';
import useAuthn from '@isrd-isi-edu/chaise/src/hooks/authn';
import useAlert from '@isrd-isi-edu/chaise/src/hooks/alerts';
import useAuthn from '@isrd-isi-edu/chaise/src/hooks/authn';
import useError from '@isrd-isi-edu/chaise/src/hooks/error';
import useRecord from '@isrd-isi-edu/chaise/src/hooks/record';

// models
import { CommentDisplayModes } from '@isrd-isi-edu/chaise/src/models/displayname';
import { LogActions, LogParentActions, LogReloadCauses, LogStackPaths, LogStackTypes } from '@isrd-isi-edu/chaise/src/models/log';
import { RecordRelatedModel } from '@isrd-isi-edu/chaise/src/models/record';
import { LogActions, LogParentActions, LogReloadCauses } from '@isrd-isi-edu/chaise/src/models/log';
import {
RecordsetConfig,
RecordsetDisplayMode,
RecordsetProps,
RecordsetSelectMode,
SelectedRow,
} from '@isrd-isi-edu/chaise/src/models/recordset';
import { LogStackPaths, LogStackTypes } from '@isrd-isi-edu/chaise/src/models/log';
import { CommentDisplayModes } from '@isrd-isi-edu/chaise/src/models/displayname';

// providers
import { ChaiseAlertType } from '@isrd-isi-edu/chaise/src/providers/alerts';

// services
import { LogService } from '@isrd-isi-edu/chaise/src/services/log';
import { CookieService } from '@isrd-isi-edu/chaise/src/services/cookie';
import { ConfigService } from '@isrd-isi-edu/chaise/src/services/config';
import { CookieService } from '@isrd-isi-edu/chaise/src/services/cookie';
import { LogService } from '@isrd-isi-edu/chaise/src/services/log';

// utils
import { addQueryParamsToURL } from '@isrd-isi-edu/chaise/src/utils/uri-utils';
import {
CUSTOM_EVENTS,
RECORDSET_DEFAULT_PAGE_SIZE,
} from '@isrd-isi-edu/chaise/src/utils/constants';
import { getRandomInt } from '@isrd-isi-edu/chaise/src/utils/math-utils';
import {
allowCustomModeRelated,
displayCustomModeRelated,
getPrefillCookieObject,
} from '@isrd-isi-edu/chaise/src/utils/record-utils';
import {
RECORDSET_DEFAULT_PAGE_SIZE,
CUSTOM_EVENTS,
} from '@isrd-isi-edu/chaise/src/utils/constants';
import { windowRef } from '@isrd-isi-edu/chaise/src/utils/window-ref';
import { getRandomInt } from '@isrd-isi-edu/chaise/src/utils/math-utils';
import { fireCustomEvent } from '@isrd-isi-edu/chaise/src/utils/ui-utils';
import Q from 'q';
import { addQueryParamsToURL } from '@isrd-isi-edu/chaise/src/utils/uri-utils';
import { windowRef } from '@isrd-isi-edu/chaise/src/utils/window-ref';
import ResizeSensor from 'css-element-queries/src/ResizeSensor';

type RelatedTableActionsProps = {
Expand Down Expand Up @@ -420,12 +415,6 @@ const RelatedTableActions = ({
.create(submissionRows, logObj)
.then(() => {
setAddPureBinaryModalProps(null);
addAlert(
<>
<code><DisplayValue value={usedRef.displayname}></DisplayValue></code> records have been successfully linked.
</>,
ChaiseAlertType.SUCCESS
);

const details = relatedModel.recordsetProps.config.containerDetails!;
updateRecordPage(true, undefined, [
Expand Down Expand Up @@ -519,45 +508,49 @@ const RelatedTableActions = ({
setShowPureBinarySpinner(true);

validateSessionBeforeMutation(() => {
const deleteResponse = (response: any) => {
setShowPureBinarySpinner(false);

// Show modal popup summarizing total # of deletions succeeded and failed
response.clickOkToDismiss = true;

// TODO: - improve partial success and use TRS to check delete rights before giving a checkbox
// - some errors could have been because of row level security
dispatchError({
error: response,
isDismissible: true,
closeBtnCallback: () => {
// ask recordset to update the modal
if (!!containerRef.current) {
// NOTE: This feels very against React but the complexity of our flow control provider seems to warrant doing this
fireCustomEvent(CUSTOM_EVENTS.FORCE_UPDATE_RECORDSET, containerRef.current, {
cause: LogReloadCauses.ENTITY_BATCH_UNLINK,
pageStates: { updateResult: true, updateCount: true, updateFacets: true },
response: response,
const deleteTuples = () => {
leafReference
.deleteBatchAssociationTuples(relatedModel.recordsetProps.parentTuple, selectedRows)
.then((response: any) => {
setShowPureBinarySpinner(false);
if (response.failedTupleData.length > 0) {
response.clickOkToDismiss = true;

// TODO: - improve partial success and use TRS to check delete rights before giving a checkbox
// - some errors could have been because of row level security
dispatchError({
error: response,
isDismissible: true,
closeBtnCallback: () => {
// ask recordset to update the modal
if (!!containerRef.current) {
// NOTE: This feels very against React but the complexity of our flow control provider seems to warrant doing this
fireCustomEvent(CUSTOM_EVENTS.FORCE_UPDATE_RECORDSET, containerRef.current, {
cause: LogReloadCauses.ENTITY_BATCH_UNLINK,
pageStates: { updateResult: true, updateCount: true, updateFacets: true },
response: response,
});
}
},
});
}
},
});
};

const deleteError = (err: any) => {
setShowPureBinarySpinner(false);
// errors that land here would be execution of code errors
// if a deletion fails/errors, that delete request is caught by ermrestJS and returned
// as part of the deleteErrors object in the success cb
// NOTE: if one of the identifying values is empty or null, an error is thrown here
dispatchError({ error: err, isDismissible: true });
else {
setUnlinkPureBinaryModalProps(null);
updateRecordPage(true, LogReloadCauses.RELATED_BATCH_UNLINK);
}
})
.catch((err: Error) => {
setShowPureBinarySpinner(false);
// errors that land here would be execution of code errors
// if a deletion fails/errors, that delete request is caught by ermrestJS and returned
// as part of the deleteErrors object in the success cb
// NOTE: if one of the identifying values is empty or null, an error is thrown here
dispatchError({ error: err, isDismissible: true });
})
};

if (!CONFIRM_DELETE) {
return leafReference
.deleteBatchAssociationTuples(relatedModel.recordsetProps.parentTuple, selectedRows)
.then(deleteResponse)
.catch(deleteError);
return deleteTuples();
}

logRecordClientAction(LogActions.UNLINK_INTEND);
Expand All @@ -574,10 +567,7 @@ const RelatedTableActions = ({
title: 'Confirm Unlink',
onConfirm: () => {
setShowDeleteConfirmationModal(null);
return leafReference
.deleteBatchAssociationTuples(relatedModel.recordsetProps.parentTuple, selectedRows)
.then(deleteResponse)
.catch(deleteError);
return deleteTuples();
},
onCancel: () => {
setShowDeleteConfirmationModal(null);
Expand All @@ -588,6 +578,7 @@ const RelatedTableActions = ({
});
});
};

setUnlinkPureBinarySubmitCB(() => submitCB);

setUnlinkPureBinaryModalProps({
Expand All @@ -613,7 +604,7 @@ const RelatedTableActions = ({

let pureAndBinaryTitleComment;
if (usedRef.comment && usedRef.comment.displayMode === CommentDisplayModes.TOOLTIP) {
pureAndBinaryTitleComment= usedRef.comment;
pureAndBinaryTitleComment = usedRef.comment;
}

const mainTable = (
Expand Down
30 changes: 9 additions & 21 deletions test/e2e/specs/all-features/record/related-table.spec.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { expect, Page, test } from '@playwright/test';
import moment from 'moment';
import { test, expect, Page } from '@playwright/test';

//locators
import ModalLocators from '@isrd-isi-edu/chaise/test/e2e/locators/modal';
import RecordsetLocators from '@isrd-isi-edu/chaise/test/e2e/locators/recordset';
import RecordLocators from '@isrd-isi-edu/chaise/test/e2e/locators/record';
import RecordeditLocators, { RecordeditInputType } from '@isrd-isi-edu/chaise/test/e2e/locators/recordedit';
import RecordsetLocators from '@isrd-isi-edu/chaise/test/e2e/locators/recordset';

//utils
import { getCatalogID, getEntityRow, importACLs } from '@isrd-isi-edu/chaise/test/e2e/utils/catalog-utils';
import { APP_NAMES, RESTRICTED_USER_STORAGE_STATE } from '@isrd-isi-edu/chaise/test/e2e/utils/constants';
import { testTooltip } from '@isrd-isi-edu/chaise/test/e2e/utils/page-utils';
import {
testAddAssociationTable, testAddRelatedTable, testBatchUnlinkAssociationTable,
testRelatedTablePresentation, testShareCiteModal
} from '@isrd-isi-edu/chaise/test/e2e/utils/record-utils';
import { APP_NAMES, RESTRICTED_USER_STORAGE_STATE } from '@isrd-isi-edu/chaise/test/e2e/utils/constants';
import { testRecordsetTableRowValues, testTotalCount } from '@isrd-isi-edu/chaise/test/e2e/utils/recordset-utils';
import { testTooltip } from '@isrd-isi-edu/chaise/test/e2e/utils/page-utils';


const testParams = {
schemaName: 'product-unordered-related-tables-links',
Expand Down Expand Up @@ -414,23 +419,6 @@ test.describe('Related tables', () => {
await okBtn.click();
await expect.soft(confirmModal).not.toBeAttached();

// make sure summary modal shows up
const summaryModal = ModalLocators.getErrorModal(page);
await expect.soft(summaryModal).toBeVisible();
await expect.soft(ModalLocators.getModalTitle(summaryModal)).toHaveText('Batch Unlink Summary');
await expect.soft(ModalLocators.getModalText(summaryModal)).toHaveText(params.successPostDeleteMessage);

// close the summary modal
await ModalLocators.getCloseBtn(summaryModal).click();
await expect.soft(summaryModal).not.toBeAttached();

// make sure the recordset modal rows update
await expect.soft(RecordsetLocators.getRows(rsModal)).toHaveCount(params.rowValuesAfter.length);

// close the recordset modal
await ModalLocators.getCloseBtn(rsModal).click();
await expect.soft(rsModal).not.toBeAttached();

// make sure correct values are displayed
const currentEl = RecordLocators.getRelatedTableAccordion(page, params.displayname);
await testRecordsetTableRowValues(currentEl, params.rowValuesAfter, true);
Expand Down
23 changes: 3 additions & 20 deletions test/e2e/utils/record-utils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Locator, Page, TestInfo, expect, test } from '@playwright/test';

// locators
import RecordLocators from '@isrd-isi-edu/chaise/test/e2e/locators/record';
import RecordsetLocators from '@isrd-isi-edu/chaise/test/e2e/locators/recordset';
import ModalLocators from '@isrd-isi-edu/chaise/test/e2e/locators/modal';
import RecordLocators from '@isrd-isi-edu/chaise/test/e2e/locators/record';
import RecordeditLocators, { RecordeditInputType } from '@isrd-isi-edu/chaise/test/e2e/locators/recordedit';
import RecordsetLocators from '@isrd-isi-edu/chaise/test/e2e/locators/recordset';

import { getCatalogID, getEntityRow, EntityRowColumnValues } from '@isrd-isi-edu/chaise/test/e2e/utils/catalog-utils';
import { EntityRowColumnValues, getCatalogID, getEntityRow } from '@isrd-isi-edu/chaise/test/e2e/utils/catalog-utils';
import { APP_NAMES, PW_PROJECT_NAMES } from '@isrd-isi-edu/chaise/test/e2e/utils/constants';
import {
clickAndVerifyDownload, clickNewTabLink, getClipboardContent,
Expand Down Expand Up @@ -733,23 +733,6 @@ export const testBatchUnlinkAssociationTable = async (page: Page, params: BatchU
await okBtn.click();
await expect.soft(confirmModal).not.toBeAttached();

// make sure summary modal shows up
const summaryModal = ModalLocators.getErrorModal(page);
await expect.soft(summaryModal).toBeVisible();
await expect.soft(ModalLocators.getModalTitle(summaryModal)).toHaveText('Batch Unlink Summary');
await expect.soft(ModalLocators.getModalText(summaryModal)).toHaveText(params.postDeleteMessage);

// close the summary modal
await ModalLocators.getCloseBtn(summaryModal).click();
await expect.soft(summaryModal).not.toBeAttached();

// make sure the recordset modal rows update
await expect.soft(RecordsetLocators.getRows(rsModal)).toHaveCount(params.rowValuesAfter.length);

// close the recordset modal
await ModalLocators.getCloseBtn(rsModal).click();
await expect.soft(rsModal).not.toBeAttached();

// make sure correct values are displayed
const currentEl = RecordLocators.getRelatedTableContainer(page, params.displayname, params.isInline);
await testRecordsetTableRowValues(currentEl, params.rowValuesAfter, true);
Expand Down

0 comments on commit cedfb0e

Please sign in to comment.