Dev #76
+89
-18
@@ -1550,8 +1550,11 @@ for ($h = $startHour; $h <= $endHour; $h++) {
|
|||||||
|
|
||||||
<?php $isJiraPlanned = !empty($plannedExternalIds[$issue['key']]); ?>
|
<?php $isJiraPlanned = !empty($plannedExternalIds[$issue['key']]); ?>
|
||||||
<button
|
<button
|
||||||
onclick="quickImportJiraByKey(this, '<?= htmlspecialchars($issue['key'] ?? '') ?>')"
|
onclick="quickImportJiraByKey(this, '<?= htmlspecialchars($issue['key'] ?? '') ?>', event)"
|
||||||
data-jira-key="<?= htmlspecialchars($issue['key'] ?? '') ?>"
|
data-jira-key="<?= htmlspecialchars($issue['key'] ?? '') ?>"
|
||||||
|
data-jira-summary="<?= htmlspecialchars($issue['summary'] ?? '') ?>"
|
||||||
|
data-jira-status="<?= htmlspecialchars($issue['status'] ?? 'To Do') ?>"
|
||||||
|
data-jira-priority="<?= htmlspecialchars($issue['priority'] ?? 'Medium') ?>"
|
||||||
class="plan-btn-jira flex items-center space-x-1 text-[11px] <?= $isJiraPlanned ? 'font-bold text-white bg-emerald-600 hover:bg-emerald-500 border border-emerald-600 shadow-xs' : 'font-semibold text-indigo-600 dark:text-indigo-400 hover:text-indigo-700 dark:hover:text-indigo-300 bg-indigo-50 dark:bg-indigo-500/10 hover:bg-indigo-100 dark:hover:bg-indigo-500/20 border border-indigo-200 dark:border-indigo-500/20' ?> px-2.5 py-1 rounded-lg transition flex-shrink-0 cursor-pointer"
|
class="plan-btn-jira flex items-center space-x-1 text-[11px] <?= $isJiraPlanned ? 'font-bold text-white bg-emerald-600 hover:bg-emerald-500 border border-emerald-600 shadow-xs' : 'font-semibold text-indigo-600 dark:text-indigo-400 hover:text-indigo-700 dark:hover:text-indigo-300 bg-indigo-50 dark:bg-indigo-500/10 hover:bg-indigo-100 dark:hover:bg-indigo-500/20 border border-indigo-200 dark:border-indigo-500/20' ?> px-2.5 py-1 rounded-lg transition flex-shrink-0 cursor-pointer"
|
||||||
title="<?= $isJiraPlanned ? 'Dit ticket is al ingepland als dagtaak (klik om status te bekijken of te herplannen)' : 'Plan in als dagtaak' ?>"
|
title="<?= $isJiraPlanned ? 'Dit ticket is al ingepland als dagtaak (klik om status te bekijken of te herplannen)' : 'Plan in als dagtaak' ?>"
|
||||||
>
|
>
|
||||||
@@ -4638,17 +4641,22 @@ document.addEventListener('click', (e) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// --- Jira Queue & Tickets Widget Engine (v2.0) ---
|
// --- Jira Queue & Tickets Widget Engine (v2.0) ---
|
||||||
const plannerJiraAssigned = <?= json_encode($jiraAssignedIssues, JSON_UNESCAPED_UNICODE) ?>;
|
const plannerJiraAssigned = <?= json_encode($jiraAssignedIssues, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
|
||||||
const plannerJiraAll = <?= json_encode($jiraAllIssues, JSON_UNESCAPED_UNICODE) ?>;
|
const plannerJiraAll = <?= json_encode($jiraAllIssues, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
|
||||||
const plannerTicketStore = new Map();
|
const plannerTicketStore = new Map();
|
||||||
plannerJiraAll.forEach(iss => {
|
(Array.isArray(plannerJiraAll) ? plannerJiraAll : []).forEach(iss => {
|
||||||
if (iss && iss.key) plannerTicketStore.set(iss.key, iss);
|
if (iss && iss.key) plannerTicketStore.set(String(iss.key).trim().toUpperCase(), iss);
|
||||||
});
|
});
|
||||||
plannerJiraAssigned.forEach(iss => {
|
(Array.isArray(plannerJiraAssigned) ? plannerJiraAssigned : []).forEach(iss => {
|
||||||
if (iss && iss.key && !plannerTicketStore.has(iss.key)) plannerTicketStore.set(iss.key, iss);
|
if (iss && iss.key) {
|
||||||
|
const normKey = String(iss.key).trim().toUpperCase();
|
||||||
|
if (!plannerTicketStore.has(normKey)) {
|
||||||
|
plannerTicketStore.set(normKey, iss);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const plannedExternalTasksMap = <?= json_encode($plannedExternalIds, JSON_UNESCAPED_UNICODE) ?> || {};
|
const plannedExternalTasksMap = <?= json_encode($plannedExternalIds, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?> || {};
|
||||||
const plannedExternalIdsSet = new Set(Object.keys(plannedExternalTasksMap));
|
const plannedExternalIdsSet = new Set(Object.keys(plannedExternalTasksMap));
|
||||||
let activePlannerJiraQueue = ''; // '': Alle, 'my': Mijn, 'DX': DX Queue, 'SD': SD Queue
|
let activePlannerJiraQueue = ''; // '': Alle, 'my': Mijn, 'DX': DX Queue, 'SD': SD Queue
|
||||||
|
|
||||||
@@ -4754,8 +4762,11 @@ function filterPlannerJira() {
|
|||||||
const isPlanned = plannedExternalIdsSet.has(issue.key);
|
const isPlanned = plannedExternalIdsSet.has(issue.key);
|
||||||
const planBtn = isPlanned
|
const planBtn = isPlanned
|
||||||
? `<button
|
? `<button
|
||||||
onclick="quickImportJiraByKey(this, '${keyEsc}')"
|
onclick="quickImportJiraByKey(this, '${keyEsc}', event)"
|
||||||
data-jira-key="${keyEsc}"
|
data-jira-key="${keyEsc}"
|
||||||
|
data-jira-summary="${summaryEsc}"
|
||||||
|
data-jira-status="${statusEsc}"
|
||||||
|
data-jira-priority="${priorityEsc}"
|
||||||
class="plan-btn-jira flex items-center space-x-1 text-[11px] font-bold text-white bg-emerald-600 hover:bg-emerald-500 border border-emerald-600 shadow-xs px-2.5 py-1 rounded-lg transition flex-shrink-0 cursor-pointer"
|
class="plan-btn-jira flex items-center space-x-1 text-[11px] font-bold text-white bg-emerald-600 hover:bg-emerald-500 border border-emerald-600 shadow-xs px-2.5 py-1 rounded-lg transition flex-shrink-0 cursor-pointer"
|
||||||
title="Dit ticket is al ingepland als dagtaak (klik om status te bekijken of te herplannen)"
|
title="Dit ticket is al ingepland als dagtaak (klik om status te bekijken of te herplannen)"
|
||||||
>
|
>
|
||||||
@@ -4763,8 +4774,11 @@ function filterPlannerJira() {
|
|||||||
<span>Ingepland</span>
|
<span>Ingepland</span>
|
||||||
</button>`
|
</button>`
|
||||||
: `<button
|
: `<button
|
||||||
onclick="quickImportJiraByKey(this, '${keyEsc}')"
|
onclick="quickImportJiraByKey(this, '${keyEsc}', event)"
|
||||||
data-jira-key="${keyEsc}"
|
data-jira-key="${keyEsc}"
|
||||||
|
data-jira-summary="${summaryEsc}"
|
||||||
|
data-jira-status="${statusEsc}"
|
||||||
|
data-jira-priority="${priorityEsc}"
|
||||||
class="plan-btn-jira flex items-center space-x-1 text-[11px] font-semibold text-indigo-600 dark:text-indigo-400 hover:text-indigo-700 dark:hover:text-indigo-300 bg-indigo-50 dark:bg-indigo-500/10 hover:bg-indigo-100 dark:hover:bg-indigo-500/20 border border-indigo-200 dark:border-indigo-500/20 px-2.5 py-1 rounded-lg transition flex-shrink-0 cursor-pointer"
|
class="plan-btn-jira flex items-center space-x-1 text-[11px] font-semibold text-indigo-600 dark:text-indigo-400 hover:text-indigo-700 dark:hover:text-indigo-300 bg-indigo-50 dark:bg-indigo-500/10 hover:bg-indigo-100 dark:hover:bg-indigo-500/20 border border-indigo-200 dark:border-indigo-500/20 px-2.5 py-1 rounded-lg transition flex-shrink-0 cursor-pointer"
|
||||||
title="Plan in als dagtaak"
|
title="Plan in als dagtaak"
|
||||||
>
|
>
|
||||||
@@ -4803,8 +4817,27 @@ function filterPlannerJira() {
|
|||||||
let _jiraDetailCurrentIssue = null;
|
let _jiraDetailCurrentIssue = null;
|
||||||
|
|
||||||
function openJiraTicketDetail(issueKey) {
|
function openJiraTicketDetail(issueKey) {
|
||||||
const issue = plannerTicketStore.get(issueKey);
|
const rawKey = String(issueKey || '').trim();
|
||||||
if (!issue) return;
|
const normKey = rawKey.toUpperCase();
|
||||||
|
let issue = plannerTicketStore.get(normKey) || plannerTicketStore.get(rawKey);
|
||||||
|
|
||||||
|
if (!issue) {
|
||||||
|
// Fallback: probeer element op te halen uit de lijst
|
||||||
|
const cardBtn = document.querySelector(`[data-jira-key="${rawKey}"]`);
|
||||||
|
const summary = cardBtn?.getAttribute('data-jira-summary') || '';
|
||||||
|
const status = cardBtn?.getAttribute('data-jira-status') || 'To Do';
|
||||||
|
const priority = cardBtn?.getAttribute('data-jira-priority') || 'Medium';
|
||||||
|
|
||||||
|
issue = {
|
||||||
|
key: rawKey,
|
||||||
|
summary: summary || `Jira item ${rawKey}`,
|
||||||
|
status: status,
|
||||||
|
priority: priority,
|
||||||
|
description: '',
|
||||||
|
url: ''
|
||||||
|
};
|
||||||
|
plannerTicketStore.set(normKey, issue);
|
||||||
|
}
|
||||||
_jiraDetailCurrentIssue = issue;
|
_jiraDetailCurrentIssue = issue;
|
||||||
|
|
||||||
// Vul header
|
// Vul header
|
||||||
@@ -4930,9 +4963,30 @@ function toggleJiraPlanDescription() {
|
|||||||
if (typeof lucide !== 'undefined') lucide.createIcons();
|
if (typeof lucide !== 'undefined') lucide.createIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
function openJiraPlanModal(issueKey) {
|
function openJiraPlanModal(issueKey, fallbackData = null) {
|
||||||
const issue = plannerTicketStore.get(issueKey);
|
const rawKey = String(issueKey || '').trim();
|
||||||
if (!issue) return;
|
const normKey = rawKey.toUpperCase();
|
||||||
|
let issue = plannerTicketStore.get(normKey) || plannerTicketStore.get(rawKey);
|
||||||
|
|
||||||
|
if (!issue) {
|
||||||
|
// Zoek fallback gegevens op de plan-knop in de DOM
|
||||||
|
const btn = document.querySelector(`[data-jira-key="${rawKey}"]`) || document.querySelector(`[data-jira-key="${normKey}"]`);
|
||||||
|
const summary = fallbackData?.summary || btn?.getAttribute('data-jira-summary') || '';
|
||||||
|
const status = fallbackData?.status || btn?.getAttribute('data-jira-status') || 'To Do';
|
||||||
|
const priority = fallbackData?.priority || btn?.getAttribute('data-jira-priority') || 'Medium';
|
||||||
|
|
||||||
|
issue = {
|
||||||
|
key: rawKey || 'JIRA-ITEM',
|
||||||
|
summary: summary || (rawKey ? `Oppakken Jira item ${rawKey}` : 'Jira taak'),
|
||||||
|
status: status,
|
||||||
|
priority: priority,
|
||||||
|
description: fallbackData?.description || '',
|
||||||
|
url: fallbackData?.url || ''
|
||||||
|
};
|
||||||
|
if (rawKey) {
|
||||||
|
plannerTicketStore.set(normKey, issue);
|
||||||
|
}
|
||||||
|
}
|
||||||
_jiraPlanCurrentIssue = issue;
|
_jiraPlanCurrentIssue = issue;
|
||||||
|
|
||||||
// Vul header
|
// Vul header
|
||||||
@@ -5350,9 +5404,26 @@ async function submitJiraPlanModal() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function quickImportJiraByKey(btn, issueKey) {
|
async function quickImportJiraByKey(btn, issueKey, event = null) {
|
||||||
// Plan knop → open de plan modal (niet direct importeren)
|
if (event) {
|
||||||
openJiraPlanModal(issueKey);
|
try {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawKey = String(issueKey || '').trim();
|
||||||
|
let fallbackData = null;
|
||||||
|
|
||||||
|
if (btn) {
|
||||||
|
fallbackData = {
|
||||||
|
summary: btn.getAttribute('data-jira-summary') || '',
|
||||||
|
status: btn.getAttribute('data-jira-status') || 'To Do',
|
||||||
|
priority: btn.getAttribute('data-jira-priority') || 'Medium'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
openJiraPlanModal(rawKey, fallbackData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user