Commit 3eea20d2 authored by ransome1's avatar ransome1
Browse files

CSS optimization, single filter results will be added automatically

parent 7a2342e6
# Privacy Policy for sleek
This document contains types of information that is collected by sleek and how I as it's developer use it.
This document contains the types of information that is collected by sleek and how I as its developer use it.
I myself am very sensible about my own privacy and in these days of massive and needless collection of personal data, I want sleek to be different. I am not interested in who sleek's users are and will therefor not gather sensitive data.
I myself am very sensible about my own privacy and in these days of massive and needless collection of personal data, I want sleek to be different. I am not interested in who sleek's users are and will therefore not gather any sensitive data.
However I want to know how many users are actively using sleek and, in case a user explicitly agrees to it, how sleek is being used. The app communicates with a Matomo instance I host myself. The data is exclusively sent via a secure SSL-encrypted connection. sleek follows a standard procedure of logging. The information collected by Matomo include only masked internet protocol (IP) addresses, operating system, screen resolution, date and time stamp as well as the user's basic app settings. Also a non personalized random user id is being generated. Like this I can see how many unique sleek users are out there without collecting sensitive data.
However, I want to know how many users are actively using sleek and, in case a user explicitly agrees to it, how sleek is being used. The app communicates with a Matomo instance I host myself. The data is exclusively sent via a secure SSL-encrypted connection. sleek follows a standard procedure of logging. The information collected by Matomo includes only masked internet protocol (IP) addresses, operating system, screen resolution, date and time stamp as well as the user's basic app settings. Also a non-personalized random user id is generated. This way, I can see how many unique sleek users are out there without collecting sensitive data.
## Default logging
Once sleek is opened, it will announce to the Matomo instance that it has been started. This happens one time per app session and has the purpose of telling me how many users are using sleek and where these users are roughly located. With this information I can for instance decide which language should be added next and so forth.
......
......@@ -212,14 +212,22 @@ body.dark #todoTable .todo .cell.itemDueDate.isPast i {
body.dark #todoTable .todo .cell.itemDueDate.isTomorrow i {
color: #fa745e !important;
}
body.dark #todoTable .todo .cell span.contexts {
body.dark #todoTable .todo .cell a.contexts {
color: #c5ede3 !important;
background: #1e6251 !important;
}
body.dark #todoTable .todo .cell span.projects {
body.dark #todoTable .todo .cell a.contexts.is-dark {
background: #123b31 !important;
color: white;
}
body.dark #todoTable .todo .cell a.projects {
color: #f1d6f1 !important;
background: #6f266f !important;
}
body.dark #todoTable .todo .cell a.projects.is-dark {
background: #491949 !important;
color: white;
}
body.dark #todoTable .todo .cell .is-white {
color: #CCCDCF;
background: none;
......@@ -338,12 +346,12 @@ body.dark .contexts button {
background: #247561;
}
body.dark .contexts button span.tag {
color: #184e41 !important;
color: #123b31 !important;
background: #c9eee5;
}
body.dark .contexts button.is-dark,
body.dark .contexts button:focus-visible {
background: #184e41 !important;
background: #123b31 !important;
color: white;
}
body.dark .projects button {
......@@ -351,12 +359,12 @@ body.dark .projects button {
background: #822c82;
}
body.dark .projects button span.tag {
color: #5c1f5c !important;
color: #491949 !important;
background: #f2daf2;
}
body.dark .projects button.is-dark,
body.dark .projects button:focus-visible {
background: #5c1f5c !important;
background: #491949 !important;
color: white;
}
body.dark .priority button:not(.A):not(.B):not(.C) {
......@@ -2002,14 +2010,20 @@ body.compact #autoCompleteContainer h4 {
}
#todoTable .cell a.tag {
text-decoration: none;
margin: 0 0.25em 0 0;
margin: 0;
}
#todoTable .cell a.tag.projects {
background: #f1d6f1;
}
#todoTable .cell a.tag.projects.is-dark {
background: #5c1f5c !important;
}
#todoTable .cell a.tag.contexts {
background: #c5ede3;
}
#todoTable .cell a.tag.contexts.is-dark {
background: #184e41 !important;
}
#todoTable .cell.categories .tag {
margin-left: 0.25em;
}
......@@ -2022,7 +2036,6 @@ body.compact #autoCompleteContainer h4 {
}
#todoTable a.cell.text {
width: auto;
flex: 1;
cursor: pointer;
color: #5a5a5a !important;
}
......
This diff is collapsed.
......@@ -3,6 +3,7 @@ import { userData, handleError, translations, setUserData, startBuilding, getCon
import { createModalJail } from "../configs/modal.config.mjs";
import { _paq } from "./matomo.mjs";
import { items } from "./todos.mjs";
import { getCaretPosition } from "./form.mjs";
import { showContent } from "./content.mjs";
import { isToday, isPast, isFuture } from "./date.mjs";
import * as filterlang from "./filterlang.mjs";
......@@ -33,6 +34,14 @@ filterContextInput.addEventListener("keydown", (event) => {
if(event.code==="Space") event.preventDefault();
})
autoCompleteContainer.addEventListener("keyup", (event) => {
// if there is only one filter shown it will be selected automatically
if(event.code==="Tab" && Object.keys(filtersCounted).length === 1) {
addFilterToInput(Object.keys(filtersCounted)[0], event.target.getAttribute("data-prefix"));
}
})
function saveFilter(newFilter, oldFilter, category) {
try {
items.objects.forEach((item) => {
......@@ -82,6 +91,7 @@ function deleteFilter(filter, category) {
}
function filterItems(items) {
try {
// TODO: this is a duplicate in todos.mjs
// selected filters are empty, unless they were persisted
if(userData.selectedFilters && userData.selectedFilters.length>0) {
selectedFilters = JSON.parse(userData.selectedFilters);
......@@ -372,7 +382,7 @@ function generateFilterData(autoCompleteCategory, autoCompleteValue, autoComplet
return;
}
// build filter buttons and add them to a fragment
let filterFragment = await generateFilterButtons(category, autoCompleteValue, autoCompletePrefix, caretPosition).then(response => {
let filterFragment = await generateFilterButtons(category, autoCompletePrefix).then(response => {
return response;
}).catch (error => {
handleError(error);
......@@ -411,8 +421,37 @@ function selectFilter(filter, category) {
setUserData("selectedFilters", JSON.stringify(selectedFilters));
startBuilding();
}
function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix, caretPosition) {
function addFilterToInput(filter, autoCompletePrefix) {
let modalFormInput = document.getElementById("modalFormInput");
let caretPosition = getCaretPosition(modalFormInput);
// split string into elements
let inputElements = modalFormInput.value.split(" ");
let i;
let x = 0;
for(i = 0; i < inputElements.length; i++) {
x += inputElements[i].length + 1;
// once caret position is found inside element the index is persisted
if(x > caretPosition) break;
}
inputElements.splice(i, 1, autoCompletePrefix + filter + " ");
modalFormInput.value = inputElements.join(" ");
// empty autoCompleteValue to prevent multiple inputs using multiple Enter presses
autoCompletePrefix = null;
// hide the suggestion container after the filter has been selected
autoCompleteContainer.blur();
autoCompleteContainer.classList.remove("is-active");
// put focus back into input so user can continue writing
modalFormInput.focus();
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Suggestion-box", "Click on filter tag", category]);
}
function generateFilterButtons(category, autoCompletePrefix) {
try {
let caretPosition = getCaretPosition(document.getElementById("modalFormInput"));
// create a fragment to collect the filters in
let filterFragment = document.createDocumentFragment();
// build one button each
......@@ -423,6 +462,7 @@ function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix,
if(category==="priority") todoFiltersItem.classList.add(filter);
todoFiltersItem.setAttribute("data-filter", filter);
todoFiltersItem.setAttribute("data-category", category);
todoFiltersItem.setAttribute("data-prefix", autoCompletePrefix);
if(autoCompletePrefix===undefined) { todoFiltersItem.setAttribute("tabindex", 0) } else { todoFiltersItem.setAttribute("tabindex", 0) }
todoFiltersItem.innerHTML = filter;
if(autoCompletePrefix==undefined) {
......@@ -486,33 +526,7 @@ function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix,
} else {
// add filter to input
todoFiltersItem.addEventListener("click", (event) => {
if(autoCompletePrefix && autoCompleteValue) {
// split string into elements
let inputElements = document.getElementById("modalFormInput").value.split(" ");
let i;
let x = 0;
for(i = 0; i < inputElements.length; i++) {
x += inputElements[i].length + 1;
// once caret position is found inside element the index is persisted
if(x > caretPosition) break;
}
// replace value at index with prefix and data attribute of filter
inputElements.splice(i, 1, autoCompletePrefix + todoFiltersItem.getAttribute("data-filter"));
document.getElementById("modalFormInput").value = inputElements.join(" ");
} else if(autoCompletePrefix) {
// add button data value to the exact caret position
document.getElementById("modalFormInput").value = [document.getElementById("modalFormInput").value.slice(0, caretPosition), todoFiltersItem.getAttribute('data-filter'), document.getElementById("modalFormInput").value.slice(caretPosition)].join('') + " ";
}
// empty autoCompleteValue to prevent multiple inputs using multiple Enter presses
autoCompleteValue = null;
autoCompletePrefix = null;
// hide the suggestion container after the filter has been selected
autoCompleteContainer.blur();
autoCompleteContainer.classList.remove("is-active");
// put focus back into input so user can continue writing
document.getElementById("modalFormInput").focus();
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Suggestion-box", "Click on filter tag", category]);
addFilterToInput(todoFiltersItem.getAttribute("data-filter"), autoCompletePrefix);
});
}
filterCounter++;
......
......@@ -510,4 +510,4 @@ window.onresize = function() {
}
}
export { show, resizeInput, setPriority, setDueDate, submitForm, toggleInputSize};
export { show, resizeInput, setPriority, setDueDate, submitForm, toggleInputSize, getCaretPosition};
......@@ -350,15 +350,25 @@ function generateTableRow(todo) {
todoTableBodyRow.appendChild(todoTableBodyCellText);
// cell for the categories
categories.forEach(category => {
if(todo[category] && category!="priority") {
todo[category].forEach(element => {
let todoTableBodyCellCategory = document.createElement("a");
todoTableBodyCellCategory.setAttribute("class", "tag " + category);
todoTableBodyCellCategory.onclick = function() {
console.log(element);
selectFilter(element, category);
}
todoTableBodyCellCategory.innerHTML = element;
// selected filters are empty, unless they were persisted
if(userData.selectedFilters && userData.selectedFilters.length>0) {
let selectedFilters = JSON.parse(userData.selectedFilters);
selectedFilters.forEach(function(item) {
if(JSON.stringify(item) === '["'+element+'","'+category+'"]') todoTableBodyCellCategory.classList.toggle("is-dark")
});
}
tableContainerCategories.appendChild(todoTableBodyCellCategory);
});
}
......
......@@ -236,14 +236,22 @@ body.dark {
}
}
.cell {
span.contexts {
a.contexts {
color: $sleek-contexts-button!important;
background: darken($sleek-contexts-button, 60%)!important;
}
span.projects {
a.contexts.is-dark {
background: darken($sleek-contexts-button, 70%)!important;
color: white;
}
a.projects {
color: $sleek-projects-button!important;
background: darken($sleek-projects-button, 60%)!important;
}
a.projects.is-dark {
background: darken($sleek-projects-button, 70%)!important;
color: white;
}
.is-white {
color: $lighter-grey;
background: none;
......@@ -379,13 +387,13 @@ body.dark {
color: $sleek-contexts-button;
background: darken($sleek-contexts-button, 55%);
span.tag {
color: darken($sleek-contexts-button, 65%)!important;
color: darken($sleek-contexts-button, 70%)!important;
background: lighten($sleek-contexts-button, 1%);
}
}
button.is-dark,
button:focus-visible {
background: darken($sleek-contexts-button, 65%)!important;
background: darken($sleek-contexts-button, 70%)!important;
color: white;
}
}
......@@ -394,13 +402,13 @@ body.dark {
color: $sleek-projects-button;
background: darken($sleek-projects-button, 55%);
span.tag {
color: darken($sleek-projects-button, 65%)!important;
color: darken($sleek-projects-button, 70%)!important;
background: lighten($sleek-projects-button, 1%);
}
}
button.is-dark,
button:focus-visible {
background: darken($sleek-projects-button, 65%)!important;
background: darken($sleek-projects-button, 70%)!important;
color: white;
}
}
......
......@@ -131,14 +131,22 @@
height: auto;
a.tag {
text-decoration: none;
margin: 0 0.25em 0 0;
margin: 0;
}
a.tag.projects {
background: $sleek-projects-button;
}
a.tag.projects.is-dark {
background: darken($sleek-projects-button, 65%)!important;
}
a.tag.contexts {
background: $sleek-contexts-button;
}
a.tag.contexts.is-dark {
background: darken($sleek-contexts-button, 65%)!important;
}
}
.cell.categories {
.tag {
......@@ -158,7 +166,7 @@
}
a.cell.text {
width: auto;
flex: 1;
//flex: 1;
cursor: pointer;
color: $dark-grey!important;
button {
......
{"theme":"light","width":1538,"height":863,"horizontal":145,"vertical":577,"maximizeWindow":false,"notifications":true,"useTextarea":false,"compactView":false,"matomoEvents":false,"drawerWidth":"500","showDueIsPast":true,"showDueIsFuture":true,"showDueIsToday":true,"showHidden":false,"showCompleted":true,"sortCompletedLast":false,"sortBy":["priority","dueString","contexts","projects"],"zoom":"100","tray":false,"showEmptyFilters":true,"dismissedNotifications":[-1319247018],"dismissedMessages":[],"hideFilterCategories":[],"language":"en","uid":"TESTING","path":"test/preferences_empty/todo.txt","files":[[1,"test/preferences_empty/todo.txt"]],"file":"test/preferences_empty/todo.txt","filterDrawer":false,"selectedFilters":[],"viewDrawer":false,"sortByLevel":["priority","dueString","contexts","projects"],"deferredTodos":true,"fileTabs":true}
\ No newline at end of file
{"theme":"light","width":1538,"height":863,"horizontal":145,"vertical":577,"maximizeWindow":false,"notifications":true,"useTextarea":false,"compactView":false,"matomoEvents":false,"drawerWidth":"500","showDueIsPast":true,"showDueIsFuture":true,"showDueIsToday":true,"showHidden":false,"showCompleted":true,"sortCompletedLast":false,"sortBy":["priority","dueString","contexts","projects"],"zoom":"100","tray":false,"showEmptyFilters":true,"dismissedNotifications":[-1319247018],"dismissedMessages":[],"hideFilterCategories":[],"language":"en","uid":"TESTING","path":"test/preferences_empty/todo.txt","files":[[1,"test/preferences_empty/todo.txt"]],"file":"test/preferences_empty/todo.txt","filterDrawer":false,"selectedFilters":[],"viewDrawer":false,"sortByLevel":["priority","dueString","contexts","projects"],"deferredTodos":true,"fileTabs":true}
{"theme":"light","width":1100,"height":700,"horizontal":129,"vertical":670,"maximizeWindow":false,"notifications":true,"useTextarea":false,"compactView":false,"matomoEvents":false,"drawerWidth":"500","showDueIsPast":true,"showDueIsFuture":true,"showDueIsToday":true,"showHidden":false,"showCompleted":true,"sortCompletedLast":false,"sortBy":["priority","dueString","contexts","projects"],"zoom":"100","tray":false,"showEmptyFilters":true,"hideFilterCategories":[],"language":"en","dismissedNotifications":[],"dismissedMessages":[],"sortByLevel":["priority","dueString","contexts","projects"],"deferredTodos":true,"fileTabs":true}
\ No newline at end of file
{"theme":"light","width":1100,"height":700,"horizontal":129,"vertical":525,"maximizeWindow":false,"notifications":true,"useTextarea":false,"compactView":false,"matomoEvents":false,"drawerWidth":"500","showDueIsPast":true,"showDueIsFuture":true,"showDueIsToday":true,"showHidden":false,"showCompleted":true,"sortCompletedLast":false,"sortBy":["priority","dueString","contexts","projects"],"zoom":"100","tray":false,"showEmptyFilters":true,"hideFilterCategories":[],"language":"en","dismissedNotifications":[],"dismissedMessages":[],"sortByLevel":["priority","dueString","contexts","projects"],"deferredTodos":true,"fileTabs":true}
\ No newline at end of file
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