Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/lib/utils/recurrence.js')
-rw-r--r--app/assets/javascripts/lib/utils/recurrence.js154
1 files changed, 154 insertions, 0 deletions
diff --git a/app/assets/javascripts/lib/utils/recurrence.js b/app/assets/javascripts/lib/utils/recurrence.js
new file mode 100644
index 00000000000..8fd26f3e393
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/recurrence.js
@@ -0,0 +1,154 @@
+import { uuids } from './uuids';
+
+/**
+ * @module recurrence
+ */
+
+const instances = {};
+
+/**
+ * Create a new unique {@link module:recurrence~RecurInstance|RecurInstance}
+ * @returns {module:recurrence.RecurInstance} The newly created {@link module:recurrence~RecurInstance|RecurInstance}
+ */
+export function create() {
+ const id = uuids()[0];
+ let handlers = {};
+ let count = 0;
+
+ /**
+ * @namespace RecurInstance
+ * @description A RecurInstance tracks the count of any occurrence as registered by calls to <code>occur</code>.
+ * <br /><br />
+ * It maintains an internal counter and a registry of handlers that can be arbitrarily assigned by a user.
+ * <br /><br />
+ * While a RecurInstance isn't specific to any particular use-case, it may be useful for:
+ * <br />
+ * <ul>
+ * <li>Tracking repeated errors across multiple - but not linked - network requests</li>
+ * <li>Tracking repeated user interactions (e.g. multiple clicks)</li>
+ * </ul>
+ * @summary A closure to track repeated occurrences of any arbitrary event.
+ * */
+ const instance = {
+ /**
+ * @type {module:uuids~UUIDv4}
+ * @description A randomly generated {@link module:uuids~UUIDv4|UUID} for this particular recurrence instance
+ * @memberof module:recurrence~RecurInstance
+ * @readonly
+ * @inner
+ */
+ get id() {
+ return id;
+ },
+ /**
+ * @type {Number}
+ * @description The number of times this particular instance of recurrence has been triggered
+ * @memberof module:recurrence~RecurInstance
+ * @readonly
+ * @inner
+ */
+ get count() {
+ return count;
+ },
+ /**
+ * @type {Object}
+ * @description The handlers assigned to this recurrence tracker
+ * @example
+ * myRecurrence.handle( 4, () => console.log( "four" ) );
+ * console.log( myRecurrence.handlers ); // {"4": () => console.log( "four" )}
+ * @memberof module:recurrence~RecurInstance
+ * @readonly
+ * @inner
+ */
+ get handlers() {
+ return handlers;
+ },
+ /**
+ * @type {Boolean}
+ * @description Delete any internal reference to the instance.
+ * <br />
+ * Keep in mind that this will only attempt to remove the <strong>internal</strong> reference.
+ * <br />
+ * If your code maintains a reference to the instance, the regular garbage collector will not free the memory.
+ * @memberof module:recurrence~RecurInstance
+ * @inner
+ */
+ free() {
+ return delete instances[id];
+ },
+ /**
+ * @description Register a handler to be called when this occurrence is seen <code>onCount</code> number of times.
+ * @param {Number} onCount - The number of times the occurrence has been seen to respond to
+ * @param {Function} behavior - A callback function to run when the occurrence has been seen <code>onCount</code> times
+ * @memberof module:recurrence~RecurInstance
+ * @inner
+ */
+ handle(onCount, behavior) {
+ if (onCount && behavior) {
+ handlers[onCount] = behavior;
+ }
+ },
+ /**
+ * @description Remove the behavior callback handler that would be run when the occurrence is seen <code>onCount</code> times
+ * @param {Number} onCount - The count identifier for which to eject the callback handler
+ * @memberof module:recurrence~RecurInstance
+ * @inner
+ */
+ eject(onCount) {
+ if (onCount) {
+ delete handlers[onCount];
+ }
+ },
+ /**
+ * @description Register that this occurrence has been seen and trigger any appropriate handlers
+ * @memberof module:recurrence~RecurInstance
+ * @inner
+ */
+ occur() {
+ count += 1;
+
+ if (typeof handlers[count] === 'function') {
+ handlers[count](count);
+ }
+ },
+ /**
+ * @description Reset this recurrence instance without destroying it entirely
+ * @param {Object} [options]
+ * @param {Boolean} [options.currentCount = true] - Whether to reset the count
+ * @param {Boolean} [options.handlersList = false] - Whether to reset the list of attached handlers back to an empty state
+ * @memberof module:recurrence~RecurInstance
+ * @inner
+ */
+ reset({ currentCount = true, handlersList = false } = {}) {
+ if (currentCount) {
+ count = 0;
+ }
+
+ if (handlersList) {
+ handlers = {};
+ }
+ },
+ };
+
+ instances[id] = instance;
+
+ return instance;
+}
+
+/**
+ * Retrieve a stored {@link module:recurrence~RecurInstance|RecurInstance} by {@link module:uuids~UUIDv4|UUID}
+ * @param {module:uuids~UUIDv4} id - The {@link module:uuids~UUIDv4|UUID} of a previously created {@link module:recurrence~RecurInstance|RecurInstance}
+ * @returns {(module:recurrence~RecurInstance|undefined)} The {@link module:recurrence~RecurInstance|RecurInstance}, or undefined if the UUID doesn't refer to a known Instance
+ */
+export function recall(id) {
+ return instances[id];
+}
+
+/**
+ * Release the memory space for a given {@link module:recurrence~RecurInstance|RecurInstance} by {@link module:uuids~UUIDv4|UUID}
+ * @param {module:uuids~UUIDv4} id - The {@link module:uuids~UUIDv4|UUID} of a previously created {@link module:recurrence~RecurInstance|RecurInstance}
+ * @returns {Boolean} Whether the reference to the stored {@link module:recurrence~RecurInstance|RecurInstance} was released
+ */
+export function free(id) {
+ return recall(id)?.free() || false;
+}