mirror of
https://github.com/LD-Reborn/Berufsschule_HAM.git
synced 2025-12-20 06:51:55 +00:00
Merge pull request #177 from LD-Reborn/176-feature-add-user-selection-drop-down-for-assets-owner-field
176 feature add user selection drop down for assets owner field
This commit is contained in:
@@ -157,4 +157,13 @@
|
|||||||
<data name="Add Barcode to print batch" xml:space="preserve">
|
<data name="Add Barcode to print batch" xml:space="preserve">
|
||||||
<value>Barcode zum Druckauftragsstapel hinzufügen</value>
|
<value>Barcode zum Druckauftragsstapel hinzufügen</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Select location" xml:space="preserve">
|
||||||
|
<value>Ort auswählen</value>
|
||||||
|
</data>
|
||||||
|
<data name="Select owner" xml:space="preserve">
|
||||||
|
<value>Besitzer auswählen</value>
|
||||||
|
</data>
|
||||||
|
<data name="Select user" xml:space="preserve">
|
||||||
|
<value>Benutzer auswählen</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
@{
|
@{
|
||||||
ViewData["Title"] = T["Assets"];
|
ViewData["Title"] = T["Assets"];
|
||||||
}
|
}
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/tom-select/dist/css/tom-select.bootstrap5.min.css" rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'"/>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/tom-select/dist/js/tom-select.complete.min.js" defer></script>
|
||||||
|
|
||||||
<partial name="_BatchButton"/>
|
<partial name="_BatchButton"/>
|
||||||
|
|
||||||
@@ -177,9 +179,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label">@T["Owner"]</label>
|
<label class="form-label">@T["Owner"]</label>
|
||||||
<input type="text" class="form-control" name="Owner" />
|
<select class="form-select" name="Owner" id="createUsersSelect">
|
||||||
|
<option value="">@T["Select owner"]</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label">@T["Serial Number"]</label>
|
<label class="form-label">@T["Serial Number"]</label>
|
||||||
<input type="text" class="form-control" name="SerialNumber" />
|
<input type="text" class="form-control" name="SerialNumber" />
|
||||||
@@ -388,9 +391,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label">@T["Owner"]</label>
|
<label class="form-label">@T["Owner"]</label>
|
||||||
<input type="text" class="form-control" name="Owner" />
|
<select class="form-select" name="Owner" id="updateUsersSelect">
|
||||||
|
<option value="">@T["Select owner"]</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label">@T["Serial Number"]</label>
|
<label class="form-label">@T["Serial Number"]</label>
|
||||||
<input type="text" class="form-control" name="SerialNumber" />
|
<input type="text" class="form-control" name="SerialNumber" />
|
||||||
@@ -485,13 +489,16 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
updateAttributesContainer.innerHTML = '';
|
updateAttributesContainer.innerHTML = '';
|
||||||
updateForm.reset();
|
updateForm.reset();
|
||||||
const locationSelect = updateForm.querySelector('#updateLocationSelect');
|
|
||||||
await loadLocationsIntoSelect(locationSelect);
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/Assets/Get?cn=${assetId}`);
|
const response = await fetch(`/Assets/Get?cn=${assetId}`);
|
||||||
const responseJson = await response.json();
|
const responseJson = await response.json();
|
||||||
const asset = responseJson.assetsModel;
|
const asset = responseJson.assetsModel;
|
||||||
|
|
||||||
|
const locationSelect = updateForm.querySelector('#updateLocationSelect');
|
||||||
|
await loadLocationsIntoSelect(locationSelect, asset.Location);
|
||||||
|
const usersSelect = updateForm.querySelector('#updateUsersSelect');
|
||||||
|
await loadUsersIntoSelect(usersSelect, asset.Owner);
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(asset)) {
|
for (const [key, value] of Object.entries(asset)) {
|
||||||
const input = updateForm.querySelector(`[name="${key}"]`);
|
const input = updateForm.querySelector(`[name="${key}"]`);
|
||||||
if (input) input.value = value;
|
if (input) input.value = value;
|
||||||
@@ -762,11 +769,67 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
const createModal = document.getElementById('createAssetModal');
|
const createModal = document.getElementById('createAssetModal');
|
||||||
createModal.addEventListener('show.bs.modal', async () => {
|
createModal.addEventListener('show.bs.modal', async () => {
|
||||||
const select = createModal.querySelector('#createLocationSelect');
|
const selectLocations = createModal.querySelector('#createLocationSelect');
|
||||||
await loadLocationsIntoSelect(select);
|
await loadLocationsIntoSelect(selectLocations);
|
||||||
|
const selectUsers = createModal.querySelector('#createUsersSelect');
|
||||||
|
await loadUsersIntoSelect(selectUsers);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<!-- TomSelect dropdowns -->
|
||||||
|
<script>
|
||||||
|
// Locations dropdowns
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const createLocationSelect = document.getElementById('createLocationSelect');
|
||||||
|
const updateLocationSelect = document.getElementById('updateLocationSelect');
|
||||||
|
|
||||||
|
async function initLocationSelect(selectElement) {
|
||||||
|
if (!selectElement) return;
|
||||||
|
await loadLocationsIntoSelect(selectElement);
|
||||||
|
new TomSelect(selectElement, {
|
||||||
|
plugins: ['clear_button'],
|
||||||
|
create: false,
|
||||||
|
sortField: { field: 'text', direction: 'asc' },
|
||||||
|
placeholder: '@T["Select location"]',
|
||||||
|
maxOptions: 500, // avoid performance hit if there are many
|
||||||
|
render: {
|
||||||
|
no_results: function(data, escape) {
|
||||||
|
return `<div class="no-results">@T["No locations found"]</div>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initLocationSelect(createLocationSelect);
|
||||||
|
initLocationSelect(updateLocationSelect);
|
||||||
|
|
||||||
|
// Users dropdowns
|
||||||
|
const createUsersSelect = document.getElementById('createUsersSelect');
|
||||||
|
const updateUsersSelect = document.getElementById('updateUsersSelect');
|
||||||
|
|
||||||
|
async function initUsersSelect(selectElement) {
|
||||||
|
if (!selectElement) return;
|
||||||
|
await loadUsersIntoSelect(selectElement);
|
||||||
|
new TomSelect(selectElement, {
|
||||||
|
plugins: ['clear_button'],
|
||||||
|
create: false,
|
||||||
|
sortField: { field: 'text', direction: 'asc' },
|
||||||
|
placeholder: '@T["Select user"]',
|
||||||
|
maxOptions: 500, // avoid performance hit if there are many
|
||||||
|
render: {
|
||||||
|
no_results: function(data, escape) {
|
||||||
|
return `<div class="no-results">@T["No users found"]</div>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initUsersSelect(createUsersSelect);
|
||||||
|
initUsersSelect(updateUsersSelect);
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<partial name="_Batch"/>
|
<partial name="_Batch"/>
|
||||||
@@ -20,7 +20,9 @@
|
|||||||
<script>
|
<script>
|
||||||
window.appTranslations = {
|
window.appTranslations = {
|
||||||
selectLocation: '@T["Select location"]',
|
selectLocation: '@T["Select location"]',
|
||||||
errorLoading: '@T["Error loading locations"]'
|
errorLoadingLocations: '@T["Error loading locations"]',
|
||||||
|
selectUser: '@T["Select user"]',
|
||||||
|
errorLoadingUsers: '@T["Error loading users"]'
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -40,4 +40,27 @@ body {
|
|||||||
width: 2rem;
|
width: 2rem;
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Tomselect dark mode theme */
|
||||||
|
[data-bs-theme="dark"] .ts-control,
|
||||||
|
[data-bs-theme="dark"] .ts-dropdown {
|
||||||
|
color: #f8f9fa !important;
|
||||||
|
border-color: #444 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .ts-control input,
|
||||||
|
[data-bs-theme="dark"] .ts-dropdown .option,
|
||||||
|
[data-bs-theme="dark"] .ts-dropdown .item {
|
||||||
|
color: #f8f9fa !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .ts-dropdown .option:hover,
|
||||||
|
[data-bs-theme="dark"] .ts-dropdown .active {
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme="dark"] .ts-control .item {
|
||||||
|
color: #f8f9fa !important;
|
||||||
|
border-color: #666 !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -123,20 +123,65 @@ async function loadLocationsIntoSelect(selectElement, selectedValue = null) {
|
|||||||
const response = await fetch('/Locations/Index');
|
const response = await fetch('/Locations/Index');
|
||||||
const locations = await response.json();
|
const locations = await response.json();
|
||||||
|
|
||||||
selectElement.innerHTML = `<option value="">${appTranslations.selectLocation}</option>`;
|
const ts = selectElement.tomselect;
|
||||||
|
|
||||||
|
if (!ts) {
|
||||||
|
selectElement.innerHTML = `<option value="">${appTranslations.selectLocation}</option>`;
|
||||||
|
locations.forEach(loc => {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = loc.location;
|
||||||
|
option.textContent = loc.location;
|
||||||
|
if (selectedValue && selectedValue === loc.location) {
|
||||||
|
option.selected = true;
|
||||||
|
}
|
||||||
|
selectElement.appendChild(option);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ts.clearOptions();
|
||||||
|
ts.addOption(locations.map(loc => ({
|
||||||
|
value: loc.location,
|
||||||
|
text: loc.location
|
||||||
|
})));
|
||||||
|
ts.refreshOptions(false);
|
||||||
|
|
||||||
|
if (selectedValue) {
|
||||||
|
ts.setValue(selectedValue);
|
||||||
|
} else {
|
||||||
|
ts.clear(true);
|
||||||
|
}
|
||||||
|
|
||||||
locations.forEach(loc => {
|
|
||||||
const text = `${loc.description.Location}, Room ${loc.description.RoomNumber}, Seat ${loc.description.Seat}`;
|
|
||||||
const option = document.createElement('option');
|
|
||||||
option.value = loc.location;
|
|
||||||
option.textContent = text;
|
|
||||||
if (selectedValue && selectedValue === loc.location) {
|
|
||||||
option.selected = true;
|
|
||||||
}
|
|
||||||
selectElement.appendChild(option);
|
|
||||||
});
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error loading locations:', err);
|
console.error('Error loading locations:', err);
|
||||||
showToast(appTranslations.errorLoading, 'danger');
|
showToast(appTranslations.errorLoadingLocations, 'danger');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadUsersIntoSelect(selectElement, selectedValue = null) {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/Users/Index?Cn=false&Sn=false&Title=false&Description=false&JpegPhoto=false&UserPassword=false');
|
||||||
|
const users = await response.json();
|
||||||
|
|
||||||
|
const ts = selectElement.tomselect;
|
||||||
|
if (!ts) {
|
||||||
|
selectElement.innerHTML = `<option value="">${appTranslations.selectUser}</option>`;
|
||||||
|
users.forEach(u => {
|
||||||
|
const opt = document.createElement('option');
|
||||||
|
opt.value = u.uid;
|
||||||
|
opt.textContent = u.uid;
|
||||||
|
selectElement.appendChild(opt);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ts.clearOptions();
|
||||||
|
ts.addOption(users.map(u => ({ value: u.uid, text: u.uid })));
|
||||||
|
ts.refreshOptions(false);
|
||||||
|
|
||||||
|
if (selectedValue) ts.setValue(selectedValue);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error loading users:', err);
|
||||||
|
showToast(appTranslations.errorLoadingUsers, 'danger');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user