Files
led-controller/src/static/color_palette.js

145 lines
4.4 KiB
JavaScript

document.addEventListener('DOMContentLoaded', () => {
const paletteButton = document.getElementById('color-palette-btn');
const paletteModal = document.getElementById('color-palette-modal');
const closeButton = document.getElementById('color-palette-close-btn');
const paletteContainer = document.getElementById('palette-container');
const paletteNewColor = document.getElementById('palette-new-color');
const paletteAddButton = document.getElementById('palette-add-color-btn');
const profileNameDisplay = document.getElementById('palette-current-profile-name');
if (!paletteButton || !paletteModal || !paletteContainer) {
return;
}
let currentProfileId = null;
let currentPalette = [];
let currentProfileName = null;
const renderPalette = () => {
paletteContainer.innerHTML = '';
if (!currentPalette.length) {
const empty = document.createElement('p');
empty.className = 'muted-text';
empty.textContent = 'No colors in palette.';
paletteContainer.appendChild(empty);
return;
}
currentPalette.forEach((color, index) => {
const row = document.createElement('div');
row.className = 'profiles-row';
row.dataset.color = color;
const swatch = document.createElement('div');
swatch.style.width = '28px';
swatch.style.height = '28px';
swatch.style.borderRadius = '4px';
swatch.style.backgroundColor = color;
swatch.style.border = '1px solid #4a4a4a';
const label = document.createElement('span');
label.textContent = color;
const removeButton = document.createElement('button');
removeButton.className = 'btn btn-danger btn-small';
removeButton.textContent = 'Remove';
removeButton.addEventListener('click', async () => {
const updated = currentPalette.filter((_, i) => i !== index);
await savePalette(updated);
});
row.appendChild(swatch);
row.appendChild(label);
row.appendChild(removeButton);
paletteContainer.appendChild(row);
});
};
const loadPalette = async () => {
try {
const currentResponse = await fetch('/profiles/current', {
headers: { Accept: 'application/json' },
});
if (!currentResponse.ok) {
throw new Error('Failed to load current profile');
}
const currentData = await currentResponse.json();
currentProfileId = currentData.id || null;
const profile = currentData.profile || null;
currentProfileName = profile ? profile.name : null;
if (profileNameDisplay) {
profileNameDisplay.textContent = currentProfileName || currentProfileId || 'None';
}
if (!currentProfileId || !profile) {
currentPalette = [];
renderPalette();
return;
}
currentPalette = profile.palette || profile.color_palette || [];
renderPalette();
} catch (error) {
console.error('Failed to load palette:', error);
currentPalette = [];
renderPalette();
}
};
const savePalette = async (newPalette) => {
if (!currentProfileId) {
alert('No profile selected.');
return;
}
try {
const response = await fetch('/profiles/current', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
palette: newPalette,
color_palette: newPalette,
}),
});
if (!response.ok) {
throw new Error('Failed to save palette');
}
currentPalette = newPalette;
renderPalette();
} catch (error) {
console.error('Failed to save palette:', error);
alert('Failed to save palette.');
}
};
const openModal = () => {
paletteModal.classList.add('active');
loadPalette();
};
const closeModal = () => {
paletteModal.classList.remove('active');
};
paletteButton.addEventListener('click', openModal);
if (closeButton) {
closeButton.addEventListener('click', closeModal);
}
if (paletteAddButton && paletteNewColor) {
paletteAddButton.addEventListener('click', async () => {
const color = paletteNewColor.value;
if (!color) {
return;
}
if (currentPalette.includes(color)) {
alert('Color already in palette.');
return;
}
await savePalette([...currentPalette, color]);
});
}
paletteModal.addEventListener('click', (event) => {
if (event.target === paletteModal) {
closeModal();
}
});
});