Enhance settings page; add room management functionality with combo box integration and update rendering logic for improved usability
This commit is contained in:
parent
ad413c3f1b
commit
ec08dd8ef1
4 changed files with 56 additions and 13 deletions
|
@ -436,4 +436,5 @@ def settings():
|
||||||
types = db.session.query(Item.id, Item.description.label("name")).order_by(Item.description).all()
|
types = db.session.query(Item.id, Item.description.label("name")).order_by(Item.description).all()
|
||||||
sections = db.session.query(Area).order_by(Area.name).all()
|
sections = db.session.query(Area).order_by(Area.name).all()
|
||||||
functions = db.session.query(RoomFunction.id, RoomFunction.description.label("name")).order_by(RoomFunction.description).all()
|
functions = db.session.query(RoomFunction.id, RoomFunction.description.label("name")).order_by(RoomFunction.description).all()
|
||||||
return render_template('settings.html', title="Settings", brands=brands, types=types, sections=sections, functions=functions)
|
rooms = eager_load_room_relationships(db.session.query(Room).order_by(Room.name)).all()
|
||||||
|
return render_template('settings.html', title="Settings", brands=brands, types=types, sections=sections, functions=functions, rooms=rooms)
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
const ComboBoxWidget = (() => {
|
const ComboBoxWidget = (() => {
|
||||||
let tempIdCounter = -1;
|
let tempIdCounter = -1;
|
||||||
|
|
||||||
function initComboBox(ns) {
|
function initComboBox(ns, config = {}) {
|
||||||
const input = document.querySelector(`#${ns}-input`);
|
const input = document.querySelector(`#${ns}-input`);
|
||||||
const list = document.querySelector(`#${ns}-list`);
|
const list = document.querySelector(`#${ns}-list`);
|
||||||
const addBtn = document.querySelector(`#${ns}-add`);
|
const addBtn = document.querySelector(`#${ns}-add`);
|
||||||
const removeBtn = document.querySelector(`#${ns}-remove`);
|
const removeBtn = document.querySelector(`#${ns}-remove`);
|
||||||
let currentlyEditing = null;
|
let currentlyEditing = null;
|
||||||
|
let tempIdCounter = -1;
|
||||||
|
|
||||||
if (!input || !list || !addBtn || !removeBtn) {
|
if (!input || !list || !addBtn || !removeBtn) {
|
||||||
console.warn(`ComboBoxWidget: Missing elements for namespace '${ns}'`);
|
console.warn(`ComboBoxWidget: Missing elements for namespace '${ns}'`);
|
||||||
|
@ -19,6 +20,7 @@ const ComboBoxWidget = (() => {
|
||||||
|
|
||||||
input.addEventListener('input', () => {
|
input.addEventListener('input', () => {
|
||||||
addBtn.disabled = input.value.trim() === '';
|
addBtn.disabled = input.value.trim() === '';
|
||||||
|
updateAddButtonIcon();
|
||||||
});
|
});
|
||||||
|
|
||||||
list.addEventListener('change', () => {
|
list.addEventListener('change', () => {
|
||||||
|
@ -26,10 +28,9 @@ const ComboBoxWidget = (() => {
|
||||||
removeBtn.disabled = selected.length === 0;
|
removeBtn.disabled = selected.length === 0;
|
||||||
|
|
||||||
if (selected.length === 1) {
|
if (selected.length === 1) {
|
||||||
// Load the text into input for editing
|
|
||||||
input.value = selected[0].textContent;
|
input.value = selected[0].textContent;
|
||||||
addBtn.disabled = input.value.trim() === '';
|
|
||||||
currentlyEditing = selected[0];
|
currentlyEditing = selected[0];
|
||||||
|
addBtn.disabled = input.value.trim() === '';
|
||||||
} else {
|
} else {
|
||||||
input.value = '';
|
input.value = '';
|
||||||
currentlyEditing = null;
|
currentlyEditing = null;
|
||||||
|
@ -44,28 +45,55 @@ const ComboBoxWidget = (() => {
|
||||||
if (!newItem) return;
|
if (!newItem) return;
|
||||||
|
|
||||||
if (currentlyEditing) {
|
if (currentlyEditing) {
|
||||||
|
if (config.onEdit) {
|
||||||
|
config.onEdit(currentlyEditing, newItem);
|
||||||
|
} else {
|
||||||
currentlyEditing.textContent = newItem;
|
currentlyEditing.textContent = newItem;
|
||||||
|
}
|
||||||
currentlyEditing = null;
|
currentlyEditing = null;
|
||||||
} else {
|
} else {
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
option.textContent = newItem;
|
option.textContent = newItem;
|
||||||
option.value = tempIdCounter--;
|
option.value = tempIdCounter--;
|
||||||
|
|
||||||
|
if (config.onAdd) {
|
||||||
|
config.onAdd(option);
|
||||||
|
}
|
||||||
|
|
||||||
list.appendChild(option);
|
list.appendChild(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
input.value = '';
|
input.value = '';
|
||||||
addBtn.disabled = true;
|
addBtn.disabled = true;
|
||||||
removeBtn.disabled = true;
|
removeBtn.disabled = true;
|
||||||
|
updateAddButtonIcon();
|
||||||
|
|
||||||
|
if (config.sort !== false) {
|
||||||
sortOptions(list);
|
sortOptions(list);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
removeBtn.addEventListener('click', () => {
|
removeBtn.addEventListener('click', () => {
|
||||||
Array.from(list.selectedOptions).forEach(opt => opt.remove());
|
Array.from(list.selectedOptions).forEach(option => {
|
||||||
|
if (config.onRemove) {
|
||||||
|
config.onRemove(option);
|
||||||
|
}
|
||||||
|
option.remove();
|
||||||
|
});
|
||||||
|
|
||||||
currentlyEditing = null;
|
currentlyEditing = null;
|
||||||
removeBtn.disabled = true;
|
|
||||||
input.value = '';
|
input.value = '';
|
||||||
addBtn.disabled = true;
|
addBtn.disabled = true;
|
||||||
|
removeBtn.disabled = true;
|
||||||
|
updateAddButtonIcon();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function sortOptions(selectElement) {
|
||||||
|
const sorted = Array.from(selectElement.options)
|
||||||
|
.sort((a, b) => a.text.localeCompare(b.text));
|
||||||
|
selectElement.innerHTML = '';
|
||||||
|
sorted.forEach(option => selectElement.appendChild(option));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortOptions(selectElement) {
|
function sortOptions(selectElement) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{% import "fragments/_icon_fragment.html" as icons %}
|
{% import "fragments/_icon_fragment.html" as icons %}
|
||||||
|
|
||||||
{% macro render_combobox(id, options, label=none, placeholder=none) %}
|
{% macro render_combobox(id, options, label=none, placeholder=none, onAdd=none, onRemove=none, onEdit=none) %}
|
||||||
{% if label %}
|
{% if label %}
|
||||||
<label for="{{ id }}-input" class="form-label">{{ label }}</label>
|
<label for="{{ id }}-input" class="form-label">{{ label }}</label>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -23,7 +23,11 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
ComboBoxWidget.initComboBox("{{ id }}");
|
ComboBoxWidget.initComboBox("{{ id }}", {
|
||||||
|
{% if onAdd %}onAdd: {{ onAdd }},{% endif %}
|
||||||
|
{% if onRemove %}onRemove: {{ onRemove }},{% endif %}
|
||||||
|
{% if onEdit %}onEdit: {{ onEdit }}{% endif %}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
|
@ -57,6 +57,16 @@
|
||||||
) }}
|
) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
{{ combos.render_combobox(
|
||||||
|
id='room',
|
||||||
|
options=rooms,
|
||||||
|
label='Rooms',
|
||||||
|
placeholder='Add a new room'
|
||||||
|
) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue