@@ -115,13 +115,13 @@ def change_password_handler(old_password, new_password):
115115def load_user_settings ():
116116 """Load user settings from user_settings.toml"""
117117 settings_file = os .path .join (settings .APP_FOLDER , "user_settings.toml" )
118- default_settings = {"selected_theme" : "AlienDark " }
118+ default_settings = {"selected_theme" : "Modern " }
119119
120120 if not os .path .exists (settings_file ):
121121 # Create default settings file
122122 try :
123123 with open (settings_file , "w" ) as fp :
124- fp .write ('selected_theme = "AlienDark "\n ' )
124+ fp .write ('selected_theme = "Modern "\n ' )
125125 return default_settings
126126 except Exception :
127127 return default_settings
@@ -179,11 +179,11 @@ def normalize_selected_theme(selected_theme, available_themes=None):
179179 themes = available_themes if available_themes is not None else get_available_themes ()
180180 if selected_theme and selected_theme in themes :
181181 return selected_theme
182- if "AlienDark " in themes :
183- return "AlienDark "
182+ if "Modern " in themes :
183+ return "Modern "
184184 if themes :
185185 return themes [0 ]
186- return "AlienDark "
186+ return "Modern "
187187
188188
189189def _safe_name (value ):
@@ -233,6 +233,26 @@ def build_theme_partials(selected_theme, partial_names):
233233 }
234234
235235
236+ def get_system_info_payload ():
237+ """Collect system and loaded module version information."""
238+ os_info = f"{ platform .system ()} { platform .release ()} "
239+ items = [
240+ {"name" : "os" , "version" : os_info },
241+ {"name" : "py4web" , "version" : __version__ },
242+ {"name" : "python" , "version" : sys .version },
243+ ]
244+ for module in sorted (sys .modules ):
245+ if "." in module :
246+ continue
247+ try :
248+ imported = __import__ (module )
249+ if "__version__" in dir (imported ):
250+ items .append ({"name" : module , "version" : imported .__version__ })
251+ except ImportError :
252+ pass
253+ return items
254+
255+
236256session = Session ()
237257T = Translator (settings .T_FOLDER )
238258authenticated = ActionFactory (Logged (session ))
@@ -252,7 +272,7 @@ def index():
252272 themes = get_available_themes ()
253273 user_settings = load_user_settings ()
254274 selected_theme = normalize_selected_theme (
255- user_settings .get ("selected_theme" , "AlienDark " ), themes
275+ user_settings .get ("selected_theme" , "Modern " ), themes
256276 )
257277 theme_partials = build_theme_partials (selected_theme , ["index_header_actions" ])
258278
@@ -315,26 +335,46 @@ def save_theme():
315335 user_settings ["selected_theme" ] = theme
316336 return save_user_settings (user_settings )
317337
338+ @action ("settings" )
339+ @action .uses (Logged (session ), "settings.html" )
340+ @catch_errors
341+ def settings_page ():
342+ themes = get_available_themes ()
343+ user_settings = load_user_settings ()
344+ selected_theme = normalize_selected_theme (
345+ user_settings .get ("selected_theme" , "Modern" ), themes
346+ )
347+ return dict (
348+ themes = themes ,
349+ selected_theme = selected_theme ,
350+ message = "" ,
351+ message_type = "" ,
352+ )
353+
318354 @action ("tickets/search" )
319355 @action .uses (Logged (session ), "dbadmin.html" )
320356 def dbadmin ():
321357 db = error_logger .database_logger .db
322358 themes = get_available_themes ()
323359 user_settings = load_user_settings ()
324360 selected_theme = normalize_selected_theme (
325- user_settings .get ("selected_theme" , "AlienDark " ), themes
361+ user_settings .get ("selected_theme" , "Modern " ), themes
326362 )
327363 theme_partials = build_theme_partials (
328364 selected_theme , ["dbadmin_nav" , "dbadmin_footer_back" ]
329365 )
366+ filter_app = request .query .get ("app_name" , "" ).strip ()
330367
331368 def make_grid ():
332369 make_safe (db )
333370 table = db .py4web_error
371+ query = (table .app_name == filter_app ) if filter_app else table
334372 columns = [field for field in table if not field .name == "snapshot" ]
335373 return Grid (
336- table ,
374+ query ,
337375 columns = columns ,
376+ search_queries = None ,
377+ create = False ,
338378 details = False ,
339379 editable = False ,
340380 pre_action_buttons = [
@@ -348,7 +388,7 @@ def make_grid():
348388
349389 grid = action .uses (db )(make_grid )()
350390 return dict (
351- app_name = "" ,
391+ app_name = filter_app ,
352392 table_name = "py4web_error" ,
353393 grid = grid ,
354394 themes = themes ,
@@ -362,7 +402,7 @@ def dbadmin(app_name, db_name, table_name):
362402 themes = get_available_themes ()
363403 user_settings = load_user_settings ()
364404 selected_theme = normalize_selected_theme (
365- user_settings .get ("selected_theme" , "AlienDark " ), themes
405+ user_settings .get ("selected_theme" , "Modern " ), themes
366406 )
367407 theme_partials = build_theme_partials (
368408 selected_theme , ["dbadmin_nav" , "dbadmin_footer_back" ]
@@ -415,22 +455,21 @@ def make_grid():
415455 @session_secured
416456 @catch_errors
417457 def info ():
418- # Start with OS information
419- os_info = f"{ platform .system ()} { platform .release ()} "
420- vars = [
421- {"name" : "os" , "version" : os_info },
422- {"name" : "py4web" , "version" : __version__ },
423- {"name" : "python" , "version" : sys .version }
424- ]
425- for module in sorted (sys .modules ):
426- if not "." in module :
427- try :
428- m = __import__ (module )
429- if "__version__" in dir (m ):
430- vars .append ({"name" : module , "version" : m .__version__ })
431- except ImportError :
432- pass
433- return {"status" : "success" , "payload" : vars }
458+ return {"status" : "success" , "payload" : get_system_info_payload ()}
459+
460+ @action ("system_info" )
461+ @action .uses (Logged (session ), "system_info.html" )
462+ def system_info_page ():
463+ themes = get_available_themes ()
464+ user_settings = load_user_settings ()
465+ selected_theme = normalize_selected_theme (
466+ user_settings .get ("selected_theme" , "Modern" ), themes
467+ )
468+ return dict (
469+ info_items = get_system_info_payload (),
470+ themes = themes ,
471+ selected_theme = selected_theme ,
472+ )
434473
435474 @action ("routes" )
436475 @session_secured
@@ -703,7 +742,21 @@ def packed(path):
703742 def tickets ():
704743 """Returns most recent tickets grouped by path+error"""
705744 tickets = safely (error_logger .database_logger .get ) if MODE != "DEMO" else None
706- return {"payload" : tickets or [], "status" : "success" }
745+ total_count = 0
746+ if MODE != "DEMO" :
747+ total_count = safely (
748+ lambda : error_logger .database_logger .db (
749+ error_logger .database_logger .db .py4web_error
750+ ).count ()
751+ ) or 0
752+ return {"payload" : tickets or [], "total_count" : total_count , "status" : "success" }
753+
754+ @action ("tickets/delete_all" , method = ["POST" ])
755+ @action .uses (Logged (session ))
756+ def delete_all_tickets ():
757+ if MODE != "demo" :
758+ safely (error_logger .database_logger .clear )
759+ redirect (URL ("tickets/search" ))
707760
708761 @action ("clear" )
709762 @session_secured
@@ -718,17 +771,21 @@ def error_ticket(ticket_uuid):
718771 themes = get_available_themes ()
719772 user_settings = load_user_settings ()
720773 selected_theme = normalize_selected_theme (
721- user_settings .get ("selected_theme" , "AlienDark" ), themes
774+ user_settings .get ("selected_theme" , "Modern" ), themes
775+ )
776+ theme_partials = build_theme_partials (
777+ selected_theme , ["dbadmin_nav" , "dbadmin_footer_back" ]
722778 )
723779 if MODE != "demo" :
724780 return dict (
725781 ticket = safely (
726782 lambda : error_logger .database_logger .get (ticket_uuid = ticket_uuid )
727783 ),
728- selected_theme = selected_theme
784+ selected_theme = selected_theme ,
785+ theme_partials = theme_partials ,
729786 )
730787 else :
731- return dict (ticket = None , selected_theme = selected_theme )
788+ return dict (ticket = None , selected_theme = selected_theme , theme_partials = theme_partials )
732789
733790 @action ("rest/<path:path>" , method = ["GET" , "POST" , "PUT" , "DELETE" ])
734791 @session_secured
@@ -921,8 +978,16 @@ def new_app():
921978 def gitlog (project ):
922979 themes = get_available_themes ()
923980 user_settings = load_user_settings ()
981+ selected_theme = normalize_selected_theme (
982+ user_settings .get ("selected_theme" , "Modern" ), themes
983+ )
924984 if not is_git_repo (os .path .join (FOLDER , project )):
925- return "Project is not a GIT repo"
985+ return dict (
986+ status = "error" ,
987+ error = "Project is not a GIT repo" ,
988+ project = project ,
989+ selected_theme = selected_theme ,
990+ )
926991 branches = get_branches (cwd = os .path .join (FOLDER , project ))
927992 commits = get_commits (cwd = os .path .join (FOLDER , project ))
928993 return dict (
@@ -931,9 +996,7 @@ def gitlog(project):
931996 checkout = checkout ,
932997 project = project ,
933998 branches = branches ,
934- selected_theme = normalize_selected_theme (
935- user_settings .get ("selected_theme" , "AlienDark" ), themes
936- ),
999+ selected_theme = selected_theme ,
9371000 )
9381001
9391002 @authenticated .callback ()
@@ -987,7 +1050,7 @@ def translations(name):
9871050 return dict (
9881051 languages = t .languages ,
9891052 selected_theme = normalize_selected_theme (
990- user_settings .get ("selected_theme" , "AlienDark " ), themes
1053+ user_settings .get ("selected_theme" , "Modern " ), themes
9911054 ),
9921055 )
9931056
0 commit comments