algomancy-gui 0.3.16__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 (46) hide show
  1. algomancy_gui/__init__.py +0 -0
  2. algomancy_gui/admin_page/__init__.py +1 -0
  3. algomancy_gui/admin_page/admin.py +362 -0
  4. algomancy_gui/admin_page/sessions.py +57 -0
  5. algomancy_gui/appconfiguration.py +291 -0
  6. algomancy_gui/compare_page/__init__.py +1 -0
  7. algomancy_gui/compare_page/compare.py +360 -0
  8. algomancy_gui/compare_page/kpicard.py +236 -0
  9. algomancy_gui/compare_page/scenarioselector.py +99 -0
  10. algomancy_gui/componentids.py +177 -0
  11. algomancy_gui/contentregistry.py +167 -0
  12. algomancy_gui/cqmloader.py +58 -0
  13. algomancy_gui/data_page/__init__.py +1 -0
  14. algomancy_gui/data_page/data.py +77 -0
  15. algomancy_gui/data_page/datamanagementdeletemodal.py +260 -0
  16. algomancy_gui/data_page/datamanagementderivemodal.py +201 -0
  17. algomancy_gui/data_page/datamanagementdownloadmodal.py +193 -0
  18. algomancy_gui/data_page/datamanagementimportmodal.py +438 -0
  19. algomancy_gui/data_page/datamanagementsavemodal.py +191 -0
  20. algomancy_gui/data_page/datamanagementtopbar.py +123 -0
  21. algomancy_gui/data_page/datamanagementuploadmodal.py +366 -0
  22. algomancy_gui/data_page/dialogcallbacks.py +51 -0
  23. algomancy_gui/data_page/filenamematcher.py +109 -0
  24. algomancy_gui/defaultloader.py +36 -0
  25. algomancy_gui/gui_launcher.py +183 -0
  26. algomancy_gui/home_page/__init__.py +1 -0
  27. algomancy_gui/home_page/home.py +16 -0
  28. algomancy_gui/layout.py +199 -0
  29. algomancy_gui/layouthelpers.py +30 -0
  30. algomancy_gui/managergetters.py +28 -0
  31. algomancy_gui/overview_page/__init__.py +1 -0
  32. algomancy_gui/overview_page/overview.py +20 -0
  33. algomancy_gui/py.typed +0 -0
  34. algomancy_gui/scenario_page/__init__.py +0 -0
  35. algomancy_gui/scenario_page/delete_confirmation.py +29 -0
  36. algomancy_gui/scenario_page/new_scenario_creator.py +104 -0
  37. algomancy_gui/scenario_page/new_scenario_parameters_window.py +154 -0
  38. algomancy_gui/scenario_page/scenario_badge.py +36 -0
  39. algomancy_gui/scenario_page/scenario_cards.py +119 -0
  40. algomancy_gui/scenario_page/scenarios.py +596 -0
  41. algomancy_gui/sessionmanager.py +168 -0
  42. algomancy_gui/settingsmanager.py +43 -0
  43. algomancy_gui/stylingconfigurator.py +740 -0
  44. algomancy_gui-0.3.16.dist-info/METADATA +71 -0
  45. algomancy_gui-0.3.16.dist-info/RECORD +46 -0
  46. algomancy_gui-0.3.16.dist-info/WHEEL +4 -0
