-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
146 lines (124 loc) · 29.7 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./src/api.js":
/*!********************!*\
!*** ./src/api.js ***!
\********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ API: () => (/* binding */ API),\n/* harmony export */ listNameToID: () => (/* binding */ listNameToID)\n/* harmony export */ });\n/* harmony import */ var _cardhandler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./cardhandler */ \"./src/cardhandler.js\");\n/* harmony import */ var _cardlist__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./cardlist */ \"./src/cardlist.js\");\n/* harmony import */ var _layout__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./layout */ \"./src/layout.js\");\n/* harmony import */ var _task__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./task */ \"./src/task.js\");\n\n\n\n\n\n\n\n\nclass API {\n get Tasks() {\n return this.tasks;\n }\n\n get TaskLists() {\n return Array.from(this.cardHandler.Lists.values());\n }\n\n get CurrentTaskIndex() {\n return this.currentTaskIndex;\n }\n\n constructor() {\n this.currentTaskIndex = 0;\n this.tasks = new Map();\n this.cardHandler = new _cardhandler__WEBPACK_IMPORTED_MODULE_0__.CardHandler();\n }\n\n serializeToLocalStorage() {\n const kanbanStr = JSON.stringify({\n index: this.currentTaskIndex,\n tasks: Array.from(this.tasks.entries()),\n taskLists: Array.from(this.cardHandler.Lists.keys()),\n });\n localStorage.setItem(\"my-kanban-board\", kanbanStr);\n }\n\n tryLoadFromLocalStorage() {\n const boardDataStr = localStorage.getItem(\"my-kanban-board\");\n if (!boardDataStr) {\n return;\n }\n\n const boardData = JSON.parse(boardDataStr);\n this.currentTaskIndex = boardData.index;\n\n boardData.tasks.forEach((item) =>\n this.tasks.set(item[0], _task__WEBPACK_IMPORTED_MODULE_3__.TaskItem.fromLoadedData(item[1]))\n );\n boardData.taskLists.forEach((list) =>\n this.cardHandler.push(new _cardlist__WEBPACK_IMPORTED_MODULE_1__.CardList(list, listNameToID(list)))\n );\n\n this.cardHandler.setHasDefault();\n\n (0,_layout__WEBPACK_IMPORTED_MODULE_2__.generateElementsFromLoadedData)(this);\n }\n\n removeTaskItem(item) {\n this.tasks.delete(item.ID);\n }\n\n tryAddNewList() {\n return this.cardHandler.tryAddNewList();\n }\n\n /**\n * @param {string} identifier\n */\n taskListContains(identifier) {\n return this.cardHandler.Lists.has(identifier);\n }\n\n /**\n * @param {string} oldID\n * @param {string} newID\n */\n renameTaskList(oldID, newID) {\n this.cardHandler.renameTaskList(oldID, newID);\n this.cardHandler.setHasDefault();\n }\n\n /**\n * @param {string} identifier\n */\n deleteTaskList(identifier) {\n this.cardHandler.removeWithID(identifier);\n }\n\n /**\n * @param {Date} createdAt\n * @param {string} listID\n * @param {string} title\n * @param {string} tag\n * @param {Date} dueDate\n * @param {string} color\n * @param {string} description\n */\n addNewTask(\n createdAt,\n listID,\n title,\n tag,\n dueDate,\n color,\n description\n ) {\n this.tasks.set(\n this.currentTaskIndex,\n new _task__WEBPACK_IMPORTED_MODULE_3__.TaskItem(\n this.currentTaskIndex,\n createdAt,\n listID,\n title,\n tag,\n dueDate,\n color,\n description\n )\n );\n this.advanceTask();\n }\n\n /**\n * @param {string} identifier\n * @returns {TaskItem}\n */\n getTaskFromID(identifier) {\n const indexStr = identifier.lastIndexOf(\"-\") + 1;\n const taskIndex = +identifier.slice(indexStr);\n const task = this.tasks.get(taskIndex);\n if (!task) {\n console.log(identifier);\n throw new Error(`Fatal task fetch error. Tried to fetch item with index: ${taskIndex}`);\n }\n return task;\n }\n\n advanceTask() {\n this.currentTaskIndex += 1;\n }\n}\n\n/**\n * @param {string} value \n * @returns \n */\nfunction listNameToID(value) {\n let newName = new String(value);\n newName = newName.replace(\" \", \"-\").toLocaleLowerCase().concat(\"-list\");\n return newName.toString();\n}\n\n\n//# sourceURL=webpack://kanban-board/./src/api.js?");
/***/ }),
/***/ "./src/cardhandler.js":
/*!****************************!*\
!*** ./src/cardhandler.js ***!
\****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CardHandler: () => (/* binding */ CardHandler)\n/* harmony export */ });\n/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./api */ \"./src/api.js\");\n/* harmony import */ var _cardlist__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./cardlist */ \"./src/cardlist.js\");\n\n\n\n\n\nclass CardHandler {\n get HasDefault() {\n return this.hasDefault;\n }\n\n get Lists() {\n return this.lists;\n }\n\n constructor() {\n this.hasDefault = false;\n this.lists = new Map();\n }\n\n setHasDefault() {\n this.hasDefault = this.lists.has(\"New List\");\n }\n\n /**\n * \n * @param {CardList} list \n */\n push(list) {\n this.lists.set(list.Identifier, list);\n }\n\n /**\n * @returns {boolean}\n */\n tryAddNewList() {\n if (this.hasDefault) {\n return false;\n }\n\n this.lists.set(\"New List\", new _cardlist__WEBPACK_IMPORTED_MODULE_1__.CardList(\"New List\", \"new-list\"));\n this.hasDefault = true;\n\n return true;\n }\n\n /**\n * \n * @param {string} identifier \n * @returns \n */\n removeWithID(identifier) {\n for (const [id, list] of this.lists.entries()) {\n if (list.ElementID === identifier) {\n this.lists.delete(id);\n this.setHasDefault();\n return;\n }\n }\n }\n\n /**\n * @param {string} oldID \n * @param {string} newID\n */\n renameTaskList(oldID, newID) {\n const oldCard = this.lists.get(oldID);\n if (oldCard) {\n this.lists.delete(oldID);\n this.lists.set(newID, oldCard);\n return;\n }\n\n this.lists.set(newID, new _cardlist__WEBPACK_IMPORTED_MODULE_1__.CardList(newID, (0,_api__WEBPACK_IMPORTED_MODULE_0__.listNameToID)(newID)));\n }\n}\n\n\n//# sourceURL=webpack://kanban-board/./src/cardhandler.js?");
/***/ }),
/***/ "./src/cardlist.js":
/*!*************************!*\
!*** ./src/cardlist.js ***!
\*************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CardList: () => (/* binding */ CardList)\n/* harmony export */ });\n\n\nclass CardList {\n get Identifier() {\n return this.identifier;\n }\n\n get ElementID() {\n return this.elementID;\n }\n\n constructor(identifier, elementID) {\n this.identifier = identifier;\n this.elementID = elementID;\n }\n}\n\n\n//# sourceURL=webpack://kanban-board/./src/cardlist.js?");
/***/ }),
/***/ "./src/dragging.js":
/*!*************************!*\
!*** ./src/dragging.js ***!
\*************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ setupDraggables: () => (/* binding */ setupDraggables),\n/* harmony export */ setupListDragZone: () => (/* binding */ setupListDragZone)\n/* harmony export */ });\n/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./api */ \"./src/api.js\");\n/* harmony import */ var _layout__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./layout */ \"./src/layout.js\");\n\n\n\n\n\n/**\n * @param {API} api\n */\nfunction setupDraggables(api) {\n const dragables = document.querySelectorAll(\".task\");\n const droppables = document.querySelectorAll(\".list-content\");\n\n dragables.forEach((task) => (0,_layout__WEBPACK_IMPORTED_MODULE_1__.addDragListeners)(task));\n droppables.forEach((zone) => setupListDragZone(api, zone));\n}\n\n/**\n * @param {API} api\n * @param {HTMLElement} zone\n */\nfunction setupListDragZone(api, zone) {\n zone.addEventListener(\"dragover\", (e) => {\n e.preventDefault();\n\n const bottomTask = insertAboveTask(zone, e.clientY);\n const currentTask = document.querySelector(\".is-dragging\");\n\n const taskItem = api.getTaskFromID(currentTask.id);\n taskItem.setListID(zone.getAttribute(\"value\"));\n\n if (!bottomTask) {\n zone.appendChild(currentTask);\n } else {\n zone.insertBefore(currentTask, bottomTask);\n }\n\n // Serialize to disk, after changes\n api.serializeToLocalStorage();\n });\n}\n\nfunction insertAboveTask(zone, mouseY) {\n // Grab all tasks that aren't currently being dragged\n const els = zone.querySelectorAll(\".task:not(.is-dragging)\");\n\n let closestTask = null;\n let closestOffset = Number.NEGATIVE_INFINITY;\n\n els.forEach((task) => {\n const { top } = task.getBoundingClientRect();\n const offset = mouseY - top;\n\n if (offset < 0 && offset > closestOffset) {\n closestOffset = offset;\n closestTask = task;\n }\n });\n\n return closestTask;\n}\n\n\n//# sourceURL=webpack://kanban-board/./src/dragging.js?");
/***/ }),
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./api */ \"./src/api.js\");\n/* harmony import */ var _dragging__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dragging */ \"./src/dragging.js\");\n/* harmony import */ var _layout__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./layout */ \"./src/layout.js\");\n\n\n\n\n\n\nwindow.addEventListener(\"load\", function() {\n const api = new _api__WEBPACK_IMPORTED_MODULE_0__.API();\n api.tryLoadFromLocalStorage();\n\n (0,_layout__WEBPACK_IMPORTED_MODULE_2__.setupAddTask)(api);\n (0,_layout__WEBPACK_IMPORTED_MODULE_2__.setupListAddButton)(api);\n (0,_dragging__WEBPACK_IMPORTED_MODULE_1__.setupDraggables)(api);\n\n (0,_layout__WEBPACK_IMPORTED_MODULE_2__.setupErrorModalLayout)();\n (0,_layout__WEBPACK_IMPORTED_MODULE_2__.setupModalLayout)();\n});\n\n\n//# sourceURL=webpack://kanban-board/./src/index.js?");
/***/ }),
/***/ "./src/layout.js":
/*!***********************!*\
!*** ./src/layout.js ***!
\***********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ addDragListeners: () => (/* binding */ addDragListeners),\n/* harmony export */ generateElementsFromLoadedData: () => (/* binding */ generateElementsFromLoadedData),\n/* harmony export */ setupAddTask: () => (/* binding */ setupAddTask),\n/* harmony export */ setupErrorModalLayout: () => (/* binding */ setupErrorModalLayout),\n/* harmony export */ setupListAddButton: () => (/* binding */ setupListAddButton),\n/* harmony export */ setupModalLayout: () => (/* binding */ setupModalLayout),\n/* harmony export */ setupNewTaskModalFields: () => (/* binding */ setupNewTaskModalFields),\n/* harmony export */ showErrorModal: () => (/* binding */ showErrorModal)\n/* harmony export */ });\n/* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./api */ \"./src/api.js\");\n/* harmony import */ var _dragging__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dragging */ \"./src/dragging.js\");\n/* harmony import */ var _task__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./task */ \"./src/task.js\");\n\n\n\n\n\n\n/**\n * \n * @param {API} api \n */\nfunction setupListAddButton(api) {\n const btn = document.querySelector(\"#list-add-btn\");\n btn.onclick = () => {\n const listDiv = document.querySelector(\"#task-lists\");\n const listEl = createDefaultList(api);\n if (!listEl) {\n showErrorModal(\"Cannot create default list, as one already exists.\");\n return;\n }\n\n listDiv.insertBefore(listEl, listDiv.children[listDiv.children.length - 1]);\n\n // Save results to disk\n api.serializeToLocalStorage();\n };\n}\n\nfunction setupErrorModalLayout() {\n const modal = document.querySelector(\"#error-modal\");\n const close = document.querySelector(\"#error-modal-close\");\n\n close.onclick = function (e) {\n e.preventDefault();\n modal.style.display = \"none\";\n };\n}\n\nfunction setupModalLayout() {\n // Get the modal\n const modal = document.querySelector(\"#modal\");\n const modalHeader = document.querySelector(\"#modal-header\");\n\n // Get the <span> element that closes the modal\n const span = document.querySelector(\"#close\");\n const colorSelected = document.querySelector(\"#color-selected\");\n const firstStyle = colorSelected.options[0].style;\n colorSelected.value = firstStyle.backgroundColor;\n colorSelected.style.background = firstStyle.backgroundColor;\n\n span.onclick = function () {\n modal.style.display = \"none\";\n };\n\n colorSelected.onchange = function () {\n const color = colorSelected.options[colorSelected.selectedIndex].style.backgroundColor;\n\n colorSelected.style.backgroundColor = color;\n modalHeader.style.backgroundColor = color;\n };\n}\n\n/**\n * \n * @param {HTMLElement} el \n */\nfunction addDragListeners(el) {\n el.addEventListener(\"dragstart\", () => {\n el.classList.add(\"is-dragging\");\n });\n el.addEventListener(\"dragend\", () => {\n el.classList.remove(\"is-dragging\");\n });\n}\n\n/**\n * \n * @param {string} message \n */\nfunction showErrorModal(message) {\n const errorModal = document.querySelector(\"#error-modal\");\n const modalText = document.querySelector(\"#error-modal-text\") ;\n\n modalText.innerText = message;\n errorModal.style.display = \"block\";\n}\n\n/**\n * \n * @param {API} api \n */\nfunction setupAddTask(api) {\n const form = document.querySelector(\"#add-task-btn\");\n\n form.onclick = (e) => {\n e.preventDefault();\n\n const lists = document.querySelectorAll(\".swim-list\");\n if (lists.length === 0) {\n showErrorModal(\"No lists available to add a task.\");\n return;\n }\n\n const modal = document.querySelector(\"#modal\");\n modal.style.display = \"block\";\n setupNewTaskModalFields(api);\n };\n}\n\n/**\n * \n * @param {API} api \n */\nfunction setupNewTaskModalFields(api) {\n const modal = document.querySelector(\"#modal\");\n const modalHeader = document.querySelector(\"#modal-header\");\n const createdOn = document.querySelector(\"#created-on\");\n const taskTitle = document.querySelector(\"#task-title\");\n const taskDesc = document.querySelector(\"#task-desc\");\n const saveBtn = document.querySelector(\"#modal-save-btn\");\n const deleteBtn = document.querySelector(\"#modal-delete-btn\");\n\n const tagKind = document.querySelector(\"#kind-option\");\n tagKind.value = \"prg\";\n\n const dueDate = document.querySelector(\"#due-date\");\n dueDate.valueAsDate = null;\n\n const colorSelected = document.querySelector(\"#color-selected\");\n const firstStyle = colorSelected.options[0].style;\n colorSelected.value = firstStyle.backgroundColor;\n colorSelected.style.background = firstStyle.backgroundColor;\n\n modalHeader.style.backgroundColor = colorSelected.value;\n\n const taskTitleText = `Task Title #${api.CurrentTaskIndex + 1}`;\n taskTitle.value = taskTitleText;\n taskDesc.value = \"\";\n\n const date = new Date();\n modal.style.display = \"block\";\n createdOn.innerText = `Created on ${date.toDateString()}`;\n\n saveBtn.onclick = () => {\n if (taskTitle.value === taskTitleText) {\n showErrorModal(\"Invalid title name.\");\n return;\n }\n\n // Add to todo list\n const firstList = document.querySelectorAll(\".swim-list\")[0];\n const listContent = firstList.querySelector(\".list-content\");\n\n const taskEl = createTaskItemElement(api, taskTitle.value, api.CurrentTaskIndex);\n listContent.appendChild(taskEl);\n\n const tagKind = document.querySelector(\"#kind-option\");\n const dueDate = document.querySelector(\"#due-date\");\n const colorSelected = document.querySelector(\"#color-selected\");\n\n api.addNewTask(\n date,\n firstList.id,\n taskTitle.value,\n (0,_task__WEBPACK_IMPORTED_MODULE_2__.tagStrToKind)(tagKind.value),\n dueDate.valueAsDate,\n colorSelected.style.background,\n taskDesc.value\n );\n\n // Save results to disk\n api.serializeToLocalStorage();\n\n // Hide modal\n modal.style.display = \"none\";\n };\n\n // Hide delete button when creating new task\n deleteBtn.style.display = \"none\";\n}\n\n/**\n * \n * @param {API} api \n */\nfunction generateElementsFromLoadedData(api) {\n const listDiv = document.querySelector(\"#task-lists\");\n\n // Generate all list elements\n api.TaskLists.forEach((list) => {\n const listEl = createListWithName(api, list.Identifier);\n listDiv.insertBefore(listEl, listDiv.children[listDiv.children.length - 1]);\n });\n\n // Generate all task elements\n api.Tasks.forEach((task) => {\n const list = document.querySelector(`#${task.ListID}`);\n const content = list.querySelector(\".list-content\");\n content.appendChild(createTaskItemElement(api, task.Title, task.ID));\n });\n}\n\n/**\n * \n * @param {API} api \n * @param {string} taskID \n */\nfunction populateTaskModalFields(api, taskID) {\n const task = api.getTaskFromID(taskID);\n\n const modal = document.querySelector(\"#modal\");\n const modalHeader = document.querySelector(\"#modal-header\");\n const createdOn = document.querySelector(\"#created-on\");\n const taskTitle = document.querySelector(\"#task-title\");\n const saveBtn = document.querySelector(\"#modal-save-btn\");\n const deleteBtn = document.querySelector(\"#modal-delete-btn\");\n const taskDesc = document.querySelector(\"#task-desc\");\n\n const tagKind = document.querySelector(\"#kind-option\");\n const dueDate = document.querySelector(\"#due-date-option\");\n const colorSelected = document.querySelector(\"#color-selected\");\n\n const taskTitleText = task.Title;\n taskTitle.value = taskTitleText;\n taskDesc.value = task.Description;\n createdOn.innerText = `Created on ${task.CreatedAt.toDateString()}`;\n\n tagKind.value = (0,_task__WEBPACK_IMPORTED_MODULE_2__.tagKindToStr)(task.Tag);\n dueDate.valueAsDate = task.DueDate;\n\n modalHeader.style.background = task.Color;\n colorSelected.value = task.Color;\n colorSelected.style.background = task.Color;\n\n saveBtn.onclick = () => {\n task.applyFields(\n taskTitle.value,\n (0,_task__WEBPACK_IMPORTED_MODULE_2__.tagStrToKind)(tagKind.value),\n dueDate.valueAsDate,\n colorSelected.style.background,\n taskDesc.value\n );\n\n // Save results to disk\n api.serializeToLocalStorage();\n\n // Hide modal\n modal.style.display = \"none\";\n };\n\n deleteBtn.style.display = \"inline\";\n deleteBtn.onclick = () => {\n // TODO: Add confirmation modal\n\n api.removeTaskItem(task);\n\n const listEl = document.querySelector(`#${task.ListID}`);\n const content = listEl.querySelector(\".list-content\");\n content.removeChild(document.querySelector(`#task-id-${task.ID}`));\n\n // Save results to disk\n api.serializeToLocalStorage();\n\n // Hide modal\n modal.style.display = \"none\";\n };\n\n // Show modal\n modal.style.display = \"block\";\n}\n\n/**\n * \n * @param {API} api \n * @param {string} taskTitle \n * @param {number} index \n * @returns \n */\nfunction createTaskItemElement(api, taskTitle, index) {\n /**\n * <div class=\"task\" draggable=\"true\">\n <p class=\"task-title\">Get Groceries</p>\n <button class=\"task-edit\">...</button>\n </div>\n */\n const taskID = `task-id-${index}`;\n const newTask = document.createElement(\"div\");\n newTask.className = \"task\";\n newTask.id = taskID;\n newTask.setAttribute(\"draggable\", \"true\");\n\n const taskTitleEl = document.createElement(\"p\");\n newTask.appendChild(taskTitleEl);\n\n taskTitleEl.className = \"task-title\";\n taskTitleEl.innerText = taskTitle;\n\n const innerBtn = document.createElement(\"button\");\n newTask.appendChild(innerBtn);\n\n innerBtn.className = \"task-edit\";\n innerBtn.innerText = \"...\";\n innerBtn.onclick = () => populateTaskModalFields(api, taskID);\n\n addDragListeners(newTask);\n\n return newTask;\n}\n\n/**\n * \n * @param {API} api \n * @returns \n */\nfunction createDefaultList(api) {\n if (!api.tryAddNewList()) {\n return null;\n }\n\n return createListWithName(api, \"New List\");\n}\n\n/**\n * \n * @param {API} api \n * @param {string} title \n * @returns \n */\nfunction createListWithName(api, title) {\n /**\n * <div class=\"swim-list\" id=\"todo-list\">\n <input class=\"list-heading\" type=\"text\">TODO</h3>\n </div>\n */\n const listID = (0,_api__WEBPACK_IMPORTED_MODULE_0__.listNameToID)(title);\n\n const el = document.createElement(\"div\");\n el.className = \"swim-list\";\n el.id = listID;\n\n const header = document.createElement(\"div\");\n el.appendChild(header);\n header.className = \"list-heading-inner-text\";\n\n const headerTitle = document.createElement(\"input\");\n header.appendChild(headerTitle);\n\n headerTitle.className = \"list-heading-input\";\n headerTitle.type = \"text\";\n headerTitle.value = title;\n headerTitle.defaultValue = title;\n\n headerTitle.onchange = (e) => listHeaderChange(el, headerTitle, e, api);\n\n const listContentZone = document.createElement(\"div\");\n el.appendChild(listContentZone);\n\n listContentZone.setAttribute(\"value\", listID);\n listContentZone.className = \"list-content\";\n\n (0,_dragging__WEBPACK_IMPORTED_MODULE_1__.setupListDragZone)(api, listContentZone);\n\n const deleteSpan = document.createElement(\"span\");\n header.appendChild(deleteSpan);\n\n deleteSpan.className = \"list-delete-span\";\n deleteSpan.innerText = \"\\u{00D7}\";\n deleteSpan.onclick = (e) => {\n e.preventDefault();\n\n if (listContentZone.children.length > 0) {\n showErrorModal(\"Cannot delete list that contains tasks.\");\n return;\n }\n\n const listDiv = document.querySelector(\"#task-lists\");\n listDiv.removeChild(el);\n\n api.deleteTaskList(listID);\n\n // Save results to disk\n api.serializeToLocalStorage();\n };\n\n return el;\n}\n\n/**\n * \n * @param {HTMLElement} el \n * @param {HTMLInputElement} self \n * @param {Event} e \n * @param {API} api \n * @returns \n */\nfunction listHeaderChange(el, self, e, api) {\n e.preventDefault();\n\n const newID = (0,_api__WEBPACK_IMPORTED_MODULE_0__.listNameToID)(self.value);\n if (el.id === newID) {\n return;\n }\n\n if (api.taskListContains(self.value)) {\n showErrorModal(`Task list with name '${self.value}' already exists.`);\n self.value = self.defaultValue;\n return;\n }\n\n const content = el.querySelector(\".list-content\");\n content.setAttribute(\"value\", newID);\n\n api.renameTaskList(self.defaultValue, self.value);\n\n self.defaultValue = self.value;\n el.id = newID;\n\n // Save results to disk\n api.serializeToLocalStorage();\n}\n\n\n//# sourceURL=webpack://kanban-board/./src/layout.js?");
/***/ }),
/***/ "./src/task.js":
/*!*********************!*\
!*** ./src/task.js ***!
\*********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ TagKind: () => (/* binding */ TagKind),\n/* harmony export */ TaskItem: () => (/* binding */ TaskItem),\n/* harmony export */ tagKindToStr: () => (/* binding */ tagKindToStr),\n/* harmony export */ tagStrToKind: () => (/* binding */ tagStrToKind)\n/* harmony export */ });\n\n\nconst TagKind = {\n Programming: 0,\n Graphics: 1,\n Documentation: 2,\n};\n\nclass TaskItem {\n // Properties\n get ID() {\n return this.id;\n }\n\n get CreatedAt() {\n return this.createdAt;\n }\n\n get ListID() {\n return this.listID;\n }\n\n get Title() {\n return this.title;\n }\n\n get Tag() {\n return this.tag;\n }\n\n get DueDate() {\n return this.dueDate;\n }\n\n get Color() {\n return this.color;\n }\n\n get Description() {\n return this.description;\n }\n\n /**\n * \n * @param {string} id \n * @param {Date} createdAt \n * @param {string} listID \n * @param {string} title \n * @param {TagKind} tag \n * @param {Date | null} dueDate \n * @param {string} color \n * @param {string} description \n */\n constructor(\n id,\n createdAt,\n listID,\n title,\n tag,\n dueDate,\n color,\n description\n ) {\n this.id = id;\n this.createdAt = createdAt;\n this.listID = listID;\n this.title = title;\n this.tag = tag;\n this.dueDate = dueDate;\n this.color = color;\n this.description = description;\n }\n\n /**\n * \n * @param {TaskItem} item \n * @returns \n */\n static fromLoadedData(item) {\n return new TaskItem(\n item.id,\n new Date(item.createdAt),\n item.listID,\n item.title,\n item.tag,\n !item.dueDate ? null : new Date(item.dueDate),\n item.color,\n item.description\n );\n }\n\n /**\n * \n * @param {string} listID \n */\n setListID(listID) {\n this.listID = listID;\n }\n\n /**\n * \n * @param {string} title \n * @param {TagKind} tag \n * @param {Date | null} dueDate \n * @param {string} color \n * @param {string} description \n */\n applyFields(\n title,\n tag,\n dueDate,\n color,\n description\n ) {\n this.title = title;\n this.tag = tag;\n this.dueDate = dueDate;\n this.color = color;\n this.description = description;\n }\n}\n\n/**\n * \n * @param {string} tagStr \n * @returns \n */\nfunction tagStrToKind(tagStr) {\n switch (tagStr) {\n case \"prg\":\n return TagKind.Programming;\n case \"gfx\":\n return TagKind.Graphics;\n case \"doc\":\n return TagKind.Documentation;\n default:\n throw new Error(`Undefined tag kind '${tagStr}'`);\n }\n}\n\n/**\n * \n * @param {TagKind} tag \n * @returns \n */\nfunction tagKindToStr(tag) {\n switch (tag) {\n case TagKind.Programming:\n return \"prg\";\n case TagKind.Graphics:\n return \"gfx\";\n case TagKind.Documentation:\n return \"doc\";\n }\n}\n\n\n//# sourceURL=webpack://kanban-board/./src/task.js?");
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module can't be inlined because the eval devtool is used.
/******/ var __webpack_exports__ = __webpack_require__("./src/index.js");
/******/
/******/ })()
;