Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ransome
sleek
Commits
e056c464
Commit
e056c464
authored
May 27, 2021
by
ransome1
Browse files
WIP: Filters can be bulk changed/deleted, empty filters won't disappear any longer
parent
ed867889
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
e056c464
...
...
@@ -126,3 +126,4 @@ A prioritized backlog of new features and known issues can be found <a href="htt
-
vanillajs-datepicker: https://github.com/mymth/vanillajs-datepicker
-
i18next: https://github.com/i18next/i18next
-
Matomo: https://github.com/matomo-org/matomo
-
chokidar: https://github.com/paulmillr/chokidar
package.json
View file @
e056c464
{
"name"
:
"sleek"
,
"productName"
:
"sleek"
,
"version"
:
"1.0.
4
-1"
,
"version"
:
"1.0.
5
-1"
,
"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"
,
"category"
:
"ProjectManagement"
,
...
...
src/css/dark.css
View file @
e056c464
...
...
@@ -265,6 +265,17 @@ nav ul li.is-highlighted a {
background
:
#212224
!important
;
}
#filterMenu
.card
{
background
:
#3B3B3B
;
}
#filterMenu
.card
#filterMenuSave
{
background-color
:
transparent
!important
;
border-right
:
1px
solid
#212224
!important
;
}
#filterMenu
.card-footer
{
border-top
:
1px
solid
#212224
!important
;
}
.contexts
.button
{
color
:
#c5ede3
;
background
:
#247561
;
...
...
src/css/dark.css.map
View file @
e056c464
{"version":3,"sourceRoot":"","sources":["../scss/dark.scss","../scss/variables.scss"],"names":[],"mappings":"AAGA;EACE,kBCOa;EDNb;;;AAEF;EACE;;;AAEF;AAAA;EAEE;;;AAEF;AAAA;AAAA;EAGE,OCZa;;;ADcf;AAAA;AAAA;EAGE;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAOE;EACA;;;AAEF;EACE;;;AAEF;AAAA;EAEE;EACA;;;AAEF;EACE;;;AAEF;AAAA;EAEE;;AACA;AAAA;EACE;;;AAGJ;AAAA;EAEE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE,kBC3EY;;AD4EZ;EACE,OCjFW;;ADoFX;EACE;;AAGA;EACE,OCzFO;ED0FP;;AAEF;AAAA;EAEE,OC9FO;ED+FP;EACA,kBC3FW;;AD8Ff;EACE,OCpGS;EDqGT;EACA,kBCjGa;;;ADuGf;EACE;;AAEF;EACE;;;AAIN;EACE,kBC/Ga;;ADgHb;EACE;;;AAIF;EACE;EACA;;;AAIF;EACE,kBC7He;;AD+HjB;EACE,OCrIW;;ADuIb;EACE;;AAGA;EACE,OC7IS;;ADgJb;EACE,cC3Ie;;AD4If;EACE,OClJS;;ADoJX;EACE;;AAEF;EACE,OCxJS;;AD0JX;EACE;;AACA;EACE,OCxJW;;AD2Jf;AAAA;EAEE,OC1JY;;AD2JZ;AAAA;EACE;;AAIF;EACE;;AAIF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE,OCtLO;EDuLP;;AAGJ;EACE,OC3LS;;AD6LX;EACE,YCzLa;ED0Lb;;AAEF;EACE,YC9LQ;;;ADmMZ;EACE;EACA;EACA;;AAEF;EACE;;AAGA;AAAA;AAAA;AAAA;EAIE;;AAEF;EACE,YClNa;;;ADuNjB;AAAA;EAEE;EACA;EACA;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE,YCrOU;;ADsOV;EACE,cCrOS;;;ADyOf;EACE,YC3OiB;;AD4OjB;EACE,OClPW;;;ADsPb;EACE;;AACA;EACE;;AAIJ;EACE;;AAEF;EACE;;AAEF;EACE;;;AAKF;EACE,OC7PoB;ED8PpB;;AACA;EACE;EACA;;AAGJ;EACE;EACA;;;AAIF;EACE,OC1QoB;ED2QpB;;AACA;EACE;EACA;;AAGJ;EACE;EACA;;;AAIF;EACE;;;AAKA;EACE,kBCzSM;;AD2SR;EACE;;AAEF;EACE;;AAEF;EACE;;;AAMF;EACE,YCvTa;EDwTb,OC7TS;;AD8TT;EACE;;AAEF;AACE;AAAA;AAAA;;AAIF;AAAA;EAEE,cCpUM;;;ADyUd;EACE;;AACA;EACE;;AAEF;EACE;;AAEF;AAAA;AAAA;EAGE;EACA;;AAEF;EACE;;AAEF;AAAA;EAEE;EACA;;AAEF;AAAA;EAEE,YChWe;EDiWf;;AAEF;AAAA;EAEE;;AAEF;AAAA;AAAA;EAGE;;AAEF;EACE;;AAEF;EACE;EACA,cCnXQ;;ADqXV;EACE,cCzXW;;AD2Xb;EACE;EACA,cC7XW;;;ADgYf;EACE;;AACA;EACE,OCnYW;EDoYX;;AACA;EACE;;;AAKJ;AAAA;AAAA;EAGE;EACA;EACA;;;AAGJ;EACE;;AACA;EACE;;AAEF;AAAA;EAEE;;AAEF;AAAA;EAEE;;AAEF;EACE,YC7ZU;ED8ZV;;AACA;AAAA;AAAA;EAGE;EACA;;AAEF;EACE;;AAEF;AAAA;EAEE,OC1aQ;ED2aR;;AAEF;AAAA;EAEE,OC/aQ;EDgbR,YCpbS;;;ADybb;EACE;;AAEF;AAAA;EAEE,OC9bW","file":"dark.css"}
\ No newline at end of file
{"version":3,"sourceRoot":"","sources":["../scss/dark.scss","../scss/variables.scss"],"names":[],"mappings":"AAGA;EACE,kBCOa;EDNb;;;AAEF;EACE;;;AAEF;AAAA;EAEE;;;AAEF;AAAA;AAAA;EAGE,OCZa;;;ADcf;AAAA;AAAA;EAGE;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAOE;EACA;;;AAEF;EACE;;;AAEF;AAAA;EAEE;EACA;;;AAEF;EACE;;;AAEF;AAAA;EAEE;;AACA;AAAA;EACE;;;AAGJ;AAAA;EAEE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE,kBC3EY;;AD4EZ;EACE,OCjFW;;ADoFX;EACE;;AAGA;EACE,OCzFO;ED0FP;;AAEF;AAAA;EAEE,OC9FO;ED+FP;EACA,kBC3FW;;AD8Ff;EACE,OCpGS;EDqGT;EACA,kBCjGa;;;ADuGf;EACE;;AAEF;EACE;;;AAIN;EACE,kBC/Ga;;ADgHb;EACE;;;AAIF;EACE;EACA;;;AAIF;EACE,kBC7He;;AD+HjB;EACE,OCrIW;;ADuIb;EACE;;AAGA;EACE,OC7IS;;ADgJb;EACE,cC3Ie;;AD4If;EACE,OClJS;;ADoJX;EACE;;AAEF;EACE,OCxJS;;AD0JX;EACE;;AACA;EACE,OCxJW;;AD2Jf;AAAA;EAEE,OC1JY;;AD2JZ;AAAA;EACE;;AAIF;EACE;;AAIF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE,OCtLO;EDuLP;;AAGJ;EACE,OC3LS;;AD6LX;EACE,YCzLa;ED0Lb;;AAEF;EACE,YC9LQ;;;ADmMZ;EACE;EACA;EACA;;AAEF;EACE;;AAGA;AAAA;AAAA;AAAA;EAIE;;AAEF;EACE,YClNa;;;ADuNjB;AAAA;EAEE;EACA;EACA;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE,YCrOU;;ADsOV;EACE,cCrOS;;;ADyOf;EACE,YC3OiB;;AD4OjB;EACE,OClPW;;;ADsPb;EACE;;AACA;EACE;;AAIJ;EACE;;AAEF;EACE;;AAEF;EACE;;;AAIF;EACE,YCpQe;;ADqQf;EACE;EACA;;AAGJ;EACE;;;AAIF;EACE,OCxQoB;EDyQpB;;AACA;EACE;EACA;;AAGJ;EACE;EACA;;;AAIF;EACE,OCrRoB;EDsRpB;;AACA;EACE;EACA;;AAGJ;EACE;EACA;;;AAIF;EACE;;;AAKA;EACE,kBCpTM;;ADsTR;EACE;;AAEF;EACE;;AAEF;EACE;;;AAMF;EACE,YClUa;EDmUb,OCxUS;;ADyUT;EACE;;AAEF;AACE;AAAA;AAAA;;AAIF;AAAA;EAEE,cC/UM;;;ADoVd;EACE;;AACA;EACE;;AAEF;EACE;;AAEF;AAAA;AAAA;EAGE;EACA;;AAEF;EACE;;AAEF;AAAA;EAEE;EACA;;AAEF;AAAA;EAEE,YC3We;ED4Wf;;AAEF;AAAA;EAEE;;AAEF;AAAA;AAAA;EAGE;;AAEF;EACE;;AAEF;EACE;EACA,cC9XQ;;ADgYV;EACE,cCpYW;;ADsYb;EACE;EACA,cCxYW;;;AD2Yf;EACE;;AACA;EACE,OC9YW;ED+YX;;AACA;EACE;;;AAKJ;AAAA;AAAA;EAGE;EACA;EACA;;;AAGJ;EACE;;AACA;EACE;;AAEF;AAAA;EAEE;;AAEF;AAAA;EAEE;;AAEF;EACE,YCxaU;EDyaV;;AACA;AAAA;AAAA;EAGE;EACA;;AAEF;EACE;;AAEF;AAAA;EAEE,OCrbQ;EDsbR;;AAEF;AAAA;EAEE,OC1bQ;ED2bR,YC/bS;;;ADocb;EACE;;AAEF;AAAA;EAEE,OCzcW","file":"dark.css"}
\ No newline at end of file
src/css/style.css
View file @
e056c464
...
...
@@ -348,6 +348,10 @@ nav ul:nth-child(2) {
overflow-x
:
hidden
;
padding
:
2em
;
background
:
#ebebeb
;
/*.dropdown-item.is-greyed-out {
opacity: .75;
-webkit-filter: grayscale(100%);
}*/
/*#btnResetAllFilters {
display: none;
}
...
...
@@ -373,6 +377,13 @@ nav ul:nth-child(2) {
top
:
-0.75em
;
z-index
:
35
;
}
#drawerContainer
.drawer
.is-greyed-out
{
opacity
:
0.75
;
-webkit-filter
:
grayscale
(
100%
);
}
#drawerContainer
.drawer
.button.is-greyed-out
{
cursor
:
default
;
}
#drawerContainer
.drawer
h4
.is-4
{
font-size
:
1.35em
;
color
:
#4a4a4a
;
...
...
@@ -385,10 +396,6 @@ nav ul:nth-child(2) {
padding
:
0
;
margin
:
0
0
1.5em
0
;
}
#drawerContainer
.drawer
.dropdown-item.is-greyed-out
{
opacity
:
0.75
;
-webkit-filter
:
grayscale
(
100%
);
}
#drawerContainer
.drawer
table
tr
td
:nth-child
(
odd
)
{
width
:
auto
;
vertical-align
:
middle
;
...
...
@@ -769,6 +776,24 @@ nav ul:nth-child(2) {
display
:
block
;
}
#filterMenu
{
display
:
none
;
position
:
fixed
;
z-index
:
60
;
}
#filterMenu
#filterMenuSave
{
cursor
:
pointer
;
border
:
none
;
border-right
:
1px
solid
#f5f5f5
;
}
#filterMenu
#filterMenuDelete
{
color
:
#ff3860
;
}
#filterMenu
.is-active
{
display
:
block
;
}
.contentContainer
{
width
:
100%
;
height
:
90%
;
...
...
src/css/style.css.map
View file @
e056c464
This diff is collapsed.
Click to expand it.
src/index.html
View file @
e056c464
...
...
@@ -479,7 +479,7 @@
</tr>
<tr>
<td><a
href=
"https://github.com/matomo-org/matomo"
target=
"_blank"
>
Matomo
</a></td>
<td></td>
<td><
a
href=
"https://github.com/paulmillr/chokidar"
target=
"_blank"
>
chokidar
</a><
/td>
<td></td>
<td></td>
</tr>
...
...
@@ -637,6 +637,22 @@
</div>
</div>
<div
id=
"autoCompleteContainer"
class=
"drawer card"
></div>
<div
id=
"filterMenu"
class=
"flex-row "
>
<form
class=
"card"
>
<div
class=
"card-content"
>
<input
id=
"filterMenuInput"
class=
"input"
type=
"text"
>
</div>
<footer
class=
"card-footer"
>
<input
type=
"submit"
id=
"filterMenuSave"
class=
"card-footer-item"
>
<a
href=
"#"
id=
"filterMenuDelete"
class=
"card-footer-item"
></a>
</footer>
</form>
</div>
<div
id=
"modalChangeFile"
class=
"modal"
tabindex=
"0"
>
<div
class=
"modal-background"
></div>
<div
class=
"modal-content"
>
...
...
src/js/filters.mjs
View file @
e056c464
...
...
@@ -6,7 +6,43 @@ const modalFormInput = document.getElementById("modalFormInput");
const
todoTableSearch
=
document
.
getElementById
(
"
todoTableSearch
"
);
const
autoCompleteContainer
=
document
.
getElementById
(
"
autoCompleteContainer
"
);
const
todoFilters
=
document
.
getElementById
(
"
todoFilters
"
);
let
categories
,
filtersCounted
,
selectedFilters
,
container
,
headline
;
const
filterMenu
=
document
.
getElementById
(
"
filterMenu
"
);
const
filterMenuInput
=
document
.
getElementById
(
"
filterMenuInput
"
);
const
filterMenuSave
=
document
.
getElementById
(
"
filterMenuSave
"
);
const
filterMenuDelete
=
document
.
getElementById
(
"
filterMenuDelete
"
);
filterMenuSave
.
value
=
translations
.
save
;
filterMenuDelete
.
innerHTML
=
translations
.
delete
;
let
categories
,
filtersCounted
,
filtersCountedReduced
,
selectedFilters
,
container
,
headline
;
function
saveFilter
(
newFilter
,
oldFilter
,
category
)
{
items
.
objects
.
forEach
((
item
)
=>
{
if
(
category
!==
"
priority
"
&&
item
[
category
])
{
const
index
=
item
[
category
].
findIndex
((
el
)
=>
el
===
oldFilter
);
item
[
category
][
index
]
=
newFilter
;
}
else
if
(
category
===
"
priority
"
&&
item
[
category
]
===
oldFilter
)
{
item
[
category
]
=
newFilter
.
toUpperCase
();
}
});
// persisted filters will be removed
setUserData
(
"
selectedFilters
"
,
[]);
//write the data to the file
// a newline character is added to prevent other todo.txt apps to append new todos to the last line
window
.
api
.
send
(
"
writeToFile
"
,
[
items
.
objects
.
join
(
"
\n
"
).
toString
()
+
"
\n
"
,
userData
.
file
]);
}
function
deleteFilter
(
filter
,
category
)
{
items
.
objects
.
forEach
((
item
)
=>
{
if
(
item
[
category
])
{
const
index
=
item
[
category
].
indexOf
(
filter
);
if
(
index
!==-
1
)
item
[
category
].
splice
(
index
,
1
);
if
(
item
[
category
].
length
===
0
)
item
[
category
]
=
null
;
}
});
// persisted filters will be removed
setUserData
(
"
selectedFilters
"
,
[]);
//write the data to the file
// a newline character is added to prevent other todo.txt apps to append new todos to the last line
window
.
api
.
send
(
"
writeToFile
"
,
[
items
.
objects
.
join
(
"
\n
"
).
toString
()
+
"
\n
"
,
userData
.
file
]);
}
function
filterItems
(
items
,
searchString
)
{
try
{
// selected filters are empty, unless they were persisted
...
...
@@ -80,7 +116,7 @@ function generateFilterData(autoCompleteCategory, autoCompleteValue, autoComplet
// array to collect all the available filters in the data
let
filters
=
new
Array
();
// run the array and collect all possible filters, duplicates included
items
.
filtered
.
forEach
((
item
)
=>
{
items
.
objects
.
forEach
((
item
)
=>
{
// check if the object has values in either the project or contexts field
if
(
item
[
category
])
{
// push all filters found so far into an array
...
...
@@ -126,7 +162,7 @@ function generateFilterData(autoCompleteCategory, autoCompleteValue, autoComplet
// https://wsvincent.com/javascript-remove-duplicates-array/
filters
=
[...
new
Set
(
filters
.
join
(
"
,
"
).
split
(
"
,
"
))];
// filter persisted filters
if
(
userData
.
selectedFilters
&&
userData
.
selectedFilters
.
length
>
0
)
{
/*
if(userData.selectedFilters && userData.selectedFilters.length>0) {
selectedFilters = JSON.parse(userData.selectedFilters);
// check if selected filters is still part of all available filters
selectedFilters.forEach(function(selectedFilter,index){
...
...
@@ -140,7 +176,45 @@ function generateFilterData(autoCompleteCategory, autoCompleteValue, autoComplet
}
}
});
}
}*/
// TODO: basically a duplicate
// count reduced filter when persisted filters are present
let
filtersReduced
=
new
Array
();
items
.
filtered
.
forEach
((
item
)
=>
{
// check if the object has values in either the project or contexts field
if
(
item
[
category
])
{
// push all filters found so far into an array
for
(
let
filter
in
item
[
category
])
{
// if user has not opted for showComplete we skip the filter of this particular item
if
(
userData
.
showCompleted
==
false
&&
item
.
complete
==
true
)
{
continue
;
// if task is hidden the filter will be marked
}
else
if
(
item
.
h
)
{
filtersReduced
.
push
([
item
[
category
][
filter
],
0
]);
}
else
{
filtersReduced
.
push
([
item
[
category
][
filter
],
1
]);
}
}
}
});
filtersCountedReduced
=
filtersReduced
.
reduce
(
function
(
filters
,
filter
)
{
// if filter is already in object and should be counted
if
(
filter
[
1
]
&&
(
filter
[
0
]
in
filters
))
{
filters
[
filter
[
0
]]
++
;
// new filter in object and should be counted
}
else
if
(
filter
[
1
])
{
filters
[
filter
[
0
]]
=
1
;
// do not count if filter is suppose to be hidden
// only overwrite value with 0 if the filter doesn't already exist in object
}
else
if
(
!
filter
[
1
]
&&
!
(
filter
[
0
]
in
filters
))
{
filters
[
filter
[
0
]]
=
0
;
}
if
(
filters
!=
null
)
{
return
filters
;
}
},
{});
// build the filter buttons
if
(
filters
[
0
]
!=
""
&&
filters
.
length
>
0
)
{
generateFilterButtons
(
category
,
autoCompleteValue
,
autoCompletePrefix
,
caretPosition
).
then
(
response
=>
{
...
...
@@ -253,13 +327,39 @@ function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix,
selectedFilters
.
forEach
(
function
(
item
)
{
if
(
JSON
.
stringify
(
item
)
===
'
["
'
+
filter
+
'
","
'
+
category
+
'
"]
'
)
todoFiltersItem
.
classList
.
toggle
(
"
is-dark
"
)
});
todoFiltersItem
.
innerHTML
+=
"
<span class=
\"
tag is-rounded
\"
>
"
+
filtersCounted
[
filter
]
+
"
</span>
"
;
// create the event listener for filter selection by user
todoFiltersItem
.
addEventListener
(
"
click
"
,
()
=>
{
selectFilter
(
todoFiltersItem
.
getAttribute
(
'
data-filter
'
),
todoFiltersItem
.
getAttribute
(
'
data-category
'
))
// trigger matomo event
if
(
userData
.
matomoEvents
)
_paq
.
push
([
"
trackEvent
"
,
"
Filter-Drawer
"
,
"
Click on filter tag
"
,
category
]);
// context menu
todoFiltersItem
.
addEventListener
(
"
contextmenu
"
,
event
=>
{
filterMenu
.
style
.
left
=
event
.
x
+
"
px
"
;
filterMenu
.
style
.
top
=
event
.
y
+
"
px
"
;
filterMenu
.
classList
.
add
(
"
is-active
"
);
filterMenuInput
.
value
=
filter
;
filterMenuInput
.
focus
();
filterMenuSave
.
onclick
=
function
()
{
if
(
filterMenuInput
.
value
!==
filter
)
{
saveFilter
(
filterMenuInput
.
value
,
filter
,
category
);
}
else
{
filterMenu
.
classList
.
remove
(
"
is-active
"
);
}
}
filterMenuDelete
.
onclick
=
function
()
{
deleteFilter
(
filter
,
category
);
}
});
if
(
filtersCountedReduced
[
filter
])
{
todoFiltersItem
.
innerHTML
+=
"
<span class=
\"
tag is-rounded
\"
>
"
+
filtersCountedReduced
[
filter
]
+
"
</span>
"
;
// create the event listener for filter selection by user
todoFiltersItem
.
addEventListener
(
"
click
"
,
()
=>
{
selectFilter
(
todoFiltersItem
.
getAttribute
(
'
data-filter
'
),
todoFiltersItem
.
getAttribute
(
'
data-category
'
))
// trigger matomo event
if
(
userData
.
matomoEvents
)
_paq
.
push
([
"
trackEvent
"
,
"
Filter-Drawer
"
,
"
Click on filter tag
"
,
category
]);
});
}
else
{
todoFiltersItem
.
classList
.
add
(
"
is-greyed-out
"
);
todoFiltersItem
.
innerHTML
+=
"
<span class=
\"
tag is-rounded
\"
>0</span>
"
;
}
// autocomplete container
}
else
{
// add filter to input
...
...
src/js/todos.mjs
View file @
e056c464
...
...
@@ -246,19 +246,19 @@ function generateTableRow(todo) {
if
(
userData
.
matomoEvents
)
_paq
.
push
([
"
trackEvent
"
,
"
Todo-Table
"
,
"
Click on Todo item
"
]);
}
}
// cell for the categories
categories
.
forEach
(
category
=>
{
if
(
todo
[
category
]
&&
category
!=
"
priority
"
)
{
todo
[
category
].
forEach
(
el
=>
{
let
todoTableBodyCellCategory
=
document
.
createElement
(
"
span
"
);
todoTableBodyCellCategory
.
setAttribute
(
"
class
"
,
"
tag
"
+
category
);
todoTableBodyCellCategory
.
innerHTML
=
el
;
tableContainerCategories
.
appendChild
(
todoTableBodyCellCategory
);
});
}
});
// only add the categories to text cell if it has child nodes
if
(
tableContainerCategories
.
hasChildNodes
())
todoTableBodyCellText
.
appendChild
(
tableContainerCategories
);
// cell for the categories
categories
.
forEach
(
category
=>
{
if
(
todo
[
category
]
&&
category
!=
"
priority
"
)
{
todo
[
category
].
forEach
(
el
=>
{
let
todoTableBodyCellCategory
=
document
.
createElement
(
"
span
"
);
todoTableBodyCellCategory
.
setAttribute
(
"
class
"
,
"
tag
"
+
category
);
todoTableBodyCellCategory
.
innerHTML
=
el
;
tableContainerCategories
.
appendChild
(
todoTableBodyCellCategory
);
});
}
});
// only add the categories to text cell if it has child nodes
if
(
tableContainerCategories
.
hasChildNodes
())
todoTableBodyCellText
.
appendChild
(
tableContainerCategories
);
// check for and add a given due date
if
(
todo
.
due
)
{
var
tag
=
convertDate
(
todo
.
due
);
...
...
src/main.js
View file @
e056c464
...
...
@@ -147,7 +147,7 @@ const createWindow = async function() {
break
;
}
}
const
startFileWatcher
=
async
function
(
file
)
{
const
startFileWatcher
=
function
(
file
)
{
try
{
if
(
!
fs
.
existsSync
(
file
))
throw
(
"
File not found on disk
"
)
// use the loop to check if the new path is already in the user data
...
...
@@ -171,7 +171,8 @@ const createWindow = async function() {
userData
.
set
(
"
files
"
,
userData
.
data
.
files
);
userData
.
data
.
file
=
file
;
userData
.
set
(
"
file
"
,
file
);
fileWatcher
=
await
chokidar
.
watch
(
file
);
if
(
fileWatcher
)
fileWatcher
.
close
();
fileWatcher
=
chokidar
.
watch
(
file
);
fileWatcher
.
on
(
"
add
"
,
function
()
{
getContent
(
file
).
then
(
content
=>
{
...
...
src/render.js
View file @
e056c464
...
...
@@ -133,6 +133,8 @@ function configureMatomo() {
}
function
configureMainView
()
{
try
{
// close filterMenu if open
if
(
filterMenu
.
classList
.
contains
(
"
is-active
"
))
filterMenu
.
classList
.
remove
(
"
is-active
"
);
// set scaling factor if default font size has changed
if
(
userData
.
zoom
)
{
html
.
style
.
zoom
=
userData
.
zoom
+
"
%
"
;
...
...
@@ -159,7 +161,6 @@ function configureMainView() {
// check if archive button should be enabled
setButtonState
(
"
btnArchiveTodos
"
);
// file is defined, but content is empty
console
.
log
(
userData
.
file
);
if
(
userData
.
file
&&
todos
.
items
.
objects
.
length
===
0
)
{
addTodoContainer
.
classList
.
add
(
"
is-active
"
);
todoTableSearchContainer
.
classList
.
remove
(
"
is-active
"
);
...
...
@@ -294,6 +295,13 @@ function registerEvents() {
// ########################################################################################################################
// ONCLICK DEFINITIONS, FILE AND EVENT LISTENERS
// ########################################################################################################################
body
.
onclick
=
function
(
event
)
{
if
(
filterMenu
.
classList
.
contains
(
"
is-active
"
))
{
if
(
!
filterMenu
.
contains
(
event
.
target
))
{
filterMenu
.
classList
.
remove
(
"
is-active
"
);
}
}
}
a
.
forEach
(
el
=>
el
.
addEventListener
(
"
click
"
,
function
(
el
)
{
if
(
el
.
target
.
href
&&
el
.
target
.
href
===
"
#
"
)
el
.
preventDefault
();
}));
...
...
@@ -446,17 +454,17 @@ function registerKeyboardShortcuts() {
// CMD/metaKey only works on keydown
window
.
addEventListener
(
"
keydown
"
,
function
(
event
)
{
// open file
if
((
event
.
ctrlKey
||
event
.
metaKey
)
&&
event
.
key
===
"
o
"
)
{
if
((
event
.
ctrlKey
||
event
.
metaKey
)
&&
event
.
key
===
"
o
"
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
window
.
api
.
send
(
"
openOrCreateFile
"
,
"
open
"
);
}
// create file
if
((
event
.
ctrlKey
||
event
.
metaKey
)
&&
event
.
key
===
"
c
"
)
{
if
((
event
.
ctrlKey
||
event
.
metaKey
)
&&
event
.
key
===
"
c
"
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
window
.
api
.
send
(
"
openOrCreateFile
"
,
"
create
"
);
}
},
true
)
window
.
addEventListener
(
"
keyup
"
,
function
(
event
)
{
// open settings
if
(
event
.
key
===
"
,
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
document
.
activeElement
.
id
!=
"
todoTableSearch
"
)
{
if
(
event
.
key
===
"
,
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
content
.
showContent
(
document
.
getElementById
(
"
modalSettings
"
)).
then
(
function
(
response
)
{
console
.
info
(
response
);
}).
catch
(
function
(
error
)
{
...
...
@@ -464,7 +472,7 @@ function registerKeyboardShortcuts() {
});
}
// open help
if
(
event
.
key
===
"
?
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
document
.
activeElement
.
id
!=
"
todoTableSearch
"
)
{
if
(
event
.
key
===
"
?
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
content
.
showContent
(
document
.
getElementById
(
"
modalHelp
"
)).
then
(
function
(
response
)
{
console
.
info
(
response
);
}).
catch
(
function
(
error
)
{
...
...
@@ -472,7 +480,7 @@ function registerKeyboardShortcuts() {
});
}
// create new todo
if
(
event
.
key
===
"
n
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
document
.
activeElement
.
id
!=
"
todoTableSearch
"
)
{
if
(
event
.
key
===
"
n
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
form
.
show
().
then
(
function
(
response
)
{
console
.
info
(
response
);
}).
catch
(
function
(
error
)
{
...
...
@@ -480,11 +488,11 @@ function registerKeyboardShortcuts() {
});
}
// find todo
if
(
event
.
key
===
"
f
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
document
.
activeElement
.
id
!=
"
todoTableSearch
"
)
{
if
(
event
.
key
===
"
f
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
todoTableSearch
.
focus
();
}
// reset filters
if
(
event
.
key
===
"
0
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
document
.
activeElement
.
id
!=
"
todoTableSearch
"
)
{
if
(
event
.
key
===
"
0
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
resetFilters
().
then
(
function
(
response
)
{
console
.
info
(
response
);
}).
catch
(
function
(
error
)
{
...
...
@@ -492,7 +500,7 @@ function registerKeyboardShortcuts() {
});
}
// toggle completed todos
if
(
event
.
key
===
"
h
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
document
.
activeElement
.
id
!=
"
todoTableSearch
"
)
{
if
(
event
.
key
===
"
h
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
view
.
toggle
(
"
showCompleted
"
).
then
(
function
(
response
)
{
console
.
info
(
response
);
}).
catch
(
function
(
error
)
{
...
...
@@ -500,7 +508,7 @@ function registerKeyboardShortcuts() {
});
}
// archive todos
if
(
event
.
key
===
"
a
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
document
.
activeElement
.
id
!=
"
todoTableSearch
"
)
{
if
(
event
.
key
===
"
a
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
todos
.
archiveTodos
().
then
(
function
(
response
)
{
console
.
info
(
response
);
}).
catch
(
function
(
error
)
{
...
...
@@ -508,7 +516,7 @@ function registerKeyboardShortcuts() {
});
}
// toggle dark mode
if
(
event
.
key
===
"
d
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
document
.
activeElement
.
id
!=
"
todoTableSearch
"
)
{
if
(
event
.
key
===
"
d
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
setTheme
(
true
).
then
(
function
(
response
)
{
console
.
info
(
response
);
}).
catch
(
function
(
error
)
{
...
...
@@ -516,7 +524,7 @@ function registerKeyboardShortcuts() {
});
}
// show filter drawer
if
(
event
.
key
===
"
b
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
document
.
activeElement
.
id
!=
"
todoTableSearch
"
)
{
if
(
event
.
key
===
"
b
"
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
drawer
.
showDrawer
(
"
toggle
"
,
"
navBtnFilter
"
,
"
filterDrawer
"
).
then
(
function
(
result
)
{
console
.
log
(
result
);
}).
catch
(
function
(
error
)
{
...
...
@@ -524,10 +532,18 @@ function registerKeyboardShortcuts() {
});
}
// reload window
if
((
event
.
key
===
"
.
"
||
event
.
key
===
"
F5
"
)
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
document
.
activeElement
.
id
!=
"
todoTableSearch
"
)
{
if
((
event
.
key
===
"
.
"
||
event
.
key
===
"
F5
"
)
&&
!
modalForm
.
classList
.
contains
(
"
is-active
"
)
&&
(
document
.
activeElement
.
id
!=
"
todoTableSearch
"
&&
document
.
activeElement
.
id
!=
"
filterMenuInput
"
&&
document
.
activeElement
.
id
!=
"
modalFormInput
"
)
)
{
location
.
reload
(
true
);
}
},
true
)
// shortcuts for search input field
todoTableSearch
.
addEventListener
(
"
keydown
"
,
function
()
{
if
(
event
.
key
===
"
Escape
"
)
todoTableSearch
.
blur
();
});
// shortcuts for filter menu input field
filterMenuInput
.
addEventListener
(
"
keydown
"
,
function
()
{
if
(
event
.
key
===
"
Escape
"
)
filterMenu
.
classList
.
remove
(
"
is-active
"
);
});
// shortcuts for modal form
modalForm
.
addEventListener
(
"
keydown
"
,
function
(
event
)
{
// priority up
...
...
src/scss/dark.scss
View file @
e056c464
...
...
@@ -266,7 +266,18 @@ nav {
background
:
$almost-black
!
important
;
}
}
#filterMenu
{
.card
{
background
:
$even-darker-grey
;
#filterMenuSave
{
background-color
:
transparent
!
important
;
border-right
:
1px
solid
$almost-black
!
important
;
}
}
.card-footer
{
border-top
:
1px
solid
$almost-black
!
important
;
}
}
.contexts
{
.button
{
color
:
$sleek-contexts-button
;
...
...
src/scss/style.scss
View file @
e056c464
...
...
@@ -333,6 +333,13 @@ nav {
z-index
:
35
;
}
}
.is-greyed-out
{
opacity
:
.75
;
-webkit-filter
:
grayscale
(
100%
);
}
.button.is-greyed-out
{
cursor
:
default
;
}
h4
.is-4
{
font-size
:
1
.35em
;
color
:
$dark-grey
;
...
...
@@ -345,10 +352,10 @@ nav {
padding
:
0
;
margin
:
0
0
1
.5em
0
;
}
.dropdown-item.is-greyed-out
{
/*
.dropdown-item.is-greyed-out {
opacity: .75;
-webkit-filter: grayscale(100%);
}
}
*/
/*#btnResetAllFilters {
display: none;
}
...
...
@@ -745,6 +752,22 @@ nav {
#autoCompleteContainer
.is-active
{
display
:
block
;
}
#filterMenu
{
display
:
none
;
position
:
fixed
;
z-index
:
60
;
#filterMenuSave
{
cursor
:
pointer
;
border
:
none
;
border-right
:
1px
solid
$almost-white
;
}
#filterMenuDelete
{
color
:
$has-text-danger
;
}
}
#filterMenu
.is-active
{
display
:
block
;
}
.contentContainer
{
width
:
100%
;
height
:
90%
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment