fix: corretta modifica massiva scassata da claude. fix: e possibile inserire clienti non esistenti come in otrs.
This commit is contained in:
@@ -665,9 +665,17 @@ const TicketBulkView = {
|
||||
const type_id = document.getElementById(`bulk-type-${id}`).value;
|
||||
const ownerId = document.getElementById(`bulk-owner-${id}`).value;
|
||||
const responsibleId = document.getElementById(`bulk-responsible-${id}`).value;
|
||||
const customerId = document.getElementById(`bulk-customer-${id}`).value;
|
||||
const customerUserId = document.getElementById(`bulk-customer-user-id-${id}`).value;
|
||||
const customerSearch = document.getElementById(`bulk-customer-search-${id}`).value;
|
||||
let customerId = document.getElementById(`bulk-customer-${id}`).value;
|
||||
let customerUserId = document.getElementById(`bulk-customer-user-id-${id}`).value;
|
||||
const customerSearch = document.getElementById(`bulk-customer-search-${id}`).value.trim();
|
||||
|
||||
if (!customerUserId && customerSearch) {
|
||||
customerUserId = customerSearch;
|
||||
if (!customerId) {
|
||||
customerId = customerSearch;
|
||||
}
|
||||
}
|
||||
|
||||
const subject = document.getElementById(`bulk-subject-${id}`).value.trim();
|
||||
const body = document.getElementById(`bulk-body-${id}`).value.trim();
|
||||
const priority_id = document.getElementById(`bulk-priority-${id}`).value;
|
||||
|
||||
@@ -243,6 +243,14 @@ const TicketCreateView = {
|
||||
if (this.savedState && this.savedState.body) {
|
||||
this.quill.root.innerHTML = this.savedState.body;
|
||||
}
|
||||
|
||||
// Prevent tab navigation on toolbar items
|
||||
const toolbar = container.querySelector('.ql-toolbar');
|
||||
if (toolbar) {
|
||||
toolbar.querySelectorAll('button, select, span[role="button"], input').forEach(el => {
|
||||
el.setAttribute('tabindex', '-1');
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.quill = null;
|
||||
}
|
||||
@@ -589,9 +597,17 @@ const TicketCreateView = {
|
||||
const priority_id = document.getElementById('create-priority').value;
|
||||
const type_id = document.getElementById('create-type')?.value;
|
||||
|
||||
const customerId = customerIdInput.value;
|
||||
const userSearchVal = userSearchInput.value.trim();
|
||||
let customerId = customerIdInput.value;
|
||||
let customerUserId = customerUserIdInput.value;
|
||||
|
||||
if (!customerUserId && userSearchVal) {
|
||||
customerUserId = userSearchVal;
|
||||
if (!customerId) {
|
||||
customerId = userSearchVal;
|
||||
}
|
||||
}
|
||||
|
||||
const ownerId = ownerIdInput.value;
|
||||
const responsibleId = responsibleIdInput.value;
|
||||
|
||||
|
||||
@@ -317,7 +317,6 @@ const TicketDetailView = {
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Initialize Quill Editor for Note
|
||||
if (window.Quill) {
|
||||
this.noteQuill = new Quill('#note-body-editor', {
|
||||
theme: 'snow',
|
||||
@@ -331,6 +330,14 @@ const TicketDetailView = {
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
// Prevent tab navigation on toolbar items
|
||||
const toolbar = container.querySelector('.ql-toolbar');
|
||||
if (toolbar) {
|
||||
toolbar.querySelectorAll('button, select, span[role="button"], input').forEach(el => {
|
||||
el.setAttribute('tabindex', '-1');
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.noteQuill = null;
|
||||
}
|
||||
@@ -450,6 +457,12 @@ const TicketDetailView = {
|
||||
|
||||
// Save quick-edit
|
||||
saveBtn.addEventListener('click', async () => {
|
||||
const customerSearch = customerSearchInput ? customerSearchInput.value.trim() : '';
|
||||
if (customerSearch && !customerUserIdInput.value) {
|
||||
customerUserIdInput.value = customerSearch;
|
||||
customerIdInput.value = customerSearch;
|
||||
}
|
||||
|
||||
const updates = {};
|
||||
fields.forEach(el => {
|
||||
const field = el.dataset.field;
|
||||
|
||||
@@ -85,6 +85,13 @@ const TicketListView = {
|
||||
${(App.lookups.users || []).map(u => `<option value="${u.id}">${u.first_name} ${u.last_name}</option>`).join('')}
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-group" style="position:relative;">
|
||||
<span class="filter-label">Cliente</span>
|
||||
<input type="text" class="form-input filter-select" id="batch-customer-search" placeholder="Cerca cliente..." autocomplete="off" style="width:160px; padding: 4px 8px; font-family: inherit; font-size: 0.85rem;" />
|
||||
<input type="hidden" id="batch-customer-user-id" />
|
||||
<input type="hidden" id="batch-customer-id" />
|
||||
<div id="batch-customer-suggestions" class="autocomplete-suggestions" style="display:none; top: 100%; left: 0; width: 280px; z-index: 1001;"></div>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-sm" id="batch-apply">Applica</button>
|
||||
<button class="btn btn-primary btn-sm" id="batch-merge" disabled style="background: var(--accent-secondary); border-color: var(--accent-secondary); margin-left: 8px;">Unisci Selezionati</button>
|
||||
<button class="btn btn-ghost btn-xs" id="batch-cancel">Annulla</button>
|
||||
@@ -277,10 +284,83 @@ const TicketListView = {
|
||||
tr.classList.remove('selected');
|
||||
tr.classList.remove('first-selected');
|
||||
});
|
||||
const batchCustomerSearch = document.getElementById('batch-customer-search');
|
||||
const batchCustomerUserId = document.getElementById('batch-customer-user-id');
|
||||
const batchCustomerId = document.getElementById('batch-customer-id');
|
||||
if (batchCustomerSearch) batchCustomerSearch.value = '';
|
||||
if (batchCustomerUserId) batchCustomerUserId.value = '';
|
||||
if (batchCustomerId) batchCustomerId.value = '';
|
||||
const batchState = document.getElementById('batch-state');
|
||||
if (batchState) batchState.value = '';
|
||||
const batchQueue = document.getElementById('batch-queue');
|
||||
if (batchQueue) batchQueue.value = '';
|
||||
const batchOwner = document.getElementById('batch-owner');
|
||||
if (batchOwner) batchOwner.value = '';
|
||||
|
||||
this.updateBatchBar();
|
||||
});
|
||||
}
|
||||
|
||||
// Batch Customer User Autocomplete
|
||||
const batchCustomerSearchInput = document.getElementById('batch-customer-search');
|
||||
const batchCustomerSuggestionsDiv = document.getElementById('batch-customer-suggestions');
|
||||
const batchCustomerUserIdInput = document.getElementById('batch-customer-user-id');
|
||||
const batchCustomerIdInput = document.getElementById('batch-customer-id');
|
||||
|
||||
let batchCustomerDebounce;
|
||||
if (batchCustomerSearchInput) {
|
||||
batchCustomerSearchInput.addEventListener('input', () => {
|
||||
clearTimeout(batchCustomerDebounce);
|
||||
const q = batchCustomerSearchInput.value.trim();
|
||||
if (q.length < 2) {
|
||||
batchCustomerSuggestionsDiv.style.display = 'none';
|
||||
if (batchCustomerUserIdInput) batchCustomerUserIdInput.value = '';
|
||||
if (batchCustomerIdInput) batchCustomerIdInput.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
batchCustomerDebounce = setTimeout(async () => {
|
||||
try {
|
||||
const users = await App.api(`/api/customer-users/search?q=${encodeURIComponent(q)}`);
|
||||
if (users.length === 0) {
|
||||
batchCustomerSuggestionsDiv.innerHTML = '<div class="autocomplete-suggestion-item" style="color:var(--text-muted); cursor:default;">Nessun utente trovato</div>';
|
||||
batchCustomerSuggestionsDiv.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
|
||||
batchCustomerSuggestionsDiv.innerHTML = users.map(u => `
|
||||
<div class="autocomplete-suggestion-item" data-login="${App.escapeHtml(u.login)}" data-customer-id="${App.escapeHtml(u.customer_id || '')}" data-name="${App.escapeHtml(u.first_name + ' ' + u.last_name)}">
|
||||
<strong>${App.escapeHtml(u.first_name)} ${App.escapeHtml(u.last_name)}</strong>
|
||||
<span style="font-size:0.75rem; color:var(--text-muted); margin-left:var(--space-xs); font-weight:normal;">(Login: ${App.escapeHtml(u.login)} | Azienda: ${App.escapeHtml(u.customer_id || '—')})</span>
|
||||
</div>
|
||||
`).join('');
|
||||
batchCustomerSuggestionsDiv.style.display = 'block';
|
||||
|
||||
// Bind click
|
||||
batchCustomerSuggestionsDiv.querySelectorAll('.autocomplete-suggestion-item').forEach(item => {
|
||||
if (item.dataset.login) {
|
||||
item.addEventListener('click', () => {
|
||||
batchCustomerSearchInput.value = item.dataset.name;
|
||||
if (batchCustomerUserIdInput) batchCustomerUserIdInput.value = item.dataset.login;
|
||||
if (batchCustomerIdInput) batchCustomerIdInput.value = item.dataset.customerId || '';
|
||||
batchCustomerSuggestionsDiv.style.display = 'none';
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}, 300);
|
||||
});
|
||||
}
|
||||
|
||||
// Close suggestions on click outside
|
||||
document.addEventListener('click', (e) => {
|
||||
if (batchCustomerSearchInput && e.target !== batchCustomerSearchInput && e.target !== batchCustomerSuggestionsDiv) {
|
||||
batchCustomerSuggestionsDiv.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Pagination
|
||||
document.querySelectorAll('.pagination-btn[data-page]').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
@@ -316,10 +396,22 @@ const TicketListView = {
|
||||
const batchState = document.getElementById('batch-state')?.value;
|
||||
const batchQueue = document.getElementById('batch-queue')?.value;
|
||||
const batchOwner = document.getElementById('batch-owner')?.value;
|
||||
const batchCustomerSearch = document.getElementById('batch-customer-search')?.value.trim();
|
||||
let batchCustomerUserId = document.getElementById('batch-customer-user-id')?.value;
|
||||
let batchCustomerId = document.getElementById('batch-customer-id')?.value;
|
||||
|
||||
if (!batchCustomerUserId && batchCustomerSearch) {
|
||||
batchCustomerUserId = batchCustomerSearch;
|
||||
if (!batchCustomerId) {
|
||||
batchCustomerId = batchCustomerSearch;
|
||||
}
|
||||
}
|
||||
|
||||
if (batchState) updates.ticket_state_id = parseInt(batchState);
|
||||
if (batchQueue) updates.queue_id = parseInt(batchQueue);
|
||||
if (batchOwner) updates.user_id = parseInt(batchOwner);
|
||||
if (batchCustomerUserId) updates.customer_user_id = batchCustomerUserId;
|
||||
if (batchCustomerId) updates.customer_id = batchCustomerId;
|
||||
|
||||
if (Object.keys(updates).length === 0) {
|
||||
Toast.warning('Seleziona almeno un campo da modificare');
|
||||
|
||||
Reference in New Issue
Block a user