From cc39949464de297d8f9c4e2252df4159d11dcd6f Mon Sep 17 00:00:00 2001 From: William Braeckman Date: Thu, 13 Mar 2025 10:02:43 +0100 Subject: [PATCH] [REF] runbot: extract diff display to own component Also modernize code of the diff match patch use. --- runbot/static/src/js/fields/diff_display.js | 79 +++++++++++++++++++ runbot/static/src/js/fields/diff_display.xml | 14 ++++ runbot/static/src/js/fields/tracking_value.js | 56 ++----------- .../static/src/js/fields/tracking_value.xml | 15 +--- 4 files changed, 102 insertions(+), 62 deletions(-) create mode 100644 runbot/static/src/js/fields/diff_display.js create mode 100644 runbot/static/src/js/fields/diff_display.xml diff --git a/runbot/static/src/js/fields/diff_display.js b/runbot/static/src/js/fields/diff_display.js new file mode 100644 index 00000000..074364de --- /dev/null +++ b/runbot/static/src/js/fields/diff_display.js @@ -0,0 +1,79 @@ +import { Component, onWillRender } from '@odoo/owl'; + +import { diff_match_patch } from "@runbot/libs/diff_match_patch/diff_match_patch"; + + +export class DiffDisplay extends Component { + static template = 'runbot.DiffDisplay'; + static props = { + fromValue: { type: String }, + toValue: { type: String }, + lineFilter: { type: Function }, + } + static defaultProps = { + lineFilter: (line) => line.type !== 'kept', + } + + setup() { + onWillRender(() => { + this.lines = this.makeLines(this.props.fromValue, this.props.toValue); + }); + } + + makeLines(oldValue, newValue) { + const diff = this.makeDiff(oldValue, newValue); + const lines = this.prepareForRendering(diff); + return lines; + } + + makeDiff(text1, text2) { + const dmp = new diff_match_patch(); + const a = dmp.diff_linesToChars_(text1, text2); + const lineText1 = a.chars1; + const lineText2 = a.chars2; + const lineArray = a.lineArray; + const diffs = dmp.diff_main(lineText1, lineText2, false); + dmp.diff_charsToLines_(diffs, lineArray); + dmp.diff_cleanupSemantic(diffs); + return diffs; + } + + prepareForRendering(diffs) { + let preLineCounter = 0; + let postLineCounter = 0; + return diffs.reduce((lines, {0: diff_type, 1: data}) => { + data.split('\n').forEach(line => { + line = line + .replace(/&/g, '&') + .replace(//g, '>'); + let type, colOne, colTwo; + switch (diff_type) { + case 0: //kept + type = 'kept' + colOne = '' + colTwo = postLineCounter; + preLineCounter++; postLineCounter++; + break; + case -1: //removed + type = 'removed'; + colOne = preLineCounter; + colTwo = '-'; + preLineCounter++; + break; + case 1: //added + type = 'added'; + colOne = '+'; + colTwo = postLineCounter; + postLineCounter++; + break; + default: + console.warn('Unknown diff_type', diff_type) + return; + } + lines.push({type, colOne, colTwo, line}); + }) + return lines + }, []); + } +} diff --git a/runbot/static/src/js/fields/diff_display.xml b/runbot/static/src/js/fields/diff_display.xml new file mode 100644 index 00000000..3e3f46ba --- /dev/null +++ b/runbot/static/src/js/fields/diff_display.xml @@ -0,0 +1,14 @@ + + + +
+ + + +
+ + +
+
+
+
diff --git a/runbot/static/src/js/fields/tracking_value.js b/runbot/static/src/js/fields/tracking_value.js index b6403748..c5cae058 100644 --- a/runbot/static/src/js/fields/tracking_value.js +++ b/runbot/static/src/js/fields/tracking_value.js @@ -2,6 +2,11 @@ import { patch } from "@web/core/utils/patch"; import { Message } from "@mail/core/common/message"; import { diff_match_patch } from "@runbot/libs/diff_match_patch/diff_match_patch"; +import { DiffDisplay } from './diff_display'; + +patch(Message, { + components: {...Message.components, DiffDisplay}, +}); patch(Message.prototype, { setup() { @@ -13,9 +18,6 @@ patch(Message.prototype, { const newValue = trackingValue.newValue.value; return ((oldValue && typeof oldValue=== 'string' && oldValue.includes('\n')) && (newValue && typeof oldValue=== 'string' && newValue.includes('\n'))) }, - formatTracking(trackingType, trackingValue) { - return super.formatTracking(trackingType, trackingValue) - }, toggleKept() { this.kept = !this.kept; }, @@ -29,52 +31,4 @@ patch(Message.prototype, { navigator.clipboard.writeText(trackingValue.newValue.value); }; }, - lines(trackingValue) { - const oldValue = trackingValue.oldValue.value; - const newValue = trackingValue.newValue.value; - const diff = this.makeDiff(oldValue, newValue); - const lines = this.prepareForRendering(diff); - return lines; - }, - makeDiff(text1, text2) { - var dmp = new diff_match_patch(); - var a = dmp.diff_linesToChars_(text1, text2); - var lineText1 = a.chars1; - var lineText2 = a.chars2; - var lineArray = a.lineArray; - var diffs = dmp.diff_main(lineText1, lineText2, false); - dmp.diff_charsToLines_(diffs, lineArray); - dmp.diff_cleanupSemantic(diffs); - return diffs; - }, - prepareForRendering(diffs) { - var lines = []; - var pre_line_counter = 0 - var post_line_counter = 0 - for (var x = 0; x < diffs.length; x++) { - var diff_type = diffs[x][0]; - var data = diffs[x][1]; - var data_lines = data.split('\n'); - for (var line_index in data_lines) { - var line = data_lines[line_index]; - line = line.replace(/&/g, '&'); - line = line.replace(//g, '>'); - //text = text.replace(/\n/g, '
'); - //text = text.replace(/ /g, '  '); - if (diff_type == -1) { - lines.push({type:'removed', pre_line_counter: pre_line_counter, post_line_counter: '-', line: line}) - pre_line_counter += 1 - } else if (diff_type == 0) { - lines.push({type:'kept', pre_line_counter: '', post_line_counter: post_line_counter, line: line}) - pre_line_counter += 1 - post_line_counter +=1 - } else if (diff_type == 1) { - lines.push({type:'added', pre_line_counter: '+', post_line_counter: post_line_counter, line: line}) - post_line_counter +=1 - } - } - } - return lines; - }, }); diff --git a/runbot/static/src/js/fields/tracking_value.xml b/runbot/static/src/js/fields/tracking_value.xml index 9aaca233..16efe135 100644 --- a/runbot/static/src/js/fields/tracking_value.xml +++ b/runbot/static/src/js/fields/tracking_value.xml @@ -10,17 +10,10 @@
()
-
- - - - - -
- - -
-
+