2 Commits

Author SHA1 Message Date
Daniel Dybing
b100533e03 Refactor: Move theme and display settings to a dedicated Settings menu
All checks were successful
Build Tamigo CLI / Build Linux Binary (pull_request) Successful in 53s
Build Tamigo CLI / Build Windows Binary (pull_request) Successful in 44s
2026-03-14 11:53:53 +01:00
Daniel Dybing
d0196fefd0 Fix issue1: Hide zero-hour days by default and add toggle option in menu 2026-03-14 11:52:31 +01:00
2 changed files with 70 additions and 7 deletions

View File

@@ -20,10 +20,13 @@ def load_config():
if os.path.exists(CONFIG_FILE): if os.path.exists(CONFIG_FILE):
try: try:
with open(CONFIG_FILE, "r") as f: with open(CONFIG_FILE, "r") as f:
return json.load(f) config = json.load(f)
if "show_zero_hours" not in config:
config["show_zero_hours"] = False
return config
except: except:
pass pass
return {"theme": "fallout"} # Default to fallout because it's cooler return {"theme": "fallout", "show_zero_hours": False} # Default to fallout and hide zero hours
def save_config(config): def save_config(config):
with open(CONFIG_FILE, "w") as f: with open(CONFIG_FILE, "w") as f:
@@ -190,6 +193,8 @@ def get_worked_days(client, start_date_dt, end_date_dt):
with console.status("[highlight]INITIALIZING DATA RETRIEVAL...[/highlight]" if current_theme_name == "fallout" else "Fetching data..."): with console.status("[highlight]INITIALIZING DATA RETRIEVAL...[/highlight]" if current_theme_name == "fallout" else "Fetching data..."):
data = client.get_employee_actual_shifts(start_date_dt, end_date_dt) data = client.get_employee_actual_shifts(start_date_dt, end_date_dt)
show_zero = current_config.get("show_zero_hours", False)
if data: if data:
work_days = {} work_days = {}
for item in data: for item in data:
@@ -200,6 +205,11 @@ def get_worked_days(client, start_date_dt, end_date_dt):
if hours == 0 and item.get("StartTime") and item.get("EndTime"): if hours == 0 and item.get("StartTime") and item.get("EndTime"):
st, et = parse_tamigo_date(item.get("StartTime")), parse_tamigo_date(item.get("EndTime")) st, et = parse_tamigo_date(item.get("StartTime")), parse_tamigo_date(item.get("EndTime"))
if st and et: hours = (et - st).total_seconds() / 3600.0 if st and et: hours = (et - st).total_seconds() / 3600.0
# Filter zero hours if requested
if hours == 0 and not show_zero:
continue
if (hours > 0 or item.get("CheckInTime") or item.get("ActualStartTime") or item.get("StartTime")) and not item.get("IsAbsent", False): if (hours > 0 or item.get("CheckInTime") or item.get("ActualStartTime") or item.get("StartTime")) and not item.get("IsAbsent", False):
if date_str not in work_days: work_days[date_str] = {"hours": hours, "text": item.get("ActualShiftText") or item.get("ActivityName") or "WORKED"} if date_str not in work_days: work_days[date_str] = {"hours": hours, "text": item.get("ActualShiftText") or item.get("ActivityName") or "WORKED"}
else: work_days[date_str]["hours"] += hours else: work_days[date_str]["hours"] += hours
@@ -305,9 +315,10 @@ def main():
def menu(client): def menu(client):
while True: while True:
settings_text = "SETTINGS" if current_theme_name == "fallout" else "Settings"
choice = questionary.select( choice = questionary.select(
"SELECT ACTION:" if current_theme_name == "fallout" else "What would you like to do?", "SELECT ACTION:" if current_theme_name == "fallout" else "What would you like to do?",
choices=["Calculate actual work days", "Export hours worked", "Show profile info", "Switch UI Theme", "Logout and Exit"], choices=["Calculate actual work days", "Export hours worked", "Show profile info", settings_text, "Logout and Exit"],
style=theme_data["questionary"] style=theme_data["questionary"]
).ask() ).ask()
@@ -316,13 +327,38 @@ def menu(client):
elif choice == "Show profile info": elif choice == "Show profile info":
if client.user_info: console.print_json(data=client.user_info) if client.user_info: console.print_json(data=client.user_info)
else: console.print("[error]ERROR: NO PROFILE INFO.[/error]") else: console.print("[error]ERROR: NO PROFILE INFO.[/error]")
elif choice == "Switch UI Theme": elif choice == settings_text:
new_theme = "normal" if current_theme_name == "fallout" else "fallout" settings_menu()
apply_theme(new_theme)
console.print(f"[success]UI THEME SET TO: {new_theme.upper()}[/success]")
else: else:
console.print("[highlight]SYSTEM SHUTDOWN...[/highlight]" if current_theme_name == "fallout" else "Exiting...") console.print("[highlight]SYSTEM SHUTDOWN...[/highlight]" if current_theme_name == "fallout" else "Exiting...")
break break
def settings_menu():
while True:
show_zero = current_config.get("show_zero_hours", False)
toggle_text = "HIDE ZERO-HOUR DAYS" if current_theme_name == "fallout" else "Hide zero-hour days"
if not show_zero:
toggle_text = "SHOW ZERO-HOUR DAYS" if current_theme_name == "fallout" else "Show zero-hour days"
back_text = "BACK" if current_theme_name == "fallout" else "Back"
choice = questionary.select(
"SELECT SETTING:" if current_theme_name == "fallout" else "Settings:",
choices=["Switch UI Theme", toggle_text, back_text],
style=theme_data["questionary"]
).ask()
if choice == "Switch UI Theme":
new_theme = "normal" if current_theme_name == "fallout" else "fallout"
apply_theme(new_theme)
console.print(f"[success]UI THEME SET TO: {new_theme.upper()}[/success]")
elif choice == toggle_text:
current_config["show_zero_hours"] = not show_zero
save_config(current_config)
state = "VISIBLE" if not show_zero else "HIDDEN"
console.print(f"[success]ZERO-HOUR DAYS ARE NOW {state}.[/success]" if current_theme_name == "fallout" else f"[success]Zero-hour days are now {state.lower()}.[/success]")
else:
break
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@@ -41,6 +41,33 @@ class TestTamigoExport(unittest.TestCase):
self.assertIn("2025-03-10", work_days) self.assertIn("2025-03-10", work_days)
self.assertEqual(work_days["2025-03-10"]["hours"], 8.0) self.assertEqual(work_days["2025-03-10"]["hours"], 8.0)
def test_get_worked_days_zero_hour_filtering(self):
# Mock API response with a 0-hour shift (missing EndTime so it stays 0)
mock_shifts = [
{
"Date": "/Date(1741564800000)/", # 2025-03-10
"StartTime": "2025-03-10T09:00:00Z",
"ActualShiftHours": 0,
"ActualShiftText": "Sick Day",
"IsAbsent": False
}
]
self.client.get_employee_actual_shifts.return_value = mock_shifts
start_date = datetime(2025, 3, 1)
end_date = datetime(2025, 3, 15)
# 1. Test with show_zero_hours = False (Default)
with patch('tamigo.console'), patch('tamigo.current_config', {'show_zero_hours': False}):
work_days = get_worked_days(self.client, start_date, end_date)
self.assertEqual(len(work_days), 0)
# 2. Test with show_zero_hours = True
with patch('tamigo.console'), patch('tamigo.current_config', {'show_zero_hours': True}):
work_days = get_worked_days(self.client, start_date, end_date)
self.assertEqual(len(work_days), 1)
self.assertIn("2025-03-10", work_days)
self.assertEqual(work_days["2025-03-10"]["hours"], 0)
@patch('tamigo.select_date_range') @patch('tamigo.select_date_range')
@patch('tamigo.get_worked_days') @patch('tamigo.get_worked_days')
@patch('questionary.select') @patch('questionary.select')