A light weight PHP PDO SQLite3 KanBan Board.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

242 lines
6.5 KiB

import DropZone from "./DropZone.js";
import KanbanAPI from "../api/KanbanAPI.js";
import Dialog from "./Dialog.js";
import Priority from "./Priority.js";
import Complexity from "./Complexity.js";
export default class Item {
constructor(data) {
this.data = { ...data };
this.content = data.content || "";
const bottomDropZone = DropZone.createDropZone();
this.elements = {};
this.elements.root = Item.createRoot();
this.elements.input =
this.elements.root.querySelector(
".kanban__item-input"
);
this.elements.root.dataset.id = String(data.id);
this.elements.root.className =
`kanban__item color-${data.color || "yellow"}`;
this.elements.root.querySelector(
".kanban__number"
).textContent = String(data.id);
this.elements.root.querySelector(
".kanban__assign"
).textContent = data.assign || "";
this.elements.input.textContent = this.content;
this.renderDescription(data.description);
this.renderTags(data.tags);
this.renderDates(data);
this.renderTaskInformation(data);
this.renderComplexity(data.complexity);
this.renderPriority(data.priority);
this.elements.root.appendChild(bottomDropZone);
this.elements.input.addEventListener("blur", () => {
this.saveInlineContent();
});
this.elements.root.addEventListener("dblclick", event => {
if (event.target.closest(".kanban__dropzone")) {
return;
}
Dialog.modify_task(data.id);
});
this.elements.root.addEventListener("dragstart", event => {
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.setData(
"text/plain",
String(data.id)
);
this.elements.root.classList.add(
"kanban__item--dragging"
);
});
this.elements.root.addEventListener("dragend", () => {
this.elements.root.classList.remove(
"kanban__item--dragging"
);
});
this.elements.input.addEventListener("drop", event => {
event.preventDefault();
});
}
async saveInlineContent() {
const newContent =
this.elements.input.textContent.trim();
if (newContent === this.content) {
return;
}
if (newContent === "") {
this.elements.input.textContent = this.content;
return;
}
try {
await KanbanAPI.updateItem(this.data.id, {
content: newContent
});
this.content = newContent;
this.data.content = newContent;
} catch (error) {
console.error(error);
this.elements.input.textContent = this.content;
}
}
renderDescription(description) {
if (!description) {
return;
}
const indicator = document.createElement("span");
const icon = document.createElement("i");
icon.textContent = "✍";
icon.title = description;
indicator.appendChild(icon);
this.elements.root.appendChild(indicator);
}
renderTags(tags) {
if (!tags) {
return;
}
const tagElement = document.createElement("span");
tagElement.className = "kanban__tags";
tagElement.textContent = tags;
this.elements.root.appendChild(tagElement);
}
renderDates(data) {
if (Item.isValidDate(data.start)) {
const startElement = document.createElement("span");
startElement.className = "date";
startElement.textContent =
`| Start: ${Item.formatDate(data.start)}`;
this.elements.root.appendChild(startElement);
}
if (Item.isValidDate(data.due)) {
const dueElement = document.createElement("span");
dueElement.className = "datetime";
dueElement.textContent =
`| Due: ${new Date(data.due).toLocaleString()}`;
this.elements.root.appendChild(dueElement);
}
}
renderTaskInformation(data) {
const information = [];
if (data.estimate !== null && data.estimate !== undefined) {
information.push(`| Estimate: ${data.estimate}h`);
}
if (
data.timeSpent !== null &&
data.timeSpent !== undefined
) {
information.push(`| Spent: ${data.timeSpent}h`);
}
if (information.length === 0) {
return;
}
const informationElement =
document.createElement("span");
informationElement.className =
"kanban__task-information";
informationElement.textContent =
information.join(" | ");
this.elements.root.appendChild(informationElement);
}
renderPriority(priority) {
const priorityElement =
document.createElement("span");
priorityElement.className = "kanban__priority";
priorityElement.textContent =
Priority.get_priority(Number(priority));
this.elements.root.appendChild(priorityElement);
}
renderComplexity(level) {
const complexityElement =
document.createElement("div");
complexityElement.className = "kanban__complexity";
complexityElement.textContent =
Complexity.get_complexity(Number(level));
this.elements.root.appendChild(complexityElement);
}
static isValidDate(value) {
if (!value) {
return false;
}
const date = new Date(value);
return !Number.isNaN(date.getTime());
}
static formatDate(value) {
const [year, month, day] = value.split("-");
if (!year || !month || !day) {
return value;
}
return new Date(
Number(year),
Number(month) - 1,
Number(day)
).toLocaleDateString();
}
static createRoot() {
const template = document.createElement("template");
template.innerHTML = `
<div class="kanban__item" draggable="true">
<div class="kanban__number"></div>
<div class="kanban__assign"></div>
<div class="kanban__item-input"
contenteditable="true"></div>
</div>
`;
return template.content.firstElementChild;
}
}