Skip to main content

Примеры скриптов конфигуратора

В статье представлены скрипты, которые вы можете использовать в конфигураторе и редактировать в любых ваших целях.

ВАЖНО: скрипты не проходили полноценного тестирования и не являются штатным функционалом, поэтому можно ожидать, что они будут сбоить или работать неожидаемым образом.

 
Добавляет второго исполнителя ко всем задачам первого исполнителя

Для запуска скрипта нужно из-под администратора нажать Ctrl + Shift + / , в первом поле заполнить почту уже существующего исполнителя, во втором — нового исполнителя.

Скрипт включает второго пользователя во все проекты существующего под ролью Сотрудник, не забудьте ее сменить.

Работает только в браузере с возможностью открыть запрос (prompt).

Events.onKeyUp = function (event) { // следим за клавиатурой
  if (Events.isShiftPressed() && 
  Events.isCtrlPressed() && 
  Current.user.isAdmin &&
  event.keyCode === 191) { // если вызывает админ через Shift, Ctrl и /
   const assignedUserEmail = prompt('Введите email текущего исполнителя') // запрашиваем первый емейл
   const userToAssignEmail = prompt('Введите email нового исполнителя') // запрашиваем второй
   const assignedUser = Users.listAll().find(user => user.email === assignedUserEmail) // найдем текущего исполнителя
   const userToAssign = Users.listAll().find(user => user.email === userToAssignEmail)// найдем второго исполнителя
  // если емейлы не найдены, то показываем ошибку
   if (assignedUser === undefined) {alert('Email текущего исполнителя не найден')}
   if (userToAssign === undefined) {alert('Email нового исполнителя не найден')}

   if (userToAssign !== undefined && userToAssign !== undefined) { // если все нормально
     for (const project of Current.company.list())
      for (const boards of project.list()) // проекты на доски
      for (const columns of boards.list()) // доски на колонки
      for (const task of columns.list()) { // колонки на задачи
        if (Users.isUserAssigned(assignedUser, task)) { // если старый сотрудник подписан
          const usersInTask = Users.getAssigned(task, true) // получим список уже подписанных сотрудников
          const newUsersList = [...usersInTask, userToAssign] // добавим в него нового
    Users.assignUser(newUsersList, task) // применим этот список
    Users.addToChat(userToAssign, task) // подпишем в чат
     if (Users.isInProject(assignedUser, project)) { // в проекты, в которые добавлен текущий исполнитель
        Users.addToProject(userToAssign, project) // подпишем второго исполнителя
       }
  }}}
}}

Крепит к названию новой задачи номер со сквозной нумерацией по компании.

image.png

function addTo(task) {
    var data = task.getData();
    if (data.id) {
        return;
    }
    var cData = Current.company.getData();
    var curId = cData.currentId || 1;
    curId++;
    data.id = 'ID' + curId;
    task.setData(data);
    cData.currentId = curId;
    Current.company.setData(cData);
}

function getId(task, recur) {
    var data = task.getData();
    if (!data.id) {
        if (recur) {
            return;
        }
        addTo(task);
        return getId(task, true);
    }
    return data.id;
}

Items.onAdd = function(task) {
    if (task.type !== 'Task') {
        return;
    }
    addTo(task);
    var data = task.getData();
    task.name = '[' + data.id + ']' + ' ' + task.name; //Добавляет в название задачи ID
};

Вставляет сквозные по компании ID задач в тело карточки задач.

image.png

function addTo(task) {
    var data = task.getData();
    if (data.id) {
        return;
    }
    var cData = Current.company.getData();
    var curId = cData.currentId || 1;
    curId++;
    data.id = 'ID' + curId;
    task.setData(data);
    cData.currentId = curId;
    Current.company.setData(cData);
}

function getId(task, recur) {
    var data = task.getData();
    if (!data.id) {
        if (recur) {
            return;
        }
        addTo(task);
        return getId(task, true);
    }
    return data.id;
}

Items.onAdd = function(task) {
    if (task.type !== 'Task') {
        return;
    }
    addTo(task);
};

var style = {
    position: 'absolute',
    fontSize: '9px',
    right: '4px',
    top: '-1px',
    fontWeight: 'bold'
};

Items.onList = function(obj, arr) {
    if (obj.type === 'Column') {
        arr.forEach(function(t) {
            var id = getId(t);
            var el = UI.text(id);
            el.style = style;
            t.ui.clear();
            t.ui.add(el);
        });
    }
    return arr;
};
Архивация задач при выполнении.

