Старый МТФ
В портальном блоке Smart Html слева выводится список незавершеных задач из категории, а справа — список завершенных. По клику на задачу она переводится в статус "Завершено" и переходит из левого списка в правый. После этого страница перезагружается, чтобы отобразить обновленные данные. Если переход невозможен, выдается окно с предупреждением (swal — SweetAlert — замена стандартного окна предупреждения).
Полезные ссылки
Работа с блоком Smart Html описана здесь.
Для обращения к данным, отбираемым с помощью смарт-выражений, используется шаблонизатор mustache.
Описание шаблонизатора mustache на английском
Описание шаблонизатора mustache на русском
Решение
Верстка блока
<div class='block-wrapper'>
<div class='block-wrapper__tasks'>
<h3>Задачи <i id="addNewTask" class="add-task fa fa-plus-circle"></i></h3>
<div>
{{#smart555}}
<div>
<span data-state-id='{{stateID}}' data-task-id='{{taskID}}' class='task-item'>{{description}}</span>
<i data-task-id='{{taskID}}' class="to-complete fa fa-arrow-right"></i>
</div>
{{/smart555}}
</div>
</div>
<div class='block-wrapper__completed-tasks'>
<h3>Завершенные задачи</h3>
<div class="block-wrapper__completed-tasks-list"></div>
</div>
</div>
JS-вставка
В начале JS-вставки подключаются скрипты polyfill и sweetalert. Их можно подключать непосредственно из HTML-верстки, но считается правилом хорошего тона подключать все скрипты из JS. |
---|
//polyfill
var promisePolyfill = document.createElement('script');
promisePolyfill.setAttribute('src','https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.js');
document.head.appendChild(promisePolyfill);
//sweetalert
var sweetAlertScript = document.createElement('script');
sweetAlertScript.setAttribute('src','https://cdn.jsdelivr.net/npm/sweetalert2@8');
document.head.appendChild(sweetAlertScript);
// обновление страницы
function reloadPage() {
window.location.reload();
}
(window.firstForma.portal.block(1234)).onLoaded(function() {
// назначаем обработчик для события клика по кнопке создания задачи
document.getElementById('addNewTask').addEventListener('click', function() {
var openedWindow = radopen('/NewTask.aspx?&SubCatID=123456&returnjs=window.top.reloadPage();');
});
// для каждой задачи назначаем обработчик для события клика по тексту задачи
var tasks = document.getElementsByClassName('task-item');
var completedTasks = [];
for (var i = 0; i < tasks.length; i++) {
var stateId = tasks[i].dataset.stateId;
tasks[i].addEventListener('click', function() {
var task = event.target;
var taskId = task.dataset.taskId;
var url = '/MainTaskForm.aspx?taskId=' + taskId;
var openedWindow = radopen(url);
});
// stateId = 3 соответствует статусу "Завершено", завершенные задачи заносим в отдельный список
if (+stateId === 3) {
completedTasks.push({
taskId: tasks[i].dataset.taskId,
taskText: tasks[i].innerHTML
});
}
}
function isTasksArrayIncludedTask(taskArray, taskId) {
var isTasksArrayIncludedTask = taskArray.find(function (task) {
return task.taskId === taskId;
});
return !!isTasksArrayIncludedTask;
}
// готовим Promise, см. здесь
function httpPostRequest(url, data) {
var data = data || {};
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url);
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.onload = function() {
if (this.status == 200) {
resolve(this.response);
} else {
reject(this.response);
}
};
xhr.onerror = function() {
reject(new Error("Network Error"));
};
xhr.send(data);
});
}
// функция добавляет завершенные задачи в список в правой половине блока
// tasks: {taskId: number; taskText: string}[]
function addCompletedTasks(tasks) {
var completedTaskWrapper = document.getElementsByClassName('block-wrapper__completed-tasks-list')[0];
for (var i = 0; i < tasks.length; i++) {
var completedTask = document.createElement('div');
completedTask.innerHTML = tasks[i].taskText;
completedTask.dataset.taskId = tasks[i].taskId;
completedTask.classList.add('completed-task-item');
completedTaskWrapper.appendChild(completedTask);
}
}
// функция удаляет завершенные задачи из списка в левой половине блока
// tasks: {taskId: number; taskText: string}[]
function removeTasks(tasks) {
var itemsToRemove = [];
var taskItems = document.getElementsByClassName('task-item');
for (var i = 0; i < taskItems.length; i++) {
var currentTask = taskItems[i];
if (isTasksArrayIncludedTask(tasks, currentTask.dataset.taskId)) {
itemsToRemove.push(currentTask);
}
}
for (var i = 0; i < itemsToRemove.length; i++) {
itemsToRemove[i].parentNode.remove();
}
}
// переносим завершенные задачи из левой части в правую
addCompletedTasks(completedTasks);
removeTasks(completedTasks);
// назначаем обработчик для события клика для каждой кнопки завершения задачи
var completeButtons = document.getElementsByClassName('to-complete');
for (var i = 0; i < completeButtons.length; i++) {
completeButtons[i].addEventListener('click', function(event) {
var plusBtn = event.target;
var taskId = plusBtn.dataset.taskId;
var url = '/app/v1.0/api/task/step/' + taskId;
var data = JSON.stringify({stepId: 99, comment: "Задача завершена"});
var completedTask = [{
taskId: taskId,
taskText: event.target.parentNode.getElementsByClassName('task-item')[0].innerText
}];
httpPostRequest(url, data).then(
function(response) {
addCompletedTasks(completedTask);
removeTasks(completedTask);
},
function(error) {
Swal.fire({
type: 'error',
title: 'Ошибка',
text: JSON.parse(error).message,
footer: '<a href="https://1forma.ru/help.html" target="_blank">Помощь</a>'
});
}
);
});
}
});