zebra-day 0.0.37__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 (181) hide show
  1. zebra_day/__init__.py +35 -0
  2. zebra_day/bin/__init__.py +0 -0
  3. zebra_day/bin/fetch_zebra_config.py +15 -0
  4. zebra_day/bin/generate_coord_grid_zpl.py +50 -0
  5. zebra_day/bin/print_zpl_from_file.py +21 -0
  6. zebra_day/bin/probe_new_label_dimensions.py +75 -0
  7. zebra_day/bin/scan_for_networed_zebra_printers_arp_scan.sh +1 -0
  8. zebra_day/bin/scan_for_networed_zebra_printers_curl.sh +30 -0
  9. zebra_day/bin/zserve.py +701 -259
  10. zebra_day/cli/__init__.py +240 -0
  11. zebra_day/cli/cognito.py +121 -0
  12. zebra_day/cli/gui.py +255 -0
  13. zebra_day/cli/printer.py +168 -0
  14. zebra_day/cli/template.py +176 -0
  15. zebra_day/cmd_mgr.py +35 -0
  16. zebra_day/etc/Monoid-Regular-HalfTight-Dollar-0-1-l.ttf +0 -0
  17. zebra_day/etc/label_styles/blank.zpl +0 -0
  18. zebra_day/etc/label_styles/cornersStripOf4Squares_1inX1in.zpl +55 -0
  19. zebra_day/etc/label_styles/corners_1inX2in.zpl +28 -0
  20. zebra_day/etc/label_styles/corners_20cmX30cm.zpl +6 -0
  21. zebra_day/etc/label_styles/corners_smallTube.zpl +7 -0
  22. zebra_day/etc/label_styles/corners_unspecifiedDimensions.zpl +15 -0
  23. zebra_day/etc/label_styles/generic_2inX1in.zpl +21 -0
  24. zebra_day/etc/label_styles/plate_1inX0.25in.zpl +9 -0
  25. zebra_day/etc/label_styles/plate_1inX0.25inHD.zpl +9 -0
  26. zebra_day/etc/label_styles/smallTubeWdotHD_prod.zpl +8 -0
  27. zebra_day/etc/label_styles/smallTubeWdot_corners.zpl +7 -0
  28. zebra_day/etc/label_styles/smallTubeWdot_prod.zpl +8 -0
  29. zebra_day/etc/label_styles/smallTubeWdot_prodAlt1.zpl +6 -0
  30. zebra_day/etc/label_styles/smallTubeWdot_prodAlt1b.zpl +3 -0
  31. zebra_day/etc/label_styles/smallTubeWdot_prodV2.zpl +8 -0
  32. zebra_day/etc/label_styles/smallTubeWdot_reagent.zpl +29 -0
  33. zebra_day/etc/label_styles/stripOf4Squares_1inX1in.zpl +32 -0
  34. zebra_day/etc/label_styles/test_800dX800dCoordinateArray.zpl +1 -0
  35. zebra_day/etc/label_styles/tmps/.hold +0 -0
  36. zebra_day/etc/label_styles/tmps/tmp_zpl_templates.here +0 -0
  37. zebra_day/etc/label_styles/tube_20mmX30mmA.zpl +7 -0
  38. zebra_day/etc/label_styles/tube_2inX0.3in.zpl +15 -0
  39. zebra_day/etc/label_styles/tube_2inX0.5in.zpl +15 -0
  40. zebra_day/etc/label_styles/tube_2inX0.5inHD.zpl +15 -0
  41. zebra_day/etc/label_styles/tube_2inX1in.zpl +25 -0
  42. zebra_day/etc/label_styles/tube_2inX1inHD.zpl +22 -0
  43. zebra_day/etc/label_styles/tube_2inX1inHDv3.zpl +21 -0
  44. zebra_day/etc/old_printer_config/.hold +0 -0
  45. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.022846_printer_config.json +1 -0
  46. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.033657_printer_config.json +1 -0
  47. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.039597_printer_config.json +3 -0
  48. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.047295_printer_config.json +1 -0
  49. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.055804_printer_config.json +1 -0
  50. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.061337_printer_config.json +3 -0
  51. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.073326_printer_config.json +1 -0
  52. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.081950_printer_config.json +1 -0
  53. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.088251_printer_config.json +3 -0
  54. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.096501_printer_config.json +1 -0
  55. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.104767_printer_config.json +1 -0
  56. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.110364_printer_config.json +3 -0
  57. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.118239_printer_config.json +1 -0
  58. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.125950_printer_config.json +1 -0
  59. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.349866_printer_config.json +1 -0
  60. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.361085_printer_config.json +3 -0
  61. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.558323_printer_config.json +1 -0
  62. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.565756_printer_config.json +3 -0
  63. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.739070_printer_config.json +16 -0
  64. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.753796_printer_config.json +1 -0
  65. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.760201_printer_config.json +3 -0
  66. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.768747_printer_config.json +1 -0
  67. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.775312_printer_config.json +3 -0
  68. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.782533_printer_config.json +1 -0
  69. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.789287_printer_config.json +1 -0
  70. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.794230_printer_config.json +3 -0
  71. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.800021_printer_config.json +5 -0
  72. zebra_day/etc/printer_config.json +16 -0
  73. zebra_day/etc/printer_config.template.json +16 -0
  74. zebra_day/etc/tmp_printers0.json +5 -0
  75. zebra_day/etc/tmp_printers374.json +5 -0
  76. zebra_day/etc/tmp_printers383.json +5 -0
  77. zebra_day/etc/tmp_printers450.json +5 -0
  78. zebra_day/etc/tmp_printers504.json +5 -0
  79. zebra_day/etc/tmp_printers608.json +5 -0
  80. zebra_day/etc/tmp_printers657.json +5 -0
  81. zebra_day/etc/tmp_printers838.json +5 -0
  82. zebra_day/etc/tmp_printers839.json +5 -0
  83. zebra_day/etc/tmp_printers933.json +5 -0
  84. zebra_day/etc/tmp_printers957.json +5 -0
  85. zebra_day/exceptions.py +88 -0
  86. zebra_day/files/.hold +0 -0
  87. zebra_day/files/hold +0 -0
  88. zebra_day/files/test_png_17696.png +0 -0
  89. zebra_day/files/test_png_23477.png +0 -0
  90. zebra_day/files/test_png_28157.png +0 -0
  91. zebra_day/files/test_png_35832.png +0 -0
  92. zebra_day/files/test_png_36400.png +0 -0
  93. zebra_day/files/test_png_40816.png +0 -0
  94. zebra_day/files/test_png_49564.png +0 -0
  95. zebra_day/files/test_png_53848.png +0 -0
  96. zebra_day/files/test_png_62542.png +0 -0
  97. zebra_day/files/test_png_91597.png +0 -0
  98. zebra_day/files/test_png_93633.png +0 -0
  99. zebra_day/files/tmpbjo3k7q1.png +0 -0
  100. zebra_day/files/tmpigtr4pwy.png +0 -0
  101. zebra_day/files/zpl_label_tube_2inX1in_2026-02-01_01:51:24.370964.png +0 -0
  102. zebra_day/logging_config.py +74 -0
  103. zebra_day/logs/.hold +0 -0
  104. zebra_day/logs/print_requests.log +2 -0
  105. zebra_day/paths.py +143 -0
  106. zebra_day/print_mgr.py +487 -103
  107. zebra_day/static/datschund.css +140 -0
  108. zebra_day/static/datschund.png +0 -0
  109. zebra_day/static/daylily.png +0 -0
  110. zebra_day/static/favicon.svg +20 -0
  111. zebra_day/static/general.css +99 -0
  112. zebra_day/static/js/zebra_modern.js +172 -0
  113. zebra_day/static/lsmc.css +354 -0
  114. zebra_day/static/moon.jpeg +0 -0
  115. zebra_day/static/oakland.css +197 -0
  116. zebra_day/static/petrichor.css +150 -0
  117. zebra_day/static/popday_daylily.css +140 -0
  118. zebra_day/static/style.css +183 -0
  119. zebra_day/static/triangles.css +122 -0
  120. zebra_day/static/tron.css +277 -0
  121. zebra_day/static/zebra_modern.css +771 -0
  122. zebra_day/static/zebras.css +176 -0
  123. zebra_day/templates/base.html +36 -0
  124. zebra_day/templates/bpr.html +72 -0
  125. zebra_day/templates/build_new_config.html +36 -0
  126. zebra_day/templates/build_print_request.html +32 -0
  127. zebra_day/templates/chg_ui_style.html +19 -0
  128. zebra_day/templates/edit_template.html +128 -0
  129. zebra_day/templates/edit_zpl.html +37 -0
  130. zebra_day/templates/index.html +82 -0
  131. zebra_day/templates/legacy/base.html +37 -0
  132. zebra_day/templates/legacy/bpr.html +72 -0
  133. zebra_day/templates/legacy/build_new_config.html +36 -0
  134. zebra_day/templates/legacy/build_print_request.html +32 -0
  135. zebra_day/templates/legacy/chg_ui_style.html +19 -0
  136. zebra_day/templates/legacy/edit_template.html +128 -0
  137. zebra_day/templates/legacy/edit_zpl.html +37 -0
  138. zebra_day/templates/legacy/index.html +82 -0
  139. zebra_day/templates/legacy/list_prior_configs.html +24 -0
  140. zebra_day/templates/legacy/print_result.html +30 -0
  141. zebra_day/templates/legacy/printer_details.html +25 -0
  142. zebra_day/templates/legacy/printer_status.html +70 -0
  143. zebra_day/templates/legacy/save_result.html +17 -0
  144. zebra_day/templates/legacy/send_print_request.html +34 -0
  145. zebra_day/templates/legacy/simple_print.html +94 -0
  146. zebra_day/templates/legacy/view_pstation_json.html +29 -0
  147. zebra_day/templates/list_prior_configs.html +24 -0
  148. zebra_day/templates/modern/base.html +98 -0
  149. zebra_day/templates/modern/config.html +141 -0
  150. zebra_day/templates/modern/dashboard.html +160 -0
  151. zebra_day/templates/modern/print_request.html +141 -0
  152. zebra_day/templates/modern/print_result.html +88 -0
  153. zebra_day/templates/modern/printer_detail.html +117 -0
  154. zebra_day/templates/modern/printers.html +133 -0
  155. zebra_day/templates/modern/save_result.html +46 -0
  156. zebra_day/templates/modern/template_editor.html +172 -0
  157. zebra_day/templates/modern/templates.html +122 -0
  158. zebra_day/templates/print_result.html +30 -0
  159. zebra_day/templates/printer_details.html +25 -0
  160. zebra_day/templates/printer_status.html +70 -0
  161. zebra_day/templates/save_result.html +17 -0
  162. zebra_day/templates/send_print_request.html +34 -0
  163. zebra_day/templates/simple_print.html +94 -0
  164. zebra_day/templates/view_pstation_json.html +29 -0
  165. zebra_day/web/__init__.py +9 -0
  166. zebra_day/web/app.py +171 -0
  167. zebra_day/web/auth.py +172 -0
  168. zebra_day/web/middleware.py +159 -0
  169. zebra_day/web/routers/__init__.py +2 -0
  170. zebra_day/web/routers/api.py +163 -0
  171. zebra_day/web/routers/ui.py +1051 -0
  172. zebra_day/zpl_renderer.py +273 -0
  173. zebra_day-1.0.2.dist-info/METADATA +786 -0
  174. zebra_day-1.0.2.dist-info/RECORD +179 -0
  175. {zebra_day-0.0.37.dist-info → zebra_day-1.0.2.dist-info}/WHEEL +1 -1
  176. zebra_day-1.0.2.dist-info/entry_points.txt +4 -0
  177. zebra_day/bin/te.py +0 -905
  178. zebra_day-0.0.37.dist-info/METADATA +0 -1177
  179. zebra_day-0.0.37.dist-info/RECORD +0 -10
  180. {zebra_day-0.0.37.dist-info → zebra_day-1.0.2.dist-info/licenses}/LICENSE +0 -0
  181. {zebra_day-0.0.37.dist-info → zebra_day-1.0.2.dist-info}/top_level.txt +0 -0
