fixing missing barcodes

This commit is contained in:
2025-06-25 18:11:12 -04:00
parent 9f33e1aeb6
commit 6dc276a292
4 changed files with 216 additions and 30 deletions

View File

@@ -70,7 +70,46 @@ def tenant_index(tenant_id):
if tenant is None: if tenant is None:
# Reserved tenant ID or invalid # Reserved tenant ID or invalid
return jsonify({"error": f"'{tenant_id}' is a reserved name and cannot be used as a tenant ID"}), 404 return jsonify({"error": f"'{tenant_id}' is a reserved name and cannot be used as a tenant ID"}), 404
return render_template('index.html', tenant=tenant)
# Load products for this tenant
products = load_products(tenant_id)
return render_template('index.html', tenant=tenant, products=products)
@app.route('/<tenant:tenant_id>/settings')
def tenant_settings(tenant_id):
# Get tenant
tenant = database.get_or_create_tenant(tenant_id)
if tenant is None:
return jsonify({"error": f"'{tenant_id}' is a reserved name and cannot be used as a tenant ID"}), 404
# Get custom AR fields for this tenant
custom_fields = database.get_custom_ar_fields(tenant_id)
# Get server URL for API endpoint display
server_url = database.get_server_url()
return render_template('tenant_settings.html', tenant=tenant, custom_fields=custom_fields, server_url=server_url)
@app.route('/<tenant:tenant_id>/settings/credentials', methods=['POST'])
def update_tenant_credentials(tenant_id):
# Get tenant
tenant = database.get_tenant(tenant_id)
if tenant is None:
return jsonify({"error": "Tenant not found"}), 404
username = request.form.get('username', '').strip()
password = request.form.get('password', '').strip()
if not username:
flash('Username is required.', 'error')
return redirect(f'/{tenant_id}/settings')
# Update credentials
database.update_tenant_credentials(tenant_id, username, password if password else None)
flash('Credentials updated successfully.', 'success')
return redirect(f'/{tenant_id}/settings')
def check_basic_auth(auth_header, tenant_id): def check_basic_auth(auth_header, tenant_id):
"""Validate Basic authentication credentials for a tenant""" """Validate Basic authentication credentials for a tenant"""
@@ -119,10 +158,14 @@ def get_ar_info(tenant_id):
def filter_and_process_fields(product_fields): def filter_and_process_fields(product_fields):
# Filter to only include fields defined in custom AR fields # Filter to only include fields defined in custom AR fields
filtered_fields = [] filtered_fields = []
# Get field types for all custom fields
field_types = {f['fieldName']: f['fieldType'] for f in custom_fields}
for field in product_fields: for field in product_fields:
if field['fieldName'] in custom_field_names: if field['fieldName'] in custom_field_names:
# Create absolute URL for image fields # Create absolute URL for IMAGE_URI fields
if field['fieldName'] == '_image' and field['value']: if field_types.get(field['fieldName']) == 'IMAGE_URI' and field['value']:
# If it's already an absolute URL, leave it as is # If it's already an absolute URL, leave it as is
if not field['value'].startswith('http'): if not field['value'].startswith('http'):
# Build absolute URL using request host with tenant # Build absolute URL using request host with tenant

View File

@@ -86,8 +86,8 @@
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<p><strong>AR Info URL:</strong> <p><strong>AR Info URL:</strong>
<a href="{{ url_for('get_ar_info', barcode=product_id) }}" target="_blank"> <a href="{{ url_for('get_ar_info', tenant_id=tenant_id, barcode=product_id) }}" target="_blank">
{{ url_for('get_ar_info', barcode=product_id, _external=True) }} {{ url_for('get_ar_info', tenant_id=tenant_id, barcode=product_id, _external=True) }}
</a> </a>
</p> </p>
</div> </div>

View File

