mirror of
https://git.imnavajas.es/jjimenez/safekat.git
synced 2025-07-25 22:52:08 +00:00
terminando servicios manipulados y preimpresion
This commit is contained in:
@ -1,471 +0,0 @@
|
||||
/**
|
||||
* App Kanban
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
(async function () {
|
||||
let boards;
|
||||
const kanbanSidebar = document.querySelector('.kanban-update-item-sidebar'),
|
||||
kanbanWrapper = document.querySelector('.kanban-wrapper'),
|
||||
commentEditor = document.querySelector('.comment-editor'),
|
||||
kanbanAddNewBoard = document.querySelector('.kanban-add-new-board'),
|
||||
kanbanAddNewInput = [].slice.call(document.querySelectorAll('.kanban-add-board-input')),
|
||||
kanbanAddBoardBtn = document.querySelector('.kanban-add-board-btn'),
|
||||
datePicker = document.querySelector('#due-date'),
|
||||
select2 = $('.select2'), // ! Using jquery vars due to select2 jQuery dependency
|
||||
assetsPath = document.querySelector('html').getAttribute('data-assets-path');
|
||||
|
||||
// Init kanban Offcanvas
|
||||
const kanbanOffcanvas = new bootstrap.Offcanvas(kanbanSidebar);
|
||||
|
||||
// Get kanban data
|
||||
const kanbanResponse = await fetch(assetsPath + 'json/kanban.json');
|
||||
if (!kanbanResponse.ok) {
|
||||
console.error('error', kanbanResponse);
|
||||
}
|
||||
boards = await kanbanResponse.json();
|
||||
|
||||
// datepicker init
|
||||
if (datePicker) {
|
||||
datePicker.flatpickr({
|
||||
monthSelectorType: 'static',
|
||||
altInput: true,
|
||||
altFormat: 'j F, Y',
|
||||
dateFormat: 'Y-m-d'
|
||||
});
|
||||
}
|
||||
|
||||
//! TODO: Update Event label and guest code to JS once select removes jQuery dependency
|
||||
// select2
|
||||
if (select2.length) {
|
||||
function renderLabels(option) {
|
||||
if (!option.id) {
|
||||
return option.text;
|
||||
}
|
||||
var $badge = "<div class='badge " + $(option.element).data('color') + " rounded-pill'> " + option.text + '</div>';
|
||||
return $badge;
|
||||
}
|
||||
|
||||
select2.each(function () {
|
||||
var $this = $(this);
|
||||
$this.wrap("<div class='position-relative'></div>").select2({
|
||||
placeholder: 'Select Label',
|
||||
dropdownParent: $this.parent(),
|
||||
templateResult: renderLabels,
|
||||
templateSelection: renderLabels,
|
||||
escapeMarkup: function (es) {
|
||||
return es;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Comment editor
|
||||
if (commentEditor) {
|
||||
new Quill(commentEditor, {
|
||||
modules: {
|
||||
toolbar: '.comment-toolbar'
|
||||
},
|
||||
placeholder: 'Write a Comment... ',
|
||||
theme: 'snow'
|
||||
});
|
||||
}
|
||||
|
||||
// Render board dropdown
|
||||
function renderBoardDropdown() {
|
||||
return (
|
||||
"<div class='dropdown'>" +
|
||||
"<i class='dropdown-toggle ti ti-dots-vertical cursor-pointer' id='board-dropdown' data-bs-toggle='dropdown' aria-haspopup='true' aria-expanded='false'></i>" +
|
||||
"<div class='dropdown-menu dropdown-menu-end' aria-labelledby='board-dropdown'>" +
|
||||
"<a class='dropdown-item delete-board' href='javascript:void(0)'> <i class='ti ti-trash ti-xs' me-1></i> <span class='align-middle'>Delete</span></a>" +
|
||||
"<a class='dropdown-item' href='javascript:void(0)'><i class='ti ti-edit ti-xs' me-1></i> <span class='align-middle'>Rename</span></a>" +
|
||||
"<a class='dropdown-item' href='javascript:void(0)'><i class='ti ti-archive ti-xs' me-1></i> <span class='align-middle'>Archive</span></a>" +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
// Render item dropdown
|
||||
function renderDropdown() {
|
||||
return (
|
||||
"<div class='dropdown kanban-tasks-item-dropdown'>" +
|
||||
"<i class='dropdown-toggle ti ti-dots-vertical' id='kanban-tasks-item-dropdown' data-bs-toggle='dropdown' aria-haspopup='true' aria-expanded='false'></i>" +
|
||||
"<div class='dropdown-menu dropdown-menu-end' aria-labelledby='kanban-tasks-item-dropdown'>" +
|
||||
"<a class='dropdown-item' href='javascript:void(0)'>Copy task link</a>" +
|
||||
"<a class='dropdown-item' href='javascript:void(0)'>Duplicate task</a>" +
|
||||
"<a class='dropdown-item delete-task' href='javascript:void(0)'>Delete</a>" +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
// Render header
|
||||
function renderHeader(color, text) {
|
||||
return (
|
||||
"<div class='d-flex justify-content-between flex-wrap align-items-center mb-2 pb-1'>" +
|
||||
"<div class='item-badges'> " +
|
||||
"<div class='badge rounded-pill bg-label-" +
|
||||
color +
|
||||
"'> " +
|
||||
text +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
renderDropdown() +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
// Render avatar
|
||||
function renderAvatar(images, pullUp, size, margin, members) {
|
||||
var $transition = pullUp ? ' pull-up' : '',
|
||||
$size = size ? 'avatar-' + size + '' : '',
|
||||
member = members == undefined ? ' ' : members.split(',');
|
||||
|
||||
return images == undefined
|
||||
? ' '
|
||||
: images
|
||||
.split(',')
|
||||
.map(function (img, index, arr) {
|
||||
var $margin = margin && index !== arr.length - 1 ? ' me-' + margin + '' : '';
|
||||
|
||||
return (
|
||||
"<div class='avatar " +
|
||||
$size +
|
||||
$margin +
|
||||
"'" +
|
||||
"data-bs-toggle='tooltip' data-bs-placement='top'" +
|
||||
"title='" +
|
||||
member[index] +
|
||||
"'" +
|
||||
'>' +
|
||||
"<img src='" +
|
||||
assetsPath +
|
||||
'img/avatars/' +
|
||||
img +
|
||||
"' alt='Avatar' class='rounded-circle " +
|
||||
$transition +
|
||||
"'>" +
|
||||
'</div>'
|
||||
);
|
||||
})
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
// Render footer
|
||||
function renderFooter(attachments, comments, assigned, members) {
|
||||
return (
|
||||
"<div class='d-flex justify-content-between align-items-center flex-wrap mt-2 pt-1'>" +
|
||||
"<div class='d-flex'> <span class='d-flex align-items-center me-2'><i class='ti ti-paperclip ti-xs me-1'></i>" +
|
||||
"<span class='attachments'>" +
|
||||
attachments +
|
||||
'</span>' +
|
||||
"</span> <span class='d-flex align-items-center ms-1'><i class='ti ti-message-dots ti-xs me-1'></i>" +
|
||||
'<span> ' +
|
||||
comments +
|
||||
' </span>' +
|
||||
'</span></div>' +
|
||||
"<div class='avatar-group d-flex align-items-center assigned-avatar'>" +
|
||||
renderAvatar(assigned, true, 'xs', null, members) +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
// Init kanban
|
||||
const kanban = new jKanban({
|
||||
element: '.kanban-wrapper',
|
||||
gutter: '15px',
|
||||
widthBoard: '250px',
|
||||
dragItems: true,
|
||||
boards: boards,
|
||||
dragBoards: true,
|
||||
addItemButton: true,
|
||||
buttonContent: '+ Add Item',
|
||||
itemAddOptions: {
|
||||
enabled: true, // add a button to board for easy item creation
|
||||
content: '+ Add New Item', // text or html content of the board button
|
||||
class: 'kanban-title-button btn', // default class of the button
|
||||
footer: false // position the button on footer
|
||||
},
|
||||
click: function (el) {
|
||||
let element = el;
|
||||
let title = element.getAttribute('data-eid')
|
||||
? element.querySelector('.kanban-text').textContent
|
||||
: element.textContent,
|
||||
date = element.getAttribute('data-due-date'),
|
||||
dateObj = new Date(),
|
||||
year = dateObj.getFullYear(),
|
||||
dateToUse = date
|
||||
? date + ', ' + year
|
||||
: dateObj.getDate() + ' ' + dateObj.toLocaleString('en', { month: 'long' }) + ', ' + year,
|
||||
label = element.getAttribute('data-badge-text'),
|
||||
avatars = element.getAttribute('data-assigned');
|
||||
|
||||
// Show kanban offcanvas
|
||||
kanbanOffcanvas.show();
|
||||
|
||||
// To get data on sidebar
|
||||
kanbanSidebar.querySelector('#title').value = title;
|
||||
kanbanSidebar.querySelector('#due-date').nextSibling.value = dateToUse;
|
||||
|
||||
// ! Using jQuery method to get sidebar due to select2 dependency
|
||||
$('.kanban-update-item-sidebar').find(select2).val(label).trigger('change');
|
||||
|
||||
// Remove & Update assigned
|
||||
kanbanSidebar.querySelector('.assigned').innerHTML = '';
|
||||
kanbanSidebar
|
||||
.querySelector('.assigned')
|
||||
.insertAdjacentHTML(
|
||||
'afterbegin',
|
||||
renderAvatar(avatars, false, 'xs', '1', el.getAttribute('data-members')) +
|
||||
"<div class='avatar avatar-xs ms-1'>" +
|
||||
"<span class='avatar-initial rounded-circle bg-label-secondary'><i class='ti ti-plus ti-xs text-heading'></i></span>" +
|
||||
'</div>'
|
||||
);
|
||||
},
|
||||
|
||||
buttonClick: function (el, boardId) {
|
||||
const addNew = document.createElement('form');
|
||||
addNew.setAttribute('class', 'new-item-form');
|
||||
addNew.innerHTML =
|
||||
'<div class="mb-3">' +
|
||||
'<textarea class="form-control add-new-item" rows="2" placeholder="Add Content" autofocus required></textarea>' +
|
||||
'</div>' +
|
||||
'<div class="mb-3">' +
|
||||
'<button type="submit" class="btn btn-primary btn-sm me-2">Add</button>' +
|
||||
'<button type="button" class="btn btn-label-secondary btn-sm cancel-add-item">Cancel</button>' +
|
||||
'</div>';
|
||||
kanban.addForm(boardId, addNew);
|
||||
|
||||
addNew.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
const currentBoard = [].slice.call(
|
||||
document.querySelectorAll('.kanban-board[data-id=' + boardId + '] .kanban-item')
|
||||
);
|
||||
kanban.addElement(boardId, {
|
||||
title: "<span class='kanban-text'>" + e.target[0].value + '</span>',
|
||||
id: boardId + '-' + currentBoard.length + 1
|
||||
});
|
||||
|
||||
// add dropdown in new boards
|
||||
const kanbanText = [].slice.call(
|
||||
document.querySelectorAll('.kanban-board[data-id=' + boardId + '] .kanban-text')
|
||||
);
|
||||
kanbanText.forEach(function (e) {
|
||||
e.insertAdjacentHTML('beforebegin', renderDropdown());
|
||||
});
|
||||
|
||||
// prevent sidebar to open onclick dropdown buttons of new tasks
|
||||
const newTaskDropdown = [].slice.call(document.querySelectorAll('.kanban-item .kanban-tasks-item-dropdown'));
|
||||
if (newTaskDropdown) {
|
||||
newTaskDropdown.forEach(function (e) {
|
||||
e.addEventListener('click', function (el) {
|
||||
el.stopPropagation();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// delete tasks for new boards
|
||||
const deleteTask = [].slice.call(
|
||||
document.querySelectorAll('.kanban-board[data-id=' + boardId + '] .delete-task')
|
||||
);
|
||||
deleteTask.forEach(function (e) {
|
||||
e.addEventListener('click', function () {
|
||||
const id = this.closest('.kanban-item').getAttribute('data-eid');
|
||||
kanban.removeElement(id);
|
||||
});
|
||||
});
|
||||
addNew.remove();
|
||||
});
|
||||
|
||||
// Remove form on clicking cancel button
|
||||
addNew.querySelector('.cancel-add-item').addEventListener('click', function (e) {
|
||||
addNew.remove();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Kanban Wrapper scrollbar
|
||||
if (kanbanWrapper) {
|
||||
new PerfectScrollbar(kanbanWrapper);
|
||||
}
|
||||
|
||||
const kanbanContainer = document.querySelector('.kanban-container'),
|
||||
kanbanTitleBoard = [].slice.call(document.querySelectorAll('.kanban-title-board')),
|
||||
kanbanItem = [].slice.call(document.querySelectorAll('.kanban-item'));
|
||||
|
||||
// Render custom items
|
||||
if (kanbanItem) {
|
||||
kanbanItem.forEach(function (el) {
|
||||
const element = "<span class='kanban-text'>" + el.textContent + '</span>';
|
||||
let img = '';
|
||||
if (el.getAttribute('data-image') !== null) {
|
||||
img =
|
||||
"<img class='img-fluid rounded mb-2' src='" +
|
||||
assetsPath +
|
||||
'img/elements/' +
|
||||
el.getAttribute('data-image') +
|
||||
"'>";
|
||||
}
|
||||
el.textContent = '';
|
||||
if (el.getAttribute('data-badge') !== undefined && el.getAttribute('data-badge-text') !== undefined) {
|
||||
el.insertAdjacentHTML(
|
||||
'afterbegin',
|
||||
renderHeader(el.getAttribute('data-badge'), el.getAttribute('data-badge-text')) + img + element
|
||||
);
|
||||
}
|
||||
if (
|
||||
el.getAttribute('data-comments') !== undefined ||
|
||||
el.getAttribute('data-due-date') !== undefined ||
|
||||
el.getAttribute('data-assigned') !== undefined
|
||||
) {
|
||||
el.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
renderFooter(
|
||||
el.getAttribute('data-attachments'),
|
||||
el.getAttribute('data-comments'),
|
||||
el.getAttribute('data-assigned'),
|
||||
el.getAttribute('data-members')
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// To initialize tooltips for rendered items
|
||||
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl);
|
||||
});
|
||||
|
||||
// prevent sidebar to open onclick dropdown buttons of tasks
|
||||
const tasksItemDropdown = [].slice.call(document.querySelectorAll('.kanban-tasks-item-dropdown'));
|
||||
if (tasksItemDropdown) {
|
||||
tasksItemDropdown.forEach(function (e) {
|
||||
e.addEventListener('click', function (el) {
|
||||
el.stopPropagation();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Toggle add new input and actions add-new-btn
|
||||
if (kanbanAddBoardBtn) {
|
||||
kanbanAddBoardBtn.addEventListener('click', () => {
|
||||
kanbanAddNewInput.forEach(el => {
|
||||
el.value = '';
|
||||
el.classList.toggle('d-none');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Render add new inline with boards
|
||||
if (kanbanContainer) {
|
||||
kanbanContainer.appendChild(kanbanAddNewBoard);
|
||||
}
|
||||
|
||||
// Makes kanban title editable for rendered boards
|
||||
if (kanbanTitleBoard) {
|
||||
kanbanTitleBoard.forEach(function (elem) {
|
||||
elem.addEventListener('mouseenter', function () {
|
||||
this.contentEditable = 'true';
|
||||
});
|
||||
|
||||
// Appends delete icon with title
|
||||
elem.insertAdjacentHTML('afterend', renderBoardDropdown());
|
||||
});
|
||||
}
|
||||
|
||||
// To delete Board for rendered boards
|
||||
const deleteBoards = [].slice.call(document.querySelectorAll('.delete-board'));
|
||||
if (deleteBoards) {
|
||||
deleteBoards.forEach(function (elem) {
|
||||
elem.addEventListener('click', function () {
|
||||
const id = this.closest('.kanban-board').getAttribute('data-id');
|
||||
kanban.removeBoard(id);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Delete task for rendered boards
|
||||
const deleteTask = [].slice.call(document.querySelectorAll('.delete-task'));
|
||||
if (deleteTask) {
|
||||
deleteTask.forEach(function (e) {
|
||||
e.addEventListener('click', function () {
|
||||
const id = this.closest('.kanban-item').getAttribute('data-eid');
|
||||
kanban.removeElement(id);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Cancel btn add new input
|
||||
const cancelAddNew = document.querySelector('.kanban-add-board-cancel-btn');
|
||||
if (cancelAddNew) {
|
||||
cancelAddNew.addEventListener('click', function () {
|
||||
kanbanAddNewInput.forEach(el => {
|
||||
el.classList.toggle('d-none');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Add new board
|
||||
if (kanbanAddNewBoard) {
|
||||
kanbanAddNewBoard.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
const thisEle = this,
|
||||
value = thisEle.querySelector('.form-control').value,
|
||||
id = value.replace(/\s+/g, '-').toLowerCase();
|
||||
kanban.addBoards([
|
||||
{
|
||||
id: id,
|
||||
title: value
|
||||
}
|
||||
]);
|
||||
|
||||
// Adds delete board option to new board, delete new boards & updates data-order
|
||||
const kanbanBoardLastChild = document.querySelectorAll('.kanban-board:last-child')[0];
|
||||
if (kanbanBoardLastChild) {
|
||||
const header = kanbanBoardLastChild.querySelector('.kanban-title-board');
|
||||
header.insertAdjacentHTML('afterend', renderBoardDropdown());
|
||||
|
||||
// To make newly added boards title editable
|
||||
kanbanBoardLastChild.querySelector('.kanban-title-board').addEventListener('mouseenter', function () {
|
||||
this.contentEditable = 'true';
|
||||
});
|
||||
}
|
||||
|
||||
// Add delete event to delete newly added boards
|
||||
const deleteNewBoards = kanbanBoardLastChild.querySelector('.delete-board');
|
||||
if (deleteNewBoards) {
|
||||
deleteNewBoards.addEventListener('click', function () {
|
||||
const id = this.closest('.kanban-board').getAttribute('data-id');
|
||||
kanban.removeBoard(id);
|
||||
});
|
||||
}
|
||||
|
||||
// Remove current append new add new form
|
||||
if (kanbanAddNewInput) {
|
||||
kanbanAddNewInput.forEach(el => {
|
||||
el.classList.add('d-none');
|
||||
});
|
||||
}
|
||||
|
||||
// To place inline add new btn after clicking add btn
|
||||
if (kanbanContainer) {
|
||||
kanbanContainer.appendChild(kanbanAddNewBoard);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Clear comment editor on close
|
||||
kanbanSidebar.addEventListener('hidden.bs.offcanvas', function () {
|
||||
kanbanSidebar.querySelector('.ql-editor').firstElementChild.innerHTML = '';
|
||||
});
|
||||
|
||||
// Re-init tooltip when offcanvas opens(Bootstrap bug)
|
||||
if (kanbanSidebar) {
|
||||
kanbanSidebar.addEventListener('shown.bs.offcanvas', function () {
|
||||
const tooltipTriggerList = [].slice.call(kanbanSidebar.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl);
|
||||
});
|
||||
});
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user