createSummaryVisualization = function (data, referenceData, showAdded=true, showRemoved=true, addColor='#66C2A5', removeColor='#F05268') {
var columns = Object.keys(data[0]);
var referenceColumns = Object.keys(referenceData[0]);
var addedColumns = referenceColumns.filter(
(column) => !columns.includes(column)
);
var removedColumns = columns.filter(
(column) => !referenceColumns.includes(column)
);
var addedRows = showAdded ? referenceData.slice(data.length) : [];
var removedRows = showRemoved ? data.slice(referenceData.length) : [];
var allColumns = Array.from(new Set([...columns, ...referenceColumns]));
if(!showAdded) {
allColumns = allColumns.filter((column) => !addedColumns.includes(column))
}
if(!showRemoved) {
allColumns = allColumns.filter((column) => !removedColumns.includes(column))
}
var gapX = spacing;
var gapY = spacing;
var marginTop = 0;
var marginLeft = 0;
var div = d3.create("div");
div
.style('display', 'flex')
.style('flex-direction', 'column')
.style('gap', '1px');
// Create groups for each row
var rows = div
.selectAll("div.row")
.data(data.concat(addedRows)) // Include added rows
.enter()
.append("div")
.classed("row", true)
.style('display', 'flex')
.style('gap', '1px');
// .attr("transform", function (d, i) {
// var rowY = i * (cellHeight + gapY);
// return "translate(0," + (rowY + (i > 0 ? marginTop : 0)) + ")";
// });
// Create rectangles for each cell within the rows
var rectangles = rows
.selectAll("div.cell")
.data(function (d, i) {
return allColumns.map(function (column) {
if (i < data.length) {
// original rows
return { column: column, value: d[column], rowIndex: i };
} else {
// new rows
return {
column: column,
value: referenceData[i][column],
rowIndex: i
};
}
});
})
.enter()
.append("div")
.classed("cell", true)
.style("aspect-ratio", "3 / 2")
.style("min-width", "1px")
.style("min-height", "1px")
.style("aspect-ratio", "1 / 1")
.style("flex-grow", "1")
.style("flex-shrink", "0")
.style("flex-basis", "1px")
.style("text-overflow", "clip")
.style("overflow", "hidden")
.style("white-space", "nowrap")
.style("font-size", "0.66em")
.style("display", "flex")
.style("flex-direction", "column")
.style("align-items", "start")
.style("justify-content", "center")
.attr('title', (d) => d.value)
.html((d) => {
if (removedColumns.includes(d.column)) {
// return `
// <s>${referenceData[d.rowIndex]?.[d.column]}</s>
// `
} else if (addedColumns.includes(d.column)) {
} else if (d.rowIndex >= data.length ) {
} else if (d.rowIndex >= referenceData.length ) {
// return `
// <s>${referenceData[d.rowIndex]?.[d.column]}</s>
// `
} else if (d.value !== referenceData[d.rowIndex]?.[d.column]) {
return `
<s>${referenceData[d.rowIndex]?.[d.column]}</s>
<span>${d.value}</span>
`
}
return d.value
})
// .style("height", cellHeight+"px")
// .attr("x", function (d, i) {
// var colIndex = allColumns.indexOf(d.column);
// return colIndex * (cellWidth + gapX) + (i > 0 ? marginLeft : 0);
// })
.style("background", function (d) {
if (removedColumns.includes(d.column)) {
return removeColor; // Removed column
} else if (addedColumns.includes(d.column)) {
return addColor; // Added column
} else if (d.rowIndex >= data.length ) {
return addColor; // Added row
} else if (d.rowIndex >= referenceData.length ) {
return removeColor; // removed row
} else if (d.value !== referenceData[d.rowIndex]?.[d.column]) {
return "#FBE156"; // changed cell
}
return "#F5F5F5"; // Unchanged cells
});
// Add tooltips to show content
rectangles.append("title").text(function (d) {
return d.value;
});
return div.node();
}