zebra-day 0.0.37__py3-none-any.whl → 2.0.0__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 (173) hide show
  1. zebra_day/__init__.py +35 -0
  2. zebra_day/bin/__init__.py +0 -0
  3. zebra_day/cli/__init__.py +240 -0
  4. zebra_day/cli/cognito.py +121 -0
  5. zebra_day/cli/gui.py +338 -0
  6. zebra_day/cli/printer.py +168 -0
  7. zebra_day/cli/template.py +176 -0
  8. zebra_day/cmd_mgr.py +35 -0
  9. zebra_day/etc/Monoid-Regular-HalfTight-Dollar-0-1-l.ttf +0 -0
  10. zebra_day/etc/label_styles/blank.zpl +0 -0
  11. zebra_day/etc/label_styles/cornersStripOf4Squares_1inX1in.zpl +55 -0
  12. zebra_day/etc/label_styles/corners_1inX2in.zpl +28 -0
  13. zebra_day/etc/label_styles/corners_20cmX30cm.zpl +6 -0
  14. zebra_day/etc/label_styles/corners_smallTube.zpl +7 -0
  15. zebra_day/etc/label_styles/corners_unspecifiedDimensions.zpl +15 -0
  16. zebra_day/etc/label_styles/generic_2inX1in.zpl +21 -0
  17. zebra_day/etc/label_styles/plate_1inX0.25in.zpl +9 -0
  18. zebra_day/etc/label_styles/plate_1inX0.25inHD.zpl +9 -0
  19. zebra_day/etc/label_styles/smallTubeWdotHD_prod.zpl +8 -0
  20. zebra_day/etc/label_styles/smallTubeWdot_corners.zpl +7 -0
  21. zebra_day/etc/label_styles/smallTubeWdot_prod.zpl +8 -0
  22. zebra_day/etc/label_styles/smallTubeWdot_prodAlt1.zpl +6 -0
  23. zebra_day/etc/label_styles/smallTubeWdot_prodAlt1b.zpl +3 -0
  24. zebra_day/etc/label_styles/smallTubeWdot_prodV2.zpl +8 -0
  25. zebra_day/etc/label_styles/smallTubeWdot_reagent.zpl +29 -0
  26. zebra_day/etc/label_styles/stripOf4Squares_1inX1in.zpl +32 -0
  27. zebra_day/etc/label_styles/test_800dX800dCoordinateArray.zpl +1 -0
  28. zebra_day/etc/label_styles/tmps/.hold +0 -0
  29. zebra_day/etc/label_styles/tmps/tmp_zpl_templates.here +0 -0
  30. zebra_day/etc/label_styles/tube_20mmX30mmA.zpl +7 -0
  31. zebra_day/etc/label_styles/tube_2inX0.3in.zpl +15 -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_2inX1in.zpl +25 -0
  35. zebra_day/etc/label_styles/tube_2inX1inHD.zpl +22 -0
  36. zebra_day/etc/label_styles/tube_2inX1inHDv3.zpl +21 -0
  37. zebra_day/etc/old_printer_config/.hold +0 -0
  38. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.022846_printer_config.json +1 -0
  39. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.033657_printer_config.json +1 -0
  40. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.039597_printer_config.json +3 -0
  41. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.047295_printer_config.json +1 -0
  42. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.055804_printer_config.json +1 -0
  43. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.061337_printer_config.json +3 -0
  44. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.073326_printer_config.json +1 -0
  45. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.081950_printer_config.json +1 -0
  46. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.088251_printer_config.json +3 -0
  47. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.096501_printer_config.json +1 -0
  48. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.104767_printer_config.json +1 -0
  49. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.110364_printer_config.json +3 -0
  50. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.118239_printer_config.json +1 -0
  51. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.125950_printer_config.json +1 -0
  52. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.349866_printer_config.json +1 -0
  53. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.361085_printer_config.json +3 -0
  54. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.558323_printer_config.json +1 -0
  55. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.565756_printer_config.json +3 -0
  56. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.739070_printer_config.json +16 -0
  57. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.753796_printer_config.json +1 -0
  58. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.760201_printer_config.json +3 -0
  59. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.768747_printer_config.json +1 -0
  60. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.775312_printer_config.json +3 -0
  61. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.782533_printer_config.json +1 -0
  62. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.789287_printer_config.json +1 -0
  63. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.794230_printer_config.json +3 -0
  64. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.800021_printer_config.json +5 -0
  65. zebra_day/etc/printer_config.json +4 -0
  66. zebra_day/etc/printer_config.template.json +24 -0
  67. zebra_day/etc/tmp_printers0.json +5 -0
  68. zebra_day/etc/tmp_printers120.json +10 -0
  69. zebra_day/etc/tmp_printers145.json +10 -0
  70. zebra_day/etc/tmp_printers207.json +10 -0
  71. zebra_day/etc/tmp_printers374.json +5 -0
  72. zebra_day/etc/tmp_printers383.json +5 -0
  73. zebra_day/etc/tmp_printers450.json +5 -0
  74. zebra_day/etc/tmp_printers469.json +10 -0
  75. zebra_day/etc/tmp_printers485.json +10 -0
  76. zebra_day/etc/tmp_printers504.json +5 -0
  77. zebra_day/etc/tmp_printers531.json +10 -0
  78. zebra_day/etc/tmp_printers540.json +10 -0
  79. zebra_day/etc/tmp_printers542.json +10 -0
  80. zebra_day/etc/tmp_printers552.json +10 -0
  81. zebra_day/etc/tmp_printers608.json +5 -0
  82. zebra_day/etc/tmp_printers657.json +5 -0
  83. zebra_day/etc/tmp_printers715.json +10 -0
  84. zebra_day/etc/tmp_printers838.json +5 -0
  85. zebra_day/etc/tmp_printers839.json +5 -0
  86. zebra_day/etc/tmp_printers933.json +5 -0
  87. zebra_day/etc/tmp_printers957.json +5 -0
  88. zebra_day/etc/tmp_printers972.json +10 -0
  89. zebra_day/exceptions.py +88 -0
  90. zebra_day/files/.hold +0 -0
  91. zebra_day/files/blank_preview.png +0 -0
  92. zebra_day/files/corners_20cmX30cm_preview.png +0 -0
  93. zebra_day/files/generic_2inX1in_preview.png +0 -0
  94. zebra_day/files/hold +0 -0
  95. zebra_day/files/test_png_12020.png +0 -0
  96. zebra_day/files/test_png_12352.png +0 -0
  97. zebra_day/files/test_png_15472.png +0 -0
  98. zebra_day/files/test_png_17696.png +0 -0
  99. zebra_day/files/test_png_23477.png +0 -0
  100. zebra_day/files/test_png_24493.png +0 -0
  101. zebra_day/files/test_png_28157.png +0 -0
  102. zebra_day/files/test_png_30069.png +0 -0
  103. zebra_day/files/test_png_35832.png +0 -0
  104. zebra_day/files/test_png_36400.png +0 -0
  105. zebra_day/files/test_png_40816.png +0 -0
  106. zebra_day/files/test_png_47791.png +0 -0
  107. zebra_day/files/test_png_47799.png +0 -0
  108. zebra_day/files/test_png_49564.png +0 -0
  109. zebra_day/files/test_png_53848.png +0 -0
  110. zebra_day/files/test_png_55588.png +0 -0
  111. zebra_day/files/test_png_58809.png +0 -0
  112. zebra_day/files/test_png_62542.png +0 -0
  113. zebra_day/files/test_png_67242.png +0 -0
  114. zebra_day/files/test_png_89893.png +0 -0
  115. zebra_day/files/test_png_91597.png +0 -0
  116. zebra_day/files/test_png_93633.png +0 -0
  117. zebra_day/files/tmpbjo3k7q1.png +0 -0
  118. zebra_day/files/tmpigtr4pwy.png +0 -0
  119. zebra_day/files/tube_20mmX30mmA_preview.png +0 -0
  120. zebra_day/files/zpl_label_tube_2inX1in_2026-02-01_01:51:24.370964.png +0 -0
  121. zebra_day/logging_config.py +74 -0
  122. zebra_day/logs/.hold +0 -0
  123. zebra_day/logs/print_requests.log +2 -0
  124. zebra_day/paths.py +143 -0
  125. zebra_day/print_mgr.py +557 -117
  126. zebra_day/static/datschund.css +140 -0
  127. zebra_day/static/datschund.png +0 -0
  128. zebra_day/static/daylily.png +0 -0
  129. zebra_day/static/favicon.svg +20 -0
  130. zebra_day/static/general.css +99 -0
  131. zebra_day/static/js/zebra_modern.js +172 -0
  132. zebra_day/static/lsmc.css +354 -0
  133. zebra_day/static/moon.jpeg +0 -0
  134. zebra_day/static/oakland.css +197 -0
  135. zebra_day/static/petrichor.css +150 -0
  136. zebra_day/static/popday_daylily.css +140 -0
  137. zebra_day/static/style.css +183 -0
  138. zebra_day/static/triangles.css +122 -0
  139. zebra_day/static/tron.css +277 -0
  140. zebra_day/static/zebra_modern.css +771 -0
  141. zebra_day/static/zebras.css +176 -0
  142. zebra_day/templates/modern/base.html +98 -0
  143. zebra_day/templates/modern/config.html +141 -0
  144. zebra_day/templates/modern/config_backups.html +59 -0
  145. zebra_day/templates/modern/config_editor.html +95 -0
  146. zebra_day/templates/modern/config_new.html +93 -0
  147. zebra_day/templates/modern/dashboard.html +160 -0
  148. zebra_day/templates/modern/print_request.html +145 -0
  149. zebra_day/templates/modern/print_result.html +88 -0
  150. zebra_day/templates/modern/printer_detail.html +244 -0
  151. zebra_day/templates/modern/printers.html +144 -0
  152. zebra_day/templates/modern/save_result.html +46 -0
  153. zebra_day/templates/modern/template_editor.html +175 -0
  154. zebra_day/templates/modern/templates.html +122 -0
  155. zebra_day/web/__init__.py +9 -0
  156. zebra_day/web/app.py +248 -0
  157. zebra_day/web/auth.py +172 -0
  158. zebra_day/web/middleware.py +159 -0
  159. zebra_day/web/routers/__init__.py +2 -0
  160. zebra_day/web/routers/api.py +313 -0
  161. zebra_day/web/routers/ui.py +636 -0
  162. zebra_day/zpl_renderer.py +273 -0
  163. zebra_day-2.0.0.dist-info/METADATA +847 -0
  164. zebra_day-2.0.0.dist-info/RECORD +168 -0
  165. {zebra_day-0.0.37.dist-info → zebra_day-2.0.0.dist-info}/WHEEL +1 -1
  166. zebra_day-2.0.0.dist-info/entry_points.txt +4 -0
  167. zebra_day/bin/scan_for_networed_zebra_printers.py +0 -23
  168. zebra_day/bin/te.py +0 -905
  169. zebra_day/bin/zserve.py +0 -620
  170. zebra_day-0.0.37.dist-info/METADATA +0 -1177
  171. zebra_day-0.0.37.dist-info/RECORD +0 -10
  172. {zebra_day-0.0.37.dist-info → zebra_day-2.0.0.dist-info/licenses}/LICENSE +0 -0
  173. {zebra_day-0.0.37.dist-info → zebra_day-2.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,144 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}Printers - Zebra Day{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="page-header">
7
+ <h1 class="page-title">{% if lab %}{{ lab }} Printers{% else %}All Printers{% endif %}</h1>
8
+ <p class="page-subtitle">View and manage Zebra printers</p>
9
+ </div>
10
+
11
+ <!-- Labs Navigation -->
12
+ {% if not lab and labs %}
13
+ <div class="card mb-lg">
14
+ <div class="card-header">
15
+ <h3 class="card-title">Select a Lab</h3>
16
+ </div>
17
+ <div class="grid grid-4">
18
+ {% for lab_name in labs %}
19
+ <a href="/printers/{{ lab_name }}" class="action-card">
20
+ <i class="fas fa-building"></i>
21
+ <div>
22
+ <strong>{{ lab_name }}</strong>
23
+ <small class="text-muted d-block">View printers</small>
24
+ </div>
25
+ </a>
26
+ {% endfor %}
27
+ </div>
28
+ </div>
29
+ {% endif %}
30
+
31
+ <!-- Printers Table -->
32
+ {% if printers %}
33
+ <div class="card">
34
+ <div class="card-header">
35
+ <h3 class="card-title">Printers{% if lab %} in {{ lab_name | default(lab) }}{% endif %}</h3>
36
+ <a href="/config?action=scan&lab={{ lab | default('') }}" class="btn btn-outline btn-sm">
37
+ <i class="fas fa-sync"></i> Rescan
38
+ </a>
39
+ </div>
40
+ <div class="table-container" style="box-shadow: none;">
41
+ <table class="table">
42
+ <thead>
43
+ <tr>
44
+ <th>Printer</th>
45
+ <th>Location</th>
46
+ <th>IP Address</th>
47
+ <th>Status</th>
48
+ <th>Label Styles</th>
49
+ <th>Actions</th>
50
+ </tr>
51
+ </thead>
52
+ <tbody>
53
+ {% for printer in printers %}
54
+ <tr>
55
+ <td>
56
+ <strong>{{ printer.name }}</strong><br>
57
+ <small class="text-muted">{{ printer.manufacturer | default('zebra') | title }} {{ printer.model | default('Unknown model') }}</small>
58
+ {% if printer.id != printer.name %}
59
+ <br><small class="text-muted">ID: {{ printer.id }}</small>
60
+ {% endif %}
61
+ </td>
62
+ <td>
63
+ {% if printer.lab_location %}
64
+ <span class="badge badge-info">{{ printer.lab_location }}</span>
65
+ {% else %}
66
+ <span class="text-muted">—</span>
67
+ {% endif %}
68
+ </td>
69
+ <td>
70
+ {% if printer.ip_address != 'dl_png' %}
71
+ <a href="http://{{ printer.ip_address }}" target="_blank">{{ printer.ip_address }}</a>
72
+ {% else %}
73
+ <span class="text-muted">{{ printer.ip_address }}</span>
74
+ {% endif %}
75
+ </td>
76
+ <td>
77
+ {% if printer.status == 'online' %}
78
+ <span class="badge badge-success"><i class="fas fa-check-circle"></i> Online</span>
79
+ {% else %}
80
+ <span class="badge badge-error"><i class="fas fa-times-circle"></i> Offline</span>
81
+ {% endif %}
82
+ </td>
83
+ <td>
84
+ {% for style in printer.label_zpl_styles[:3] %}
85
+ <span class="badge badge-primary">{{ style }}</span>
86
+ {% endfor %}
87
+ {% if printer.label_zpl_styles | length > 3 %}
88
+ <span class="text-muted">+{{ printer.label_zpl_styles | length - 3 }} more</span>
89
+ {% endif %}
90
+ </td>
91
+ <td>
92
+ <a href="/printers/{{ lab }}/{{ printer.id }}" class="btn btn-sm btn-outline">
93
+ <i class="fas fa-info-circle"></i> Details
94
+ </a>
95
+ <a href="/print?lab={{ lab }}&printer={{ printer.id }}" class="btn btn-sm btn-primary">
96
+ <i class="fas fa-print"></i> Print
97
+ </a>
98
+ </td>
99
+ </tr>
100
+ {% endfor %}
101
+ </tbody>
102
+ </table>
103
+ </div>
104
+ </div>
105
+ {% elif lab %}
106
+ <div class="card">
107
+ <div class="empty-state">
108
+ <i class="fas fa-print"></i>
109
+ <p>No printers found in {{ lab }}</p>
110
+ <a href="/config?action=scan&lab={{ lab }}" class="btn btn-primary">
111
+ <i class="fas fa-wifi"></i> Scan Network
112
+ </a>
113
+ </div>
114
+ </div>
115
+ {% endif %}
116
+
117
+ <!-- Scan Network Card -->
118
+ <div class="card mt-lg">
119
+ <div class="card-header">
120
+ <h3 class="card-title">Scan Network for Printers</h3>
121
+ </div>
122
+ <form action="/config/scan" method="get" class="grid grid-3">
123
+ <div class="form-group mb-0">
124
+ <label class="form-label">IP Range</label>
125
+ <input type="text" name="ip_stub" class="form-control" value="{{ ip_root | default('192.168.1') }}" placeholder="192.168.1">
126
+ </div>
127
+ <div class="form-group mb-0">
128
+ <label class="form-label">Lab Name</label>
129
+ <input type="text" name="lab" class="form-control" list="lab_names" value="{{ lab | default('') }}" placeholder="Enter lab name">
130
+ <datalist id="lab_names">
131
+ {% for lab_name in labs %}
132
+ <option value="{{ lab_name }}">
133
+ {% endfor %}
134
+ </datalist>
135
+ </div>
136
+ <div class="form-group mb-0" style="display: flex; align-items: flex-end;">
137
+ <button type="submit" class="btn btn-primary">
138
+ <i class="fas fa-search"></i> Scan Network
139
+ </button>
140
+ </div>
141
+ </form>
142
+ </div>
143
+ {% endblock %}
144
+
@@ -0,0 +1,46 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}{{ title }}{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="page-header">
7
+ <h1 class="page-title">Template Saved</h1>
8
+ <p class="page-subtitle">Your changes have been saved to a draft file</p>
9
+ </div>
10
+
11
+ <div class="card">
12
+ <div class="card-header">
13
+ <span class="card-icon text-success"><i class="fas fa-check-circle"></i></span>
14
+ <h3 class="card-title">Success</h3>
15
+ </div>
16
+
17
+ <p>Your changes have been saved to a new draft file:</p>
18
+
19
+ <div class="alert alert-info mt-md">
20
+ <i class="fas fa-file-code"></i>
21
+ <code>{{ new_filename }}</code>
22
+ </div>
23
+
24
+ <p class="text-muted mt-md">
25
+ Draft files are saved in the <code>tmps/</code> directory. To promote a draft to stable,
26
+ rename the file and move it to the main label_styles directory.
27
+ </p>
28
+ </div>
29
+
30
+ <div class="card mt-lg">
31
+ <div class="d-flex" style="justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--spacing-md);">
32
+ <a href="/templates" class="btn btn-outline">
33
+ <i class="fas fa-arrow-left"></i> Back to Templates
34
+ </a>
35
+ <div class="d-flex gap-md">
36
+ <a href="/templates/edit?filename={{ new_filename }}&dtype=tmps" class="btn btn-primary">
37
+ <i class="fas fa-edit"></i> Continue Editing
38
+ </a>
39
+ <a href="/" class="btn btn-outline">
40
+ <i class="fas fa-home"></i> Dashboard
41
+ </a>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ {% endblock %}
46
+
@@ -0,0 +1,175 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}Edit: {{ filename }} - Zebra Day{% endblock %}
4
+
5
+ {% block extra_head %}
6
+ <style>
7
+ .editor-container { display: grid; grid-template-columns: 1fr 1fr; gap: var(--spacing-lg); }
8
+ .editor-textarea { min-height: 500px; font-family: var(--font-mono); font-size: 14px; }
9
+ .preview-frame { background: var(--color-white); border-radius: var(--radius-md); padding: var(--spacing-lg); min-height: 300px; }
10
+ @media (max-width: 1024px) { .editor-container { grid-template-columns: 1fr; } }
11
+ </style>
12
+ {% endblock %}
13
+
14
+ {% block content %}
15
+ <div class="page-header">
16
+ <h1 class="page-title">Edit: {{ filename }}</h1>
17
+ <p class="page-subtitle">{% if dtype %}Draft template{% else %}Stable template{% endif %}</p>
18
+ </div>
19
+
20
+ <!-- Breadcrumb -->
21
+ <div class="mb-lg">
22
+ <a href="/" class="text-muted">Dashboard</a>
23
+ <span class="text-muted"> / </span>
24
+ <a href="/templates">Templates</a>
25
+ <span class="text-muted"> / </span>
26
+ <span>{{ filename }}</span>
27
+ </div>
28
+
29
+ <form id="editor-form" action="/save" method="post">
30
+ <input type="hidden" name="filename" value="{{ filename }}">
31
+
32
+ <div class="editor-container">
33
+ <!-- Editor Panel -->
34
+ <div class="card">
35
+ <div class="card-header">
36
+ <h3 class="card-title"><i class="fas fa-code"></i> ZPL Code</h3>
37
+ <button type="button" class="btn btn-outline btn-sm" onclick="previewTemplate()">
38
+ <i class="fas fa-eye"></i> Preview
39
+ </button>
40
+ </div>
41
+ <textarea name="content" id="zpl-editor" class="form-control editor-textarea">{{ content }}</textarea>
42
+ </div>
43
+
44
+ <!-- Preview Panel -->
45
+ <div class="card">
46
+ <div class="card-header">
47
+ <h3 class="card-title"><i class="fas fa-image"></i> Preview</h3>
48
+ <span class="badge badge-info" id="preview-status">Ready</span>
49
+ </div>
50
+ <div class="preview-frame" id="preview-container">
51
+ <div class="empty-state">
52
+ <i class="fas fa-image"></i>
53
+ <p>Click Preview to generate</p>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ </div>
58
+
59
+ <!-- Save Options -->
60
+ <div class="card mt-lg">
61
+ <div class="card-header">
62
+ <h3 class="card-title">Save Options</h3>
63
+ </div>
64
+ <div class="grid grid-3">
65
+ <div class="form-group mb-0">
66
+ <label class="form-label">Draft Tag</label>
67
+ <input type="text" name="ftag" class="form-control" value="draft" placeholder="Tag for draft version">
68
+ </div>
69
+ <div class="form-group mb-0">
70
+ <label class="form-label">Test Lab</label>
71
+ <select name="lab" class="form-control" id="test-lab" onchange="updateTestPrinters()">
72
+ <option value="">Select lab...</option>
73
+ {% for lab in labs %}
74
+ <option value="{{ lab }}">{{ lab }}</option>
75
+ {% endfor %}
76
+ </select>
77
+ </div>
78
+ <div class="form-group mb-0">
79
+ <label class="form-label">Test Printer</label>
80
+ <select name="printer" class="form-control" id="test-printer">
81
+ <option value="">Select printer...</option>
82
+ </select>
83
+ </div>
84
+ </div>
85
+ </div>
86
+
87
+ <!-- Actions -->
88
+ <div class="card mt-lg">
89
+ <div class="d-flex" style="justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--spacing-md);">
90
+ <a href="/templates" class="btn btn-outline">
91
+ <i class="fas fa-arrow-left"></i> Cancel
92
+ </a>
93
+ <div class="d-flex gap-md">
94
+ <button type="button" class="btn btn-outline" onclick="testPrint()">
95
+ <i class="fas fa-print"></i> Test Print
96
+ </button>
97
+ <button type="submit" class="btn btn-primary">
98
+ <i class="fas fa-save"></i> Save as Draft
99
+ </button>
100
+ </div>
101
+ </div>
102
+ </div>
103
+ </form>
104
+ {% endblock %}
105
+
106
+ {% block extra_scripts %}
107
+ <script>
108
+ var labsDict = {{ labs_dict | safe }};
109
+
110
+ function updateTestPrinters() {
111
+ var labSelect = document.getElementById('test-lab');
112
+ var printerSelect = document.getElementById('test-printer');
113
+ var lab = labSelect.value;
114
+
115
+ printerSelect.innerHTML = '<option value="">Select printer...</option>';
116
+ if (lab && labsDict[lab] && labsDict[lab].printers) {
117
+ // v2 schema: printers are nested under 'printers' key
118
+ var printers = labsDict[lab].printers;
119
+ for (var printerId in printers) {
120
+ var printerInfo = printers[printerId];
121
+ var option = document.createElement('option');
122
+ option.value = printerId;
123
+ option.text = printerInfo.printer_name || printerId;
124
+ printerSelect.appendChild(option);
125
+ }
126
+ }
127
+ }
128
+
129
+ async function previewTemplate() {
130
+ var statusBadge = document.getElementById('preview-status');
131
+ var container = document.getElementById('preview-container');
132
+ var content = document.getElementById('zpl-editor').value;
133
+
134
+ statusBadge.textContent = 'Loading...';
135
+ statusBadge.className = 'badge badge-warning';
136
+
137
+ try {
138
+ var response = await fetch('/api/v1/preview_zpl', {
139
+ method: 'POST',
140
+ headers: { 'Content-Type': 'application/json' },
141
+ body: JSON.stringify({ zpl_content: content })
142
+ });
143
+ var data = await response.json();
144
+ if (data.png_url) {
145
+ container.innerHTML = '<img src="' + data.png_url + '" alt="Preview" style="max-width: 100%;">';
146
+ statusBadge.textContent = 'Ready';
147
+ statusBadge.className = 'badge badge-success';
148
+ } else {
149
+ throw new Error(data.error || 'Preview failed');
150
+ }
151
+ } catch (err) {
152
+ container.innerHTML = '<div class="empty-state"><i class="fas fa-exclamation-triangle"></i><p>' + err.message + '</p></div>';
153
+ statusBadge.textContent = 'Error';
154
+ statusBadge.className = 'badge badge-error';
155
+ }
156
+ }
157
+
158
+ function testPrint() {
159
+ var lab = document.getElementById('test-lab').value;
160
+ var printer = document.getElementById('test-printer').value;
161
+ if (!lab || !printer) {
162
+ showToast('warning', 'Select Printer', 'Please select a lab and printer for test print.');
163
+ return;
164
+ }
165
+ var content = document.getElementById('zpl-editor').value;
166
+ var form = document.createElement('form');
167
+ form.method = 'POST';
168
+ form.action = '/api/v1/print_raw_zpl';
169
+ form.innerHTML = '<input name="lab" value="' + lab + '"><input name="printer" value="' + printer + '"><textarea name="zpl_content">' + content + '</textarea>';
170
+ document.body.appendChild(form);
171
+ form.submit();
172
+ }
173
+ </script>
174
+ {% endblock %}
175
+
@@ -0,0 +1,122 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}Templates - Zebra Day{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="page-header">
7
+ <h1 class="page-title">ZPL Templates</h1>
8
+ <p class="page-subtitle">Manage label templates and styles</p>
9
+ </div>
10
+
11
+ <div class="grid grid-2">
12
+ <!-- Stable Templates -->
13
+ <div class="card">
14
+ <div class="card-header">
15
+ <h3 class="card-title">
16
+ <i class="fas fa-check-circle text-success"></i> Stable Templates
17
+ </h3>
18
+ <span class="badge badge-success">{{ stable_templates | length }}</span>
19
+ </div>
20
+ {% if stable_templates %}
21
+ <div class="table-container" style="box-shadow: none;">
22
+ <table class="table">
23
+ <thead>
24
+ <tr>
25
+ <th>Template Name</th>
26
+ <th>Actions</th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ {% for template in stable_templates %}
31
+ <tr>
32
+ <td>
33
+ <i class="fas fa-file-code text-muted"></i>
34
+ <strong>{{ template }}</strong>
35
+ </td>
36
+ <td>
37
+ <a href="/templates/edit?filename={{ template }}" class="btn btn-sm btn-outline">
38
+ <i class="fas fa-edit"></i> Edit
39
+ </a>
40
+ <a href="/templates/preview?filename={{ template }}" class="btn btn-sm btn-primary">
41
+ <i class="fas fa-eye"></i> Preview
42
+ </a>
43
+ </td>
44
+ </tr>
45
+ {% endfor %}
46
+ </tbody>
47
+ </table>
48
+ </div>
49
+ {% else %}
50
+ <div class="empty-state">
51
+ <i class="fas fa-file-code"></i>
52
+ <p>No stable templates found</p>
53
+ </div>
54
+ {% endif %}
55
+ </div>
56
+
57
+ <!-- Draft Templates -->
58
+ <div class="card">
59
+ <div class="card-header">
60
+ <h3 class="card-title">
61
+ <i class="fas fa-pencil-alt text-warning"></i> Draft Templates
62
+ </h3>
63
+ <span class="badge badge-warning">{{ draft_templates | length }}</span>
64
+ </div>
65
+ {% if draft_templates %}
66
+ <div class="table-container" style="box-shadow: none;">
67
+ <table class="table">
68
+ <thead>
69
+ <tr>
70
+ <th>Template Name</th>
71
+ <th>Actions</th>
72
+ </tr>
73
+ </thead>
74
+ <tbody>
75
+ {% for template in draft_templates %}
76
+ <tr>
77
+ <td>
78
+ <i class="fas fa-file-alt text-muted"></i>
79
+ <strong>{{ template }}</strong>
80
+ </td>
81
+ <td>
82
+ <a href="/templates/edit?filename={{ template }}&dtype=tmps" class="btn btn-sm btn-outline">
83
+ <i class="fas fa-edit"></i> Edit
84
+ </a>
85
+ <a href="/templates/preview?filename={{ template }}&dtype=tmps" class="btn btn-sm btn-primary">
86
+ <i class="fas fa-eye"></i> Preview
87
+ </a>
88
+ </td>
89
+ </tr>
90
+ {% endfor %}
91
+ </tbody>
92
+ </table>
93
+ </div>
94
+ {% else %}
95
+ <div class="empty-state">
96
+ <i class="fas fa-pencil-alt"></i>
97
+ <p>No draft templates yet</p>
98
+ <small class="text-muted">Edit a stable template to create a draft</small>
99
+ </div>
100
+ {% endif %}
101
+ </div>
102
+ </div>
103
+
104
+ <!-- Format Keys Reference -->
105
+ <div class="card mt-lg">
106
+ <div class="card-header">
107
+ <h3 class="card-title">Template Format Keys</h3>
108
+ </div>
109
+ <p class="text-muted mb-lg">Use these placeholders in your ZPL templates to insert dynamic data:</p>
110
+ <div class="grid grid-4">
111
+ <div><code>{uid_barcode}</code> - Barcode value</div>
112
+ <div><code>{alt_a}</code> - Custom field A</div>
113
+ <div><code>{alt_b}</code> - Custom field B</div>
114
+ <div><code>{alt_c}</code> - Custom field C</div>
115
+ <div><code>{alt_d}</code> - Custom field D</div>
116
+ <div><code>{alt_e}</code> - Custom field E</div>
117
+ <div><code>{alt_f}</code> - Custom field F</div>
118
+ <div><code>{rec_date}</code> - Record date</div>
119
+ </div>
120
+ </div>
121
+ {% endblock %}
122
+
@@ -0,0 +1,9 @@
1
+ """
2
+ zebra_day web application module.
3
+
4
+ FastAPI-based web interface for managing Zebra printers and label templates.
5
+ """
6
+ from zebra_day.web.app import create_app
7
+
8
+ __all__ = ["create_app"]
9
+