Commit 13092a65 authored by ransome1's avatar ransome1
Browse files

Added Snyk to code scanning workflow, refactored: form.mjs, added test cases

parent 792a78ff
......@@ -13,6 +13,7 @@ jobs:
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
njsscan:
needs: snyk
name: njsscan
runs-on: ubuntu-latest
steps:
......
......@@ -26,4 +26,5 @@ package-lock.json
.yarnclean
sleek.sublime-project
sleek.sublime-workspace
*conflict*
\ No newline at end of file
*conflict*
*_done.txt
\ No newline at end of file
......@@ -1182,7 +1182,12 @@ nav ul:nth-child(2):hover #versionNumber {
padding: 0.75em !important;
}
#modalForm #modalFormInputResize {
top: 1.65em;
top: 1.4em !important;
}
.modal-content,
.modal-card {
width: 100% !important;
}
.modal.content .modal-card {
......@@ -1302,7 +1307,11 @@ body.compact #modalForm textarea {
padding: 0.75em !important;
}
body.compact #modalForm #modalFormInputResize {
top: 1.65em;
top: 1.4em !important;
}
body.compact .modal-content,
body.compact .modal-card {
width: 100% !important;
}
body.compact .modal.content .modal-card {
padding: 1em !important;
......
This diff is collapsed.
......@@ -242,8 +242,8 @@
</div>
</div>
<section id="modalForm" class="modal" data-item="">
<div class="modal-background"></div>
<form id="modalForm" class="modal" data-item="">
<div class="modal-background" role="cancel"></div>
<div class="modal-content">
<div class="card">
<div class="card-content">
......@@ -347,15 +347,15 @@
</div>
<footer class="card-footer">
<button id="btnSave" class="card-footer-item" tabindex="0"></button>
<button id="btnItemStatus" class="card-footer-item" tabindex="0"></button>
<button id="btnSave" type="submit" class="card-footer-item" tabindex="0"></button>
<button id="btnItemStatus" class="card-footer-item is-hidden" tabindex="0"></button>
<button id="btnCancel" class="card-footer-item" role="cancel" tabindex="0"></button>
</footer>
</div>
</div>
</section>
</form>
<div id="modalSettings" class="modal content" tabindex="0">
<div class="modal-background"></div>
<div class="modal-background" role="cancel"></div>
<div class="modal-card">
<div class="tabs is-centered">
&nbsp;
......@@ -490,11 +490,11 @@
</tr>
</table>
</section>
<button class="modal-close close is-large" aria-label="close" tabindex="0"></button>
<button class="modal-close close is-large" role="cancel" tabindex="0"></button>
</div>
</div>
<div id="modalHelp" class="modal content" tabindex="0">
<div class="modal-background"></div>
<div class="modal-background" role="cancel"></div>
<div class="modal-card">
<div class="tabs is-centered">
<ul>
......@@ -769,7 +769,7 @@
</tr>
</table>
</section>
<button class="modal-close close is-large" aria-label="close" tabindex="0"></button>
<button class="modal-close close is-large" role="cancel" tabindex="0"></button>
</div>
</div>
......@@ -796,7 +796,7 @@
</div>
<div id="modalChangeFile" class="modal" tabindex="0">
<div class="modal-background"></div>
<div class="modal-background" role="cancel"></div>
<div class="modal-content">
<div class="card">
<div class="card-content">
......@@ -805,14 +805,14 @@
<footer class="card-footer">
<button id="btnFilesOpenTodoFile" class="card-footer-item" tabindex="0"><i class="fas fa-folder-open"></i>&nbsp;<span id="modalChangeFileOpen"></span></button>
<button id="btnFilesCreateTodoFile" class="card-footer-item" tabindex="0"><i class="fas fa-plus-circle"></i>&nbsp;<span id="modalChangeFileCreate"></span></button>
<button class="card-footer-item" role="cancel" tabindex="0"></button>
<button id="btnFilesCancel" class="card-footer-item" role="cancel" tabindex="0"></button>
</footer>
</div>
</div>
</div>
<div id="modalPrompt" class="modal">
<div class="modal-background"></div>
<div class="modal-background" role="cancel"></div>
<div class="modal-content">
<div class="card">
<div id="modalPromptContent" class="card-content"></div>
......@@ -826,13 +826,13 @@
<section id="messages">
<article id="messageGenericContainer" class="notification" data="generic">
<button id="messageGenericContainerClose" class="delete" aria-label="delete" data-message="generic"></button>
<button id="messageGenericContainerClose" class="delete" role="cancel" data-message="generic"></button>
<p id="messageGenericMessage"></p>
</article>
<article class="message fixed" data="logging">
<div class="message-header">
<p><span id="messageLoggingTitle"></span></p>
<button class="delete close" aria-label="delete" data-message="logging" tabindex="-1"></button>
<button class="delete close" role="cancel" data-message="logging" tabindex="-1"></button>
</div>
<div class="message-body">
<p><span id="messageLoggingBody"></span></p>
......@@ -842,7 +842,7 @@
<article class="message fixed" data="share">
<div class="message-header">
<p><span id="messageShareTitle"></span></p>
<button class="delete close" aria-label="delete" data-message="share" tabindex="-1"></button>
<button class="delete close" role="cancel" data-message="share" tabindex="-1"></button>
</div>
<div class="message-body">
<p><span id="messageShareBody"></span></p>
......
......@@ -5,6 +5,7 @@ import { createModalJail } from "./jail.mjs";
import { getConfirmation } from "./prompt.mjs";
import { handleError } from "./helper.mjs";
const html = document.getElementById("html");
const addAsTodo = document.getElementById("addAsTodo");
const compactViewBody = document.getElementById("compactViewBody");
const compactViewHeadline = document.getElementById("compactViewHeadline");
......@@ -59,7 +60,6 @@ const helpTabRecurrencesTitle1 = document.getElementById("helpTabRecurrencesTitl
const modalWindows = document.querySelectorAll(".modal");
const reviewSourceforge = document.getElementById("reviewSourceforge");
const reviewWindowsStore = document.getElementById("reviewWindowsStore");
const settingsLanguage = document.getElementById("settingsLanguage");
const settingsTabAbout = document.getElementById("settingsTabAbout");
const settingsTabAboutContribute = document.getElementById("settingsTabAboutContribute");
const settingsTabAboutCopyrightLicense = document.getElementById("settingsTabAboutCopyrightLicense");
......@@ -83,13 +83,11 @@ const shareFacebook = document.getElementById("shareFacebook");
const shareLinkedin = document.getElementById("shareLinkedin");
const shareTwitter = document.getElementById("shareTwitter");
const submitIssuesOnGithub = document.getElementById("submitIssuesOnGithub");
const toggleNotifications = document.getElementById("toggleNotifications");
const toggleTheme = document.getElementById("toggleTheme");
const toggleTray = document.getElementById("tray");
const zoom = document.getElementById("zoom");
const zoomBody = document.getElementById("zoomBody");
const zoomHeadline = document.getElementById("zoomHeadline");
const zoomUndo = document.getElementById("zoomUndo");
const language = document.getElementById("language");
addAsTodo.innerHTML = translations.addAsTodo;
compactViewBody.innerHTML = translations.compactViewBody;
......@@ -180,7 +178,7 @@ language.onchange = function() {
handleError(error);
});
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Settings", "Language changed to: " + languageCode]);
if(userData.matomoEvents) _paq.push(["trackEvent", "Settings", "Language changed to: " + this.value]);
}
zoom.onchange = function() {
setZoom(this.value).then(response => {
......@@ -230,7 +228,6 @@ function setZoom(value) {
function setLanguage(languageCode) {
window.api.send("changeLanguage", languageCode);
}
function setFriendlyLanguageNames() {
try {
......@@ -265,9 +262,7 @@ function setFriendlyLanguageNames() {
return Promise.reject(error);
}
}
export function showModal(modalId) {
try {
// in case a content window was open, it will be closed
......@@ -326,9 +321,7 @@ export function showModal(modalId) {
error.functionName = showModal.name;
return Promise.reject(error);
}
}
// generate friendly names for language dropdown
setFriendlyLanguageNames().then(function(response) {
console.info(response);
......
......@@ -31,7 +31,7 @@ export const startDragging = (event) => {
document.body.removeEventListener("pointermove", mouseDragHandler);
return;
}
const paneOriginAdjustment = ("left" === "right") ? 1 : -1;
const paneOriginAdjustment = -1;
setPaneWidth((xOffset - moveEvent.pageX ) * paneOriginAdjustment + startingPaneWidth);
};
document.body.addEventListener("pointermove", mouseDragHandler);
......
"use strict";
import { setUserData, translations, userData } from "../render.js";
import { resetFilters } from "./filters.mjs";
import { show } from "./form.mjs";
import { resetModal, handleError } from "./helper.mjs";
import { show, resetForm } from "./form.mjs";
import { handleError } from "./helper.mjs";
import { showModal } from "./content.mjs";
import { _paq } from "./matomo.mjs";
import { getConfirmation } from "./prompt.mjs";
......@@ -22,17 +22,13 @@ const filterContext = document.getElementById("filterContext");
const todoContext = document.getElementById("todoContext");
const todoTable = document.getElementById("todoTable");
const btnMessageLogging = document.getElementById("btnMessageLogging");
const modalBackground = document.querySelectorAll('.modal-background');
const modalClose = document.querySelectorAll('.close');
const modalBackgrounds = document.querySelectorAll(".modal-background");
const modalClose = document.querySelectorAll(".close");
const cancel = document.querySelectorAll("[role='cancel']");
cancel.forEach(function(item) {
item.innerHTML = translations.cancel;
});
export function registerEvents() {
try {
body.onclick = async function(event) {
// close todo context if click is outside of it
if(filterContext.classList.contains("is-active")) {
if(!filterContext.contains(event.target)) {
......@@ -46,32 +42,40 @@ export function registerEvents() {
todoContext.classList.remove("is-active");
}
}
// TODO: describe
if(recurrencePickerContainer.classList.contains("is-active")) {
if(!recurrencePickerContainer.contains(event.target)) {
recurrencePickerContainer.classList.remove("is-active");
}
}
}
a.forEach(el => el.addEventListener("click", function(el) {
if(el.target.href && el.target.href === "#") el.preventDefault();
}));
btnMessageLogging.onclick = function () {
showModal("modalSettings");
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Message", "Click on Settings"]);
}
btnFilesCreateTodoFile.onclick = function() {
window.api.send("openOrCreateFile", "create");
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Change-Modal", "Click on Create file"]);
}
btnFilesOpenTodoFile.onclick = function() {
window.api.send("openOrCreateFile", "open");
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Change-Modal", "Click on Open file"]);
}
btnAddTodoContainer.onclick = function () {
// just in case the form will be cleared first
resetModal().then(function(response) {
console.info(response);
}).catch(function(error) {
handleError(error);
});
show();
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Menu", "Click on add todo"]);
......@@ -83,67 +87,50 @@ export function registerEvents() {
if(userData.matomoEvents) _paq.push(["trackEvent", "Error-Container", "Click on Copy to clipboard"]);
}
});
btnFiltersResetFilters.onclick = function() {
resetFilters(true);
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Filter-Drawer", "Click on reset button"])
}
btnNoResultContainerResetFilters.onclick = function() {
resetFilters(true);
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "No Result Container", "Click on reset button"])
}
// event for all cancel buttons
cancel.forEach(function(el) {
el.onclick = function(event) {
event.preventDefault;
el.parentElement.parentElement.parentElement.parentElement.classList.remove("is-active");
resetModal().then(function(response) {
console.info(response);
}).catch(function(error) {
handleError(error);
});
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Form", "Click on Cancel"]);
}
});
messageGenericContainerClose.onclick = function() {
this.parentElement.classList.remove("is-active")
}
modalBackground.forEach(function(el) {
el.onclick = function() {
const modalObject = document.getElementById(el.parentElement.id);
if(modalObject.id==="modalPrompt") return false;
// if modal is modalForm and input is equal the data item
if(modalObject.id === "modalForm" && modalForm.getAttribute("data-item") !== document.getElementById("modalFormInput").value) {
getConfirmation(resetModal, translations.modalBackgroundAttention, modalObject);
} else {
resetModal(modalObject).then(function(result) {
console.log(result);
// event for all cancel buttons
cancel.forEach(function(element) {
element.onclick = function(event) {
event.preventDefault();
// in case this is a message, closing will be persisted
if(element.getAttribute("data-message") && !userData.dismissedMessages.includes(element.getAttribute("data-message"))) {
userData.dismissedMessages.push(element.getAttribute("data-message"));
setUserData("dismissedMessages", userData.dismissedMessages);
}
const modal = this.closest(".modal, .message");
modal.classList.remove("is-active");
if(modal.id === "modalForm") {
resetForm().then(function(response) {
console.info(response);
}).catch(function(error) {
handleError(error);
});
}
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Modal", "Click on Background"]);
}
});
modalClose.forEach(function(el) {
el.onclick = function() {
if(el.getAttribute("data-message")) {
// persist closed message, so it won't show again
if(!userData.dismissedMessages.includes(el.getAttribute("data-message"))) userData.dismissedMessages.push(el.getAttribute("data-message"))
setUserData("dismissedMessages", userData.dismissedMessages);
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Message", "Click on Close"]);
} else {
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Modal", "Click on Close"]);
}
el.parentElement.parentElement.classList.remove("is-active");
if(userData.matomoEvents) _paq.push(["trackEvent", "Form", "Click on Cancel"]);
}
});
messageGenericContainerClose.onclick = function() {
this.parentElement.classList.remove("is-active")
}
return Promise.resolve("Success: Events registered");
} catch(error) {
error.functionName = register.name;
return Promise.reject(error);
......
"use strict";
import { _paq } from "./matomo.mjs";
import { appData, userData, getUserData, setUserData, translations } from "../render.js";
import { appData, userData, setUserData, translations } from "../render.js";
import { createModalJail } from "./jail.mjs";
import { focusRow } from "./keyboard.mjs";
import { resetFilters } from "./filters.mjs";
import { resetModal, handleError } from "./helper.mjs";
import { handleError } from "./helper.mjs";
import { showOnboarding } from "./onboarding.mjs";
const fileTabBar = document.getElementById("fileTabBar");
......@@ -12,10 +11,12 @@ const fileTabBarList = document.querySelector("#fileTabBar ul");
const modalChangeFile = document.getElementById("modalChangeFile");
const modalChangeFileCreate = document.getElementById("modalChangeFileCreate");
const modalChangeFileOpen = document.getElementById("modalChangeFileOpen");
const btnFilesCancel = document.getElementById("btnFilesCancel");
const modalChangeFileTable = document.getElementById("modalChangeFileTable");
modalChangeFileCreate.innerHTML = translations.createFile;
modalChangeFileOpen.innerHTML = translations.openFile;
btnFilesCancel.innerHTML = translations.cancel;
function removeFileFromList(index, removeFile) {
try {
......@@ -76,11 +77,6 @@ function removeFileFromList(index, removeFile) {
newIndex = 0;
}
// add active flag from file
//userData.files[newIndex][0] = 1;
// add tab bar flag from file
//userData.files[newIndex][2] = 1;
setUserData("files", userData.files).then(response => {
console.info(response);
}).catch(error => {
......
......@@ -3,13 +3,12 @@ import { userData, setUserData, translations, startBuilding } from "../render.js
import { createModalJail } from "./jail.mjs";
import { _paq } from "./matomo.mjs";
import { items } from "./todos.mjs";
import { getCaretPosition } from "./form.mjs";
import { showModal } from "./content.mjs";
import { getConfirmation } from "./prompt.mjs";
import { isToday, isPast, isFuture } from "./date.mjs";
import * as filterlang from "./filterlang.mjs";
import { runQuery } from "./filterquery.mjs";
import { handleError } from "./helper.mjs";
import { handleError, getCaretPosition } from "./helper.mjs";
const todoTableSearch = document.getElementById("todoTableSearch");
const autoCompleteContainer = document.getElementById("autoCompleteContainer");
......@@ -445,8 +444,10 @@ function addFilterToInput(filter, autoCompletePrefix) {
// empty autoCompleteValue to prevent multiple inputs using multiple Enter presses
autoCompletePrefix = null;
// hide the suggestion container after the filter has been selected
// hide and clear the suggestion container after the filter has been selected
autoCompleteContainer.blur();
autoCompleteContainer.innerHTML = "";
autoCompleteContainer.classList.remove("is-active");
// put focus back into input so user can continue writing
modalFormInput.focus();
......@@ -528,9 +529,9 @@ function generateFilterButtons(category, autoCompletePrefix) {
// autocomplete container
} else {
// add filter to input
todoFiltersItem.addEventListener("click", () => {
addFilterToInput(todoFiltersItem.getAttribute("data-filter"), autoCompletePrefix);
});
todoFiltersItem.onclick = function() {
addFilterToInput(this.getAttribute("data-filter"), autoCompletePrefix);
}
}
filterCounter++;
filterFragment.appendChild(todoFiltersItem);
......
This diff is collapsed.
"use strict";
import { appData, userData, setUserData, translations } from "../render.js";
import { generateGroups, items } from "./todos.mjs";
import { generateGroups, items, createTodoObject } from "./todos.mjs";
import { isToday, isPast } from "./date.mjs";
import { generateFileTabs } from "./files.mjs";
import { showGenericMessage } from "./messages.mjs";
......@@ -116,42 +116,6 @@ export function getBadgeCount() {
});
return count;
}
export function resetModal(modal) {
try {
const modalForm = document.getElementById("modalForm");
if(modal) {
// remove is-active from modal
modal.classList.remove("is-active");
// remove any previously set data-item attributes
modal.removeAttribute("data-item");
}
// reset priority setting
document.getElementById("priorityPicker").selectedIndex = 0;
// if recurrence picker was open it is now being closed
document.getElementById("recurrencePickerContainer").classList.remove("is-active");
// clear previous recurrence selection
document.getElementById("recurrencePickerInput").value = null;
// if file chooser was open it is now being closed
document.getElementById("modalChangeFile").classList.remove("is-active");
// hide suggestion box if it was open
document.getElementById("autoCompleteContainer").classList.remove("is-active");
// remove focus from suggestion container
document.getElementById("autoCompleteContainer").blur();
// close
modalForm.classList.remove("is-active");
// remove the data item as we don't need it anymore
//modalForm.removeAttribute("data-item");
modalForm.setAttribute("data-item", "");
// clean up the modal
document.getElementById("modalFormAlert").parentElement.classList.remove("is-active", 'is-warning', 'is-danger');
// clear the content in the input field as it's not needed anymore
document.getElementById("modalFormInput").value = null;
return Promise.resolve("Info: Modal closed and cleaned up");
} catch (error) {
error.functionName = resetModal.name;
return Promise.reject(error);
}
}
export function configureMainView() {
try {
......@@ -310,3 +274,35 @@ export function formatDate(date) {
padTo2Digits(date.getDate()),
].join('-');
}
export function setDueDate(days) {
try {
const todo = createTodoObject(modalFormInput.value);
if(days === 0) {
todo.due = undefined;
todo.dueString = undefined;
} else if(days && todo.due) {
todo.due = new Date(new Date(todo.dueString).setDate(new Date(todo.dueString).getDate() + days));
todo.dueString = todo.due.toISOString().substr(0, 10);
// when no due date is available we fallback to todays date
} else if(days && !todo.due) {
todo.due = new Date(new Date().setDate(new Date().getDate() + days));
todo.dueString = todo.due.toISOString().substr(0, 10);
}
modalFormInput.value = todo.toString();
return Promise.resolve("Success: Due date changed to " + todo.dueString)
} catch(error) {
error.functionName = setDueDate.name;
return Promise.reject(error);
}
}
export function getCaretPosition(element) {
if((element.selectionStart !== null) && (element.selectionStart !== undefined)) return element.selectionStart;
return false;
}
\ No newline at end of file
......@@ -38,7 +38,7 @@ export function createModalJail(modal) {
return Promise.resolve("Success: Created jail for " + modal.id);
} catch(error) {
error.functionName = showModal.name;
error.functionName = createModalJail.name;
return Promise.reject(error);
}
......
"use strict";
import { createTodoContext, setTodoComplete, archiveTodos, items } from "./todos.mjs";
import { getConfirmation } from "./prompt.mjs";
import { pasteItemsToClipboard } from "./helper.mjs";
import { pasteItemsToClipboard, setDueDate } from "./helper.mjs";
import { removeFileFromList } from "./files.mjs";
import { resetFilters } from "./filters.mjs";