@@ -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
+
@@ -0,0 +1,117 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}{{ printer_name }} - Zebra Day{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="page-header">
7
+ <h1 class="page-title">{{ printer_name }}</h1>
8
+ <p class="page-subtitle">Printer details for {{ lab }}</p>
9
+ </div>
10
+
11
+ <!-- Breadcrumb -->
12
+ <div class="mb-lg">
13
+ <a href="/" class="text-muted">Dashboard</a>
14
+ <span class="text-muted"> / </span>
15
+ <a href="/printers">Printers</a>
16
+ <span class="text-muted"> / </span>
17
+ <a href="/printers/{{ lab }}">{{ lab }}</a>
18
+ <span class="text-muted"> / </span>
19
+ <span>{{ printer_name }}</span>
20
+ </div>
21
+
22
+ <div class="grid grid-2">
23
+ <!-- Printer Info -->
24
+ <div class="card">
25
+ <div class="card-header">
26
+ <h3 class="card-title">Printer Information</h3>
27
+ {% if printer_info.ip_address != 'dl_png' %}
28
+ <a href="http://{{ printer_info.ip_address }}" target="_blank" class="btn btn-outline btn-sm">
29
+ <i class="fas fa-external-link-alt"></i> Web Interface
30
+ </a>
31
+ {% endif %}
32
+ </div>
33
+ <table class="table" style="background: transparent; box-shadow: none;">
34
+ <tbody>
35
+ {% for key, value in printer_info.items() %}
36
+ <tr>
37
+ <td style="width: 40%;"><strong>{{ key }}</strong></td>
38
+ <td>
39
+ {% if key == 'ip_address' and value != 'dl_png' %}
40
+ <a href="http://{{ value }}" target="_blank">{{ value }}</a>
41
+ {% elif key == 'status' %}
42
+ {% if value == 'online' %}
43
+ <span class="badge badge-success">Online</span>
44
+ {% else %}
45
+ <span class="badge badge-error">Offline</span>
46
+ {% endif %}
47
+ {% elif key == 'label_zpl_styles' %}
48
+ {% for style in value %}
49
+ <span class="badge badge-primary">{{ style }}</span>
50
+ {% endfor %}
51
+ {% else %}
52
+ {{ value }}
53
+ {% endif %}
54
+ </td>
55
+ </tr>
56
+ {% endfor %}
57
+ </tbody>
58
+ </table>
59
+ </div>
60
+
61
+ <!-- Quick Actions -->
62
+ <div class="card">
63
+ <div class="card-header">
64
+ <h3 class="card-title">Quick Actions</h3>
65
+ </div>
66
+ <div class="quick-actions">
67
+ <a href="/print?lab={{ lab }}&printer={{ printer_name }}" class="action-card">
68
+ <i class="fas fa-print"></i>
69
+ <div>
70
+ <strong>Print Label</strong>
71
+ <small class="text-muted d-block">Send a print request</small>
72
+ </div>
73
+ </a>
74
+ <a href="/templates" class="action-card">
75
+ <i class="fas fa-file-code"></i>
76
+ <div>
77
+ <strong>View Templates</strong>
78
+ <small class="text-muted d-block">Available label styles</small>
79
+ </div>
80
+ </a>
81
+ </div>
82
+ </div>
83
+ </div>
84
+
85
+ <!-- Printer Configuration -->
86
+ {% if printer_config %}
87
+ <div class="card mt-lg">
88
+ <div class="card-header">
89
+ <h3 class="card-title">Printer Configuration</h3>
90
+ <button class="btn btn-outline btn-sm" onclick="copyToClipboard(document.getElementById('printer-config').textContent)">
91
+ <i class="fas fa-copy"></i> Copy
92
+ </button>
93
+ </div>
94
+ <pre id="printer-config">{{ printer_config }}</pre>
95
+ </div>
96
+ {% endif %}
97
+
98
+ <!-- Test Print Section -->
99
+ <div class="card mt-lg">
100
+ <div class="card-header">
101
+ <h3 class="card-title">Test Print</h3>
102
+ </div>
103
+ <p class="text-muted mb-lg">Send a test label to verify the printer is working correctly.</p>
104
+ <div class="grid grid-3">
105
+ {% for style in printer_info.label_zpl_styles[:6] %}
106
+ <a href="/print?lab={{ lab }}&printer={{ printer_name }}&template={{ style }}&test=1" class="action-card">
107
+ <i class="fas fa-tag"></i>
108
+ <div>
109
+ <strong>{{ style }}</strong>
110
+ <small class="text-muted d-block">Test print</small>
111
+ </div>
112
+ </a>
113
+ {% endfor %}
114
+ </div>
115
+ </div>
116
+ {% endblock %}
117
+
@@ -0,0 +1,133 @@
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 }}{% 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>IP Address</th>
46
+ <th>Status</th>
47
+ <th>Label Styles</th>
48
+ <th>Actions</th>
49
+ </tr>
50
+ </thead>
51
+ <tbody>
52
+ {% for printer in printers %}
53
+ <tr>
54
+ <td>
55
+ <strong>{{ printer.name }}</strong><br>
56
+ <small class="text-muted">{{ printer.model | default('Unknown model') }}</small>
57
+ </td>
58
+ <td>
59
+ {% if printer.ip_address != 'dl_png' %}
60
+ <a href="http://{{ printer.ip_address }}" target="_blank">{{ printer.ip_address }}</a>
61
+ {% else %}
62
+ <span class="text-muted">{{ printer.ip_address }}</span>
63
+ {% endif %}
64
+ </td>
65
+ <td>
66
+ {% if printer.status == 'online' %}
67
+ <span class="badge badge-success">Online</span>
68
+ {% else %}
69
+ <span class="badge badge-error">Offline</span>
70
+ {% endif %}
71
+ </td>
72
+ <td>
73
+ {% for style in printer.label_zpl_styles[:3] %}
74
+ <span class="badge badge-primary">{{ style }}</span>
75
+ {% endfor %}
76
+ {% if printer.label_zpl_styles | length > 3 %}
77
+ <span class="text-muted">+{{ printer.label_zpl_styles | length - 3 }} more</span>
78
+ {% endif %}
79
+ </td>
80
+ <td>
81
+ <a href="/printers/{{ lab }}/{{ printer.name }}" class="btn btn-sm btn-outline">
82
+ <i class="fas fa-info-circle"></i> Details
83
+ </a>
84
+ <a href="/print?lab={{ lab }}&printer={{ printer.name }}" class="btn btn-sm btn-primary">
85
+ <i class="fas fa-print"></i> Print
86
+ </a>
87
+ </td>
88
+ </tr>
89
+ {% endfor %}
90
+ </tbody>
91
+ </table>
92
+ </div>
93
+ </div>
94
+ {% elif lab %}
95
+ <div class="card">
96
+ <div class="empty-state">
97
+ <i class="fas fa-print"></i>
98
+ <p>No printers found in {{ lab }}</p>
99
+ <a href="/config?action=scan&lab={{ lab }}" class="btn btn-primary">
100
+ <i class="fas fa-wifi"></i> Scan Network
101
+ </a>
102
+ </div>
103
+ </div>
104
+ {% endif %}
105
+
106
+ <!-- Scan Network Card -->
107
+ <div class="card mt-lg">
108
+ <div class="card-header">
109
+ <h3 class="card-title">Scan Network for Printers</h3>
110
+ </div>
111
+ <form action="/config/scan" method="get" class="grid grid-3">
112
+ <div class="form-group mb-0">
113
+ <label class="form-label">IP Range</label>
114
+ <input type="text" name="ip_stub" class="form-control" value="{{ ip_root | default('192.168.1') }}" placeholder="192.168.1">
115
+ </div>
116
+ <div class="form-group mb-0">
117
+ <label class="form-label">Lab Name</label>
118
+ <input type="text" name="lab" class="form-control" list="lab_names" value="{{ lab | default('') }}" placeholder="Enter lab name">
119
+ <datalist id="lab_names">
120
+ {% for lab_name in labs %}
121
+ <option value="{{ lab_name }}">
122
+ {% endfor %}
123
+ </datalist>
124
+ </div>
125
+ <div class="form-group mb-0" style="display: flex; align-items: flex-end;">
126
+ <button type="submit" class="btn btn-primary">
127
+ <i class="fas fa-search"></i> Scan Network
128
+ </button>
129
+ </div>
130
+ </form>
131
+ </div>
132
+ {% endblock %}
133
+
@@ -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
+