@saltcorn/history-control 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/rowdiffview.js +75 -17
package/package.json
CHANGED
package/rowdiffview.js
CHANGED
|
@@ -23,6 +23,7 @@ const {
|
|
|
23
23
|
button,
|
|
24
24
|
} = require("@saltcorn/markup/tags");
|
|
25
25
|
const { radio_group, checkbox_group } = require("@saltcorn/markup/helpers");
|
|
26
|
+
const { picked_fields_to_query } = require("@saltcorn/data/plugin-helper");
|
|
26
27
|
const moment = require("moment");
|
|
27
28
|
|
|
28
29
|
const get_state_fields = () => [
|
|
@@ -49,7 +50,23 @@ const configuration_workflow = (req) =>
|
|
|
49
50
|
state_fields.some((sf) => sf.name === "id")
|
|
50
51
|
);
|
|
51
52
|
const show_view_opts = show_views.map((v) => v.select_option);
|
|
53
|
+
let blurb;
|
|
54
|
+
if (table.provider_name)
|
|
55
|
+
blurb = [
|
|
56
|
+
div(
|
|
57
|
+
{ class: "alert alert-danger fst-normal" },
|
|
58
|
+
`Use this view on a standard database table, not a provided table`
|
|
59
|
+
),
|
|
60
|
+
];
|
|
61
|
+
else if (!table.versioned)
|
|
62
|
+
blurb = [
|
|
63
|
+
div(
|
|
64
|
+
{ class: "alert alert-danger fst-normal" },
|
|
65
|
+
`Version history is not enabled for this table`
|
|
66
|
+
),
|
|
67
|
+
];
|
|
52
68
|
return new Form({
|
|
69
|
+
blurb,
|
|
53
70
|
fields: [
|
|
54
71
|
{
|
|
55
72
|
name: "show_view",
|
|
@@ -70,6 +87,11 @@ const configuration_workflow = (req) =>
|
|
|
70
87
|
options: show_view_opts,
|
|
71
88
|
},
|
|
72
89
|
},
|
|
90
|
+
{
|
|
91
|
+
name: "comparison",
|
|
92
|
+
label: "Side-by-side comparison",
|
|
93
|
+
type: "Bool",
|
|
94
|
+
},
|
|
73
95
|
{
|
|
74
96
|
name: "min_interval_secs",
|
|
75
97
|
label: "Minimum interval (s)",
|
|
@@ -91,7 +113,7 @@ const configuration_workflow = (req) =>
|
|
|
91
113
|
const run = async (
|
|
92
114
|
table_id,
|
|
93
115
|
viewname,
|
|
94
|
-
{ show_view, min_interval_secs, date_format },
|
|
116
|
+
{ show_view, min_interval_secs, date_format, comparison },
|
|
95
117
|
state,
|
|
96
118
|
extraArgs
|
|
97
119
|
) => {
|
|
@@ -104,29 +126,55 @@ const run = async (
|
|
|
104
126
|
|
|
105
127
|
let hist = await table.get_history(id);
|
|
106
128
|
|
|
129
|
+
if (!hist || !hist.length) return "No versions recorded";
|
|
130
|
+
|
|
107
131
|
let last = 0;
|
|
108
132
|
let last_changed_by = undefined;
|
|
109
|
-
hist = hist.filter((row) => {
|
|
110
|
-
const myEpoch = Math.round(new Date(row._time).getTime() / 1000);
|
|
111
|
-
if (
|
|
112
|
-
myEpoch - last > min_interval_secs ||
|
|
113
|
-
(row._userid && row._userid !== last_changed_by)
|
|
114
|
-
) {
|
|
115
|
-
//include
|
|
116
|
-
last = myEpoch;
|
|
117
|
-
last_changed_by = row._userid;
|
|
118
|
-
return true;
|
|
119
|
-
} else return false;
|
|
120
|
-
});
|
|
121
133
|
|
|
122
|
-
|
|
123
|
-
|
|
134
|
+
hist = hist
|
|
135
|
+
.filter((row) => {
|
|
136
|
+
const myEpoch = Math.round(new Date(row._time).getTime() / 1000);
|
|
137
|
+
if (
|
|
138
|
+
myEpoch - last > min_interval_secs ||
|
|
139
|
+
(row._userid && row._userid !== last_changed_by)
|
|
140
|
+
) {
|
|
141
|
+
//include
|
|
142
|
+
last = myEpoch;
|
|
143
|
+
last_changed_by = row._userid;
|
|
144
|
+
return true;
|
|
145
|
+
} else return false;
|
|
146
|
+
})
|
|
147
|
+
.reverse();
|
|
148
|
+
const view = View.findOne({ name: show_view });
|
|
149
|
+
|
|
150
|
+
const { joinFields } = picked_fields_to_query(
|
|
151
|
+
view.configuration.columns,
|
|
152
|
+
table.fields,
|
|
153
|
+
view.configurationlayout,
|
|
154
|
+
extraArgs.req,
|
|
155
|
+
table
|
|
156
|
+
);
|
|
157
|
+
for (const [nm, jf] of Object.entries(joinFields)) {
|
|
158
|
+
const refVals = new Set(hist.map((r) => r[jf.ref]));
|
|
159
|
+
const refField = table.getField(jf.ref);
|
|
160
|
+
const reftable = Table.findOne(refField.reftable_name);
|
|
161
|
+
const rows = await reftable.getRows({
|
|
162
|
+
id: { in: [...refVals] },
|
|
163
|
+
});
|
|
164
|
+
const rowsByVal = {};
|
|
165
|
+
rows.forEach((r) => {
|
|
166
|
+
rowsByVal[r[reftable.pk_name]] = r;
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
hist.forEach((h) => {
|
|
170
|
+
h[nm] = rowsByVal[h[jf.ref]]?.[jf.target];
|
|
171
|
+
});
|
|
172
|
+
}
|
|
124
173
|
|
|
125
174
|
const userIds = new Set(hist.map((h) => h._userid));
|
|
126
175
|
const users = await User.find({ id: { in: [...userIds] } });
|
|
127
176
|
const emails = {};
|
|
128
177
|
users.forEach((u) => (emails[u.id] = u.email));
|
|
129
|
-
const view = View.findOne({ name: show_view });
|
|
130
178
|
const rendered = await view.viewtemplateObj.renderRows(
|
|
131
179
|
table,
|
|
132
180
|
view.name,
|
|
@@ -169,7 +217,17 @@ const run = async (
|
|
|
169
217
|
"aria-labelledby": `a${stateHash}head${ix}`,
|
|
170
218
|
"data-bs-parent": `#top${stateHash}`,
|
|
171
219
|
},
|
|
172
|
-
div(
|
|
220
|
+
div(
|
|
221
|
+
{ class: ["accordion-body"] },
|
|
222
|
+
comparison && ix < rendered.length - 1
|
|
223
|
+
? div(
|
|
224
|
+
{ class: "d-flex align-middle" },
|
|
225
|
+
div({ class: "border p-1 m-1" }, rendered[ix + 1]),
|
|
226
|
+
i({ class: "m-2 fas fa-arrow-right" }),
|
|
227
|
+
div({ class: "border p-1 m-1" }, html)
|
|
228
|
+
)
|
|
229
|
+
: html
|
|
230
|
+
)
|
|
173
231
|
)
|
|
174
232
|
);
|
|
175
233
|
})
|