- HTML-Vorlagen werden separat verteilt (nicht mehr im Plugin-Repo) - background.js: insertText API für korrekte Darstellung im Composer - background.js: automatischer Wechsel zu HTML-Modus bei Plain-Text - Options-Seite: komplett überarbeitetes UI mit Hotel-Branding - Popup: deutsches UI, gestylte Template-Auswahl - Notifications auf Deutsch - Fertige XPI im Repo
253 lines
8.1 KiB
JavaScript
253 lines
8.1 KiB
JavaScript
// templates_options/templates_options.js
|
|
|
|
const TEMPLATE_STORAGE_KEY = 'message_templates';
|
|
|
|
// Initialization of IDs
|
|
const templateForm = document.getElementById('template-form');
|
|
const templateList = document.getElementById('templates-list');
|
|
const noTemplatesMessage = document.getElementById('no-templates');
|
|
const saveButton = document.getElementById('save-button');
|
|
const cancelButton = document.getElementById('cancel-edit');
|
|
const formLegend = document.getElementById('form-legend');
|
|
|
|
/**
|
|
* Retrieves all templates from Thunderbird 'storage'
|
|
* @returns {Promise<Array>} Array of template objects
|
|
*/
|
|
async function getTemplates() {
|
|
try {
|
|
const result = await browser.storage.local.get(TEMPLATE_STORAGE_KEY);
|
|
// Returns an empty array if no data is stored
|
|
return result[TEMPLATE_STORAGE_KEY] || [];
|
|
} catch (error) {
|
|
console.error("Error retrieving templates:", error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Saves the array of templates to Thunderbird 'storage'
|
|
* @param {Array} templates Array of template objects
|
|
*/
|
|
async function saveTemplates(templates) {
|
|
try {
|
|
await browser.storage.local.set({ [TEMPLATE_STORAGE_KEY]: templates });
|
|
console.log("Templates successfully saved.");
|
|
} catch (error) {
|
|
console.error("Error saving templates:", error);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Displays templates on the HTML page
|
|
* @param {Array} templates Array of template objects
|
|
*/
|
|
function renderTemplates(templates) {
|
|
templateList.innerHTML = ''; // Clear the existing list
|
|
|
|
if (templates.length === 0) {
|
|
templateList.appendChild(noTemplatesMessage);
|
|
noTemplatesMessage.style.display = 'block';
|
|
return;
|
|
}
|
|
noTemplatesMessage.style.display = 'none';
|
|
|
|
templates.forEach(template => {
|
|
const item = document.createElement('div');
|
|
item.className = 'template-item';
|
|
item.innerHTML = `
|
|
<input type="checkbox" class="template-checkbox" data-id="${template.id}">
|
|
<span class="template-name">${template.name}</span>
|
|
<div class="template-actions">
|
|
<button data-id="${template.id}" class="edit-btn">Bearbeiten</button>
|
|
<button data-id="${template.id}" class="delete-btn">Löschen</button>
|
|
</div>
|
|
`;
|
|
templateList.appendChild(item);
|
|
});
|
|
|
|
// Adding Listeners for Edit/Delete
|
|
document.querySelectorAll('.edit-btn').forEach(button => {
|
|
button.addEventListener('click', handleEdit);
|
|
});
|
|
document.querySelectorAll('.delete-btn').forEach(button => {
|
|
button.addEventListener('click', handleDelete);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Handles form submission (Add or Save Edited)
|
|
*/
|
|
templateForm.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
|
|
const id = document.getElementById('template-id').value;
|
|
const name = document.getElementById('template-name').value;
|
|
const content = document.getElementById('template-content').value;
|
|
|
|
let templates = await getTemplates();
|
|
|
|
if (id) {
|
|
// EDITING EXISTING
|
|
const index = templates.findIndex(t => t.id === id);
|
|
if (index > -1) {
|
|
templates[index] = { id, name, content };
|
|
}
|
|
} else {
|
|
// ADDING NEW
|
|
const newId = Date.now().toString(); // Simple unique ID
|
|
templates.push({ id: newId, name, content });
|
|
}
|
|
|
|
await saveTemplates(templates);
|
|
renderTemplates(templates);
|
|
resetForm();
|
|
});
|
|
|
|
/**
|
|
* Deletes a template
|
|
*/
|
|
async function handleDelete(e) {
|
|
if (!confirm('Diese Vorlage wirklich löschen?')) {
|
|
return;
|
|
}
|
|
const idToDelete = e.target.dataset.id;
|
|
let templates = await getTemplates();
|
|
|
|
// Filter to exclude the template with that ID
|
|
templates = templates.filter(t => t.id !== idToDelete);
|
|
|
|
await saveTemplates(templates);
|
|
renderTemplates(templates);
|
|
}
|
|
|
|
/**
|
|
* Loads template data into the edit form
|
|
*/
|
|
async function handleEdit(e) {
|
|
const idToEdit = e.target.dataset.id;
|
|
const templates = await getTemplates();
|
|
const template = templates.find(t => t.id === idToEdit);
|
|
|
|
if (template) {
|
|
document.getElementById('template-id').value = template.id;
|
|
document.getElementById('template-name').value = template.name;
|
|
document.getElementById('template-content').value = template.content;
|
|
|
|
// Update UI to signal editing
|
|
formLegend.textContent = 'Vorlage bearbeiten';
|
|
saveButton.textContent = 'Aktualisieren';
|
|
cancelButton.style.display = 'inline';
|
|
|
|
// Scroll to the top of the form
|
|
window.scrollTo(0, 0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resets the editing state and clears the form
|
|
*/
|
|
function resetForm() {
|
|
templateForm.reset();
|
|
document.getElementById('template-id').value = '';
|
|
|
|
formLegend.textContent = 'Neue Vorlage erstellen';
|
|
saveButton.textContent = 'Speichern';
|
|
cancelButton.style.display = 'none';
|
|
}
|
|
|
|
cancelButton.addEventListener('click', resetForm);
|
|
|
|
/**
|
|
* Select all / deselect all checkboxes
|
|
*/
|
|
document.getElementById('select-all-button').addEventListener('click', () => {
|
|
const checkboxes = document.querySelectorAll('.template-checkbox');
|
|
const allChecked = Array.from(checkboxes).every(cb => cb.checked);
|
|
checkboxes.forEach(cb => cb.checked = !allChecked);
|
|
});
|
|
|
|
/**
|
|
* Delete all selected templates
|
|
*/
|
|
document.getElementById('delete-selected-button').addEventListener('click', async () => {
|
|
const checked = document.querySelectorAll('.template-checkbox:checked');
|
|
if (checked.length === 0) return;
|
|
|
|
if (!confirm(`${checked.length} Template(s) wirklich löschen?`)) return;
|
|
|
|
const idsToDelete = new Set(Array.from(checked).map(cb => cb.dataset.id));
|
|
let templates = await getTemplates();
|
|
templates = templates.filter(t => !idsToDelete.has(t.id));
|
|
|
|
await saveTemplates(templates);
|
|
renderTemplates(templates);
|
|
});
|
|
|
|
/**
|
|
* Handles import of HTML files as templates.
|
|
* Filename (without extension) becomes the template name.
|
|
* Existing templates with the same name are overwritten.
|
|
*/
|
|
document.getElementById('import-button').addEventListener('click', async () => {
|
|
const fileInput = document.getElementById('import-files');
|
|
const statusEl = document.getElementById('import-status');
|
|
const files = fileInput.files;
|
|
|
|
if (files.length === 0) {
|
|
statusEl.textContent = 'Bitte Dateien auswählen!';
|
|
statusEl.style.color = 'red';
|
|
statusEl.style.display = 'inline';
|
|
return;
|
|
}
|
|
|
|
let templates = await getTemplates();
|
|
let importCount = 0;
|
|
|
|
for (const file of files) {
|
|
const content = await file.text();
|
|
const name = file.name.replace(/\.html?$/i, '');
|
|
|
|
// Extract body content if it's a full HTML document
|
|
let body = content;
|
|
const bodyMatch = content.match(/<body[^>]*>([\s\S]*)<\/body>/i);
|
|
if (bodyMatch) {
|
|
body = bodyMatch[1].trim();
|
|
}
|
|
|
|
// Check if template with same name exists
|
|
const existingIndex = templates.findIndex(
|
|
t => t.name.toLowerCase() === name.toLowerCase()
|
|
);
|
|
|
|
if (existingIndex > -1) {
|
|
// Overwrite existing
|
|
templates[existingIndex].content = body;
|
|
} else {
|
|
// Add new
|
|
templates.push({
|
|
id: Date.now().toString() + importCount,
|
|
name: name,
|
|
content: body
|
|
});
|
|
}
|
|
importCount++;
|
|
}
|
|
|
|
await saveTemplates(templates);
|
|
renderTemplates(templates);
|
|
|
|
statusEl.textContent = `${importCount} Vorlage(n) importiert!`;
|
|
statusEl.style.color = 'green';
|
|
statusEl.style.display = 'inline';
|
|
fileInput.value = '';
|
|
|
|
setTimeout(() => { statusEl.style.display = 'none'; }, 3000);
|
|
});
|
|
|
|
// Load templates on page load
|
|
window.addEventListener('load', async () => {
|
|
const templates = await getTemplates();
|
|
renderTemplates(templates);
|
|
}); |