@@ -5,37 +5,76 @@
{% block content %} {% block content %}
<div class="row mt-4"> <div class="row mt-4">
<div class="col-md-12"> <div class="col-md-12">
<div class="jumbotron"> <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>
<h1 class="display-4">KCAP Demo Server{% if tenant %} - {{ tenant.name }}{% endif %}</h1> <h1 class="display-4">KCAP Demo Server{% if tenant %} - {{ tenant.name }}{% endif %}</h1>
<p class="lead">Manage your product catalog and AR content for barcode scanning applications.</p> <p class="lead">Manage your product catalog and AR content for barcode scanning applications.</p>
<hr class="my-4"> <hr class="my-4">
<div class="mt-4"> <div class="mt-4">
<h2>Quick Actions</h2> <div class="d-flex justify-content-between align-items-center mb-3">
<div class="row"> <h2>Products</h2>
<div class="col-md-6"> <a href="/{{ tenant.id }}/admin/add" class="btn btn-primary">
<div class="card mb-3"> <i class="bi bi-plus-circle"></i> Add New Product
<div class="card-body"> </a>
<h5 class="card-title">Product Management</h5> </div>
<p class="card-text">Add, edit, and manage your product catalog with custom fields.</p>
{% if tenant %} {% if products %}
<a href="/{{ tenant.id }}/admin/" class="btn btn-primary">Manage Products</a> <div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Product ID</th>
<th>Name</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for product_id, product_data in products.items() %}
<tr>
<td>{{ product_id }}</td>
<td>
{% for field in product_data %}
{% if field.fieldName == '_name' %}
{{ field.value }}
{% endif %} {% endif %}
</div> {% endfor %}
</div> </td>
</div> <td>
<div class="col-md-6"> {% for field in product_data %}
<div class="card mb-3"> {% if field.fieldName == '_price' %}
<div class="card-body"> {{ field.value }}
<h5 class="card-title">AR Field Configuration</h5>
<p class="card-text">Customize the fields returned by AR content endpoints.</p>
{% if tenant %}
<a href="/{{ tenant.id }}/admin/ar_fields" class="btn btn-primary">Configure AR Fields</a>
{% endif %} {% endif %}
{% endfor %}
</td>
<td>
<a href="/{{ tenant.id }}/admin/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">
<i class="bi bi-upc-scan"></i> Barcodes
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </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> </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> </div>
</div> {% endif %}
</div> </div>
<div class="mt-4"> <div class="mt-4">

View File

@@ -0,0 +1,104 @@
{% extends "layout.html" %}
{% block title %}Settings - {{ tenant.name }} - KCAP Demo Server{% endblock %}
{% block content %}
<div class="row mt-4">
<div class="col-md-12">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>Settings - {{ tenant.name }}</h1>
<a href="/{{ tenant.id }}/" class="btn btn-secondary">
<i class="bi bi-arrow-left"></i> Back to Dashboard
</a>
</div>
<div class="row">
<!-- Device Password Section -->
<div class="col-md-6">
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0"><i class="bi bi-shield-lock"></i> Device Authentication</h5>
</div>
<div class="card-body">
<p class="text-muted">Configure the username and password for device authentication.</p>
<form method="POST" action="/{{ tenant.id }}/settings/credentials">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username"
value="{{ tenant.username }}" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password"
placeholder="Enter new password to change" autocomplete="new-password">
<div class="form-text">Leave blank to keep current password</div>
</div>
<button type="submit" class="btn btn-primary">
<i class="bi bi-save"></i> Update Credentials
</button>
</form>
</div>
</div>
</div>
<!-- Custom AR Fields Section -->
<div class="col-md-6">
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0"><i class="bi bi-list-ul"></i> Custom AR Content Fields</h5>
</div>
<div class="card-body">
<p class="text-muted">Manage the fields that are returned in the AR content API.</p>
<a href="/{{ tenant.id }}/admin/ar_fields" class="btn btn-primary">
<i class="bi bi-gear"></i> Manage AR Fields
</a>
{% if custom_fields %}
<div class="mt-3">
<h6>Current Fields:</h6>
<ul class="list-group">
{% for field in custom_fields %}
<li class="list-group-item d-flex justify-content-between align-items-center">
<div>
<strong>{{ field.label }}</strong>
<small class="text-muted">({{ field.fieldName }})</small>
</div>
<span class="badge bg-secondary">{{ field.fieldType }}</span>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Additional Settings -->
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h5 class="mb-0"><i class="bi bi-info-circle"></i> Tenant Information</h5>
</div>
<div class="card-body">
<dl class="row">
<dt class="col-sm-3">Tenant ID:</dt>
<dd class="col-sm-9"><code>{{ tenant.id }}</code></dd>
<dt class="col-sm-3">Tenant Name:</dt>
<dd class="col-sm-9">{{ tenant.name }}</dd>
<dt class="col-sm-3">API Endpoint:</dt>
<dd class="col-sm-9"><code>{{ server_url }}/{{ tenant.id }}/arinfo</code></dd>
<dt class="col-sm-3">Created:</dt>
<dd class="col-sm-9">{{ tenant.created_at }}</dd>
</dl>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}