Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / history / js / history.es6.js
diff --git a/web/core/modules/history/js/history.es6.js b/web/core/modules/history/js/history.es6.js
new file mode 100644 (file)
index 0000000..53a1d05
--- /dev/null
@@ -0,0 +1,130 @@
+/**
+ * @file
+ * JavaScript API for the History module, with client-side caching.
+ *
+ * May only be loaded for authenticated users, with the History module enabled.
+ */
+
+(function ($, Drupal, drupalSettings, storage) {
+  const currentUserID = parseInt(drupalSettings.user.uid, 10);
+
+  // Any comment that is older than 30 days is automatically considered read,
+  // so for these we don't need to perform a request at all!
+  const thirtyDaysAgo = Math.round(new Date().getTime() / 1000) - 30 * 24 * 60 * 60;
+
+  // Use the data embedded in the page, if available.
+  let embeddedLastReadTimestamps = false;
+  if (drupalSettings.history && drupalSettings.history.lastReadTimestamps) {
+    embeddedLastReadTimestamps = drupalSettings.history.lastReadTimestamps;
+  }
+
+  /**
+   * @namespace
+   */
+  Drupal.history = {
+
+    /**
+     * Fetch "last read" timestamps for the given nodes.
+     *
+     * @param {Array} nodeIDs
+     *   An array of node IDs.
+     * @param {function} callback
+     *   A callback that is called after the requested timestamps were fetched.
+     */
+    fetchTimestamps(nodeIDs, callback) {
+      // Use the data embedded in the page, if available.
+      if (embeddedLastReadTimestamps) {
+        callback();
+        return;
+      }
+
+      $.ajax({
+        url: Drupal.url('history/get_node_read_timestamps'),
+        type: 'POST',
+        data: { 'node_ids[]': nodeIDs },
+        dataType: 'json',
+        success(results) {
+          for (const nodeID in results) {
+            if (results.hasOwnProperty(nodeID)) {
+              storage.setItem(`Drupal.history.${currentUserID}.${nodeID}`, results[nodeID]);
+            }
+          }
+          callback();
+        },
+      });
+    },
+
+    /**
+     * Get the last read timestamp for the given node.
+     *
+     * @param {number|string} nodeID
+     *   A node ID.
+     *
+     * @return {number}
+     *   A UNIX timestamp.
+     */
+    getLastRead(nodeID) {
+      // Use the data embedded in the page, if available.
+      if (embeddedLastReadTimestamps && embeddedLastReadTimestamps[nodeID]) {
+        return parseInt(embeddedLastReadTimestamps[nodeID], 10);
+      }
+      return parseInt(storage.getItem(`Drupal.history.${currentUserID}.${nodeID}`) || 0, 10);
+    },
+
+    /**
+     * Marks a node as read, store the last read timestamp client-side.
+     *
+     * @param {number|string} nodeID
+     *   A node ID.
+     */
+    markAsRead(nodeID) {
+      $.ajax({
+        url: Drupal.url(`history/${nodeID}/read`),
+        type: 'POST',
+        dataType: 'json',
+        success(timestamp) {
+          // If the data is embedded in the page, don't store on the client
+          // side.
+          if (embeddedLastReadTimestamps && embeddedLastReadTimestamps[nodeID]) {
+            return;
+          }
+
+          storage.setItem(`Drupal.history.${currentUserID}.${nodeID}`, timestamp);
+        },
+      });
+    },
+
+    /**
+     * Determines whether a server check is necessary.
+     *
+     * Any content that is >30 days old never gets a "new" or "updated"
+     * indicator. Any content that was published before the oldest known reading
+     * also never gets a "new" or "updated" indicator, because it must've been
+     * read already.
+     *
+     * @param {number|string} nodeID
+     *   A node ID.
+     * @param {number} contentTimestamp
+     *   The time at which some content (e.g. a comment) was published.
+     *
+     * @return {bool}
+     *   Whether a server check is necessary for the given node and its
+     *   timestamp.
+     */
+    needsServerCheck(nodeID, contentTimestamp) {
+      // First check if the content is older than 30 days, then we can bail
+      // early.
+      if (contentTimestamp < thirtyDaysAgo) {
+        return false;
+      }
+
+      // Use the data embedded in the page, if available.
+      if (embeddedLastReadTimestamps && embeddedLastReadTimestamps[nodeID]) {
+        return contentTimestamp > parseInt(embeddedLastReadTimestamps[nodeID], 10);
+      }
+
+      const minLastReadTimestamp = parseInt(storage.getItem(`Drupal.history.${currentUserID}.${nodeID}`) || 0, 10);
+      return contentTimestamp > minLastReadTimestamp;
+    },
+  };
+}(jQuery, Drupal, drupalSettings, window.localStorage));