Commit 27d62115 authored by ransome1's avatar ransome1
Browse files

Optimized CSS, added business days recurrence, removed autocreation of rec todos

parent eee8c3cf
# sleek # sleek
## sleek is a todo app based on todo.txt, free and open-source. Available for Linux, Windows and MacOS ## sleek is a todo app based on todo.txt, free and open-source. Available for Linux, Windows and MacOS
+ [Support sleek](#support-sleek)
+ [Screenshots](#screenshots) + [Screenshots](#screenshots)
+ [Support sleek](#support-sleek)
+ [Get it from Microsoft Store](#get-sleek-from-microsoft-store) + [Get it from Microsoft Store](#get-sleek-from-microsoft-store)
+ [Get it from Snap Store](#get-sleek-from-snap-store) + [Get it from Snap Store](#get-sleek-from-snap-store)
+ [Get it from Flathub](#get-sleek-from-flathub) + [Get it from Flathub](#get-sleek-from-flathub)
+ [Get it from Arch User Repository](#get-sleek-from-arch-user-repository) + [Get it from Arch User Repository](#get-sleek-from-arch-user-repository)
+ [Download it](#download-sleek) + [Download it](#download-sleek)
+ [Build sleek from source code](#build-sleek-from-source-code) + [Build it from source code](#build-sleek-from-source-code)
+ [sleeks state of development](#sleeks-state-of-development) + [State of development](#sleeks-state-of-development)
+ [Features](#features) + [Features](#features)
+ [Used libraries](#used-libraries) + [Used libraries](#used-libraries)
...@@ -73,33 +73,23 @@ A prioritized backlog of new features and known issues can be found <a href="htt ...@@ -73,33 +73,23 @@ A prioritized backlog of new features and known issues can be found <a href="htt
- edited - edited
- marked as complete (and vice versa) - marked as complete (and vice versa)
- deleted - deleted
* A todo can be hidden (add "h:1") but its attributes will appear in filter list and auto complete * <a href="https://github.com/ransome1/sleek/wiki/Hidden-todos">A todo can be hidden but its attributes will be available in the filter drawer and autocomplete function</a>
* Dark and light mode can be toggled * Dark and light mode can be toggled
* A compact view is available * A compact view is available
* Completed todos can be bulk archived to a separate done.txt ([name of todo file]_done.txt) file * Completed todos can be bulk archived to a separate done.txt ([name of todo file]_done.txt) file
* Completed todos can be shown or hidden * Completed todos can be shown or hidden
* Todos can be enriched by * Todos can be enriched, sorted and grouped by
- contexts - contexts
- projects - projects
- start dates - start dates
- due dates - due dates
* Multi line todos can be created * Multi line todos can be created
* A due date can be set using a datepicker * Todos can have a due date
* Todos can repeat themselves based on a given due date. You can use a dedicated picker to add the recurrence or type it in by hand: * <a href="https://github.com/ransome1/sleek/wiki/Recurring-todos">Todos can repeat themselves</a>
- "rec:d" (daily)
- "rec:w" (weekly)
- "rec:m" (monthly)
- "rec:y" (annually)
- also more specific recurrences are possible: "rec:2d" (every 2nd day)
* Available contexts and projects will be suggested according to your input * Available contexts and projects will be suggested according to your input
* Todos can be filtered by contexts, projects and priorities * Todos can be filtered by contexts, projects and priorities
* Filters can be renamed or deleted by right clicking on them * Filters can be renamed or deleted by right clicking on them
* Filters are sorted alphanummerically * Filters are sorted alphanummerically
* Todos can be sorted and grouped by
- Priorites
- Due dates
- Projects
- Contexts
* Todos can be looked up using full-text search * Todos can be looked up using full-text search
* Hyperlinks are detected automatically and can be clicked using the icon * Hyperlinks are detected automatically and can be clicked using the icon
* Alarms will be triggered when a todo is due tomorrow or today * Alarms will be triggered when a todo is due tomorrow or today
...@@ -112,11 +102,11 @@ A prioritized backlog of new features and known issues can be found <a href="htt ...@@ -112,11 +102,11 @@ A prioritized backlog of new features and known issues can be found <a href="htt
- Italian - Italian
- Spanish - Spanish
- French - French
- Simplified Chinese - Simplified Chinese (简体中文)
* sleek can be minimized to tray * sleek can be minimized to tray
* Tabindex available * Tabindex available
* Existing todos can be used as templates for new ones * Existing todos can be used as templates for new ones
* <a href="https://github.com/ransome1/sleek/wiki/Keyboard-shortcuts">Keyboard shortcuts</a> following todotxt.net * <a href="https://github.com/ransome1/sleek/wiki/Keyboard-shortcuts">Keyboard shortcuts following todotxt.net</a>
### Used libraries ### Used libraries
- Electron: https://github.com/electron/electron - Electron: https://github.com/electron/electron
......
{ {
"name": "sleek", "name": "sleek",
"productName": "sleek", "productName": "sleek",
"version": "1.0.5-5", "version": "1.0.5",
"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",
...@@ -72,14 +72,15 @@ ...@@ -72,14 +72,15 @@
], ],
"icon": "assets/icons/sleek.ico", "icon": "assets/icons/sleek.ico",
"publisherName": "CN=2B3D4037-FF2E-4C36-84A6-CFF49F585C0C", "publisherName": "CN=2B3D4037-FF2E-4C36-84A6-CFF49F585C0C",
"artifactName": "${productName}-${version}.${ext}" "artifactName": "${productName}-${version}-win.${ext}"
}, },
"appx": { "appx": {
"displayName": "sleek - Todo.txt app for Windows, free and open-source", "displayName": "sleek - Todo.txt app for Windows, free and open-source",
"identityName": "17450RobinAhle.sleektodomanager", "identityName": "17450RobinAhle.sleektodomanager",
"publisher": "CN=2B3D4037-FF2E-4C36-84A6-CFF49F585C0C", "publisher": "CN=2B3D4037-FF2E-4C36-84A6-CFF49F585C0C",
"publisherDisplayName": "Robin Ahle", "publisherDisplayName": "Robin Ahle",
"applicationId": "RobinAhle.sleektodomanager" "applicationId": "RobinAhle.sleektodomanager",
"artifactName": "${productName}-${version}.${ext}"
} }
}, },
"appImage": { "appImage": {
......
name: sleek name: sleek
base: core18 base: core18
version: '1.0.4' version: '1.0.5'
summary: Todo app based on the todo.txt format for Linux, free and open-source summary: Todo app based on the todo.txt format for Linux, free and open-source
description: | description: |
sleek is an open-source todo app that makes use of the todo.txt format. sleeks GUI is modern and simple but still offers a decent set of functions which help users getting things done. sleek is available as a client for Windows, MacOS and Linux. sleek is an open-source todo app that makes use of the todo.txt format. sleeks GUI is modern and simple but still offers a decent set of functions which help users getting things done. sleek is available as a client for Windows, MacOS and Linux.
......
...@@ -24,7 +24,6 @@ const i18nextOptions = { ...@@ -24,7 +24,6 @@ const i18nextOptions = {
}, },
saveMissing: true saveMissing: true
}; };
i18next i18next
.use(LanguageDetector) .use(LanguageDetector)
.use(i18nextBackend) .use(i18nextBackend)
......
...@@ -3,6 +3,10 @@ body { ...@@ -3,6 +3,10 @@ body {
color: #CCCDCF; color: #CCCDCF;
} }
code, pre {
background-color: #212224 !important;
}
a { a {
color: white; color: white;
} }
...@@ -55,6 +59,10 @@ input[type=checkbox]:active { ...@@ -55,6 +59,10 @@ input[type=checkbox]:active {
button { button {
color: white !important; color: white !important;
background: transparent !important;
}
button i {
color: #CCCDCF !important;
} }
button.is-link, button.is-link,
...@@ -205,6 +213,9 @@ nav ul li.is-highlighted a { ...@@ -205,6 +213,9 @@ nav ul li.is-highlighted a {
background: #2d2d2d; background: #2d2d2d;
} }
#modalForm i {
color: #CCCDCF !important;
}
#modalForm button { #modalForm button {
color: white; color: white;
border-color: #3B3B3B !important; border-color: #3B3B3B !important;
...@@ -255,6 +266,9 @@ nav ul li.is-highlighted a { ...@@ -255,6 +266,9 @@ nav ul li.is-highlighted a {
#drawerContainer .drawer h4.is-4 { #drawerContainer .drawer h4.is-4 {
color: white; color: white;
} }
#drawerContainer .drawer h4.is-4 i {
color: #CCCDCF !important;
}
#drawerContainer a.drawerClose { #drawerContainer a.drawerClose {
background: #3B3B3B !important; background: #3B3B3B !important;
} }
...@@ -336,10 +350,6 @@ nav ul li.is-highlighted a { ...@@ -336,10 +350,6 @@ nav ul li.is-highlighted a {
border-color: #2d2d2d; border-color: #2d2d2d;
} }
.column.content .button {
background: #2d2d2d !important;
}
.modal.content { .modal.content {
color: #CCCDCF !important; color: #CCCDCF !important;
} }
...@@ -395,6 +405,9 @@ nav ul li.is-highlighted a { ...@@ -395,6 +405,9 @@ nav ul li.is-highlighted a {
.message.fixed { .message.fixed {
background: transparent !important; background: transparent !important;
} }
.message.fixed i {
color: white !important;
}
.message.fixed .message-body { .message.fixed .message-body {
color: #CCCDCF; color: #CCCDCF;
background: #3B3B3B !important; background: #3B3B3B !important;
...@@ -403,7 +416,6 @@ nav ul li.is-highlighted a { ...@@ -403,7 +416,6 @@ nav ul li.is-highlighted a {
background: #2d2d2d !important; background: #2d2d2d !important;
} }
.dueDate svg,
.dueDate #datePickerInput, .dueDate #datePickerInput,
.dueDate #datePickerInput::placeholder { .dueDate #datePickerInput::placeholder {
color: white !important; color: white !important;
......
{"version":3,"sourceRoot":"","sources":["../scss/dark.scss","../scss/variables.scss"],"names":[],"mappings":"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","file":"dark.css"} {"version":3,"sourceRoot":"","sources":["../scss/dark.scss","../scss/variables.scss"],"names":[],"mappings":"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","file":"dark.css"}
\ No newline at end of file \ No newline at end of file
...@@ -154,9 +154,6 @@ strong { ...@@ -154,9 +154,6 @@ strong {
font-weight: normal !important; font-weight: normal !important;
} }
/*svg {
color: $has-text-link;
}*/
code, pre { code, pre {
font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace !important; font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace !important;
background-color: #ebebeb !important; background-color: #ebebeb !important;
...@@ -254,7 +251,6 @@ nav ul:nth-child(2) { ...@@ -254,7 +251,6 @@ nav ul:nth-child(2) {
padding: 0 0.5em; padding: 0 0.5em;
} }
#recurrencePicker .card .content div.options { #recurrencePicker .card .content div.options {
width: 8em;
text-align: left; text-align: left;
} }
#recurrencePicker .card .content #recurrencePickerDecrease, #recurrencePicker .card .content #recurrencePickerDecrease,
...@@ -267,7 +263,7 @@ nav ul:nth-child(2) { ...@@ -267,7 +263,7 @@ nav ul:nth-child(2) {
width: 2em; width: 2em;
} }
#recurrencePicker .card label { #recurrencePicker .card label {
width: 100%; display: block;
padding: 0; padding: 0;
margin: 0.25em 0; margin: 0.25em 0;
} }
...@@ -1053,24 +1049,16 @@ nav ul:nth-child(2) { ...@@ -1053,24 +1049,16 @@ nav ul:nth-child(2) {
.modal.content .modal-card-body table.settings tr td { .modal.content .modal-card-body table.settings tr td {
position: relative; position: relative;
} }
.modal.content .modal-card-body table.settings tr td .toggle .select,
.modal.content .modal-card-body table.settings tr td .toggle select,
.modal.content .modal-card-body table.settings tr td .field .select,
.modal.content .modal-card-body table.settings tr td .field select {
width: 100%;
padding-right: 0;
}
.modal.content .modal-card-body table.settings tr td .alert { .modal.content .modal-card-body table.settings tr td .alert {
position: absolute; position: absolute;
top: 1em; top: 1em;
left: -0.8em; left: -0.8em;
} }
.modal.content .modal-card-body table.settings tr td:first-child { .modal.content .modal-card-body table.settings tr td:first-child {
width: 80%;
padding-right: 3em; padding-right: 3em;
} }
.modal.content .modal-card-body table.settings tr td:last-child { .modal.content .modal-card-body table.settings tr td:last-child {
width: 20%; width: 25%;
} }
.modal.content .modal-card-body table.shortcuts td .tag { .modal.content .modal-card-body table.shortcuts td .tag {
font-size: 1em !important; font-size: 1em !important;
......
This diff is collapsed.
...@@ -288,6 +288,10 @@ ...@@ -288,6 +288,10 @@
<input type="radio" class="selection" name="recurrence" value="d"> <input type="radio" class="selection" name="recurrence" value="d">
<span id="recurrencePickerDay"></span> <span id="recurrencePickerDay"></span>
</label> </label>
<label class="radio">
<input type="radio" class="selection" name="recurrence" value="b">
<span id="recurrencePickerBusinessDay"></span>
</label>
<label class="radio"> <label class="radio">
<input type="radio" class="selection" name="recurrence" value="w"> <input type="radio" class="selection" name="recurrence" value="w">
<span id="recurrencePickerWeek"></span> <span id="recurrencePickerWeek"></span>
......
...@@ -298,6 +298,7 @@ function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix, ...@@ -298,6 +298,7 @@ function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix,
todoFilterHeadline.innerHTML = "<i class=\"far fa-eye-slash\" tabindex=\"-1\"></i>&nbsp;" + headline; todoFilterHeadline.innerHTML = "<i class=\"far fa-eye-slash\" tabindex=\"-1\"></i>&nbsp;" + headline;
// add click event // add click event
todoFilterHeadline.onclick = function() { todoFilterHeadline.onclick = function() {
document.getElementById("todoTableWrapper").scrollTo(0,0);
let hideFilterCategories = userData.hideFilterCategories; let hideFilterCategories = userData.hideFilterCategories;
if(hideFilterCategories.includes(category)) { if(hideFilterCategories.includes(category)) {
hideFilterCategories.splice(hideFilterCategories.indexOf(category),1) hideFilterCategories.splice(hideFilterCategories.indexOf(category),1)
...@@ -376,6 +377,7 @@ function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix, ...@@ -376,6 +377,7 @@ function generateFilterButtons(category, autoCompleteValue, autoCompletePrefix,
todoFiltersItem.innerHTML += " <span class=\"tag is-rounded\">" + filtersCountedReduced[filter] + "</span>"; todoFiltersItem.innerHTML += " <span class=\"tag is-rounded\">" + filtersCountedReduced[filter] + "</span>";
// create the event listener for filter selection by user // create the event listener for filter selection by user
todoFiltersItem.addEventListener("click", () => { todoFiltersItem.addEventListener("click", () => {
document.getElementById("todoTableWrapper").scrollTo(0,0);
selectFilter(todoFiltersItem.getAttribute('data-filter'), todoFiltersItem.getAttribute('data-category')) selectFilter(todoFiltersItem.getAttribute('data-filter'), todoFiltersItem.getAttribute('data-category'))
// trigger matomo event // trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Filter-Drawer", "Click on filter tag", category]); if(userData.matomoEvents) _paq.push(["trackEvent", "Filter-Drawer", "Click on filter tag", category]);
......
...@@ -109,13 +109,6 @@ function getCaretPosition(inputId) { ...@@ -109,13 +109,6 @@ function getCaretPosition(inputId) {
return false; return false;
} }
} }
function resizeInput(input) {
if(input.value) {
input.style.width = input.value.length + 8 + "ch";
} else if(!input.value && input.placeholder) {
input.style.width = input.placeholder.length + 8 + "ch";
}
}
function positionAutoCompleteContainer() { function positionAutoCompleteContainer() {
// Adjust position of suggestion box to input field // Adjust position of suggestion box to input field
let modalFormInputPosition = document.getElementById("modalFormInput").getBoundingClientRect(); let modalFormInputPosition = document.getElementById("modalFormInput").getBoundingClientRect();
...@@ -166,6 +159,13 @@ function modalFormInputEvent() { ...@@ -166,6 +159,13 @@ function modalFormInputEvent() {
autoCompleteContainer.blur(); autoCompleteContainer.blur();
} }
} }
function resizeInput(input) {
if(input.value) {
input.style.width = input.value.length + 6 + "ch";
} else if(!input.value && input.placeholder) {
input.style.width = input.placeholder.length + 6 + "ch";
}
}
function setPriority(priority) { function setPriority(priority) {
try { try {
const setPriorityInput = function(priority) { const setPriorityInput = function(priority) {
......
...@@ -10,6 +10,8 @@ const recurrencePickerInput = document.getElementById("recurrencePickerInput"); ...@@ -10,6 +10,8 @@ const recurrencePickerInput = document.getElementById("recurrencePickerInput");
const recurrencePickerSpinner = document.getElementById("recurrencePickerSpinner"); const recurrencePickerSpinner = document.getElementById("recurrencePickerSpinner");
const recurrencePickerDay = document.getElementById("recurrencePickerDay"); const recurrencePickerDay = document.getElementById("recurrencePickerDay");
recurrencePickerDay.innerHTML = translations.day; recurrencePickerDay.innerHTML = translations.day;
const recurrencePickerBusinessDay = document.getElementById("recurrencePickerBusinessDay");
recurrencePickerBusinessDay.innerHTML = translations.bday;
const recurrencePickerWeek = document.getElementById("recurrencePickerWeek"); const recurrencePickerWeek = document.getElementById("recurrencePickerWeek");
recurrencePickerWeek.innerHTML = translations.week; recurrencePickerWeek.innerHTML = translations.week;
const recurrencePickerMonth = document.getElementById("recurrencePickerMonth"); const recurrencePickerMonth = document.getElementById("recurrencePickerMonth");
...@@ -33,24 +35,30 @@ export function setInput(recurrence) { ...@@ -33,24 +35,30 @@ export function setInput(recurrence) {
if(recSplit.mul > 1) { if(recSplit.mul > 1) {
switch (recSplit.period) { switch (recSplit.period) {
case "d": case "d":
label = recurrencePickerDay; label = translations.day_plural;
break;
case "b":
label = translations.bday_plural;
break; break;
case "w": case "w":
label = recurrencePickerWeek; label = translations.week_plural;
break; break;
case "m": case "m":
label = recurrencePickerMonth; label = translations.month_plural;
break; break;
case "y": case "y":
label = recurrencePickerYear; label = translations.year_plural;
break; break;
} }
label = translations.every + " " + recSplit.mul + " " + label.innerHTML; label = translations.every + " " + recSplit.mul + " " + label;
} else { } else {
switch (recSplit.period) { switch (recSplit.period) {
case "d": case "d":
label = translations.daily; label = translations.daily;
break; break;
case "b":
label = translations.bdaily;
break;
case "w": case "w":
label = translations.weekly; label = translations.weekly;
break; break;
...@@ -138,11 +146,13 @@ function showRecurrences() { ...@@ -138,11 +146,13 @@ function showRecurrences() {
} }
function setRecurrenceOptionLabels(mul) { function setRecurrenceOptionLabels(mul) {
if(mul>1) { if(mul>1) {
recurrencePickerBusinessDay.innerHTML = translations.bday_plural;
recurrencePickerDay.innerHTML = translations.day_plural; recurrencePickerDay.innerHTML = translations.day_plural;
recurrencePickerWeek.innerHTML = translations.week_plural; recurrencePickerWeek.innerHTML = translations.week_plural;
recurrencePickerMonth.innerHTML = translations.month_plural; recurrencePickerMonth.innerHTML = translations.month_plural;
recurrencePickerYear.innerHTML = translations.year_plural; recurrencePickerYear.innerHTML = translations.year_plural;
} else { } else {
recurrencePickerBusinessDay.innerHTML = translations.bday;
recurrencePickerDay.innerHTML = translations.day; recurrencePickerDay.innerHTML = translations.day;
recurrencePickerWeek.innerHTML = translations.week; recurrencePickerWeek.innerHTML = translations.week;
recurrencePickerMonth.innerHTML = translations.month; recurrencePickerMonth.innerHTML = translations.month;
......
...@@ -26,19 +26,9 @@ function generateRecurrence(todo) { ...@@ -26,19 +26,9 @@ function generateRecurrence(todo) {
recurringTodo.complete = false; recurringTodo.complete = false;
recurringTodo.completed = null; recurringTodo.completed = null;
// if the item to be duplicated has been completed before the due date, the recurring item needs to be set incomplete again // if the item to be duplicated has been completed before the due date, the recurring item needs to be set incomplete again
if(recurringTodo.due && isFuture(recurringTodo.due)) { recurringTodo.date = new Date;
recurringTodo.date = new Date; recurringTodo.due = getRecurrenceDate(recurringTodo.date, todo.rec);
recurringTodo.due = getRecurrenceDate(todo.due, todo.rec); recurringTodo.dueString = convertDate(getRecurrenceDate(recurringTodo.date, todo.rec));
recurringTodo.dueString = convertDate(getRecurrenceDate(todo.due, todo.rec));
} else if(!recurringTodo.due) {
recurringTodo.date = new Date;
recurringTodo.due = getRecurrenceDate(todo.completed, todo.rec);
recurringTodo.dueString = convertDate(getRecurrenceDate(todo.completed, todo.rec));
} else {
recurringTodo.date = todo.due;
recurringTodo.due = getRecurrenceDate(todo.due, todo.rec);
recurringTodo.dueString = convertDate(getRecurrenceDate(todo.due, todo.rec));
}
// get index of recurring todo // get index of recurring todo
const index = items.objects.map(function(item) {return item.toString().replaceAll(String.fromCharCode(16)," "); }).indexOf(recurringTodo.toString().replaceAll(String.fromCharCode(16)," ")); const index = items.objects.map(function(item) {return item.toString().replaceAll(String.fromCharCode(16)," "); }).indexOf(recurringTodo.toString().replaceAll(String.fromCharCode(16)," "));
// only add recurring todo if it is not already in the list // only add recurring todo if it is not already in the list
...@@ -60,6 +50,21 @@ function getRecurrenceDate(due, recurrence) { ...@@ -60,6 +50,21 @@ function getRecurrenceDate(due, recurrence) {
let days = 0; let days = 0;
let months = 0; let months = 0;
switch (recSplit.period) { switch (recSplit.period) {
case "b":
// add "mul" business days, defined as not Sat or Sun
{
let bdays_left = recSplit.mul;
let millisec_due = due.getTime();
let day_of_week = due.getDay(); // 0=Sunday, 1..5 weekday, 6=Saturday
while (bdays_left > 0) {
millisec_due += 1000 * 60 * 60 * 24; // add a day to time
day_of_week = (day_of_week + 1)% 7; // new day of week
if (day_of_week != 0 && day_of_week != 6) {
bdays_left--; // one business day step accounted for!
}
}
return new Date(millisec_due);
}
case "d": case "d":
days = 1; days = 1;
break; break;
......
...@@ -181,10 +181,10 @@ function generateTable(groups, append) { ...@@ -181,10 +181,10 @@ function generateTable(groups, append) {
let dividerRow; let dividerRow;
// completed todos // completed todos
if(userData.sortCompletedLast && groups[group][0]==="completed") { if(userData.sortCompletedLast && groups[group][0]==="completed") {
dividerRow = document.createRange().createContextualFragment("<div id=\"" + userData.sortBy + groups[group][0] + "\" class=\"flex-table group\" role=\"rowgroup\"><div class=\"flex-row\" role=\"cell\"></div></div>") dividerRow = document.createRange().createContextualFragment("<div id=\"" + userData.sortBy + groups[group][0] + "\" class=\"flex-table " + userData.sortBy + " " + groups[group][0] + " group\" role=\"rowgroup\"><div class=\"flex-row\" role=\"cell\"></div></div>")
// for priority, context and project // for priority, context and project
} else if(groups[group][0]!="null" && userData.sortBy!="dueString") { } else if(groups[group][0]!="null" && userData.sortBy!="dueString") {
dividerRow = document.createRange().createContextualFragment("<div id=\"" + userData.sortBy + groups[group][0] + "\" class=\"flex-table " + userData.sortBy + " group\" role=\"rowgroup\"><div class=\"flex-row\" role=\"cell\"><span class=\"button " + groups[group][0] + "\">" + groups[group][0].replace(/,/g, ', ') + "</span></div></div>") dividerRow = document.createRange().createContextualFragment("<div id=\"" + userData.sortBy + groups[group][0] + "\" class=\"flex-table " + userData.sortBy + " " + groups[group][0] + " group\" role=\"rowgroup\"><div class=\"flex-row\" role=\"cell\"><span class=\"button " + groups[group][0] + "\">" + groups[group][0].replace(/,/g, ', ') + "</span></div></div>")
// if sorting is by due date // if sorting is by due date
} else if(userData.sortBy==="dueString" && groups[group][1][0].due) { } else if(userData.sortBy==="dueString" && groups[group][1][0].due) {
if(isToday(groups[group][1][0].due)) { if(isToday(groups[group][1][0].due)) {
...@@ -207,13 +207,6 @@ function generateTable(groups, append) { ...@@ -207,13 +207,6 @@ function generateTable(groups, append) {
// if this todo is not a recurring one the rec value will be set to null // if this todo is not a recurring one the rec value will be set to null
if(!todo.rec) { if(!todo.rec) {
todo.rec = null; todo.rec = null;
// if item is due today or in the past and has recurrence it will be duplicated