Commit 623441bd authored by ransome1's avatar ransome1
Browse files

Added empty state for filter categories in drawer, added updated br-pt translations

parent 2523137f
{ {
"name": "sleek", "name": "sleek",
"productName": "sleek", "productName": "sleek",
"version": "1.0.9-rc.1", "version": "1.0.9-rc.2",
"description": "Todo app based on todo.txt for Linux, Windows and MacOS, free and open-source", "description": "Todo app based on todo.txt for Linux, Windows and MacOS, free and open-source",
"synopsis": "Todo app based on todo.txt for Linux, Windows and MacOS, free and open-source", "synopsis": "Todo app based on todo.txt for Linux, Windows and MacOS, free and open-source",
"category": "ProjectManagement", "category": "ProjectManagement",
......
...@@ -1418,28 +1418,31 @@ body.compact #autoCompleteContainer h4 { ...@@ -1418,28 +1418,31 @@ body.compact #autoCompleteContainer h4 {
#drawerContainer .drawer button.is-greyed-out .tag { #drawerContainer .drawer button.is-greyed-out .tag {
display: none; display: none;
} }
#drawerContainer .drawer h4.is-4 { #drawerContainer .drawer section {
width: 100%;
padding: 0;
margin: 0 0 1.5em 0;
}
#drawerContainer .drawer section h4.is-4 {
font-size: 1.25em; font-size: 1.25em;
font-family: FreeSansBold; font-family: FreeSansBold;
margin-bottom: 0em; margin: 0 0 0.75em 0;
} }
#drawerContainer .drawer h4.is-4.clickable { #drawerContainer .drawer section h4.is-4.clickable {
cursor: pointer; cursor: pointer;
display: inline; display: inline;
} }
#drawerContainer .drawer h4.is-4.clickable i { #drawerContainer .drawer section h4.is-4.clickable i {
color: #3273dc; color: #3273dc;
} }
#drawerContainer .drawer h4.is-4.clickable::after { #drawerContainer .drawer section h4.is-4.clickable::after {
height: 1em; height: 1em;
display: block; display: block;
content: "\a"; content: "\a";
white-space: pre; white-space: pre;
} }
#drawerContainer .drawer section { #drawerContainer .drawer section .todoFilterHint {
width: 100%; cursor: pointer;
padding: 0;
margin: 0 0 1.5em 0;
} }
#drawerContainer .drawer table tr td:nth-child(odd) { #drawerContainer .drawer table tr td:nth-child(odd) {
width: auto; width: auto;
......
This diff is collapsed.
...@@ -3,6 +3,7 @@ import { userData, handleError, translations, setUserData, startBuilding, getCon ...@@ -3,6 +3,7 @@ import { userData, handleError, translations, setUserData, startBuilding, getCon
import { createModalJail } from "../configs/modal.config.mjs"; 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 { showContent } from "./content.mjs";
import { isToday, isPast, isFuture } from "./date.mjs"; import { isToday, isPast, isFuture } from "./date.mjs";
import * as filterlang from "./filterlang.mjs"; import * as filterlang from "./filterlang.mjs";
import { runQuery } from "./filterquery.mjs"; import { runQuery } from "./filterquery.mjs";
...@@ -169,6 +170,83 @@ function filterItems(items) { ...@@ -169,6 +170,83 @@ function filterItems(items) {
return Promise.reject(error); return Promise.reject(error);
} }
} }
function generateCategoryContainer(category, autoCompletePrefix, filterFragment) {
try {
let hideFilterCategories = userData.hideFilterCategories;
selectedFilters = new Array;
if(userData.selectedFilters && userData.selectedFilters.length>0) selectedFilters = JSON.parse(userData.selectedFilters);
// creates a div for the specific filter section
let todoFiltersContainer = document.createElement("section");
todoFiltersContainer.setAttribute("class", category);
// translate headline
if(category=="contexts") {
headline = translations.contexts;
} else if(category=="projects"){
headline = translations.projects;
} else if(category=="priority"){
headline = translations.priority;
}
// if filters are available and if container is not the autocomplete one
let todoFilterHeadline = document.createElement("h4");
// show suggestion box when prefix is present
if(autoCompletePrefix!==undefined) {
autoCompleteContainer.classList.add("is-active");
autoCompleteContainer.focus();
todoFilterHeadline.innerHTML = headline;
} else {
todoFilterHeadline.setAttribute("class", "is-4 clickable");
// setup greyed out state
if(hideFilterCategories.includes(category)) {
todoFilterHeadline.innerHTML = "<i class=\"far fa-eye\" tabindex=\"-1\"></i>&nbsp;" + headline;
todoFilterHeadline.classList.add("is-greyed-out");
} else {
todoFilterHeadline.innerHTML = "<i class=\"far fa-eye-slash\" tabindex=\"-1\"></i>&nbsp;" + headline;
todoFilterHeadline.classList.remove("is-greyed-out");
}
// add click event
todoFilterHeadline.onclick = function() {
document.getElementById("todoTableWrapper").scrollTo(0,0);
if(hideFilterCategories.includes(category)) {
hideFilterCategories.splice(hideFilterCategories.indexOf(category),1)
} else {
hideFilterCategories.push(category);
hideFilterCategories = [...new Set(hideFilterCategories.join(",").split(","))];
}
setUserData("hideFilterCategories", hideFilterCategories)
startBuilding();
}
}
// add the headline before category container
todoFiltersContainer.appendChild(todoFilterHeadline);
// add filter fragment
if(filterFragment.childElementCount > 0) {
todoFiltersContainer.appendChild(filterFragment);
// if no filter fragment is available a empty filter container will be shown
} else {
let todoFilterHint = document.createElement("div");
todoFilterHint.setAttribute("class", "todoFilterHint");
todoFilterHint.innerHTML = "<i class=\"fas fa-question-circle\"></i> No " + category + " available. Learn how to add one.";
todoFilterHint.onclick = function() {
showContent("modalHelp");
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Drawer", "Click on Help"]);
}
todoFiltersContainer.appendChild(todoFilterHint);
}
// add filter fragment if it is available
if(filterFragment) {
todoFiltersContainer.appendChild(filterFragment);
}
// return the container
return Promise.resolve(todoFiltersContainer);
} catch (error) {
error.functionName = generateCategoryContainer.name;
return Promise.reject(error);
}
}
function generateFilterData(autoCompleteCategory, autoCompleteValue, autoCompletePrefix, caretPosition) { function generateFilterData(autoCompleteCategory, autoCompleteValue, autoCompletePrefix, caretPosition) {
try { try {
// reset filter counter // reset filter counter
...@@ -191,11 +269,10 @@ function generateFilterData(autoCompleteCategory, autoCompleteValue, autoComplet ...@@ -191,11 +269,10 @@ function generateFilterData(autoCompleteCategory, autoCompleteValue, autoComplet
// needs to be reset every run, because it can be overwritten by previous autocomplete // needs to be reset every run, because it can be overwritten by previous autocomplete
categories = ["priority", "contexts", "projects"]; categories = ["priority", "contexts", "projects"];
} }
categories.forEach((category) => {
// TODO build empty container shells here let todoFiltersContainer;
//console.log(category);
categories.forEach(async (category) => {
// array to collect all the available filters in the data // array to collect all the available filters in the data
let filters = new Array(); let filters = new Array();
let filterArray; let filterArray;
...@@ -281,26 +358,29 @@ function generateFilterData(autoCompleteCategory, autoCompleteValue, autoComplet ...@@ -281,26 +358,29 @@ function generateFilterData(autoCompleteCategory, autoCompleteValue, autoComplet
} else if(!filter[1] && !(filter[0] in filters)) { } else if(!filter[1] && !(filter[0] in filters)) {
filters[filter[0]] = 0; filters[filter[0]] = 0;
} }
if(filters!=null) { if(filters!==null) {
return filters; return filters;
} }
}, {}); }, {});
// build the filter buttons // TODO can this be done above already?
if(filters[0]!="" && filters.length>0) { // remove empty filter entries
// add category length to total filter count filters = filters.filter(function(filter) {
generateFilterButtons(category, autoCompleteValue, autoCompletePrefix, caretPosition).then(response => { //console.log(filter[0]);
if(userData.hideFilterCategories.includes(category)) { if(filter[0]) return filter;
response.classList.add("is-greyed-out"); });
} // build filter buttons and add them to a fragment
container.appendChild(response); let filterFragment = await generateFilterButtons(category, autoCompleteValue, autoCompletePrefix, caretPosition).then(response => {
}).catch (error => { return response;
handleError(error); }).catch (error => {
}); handleError(error);
} else { });
autoCompleteContainer.classList.remove("is-active"); // build and configure the category container and finally append the fragments
autoCompleteContainer.blur(); todoFiltersContainer = await generateCategoryContainer(category, autoCompletePrefix, filterFragment).then(response => {
console.log("Info: No " + category + " found in todo.txt data, so no filters will be generated"); return response;
} }).catch (error => {
handleError(error);
});
container.appendChild(todoFiltersContainer);
}); });
return Promise.resolve("Success: Filter data generated"); return Promise.resolve("Success: Filter data generated");
} catch (error) { } catch (error) {
...@@ -330,63 +410,8 @@ function selectFilter(filter, category) { ...@@ -330,63 +410,8 @@ function selectFilter(filter, category) {
} }
function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix, caretPosition) { function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix, caretPosition) {
try { try {
let hideFilterCategories = userData.hideFilterCategories; // create a fragment to collect the filters in
selectedFilters = new Array; let filterFragment = document.createDocumentFragment();
if(userData.selectedFilters && userData.selectedFilters.length>0) selectedFilters = JSON.parse(userData.selectedFilters);
// creates a div for the specific filter section
let todoFiltersContainer = document.createElement("section");
todoFiltersContainer.setAttribute("class", category);
// translate headline
if(category=="contexts") {
headline = translations.contexts;
} else if(category=="projects"){
headline = translations.projects;
} else if(category=="priority"){
headline = translations.priority;
}
if(autoCompletePrefix===undefined && userData.showEmptyFilters) {
// create a sub headline element
let todoFilterHeadline = document.createElement("h4");
todoFilterHeadline.setAttribute("class", "is-4 clickable");
// setup greyed out state
if(hideFilterCategories.includes(category)) {
todoFilterHeadline.innerHTML = "<i class=\"far fa-eye\" tabindex=\"-1\"></i>&nbsp;" + headline;
todoFilterHeadline.classList.add("is-greyed-out");
} else {
todoFilterHeadline.innerHTML = "<i class=\"far fa-eye-slash\" tabindex=\"-1\"></i>&nbsp;" + headline;
todoFilterHeadline.classList.remove("is-greyed-out");
}
// add click event
todoFilterHeadline.onclick = function() {
document.getElementById("todoTableWrapper").scrollTo(0,0);
if(hideFilterCategories.includes(category)) {
hideFilterCategories.splice(hideFilterCategories.indexOf(category),1)
} else {
hideFilterCategories.push(category);
hideFilterCategories = [...new Set(hideFilterCategories.join(",").split(","))];
}
setUserData("hideFilterCategories", hideFilterCategories)
startBuilding();
}
// add the headline before category container
todoFiltersContainer.appendChild(todoFilterHeadline);
} else {
let todoFilterHeadline = document.createElement("h4");
// show suggestion box when prefix is present
if(autoCompletePrefix!==undefined) {
autoCompleteContainer.classList.add("is-active");
autoCompleteContainer.focus();
}
todoFilterHeadline.setAttribute("tabindex", -1);
// create a sub headline element
todoFilterHeadline.setAttribute("class", "is-4");
// no need for tab index if the headline is in suggestion box
//if(autoCompletePrefix==undefined)
todoFilterHeadline.innerHTML = headline;
// add the headline before category container
todoFiltersContainer.appendChild(todoFilterHeadline);
}
// to figure out how many buttons with filters behind them have been build in the end
// build one button each // build one button each
for (let filter in filtersCounted) { for (let filter in filtersCounted) {
// skip this loop if no filters are present // skip this loop if no filters are present
...@@ -406,7 +431,6 @@ function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix, ...@@ -406,7 +431,6 @@ function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix,
todoFiltersItem.addEventListener("contextmenu", event => { todoFiltersItem.addEventListener("contextmenu", event => {
// jail the modal // jail the modal
createModalJail(filterContext); createModalJail(filterContext);
filterContext.style.left = event.x + "px"; filterContext.style.left = event.x + "px";
filterContext.style.top = event.y + "px"; filterContext.style.top = event.y + "px";
filterContext.classList.add("is-active"); filterContext.classList.add("is-active");
...@@ -485,9 +509,9 @@ function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix, ...@@ -485,9 +509,9 @@ function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix,
}); });
} }
filterCounter++; filterCounter++;
todoFiltersContainer.appendChild(todoFiltersItem); filterFragment.appendChild(todoFiltersItem);
} }
return Promise.resolve(todoFiltersContainer); return Promise.resolve(filterFragment);
} catch (error) { } catch (error) {
error.functionName = generateFilterButtons.name; error.functionName = generateFilterButtons.name;
return Promise.reject(error); return Promise.reject(error);
......
...@@ -143,18 +143,18 @@ function configureMainView() { ...@@ -143,18 +143,18 @@ function configureMainView() {
// check if archive button should be enabled // check if archive button should be enabled
//setButtonState("btnArchiveTodos"); //setButtonState("btnArchiveTodos");
// configure navigation // configure navigation
if(filters.filterCounter===0) { // if(filters.filterCounter===0) {
// hide filter nav button // // hide filter nav button
navBtnFilter.classList.add("is-hidden"); // navBtnFilter.classList.add("is-hidden");
// close filter drawer // // close filter drawer
drawer.show(navBtnFilter, document.getElementById(navBtnFilter.getAttribute("data-drawer")), true).then(function(result) { // drawer.show(navBtnFilter, document.getElementById(navBtnFilter.getAttribute("data-drawer")), true).then(function(result) {
console.log(result); // console.log(result);
}).catch(function(error) { // }).catch(function(error) {
handleError(error); // handleError(error);
}); // });
} else { // } else {
navBtnFilter.classList.remove("is-hidden"); // navBtnFilter.classList.remove("is-hidden");
} // }
// configure table view // configure table view
if(userData.file && todos.items.objects.length===0) { if(userData.file && todos.items.objects.length===0) {
addTodoContainer.classList.add("is-active"); addTodoContainer.classList.add("is-active");
......
...@@ -120,28 +120,31 @@ ...@@ -120,28 +120,31 @@
display: none; display: none;
} }
} }
h4.is-4 {
font-size: 1.25em;
font-family: FreeSansBold;
margin-bottom: 0em;
}
h4.is-4.clickable {
cursor: pointer;
display: inline;
i {
color: $has-text-link;
}
}
h4.is-4.clickable::after {
height: 1em;
display: block;
content: '\A';
white-space: pre;
}
section { section {
width: 100%; width: 100%;
padding: 0; padding: 0;
margin: 0 0 1.5em 0; margin: 0 0 1.5em 0;
h4.is-4 {
font-size: 1.25em;
font-family: FreeSansBold;
margin: 0 0 0.75em 0;
}
h4.is-4.clickable {
cursor: pointer;
display: inline;
i {
color: $has-text-link;
}
}
h4.is-4.clickable::after {
height: 1em;
display: block;
content: '\A';
white-space: pre;
}
.todoFilterHint {
cursor: pointer;
}
} }
table tr td:nth-child(odd) { table tr td:nth-child(odd) {
width: auto; width: auto;
......
...@@ -194,9 +194,6 @@ ...@@ -194,9 +194,6 @@
button { button {
margin: 0 .5rem .5rem 0; margin: 0 .5rem .5rem 0;
} }
// button:focus-visible {
// background: white!important;
// }
} }
section::-webkit-scrollbar { section::-webkit-scrollbar {
background-color: transparent; background-color: transparent;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment