- Introduced tests for drift operations UI and backend to ensure proper handling of ignore rules and UI elements. - Added tests for email identity API to validate email linking and identity retrieval without updates. - Implemented tests for email purchase link service to verify correct handling of purchase mail links and conflict scenarios. - Created tests for email reply automation to ensure proper routing and processing of replies based on classification. - Developed tests for email sender creation to validate suggestions and handling of existing contacts and companies. - Added tests for email sender identity to ensure correct matching of contacts and domains. - Implemented tests for work desk functionalities to validate task management, meeting registrations, and timer functionalities.
79 lines
3.8 KiB
JavaScript
79 lines
3.8 KiB
JavaScript
/* Move existing bookings without changing employee or duration. */
|
|
(() => {
|
|
'use strict';
|
|
const host = document.getElementById('casePlannerWeek');
|
|
if (!host) return;
|
|
let drag = null, saving = false;
|
|
function clear() {
|
|
host.querySelectorAll('.is-moving,.is-drop-target').forEach(node => node.classList.remove('is-moving','is-drop-target'));
|
|
drag = null;
|
|
}
|
|
function target(event) {
|
|
const day = event.target.closest('.v5-time-day');
|
|
if (!day || !drag) return null;
|
|
const offset = (event.clientY-day.getBoundingClientRect().top)/1.6 - drag.offset;
|
|
const minutes = Math.max(0, Math.min(1425, Math.round((Number(host.dataset.firstHour)*60+offset)/15)*15));
|
|
const start = new Date(`${day.dataset.date}T00:00:00`);
|
|
start.setMinutes(minutes);
|
|
// A segment after midnight still moves the complete original booking.
|
|
start.setTime(start.getTime() - drag.segmentOffset);
|
|
return {day, start};
|
|
}
|
|
host.addEventListener('dragstart', event => {
|
|
const card = event.target.closest('[data-move-id]');
|
|
if (!card || saving || event.target.closest('.case-slot-resize')) {event.preventDefault(); return;}
|
|
drag = {
|
|
card, offset: (event.clientY-card.getBoundingClientRect().top)/1.6,
|
|
segmentOffset: new Date(card.dataset.segmentStart)-new Date(card.dataset.start),
|
|
};
|
|
card.classList.add('is-moving');
|
|
event.dataTransfer.effectAllowed = 'move';
|
|
event.dataTransfer.setData('text/plain', card.dataset.moveId);
|
|
});
|
|
host.addEventListener('dragover', event => {
|
|
const drop = target(event);
|
|
if (!drop) return;
|
|
event.preventDefault();
|
|
event.dataTransfer.dropEffect = 'move';
|
|
host.querySelectorAll('.is-drop-target').forEach(node => node.classList.remove('is-drop-target'));
|
|
drop.day.classList.add('is-drop-target');
|
|
drag.card.title = `Flyt til ${drop.start.toLocaleString('da-DK', {weekday:'short',hour:'2-digit',minute:'2-digit'})}`;
|
|
});
|
|
host.addEventListener('drop', async event => {
|
|
const drop = target(event);
|
|
if (!drop || saving) return;
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
const {card} = drag;
|
|
const start = new Date(card.dataset.start), end = new Date(card.dataset.end);
|
|
clear();
|
|
if (drop.start.getTime() === start.getTime()) return;
|
|
const payload = {
|
|
version: Number(card.dataset.version), starts_at: drop.start.toISOString(),
|
|
ends_at: new Date(drop.start.getTime()+(end.getTime()-start.getTime())).toISOString(),
|
|
};
|
|
saving = true;
|
|
try {
|
|
for (;;) {
|
|
const response = await fetch(`/api/v1/planner/allocations/${Number(card.dataset.moveId)}`, {
|
|
method:'PATCH', credentials:'include', headers:{'Content-Type':'application/json'}, body:JSON.stringify(payload),
|
|
});
|
|
const body = await response.json();
|
|
if (response.ok) break;
|
|
const message = typeof body.detail === 'string' ? body.detail : body.detail?.message;
|
|
if (response.status === 409 && body.detail?.conflict_status && !payload.confirm_conflicts && window.confirm(`${message}. Vil du flytte aftalen alligevel?`)) {
|
|
payload.confirm_conflicts = true;
|
|
continue;
|
|
}
|
|
throw new Error(message || 'Kunne ikke flytte aftalen');
|
|
}
|
|
window.showCaseFeedback('Aftalen er flyttet', 'success');
|
|
} catch (error) {
|
|
window.showCaseFeedback(error.message);
|
|
} finally {
|
|
try {await window.loadEmbeddedCasePlanner(true);} finally {saving = false;}
|
|
}
|
|
});
|
|
host.addEventListener('dragend', clear);
|
|
})();
|