mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 22:43:42 +00:00
The todo_widget was using the using a counter to store the key value of every task. This would cause assiging multiple tasks the same key value in a race condition. To avoid this we make "sender_id" a part of the key along with the counter. Also the `key` now not being a integer value, we can't use it to find the index of the task using it. Thus, a function is made that will find the index of task whose key is sent by the user to strike.
186 lines
5.3 KiB
JavaScript
186 lines
5.3 KiB
JavaScript
const render_widgets_todo_widget = require('../templates/widgets/todo_widget.hbs');
|
|
const render_widgets_todo_widget_tasks = require('../templates/widgets/todo_widget_tasks.hbs');
|
|
|
|
exports.task_data_holder = function () {
|
|
const self = {};
|
|
|
|
const all_tasks = [];
|
|
const pending_tasks = [];
|
|
const completed_tasks = [];
|
|
let my_idx = 1;
|
|
|
|
self.get_widget_data = function () {
|
|
|
|
const widget_data = {
|
|
pending_tasks: pending_tasks,
|
|
completed_tasks: completed_tasks,
|
|
};
|
|
|
|
return widget_data;
|
|
};
|
|
|
|
self.check_task = {
|
|
task_exists: function (task) {
|
|
const task_exists = all_tasks.some(item => item.task === task);
|
|
return task_exists;
|
|
},
|
|
|
|
get_task_index: function (list, val) {
|
|
return Object.keys(list).find(index => list[index].key === val);
|
|
},
|
|
};
|
|
|
|
self.handle = {
|
|
new_task: {
|
|
outbound: function (task, desc) {
|
|
const event = {
|
|
type: 'new_task',
|
|
key: my_idx,
|
|
task: task,
|
|
desc: desc,
|
|
completed: false,
|
|
};
|
|
my_idx += 1;
|
|
|
|
if (!self.check_task.task_exists(task)) {
|
|
return event;
|
|
}
|
|
return;
|
|
},
|
|
|
|
inbound: function (sender_id, data) {
|
|
const idx = data.key;
|
|
const key = idx + "," + sender_id;
|
|
const task = data.task;
|
|
const desc = data.desc;
|
|
const completed = data.completed;
|
|
|
|
const task_data = {
|
|
task: task,
|
|
desc: desc,
|
|
user_id: sender_id,
|
|
key: key,
|
|
completed: completed,
|
|
};
|
|
|
|
if (!self.check_task.task_exists(task)) {
|
|
pending_tasks.push(task_data);
|
|
all_tasks.push(task_data);
|
|
|
|
if (my_idx <= idx) {
|
|
my_idx = idx + 1;
|
|
}
|
|
}
|
|
},
|
|
},
|
|
|
|
strike: {
|
|
outbound: function (key) {
|
|
const event = {
|
|
type: 'strike',
|
|
key: key,
|
|
};
|
|
|
|
return event;
|
|
},
|
|
|
|
inbound: function (sender_id, data) {
|
|
const key = data.key;
|
|
const task_index = self.check_task.get_task_index(all_tasks, key);
|
|
const task = all_tasks[task_index];
|
|
let index;
|
|
|
|
if (task === undefined) {
|
|
blueslip.error('unknown key for tasks: ' + key);
|
|
return;
|
|
}
|
|
|
|
all_tasks[task_index].completed = !all_tasks[task_index].completed;
|
|
|
|
// toggle
|
|
if (task.completed) {
|
|
index = pending_tasks.indexOf(task);
|
|
pending_tasks.splice(index, 1);
|
|
completed_tasks.unshift(task);
|
|
} else {
|
|
index = completed_tasks.indexOf(task);
|
|
completed_tasks.splice(index, 1);
|
|
pending_tasks.push(task);
|
|
}
|
|
},
|
|
},
|
|
};
|
|
|
|
self.handle_event = function (sender_id, data) {
|
|
const type = data.type;
|
|
if (self.handle[type]) {
|
|
self.handle[type].inbound(sender_id, data);
|
|
}
|
|
};
|
|
|
|
return self;
|
|
};
|
|
|
|
exports.activate = function (opts) {
|
|
const elem = opts.elem;
|
|
const callback = opts.callback;
|
|
|
|
const task_data = exports.task_data_holder();
|
|
|
|
function render() {
|
|
const html = render_widgets_todo_widget();
|
|
elem.html(html);
|
|
|
|
elem.find("button.add-task").on('click', function (e) {
|
|
e.stopPropagation();
|
|
elem.find(".widget-error").text('');
|
|
const task = elem.find("input.add-task").val().trim();
|
|
const desc = elem.find("input.add-desc").val().trim();
|
|
|
|
if (task === '') {
|
|
return;
|
|
}
|
|
|
|
elem.find(".add-task").val('').focus();
|
|
elem.find(".add-desc").val('').focus();
|
|
|
|
const task_exists = task_data.check_task.task_exists(task);
|
|
if (task_exists) {
|
|
elem.find(".widget-error").text(i18n.t('Task already exists'));
|
|
return;
|
|
}
|
|
|
|
const data = task_data.handle.new_task.outbound(task, desc);
|
|
callback(data);
|
|
});
|
|
}
|
|
|
|
function render_results() {
|
|
const widget_data = task_data.get_widget_data();
|
|
const html = render_widgets_todo_widget_tasks(widget_data);
|
|
elem.find('ul.todo-widget').html(html);
|
|
elem.find(".widget-error").text('');
|
|
|
|
elem.find("button.task").on('click', function (e) {
|
|
e.stopPropagation();
|
|
const key = $(e.target).attr('data-key');
|
|
|
|
const data = task_data.handle.strike.outbound(key);
|
|
callback(data);
|
|
});
|
|
}
|
|
|
|
elem.handle_events = function (events) {
|
|
for (const event of events) {
|
|
task_data.handle_event(event.sender_id, event.data);
|
|
}
|
|
|
|
render_results();
|
|
};
|
|
|
|
render();
|
|
render_results();
|
|
};
|
|
|
|
window.todo_widget = exports;
|