algomancy-quickstart 0.7.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.
- algomancy_quickstart/__init__.py +2 -0
- algomancy_quickstart/asset_manager.py +202 -0
- algomancy_quickstart/data_inference.py +517 -0
- algomancy_quickstart/main.py +62 -0
- algomancy_quickstart/quickstart.py +683 -0
- algomancy_quickstart/styling_wizard.py +347 -0
- algomancy_quickstart/templates/__init__.py +0 -0
- algomancy_quickstart/templates/algorithm.py.jinja +104 -0
- algomancy_quickstart/templates/assets/CQM-logo-white.png +0 -0
- algomancy_quickstart/templates/assets/cqm-button-white.png +0 -0
- algomancy_quickstart/templates/assets/cqm-button.png +0 -0
- algomancy_quickstart/templates/assets/cqm-logo.png +0 -0
- algomancy_quickstart/templates/assets/css/button_colors.css +285 -0
- algomancy_quickstart/templates/assets/css/cqm_loader.css +47 -0
- algomancy_quickstart/templates/assets/css/sidebar_layout.css +189 -0
- algomancy_quickstart/templates/assets/css/theme_colors.css +90 -0
- algomancy_quickstart/templates/assets/letter-c.svg +4 -0
- algomancy_quickstart/templates/assets/letter-m.svg +4 -0
- algomancy_quickstart/templates/assets/letter-q.svg +4 -0
- algomancy_quickstart/templates/assets/letters/letter-c.png +0 -0
- algomancy_quickstart/templates/assets/letters/letter-m.png +0 -0
- algomancy_quickstart/templates/assets/letters/letter-q.png +0 -0
- algomancy_quickstart/templates/assets/pepsi_girl.jpeg +0 -0
- algomancy_quickstart/templates/assets/style.css +421 -0
- algomancy_quickstart/templates/compare_page.py.jinja +133 -0
- algomancy_quickstart/templates/data_page.py.jinja +94 -0
- algomancy_quickstart/templates/etl_factory.py.jinja +108 -0
- algomancy_quickstart/templates/etl_factory_generated.py.jinja +82 -0
- algomancy_quickstart/templates/generated_schemas.py.jinja +55 -0
- algomancy_quickstart/templates/home_page.py.jinja +65 -0
- algomancy_quickstart/templates/kpi.py.jinja +76 -0
- algomancy_quickstart/templates/main.py.jinja +42 -0
- algomancy_quickstart/templates/main_custom.py.jinja +55 -0
- algomancy_quickstart/templates/main_generated_etl.py.jinja +72 -0
- algomancy_quickstart/templates/main_with_styling.py.jinja +83 -0
- algomancy_quickstart/templates/overview_page.py.jinja +98 -0
- algomancy_quickstart/templates/scenario_page.py.jinja +77 -0
- algomancy_quickstart/templates/schema.py.jinja +58 -0
- algomancy_quickstart/templates/styling_config.py.jinja +53 -0
- algomancy_quickstart-0.7.0.dist-info/METADATA +29 -0
- algomancy_quickstart-0.7.0.dist-info/RECORD +42 -0
- algomancy_quickstart-0.7.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
@import url('/example/assets/css/theme_colors.css');
|
|
2
|
+
@import url('/example/assets/css/sidebar_layout.css');
|
|
3
|
+
@import url('/example/assets/css/button_colors.css');
|
|
4
|
+
@import url('/example/assets/css/cqm_loader.css');
|
|
5
|
+
|
|
6
|
+
/* =========================
|
|
7
|
+
Base elements & utilities
|
|
8
|
+
========================= */
|
|
9
|
+
hr {
|
|
10
|
+
border-top: 2px solid gray;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/*todo buttons on scenario page should be styled separately*/
|
|
14
|
+
|
|
15
|
+
.btn {
|
|
16
|
+
border-color: var(--theme-secondary); /* todo this should respond to unified button colors */
|
|
17
|
+
background-color: var(--theme-secondary);
|
|
18
|
+
color: var(--text-selected)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.btn:hover {
|
|
22
|
+
border-color: var(--theme-tertiary);
|
|
23
|
+
background-color: var(--theme-tertiary);
|
|
24
|
+
color: var(--text-highlight);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.rc-slider-track {
|
|
28
|
+
background-color: var(--theme-secondary);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.rc-slider-dot-active, .rc-slider-handle, .rc-slider-handle:focus {
|
|
32
|
+
border-color: var(--theme-secondary);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.rc-slider-handle:active {
|
|
36
|
+
border-color: var(--theme-secondary);
|
|
37
|
+
box-shadow: 0 0 0 2px rgb(from var(--theme-secondary) r g b /0.3) ;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.CalendarDay__selected, .CalendarDay__selected:active, .CalendarDay__selected:hover {
|
|
41
|
+
background: var(--theme-primary);
|
|
42
|
+
border: 1px double var(--theme-primary);
|
|
43
|
+
color: var(--text-selected);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.CalendarDay__selected_span {
|
|
47
|
+
background: var(--theme-secondary);
|
|
48
|
+
border: 1px double var(--theme-secondary);
|
|
49
|
+
color: var(--text-selected);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.DayPickerKeyboardShortcuts_show {
|
|
53
|
+
display: none;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.DateInput_input__focused {
|
|
57
|
+
border-bottom: 2px solid var(--theme-primary);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* =========================
|
|
61
|
+
Layout containers
|
|
62
|
+
========================= */
|
|
63
|
+
.page-content {
|
|
64
|
+
padding: 2rem;
|
|
65
|
+
transition: margin-left 0.3s ease-in-out;
|
|
66
|
+
background-color: var(--background-color);
|
|
67
|
+
color: var(--text-color);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.page-content.collapsed {
|
|
71
|
+
margin-left: 80px; /* Width of the collapsed sidebar */
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.page-content.expanded {
|
|
75
|
+
margin-left: 270px; /* Width of the expanded sidebar */
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.layout-container {
|
|
79
|
+
background-color: var(--background-color);
|
|
80
|
+
min-height: 100vh;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* =========================
|
|
84
|
+
Controls & components
|
|
85
|
+
========================= */
|
|
86
|
+
/* Accordion styling */
|
|
87
|
+
.accordion-button {
|
|
88
|
+
background-color: var(--card-surface);
|
|
89
|
+
color: var(--text-color);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.accordion-item {
|
|
93
|
+
background-color: var(--card-surface);
|
|
94
|
+
border-radius: 6px;
|
|
95
|
+
transition: background-color 0.2s ease-in-out;
|
|
96
|
+
border: 1px solid rgba(0,0,0,0.1);
|
|
97
|
+
border-left: 0;
|
|
98
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
99
|
+
color: var(--text-color);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Styling for dropdown menus */
|
|
103
|
+
.Select-control, .Select-menu-outer, .Select-input {
|
|
104
|
+
background-color: var(--card-surface);
|
|
105
|
+
color: var(--text-color);
|
|
106
|
+
transition: box-shadow 0.2s ease-in-out;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.Select-value-label, .Select-option {
|
|
110
|
+
color: var(--text-color);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.Select--single > .Select-control .Select-value, .Select-placeholder {
|
|
114
|
+
background-color: var(--card-surface);
|
|
115
|
+
color: var(--text-color);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.VirtualizedSelectOption {
|
|
119
|
+
background-color: var(--card-surface);
|
|
120
|
+
color: var(--text-color);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.VirtualizedSelectFocusedOption {
|
|
124
|
+
background-color: var(--theme-secondary);
|
|
125
|
+
color: var(--text-selected);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.Select--multi .Select-value-icon {
|
|
129
|
+
color: var(--text-color);
|
|
130
|
+
/*background-color: rgb(from var(--theme-secondary) r g b /0.2);*/
|
|
131
|
+
border-right-color: var(--theme-secondary);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.Select--multi .Select-value-icon:hover {
|
|
135
|
+
color: var(--text-selected);
|
|
136
|
+
background-color: rgb(from var(--theme-secondary) r g b /0.5);
|
|
137
|
+
border-right-color: var(--theme-secondary);
|
|
138
|
+
transition: background-color 0.2s ease-in-out;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.Select--multi .Select-value {
|
|
142
|
+
color: var(--text-color);
|
|
143
|
+
background-color: rgb(from var(--theme-secondary) r g b /0.2);
|
|
144
|
+
border-color: var(--theme-secondary);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.is-focused:not(.is-open)>.Select-control {
|
|
148
|
+
border-color: var(--theme-secondary);
|
|
149
|
+
box-shadow: 0 0 0 2px rgb(from var(--theme-secondary) r g b /0.3) ;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.is-open>.Select-control {
|
|
153
|
+
background-color: var(--card-surface);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* styling for input groups */
|
|
157
|
+
.form-control, input.form-control {
|
|
158
|
+
background-color: var(--card-surface);
|
|
159
|
+
color: var(--text-color);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.form-control:focus, input.form-control:focus {
|
|
163
|
+
background-color: var(--card-surface);
|
|
164
|
+
color: var(--text-color);
|
|
165
|
+
border-color: var(--theme-secondary);
|
|
166
|
+
box-shadow: 0 0 0 0.2rem rgb(from var(--theme-secondary) r g b /0.3);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.form-control::placeholder, input.form-control::placeholder {
|
|
170
|
+
color: var(--text-color);
|
|
171
|
+
opacity: 0.6;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* styling for checkboxes */
|
|
175
|
+
.form-check-input {
|
|
176
|
+
background-color: var(--card-surface);
|
|
177
|
+
border-color: var(--text-color);
|
|
178
|
+
color: var(--text-color);
|
|
179
|
+
transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out;
|
|
180
|
+
cursor: pointer;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.form-check-input:checked {
|
|
184
|
+
background-color: var(--toggle-active-color);
|
|
185
|
+
border-color: var(--toggle-active-color);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.form-check-input:focus {
|
|
189
|
+
box-shadow: 0 0 0 0.2rem var(--toggle-shadow-color);
|
|
190
|
+
border-color: var(--toggle-active-color);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.form-switch .form-check-input {
|
|
194
|
+
background-color: var(--toggle-background-color);
|
|
195
|
+
background-image: var(--toggle-handle-inactive);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.form-switch .form-check-input:checked {
|
|
199
|
+
background-color: var(--toggle-active-color);
|
|
200
|
+
background-image: var(--toggle-handle-selected);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.form-switch .form-check-input:focus, .form-check-input:active{
|
|
204
|
+
background-image: var(--toggle-handle-focussed)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.form-switch .form-check-input:checked:focus {
|
|
208
|
+
box-shadow: 0 0 0 0.2rem var(--toggle-shadow-color);
|
|
209
|
+
background-image: var(--toggle-handle-selected)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* daq.BooleanSwitch background color */
|
|
213
|
+
.gJuplL {
|
|
214
|
+
background-color: var(--toggle-active-color) !important;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/* =========================
|
|
218
|
+
Scenario cards & new scenario controls
|
|
219
|
+
========================= */
|
|
220
|
+
.scenario-card {
|
|
221
|
+
cursor: pointer;
|
|
222
|
+
transition: background-color 0.2s ease-in-out;
|
|
223
|
+
background-color: var(--card-surface);
|
|
224
|
+
border-radius: 6px;
|
|
225
|
+
border: 1px solid #ddd;
|
|
226
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
227
|
+
padding : 8px 12px;
|
|
228
|
+
margin-bottom: 10px;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.scenario-card.selected {
|
|
232
|
+
background-color: var(--theme-secondary);
|
|
233
|
+
color: var(--text-selected);
|
|
234
|
+
border-color: var(--theme-secondary);
|
|
235
|
+
transition: all 0.25s ease-in-out;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.scenario-card.hidden {
|
|
239
|
+
display: none;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.scenario-progress-bar .progress-bar{
|
|
243
|
+
background-color: var(--theme-secondary) !important;
|
|
244
|
+
animation: progress-bar-stripes 1s linear infinite;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/* =========================
|
|
248
|
+
Admin page log window
|
|
249
|
+
========================= */
|
|
250
|
+
.admin-log-card {
|
|
251
|
+
display: flex;
|
|
252
|
+
flex-direction: column;
|
|
253
|
+
height: calc(100vh - 380px); /* Adjust based on other content */
|
|
254
|
+
min-height: 300px; /* Set a reasonable minimum */
|
|
255
|
+
overflow-y: auto; /* Allow scrolling if content exceeds height */
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
.admin-log-window {
|
|
260
|
+
flex: 1;
|
|
261
|
+
overflow-y: auto;
|
|
262
|
+
font-family: monospace;
|
|
263
|
+
white-space: pre-wrap;
|
|
264
|
+
background-color: #f8f9fa;
|
|
265
|
+
padding: 10px;
|
|
266
|
+
border-radius: 5px;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/* =========================
|
|
270
|
+
Themed modals & their contents
|
|
271
|
+
========================= */
|
|
272
|
+
.themed-modal {
|
|
273
|
+
color: var(--text-color);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.themed-modal .modal-header {
|
|
277
|
+
background-color: var(--theme-primary); /* issue: the modal does not respond to the variable update */
|
|
278
|
+
border-bottom: 1px solid rgba(0,0,0,0.1);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.themed-modal .modal-title {
|
|
282
|
+
color: var(--text-selected);
|
|
283
|
+
font-weight: 600;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.themed-modal .modal-body, .modal-footer{
|
|
287
|
+
background-color: var(--background-color);
|
|
288
|
+
color: var(--text-color);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.themed-modal .uploaded-files-card,
|
|
292
|
+
.themed-modal .uploaded-files-table {
|
|
293
|
+
background-color: var(--background-color);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.themed-modal .uploaded-files-table {
|
|
297
|
+
color: var(--text-color);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.themed-modal .uploaded-files-table .uploaded-files-header {
|
|
301
|
+
color: var(--text-color);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.themed-modal .uploaded-files-table .uploaded-file-good{
|
|
305
|
+
color: var(--text-color);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.themed-modal .uploaded-files-table .uploaded-file-bad{
|
|
309
|
+
color: #b92629;
|
|
310
|
+
text-decoration: line-through;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* =========================
|
|
314
|
+
Scenario page specifics
|
|
315
|
+
========================= */
|
|
316
|
+
|
|
317
|
+
.scenario-multi-btn-created { /* process */
|
|
318
|
+
background-color: #1b9e08;
|
|
319
|
+
border: 0;
|
|
320
|
+
color: #FFFFFF;
|
|
321
|
+
min-width: 80px;
|
|
322
|
+
pointer-events: all;
|
|
323
|
+
transition: background-color 0.2s ease-in-out;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.scenario-multi-btn-created:hover { /* process */
|
|
327
|
+
background-color: #105906;
|
|
328
|
+
color: #FFFFFF;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
.scenario-multi-btn-completed { /* refresh */
|
|
333
|
+
background-color: #4487d5;
|
|
334
|
+
border: 0;
|
|
335
|
+
color: #FFFFFF;
|
|
336
|
+
min-width: 80px;
|
|
337
|
+
pointer-events: all;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.scenario-multi-btn-completed:hover, .scenario-multi-btn-completed:focus {
|
|
341
|
+
background-color: #2b5688;
|
|
342
|
+
color: #FFFFFF;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.scenario-multi-btn-queued, .scenario-delete-btn-created, .scenario-delete-btn-completed { /* cancel */
|
|
346
|
+
background-color: #bd1414;
|
|
347
|
+
border: 0;
|
|
348
|
+
color: #FFFFFF;
|
|
349
|
+
min-width: 80px;
|
|
350
|
+
pointer-events: all;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.scenario-multi-btn-queued:hover, .scenario-multi-btn-queued:focus,
|
|
354
|
+
.scenario-delete-btn-created:hover, .scenario-delete-btn-created:focus,
|
|
355
|
+
.scenario-delete-btn-completed:hover, .scenario-delete-btn-completed:focus {
|
|
356
|
+
background-color: #770d0d;
|
|
357
|
+
color: #FFFFFF;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.scenario-delete-btn-queued { /* delete */
|
|
361
|
+
background-color: #a14a4a;
|
|
362
|
+
border: 0;
|
|
363
|
+
color: #FFFFFF;
|
|
364
|
+
min-width: 80px;
|
|
365
|
+
pointer-events: none;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
/* =========================
|
|
370
|
+
Compare page (mirrors performance page styles)
|
|
371
|
+
========================= */
|
|
372
|
+
.compare-page {
|
|
373
|
+
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.compare-page .side-by-side-viewer,
|
|
377
|
+
.compare-page .compare-view,
|
|
378
|
+
.compare-page .details-view{
|
|
379
|
+
margin-bottom: 10px;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.compare-page .kpi-cards{
|
|
383
|
+
margin-bottom: 0;
|
|
384
|
+
display: flex;
|
|
385
|
+
flex-wrap: wrap;
|
|
386
|
+
justify-content: flex-start;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.compare-page .kpi-cards .kpi-card-wrapper{
|
|
390
|
+
flex: 1 1 300px;
|
|
391
|
+
width: 400px;
|
|
392
|
+
height: 200px;
|
|
393
|
+
margin: 10px;
|
|
394
|
+
display: flex;
|
|
395
|
+
flex-direction: column;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* details/compare view margin moved into grouped rule above */
|
|
399
|
+
|
|
400
|
+
/* =========================
|
|
401
|
+
Page content min-heights
|
|
402
|
+
========================= */
|
|
403
|
+
.data-page-content {
|
|
404
|
+
min-height: 500px;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.scenario-page-content {
|
|
408
|
+
min-height: 500px;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/* Prevent initial flash of loading spinner */
|
|
412
|
+
.loading-wrapper > div:first-child {
|
|
413
|
+
opacity: 0;
|
|
414
|
+
animation: fadeInSpinner 0.1s ease-in 2s forwards;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
@keyframes fadeInSpinner {
|
|
418
|
+
to {
|
|
419
|
+
opacity: 1;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Custom compare page template for {{ project_name }}.
|
|
3
|
+
|
|
4
|
+
This module defines a custom compare page for side-by-side scenario comparison.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dash import html
|
|
8
|
+
from algomancy_content import BaseComparePage
|
|
9
|
+
from algomancy_scenario import Scenario
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class {{ class_name }}ComparePage(BaseComparePage):
|
|
13
|
+
"""
|
|
14
|
+
Custom compare page implementation for {{ project_name }}.
|
|
15
|
+
|
|
16
|
+
TODO: Customize the compare page layout and behavior.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def create_side_by_side_content(scenario: Scenario, side: str) -> html.Div:
|
|
21
|
+
"""
|
|
22
|
+
Create content for one side of the side-by-side comparison view.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
scenario: The Scenario object to display.
|
|
26
|
+
side: Identifier for which side ("left" or "right").
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
A Dash html.Div containing the scenario content.
|
|
30
|
+
|
|
31
|
+
TODO: Customize the side-by-side scenario display.
|
|
32
|
+
"""
|
|
33
|
+
return html.Div(
|
|
34
|
+
[
|
|
35
|
+
html.H3(f"{scenario.tag} ({side.capitalize()})"),
|
|
36
|
+
html.P(f"Scenario ID: {scenario.id}"),
|
|
37
|
+
html.P(f"Status: {scenario.status}"),
|
|
38
|
+
# TODO: Add scenario-specific content (parameters, results, charts)
|
|
39
|
+
],
|
|
40
|
+
className=f"compare-side-{side}",
|
|
41
|
+
style={"padding": "15px", "border": "1px solid #ddd"},
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def create_compare_section(left: Scenario, right: Scenario) -> html.Div:
|
|
46
|
+
"""
|
|
47
|
+
Create a consolidated comparison section for both scenarios.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
left: The left scenario.
|
|
51
|
+
right: The right scenario.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
A Dash html.Div containing the comparison content.
|
|
55
|
+
|
|
56
|
+
TODO: Implement comparison logic and visualizations.
|
|
57
|
+
"""
|
|
58
|
+
return html.Div(
|
|
59
|
+
[
|
|
60
|
+
html.H3("Scenario Comparison"),
|
|
61
|
+
html.Table(
|
|
62
|
+
[
|
|
63
|
+
html.Tr([
|
|
64
|
+
html.Th("Metric"),
|
|
65
|
+
html.Th(left.tag),
|
|
66
|
+
html.Th(right.tag),
|
|
67
|
+
]),
|
|
68
|
+
html.Tr([
|
|
69
|
+
html.Td("Status"),
|
|
70
|
+
html.Td(left.status),
|
|
71
|
+
html.Td(right.status),
|
|
72
|
+
]),
|
|
73
|
+
# TODO: Add more comparison metrics
|
|
74
|
+
],
|
|
75
|
+
style={"width": "100%", "borderCollapse": "collapse"},
|
|
76
|
+
),
|
|
77
|
+
],
|
|
78
|
+
style={"padding": "20px"},
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def create_details_section(left: Scenario, right: Scenario) -> html.Div:
|
|
83
|
+
"""
|
|
84
|
+
Create a detailed analysis section comparing both scenarios.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
left: The left scenario.
|
|
88
|
+
right: The right scenario.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
A Dash html.Div containing the detailed comparison content.
|
|
92
|
+
|
|
93
|
+
TODO: Implement detailed analysis and insights.
|
|
94
|
+
"""
|
|
95
|
+
return html.Div(
|
|
96
|
+
[
|
|
97
|
+
html.H3("Detailed Analysis"),
|
|
98
|
+
html.Div(
|
|
99
|
+
[
|
|
100
|
+
html.H4("Key Differences"),
|
|
101
|
+
html.Ul(
|
|
102
|
+
[
|
|
103
|
+
html.Li(f"Left scenario: {left.tag}"),
|
|
104
|
+
html.Li(f"Right scenario: {right.tag}"),
|
|
105
|
+
# TODO: Add detailed difference analysis
|
|
106
|
+
]
|
|
107
|
+
),
|
|
108
|
+
]
|
|
109
|
+
),
|
|
110
|
+
html.Hr(),
|
|
111
|
+
html.Div(
|
|
112
|
+
[
|
|
113
|
+
html.H4("Performance Analysis"),
|
|
114
|
+
html.P("TODO: Add charts and statistical comparisons"),
|
|
115
|
+
# TODO: Add graphs, KPI comparisons, etc.
|
|
116
|
+
]
|
|
117
|
+
),
|
|
118
|
+
],
|
|
119
|
+
style={"padding": "20px"},
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
def register_callbacks() -> None:
|
|
124
|
+
"""
|
|
125
|
+
Register Dash callbacks for this page if needed.
|
|
126
|
+
|
|
127
|
+
TODO: Add any interactive behavior for the compare page.
|
|
128
|
+
"""
|
|
129
|
+
# Example:
|
|
130
|
+
# @app.callback(...)
|
|
131
|
+
# def compare_scenarios(...):
|
|
132
|
+
# pass
|
|
133
|
+
pass
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Custom data page template for {{ project_name }}.
|
|
3
|
+
|
|
4
|
+
This module defines a custom data page for viewing and managing raw data.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dash import html
|
|
8
|
+
from algomancy_content import BaseDataPage
|
|
9
|
+
from algomancy_data import DataSource
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class {{ class_name }}DataPage(BaseDataPage):
|
|
13
|
+
"""
|
|
14
|
+
Custom data page implementation for {{ project_name }}.
|
|
15
|
+
|
|
16
|
+
TODO: Customize the data page layout and behavior.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def create_content(data: DataSource) -> html.Div:
|
|
21
|
+
"""
|
|
22
|
+
Define the layout and content of the data page based on the provided data.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
data: The DataSource object containing the data to display.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
A Dash html.Div containing the page content.
|
|
29
|
+
|
|
30
|
+
TODO: Implement your custom data page layout.
|
|
31
|
+
"""
|
|
32
|
+
# Check if data has tables attribute
|
|
33
|
+
data_info = []
|
|
34
|
+
if hasattr(data, "tables") and isinstance(data.tables, dict):
|
|
35
|
+
data_info.append(html.H3("Available Data Tables"))
|
|
36
|
+
table_list = []
|
|
37
|
+
for key, table in data.tables.items():
|
|
38
|
+
table_list.append(
|
|
39
|
+
html.Li(
|
|
40
|
+
f"{key}: {len(table)} rows × {len(table.columns)} columns"
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
data_info.append(html.Ul(table_list))
|
|
44
|
+
else:
|
|
45
|
+
data_info.append(html.P("Data structure information not available."))
|
|
46
|
+
|
|
47
|
+
return html.Div(
|
|
48
|
+
[
|
|
49
|
+
html.H1("{{ project_name }} Data View"),
|
|
50
|
+
html.P(
|
|
51
|
+
"This page displays the raw data loaded into the application."
|
|
52
|
+
),
|
|
53
|
+
html.Hr(),
|
|
54
|
+
html.Div(data_info),
|
|
55
|
+
html.Hr(),
|
|
56
|
+
html.Div(
|
|
57
|
+
[
|
|
58
|
+
html.H3("Data Management Features"),
|
|
59
|
+
html.Ul(
|
|
60
|
+
[
|
|
61
|
+
html.Li("View and filter raw data tables"),
|
|
62
|
+
html.Li("Export data to various formats"),
|
|
63
|
+
html.Li("Validate data quality and completeness"),
|
|
64
|
+
html.Li("Customize this page in src/pages/data_page.py"),
|
|
65
|
+
]
|
|
66
|
+
),
|
|
67
|
+
]
|
|
68
|
+
),
|
|
69
|
+
# TODO: Add data table components (e.g., dash_table.DataTable), filters, export buttons
|
|
70
|
+
# Example:
|
|
71
|
+
# html.Div([
|
|
72
|
+
# dash_table.DataTable(
|
|
73
|
+
# id='data-table',
|
|
74
|
+
# columns=[{"name": i, "id": i} for i in data.tables['your_table'].columns],
|
|
75
|
+
# data=data.tables['your_table'].to_dict('records'),
|
|
76
|
+
# page_size=10,
|
|
77
|
+
# )
|
|
78
|
+
# ])
|
|
79
|
+
],
|
|
80
|
+
style={"padding": "20px"},
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def register_callbacks() -> None:
|
|
85
|
+
"""
|
|
86
|
+
Register Dash callbacks for this page if needed.
|
|
87
|
+
|
|
88
|
+
TODO: Add any interactive behavior for the data page.
|
|
89
|
+
"""
|
|
90
|
+
# Example:
|
|
91
|
+
# @app.callback(...)
|
|
92
|
+
# def filter_data(...):
|
|
93
|
+
# pass
|
|
94
|
+
pass
|