Skip to content

Instantly share code, notes, and snippets.

@Daymannovaes
Last active July 28, 2017 16:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Daymannovaes/df8ec50ea00948330c2255031dd8936b to your computer and use it in GitHub Desktop.
Save Daymannovaes/df8ec50ea00948330c2255031dd8936b to your computer and use it in GitHub Desktop.
function arrayDiffToHtmlTable(prevArray = [], currArray = []) {
let ALL_KEYS = getAllKeys(prevArray, currArray);
let mappedObjects = mapObjects(prevArray, currArray);
let table = '<table>' + buildTableHeader();
for(let key of Object.keys(mappedObjects)) {
let prevObj = mappedObjects[key][0];
let currObj = mappedObjects[key][1];
table += buildHtmlRow(prevObj, currObj);
}
return `${table}</table>`;
function buildTableHeader() {
let row = '<tr>';
row += ALL_KEYS.map(key => `<th>${key.replace(/\./g, '_')}</th>`).join('');
return `${row}</tr>`;
}
function getAllKeys(prevArray, currArray) {
let array = prevArray.concat(currArray);
let keys = array.map(item => getKeysFromObject(item)); // array of array of keys
keys = [].concat.apply([], keys); // flatten in only one array
return [... new Set(keys)]; // return uniq keys
}
// getKeysFromObject({a:1, b:2, c:{d:3, e:{f:2, g:{h:5}}}}) should return ["a", "b", "c.d", "c.e.f", "c.e.g.h"]
function getKeysFromObject(object, base = '') {
let keys = [];
for(let prop of Object.keys(object)) {
if(typeof object[prop] === 'object') {
let propKeys = getKeysFromObject(object[prop], `${base}${prop}.`);
keys = keys.concat(propKeys);
}
else keys = keys.concat(base + prop);
}
return keys;
}
// should return in the form { [_id]: [prevObject, currObject] } for every row
// if prevObject is null (i.e., currObject is totally new), it returns [null, currObject] for that row
function mapObjects(prevArray, currArray) {
let map = {};
prevArray.forEach(item => map[item._id] = [item]);
currArray.forEach(item => {
if(!map[item._id]) map[item._id] = [null];
map[item._id].push(item);
});
return map;
}
function buildHtmlRow(prevObj, currObj) {
let row = '<tr>';
if(!prevObj) {
ALL_KEYS.forEach(key => {
let value = getObjectValue(currObj, key);
row += `<td><strong>${value || ''}</strong></td>`;
});
} else {
ALL_KEYS.forEach(key => {
let prevValue = getObjectValue(prevObj, key);
let currValue = getObjectValue(currObj, key);
if(nullOrUndefined(prevValue) && nullOrUndefined(currValue)) row += `<td></td>`;
else if(prevValue && nullOrUndefined(currValue)) row += `<td><strong>DELETED<strong></td>`;
else if(prevValue === currValue) row += `<td>${currValue}</td>`;
else if(prevValue !== currValue) row += `<td><strong>${currValue}</strong></td>`;
});
}
return `${row}</tr>`;
}
// you can use getObjectValue({ meta: { subKey1: 123 } }, 'meta.subKey1')
function getObjectValue(object, prop) {
if(!object) return null;
let parts = prop.split('.');
if(parts.length === 1) return object[prop];
let baseProp = parts[0];
return getObjectValue(object[baseProp], parts.splice(1).join('.'));
}
function nullOrUndefined(value) {
return value === null || typeof value === 'undefined';
}
}
module.exports.arrayDiffToHtmlTable = arrayDiffToHtmlTable;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment