gr-email-editor: improve unsaved changes detection
Release-Notes: gr-email-editor: improve unsaved changes detection
Change-Id: I87b35b5ca7d4e50037ff9e2d6005db7a9ee18b88
diff --git a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.ts b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.ts
index 9c99ae0..634b17a 100644
--- a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.ts
+++ b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.ts
@@ -8,15 +8,16 @@
import {EmailInfo} from '../../../types/common';
import {getAppContext} from '../../../services/app-context';
import {LitElement, css, html} from 'lit';
-import {customElement, property, state} from 'lit/decorators.js';
+import {customElement, state} from 'lit/decorators.js';
import {sharedStyles} from '../../../styles/shared-styles';
import {grFormStyles} from '../../../styles/gr-form-styles';
import {ValueChangedEvent} from '../../../types/events';
import {fire} from '../../../utils/event-util';
+import {notDeepEqual} from '../../../utils/deep-util';
@customElement('gr-email-editor')
export class GrEmailEditor extends LitElement {
- @property({type: Boolean}) hasUnsavedChanges = false;
+ @state() private originalEmails: EmailInfo[] = [];
/* private but used in test */
@state() emails: EmailInfo[] = [];
@@ -110,7 +111,8 @@
loadData() {
return this.restApiService.getAccountEmails().then(emails => {
- this.emails = emails ?? [];
+ this.originalEmails = emails ?? [];
+ this.emails = emails ? [...emails] : [];
});
}
@@ -128,9 +130,10 @@
}
return Promise.all(promises).then(() => {
+ this.originalEmails = this.emails;
this.emailsToRemove = [];
this.newPreferred = '';
- this.setHasUnsavedChanges(false);
+ this.setHasUnsavedChanges();
});
}
@@ -141,10 +144,12 @@
if (indexStr === null) return;
const index = Number(indexStr);
const email = this.emails[index];
- this.emailsToRemove = [...this.emailsToRemove, email];
+ // Don't add project to emailsToRemove if it wasn't in
+ // originalEmails.
+ if (this.originalEmails.includes(email)) this.emailsToRemove.push(email);
this.emails.splice(index, 1);
this.requestUpdate();
- this.setHasUnsavedChanges(true);
+ this.setHasUnsavedChanges();
}
private handlePreferredControlClick(e: Event) {
@@ -165,7 +170,7 @@
this.emails[i].preferred = true;
this.requestUpdate();
this.newPreferred = preferred;
- this.setHasUnsavedChanges(true);
+ this.setHasUnsavedChanges();
} else if (this.emails[i].preferred) {
this.emails[i].preferred = false;
this.requestUpdate();
@@ -177,9 +182,11 @@
return preferred ?? false;
}
- private setHasUnsavedChanges(value: boolean) {
- this.hasUnsavedChanges = value;
- fire(this, 'has-unsaved-changes-changed', {value});
+ private setHasUnsavedChanges() {
+ const hasUnsavedChanges =
+ notDeepEqual(this.originalEmails, this.emails) ||
+ this.emailsToRemove.length > 0;
+ fire(this, 'has-unsaved-changes-changed', {value: hasUnsavedChanges});
}
}
diff --git a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.ts b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.ts
index 25c9b97..39c3288 100644
--- a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.ts
+++ b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.ts
@@ -123,6 +123,12 @@
});
test('renders', () => {
+ const hasUnsavedChangesSpy = sinon.spy();
+ element.addEventListener(
+ 'has-unsaved-changes-changed',
+ hasUnsavedChangesSpy
+ );
+
const rows = element
.shadowRoot!.querySelector('table')!
.querySelectorAll('tbody tr');
@@ -144,15 +150,21 @@
);
assert.isNotOk(rows[2].querySelector('gr-button')!.disabled);
- assert.isFalse(element.hasUnsavedChanges);
+ assert.isFalse(hasUnsavedChangesSpy.called);
});
test('edit preferred', () => {
+ const hasUnsavedChangesSpy = sinon.spy();
+ element.addEventListener(
+ 'has-unsaved-changes-changed',
+ hasUnsavedChangesSpy
+ );
+
const radios = element
.shadowRoot!.querySelector('table')!
.querySelectorAll<HTMLInputElement>('input[type=radio]');
- assert.isFalse(element.hasUnsavedChanges);
+ assert.isFalse(hasUnsavedChangesSpy.called);
assert.isNotOk(element.newPreferred);
assert.equal(element.emailsToRemove.length, 0);
assert.equal(element.emails.length, 3);
@@ -162,7 +174,7 @@
radios[0].click();
- assert.isTrue(element.hasUnsavedChanges);
+ assert.isTrue(hasUnsavedChangesSpy.called);
assert.isOk(element.newPreferred);
assert.equal(element.emailsToRemove.length, 0);
assert.equal(element.emails.length, 3);
@@ -172,18 +184,24 @@
});
test('delete email', () => {
+ const hasUnsavedChangesSpy = sinon.spy();
+ element.addEventListener(
+ 'has-unsaved-changes-changed',
+ hasUnsavedChangesSpy
+ );
+
const buttons = element
.shadowRoot!.querySelector('table')!
.querySelectorAll('gr-button');
- assert.isFalse(element.hasUnsavedChanges);
+ assert.isFalse(hasUnsavedChangesSpy.called);
assert.isNotOk(element.newPreferred);
assert.equal(element.emailsToRemove.length, 0);
assert.equal(element.emails.length, 3);
buttons[2].click();
- assert.isTrue(element.hasUnsavedChanges);
+ assert.isTrue(hasUnsavedChangesSpy.called);
assert.isNotOk(element.newPreferred);
assert.equal(element.emailsToRemove.length, 1);
assert.equal(element.emails.length, 2);
@@ -192,6 +210,12 @@
});
test('save changes', async () => {
+ const hasUnsavedChangesSpy = sinon.spy();
+ element.addEventListener(
+ 'has-unsaved-changes-changed',
+ hasUnsavedChangesSpy
+ );
+
const deleteEmailSpy = spyRestApi('deleteAccountEmail');
const setPreferredSpy = spyRestApi('setPreferredAccountEmail');
@@ -199,7 +223,7 @@
.shadowRoot!.querySelector('table')!
.querySelectorAll('tbody tr');
- assert.isFalse(element.hasUnsavedChanges);
+ assert.isFalse(hasUnsavedChangesSpy.called);
assert.isNotOk(element.newPreferred);
assert.equal(element.emailsToRemove.length, 0);
assert.equal(element.emails.length, 3);
@@ -208,7 +232,8 @@
rows[0].querySelector('gr-button')!.click();
rows[2].querySelector<HTMLInputElement>('input[type=radio]')!.click();
- assert.isTrue(element.hasUnsavedChanges);
+ assert.isTrue(hasUnsavedChangesSpy.called);
+ assert.isTrue(hasUnsavedChangesSpy.lastCall.args[0].detail.value);
assert.equal(element.newPreferred, 'email@three.com');
assert.equal(element.emailsToRemove.length, 1);
assert.equal(element.emailsToRemove[0].email, 'email@one.com');
@@ -219,5 +244,6 @@
assert.equal(deleteEmailSpy.getCall(0).args[0], 'email@one.com');
assert.isTrue(setPreferredSpy.called);
assert.equal(setPreferredSpy.getCall(0).args[0], 'email@three.com');
+ assert.isFalse(hasUnsavedChangesSpy.lastCall.args[0].detail.value);
});
});
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
index 7ad0bef..e1ce5cc 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
@@ -462,7 +462,6 @@
<fieldset id="email">
<gr-email-editor
id="emailEditor"
- ?hasUnsavedChanges=${this.emailsChanged}
@has-unsaved-changes-changed=${(
e: ValueChangedEvent<boolean>
) => {