Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(composite): onSave always include last dataContext on few inserts #1271

Merged
merged 1 commit into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,10 @@ describe('CompositeEditorService', () => {
jest.spyOn(dataViewStub, 'getItemCount').mockReturnValue(1);
jest.spyOn(dataViewStub, 'getItems').mockReturnValue([mockProduct1]);
const gridSrvAddItemSpy = jest.spyOn(gridServiceStub, 'addItem');
const saveSpy = jest.spyOn(gridStub.getEditController() as any, 'commitCurrentEdit');
(getEditControllerMock as any).commitCurrentEdit = () => {
gridStub.onAddNewRow.notify({ grid: gridStub, item: mockProduct2, column: columnsMock[0] });
return true;
};

const mockModalOptions = { headerTitle: 'Details', modalType: 'create' } as CompositeEditorOpenDetailOption;
component = new SlickCompositeEditorComponent();
Expand All @@ -1025,7 +1028,6 @@ describe('CompositeEditorService', () => {
gridStub.onCompositeEditorChange.notify({ row: 0, cell: 0, column: columnsMock[0], item: mockProduct2, formValues: { productName: 'test' }, editors: {}, grid: gridStub });

compositeFooterSaveBtnElm.click();
gridStub.onAddNewRow.notify({ grid: gridStub, item: mockProduct2, column: columnsMock[0] });

setTimeout(() => {
expect(component).toBeTruthy();
Expand All @@ -1037,7 +1039,6 @@ describe('CompositeEditorService', () => {
expect(productNameLabelElm.textContent).toBe('Product');
expect(productNameDetailCellElm.classList.contains('modified')).toBe(true);
expect(gridSrvAddItemSpy).toHaveBeenCalledWith({ ...mockProduct2, id: 2 }, undefined);
expect(saveSpy).toHaveBeenCalled();
done();
});
});
Expand Down Expand Up @@ -1148,10 +1149,13 @@ describe('CompositeEditorService', () => {
jest.spyOn(gridStub, 'getDataItem').mockReturnValue(mockNewProduct2);
jest.spyOn(dataViewStub, 'getItems').mockReturnValue([mockProduct1]);
const gridSrvAddItemSpy = jest.spyOn(gridServiceStub, 'addItem');
const saveSpy = jest.spyOn(gridStub.getEditController() as any, 'commitCurrentEdit');

(getEditControllerMock as any).commitCurrentEdit = () => {
gridStub.onAddNewRow.notify({ grid: gridStub, item: mockNewProduct2, column: columnsMock[0] });
return true;
};
const mockCreateOnSave = jest.fn();
mockCreateOnSave.mockResolvedValue(Promise.resolve(true));

const mockModalOptions = { headerTitle: 'Details', modalType: 'create', insertNewId: 3, onSave: mockCreateOnSave } as CompositeEditorOpenDetailOption;
component = new SlickCompositeEditorComponent();
component.init(gridStub, container);
Expand All @@ -1171,7 +1175,6 @@ describe('CompositeEditorService', () => {
gridStub.onCompositeEditorChange.notify({ row: 0, cell: 0, column: columnsMock[0], item: mockNewProduct2, formValues: { productName: 'test' }, editors: {}, grid: gridStub });

compositeFooterSaveBtnElm.click();
gridStub.onAddNewRow.notify({ grid: gridStub, item: mockNewProduct2, column: columnsMock[0] });

setTimeout(() => {
expect(component).toBeTruthy();
Expand All @@ -1183,7 +1186,6 @@ describe('CompositeEditorService', () => {
expect(productNameLabelElm.textContent).toBe('Product');
expect(productNameDetailCellElm.classList.contains('modified')).toBe(true);
expect(gridSrvAddItemSpy).toHaveBeenCalledWith({ ...mockNewProduct2, id: 3 }, undefined);
expect(saveSpy).toHaveBeenCalled();
expect(mockCreateOnSave).toHaveBeenCalledWith({ productName: 'test' }, { gridRowIndexes: [], dataContextIds: [] }, { ...mockNewProduct2, id: 3 });
done();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -500,9 +500,8 @@ export class SlickCompositeEditorComponent implements ExternalResource {

// when adding a new row to the grid, we need to invalidate that row and re-render the grid
this._eventHandler.subscribe(this.grid.onAddNewRow, (_e, args) => {
this.insertNewItemInDataView(args.item);
this._originalDataContext = args.item; // this becomes the new data context
this.dispose();
this._originalDataContext = this.insertNewItemInDataView(args.item); // this becomes the new data context
// this.disposeComponent();
});
}
return this;
Expand Down Expand Up @@ -917,7 +916,7 @@ export class SlickCompositeEditorComponent implements ExternalResource {
}

/** switch case handler to determine which code to execute depending on the modal type */
protected handleSaveClicked() {
protected async handleSaveClicked() {
const modalType = this._options?.modalType;
switch (modalType) {
case 'mass-update':
Expand Down Expand Up @@ -962,14 +961,18 @@ export class SlickCompositeEditorComponent implements ExternalResource {
// commit the changes into the grid
// if it's a "create" then it will triggered the "onAddNewRow" event which will in term push it to the grid
// while an "edit" will simply applies the changes directly on the same row
this.grid.getEditController()?.commitCurrentEdit();
let isFormValid = this.grid.getEditController()?.commitCurrentEdit();

// if the user provided the "onSave" callback, let's execute it with the item data context
if (typeof this._options?.onSave === 'function') {
const itemDataContext = this.grid.getDataItem(this._lastActiveRowNumber); // we can get item data context directly from DataView
this._options?.onSave(this.formValues, this.getCurrentRowSelections(), itemDataContext);
if (isFormValid && typeof this._options?.onSave === 'function') {
const itemDataContext = (modalType === 'create')
? this._originalDataContext // the inserted item was copied to our ref by the "onAddNewRow" event
: this.grid.getDataItem(this._lastActiveRowNumber); // for clone, we can get item data context directly from DataView
isFormValid = await this._options?.onSave(this.formValues, this.getCurrentRowSelections(), itemDataContext);
}
if (isFormValid) {
this.dispose(); // when the form is valid, we can close the modal
}

break;
}
}
Expand All @@ -985,6 +988,7 @@ export class SlickCompositeEditorComponent implements ExternalResource {
} else {
this.executeOnError({ type: 'error', code: 'ITEM_ALREADY_EXIST', message: `The item object which you are trying to add already exist with the same Id:: ${newId}` });
}
return item;
}

protected parseText(inputText: string, mappedArgs: any): string {
Expand Down
86 changes: 72 additions & 14 deletions test/cypress/e2e/example12.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,17 +241,64 @@ describe('Example 12 - Composite Editor Modal', () => {
cy.get('.item-details-container.editor-title .item-details-validation').contains('* This is a required field.');
});

it('should fill in the (Create Item) form inputs and expect a new row in the grid', () => {
it('should fill in the (Create Item) as Task 7777 and expect a new row in the grid', () => {
cy.get('textarea').type('Task 7777');
cy.get('.item-details-container.editor-title .item-details-validation').should('be.empty');
cy.get('.item-details-container.editor-title .modified').should('have.length', 1);

cy.get('.item-details-editor-container .slider-editor-input.editor-percentComplete').as('range').invoke('val', 44).trigger('change', { force: true });
cy.get('.item-details-editor-container .input-group-text').contains('44');
cy.get('.item-details-container.editor-percentComplete .modified').should('have.length', 1);

cy.get('.item-details-container.editor-product .autocomplete').type('sleek');
cy.get('.slick-autocomplete.autocomplete-custom-four-corners').should('be.visible');
cy.get('.slick-autocomplete.autocomplete-custom-four-corners').find('div:nth(0)').click();
cy.get('.item-details-container.editor-product .modified').should('have.length', 1);

cy.get('.item-details-container.editor-duration .editor-text').type('33');
cy.get('.item-details-container.editor-duration .modified').should('have.length', 1);

cy.get('.item-details-container.editor-origin .autocomplete').type('au');
cy.get('.slick-autocomplete:visible').find('div:nth(1)').click();
cy.get('.item-details-container.editor-origin .autocomplete').invoke('val').then(text => expect(text).to.eq('Austria'));
cy.get('.item-details-container.editor-origin .modified').should('have.length', 1);

cy.get('.btn-save').contains('Save').click();
cy.get('.slick-editor-modal').should('not.exist');

cy.window().then((win) => {
expect(win.console.log).to.be.calledWithMatch('create item data context', {
id: 501, title: 'Task 7777', completed: false, complexity: '', duration: 33, finish: '',
percentComplete: 44, start: '', origin: { name: 'Austria', code: 'AT' },
product: { id: 0, icon: 'mdi-arrow-collapse', itemName: 'Sleek Metal Computer', itemTypeName: 'I', listPrice: 2100.23 },
});
});
});

it('should have new TASK 7777 displayed on first row', () => {
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(1)`).contains('TASK 7777', { matchCase: false });
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(2)`).should('contain', '33 days');
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(4)`).should('contain', '44');
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(5)`).find('.editing-field').should('have.length', 1);
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(7)`).find('.mdi.mdi-check.checkmark-icon').should('have.length', 0);
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(8)`).should('be.empty');
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(9)`).should('contain', 'Sleek Metal Computer');

// next few rows Title should be unchanged
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(1)`).contains('TASK 0', { matchCase: false });
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(1)`).contains('TASK 1111', { matchCase: false });
});

it('should fill in the (Create Item) form inputs with Task 8888 and expect a new row in the grid', () => {
cy.get('[data-test="open-modal-create-btn"]').click();
cy.get('.slick-editor-modal-title').contains('Inserting New Task');

cy.get('textarea').type('Task');
cy.get('.item-details-container.editor-title .item-details-validation').contains('* Your title is invalid, it must start with "Task" followed by a number.');
cy.get('textarea').type(' 8888');
cy.get('.item-details-container.editor-title .item-details-validation').should('be.empty');
cy.get('.item-details-container.editor-title .modified').should('have.length', 1);

// cy.get('.slick-large-editor-text.editor-title')
// .should('have.css', 'border')
// .and('contain', `solid ${UNSAVED_RGB_COLOR}`);

cy.get('.item-details-editor-container .slider-editor-input.editor-percentComplete').as('range').invoke('val', 5).trigger('change', { force: true });
cy.get('.item-details-editor-container .input-group-text').contains('5');
cy.get('.item-details-container.editor-percentComplete .modified').should('have.length', 1);
Expand Down Expand Up @@ -279,6 +326,14 @@ describe('Example 12 - Composite Editor Modal', () => {

cy.get('.btn-save').contains('Save').click();
cy.get('.slick-editor-modal').should('not.exist');

cy.window().then((win) => {
expect(win.console.log).to.be.calledWithMatch('create item data context', {
id: 502, title: 'Task 8888', completed: true, complexity: '', duration: 22, percentComplete: 5,
start: '', origin: { name: 'Antarctica', code: 'AQ' },
product: { id: 1, icon: 'mdi-arrow-expand', itemName: 'Tasty Granite Table', itemTypeName: 'I', listPrice: 3200.12 },
});
});
});

it('should have new TASK 8888 displayed on first row', () => {
Expand All @@ -291,14 +346,16 @@ describe('Example 12 - Composite Editor Modal', () => {
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(9)`).should('contain', 'Tasty Granite Table');

// next few rows Title should be unchanged
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(1)`).contains('TASK 0', { matchCase: false });
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(1)`).contains('TASK 1111', { matchCase: false });
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(1)`).contains('TASK 8888', { matchCase: false });
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(1)`).contains('TASK 7777', { matchCase: false });
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(1)`).contains('TASK 0', { matchCase: false });
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 3}px;"] > .slick-cell:nth(1)`).contains('TASK 1111', { matchCase: false });
});

it('should open the Composite Editor (Edit Item) and expect all form inputs to be filled with TASK 8888 data of previous create item', () => {
it('should open the Composite Editor (Edit Item) and expect all form inputs to be filled with TASK 8888 data of previously created item', () => {
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(3)`).click({ force: true });
cy.get('[data-test="open-modal-edit-btn"]').click();
cy.get('.slick-editor-modal-title').contains('Editing - Task 8888 (id: 501)');
cy.get('.slick-editor-modal-title').contains('Editing - Task 8888 (id: 502)');

cy.get('textarea').contains('Task 8888').type('Task 8899');
cy.get('.item-details-editor-container .slider-editor-input.editor-percentComplete').as('range').invoke('val', 7).trigger('change', { force: true });
Expand All @@ -325,15 +382,16 @@ describe('Example 12 - Composite Editor Modal', () => {
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(9)`).should('contain', 'Tasty Granite Table');

// next few rows Title should be unchanged
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(1)`).contains('TASK 0', { matchCase: false });
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(1)`).contains('TASK 1111', { matchCase: false });
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 1}px;"] > .slick-cell:nth(1)`).contains('TASK 7777', { matchCase: false });
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 2}px;"] > .slick-cell:nth(1)`).contains('TASK 0', { matchCase: false });
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 3}px;"] > .slick-cell:nth(1)`).contains('TASK 1111', { matchCase: false });
});

it('should open the Composite Editor (Mass Update) and be able to change some of the inputs in the form', () => {
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(3)`).click();
cy.get('[data-test="open-modal-mass-update-btn"]').wait(200).click();
cy.get('.slick-editor-modal-title').should('contain', 'Mass Update All Records');
cy.get('.footer-status-text').should('contain', 'All 501 records selected');
cy.get('.footer-status-text').should('contain', 'All 502 records selected');

cy.get('.item-details-editor-container .editor-checkbox').check();
cy.get('.item-details-container.editor-completed .modified').should('have.length', 1);
Expand Down Expand Up @@ -393,7 +451,7 @@ describe('Example 12 - Composite Editor Modal', () => {
cy.get(`[style="top: ${GRID_ROW_HEIGHT * 0}px;"] > .slick-cell:nth(3)`).click();
cy.get('[data-test="open-modal-mass-update-btn"]').wait(200).click();
cy.get('.slick-editor-modal-title').should('contain', 'Mass Update All Records');
cy.get('.footer-status-text').should('contain', 'All 501 records selected');
cy.get('.footer-status-text').should('contain', 'All 502 records selected');

cy.get('.item-details-editor-container .editor-checkbox').check();
cy.get('.item-details-container.editor-completed .modified').should('have.length', 1);
Expand Down Expand Up @@ -449,7 +507,7 @@ describe('Example 12 - Composite Editor Modal', () => {

it('should be able to open the Composite Editor (Mass Selection) and be able to change some of the inputs in the form', () => {
cy.get('.slick-editor-modal-title').should('contain', 'Update Selected Records');
cy.get('.footer-status-text').should('contain', '2 of 501 selected');
cy.get('.footer-status-text').should('contain', '2 of 502 selected');

cy.get('.item-details-editor-container .editor-checkbox').check();
cy.get('.item-details-container.editor-completed .modified').should('have.length', 1);
Expand Down