Add dynamic custom field display and remove redundant admin routes
Major improvements to tenant management: 1. Dynamic field display - Product lists now automatically show all custom fields based on tenant configuration (e.g., inventory, custom attributes) 2. Fixed Jinja2 template scoping issue - Product field values now correctly display in edit forms using selectattr filter 3. Simplified URL structure - Removed redundant /tenant/admin/ routes, all product management now at /tenant/ root 4. Enhanced tenant landing page - Added delete functionality with confirmation modal, shows all custom fields except images 5. Updated all routes and redirects to use simplified paths (/tenant/add, /tenant/edit, etc.) This consolidates the interface so /tenant/ serves as the main dashboard with full product management capabilities, while /tenant/settings handles configuration.
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
<div class="mt-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h2>Products</h2>
|
||||
<a href="/{{ tenant.id }}/admin/add" class="btn btn-primary">
|
||||
<a href="/{{ tenant.id }}/add" class="btn btn-primary">
|
||||
<i class="bi bi-plus-circle"></i> Add New Product
|
||||
</a>
|
||||
</div>
|
||||
@@ -29,8 +29,11 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Product ID</th>
|
||||
<th>Name</th>
|
||||
<th>Price</th>
|
||||
{% for custom_field in custom_fields %}
|
||||
{% if custom_field.fieldName != '_id' and custom_field.fieldType != 'IMAGE_URI' %}
|
||||
<th>{{ custom_field.label }}</th>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -38,45 +41,42 @@
|
||||
{% for product_id, product_data in products.items() %}
|
||||
<tr>
|
||||
<td>{{ product_id }}</td>
|
||||
{% for custom_field in custom_fields %}
|
||||
{% if custom_field.fieldName != '_id' and custom_field.fieldType != 'IMAGE_URI' %}
|
||||
<td>
|
||||
{% set matching_fields = product_data|selectattr('fieldName', 'equalto', custom_field.fieldName)|list %}
|
||||
{{ matching_fields[0].value if matching_fields else '' }}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<td>
|
||||
{% for field in product_data %}
|
||||
{% if field.fieldName == '_name' %}
|
||||
{{ field.value }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
{% for field in product_data %}
|
||||
{% if field.fieldName == '_price' %}
|
||||
{{ field.value }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="/{{ tenant.id }}/admin/edit/{{ product_id }}" class="btn btn-sm btn-outline-primary">
|
||||
<a href="/{{ tenant.id }}/edit/{{ product_id }}" class="btn btn-sm btn-outline-primary">
|
||||
<i class="bi bi-pencil"></i> Edit
|
||||
</a>
|
||||
<a href="/{{ tenant.id }}/admin/generate_barcode_page/{{ product_id }}" class="btn btn-sm btn-outline-success">
|
||||
<a href="/{{ tenant.id }}/generate_barcode_page/{{ product_id }}" class="btn btn-sm btn-outline-success">
|
||||
<i class="bi bi-upc-scan"></i> Barcodes
|
||||
</a>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger"
|
||||
data-bs-toggle="modal" data-bs-target="#deleteModal"
|
||||
data-product-id="{{ product_id }}"
|
||||
data-product-name="{% set matching_fields = product_data|selectattr('fieldName', 'equalto', '_name')|list %}{{ matching_fields[0].value if matching_fields else product_id }}">
|
||||
<i class="bi bi-trash"></i> Delete
|
||||
</button>
|
||||
<form id="delete-form-{{ product_id }}" action="/{{ tenant.id }}/delete/{{ product_id }}" method="POST" style="display: none;">
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<a href="/{{ tenant.id }}/admin/" class="btn btn-secondary">
|
||||
<i class="bi bi-list-task"></i> Manage All Products
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="bi bi-info-circle"></i> No products available yet. Click "Add New Product" to get started.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mt-4">
|
||||
<h2>Getting Started</h2>
|
||||
<ol>
|
||||
@@ -89,4 +89,51 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Delete Confirmation Modal -->
|
||||
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-danger text-white">
|
||||
<h5 class="modal-title" id="deleteModalLabel">Confirm Deletion</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Are you sure you want to delete the product <strong id="delete-product-name"></strong>?</p>
|
||||
<p class="text-danger"><i class="bi bi-exclamation-triangle-fill"></i> This action cannot be undone.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" id="confirm-delete-btn">Delete Product</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
// Delete confirmation modal functionality
|
||||
const deleteModal = document.getElementById('deleteModal');
|
||||
if (deleteModal) {
|
||||
deleteModal.addEventListener('show.bs.modal', function (event) {
|
||||
// Button that triggered the modal
|
||||
const button = event.relatedTarget;
|
||||
|
||||
// Extract product info from data attributes
|
||||
const productId = button.getAttribute('data-product-id');
|
||||
const productName = button.getAttribute('data-product-name');
|
||||
|
||||
// Update modal content
|
||||
const modalProductName = document.getElementById('delete-product-name');
|
||||
modalProductName.textContent = productName + " (ID: " + productId + ")";
|
||||
|
||||
// Setup the confirm button action
|
||||
const confirmDeleteBtn = document.getElementById('confirm-delete-btn');
|
||||
confirmDeleteBtn.onclick = function() {
|
||||
document.getElementById('delete-form-' + productId).submit();
|
||||
};
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user