diff --git a/css/styles.css b/css/styles.css index 5b0ffcc822..4f24befb2f 100644 --- a/css/styles.css +++ b/css/styles.css @@ -5,18 +5,18 @@ table { border-collapse: collapse; margin-bottom: 20px; font-family: Arial, sans-serif; - background-color: #222; /* Dark background color */ - color: #fff; /* Light text color */ + background-color: #222; + color: #fff; font-size: 0.8em; } /* Style the table header */ th { background: none; - text-align: left; + text-align: center; padding: 8px; font-weight: bold; - border-bottom: 2px solid #444; /* Slightly darker border color */ + border-bottom: 2px solid #444; } /* Style the table cells */ @@ -27,17 +27,17 @@ td { /* Alternate row background color */ tr:nth-child(even) { - background-color: #333; /* Darker background for even rows */ + background-color: #333; } /* Hover effect for table rows */ tr:hover { - background-color: #444; /* Slightly lighter background on hover */ + background-color: #444; } /* Style the links */ a { - color: #70b4eb; /* Light color for links */ + color: #70b4eb; text-decoration: none; /* Remove underlines from links */ } @@ -67,36 +67,18 @@ body { } /* Define a class for green-colored icons */ -.green-icon { - color: #9de598; -} - -/* Define a class for red-colored icons (and entire row) */ -.red-icon, .alert { - color: #ff5c3f; -} - -/* Define a class for green-colored icons */ -.green-icon { +td.green-cell { color: #9de598; } -/* Define a class for "pending" cells */ -.red-cell { - background-color: #ff5c3f; -} - -.red-cell>a { - color: black -} - -/* Define a class for "pending" cells */ -.yellow-cell { - background-color: #aa9d26; +.red-cell, .red-cell>a { + color: #ff5c3f; + font-weight: bold; } -.yellow-cell>a { - color: black +.yellow-cell, .yellow-cell>a { + color: #bdad21; + font-weight: bold; } /* Media query for larger viewports */ @@ -111,4 +93,12 @@ body { td { padding: 8px; } +} + +/* Alignment */ +.align-right { + text-align: right; +} +.align-center { + text-align: center; } \ No newline at end of file diff --git a/src/lf_workflow_dash/__init__.py b/src/lf_workflow_dash/__init__.py index b564b856e2..e69de29bb2 100644 --- a/src/lf_workflow_dash/__init__.py +++ b/src/lf_workflow_dash/__init__.py @@ -1,3 +0,0 @@ -from .example_module import greetings, meaning - -__all__ = ["greetings", "meaning"] diff --git a/src/lf_workflow_dash/data_types.py b/src/lf_workflow_dash/data_types.py index db9be733f8..614da92bed 100644 --- a/src/lf_workflow_dash/data_types.py +++ b/src/lf_workflow_dash/data_types.py @@ -14,9 +14,13 @@ class WorkflowElemData: workflow_url: str = "" workflow_status: str = "" display_class: str = "" + icon_class: str = "" last_run_url: str = "" owner: str = "" repo: str = "" + conclusion_time: str = "" + conclusion_date: str = "" + # TODO add is_stale def __init__(self, workflow_name, repo_url, owner, repo): self.workflow_name = workflow_name @@ -25,19 +29,28 @@ def __init__(self, workflow_name, repo_url, owner, repo): self.workflow_url = f"{repo_url}/actions/workflows/{self.workflow_name}" self.workflow_status = "pending" self.display_class = "yellow-cell" + self.icon_class = "fa fa-question-circle" + # TODO add is_stale - def set_status(self, status): + def set_status(self, status, conclusion_time): """Set the completion status of a workflow. This will also update the display class to suit the warning level. + TODO update docstring to add is_stale logic + Args: status (str): how the workflow completed (e.g. "success" or "failure") """ self.workflow_status = status + self.conclusion_time = conclusion_time + # TODO self.is_stale = is_stale + # TODO a nested branch here - first check if it's stale, and only if it isn't, check success if status == "success": - self.display_class = "" + self.display_class = "green-cell" + self.icon_class = "fa fa-check-circle" elif status == "failure": self.display_class = "red-cell" + self.icon_class = "fa fa-times-circle" @dataclass @@ -106,7 +119,7 @@ def read_yaml_file(file_path): all_projects.append(project_data) timezone = pytz.timezone("America/New_York") - last_updated = datetime.now(timezone).strftime("%H:%M %B %d, %Y") + last_updated = datetime.now(timezone).strftime("%H:%M %B %d, %Y (US-NYC)") return { "page_title": page_title, diff --git a/src/lf_workflow_dash/example_module.py b/src/lf_workflow_dash/example_module.py deleted file mode 100644 index f76e8371e9..0000000000 --- a/src/lf_workflow_dash/example_module.py +++ /dev/null @@ -1,23 +0,0 @@ -"""An example module containing simplistic functions.""" - - -def greetings() -> str: - """A friendly greeting for a future friend. - - Returns - ------- - str - A typical greeting from a software engineer. - """ - return "Hello from LINCC-Frameworks!" - - -def meaning() -> int: - """The meaning of life, the universe, and everything. - - Returns - ------- - int - The meaning of life. - """ - return 42 diff --git a/src/lf_workflow_dash/github_request.py b/src/lf_workflow_dash/github_request.py index d275dcd2fd..386a85f2f4 100644 --- a/src/lf_workflow_dash/github_request.py +++ b/src/lf_workflow_dash/github_request.py @@ -1,4 +1,29 @@ +from datetime import datetime import requests +import pytz + +def get_conclusion_time(last_run): + """Get the workflow conclusion time and set the proper timezone + + Args: + last_run (dict): the most recent run of the workflow + """ + timestamp_str = last_run["updated_at"] + + # Parse the timestamp + timestamp = datetime.strptime(timestamp_str, "%Y-%m-%dT%H:%M:%SZ") + + # Define the time zones for UTC and New York + utc_timezone = pytz.timezone("UTC") + ny_timezone = pytz.timezone("America/New_York") + + # Convert the timestamp to New York time + timestamp_ny = timestamp.replace(tzinfo=utc_timezone).astimezone(ny_timezone) + + # Format the timestamp + formatted_timestamp = timestamp_ny.strftime("%H:%M
%m/%d/%y") + + return formatted_timestamp def update_workflow_status(workflow_elem, token): @@ -25,28 +50,39 @@ def update_workflow_status(workflow_elem, token): response = requests.request("GET", request_url, headers=headers, data=payload, timeout=15) status_code = response.status_code conclusion = "pending" + conclusion_time = "" + # TODO set is_stale # Process data if status_code == 200: # API was successful response_json = response.json() if len(response_json["workflow_runs"]) == 0: # workflow has no runs conclusion = "not yet run" + else: last_run = response_json["workflow_runs"][0] # Get the workflow conclusion ("success", "failure", etc) conclusion = last_run["conclusion"] + # Get the time this workflow concluded (in New York time) + conclusion_time = get_conclusion_time(last_run) + # Check if the workflow is currently being executed if conclusion is None: # try next most recent if len(response_json["workflow_runs"]) > 1: last_run = response_json["workflow_runs"][1] conclusion = last_run["conclusion"] + conclusion_time = get_conclusion_time(last_run) else: conclusion = "pending" + conclusion_time = "" + + # TODO set is_stale + else: print(" ", status_code) conclusion = status_code - workflow_elem.set_status(conclusion) + workflow_elem.set_status(conclusion, conclusion_time) diff --git a/templates/dash_template.jinja b/templates/dash_template.jinja index 8eee442a8e..c8c414d73a 100644 --- a/templates/dash_template.jinja +++ b/templates/dash_template.jinja @@ -9,34 +9,86 @@ - - - - - - - + + + + + + + + {% for project in all_projects %} - - - - + + + + + + + + + + + + + + + + + + + + + + {% endfor %} -
RepositoryNightly TestNightly
Benchmarks
Build DocsLive BuildOther
workflows
RepositoryNightly TestNightly
Benchmarks
Build DocsLive BuildOther Workflows
{{project.repo}}{{project.smoke_test.workflow_status}}{{project.benchmarks.workflow_status}}{{project.build_docs.workflow_status}}{{project.live_build.workflow_status}} + {{project.smoke_test.workflow_status}} + + + + + {{project.smoke_test.conclusion_time}} + + + {{project.benchmarks.workflow_status}} + + + + + {{project.benchmarks.conclusion_time}} + + + {{project.build_docs.workflow_status}} + + + + + {{project.build_docs.conclusion_time}} + + + {{project.live_build.workflow_status}} + + + + + {{project.live_build.conclusion_time}} + + {% for workflow in project.other_workflows %} - {{workflow.name}} {{workflow.status}} + {{workflow.name}} {{workflow.status}} {% endfor %}
+

- Last Updated {{last_updated}} | - {{dash_repo}} + Last Updated {{last_updated}} | + {{dash_repo}}

+ \ No newline at end of file