2024-07-27 15:40:35 -04:00
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.log('DOM fully loaded and parsed.');
|
|
|
|
|
2024-07-27 15:40:35 -04:00
|
|
|
const paletteSelector = document.getElementById('palette-selector');
|
|
|
|
const newPaletteButton = document.getElementById('new-palette');
|
|
|
|
const newPaletteForm = document.getElementById('new-palette-form');
|
|
|
|
const createPaletteForm = document.getElementById('create-palette-form');
|
|
|
|
const addColorForm = document.getElementById('add-color-form');
|
|
|
|
const createColorForm = document.getElementById('create-color-form');
|
|
|
|
const colorEditorsDiv = document.getElementById('color-editors');
|
|
|
|
const addColorButton = document.getElementById('add-color');
|
|
|
|
const savePaletteButton = document.getElementById('save-palette');
|
2024-07-28 18:06:05 -04:00
|
|
|
const exportPaletteButton = document.getElementById('export-palette');
|
|
|
|
const importPaletteButton = document.getElementById('import-palette');
|
|
|
|
const importFileInput = document.getElementById('import-file');
|
|
|
|
const renamePaletteButton = document.getElementById('rename-palette');
|
|
|
|
const renamePaletteNameInput = document.getElementById('rename-palette-name');
|
|
|
|
const deletePaletteButton = document.getElementById('delete-palette');
|
|
|
|
const deleteModal = new bootstrap.Modal(document.getElementById('deleteModal'), {});
|
|
|
|
const confirmDeleteCheckbox = document.getElementById('confirmDeleteCheckbox');
|
|
|
|
const confirmDeleteButton = document.getElementById('confirmDeleteButton');
|
|
|
|
|
|
|
|
// CSRF token
|
|
|
|
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
|
|
|
|
|
|
|
|
// Logging element states
|
|
|
|
console.log('paletteSelector:', paletteSelector);
|
|
|
|
console.log('newPaletteButton:', newPaletteButton);
|
|
|
|
console.log('newPaletteForm:', newPaletteForm);
|
|
|
|
console.log('createPaletteForm:', createPaletteForm);
|
|
|
|
console.log('addColorForm:', addColorForm);
|
|
|
|
console.log('createColorForm:', createColorForm);
|
|
|
|
console.log('colorEditorsDiv:', colorEditorsDiv);
|
|
|
|
console.log('addColorButton:', addColorButton);
|
|
|
|
console.log('savePaletteButton:', savePaletteButton);
|
|
|
|
console.log('deletePaletteButton:', deletePaletteButton);
|
|
|
|
console.log('csrfToken:', csrfToken);
|
|
|
|
|
|
|
|
if (!paletteSelector || !newPaletteButton || !newPaletteForm || !createPaletteForm || !addColorForm || !createColorForm || !colorEditorsDiv || !addColorButton || !savePaletteButton || !exportPaletteButton || !importPaletteButton || !importFileInput || !renamePaletteButton || !renamePaletteNameInput || !deletePaletteButton) {
|
|
|
|
console.error('Missing required elements on the page.');
|
|
|
|
return;
|
|
|
|
}
|
2024-07-27 15:40:35 -04:00
|
|
|
|
|
|
|
newPaletteButton.addEventListener('click', function() {
|
|
|
|
newPaletteForm.style.display = 'block';
|
|
|
|
});
|
|
|
|
|
|
|
|
createPaletteForm.addEventListener('submit', function(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
const formData = new FormData(createPaletteForm);
|
2024-07-28 18:06:05 -04:00
|
|
|
console.log('Creating new palette with data:', formData);
|
2024-07-27 15:40:35 -04:00
|
|
|
fetch('/palette-editor', {
|
|
|
|
method: 'POST',
|
2024-07-28 18:06:05 -04:00
|
|
|
body: formData,
|
|
|
|
headers: {
|
|
|
|
'X-CSRF-TOKEN': csrfToken
|
|
|
|
}
|
2024-07-27 15:40:35 -04:00
|
|
|
})
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.log('Palette created:', data);
|
|
|
|
fetchPalettes().then(() => {
|
|
|
|
const newOption = document.createElement('option');
|
|
|
|
newOption.value = data.id;
|
|
|
|
newOption.text = data.name;
|
|
|
|
paletteSelector.add(newOption);
|
|
|
|
paletteSelector.value = data.id;
|
|
|
|
loadPaletteColors(data.id);
|
|
|
|
});
|
2024-07-27 15:40:35 -04:00
|
|
|
newPaletteForm.style.display = 'none';
|
|
|
|
createPaletteForm.reset();
|
|
|
|
})
|
|
|
|
.catch(error => {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.error('Error creating palette:', error);
|
2024-07-27 15:40:35 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
paletteSelector.addEventListener('change', function() {
|
|
|
|
const paletteId = paletteSelector.value;
|
2024-07-28 18:06:05 -04:00
|
|
|
console.log('Palette selected:', paletteId);
|
2024-07-27 15:40:35 -04:00
|
|
|
if (paletteId) {
|
|
|
|
loadPaletteColors(paletteId);
|
2024-07-28 18:06:05 -04:00
|
|
|
checkPaletteRestrictions();
|
2024-07-27 15:40:35 -04:00
|
|
|
} else {
|
|
|
|
addColorForm.style.display = 'none';
|
|
|
|
colorEditorsDiv.innerHTML = '';
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
addColorButton.addEventListener('click', function() {
|
|
|
|
addColorEditor();
|
|
|
|
});
|
|
|
|
|
|
|
|
savePaletteButton.addEventListener('click', function() {
|
|
|
|
const paletteId = createColorForm.getAttribute('data-palette-id');
|
|
|
|
const colorEditors = document.querySelectorAll('.color-editor');
|
2024-07-28 18:06:05 -04:00
|
|
|
const colorUpdates = [];
|
|
|
|
|
2024-07-27 15:40:35 -04:00
|
|
|
colorEditors.forEach(editor => {
|
|
|
|
const colorId = editor.getAttribute('data-color-id');
|
|
|
|
const colorName = editor.querySelector('.color-name').value;
|
|
|
|
const colorHex = editor.querySelector('.color-hex-input').value;
|
2024-07-28 18:06:05 -04:00
|
|
|
colorUpdates.push({
|
|
|
|
colorId,
|
|
|
|
colorName,
|
|
|
|
colorHex
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
console.log('Saving palette with ID:', paletteId);
|
|
|
|
colorUpdates.forEach(({colorId, colorName, colorHex}) => {
|
|
|
|
console.log(`Saving color: ${colorName} (${colorHex}) with ID: ${colorId}`);
|
2024-07-27 15:40:35 -04:00
|
|
|
if (colorId) {
|
|
|
|
// Update existing color
|
|
|
|
fetch(`/palette-editor/${paletteId}/colors/${colorId}`, {
|
|
|
|
method: 'PUT',
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json',
|
2024-07-28 18:06:05 -04:00
|
|
|
'X-CSRF-TOKEN': csrfToken
|
2024-07-27 15:40:35 -04:00
|
|
|
},
|
|
|
|
body: JSON.stringify({ name: colorName, hex_value: colorHex })
|
|
|
|
})
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.log('Color updated:', data);
|
2024-07-27 15:40:35 -04:00
|
|
|
})
|
|
|
|
.catch(error => {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.error('Error updating color:', error);
|
2024-07-27 15:40:35 -04:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// Add new color
|
|
|
|
fetch(`/palette-editor/${paletteId}/colors`, {
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json',
|
2024-07-28 18:06:05 -04:00
|
|
|
'X-CSRF-TOKEN': csrfToken
|
2024-07-27 15:40:35 -04:00
|
|
|
},
|
|
|
|
body: JSON.stringify({ name: colorName, hex_value: colorHex })
|
|
|
|
})
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.log('Color added:', data);
|
2024-07-27 15:40:35 -04:00
|
|
|
editor.setAttribute('data-color-id', data.id);
|
|
|
|
})
|
|
|
|
.catch(error => {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.error('Error adding color:', error);
|
2024-07-27 15:40:35 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2024-07-28 18:06:05 -04:00
|
|
|
exportPaletteButton.addEventListener('click', function() {
|
|
|
|
const paletteId = paletteSelector.value;
|
|
|
|
console.log('Exporting palette with ID:', paletteId);
|
|
|
|
if (paletteId) {
|
|
|
|
fetch(`/palette-editor/${paletteId}/export`)
|
|
|
|
.then(response => {
|
|
|
|
if (!response.ok) {
|
|
|
|
throw new Error('Network response was not ok');
|
|
|
|
}
|
|
|
|
return response.blob();
|
|
|
|
})
|
|
|
|
.then(blob => {
|
|
|
|
const url = window.URL.createObjectURL(blob);
|
|
|
|
const a = document.createElement('a');
|
|
|
|
a.style.display = 'none';
|
|
|
|
a.href = url;
|
|
|
|
a.download = `${paletteSelector.options[paletteSelector.selectedIndex].text}.pal`;
|
|
|
|
document.body.appendChild(a);
|
|
|
|
a.click();
|
|
|
|
window.URL.revokeObjectURL(url);
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
console.error('Error exporting palette:', error);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
alert('Please select a palette to export.');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
importPaletteButton.addEventListener('click', function() {
|
|
|
|
importFileInput.click();
|
|
|
|
});
|
|
|
|
|
|
|
|
importFileInput.addEventListener('change', function(event) {
|
|
|
|
const file = event.target.files[0];
|
|
|
|
if (file) {
|
|
|
|
const formData = new FormData();
|
|
|
|
formData.append('file', file);
|
|
|
|
|
|
|
|
console.log('Importing palette from file:', file.name);
|
|
|
|
fetch('/palette-editor/import', {
|
|
|
|
method: 'POST',
|
|
|
|
body: formData,
|
|
|
|
headers: {
|
|
|
|
'X-CSRF-TOKEN': csrfToken
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
|
|
|
console.log('Palette imported successfully', data);
|
|
|
|
const newOption = document.createElement('option');
|
|
|
|
newOption.value = data.palette.id;
|
|
|
|
newOption.text = data.palette.name;
|
|
|
|
paletteSelector.add(newOption);
|
|
|
|
paletteSelector.value = data.palette.id;
|
|
|
|
loadPaletteColors(data.palette.id);
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
console.error('Error importing palette:', error);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
renamePaletteButton.addEventListener('click', function() {
|
|
|
|
const paletteId = paletteSelector.value;
|
|
|
|
const newName = renamePaletteNameInput.value.trim();
|
|
|
|
console.log('Renaming palette ID:', paletteId, 'to:', newName);
|
|
|
|
if (!paletteId) {
|
|
|
|
alert('Please select a palette to rename.');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!newName) {
|
|
|
|
alert('Please enter a new name for the palette.');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fetch(`/palette-editor/${paletteId}/rename`, {
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
'X-CSRF-TOKEN': csrfToken
|
|
|
|
},
|
|
|
|
body: JSON.stringify({ name: newName })
|
|
|
|
})
|
|
|
|
.then(response => {
|
|
|
|
if (!response.ok) {
|
|
|
|
throw new Error('Network response was not ok');
|
|
|
|
}
|
|
|
|
return response.json();
|
|
|
|
})
|
|
|
|
.then(data => {
|
|
|
|
console.log('Palette renamed:', data);
|
|
|
|
fetchPalettes().then(() => {
|
|
|
|
const option = Array.from(paletteSelector.options).find(option => option.value == paletteId);
|
|
|
|
if (option) {
|
|
|
|
option.text = newName;
|
|
|
|
paletteSelector.value = paletteId;
|
|
|
|
}
|
|
|
|
loadPaletteColors(paletteId);
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
console.error('Error renaming palette:', error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
deletePaletteButton.addEventListener('click', function() {
|
|
|
|
const paletteId = paletteSelector.value;
|
|
|
|
console.log('Preparing to delete palette ID:', paletteId);
|
|
|
|
if (!paletteId) {
|
|
|
|
alert('Please select a palette to delete.');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Show modal
|
|
|
|
deleteModal.show();
|
|
|
|
});
|
|
|
|
|
|
|
|
confirmDeleteCheckbox.addEventListener('change', function() {
|
|
|
|
confirmDeleteButton.disabled = !confirmDeleteCheckbox.checked;
|
|
|
|
});
|
|
|
|
|
|
|
|
confirmDeleteButton.addEventListener('click', function() {
|
|
|
|
const paletteId = paletteSelector.value;
|
|
|
|
console.log('Deleting palette with ID:', paletteId);
|
|
|
|
if (paletteId && confirmDeleteCheckbox.checked) {
|
|
|
|
fetch(`/palette-editor/${paletteId}`, {
|
|
|
|
method: 'DELETE',
|
|
|
|
headers: {
|
|
|
|
'X-CSRF-TOKEN': csrfToken
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
|
|
|
console.log('Palette deleted:', data);
|
|
|
|
fetchPalettes().then(() => {
|
|
|
|
const option = Array.from(paletteSelector.options).find(option => option.value == paletteId);
|
|
|
|
if (option) {
|
|
|
|
paletteSelector.removeChild(option);
|
|
|
|
}
|
|
|
|
const defaultPaletteOption = Array.from(paletteSelector.options).find(option => option.text === 'default-colors');
|
|
|
|
if (defaultPaletteOption) {
|
|
|
|
defaultPaletteOption.selected = true;
|
|
|
|
loadPaletteColors(defaultPaletteOption.value);
|
|
|
|
} else {
|
|
|
|
paletteSelector.value = '';
|
|
|
|
colorEditorsDiv.innerHTML = '';
|
|
|
|
}
|
|
|
|
});
|
|
|
|
deleteModal.hide();
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
console.error('Error deleting palette:', error);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2024-07-27 15:40:35 -04:00
|
|
|
function loadPaletteColors(paletteId) {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.log('Loading colors for palette ID:', paletteId);
|
2024-07-27 15:40:35 -04:00
|
|
|
fetch(`/palette-editor/${paletteId}/colors`)
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.log('Loaded palette colors:', data);
|
2024-07-27 15:40:35 -04:00
|
|
|
colorEditorsDiv.innerHTML = '';
|
|
|
|
data.forEach(color => {
|
|
|
|
addColorEditor(color.id, color.name, color.hex_value);
|
|
|
|
});
|
|
|
|
addColorForm.style.display = 'block';
|
|
|
|
createColorForm.setAttribute('data-palette-id', paletteId);
|
|
|
|
})
|
|
|
|
.catch(error => {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.error('Error loading palette colors:', error);
|
2024-07-27 15:40:35 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function addColorEditor(colorId = '', colorName = '', colorHex = '#ffffff') {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.log(`Adding color editor for color: ${colorName} (${colorHex}) with ID: ${colorId}`);
|
2024-07-27 15:40:35 -04:00
|
|
|
const editor = document.createElement('div');
|
|
|
|
editor.className = 'color-editor col-md-2 mb-3';
|
|
|
|
editor.setAttribute('data-color-id', colorId);
|
|
|
|
editor.innerHTML = `
|
|
|
|
<div class="form-row align-items-end">
|
|
|
|
<div class="col-12">
|
|
|
|
<label>Color Name:</label>
|
|
|
|
<input type="text" class="form-control color-name" value="${colorName}" required>
|
|
|
|
</div>
|
|
|
|
<div class="col-12">
|
|
|
|
<label>Color Hex:</label>
|
|
|
|
<div class="color-picker"></div>
|
|
|
|
<input type="hidden" class="color-hex-input" value="${colorHex}" required>
|
|
|
|
</div>
|
|
|
|
<div class="col-12 text-right mt-2">
|
|
|
|
<button type="button" class="btn btn-danger btn-sm delete-color"><i class="fas fa-trash-alt"></i></button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
`;
|
|
|
|
colorEditorsDiv.appendChild(editor);
|
|
|
|
|
|
|
|
const deleteButton = editor.querySelector('.delete-color');
|
|
|
|
deleteButton.addEventListener('click', function() {
|
2024-07-28 18:06:05 -04:00
|
|
|
const paletteId = createColorForm.getAttribute('data-palette-id');
|
|
|
|
if (paletteId === '1') {
|
|
|
|
alert('Cannot delete colors from the default-colors palette.');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
console.log('Deleting color ID:', colorId, 'from palette ID:', paletteId);
|
2024-07-27 15:40:35 -04:00
|
|
|
if (colorId) {
|
|
|
|
fetch(`/palette-editor/${paletteId}/colors/${colorId}`, {
|
|
|
|
method: 'DELETE',
|
|
|
|
headers: {
|
2024-07-28 18:06:05 -04:00
|
|
|
'X-CSRF-TOKEN': csrfToken
|
2024-07-27 15:40:35 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.log('Color deleted:', data.message);
|
2024-07-27 15:40:35 -04:00
|
|
|
colorEditorsDiv.removeChild(editor);
|
|
|
|
})
|
|
|
|
.catch(error => {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.error('Error deleting color:', error);
|
2024-07-27 15:40:35 -04:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
colorEditorsDiv.removeChild(editor);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const pickr = Pickr.create({
|
|
|
|
el: editor.querySelector('.color-picker'),
|
|
|
|
theme: 'classic', // or 'monolith', or 'nano'
|
|
|
|
default: colorHex,
|
|
|
|
components: {
|
|
|
|
preview: true,
|
|
|
|
opacity: false,
|
|
|
|
hue: true,
|
|
|
|
|
|
|
|
interaction: {
|
|
|
|
hex: true,
|
|
|
|
input: true,
|
|
|
|
clear: true,
|
|
|
|
save: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
pickr.on('save', (color, instance) => {
|
|
|
|
editor.querySelector('.color-hex-input').value = color.toHEXA().toString();
|
|
|
|
pickr.hide();
|
|
|
|
});
|
|
|
|
|
|
|
|
pickr.on('clear', instance => {
|
|
|
|
editor.querySelector('.color-hex-input').value = '';
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-07-28 18:06:05 -04:00
|
|
|
function fetchPalettes() {
|
|
|
|
console.log('Fetching palettes from the server');
|
|
|
|
return fetch('/palette-editor')
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
|
|
|
console.log('Fetched palettes:', data);
|
|
|
|
paletteSelector.innerHTML = '';
|
|
|
|
data.forEach(palette => {
|
|
|
|
const option = document.createElement('option');
|
|
|
|
option.value = palette.id;
|
|
|
|
option.text = palette.name;
|
|
|
|
paletteSelector.add(option);
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
console.error('Error fetching palettes:', error);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function checkPaletteRestrictions() {
|
|
|
|
const paletteId = paletteSelector.value;
|
|
|
|
const isDefaultPalette = paletteId === '1';
|
|
|
|
|
|
|
|
console.log('Checking restrictions for palette ID:', paletteId, 'isDefaultPalette:', isDefaultPalette);
|
|
|
|
|
|
|
|
deletePaletteButton.disabled = isDefaultPalette;
|
|
|
|
addColorButton.disabled = isDefaultPalette;
|
|
|
|
savePaletteButton.disabled = isDefaultPalette;
|
|
|
|
|
|
|
|
if (isDefaultPalette) {
|
|
|
|
document.querySelectorAll('.delete-color').forEach(button => {
|
|
|
|
button.disabled = true;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
document.querySelectorAll('.delete-color').forEach(button => {
|
|
|
|
button.disabled = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-27 15:40:35 -04:00
|
|
|
// Load default colors on page load
|
|
|
|
window.onload = function() {
|
2024-07-28 18:06:05 -04:00
|
|
|
console.log('Page loaded, selecting default palette if available');
|
2024-07-27 15:40:35 -04:00
|
|
|
const defaultPaletteOption = Array.from(paletteSelector.options).find(option => option.text === 'default-colors');
|
|
|
|
if (defaultPaletteOption) {
|
|
|
|
defaultPaletteOption.selected = true;
|
|
|
|
loadPaletteColors(defaultPaletteOption.value);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|