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,176 @@
1
+ @font-face {
2
+ font-family: 'Monoid';
3
+ src: url('/etc/Monoid-Regular-HalfTight-Dollar-0-1-l.ttf') format('truetype');
4
+ font-weight: normal;
5
+ font-style: normal;
6
+ }
7
+
8
+ body {
9
+ font-family: 'Monoid', monospace;
10
+ background-image: repeating-linear-gradient(
11
+ -45deg,
12
+ rgba(200,200,200,0.1),
13
+ rgba(100,100,100,0.1) 10px,
14
+ rgba(0,0,0,0.1) 10px,
15
+ rgba(0,0,0,0.1) 20px
16
+ ); /* Zebra stripes for the body */
17
+ color: #333333;
18
+ margin: 0;
19
+ padding: 20px;
20
+ }
21
+
22
+ h1, h2 {
23
+ color: #FFFFFF; /* White headers to contrast against the stripes */
24
+ border-bottom: 3px solid #333333; /* Dark border to separate headers */
25
+ padding-bottom: 5px;
26
+ background-color: #000000; /* Solid black background to make headers pop */
27
+ padding: 5px;
28
+ }
29
+
30
+ ul {
31
+ list-style-type: none;
32
+ padding: 0;
33
+ }
34
+
35
+ li::before {
36
+ content: '•'; /* Bullet point */
37
+ color: #FFFFFF; /* White color to contrast with the stripes */
38
+ font-weight: bold; /* Emphasize the bullet point */
39
+ display: inline-block;
40
+ margin-right: 10px;
41
+ }
42
+
43
+ a {
44
+ color: #FF4500; /* Orange to contrast against the black & white */
45
+ text-decoration: none;
46
+ transition: color 0.3s ease;
47
+ }
48
+
49
+ a:hover {
50
+ color: #FF6347; /* Slight variation of orange for hover */
51
+ }
52
+
53
+ small {
54
+ color: rgba(22,181,131,0.8);
55
+ }
56
+
57
+ hr {
58
+ border: 0;
59
+ height: 2px;
60
+ background-image: linear-gradient(to right, #FFFFFF, #000000, #FFFFFF);
61
+ margin: 20px 0;
62
+ }
63
+
64
+ input[type=text], textarea {
65
+ background-color: #FFFFFF;
66
+ color: #333333;
67
+ border: 2px solid #000000;
68
+ border-radius: 5px;
69
+ padding: 5px 10px;
70
+ outline: none;
71
+ transition: border-color 0.3s ease;
72
+ }
73
+
74
+ input[type=text]:hover, textarea:hover {
75
+ border-color: #FF4500;
76
+ }
77
+
78
+ input[type=text]:focus, textarea:focus {
79
+ border-color: #FF6347;
80
+ box-shadow: 0 0 5px #FF6347;
81
+ }
82
+
83
+ input[type=submit], button {
84
+ background-color: #FF4500;
85
+ color: #FFFFFF;
86
+ border: none;
87
+ border-radius: 5px;
88
+ padding: 5px 10px;
89
+ cursor: pointer;
90
+ transition: background-color 0.3s ease;
91
+ }
92
+
93
+ input[type=submit]:hover, button:hover {
94
+ background-color: #FF6347;
95
+ }
96
+
97
+ select {
98
+ background-color: #FFFFFF;
99
+ color: #333333;
100
+ border: 2px solid #000000;
101
+ padding: 5px 10px;
102
+ border-radius: 5px;
103
+ appearance: none;
104
+ cursor: pointer;
105
+ }
106
+
107
+ textarea::-webkit-scrollbar {
108
+ width: 10px;
109
+ }
110
+
111
+ textarea::-webkit-scrollbar-thumb {
112
+ background-color: #FF4500;
113
+ border-radius: 5px;
114
+ }
115
+
116
+ textarea::-webkit-scrollbar-track {
117
+ background-color: #FFFFFF;
118
+ border-radius: 5px;
119
+ }
120
+
121
+ input[type="button"] {
122
+ background-color: #000000;
123
+ color: #FFFFFF;
124
+ border: 2px solid #FF4500;
125
+ padding: 5px 10px;
126
+ font-size: 16px;
127
+ border-radius: 5px;
128
+ transition: all 0.3s ease;
129
+ cursor: pointer;
130
+ font-family: 'Monoid', monospace;
131
+ }
132
+
133
+ input[type="button"]:hover {
134
+ background-color: #FF4500;
135
+ color: #000000;
136
+ }
137
+
138
+ input[type="button"]:active {
139
+ background-color: #FF6347;
140
+ }
141
+
142
+ input[type="button"]:focus {
143
+ box-shadow: 0 0 10px #FF6347;
144
+ }
145
+
146
+
147
+ #spinner {
148
+ display: flex;
149
+ justify-content: center;
150
+ align-items: center;
151
+ position: fixed;
152
+ top: 0;
153
+ left: 0;
154
+ width: 100%;
155
+ height: 100%;
156
+ background: rgba(0, 0, 0, 0.6);
157
+ z-index: 9999;
158
+ }
159
+
160
+ #spinner.spinner-hidden {
161
+ display: none;
162
+ }
163
+
164
+ .loader {
165
+ border: 8px solid #ECF0F1;
166
+ border-top: 8px solid #3498DB;
167
+ border-radius: 50%;
168
+ width: 50px;
169
+ height: 50px;
170
+ animation: spin 1s linear infinite;
171
+ }
172
+
173
+ @keyframes spin {
174
+ 0% { transform: rotate(0deg); }
175
+ 100% { transform: rotate(360deg); }
176
+ }
@@ -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,59 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}Config Backups - Zebra Day{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="page-header">
7
+ <h1 class="page-title">Configuration Backups</h1>
8
+ <div class="header-actions">
9
+ <a href="/config" class="btn btn-outline"><i class="fas fa-arrow-left"></i> Back</a>
10
+ </div>
11
+ </div>
12
+
13
+ <div class="card">
14
+ <div class="card-header">
15
+ <h3 class="card-title"><i class="fas fa-history"></i> Saved Configuration Files</h3>
16
+ <span class="badge">{{ backup_files | length }} backups</span>
17
+ </div>
18
+
19
+ <p class="text-muted mb-md" style="padding: 0 1rem;">
20
+ To restore a backup, download the file, open in a text editor, copy the contents,
21
+ then paste into the <a href="/config/edit">config editor</a> and save.
22
+ </p>
23
+
24
+ {% if backup_files %}
25
+ <div class="table-container">
26
+ <table class="table">
27
+ <thead>
28
+ <tr>
29
+ <th>Filename</th>
30
+ <th>Actions</th>
31
+ </tr>
32
+ </thead>
33
+ <tbody>
34
+ {% for file in backup_files %}
35
+ <tr>
36
+ <td>
37
+ <i class="fas fa-file-code text-muted"></i>
38
+ {{ file }}
39
+ </td>
40
+ <td>
41
+ <a href="/etc/old_printer_config/{{ file }}" class="btn btn-sm btn-outline" download>
42
+ <i class="fas fa-download"></i> Download
43
+ </a>
44
+ </td>
45
+ </tr>
46
+ {% endfor %}
47
+ </tbody>
48
+ </table>
49
+ </div>
50
+ {% else %}
51
+ <div class="empty-state">
52
+ <i class="fas fa-history"></i>
53
+ <p>No backup files found</p>
54
+ <small class="text-muted">Backups are created automatically when you save configuration changes</small>
55
+ </div>
56
+ {% endif %}
57
+ </div>
58
+ {% endblock %}
59
+
@@ -0,0 +1,95 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}{{ title }} - Zebra Day{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="page-header">
7
+ <h1 class="page-title">{{ title }}</h1>
8
+ <div class="header-actions">
9
+ <a href="/config" class="btn btn-outline"><i class="fas fa-arrow-left"></i> Back</a>
10
+ {% if mode == 'edit' %}
11
+ <button type="button" class="btn btn-outline" onclick="resetConfig()"><i class="fas fa-undo"></i> Reset</button>
12
+ <button type="button" class="btn btn-outline" onclick="clearConfig()"><i class="fas fa-trash"></i> Clear</button>
13
+ {% endif %}
14
+ </div>
15
+ </div>
16
+
17
+ {% if error_msg %}
18
+ <div class="alert alert-error mb-lg">
19
+ <i class="fas fa-exclamation-circle"></i> {{ error_msg }}
20
+ </div>
21
+ {% endif %}
22
+
23
+ <div class="card">
24
+ <div class="card-header">
25
+ <h3 class="card-title"><i class="fas fa-file-code"></i> Printer Configuration JSON</h3>
26
+ {% if mode == 'edit' %}
27
+ <span class="badge badge-warning">Editing</span>
28
+ {% else %}
29
+ <span class="badge badge-info">Read Only</span>
30
+ {% endif %}
31
+ </div>
32
+ <form method="post" action="/config/save">
33
+ <div class="form-group">
34
+ <textarea name="json_data" id="json-editor" class="form-control code-editor" rows="30" {% if mode != 'edit' %}readonly{% endif %}>{{ config_json }}</textarea>
35
+ </div>
36
+ {% if mode == 'edit' %}
37
+ <div class="form-actions">
38
+ <button type="submit" class="btn btn-primary" onclick="showLoading('Saving configuration...')">
39
+ <i class="fas fa-save"></i> Save Configuration
40
+ </button>
41
+ </div>
42
+ {% endif %}
43
+ </form>
44
+ </div>
45
+
46
+ <style>
47
+ .code-editor {
48
+ font-family: 'JetBrains Mono', 'Consolas', monospace;
49
+ font-size: 0.875rem;
50
+ line-height: 1.5;
51
+ background: var(--color-gray-700);
52
+ border: 1px solid var(--color-gray-600);
53
+ padding: 1rem;
54
+ resize: vertical;
55
+ min-height: 400px;
56
+ }
57
+ .code-editor:read-only {
58
+ background: var(--color-gray-800);
59
+ cursor: default;
60
+ }
61
+ .form-actions {
62
+ display: flex;
63
+ gap: 1rem;
64
+ padding: 1rem;
65
+ border-top: 1px solid var(--color-gray-600);
66
+ }
67
+ </style>
68
+
69
+ <script>
70
+ async function resetConfig() {
71
+ if (confirm('Reset configuration to template defaults? This will backup the current config.')) {
72
+ showLoading('Resetting configuration...');
73
+ window.location.href = '/config/reset';
74
+ }
75
+ }
76
+
77
+ async function clearConfig() {
78
+ if (confirm('Clear all printer configuration? This will backup the current config.')) {
79
+ showLoading('Clearing configuration...');
80
+ window.location.href = '/config/clear';
81
+ }
82
+ }
83
+
84
+ // Auto-format JSON on blur
85
+ document.getElementById('json-editor')?.addEventListener('blur', function() {
86
+ try {
87
+ const parsed = JSON.parse(this.value);
88
+ this.value = JSON.stringify(parsed, null, 4);
89
+ } catch (e) {
90
+ // Invalid JSON, leave as-is
91
+ }
92
+ });
93
+ </script>
94
+ {% endblock %}
95
+
@@ -0,0 +1,93 @@
1
+ {% extends "modern/base.html" %}
2
+
3
+ {% block title %}New Configuration - Zebra Day{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="page-header">
7
+ <h1 class="page-title">Build New Configuration</h1>
8
+ <div class="header-actions">
9
+ <a href="/config" class="btn btn-outline"><i class="fas fa-arrow-left"></i> Back</a>
10
+ </div>
11
+ </div>
12
+
13
+ <div class="grid grid-2">
14
+ <!-- Network Scan -->
15
+ <div class="card">
16
+ <div class="card-header">
17
+ <h3 class="card-title"><i class="fas fa-wifi"></i> Scan Network for Printers</h3>
18
+ </div>
19
+ <form action="/config/scan" method="get">
20
+ <div class="form-group">
21
+ <label class="form-label">IP Range Prefix</label>
22
+ <input type="text" name="ip_stub" class="form-control" value="{{ ip_root }}" placeholder="192.168.1">
23
+ <small class="text-muted">Enter the first three octets of your network</small>
24
+ </div>
25
+ <div class="form-group">
26
+ <label class="form-label">Lab Name</label>
27
+ <input type="text" name="lab" class="form-control" value="scan-results" placeholder="Enter lab name">
28
+ <small class="text-muted">Printers found will be added to this lab</small>
29
+ </div>
30
+ <div class="form-group">
31
+ <label class="form-label">Scan Wait Time</label>
32
+ <select name="scan_wait" class="form-control">
33
+ <option value="0.15">Fast (0.15s)</option>
34
+ <option value="0.25" selected>Normal (0.25s)</option>
35
+ <option value="0.5">Slow (0.5s)</option>
36
+ <option value="1.0">Very Slow (1.0s)</option>
37
+ </select>
38
+ <small class="text-muted">Longer wait times find more printers on slow networks</small>
39
+ </div>
40
+ <button type="submit" class="btn btn-primary" onclick="showLoading('Scanning network for Zebra printers...')">
41
+ <i class="fas fa-search"></i> Start Network Scan
42
+ </button>
43
+ </form>
44
+ </div>
45
+
46
+ <!-- Quick Actions -->
47
+ <div class="card">
48
+ <div class="card-header">
49
+ <h3 class="card-title"><i class="fas fa-bolt"></i> Quick Actions</h3>
50
+ </div>
51
+ <div class="quick-actions">
52
+ <a href="/config/reset" class="action-card" onclick="return confirm('Reset config to template defaults?')">
53
+ <i class="fas fa-undo"></i>
54
+ <div>
55
+ <strong>Reset to Template</strong>
56
+ <small class="text-muted d-block">Restore default configuration</small>
57
+ </div>
58
+ </a>
59
+ <a href="/config/clear" class="action-card" onclick="return confirm('Clear all printer configuration?')">
60
+ <i class="fas fa-trash"></i>
61
+ <div>
62
+ <strong>Clear Configuration</strong>
63
+ <small class="text-muted d-block">Remove all printers</small>
64
+ </div>
65
+ </a>
66
+ <a href="/config/edit" class="action-card">
67
+ <i class="fas fa-edit"></i>
68
+ <div>
69
+ <strong>Manual Edit</strong>
70
+ <small class="text-muted d-block">Edit JSON directly</small>
71
+ </div>
72
+ </a>
73
+ </div>
74
+
75
+ <hr class="my-md">
76
+
77
+ <h4 class="mb-md">Existing Labs</h4>
78
+ {% if labs %}
79
+ <div class="grid grid-3">
80
+ {% for lab in labs %}
81
+ <a href="/printers/{{ lab }}" class="action-card">
82
+ <i class="fas fa-building"></i>
83
+ <strong>{{ lab }}</strong>
84
+ </a>
85
+ {% endfor %}
86
+ </div>
87
+ {% else %}
88
+ <p class="text-muted">No labs configured yet. Run a network scan to discover printers.</p>
89
+ {% endif %}
90
+ </div>
91
+ </div>
92
+ {% endblock %}
93
+