import * as api from '../api.js';
import { showModal } from '../components/modal.js';
const el = () => document.getElementById('page-mappings');
export async function initMappings() {
el().innerHTML = `
App Mappings
Map process names, window titles, or URLs to categories
+ New Mapping
`;
document.getElementById('btn-new-mapping').addEventListener('click', () => showMappingForm());
await loadMappings();
}
async function loadMappings() {
try {
const mappings = await api.mappings.list();
const container = document.getElementById('mapping-list');
if (!mappings || !mappings.length) {
container.innerHTML = `No mappings configured
`;
return;
}
container.innerHTML = `
Pattern Match Type Category Friendly Name Actions
${mappings.map(m => `
${esc(m.pattern)}
${m.matchType}
${esc(m.category)}
${esc(m.friendlyName) || '- '}
Edit
Delete
`).join('')}
`;
container.querySelectorAll('[data-edit]').forEach(btn => {
btn.addEventListener('click', () => {
const m = mappings.find(x => x.id === parseInt(btn.dataset.edit));
if (m) showMappingForm(m);
});
});
container.querySelectorAll('[data-delete]').forEach(btn => {
btn.addEventListener('click', () => confirmDelete(parseInt(btn.dataset.delete)));
});
} catch (e) {
document.getElementById('mapping-list').innerHTML = `Failed to load mappings
`;
}
}
function showMappingForm(existing = null) {
const title = existing ? 'Edit Mapping' : 'New Mapping';
showModal(title, `
Pattern *
Match Type *
Process Name
Title Contains
URL Contains
Category *
Friendly Name
`,
[
{ label: 'Cancel', onClick: () => {} },
{
label: existing ? 'Save' : 'Create', cls: 'btn-primary', onClick: async (modal) => {
const pattern = modal.querySelector('#map-pattern').value.trim();
const matchType = modal.querySelector('#map-match-type').value;
const category = modal.querySelector('#map-category').value.trim();
const friendlyName = modal.querySelector('#map-friendly').value.trim() || null;
if (!pattern || !category) { alert('Pattern and Category are required'); throw new Error('cancel'); }
const body = { pattern, matchType, category, friendlyName };
if (existing) await api.mappings.update(existing.id, body);
else await api.mappings.create(body);
loadMappings();
},
},
]);
setTimeout(() => document.getElementById('map-pattern')?.focus(), 100);
}
function confirmDelete(id) {
showModal('Delete Mapping', `Are you sure you want to delete this mapping?
`, [
{ label: 'Cancel', onClick: () => {} },
{
label: 'Delete', cls: 'btn-danger', onClick: async () => {
await api.mappings.remove(id);
loadMappings();
},
},
]);
}
function esc(str) {
if (!str) return '';
const d = document.createElement('div');
d.textContent = str;
return d.innerHTML;
}