mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Adding confirmation before remove last widget for a table
Summary: When last widget for a table is removed, user is informed about that and can decide between removing the widget and removing both table and widget Test Plan: Updated Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D4295
This commit is contained in:
@@ -178,9 +178,7 @@ describe('SelectBySummary', function() {
|
||||
|
||||
it('should filter a summary table selected by a less detailed summary table', async function() {
|
||||
// Delete the Table1 widget so that we can hide the table in ACL without hiding the whole page.
|
||||
const menu = await gu.openSectionMenu('viewLayout', 'TABLE1');
|
||||
await menu.findContent('.test-cmd-name', 'Delete widget').click();
|
||||
await gu.waitForServer();
|
||||
await gu.deleteWidget('TABLE1');
|
||||
|
||||
// Open the ACL UI
|
||||
await driver.find('.test-tools-access-rules').click();
|
||||
|
||||
@@ -761,6 +761,96 @@ describe("ViewLayoutCollapse", function() {
|
||||
await gu.checkForErrors();
|
||||
});
|
||||
|
||||
it('should prompt when last section is removed from tray', async () => {
|
||||
const revert = await gu.begin();
|
||||
|
||||
// Add brand new table and collapse it.
|
||||
await gu.addNewSection('Table', 'New Table', {tableName: 'ToCollapse'});
|
||||
await collapseByMenu('ToCollapse');
|
||||
|
||||
// Now try to remove it, we should see prompt.
|
||||
await openCollapsedSectionMenu('ToCollapse');
|
||||
await driver.find('.test-section-delete').click();
|
||||
assert.match(
|
||||
await driver.find('.test-modal-title').getText(),
|
||||
/Table ToCollapse will no longer be visible/
|
||||
);
|
||||
|
||||
// Select first option, to delete both table and widget.
|
||||
await driver.find('.test-option-deleteDataAndWidget').click();
|
||||
await driver.find('.test-modal-confirm').click();
|
||||
await gu.waitForServer();
|
||||
|
||||
// Make sure it is removed.
|
||||
assert.deepEqual(await collapsedSectionTitles(), []);
|
||||
assert.deepEqual(await visibleTables(), ['Companies', 'Investments']);
|
||||
await gu.sendKeys(Key.ESCAPE);
|
||||
|
||||
// Single undo should add it back.
|
||||
await gu.undo();
|
||||
assert.deepEqual(await collapsedSectionTitles(), ['TOCOLLAPSE']);
|
||||
assert.deepEqual(await visibleTables(), ['Companies', 'Investments', 'ToCollapse']);
|
||||
|
||||
// Now do the same but, keep data.
|
||||
await openCollapsedSectionMenu('ToCollapse');
|
||||
await driver.find('.test-section-delete').click();
|
||||
await driver.findWait('.test-modal-dialog', 100);
|
||||
await driver.find('.test-option-deleteOnlyWidget').click();
|
||||
await driver.find('.test-modal-confirm').click();
|
||||
await gu.waitForServer();
|
||||
|
||||
// Make sure it is removed.
|
||||
assert.deepEqual(await collapsedSectionTitles(), []);
|
||||
assert.deepEqual(await visibleTables(), ['Companies', 'Investments', 'ToCollapse']);
|
||||
|
||||
// Test single undo.
|
||||
await gu.undo();
|
||||
assert.deepEqual(await collapsedSectionTitles(), ['TOCOLLAPSE']);
|
||||
assert.deepEqual(await visibleTables(), ['Companies', 'Investments', 'ToCollapse']);
|
||||
|
||||
// Uncollapse it, and do the same with normal section.
|
||||
await addToMainByMenu('ToCollapse');
|
||||
|
||||
// Now try to remove it, we should see prompt.
|
||||
assert.include(
|
||||
await driver.findAll('.test-viewsection-title', e => e.getText()), 'TOCOLLAPSE');
|
||||
|
||||
await gu.openSectionMenu('viewLayout', 'ToCollapse');
|
||||
await driver.find('.test-section-delete').click();
|
||||
await driver.findWait('.test-modal-dialog', 100);
|
||||
await driver.find('.test-option-deleteOnlyWidget').click();
|
||||
await driver.find('.test-modal-confirm').click();
|
||||
await gu.waitForServer();
|
||||
assert.notInclude(
|
||||
await driver.findAll('.test-viewsection-title', e => e.getText()), 'TOCOLLAPSE');
|
||||
assert.deepEqual(await visibleTables(), ['Companies', 'Investments', 'ToCollapse']);
|
||||
// Test undo.
|
||||
await gu.undo();
|
||||
assert.include(
|
||||
await driver.findAll('.test-viewsection-title', e => e.getText()), 'TOCOLLAPSE');
|
||||
|
||||
// Do the same but delete data and widget.
|
||||
await gu.openSectionMenu('viewLayout', 'ToCollapse');
|
||||
await driver.find('.test-section-delete').click();
|
||||
await driver.findWait('.test-modal-dialog', 100);
|
||||
await driver.find('.test-option-deleteDataAndWidget').click();
|
||||
await driver.find('.test-modal-confirm').click();
|
||||
await gu.waitForServer();
|
||||
|
||||
// Make sure it is removed.
|
||||
assert.notInclude(
|
||||
await driver.findAll('.test-viewsection-title', e => e.getText()), 'TOCOLLAPSE');
|
||||
assert.deepEqual(await visibleTables(), ['Companies', 'Investments']);
|
||||
|
||||
// Test undo.
|
||||
await gu.undo();
|
||||
assert.include(
|
||||
await driver.findAll('.test-viewsection-title', e => e.getText()), 'TOCOLLAPSE');
|
||||
assert.deepEqual(await visibleTables(), ['Companies', 'Investments', 'ToCollapse']);
|
||||
|
||||
await revert();
|
||||
});
|
||||
|
||||
it("should switch active section when collapsed", async () => {
|
||||
const revert = await gu.begin();
|
||||
await gu.selectSectionByTitle(gu.exactMatch(COMPANIES));
|
||||
@@ -989,3 +1079,11 @@ async function waitForSave() {
|
||||
await gu.waitForServer();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
async function visibleTables() {
|
||||
await driver.findWait('.test-dp-add-new', 2000).doClick();
|
||||
await driver.find('.test-dp-add-new-page').doClick();
|
||||
const titles = await driver.findAll('.test-wselect-table', e => e.getText());
|
||||
await gu.sendKeys(Key.ESCAPE);
|
||||
return titles.map(x => x.trim()).filter(Boolean).filter(x => x !== 'New Table');
|
||||
}
|
||||
|
||||
@@ -113,8 +113,7 @@ describe('Views.ntest', function() {
|
||||
await gu.waitForServer();
|
||||
await gu.actions.viewSection('TABLE4').selectSection();
|
||||
// Delete the section
|
||||
await gu.actions.viewSection('TABLE4').selectMenuOption('viewLayout', 'Delete widget');
|
||||
await gu.waitForServer();
|
||||
await gu.deleteWidget('TABLE4');
|
||||
// Assert that the default section (Table1 record) is now active.
|
||||
assert.equal(await $('.active_section > .viewsection_title').text(), 'TABLE1');
|
||||
// Assert that focus is returned to the deleted section on undo.
|
||||
|
||||
@@ -3791,6 +3791,19 @@ export async function waitForAccessDenied() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a widget by title. Optionally confirms deletion only for the widget without the data.
|
||||
*/
|
||||
export async function deleteWidget(title: string) {
|
||||
const menu = await openSectionMenu('viewLayout', title);
|
||||
await menu.findContent('.test-cmd-name', 'Delete widget').click();
|
||||
if (await driver.findWait('.test-option-deleteOnlyWidget', 100).isPresent()) {
|
||||
await driver.find('.test-option-deleteOnlyWidget').click();
|
||||
await driver.find('.test-modal-confirm').click();
|
||||
}
|
||||
await waitForServer();
|
||||
}
|
||||
|
||||
} // end of namespace gristUtils
|
||||
|
||||
stackWrapOwnMethods(gristUtils);
|
||||
|
||||
Reference in New Issue
Block a user