diff --git a/bundle.js b/bundle.js index aefad89..14ba99c 100755 --- a/bundle.js +++ b/bundle.js @@ -104,7 +104,7 @@ async function bundleJS(inputDir, outputDir, watch) { let buildContext = await esbuild.context({ entryPoints: { carts: `${inputDir}/carts.js`, - "changes-new": `${inputDir}/changes-new.js`, + changes: `${inputDir}/changes.js`, index: `${inputDir}/index.js`, }, bundle: true, diff --git a/site/changes-new.html b/site/changes-new.html deleted file mode 100644 index 5d429e6..0000000 --- a/site/changes-new.html +++ /dev/null @@ -1,11 +0,0 @@ -%%_templates/_header.html%% %%_templates/_menu.html%% - -
-

Preisänderungen

- - -
- - - -%%_templates/_footer.html%% diff --git a/site/changes-new.js b/site/changes-new.js deleted file mode 100644 index e042841..0000000 --- a/site/changes-new.js +++ /dev/null @@ -1,11 +0,0 @@ -const model = require("./model"); -require("./views"); - -(async () => { - await model.load(); - const itemsFilter = document.querySelector("items-filter"); - const itemsList = document.querySelector("items-list"); - itemsList.elements.sort.value = "chain-and-name"; - itemsFilter.model = itemsList.model = model.items; - itemsFilter.filter(); -})(); diff --git a/site/changes-old.html b/site/changes-old.html new file mode 100644 index 0000000..557528e --- /dev/null +++ b/site/changes-old.html @@ -0,0 +1,25 @@ +%%_templates/_header.html%% %%_templates/_menu.html%% + +
+

Preisänderungen

+
+
+ + +
+ +
+
+
+
+ +
+ + + + + +%%_templates/_footer.html%% diff --git a/site/changes-old.js b/site/changes-old.js new file mode 100644 index 0000000..3fb08fe --- /dev/null +++ b/site/changes-old.js @@ -0,0 +1,164 @@ +let changeDates = []; +let items = []; + +async function load() { + items = await loadItems(); + items.sort((a, b) => { + if (a.store < b.store) { + return -1; + } else if (a.store > b.store) { + return 1; + } + + if (a.name < b.name) { + return -1; + } else if (a.name > b.name) { + return 1; + } + + return 0; + }); + + const dates = {}; + for (const item of items) { + if (item.priceHistory.length == 1) continue; + for (let i = 0; i < item.priceHistory.length; i++) { + const price = item.priceHistory[i]; + if (i + 1 < item.priceHistory.length) { + if (item.priceHistory[i].price != item.priceHistory[i + 1].price) dates[price.date] = dates[price.date] ? dates[price.date] + 1 : 1; + } + } + } + const dateNames = Object.keys(dates).sort((a, b) => b.localeCompare(a)); + + const dateSelection = document.querySelector("#dates"); + dateNames.forEach((dateName, index) => { + const option = dom("option", dateName + " (" + dates[dateName] + ")"); + option.setAttribute("value", dateName); + if (index == 0) option.selected = true; + dateSelection.appendChild(option); + }); + + document.querySelectorAll("#type").forEach((changeType) => { + changeType.addEventListener("change", () => showResults(items)); + }); + + dateSelection.addEventListener("change", () => { + showResults(items); + }); + + const filtersStore = document.querySelector("#filters-store"); + filtersStore.innerHTML = ` + ${customCheckbox(`all`, "Alle", true, "gray")} + ${STORE_KEYS.map((store) => + customCheckbox(store, stores[store].name, stores[store].name.toLowerCase().endsWith("de") ? false : true, stores[store].color) + ).join(" ")} + `; + filtersStore.querySelector("#all").addEventListener("change", () => { + const checked = filtersStore.querySelector("#all").checked; + STORE_KEYS.forEach((store) => (filtersStore.querySelector(`#${store}`).checked = checked)); + showResults(items); + }); + + document.querySelector("#filters-changes").innerHTML = ` + ${customCheckbox(`increases`, "Teurer", true, "gray")} + ${customCheckbox(`decreases`, "Billiger", true, "gray")} + `; + + document.querySelectorAll("input").forEach((input) => { + if (input.id == "all" && input.id != "type") return; + input.addEventListener("change", () => showResults(items)); + }); + + let timeoutId; + document.querySelector("#filter").addEventListener("input", () => { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => { + if (document.querySelector("#filter").value.trim().startsWith("!")) { + document.querySelector("#filters-store").classList.add("hidden"); + document.querySelector("#filters-changes").classList.add("hidden"); + } else { + document.querySelector("#filters-store").classList.remove("hidden"); + document.querySelector("#filters-changes").classList.remove("hidden"); + } + showResults(items); + }, 50); + }); + + showResults(items); +} + +function showResults(items) { + const query = document.querySelector("#filter").value.trim(); + let today = null; + if (document.querySelector("#date").checked) { + today = document.querySelector("#dates").value; + if (!query.startsWith("!")) document.querySelector("#filters-changes").classList.remove("hidden"); + } else { + document.querySelector("#filters-changes").classList.add("hidden"); + } + const increases = document.querySelector("#increases").checked; + const decreases = document.querySelector("#decreases").checked; + const storeCheckboxes = STORE_KEYS.map((store) => document.querySelector(`#${store}`)); + const checkedStores = STORE_KEYS.filter((store, i) => storeCheckboxes[i].checked); + let changedItems = []; + for (const item of items) { + if (item.priceHistory.length < 2) continue; + if (!checkedStores.includes(item.store)) continue; + + if (today) { + for (let i = 0; i < item.priceHistory.length; i++) { + if (item.priceHistory[i].date == today && i + 1 < item.priceHistory.length) { + if (increases && item.priceHistory[i].price > item.priceHistory[i + 1].price) { + changedItems.push(item); + } + if (decreases && item.priceHistory[i].price < item.priceHistory[i + 1].price) { + changedItems.push(item); + } + } + } + } else { + if (item.priceHistory[0].price < item.priceHistory[1].price) changedItems.push(item); + } + } + + const total = changedItems.length; + if (query.startsWith("!") || query.length >= 3) + changedItems = searchItems(changedItems, document.querySelector("#filter").value, checkedStores, false, 0, 10000, false, false); + document.querySelector("#numresults").innerText = "Resultate: " + changedItems.length + (total > changedItems.length ? " / " + total : ""); + const table = document.querySelector("#result"); + table.innerHTML = ""; + if (changedItems.length == 0) return; + const header = dom( + "thead", + ` + Kette + Name + + Preis + + + + + ` + ); + const showHideAll = header.querySelectorAll("th:nth-child(3)")[0]; + showHideAll.style["cursor"] = "pointer"; + showHideAll.showAll = true; + showHideAll.addEventListener("click", () => { + showHideAll.querySelector(".expander").innerText = showHideAll.querySelector(".expander").innerText == "+" ? "-" : "+"; + table.querySelectorAll(".priceinfo").forEach((el) => (showHideAll.showAll ? el.classList.remove("hidden") : el.classList.add("hidden"))); + showHideAll.showAll = !showHideAll.showAll; + }); + + table.appendChild(header); + + for (let item of changedItems) { + item = JSON.parse(JSON.stringify(item)); + const itemDom = itemToDOM(item); + table.appendChild(itemDom); + } + + table.classList.remove("hidden"); +} + +load(); diff --git a/site/changes.html b/site/changes.html index 13a9112..fe6eb6f 100644 --- a/site/changes.html +++ b/site/changes.html @@ -2,24 +2,10 @@

Preisänderungen

-
-
- - -
- -
-
-
-
- + +
- - %%_templates/_footer.html%% diff --git a/site/changes.js b/site/changes.js index 3fb08fe..e042841 100644 --- a/site/changes.js +++ b/site/changes.js @@ -1,164 +1,11 @@ -let changeDates = []; -let items = []; +const model = require("./model"); +require("./views"); -async function load() { - items = await loadItems(); - items.sort((a, b) => { - if (a.store < b.store) { - return -1; - } else if (a.store > b.store) { - return 1; - } - - if (a.name < b.name) { - return -1; - } else if (a.name > b.name) { - return 1; - } - - return 0; - }); - - const dates = {}; - for (const item of items) { - if (item.priceHistory.length == 1) continue; - for (let i = 0; i < item.priceHistory.length; i++) { - const price = item.priceHistory[i]; - if (i + 1 < item.priceHistory.length) { - if (item.priceHistory[i].price != item.priceHistory[i + 1].price) dates[price.date] = dates[price.date] ? dates[price.date] + 1 : 1; - } - } - } - const dateNames = Object.keys(dates).sort((a, b) => b.localeCompare(a)); - - const dateSelection = document.querySelector("#dates"); - dateNames.forEach((dateName, index) => { - const option = dom("option", dateName + " (" + dates[dateName] + ")"); - option.setAttribute("value", dateName); - if (index == 0) option.selected = true; - dateSelection.appendChild(option); - }); - - document.querySelectorAll("#type").forEach((changeType) => { - changeType.addEventListener("change", () => showResults(items)); - }); - - dateSelection.addEventListener("change", () => { - showResults(items); - }); - - const filtersStore = document.querySelector("#filters-store"); - filtersStore.innerHTML = ` - ${customCheckbox(`all`, "Alle", true, "gray")} - ${STORE_KEYS.map((store) => - customCheckbox(store, stores[store].name, stores[store].name.toLowerCase().endsWith("de") ? false : true, stores[store].color) - ).join(" ")} - `; - filtersStore.querySelector("#all").addEventListener("change", () => { - const checked = filtersStore.querySelector("#all").checked; - STORE_KEYS.forEach((store) => (filtersStore.querySelector(`#${store}`).checked = checked)); - showResults(items); - }); - - document.querySelector("#filters-changes").innerHTML = ` - ${customCheckbox(`increases`, "Teurer", true, "gray")} - ${customCheckbox(`decreases`, "Billiger", true, "gray")} - `; - - document.querySelectorAll("input").forEach((input) => { - if (input.id == "all" && input.id != "type") return; - input.addEventListener("change", () => showResults(items)); - }); - - let timeoutId; - document.querySelector("#filter").addEventListener("input", () => { - clearTimeout(timeoutId); - timeoutId = setTimeout(() => { - if (document.querySelector("#filter").value.trim().startsWith("!")) { - document.querySelector("#filters-store").classList.add("hidden"); - document.querySelector("#filters-changes").classList.add("hidden"); - } else { - document.querySelector("#filters-store").classList.remove("hidden"); - document.querySelector("#filters-changes").classList.remove("hidden"); - } - showResults(items); - }, 50); - }); - - showResults(items); -} - -function showResults(items) { - const query = document.querySelector("#filter").value.trim(); - let today = null; - if (document.querySelector("#date").checked) { - today = document.querySelector("#dates").value; - if (!query.startsWith("!")) document.querySelector("#filters-changes").classList.remove("hidden"); - } else { - document.querySelector("#filters-changes").classList.add("hidden"); - } - const increases = document.querySelector("#increases").checked; - const decreases = document.querySelector("#decreases").checked; - const storeCheckboxes = STORE_KEYS.map((store) => document.querySelector(`#${store}`)); - const checkedStores = STORE_KEYS.filter((store, i) => storeCheckboxes[i].checked); - let changedItems = []; - for (const item of items) { - if (item.priceHistory.length < 2) continue; - if (!checkedStores.includes(item.store)) continue; - - if (today) { - for (let i = 0; i < item.priceHistory.length; i++) { - if (item.priceHistory[i].date == today && i + 1 < item.priceHistory.length) { - if (increases && item.priceHistory[i].price > item.priceHistory[i + 1].price) { - changedItems.push(item); - } - if (decreases && item.priceHistory[i].price < item.priceHistory[i + 1].price) { - changedItems.push(item); - } - } - } - } else { - if (item.priceHistory[0].price < item.priceHistory[1].price) changedItems.push(item); - } - } - - const total = changedItems.length; - if (query.startsWith("!") || query.length >= 3) - changedItems = searchItems(changedItems, document.querySelector("#filter").value, checkedStores, false, 0, 10000, false, false); - document.querySelector("#numresults").innerText = "Resultate: " + changedItems.length + (total > changedItems.length ? " / " + total : ""); - const table = document.querySelector("#result"); - table.innerHTML = ""; - if (changedItems.length == 0) return; - const header = dom( - "thead", - ` - Kette - Name - - Preis - + - - - ` - ); - const showHideAll = header.querySelectorAll("th:nth-child(3)")[0]; - showHideAll.style["cursor"] = "pointer"; - showHideAll.showAll = true; - showHideAll.addEventListener("click", () => { - showHideAll.querySelector(".expander").innerText = showHideAll.querySelector(".expander").innerText == "+" ? "-" : "+"; - table.querySelectorAll(".priceinfo").forEach((el) => (showHideAll.showAll ? el.classList.remove("hidden") : el.classList.add("hidden"))); - showHideAll.showAll = !showHideAll.showAll; - }); - - table.appendChild(header); - - for (let item of changedItems) { - item = JSON.parse(JSON.stringify(item)); - const itemDom = itemToDOM(item); - table.appendChild(itemDom); - } - - table.classList.remove("hidden"); -} - -load(); +(async () => { + await model.load(); + const itemsFilter = document.querySelector("items-filter"); + const itemsList = document.querySelector("items-list"); + itemsList.elements.sort.value = "chain-and-name"; + itemsFilter.model = itemsList.model = model.items; + itemsFilter.filter(); +})(); diff --git a/site/index-old.html b/site/index-old.html index 9b44633..a0e2aa8 100644 --- a/site/index-old.html +++ b/site/index-old.html @@ -26,6 +26,6 @@ - + %%_templates/_footer.html%% diff --git a/site/model/items.js b/site/model/items.js index f6dd154..9d005e3 100644 --- a/site/model/items.js +++ b/site/model/items.js @@ -69,30 +69,9 @@ class Items extends Model { return this._lookup; } - async load() { - let start = performance.now(); - const compressedItemsPerStore = []; - for (const store of STORE_KEYS) { - compressedItemsPerStore.push( - new Promise(async (resolve) => { - const start = performance.now(); - try { - const response = await fetch(`data/latest-canonical.${store}.compressed.json`); - const json = await response.json(); - log(`Items - loading compressed items for ${store} took ${deltaTime(start)} secs`); - resolve(decompress(json)); - } catch (e) { - log(`Items - error while loading compressed items for ${store} ${e.message}`); - resolve([]); - } - }) - ); - } - const items = [].concat(...(await Promise.all(compressedItemsPerStore))); - log(`Items - loaded ${items.length} items took ${deltaTime(start).toFixed(4)} secs`); - + processItems(items) { const lookup = {}; - start = performance.now(); + const start = performance.now(); for (const item of items) { lookup[item.store + item.id] = item; item.search = item.name + " " + item.quantity + " " + item.unit; @@ -136,10 +115,34 @@ class Items extends Model { }); log(`Items - processing ${items.length} items took ${deltaTime(start).toFixed(4)} secs`); - this._items = items; this._lookup = lookup; } + + async load() { + let start = performance.now(); + const compressedItemsPerStore = []; + for (const store of STORE_KEYS) { + compressedItemsPerStore.push( + new Promise(async (resolve) => { + const start = performance.now(); + try { + const response = await fetch(`data/latest-canonical.${store}.compressed.json`); + const json = await response.json(); + log(`Items - loading compressed items for ${store} took ${deltaTime(start)} secs`); + resolve(decompress(json)); + } catch (e) { + log(`Items - error while loading compressed items for ${store} ${e.message}`); + resolve([]); + } + }) + ); + } + const items = [].concat(...(await Promise.all(compressedItemsPerStore))); + log(`Items - loaded ${items.length} items took ${deltaTime(start).toFixed(4)} secs`); + + this.processItems(items); + } } exports.Items = Items;