// Архивирует задачи при их выполнении
Items.onUpdate = function(obj) { // вызываем при обновлении 
    if (obj.isCompleted() === true) { // если задача выполнена
        obj.setTaskCompleted(true); // то архивируем ее
    }
};


Закрытие задачи при перемещении в определенную колонку.

// При перемещении в определенную колонку задача закрывается. Нужно только вписать id колонки
Items.onMove = function(obj, from, to) {
    if (to.id === 'сюда вписать id колонки') { //если id колонки совпадает
        obj.setCompleted(true) //то выполняем задачу
    }
};


Отправка сообщения в чат при изменении чеклистов.

Items.onUpdate = function(obj) { //при обновлении 
    if (obj.type === 'Task') { //если объект — задача
        const checkListsFact = Chat.getSubtasks(obj); // получаем чеклисты 
        const checkListsDump = obj.getData().checklists; // получаем дамп записи чеклистов
        if (JSON.stringify(checkListsFact) !== JSON.stringify(checkListsDump)) { //если дамп и чеклисты не совпадают
            if (checkListsDump === undefined) { //если дамп пуст
                obj.setData({
                    checklists: checkListsFact
                }); //записываем дамп
            } else if (checkListsFact.length !== checkListsDump.length) { //иначе сравниваем длину чеклста и дампа.
                // если разница есть → что-то делали со списком чеклистов
                obj.setData({
                    checklists: checkListsFact
                }); // записываем дамп
                Chat.postMessage(obj, Users.get(''), 'Изменен список чеклиста') // пишем в чат об изменении списка чеклиста
            } else { //иначе → если менялся не список чеклиста, то менялся пункт чеклиста
                obj.setData({
                    checklists: checkListsFact
                }); // записываем дамп
                Chat.postMessage(obj, Users.get(''), 'Изменен пункт чеклиста') // пишем в чат, что менялся пункт чеклиста
            }
        }
    }
};


Считает количество задач в колонке и печатает его в интерфейсе.

image.png

// Пишет количество задач в колонках при отрисовке страницы и обновлении объектов.
// Вносить в него ничего не надо, можно в p.style поменять что-то на свой вкус
Current.onBoardChange = function(oldBoard, newBoard) { //работаем при смене доски
    const listOfColumns = Current.board.list() //получаем список колонок
    listOfColumns.forEach(function(i) { // перебираем каждую колонку
        const column = Items.get(i.id); // получаем id колонки
        const numberTasks = column.list() // берем общее количество задач в колонке
        const tasksIsNotArchived = numberTasks.filter(x => x.isArchived() === false) // забирем задачи не в ахиве
        const p = UI.panel(); // создаем контейнер
        column.ui.clear() // предварительно очищаем, чтобы удалить предыдущий и не дублировать
        column.ui.add(p);
        p.style = {
            margin: 'auto',
            width: '100px',
            padding: 'auto',
            color: '#572'
        }; // оформляем контейнер
        p.add(UI.text('Задач: ' + tasksIsNotArchived.length)); // пишем текст
    })
}


Items.onUpdate = function(obj) { //вызываем функцию при обновлении, 
    // чтобы работало в реальном времени
    Current.onBoardChange()
};


Запрашивает обязательный комментарий при закрытии задачи и печатает его в описание.

Работает только в браузере с возможностью открыть запрос (prompt).

//Требует комментарий при закрытии задачи
Items.onUpdate = function(obj) { // при обновлении
    if (obj.type === 'Task') { //если это задача
        if (!obj.isCompleted() && obj.getData().completed === undefined) { // если задача новая
            obj.setData({
                completed: false
            }) // записываем, что она открыта
        } else if (obj.isCompleted() && obj.getData().completed === false) { // если уже записано
            let comment = prompt('Введите комментарий') //запрашиваем комментарий
            if (!comment) { //если комментария нет
                obj.setCompleted(false) // оставляем задачу открытой
            } else { //иначе
                Chat.postMessage(obj, '', `Задача закрыта пользователем ${Current.user.name}`) //пишем в чат, что закрыли задачу
                Chat.setDescription(obj, Chat.getDescription(obj) + '<br> <p><b>Комментарий пользователя ' + Current.user.name + ': </b></p>' +
                    '<p>' + comment + '</p>') //пишем в описание комментарий
                obj.setData({
                    completed: true
                }) //пишем 
            }
        } else if (!obj.isCompleted() && obj.getData().completed === true) { //если потом задачу открыли
            obj.setData({
                completed: false
            }) //то возвращаемся к первому else if
        }
    }
}


Запрашивает обязательный комментарий при перемещении задачи в другую колонку и печатает его в описание.

Работает только в браузере с возможностью открыть запрос (prompt).

