a85747f13d
Руководитель может менять catalog_work в таблице и удалять записи. Co-authored-by: Cursor <cursoragent@cursor.com>
402 lines
16 KiB
JavaScript
402 lines
16 KiB
JavaScript
function itTabSwitch(tab) {
|
|
document.querySelectorAll('.it-panel').forEach(function (panel) {
|
|
panel.style.display = panel.id === 'it-panel-' + tab ? '' : 'none';
|
|
});
|
|
document.querySelectorAll('.it-tab-btn').forEach(function (btn) {
|
|
var active = btn.getAttribute('data-tab') === tab;
|
|
btn.classList.toggle('it-tab-active', active);
|
|
btn.style.background = active ? 'var(--color-card)' : 'transparent';
|
|
btn.style.color = active ? 'var(--color-card-foreground)' : 'var(--color-muted-foreground)';
|
|
btn.style.boxShadow = active ? '0 1px 2px rgb(0 0 0/0.08)' : '';
|
|
});
|
|
}
|
|
|
|
function itToggleRow(key) {
|
|
var row = document.getElementById('it-row-' + key);
|
|
var toggle = document.getElementById('it-toggle-' + key);
|
|
if (!row) return;
|
|
var opening = row.style.display === 'none';
|
|
row.style.display = opening ? 'table-row' : 'none';
|
|
if (toggle) toggle.style.transform = opening ? 'rotate(90deg)' : '';
|
|
}
|
|
|
|
function itPanelOpen(id) {
|
|
var panel = document.getElementById(id);
|
|
var overlay = document.getElementById(id + '-overlay');
|
|
if (overlay) overlay.style.display = 'block';
|
|
if (panel) panel.style.transform = 'translateX(0)';
|
|
document.body.style.overflow = 'hidden';
|
|
}
|
|
|
|
function itPanelClose(id) {
|
|
var panel = document.getElementById(id);
|
|
var overlay = document.getElementById(id + '-overlay');
|
|
if (overlay) overlay.style.display = 'none';
|
|
if (panel) panel.style.transform = 'translateX(100%)';
|
|
document.body.style.overflow = '';
|
|
}
|
|
|
|
function itContractServiceToggle(serviceTypeCode) {
|
|
var block = document.getElementById('it-contract-ip-block');
|
|
if (!block) return;
|
|
var show = serviceTypeCode === 'internet';
|
|
block.style.display = show ? '' : 'none';
|
|
if (!show) {
|
|
var checkbox = block.querySelector('input[name=dedicated_ip]');
|
|
var ipField = document.getElementById('it-contract-ip-field');
|
|
if (checkbox) checkbox.checked = false;
|
|
if (ipField) ipField.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
function itContractFrameworkToggle(isFramework) {
|
|
var parentWrap = document.getElementById('it-contract-parent-wrap');
|
|
var locationWrap = document.getElementById('it-contract-location-wrap');
|
|
var locationSelect = document.getElementById('it-contract-location-select');
|
|
var locationRequired = document.getElementById('it-contract-location-required');
|
|
|
|
if (parentWrap) {
|
|
parentWrap.style.display = isFramework ? 'none' : '';
|
|
}
|
|
if (isFramework) {
|
|
var sel = document.getElementById('it-contract-parent-select');
|
|
if (sel) sel.value = '';
|
|
}
|
|
|
|
if (locationWrap) {
|
|
locationWrap.style.display = isFramework ? 'none' : '';
|
|
}
|
|
if (locationSelect) {
|
|
locationSelect.required = !isFramework;
|
|
if (isFramework) locationSelect.value = '';
|
|
}
|
|
if (locationRequired) {
|
|
locationRequired.style.display = isFramework ? 'none' : '';
|
|
}
|
|
}
|
|
|
|
function itContractFilterParents() {
|
|
var providerSelect = document.getElementById('it-contract-provider-select');
|
|
var parentSelect = document.getElementById('it-contract-parent-select');
|
|
if (!providerSelect || !parentSelect) return;
|
|
var providerId = providerSelect.value;
|
|
Array.prototype.forEach.call(parentSelect.options, function (opt) {
|
|
if (!opt.value) {
|
|
opt.hidden = false;
|
|
return;
|
|
}
|
|
opt.hidden = providerId && opt.getAttribute('data-provider') !== providerId;
|
|
});
|
|
if (parentSelect.selectedOptions[0] && parentSelect.selectedOptions[0].hidden) {
|
|
parentSelect.value = '';
|
|
}
|
|
}
|
|
|
|
// --- Масовий вибір екземплярів обладнання ---
|
|
// --- Выдача оборудования: тип → список ---
|
|
function itAssignTargetChanged(selectEl) {
|
|
var root = selectEl.closest('[data-assign-widget]');
|
|
if (!root) return;
|
|
var target = selectEl.value || '';
|
|
root.querySelectorAll('[data-assign-pick]').forEach(function (pick) {
|
|
var match = pick.getAttribute('data-assign-pick') === target;
|
|
pick.style.display = match ? '' : 'none';
|
|
pick.querySelectorAll('select').forEach(function (inp) {
|
|
inp.disabled = !match;
|
|
if (!match) {
|
|
inp.value = '';
|
|
// searchable-select слушает change
|
|
inp.dispatchEvent(new Event('change', { bubbles: true }));
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function itBulkToggleAll(headerCheckbox) {
|
|
document.querySelectorAll('.it-equip-check').forEach(function (cb) {
|
|
cb.checked = headerCheckbox.checked;
|
|
});
|
|
itBulkUpdate();
|
|
}
|
|
|
|
function itBulkUpdate() {
|
|
var checked = Array.prototype.slice.call(document.querySelectorAll('.it-equip-check:checked'));
|
|
var panel = document.getElementById('it-equipment-bulk-assign');
|
|
var countEl = document.getElementById('it-bulk-assign-count');
|
|
var inputs = document.getElementById('it-bulk-assign-inputs');
|
|
if (!panel) return;
|
|
if (checked.length) {
|
|
panel.style.display = 'block';
|
|
if (countEl) countEl.textContent = checked.length;
|
|
if (inputs) {
|
|
// переносимо id відмічених у hidden-поля всередині форми видачі
|
|
inputs.innerHTML = '';
|
|
checked.forEach(function (cb) {
|
|
var hidden = document.createElement('input');
|
|
hidden.type = 'hidden';
|
|
hidden.name = 'equipment_ids';
|
|
hidden.value = cb.value;
|
|
inputs.appendChild(hidden);
|
|
});
|
|
}
|
|
} else {
|
|
panel.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
function itBulkClearSelection() {
|
|
document.querySelectorAll('.it-equip-check').forEach(function (cb) { cb.checked = false; });
|
|
var headerAll = document.querySelector('th input[onclick^="itBulkToggleAll"]');
|
|
if (headerAll) headerAll.checked = false;
|
|
itBulkUpdate();
|
|
}
|
|
|
|
function itSetSearchableSelectValue(selectId, value) {
|
|
var select = document.getElementById(selectId);
|
|
if (!select) return;
|
|
select.value = value || '';
|
|
select.dispatchEvent(new Event('change', { bubbles: true }));
|
|
var widget = select.closest('.searchable-select');
|
|
if (widget && widget._search) {
|
|
var opt = select.options[select.selectedIndex];
|
|
widget._search.value = (opt && opt.value) ? opt.textContent : '';
|
|
if (typeof widget._updateClear === 'function') widget._updateClear();
|
|
else if (widget._clear) widget._clear.style.display = select.value ? 'flex' : 'none';
|
|
}
|
|
}
|
|
|
|
function itWorkCatalogData() {
|
|
var el = document.getElementById('it-work-catalog-data');
|
|
if (!el) return { categories: [], works: [], detail_labels: {} };
|
|
try {
|
|
return JSON.parse(el.textContent || '{}');
|
|
} catch (e) {
|
|
return { categories: [], works: [], detail_labels: {} };
|
|
}
|
|
}
|
|
|
|
function itWorklogCategoryChanged() {
|
|
var cat = document.getElementById('it-worklog-category');
|
|
var work = document.getElementById('it-worklog-work');
|
|
if (!work) return;
|
|
var catId = cat ? cat.value : '';
|
|
var data = itWorkCatalogData();
|
|
var works = (data.works || []).filter(function (w) {
|
|
return !catId || String(w.category_id) === String(catId);
|
|
});
|
|
work.innerHTML = '';
|
|
var empty = document.createElement('option');
|
|
empty.value = '';
|
|
empty.textContent = catId ? '— Выберите работу —' : '— Сначала выберите категорию —';
|
|
work.appendChild(empty);
|
|
works.forEach(function (w) {
|
|
var opt = document.createElement('option');
|
|
opt.value = String(w.id);
|
|
opt.textContent = w.name;
|
|
work.appendChild(opt);
|
|
});
|
|
itWorklogWorkChanged();
|
|
}
|
|
|
|
function itWorklogWorkChanged() {
|
|
var workSelect = document.getElementById('it-worklog-work');
|
|
var detailsBox = document.getElementById('it-worklog-details');
|
|
var notesEl = document.getElementById('it-worklog-work-notes');
|
|
if (!detailsBox) return;
|
|
var data = itWorkCatalogData();
|
|
var labels = data.detail_labels || {};
|
|
var workId = workSelect ? workSelect.value : '';
|
|
var work = (data.works || []).find(function (w) { return String(w.id) === String(workId); });
|
|
detailsBox.innerHTML = '';
|
|
if (!work || !(work.required_details || []).length) {
|
|
detailsBox.style.display = 'none';
|
|
} else {
|
|
detailsBox.style.display = 'flex';
|
|
(work.required_details || []).forEach(function (key) {
|
|
var wrap = document.createElement('div');
|
|
var label = document.createElement('label');
|
|
label.style.cssText = 'display:block;font-size:0.8125rem;font-weight:500;color:var(--color-foreground);margin-bottom:0.375rem;';
|
|
label.textContent = labels[key] || key;
|
|
var star = document.createElement('span');
|
|
star.style.color = 'var(--color-destructive)';
|
|
star.textContent = ' *';
|
|
label.appendChild(star);
|
|
var input = document.createElement('input');
|
|
input.type = 'text';
|
|
input.name = 'detail_' + key;
|
|
input.required = true;
|
|
input.className = 'input';
|
|
input.style.width = '100%';
|
|
wrap.appendChild(label);
|
|
wrap.appendChild(input);
|
|
detailsBox.appendChild(wrap);
|
|
});
|
|
}
|
|
if (notesEl) {
|
|
if (work && work.notes) {
|
|
notesEl.style.display = '';
|
|
notesEl.textContent = work.notes;
|
|
} else {
|
|
notesEl.style.display = 'none';
|
|
notesEl.textContent = '';
|
|
}
|
|
}
|
|
}
|
|
|
|
function itWorklogRowCategoryChanged(logPk) {
|
|
var cat = document.getElementById('it-worklog-row-cat-' + logPk);
|
|
var work = document.getElementById('it-worklog-row-work-' + logPk);
|
|
if (!work) return;
|
|
var catId = cat ? cat.value : '';
|
|
var data = itWorkCatalogData();
|
|
var works = (data.works || []).filter(function (w) {
|
|
return catId && String(w.category_id) === String(catId);
|
|
});
|
|
work.innerHTML = '';
|
|
var empty = document.createElement('option');
|
|
empty.value = '';
|
|
empty.textContent = catId ? '— Выберите работу —' : '—';
|
|
work.appendChild(empty);
|
|
works.forEach(function (w) {
|
|
var opt = document.createElement('option');
|
|
opt.value = String(w.id);
|
|
opt.textContent = w.name;
|
|
work.appendChild(opt);
|
|
});
|
|
itWorklogRowWorkChanged(logPk, false);
|
|
}
|
|
|
|
function itWorklogRowWorkChanged(logPk, submit) {
|
|
var workSelect = document.getElementById('it-worklog-row-work-' + logPk);
|
|
var detailsBox = document.getElementById('it-worklog-row-details-' + logPk);
|
|
if (!detailsBox || !workSelect) return;
|
|
var data = itWorkCatalogData();
|
|
var labels = data.detail_labels || {};
|
|
var workId = workSelect.value;
|
|
var work = (data.works || []).find(function (w) { return String(w.id) === String(workId); });
|
|
var formId = 'worklog-form-' + logPk;
|
|
detailsBox.innerHTML = '';
|
|
if (work && (work.required_details || []).length) {
|
|
(work.required_details || []).forEach(function (key) {
|
|
var label = document.createElement('label');
|
|
label.style.cssText = 'font-size:0.6875rem;color:var(--color-muted-foreground);';
|
|
label.textContent = (labels[key] || key) + ' ';
|
|
var input = document.createElement('input');
|
|
input.type = 'text';
|
|
input.name = 'detail_' + key;
|
|
input.setAttribute('form', formId);
|
|
input.className = 'input';
|
|
input.style.cssText = 'width:100%;font-size:0.75rem;padding:0.2rem 0.35rem;margin-top:0.1rem;';
|
|
input.onchange = function () {
|
|
if (input.form) input.form.requestSubmit();
|
|
};
|
|
label.appendChild(document.createElement('br'));
|
|
label.appendChild(input);
|
|
detailsBox.appendChild(label);
|
|
});
|
|
}
|
|
if (submit && workId && workSelect.form) {
|
|
workSelect.form.requestSubmit();
|
|
}
|
|
}
|
|
|
|
function itWorklogFromTicket(ticket) {
|
|
if (!ticket || !ticket.id) return;
|
|
itTabSwitch('worklog');
|
|
itPanelOpen('it-worklog-panel');
|
|
|
|
itSetSearchableSelectValue('it-worklog-ticket', String(ticket.id));
|
|
if (ticket.locationId) {
|
|
itSetSearchableSelectValue('it-worklog-location', String(ticket.locationId));
|
|
}
|
|
var equipment = document.getElementById('it-worklog-equipment');
|
|
if (equipment && ticket.equipmentId) {
|
|
equipment.value = String(ticket.equipmentId);
|
|
}
|
|
var description = document.getElementById('it-worklog-description');
|
|
if (description && !description.value) {
|
|
description.value = 'Работа по заявке ' + ticket.number + (ticket.title ? ': ' + ticket.title : '');
|
|
}
|
|
var hint = document.getElementById('it-worklog-ticket-hint');
|
|
if (hint) {
|
|
hint.style.display = '';
|
|
hint.textContent = 'Заявка ' + ticket.number + (ticket.title ? ' — ' + ticket.title : '');
|
|
}
|
|
var catSelect = document.getElementById('it-worklog-category');
|
|
if (catSelect) catSelect.focus();
|
|
}
|
|
|
|
function itWorklogTicketChanged() {
|
|
var select = document.getElementById('it-worklog-ticket');
|
|
if (!select) return;
|
|
var opt = select.options[select.selectedIndex];
|
|
var hint = document.getElementById('it-worklog-ticket-hint');
|
|
if (!opt || !opt.value) {
|
|
if (hint) {
|
|
hint.style.display = 'none';
|
|
hint.textContent = '';
|
|
}
|
|
return;
|
|
}
|
|
var locationId = opt.getAttribute('data-location') || '';
|
|
var equipmentId = opt.getAttribute('data-equipment') || '';
|
|
if (locationId) itSetSearchableSelectValue('it-worklog-location', locationId);
|
|
var equipment = document.getElementById('it-worklog-equipment');
|
|
if (equipment && equipmentId) equipment.value = equipmentId;
|
|
if (hint) {
|
|
hint.style.display = '';
|
|
hint.textContent = opt.textContent.trim();
|
|
}
|
|
}
|
|
|
|
document.addEventListener('change', function (ev) {
|
|
if (ev.target && ev.target.id === 'it-worklog-ticket') {
|
|
itWorklogTicketChanged();
|
|
}
|
|
});
|
|
|
|
function itReportPreviewOpen(url, title) {
|
|
var overlay = document.getElementById('it-report-preview-overlay');
|
|
var modal = document.getElementById('it-report-preview-modal');
|
|
var frame = document.getElementById('it-report-preview-frame');
|
|
var subtitle = document.getElementById('it-report-preview-subtitle');
|
|
var openTab = document.getElementById('it-report-preview-open-tab');
|
|
if (!overlay || !modal || !frame) return;
|
|
|
|
if (subtitle) subtitle.textContent = title || '';
|
|
if (openTab) openTab.href = url;
|
|
frame.src = url;
|
|
overlay.style.display = 'block';
|
|
modal.style.display = 'flex';
|
|
document.body.style.overflow = 'hidden';
|
|
}
|
|
|
|
function itReportPreviewClose() {
|
|
var overlay = document.getElementById('it-report-preview-overlay');
|
|
var modal = document.getElementById('it-report-preview-modal');
|
|
var frame = document.getElementById('it-report-preview-frame');
|
|
if (overlay) overlay.style.display = 'none';
|
|
if (modal) modal.style.display = 'none';
|
|
if (frame) frame.src = 'about:blank';
|
|
document.body.style.overflow = '';
|
|
}
|
|
|
|
document.addEventListener('keydown', function (ev) {
|
|
if (ev.key !== 'Escape') return;
|
|
var modal = document.getElementById('it-report-preview-modal');
|
|
if (modal && modal.style.display === 'flex') itReportPreviewClose();
|
|
});
|
|
|
|
document.addEventListener('htmx:afterSwap', function (ev) {
|
|
var target = ev.detail && ev.detail.target;
|
|
if (!target || target.id !== 'main-content') return;
|
|
var root = target.querySelector('[data-it-active-tab]');
|
|
if (root && typeof itTabSwitch === 'function') {
|
|
itTabSwitch(root.getAttribute('data-it-active-tab') || 'equipment');
|
|
}
|
|
if (typeof initSearchableSelects === 'function') {
|
|
initSearchableSelects(target);
|
|
}
|
|
});
|
|
|