Commit d2c07460 authored by ransome1's avatar ransome1
Browse files

GUI refresh

parent fe080b66
...@@ -92,13 +92,13 @@ ...@@ -92,13 +92,13 @@
"artifactName": "${productName}-${version}-${arch}.${ext}" "artifactName": "${productName}-${version}-${arch}.${ext}"
}, },
"scripts": { "scripts": {
"pack": "yarn build:css && electron-builder --dir", "build:windows": "yarn build:css && yarn build:pegjs && electron-builder -w --publish never",
"build:windows": "yarn build:css && electron-builder -w --publish never", "build:macos": "yarn build:css && yarn build:pegjs && electron-builder -m --publish never",
"build:macos": "yarn build:css && electron-builder -m --publish never", "build:linux": "yarn build:css && yarn build:pegjs && electron-builder -l --publish never",
"build:linux": "yarn build:css && electron-builder -l --publish never", "build:appx": "yarn build:css && yarn build:pegjs && electron-builder -w appx --publish never",
"build:appx": "yarn build:css && electron-builder -w appx --publish never",
"build:appimage": "yarn build:css && yarn build:pegjs && electron-builder -l AppImage --publish never", "build:appimage": "yarn build:css && yarn build:pegjs && electron-builder -l AppImage --publish never",
"build:css": "sass src/scss/style.scss:src/css/style.css", "build:pegjs": "peggy --format es --output src/js/filterlang.mjs src/js/filterlang.pegjs",
"pack": "yarn build:css && yarn build:pegjs && electron-builder --dir",
"lint": "eslint --ext .js, src --ext .mjs, src", "lint": "eslint --ext .js, src --ext .mjs, src",
"test": "mocha --timeout 10000", "test": "mocha --timeout 10000",
"test1": "mocha ./test/onboarding.js --timeout 10000", "test1": "mocha ./test/onboarding.js --timeout 10000",
......
This diff is collapsed.
This diff is collapsed.
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
<li><a href="#" id="navBtnAddTodo" tabindex="0"><i class="fas fa-plus"></i></a></li> <li><a href="#" id="navBtnAddTodo" tabindex="0"><i class="fas fa-plus"></i></a></li>
<li><a href="#" id="navBtnFilter" class="drawerTrigger" data-drawer="filterDrawer" tabindex="0"><i class="fas fa-filter"></i></a></li> <li><a href="#" id="navBtnFilter" class="drawerTrigger" data-drawer="filterDrawer" tabindex="0"><i class="fas fa-filter"></i></a></li>
<li><a href="#" id="navBtnView" class="drawerTrigger" data-drawer="viewDrawer"tabindex="0"><i class="fas fa-sliders-h"></i></a></li> <li><a href="#" id="navBtnView" class="drawerTrigger" data-drawer="viewDrawer"tabindex="0"><i class="fas fa-sliders-h"></i></a></li>
<li><a href="#" id="btnOpenTodoFile" tabindex="-1"><i class="fas fa-folder-open"></i></a></li> <li><a href="#" id="btnOpenTodoFile" tabindex="0"><i class="fas fa-folder-open"></i></a></li>
<li><a href="#" id="btnTheme" tabindex="-1"><i class="fas fa-adjust"></i></a></li> <li><a href="#" id="btnTheme" tabindex="-1"><i class="fas fa-adjust"></i></a></li>
</ul> </ul>
<ul> <ul>
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
<section id="filterDrawer" class="drawer dropdown" tabindex="0"> <section id="filterDrawer" class="drawer dropdown" tabindex="0">
<div class="container"> <div class="container">
<div id="todoFilters"></div> <div id="todoFilters"></div>
<button id="btnFiltersResetFilters" class="button btnResetFilters" tabindex="0"><i class="fas fa-ban"></i>&nbsp;<span></span></button> <button id="btnFiltersResetFilters" class="btnResetFilters" tabindex="0"><i class="fas fa-ban"></i>&nbsp;<span></span></button>
</div> </div>
</section> </section>
<section id="viewDrawer" class="drawer dropdown" tabindex="0"> <section id="viewDrawer" class="drawer dropdown" tabindex="0">
...@@ -189,14 +189,14 @@ ...@@ -189,14 +189,14 @@
<section id="todoTableSearchContainer" class="inputWrapper"> <section id="todoTableSearchContainer" class="inputWrapper">
<i class="fas fa-search"></i> <i class="fas fa-search"></i>
<label id="todoTableSearchLabel" for="todoTableSearch">Search by todo.txt syntax</label> <label id="todoTableSearchLabel" for="todoTableSearch"></label>
<input id="todoTableSearch" class="input is-medium" type="search" tabindex="1" placeholder="(A) Todo text +project @context due:2020-12-12 rec:d"> <input id="todoTableSearch" class="input is-medium" type="search" tabindex="1" placeholder="(A) Todo text +project @context due:2020-12-12 rec:d">
<a href="#" id="todoTableSearchAddTodo" class="tag" tabindex="5"><i class="fas fa-plus"></i>&nbsp;Add as new todo</a> <a href="#" id="todoTableSearchAddTodo" class="tag" tabindex="5"><i class="fas fa-plus"></i>&nbsp;Add as new todo</a>
<section id="resultStats">
<span class="tag"></span>
</section>
</section> </section>
<section id="resultStats">
<span class="tag"></span>
</section>
<section id="todoTable" tabindex="-1"></section> <section id="todoTable" tabindex="-1"></section>
...@@ -219,7 +219,7 @@ ...@@ -219,7 +219,7 @@
<h1 id="addTodoContainerHeadline" class="title is-1"></h1> <h1 id="addTodoContainerHeadline" class="title is-1"></h1>
<p id="addTodoContainerSubtitle" class="subtitle"></p> <p id="addTodoContainerSubtitle" class="subtitle"></p>
<p class="file is-boxed is-centered"> <p class="file is-boxed is-centered">
<a href="#" id="btnAddTodoContainer" class="btnOnboarding"> <a href="#" id="btnAddTodoContainer" class="btnOnboarding" tabindex="0">
<i class="fas fa-plus"></i> <i class="fas fa-plus"></i>
<span id="addTodoContainerButton" class="file-label"></span> <span id="addTodoContainerButton" class="file-label"></span>
</a> </a>
...@@ -229,25 +229,23 @@ ...@@ -229,25 +229,23 @@
<section id="noResultContainer" class="contentContainer"> <section id="noResultContainer" class="contentContainer">
<h1 id="noResultContainerHeadline" class="title is-1"></h1> <h1 id="noResultContainerHeadline" class="title is-1"></h1>
<p id="noResultContainerSubtitle" class="subtitle"></p> <p id="noResultContainerSubtitle" class="subtitle"></p>
<p><button id="btnNoResultContainerResetFilters" class="btnResetFilters button" tabindex="0"><i class="fas fa-ban"></i>&nbsp;<span></span></button></p> <p><button id="btnNoResultContainerResetFilters" class="btnResetFilters" tabindex="0"><i class="fas fa-ban"></i>&nbsp;<span></span></button></p>
</section> </section>
</div> </div>
</div> </div>
<form id="modalForm" class="modal"> <section id="modalForm" class="modal">
<div class="modal-background"></div> <div class="modal-background"></div>
<div class="modal-content"> <div class="modal-content">
<div class="card"> <div class="card">
<header id="modalTitle" class="card-header-title"></header>
<div class="card-content"> <div class="card-content">
<div class="inputWrapper"> <div class="inputWrapper">
<label id="modalFormInputLabel" for="modalFormInput">Search by todo.txt syntax</label> <label id="modalFormInputLabel" for="modalFormInput"></label>
<input id="modalFormInput" class="input is-medium" type="text" tabindex="0" placeholder="(A) Todo text +project @context due:2020-12-12 rec:d"> <input id="modalFormInput" class="input is-medium" type="text" tabindex="0" placeholder="(A) Todo text +project @context due:2020-12-12 rec:d">
<a href="#" id="modalFormInputResize" class="icon is-right" tabindex="-1" data-input-type="input"><i class="fas fa-expand-alt"></i></a> <a href="#" id="modalFormInputResize" class="icon is-right" tabindex="-1" data-input-type="input"><i class="fas fa-expand-alt"></i></a>
</div> </div>
<div id="autoCompleteContainer" class="card"></div> <section id="autoCompleteContainer" class="card"></section>
<article class="message"> <article class="message">
<div id="modalFormAlert" class="message-body"></div> <div id="modalFormAlert" class="message-body"></div>
</article> </article>
...@@ -342,13 +340,13 @@ ...@@ -342,13 +340,13 @@
</div> </div>
<footer class="card-footer"> <footer class="card-footer">
<button id="btnSave" type="submit" class="card-footer-item" tabindex="0"></button> <button id="btnSave" class="card-footer-item" tabindex="0"></button>
<a href="#" id="btnItemStatus" class="card-footer-item" tabindex="0"></a> <button id="btnItemStatus" class="card-footer-item" tabindex="0"></button>
<a href="#" class="card-footer-item btnModalCancel" tabindex="0"></a> <button class="card-footer-item" role="cancel" tabindex="0"></button>
</footer> </footer>
</div> </div>
</div> </div>
</form> </section>
<div id="modalSettings" class="modal content" tabindex="0"> <div id="modalSettings" class="modal content" tabindex="0">
<div class="modal-background"></div> <div class="modal-background"></div>
...@@ -662,11 +660,11 @@ ...@@ -662,11 +660,11 @@
<div id="filterContext"> <div id="filterContext">
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<input id="filterContextInput" class="input" type="text"> <input id="filterContextInput" class="input" type="text" tabindex="0">
</div> </div>
<footer class="card-footer"> <footer class="card-footer">
<a href="#" id="filterContextSave" class="card-footer-item"></a> <button id="filterContextSave" class="card-footer-item" tabindex="0"></button>
<a href="#" id="filterContextDelete" class="card-footer-item"></a> <button id="filterContextDelete" class="card-footer-item" tabindex="0"></button
</footer> </footer>
</div> </div>
</div> </div>
...@@ -675,16 +673,13 @@ ...@@ -675,16 +673,13 @@
<div class="modal-background"></div> <div class="modal-background"></div>
<div class="modal-content"> <div class="modal-content">
<div class="card"> <div class="card">
<header>
<p id="modalChangeFileTitle" class="card-header-title"></p>
</header>
<div class="card-content"> <div class="card-content">
<table id="modalChangeFileTable"></table> <table id="modalChangeFileTable"></table>
</div> </div>
<footer class="card-footer"> <footer class="card-footer">
<a href="#" id="btnFilesOpenTodoFile" class="card-footer-item" tabindex="0"><i class="fas fa-folder-open"></i>&nbsp;<span id="modalChangeFileOpen"></span></a> <button id="btnFilesOpenTodoFile" class="card-footer-item" tabindex="0"><i class="fas fa-folder-open"></i>&nbsp;<span id="modalChangeFileOpen"></span></button>
<a href="#" id="btnFilesCreateTodoFile" class="card-footer-item" tabindex="0"><i class="fas fa-plus-circle"></i>&nbsp;<span id="modalChangeFileCreate"></span></a> <button id="btnFilesCreateTodoFile" class="card-footer-item" tabindex="0"><i class="fas fa-plus-circle"></i>&nbsp;<span id="modalChangeFileCreate"></span></button>
<a href="#" class="card-footer-item btnModalCancel" tabindex="0"></a> <button class="card-footer-item" role="cancel" tabindex="0"></button>
</footer> </footer>
</div> </div>
</div> </div>
...@@ -696,8 +691,8 @@ ...@@ -696,8 +691,8 @@
<div class="card"> <div class="card">
<div id="modalPromptContent" class="card-content"></div> <div id="modalPromptContent" class="card-content"></div>
<footer class="card-footer"> <footer class="card-footer">
<a href="#" id="modalPromptConfirm" class="card-footer-item" tabindex="0">Confirm</a> <button id="modalPromptConfirm" class="card-footer-item" tabindex="0"></a>
<a href="#" id="modalPromptCancel" class="card-footer-item" tabindex="0">Cancel</a> <button id="modalPromptCancel" role="cancel" class="card-footer-item" tabindex="0"></a>
</footer> </footer>
</div> </div>
</div> </div>
...@@ -708,25 +703,25 @@ ...@@ -708,25 +703,25 @@
<article class="message fixed" data="logging"> <article class="message fixed" data="logging">
<div class="message-header"> <div class="message-header">
<p><span id="messageLoggingTitle"></span></p> <p><span id="messageLoggingTitle"></span></p>
<button class="delete close" aria-label="delete" data-message="logging"></button> <button class="delete close" aria-label="delete" data-message="logging" tabindex="-1"></button>
</div> </div>
<div class="message-body"> <div class="message-body">
<p><span id="messageLoggingBody"></span></p> <p><span id="messageLoggingBody"></span></p>
<p><button id="btnMessageLogging" class="button" tabindex="0"><i class="fas fa-cog"></i>&nbsp;<span id="messageLoggingButton"></span></button></p> <p><button id="btnMessageLogging" tabindex="-1"><i class="fas fa-cog"></i>&nbsp;<span id="messageLoggingButton"></span></button></p>
</div> </div>
</article> </article>
<article class="message fixed" data="share"> <article class="message fixed" data="share">
<div class="message-header"> <div class="message-header">
<p><span id="messageShareTitle"></span></p> <p><span id="messageShareTitle"></span></p>
<button class="delete close" aria-label="delete" data-message="share"></button> <button class="delete close" aria-label="delete" data-message="share" tabindex="-1"></button>
</div> </div>
<div class="message-body"> <div class="message-body">
<p><span id="messageShareBody"></span></p> <p><span id="messageShareBody"></span></p>
<p class="brands"> <p class="brands">
<a href="https://twitter.com/intent/tweet?text=Check%20out%20sleek,%20a%20todo%20app%20based%20on%20todo.txt,%20free%20and%20open-source.%20Available%20for%20Linux,%20Windows%20and%20MacOS.%20https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-twitter"></i></a> <a tabindex="-1" href="https://twitter.com/intent/tweet?text=Check%20out%20sleek,%20a%20todo%20app%20based%20on%20todo.txt,%20free%20and%20open-source.%20Available%20for%20Linux,%20Windows%20and%20MacOS.%20https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-twitter"></i></a>
<a href="https://www.facebook.com/sharer/sharer.php?u=https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-facebook-square"></i></a> <a tabindex="-1" href="https://www.facebook.com/sharer/sharer.php?u=https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-facebook-square"></i></a>
<a href="https://www.linkedin.com/shareArticle?mini=true&url=https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-linkedin"></i></a> <a tabindex="-1" href="https://www.linkedin.com/shareArticle?mini=true&url=https://github.com/ransome1/sleek" target="_blank"><i class="fab fa-linkedin"></i></a>
</p> </p>
</div> </div>
</article> </article>
......
"use strict"; "use strict";
import { resetModal, handleError, userData, setUserData, translations } from "../render.js"; import { resetFilters, resetModal, handleError, userData, setUserData, translations } from "../render.js";
import { _paq } from "./matomo.mjs"; import { _paq } from "./matomo.mjs";
import { createModalJail } from "../configs/modal.config.mjs"; import { createModalJail } from "../configs/modal.config.mjs";
...@@ -22,11 +22,15 @@ function showFiles() { ...@@ -22,11 +22,15 @@ function showFiles() {
let cell3 = row.insertCell(2); let cell3 = row.insertCell(2);
row.setAttribute("data-path", files[file][1]); row.setAttribute("data-path", files[file][1]);
if(files[file][0]===1) { if(files[file][0]===1) {
cell1.innerHTML = "<button class=\"button\" disabled>" + translations.selected + "</button>"; cell1.innerHTML = "<button disabled>" + translations.selected + "</button>";
} else { } else {
cell1.innerHTML = "<button class=\"button is-link\" tabindex=\"0\">" + translations.select + "</button>"; cell1.innerHTML = "<button tabindex=\"0\">" + translations.select + "</button>";
cell1.onclick = function() { cell1.onclick = function() {
setUserData("selectedFilters", []); resetFilters().then(function(response) {
console.info(response);
}).catch(function(error) {
handleError(error);
});
resetModal().then(response => { resetModal().then(response => {
window.api.send("startFileWatcher", this.parentElement.getAttribute("data-path")); window.api.send("startFileWatcher", this.parentElement.getAttribute("data-path"));
console.info(response); console.info(response);
......
This diff is collapsed.
{{
import { addIntervalToDate } from "./recurrences.mjs";
}}
filterQuery
= _ left:orExpr _ { return left; }
/ _ { return []; }
orExpr
= left:andExpr _ OrOp _ right:orExpr { return left.concat(right, ["||"]); }
/ left:andExpr { return left; }
andExpr
= left:notExpr _ AndOp _ right:andExpr { return left.concat(right, ["&&"]); }
/ left:notExpr { return left; }
notExpr
= NotOp _ left:notExpr { return left.concat(["!!"]); }
/ left:boolExpr { return left; }
boolExpr
= left:project { return left; }
/ left:context { return left; }
/ "(" _ left:orExpr _ ")" { return left; }
/ left:comparison { return left; }
/ "complete" { return ["complete"]; }
/ left:StringLiteral { return ["string", left]; }
/ left:RegexLiteral { return ["regex", left]; }
project
= "+" left:name { return ["++", left]; }
/ "+" { return ["++", "*"]; }
context
= "@" left:name { return ["@@", left]; }
/ "@" { return ["@@", "*"]; }
OrOp
= "||"
/ "or"i
AndOp
= "&&"
/ "and"i
NotOp
= "!"
/ "not"i
comparison
= left:priorityComparison { return left; }
/ left:dueComparison { return left; }
priorityComparison
= priorityKeyword _ op:compareOp _ right:priorityLiteral { return ["priority", right, op]; }
/ priorityKeyword { return ["priority"]; }
priorityLiteral
= [A-Z] { return text(); }
priorityKeyword
= "pri" ("o" ("r" ("i" ("t" "y"?)?)?)?)?
dueComparison
= "due" _ op:compareOp _ right:dateExpr { return ["due"].concat(right, [op]); }
/ "due" { return ["due"]; }
dateExpr
= left:dateLiteral _ op:dateOp _ count:number unit:[dbwmy] {
if (op == "-") {
count = count * -1;
}
// we do our date math with the same code as we use for
// recurrence calculations. All dates are returned from
// the parser as millisec since epoch (getTime()) to
// simplify comparisons in the filter lang execution engine.
let d = addIntervalToDate(new Date(left), count, unit);
return d.getTime();
}
/ left:dateLiteral { return left; }
dateOp
= "+" { return text(); }
/ "-" { return text(); }
compareOp
= "==" { return text(); }
/ "!=" { return text(); }
/ ">=" { return text(); }
/ "<=" { return text(); }
/ ">" { return text(); }
/ "<" { return text(); }
dateLiteral
= year:number4 "-" month: number2 "-" day:number2 {
let d = new Date(year, month-1, day);
return d.getTime();
}
/ "today" {
let d = new Date(); // now, w current time of day
d = new Date(d.getFullYear(), d.getMonth(), d.getDate());
return d.getTime();
}
/ "tomorrow" {
let d = new Date(); // now, w current time of day
d = new Date(d.getFullYear(), d.getMonth(), d.getDate());
return d.getTime() + 24*60*60*1000;
}
/ "yesterday" {
let d = new Date(); // now, w current time of day
d = new Date(d.getFullYear(), d.getMonth(), d.getDate());
return d.getTime() - 24*60*60*1000;
}
number4
= [0-9][0-9][0-9][0-9] { return text(); }
number2
= [0-9][0-9] { return text(); }
number
= [0-9]+ { return text(); }
StringLiteral "string"
= '"' chars:DoubleStringCharacter* '"'? {
return chars.join("");
}
/ "'" chars:SingleStringCharacter* "'"? {
return chars.join("");
}
DoubleStringCharacter
= '\\' '"' { return '"'; }
/ !'"' SourceCharacter { return text(); }
SingleStringCharacter
= '\\' "'" { return "'"; }
/ !"'" SourceCharacter { return text(); }
RegexLiteral "regex"
= "/" chars:RegexCharacter* "/" "i" {
return new RegExp(chars.join(""), "i");
}
/ "/" chars:RegexCharacter* "/"? {
return new RegExp(chars.join(""));
}
RegexCharacter
= "\\" "/" { return "/"; }
/ !"/" SourceCharacter { return text(); }
SourceCharacter
= .
name
= '"' nonblank+ '"' { return text(); }
/ nonblank+ '"' { return '"' + text(); }
/ nonblank+ { return text(); }
nonblank
= [^ \t\n\r"()]
_ "whitespace"
= [ \t\n\r]*
// This is a simple stack machine that executes a filter language query
// compiled by filterlang.pegjs (which generates filterlang.mjs).
// The compiled query consists of a list of postfix opcodes designed
// specifically for todo.txt searching and filtering.
function runQuery(item, compiledQuery) {
if (!compiledQuery) {
return true; // a null query matches everything
}
let stack = [];
let operand1 = false;
let operand2 = false;
let next = 0;
let q = compiledQuery.slice(); // shallow copy
while (q.length > 0) {
const opcode = q.shift();
switch(opcode) {
case "priority":
stack.push(item.priority);
break;
case "due":
let d = item.due;
if (d) {
// normalize date to have time of midnight in local zone
// we represent dates as millisec from epoch to simplify comparison
d = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
}
stack.push(d);
break;
case "complete":
stack.push(item.complete);
break;
case "string":
next = q.shift(); // the string value to match
stack.push(item.toString().toLowerCase().indexOf(next.toLowerCase()) !== -1);
break;
case "regex":
next = q.shift(); // the regex to match
stack.push(next.test(item.toString()));
break;
case "==":
operand2 = stack.pop();
operand1 = stack.pop();
stack.push(operand1 == operand2);
break;
case "!=":
operand2 = stack.pop();
operand1 = stack.pop();
stack.push(operand1 != operand2);
break;
case "<":
operand2 = stack.pop();
operand1 = stack.pop();
stack.push(operand1 < operand2);
break;
case "<=":
operand2 = stack.pop();
operand1 = stack.pop();
stack.push(operand1 <= operand2);
break;
case ">":
operand2 = stack.pop();
operand1 = stack.pop();
stack.push(operand1 > operand2);
break;
case ">=":
operand2 = stack.pop();
operand1 = stack.pop();
stack.push(operand1 >= operand2);
break;
case "++":
next = q.shift();
if (next == "*") {
stack.push(item.projects ? true : false);
} else if (next.startsWith('"')) {
stack.push(item.projects && item.projects.includes(next.slice(1,-1)));
} else {
// match for next as a substring of the project name
stack.push(item.projects && item.projects.findIndex(function(p) {
return p.indexOf(next) > -1;
}) > -1);
}
break;
case "@@":
next = q.shift();
if (next == "*") {
stack.push(item.contexts ? true : false);
} else if (next.startsWith('"')) {
stack.push(item.contexts && item.contexts.includes(next.slice(1,-1)));
} else {
// match for next as a substring of the context name
stack.push(item.contexts && item.contexts.findIndex(function(c) {
return c.indexOf(next) > -1;
}) > -1);
}
break;
case "||":
operand2 = stack.pop();
operand1 = stack.pop();
stack.push(operand1 || operand2);
break;
case "&&":
operand2 = stack.pop();
operand1 = stack.pop();
stack.push(operand1 && operand2);
break;
case "!!":
operand1 = stack.pop();
stack.push(!operand1);
break;
default:
// should be a data item like a string or date in millisec, ...
stack.push(opcode);
break;
}
}
return stack.pop();
}
export { runQuery };
"use strict"; "use strict";
import { userData, handleError, translations, setUserData, startBuilding, getConfirmation } from "../render.js"; import { userData, handleError, translations, setUserData, startBuilding, getConfirmation } from "../render.js";
import { createModalJail } from "../configs/modal.config.mjs";
import { _paq } from "./matomo.mjs"; import { _paq } from "./matomo.mjs";
import { items } from "./todos.mjs"; import { items } from "./todos.mjs";
import { isToday, isPast, isFuture } from "./date.mjs"; import { isToday, isPast, isFuture } from "./date.mjs";
import * as filterlang from "./filterlang.mjs";
import { runQuery } from "./filterquery.mjs";
const todoTableSearch = document.getElementById("todoTableSearch"); const todoTableSearch = document.getElementById("todoTableSearch");
const autoCompleteContainer = document.getElementById("autoCompleteContainer"); const autoCompleteContainer = document.getElementById("autoCompleteContainer");
...@@ -17,6 +20,8 @@ let categories, ...@@ -17,6 +20,8 @@ let categories,
filtersCounted,