diff --git a/lib/Utils/MultiCurlHandler.php b/lib/Utils/MultiCurlHandler.php index b8864ff681..160f0c17a1 100644 --- a/lib/Utils/MultiCurlHandler.php +++ b/lib/Utils/MultiCurlHandler.php @@ -399,6 +399,15 @@ public function getErrors() { return array_filter( $map ); // <- remove null array entries } + /** + * @param $tokenHash + * + * @return int + */ + public function getStatusCode( $tokenHash ) { + return (int)$this->multi_curl_info[ $tokenHash ][ 'http_code' ]; + } + public function clear(){ $this->multiCurlCloseAll(); $this->curl_headers_requests = []; @@ -428,4 +437,4 @@ protected function _callbackExecute( $record, Callable $function = null ){ return $record; } -} +} diff --git a/public/css/sass/lexiqa.scss b/public/css/sass/lexiqa.scss index b7891ae14d..a50d66272b 100755 --- a/public/css/sass/lexiqa.scss +++ b/public/css/sass/lexiqa.scss @@ -104,7 +104,7 @@ .icon-cancel-circle:before { line-height: 40px; float: left; - font-size: 18px; + font-size: 16px; } .tooltip-error-ignore-text { margin-left: 5px; @@ -117,6 +117,19 @@ border-top: 1px solid rgba(255, 255, 255, 0.36); } } + .tooltip-suggestion-container { + display: flex; + flex-direction: column; + padding: 0 0.5rem 0.5rem; + } + .tooltip-suggestion-container ul > li { + font-weight: bold; + cursor: pointer; + line-height: 22px; + } + .tooltip-suggestion-container ul > li:hover { + color: #4184c4; + } } /* ============================== diff --git a/public/js/cat_source/es6/components/segments/Editarea.js b/public/js/cat_source/es6/components/segments/Editarea.js index 3cfbaabac3..dc062ac883 100644 --- a/public/js/cat_source/es6/components/segments/Editarea.js +++ b/public/js/cat_source/es6/components/segments/Editarea.js @@ -8,6 +8,7 @@ import { getDefaultKeyBinding, KeyBindingUtil, CompositeDecorator, + SelectionState, } from 'draft-js' import SegmentConstants from '../../constants/SegmentConstants' @@ -24,6 +25,7 @@ import checkForMissingTags from './utils/DraftMatecatUtils/TagMenu/checkForMissi import updateEntityData from './utils/DraftMatecatUtils/updateEntityData' import LexiqaUtils from '../../utils/lxq.main' import updateLexiqaWarnings from './utils/DraftMatecatUtils/updateLexiqaWarnings' +import transformLexiqaPoints from './utils/DraftMatecatUtils/transformLexiqaPoints' import insertText from './utils/DraftMatecatUtils/insertText' import {tagSignatures} from './utils/DraftMatecatUtils/tagModel' import SegmentActions from '../../actions/SegmentActions' @@ -205,6 +207,7 @@ class Editarea extends React.Component { sid, false, this.getUpdatedSegmentInfo, + this.replaceWordAt, ) _.remove( this.decoratorsStructure, @@ -522,6 +525,27 @@ class Editarea extends React.Component { } } + replaceWordAt = ({newWord, start, end}) => { + const startIndex = start + const endIndex = end + const selection = this.state.editorState.getSelection().merge({ + anchorOffset: startIndex, + focusOffset: endIndex, + }) + const contentState = Modifier.replaceText( + this.state.editorState.getCurrentContent(), + selection, + newWord, + ) + const updatedState = EditorState.push(this.state.editorState, contentState) + this.setState({editorState: updatedState}, () => { + // Reactivate decorators + this.updateTranslationDebounced() + // Stop composition mode + this.onCompositionStopDebounced() + }) + } + render() { const { editorState, diff --git a/public/js/cat_source/es6/components/segments/LexiqaHighlight/LexiqaHighlight.component.js b/public/js/cat_source/es6/components/segments/LexiqaHighlight/LexiqaHighlight.component.js index 20a3e154e6..19e5c3c7d2 100644 --- a/public/js/cat_source/es6/components/segments/LexiqaHighlight/LexiqaHighlight.component.js +++ b/public/js/cat_source/es6/components/segments/LexiqaHighlight/LexiqaHighlight.component.js @@ -84,7 +84,10 @@ class LexiqaHighlight extends Component { onMouseLeave={() => this.hideTooltip(300)} > {showTooltip && segmentOpened && warning && warning.messages && ( - + )} {children} diff --git a/public/js/cat_source/es6/components/segments/TooltipInfo/LexiqaTooltipInfo.component.js b/public/js/cat_source/es6/components/segments/TooltipInfo/LexiqaTooltipInfo.component.js index 539ec3e480..e1cb997142 100644 --- a/public/js/cat_source/es6/components/segments/TooltipInfo/LexiqaTooltipInfo.component.js +++ b/public/js/cat_source/es6/components/segments/TooltipInfo/LexiqaTooltipInfo.component.js @@ -9,23 +9,55 @@ class LexiqaTooltipInfo extends Component { } buildTooltipError = () => { - let messages = this.props.messages - let html = [] - _.each(messages, (message, i) => { - html.push( -
- {message.msg} -
this.ignoreError(message)} - > - - Ignore -
-
, - ) - }) - return html + const {messages} = this.props + const suggestions = messages.filter((item) => item.type === 'suggestion') + const errors = messages.filter((item) => item.type !== 'suggestion') + + const errorsHtml = errors.map((error, i) => ( +
+ {error.msg} +
this.ignoreError(error)} + > + + Ignore +
+
+ )) + + const suggestionsList = suggestions.map((suggestion, i) => ( +
  • + this.replaceWord({ + newWord: suggestion.msg, + start: suggestion.start, + end: suggestion.end, + }) + } + > + {suggestion.msg} +
  • + )) + + const suggestionsHtml = suggestions.length > 0 && ( +
    +
      {suggestionsList}
    +
    + ) + + return ( + <> + {errorsHtml} + {suggestionsHtml} + + ) + } + + replaceWord = ({newWord, start, end}) => { + this.props.onReplaceWord({newWord, start, end}) + //LXQ.redoHighlighting(segmentId, false) } render() { diff --git a/public/js/cat_source/es6/components/segments/utils/DraftMatecatUtils/activateLexiqa.js b/public/js/cat_source/es6/components/segments/utils/DraftMatecatUtils/activateLexiqa.js index ff45a9e03e..d1b8c4f797 100644 --- a/public/js/cat_source/es6/components/segments/utils/DraftMatecatUtils/activateLexiqa.js +++ b/public/js/cat_source/es6/components/segments/utils/DraftMatecatUtils/activateLexiqa.js @@ -11,6 +11,7 @@ const activateLexiqa = ( sid, isSource, getUpdatedSegmentInfo, + replaceWordAt, ) => { const generateLexiqaDecorator = (warnings, sid, isSource, decoratorName) => { return { @@ -35,6 +36,7 @@ const activateLexiqa = ( sid, isSource, getUpdatedSegmentInfo, + replaceWordAt, }, } } diff --git a/public/js/cat_source/es6/components/segments/utils/DraftMatecatUtils/transformLexiqaPoints.js b/public/js/cat_source/es6/components/segments/utils/DraftMatecatUtils/transformLexiqaPoints.js new file mode 100644 index 0000000000..01bddc6552 --- /dev/null +++ b/public/js/cat_source/es6/components/segments/utils/DraftMatecatUtils/transformLexiqaPoints.js @@ -0,0 +1,58 @@ +import getEntities from './getEntities' +import {isToReplaceForLexiqa} from './tagModel' + +const transformLexiqaPoints = (editorState, start, end) => { + const contentState = editorState.getCurrentContent() + const blocks = contentState.getBlockMap() + let maxCharsInBlocks = 0 + const result = {} + const entities = getEntities(editorState) + blocks.forEach((loopedContentBlock) => { + const firstBlockKey = contentState.getFirstBlock().getKey() + const loopedBlockKey = loopedContentBlock.getKey() + // Add current block length + const newLineChar = loopedBlockKey !== firstBlockKey ? 1 : 0 + maxCharsInBlocks += loopedContentBlock.getLength() + newLineChar + const entitiesInBlock = entities.filter( + (ent) => ent.blockKey === loopedBlockKey, + ) + // Todo: warnings between 2 block are now ignored + const alreadyScannedChars = + maxCharsInBlocks - loopedContentBlock.getLength() + // remove offset added by '<' and '>' that wrap tags preceding current warning + entitiesInBlock.forEach((ent) => { + if ( + ent.start + alreadyScannedChars < start && + ent.end + alreadyScannedChars <= start + ) { + if (!isToReplaceForLexiqa(ent.entity.getData().name)) { + start -= 2 + end -= 2 + } + } + }) + if ( + start < maxCharsInBlocks && + end <= maxCharsInBlocks && + (start >= alreadyScannedChars || start === alreadyScannedChars - 1) + ) { + // Lexiqa warning length isn't valid, recompute length based on offset + let warnLength = end - start + let relativeStart = start - alreadyScannedChars + // Strings passed to lexiqa includes newlines so if two spaces are at the end of the line, + // they will be paired with newline char, causing lexiqa error to be of length 3. + // Same occurs if spaces are placed at the begininning of a new block: they will be paired with previous + // block's newline. Here we correct the last case, forcing error to start on the new block and ignoring newline char + if (start === alreadyScannedChars - 1) { + warnLength -= 1 // delete newline + relativeStart += 1 // start on next block + } + const relativeEnd = relativeStart + warnLength + result.start = relativeStart + result.end = relativeEnd + } + }) + return result +} + +export default transformLexiqaPoints diff --git a/public/js/cat_source/es6/utils/lxq.main.js b/public/js/cat_source/es6/utils/lxq.main.js index 1c2ca3b289..3b9f8605e6 100644 --- a/public/js/cat_source/es6/utils/lxq.main.js +++ b/public/js/cat_source/es6/utils/lxq.main.js @@ -631,6 +631,18 @@ LXQ.init = function () { }) } }) + if (!isSource) { + // let warningData = LXQ.lexiqaData.lexiqaWarnings[sid] + const {suggestions, start, end} = range + $.each(suggestions, function (i, suggest) { + messages.push({ + msg: suggest, + start: start, + end: end, + type: 'suggestion', + }) + }) + } return messages }