File without changes
@@ -0,0 +1 @@
1
+ # This file is intentionally left empty to make the directory a Python package.
@@ -0,0 +1,362 @@
1
+ from dash import (
2
+ Output,
3
+ Input,
4
+ State,
5
+ callback,
6
+ get_app,
7
+ html,
8
+ dcc,
9
+ callback_context,
10
+ no_update,
11
+ )
12
+ import dash_bootstrap_components as dbc
13
+
14
+ from .sessions import create_new_session_window
15
+ from ..componentids import (
16
+ ADMIN_NEW_SESSION,
17
+ ACTIVE_SESSION,
18
+ ADMIN_SELECT_SESSION,
19
+ ADMIN_LOG_WINDOW,
20
+ ADMIN_LOG_INTERVAL,
21
+ ADMIN_LOG_FILTER,
22
+ ADMIN_PAGE,
23
+ ADMIN_COPY_SESSION,
24
+ SESSION_CREATOR_MODAL,
25
+ NEW_SESSION_BUTTON,
26
+ NEW_SESSION_NAME,
27
+ HOW_TO_CREATE_NEW_SESSION,
28
+ )
29
+ from algomancy_utils.logger import Logger, MessageStatus
30
+ from algomancy_gui.managergetters import get_manager
31
+ from ..sessionmanager import SessionManager
32
+
33
+
34
+ def admin_page():
35
+ """Returns the HTML page layout which the callbacks use to create the page."""
36
+ return html.Div(id=ADMIN_PAGE)
37
+
38
+
39
+ def admin_header():
40
+ """Creates the header for the admin page."""
41
+ return [
42
+ html.H1("Admin"),
43
+ html.P(
44
+ "This is where settings are managed and an overview of the jobs is provided."
45
+ ),
46
+ html.Hr(),
47
+ ]
48
+
49
+
50
+ def admin_sessions(session_id):
51
+ """Creates a page-section where sessions can be selected and created."""
52
+
53
+ if not get_app().server.use_sessions:
54
+ return []
55
+
56
+ session_manager: SessionManager = get_app().server.session_manager
57
+ sessions = session_manager.sessions_names
58
+
59
+ return [
60
+ html.H3("Sessions"),
61
+ dcc.Store(
62
+ id=HOW_TO_CREATE_NEW_SESSION,
63
+ data=False,
64
+ ),
65
+ dbc.Row(
66
+ [
67
+ dbc.Col(
68
+ [
69
+ html.Label("Select session:"),
70
+ dcc.Dropdown(
71
+ id=ADMIN_SELECT_SESSION,
72
+ options=[{"label": s, "value": s} for s in sessions],
73
+ value=session_id,
74
+ clearable=False,
75
+ ),
76
+ ],
77
+ width="auto",
78
+ className="d-flex flex-column justify-content-end",
79
+ style={"minWidth": "250px"},
80
+ ),
81
+ # New Session button
82
+ dbc.Col(
83
+ dbc.Button(
84
+ "New Session",
85
+ id=ADMIN_NEW_SESSION,
86
+ className="ms-2 w-100",
87
+ style={
88
+ "backgroundColor": "var(--theme-secondary)",
89
+ "color": "var(--text-selected)",
90
+ "border": "none",
91
+ "height": "38px",
92
+ },
93
+ ),
94
+ width="auto",
95
+ className="d-flex align-items-end",
96
+ ),
97
+ # Copy Session button
98
+ dbc.Col(
99
+ dbc.Button(
100
+ "Copy Session",
101
+ id=ADMIN_COPY_SESSION,
102
+ className="ms-2 w-100",
103
+ style={
104
+ "backgroundColor": "var(--theme-secondary)",
105
+ "color": "var(--text-selected)",
106
+ "border": "none",
107
+ "height": "38px%",
108
+ },
109
+ ),
110
+ width="auto",
111
+ className="d-flex align-items-end",
112
+ ),
113
+ ],
114
+ className="g-1",
115
+ ),
116
+ html.Hr(),
117
+ ]
118
+
119
+
120
+ def admin_system_logs():
121
+ """Creates a page-section where system logs are displayed."""
122
+ return [
123
+ html.H3("System Logs"),
124
+ html.P("This window displays logging messages from the scenario manager."),
125
+ # Log filter dropdown
126
+ dbc.Row(
127
+ [
128
+ dbc.Col(
129
+ [
130
+ html.Label("Filter by status:"),
131
+ dcc.Dropdown(
132
+ id=ADMIN_LOG_FILTER,
133
+ options=[
134
+ {"label": "All", "value": "ALL"},
135
+ {"label": "Info", "value": "INFO"},
136
+ {"label": "Success", "value": "SUCCESS"},
137
+ {"label": "Warning", "value": "WARNING"},
138
+ {"label": "Error", "value": "ERROR"},
139
+ ],
140
+ value="ALL",
141
+ clearable=False,
142
+ ),
143
+ ],
144
+ width=3,
145
+ )
146
+ ],
147
+ className="mb-3",
148
+ ),
149
+ # Scrollable log window
150
+ dbc.Card(
151
+ [
152
+ dbc.CardBody(
153
+ [html.Div(id=ADMIN_LOG_WINDOW, className="admin-log-window")]
154
+ )
155
+ ],
156
+ className="admin-log-card mb-4",
157
+ ),
158
+ # Interval for updating logs
159
+ dcc.Interval(
160
+ id=ADMIN_LOG_INTERVAL,
161
+ interval=2000, # 2 seconds
162
+ n_intervals=0,
163
+ ),
164
+ ]
165
+
166
+
167
+ @callback(
168
+ Output(ADMIN_PAGE, "children"),
169
+ Input(ACTIVE_SESSION, "data"),
170
+ )
171
+ def create_admin_page(session_id):
172
+ """
173
+ Creates the admin page layout.
174
+
175
+ from ..componentids import ADMIN_LOG_WINDOW, ADMIN_LOG_FILTER, ADMIN_LOG_INTERVAL
176
+ from algomancy_utils import MessageStatus
177
+ This page provides settings management, an overview of system jobs,
178
+ and a scrollable window displaying logging messages from the scenario_manager.
179
+
180
+ Returns:
181
+ List: to fill the Dash HTML component representing the admin page
182
+ """
183
+ admin_content = (
184
+ admin_header()
185
+ + admin_sessions(session_id)
186
+ + admin_system_logs()
187
+ + [create_new_session_window()]
188
+ )
189
+ return admin_content
190
+
191
+
192
+ @callback(
193
+ Output(ACTIVE_SESSION, "data"),
194
+ Input(ADMIN_SELECT_SESSION, "value"),
195
+ )
196
+ def load_session(session_id):
197
+ """Updates the active session when a new session is selected using the dropdown."""
198
+ return session_id
199
+
200
+
201
+ @callback(
202
+ Output(ADMIN_LOG_WINDOW, "children"),
203
+ [Input(ADMIN_LOG_INTERVAL, "n_intervals"), Input(ADMIN_LOG_FILTER, "value")],
204
+ )
205
+ def update_log_window(n_intervals, filter_value):
206
+ """
207
+ Updates the log window with messages from the session_manager's logger.
208
+
209
+ Args:
210
+ n_intervals (int): Number of intervals elapsed (from dcc.Interval)
211
+ filter_value (str): Selected filter value for log messages
212
+ session_id (str): ID of active session
213
+
214
+ Returns:
215
+ list: List of HTML components representing log messages
216
+ """
217
+ # Get the scenario manager
218
+
219
+ manager = get_manager(get_app().server)
220
+
221
+ # Get the logger from the session manager
222
+ logger: Logger = manager.logger
223
+
224
+ # Get logs based on filter
225
+ if filter_value == "ALL":
226
+ logs = logger.get_logs()
227
+ else:
228
+ # Convert string filter value to MessageStatus enum
229
+ status_filter = MessageStatus[filter_value]
230
+ logs = logger.get_logs(status_filter=status_filter)
231
+
232
+ # Format logs for display
233
+ log_components = []
234
+
235
+ for log in logs:
236
+ # Determine style based on log status
237
+ style = {
238
+ "padding": "5px",
239
+ "borderBottom": "1px solid #ddd",
240
+ "fontSize": "0.9em",
241
+ }
242
+
243
+ # Add color based on status
244
+ if log.status == MessageStatus.INFO:
245
+ style["color"] = "#0d6efd" # blue
246
+ elif log.status == MessageStatus.SUCCESS:
247
+ style["color"] = "#198754" # green
248
+ elif log.status == MessageStatus.WARNING:
249
+ style["color"] = "#fd7e14" # orange
250
+ elif log.status == MessageStatus.ERROR:
251
+ style["color"] = "#dc3545" # red
252
+
253
+ # Create log entry component
254
+ log_entry = html.Div(
255
+ f"[{log.timestamp.strftime('%Y-%m-%d %H:%M:%S')}] {log.status.name}: {log.message}",
256
+ style=style,
257
+ )
258
+
259
+ log_components.append(log_entry)
260
+
261
+ # Reverse to show newest logs at the top
262
+ log_components.reverse()
263
+
264
+ return log_components
265
+
266
+
267
+ @callback(
268
+ Output(NEW_SESSION_BUTTON, "disabled"),
269
+ Output(f"{NEW_SESSION_BUTTON}-tooltip-container", "children"),
270
+ Input(NEW_SESSION_NAME, "value"),
271
+ )
272
+ def validate_session_name(session_name: str):
273
+ """
274
+ Validates the session name before creating a new session.
275
+ The new session button is disabled if the session name is invalid.
276
+ A name is considered invalid if it is empty or already exists.
277
+ A tooltip is displayed if the session name is invalid with a short explanation.
278
+ """
279
+ if not get_app().server.use_sessions:
280
+ return no_update, no_update
281
+ existing_names = get_app().server.session_manager.sessions_names
282
+
283
+ if not session_name:
284
+ tooltip = dbc.Tooltip(
285
+ "Session name cannot be empty.",
286
+ target=f"{NEW_SESSION_BUTTON}-wrapper",
287
+ placement="top",
288
+ id=f"{NEW_SESSION_BUTTON}-tooltip",
289
+ )
290
+ return True, tooltip
291
+
292
+ if session_name in existing_names:
293
+ tooltip = dbc.Tooltip(
294
+ "Session name already exists.",
295
+ target=f"{NEW_SESSION_BUTTON}-wrapper",
296
+ placement="top",
297
+ id=f"{NEW_SESSION_BUTTON}-tooltip",
298
+ )
299
+ return True, tooltip
300
+
301
+ # valid -> enable button and remove tooltip from DOM
302
+ return False, None
303
+
304
+
305
+ @callback(
306
+ [
307
+ Output(SESSION_CREATOR_MODAL, "is_open"),
308
+ Output(NEW_SESSION_NAME, "value"),
309
+ Output(HOW_TO_CREATE_NEW_SESSION, "data"),
310
+ Output(ADMIN_SELECT_SESSION, "value"),
311
+ ],
312
+ [
313
+ Input(ADMIN_NEW_SESSION, "n_clicks"),
314
+ Input(ADMIN_COPY_SESSION, "n_clicks"),
315
+ Input(NEW_SESSION_BUTTON, "n_clicks"),
316
+ Input(f"{NEW_SESSION_BUTTON}-cancel", "n_clicks"),
317
+ ],
318
+ [
319
+ State(NEW_SESSION_NAME, "value"),
320
+ State(SESSION_CREATOR_MODAL, "is_open"),
321
+ State(ACTIVE_SESSION, "data"),
322
+ State(HOW_TO_CREATE_NEW_SESSION, "data"),
323
+ ],
324
+ prevent_initial_call=True,
325
+ )
326
+ def toggle_session_creator_modal(
327
+ open_new_click,
328
+ open_copy_click,
329
+ confirm_clicked,
330
+ cancel_click,
331
+ new_session_name: str,
332
+ is_open: bool,
333
+ session_id: str,
334
+ copy_session: bool,
335
+ ):
336
+ """
337
+ Handles all buttons that have to do with creating a new session.
338
+ This is the opening of the model via the new or copy session buttons,
339
+ the creation of the new session, and the closing of the modal.
340
+
341
+ Coping a session and creating a new session opens the same modal.
342
+ Therefore, the information of the button which is clicked is stored.
343
+ """
344
+ ctx = callback_context
345
+ if not ctx.triggered:
346
+ return no_update, no_update, no_update, no_update
347
+ triggered_id = ctx.triggered[0]["prop_id"].split(".")[0]
348
+ if triggered_id == ADMIN_NEW_SESSION and not is_open:
349
+ return True, "", False, no_update
350
+ if triggered_id == ADMIN_COPY_SESSION and not is_open:
351
+ return True, "", True, no_update
352
+ if triggered_id == NEW_SESSION_BUTTON and is_open:
353
+ session_manager: SessionManager = get_app().server.session_manager
354
+ if copy_session:
355
+ session_manager.copy_session(session_id, new_session_name)
356
+ else:
357
+ session_manager.create_new_session(new_session_name)
358
+
359
+ return False, "", no_update, new_session_name
360
+ if triggered_id == f"{NEW_SESSION_BUTTON}-cancel":
361
+ return False, "", no_update, no_update
362
+ return is_open, "", no_update, no_update
@@ -0,0 +1,57 @@
1
+ import dash_bootstrap_components as dbc
2
+ from dash import get_app, html
3
+
4
+ from ..componentids import (
5
+ NEW_SESSION_BUTTON,
6
+ SESSION_CREATOR_MODAL,
7
+ NEW_SESSION_NAME,
8
+ )
9
+ from ..stylingconfigurator import StylingConfigurator
10
+
11
+
12
+ def create_new_session_window() -> dbc.Modal:
13
+ """Creates the modal for creating a new session.
14
+
15
+ Coping a session and creating a new session opens the same modal.
16
+ Therefore, the information of the button which is clicked is stored.
17
+ """
18
+ sc: StylingConfigurator = get_app().server.styling_config
19
+ window = dbc.Modal(
20
+ [
21
+ dbc.ModalHeader(dbc.ModalTitle("Create New Session"), close_button=False),
22
+ dbc.ModalBody(
23
+ [
24
+ dbc.Label("Session name:"),
25
+ dbc.Input(id=NEW_SESSION_NAME, placeholder="Session name"),
26
+ ]
27
+ ),
28
+ dbc.ModalFooter(
29
+ [
30
+ html.Div(
31
+ dbc.Button(
32
+ "Create",
33
+ id=NEW_SESSION_BUTTON,
34
+ class_name="new-session-confirm-button",
35
+ ),
36
+ id=f"{NEW_SESSION_BUTTON}-wrapper",
37
+ style={"display": "inline-block"},
38
+ ),
39
+ html.Div(id=f"{NEW_SESSION_BUTTON}-tooltip-container"),
40
+ dbc.Button(
41
+ "Cancel",
42
+ id=f"{NEW_SESSION_BUTTON}-cancel",
43
+ class_name="new-session-cancel-button ms-auto",
44
+ ),
45
+ ]
46
+ ),
47
+ ],
48
+ id=SESSION_CREATOR_MODAL,
49
+ is_open=False,
50
+ centered=True,
51
+ class_name="themed-modal",
52
+ style=sc.initiate_theme_colors(),
53
+ keyboard=False,
54
+ backdrop="static",
55
+ )
56
+
57
+ return window