zebra-day 0.0.32__py3-none-any.whl → 1.0.2__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.
Files changed (190) hide show
  1. zebra_day/__init__.py +35 -0
  2. zebra_day/bin/fetch_zebra_config.py +15 -0
  3. zebra_day/bin/generate_coord_grid_zpl.py +50 -0
  4. zebra_day/bin/print_zpl_from_file.py +21 -0
  5. zebra_day/bin/probe_new_label_dimensions.py +75 -0
  6. zebra_day/bin/scan_for_networed_zebra_printers_curl.sh +2 -1
  7. zebra_day/bin/zserve.py +701 -259
  8. zebra_day/cli/__init__.py +240 -0
  9. zebra_day/cli/cognito.py +121 -0
  10. zebra_day/cli/gui.py +255 -0
  11. zebra_day/cli/printer.py +168 -0
  12. zebra_day/cli/template.py +176 -0
  13. zebra_day/cmd_mgr.py +35 -0
  14. zebra_day/etc/label_styles/blank.zpl +0 -0
  15. zebra_day/etc/label_styles/cornersStripOf4Squares_1inX1in.zpl +55 -0
  16. zebra_day/etc/label_styles/corners_1inX2in.zpl +28 -0
  17. zebra_day/etc/label_styles/corners_20cmX30cm.zpl +6 -0
  18. zebra_day/etc/label_styles/corners_smallTube.zpl +7 -0
  19. zebra_day/etc/label_styles/corners_unspecifiedDimensions.zpl +15 -0
  20. zebra_day/etc/label_styles/plate_1inX0.25inHD.zpl +9 -0
  21. zebra_day/etc/label_styles/smallTubeWdotHD_prod.zpl +8 -0
  22. zebra_day/etc/label_styles/smallTubeWdot_corners.zpl +7 -0
  23. zebra_day/etc/label_styles/smallTubeWdot_prod.zpl +8 -0
  24. zebra_day/etc/label_styles/smallTubeWdot_prodAlt1.zpl +6 -0
  25. zebra_day/etc/label_styles/smallTubeWdot_prodAlt1b.zpl +3 -0
  26. zebra_day/etc/label_styles/smallTubeWdot_prodV2.zpl +8 -0
  27. zebra_day/etc/label_styles/smallTubeWdot_reagent.zpl +29 -0
  28. zebra_day/etc/label_styles/stripOf4Squares_1inX1in.zpl +32 -0
  29. zebra_day/etc/label_styles/test_800dX800dCoordinateArray.zpl +1 -0
  30. zebra_day/etc/label_styles/tmps/tmp_zpl_templates.here +0 -0
  31. zebra_day/etc/label_styles/tube_20mmX30mmA.zpl +7 -0
  32. zebra_day/etc/label_styles/tube_2inX0.5in.zpl +15 -0
  33. zebra_day/etc/label_styles/tube_2inX0.5inHD.zpl +15 -0
  34. zebra_day/etc/label_styles/tube_2inX1inHD.zpl +22 -0
  35. zebra_day/etc/label_styles/tube_2inX1inHDv3.zpl +21 -0
  36. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.022846_printer_config.json +1 -0
  37. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.033657_printer_config.json +1 -0
  38. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.039597_printer_config.json +3 -0
  39. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.047295_printer_config.json +1 -0
  40. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.055804_printer_config.json +1 -0
  41. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.061337_printer_config.json +3 -0
  42. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.073326_printer_config.json +1 -0
  43. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.081950_printer_config.json +1 -0
  44. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.088251_printer_config.json +3 -0
  45. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.096501_printer_config.json +1 -0
  46. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.104767_printer_config.json +1 -0
  47. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.110364_printer_config.json +3 -0
  48. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.118239_printer_config.json +1 -0
  49. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.125950_printer_config.json +1 -0
  50. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.349866_printer_config.json +1 -0
  51. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.361085_printer_config.json +3 -0
  52. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.558323_printer_config.json +1 -0
  53. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.565756_printer_config.json +3 -0
  54. zebra_day/etc/old_printer_config/{2023-10-25_02:19:04.139607_printer_config.json → 2026-02-01_01:51:29.739070_printer_config.json} +4 -3
  55. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.753796_printer_config.json +1 -0
  56. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.760201_printer_config.json +3 -0
  57. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.768747_printer_config.json +1 -0
  58. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.775312_printer_config.json +3 -0
  59. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.782533_printer_config.json +1 -0
  60. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.789287_printer_config.json +1 -0
  61. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.794230_printer_config.json +3 -0
  62. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.800021_printer_config.json +5 -0
  63. zebra_day/etc/printer_config.json +3 -54
  64. zebra_day/etc/printer_config.template.json +3 -2
  65. zebra_day/etc/tmp_printers0.json +5 -0
  66. zebra_day/etc/tmp_printers374.json +5 -0
  67. zebra_day/etc/tmp_printers383.json +5 -0
  68. zebra_day/etc/tmp_printers450.json +5 -0
  69. zebra_day/etc/tmp_printers504.json +5 -0
  70. zebra_day/etc/tmp_printers608.json +5 -0
  71. zebra_day/etc/tmp_printers657.json +5 -0
  72. zebra_day/etc/tmp_printers838.json +5 -0
  73. zebra_day/etc/tmp_printers839.json +5 -0
  74. zebra_day/etc/tmp_printers933.json +5 -0
  75. zebra_day/etc/tmp_printers957.json +5 -0
  76. zebra_day/exceptions.py +88 -0
  77. zebra_day/files/hold +0 -0
  78. zebra_day/files/test_png_17696.png +0 -0
  79. zebra_day/files/test_png_23477.png +0 -0
  80. zebra_day/files/test_png_28157.png +0 -0
  81. zebra_day/files/test_png_35832.png +0 -0
  82. zebra_day/files/test_png_36400.png +0 -0
  83. zebra_day/files/test_png_40816.png +0 -0
  84. zebra_day/files/test_png_49564.png +0 -0
  85. zebra_day/files/test_png_53848.png +0 -0
  86. zebra_day/files/test_png_62542.png +0 -0
  87. zebra_day/files/test_png_91597.png +0 -0
  88. zebra_day/files/test_png_93633.png +0 -0
  89. zebra_day/files/tmpbjo3k7q1.png +0 -0
  90. zebra_day/files/tmpigtr4pwy.png +0 -0
  91. zebra_day/files/zpl_label_tube_2inX1in_2026-02-01_01:51:24.370964.png +0 -0
  92. zebra_day/logging_config.py +74 -0
  93. zebra_day/logs/.hold +0 -0
  94. zebra_day/logs/print_requests.log +2 -0
  95. zebra_day/paths.py +143 -0
  96. zebra_day/print_mgr.py +489 -103
  97. zebra_day/static/datschund.css +63 -43
  98. zebra_day/static/datschund.png +0 -0
  99. zebra_day/static/daylily.png +0 -0
  100. zebra_day/static/favicon.svg +20 -0
  101. zebra_day/static/general.css +99 -0
  102. zebra_day/static/js/zebra_modern.js +172 -0
  103. zebra_day/static/lsmc.css +354 -0
  104. zebra_day/static/moon.jpeg +0 -0
  105. zebra_day/static/oakland.css +0 -32
  106. zebra_day/static/popday_daylily.css +1 -1
  107. zebra_day/static/style.css +39 -0
  108. zebra_day/static/zebra_modern.css +771 -0
  109. zebra_day/templates/base.html +36 -0
  110. zebra_day/templates/bpr.html +72 -0
  111. zebra_day/templates/build_new_config.html +36 -0
  112. zebra_day/templates/build_print_request.html +32 -0
  113. zebra_day/templates/chg_ui_style.html +19 -0
  114. zebra_day/templates/edit_template.html +128 -0
  115. zebra_day/templates/edit_zpl.html +37 -0
  116. zebra_day/templates/index.html +82 -0
  117. zebra_day/templates/legacy/base.html +37 -0
  118. zebra_day/templates/legacy/bpr.html +72 -0
  119. zebra_day/templates/legacy/build_new_config.html +36 -0
  120. zebra_day/templates/legacy/build_print_request.html +32 -0
  121. zebra_day/templates/legacy/chg_ui_style.html +19 -0
  122. zebra_day/templates/legacy/edit_template.html +128 -0
  123. zebra_day/templates/legacy/edit_zpl.html +37 -0
  124. zebra_day/templates/legacy/index.html +82 -0
  125. zebra_day/templates/legacy/list_prior_configs.html +24 -0
  126. zebra_day/templates/legacy/print_result.html +30 -0
  127. zebra_day/templates/legacy/printer_details.html +25 -0
  128. zebra_day/templates/legacy/printer_status.html +70 -0
  129. zebra_day/templates/legacy/save_result.html +17 -0
  130. zebra_day/templates/legacy/send_print_request.html +34 -0
  131. zebra_day/templates/legacy/simple_print.html +94 -0
  132. zebra_day/templates/legacy/view_pstation_json.html +29 -0
  133. zebra_day/templates/list_prior_configs.html +24 -0
  134. zebra_day/templates/modern/base.html +98 -0
  135. zebra_day/templates/modern/config.html +141 -0
  136. zebra_day/templates/modern/dashboard.html +160 -0
  137. zebra_day/templates/modern/print_request.html +141 -0
  138. zebra_day/templates/modern/print_result.html +88 -0
  139. zebra_day/templates/modern/printer_detail.html +117 -0
  140. zebra_day/templates/modern/printers.html +133 -0
  141. zebra_day/templates/modern/save_result.html +46 -0
  142. zebra_day/templates/modern/template_editor.html +172 -0
  143. zebra_day/templates/modern/templates.html +122 -0
  144. zebra_day/templates/print_result.html +30 -0
  145. zebra_day/templates/printer_details.html +25 -0
  146. zebra_day/templates/printer_status.html +70 -0
  147. zebra_day/templates/save_result.html +17 -0
  148. zebra_day/templates/send_print_request.html +34 -0
  149. zebra_day/templates/simple_print.html +94 -0
  150. zebra_day/templates/view_pstation_json.html +29 -0
  151. zebra_day/web/__init__.py +9 -0
  152. zebra_day/web/app.py +171 -0
  153. zebra_day/web/auth.py +172 -0
  154. zebra_day/web/middleware.py +159 -0
  155. zebra_day/web/routers/__init__.py +2 -0
  156. zebra_day/web/routers/api.py +163 -0
  157. zebra_day/web/routers/ui.py +1051 -0
  158. zebra_day/zpl_renderer.py +273 -0
  159. zebra_day-1.0.2.dist-info/METADATA +786 -0
  160. zebra_day-1.0.2.dist-info/RECORD +179 -0
  161. {zebra_day-0.0.32.dist-info → zebra_day-1.0.2.dist-info}/WHEEL +1 -1
  162. zebra_day-1.0.2.dist-info/entry_points.txt +4 -0
  163. zebra_day/etc/.blind +0 -1
  164. zebra_day/etc/current_style.txt +0 -1
  165. zebra_day/etc/label_styles/test_2inX1in.zpl +0 -22
  166. zebra_day/etc/label_styles/tmps/labware_2inX1in.na.2023-10-24_12:49:21.045127.zpl +0 -21
  167. zebra_day/etc/label_styles/tmps/labware_2inX1in.naggg.2023-10-24_16:02:04.704814.8888.2023-10-24_16:02:16.443911.zpl +0 -21
  168. zebra_day/etc/label_styles/tmps/labware_2inX1in.naggg.2023-10-24_16:02:04.704814.zpl +0 -21
  169. zebra_day/etc/label_styles/tmps/test_2inX1in.na.2023-10-24_12:45:37.002774.zpl +0 -22
  170. zebra_day/etc/old_printer_config/2023-10-24_16:06:06.931764_printer_config.json +0 -67
  171. zebra_day/etc/printer_config.json~ +0 -67
  172. zebra_day/files/tmp_2olihg4.png +0 -0
  173. zebra_day/files/tmpveojoyvn.png +0 -0
  174. zebra_day/files/zpl_label_labware_2inX1in_2023-10-25_02:30:08.093631.png +0 -0
  175. zebra_day/files/zpl_label_test_2inX1in_2023-10-24_15:54:29.343124.png +0 -0
  176. zebra_day/files/zpl_label_test_2inX1in_2023-10-24_16:01:45.670132.png +0 -0
  177. zebra_day/static/beyonce.css +0 -227
  178. zebra_day/static/datschund_on_moon.css +0 -164
  179. zebra_day/static/medicalsci.css +0 -144
  180. zebra_day/static/moar_zebra.css +0 -133
  181. zebra_day/static/popday.css +0 -140
  182. zebra_day/static/popday_dark.css +0 -140
  183. zebra_day/static/popday_dog.css +0 -140
  184. zebra_day-0.0.32.dist-info/METADATA +0 -14
  185. zebra_day-0.0.32.dist-info/RECORD +0 -53
  186. zebra_day-0.0.32.dist-info/entry_points.txt +0 -2
  187. /zebra_day/{etc/label_styles/blank_0inX0in.zpl → bin/__init__.py} +0 -0
  188. /zebra_day/etc/label_styles/{labware_2inX1in.zpl → generic_2inX1in.zpl} +0 -0
  189. {zebra_day-0.0.32.dist-info → zebra_day-1.0.2.dist-info/licenses}/LICENSE +0 -0
  190. {zebra_day-0.0.32.dist-info → zebra_day-1.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,98 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{% block title %}Zebra Day{% endblock %}</title>
7
+ <link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
11
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
12
+ <link rel="stylesheet" href="/static/zebra_modern.css?v={{ cache_bust | default('1') }}">
13
+ {% block extra_head %}{% endblock %}
14
+ </head>
15
+ <body>
16
+ <!-- Zebra stripe accent bar -->
17
+ <div class="zebra-stripe-bar"></div>
18
+
19
+ <!-- Header -->
20
+ <header class="header">
21
+ <div class="container">
22
+ <div class="header-content">
23
+ <a href="/" class="logo">
24
+ <svg class="logo-icon" viewBox="0 0 32 32" width="32" height="32">
25
+ <rect width="32" height="32" rx="6" fill="#1a1a2e"/>
26
+ <path d="M6 8h20v3H6zM6 14h20v3H6zM6 20h20v3H6z" fill="#fff"/>
27
+ <text x="16" y="22" font-family="Inter,sans-serif" font-size="14" font-weight="700" fill="#6366f1" text-anchor="middle">Z</text>
28
+ </svg>
29
+ <span>Zebra Day</span>
30
+ </a>
31
+ <button class="menu-toggle" id="menu-toggle" aria-label="Toggle menu">
32
+ <i class="fas fa-bars"></i>
33
+ </button>
34
+ <nav class="nav">
35
+ <ul class="nav-links" id="nav-links">
36
+ <li><a href="/" class="nav-link {% if active_page == 'dashboard' %}active{% endif %}"><i class="fas fa-home"></i> Dashboard</a></li>
37
+ <li><a href="/printers" class="nav-link {% if active_page == 'printers' %}active{% endif %}"><i class="fas fa-print"></i> Printers</a></li>
38
+ <li><a href="/templates" class="nav-link {% if active_page == 'templates' %}active{% endif %}"><i class="fas fa-file-code"></i> Templates</a></li>
39
+ <li><a href="/print" class="nav-link {% if active_page == 'print' %}active{% endif %}"><i class="fas fa-tag"></i> Print Label</a></li>
40
+ <li><a href="/config" class="nav-link {% if active_page == 'config' %}active{% endif %}"><i class="fas fa-cog"></i> Config</a></li>
41
+ </ul>
42
+ </nav>
43
+ <div class="nav-actions">
44
+ <a href="/legacy" class="btn btn-outline btn-sm" title="Switch to legacy interface">
45
+ <i class="fas fa-history"></i> Legacy UI
46
+ </a>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ </header>
51
+
52
+ <!-- Toast notifications container -->
53
+ <div class="toast-container" id="toast-container"></div>
54
+
55
+ <!-- Loading overlay -->
56
+ <div class="loading-overlay d-none" id="loading-overlay">
57
+ <div class="loading-spinner">
58
+ <div class="spinner"></div>
59
+ <p>Loading...</p>
60
+ </div>
61
+ </div>
62
+
63
+ <!-- Main content -->
64
+ <main class="main">
65
+ <div class="container">
66
+ {% block content %}{% endblock %}
67
+ </div>
68
+ </main>
69
+
70
+ <!-- Footer -->
71
+ <footer class="footer">
72
+ <div class="container">
73
+ <div class="footer-content">
74
+ <div class="footer-info">
75
+ <span>Zebra Day v{{ version | default('0.7.0') }}</span>
76
+ <span class="footer-sep">•</span>
77
+ <span>IP: {{ local_ip | default('unknown') }}</span>
78
+ </div>
79
+ <div class="footer-links">
80
+ <a href="/docs" target="_blank"><i class="fas fa-book"></i> API Docs</a>
81
+ <a href="https://github.com/Daylily-Informatics/zebra_day" target="_blank"><i class="fab fa-github"></i> GitHub</a>
82
+ </div>
83
+ </div>
84
+ </div>
85
+ </footer>
86
+
87
+ <!-- Global config -->
88
+ <script>
89
+ window.ZebraConfig = {
90
+ apiBase: '{{ api_base | default("") }}',
91
+ localIp: '{{ local_ip | default("") }}'
92
+ };
93
+ </script>
94
+ <script src="/static/js/zebra_modern.js?v={{ cache_bust | default('1') }}"></script>
95
+ {% block extra_scripts %}{% endblock %}
96
+ </body>
97
+ </html>
98
+
@@ -0,0 +1,141 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}Configuration - Zebra Day{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="page-header">
7
+ <h1 class="page-title">Configuration</h1>
8
+ <p class="page-subtitle">Manage printer configuration and settings</p>
9
+ </div>
10
+
11
+ <div class="grid grid-2">
12
+ <!-- Printer Configuration -->
13
+ <div class="card">
14
+ <div class="card-header">
15
+ <h3 class="card-title"><i class="fas fa-cog"></i> Printer Configuration</h3>
16
+ </div>
17
+ <div class="quick-actions">
18
+ <a href="/config/view" class="action-card">
19
+ <i class="fas fa-eye"></i>
20
+ <div>
21
+ <strong>View Config</strong>
22
+ <small class="text-muted d-block">View printers.json</small>
23
+ </div>
24
+ </a>
25
+ <a href="/config/edit" class="action-card">
26
+ <i class="fas fa-edit"></i>
27
+ <div>
28
+ <strong>Edit Config</strong>
29
+ <small class="text-muted d-block">Modify printers.json</small>
30
+ </div>
31
+ </a>
32
+ <a href="/config/backups" class="action-card">
33
+ <i class="fas fa-history"></i>
34
+ <div>
35
+ <strong>Backups</strong>
36
+ <small class="text-muted d-block">Prior config files</small>
37
+ </div>
38
+ </a>
39
+ <a href="/config/new" class="action-card">
40
+ <i class="fas fa-plus"></i>
41
+ <div>
42
+ <strong>New Config</strong>
43
+ <small class="text-muted d-block">Build from scratch</small>
44
+ </div>
45
+ </a>
46
+ </div>
47
+ </div>
48
+
49
+ <!-- Network Scan -->
50
+ <div class="card">
51
+ <div class="card-header">
52
+ <h3 class="card-title"><i class="fas fa-wifi"></i> Network Scanner</h3>
53
+ </div>
54
+ <form action="/config/scan" method="get">
55
+ <div class="form-group">
56
+ <label class="form-label">IP Range</label>
57
+ <input type="text" name="ip_stub" class="form-control" value="{{ ip_root | default('192.168.1') }}" placeholder="192.168.1">
58
+ <small class="text-muted">Enter the first three octets of your network</small>
59
+ </div>
60
+ <div class="form-group">
61
+ <label class="form-label">Lab Name</label>
62
+ <input type="text" name="lab" class="form-control" list="lab-names" placeholder="Enter lab name">
63
+ <datalist id="lab-names">
64
+ {% for lab in labs %}
65
+ <option value="{{ lab }}">
66
+ {% endfor %}
67
+ </datalist>
68
+ </div>
69
+ <button type="submit" class="btn btn-primary" onclick="showLoading('Scanning network...')">
70
+ <i class="fas fa-search"></i> Scan for Printers
71
+ </button>
72
+ </form>
73
+ </div>
74
+ </div>
75
+
76
+ <!-- Current Config Summary -->
77
+ <div class="card mt-lg">
78
+ <div class="card-header">
79
+ <h3 class="card-title">Current Configuration</h3>
80
+ <a href="/config/view" class="btn btn-outline btn-sm">
81
+ <i class="fas fa-external-link-alt"></i> View Full
82
+ </a>
83
+ </div>
84
+ {% if config_summary %}
85
+ <div class="grid grid-4 mb-lg">
86
+ <div class="stat-card">
87
+ <div class="card-icon primary"><i class="fas fa-building"></i></div>
88
+ <div>
89
+ <div class="stat-value">{{ config_summary.labs }}</div>
90
+ <div class="stat-label">Labs</div>
91
+ </div>
92
+ </div>
93
+ <div class="stat-card">
94
+ <div class="card-icon success"><i class="fas fa-print"></i></div>
95
+ <div>
96
+ <div class="stat-value">{{ config_summary.printers }}</div>
97
+ <div class="stat-label">Printers</div>
98
+ </div>
99
+ </div>
100
+ <div class="stat-card">
101
+ <div class="card-icon info"><i class="fas fa-file-code"></i></div>
102
+ <div>
103
+ <div class="stat-value">{{ config_summary.templates }}</div>
104
+ <div class="stat-label">Templates</div>
105
+ </div>
106
+ </div>
107
+ <div class="stat-card">
108
+ <div class="card-icon warning"><i class="fas fa-clock"></i></div>
109
+ <div>
110
+ <div class="stat-value">{{ config_summary.backups }}</div>
111
+ <div class="stat-label">Backups</div>
112
+ </div>
113
+ </div>
114
+ </div>
115
+ {% endif %}
116
+
117
+ <!-- Labs List -->
118
+ {% if labs %}
119
+ <h4 class="mb-md">Configured Labs</h4>
120
+ <div class="grid grid-5">
121
+ {% for lab in labs %}
122
+ <a href="/printers/{{ lab }}" class="action-card">
123
+ <i class="fas fa-building"></i>
124
+ <div>
125
+ <strong>{{ lab }}</strong>
126
+ </div>
127
+ </a>
128
+ {% endfor %}
129
+ </div>
130
+ {% else %}
131
+ <div class="empty-state">
132
+ <i class="fas fa-cog"></i>
133
+ <p>No labs configured</p>
134
+ <a href="/config/scan" class="btn btn-primary">
135
+ <i class="fas fa-wifi"></i> Scan Network
136
+ </a>
137
+ </div>
138
+ {% endif %}
139
+ </div>
140
+ {% endblock %}
141
+
@@ -0,0 +1,160 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}Dashboard - Zebra Day{% endblock %}
4
+
5
+ {% block content %}
6
+ <!-- Page Header -->
7
+ <div class="page-header">
8
+ <h1 class="page-title">Zebra Day Dashboard</h1>
9
+ <p class="page-subtitle">Zebra printer and label template management</p>
10
+ </div>
11
+
12
+ <!-- Stats Grid -->
13
+ <div class="grid grid-4 mb-xl">
14
+ <a href="/printers" class="stat-card stat-card-clickable">
15
+ <div class="card-icon primary">
16
+ <i class="fas fa-print"></i>
17
+ </div>
18
+ <div>
19
+ <div class="stat-value">{{ stats.total_printers | default(0) }}</div>
20
+ <div class="stat-label">Total Printers</div>
21
+ </div>
22
+ </a>
23
+
24
+ <a href="/printers" class="stat-card stat-card-clickable">
25
+ <div class="card-icon success">
26
+ <i class="fas fa-check-circle"></i>
27
+ </div>
28
+ <div>
29
+ <div class="stat-value">{{ stats.online_printers | default(0) }}</div>
30
+ <div class="stat-label">Online</div>
31
+ </div>
32
+ </a>
33
+
34
+ <a href="/printers" class="stat-card stat-card-clickable">
35
+ <div class="card-icon info">
36
+ <i class="fas fa-building"></i>
37
+ </div>
38
+ <div>
39
+ <div class="stat-value">{{ stats.total_labs | default(0) }}</div>
40
+ <div class="stat-label">Labs</div>
41
+ </div>
42
+ </a>
43
+
44
+ <a href="/templates" class="stat-card stat-card-clickable">
45
+ <div class="card-icon warning">
46
+ <i class="fas fa-file-code"></i>
47
+ </div>
48
+ <div>
49
+ <div class="stat-value">{{ stats.total_templates | default(0) }}</div>
50
+ <div class="stat-label">Templates</div>
51
+ </div>
52
+ </a>
53
+ </div>
54
+
55
+ <!-- Main Content Grid -->
56
+ <div class="grid grid-2">
57
+ <!-- Quick Actions -->
58
+ <div class="card">
59
+ <div class="card-header">
60
+ <h3 class="card-title">Quick Actions</h3>
61
+ </div>
62
+ <div class="quick-actions">
63
+ <a href="/print" class="action-card">
64
+ <i class="fas fa-tag"></i>
65
+ <div>
66
+ <strong>Print Label</strong>
67
+ <small class="text-muted d-block">Send a print request</small>
68
+ </div>
69
+ </a>
70
+ <a href="/config?action=scan" class="action-card">
71
+ <i class="fas fa-wifi"></i>
72
+ <div>
73
+ <strong>Scan Network</strong>
74
+ <small class="text-muted d-block">Discover printers</small>
75
+ </div>
76
+ </a>
77
+ <a href="/templates" class="action-card">
78
+ <i class="fas fa-edit"></i>
79
+ <div>
80
+ <strong>Edit Templates</strong>
81
+ <small class="text-muted d-block">Manage ZPL files</small>
82
+ </div>
83
+ </a>
84
+ <a href="/config" class="action-card">
85
+ <i class="fas fa-cog"></i>
86
+ <div>
87
+ <strong>Configuration</strong>
88
+ <small class="text-muted d-block">View/edit settings</small>
89
+ </div>
90
+ </a>
91
+ </div>
92
+ </div>
93
+
94
+ <!-- Labs Overview -->
95
+ <div class="card">
96
+ <div class="card-header">
97
+ <h3 class="card-title">Labs</h3>
98
+ <a href="/printers" class="btn btn-outline btn-sm">View All</a>
99
+ </div>
100
+ {% if labs %}
101
+ <div class="table-container" style="box-shadow: none;">
102
+ <table class="table">
103
+ <thead>
104
+ <tr>
105
+ <th>Lab Name</th>
106
+ <th>Printers</th>
107
+ <th>Actions</th>
108
+ </tr>
109
+ </thead>
110
+ <tbody>
111
+ {% for lab_name, printers in labs.items() %}
112
+ <tr>
113
+ <td><strong>{{ lab_name }}</strong></td>
114
+ <td>{{ printers | length }} printer(s)</td>
115
+ <td>
116
+ <a href="/printers/{{ lab_name }}" class="btn btn-sm btn-outline">
117
+ <i class="fas fa-eye"></i> View
118
+ </a>
119
+ </td>
120
+ </tr>
121
+ {% endfor %}
122
+ </tbody>
123
+ </table>
124
+ </div>
125
+ {% else %}
126
+ <div class="empty-state">
127
+ <i class="fas fa-building"></i>
128
+ <p>No labs configured yet</p>
129
+ <a href="/config?action=scan" class="btn btn-primary">
130
+ <i class="fas fa-wifi"></i> Scan Network
131
+ </a>
132
+ </div>
133
+ {% endif %}
134
+ </div>
135
+ </div>
136
+
137
+ <!-- API Documentation -->
138
+ <div class="card mt-lg">
139
+ <div class="card-header">
140
+ <h3 class="card-title">API Documentation</h3>
141
+ </div>
142
+ <div class="grid grid-2">
143
+ <a href="/docs" target="_blank" class="action-card">
144
+ <i class="fas fa-book-open"></i>
145
+ <div>
146
+ <strong>Swagger UI</strong>
147
+ <small class="text-muted d-block">Interactive API documentation</small>
148
+ </div>
149
+ </a>
150
+ <a href="/redoc" target="_blank" class="action-card">
151
+ <i class="fas fa-file-alt"></i>
152
+ <div>
153
+ <strong>ReDoc</strong>
154
+ <small class="text-muted d-block">Read-only API reference</small>
155
+ </div>
156
+ </a>
157
+ </div>
158
+ </div>
159
+ {% endblock %}
160
+
@@ -0,0 +1,141 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}Print Label - Zebra Day{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="page-header">
7
+ <h1 class="page-title">Print Label</h1>
8
+ <p class="page-subtitle">Send a label print request to a Zebra printer</p>
9
+ </div>
10
+
11
+ <form id="print-form" action="/_print_label" method="get">
12
+ <div class="grid grid-2">
13
+ <!-- Printer Selection -->
14
+ <div class="card">
15
+ <div class="card-header">
16
+ <h3 class="card-title">1. Select Printer</h3>
17
+ </div>
18
+ <div class="form-group">
19
+ <label class="form-label required">Lab</label>
20
+ <select id="lab-select" name="lab" class="form-control" onchange="updatePrinters()" required>
21
+ <option value="">Select a lab...</option>
22
+ {% for lab in labs %}
23
+ <option value="{{ lab }}" {% if selected_lab == lab %}selected{% endif %}>{{ lab }}</option>
24
+ {% endfor %}
25
+ </select>
26
+ </div>
27
+ <div class="form-group">
28
+ <label class="form-label required">Printer</label>
29
+ <select id="printer-select" name="printer" class="form-control" required>
30
+ <option value="">Select a printer...</option>
31
+ </select>
32
+ </div>
33
+ <div class="form-group mb-0">
34
+ <label class="form-label required">Label Template</label>
35
+ <select name="label_zpl_style" class="form-control" required>
36
+ <option value="">Select a template...</option>
37
+ {% if stable_templates %}
38
+ <optgroup label="Stable Templates">
39
+ {% for template in stable_templates %}
40
+ <option value="{{ template }}" {% if selected_template == template %}selected{% endif %}>{{ template }}</option>
41
+ {% endfor %}
42
+ </optgroup>
43
+ {% endif %}
44
+ {% if draft_templates %}
45
+ <optgroup label="Draft Templates">
46
+ {% for template in draft_templates %}
47
+ <option value="{{ template }}" {% if selected_template == template %}selected{% endif %}>{{ template }}</option>
48
+ {% endfor %}
49
+ </optgroup>
50
+ {% endif %}
51
+ </select>
52
+ </div>
53
+ </div>
54
+
55
+ <!-- Label Data -->
56
+ <div class="card">
57
+ <div class="card-header">
58
+ <h3 class="card-title">2. Label Data</h3>
59
+ </div>
60
+ <div class="form-group">
61
+ <label class="form-label">UID Barcode</label>
62
+ <input type="text" name="uid_barcode" class="form-control" placeholder="Enter barcode value">
63
+ </div>
64
+ <div class="grid grid-2" style="gap: var(--spacing-md);">
65
+ <div class="form-group">
66
+ <label class="form-label">Alt A</label>
67
+ <input type="text" name="alt_a" class="form-control" placeholder="Field A">
68
+ </div>
69
+ <div class="form-group">
70
+ <label class="form-label">Alt B</label>
71
+ <input type="text" name="alt_b" class="form-control" placeholder="Field B">
72
+ </div>
73
+ <div class="form-group">
74
+ <label class="form-label">Alt C</label>
75
+ <input type="text" name="alt_c" class="form-control" placeholder="Field C">
76
+ </div>
77
+ <div class="form-group">
78
+ <label class="form-label">Alt D</label>
79
+ <input type="text" name="alt_d" class="form-control" placeholder="Field D">
80
+ </div>
81
+ <div class="form-group">
82
+ <label class="form-label">Alt E</label>
83
+ <input type="text" name="alt_e" class="form-control" placeholder="Field E">
84
+ </div>
85
+ <div class="form-group mb-0">
86
+ <label class="form-label">Alt F</label>
87
+ <input type="text" name="alt_f" class="form-control" placeholder="Field F">
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </div>
92
+
93
+ <!-- Submit -->
94
+ <div class="card mt-lg">
95
+ <div class="d-flex" style="justify-content: space-between; align-items: center;">
96
+ <a href="/" class="btn btn-outline">
97
+ <i class="fas fa-arrow-left"></i> Cancel
98
+ </a>
99
+ <button type="submit" class="btn btn-primary btn-lg" onclick="showLoading('Sending print request...')">
100
+ <i class="fas fa-print"></i> Print Label
101
+ </button>
102
+ </div>
103
+ </div>
104
+ </form>
105
+ {% endblock %}
106
+
107
+ {% block extra_scripts %}
108
+ <script>
109
+ var labsDict = {{ labs_dict | safe }};
110
+ var selectedPrinter = '{{ selected_printer | default("") }}';
111
+
112
+ function updatePrinters() {
113
+ var labSelect = document.getElementById('lab-select');
114
+ var printerSelect = document.getElementById('printer-select');
115
+ var lab = labSelect.value;
116
+
117
+ printerSelect.innerHTML = '<option value="">Select a printer...</option>';
118
+
119
+ if (lab && labsDict[lab]) {
120
+ for (var printer in labsDict[lab]) {
121
+ var option = document.createElement('option');
122
+ option.value = printer;
123
+ option.text = printer;
124
+ if (printer === selectedPrinter) {
125
+ option.selected = true;
126
+ }
127
+ printerSelect.appendChild(option);
128
+ }
129
+ }
130
+ }
131
+
132
+ // Initialize printers if lab is pre-selected
133
+ document.addEventListener('DOMContentLoaded', function() {
134
+ var labSelect = document.getElementById('lab-select');
135
+ if (labSelect.value) {
136
+ updatePrinters();
137
+ }
138
+ });
139
+ </script>
140
+ {% endblock %}
141
+
@@ -0,0 +1,88 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}Print Result - Zebra Day{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="page-header">
7
+ <h1 class="page-title">Print Result</h1>
8
+ <p class="page-subtitle">Label print request completed</p>
9
+ </div>
10
+
11
+ <div class="grid grid-2">
12
+ <!-- Result Card -->
13
+ <div class="card">
14
+ <div class="card-header">
15
+ <h3 class="card-title">
16
+ {% if success %}
17
+ <i class="fas fa-check-circle text-success"></i> Success
18
+ {% else %}
19
+ <i class="fas fa-times-circle text-error"></i> Failed
20
+ {% endif %}
21
+ </h3>
22
+ </div>
23
+
24
+ {% if success %}
25
+ <p class="mb-lg">Your label has been sent to the printer successfully.</p>
26
+ {% else %}
27
+ <p class="mb-lg text-error">{{ error_message | default('An error occurred while printing.') }}</p>
28
+ {% endif %}
29
+
30
+ {% if full_url %}
31
+ <div class="form-group">
32
+ <label class="form-label">Request URL</label>
33
+ <div class="d-flex gap-sm">
34
+ <input type="text" class="form-control" value="{{ full_url }}" readonly id="request-url">
35
+ <button type="button" class="btn btn-outline btn-sm" onclick="copyToClipboard(document.getElementById('request-url').value)">
36
+ <i class="fas fa-copy"></i>
37
+ </button>
38
+ </div>
39
+ <small class="text-muted">Save this URL to quickly repeat this print request</small>
40
+ </div>
41
+ {% endif %}
42
+
43
+ <div class="quick-actions mt-lg">
44
+ <a href="/print" class="action-card">
45
+ <i class="fas fa-print"></i>
46
+ <div>
47
+ <strong>Print Another</strong>
48
+ <small class="text-muted d-block">New print request</small>
49
+ </div>
50
+ </a>
51
+ <a href="/" class="action-card">
52
+ <i class="fas fa-home"></i>
53
+ <div>
54
+ <strong>Dashboard</strong>
55
+ <small class="text-muted d-block">Go back home</small>
56
+ </div>
57
+ </a>
58
+ </div>
59
+ </div>
60
+
61
+ <!-- Preview Card -->
62
+ {% if png_url %}
63
+ <div class="card">
64
+ <div class="card-header">
65
+ <h3 class="card-title">Label Preview</h3>
66
+ <a href="{{ png_url }}" target="_blank" class="btn btn-outline btn-sm">
67
+ <i class="fas fa-external-link-alt"></i> Open Full Size
68
+ </a>
69
+ </div>
70
+ <div style="text-align: center; background: var(--color-white); padding: var(--spacing-lg); border-radius: var(--radius-md);">
71
+ <img src="{{ png_url }}" alt="Label preview" style="max-width: 100%; height: auto;">
72
+ </div>
73
+ </div>
74
+ {% else %}
75
+ <div class="card">
76
+ <div class="card-header">
77
+ <h3 class="card-title">Label Preview</h3>
78
+ </div>
79
+ <div class="empty-state">
80
+ <i class="fas fa-image"></i>
81
+ <p>Preview sent directly to printer</p>
82
+ <small class="text-muted">PNG preview is only available when using the dl_png virtual printer</small>
83
+ </div>
84
+ </div>
85
+ {% endif %}
86
+ </div>
87
+ {% endblock %}
88
+