413 lines
14 KiB
JavaScript
413 lines
14 KiB
JavaScript
import { state } from './state.js';
|
|
import { toggleFields } from './home.js';
|
|
|
|
/**
|
|
* Toggles the visibility of the note list and reference elements.
|
|
*
|
|
* @param {boolean} [openSidebar=true] - Whether to open the sidebar after toggling the visibility.
|
|
* @return {void}
|
|
*/
|
|
export function openNote(openSidebar = true) {
|
|
const noteList = document.querySelector('#note-list');
|
|
const refs = document.querySelector('#ref');
|
|
|
|
if (noteList.style.display == 'block') {
|
|
noteList.style.display = 'none';
|
|
refs.style.display = 'block';
|
|
} else {
|
|
noteList.style.display = 'block';
|
|
refs.style.display = 'none';
|
|
}
|
|
|
|
if (openSidebar) {
|
|
document.querySelector('.toggle').click();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Starts the save process by updating the save-check element's classList, removing error, fa-times-circle, and fa-save classes,
|
|
* adding the 'saving' and 'fa-save' classes, and setting the opacity to 1.
|
|
*
|
|
* @return {void} This function does not return anything.
|
|
*/
|
|
export function startSave() {
|
|
document.querySelector('#save-check').classList.remove('error', 'fa-times-circle', 'fa-save');
|
|
document.querySelector('#save-check').classList.add('saving', 'fa-save');
|
|
document.querySelector('#save-check').style.opacity = 1;
|
|
}
|
|
|
|
/**
|
|
* Displays a checkmark animation on the screen.
|
|
*
|
|
* @param {none} - This function does not take any parameters.
|
|
* @return {none} - This function does not return any value.
|
|
*/
|
|
export function showSave() {
|
|
if (state.saved) { return; }
|
|
|
|
var checkmark = document.getElementById("save-check");
|
|
checkmark.classList.add('fa-save');
|
|
|
|
// Schedule the animation to run every 1 second (which is equivalent to a 1-second delay between each iteration)
|
|
var si = setInterval(function () {
|
|
// Increment the opacity of the checkmark by 0.01 each time
|
|
op = parseFloat(checkmark.style.opacity);
|
|
checkmark.style.opacity = op - 0.1;
|
|
|
|
// If the opacity is greater than or equal to 1, reset it back to 0 and stop the animation
|
|
if (checkmark.style.opacity == 0.1) {
|
|
checkmark.style.opacity = 0;
|
|
clearInterval(si);
|
|
state.saved = false;
|
|
}
|
|
}, 100);
|
|
}
|
|
|
|
/**
|
|
* function to discard the note by clearing all input fields and closing the menu.
|
|
*/
|
|
export function deleteNote(noteId, link) {
|
|
document.querySelector('#noteTitle').value = '';
|
|
document.querySelector('#speaker').value = 0;
|
|
document.querySelector('#series').value = 0;
|
|
document.querySelector('#template').value = 0;
|
|
document.querySelector('#passage').value = '';
|
|
document.querySelector('#notes').value = '';
|
|
document.querySelector('#recording').value = '';
|
|
document.querySelector('#noteDate').value = '';
|
|
document.querySelector('#noteId').value = '';
|
|
|
|
var row = link.parentElement.parentElement;
|
|
|
|
fetch('/delete-note', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
'id': noteId
|
|
})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.msg != 'deleted') {
|
|
return;
|
|
}
|
|
|
|
alert('Note deleted.');
|
|
row.remove();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Validates a note by checking if all required fields are filled.
|
|
*
|
|
* @return {boolean} Returns true if all required fields are filled, false otherwise.
|
|
*/
|
|
export function validateNote() {
|
|
const note = document.querySelector('#notes');
|
|
const date = document.querySelector('#noteDate');
|
|
const speaker = document.querySelector('#speaker');
|
|
const series = document.querySelector('#series');
|
|
const title = document.querySelector('#noteTitle');
|
|
const psg = document.querySelector('#passage');
|
|
|
|
let ret = true;
|
|
|
|
if (!title.value.length) { title.classList.add('input-error'); ret = false; }
|
|
if (!date.value) { date.classList.add('input-error'); ret = false; }
|
|
if (!parseInt(speaker.value)) { speaker.classList.add('input-error'); ret = false; }
|
|
if (!parseInt(series.value)) { series.classList.add('input-error'); ret = false; }
|
|
if (!psg.value) { psg.classList.add('input-error'); ret = false; }
|
|
if (!note.value.length) { note.classList.add('input-error'); ret = false; }
|
|
|
|
if (!ret) {
|
|
toggleFields(null, true);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Resets the state of the note editor by clearing the text and form fields,
|
|
* resetting the references, and removing any dirty classes. It also sets the
|
|
* date to the current date, clears the speaker, series, template, passage,
|
|
* recording, and note ID fields. Finally, it clears the reference list and
|
|
* reference display.
|
|
*
|
|
* @return {void} This function does not return anything.
|
|
*/
|
|
export function newNote() {
|
|
notes = document.querySelector('#notes');
|
|
notes.text = '';
|
|
notes.value = '';
|
|
state.references = {};
|
|
state.saved = true;
|
|
state.textDirty = false;
|
|
document.querySelector('#note-header-left h2').classList.remove('dirty');
|
|
|
|
dt = new Date();
|
|
document.querySelector('#noteDate').value = dt.getFullYear() + '-' +
|
|
(dt.getMonth() < 9 ? '0' + (dt.getMonth() + 1) : (dt.getMonth() + 1)) + '-' +
|
|
(dt.getDate() < 10 ? '0' + dt.getDate() : dt.getDate());
|
|
document.querySelector('#noteTitle').value = '';
|
|
document.querySelector('#speaker').value = 0;
|
|
document.querySelector('#series').value = 0;
|
|
document.querySelector('#template').value = 0;
|
|
document.querySelector('#passage').value = '';
|
|
document.querySelector('#recording').value = '';
|
|
document.querySelector('#noteId').value = '';
|
|
|
|
document.querySelector('#ref-list').innerHTML = '';
|
|
document.querySelector('#ref').innerHTML = '';
|
|
document.querySelector('.toggle').click();
|
|
}
|
|
|
|
/**
|
|
* Save a note by sending it to the server for storage.
|
|
*
|
|
* @param {Event} event - The event object triggering the save action.
|
|
* @return {void} No explicit return value.
|
|
*/
|
|
export function saveNote(event) {
|
|
console.debug('called saveNote '+new Date());
|
|
if (event) {
|
|
event.preventDefault();
|
|
}
|
|
|
|
if (!state.textDirty) {
|
|
clearTimeout(state.to);
|
|
state.to = setTimeout(saveNote, state.saveInterval);
|
|
return;
|
|
}
|
|
|
|
document.querySelector('#noteTitle').classList.remove('input-error');
|
|
document.querySelector('#noteDate').classList.remove('input-error');
|
|
document.querySelector('#speaker').classList.remove('input-error');
|
|
document.querySelector('#series').classList.remove('input-error');
|
|
document.querySelector('#passage').classList.remove('input-error');
|
|
document.querySelector('#notes').classList.remove('input-error');
|
|
|
|
if (!validateNote()) {
|
|
clearTimeout(state.to);
|
|
state.to = setTimeout(saveNote, state.saveInterval);
|
|
return;
|
|
}
|
|
|
|
let saveCheck = document.querySelector('#save-check');
|
|
var noteText = document.querySelector('#notes').value;
|
|
|
|
startSave();
|
|
|
|
var note = {
|
|
id: document.querySelector("#noteId").value,
|
|
date: document.querySelector('#noteDate').value,
|
|
title: document.querySelector('#noteTitle').value,
|
|
speaker: document.querySelector('#speaker').value,
|
|
series: document.querySelector('#series').value,
|
|
passage: document.querySelector('#passage').value,
|
|
note: document.querySelector('#notes').value,
|
|
recording: document.querySelector('#recording').value,
|
|
refs: references
|
|
};
|
|
$.ajax({
|
|
url: '/save-note',
|
|
method: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify(note),
|
|
dataType: 'json',
|
|
timeout: state.saveTimeout
|
|
})
|
|
.done(function (data) {
|
|
if (data.msg == 'saved' && !state.saved) {
|
|
state.saveFailureCount = SAVE_FAILURE_LIMIT;
|
|
saveCheck.classList.remove('saving', 'error', 'fa-times-circle', 'fa-save');
|
|
showSave();
|
|
if (noteText == document.querySelector('#notes').value) {
|
|
state.saved = true;
|
|
state.textDirty = false;
|
|
document.querySelector('note-header h2').classList.remove('dirty');
|
|
document.querySelector('mobile-note-header h2').classList.remove('dirty');
|
|
}
|
|
|
|
if (data.new) {
|
|
document.querySelector('#noteId').value = data.id;
|
|
}
|
|
}
|
|
})
|
|
.fail(function (xhr, status, error) {
|
|
state.saveFailureCount--;
|
|
saveCheck.classList.remove('saving', 'fa-save');
|
|
saveCheck.classList.add('fa-times-circle', 'error');
|
|
console.error(error);
|
|
})
|
|
.always(function (xhr, status) {
|
|
if (status == 'timeout') {
|
|
saveCheck.classList.remove('saving', 'fa-save');
|
|
saveCheck.classList.add('error', 'fa-times-circle');
|
|
}
|
|
clearTimeout(to);
|
|
if (state.saveFailureCount > 0) {
|
|
state.to = setTimeout(saveNote, state.saveInterval);
|
|
} else {
|
|
state.saveFailureCount = SAVE_FAILURE_LIMIT;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Function that finds reference links and fetches passage data when clicked.
|
|
*/
|
|
export function findRefLinks() {
|
|
var links = document.querySelector('#ref-text').querySelectorAll('a');
|
|
|
|
for (var i = 0; i < links.length; i++) {
|
|
links[i].addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
if (!this.href.includes('get-passage')) {
|
|
return;
|
|
}
|
|
var passage = this.href.split('/');
|
|
passage = passage[passage.length - 1];
|
|
|
|
fetch(this.href, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
'passage': passage
|
|
})
|
|
})
|
|
.then(response => response.text())
|
|
.then(result => {
|
|
passage = passage.replace(/\+/g, ' ');
|
|
psg = passage.split(' ');
|
|
if (psg.length > 2) {
|
|
book = psg[0] + ' ' + psg[1];
|
|
cv = psg[2];
|
|
} else {
|
|
book = psg[0];
|
|
cv = psg[1];
|
|
}
|
|
showPassage(
|
|
e,
|
|
"<button onclick='closePopup()'>Close</button> " +
|
|
"<button onclick=\"queryRef('bible', '" + book + "', '" + cv + "')\">Open Ref</button><br/>" +
|
|
result);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Finds all links in the note preview and adds event listeners to them.
|
|
*
|
|
* @return {void}
|
|
*/
|
|
export function findLinks() {
|
|
var links = document.querySelector('#notePreview').querySelectorAll('a');
|
|
|
|
for (var i = 0; i < links.length; i++) {
|
|
links[i].addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
if (!this.href.includes('get-passage')) {
|
|
return;
|
|
}
|
|
var passage = this.href.split('/');
|
|
passage = passage[passage.length - 1];
|
|
|
|
fetch(this.href, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
'passage': passage
|
|
})
|
|
})
|
|
.then(response => response.text())
|
|
.then(result => {
|
|
passage = passage.replace(/\+/g, ' ');
|
|
psg = passage.split(' ');
|
|
if (psg.length > 2) {
|
|
book = psg[0] + ' ' + psg[1];
|
|
cv = psg[2];
|
|
} else {
|
|
book = psg[0];
|
|
cv = psg[1];
|
|
}
|
|
showPassage(
|
|
e,
|
|
"<button onclick='home.closePopup()'>Close</button> " +
|
|
"<button onclick=\"home.queryRef('bible', '" + book + "', '" + cv + "')\">Open Ref</button><br/>" +
|
|
result);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Opens the share note functionality.
|
|
*/
|
|
export function openShareNote() {
|
|
var id = document.querySelector('#noteId').value;
|
|
if (!id) {
|
|
alert('No Open Note Found');
|
|
return;
|
|
}
|
|
|
|
bd = document.querySelector('#modal-backdrop');
|
|
bd.style.display = 'block';
|
|
cont = document.querySelector('#modal-container');
|
|
cont.style.display = bd.style.display;
|
|
|
|
emailCont = document.querySelector('#modal-container');
|
|
emailCont.style.left = ((window.innerWidth / 2) - (emailCont.clientWidth / 2)) + 'px';
|
|
emailCont.style.top = ((window.innerHeight / 2) - (emailCont.clientHeight / 2)) + 'px';
|
|
}
|
|
|
|
/**
|
|
* Closes the share note modal by hiding the backdrop and container,
|
|
* and clears the email input value.
|
|
*/
|
|
export function closeShareNote() {
|
|
var bd = document.querySelector('#modal-backdrop');
|
|
var cont = document.querySelector('#modal-container');
|
|
bd.style.display = 'none';
|
|
cont.style.display = 'none';
|
|
document.querySelector('#shareEmail').value = '';
|
|
}
|
|
|
|
/**
|
|
* Function to share a note by sending the note ID and email to the server.
|
|
*/
|
|
export function shareNote(event) {
|
|
var id = document.querySelector('#noteId').value;
|
|
var email = document.querySelector('#shareEmail').value;
|
|
if (!id || !email) {
|
|
alert('Invalid Input');
|
|
return;
|
|
}
|
|
|
|
fetch('/share-note', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
'id': id,
|
|
'email': email
|
|
})
|
|
})
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
if (result) {
|
|
alert(result.msg);
|
|
}
|
|
});
|
|
|
|
closeShareNote();
|
|
}
|
|
|