You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
2.7 KiB
JavaScript
108 lines
2.7 KiB
JavaScript
'use strict';
|
|
|
|
const assureArray = require("assure-array");
|
|
const createEventEmitter = require("create-event-emitter");
|
|
const uuid = require("uuid");
|
|
|
|
const findAndSplice = require("../find-and-splice");
|
|
|
|
module.exports = function createTaskTracker() {
|
|
let tasks = [];
|
|
|
|
return createEventEmitter({
|
|
addTask: function addTask(name, indicator, userIds, roleIds, options) {
|
|
let mergedOptions = Object.assign({
|
|
removeWhenDone: true
|
|
}, options);
|
|
|
|
let indicatorType;
|
|
|
|
if (typeof indicator.completed === "function" && typeof indicator.finish === "function") {
|
|
indicatorType = "are-we-there-yet";
|
|
} else if (typeof indicator.await === "function" && typeof indicator.report === "function") {
|
|
indicatorType = "progress-indicator";
|
|
} else {
|
|
throw new Error("Unrecognized indicator type");
|
|
}
|
|
|
|
let task = createEventEmitter({
|
|
id: uuid.v4(),
|
|
name: name,
|
|
started: Date.now(),
|
|
userIds: assureArray(userIds),
|
|
roleIds: assureArray(roleIds),
|
|
indicator: indicator,
|
|
type: indicatorType,
|
|
progress: 0,
|
|
lastOperation: null,
|
|
lastUpdated: null
|
|
});
|
|
|
|
let reportChange = () => {
|
|
this.emit("progress", task, task.progress, task.lastOperation);
|
|
task.emit("progress", task.progress, task.lastOperation);
|
|
}
|
|
|
|
let reportCompleted = () => {
|
|
this.emit("completed", task);
|
|
task.emit("completed");
|
|
|
|
if (mergedOptions.removeWhenDone) {
|
|
this.removeTask(task);
|
|
}
|
|
}
|
|
|
|
tasks.push(task);
|
|
|
|
if (indicatorType === "are-we-there-yet") {
|
|
indicator.on("change", (name, completed, tracker) => {
|
|
task.progress = completed;
|
|
task.lastOperation = name;
|
|
task.lastUpdated = Date.now();
|
|
reportChange();
|
|
|
|
if (completed === 1) {
|
|
reportCompleted();
|
|
}
|
|
});
|
|
} else if (indicatorType === "progress-indicator") {
|
|
indicator.on("progress", (progress, description, completed, total) => {
|
|
task.progress = progress;
|
|
task.lastOperation = description;
|
|
task.lastUpdated = Date.now();
|
|
reportChange();
|
|
});
|
|
|
|
indicator.on("completed", () => {
|
|
reportCompleted();
|
|
});
|
|
}
|
|
|
|
this.emit("newTask", task);
|
|
|
|
assureArray(userIds).forEach((userId) => {
|
|
this.emit(`newTask:user:${userId}`, task);
|
|
});
|
|
|
|
assureArray(roleIds).forEach((roleId) => {
|
|
this.emit(`newTask:role:${roleId}`, task);
|
|
});
|
|
|
|
return task;
|
|
},
|
|
removeTask: function removeTask(task) {
|
|
// FIXME: Do we need to remove event handlers to prevent a memory leak here?
|
|
findAndSplice(tasks, task);
|
|
},
|
|
byUser: function getTasksByUser(userId) {
|
|
return tasks.filter((task) => task.userIds.includes(userId));
|
|
},
|
|
byRole: function getTasksByRole(roleId) {
|
|
return tasks.filter((task) => task.roleIds.includes(roleId))
|
|
},
|
|
all: function getAllTasks() {
|
|
return tasks;
|
|
}
|
|
});
|
|
}
|