1 | /** Javascript file for editing and especially deleting user comments in a documentediting situation */
|
---|
2 |
|
---|
3 | // Function called by documentedit_scripts_util.js when saving and rebuilding.
|
---|
4 | // This function should return usercomments data (only exists for doc root's section) so that
|
---|
5 | // setMetadataArray can be called for doc root and the entire collection rebuilt with the changes
|
---|
6 | function getUserCommentsEditDataForSaving(userCommentsMetaFields, userCommentsRowsChanged,
|
---|
7 | docids_to_delCommentsMetapositions) {
|
---|
8 | // https://medium.com/@martin.crabtree/javascript-tracking-key-value-pairs-using-hashmaps-7de6df598257
|
---|
9 | // Just using JS object. Not using Map in case it's not always compatible with older
|
---|
10 | // browsers we still support on 32 bit linux.
|
---|
11 | var docIDs_to_metatable_map = {};
|
---|
12 |
|
---|
13 | var i = 0;
|
---|
14 | for (i = 0; i < userCommentsRowsChanged.length; i++) {
|
---|
15 | // need docID, metaname, metaval, metapos, and set metamode to override
|
---|
16 |
|
---|
17 | var changedElem = userCommentsRowsChanged[i];
|
---|
18 | //console.dir(changedElem);
|
---|
19 |
|
---|
20 | var metaval = changedElem.value; //changedElem.textContent; // gets orig value
|
---|
21 | metaval = metaval.replace(/ /g, " "); // copied from docedit_scripts_utl, when procsesing the array called changes.
|
---|
22 | metaval = encodeDelimiters(metaval);
|
---|
23 |
|
---|
24 | var currentElem = changedElem;
|
---|
25 | while((currentElem = currentElem.parentNode).tagName != "TABLE");
|
---|
26 | var docID = currentElem.getAttribute("id").substring("usercomments-".length);
|
---|
27 |
|
---|
28 | currentElem = changedElem;
|
---|
29 | while((currentElem = currentElem.parentNode).tagName != "TR");
|
---|
30 | var metapos = currentElem.firstElementChild.textContent;
|
---|
31 |
|
---|
32 | // don't consider edits in user comment rows that have also been marked for deletion
|
---|
33 | var metapositionsToBeDeleted = docids_to_delCommentsMetapositions[docID];
|
---|
34 | if(metapositionsToBeDeleted !== undefined) {
|
---|
35 | // https://www.digitalocean.com/community/tutorials/js-array-search-methods
|
---|
36 | if(metapositionsToBeDeleted.indexOf(metapos) != -1) {
|
---|
37 | alert("Discarding edit at metapos " + metapos + " as user comment row is to be deleted.");
|
---|
38 | continue;
|
---|
39 | }
|
---|
40 | }
|
---|
41 |
|
---|
42 | //currentElem = changedElem.parentNode; //TD
|
---|
43 | currentElem = changedElem;
|
---|
44 | while((currentElem = currentElem.parentNode).tagName != "TD");
|
---|
45 | // count number of previous siblings
|
---|
46 | var th = 0;
|
---|
47 | while((currentElem = currentElem.previousSibling) != null) {
|
---|
48 | th++;
|
---|
49 | }
|
---|
50 | var metaname = userCommentsMetaFields[th-1]; // first column is invisible metapos col
|
---|
51 |
|
---|
52 | //alert("docid: " + docID + " metaname: " + metaname + " metaval: " + metaval + " metapos: " + metapos);
|
---|
53 |
|
---|
54 | // https://dmitripavlutin.com/check-if-object-has-property-javascript/
|
---|
55 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/null
|
---|
56 | if(docIDs_to_metatable_map[docID] === undefined) {
|
---|
57 | docIDs_to_metatable_map[docID] = [];
|
---|
58 | }
|
---|
59 | docIDs_to_metatable_map[docID].push({metaname:metaname,metavalue:metaval,metapos:metapos});
|
---|
60 | }
|
---|
61 |
|
---|
62 | var docids = Object.keys(docIDs_to_metatable_map);
|
---|
63 | i = 0;
|
---|
64 | var docArray = [];
|
---|
65 | for(i = 0; i < docids.length; i++) {
|
---|
66 | var docid = docids[i];
|
---|
67 | var metatable = docIDs_to_metatable_map[docid];
|
---|
68 | docArray.push({
|
---|
69 | docid:docid,
|
---|
70 | metatable:metatable/*,
|
---|
71 | metamode:"override"*/ // metamode set universally to override in
|
---|
72 | // documentedit_scripts_util.js::processChangesLoop when change.type=editUserComments
|
---|
73 | });
|
---|
74 | }
|
---|
75 |
|
---|
76 | //alert("editing: " + JSON.stringify(docArray));
|
---|
77 |
|
---|
78 | return docArray;
|
---|
79 | }
|
---|
80 |
|
---|
81 | // Function called by documentedit_scripts_util.js when saving and rebuilding.
|
---|
82 | // This function should return usercomments data (only exists for doc root's section) so that
|
---|
83 | // removeMetadataArray can be called for doc root and the collection rebuilt with the deletions
|
---|
84 | function getUserCommentsDeletions(userCommentsMetaFields, docids_to_delCommentsMetapositions) {
|
---|
85 |
|
---|
86 | var docids = Object.keys(docids_to_delCommentsMetapositions);
|
---|
87 | var docArray = [];
|
---|
88 | var i = 0;
|
---|
89 | for(i = 0; i < docids.length; i++) { //if(docids.length > 0) {
|
---|
90 | var _docid = docids[i];
|
---|
91 | var delCommentsMetapositions = docids_to_delCommentsMetapositions[_docid].sort();
|
---|
92 | // sort unnecessary as modmetadataaction.pm ensures (reverse) sort of metapositions
|
---|
93 |
|
---|
94 | // build up the data structure for all the usercomments to be deleted
|
---|
95 | if(delCommentsMetapositions.length > 0) {
|
---|
96 | //console.log("About to delete position: " + delCommentsMetapositions);
|
---|
97 | var timestamp_rec = {
|
---|
98 | metaname: userCommentsMetaFields[0],
|
---|
99 | metapositions: delCommentsMetapositions
|
---|
100 | };
|
---|
101 | var username_rec = {
|
---|
102 | metaname: userCommentsMetaFields[1],
|
---|
103 | metapositions: delCommentsMetapositions
|
---|
104 | };
|
---|
105 | var comment_rec = {
|
---|
106 | metaname: userCommentsMetaFields[2],
|
---|
107 | metapositions: delCommentsMetapositions
|
---|
108 | };
|
---|
109 |
|
---|
110 |
|
---|
111 | var doc_rec = {
|
---|
112 | docid: _docid,
|
---|
113 | metatable: [username_rec, timestamp_rec, comment_rec]
|
---|
114 | };
|
---|
115 |
|
---|
116 | docArray.push(doc_rec);
|
---|
117 | }
|
---|
118 | }
|
---|
119 |
|
---|
120 | //alert("deleting: " + JSON.stringify(docArray));
|
---|
121 | return docArray;
|
---|
122 | }
|
---|
123 |
|
---|
124 | // Determine if the user comment edits should be a synchronous AJAX call
|
---|
125 | function forceSyncUserCommentsEdits(editsDocArray, docids_to_delCommentsMetapositions) {
|
---|
126 | var forceSync = false;
|
---|
127 | var docids = Object.keys(docids_to_delCommentsMetapositions);
|
---|
128 | if(docids.length == 0) { // no user comments deletions, so can process user comment edits async
|
---|
129 | return false;
|
---|
130 | }
|
---|
131 | var edits = Object.keys(editsDocArray);
|
---|
132 | if(edits.length == 0) { // no user comments edits
|
---|
133 | return false;
|
---|
134 | }
|
---|
135 |
|
---|
136 | var i = 0;
|
---|
137 | for(i = 0; i < docids.length; i++) {
|
---|
138 | var docid = docids[i];
|
---|
139 |
|
---|
140 | // sort metapositions of deletes to get at lowest metaposition for this docid
|
---|
141 | var metapositions = docids_to_delCommentsMetapositions[docid].sort(); // non-zero length array
|
---|
142 | var lowestDelMetapos = metapositions[0]; // lowest metaposition at lowest index
|
---|
143 |
|
---|
144 | // https://javascript.plainenglish.io/check-if-an-array-contains-an-object-with-a-certain-property-value-in-javascript-5325295a5820
|
---|
145 | // https://stackoverflow.com/questions/237104/how-do-i-check-if-an-array-includes-a-value-in-javascript/24827594#24827594
|
---|
146 | // https://stackoverflow.com/questions/254302/how-can-i-determine-the-type-of-an-html-element-in-javascript
|
---|
147 |
|
---|
148 | var match_docRecord = editsDocArray.find((doc_rec) => doc_rec.docid === docid);
|
---|
149 | if (match_docRecord) { // defined: this docid exists in an object in array
|
---|
150 | //if(editsDocArray.some(item => item.docid === docid)) { // this docid exists in object
|
---|
151 | //if(editsDocArray[docid] !== undefined) {
|
---|
152 | // compare lowest metaposition of user comment to be deleted for this docid
|
---|
153 | // against the highest metapos of user comment being edited for this docid
|
---|
154 | // Metapositions array of deletes would contain metapos in ascending order
|
---|
155 | var metatable = match_docRecord.metatable; // array of non-zero length
|
---|
156 | //alert("Found docid match " + JSON.stringify(match_docRecord) + " comparing low metapos " + lowestDelMetapos);
|
---|
157 |
|
---|
158 | // https://www.digitalocean.com/community/tutorials/js-array-search-methods
|
---|
159 | // Get array of user comment edits that are affected by deletions happening earlier
|
---|
160 | // in the file (deletes that have a lower metapos than the metapos of the edit).
|
---|
161 | var editsAffectedByDeletes = metatable.filter(meta_rec => meta_rec.metapos >= lowestDelMetapos);
|
---|
162 | if(editsAffectedByDeletes.length > 0) { //if any edits affected by dels, forceSync ajax
|
---|
163 | forceSync = true; // ensure we process all edits first before processing deletes
|
---|
164 | //alert("FORCE_SYNC because " + JSON.stringify(editsAffectedByDeletes)
|
---|
165 | // + " are affected by deletes starting: " + lowestDelMetapos);
|
---|
166 | } // else all user comment edits for this docid happen earlier (lower metapos) to deletes
|
---|
167 | }
|
---|
168 | }
|
---|
169 | return forceSync;
|
---|
170 | }
|
---|
171 |
|
---|
172 | function addEditUserCommentsLink(cell) {
|
---|
173 | cell = $(cell);
|
---|
174 | var doc_id = cell.attr("id").substring(6);
|
---|
175 |
|
---|
176 | var edit_usercomments_table = document.getElementById("usercomments-"+doc_id);
|
---|
177 |
|
---|
178 | var edit_meta_table = document.getElementById("meta"+doc_id);
|
---|
179 | var comments = edit_meta_table.querySelectorAll('.metaTableCellArea.gsusercomment');
|
---|
180 | var gsMetaPrefix = "gs"; // metadata name prefix
|
---|
181 |
|
---|
182 | var unames = [];
|
---|
183 | var timestamps = [];
|
---|
184 |
|
---|
185 |
|
---|
186 | if(comments.length <= 0) {
|
---|
187 | gsMetaPrefix = "";
|
---|
188 |
|
---|
189 | comments = edit_meta_table.querySelectorAll('.metaTableCellArea.usercomment');
|
---|
190 | if(comments.length <= 0) {
|
---|
191 | return;
|
---|
192 | }
|
---|
193 | }
|
---|
194 |
|
---|
195 |
|
---|
196 | var classname = ".metaTableCellArea." + gsMetaPrefix + "username";
|
---|
197 | unames = edit_meta_table.querySelectorAll(classname);
|
---|
198 | classname = ".metaTableCellArea." + gsMetaPrefix + "usertimestamp";
|
---|
199 | timestamps = edit_meta_table.querySelectorAll(classname);
|
---|
200 |
|
---|
201 | //console.log(comments[0].textContent);
|
---|
202 | //console.log(unames[0].textContent);
|
---|
203 | //console.log(timestamps[0].textContent);
|
---|
204 |
|
---|
205 |
|
---|
206 | var headerRow = document.createElement("tr");
|
---|
207 | edit_usercomments_table.appendChild(headerRow);
|
---|
208 |
|
---|
209 | var i = 0;
|
---|
210 | // work with tbody child of metadatatable's table element
|
---|
211 | edit_meta_table = edit_meta_table.firstElementChild;
|
---|
212 | for(i = 0; i < comments.length; i++) {
|
---|
213 | var newRow = document.createElement("tr");
|
---|
214 | edit_usercomments_table.appendChild(newRow);
|
---|
215 |
|
---|
216 | var rowNumCell, txtNode;
|
---|
217 | if(i == 0) {
|
---|
218 | rowNumCell = document.createElement("th");
|
---|
219 | rowNumCell.setAttribute("class", "metaposCell");
|
---|
220 | txtNode = document.createTextNode("metapos");
|
---|
221 | rowNumCell.appendChild(txtNode);
|
---|
222 | headerRow.appendChild(rowNumCell);
|
---|
223 | }
|
---|
224 | rowNumCell = document.createElement("td");
|
---|
225 | rowNumCell.setAttribute("class", "metaposCell");
|
---|
226 | txtNode = document.createTextNode(i+"");
|
---|
227 | rowNumCell.appendChild(txtNode);
|
---|
228 | newRow.appendChild(rowNumCell);
|
---|
229 |
|
---|
230 |
|
---|
231 | //Row we work with each time: get the closest ancestor of comments[i] that is a <tr>
|
---|
232 | // If you change the order the rows are moved into usercomments-table below, the
|
---|
233 | // userCommentsMetaFields[] array ordering in documentedit_scripts_util.js will be affected
|
---|
234 | shiftRowData(timestamps[i].closest("tr"), edit_meta_table, newRow, i, headerRow);
|
---|
235 | shiftRowData(unames[i].closest("tr"), edit_meta_table, newRow, i, headerRow);
|
---|
236 | shiftRowData(comments[i].closest("tr"), edit_meta_table, newRow, i, headerRow);
|
---|
237 |
|
---|
238 | //console.log("NEWROW:" + newRow.firstElementChild.textContent);
|
---|
239 | addRemoveLinkToRow(newRow);
|
---|
240 |
|
---|
241 | }
|
---|
242 |
|
---|
243 | var row = cell.parent();
|
---|
244 | var newCell = $("<td>", {
|
---|
245 | "style": "font-size:0.7em; padding:0px 10px",
|
---|
246 | "class": "editMapGPSButton"
|
---|
247 | });
|
---|
248 | var linkSpan = $("<span>", {
|
---|
249 | "class": "ui-state-default ui-corner-all",
|
---|
250 | "style": "padding: 2px; float:left;"
|
---|
251 | });
|
---|
252 |
|
---|
253 | var linkLabel = $("<span>" + gs.text.de.edit_usercomments + "</span>");
|
---|
254 | var linkIcon = $("<span>", {
|
---|
255 | "class": "ui-icon ui-icon-folder-collapsed"
|
---|
256 | });
|
---|
257 | newCell.linkIcon = linkIcon;
|
---|
258 | newCell.linkLabel = linkLabel;
|
---|
259 |
|
---|
260 | var uList = $("<ul>", {
|
---|
261 | "style": "outline: 0 none; margin:0px; padding:0px;"
|
---|
262 | });
|
---|
263 | var labelItem = $("<li>", {
|
---|
264 | "style": "float:left; list-style:none outside none;"
|
---|
265 | });
|
---|
266 | var iconItem = $("<li>", {
|
---|
267 | "style": "float:left; list-style:none outside none;"
|
---|
268 | });
|
---|
269 |
|
---|
270 | uList.append(iconItem);
|
---|
271 | uList.append(labelItem);
|
---|
272 | labelItem.append(linkLabel);
|
---|
273 | iconItem.append(linkIcon);
|
---|
274 |
|
---|
275 | var newLink = $("<a>", {
|
---|
276 | "href": "javascript:;"
|
---|
277 | });
|
---|
278 |
|
---|
279 | newLink.on("click", function () {
|
---|
280 | if (edit_usercomments_table.style.display == "none") {
|
---|
281 | linkLabel.html(gs.text.de.hide_usercomments);
|
---|
282 | linkIcon.attr("class", "ui-icon ui-icon-folder-open");
|
---|
283 | edit_usercomments_table.style.display = "block";
|
---|
284 | } else {
|
---|
285 | linkLabel.html(gs.text.de.edit_usercomments);
|
---|
286 | linkIcon.attr("class", "ui-icon ui-icon-folder-collapsed");
|
---|
287 | edit_usercomments_table.style.display = "none";
|
---|
288 |
|
---|
289 | }
|
---|
290 | });
|
---|
291 |
|
---|
292 | newLink.append(uList);
|
---|
293 | linkSpan.append(newLink);
|
---|
294 | newCell.append(linkSpan);
|
---|
295 | row.append(newCell);
|
---|
296 | }
|
---|
297 |
|
---|
298 | function makeHeaderCellFrom(row, headerRow) {
|
---|
299 | var cellName = row.querySelector('.metaTableCellName').textContent;
|
---|
300 | var headerCell = document.createElement("th");
|
---|
301 | headerCell.setAttribute("class", "metaTableCellName");
|
---|
302 | var txt = document.createTextNode(cellName);
|
---|
303 | headerCell.appendChild(txt);
|
---|
304 | headerRow.appendChild(headerCell);
|
---|
305 | }
|
---|
306 |
|
---|
307 | function shiftRowData(row, edit_meta_table, newRow, rownum, headerRow) {
|
---|
308 | if(rownum == 0) {
|
---|
309 | makeHeaderCellFrom(row, headerRow);
|
---|
310 | }
|
---|
311 | edit_meta_table.removeChild(row);
|
---|
312 | var oldCell = row.querySelector('.metaTableCell');
|
---|
313 | newRow.appendChild(oldCell);
|
---|
314 | var el = oldCell.querySelector('.metaTableCellArea');
|
---|
315 | el.classList.add("threecol");
|
---|
316 | }
|
---|