// Запрашивает обязательный комментарий при перемещении задачи
Items.onMove = function(obj, from, to) {
    if (to.id === 'id колонки') { //если id колонки совпадает
        let comment = prompt('Введите комментарий') //запрашиваем комментарий
        if (!comment) { //если комментария нет
            return false // отказываем
        } else { //иначе
            Chat.postMessage(obj, '', `Задача перемещена пользователем ${Current.user.name}`) //пишем в чат, что переместили задачу
            Chat.setDescription(obj, Chat.getDescription(obj) + '<br> <p><b>Комментарий пользователя ' + Current.user.name + ': </b></p>' +
                '<p>' + comment + '</p>') //пишем в описание комментарий
        }
        return true
    }
}


Назначение пользователя в определенной колонке.

// Добавляет исполнителя в задачу, если ее переместить в колонку и у задачи нет исполнителя.
// Надо вписать id колонки и id пользователя. 
// Для текущего пользователя (кто перемещает задачу) можно вместо id пользователя вписать Current.user.id без кавычек, это сделает его исполнителем
Items.onMove = function(obj, from, to) {
    const task = Items.get(obj.id) //берем id таска
    const user = Users.get('id пользователя'); //берем id пользователя
    if (to.id === '<id колонки>' && !Users.getAssigned(task)) { //если id колонки совпадает
        //и в задаче нет исполнителя
        Users.assignUser(user, task); // назначаем пользователя
    }
};


Скрывает задачу не из "белого списка" аккаунтов, если на нее навесить определенный стикер.

// Скрывает задачу, если на него закреплен стикер (в примере — состояние "Запрет" для стикера "Ограничение")
// userRestrict — массив, в который вносятся emailы, для которых задача скрывается
Items.isHidden = function(object) { // функция скрытия
    const stickerRestrict = Stickers.get('Ограничение'); // забираем нужный текстовый стикер
    const allowToSee = Stickers.getValue(object, stickerRestrict); //забираем состояние этого стикера
    const userRestrict = ['example1@example.com', 'example2@example.com']; //массив почт, для которых задача скроется
    function checkEmail(email) { // функция, которая возвращает совпадение запрещенного списка с текущим пользователем
        return email === Current.user.email
    }
    const restrict = userRestrict.find(checkEmail); // ищет совпадение 

    if (object.type === 'Task' && allowToSee === 'Запрет' && restrict !== undefined) { //если задача со стикером Запрет 
        // и текущий пользователь попадает в список
        return true // скрываем
    }
    return false; // в остальных случаях должно быть открыто
};


Сообщение в чат при удалении исполнителя.

Stickers.onUnpin = function(task, sticker) { //при откреплении стикера
    if (sticker.name === 'User') { //если ститкер — исполнитель
        const userID = Stickers.getValue(task, sticker) //берем id исполнителя
        const userName = Users.get(userID).name //получаем его имя
        Chat.postMessage(task, '', `${userName} удален из исполнителей задачи`) // пишем в чат задачи
    }
    return true;
}


Сообщение в чат при добавлении файла в описание задачи.

// Добавляет сообщене в чат задачи при добавлении вложения в описание.
Items.onUpdate = function(obj) {
    if (obj.type === 'Task') { //фильтруем только задачи
        let descDump = obj.getData().description; //берем наш дамп описания задачи
        if (descDump === undefined) {
            descDump = ''
        } //если дампа нет, то оставляем его пустым
        const currenDesc = Chat.getDescription(obj); // берем описание задачи
        const diff = findDiff(descDump, currenDesc) // сравниваем и находим разницу
        if (diff.includes('file-link-cnt')) { // если в разнице есть свойство вложения
            Chat.postMessage(obj, '', 'Файл добавлен в описание') // пишем в чат
        }
        obj.setData({
            description: currenDesc
        }) // сохраняем текущее описание в дамп на будущее
    }
};

function findDiff(str1, str2) { // это функция, которая сравнивает две строки и выводят между ними разницу
    let diff = "";
    str2.split('').forEach(function(val, i) {
        if (val != str1.charAt(i))
            diff += val;
    });
    return diff;
}


Сообщение в чат о прикреплении/изменении дедлайна.

//Реагирует на создание и изменение дедлайна задачи, отписывая сообщение в чат задачи. 
//Удаление дедлайна игнорирует
Stickers.onPin = function(task, sticker, value) { //при прикреплении стикера
    if (sticker.type === 'Deadline' && value !== undefined) { //если это дедлайн и у него у него есть значение
        Chat.postMessage(task, '', 'Прикреплен/изменен дедлайн'); //пишем сообщение в чат
    }
};