dd79f15b9332156c8e6c7c47b2e9ba7aa0845473
[yaffs-website] / web / core / modules / tracker / js / tracker-history.es6.js
1 /**
2  * Attaches behaviors for the Tracker module's History module integration.
3  *
4  * May only be loaded for authenticated users, with the History module enabled.
5  */
6 (function($, Drupal, window) {
7   function processNodeNewIndicators($placeholders) {
8     const newNodeString = Drupal.t('new');
9     const updatedNodeString = Drupal.t('updated');
10
11     $placeholders.each((index, placeholder) => {
12       const timestamp = parseInt(
13         placeholder.getAttribute('data-history-node-timestamp'),
14         10,
15       );
16       const nodeID = placeholder.getAttribute('data-history-node-id');
17       const lastViewTimestamp = Drupal.history.getLastRead(nodeID);
18
19       if (timestamp > lastViewTimestamp) {
20         const message =
21           lastViewTimestamp === 0 ? newNodeString : updatedNodeString;
22         $(placeholder).append(`<span class="marker">${message}</span>`);
23       }
24     });
25   }
26
27   function processNewRepliesIndicators($placeholders) {
28     // Figure out which placeholders need the "x new" replies links.
29     const placeholdersToUpdate = {};
30     $placeholders.each((index, placeholder) => {
31       const timestamp = parseInt(
32         placeholder.getAttribute('data-history-node-last-comment-timestamp'),
33         10,
34       );
35       const nodeID = placeholder.previousSibling.previousSibling.getAttribute(
36         'data-history-node-id',
37       );
38       const lastViewTimestamp = Drupal.history.getLastRead(nodeID);
39
40       // Queue this placeholder's "X new" replies link to be downloaded from the
41       // server.
42       if (timestamp > lastViewTimestamp) {
43         placeholdersToUpdate[nodeID] = placeholder;
44       }
45     });
46
47     // Perform an AJAX request to retrieve node view timestamps.
48     const nodeIDs = Object.keys(placeholdersToUpdate);
49     if (nodeIDs.length === 0) {
50       return;
51     }
52     $.ajax({
53       url: Drupal.url('comments/render_new_comments_node_links'),
54       type: 'POST',
55       data: { 'node_ids[]': nodeIDs },
56       dataType: 'json',
57       success(results) {
58         Object.keys(results || {}).forEach(nodeID => {
59           if (placeholdersToUpdate.hasOwnProperty(nodeID)) {
60             const url = results[nodeID].first_new_comment_link;
61             const text = Drupal.formatPlural(
62               results[nodeID].new_comment_count,
63               '1 new',
64               '@count new',
65             );
66             $(placeholdersToUpdate[nodeID]).append(
67               `<br /><a href="${url}">${text}</a>`,
68             );
69           }
70         });
71       },
72     });
73   }
74
75   /**
76    * Render "new" and "updated" node indicators, as well as "X new" replies links.
77    */
78   Drupal.behaviors.trackerHistory = {
79     attach(context) {
80       // Find all "new" comment indicator placeholders newer than 30 days ago that
81       // have not already been read after their last comment timestamp.
82       const nodeIDs = [];
83       const $nodeNewPlaceholders = $(context)
84         .find('[data-history-node-timestamp]')
85         .once('history')
86         .filter(function() {
87           const nodeTimestamp = parseInt(
88             this.getAttribute('data-history-node-timestamp'),
89             10,
90           );
91           const nodeID = this.getAttribute('data-history-node-id');
92           if (Drupal.history.needsServerCheck(nodeID, nodeTimestamp)) {
93             nodeIDs.push(nodeID);
94             return true;
95           }
96
97           return false;
98         });
99
100       // Find all "new" comment indicator placeholders newer than 30 days ago that
101       // have not already been read after their last comment timestamp.
102       const $newRepliesPlaceholders = $(context)
103         .find('[data-history-node-last-comment-timestamp]')
104         .once('history')
105         .filter(function() {
106           const lastCommentTimestamp = parseInt(
107             this.getAttribute('data-history-node-last-comment-timestamp'),
108             10,
109           );
110           const nodeTimestamp = parseInt(
111             this.previousSibling.previousSibling.getAttribute(
112               'data-history-node-timestamp',
113             ),
114             10,
115           );
116           // Discard placeholders that have zero comments.
117           if (lastCommentTimestamp === nodeTimestamp) {
118             return false;
119           }
120           const nodeID = this.previousSibling.previousSibling.getAttribute(
121             'data-history-node-id',
122           );
123           if (Drupal.history.needsServerCheck(nodeID, lastCommentTimestamp)) {
124             if (nodeIDs.indexOf(nodeID) === -1) {
125               nodeIDs.push(nodeID);
126             }
127             return true;
128           }
129
130           return false;
131         });
132
133       if (
134         $nodeNewPlaceholders.length === 0 &&
135         $newRepliesPlaceholders.length === 0
136       ) {
137         return;
138       }
139
140       // Fetch the node read timestamps from the server.
141       Drupal.history.fetchTimestamps(nodeIDs, () => {
142         processNodeNewIndicators($nodeNewPlaceholders);
143         processNewRepliesIndicators($newRepliesPlaceholders);
144       });
145     },
146   };
147 })(jQuery, Drupal, window);