2025-05-08 20:49:15 -04:00
|
|
|
{% extends "layout.html" %}
|
|
|
|
|
|
|
|
|
|
{% block title %}Home - KCAP Demo Server{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block content %}
|
|
|
|
|
<div class="row mt-4">
|
|
|
|
|
<div class="col-md-12">
|
2025-06-25 18:11:12 -04:00
|
|
|
<div class="jumbotron position-relative">
|
|
|
|
|
<div class="position-absolute top-0 end-0 p-3">
|
|
|
|
|
<a href="/{{ tenant.id }}/settings" class="btn btn-secondary" title="Settings">
|
|
|
|
|
<i class="bi bi-gear-fill"></i> Settings
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
2025-06-19 14:25:42 -04:00
|
|
|
<h1 class="display-4">KCAP Demo Server{% if tenant %} - {{ tenant.name }}{% endif %}</h1>
|
2025-06-19 15:46:22 -04:00
|
|
|
<p class="lead">Manage your product catalog and AR content for barcode scanning applications.</p>
|
2025-05-08 20:49:15 -04:00
|
|
|
<hr class="my-4">
|
2025-06-19 15:46:22 -04:00
|
|
|
|
2025-05-08 20:49:15 -04:00
|
|
|
<div class="mt-4">
|
2025-06-25 18:11:12 -04:00
|
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
|
|
|
<h2>Products</h2>
|
2025-10-20 17:11:26 -04:00
|
|
|
<a href="/{{ tenant.id }}/add" class="btn btn-primary">
|
2025-06-25 18:11:12 -04:00
|
|
|
<i class="bi bi-plus-circle"></i> Add New Product
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{% if products %}
|
|
|
|
|
<div class="table-responsive">
|
|
|
|
|
<table class="table table-striped table-hover">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>Product ID</th>
|
2025-10-20 17:11:26 -04:00
|
|
|
{% for custom_field in custom_fields %}
|
2025-10-20 17:17:58 -04:00
|
|
|
{% if custom_field.fieldName != '_id' %}
|
2025-10-20 17:11:26 -04:00
|
|
|
<th>{{ custom_field.label }}</th>
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% endfor %}
|
2025-06-25 18:11:12 -04:00
|
|
|
<th>Actions</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
{% for product_id, product_data in products.items() %}
|
|
|
|
|
<tr>
|
|
|
|
|
<td>{{ product_id }}</td>
|
2025-10-20 17:11:26 -04:00
|
|
|
{% for custom_field in custom_fields %}
|
2025-10-20 17:17:58 -04:00
|
|
|
{% if custom_field.fieldName != '_id' %}
|
2025-10-20 17:11:26 -04:00
|
|
|
<td>
|
|
|
|
|
{% set matching_fields = product_data|selectattr('fieldName', 'equalto', custom_field.fieldName)|list %}
|
2025-10-20 17:17:58 -04:00
|
|
|
{% if custom_field.fieldType == 'IMAGE_URI' %}
|
|
|
|
|
{% if matching_fields and matching_fields[0].value %}
|
|
|
|
|
<div class="product-image-container">
|
|
|
|
|
<img src="/{{ tenant.id }}{{ matching_fields[0].value }}" alt="{{ custom_field.label }}" class="product-image">
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% else %}
|
|
|
|
|
{{ matching_fields[0].value if matching_fields else '' }}
|
|
|
|
|
{% endif %}
|
2025-10-20 17:11:26 -04:00
|
|
|
</td>
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% endfor %}
|
2025-06-25 18:11:12 -04:00
|
|
|
<td>
|
2025-10-20 17:11:26 -04:00
|
|
|
<a href="/{{ tenant.id }}/edit/{{ product_id }}" class="btn btn-sm btn-outline-primary">
|
2025-06-25 18:11:12 -04:00
|
|
|
<i class="bi bi-pencil"></i> Edit
|
|
|
|
|
</a>
|
2025-10-20 17:11:26 -04:00
|
|
|
<a href="/{{ tenant.id }}/generate_barcode_page/{{ product_id }}" class="btn btn-sm btn-outline-success">
|
2025-06-25 18:11:12 -04:00
|
|
|
<i class="bi bi-upc-scan"></i> Barcodes
|
|
|
|
|
</a>
|
2025-10-20 17:11:26 -04:00
|
|
|
<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>
|
2025-06-25 18:11:12 -04:00
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</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.
|
2025-06-19 15:46:22 -04:00
|
|
|
</div>
|
2025-06-25 18:11:12 -04:00
|
|
|
{% endif %}
|
2025-05-08 20:49:15 -04:00
|
|
|
</div>
|
2025-10-20 17:11:26 -04:00
|
|
|
|
2025-05-08 20:49:15 -04:00
|
|
|
<div class="mt-4">
|
2025-06-19 15:46:22 -04:00
|
|
|
<h2>Getting Started</h2>
|
|
|
|
|
<ol>
|
|
|
|
|
<li>Configure your AR fields to define what information is returned for products</li>
|
|
|
|
|
<li>Add products to your catalog with the configured fields</li>
|
|
|
|
|
<li>Generate barcodes for your products</li>
|
|
|
|
|
<li>Use the AR endpoints in your scanning application</li>
|
|
|
|
|
</ol>
|
2025-05-08 20:49:15 -04:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-10-20 17:11:26 -04:00
|
|
|
|
|
|
|
|
<!-- 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>
|
2025-05-08 20:49:15 -04:00
|
|
|
{% endblock %}
|