297 lines
9.9 KiB
JavaScript
297 lines
9.9 KiB
JavaScript
document.addEventListener("DOMContentLoaded", function () {
|
|
attachEventListeners();
|
|
initializeTagifyOnNotes();
|
|
initializeDarkModeToggle();
|
|
setInitialDarkModeState();
|
|
});
|
|
|
|
function attachEventListeners() {
|
|
attachCollapseListeners();
|
|
manageAreaState();
|
|
attachTaskClickListeners();
|
|
attachProjectModalListeners();
|
|
attachAreaModalListeners();
|
|
attachNoteClickListeners();
|
|
}
|
|
|
|
function initializeDarkModeToggle() {
|
|
const darkModeToggle = document.querySelector('#darkModeToggle');
|
|
const darkModeIcon = document.querySelector('#darkModeIcon');
|
|
const isDarkMode = localStorage.getItem('darkMode') === 'true';
|
|
|
|
updateDarkMode(isDarkMode);
|
|
|
|
darkModeToggle.addEventListener('click', function () {
|
|
const isDarkMode = localStorage.getItem('darkMode') === 'true';
|
|
updateDarkMode(!isDarkMode);
|
|
});
|
|
}
|
|
|
|
function updateDarkMode(enabled) {
|
|
document.body.classList.toggle('dark-mode', enabled);
|
|
localStorage.setItem('darkMode', enabled);
|
|
darkModeIcon.classList.toggle('bi-moon', !enabled);
|
|
darkModeIcon.classList.toggle('bi-sun', enabled);
|
|
// Update link colors and other necessary elements
|
|
updateLinkColors(enabled);
|
|
updateDropdownMenus(enabled);
|
|
}
|
|
|
|
function updateLinkColors(darkModeEnabled) {
|
|
const links = document.querySelectorAll('.link-dark, .link-light');
|
|
links.forEach(link => {
|
|
link.classList.toggle('link-dark', !darkModeEnabled);
|
|
link.classList.toggle('link-light', darkModeEnabled);
|
|
});
|
|
}
|
|
|
|
function setInitialDarkModeState() {
|
|
const isDarkMode = localStorage.getItem('darkMode') === 'true';
|
|
const darkModeToggle = document.querySelector('#darkModeToggle');
|
|
if (darkModeToggle) {
|
|
darkModeToggle.checked = isDarkMode;
|
|
document.body.classList.toggle('dark-mode', isDarkMode);
|
|
updateLinkColors(isDarkMode);
|
|
}
|
|
}
|
|
|
|
function updateDropdownMenus(enableDarkMode) {
|
|
document.querySelectorAll('.dropdown-menu').forEach(menu => {
|
|
menu.classList.toggle('dropdown-menu-dark', enableDarkMode);
|
|
});
|
|
}
|
|
|
|
function initializeTagifyOnNotes() {
|
|
document.querySelectorAll('[id^="note_tags_new_"]').forEach(function(element) {
|
|
new Tagify(element);
|
|
});
|
|
}
|
|
|
|
function attachCollapseListeners() {
|
|
document.querySelectorAll('.collapse').forEach(collapseElement => {
|
|
collapseElement.addEventListener('show.bs.collapse', () => toggleFolderIcon(collapseElement, true));
|
|
collapseElement.addEventListener('hide.bs.collapse', () => toggleFolderIcon(collapseElement, false));
|
|
});
|
|
}
|
|
|
|
function manageAreaState() {
|
|
document.querySelectorAll('.area-item a.nav-link').forEach(link => {
|
|
const areaId = link.getAttribute('href').replace('#', '');
|
|
const areaElement = document.getElementById(areaId);
|
|
if (areaElement) {
|
|
const isExpanded = localStorage.getItem('#' + areaId) === 'true';
|
|
if (isExpanded) {
|
|
link.setAttribute('aria-expanded', 'true');
|
|
areaElement.classList.add('show');
|
|
} else {
|
|
link.setAttribute('aria-expanded', 'false');
|
|
areaElement.classList.remove('show');
|
|
}
|
|
}
|
|
});
|
|
|
|
// Save the state of areas when clicked
|
|
document.querySelectorAll('.area-item a.nav-link').forEach(link => {
|
|
link.addEventListener('click', function (event) {
|
|
event.preventDefault(); // Prevent default action to manually control collapse
|
|
const areaId = this.getAttribute('href').replace('#', '');
|
|
const isExpanded = this.getAttribute('aria-expanded') === 'false'; // Toggle the state based on current state
|
|
localStorage.setItem('#' + areaId, isExpanded);
|
|
if (isExpanded) {
|
|
this.setAttribute('aria-expanded', 'true');
|
|
document.getElementById(areaId).classList.add('show');
|
|
} else {
|
|
this.setAttribute('aria-expanded', 'false');
|
|
document.getElementById(areaId).classList.remove('show');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Ensure this function is called when the DOM is fully loaded
|
|
document.addEventListener("DOMContentLoaded", manageAreaState);
|
|
|
|
function toggleFolderIcon(collapseElement, isOpening) {
|
|
const closedFolderIcon = collapseElement.previousElementSibling?.querySelector('.bi-folder');
|
|
const openFolderIcon = collapseElement.previousElementSibling?.querySelector('.bi-folder2-open');
|
|
|
|
if (closedFolderIcon && openFolderIcon) {
|
|
closedFolderIcon.classList.toggle('d-none', isOpening);
|
|
openFolderIcon.classList.toggle('d-none', !isOpening);
|
|
}
|
|
}
|
|
|
|
function attachTaskClickListeners() {
|
|
document.querySelectorAll('.task-item').forEach(taskElement => {
|
|
taskElement.addEventListener('click', event => {
|
|
if (!event.target.closest('.toggle-completion')) {
|
|
openEditTaskModal(taskElement.dataset.taskId);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function openEditTaskModal(taskId) {
|
|
const formContainer = document.getElementById('edit_task_form_' + taskId);
|
|
if (!formContainer) {
|
|
console.error('Edit form not found for task: ' + taskId);
|
|
return;
|
|
}
|
|
const formHtml = formContainer.innerHTML;
|
|
const editTaskFormContainer = document.getElementById('editTaskFormContainer');
|
|
editTaskFormContainer.innerHTML = formHtml;
|
|
|
|
new Tagify(editTaskFormContainer.querySelector('#task_tags_' + taskId));
|
|
|
|
new bootstrap.Modal(document.getElementById('editTaskModal')).show();
|
|
}
|
|
|
|
function attachProjectModalListeners() {
|
|
document.querySelectorAll('[data-bs-toggle="modal"][data-project-id]').forEach(button => {
|
|
button.addEventListener('click', () => openProjectModalForEdit(button.getAttribute('data-project-id')));
|
|
});
|
|
}
|
|
|
|
function attachNoteClickListeners() {
|
|
document.querySelectorAll('.note-item').forEach(noteElement => {
|
|
noteElement.addEventListener('click', event => {
|
|
const noteId = noteElement.getAttribute('data-note-id');
|
|
if (noteId) {
|
|
openEditNoteModal(noteId);
|
|
} else {
|
|
console.error('Note ID not found for element:', noteElement);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function openEditNoteModal(noteId) {
|
|
const formContainer = document.getElementById('edit_note_form_' + noteId);
|
|
if (!formContainer) {
|
|
console.error('Edit form not found for note: ' + noteId);
|
|
return;
|
|
}
|
|
const formHtml = formContainer.innerHTML;
|
|
const editNoteFormContainer = document.getElementById('editNoteFormContainer');
|
|
editNoteFormContainer.innerHTML = formHtml;
|
|
|
|
new Tagify(editNoteFormContainer.querySelector('#note_tags_' + noteId));
|
|
|
|
new bootstrap.Modal(document.getElementById('editNoteModal')).show();
|
|
}
|
|
|
|
function openProjectModalForEdit(projectId) {
|
|
fetch('/project/' + projectId)
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error('Network response was not ok.');
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(projectData => {
|
|
document.getElementById('projectName').value = projectData.name;
|
|
document.getElementById('projectDescription').value = projectData.description || '';
|
|
var projectForm = document.getElementById('projectForm');
|
|
if (projectForm) {
|
|
projectForm.action = '/projects/' + projectId;
|
|
projectForm.method = 'patch';
|
|
}
|
|
|
|
var modal = new bootstrap.Modal(document.getElementById('editProjectModal'));
|
|
modal.show();
|
|
})
|
|
.catch(error => {
|
|
console.error('Error fetching project data:', error);
|
|
});
|
|
}
|
|
|
|
function attachAreaModalListeners() {
|
|
document.querySelectorAll('.open-new-area-modal').forEach(button => {
|
|
button.addEventListener('click', () => new bootstrap.Modal(document.getElementById('newAreaModal')).show());
|
|
});
|
|
|
|
document.querySelectorAll('.open-edit-area-modal').forEach(button => {
|
|
button.addEventListener('click', () => openEditAreaModal(button.dataset.areaId));
|
|
});
|
|
}
|
|
|
|
function deleteProject(projectId) {
|
|
if (confirm('Are you sure you want to delete this project?')) {
|
|
const form = document.getElementById('delete_project_' + projectId);
|
|
form.submit();
|
|
}
|
|
}
|
|
|
|
function deleteArea(areaId) {
|
|
if (confirm('Are you sure you want to delete this area?')) {
|
|
const form = document.getElementById('delete_area_' + areaId);
|
|
form.submit();
|
|
}
|
|
}
|
|
|
|
function openEditAreaModal(areaId) {
|
|
fetchAreaDataAndPopulateModal(areaId);
|
|
const modal = new bootstrap.Modal(document.getElementById('editAreaModal'));
|
|
modal.show();
|
|
}
|
|
|
|
function fetchAreaDataAndPopulateModal(areaId) {
|
|
fetch('/areas/' + areaId + '/data')
|
|
.then(response => response.json())
|
|
.then(areaData => {
|
|
populateAreaEditForm(areaData);
|
|
})
|
|
.catch(error => console.error('Error fetching area data:', error));
|
|
}
|
|
|
|
function populateAreaEditForm(areaData) {
|
|
document.getElementById('editAreaName').value = areaData.name;
|
|
}
|
|
|
|
function toggleTaskCompletion(event, taskId) {
|
|
event.stopPropagation();
|
|
fetch('/task/' + taskId + '/toggle_completion', {
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ _method: 'patch' })
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) throw new Error('Network response was not ok');
|
|
return response.json();
|
|
})
|
|
.then(data => updateTaskCompletionStatus(taskId, data))
|
|
.catch(error => console.error('There has been a problem with your fetch operation:', error));
|
|
}
|
|
|
|
function updateTaskCompletionStatus(taskId, data) {
|
|
const iconSpan = document.querySelector('.task-item[data-task-id="' + taskId + '"] .toggle-completion');
|
|
const taskIcon = iconSpan.querySelector('.bi');
|
|
const taskDiv = iconSpan.closest('.task-item');
|
|
|
|
if (data.done) {
|
|
taskIcon.classList.remove('bi-circle', 'text-warning', 'text-danger');
|
|
taskIcon.classList.add('bi-check-circle-fill', 'text-success');
|
|
taskDiv.classList.add('opacity-50');
|
|
|
|
} else {
|
|
taskIcon.classList.remove('bi-check-circle-fill', 'text-success');
|
|
taskIcon.classList.add('bi-circle');
|
|
taskDiv.classList.remove('opacity-50');
|
|
applyPriorityColor(taskIcon, data.priority);
|
|
}
|
|
setTimeout(() => taskDiv.remove(), 200);
|
|
}
|
|
|
|
function applyPriorityColor(taskIcon, priority) {
|
|
taskIcon.classList.remove('text-warning', 'text-danger', 'text-secondary');
|
|
switch (priority) {
|
|
case 'Medium':
|
|
taskIcon.classList.add('text-warning');
|
|
break;
|
|
case 'High':
|
|
taskIcon.classList.add('text-danger');
|
|
break;
|
|
default:
|
|
taskIcon.classList.add('text-secondary');
|
|
}
|
|
}
|