fixing missing barcodes
This commit is contained in:
49
src/app.py
49
src/app.py
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
104
src/templates/tenant_settings.html
Normal file
104
src/templates/tenant_settings.html
Normal 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 %}
|
||||||
Reference in New Issue
Block a user