inline edit confirm unsaved switch to another field
This commit is contained in:
@@ -390,6 +390,7 @@
|
||||
"massRemoveResult": "{count} records have been removed",
|
||||
"massRemoveResultSingle": "{count} record has been removed",
|
||||
"noRecordsRemoved": "No records were removed",
|
||||
"changesLossConfirmation": "Unsaved changes will be lost. Are you sure?",
|
||||
"clickToRefresh": "Click to refresh",
|
||||
"writeYourCommentHere": "Write your comment here",
|
||||
"writeMessageToUser": "Write a message to {user}",
|
||||
|
||||
@@ -35,6 +35,14 @@ import {Events} from 'bullbone';
|
||||
*/
|
||||
class ViewRecordHelper {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {{
|
||||
* isChanged: boolean,
|
||||
* }}
|
||||
*/
|
||||
state
|
||||
|
||||
/**
|
||||
* @param {Object.<string, *>} [defaultFieldStates] Default field states.
|
||||
* @param {Object.<string, *>} [defaultPanelStates] Default panel states.
|
||||
@@ -61,6 +69,10 @@ class ViewRecordHelper {
|
||||
this.hiddenPanels = {};
|
||||
/** @private */
|
||||
this.fieldOptionListMap = {};
|
||||
|
||||
this.state = {
|
||||
isChanged: false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,6 +221,26 @@ class ViewRecordHelper {
|
||||
hasFieldOptionList(field) {
|
||||
return (field in this.fieldOptionListMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is changed.
|
||||
*
|
||||
* @return {boolean}
|
||||
* @since 9.2.0
|
||||
*/
|
||||
isChanged() {
|
||||
return this.state.isChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set is changed.
|
||||
*
|
||||
* @param {boolean} isChanged
|
||||
* @since 9.2.0
|
||||
*/
|
||||
setIsChanged(isChanged) {
|
||||
this.state.isChanged = isChanged;
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(ViewRecordHelper.prototype, Events);
|
||||
|
||||
@@ -1411,64 +1411,65 @@ class BaseFieldView extends View {
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
inlineEdit() {
|
||||
async inlineEdit() {
|
||||
if (this.recordHelper && this.recordHelper.isChanged()) {
|
||||
await this.confirm(this.translate('changesLossConfirmation', 'messages'));
|
||||
}
|
||||
|
||||
this.trigger('edit', this);
|
||||
|
||||
this.initialAttributes = this.model.getClonedAttributes();
|
||||
|
||||
this._isInlineEditMode = true;
|
||||
|
||||
const promise = this.setEditMode()
|
||||
.then(() => this.reRender(true))
|
||||
.then(() => this.addInlineEditLinks())
|
||||
.then(() => {
|
||||
this.$el.on('keydown.inline-edit', e => {
|
||||
const key = Espo.Utils.getKeyFromKeyEvent(e);
|
||||
|
||||
if (key === 'Control+Enter') {
|
||||
e.stopPropagation();
|
||||
|
||||
if (document.activeElement instanceof HTMLInputElement) {
|
||||
// Fields may need to fetch data first.
|
||||
document.activeElement.dispatchEvent(new Event('change', {bubbles: true}));
|
||||
}
|
||||
|
||||
this.fetchToModel();
|
||||
this.inlineEditSave();
|
||||
|
||||
setTimeout(() => {
|
||||
this.get$cell().focus();
|
||||
}, 100);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (key === 'Escape') {
|
||||
e.stopPropagation();
|
||||
|
||||
this.inlineEditClose()
|
||||
.then(() => {
|
||||
this.get$cell().focus();
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (key === 'Control+KeyS') {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.fetchToModel();
|
||||
this.inlineEditSave({bypassClose: true});
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => this.focusOnInlineEdit(), 10);
|
||||
});
|
||||
|
||||
this.trigger('inline-edit-on');
|
||||
|
||||
return promise;
|
||||
await this.setEditMode();
|
||||
await this.reRender(true);
|
||||
await this.addInlineEditLinks();
|
||||
|
||||
this.$el.on('keydown.inline-edit', e => {
|
||||
const key = Espo.Utils.getKeyFromKeyEvent(e);
|
||||
|
||||
if (key === 'Control+Enter') {
|
||||
e.stopPropagation();
|
||||
|
||||
if (document.activeElement instanceof HTMLInputElement) {
|
||||
// Fields may need to fetch data first.
|
||||
document.activeElement.dispatchEvent(new Event('change', {bubbles: true}));
|
||||
}
|
||||
|
||||
this.fetchToModel();
|
||||
this.inlineEditSave();
|
||||
|
||||
setTimeout(() => {
|
||||
this.get$cell().focus();
|
||||
}, 100);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (key === 'Escape') {
|
||||
e.stopPropagation();
|
||||
|
||||
this.inlineEditClose()
|
||||
.then(() => {
|
||||
this.get$cell().focus();
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (key === 'Control+KeyS') {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.fetchToModel();
|
||||
this.inlineEditSave({bypassClose: true});
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => this.focusOnInlineEdit(), 10);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2304,6 +2304,7 @@ class DetailRecordView extends BaseRecordView {
|
||||
|
||||
setIsChanged() {
|
||||
this.isChanged = true;
|
||||
this.recordHelper.setIsChanged(true);
|
||||
|
||||
if (this.confirmLeaveDisabled) {
|
||||
return;
|
||||
@@ -2314,6 +2315,7 @@ class DetailRecordView extends BaseRecordView {
|
||||
|
||||
setIsNotChanged() {
|
||||
this.isChanged = false;
|
||||
this.recordHelper.setIsChanged(false);
|
||||
|
||||
if (this.confirmLeaveDisabled) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user