Filter changes #86
@@ -1473,14 +1473,193 @@ function updateProjectPills() {
|
||||
});
|
||||
}
|
||||
|
||||
// Hulpfunctie: Match een issue tegen een JQL clausule
|
||||
function matchJqlClause(iss, jql) {
|
||||
if (!jql || typeof jql !== 'string') return true;
|
||||
const trimmed = jql.trim();
|
||||
if (!trimmed) return true;
|
||||
|
||||
const issPKey = getIssueProjectKey(iss);
|
||||
const issPName = (iss.project || '').toLowerCase().trim();
|
||||
const issOl = (iss.onderwerp_logging || '').toLowerCase().trim();
|
||||
const issSum = (iss.summary || '').toLowerCase();
|
||||
const issPriority = (iss.priority || '').toLowerCase().trim();
|
||||
const issType = (iss.issue_type || '').toLowerCase().trim();
|
||||
const issStatus = (iss.status || '').toLowerCase().trim();
|
||||
|
||||
// Normalisatie helper voor onderwerpteksten (verwijder leestekens, spaties, streepjes voor flexibele matching)
|
||||
function normalizeText(str) {
|
||||
if (!str) return '';
|
||||
return str.toLowerCase().replace(/["']/g, '').replace(/[-_\s]/g, '').trim();
|
||||
}
|
||||
|
||||
// Splits condities op AND (hoofdletterongevoelig)
|
||||
const conditions = trimmed.split(/\s+AND\s+/i);
|
||||
|
||||
for (let rawCond of conditions) {
|
||||
const cond = rawCond.trim();
|
||||
if (!cond) continue;
|
||||
|
||||
// --- 1. Project condities ---
|
||||
// project = "SD" of project = SD
|
||||
const projEqMatch = cond.match(/^project\s*=\s*["']?([A-Z0-9_-]+)["']?$/i);
|
||||
if (projEqMatch) {
|
||||
const req = projEqMatch[1].toUpperCase().trim();
|
||||
if (issPKey !== req && !issPName.includes(req.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// project != "SD" of project != SD
|
||||
const projNeqMatch = cond.match(/^project\s*!=\s*["']?([A-Z0-9_-]+)["']?$/i);
|
||||
if (projNeqMatch) {
|
||||
const notReq = projNeqMatch[1].toUpperCase().trim();
|
||||
if (issPKey === notReq || issPName.includes(notReq.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// project in ("SD", "IN")
|
||||
const projInMatch = cond.match(/^project\s+in\s*\(([^)]+)\)$/i);
|
||||
if (projInMatch) {
|
||||
const allowed = projInMatch[1].split(',').map(s => s.replace(/["']/g, '').toUpperCase().trim());
|
||||
if (!allowed.includes(issPKey) && !allowed.some(p => issPName.includes(p.toLowerCase()))) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// project not in ("SD", "IN")
|
||||
const projNotInMatch = cond.match(/^project\s+not\s+in\s*\(([^)]+)\)$/i);
|
||||
if (projNotInMatch) {
|
||||
const disallowed = projNotInMatch[1].split(',').map(s => s.replace(/["']/g, '').toUpperCase().trim());
|
||||
if (disallowed.includes(issPKey) || disallowed.some(p => issPName.includes(p.toLowerCase()))) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// --- 2. Onderwerp logging condities ---
|
||||
// bv: "Onderwerp logging[dropdown]" in (Koppelingen, SSO-koppeling, Rest-endpoints, Datadump, UWV-koppeling, Migratie)
|
||||
const olInMatch = cond.match(/["']?(?:onderwerp(?:[\w\s\[\]_-]*)?|customfield_\d+)["']?\s+in\s*\(([^)]+)\)/i);
|
||||
if (olInMatch) {
|
||||
const allowedTopics = olInMatch[1].split(',').map(s => normalizeText(s)).filter(Boolean);
|
||||
const normOl = normalizeText(issOl);
|
||||
let matched = false;
|
||||
if (normOl) {
|
||||
matched = allowedTopics.some(t => normOl === t || normOl.includes(t) || t.includes(normOl));
|
||||
}
|
||||
if (!matched && !normOl) {
|
||||
// Als onderwerp_logging op het ticket leeg is, kijk in de summary
|
||||
const normSum = normalizeText(issSum);
|
||||
matched = allowedTopics.some(t => normSum.includes(t));
|
||||
}
|
||||
if (!matched) return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// "Onderwerp logging[dropdown]" not in (...)
|
||||
const olNotInMatch = cond.match(/["']?(?:onderwerp(?:[\w\s\[\]_-]*)?|customfield_\d+)["']?\s+not\s+in\s*\(([^)]+)\)/i);
|
||||
if (olNotInMatch) {
|
||||
const forbiddenTopics = olNotInMatch[1].split(',').map(s => normalizeText(s)).filter(Boolean);
|
||||
const normOl = normalizeText(issOl);
|
||||
if (normOl && forbiddenTopics.some(t => normOl === t || normOl.includes(t) || t.includes(normOl))) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// "Onderwerp logging[dropdown]" = "..."
|
||||
const olEqMatch = cond.match(/["']?(?:onderwerp(?:[\w\s\[\]_-]*)?|customfield_\d+)["']?\s*=\s*["']?([^"'\)]+)["']?/i);
|
||||
if (olEqMatch) {
|
||||
const reqTopic = normalizeText(olEqMatch[1]);
|
||||
const normOl = normalizeText(issOl);
|
||||
const matched = (normOl === reqTopic || normOl.includes(reqTopic) || reqTopic.includes(normOl) || (!normOl && normalizeText(issSum).includes(reqTopic)));
|
||||
if (!matched) return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// "Onderwerp logging[dropdown]" != "..."
|
||||
const olNeqMatch = cond.match(/["']?(?:onderwerp(?:[\w\s\[\]_-]*)?|customfield_\d+)["']?\s*!=\s*["']?([^"'\)]+)["']?/i);
|
||||
if (olNeqMatch) {
|
||||
const notTopic = normalizeText(olNeqMatch[1]);
|
||||
const normOl = normalizeText(issOl);
|
||||
if (normOl && (normOl === notTopic || normOl.includes(notTopic))) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// --- 3. Prioriteit condities ---
|
||||
const prioInMatch = cond.match(/^priority\s+in\s*\(([^)]+)\)$/i);
|
||||
if (prioInMatch) {
|
||||
const allowed = prioInMatch[1].split(',').map(s => s.replace(/["']/g, '').toLowerCase().trim());
|
||||
if (!allowed.includes(issPriority)) return false;
|
||||
continue;
|
||||
}
|
||||
const prioEqMatch = cond.match(/^priority\s*=\s*["']?([^"']+)["']?$/i);
|
||||
if (prioEqMatch) {
|
||||
const req = prioEqMatch[1].toLowerCase().trim();
|
||||
if (issPriority !== req) return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// --- 4. Type condities ---
|
||||
const typeInMatch = cond.match(/^(?:issuetype|type)\s+in\s*\(([^)]+)\)$/i);
|
||||
if (typeInMatch) {
|
||||
const allowed = typeInMatch[1].split(',').map(s => s.replace(/["']/g, '').toLowerCase().trim());
|
||||
if (!allowed.includes(issType)) return false;
|
||||
continue;
|
||||
}
|
||||
const typeEqMatch = cond.match(/^(?:issuetype|type)\s*=\s*["']?([^"']+)["']?$/i);
|
||||
if (typeEqMatch) {
|
||||
const req = typeEqMatch[1].toLowerCase().trim();
|
||||
if (issType !== req) return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// --- 5. StatusCategory conditie ---
|
||||
if (/statusCategory\s*!=\s*Done/i.test(cond)) {
|
||||
if (isDoneStatus(issStatus) || (iss.status_category || '').toLowerCase() === 'done') {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (/statusCategory\s*=\s*Done/i.test(cond)) {
|
||||
if (!isDoneStatus(issStatus) && (iss.status_category || '').toLowerCase() !== 'done') {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// --- 6. Status condities ---
|
||||
const statusInMatch = cond.match(/^status\s+in\s*\(([^)]+)\)$/i);
|
||||
if (statusInMatch) {
|
||||
const allowed = statusInMatch[1].split(',').map(s => s.replace(/["']/g, '').toLowerCase().trim());
|
||||
if (!allowed.includes(issStatus)) return false;
|
||||
continue;
|
||||
}
|
||||
const statusEqMatch = cond.match(/^status\s*=\s*["']?([^"']+)["']?$/i);
|
||||
if (statusEqMatch) {
|
||||
const req = statusEqMatch[1].toLowerCase().trim();
|
||||
if (issStatus !== req) return false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Hulpfunctie: Bepaal of een ticket tot een specifieke wachtrij behoort
|
||||
function isIssueInQueue(iss, qCode) {
|
||||
if (!qCode) return true;
|
||||
const code = qCode.toUpperCase().trim();
|
||||
const pKey = getIssueProjectKey(iss);
|
||||
const pName = (iss.project || '').toLowerCase().trim();
|
||||
const ol = (iss.onderwerp_logging || '').toLowerCase().trim();
|
||||
const sum = (iss.summary || '').toLowerCase();
|
||||
const pKey = (iss.project_key || '').toUpperCase().trim();
|
||||
const pName = (iss.project || '').toLowerCase().trim();
|
||||
|
||||
// Multi-queue matching voor de ingelogde gebruiker
|
||||
if (code === 'MY_QUEUES') {
|
||||
@@ -1489,38 +1668,51 @@ function isIssueInQueue(iss, qCode) {
|
||||
return myQueues.some(q => isIssueInQueue(iss, q));
|
||||
}
|
||||
|
||||
const dxTerms = ['koppeling', 'sso', 'endpoint', 'rest', 'datadump', 'uwv', 'migratie', 'api', 'webhook', 'integrat'];
|
||||
const matchesDx = dxTerms.some(t => ol.includes(t) || sum.includes(t));
|
||||
|
||||
if (code === 'DX') {
|
||||
return matchesDx;
|
||||
}
|
||||
if (code === 'SD') {
|
||||
return (pKey === 'SD' || pName.includes('servicedesk') || !matchesDx);
|
||||
}
|
||||
if (code === 'IN') {
|
||||
return (pKey === 'IN' || pName.includes('interface') || matchesDx || ol.includes('interface') || sum.includes('interface'));
|
||||
}
|
||||
if (code === 'AAN') {
|
||||
return (pKey === 'AAN' || pName.includes('aanvraag') || ol.includes('aanvraag') || sum.includes('aanvraag'));
|
||||
}
|
||||
if (code === 'GEN') {
|
||||
return (pKey === 'GEN' || pName.includes('general') || pName.includes('algemeen') || ol.includes('general') || ol.includes('algemeen'));
|
||||
}
|
||||
|
||||
// Aangepaste wachtrijfilter uit de database
|
||||
// 1. Zoek geconfigureerd wachtrijfilter in jiraData.queue_filters (database)
|
||||
const fObj = (jiraData.queue_filters || []).find(f => f.filter_code && f.filter_code.toUpperCase() === code);
|
||||
if (fObj) {
|
||||
if (fObj.project_key && pKey && fObj.project_key.toUpperCase() !== pKey) {
|
||||
return false;
|
||||
// Project key validatie indien expliciet in filter ingesteld
|
||||
if (fObj.project_key) {
|
||||
const filterPKey = fObj.project_key.toUpperCase().trim();
|
||||
if (pKey !== filterPKey && !pName.includes(filterPKey.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const clause = (fObj.jql_clause || '').toLowerCase();
|
||||
if (ol && (clause.includes(ol) || ol.includes(code.toLowerCase()))) {
|
||||
return true;
|
||||
// JQL clausule evaluatie
|
||||
if (fObj.jql_clause && fObj.jql_clause.trim()) {
|
||||
return matchJqlClause(iss, fObj.jql_clause);
|
||||
}
|
||||
// Als er alleen een project_key was zonder nadere jql_clause:
|
||||
if (fObj.project_key) {
|
||||
const filterPKey = fObj.project_key.toUpperCase().trim();
|
||||
return pKey === filterPKey || pName.includes(filterPKey.toLowerCase());
|
||||
}
|
||||
if (clause.includes('koppeling') && matchesDx) return true;
|
||||
if (clause.includes(pKey.toLowerCase())) return true;
|
||||
}
|
||||
|
||||
// 2. Fallbacks voor standaard wachtrijen (als er geen filter in de database staat)
|
||||
if (code === 'DX') {
|
||||
const isSd = (pKey === 'SD' || pName.includes('servicedesk'));
|
||||
if (!isSd) return false;
|
||||
const dxTerms = ['koppeling', 'sso', 'endpoint', 'rest', 'datadump', 'uwv', 'migratie'];
|
||||
return dxTerms.some(t => ol.includes(t) || sum.includes(t));
|
||||
}
|
||||
|
||||
if (code === 'SD') {
|
||||
return (pKey === 'SD' || pName.includes('servicedesk'));
|
||||
}
|
||||
|
||||
if (code === 'IN') {
|
||||
return (pKey === 'IN' || pName.includes('interface'));
|
||||
}
|
||||
|
||||
if (code === 'AAN') {
|
||||
return (pKey === 'AAN' || pName.includes('aanvraag'));
|
||||
}
|
||||
|
||||
if (code === 'GEN') {
|
||||
return (pKey === 'GEN' || pName.includes('general') || pName.includes('algemeen'));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1561,7 +1753,7 @@ function updateProjectCounts() {
|
||||
const el = document.getElementById(`projCount_${key}`);
|
||||
if (el) {
|
||||
const cnt = currentList.filter(iss => {
|
||||
const pk = (iss.project_key || '').toUpperCase().trim();
|
||||
const pk = getIssueProjectKey(iss);
|
||||
const pn = (iss.project || '').toLowerCase().trim();
|
||||
if (pk === key) return true;
|
||||
if (key === 'SD' && pn.includes('servicedesk')) return true;
|
||||
@@ -1589,7 +1781,7 @@ function updateQueueCounts() {
|
||||
if (currentProject) {
|
||||
const pNorm = currentProject.trim().toUpperCase();
|
||||
currentList = currentList.filter(iss => {
|
||||
const pk = (iss.project_key || '').trim().toUpperCase();
|
||||
const pk = getIssueProjectKey(iss);
|
||||
const pn = (iss.project || '').trim().toLowerCase();
|
||||
return pk === pNorm || pn.includes(pNorm.toLowerCase());
|
||||
});
|
||||
@@ -1689,7 +1881,7 @@ function applyFilters() {
|
||||
|
||||
// Filter tickets
|
||||
const filtered = all.filter(iss => {
|
||||
const issPKey = (iss.project_key || '').toUpperCase().trim();
|
||||
const issPKey = getIssueProjectKey(iss);
|
||||
const issPName = (iss.project || '').toLowerCase().trim();
|
||||
|
||||
// 1. Status Filter via Checkboxes
|
||||
|
||||
+15
-4
@@ -4671,15 +4671,26 @@ let activePlannerJiraQueue = ''; // '': Alle, 'my': Mijn, 'DX': DX Queue, 'SD':
|
||||
|
||||
function isIssueInQueue(iss, qCode) {
|
||||
if (!qCode) return true;
|
||||
const code = qCode.toUpperCase();
|
||||
const code = qCode.toUpperCase().trim();
|
||||
let pKey = (iss.project_key || '').toUpperCase().trim();
|
||||
if (!pKey && iss.key) {
|
||||
const parts = iss.key.split('-');
|
||||
if (parts.length > 0) pKey = parts[0].toUpperCase().trim();
|
||||
}
|
||||
const pName = (iss.project || '').toLowerCase().trim();
|
||||
const isSd = (pKey === 'SD' || pName.includes('servicedesk') || !pKey);
|
||||
|
||||
const ol = (iss.onderwerp_logging || '').toLowerCase().trim();
|
||||
const sum = (iss.summary || '').toLowerCase();
|
||||
|
||||
const dxTerms = ['koppeling', 'sso', 'endpoint', 'rest', 'datadump', 'uwv', 'migratie', 'api', 'webhook', 'integrat'];
|
||||
const matchesDx = dxTerms.some(t => ol.includes(t) || sum.includes(t));
|
||||
const dxTerms = ['koppeling', 'sso', 'endpoint', 'rest', 'datadump', 'uwv', 'migratie'];
|
||||
const matchesDx = isSd && dxTerms.some(t => ol.includes(t) || sum.includes(t));
|
||||
|
||||
if (code === 'DX') return matchesDx;
|
||||
if (code === 'SD') return !matchesDx;
|
||||
if (code === 'SD') return isSd && !matchesDx;
|
||||
if (code === 'IN') return (pKey === 'IN' || pName.includes('interface'));
|
||||
if (code === 'AAN') return (pKey === 'AAN' || pName.includes('aanvraag'));
|
||||
if (code === 'GEN') return (pKey === 'GEN' || pName.includes('general') || pName.includes('algemeen'));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user