From 3d2101f8ff2ab365b6f07eda8c1d20096c6aaf11 Mon Sep 17 00:00:00 2001 From: efloden Date: Mon, 2 Jul 2018 11:29:00 +1000 Subject: [PATCH] fix: use latest versionNum when resolving with original --- .../editor/service/TranslationService.java | 3 +- .../editor/actions/phrases-action-types.js | 3 +- .../src/app/editor/actions/phrases-actions.js | 78 ++++++++++--------- .../components/ConcurrentModal/index.tsx | 21 ++--- .../components/TransUnitTranslationHeader.js | 2 +- .../src/app/editor/containers/MainContent.js | 16 ++-- .../editor/reducers/phrase-reducer/index.js | 39 ++++++++-- 7 files changed, 100 insertions(+), 62 deletions(-) diff --git a/server/services/src/main/java/org/zanata/rest/editor/service/TranslationService.java b/server/services/src/main/java/org/zanata/rest/editor/service/TranslationService.java index 46e0ec51b4..4fa1739e1a 100644 --- a/server/services/src/main/java/org/zanata/rest/editor/service/TranslationService.java +++ b/server/services/src/main/java/org/zanata/rest/editor/service/TranslationService.java @@ -129,12 +129,13 @@ public Response put(String localeId, TranslationData data) { TranslationResult result = translationResults.get(0); if (result.isVersionNumConflict()) { HTextFlowTarget latest = result.getTranslatedTextFlowTarget(); - requestData.setContents(latest.getContents()); // Include latest translator username, last changed date in response String lastModifiedByUserName = latest.getLastModifiedBy() != null && latest.getLastModifiedBy().hasAccount() ? latest.getLastModifiedBy().getAccount().getUsername() : ""; + requestData.setContents(latest.getContents()); + requestData.setRevision(latest.getVersionNum()); requestData.setLastModifiedBy(lastModifiedByUserName); requestData.setLastModifiedDate(latest.getLastChanged()); return Response diff --git a/server/zanata-frontend/src/app/editor/actions/phrases-action-types.js b/server/zanata-frontend/src/app/editor/actions/phrases-action-types.js index 2fb2f76637..8b98b88d64 100644 --- a/server/zanata-frontend/src/app/editor/actions/phrases-action-types.js +++ b/server/zanata-frontend/src/app/editor/actions/phrases-action-types.js @@ -22,7 +22,8 @@ export const PENDING_SAVE_INITIATED = 'PENDING_SAVE_INITIATED' export const SAVE_FINISHED = 'SAVE_FINISHED' export const SAVE_FAILED = 'SAVE_FAILED' export const SAVE_CONFLICT = 'SAVE_CONFLICT' -export const SAVE_CONFLICT_RESOLVED = 'SAVE_CONFLICT_RESOLVED' +export const SAVE_CONFLICT_RESOLVED_LATEST = 'SAVE_CONFLICT_RESOLVED_LATEST' +export const SAVE_CONFLICT_RESOLVED_ORIGINAL = 'SAVE_CONFLICT_RESOLVED_ORIGINAL' export const TOGGLE_CONCURRENT_MODAL = 'TOGGLE_CONCURRENT_MODAL' diff --git a/server/zanata-frontend/src/app/editor/actions/phrases-actions.js b/server/zanata-frontend/src/app/editor/actions/phrases-actions.js index cd7e2514b1..4ec2b67392 100644 --- a/server/zanata-frontend/src/app/editor/actions/phrases-actions.js +++ b/server/zanata-frontend/src/app/editor/actions/phrases-actions.js @@ -17,7 +17,8 @@ import { SAVE_FINISHED, SAVE_FAILED, SAVE_CONFLICT, - SAVE_CONFLICT_RESOLVED, + SAVE_CONFLICT_RESOLVED_LATEST, + SAVE_CONFLICT_RESOLVED_ORIGINAL, TOGGLE_CONCURRENT_MODAL } from './phrases-action-types' import { @@ -152,32 +153,31 @@ const saveConflict = createAction(SAVE_CONFLICT, response })) -const saveConflictResolved = createAction(SAVE_CONFLICT_RESOLVED, - (phraseId, saveInfo, response, resolution) => ({ +const saveConflictResolvedLatest = createAction(SAVE_CONFLICT_RESOLVED_LATEST, + (phraseId, saveInfo, revision) => ({ phraseId, saveInfo, - response, - resolution + revision + })) + +const saveConflictResolvedOriginal = + createAction(SAVE_CONFLICT_RESOLVED_ORIGINAL, + (phraseId, saveInfo, revision) => ({ + phraseId, + saveInfo, + revision })) export const toggleConcurrentModal = createAction(TOGGLE_CONCURRENT_MODAL) -export function saveResolveConflict (latest, original, resolution) { +export function saveResolveConflictLatest (latest, original) { return (dispatch, getState) => { const stateBefore = getState() - const latestData = {...latest, revision: (latest.revision + 1)} - const phrase = { - ...latest, - ...original, - translations: original.translations, - revision: (latest.revision + 1) - } - if (resolution === 'latest') { - dispatch(saveConflictResolved( - phrase.id, latestData, latest.revision, resolution)).then( + dispatch(saveConflictResolvedLatest( + original.id, latest, latest.revision)).then( dispatch(fetchTransUnitHistory( - phrase.localeId, - phrase.id, + original.localeId, + original.id, stateBefore.context.projectSlug, stateBefore.context.versionSlug )).then( @@ -186,31 +186,35 @@ export function saveResolveConflict (latest, original, resolution) { getState().context.lang) ) ) - } else if (resolution === 'original') { - savePhrase(latestData, phrase) - .then(response => { - if (isErrorResponse(response)) { - console.error('Failed to save phrase') - dispatch(saveFailed(phrase.id, phrase, response)) - } else { - response.json().then(({ revision, status }) => { - dispatch(saveConflictResolved( - phrase.id, phrase, revision, resolution)).then( - dispatch(fetchTransUnitHistory( - phrase.localeId, - phrase.id, - stateBefore.context.projectSlug, - stateBefore.context.versionSlug + } +} + +export function saveResolveConflictOriginal (latest, original) { + return (dispatch, getState) => { + const stateBefore = getState() + savePhrase(latest, original) + .then(response => { + if (isErrorResponse(response)) { + console.error('Failed to save phrase') + dispatch(saveFailed(latest.id, original, response)) + } else { + response.json().then(({ revision, status }) => { + dispatch(saveConflictResolvedOriginal( + latest.id, original, revision)).then( + dispatch(fetchTransUnitHistory( + original.localeId, + latest.id, + stateBefore.context.projectSlug, + stateBefore.context.versionSlug )).then( fetchStatisticsInfo(dispatch, getState().context.projectSlug, getState().context.versionSlug, getState().context.docId, getState().context.lang) ) ) - }) - } - }) - } + }) + } + }) } } diff --git a/server/zanata-frontend/src/app/editor/components/ConcurrentModal/index.tsx b/server/zanata-frontend/src/app/editor/components/ConcurrentModal/index.tsx index 7db70b47c8..273ce00a59 100644 --- a/server/zanata-frontend/src/app/editor/components/ConcurrentModal/index.tsx +++ b/server/zanata-frontend/src/app/editor/components/ConcurrentModal/index.tsx @@ -15,11 +15,6 @@ import 'antd/lib/modal/style/index.less' import DateAndTimeDisplay from '../DateAndTimeDisplay' import Textarea from 'react-textarea-autosize' -export enum resolution { - latest = 'latest', - original = 'original', -} - interface Latest { content: string id: number @@ -42,7 +37,8 @@ interface Original { interface ConcurrentModalProps { closeConcurrentModal: () => void - saveResolveConflict: (latest: any, original: any, resolution: resolution) => void + saveResolveConflictLatest: (latest: any, original: any) => void + saveResolveConflictOriginal: (latest: any, original: any) => void show: boolean conflictData?: { response: Latest, @@ -53,13 +49,18 @@ interface ConcurrentModalProps { class ConcurrentModal extends React.Component { public static propTypes = { closeConcurrentModal: PropTypes.func, - saveResolveConflict: PropTypes.func.isRequired, + saveResolveConflictLatest: PropTypes.func.isRequired, + saveResolveConflictOriginal: PropTypes.func.isRequired, conflictData: PropTypes.any, show: PropTypes.bool.isRequired, } public render () { const { - closeConcurrentModal, saveResolveConflict, show, conflictData + closeConcurrentModal, + saveResolveConflictLatest, + saveResolveConflictOriginal, + show, + conflictData } = this.props if (!conflictData) { return null @@ -71,10 +72,10 @@ class ConcurrentModal extends React.Component { const lastModifiedDate = new Date(latest.lastModifiedDate) const onCancel = () => closeConcurrentModal() const saveLatest = () => { - saveResolveConflict(latest, original, resolution.latest) + saveResolveConflictLatest(latest, original) } const saveOriginal = () => { - saveResolveConflict(latest, original, resolution.original) + saveResolveConflictOriginal(latest, original) } return ( /* eslint-disable max-len */ diff --git a/server/zanata-frontend/src/app/editor/components/TransUnitTranslationHeader.js b/server/zanata-frontend/src/app/editor/components/TransUnitTranslationHeader.js index 3765489d7c..6388199357 100644 --- a/server/zanata-frontend/src/app/editor/components/TransUnitTranslationHeader.js +++ b/server/zanata-frontend/src/app/editor/components/TransUnitTranslationHeader.js @@ -46,7 +46,7 @@ class TransUnitTranslationHeader extends React.Component { icon="rollback" className={this.buttonClass} onClick={this.props.undoEdit} /> - Tooltip> + ) } diff --git a/server/zanata-frontend/src/app/editor/containers/MainContent.js b/server/zanata-frontend/src/app/editor/containers/MainContent.js index 7d7a3eb7ad..79905c8747 100644 --- a/server/zanata-frontend/src/app/editor/containers/MainContent.js +++ b/server/zanata-frontend/src/app/editor/containers/MainContent.js @@ -12,7 +12,9 @@ import { fetchAllCriteria, toggleReviewModal } from '../actions/review-trans-actions' import { - toggleConcurrentModal, saveResolveConflict + toggleConcurrentModal, + saveResolveConflictLatest, + saveResolveConflictOriginal } from '../actions/phrases-actions' import { getCriteria } from '../reducers/review-trans-reducer' import { MINOR, MAJOR, CRITICAL } from '../utils/reject-trans-util' @@ -27,7 +29,8 @@ class MainContent extends React.Component { static propTypes = { activityVisible: PropTypes.bool.isRequired, maximised: PropTypes.bool.isRequired, - saveResolveConflict: PropTypes.func.isRequired, + saveResolveConflictLatest: PropTypes.func.isRequired, + saveResolveConflictOriginal: PropTypes.func.isRequired, showConflictModal: PropTypes.bool.isRequired, showReviewModal: PropTypes.bool.isRequired, phrases: PropTypes.arrayOf(PropTypes.object).isRequired, @@ -108,7 +111,8 @@ class MainContent extends React.Component { @@ -148,8 +152,10 @@ function mapStateToProps (state, _ownProps) { function mapDispatchToProps (dispatch) { return { - saveResolveConflict: (latest, original, resolution) => dispatch( - saveResolveConflict(latest, original, resolution)), + saveResolveConflictLatest: (latest, original) => dispatch( + saveResolveConflictLatest(latest, original)), + saveResolveConflictOriginal: (latest, original) => dispatch( + saveResolveConflictOriginal(latest, original)), toggleConcurrentModal: () => dispatch(toggleConcurrentModal()), toggleReviewModal: () => dispatch(toggleReviewModal()), fetchAllCriteria: () => dispatch(fetchAllCriteria()) diff --git a/server/zanata-frontend/src/app/editor/reducers/phrase-reducer/index.js b/server/zanata-frontend/src/app/editor/reducers/phrase-reducer/index.js index c66eac5e45..5e99f610a9 100644 --- a/server/zanata-frontend/src/app/editor/reducers/phrase-reducer/index.js +++ b/server/zanata-frontend/src/app/editor/reducers/phrase-reducer/index.js @@ -27,7 +27,8 @@ import { SAVE_FAILED, SAVE_INITIATED, SAVE_CONFLICT, - SAVE_CONFLICT_RESOLVED, + SAVE_CONFLICT_RESOLVED_LATEST, + SAVE_CONFLICT_RESOLVED_ORIGINAL, SELECT_PHRASE, SELECT_PHRASE_SPECIFIC_PLURAL, TRANSLATION_TEXT_INPUT_CHANGED, @@ -244,14 +245,14 @@ export const phraseReducer = handleActions({ } }), - [SAVE_CONFLICT_RESOLVED]: (state, { getState, payload: { - phraseId, saveInfo, revision, resolution } }) => + [SAVE_CONFLICT_RESOLVED_LATEST]: (state, { getState, payload: { + phraseId, saveInfo, revision } }) => update(state, { notification: { $set: { severity: SEVERITY.INFO, message: 'Concurrent edit successfully resolved', - description: `Using the ${resolution} edit`, + description: `Using the Latest edit`, duration: 3.5 } }, @@ -261,9 +262,33 @@ export const phraseReducer = handleActions({ conflict: { $set: undefined }, inProgressSave: { $set: undefined }, newTranslations: { - $set: resolution === 'original' - ? state.detail[phraseId].newTranslations - : [saveInfo.content] + $set: [saveInfo.content] + }, + translations: { + $set: [saveInfo.content] + } + } + } + }), + + [SAVE_CONFLICT_RESOLVED_ORIGINAL]: (state, { getState, payload: { + phraseId, saveInfo, revision } }) => + update(state, { + notification: { + $set: { + severity: SEVERITY.INFO, + message: 'Concurrent edit successfully resolved', + description: `Using the Original edit`, + duration: 3.5 + } + }, + detail: { + [phraseId]: { + revision: { $set: revision }, + conflict: { $set: undefined }, + inProgressSave: { $set: undefined }, + translations: { + $set: state.detail[phraseId].newTranslations } } }