fix: ora le ricerche lavorano nuovamente in cache. feat: aggiunto pulsante per eliminare rapidamente una ricerca testuale. feat: la ricerca in alto a destra rimanda alla ricerca spudorata ed il campo viene liberato.
This commit is contained in:
1 parent
c5e17ca57a
commit
c0c8a2531c
4 files changed
+57
-54
No files matched your search
+2
-7
@@ -197,13 +197,8 @@
|
|||||||
<input type="text" class="search-input" id="global-search"
|
<input type="text" class="search-input" id="global-search"
|
||||||
placeholder="Cerca ticket (numero, titolo o corpo)..." style="padding-right: 32px;" />
|
placeholder="Cerca ticket (numero, titolo o corpo)..." style="padding-right: 32px;" />
|
||||||
<button id="global-search-clear"
|
<button id="global-search-clear"
|
||||||
style="position: absolute; right: 10px; top: 50%; transform: translateY(-50%); background: none; border: none; padding: 4px; cursor: pointer; color: var(--text-muted); display: none; align-items: center; justify-content: center;"
|
style="position: absolute; right: 10px; top: 50%; transform: translateY(-50%); background: none; border: none; padding: 0; cursor: pointer; color: var(--text-muted); display: none; align-items: center; justify-content: center; font-size: 13px; line-height: 1;"
|
||||||
title="Cancella ricerca">
|
title="Cancella ricerca">✕</button>
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
||||||
style="width:14px;height:14px;display:block;">
|
|
||||||
<path d="M18 6L6 18M6 6l12 12" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-primary btn-sm" id="topbar-new-ticket" onclick="window.location.hash='#/tickets/new'">
|
<button class="btn btn-primary btn-sm" id="topbar-new-ticket" onclick="window.location.hash='#/tickets/new'">
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:16px;height:16px;">
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:16px;height:16px;">
|
||||||
|
|||||||
+16
-11
@@ -163,12 +163,20 @@ const App = {
|
|||||||
searchInput.addEventListener('keydown', (e) => {
|
searchInput.addEventListener('keydown', (e) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const hash = window.location.hash;
|
const query = searchInput.value.trim();
|
||||||
if (!hash.startsWith('#/tickets') || hash.includes('/new') || hash.match(/#\/tickets\/\d+/)) {
|
searchInput.value = '';
|
||||||
window.location.hash = '#/tickets';
|
toggleClearBtn();
|
||||||
|
if (query) {
|
||||||
|
const newHash = `#/ricerca-spudorata?q=${encodeURIComponent(query)}`;
|
||||||
|
if (window.location.hash === newHash && typeof RicercaSpudorataView !== 'undefined') {
|
||||||
|
const input = document.getElementById('spudorata-search-input');
|
||||||
|
if (input) input.value = query;
|
||||||
|
RicercaSpudorataView.executeSearch(query);
|
||||||
|
} else {
|
||||||
|
window.location.hash = newHash;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
TicketListView.currentPage = 1;
|
window.location.hash = '#/ricerca-spudorata';
|
||||||
TicketListView.render();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -178,12 +186,9 @@ const App = {
|
|||||||
searchInput.value = '';
|
searchInput.value = '';
|
||||||
searchClearBtn.style.display = 'none';
|
searchClearBtn.style.display = 'none';
|
||||||
searchInput.focus();
|
searchInput.focus();
|
||||||
const hash = window.location.hash;
|
if (window.location.hash.startsWith('#/ricerca-spudorata') && typeof RicercaSpudorataView !== 'undefined') {
|
||||||
if (hash.startsWith('#/tickets') && !hash.includes('/new') && !hash.match(/#\/tickets\/\d+/)) {
|
RicercaSpudorataView.invalidateCache();
|
||||||
TicketListView.currentPage = 1;
|
RicercaSpudorataView.render();
|
||||||
TicketListView.render();
|
|
||||||
} else {
|
|
||||||
window.location.hash = '#/tickets';
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,36 +24,32 @@ const RicercaSpudorataView = {
|
|||||||
Filters.load();
|
Filters.load();
|
||||||
|
|
||||||
const container = document.getElementById('view-container');
|
const container = document.getElementById('view-container');
|
||||||
container.innerHTML = `
|
if (!container) return;
|
||||||
<div class="loading-screen">
|
|
||||||
<div class="spinner"></div>
|
|
||||||
<p>Inizializzazione Ricerca Spudorata...</p>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
await App.ensureLookups();
|
const urlParams = new URLSearchParams((window.location.hash.split('?')[1]) || '');
|
||||||
|
const qParam = urlParams.get('q');
|
||||||
|
|
||||||
try {
|
if (qParam && qParam !== this.searchTerm) {
|
||||||
const settings = await App.api('/api/dashboard/settings');
|
this.renderContainer(container);
|
||||||
if (settings && settings.tickets_per_page) {
|
this.bindEvents();
|
||||||
this.perPage = settings.tickets_per_page;
|
const input = document.getElementById('spudorata-search-input');
|
||||||
}
|
if (input) input.value = qParam;
|
||||||
} catch (err) {
|
this.executeSearch(qParam);
|
||||||
console.warn('Failed to load agent settings:', err);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instant render from memory cache if already searched
|
||||||
|
if (this.hasSearched && this.cachedTickets) {
|
||||||
|
this.renderContainer(container);
|
||||||
|
this.bindEvents();
|
||||||
|
this.renderLocalResults();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.renderContainer(container);
|
this.renderContainer(container);
|
||||||
this.bindEvents();
|
this.bindEvents();
|
||||||
|
|
||||||
const urlParams = new URLSearchParams((window.location.hash.split('?')[1]) || '');
|
App.ensureLookups();
|
||||||
const qParam = urlParams.get('q');
|
|
||||||
if (qParam && !this.hasSearched) {
|
|
||||||
const input = document.getElementById('spudorata-search-input');
|
|
||||||
if (input) input.value = qParam;
|
|
||||||
this.executeSearch(qParam);
|
|
||||||
} else if (this.hasSearched && this.cachedTickets) {
|
|
||||||
this.renderLocalResults();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
renderContainer(container) {
|
renderContainer(container) {
|
||||||
|
|||||||
@@ -9,15 +9,20 @@ const TicketListView = {
|
|||||||
sortDir: 'DESC',
|
sortDir: 'DESC',
|
||||||
selectedIds: new Set(),
|
selectedIds: new Set(),
|
||||||
selectedOrder: [],
|
selectedOrder: [],
|
||||||
rawTickets: null,
|
rawTicketsByMode: {
|
||||||
|
general: null,
|
||||||
|
my: null
|
||||||
|
},
|
||||||
|
lastSearchTermByMode: {
|
||||||
|
general: '',
|
||||||
|
my: ''
|
||||||
|
},
|
||||||
otrsBaseUrl: null,
|
otrsBaseUrl: null,
|
||||||
lastMode: null,
|
|
||||||
lastSearchTerm: '',
|
|
||||||
needsRefresh: false,
|
needsRefresh: false,
|
||||||
|
|
||||||
invalidateCache() {
|
invalidateCache() {
|
||||||
this.rawTickets = null;
|
this.rawTicketsByMode.general = null;
|
||||||
this.lastMode = null;
|
this.rawTicketsByMode.my = null;
|
||||||
this.needsRefresh = true;
|
this.needsRefresh = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -38,11 +43,13 @@ const TicketListView = {
|
|||||||
const container = document.getElementById('view-container');
|
const container = document.getElementById('view-container');
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
|
const cachedTickets = this.rawTicketsByMode[newMode];
|
||||||
|
const cachedSearchTerm = this.lastSearchTermByMode[newMode];
|
||||||
|
|
||||||
const shouldFetch = force ||
|
const shouldFetch = force ||
|
||||||
this.needsRefresh ||
|
this.needsRefresh ||
|
||||||
!this.rawTickets ||
|
!cachedTickets ||
|
||||||
this.lastMode !== newMode ||
|
cachedSearchTerm !== globalSearchVal;
|
||||||
this.lastSearchTerm !== globalSearchVal;
|
|
||||||
|
|
||||||
if (shouldFetch) {
|
if (shouldFetch) {
|
||||||
if (!container.querySelector('.ticket-table-wrapper') && !container.querySelector('.ticket-table')) {
|
if (!container.querySelector('.ticket-table-wrapper') && !container.querySelector('.ticket-table')) {
|
||||||
@@ -78,10 +85,9 @@ const TicketListView = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.rawTickets = data.tickets || [];
|
this.rawTicketsByMode[newMode] = data.tickets || [];
|
||||||
|
this.lastSearchTermByMode[newMode] = globalSearchVal;
|
||||||
this.otrsBaseUrl = data.otrsBaseUrl || '';
|
this.otrsBaseUrl = data.otrsBaseUrl || '';
|
||||||
this.lastMode = newMode;
|
|
||||||
this.lastSearchTerm = globalSearchVal;
|
|
||||||
this.needsRefresh = false;
|
this.needsRefresh = false;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const currentHash = (window.location.hash || '#/dashboard').split('?')[0];
|
const currentHash = (window.location.hash || '#/dashboard').split('?')[0];
|
||||||
@@ -133,8 +139,9 @@ const TicketListView = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getFilteredTickets() {
|
getFilteredTickets() {
|
||||||
if (!this.rawTickets) return [];
|
const rawTickets = this.rawTicketsByMode[Filters.currentMode] || [];
|
||||||
let list = [...this.rawTickets];
|
if (!rawTickets || rawTickets.length === 0) return [];
|
||||||
|
let list = [...rawTickets];
|
||||||
const s = Filters.state;
|
const s = Filters.state;
|
||||||
|
|
||||||
// Sub-search text filter
|
// Sub-search text filter
|
||||||
|
|||||||
Reference in new issue
Block a user