merge newui branch
This commit is contained in:
319
ui/src/settings/sync/collectionsDiffTable.js
Normal file
319
ui/src/settings/sync/collectionsDiffTable.js
Normal file
@@ -0,0 +1,319 @@
|
||||
export function collectionsDiffTable(propsArg = {}) {
|
||||
const props = store({
|
||||
rid: undefined,
|
||||
collectionA: null,
|
||||
collectionB: null,
|
||||
deleteMissing: false,
|
||||
className: "",
|
||||
});
|
||||
|
||||
const watchers = app.utils.extendStore(props, propsArg);
|
||||
|
||||
const data = store({
|
||||
hasAnyChange: false,
|
||||
get isDeleteDiff() {
|
||||
return !props.collectionB?.id && !props.collectionB?.name;
|
||||
},
|
||||
get isCreateDiff() {
|
||||
return !data.isDeleteDiff && !props.collectionA?.id;
|
||||
},
|
||||
get hasAnyChange() {
|
||||
return app.utils.hasCollectionChanges(props.collectionA, props.collectionB, props.deleteMissing);
|
||||
},
|
||||
get fieldsListA() {
|
||||
return Array.isArray(props.collectionA?.fields) ? props.collectionA?.fields : [];
|
||||
},
|
||||
get fieldsListB() {
|
||||
let fieldsB = Array.isArray(props.collectionB?.fields) ? props.collectionB?.fields : [];
|
||||
|
||||
if (!props.deleteMissing) {
|
||||
fieldsB = fieldsB.concat(
|
||||
props.collectionA?.fields?.filter((a) => {
|
||||
return !fieldsB.find((b) => a.id == b.id);
|
||||
}) || [],
|
||||
);
|
||||
}
|
||||
|
||||
return fieldsB;
|
||||
},
|
||||
get mainModelProps() {
|
||||
return app.utils
|
||||
.mergeUnique(Object.keys(props.collectionA || {}), Object.keys(props.collectionB || {}))
|
||||
.filter((key) => {
|
||||
return !["fields", "created", "updated"].includes(key);
|
||||
});
|
||||
},
|
||||
get removedFields() {
|
||||
return data.fieldsListA.filter((a) => {
|
||||
return !data.fieldsListB.find((b) => a.id == b.id);
|
||||
});
|
||||
},
|
||||
get sharedFields() {
|
||||
return data.fieldsListB.filter((b) => {
|
||||
return data.fieldsListA.find((a) => a.id == b.id);
|
||||
});
|
||||
},
|
||||
get addedFields() {
|
||||
return data.fieldsListB.filter((b) => {
|
||||
return !data.fieldsListA.find((a) => a.id == b.id);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
function stringify(value) {
|
||||
if (typeof value == "undefined") {
|
||||
return "";
|
||||
}
|
||||
|
||||
return app.utils.isObject(value) ? JSON.stringify(value, null, 4) : "" + value;
|
||||
}
|
||||
|
||||
function isDifferent(valA, valB) {
|
||||
if (valA === valB) {
|
||||
return false; // direct match
|
||||
}
|
||||
|
||||
return JSON.stringify(valA) != JSON.stringify(valB);
|
||||
}
|
||||
|
||||
function getFieldById(fields, id) {
|
||||
return (fields || []).find((f) => f.id == id);
|
||||
}
|
||||
|
||||
return t.div(
|
||||
{
|
||||
rid: props.rid,
|
||||
pbEvent: "collectionsDiffTableWrapper",
|
||||
className: () => `collections-diff-table-wrapper ${props.className}`,
|
||||
onunmount: () => {
|
||||
watchers.forEach((w) => w?.unwatch());
|
||||
},
|
||||
},
|
||||
t.div(
|
||||
{ className: "collections-diff-table-title" },
|
||||
() => {
|
||||
if (!props.collectionA?.id) {
|
||||
return [
|
||||
t.span({
|
||||
className: "label import-change-label success",
|
||||
textContent: "Added",
|
||||
}),
|
||||
t.strong({ textContent: () => props.collectionB?.name }),
|
||||
];
|
||||
}
|
||||
|
||||
if (!props.collectionB?.id) {
|
||||
return [
|
||||
t.span({
|
||||
className: "label import-change-label danger",
|
||||
textContent: "Deleted",
|
||||
}),
|
||||
t.strong({ textContent: () => props.collectionA?.name }),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
t.span({
|
||||
hidden: () => !data.hasAnyChange,
|
||||
className: "label import-change-label warning",
|
||||
textContent: "Changed",
|
||||
}),
|
||||
t.div(
|
||||
{ className: "inline-flex gap-5" },
|
||||
() => {
|
||||
if (props.collectionA?.name == props.collectionB?.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
return [
|
||||
t.strong({
|
||||
className: "txt-strikethrough txt-hint",
|
||||
textContent: props.collectionA?.name,
|
||||
}),
|
||||
t.i({
|
||||
className: "ri-arrow-right-line txt-sm",
|
||||
}),
|
||||
];
|
||||
},
|
||||
t.strong({ textContent: () => props.collectionB?.name }),
|
||||
),
|
||||
];
|
||||
},
|
||||
),
|
||||
t.table(
|
||||
{ className: "collections-diff-table" },
|
||||
t.thead(
|
||||
null,
|
||||
t.tr(
|
||||
null,
|
||||
t.th({ className: "min-width" }, "Props"),
|
||||
t.th({ width: "40%" }, "Old"),
|
||||
t.th({ width: "40%" }, "New"),
|
||||
),
|
||||
),
|
||||
t.tbody(
|
||||
null,
|
||||
() => {
|
||||
return data.mainModelProps.map((p) => {
|
||||
const isDiff = isDifferent(props.collectionA?.[p], props.collectionB?.[p]);
|
||||
return t.tr(
|
||||
{ className: isDiff ? "txt-primary" : "" },
|
||||
t.td({ className: "min-width" }, p),
|
||||
t.td(
|
||||
{
|
||||
className: () => {
|
||||
if (data.isCreateDiff) {
|
||||
return "changed-non-col";
|
||||
}
|
||||
if (isDiff) {
|
||||
return "changed-old-col";
|
||||
}
|
||||
return "";
|
||||
},
|
||||
},
|
||||
t.pre({ className: "txt diff-value" }, stringify(props.collectionA?.[p])),
|
||||
),
|
||||
t.td(
|
||||
{
|
||||
className: () => {
|
||||
if (data.isDeleteDiff) {
|
||||
return "changed-non-col";
|
||||
}
|
||||
if (isDiff) {
|
||||
return "changed-new-col";
|
||||
}
|
||||
return "";
|
||||
},
|
||||
},
|
||||
t.pre({ className: "txt diff-value" }, stringify(props.collectionB?.[p])),
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
() => {
|
||||
if (!props.deleteMissing && !data.isDeleteDiff) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rows = [];
|
||||
|
||||
for (let field of data.removedFields) {
|
||||
rows.push(
|
||||
t.tr(
|
||||
null,
|
||||
t.th(
|
||||
{ className: "min-width", colSpan: 3 },
|
||||
t.span({ className: "txt" }, "field: ", field.name),
|
||||
t.span(
|
||||
{ className: "label danger m-l-5" },
|
||||
"Deleted - ",
|
||||
t.small(null, `All stored data related to '${field.name}' will be deleted!`),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
for (let key in field) {
|
||||
const val = field[key];
|
||||
|
||||
rows.push(
|
||||
t.tr(
|
||||
null,
|
||||
t.td({ className: "min-width field-key-col" }, key),
|
||||
t.td(
|
||||
{ className: "changed-old-col" },
|
||||
t.pre({ className: "txt" }, stringify(val)),
|
||||
),
|
||||
t.td({ className: "changed-none-col" }),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return rows;
|
||||
},
|
||||
() => {
|
||||
const rows = [];
|
||||
|
||||
for (let field of data.sharedFields) {
|
||||
const fieldA = getFieldById(data.fieldsListA, field.id);
|
||||
const fieldB = getFieldById(data.fieldsListB, field.id);
|
||||
|
||||
const hasFieldChanged = isDifferent(fieldA, fieldB);
|
||||
|
||||
rows.push(
|
||||
t.tr(
|
||||
null,
|
||||
t.th(
|
||||
{ className: "min-width", colSpan: 3 },
|
||||
t.span({ className: "txt" }, "field: ", field.name),
|
||||
t.span({
|
||||
className: `label warning m-l-5 ${!hasFieldChanged ? "hidden" : ""}`,
|
||||
textContent: "Changed",
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
for (let key in field) {
|
||||
const newValue = field[key];
|
||||
|
||||
const isDiff = isDifferent(fieldA?.[key], newValue);
|
||||
|
||||
rows.push(
|
||||
t.tr(
|
||||
{ className: isDiff ? "txt-primary" : "" },
|
||||
t.td({ className: "min-width field-key-col" }, key),
|
||||
t.td(
|
||||
{ className: isDiff ? "changed-old-col" : "" },
|
||||
t.pre({ className: "txt" }, stringify(fieldA?.[key])),
|
||||
),
|
||||
t.td(
|
||||
{ className: isDiff ? "changed-new-col" : "" },
|
||||
t.pre({ className: "txt" }, stringify(newValue)),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return rows;
|
||||
},
|
||||
() => {
|
||||
const rows = [];
|
||||
|
||||
for (let field of data.addedFields) {
|
||||
rows.push(
|
||||
t.tr(
|
||||
null,
|
||||
t.th(
|
||||
{ className: "min-width", colSpan: 3 },
|
||||
t.span({ className: "txt" }, "field: ", field.name),
|
||||
t.span({ className: "label success m-l-5" }, "Added"),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
for (let key in field) {
|
||||
const val = field[key];
|
||||
|
||||
rows.push(
|
||||
t.tr(
|
||||
{ className: "txt-primary" },
|
||||
t.td({ className: "min-width field-key-col" }, key),
|
||||
t.td({ className: "changed-none-col" }),
|
||||
t.td(
|
||||
{ className: "changed-new-col" },
|
||||
t.pre({ className: "txt" }, stringify(val)),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return rows;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user