From dd8dc8c4afae393ebc677c2be03fa4c1c3a96757 Mon Sep 17 00:00:00 2001 From: Morris Brodersen Date: Thu, 30 Nov 2023 11:42:02 +0100 Subject: [PATCH] refactor for pure functional business logic --- public/scripts/TodoApp.js | 9 +- public/scripts/TodoCustomList.js | 8 +- public/scripts/TodoFrameCustom.js | 43 +--- public/scripts/TodoFrameDays.js | 36 +-- public/scripts/TodoItem.js | 6 +- public/scripts/TodoList.js | 2 +- public/scripts/TodoLogic.js | 212 ++++++++++++++++++ public/scripts/TodoStore.js | 183 +++------------ public/scripts/util.js | 9 - public/scripts/uuid.js | 8 + test/e2e/addCustomTodoList.test.mjs | 12 + ...{addItem.test.mjs => addTodoItem.test.mjs} | 0 test/e2e/deleteCustomTodoList.test.mjs | 20 ++ ...t.test.mjs => editCustomTodoList.test.mjs} | 10 - test/unit/TodoLogic.test.mjs | 143 ++++++++++++ 15 files changed, 449 insertions(+), 252 deletions(-) create mode 100644 public/scripts/TodoLogic.js create mode 100644 public/scripts/uuid.js create mode 100644 test/e2e/addCustomTodoList.test.mjs rename test/e2e/{addItem.test.mjs => addTodoItem.test.mjs} (100%) create mode 100644 test/e2e/deleteCustomTodoList.test.mjs rename test/e2e/{addCustomList.test.mjs => editCustomTodoList.test.mjs} (68%) create mode 100644 test/unit/TodoLogic.test.mjs diff --git a/public/scripts/TodoApp.js b/public/scripts/TodoApp.js index b63cb12..800d2d4 100644 --- a/public/scripts/TodoApp.js +++ b/public/scripts/TodoApp.js @@ -4,19 +4,14 @@ import { AppFps } from './AppFps.js'; import { AppIcon } from './AppIcon.js'; import { TodoFrameCustom } from './TodoFrameCustom.js'; import { TodoFrameDays } from './TodoFrameDays.js'; +import { TodoLogic } from './TodoLogic.js'; import { TodoStore } from './TodoStore.js'; -import { formatDateId } from './util.js'; /** * @param {HTMLElement} el */ export function TodoApp(el) { - let todoData = { - items: [], - customLists: [], - at: formatDateId(new Date()), - customAt: 0, - }; + let todoData = TodoLogic.initTodoData(); el.innerHTML = `
diff --git a/public/scripts/TodoCustomList.js b/public/scripts/TodoCustomList.js index ca783a5..16580cd 100644 --- a/public/scripts/TodoCustomList.js +++ b/public/scripts/TodoCustomList.js @@ -82,7 +82,7 @@ export function TodoCustomList(el) { } el.dispatchEvent( - new CustomEvent('deleteTodoList', { + new CustomEvent('deleteCustomTodoList', { detail: list, bubbles: true, }), @@ -115,15 +115,15 @@ export function TodoCustomList(el) { e.detail.index = e.detail.index ?? 0; }); - el.addEventListener('todoCustomList', (e) => { + el.addEventListener('customTodoList', (e) => { list = e.detail; update(); }); function save() { el.dispatchEvent( - new CustomEvent('saveTodoList', { - detail: { list, title: inputEl.value.trim() }, + new CustomEvent('editCustomTodoList', { + detail: { ...list, title: inputEl.value.trim() }, bubbles: true, }), ); diff --git a/public/scripts/TodoFrameCustom.js b/public/scripts/TodoFrameCustom.js index 04b3533..294211a 100644 --- a/public/scripts/TodoFrameCustom.js +++ b/public/scripts/TodoFrameCustom.js @@ -1,16 +1,13 @@ import { AppIcon } from './AppIcon.js'; import { AppSortable } from './AppSortable.js'; import { TodoCustomList } from './TodoCustomList.js'; +import { TodoLogic } from './TodoLogic.js'; /** * @param {HTMLElement} el */ export function TodoFrameCustom(el) { - let todoData = { - customLists: [], - items: [], - customAt: 0, - }; + let todoData = TodoLogic.initTodoData(); el.innerHTML = `
@@ -42,9 +39,7 @@ export function TodoFrameCustom(el) { ); el.querySelector('.add').addEventListener('click', () => { - el.dispatchEvent( - new CustomEvent('addTodoList', { detail: {}, bubbles: true }), - ); + el.dispatchEvent(new CustomEvent('addCustomTodoList', { bubbles: true })); // TODO seek if not at end }); @@ -52,9 +47,9 @@ export function TodoFrameCustom(el) { if (!e.detail.data.list) return; el.dispatchEvent( - new CustomEvent('moveTodoList', { + new CustomEvent('moveCustomTodoList', { detail: { - list: e.detail.data.list, + ...e.detail.data.list, index: e.detail.index, }, bubbles: true, @@ -63,9 +58,7 @@ export function TodoFrameCustom(el) { }); el.addEventListener('draggableOver', (e) => { - if (!e.detail.data.list) return; - - updatePositions(); + if (e.detail.data.list) updatePositions(); }); el.addEventListener('todoData', (e) => { @@ -74,14 +67,15 @@ export function TodoFrameCustom(el) { }); function update() { - const lists = getLists(); + const customLists = TodoLogic.getCustomTodoLists(todoData); + const container = el.querySelector('.container'); const obsolete = new Set(container.children); const childrenByKey = new Map(); obsolete.forEach((child) => childrenByKey.set(child.dataset.key, child)); - const children = lists.map((list) => { + const children = customLists.map((list) => { let child = childrenByKey.get(list.id); if (child) { @@ -93,7 +87,7 @@ export function TodoFrameCustom(el) { TodoCustomList(child); } - child.dispatchEvent(new CustomEvent('todoCustomList', { detail: list })); + child.dispatchEvent(new CustomEvent('customTodoList', { detail: list })); return child; }); @@ -136,21 +130,4 @@ export function TodoFrameCustom(el) { // Update collapsible on changing heights el.dispatchEvent(new CustomEvent('collapse', { bubbles: true })); } - - function getLists() { - return todoData.customLists - .map((list) => ({ - id: list.id, - index: list.index, - title: list.title, - items: getItemsForList(list.id), - })) - .sort((a, b) => a.index - b.index); - } - - function getItemsForList(listId) { - return todoData.items - .filter((item) => item.listId === listId) - .sort((a, b) => a.index - b.index); - } } diff --git a/public/scripts/TodoFrameDays.js b/public/scripts/TodoFrameDays.js index af598cd..72c3f80 100644 --- a/public/scripts/TodoFrameDays.js +++ b/public/scripts/TodoFrameDays.js @@ -1,18 +1,14 @@ import { AppDatePicker } from './AppDatePicker.js'; import { AppIcon } from './AppIcon.js'; import { TodoDay } from './TodoDay.js'; -import { formatDateId } from './util.js'; +import { TodoLogic } from './TodoLogic.js'; /** * @param {HTMLElement} el */ export function TodoFrameDays(el) { const RANGE = 14; - - let todoData = { - items: [], - at: formatDateId(new Date()), - }; + let todoData = TodoLogic.initTodoData(); el.innerHTML = `