zebra-day 1.0.2__py3-none-any.whl → 2.1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zebra_day/__init__.py +7 -2
- zebra_day/_version.py +1 -0
- zebra_day/cli/__init__.py +80 -30
- zebra_day/cli/cognito.py +15 -9
- zebra_day/cli/gui.py +101 -13
- zebra_day/cli/printer.py +34 -27
- zebra_day/cli/template.py +19 -15
- zebra_day/cmd_mgr.py +3 -6
- zebra_day/docs/gx420d-gx430d-ug-en.pdf +0 -0
- zebra_day/docs/hardware_config_guide.md +149 -0
- zebra_day/docs/programatic_guide.md +181 -0
- zebra_day/docs/qln420_zebra_manual.pdf +0 -0
- zebra_day/docs/uid_screed_light.md +38 -0
- zebra_day/docs/zd620-zd420-ug-en.pdf +0 -0
- zebra_day/docs/zebra_day_ui_guide.md +194 -0
- zebra_day/etc/printer_config.json +5 -11
- zebra_day/etc/printer_config.template.json +5 -11
- zebra_day/etc/tmp_printers120.json +10 -0
- zebra_day/etc/tmp_printers139.json +10 -0
- zebra_day/etc/tmp_printers145.json +10 -0
- zebra_day/etc/tmp_printers147.json +10 -0
- zebra_day/etc/tmp_printers207.json +10 -0
- zebra_day/etc/tmp_printers34.json +10 -0
- zebra_day/etc/tmp_printers389.json +10 -0
- zebra_day/etc/tmp_printers398.json +10 -0
- zebra_day/etc/tmp_printers437.json +10 -0
- zebra_day/etc/tmp_printers439.json +10 -0
- zebra_day/etc/tmp_printers440.json +10 -0
- zebra_day/etc/tmp_printers469.json +10 -0
- zebra_day/etc/tmp_printers485.json +10 -0
- zebra_day/etc/tmp_printers508.json +10 -0
- zebra_day/etc/tmp_printers531.json +10 -0
- zebra_day/etc/tmp_printers540.json +10 -0
- zebra_day/etc/tmp_printers542.json +10 -0
- zebra_day/etc/tmp_printers543.json +10 -0
- zebra_day/etc/tmp_printers552.json +10 -0
- zebra_day/etc/tmp_printers715.json +10 -0
- zebra_day/etc/tmp_printers835.json +10 -0
- zebra_day/etc/tmp_printers842.json +10 -0
- zebra_day/etc/tmp_printers931.json +10 -0
- zebra_day/etc/tmp_printers969.json +10 -0
- zebra_day/etc/tmp_printers972.json +10 -0
- zebra_day/exceptions.py +1 -1
- zebra_day/files/blank_preview.png +0 -0
- zebra_day/files/corners_20cmX30cm_preview.png +0 -0
- zebra_day/files/corners_smallTube_preview.png +0 -0
- zebra_day/files/generic_2inX1in_preview.png +0 -0
- zebra_day/files/test_png_12020.png +0 -0
- zebra_day/files/test_png_12352.png +0 -0
- zebra_day/files/test_png_15472.png +0 -0
- zebra_day/files/test_png_24493.png +0 -0
- zebra_day/files/test_png_2897.png +0 -0
- zebra_day/files/test_png_30069.png +0 -0
- zebra_day/files/test_png_31690.png +0 -0
- zebra_day/files/test_png_33804.png +0 -0
- zebra_day/files/test_png_34737.png +0 -0
- zebra_day/files/test_png_4161.png +0 -0
- zebra_day/files/test_png_44748.png +0 -0
- zebra_day/files/test_png_4635.png +0 -0
- zebra_day/files/test_png_47791.png +0 -0
- zebra_day/files/test_png_47799.png +0 -0
- zebra_day/files/test_png_55588.png +0 -0
- zebra_day/files/test_png_56349.png +0 -0
- zebra_day/files/test_png_58809.png +0 -0
- zebra_day/files/test_png_5936.png +0 -0
- zebra_day/files/test_png_64110.png +0 -0
- zebra_day/files/test_png_64891.png +0 -0
- zebra_day/files/test_png_67242.png +0 -0
- zebra_day/files/test_png_69002.png +0 -0
- zebra_day/files/test_png_70065.png +0 -0
- zebra_day/files/test_png_72366.png +0 -0
- zebra_day/files/test_png_77793.png +0 -0
- zebra_day/files/test_png_89893.png +0 -0
- zebra_day/files/test_png_9572.png +0 -0
- zebra_day/files/tube_20mmX30mmA_preview.png +0 -0
- zebra_day/imgs/.hold +0 -0
- zebra_day/imgs/bar_ltpurp.png +0 -0
- zebra_day/imgs/bar_purp.png +0 -0
- zebra_day/imgs/bar_purp3.png +0 -0
- zebra_day/imgs/bar_red.png +0 -0
- zebra_day/imgs/legacy/UBC_gantt_chart.png +0 -0
- zebra_day/imgs/legacy/gx420d_network_config.png +0 -0
- zebra_day/imgs/legacy/gx420d_printer_config.png +0 -0
- zebra_day/imgs/legacy/ngrok.png +0 -0
- zebra_day/imgs/legacy/printer_details.png +0 -0
- zebra_day/imgs/legacy/quick_start_test_label.png +0 -0
- zebra_day/imgs/legacy/quick_start_test_label2.png +0 -0
- zebra_day/imgs/legacy/zd620_network_config.png +0 -0
- zebra_day/imgs/legacy/zd620_printer_config.png +0 -0
- zebra_day/imgs/legacy/zday_quick_gui.png +0 -0
- zebra_day/imgs/legacy/zebra_day_alt_css_dog.png +0 -0
- zebra_day/imgs/legacy/zebra_day_alt_css_flower.png +0 -0
- zebra_day/imgs/legacy/zebra_day_alt_css_main.png +0 -0
- zebra_day/imgs/legacy/zebra_day_available_zpl_templates.png +0 -0
- zebra_day/imgs/legacy/zebra_day_bkup_pconfig.png +0 -0
- zebra_day/imgs/legacy/zebra_day_home.png +0 -0
- zebra_day/imgs/legacy/zebra_day_manual_print.png +0 -0
- zebra_day/imgs/legacy/zebra_day_printer_fleet_json.png +0 -0
- zebra_day/imgs/legacy/zebra_day_quick_ex.png +0 -0
- zebra_day/imgs/legacy/zebra_day_zpl_template_IRLa.png +0 -0
- zebra_day/imgs/legacy/zebra_day_zpl_template_IRLb.png +0 -0
- zebra_day/imgs/ui_api_docs.png +0 -0
- zebra_day/imgs/ui_config.png +0 -0
- zebra_day/imgs/ui_dashboard.png +0 -0
- zebra_day/imgs/ui_print_request.png +0 -0
- zebra_day/imgs/ui_printers.png +0 -0
- zebra_day/imgs/ui_templates.png +0 -0
- zebra_day/logging_config.py +4 -9
- zebra_day/mkcert.py +157 -0
- zebra_day/paths.py +1 -2
- zebra_day/print_mgr.py +261 -185
- zebra_day/templates/modern/config.html +7 -0
- zebra_day/templates/modern/config_backups.html +59 -0
- zebra_day/templates/modern/config_editor.html +95 -0
- zebra_day/templates/modern/config_new.html +93 -0
- zebra_day/templates/modern/print_request.html +70 -8
- zebra_day/templates/modern/printer_detail.html +161 -34
- zebra_day/templates/modern/printers.html +17 -6
- zebra_day/templates/modern/template_editor.html +7 -4
- zebra_day/web/__init__.py +1 -1
- zebra_day/web/app.py +99 -17
- zebra_day/web/auth.py +17 -15
- zebra_day/web/middleware.py +8 -5
- zebra_day/web/routers/__init__.py +0 -1
- zebra_day/web/routers/api.py +330 -31
- zebra_day/web/routers/ui.py +174 -591
- zebra_day/zpl_renderer.py +45 -34
- {zebra_day-1.0.2.dist-info → zebra_day-2.1.4.dist-info}/METADATA +144 -74
- zebra_day-2.1.4.dist-info/RECORD +240 -0
- zebra_day/bin/fetch_zebra_config.py +0 -15
- zebra_day/bin/generate_coord_grid_zpl.py +0 -50
- zebra_day/bin/print_zpl_from_file.py +0 -21
- zebra_day/bin/probe_new_label_dimensions.py +0 -75
- zebra_day/bin/scan_for_networed_zebra_printers.py +0 -23
- zebra_day/bin/scan_for_networed_zebra_printers_arp_scan.sh +0 -1
- zebra_day/bin/scan_for_networed_zebra_printers_curl.sh +0 -30
- zebra_day/bin/zserve.py +0 -1062
- zebra_day/templates/base.html +0 -36
- zebra_day/templates/bpr.html +0 -72
- zebra_day/templates/build_new_config.html +0 -36
- zebra_day/templates/build_print_request.html +0 -32
- zebra_day/templates/chg_ui_style.html +0 -19
- zebra_day/templates/edit_template.html +0 -128
- zebra_day/templates/edit_zpl.html +0 -37
- zebra_day/templates/index.html +0 -82
- zebra_day/templates/legacy/base.html +0 -37
- zebra_day/templates/legacy/bpr.html +0 -72
- zebra_day/templates/legacy/build_new_config.html +0 -36
- zebra_day/templates/legacy/build_print_request.html +0 -32
- zebra_day/templates/legacy/chg_ui_style.html +0 -19
- zebra_day/templates/legacy/edit_template.html +0 -128
- zebra_day/templates/legacy/edit_zpl.html +0 -37
- zebra_day/templates/legacy/index.html +0 -82
- zebra_day/templates/legacy/list_prior_configs.html +0 -24
- zebra_day/templates/legacy/print_result.html +0 -30
- zebra_day/templates/legacy/printer_details.html +0 -25
- zebra_day/templates/legacy/printer_status.html +0 -70
- zebra_day/templates/legacy/save_result.html +0 -17
- zebra_day/templates/legacy/send_print_request.html +0 -34
- zebra_day/templates/legacy/simple_print.html +0 -94
- zebra_day/templates/legacy/view_pstation_json.html +0 -29
- zebra_day/templates/list_prior_configs.html +0 -24
- zebra_day/templates/print_result.html +0 -30
- zebra_day/templates/printer_details.html +0 -25
- zebra_day/templates/printer_status.html +0 -70
- zebra_day/templates/save_result.html +0 -17
- zebra_day/templates/send_print_request.html +0 -34
- zebra_day/templates/simple_print.html +0 -94
- zebra_day/templates/view_pstation_json.html +0 -29
- zebra_day-1.0.2.dist-info/RECORD +0 -179
- {zebra_day-1.0.2.dist-info → zebra_day-2.1.4.dist-info}/WHEEL +0 -0
- {zebra_day-1.0.2.dist-info → zebra_day-2.1.4.dist-info}/entry_points.txt +0 -0
- {zebra_day-1.0.2.dist-info → zebra_day-2.1.4.dist-info}/licenses/LICENSE +0 -0
- {zebra_day-1.0.2.dist-info → zebra_day-2.1.4.dist-info}/top_level.txt +0 -0
zebra_day/web/routers/ui.py
CHANGED
|
@@ -2,26 +2,22 @@
|
|
|
2
2
|
UI router for zebra_day web interface.
|
|
3
3
|
|
|
4
4
|
Provides HTML endpoints for the web-based management interface.
|
|
5
|
-
|
|
6
|
-
- Modern UI: Root routes (/, /printers, /print, /templates, /config)
|
|
7
|
-
- Legacy UI: Routes under /legacy prefix
|
|
5
|
+
All routes use the modern UI design with responsive layouts.
|
|
8
6
|
"""
|
|
7
|
+
|
|
9
8
|
from __future__ import annotations
|
|
10
9
|
|
|
11
10
|
import json
|
|
12
|
-
import os
|
|
13
|
-
import subprocess
|
|
14
11
|
import tempfile
|
|
15
12
|
import time
|
|
16
13
|
from datetime import datetime
|
|
17
14
|
from pathlib import Path
|
|
18
|
-
from typing import Optional
|
|
19
15
|
|
|
20
|
-
from fastapi import APIRouter,
|
|
16
|
+
from fastapi import APIRouter, Form, HTTPException, Request
|
|
21
17
|
from fastapi.responses import HTMLResponse, RedirectResponse, Response
|
|
22
18
|
|
|
23
|
-
from zebra_day.logging_config import get_logger
|
|
24
19
|
import zebra_day.cmd_mgr as zdcm
|
|
20
|
+
from zebra_day.logging_config import get_logger
|
|
25
21
|
|
|
26
22
|
_log = get_logger(__name__)
|
|
27
23
|
|
|
@@ -29,7 +25,7 @@ router = APIRouter()
|
|
|
29
25
|
|
|
30
26
|
|
|
31
27
|
def get_template_context(request: Request, **kwargs) -> dict:
|
|
32
|
-
"""Build common template context for
|
|
28
|
+
"""Build common template context for templates."""
|
|
33
29
|
return {
|
|
34
30
|
"request": request,
|
|
35
31
|
"css_theme": f"static/{request.app.state.css_theme}",
|
|
@@ -73,7 +69,8 @@ def get_templates_list(pkg_path: Path) -> tuple[list, list]:
|
|
|
73
69
|
def get_stats(zp, pkg_path: Path) -> dict:
|
|
74
70
|
"""Calculate dashboard statistics."""
|
|
75
71
|
labs = zp.printers.get("labs", {})
|
|
76
|
-
|
|
72
|
+
# Count printers via nested 'printers' key (v2 schema)
|
|
73
|
+
total_printers = sum(len(lab_data.get("printers", {})) for lab_data in labs.values())
|
|
77
74
|
stable, draft = get_templates_list(pkg_path)
|
|
78
75
|
|
|
79
76
|
# Count backup files
|
|
@@ -93,6 +90,7 @@ def get_stats(zp, pkg_path: Path) -> dict:
|
|
|
93
90
|
# MODERN UI ROUTES (root level)
|
|
94
91
|
# =============================================================================
|
|
95
92
|
|
|
93
|
+
|
|
96
94
|
@router.get("/", response_class=HTMLResponse)
|
|
97
95
|
async def modern_dashboard(request: Request):
|
|
98
96
|
"""Modern dashboard - home page."""
|
|
@@ -141,16 +139,26 @@ async def modern_printers_by_lab(request: Request, lab: str):
|
|
|
141
139
|
if lab not in zp.printers.get("labs", {}):
|
|
142
140
|
raise HTTPException(status_code=404, detail=f"Lab '{lab}' not found")
|
|
143
141
|
|
|
142
|
+
lab_data = zp.printers["labs"][lab]
|
|
143
|
+
lab_printers = lab_data.get("printers", {})
|
|
144
|
+
|
|
144
145
|
printers = []
|
|
145
|
-
for name, info in
|
|
146
|
-
printers.append(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
146
|
+
for name, info in lab_printers.items():
|
|
147
|
+
printers.append(
|
|
148
|
+
{
|
|
149
|
+
"id": name,
|
|
150
|
+
"name": info.get("printer_name") or name, # Display name or fallback to ID
|
|
151
|
+
"printer_name": info.get("printer_name"),
|
|
152
|
+
"ip_address": info.get("ip_address", ""),
|
|
153
|
+
"lab_location": info.get("lab_location"),
|
|
154
|
+
"manufacturer": info.get("manufacturer", "zebra"),
|
|
155
|
+
"model": info.get("model", ""),
|
|
156
|
+
"serial": info.get("serial", ""),
|
|
157
|
+
"label_zpl_styles": info.get("label_zpl_styles", []),
|
|
158
|
+
"status": "online" if info.get("ip_address") else "unknown",
|
|
159
|
+
"notes": info.get("notes", ""),
|
|
160
|
+
}
|
|
161
|
+
)
|
|
154
162
|
|
|
155
163
|
ip_root = ".".join(request.app.state.local_ip.split(".")[:-1])
|
|
156
164
|
|
|
@@ -160,23 +168,29 @@ async def modern_printers_by_lab(request: Request, lab: str):
|
|
|
160
168
|
labs=list(zp.printers.get("labs", {}).keys()),
|
|
161
169
|
printers=printers,
|
|
162
170
|
lab=lab,
|
|
171
|
+
lab_name=lab_data.get("lab_name", lab),
|
|
172
|
+
available_locations=lab_data.get("available_locations", []),
|
|
163
173
|
ip_root=ip_root,
|
|
164
174
|
)
|
|
165
175
|
return templates.TemplateResponse("modern/printers.html", context)
|
|
166
176
|
|
|
167
177
|
|
|
168
|
-
@router.get("/printers/{lab}/{
|
|
169
|
-
async def modern_printer_detail(request: Request, lab: str,
|
|
178
|
+
@router.get("/printers/{lab}/{printer_id}", response_class=HTMLResponse)
|
|
179
|
+
async def modern_printer_detail(request: Request, lab: str, printer_id: str):
|
|
170
180
|
"""Modern printer detail page."""
|
|
171
181
|
zp = request.app.state.zp
|
|
172
182
|
templates = request.app.state.templates
|
|
173
183
|
|
|
174
184
|
if lab not in zp.printers.get("labs", {}):
|
|
175
185
|
raise HTTPException(status_code=404, detail=f"Lab '{lab}' not found")
|
|
176
|
-
if printer_name not in zp.printers["labs"][lab]:
|
|
177
|
-
raise HTTPException(status_code=404, detail=f"Printer '{printer_name}' not found")
|
|
178
186
|
|
|
179
|
-
|
|
187
|
+
lab_data = zp.printers["labs"][lab]
|
|
188
|
+
lab_printers = lab_data.get("printers", {})
|
|
189
|
+
|
|
190
|
+
if printer_id not in lab_printers:
|
|
191
|
+
raise HTTPException(status_code=404, detail=f"Printer '{printer_id}' not found")
|
|
192
|
+
|
|
193
|
+
printer_info = lab_printers[printer_id]
|
|
180
194
|
|
|
181
195
|
# Try to get printer configuration
|
|
182
196
|
printer_config = ""
|
|
@@ -190,8 +204,11 @@ async def modern_printer_detail(request: Request, lab: str, printer_name: str):
|
|
|
190
204
|
context = get_modern_context(
|
|
191
205
|
request,
|
|
192
206
|
active_page="printers",
|
|
193
|
-
|
|
207
|
+
printer_id=printer_id,
|
|
208
|
+
printer_name=printer_info.get("printer_name") or printer_id,
|
|
194
209
|
lab=lab,
|
|
210
|
+
lab_name=lab_data.get("lab_name", lab),
|
|
211
|
+
available_locations=lab_data.get("available_locations", []),
|
|
195
212
|
printer_info=printer_info,
|
|
196
213
|
printer_config=printer_config,
|
|
197
214
|
)
|
|
@@ -278,6 +295,53 @@ async def modern_template_edit(
|
|
|
278
295
|
return templates.TemplateResponse("modern/template_editor.html", context)
|
|
279
296
|
|
|
280
297
|
|
|
298
|
+
@router.get("/templates/preview")
|
|
299
|
+
async def modern_template_preview(
|
|
300
|
+
request: Request,
|
|
301
|
+
filename: str,
|
|
302
|
+
dtype: str = "",
|
|
303
|
+
):
|
|
304
|
+
"""Generate a PNG preview of a ZPL template.
|
|
305
|
+
|
|
306
|
+
Returns the PNG image directly or redirects to the generated file.
|
|
307
|
+
"""
|
|
308
|
+
zp = request.app.state.zp
|
|
309
|
+
pkg_path = request.app.state.pkg_path
|
|
310
|
+
|
|
311
|
+
# Find the template file
|
|
312
|
+
if dtype:
|
|
313
|
+
filepath = pkg_path / "etc" / "label_styles" / dtype / filename
|
|
314
|
+
else:
|
|
315
|
+
# Try with .zpl extension if not provided
|
|
316
|
+
if not filename.endswith(".zpl"):
|
|
317
|
+
filepath = pkg_path / "etc" / "label_styles" / f"{filename}.zpl"
|
|
318
|
+
else:
|
|
319
|
+
filepath = pkg_path / "etc" / "label_styles" / filename
|
|
320
|
+
|
|
321
|
+
if not filepath.exists():
|
|
322
|
+
raise HTTPException(status_code=404, detail=f"Template '{filename}' not found")
|
|
323
|
+
|
|
324
|
+
try:
|
|
325
|
+
# Read template content
|
|
326
|
+
zpl_content = filepath.read_text()
|
|
327
|
+
|
|
328
|
+
# Generate PNG preview
|
|
329
|
+
output_dir = pkg_path / "files"
|
|
330
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
331
|
+
|
|
332
|
+
# Use template name for output file
|
|
333
|
+
template_name = filepath.stem
|
|
334
|
+
output_path = output_dir / f"{template_name}_preview.png"
|
|
335
|
+
|
|
336
|
+
zp.generate_label_png(zpl_content, str(output_path), False)
|
|
337
|
+
|
|
338
|
+
# Return redirect to the generated file
|
|
339
|
+
return RedirectResponse(url=f"/files/{template_name}_preview.png", status_code=303)
|
|
340
|
+
|
|
341
|
+
except Exception as e:
|
|
342
|
+
raise HTTPException(status_code=500, detail=f"Preview generation failed: {e}") from None
|
|
343
|
+
|
|
344
|
+
|
|
281
345
|
@router.get("/config", response_class=HTMLResponse)
|
|
282
346
|
async def modern_config(request: Request):
|
|
283
347
|
"""Modern configuration page."""
|
|
@@ -297,438 +361,89 @@ async def modern_config(request: Request):
|
|
|
297
361
|
"backups": stats["backups"],
|
|
298
362
|
}
|
|
299
363
|
|
|
364
|
+
# Get the config file path that was loaded
|
|
365
|
+
config_file_path = getattr(zp, "printers_filename", "Unknown")
|
|
366
|
+
|
|
300
367
|
context = get_modern_context(
|
|
301
368
|
request,
|
|
302
369
|
active_page="config",
|
|
303
370
|
labs=labs,
|
|
304
371
|
ip_root=ip_root,
|
|
305
372
|
config_summary=config_summary,
|
|
373
|
+
config_file_path=config_file_path,
|
|
306
374
|
)
|
|
307
375
|
return templates.TemplateResponse("modern/config.html", context)
|
|
308
376
|
|
|
309
377
|
|
|
310
378
|
@router.get("/config/view", response_class=HTMLResponse)
|
|
311
379
|
async def modern_config_view(request: Request):
|
|
312
|
-
"""View printer configuration JSON
|
|
313
|
-
return RedirectResponse(url="/legacy/view_pstation_json", status_code=303)
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
@router.get("/config/edit", response_class=HTMLResponse)
|
|
317
|
-
async def modern_config_edit(request: Request):
|
|
318
|
-
"""Edit printer configuration JSON (redirects to legacy for now)."""
|
|
319
|
-
return RedirectResponse(url="/legacy/view_pstation_json", status_code=303)
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
@router.get("/config/backups", response_class=HTMLResponse)
|
|
323
|
-
async def modern_config_backups(request: Request):
|
|
324
|
-
"""List prior config files (redirects to legacy for now)."""
|
|
325
|
-
return RedirectResponse(url="/legacy/list_prior_printer_config_files", status_code=303)
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
@router.get("/config/new", response_class=HTMLResponse)
|
|
329
|
-
async def modern_config_new(request: Request):
|
|
330
|
-
"""Build new config (redirects to legacy for now)."""
|
|
331
|
-
return RedirectResponse(url="/legacy/build_new_printers_config_json", status_code=303)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
@router.get("/config/scan", response_class=HTMLResponse)
|
|
335
|
-
async def modern_config_scan(
|
|
336
|
-
request: Request,
|
|
337
|
-
ip_stub: str = "192.168.1",
|
|
338
|
-
scan_wait: str = "0.25",
|
|
339
|
-
lab: str = "scan-results",
|
|
340
|
-
):
|
|
341
|
-
"""Scan network for printers."""
|
|
342
|
-
zp = request.app.state.zp
|
|
343
|
-
zp.probe_zebra_printers_add_to_printers_json(
|
|
344
|
-
ip_stub=ip_stub, scan_wait=scan_wait, lab=lab
|
|
345
|
-
)
|
|
346
|
-
time.sleep(2.2)
|
|
347
|
-
return RedirectResponse(url=f"/printers/{lab}", status_code=303)
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
@router.get("/_print_label", response_class=HTMLResponse)
|
|
351
|
-
async def modern_print_label(
|
|
352
|
-
request: Request,
|
|
353
|
-
lab: Optional[str] = None,
|
|
354
|
-
printer: str = "",
|
|
355
|
-
printer_ip: str = "",
|
|
356
|
-
label_zpl_style: str = "",
|
|
357
|
-
uid_barcode: str = "",
|
|
358
|
-
alt_a: str = "",
|
|
359
|
-
alt_b: str = "",
|
|
360
|
-
alt_c: str = "",
|
|
361
|
-
alt_d: str = "",
|
|
362
|
-
alt_e: str = "",
|
|
363
|
-
alt_f: str = "",
|
|
364
|
-
labSelect: str = "",
|
|
365
|
-
):
|
|
366
|
-
"""Execute print request - modern UI."""
|
|
380
|
+
"""View printer configuration JSON."""
|
|
367
381
|
zp = request.app.state.zp
|
|
368
382
|
templates = request.app.state.templates
|
|
369
|
-
rate_limiter = request.app.state.print_rate_limiter
|
|
370
|
-
|
|
371
|
-
if lab is None:
|
|
372
|
-
lab = labSelect
|
|
373
|
-
|
|
374
|
-
client_ip = request.client.host if request.client else "unknown"
|
|
375
383
|
|
|
376
|
-
|
|
377
|
-
allowed, reason = await rate_limiter.acquire(client_ip)
|
|
378
|
-
if not allowed:
|
|
379
|
-
raise HTTPException(status_code=429, detail=reason)
|
|
380
|
-
|
|
381
|
-
try:
|
|
382
|
-
result = zp.print_zpl(
|
|
383
|
-
lab=lab,
|
|
384
|
-
printer_name=printer,
|
|
385
|
-
label_zpl_style=label_zpl_style,
|
|
386
|
-
uid_barcode=uid_barcode,
|
|
387
|
-
alt_a=alt_a,
|
|
388
|
-
alt_b=alt_b,
|
|
389
|
-
alt_c=alt_c,
|
|
390
|
-
alt_d=alt_d,
|
|
391
|
-
alt_e=alt_e,
|
|
392
|
-
alt_f=alt_f,
|
|
393
|
-
client_ip=client_ip,
|
|
394
|
-
)
|
|
395
|
-
finally:
|
|
396
|
-
rate_limiter.release()
|
|
397
|
-
|
|
398
|
-
# Build the full URL for reference
|
|
399
|
-
full_url = str(request.url)
|
|
400
|
-
|
|
401
|
-
png_url = None
|
|
402
|
-
if result and ".png" in str(result):
|
|
403
|
-
png_name = str(result).split("/")[-1]
|
|
404
|
-
png_url = f"/files/{png_name}"
|
|
405
|
-
|
|
406
|
-
context = get_modern_context(
|
|
407
|
-
request,
|
|
408
|
-
title="Print Result",
|
|
409
|
-
success=True,
|
|
410
|
-
full_url=full_url,
|
|
411
|
-
png_url=png_url,
|
|
412
|
-
)
|
|
413
|
-
return templates.TemplateResponse("modern/print_result.html", context)
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
@router.post("/save", response_class=HTMLResponse)
|
|
417
|
-
async def modern_save_template(
|
|
418
|
-
request: Request,
|
|
419
|
-
filename: str = Form(...),
|
|
420
|
-
content: str = Form(...),
|
|
421
|
-
ftag: str = Form("na"),
|
|
422
|
-
lab: str = Form(""),
|
|
423
|
-
printer: str = Form(""),
|
|
424
|
-
):
|
|
425
|
-
"""Save ZPL template as a new draft file - modern UI."""
|
|
426
|
-
templates = request.app.state.templates
|
|
427
|
-
pkg_path = request.app.state.pkg_path
|
|
428
|
-
|
|
429
|
-
rec_date = str(datetime.now()).replace(" ", "_")
|
|
430
|
-
new_filename = filename.replace(".zpl", f".{ftag}.{rec_date}.zpl")
|
|
431
|
-
|
|
432
|
-
tmps_dir = pkg_path / "etc" / "label_styles" / "tmps"
|
|
433
|
-
tmps_dir.mkdir(parents=True, exist_ok=True)
|
|
434
|
-
|
|
435
|
-
temp_filepath = tmps_dir / new_filename
|
|
436
|
-
temp_filepath.write_text(content)
|
|
437
|
-
|
|
438
|
-
context = get_modern_context(
|
|
439
|
-
request,
|
|
440
|
-
title="Template Saved",
|
|
441
|
-
new_filename=new_filename,
|
|
442
|
-
)
|
|
443
|
-
return templates.TemplateResponse("modern/save_result.html", context)
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
@router.post("/png_renderer")
|
|
447
|
-
async def modern_png_renderer(
|
|
448
|
-
request: Request,
|
|
449
|
-
filename: str = Form(...),
|
|
450
|
-
content: str = Form(...),
|
|
451
|
-
lab: str = Form(""),
|
|
452
|
-
printer: str = Form(""),
|
|
453
|
-
ftag: str = Form(""),
|
|
454
|
-
):
|
|
455
|
-
"""Render ZPL content to PNG - modern UI."""
|
|
456
|
-
zp = request.app.state.zp
|
|
457
|
-
pkg_path = request.app.state.pkg_path
|
|
458
|
-
|
|
459
|
-
files_dir = pkg_path / "files"
|
|
460
|
-
files_dir.mkdir(parents=True, exist_ok=True)
|
|
461
|
-
|
|
462
|
-
png_tmp_f = tempfile.NamedTemporaryFile(
|
|
463
|
-
suffix=".png", dir=str(files_dir), delete=False
|
|
464
|
-
).name
|
|
465
|
-
|
|
466
|
-
zp.generate_label_png(content, png_fn=png_tmp_f)
|
|
467
|
-
|
|
468
|
-
# Return just the relative path for the img src
|
|
469
|
-
return Response(
|
|
470
|
-
content=f"files/{Path(png_tmp_f).name}",
|
|
471
|
-
media_type="text/plain",
|
|
472
|
-
)
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
# =============================================================================
|
|
476
|
-
# LEGACY UI ROUTES (under /legacy prefix)
|
|
477
|
-
# =============================================================================
|
|
478
|
-
|
|
479
|
-
@router.get("/legacy", response_class=HTMLResponse)
|
|
480
|
-
async def legacy_index(request: Request):
|
|
481
|
-
"""Legacy home page."""
|
|
482
|
-
zp = request.app.state.zp
|
|
483
|
-
templates = request.app.state.templates
|
|
484
|
-
|
|
485
|
-
labs = list(zp.printers.get("labs", {}).keys())
|
|
486
|
-
|
|
487
|
-
context = get_template_context(
|
|
488
|
-
request,
|
|
489
|
-
title="Zebra Day - Home",
|
|
490
|
-
labs=labs,
|
|
491
|
-
)
|
|
492
|
-
return templates.TemplateResponse("legacy/index.html", context)
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
@router.get("/legacy/printer_status", response_class=HTMLResponse)
|
|
496
|
-
async def legacy_printer_status(request: Request, lab: str = "scan-results"):
|
|
497
|
-
"""Legacy printer status page for a lab."""
|
|
498
|
-
zp = request.app.state.zp
|
|
499
|
-
templates = request.app.state.templates
|
|
500
|
-
|
|
501
|
-
if lab not in zp.printers.get("labs", {}):
|
|
502
|
-
raise HTTPException(status_code=404, detail=f"Lab '{lab}' not found")
|
|
503
|
-
|
|
504
|
-
printers = []
|
|
505
|
-
for name, info in zp.printers["labs"][lab].items():
|
|
506
|
-
printer_data = {
|
|
507
|
-
"name": name,
|
|
508
|
-
"ip_address": info.get("ip_address", ""),
|
|
509
|
-
"model": info.get("model", ""),
|
|
510
|
-
"serial": info.get("serial", ""),
|
|
511
|
-
"label_zpl_styles": info.get("label_zpl_styles", []),
|
|
512
|
-
"arp_data": info.get("arp_data", ""),
|
|
513
|
-
"status": "unknown",
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
# Try to get printer status (curl check)
|
|
517
|
-
if info.get("ip_address") and info["ip_address"] != "dl_png":
|
|
518
|
-
try:
|
|
519
|
-
result = subprocess.run(
|
|
520
|
-
["curl", "-m", "4", info["ip_address"]],
|
|
521
|
-
capture_output=True,
|
|
522
|
-
text=True,
|
|
523
|
-
timeout=5,
|
|
524
|
-
)
|
|
525
|
-
for line in result.stdout.splitlines():
|
|
526
|
-
if "Status:" in line:
|
|
527
|
-
printer_data["status"] = line.strip()
|
|
528
|
-
break
|
|
529
|
-
except Exception:
|
|
530
|
-
printer_data["status"] = "Unable to connect"
|
|
531
|
-
|
|
532
|
-
printers.append(printer_data)
|
|
533
|
-
|
|
534
|
-
ip_root = ".".join(request.app.state.local_ip.split(".")[:-1])
|
|
384
|
+
config_json = json.dumps(zp.printers, indent=4)
|
|
535
385
|
|
|
536
386
|
context = get_template_context(
|
|
537
387
|
request,
|
|
538
|
-
title=
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
ip_root=ip_root,
|
|
542
|
-
labs=list(zp.printers.get("labs", {}).keys()),
|
|
388
|
+
title="View Configuration",
|
|
389
|
+
config_json=config_json,
|
|
390
|
+
mode="view",
|
|
543
391
|
)
|
|
544
|
-
return templates.TemplateResponse("
|
|
392
|
+
return templates.TemplateResponse("modern/config_editor.html", context)
|
|
545
393
|
|
|
546
394
|
|
|
547
|
-
@router.get("/
|
|
548
|
-
async def
|
|
549
|
-
"""
|
|
550
|
-
zp = request.app.state.zp
|
|
551
|
-
templates = request.app.state.templates
|
|
552
|
-
|
|
553
|
-
pkg_path = request.app.state.pkg_path
|
|
554
|
-
styles_dir = pkg_path / "etc" / "label_styles"
|
|
555
|
-
|
|
556
|
-
template_names = []
|
|
557
|
-
if styles_dir.exists():
|
|
558
|
-
for f in sorted(styles_dir.iterdir()):
|
|
559
|
-
if f.is_file() and f.suffix == ".zpl":
|
|
560
|
-
template_names.append(f.stem)
|
|
561
|
-
|
|
562
|
-
labs_and_printers = {
|
|
563
|
-
lab: list(printers.keys())
|
|
564
|
-
for lab, printers in zp.printers.get("labs", {}).items()
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
context = get_template_context(
|
|
568
|
-
request,
|
|
569
|
-
title="Print Label",
|
|
570
|
-
templates=template_names,
|
|
571
|
-
labs=list(zp.printers.get("labs", {}).keys()),
|
|
572
|
-
labs_and_printers=json.dumps(labs_and_printers),
|
|
573
|
-
)
|
|
574
|
-
return templates.TemplateResponse("legacy/simple_print.html", context)
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
@router.get("/legacy/edit_zpl", response_class=HTMLResponse)
|
|
578
|
-
async def legacy_edit_zpl(request: Request):
|
|
579
|
-
"""Legacy list ZPL templates for editing."""
|
|
580
|
-
templates = request.app.state.templates
|
|
581
|
-
pkg_path = request.app.state.pkg_path
|
|
582
|
-
styles_dir = pkg_path / "etc" / "label_styles"
|
|
583
|
-
|
|
584
|
-
stable_templates = []
|
|
585
|
-
draft_templates = []
|
|
586
|
-
|
|
587
|
-
if styles_dir.exists():
|
|
588
|
-
for f in sorted(styles_dir.iterdir()):
|
|
589
|
-
if f.is_file() and f.suffix == ".zpl":
|
|
590
|
-
stable_templates.append(f.name)
|
|
591
|
-
|
|
592
|
-
tmps_dir = styles_dir / "tmps"
|
|
593
|
-
if tmps_dir.exists():
|
|
594
|
-
for f in sorted(tmps_dir.iterdir()):
|
|
595
|
-
if f.is_file() and f.suffix == ".zpl":
|
|
596
|
-
draft_templates.append(f.name)
|
|
597
|
-
|
|
598
|
-
context = get_template_context(
|
|
599
|
-
request,
|
|
600
|
-
title="Edit ZPL Templates",
|
|
601
|
-
stable_templates=stable_templates,
|
|
602
|
-
draft_templates=draft_templates,
|
|
603
|
-
)
|
|
604
|
-
return templates.TemplateResponse("legacy/edit_zpl.html", context)
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
@router.get("/legacy/chg_ui_style", response_class=HTMLResponse)
|
|
608
|
-
async def legacy_chg_ui_style(request: Request, css_file: Optional[str] = None):
|
|
609
|
-
"""Legacy change UI style or show available styles."""
|
|
610
|
-
if css_file:
|
|
611
|
-
request.app.state.css_theme = css_file
|
|
612
|
-
return RedirectResponse(url="/legacy", status_code=303)
|
|
613
|
-
|
|
614
|
-
templates = request.app.state.templates
|
|
615
|
-
pkg_path = request.app.state.pkg_path
|
|
616
|
-
static_dir = pkg_path / "static"
|
|
617
|
-
|
|
618
|
-
css_files = []
|
|
619
|
-
if static_dir.exists():
|
|
620
|
-
for f in sorted(static_dir.iterdir()):
|
|
621
|
-
if f.suffix == ".css":
|
|
622
|
-
css_files.append(f.name)
|
|
623
|
-
|
|
624
|
-
context = get_template_context(request, title="Change UI Style", css_files=css_files)
|
|
625
|
-
return templates.TemplateResponse("legacy/chg_ui_style.html", context)
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
@router.get("/legacy/printer_details", response_class=HTMLResponse)
|
|
629
|
-
async def legacy_printer_details(request: Request, printer_name: str, lab: str):
|
|
630
|
-
"""Legacy show detailed printer information."""
|
|
631
|
-
zp = request.app.state.zp
|
|
632
|
-
templates = request.app.state.templates
|
|
633
|
-
|
|
634
|
-
if lab not in zp.printers.get("labs", {}):
|
|
635
|
-
raise HTTPException(status_code=404, detail=f"Lab '{lab}' not found")
|
|
636
|
-
if printer_name not in zp.printers["labs"][lab]:
|
|
637
|
-
raise HTTPException(status_code=404, detail=f"Printer '{printer_name}' not found")
|
|
638
|
-
|
|
639
|
-
printer_info = zp.printers["labs"][lab][printer_name]
|
|
640
|
-
|
|
641
|
-
# Try to get printer configuration
|
|
642
|
-
printer_config = ""
|
|
643
|
-
ip_addr = printer_info.get("ip_address", "")
|
|
644
|
-
if ip_addr and ip_addr != "dl_png":
|
|
645
|
-
try:
|
|
646
|
-
printer_config = zdcm.ZebraPrinter(ip_addr).get_configuration()
|
|
647
|
-
except Exception as e:
|
|
648
|
-
printer_config = f"Unable to retrieve config: {e}"
|
|
649
|
-
|
|
650
|
-
context = get_template_context(
|
|
651
|
-
request,
|
|
652
|
-
title=f"Printer Details - {printer_name}",
|
|
653
|
-
printer_name=printer_name,
|
|
654
|
-
lab=lab,
|
|
655
|
-
printer_info=printer_info,
|
|
656
|
-
printer_config=printer_config,
|
|
657
|
-
)
|
|
658
|
-
return templates.TemplateResponse("legacy/printer_details.html", context)
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
@router.get("/legacy/view_pstation_json", response_class=HTMLResponse)
|
|
662
|
-
async def legacy_view_pstation_json(request: Request, error_msg: Optional[str] = None):
|
|
663
|
-
"""Legacy view and edit printer configuration JSON."""
|
|
395
|
+
@router.get("/config/edit", response_class=HTMLResponse)
|
|
396
|
+
async def modern_config_edit(request: Request, error_msg: str | None = None):
|
|
397
|
+
"""Edit printer configuration JSON."""
|
|
664
398
|
zp = request.app.state.zp
|
|
665
399
|
templates = request.app.state.templates
|
|
666
400
|
|
|
667
|
-
|
|
401
|
+
config_json = json.dumps(zp.printers, indent=4)
|
|
668
402
|
|
|
669
403
|
context = get_template_context(
|
|
670
404
|
request,
|
|
671
|
-
title="
|
|
672
|
-
|
|
405
|
+
title="Edit Configuration",
|
|
406
|
+
config_json=config_json,
|
|
407
|
+
mode="edit",
|
|
673
408
|
error_msg=error_msg,
|
|
674
409
|
)
|
|
675
|
-
return templates.TemplateResponse("
|
|
410
|
+
return templates.TemplateResponse("modern/config_editor.html", context)
|
|
676
411
|
|
|
677
412
|
|
|
678
|
-
@router.post("/
|
|
679
|
-
async def
|
|
680
|
-
"""
|
|
413
|
+
@router.post("/config/save")
|
|
414
|
+
async def modern_config_save(request: Request, json_data: str = Form(...)):
|
|
415
|
+
"""Save edited printer configuration JSON."""
|
|
681
416
|
zp = request.app.state.zp
|
|
417
|
+
pkg_path = request.app.state.pkg_path
|
|
682
418
|
|
|
683
419
|
try:
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
return RedirectResponse(
|
|
687
|
-
url=f"/legacy/view_pstation_json?error_msg=Invalid+JSON:+{str(e)}",
|
|
688
|
-
status_code=303,
|
|
689
|
-
)
|
|
420
|
+
# Validate JSON
|
|
421
|
+
new_config = json.loads(json_data)
|
|
690
422
|
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
423
|
+
# Backup current config
|
|
424
|
+
json_file = pkg_path / "etc" / "printer_config.json"
|
|
425
|
+
if json_file.exists():
|
|
426
|
+
bkup_dir = pkg_path / "etc" / "old_printer_config"
|
|
427
|
+
bkup_dir.mkdir(parents=True, exist_ok=True)
|
|
428
|
+
rec_date = str(datetime.now()).replace(" ", "_")
|
|
429
|
+
bkup_file = bkup_dir / f"printer_config.{rec_date}.json"
|
|
430
|
+
bkup_file.write_text(json_file.read_text())
|
|
694
431
|
|
|
695
|
-
#
|
|
696
|
-
|
|
697
|
-
json.dump(data, f, indent=4)
|
|
432
|
+
# Save new config
|
|
433
|
+
json_file.write_text(json.dumps(new_config, indent=4))
|
|
698
434
|
|
|
699
435
|
# Reload config
|
|
700
436
|
zp.load_printer_json(json_file=zp.printers_filename, relative=False)
|
|
701
437
|
|
|
702
|
-
return RedirectResponse(url="/
|
|
703
|
-
|
|
704
|
-
except Exception as e:
|
|
705
|
-
return RedirectResponse(
|
|
706
|
-
url=f"/legacy/view_pstation_json?error_msg=Error+saving:+{str(e)}",
|
|
707
|
-
status_code=303,
|
|
708
|
-
)
|
|
709
|
-
|
|
438
|
+
return RedirectResponse(url="/config", status_code=303)
|
|
710
439
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
"""Legacy clear the printer configuration JSON."""
|
|
714
|
-
zp = request.app.state.zp
|
|
715
|
-
zp.clear_printers_json()
|
|
716
|
-
time.sleep(1.2)
|
|
717
|
-
return RedirectResponse(url="/legacy", status_code=303)
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
@router.get("/legacy/reset_pstation_json")
|
|
721
|
-
async def legacy_reset_pstation_json(request: Request):
|
|
722
|
-
"""Legacy reset printer config from template."""
|
|
723
|
-
zp = request.app.state.zp
|
|
724
|
-
zp.replace_printer_json_from_template()
|
|
725
|
-
time.sleep(1.2)
|
|
726
|
-
return RedirectResponse(url="/legacy", status_code=303)
|
|
440
|
+
except json.JSONDecodeError as e:
|
|
441
|
+
return RedirectResponse(url=f"/config/edit?error_msg=Invalid JSON: {e}", status_code=303)
|
|
727
442
|
|
|
728
443
|
|
|
729
|
-
@router.get("/
|
|
730
|
-
async def
|
|
731
|
-
"""
|
|
444
|
+
@router.get("/config/backups", response_class=HTMLResponse)
|
|
445
|
+
async def modern_config_backups(request: Request):
|
|
446
|
+
"""List prior config files."""
|
|
732
447
|
templates = request.app.state.templates
|
|
733
448
|
pkg_path = request.app.state.pkg_path
|
|
734
449
|
bkup_dir = pkg_path / "etc" / "old_printer_config"
|
|
@@ -741,15 +456,15 @@ async def legacy_list_prior_printer_config_files(request: Request):
|
|
|
741
456
|
|
|
742
457
|
context = get_template_context(
|
|
743
458
|
request,
|
|
744
|
-
title="
|
|
459
|
+
title="Configuration Backups",
|
|
745
460
|
backup_files=backup_files,
|
|
746
461
|
)
|
|
747
|
-
return templates.TemplateResponse("
|
|
462
|
+
return templates.TemplateResponse("modern/config_backups.html", context)
|
|
748
463
|
|
|
749
464
|
|
|
750
|
-
@router.get("/
|
|
751
|
-
async def
|
|
752
|
-
"""
|
|
465
|
+
@router.get("/config/new", response_class=HTMLResponse)
|
|
466
|
+
async def modern_config_new(request: Request):
|
|
467
|
+
"""Build new config page."""
|
|
753
468
|
zp = request.app.state.zp
|
|
754
469
|
templates = request.app.state.templates
|
|
755
470
|
|
|
@@ -757,109 +472,49 @@ async def legacy_build_new_printers_config_json(request: Request):
|
|
|
757
472
|
|
|
758
473
|
context = get_template_context(
|
|
759
474
|
request,
|
|
760
|
-
title="
|
|
475
|
+
title="New Configuration",
|
|
761
476
|
ip_root=ip_root,
|
|
762
477
|
labs=list(zp.printers.get("labs", {}).keys()),
|
|
763
478
|
)
|
|
764
|
-
return templates.TemplateResponse("
|
|
479
|
+
return templates.TemplateResponse("modern/config_new.html", context)
|
|
765
480
|
|
|
766
481
|
|
|
767
|
-
@router.get("/
|
|
768
|
-
async def
|
|
769
|
-
|
|
770
|
-
ip_stub: str = "192.168.1",
|
|
771
|
-
scan_wait: str = "0.25",
|
|
772
|
-
lab: str = "scan-results",
|
|
773
|
-
):
|
|
774
|
-
"""Legacy probe network for Zebra printers and add to config."""
|
|
775
|
-
zp = request.app.state.zp
|
|
776
|
-
zp.probe_zebra_printers_add_to_printers_json(
|
|
777
|
-
ip_stub=ip_stub, scan_wait=scan_wait, lab=lab
|
|
778
|
-
)
|
|
779
|
-
time.sleep(2.2)
|
|
780
|
-
return RedirectResponse(url=f"/legacy/printer_status?lab={lab}", status_code=303)
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
@router.get("/legacy/bpr", response_class=HTMLResponse)
|
|
784
|
-
async def legacy_bpr(request: Request):
|
|
785
|
-
"""Legacy build print request - select lab, printer, template."""
|
|
482
|
+
@router.get("/config/reset")
|
|
483
|
+
async def modern_config_reset(request: Request):
|
|
484
|
+
"""Reset printer config from template."""
|
|
786
485
|
zp = request.app.state.zp
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
styles_dir = pkg_path / "etc" / "label_styles"
|
|
791
|
-
|
|
792
|
-
stable_templates = []
|
|
793
|
-
draft_templates = []
|
|
794
|
-
|
|
795
|
-
if styles_dir.exists():
|
|
796
|
-
for f in sorted(styles_dir.iterdir()):
|
|
797
|
-
if f.is_file() and f.suffix == ".zpl":
|
|
798
|
-
stable_templates.append(f.stem)
|
|
799
|
-
|
|
800
|
-
tmps_dir = styles_dir / "tmps"
|
|
801
|
-
if tmps_dir.exists():
|
|
802
|
-
for f in sorted(tmps_dir.iterdir()):
|
|
803
|
-
if f.is_file() and f.suffix == ".zpl":
|
|
804
|
-
draft_templates.append(f.stem)
|
|
805
|
-
|
|
806
|
-
labs_dict = zp.printers.get("labs", {})
|
|
807
|
-
|
|
808
|
-
context = get_template_context(
|
|
809
|
-
request,
|
|
810
|
-
title="Build Print Request",
|
|
811
|
-
labs=list(labs_dict.keys()),
|
|
812
|
-
labs_dict=json.dumps(labs_dict),
|
|
813
|
-
stable_templates=stable_templates,
|
|
814
|
-
draft_templates=draft_templates,
|
|
815
|
-
)
|
|
816
|
-
return templates.TemplateResponse("legacy/bpr.html", context)
|
|
486
|
+
zp.replace_printer_json_from_template()
|
|
487
|
+
time.sleep(1.2)
|
|
488
|
+
return RedirectResponse(url="/config", status_code=303)
|
|
817
489
|
|
|
818
490
|
|
|
819
|
-
@router.get("/
|
|
820
|
-
async def
|
|
821
|
-
"""
|
|
491
|
+
@router.get("/config/clear")
|
|
492
|
+
async def modern_config_clear(request: Request):
|
|
493
|
+
"""Clear the printer configuration JSON."""
|
|
822
494
|
zp = request.app.state.zp
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
request,
|
|
827
|
-
title="Send Print Request",
|
|
828
|
-
labs=zp.printers.get("labs", {}),
|
|
829
|
-
)
|
|
830
|
-
return templates.TemplateResponse("legacy/send_print_request.html", context)
|
|
495
|
+
zp.clear_printers_json()
|
|
496
|
+
time.sleep(1.2)
|
|
497
|
+
return RedirectResponse(url="/config", status_code=303)
|
|
831
498
|
|
|
832
499
|
|
|
833
|
-
@router.get("/
|
|
834
|
-
async def
|
|
500
|
+
@router.get("/config/scan", response_class=HTMLResponse)
|
|
501
|
+
async def modern_config_scan(
|
|
835
502
|
request: Request,
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
label_zpl_style: str = "",
|
|
840
|
-
filename: str = "",
|
|
503
|
+
ip_stub: str = "192.168.1",
|
|
504
|
+
scan_wait: str = "0.25",
|
|
505
|
+
lab: str = "scan-results",
|
|
841
506
|
):
|
|
842
|
-
"""
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
context = get_template_context(
|
|
849
|
-
request,
|
|
850
|
-
title="Build Print Request",
|
|
851
|
-
lab=lab,
|
|
852
|
-
printer=printer,
|
|
853
|
-
printer_ip=printer_ip,
|
|
854
|
-
label_zpl_style=label_zpl_style,
|
|
855
|
-
)
|
|
856
|
-
return templates.TemplateResponse("legacy/build_print_request.html", context)
|
|
507
|
+
"""Scan network for printers."""
|
|
508
|
+
zp = request.app.state.zp
|
|
509
|
+
zp.probe_zebra_printers_add_to_printers_json(ip_stub=ip_stub, scan_wait=scan_wait, lab=lab)
|
|
510
|
+
time.sleep(2.2)
|
|
511
|
+
return RedirectResponse(url=f"/printers/{lab}", status_code=303)
|
|
857
512
|
|
|
858
513
|
|
|
859
|
-
@router.get("/
|
|
860
|
-
async def
|
|
514
|
+
@router.get("/_print_label", response_class=HTMLResponse)
|
|
515
|
+
async def modern_print_label(
|
|
861
516
|
request: Request,
|
|
862
|
-
lab:
|
|
517
|
+
lab: str | None = None,
|
|
863
518
|
printer: str = "",
|
|
864
519
|
printer_ip: str = "",
|
|
865
520
|
label_zpl_style: str = "",
|
|
@@ -872,7 +527,7 @@ async def legacy_print_label(
|
|
|
872
527
|
alt_f: str = "",
|
|
873
528
|
labSelect: str = "",
|
|
874
529
|
):
|
|
875
|
-
"""
|
|
530
|
+
"""Execute print request - modern UI."""
|
|
876
531
|
zp = request.app.state.zp
|
|
877
532
|
templates = request.app.state.templates
|
|
878
533
|
rate_limiter = request.app.state.print_rate_limiter
|
|
@@ -910,55 +565,20 @@ async def legacy_print_label(
|
|
|
910
565
|
png_url = None
|
|
911
566
|
if result and ".png" in str(result):
|
|
912
567
|
png_name = str(result).split("/")[-1]
|
|
913
|
-
png_url = f"/
|
|
568
|
+
png_url = f"/generated/{png_name}"
|
|
914
569
|
|
|
915
|
-
context =
|
|
570
|
+
context = get_modern_context(
|
|
916
571
|
request,
|
|
917
572
|
title="Print Result",
|
|
918
573
|
success=True,
|
|
919
574
|
full_url=full_url,
|
|
920
575
|
png_url=png_url,
|
|
921
576
|
)
|
|
922
|
-
return templates.TemplateResponse("
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
@router.get("/legacy/edit", response_class=HTMLResponse)
|
|
926
|
-
async def legacy_edit_template(
|
|
927
|
-
request: Request,
|
|
928
|
-
filename: str,
|
|
929
|
-
dtype: str = "",
|
|
930
|
-
):
|
|
931
|
-
"""Legacy edit a ZPL template file."""
|
|
932
|
-
zp = request.app.state.zp
|
|
933
|
-
templates = request.app.state.templates
|
|
934
|
-
pkg_path = request.app.state.pkg_path
|
|
935
|
-
|
|
936
|
-
if dtype:
|
|
937
|
-
filepath = pkg_path / "etc" / "label_styles" / dtype / filename
|
|
938
|
-
else:
|
|
939
|
-
filepath = pkg_path / "etc" / "label_styles" / filename
|
|
940
|
-
|
|
941
|
-
if not filepath.exists():
|
|
942
|
-
raise HTTPException(status_code=404, detail=f"Template '{filename}' not found")
|
|
943
|
-
|
|
944
|
-
content = filepath.read_text()
|
|
945
|
-
|
|
946
|
-
labs_dict = zp.printers.get("labs", {})
|
|
947
|
-
|
|
948
|
-
context = get_template_context(
|
|
949
|
-
request,
|
|
950
|
-
title=f"Edit: {filename}",
|
|
951
|
-
filename=filename,
|
|
952
|
-
content=content,
|
|
953
|
-
dtype=dtype,
|
|
954
|
-
labs=list(labs_dict.keys()),
|
|
955
|
-
labs_dict=json.dumps(labs_dict),
|
|
956
|
-
)
|
|
957
|
-
return templates.TemplateResponse("legacy/edit_template.html", context)
|
|
577
|
+
return templates.TemplateResponse("modern/print_result.html", context)
|
|
958
578
|
|
|
959
579
|
|
|
960
|
-
@router.post("/
|
|
961
|
-
async def
|
|
580
|
+
@router.post("/save", response_class=HTMLResponse)
|
|
581
|
+
async def modern_save_template(
|
|
962
582
|
request: Request,
|
|
963
583
|
filename: str = Form(...),
|
|
964
584
|
content: str = Form(...),
|
|
@@ -966,7 +586,7 @@ async def legacy_save_template(
|
|
|
966
586
|
lab: str = Form(""),
|
|
967
587
|
printer: str = Form(""),
|
|
968
588
|
):
|
|
969
|
-
"""
|
|
589
|
+
"""Save ZPL template as a new draft file - modern UI."""
|
|
970
590
|
templates = request.app.state.templates
|
|
971
591
|
pkg_path = request.app.state.pkg_path
|
|
972
592
|
|
|
@@ -979,16 +599,16 @@ async def legacy_save_template(
|
|
|
979
599
|
temp_filepath = tmps_dir / new_filename
|
|
980
600
|
temp_filepath.write_text(content)
|
|
981
601
|
|
|
982
|
-
context =
|
|
602
|
+
context = get_modern_context(
|
|
983
603
|
request,
|
|
984
604
|
title="Template Saved",
|
|
985
605
|
new_filename=new_filename,
|
|
986
606
|
)
|
|
987
|
-
return templates.TemplateResponse("
|
|
607
|
+
return templates.TemplateResponse("modern/save_result.html", context)
|
|
988
608
|
|
|
989
609
|
|
|
990
|
-
@router.post("/
|
|
991
|
-
async def
|
|
610
|
+
@router.post("/png_renderer")
|
|
611
|
+
async def modern_png_renderer(
|
|
992
612
|
request: Request,
|
|
993
613
|
filename: str = Form(...),
|
|
994
614
|
content: str = Form(...),
|
|
@@ -996,16 +616,14 @@ async def legacy_png_renderer(
|
|
|
996
616
|
printer: str = Form(""),
|
|
997
617
|
ftag: str = Form(""),
|
|
998
618
|
):
|
|
999
|
-
"""
|
|
619
|
+
"""Render ZPL content to PNG - modern UI."""
|
|
1000
620
|
zp = request.app.state.zp
|
|
1001
621
|
pkg_path = request.app.state.pkg_path
|
|
1002
622
|
|
|
1003
623
|
files_dir = pkg_path / "files"
|
|
1004
624
|
files_dir.mkdir(parents=True, exist_ok=True)
|
|
1005
625
|
|
|
1006
|
-
png_tmp_f = tempfile.NamedTemporaryFile(
|
|
1007
|
-
suffix=".png", dir=str(files_dir), delete=False
|
|
1008
|
-
).name
|
|
626
|
+
png_tmp_f = tempfile.NamedTemporaryFile(suffix=".png", dir=str(files_dir), delete=False).name
|
|
1009
627
|
|
|
1010
628
|
zp.generate_label_png(content, png_fn=png_tmp_f)
|
|
1011
629
|
|
|
@@ -1014,38 +632,3 @@ async def legacy_png_renderer(
|
|
|
1014
632
|
content=f"files/{Path(png_tmp_f).name}",
|
|
1015
633
|
media_type="text/plain",
|
|
1016
634
|
)
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
@router.post("/legacy/build_and_send_raw_print_request")
|
|
1020
|
-
async def legacy_build_and_send_raw_print_request(
|
|
1021
|
-
request: Request,
|
|
1022
|
-
lab: str = Form(...),
|
|
1023
|
-
printer: str = Form(...),
|
|
1024
|
-
content: str = Form(...),
|
|
1025
|
-
printer_ip: str = Form(""),
|
|
1026
|
-
label_zpl_style: str = Form(""),
|
|
1027
|
-
filename: str = Form(""),
|
|
1028
|
-
ftag: str = Form(""),
|
|
1029
|
-
):
|
|
1030
|
-
"""Legacy send raw ZPL content to printer."""
|
|
1031
|
-
zp = request.app.state.zp
|
|
1032
|
-
rate_limiter = request.app.state.print_rate_limiter
|
|
1033
|
-
client_ip = request.client.host if request.client else "unknown"
|
|
1034
|
-
|
|
1035
|
-
# Check rate limit
|
|
1036
|
-
allowed, reason = await rate_limiter.acquire(client_ip)
|
|
1037
|
-
if not allowed:
|
|
1038
|
-
raise HTTPException(status_code=429, detail=reason)
|
|
1039
|
-
|
|
1040
|
-
try:
|
|
1041
|
-
zp.print_zpl(
|
|
1042
|
-
lab=lab,
|
|
1043
|
-
printer_name=printer,
|
|
1044
|
-
label_zpl_style=None,
|
|
1045
|
-
zpl_content=content,
|
|
1046
|
-
client_ip=client_ip,
|
|
1047
|
-
)
|
|
1048
|
-
finally:
|
|
1049
|
-
rate_limiter.release()
|
|
1050
|
-
|
|
1051
|
-
return {"status": "sent"}
|