Refactor dropdown and table components, add dynamic table functionality, and update stylesheets for improved UI
This commit is contained in:
parent
3d20462c71
commit
32993800fe
7 changed files with 89 additions and 8 deletions
4
inventory/static/css/dropdown.css
Normal file
4
inventory/static/css/dropdown.css
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
.dropdown-search-input:focus {
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,8 @@ function DropDown(cfg) {
|
||||||
this.selectedId = v;
|
this.selectedId = v;
|
||||||
this.$refs.clear?.classList.remove('d-none');
|
this.$refs.clear?.classList.remove('d-none');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.$refs.button.addEventListener('shown.bs.dropdown', (e) => this.onShown(e));
|
||||||
},
|
},
|
||||||
|
|
||||||
itemSelect(e) {
|
itemSelect(e) {
|
||||||
|
|
@ -79,6 +81,27 @@ function DropDown(cfg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$dispatch('dropdown:cleared', {});
|
this.$dispatch('dropdown:cleared', {});
|
||||||
|
},
|
||||||
|
|
||||||
|
onShown() {
|
||||||
|
const { menu, search, content } = this.$refs || {};
|
||||||
|
if (!menu || !search || !content) return;
|
||||||
|
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
const viewportH = window.innerHeight;
|
||||||
|
const menuTop = menu.getBoundingClientRect().top;
|
||||||
|
|
||||||
|
const capByViewport = viewportH * 0.40;
|
||||||
|
const spaceBelow = viewportH - menuTop - 12;
|
||||||
|
const menuCap = Math.max(0, Math.min(capByViewport, spaceBelow));
|
||||||
|
|
||||||
|
const inputH = search.offsetHeight || 0;
|
||||||
|
const contentMax = Math.max(0, menuCap - inputH);
|
||||||
|
|
||||||
|
content.style.maxHeight = `${contentMax - 2}px`;
|
||||||
|
|
||||||
|
requestAnimationFrame(() => search.focus());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
recordId: {{ record_id|tojson if record_id else "null" }},
|
recordId: {{ record_id|tojson if record_id else "null" }},
|
||||||
field: {{ field_name|tojson if field_name else "null" }}
|
field: {{ field_name|tojson if field_name else "null" }}
|
||||||
})'
|
})'
|
||||||
hx-preserve x-init="init()">
|
hx-preserve x-init="init()" x-ref="dropdown">
|
||||||
<div class="btn-group w-100">
|
<div class="btn-group w-100">
|
||||||
<button
|
<button
|
||||||
class="btn btn-outline-dark dropdown-toggle overflow-x-hidden w-100 rounded-end{% if current_item and enabled %}-0 border-end-0{% endif %} dropdown-button"
|
class="btn btn-outline-dark dropdown-toggle overflow-x-hidden w-100 rounded-end{% if current_item and enabled %}-0 border-end-0{% endif %} dropdown-button"
|
||||||
|
|
@ -34,11 +34,11 @@
|
||||||
{{ icons.render_icon('x-lg', 16) }}
|
{{ icons.render_icon('x-lg', 16) }}
|
||||||
</button>
|
</button>
|
||||||
<input type="hidden" name="{{ id }}" id="{{ id }}" value="{{ current_item.id if current_item else '' }}" x-ref="hidden">
|
<input type="hidden" name="{{ id }}" id="{{ id }}" value="{{ current_item.id if current_item else '' }}" x-ref="hidden">
|
||||||
<ul class="dropdown-menu w-100 pt-0" style="max-height: 40vh; z-index: 9999;" id="menu{{ id }}">
|
<ul class="dropdown-menu w-100 pt-0" style="max-height: 40vh; z-index: 9999;" id="menu{{ id }}" x-ref="menu">
|
||||||
<input type="text"
|
<input type="text"
|
||||||
class="form-control rounded-bottom-0 border-start-0 border-top-0 border-end-0 dropdown-search-input"
|
class="form-control rounded-bottom-0 border-start-0 border-top-0 border-end-0 dropdown-search-input"
|
||||||
id="search{{ id }}" placeholder="Search...">
|
id="search{{ id }}" placeholder="Search..." x-ref="search">
|
||||||
<div class="overflow-auto overflow-x-hidden" style="z-index: 9999;" id="{{ id }}DropdownContent">
|
<div class="overflow-auto overflow-x-hidden" style="z-index: 9999;" id="{{ id }}DropdownContent" x-ref="content">
|
||||||
{% if list %}
|
{% if list %}
|
||||||
{% for item in list %}
|
{% for item in list %}
|
||||||
<li><a class="dropdown-item" data-inv-value="{{ item.id }}">{{
|
<li><a class="dropdown-item" data-inv-value="{{ item.id }}">{{
|
||||||
|
|
|
||||||
|
|
@ -50,3 +50,56 @@
|
||||||
<div class="container text-center">No data.</div>
|
<div class="container text-center">No data.</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro dynamic_table(headers, rows, id, entry_route=None, title=None, per_page=15) %}
|
||||||
|
<!-- Table Fragment -->
|
||||||
|
|
||||||
|
{% if rows %}
|
||||||
|
{% if title %}
|
||||||
|
<label for="datatable-{{ id|default('table')|replace(' ', '-')|lower }}" class="form-label">{{ title }}</label>
|
||||||
|
{% endif %}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table id="datatable-{{ id|default('table')|replace(' ', '-')|lower }}"
|
||||||
|
class="table table-bordered table-sm table-hover table-striped table-light m-0{% if title %} caption-top{% endif %}">
|
||||||
|
<thead class="sticky-top">
|
||||||
|
<tr>
|
||||||
|
{% for h in headers %}
|
||||||
|
<th class="text-nowrap">{{ h }}</th>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for row in rows %}
|
||||||
|
<tr {% if entry_route %}onclick="window.location='{{ url_for('main.' + entry_route, id=row.id) }}'"
|
||||||
|
style="cursor: pointer;"{% endif %}{% if row['highlight'] %} class="table-info"{% endif %}>
|
||||||
|
{% for cell in row.cells %}
|
||||||
|
<td class="text-nowrap{% if cell.type=='bool' %} text-center{% endif %}">
|
||||||
|
{% if cell.type == 'bool' %}
|
||||||
|
{{ cell.html | safe }}
|
||||||
|
{% elif cell.url %}
|
||||||
|
<a class="link-success link-underline-opacity-0" href="{{ cell.url }}">{{ cell.text }}</a>
|
||||||
|
{% else %}
|
||||||
|
{{ cell.text or '-' }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
new DataTable('#datatable-{{ id|default('table')|replace(' ', ' - ')|lower }}', {
|
||||||
|
pageLength: {{ per_page }},
|
||||||
|
scrollX: true,
|
||||||
|
scrollY: '60vh',
|
||||||
|
scrollCollapse: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{% else %}
|
||||||
|
<div class="container text-center">No data.</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
@ -28,7 +28,8 @@
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.8.1/github-markdown.min.css"
|
href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.8.1/github-markdown.min.css"
|
||||||
integrity="sha512-BrOPA520KmDMqieeM7XFe6a3u3Sb3F1JBaQnrIAmWg3EYrciJ+Qqe6ZcKCdfPv26rGcgTrJnZ/IdQEct8h3Zhw=="
|
integrity="sha512-BrOPA520KmDMqieeM7XFe6a3u3Sb3F1JBaQnrIAmWg3EYrciJ+Qqe6ZcKCdfPv26rGcgTrJnZ/IdQEct8h3Zhw=="
|
||||||
crossorigin="anonymous" referrerpolicy="no-referrer" />
|
crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/widget.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/combobox.css') }}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/dropdown.css') }}">
|
||||||
<style>
|
<style>
|
||||||
{% block style %}{% endblock %}
|
{% block style %}{% endblock %}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -26,5 +26,5 @@
|
||||||
) }}
|
) }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{{ tables.render_table(headers=header, rows=rows, id='table', entry_route=entry_route) }}
|
{{ tables.dynamic_table(headers=header, rows=rows, id='table', entry_route=entry_route) }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue