mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) simplify document comparison code, and flesh out diff with local changes
Summary: With recent changes to action history, we can now remove the temporary `finalRowContent` field from change details, since all the information we need is now in the ActionSummary. We also now have more information about the state of the common ancestor, which previously we could not get either from ActionSummary or from `finalRowContent`. We take advantage of that to flesh out rendering differences where there are some changes locally and some changes remotely. There's still a lot more to do, this is just one step. I have added a link to the UI for viewing the comparison. I wouldn't want to advertise that link until diffs are robust to name changes. Test Plan: added test, updated tests Reviewers: dsagal Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D2658
This commit is contained in:
@@ -24,6 +24,7 @@ const {urlState} = require('app/client/models/gristUrlState');
|
||||
const {SectionFilter} = require('app/client/models/SectionFilter');
|
||||
const {copyToClipboard} = require('app/client/lib/copyToClipboard');
|
||||
const {setTestState} = require('app/client/lib/testState');
|
||||
const {ExtraRows} = require('app/client/models/DataTableModelWithDiff');
|
||||
const {createFilterMenu} = require('app/client/ui/ColumnFilterMenu');
|
||||
|
||||
/**
|
||||
@@ -47,18 +48,10 @@ function BaseView(gristDoc, viewSectionModel, options) {
|
||||
|
||||
// Check if we are making a comparison with another document.
|
||||
this.comparison = this.gristDoc.comparison;
|
||||
if (this.comparison) {
|
||||
const tableId = this.schemaModel.tableId();
|
||||
// TODO: make robust to name changes.
|
||||
this.leftTableDelta = this.comparison.details.leftChanges.tableDeltas[tableId];
|
||||
this.rightTableDelta = this.comparison.details.rightChanges.tableDeltas[tableId];
|
||||
} else {
|
||||
this.rightTableDelta = null;
|
||||
this.leftTableDelta = null;
|
||||
}
|
||||
|
||||
// TODO: but accessing by tableId identifier may be problematic when the table is renamed.
|
||||
this.tableModel = this.gristDoc.getTableModelMaybeWithDiff(this.schemaModel.tableId());
|
||||
this.extraRows = new ExtraRows(this.schemaModel.tableId(), this.comparison && this.comparison.details);
|
||||
|
||||
// We use a DynamicQuerySet as the underlying RowSource, with ColumnFilters applies on top of
|
||||
// it. It filters based on section linking, re-querying as needed in case of onDemand tables.
|
||||
@@ -76,13 +69,9 @@ function BaseView(gristDoc, viewSectionModel, options) {
|
||||
}
|
||||
|
||||
if (this.comparison) {
|
||||
// Assign extra row ids for any rows added in the remote (right) table.
|
||||
// We flip their sign to make them as belonging to the remote table only.
|
||||
// TODO: if we wanted to show rows removed in the local (left) table, we'd need to
|
||||
// add those too, and come up with ids to give them. Without this, there's no
|
||||
// way to render an update that was made remotely to a row that was removed locally.
|
||||
const extraRowIds = (this.rightTableDelta && this.rightTableDelta.addRows || [])
|
||||
.map(rowId => -rowId);
|
||||
// Assign extra row ids for any rows added in the remote (right) table or removed in the
|
||||
// local (left) table.
|
||||
const extraRowIds = this.extraRows.getExtraRows();
|
||||
this._mainRowSource = rowset.ExtendedRowSource.create(this, this._mainRowSource, extraRowIds);
|
||||
}
|
||||
|
||||
|
||||
@@ -704,10 +704,6 @@ GridView.prototype.buildDom = function() {
|
||||
let vVerticalGridlines = v.optionsObj.prop('verticalGridlines');
|
||||
let vZebraStripes = v.optionsObj.prop('zebraStripes');
|
||||
|
||||
const rightAddRows = new Set(this.rightTableDelta && this.rightTableDelta.addRows.map(id => -id));
|
||||
const rightRemoveRows = new Set(this.rightTableDelta && this.rightTableDelta.removeRows);
|
||||
const leftAddRows = new Set(this.leftTableDelta && this.leftTableDelta.addRows);
|
||||
|
||||
var renameCommands = {
|
||||
nextField: function() {
|
||||
editIndex(editIndex() + 1);
|
||||
@@ -908,11 +904,8 @@ GridView.prototype.buildDom = function() {
|
||||
kd.toggleClass('record-even', () => (row._index()+1) % 2 === 0 ),
|
||||
|
||||
self.comparison ? kd.cssClass(() => {
|
||||
var rowId = row.id();
|
||||
if (rightAddRows.has(rowId)) { return 'diff-remote'; }
|
||||
else if (rightRemoveRows.has(rowId)) { return 'diff-parent'; }
|
||||
else if (leftAddRows.has(rowId)) { return 'diff-local'; }
|
||||
return '';
|
||||
const rowType = self.extraRows.getRowType(row.id());
|
||||
return rowType && `diff-${rowType}` || '';
|
||||
}) : null,
|
||||
|
||||
kd.foreach(v.viewFields(), function(field) {
|
||||
|
||||
@@ -152,26 +152,21 @@
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.diff-change .diff-parent, .diff-change .diff-remote {
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.diff-conflict .diff-parent, .diff-conflict .diff-local, .diff-conflict .diff-remote {
|
||||
display: inline-block;
|
||||
width: 33.33%;
|
||||
}
|
||||
|
||||
.diff-local {
|
||||
.diff-local, .diff-local-add {
|
||||
background-color: #dfdfff;
|
||||
}
|
||||
|
||||
.diff-parent {
|
||||
.diff-parent, .diff-remote-remove {
|
||||
background-color: #ffdfdf;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.diff-remote {
|
||||
.diff-local-remove {
|
||||
background-color: #dfdfdf;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.diff-remote, .diff-remote-add {
|
||||
background-color: #afffaf;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user