feat: add bulk images and tenant autofill
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
(() => {
|
||||
'use strict';
|
||||
|
||||
const dataElement = document.getElementById('netbox-utilities-frontend-data');
|
||||
if (!dataElement) return;
|
||||
|
||||
let config;
|
||||
try {
|
||||
config = JSON.parse(dataElement.textContent);
|
||||
} catch (_error) {
|
||||
return;
|
||||
}
|
||||
|
||||
function rewriteImageUploadLinks(root = document) {
|
||||
if (!config.image_attachment_add_url || !config.bulk_image_upload_url) return;
|
||||
const singleUploadPath = new URL(config.image_attachment_add_url, document.baseURI).pathname;
|
||||
|
||||
root.querySelectorAll('a[href]').forEach((link) => {
|
||||
const current = new URL(link.href, document.baseURI);
|
||||
if (current.pathname !== singleUploadPath) return;
|
||||
if (!current.searchParams.has('object_type') || !current.searchParams.has('object_id')) return;
|
||||
|
||||
const bulkUpload = new URL(config.bulk_image_upload_url, document.baseURI);
|
||||
bulkUpload.search = current.search;
|
||||
link.href = bulkUpload.href;
|
||||
link.title = 'Mehrere Bilder gleichzeitig hochladen';
|
||||
link.replaceChildren();
|
||||
const icon = document.createElement('i');
|
||||
icon.className = 'mdi mdi-image-multiple me-1';
|
||||
icon.setAttribute('aria-hidden', 'true');
|
||||
link.append(icon, document.createTextNode('Mehrere Bilder hochladen'));
|
||||
});
|
||||
}
|
||||
|
||||
function configureTenantConfirmation(root = document) {
|
||||
root.querySelectorAll('[data-netbox-utilities-autofilled-tenant]').forEach((field) => {
|
||||
const form = field.form;
|
||||
if (!form || form.dataset.netboxUtilitiesTenantConfirmation === 'true') return;
|
||||
form.dataset.netboxUtilitiesTenantConfirmation = 'true';
|
||||
|
||||
form.addEventListener('submit', (event) => {
|
||||
const candidateFields = form.querySelectorAll('[data-netbox-utilities-autofilled-tenant]');
|
||||
for (const candidateField of candidateFields) {
|
||||
const candidate = candidateField.dataset.netboxUtilitiesAutofilledTenant;
|
||||
if (!candidate || String(candidateField.value) !== candidate) continue;
|
||||
if (candidateField.dataset.netboxUtilitiesTenantConfirmed === candidate) continue;
|
||||
|
||||
const selectedOption = candidateField.selectedOptions?.[0];
|
||||
const tenantLabel = selectedOption?.textContent.trim() || `ID ${candidate}`;
|
||||
const confirmed = window.confirm(
|
||||
`Der Mandant „${tenantLabel}“ wurde automatisch erkannt. Bitte bestätigen Sie diese Zuordnung.`
|
||||
);
|
||||
if (!confirmed) {
|
||||
event.preventDefault();
|
||||
candidateField.focus();
|
||||
return;
|
||||
}
|
||||
candidateField.dataset.netboxUtilitiesTenantConfirmed = candidate;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function configureImagePreview(root = document) {
|
||||
const input = root.querySelector('.netbox-utilities-multi-image-input');
|
||||
const preview = document.getElementById('netbox-utilities-image-preview');
|
||||
if (!input || !preview || input.dataset.netboxUtilitiesPreview === 'true') return;
|
||||
input.dataset.netboxUtilitiesPreview = 'true';
|
||||
let objectUrls = [];
|
||||
|
||||
input.addEventListener('change', () => {
|
||||
objectUrls.forEach((url) => URL.revokeObjectURL(url));
|
||||
objectUrls = [];
|
||||
preview.replaceChildren();
|
||||
|
||||
Array.from(input.files).forEach((file) => {
|
||||
const objectUrl = URL.createObjectURL(file);
|
||||
objectUrls.push(objectUrl);
|
||||
const item = document.createElement('div');
|
||||
item.className = 'netbox-utilities-image-preview-item';
|
||||
const image = document.createElement('img');
|
||||
image.src = objectUrl;
|
||||
image.alt = '';
|
||||
const name = document.createElement('div');
|
||||
name.className = 'netbox-utilities-image-preview-name text-secondary mt-1';
|
||||
name.title = file.name;
|
||||
name.textContent = file.name;
|
||||
item.append(image, name);
|
||||
preview.appendChild(item);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initialize(root = document) {
|
||||
rewriteImageUploadLinks(root);
|
||||
configureTenantConfirmation(root);
|
||||
configureImagePreview(root);
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', () => initialize(), {once: true});
|
||||
} else {
|
||||
initialize();
|
||||
}
|
||||
document.addEventListener('htmx:afterSettle', (event) => initialize(event.target));
|
||||
})();
|
||||
@@ -10,6 +10,25 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.netbox-utilities-image-preview-item {
|
||||
width: 9rem;
|
||||
}
|
||||
|
||||
.netbox-utilities-image-preview-item img {
|
||||
width: 9rem;
|
||||
height: 7rem;
|
||||
object-fit: cover;
|
||||
border: 1px solid var(--tblr-border-color);
|
||||
border-radius: var(--tblr-border-radius);
|
||||
}
|
||||
|
||||
.netbox-utilities-image-preview-name {
|
||||
overflow: hidden;
|
||||
font-size: 0.75rem;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.netbox-utilities-sidebar-resizer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user