Merge pull request #1075 from ONLYOFFICE/feature/de-review
Feature/de review
This commit is contained in:
commit
43491e0115
|
@ -136,7 +136,8 @@
|
|||
label: string (default: "Guest") // postfix for user name
|
||||
},
|
||||
review: {
|
||||
hideReviewDisplay: false // hide button Review mode
|
||||
hideReviewDisplay: false, // hide button Review mode
|
||||
hoverMode: false // true - show review balloons on mouse move, not on click on text
|
||||
},
|
||||
chat: true,
|
||||
comments: true,
|
||||
|
@ -155,7 +156,7 @@
|
|||
compactHeader: false,
|
||||
toolbarNoTabs: false,
|
||||
toolbarHideFileName: false,
|
||||
reviewDisplay: 'original',
|
||||
reviewDisplay: 'original', // original for viewer, markup for editor
|
||||
spellcheck: true,
|
||||
compatibleFeatures: false,
|
||||
unit: 'cm' // cm, pt, inch,
|
||||
|
|
|
@ -1185,7 +1185,8 @@ define([
|
|||
renderTo : this.sdkViewName,
|
||||
canRequestUsers: (this.mode) ? this.mode.canRequestUsers : undefined,
|
||||
canRequestSendNotify: (this.mode) ? this.mode.canRequestSendNotify : undefined,
|
||||
mentionShare: (this.mode) ? this.mode.mentionShare : true
|
||||
mentionShare: (this.mode) ? this.mode.mentionShare : true,
|
||||
api: this.api
|
||||
});
|
||||
this.popover.setCommentsStore(this.popoverComments);
|
||||
}
|
||||
|
|
|
@ -131,8 +131,7 @@ define([
|
|||
this.api.asc_registerCallback('asc_onUpdateRevisionsChangesPosition', _.bind(this.onApiUpdateChangePosition, this));
|
||||
this.api.asc_registerCallback('asc_onAuthParticipantsChanged', _.bind(this.onAuthParticipantsChanged, this));
|
||||
this.api.asc_registerCallback('asc_onParticipantsChanged', _.bind(this.onAuthParticipantsChanged, this));
|
||||
this.api.asc_registerCallback('asc_onBeginViewModeInReview', _.bind(this.onBeginViewModeInReview, this));
|
||||
this.api.asc_registerCallback('asc_onEndViewModeInReview', _.bind(this.onEndViewModeInReview, this));
|
||||
this.api.asc_registerCallback('asc_onChangeDisplayModeInReview', _.bind(this.onChangeDisplayModeInReview, this));
|
||||
}
|
||||
if (this.appConfig.canReview)
|
||||
this.api.asc_registerCallback('asc_onOnTrackRevisionsChange', _.bind(this.onApiTrackRevisionsChange, this));
|
||||
|
@ -181,7 +180,7 @@ define([
|
|||
|
||||
onApiShowChange: function (sdkchange) {
|
||||
if (this.getPopover()) {
|
||||
if (sdkchange && sdkchange.length>0) {
|
||||
if (!this.appConfig.reviewHoverMode && sdkchange && sdkchange.length>0) {
|
||||
var i = 0,
|
||||
changes = this.readSDKChange(sdkchange),
|
||||
posX = sdkchange[0].get_X(),
|
||||
|
@ -256,7 +255,8 @@ define([
|
|||
if ((this.appConfig.canReview || this.appConfig.canViewReview) && _.isUndefined(this.popover)) {
|
||||
this.popover = Common.Views.ReviewPopover.prototype.getPopover({
|
||||
reviewStore : this.popoverChanges,
|
||||
renderTo : this.sdkViewName
|
||||
renderTo : this.sdkViewName,
|
||||
api: this.api
|
||||
});
|
||||
this.popover.setReviewStore(this.popoverChanges);
|
||||
}
|
||||
|
@ -595,7 +595,10 @@ define([
|
|||
|
||||
onReviewViewClick: function(menu, item, e) {
|
||||
this.turnDisplayMode(item.value);
|
||||
!this.appConfig.canReview && Common.localStorage.setItem(this.view.appPrefix + "review-mode", item.value);
|
||||
if (!this.appConfig.isEdit && !this.appConfig.isRestrictedEdit)
|
||||
Common.localStorage.setItem(this.view.appPrefix + "review-mode", item.value); // for viewer
|
||||
else if (item.value=='markup' || item.value=='simple')
|
||||
Common.localStorage.setItem(this.view.appPrefix + "review-mode-editor", item.value); // for editor save only markup modes
|
||||
Common.NotificationCenter.trigger('edit:complete', this.view);
|
||||
},
|
||||
|
||||
|
@ -685,27 +688,40 @@ define([
|
|||
|
||||
turnDisplayMode: function(mode) {
|
||||
if (this.api) {
|
||||
if (mode === 'final')
|
||||
this.api.asc_BeginViewModeInReview(true);
|
||||
else if (mode === 'original')
|
||||
this.api.asc_BeginViewModeInReview(false);
|
||||
else
|
||||
this.api.asc_EndViewModeInReview();
|
||||
var type = Asc.c_oAscDisplayModeInReview.Edit;
|
||||
switch (mode) {
|
||||
case 'final':
|
||||
type = Asc.c_oAscDisplayModeInReview.Final;
|
||||
break;
|
||||
case 'original':
|
||||
type = Asc.c_oAscDisplayModeInReview.Original;
|
||||
break;
|
||||
case 'simple':
|
||||
type = Asc.c_oAscDisplayModeInReview.Simple;
|
||||
break;
|
||||
}
|
||||
this.api.asc_SetDisplayModeInReview(type);
|
||||
}
|
||||
this.disableEditing(mode == 'final' || mode == 'original');
|
||||
this._state.previewMode = (mode == 'final' || mode == 'original');
|
||||
},
|
||||
|
||||
onBeginViewModeInReview: function(mode) {
|
||||
this.disableEditing(true);
|
||||
this.view && this.view.turnDisplayMode(mode ? 'final' : 'original');
|
||||
this._state.previewMode = true;
|
||||
},
|
||||
|
||||
onEndViewModeInReview: function() {
|
||||
this.disableEditing(false);
|
||||
this.view && this.view.turnDisplayMode('markup');
|
||||
this._state.previewMode = false;
|
||||
onChangeDisplayModeInReview: function(type) {
|
||||
this.disableEditing(type===Asc.c_oAscDisplayModeInReview.Final || type===Asc.c_oAscDisplayModeInReview.Original);
|
||||
var mode = 'markup';
|
||||
switch (type) {
|
||||
case Asc.c_oAscDisplayModeInReview.Final:
|
||||
mode = 'final';
|
||||
break;
|
||||
case Asc.c_oAscDisplayModeInReview.Original:
|
||||
mode = 'original';
|
||||
break;
|
||||
case Asc.c_oAscDisplayModeInReview.Simple:
|
||||
mode = 'simple';
|
||||
break;
|
||||
}
|
||||
this.view && this.view.turnDisplayMode(mode);
|
||||
this._state.previewMode = (type===Asc.c_oAscDisplayModeInReview.Final || type===Asc.c_oAscDisplayModeInReview.Original);
|
||||
},
|
||||
|
||||
isPreviewChangesMode: function() {
|
||||
|
@ -804,7 +820,11 @@ define([
|
|||
me.onApiTrackRevisionsChange(me.api.asc_GetLocalTrackRevisions(), me.api.asc_GetGlobalTrackRevisions());
|
||||
me.api.asc_HaveRevisionsChanges() && me.view.markChanges(true);
|
||||
|
||||
// _setReviewStatus(state, global);
|
||||
var val = Common.localStorage.getItem(me.view.appPrefix + "review-mode-editor");
|
||||
if (val===null)
|
||||
val = me.appConfig.customization && /^(original|final|markup|simple)$/i.test(me.appConfig.customization.reviewDisplay) ? me.appConfig.customization.reviewDisplay.toLocaleLowerCase() : 'markup';
|
||||
me.turnDisplayMode(val); // load display mode for all modes (viewer or editor)
|
||||
me.view.turnDisplayMode(val);
|
||||
|
||||
if ( typeof (me.appConfig.customization) == 'object' && (me.appConfig.customization.showReviewChanges==true) ) {
|
||||
me.dlgChanges = (new Common.Views.ReviewChangesDialog({
|
||||
|
@ -819,11 +839,11 @@ define([
|
|||
} else if (config.canViewReview) {
|
||||
config.canViewReview = (config.isEdit || me.api.asc_HaveRevisionsChanges(true)); // check revisions from all users
|
||||
if (config.canViewReview) {
|
||||
var val = Common.localStorage.getItem(me.view.appPrefix + "review-mode");
|
||||
var val = Common.localStorage.getItem(me.view.appPrefix + (config.isEdit || config.isRestrictedEdit ? "review-mode-editor" : "review-mode"));
|
||||
if (val===null)
|
||||
val = me.appConfig.customization && /^(original|final|markup)$/i.test(me.appConfig.customization.reviewDisplay) ? me.appConfig.customization.reviewDisplay.toLocaleLowerCase() : 'original';
|
||||
me.turnDisplayMode((config.isEdit || config.isRestrictedEdit) ? 'markup' : val); // load display mode only in viewer
|
||||
me.view.turnDisplayMode((config.isEdit || config.isRestrictedEdit) ? 'markup' : val);
|
||||
val = me.appConfig.customization && /^(original|final|markup|simple)$/i.test(me.appConfig.customization.reviewDisplay) ? me.appConfig.customization.reviewDisplay.toLocaleLowerCase() : (config.isEdit || config.isRestrictedEdit ? 'markup' : 'original');
|
||||
me.turnDisplayMode(val);
|
||||
me.view.turnDisplayMode(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -837,6 +857,14 @@ define([
|
|||
me.view.btnCommentRemove && me.view.btnCommentRemove.setDisabled(!Common.localStorage.getBool(me.view.appPrefix + "settings-livecomment", true));
|
||||
me.view.btnCommentResolve && me.view.btnCommentResolve.setDisabled(!Common.localStorage.getBool(me.view.appPrefix + "settings-livecomment", true));
|
||||
}
|
||||
|
||||
var val = Common.localStorage.getItem(me.view.appPrefix + "settings-review-hover-mode");
|
||||
if (val === null) {
|
||||
val = me.appConfig.customization && me.appConfig.customization.review ? !!me.appConfig.customization.review.hoverMode : false;
|
||||
} else
|
||||
val = !!parseInt(val);
|
||||
Common.Utils.InternalSettings.set(me.view.appPrefix + "settings-review-hover-mode", val);
|
||||
me.appConfig.reviewHoverMode = val;
|
||||
},
|
||||
|
||||
showTips: function(strings) {
|
||||
|
|
|
@ -298,6 +298,15 @@ define([
|
|||
template: menuTemplate,
|
||||
description: this.txtMarkup
|
||||
},
|
||||
{
|
||||
caption: this.txtMarkupSimpleCap,
|
||||
checkable: true,
|
||||
toggleGroup: 'menuReviewView',
|
||||
checked: false,
|
||||
value: 'simple',
|
||||
template: menuTemplate,
|
||||
description: this.txtMarkupSimple
|
||||
},
|
||||
{
|
||||
caption: this.txtFinalCap,
|
||||
checkable: true,
|
||||
|
@ -750,8 +759,9 @@ define([
|
|||
turnDisplayMode: function(mode) {
|
||||
if (this.btnReviewView) {
|
||||
this.btnReviewView.menu.items[0].setChecked(mode=='markup', true);
|
||||
this.btnReviewView.menu.items[1].setChecked(mode=='final', true);
|
||||
this.btnReviewView.menu.items[2].setChecked(mode=='original', true);
|
||||
this.btnReviewView.menu.items[1].setChecked(mode=='simple', true);
|
||||
this.btnReviewView.menu.items[2].setChecked(mode=='final', true);
|
||||
this.btnReviewView.menu.items[3].setChecked(mode=='original', true);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -850,7 +860,9 @@ define([
|
|||
txtOff: 'OFF for me',
|
||||
textWarnTrackChangesTitle: 'Enable Track Changes for everyone?',
|
||||
textWarnTrackChanges: 'Track Changes will be switched ON for all users with full access. The next time anyone opens the doc, Track Changes will remain enabled.',
|
||||
textEnable: 'Enable'
|
||||
textEnable: 'Enable',
|
||||
txtMarkupSimpleCap: 'Simple Markup',
|
||||
txtMarkupSimple: 'All changes (Editing)<br>Turn off balloons'
|
||||
}
|
||||
}()), Common.Views.ReviewChanges || {}));
|
||||
|
||||
|
|
|
@ -103,6 +103,7 @@ define([
|
|||
this.canRequestUsers = options.canRequestUsers;
|
||||
this.canRequestSendNotify = options.canRequestSendNotify;
|
||||
this.mentionShare = options.mentionShare;
|
||||
this.api = options.api;
|
||||
this.externalUsers = [];
|
||||
this._state = {commentsVisible: false, reviewVisible: false};
|
||||
|
||||
|
@ -784,7 +785,7 @@ define([
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!retainContent)
|
||||
if (!retainContent || this.isOverCursor())
|
||||
this.calculateSizeOfContent();
|
||||
},
|
||||
calculateSizeOfContent: function (testVisible) {
|
||||
|
@ -839,7 +840,34 @@ define([
|
|||
|
||||
outerHeight = Math.max(commentsView.outerHeight(), this.$window.outerHeight());
|
||||
|
||||
if (sdkBoundsHeight <= outerHeight) {
|
||||
var movePos = this.isOverCursor();
|
||||
if (movePos) {
|
||||
var newTopDown = movePos[1] + sdkPanelHeight,// try move down
|
||||
newTopUp = movePos[0] + sdkPanelHeight; // try move up
|
||||
if (newTopDown + outerHeight>sdkBoundsTop + sdkBoundsHeight) {
|
||||
var diffDown = sdkBoundsTop + sdkBoundsHeight - newTopDown;
|
||||
if (newTopUp - outerHeight<sdkBoundsTop) {
|
||||
var diffUp = newTopUp - sdkBoundsTop;
|
||||
if (diffDown < diffUp * 0.9) {// magic)
|
||||
this.$window.css({
|
||||
maxHeight: diffUp + 'px',
|
||||
top: sdkBoundsTop + 'px'
|
||||
});
|
||||
commentsView.css({height: diffUp - 3 + 'px'});
|
||||
} else {
|
||||
this.$window.css({
|
||||
maxHeight: diffDown + 'px',
|
||||
top: newTopDown + 'px'
|
||||
});
|
||||
commentsView.css({height: diffDown - 3 + 'px'});
|
||||
}
|
||||
} else
|
||||
this.$window.css('top', newTopUp - outerHeight + 'px'); // move up
|
||||
} else
|
||||
this.$window.css('top', newTopDown + 'px'); // move down
|
||||
arrowView.addClass('hidden');
|
||||
|
||||
} else if (sdkBoundsHeight <= outerHeight) {
|
||||
this.$window.css({
|
||||
maxHeight: sdkBoundsHeight - sdkPanelHeight + 'px',
|
||||
top: sdkBoundsTop + sdkPanelHeight + 'px'
|
||||
|
@ -851,6 +879,7 @@ define([
|
|||
arrowPosY = Math.min(arrowPosY, sdkBoundsHeight - (sdkPanelHeight + this.arrow.margin + this.arrow.height));
|
||||
|
||||
arrowView.css({top: arrowPosY + 'px'});
|
||||
arrowView.removeClass('hidden');
|
||||
this.scroller.scrollTop(scrollPos);
|
||||
} else {
|
||||
|
||||
|
@ -869,6 +898,7 @@ define([
|
|||
arrowPosY = Math.min(arrowPosY, outerHeight - this.arrow.margin - this.arrow.height);
|
||||
|
||||
arrowView.css({top: arrowPosY + 'px'});
|
||||
arrowView.removeClass('hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -880,6 +910,23 @@ define([
|
|||
this.scroller.update({minScrollbarLength: 40, alwaysVisibleY: true});
|
||||
}
|
||||
},
|
||||
|
||||
isOverCursor: function() {
|
||||
if (!this.api.asc_GetSelectionBounds) return;
|
||||
|
||||
var p = this.api.asc_GetSelectionBounds(),
|
||||
isCursor = Math.abs(p[0][0] - p[1][0])<0.1 && Math.abs(p[0][1] - p[1][1])<0.1 && Math.abs(p[2][0] - p[3][0])<0.1 && Math.abs(p[2][1] - p[3][1])<0.1;
|
||||
var x0 = p[0][0], y0 = p[0][1],
|
||||
x1 = p[isCursor ? 2 : 1][0], y1 = p[isCursor ? 2 : 1][1];
|
||||
var leftPos = parseInt(this.$window.css('left'))-25,
|
||||
windowWidth = this.$window.outerWidth();
|
||||
if (x0>leftPos && x0<leftPos+windowWidth || x1>leftPos && x1<leftPos+windowWidth) {
|
||||
var newTopDown = Math.max(y0, y1),// try move down
|
||||
newTopUp = Math.min(y0, y1); // try move up
|
||||
return [newTopUp, newTopDown];
|
||||
}
|
||||
},
|
||||
|
||||
saveText: function (clear) {
|
||||
if (this.commentsView && this.commentsView.cmpEl.find('.lock-area').length < 1) {
|
||||
this.textVal = undefined;
|
||||
|
|
|
@ -22,24 +22,26 @@ class InitReview extends Component {
|
|||
api.asc_SetTrackRevisions(appOptions.isReviewOnly || trackChanges===true || (trackChanges!==false) && LocalStorage.getBool("de-mobile-track-changes-" + (appOptions.fileKey || '')));
|
||||
|
||||
// Init display mode
|
||||
if (!appOptions.canReview) {
|
||||
const canViewReview = appOptions.isEdit || api.asc_HaveRevisionsChanges(true);
|
||||
|
||||
const canViewReview = appOptions.canReview || appOptions.isEdit || api.asc_HaveRevisionsChanges(true);
|
||||
if (!appOptions.canReview)
|
||||
appOptions.setCanViewReview(canViewReview);
|
||||
if (canViewReview) {
|
||||
let viewReviewMode = LocalStorage.getItem("de-view-review-mode");
|
||||
if (viewReviewMode === null)
|
||||
viewReviewMode = appOptions.customization && /^(original|final|markup)$/i.test(appOptions.customization.reviewDisplay) ? appOptions.customization.reviewDisplay.toLocaleLowerCase() : 'original';
|
||||
viewReviewMode = (appOptions.isEdit || appOptions.isRestrictedEdit) ? 'markup' : viewReviewMode;
|
||||
const displayMode = viewReviewMode.toLocaleLowerCase();
|
||||
if (displayMode === 'final') {
|
||||
api.asc_BeginViewModeInReview(true);
|
||||
} else if (displayMode === 'original') {
|
||||
api.asc_BeginViewModeInReview(false);
|
||||
} else {
|
||||
api.asc_EndViewModeInReview();
|
||||
}
|
||||
props.storeReview.changeDisplayMode(displayMode);
|
||||
if (canViewReview) {
|
||||
let viewReviewMode = (appOptions.isEdit || appOptions.isRestrictedEdit) ? null : LocalStorage.getItem("de-view-review-mode");
|
||||
if (viewReviewMode === null)
|
||||
viewReviewMode = appOptions.customization && /^(original|final|markup|simple)$/i.test(appOptions.customization.reviewDisplay) ? appOptions.customization.reviewDisplay.toLocaleLowerCase() : ( appOptions.isEdit || appOptions.isRestrictedEdit ? 'markup' : 'original');
|
||||
let displayMode = viewReviewMode.toLocaleLowerCase();
|
||||
let type = Asc.c_oAscDisplayModeInReview.Edit;
|
||||
switch (displayMode) {
|
||||
case 'final':
|
||||
type = Asc.c_oAscDisplayModeInReview.Final;
|
||||
break;
|
||||
case 'original':
|
||||
type = Asc.c_oAscDisplayModeInReview.Original;
|
||||
break;
|
||||
}
|
||||
api.asc_SetDisplayModeInReview(type);
|
||||
props.storeReview.changeDisplayMode(displayMode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -95,14 +97,17 @@ class Review extends Component {
|
|||
|
||||
onDisplayMode (mode) {
|
||||
const api = Common.EditorApi.get();
|
||||
if (mode === 'final') {
|
||||
api.asc_BeginViewModeInReview(true);
|
||||
} else if (mode === 'original') {
|
||||
api.asc_BeginViewModeInReview(false);
|
||||
} else {
|
||||
api.asc_EndViewModeInReview();
|
||||
let type = Asc.c_oAscDisplayModeInReview.Edit;
|
||||
switch (mode) {
|
||||
case 'final':
|
||||
type = Asc.c_oAscDisplayModeInReview.Final;
|
||||
break;
|
||||
case 'original':
|
||||
type = Asc.c_oAscDisplayModeInReview.Original;
|
||||
break;
|
||||
}
|
||||
!this.appConfig.canReview && LocalStorage.setItem("de-view-review-mode", mode);
|
||||
api.asc_SetDisplayModeInReview(type);
|
||||
!this.appConfig.isEdit && !this.appConfig.isRestrictedEdit && LocalStorage.setItem("de-view-review-mode", mode);
|
||||
this.props.storeReview.changeDisplayMode(mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -491,7 +491,8 @@ define([
|
|||
var showPoint, ToolTip,
|
||||
type = moveData.get_Type();
|
||||
|
||||
if (type==Asc.c_oAscMouseMoveDataTypes.Hyperlink || type==Asc.c_oAscMouseMoveDataTypes.Footnote || type==Asc.c_oAscMouseMoveDataTypes.Form) { // 1 - hyperlink, 3 - footnote
|
||||
if (type==Asc.c_oAscMouseMoveDataTypes.Hyperlink || type==Asc.c_oAscMouseMoveDataTypes.Footnote || type==Asc.c_oAscMouseMoveDataTypes.Form ||
|
||||
type==Asc.c_oAscMouseMoveDataTypes.Review && me.mode.reviewHoverMode) {
|
||||
if (isTooltipHiding) {
|
||||
mouseMoveData = moveData;
|
||||
return;
|
||||
|
@ -511,12 +512,22 @@ define([
|
|||
ToolTip = moveData.get_FormHelpText();
|
||||
if (ToolTip.length>1000)
|
||||
ToolTip = ToolTip.substr(0, 1000) + '...';
|
||||
} else if (type==Asc.c_oAscMouseMoveDataTypes.Review && moveData.get_ReviewChange()) {
|
||||
var changes = DE.getController("Common.Controllers.ReviewChanges").readSDKChange([moveData.get_ReviewChange()]);
|
||||
if (changes && changes.length>0)
|
||||
changes = changes[0];
|
||||
if (changes) {
|
||||
ToolTip = '<b>'+ Common.Utils.String.htmlEncode(AscCommon.UserInfoParser.getParsedName(changes.get('username'))) +' </b>';
|
||||
ToolTip += '<span style="font-size:10px; opacity: 0.7;">'+ changes.get('date') +'</span><br>';
|
||||
ToolTip += changes.get('changetext');
|
||||
}
|
||||
}
|
||||
|
||||
var recalc = false;
|
||||
screenTip.isHidden = false;
|
||||
|
||||
ToolTip = Common.Utils.String.htmlEncode(ToolTip);
|
||||
if (type!==Asc.c_oAscMouseMoveDataTypes.Review)
|
||||
ToolTip = Common.Utils.String.htmlEncode(ToolTip);
|
||||
|
||||
if (screenTip.tipType !== type || screenTip.tipLength !== ToolTip.length || screenTip.strTip.indexOf(ToolTip)<0 ) {
|
||||
screenTip.toolTip.setTitle((type==Asc.c_oAscMouseMoveDataTypes.Hyperlink) ? (ToolTip + '<br><b>' + me.txtPressLink + '</b>') : ToolTip);
|
||||
|
|
|
@ -398,6 +398,8 @@
|
|||
"Common.Views.ReviewChanges.txtSpelling": "Spell Checking",
|
||||
"Common.Views.ReviewChanges.txtTurnon": "Track Changes",
|
||||
"Common.Views.ReviewChanges.txtView": "Display Mode",
|
||||
"Common.Views.ReviewChanges.txtMarkupSimpleCap": "Simple Markup",
|
||||
"Common.Views.ReviewChanges.txtMarkupSimple": "All changes (Editing)<br>Turn off balloons",
|
||||
"Common.Views.ReviewChangesDialog.textTitle": "Review Changes",
|
||||
"Common.Views.ReviewChangesDialog.txtAccept": "Accept",
|
||||
"Common.Views.ReviewChangesDialog.txtAcceptAll": "Accept All Changes",
|
||||
|
|
Loading…
Reference in a new issue