tutto di troppo: fix visualizzazione email. style: riviste icone invio ed elimina, postato aggiungi ticket al grppo e informazioni laterali da a cc.
This commit is contained in:
1 parent
9ae0cec0ca
commit
cf500aabb3
7 files changed
+743
-85
No files matched your search
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* ShortcutsView — Gestione Shortcuts e Scorciatoie da Tastiera
|
||||
* Visualizza e permette la personalizzazione delle scorciatoie da tastiera.
|
||||
*/
|
||||
const ShortcutsView = {
|
||||
editingId: null,
|
||||
|
||||
render() {
|
||||
const container = document.getElementById('view-container');
|
||||
const shortcuts = this.getShortcutsList();
|
||||
|
||||
container.innerHTML = `
|
||||
<div class="view-header" style="padding:var(--space-md) var(--space-xl); display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:var(--space-sm); border-bottom:1px solid var(--border-subtle);">
|
||||
<div style="display:flex; align-items:center; gap:var(--space-sm);">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:22px; height:22px; color:var(--accent-primary);">
|
||||
<rect x="2" y="4" width="20" height="16" rx="2" />
|
||||
<path d="M6 8h.01M10 8h.01M14 8h.01M18 8h.01M6 12h.01M10 12h.01M14 12h.01M18 12h.01M8 16h8" />
|
||||
</svg>
|
||||
<span style="font-weight:700; font-size:1.1rem;">Shortcuts e Scorciatoie da Tastiera</span>
|
||||
</div>
|
||||
<button id="sc-reset-all" class="btn btn-ghost btn-sm" style="font-size:0.82rem;">
|
||||
🔄 Ripristina Predefiniti
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div style="padding:var(--space-lg) var(--space-xl); max-width:960px;">
|
||||
<p style="color:var(--text-secondary); font-size:0.88rem; margin-bottom:var(--space-lg); line-height:1.5;">
|
||||
Personalizza o abilita/disabilita le scorciatoie da tastiera rapide per velocizzare la gestione dei ticket e delle consuntivazioni.
|
||||
</p>
|
||||
|
||||
<div style="display:flex; flex-direction:column; gap:var(--space-md);">
|
||||
${shortcuts.map(sc => this.buildShortcutRow(sc)).join('')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal per la registrazione di una nuova combinazione -->
|
||||
<div id="sc-modal" class="modal" style="display:none;">
|
||||
<div class="modal-content" style="max-width:440px; text-align:center;">
|
||||
<h3 style="margin-bottom:var(--space-xs); font-size:1.1rem;" id="sc-modal-title">Modifica Shortcut</h3>
|
||||
<p style="font-size:0.85rem; color:var(--text-muted); margin-bottom:var(--space-lg);">
|
||||
Premi la combinazione di tasti desiderata sulla tastiera (es. <kbd style="background:var(--bg-tertiary); padding:2px 6px; border-radius:4px; border:1px solid var(--border-subtle);">Ctrl</kbd> + <kbd style="background:var(--bg-tertiary); padding:2px 6px; border-radius:4px; border:1px solid var(--border-subtle);">Invio</kbd>).
|
||||
</p>
|
||||
|
||||
<div id="sc-key-recorder" tabindex="0" style="padding:var(--space-lg); background:var(--bg-tertiary); border:2px dashed var(--accent-primary); border-radius:var(--radius-md); font-size:1.2rem; font-weight:700; color:var(--accent-primary); outline:none; cursor:pointer; min-height:70px; display:flex; align-items:center; justify-content:center;">
|
||||
Premi i tasti...
|
||||
</div>
|
||||
|
||||
<div style="display:flex; justify-content:flex-end; gap:var(--space-sm); margin-top:var(--space-lg);">
|
||||
<button id="sc-modal-cancel" class="btn btn-ghost btn-sm">Annulla</button>
|
||||
<button id="sc-modal-save" class="btn btn-primary btn-sm" disabled>Conferma</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
this.bindEvents();
|
||||
},
|
||||
|
||||
getShortcutsList() {
|
||||
const list = [
|
||||
{
|
||||
id: 'create_ticket_open',
|
||||
name: 'Crea Nuovo Ticket',
|
||||
description: 'Apre la pagina di creazione di un nuovo ticket',
|
||||
context: 'Globale',
|
||||
defaultCombo: { ctrl: true, alt: true, shift: false, key: 'n', enabled: true }
|
||||
},
|
||||
{
|
||||
id: 'create_ticket_submit',
|
||||
name: 'Invia Nuovo Ticket',
|
||||
description: 'Invia il modulo e crea un nuovo ticket',
|
||||
context: 'Pagina Nuovo Ticket',
|
||||
defaultCombo: { ctrl: true, alt: false, shift: false, key: 'Enter', enabled: true }
|
||||
},
|
||||
{
|
||||
id: 'quick_edit_save',
|
||||
name: 'Salva Modifica Rapida',
|
||||
description: 'Salva le modifiche apportate nei campi di Modifica Rapida',
|
||||
context: 'Pagina Dettaglio Ticket (Modifica Rapida)',
|
||||
defaultCombo: { ctrl: true, alt: false, shift: false, key: 'Enter', enabled: true }
|
||||
}
|
||||
];
|
||||
|
||||
return list.map(item => {
|
||||
const current = App.getShortcut(item.id);
|
||||
return {
|
||||
...item,
|
||||
currentCombo: current
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
buildShortcutRow(sc) {
|
||||
const combo = sc.currentCombo;
|
||||
const label = App.formatShortcutLabel(combo);
|
||||
const keysHtml = label.split(' + ').map(k => `
|
||||
<kbd style="background:var(--bg-tertiary); color:var(--text-primary); border:1px solid var(--border-subtle); border-bottom-width:2px; padding:3px 8px; border-radius:4px; font-family:monospace; font-weight:700; font-size:0.85rem; box-shadow:0 1px 2px rgba(0,0,0,0.15);">
|
||||
${App.escapeHtml(k)}
|
||||
</kbd>
|
||||
`).join(' + ');
|
||||
|
||||
return `
|
||||
<div class="card" style="display:flex; align-items:center; justify-content:space-between; padding:var(--space-md) var(--space-lg); gap:var(--space-md); border:1px solid var(--border-subtle); flex-wrap:wrap;">
|
||||
<div style="flex:1; min-width:240px;">
|
||||
<div style="font-weight:700; font-size:0.95rem; color:var(--text-primary); display:flex; align-items:center; gap:var(--space-xs);">
|
||||
${App.escapeHtml(sc.name)}
|
||||
<span class="badge" style="background:var(--bg-tertiary); color:var(--text-muted); font-size:0.72rem; font-weight:600; padding:2px 8px; border-radius:10px;">
|
||||
${App.escapeHtml(sc.context)}
|
||||
</span>
|
||||
</div>
|
||||
<div style="font-size:0.82rem; color:var(--text-secondary); margin-top:3px;">
|
||||
${App.escapeHtml(sc.description)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex; align-items:center; gap:var(--space-lg);">
|
||||
<div style="display:flex; align-items:center; gap:4px;">
|
||||
${combo.enabled ? keysHtml : '<span style="color:var(--text-muted); font-size:0.82rem; font-style:italic;">Disabilitato</span>'}
|
||||
</div>
|
||||
|
||||
<div style="display:flex; align-items:center; gap:var(--space-xs);">
|
||||
<button class="btn btn-ghost btn-sm sc-edit-btn" data-id="${sc.id}" style="height:32px; padding:4px 10px; font-size:0.82rem;">
|
||||
✏️ Modifica
|
||||
</button>
|
||||
<label class="html-toggle-container" style="margin:0; cursor:pointer;" title="Abilita/Disabilita shortcut">
|
||||
<input type="checkbox" class="sc-toggle-input" data-id="${sc.id}" ${combo.enabled ? 'checked' : ''} />
|
||||
<span style="font-size:0.8rem; color:var(--text-secondary);">${combo.enabled ? 'Attivo' : 'Off'}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
|
||||
bindEvents() {
|
||||
// Reset all
|
||||
document.getElementById('sc-reset-all')?.addEventListener('click', () => {
|
||||
if (confirm('Ripristinare tutte le scorciatoie da tastiera ai valori predefiniti?')) {
|
||||
localStorage.removeItem('otrs_shortcuts');
|
||||
Toast.success('Shortcuts ripristinati ai valori predefiniti');
|
||||
this.render();
|
||||
}
|
||||
});
|
||||
|
||||
// Toggles
|
||||
document.querySelectorAll('.sc-toggle-input').forEach(toggle => {
|
||||
toggle.addEventListener('change', (e) => {
|
||||
const id = e.target.dataset.id;
|
||||
const current = App.getShortcut(id);
|
||||
current.enabled = e.target.checked;
|
||||
App.saveCustomShortcut(id, current);
|
||||
Toast.success(`Shortcut ${current.enabled ? 'abilitato' : 'disabilitato'}`);
|
||||
this.render();
|
||||
});
|
||||
});
|
||||
|
||||
// Edit button
|
||||
let recordedCombo = null;
|
||||
const modal = document.getElementById('sc-modal');
|
||||
const recorder = document.getElementById('sc-key-recorder');
|
||||
const saveBtn = document.getElementById('sc-modal-save');
|
||||
const cancelBtn = document.getElementById('sc-modal-cancel');
|
||||
|
||||
document.querySelectorAll('.sc-edit-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
this.editingId = btn.dataset.id;
|
||||
const item = this.getShortcutsList().find(x => x.id === this.editingId);
|
||||
document.getElementById('sc-modal-title').textContent = `Modifica: ${item ? item.name : ''}`;
|
||||
recordedCombo = null;
|
||||
recorder.innerHTML = 'Premi i tasti sulla tastiera...';
|
||||
saveBtn.disabled = true;
|
||||
modal.style.display = 'flex';
|
||||
recorder.focus();
|
||||
});
|
||||
});
|
||||
|
||||
cancelBtn?.addEventListener('click', () => {
|
||||
modal.style.display = 'none';
|
||||
});
|
||||
|
||||
recorder?.addEventListener('keydown', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Ignore lone modifier presses
|
||||
if (['Control', 'Alt', 'Shift', 'Meta'].includes(e.key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ctrl = e.ctrlKey || e.metaKey;
|
||||
const alt = e.altKey;
|
||||
const shift = e.shiftKey;
|
||||
let key = e.key;
|
||||
|
||||
if (key === ' ') key = 'Space';
|
||||
|
||||
recordedCombo = { ctrl, alt, shift, key, enabled: true };
|
||||
const label = App.formatShortcutLabel(recordedCombo);
|
||||
recorder.innerHTML = label.split(' + ').map(k => `
|
||||
<kbd style="background:var(--bg-secondary); color:var(--accent-primary); border:1px solid var(--accent-primary); padding:4px 10px; border-radius:6px; font-family:monospace; margin:0 2px;">
|
||||
${App.escapeHtml(k)}
|
||||
</kbd>
|
||||
`).join(' + ');
|
||||
|
||||
saveBtn.disabled = false;
|
||||
});
|
||||
|
||||
saveBtn?.addEventListener('click', () => {
|
||||
if (this.editingId && recordedCombo) {
|
||||
App.saveCustomShortcut(this.editingId, recordedCombo);
|
||||
Toast.success('Combinazione salvata!');
|
||||
modal.style.display = 'none';
|
||||
this.render();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in new issue
Block a user