Skip to content

Commit d7a9677

Browse files
authored
Merge pull request #321 from lbedner/light-mode-support
Added Commit Badges
2 parents 8303d2a + 780a5ad commit d7a9677

26 files changed

Lines changed: 630 additions & 316 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
99
[![Commits per Month](https://img.shields.io/github/commit-activity/m/lbedner/aegis-stack)](https://github.com/lbedner/aegis-stack/commits)
1010
[![Total Commits](https://img.shields.io/github/commit-activity/t/lbedner/aegis-stack)](https://github.com/lbedner/aegis-stack/commits)
11+
[![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-orange.json)](https://github.com/copier-org/copier)
1112

1213
You need to ship reliable software, but management only gave you 2 weeks.
1314

aegis/commands/update.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,8 @@ def update_command(
275275
answers = yaml.safe_load(f) or {}
276276

277277
# Update _src_path to point to custom template
278-
answers["_src_path"] = str(template_root)
278+
# Use git+file:// URL format so Copier recognizes it as git-tracked
279+
answers["_src_path"] = f"git+file://{template_root}"
279280

280281
with open(answers_file, "w") as f:
281282
yaml.safe_dump(

aegis/core/copier_manager.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ def generate_with_copier(
200200

201201
# Update _src_path to point to repo root (where .git exists)
202202
# The copier.yml at repo root has _subdirectory setting to find actual template
203-
answers["_src_path"] = str(template_root)
203+
# Use git+file:// URL format so Copier recognizes it as git-tracked
204+
answers["_src_path"] = f"git+file://{template_root}"
204205

205206
with open(answers_file, "w") as f:
206207
yaml.safe_dump(answers, f, default_flow_style=False, sort_keys=False)

aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Frontend UI controls for styled components."""
22

3+
from .service_card import ServiceCard
34
from .table import (
45
TableCellText,
56
TableHeaderText,
@@ -50,4 +51,6 @@
5051
# Badge/Tag controls
5152
"Tag",
5253
"TechBadge",
54+
# Card layout controls
55+
"ServiceCard",
5356
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""
2+
ServiceCard Control
3+
4+
Reusable Flet control for composing service cards with 2-column layout.
5+
Provides consistent layout with thin vertical divider and vertical centering.
6+
"""
7+
8+
import flet as ft
9+
10+
11+
class ServiceCard(ft.Row):
12+
"""
13+
Reusable service card layout control.
14+
15+
Creates a clean 2-column layout with:
16+
- Left section: Technology badge (vertically centered)
17+
- Thin vertical divider
18+
- Right section: Metrics/content (full height)
19+
20+
Usage:
21+
ServiceCard(
22+
left_content=tech_badge,
23+
right_content=metrics_section,
24+
)
25+
"""
26+
27+
def __init__(
28+
self,
29+
left_content: ft.Control,
30+
right_content: ft.Control,
31+
divider_height: int = 160,
32+
left_width: int = 200,
33+
divider_color: str | None = None,
34+
):
35+
"""
36+
Initialize the ServiceCard.
37+
38+
Args:
39+
left_content: Control for left section (typically TechBadge)
40+
right_content: Control for right section (typically metrics)
41+
divider_height: Height of the vertical divider in pixels
42+
left_width: Width of the left section in pixels
43+
divider_color: Color of the vertical divider (defaults to OUTLINE_VARIANT)
44+
"""
45+
# Build the row controls
46+
controls = [
47+
# Left section: Tech badge with vertical centering
48+
ft.Container(
49+
content=ft.Column(
50+
[left_content],
51+
spacing=0,
52+
alignment=ft.MainAxisAlignment.CENTER,
53+
),
54+
width=left_width,
55+
padding=ft.padding.all(16),
56+
),
57+
# Thin vertical divider
58+
ft.Container(
59+
width=1,
60+
height=divider_height,
61+
bgcolor=divider_color or ft.Colors.OUTLINE_VARIANT,
62+
margin=ft.margin.symmetric(horizontal=16),
63+
),
64+
# Right section: Metrics/content
65+
right_content,
66+
]
67+
68+
# Initialize Row with controls
69+
super().__init__(controls=controls, expand=True)

aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/text.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ class PrimaryText(ft.Text): # type: ignore[misc]
2323
def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
2424
defaults = {
2525
"no_wrap": False,
26-
"color": Theme.Colors.TEXT_PRIMARY,
2726
"font_family": "Roboto",
2827
"size": Theme.Typography.BODY_LARGE,
2928
"weight": Theme.Typography.WEIGHT_REGULAR,
@@ -46,7 +45,6 @@ def __init__(
4645
) -> None:
4746
defaults = {
4847
"no_wrap": no_wrap,
49-
"color": Theme.Colors.TEXT_SECONDARY,
5048
"font_family": "Roboto",
5149
"size": Theme.Typography.BODY,
5250
"weight": Theme.Typography.WEIGHT_REGULAR,
@@ -66,7 +64,6 @@ class TitleText(ft.Text): # type: ignore[misc]
6664
def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
6765
# Set defaults, but allow kwargs to override
6866
defaults = {
69-
"color": Theme.Colors.TEXT_PRIMARY,
7067
"font_family": "Roboto",
7168
"size": Theme.Typography.H2,
7269
"weight": Theme.Typography.WEIGHT_BOLD,
@@ -110,7 +107,6 @@ class MetricText(ft.Text): # type: ignore[misc]
110107

111108
def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
112109
defaults = {
113-
"color": Theme.Colors.TEXT_PRIMARY,
114110
"font_family": "Roboto",
115111
"size": Theme.Typography.BODY_LARGE,
116112
"weight": Theme.Typography.WEIGHT_BOLD,
@@ -130,7 +126,6 @@ class LabelText(ft.Text): # type: ignore[misc]
130126
def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
131127
# Set defaults, but allow kwargs to override
132128
defaults = {
133-
"color": Theme.Colors.TEXT_SECONDARY,
134129
"font_family": "Roboto",
135130
"size": Theme.Typography.BODY_SMALL,
136131
"weight": Theme.Typography.WEIGHT_SEMIBOLD,
@@ -162,7 +157,6 @@ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
162157
defaults = {
163158
"size": Theme.Typography.DISPLAY,
164159
"weight": Theme.Typography.WEIGHT_BOLD,
165-
"color": Theme.Colors.TEXT_PRIMARY,
166160
"font_family": "Roboto",
167161
"selectable": True,
168162
}
@@ -181,7 +175,6 @@ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
181175
defaults = {
182176
"size": Theme.Typography.H1,
183177
"weight": Theme.Typography.WEIGHT_BOLD,
184-
"color": Theme.Colors.TEXT_PRIMARY,
185178
"font_family": "Roboto",
186179
"selectable": True,
187180
}
@@ -200,7 +193,6 @@ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
200193
defaults = {
201194
"size": Theme.Typography.H2,
202195
"weight": Theme.Typography.WEIGHT_BOLD,
203-
"color": Theme.Colors.TEXT_PRIMARY,
204196
"font_family": "Roboto",
205197
"selectable": True,
206198
}
@@ -219,7 +211,6 @@ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
219211
defaults = {
220212
"size": Theme.Typography.H3,
221213
"weight": Theme.Typography.WEIGHT_SEMIBOLD,
222-
"color": Theme.Colors.TEXT_PRIMARY,
223214
"font_family": "Roboto",
224215
"selectable": True,
225216
}
@@ -238,7 +229,6 @@ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
238229
defaults = {
239230
"size": Theme.Typography.BODY,
240231
"weight": Theme.Typography.WEIGHT_REGULAR,
241-
"color": Theme.Colors.TEXT_PRIMARY,
242232
"font_family": "Roboto",
243233
"selectable": True,
244234
}
@@ -338,7 +328,6 @@ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
338328
defaults = {
339329
"size": Theme.Typography.BODY_LARGE,
340330
"weight": Theme.Typography.WEIGHT_BOLD,
341-
"color": Theme.Colors.TEXT_PRIMARY,
342331
"font_family": "Roboto",
343332
"selectable": True,
344333
}
@@ -357,7 +346,6 @@ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
357346
defaults = {
358347
"size": Theme.Typography.BODY,
359348
"weight": Theme.Typography.WEIGHT_REGULAR,
360-
"color": Theme.Colors.TEXT_SECONDARY,
361349
"font_family": "Roboto",
362350
"selectable": True,
363351
}
@@ -382,7 +370,6 @@ def __init__(
382370
defaults = {
383371
"size": Theme.Typography.BODY,
384372
"weight": Theme.Typography.WEIGHT_REGULAR,
385-
"color": Theme.Colors.TEXT_SECONDARY,
386373
"font_family": "Roboto",
387374
"overflow": ft.TextOverflow.ELLIPSIS,
388375
"width": width,
@@ -403,7 +390,6 @@ def __init__(self, value: str, opacity: float = 1.0, **kwargs: Any) -> None:
403390
defaults = {
404391
"size": Theme.Typography.BODY,
405392
"weight": Theme.Typography.WEIGHT_BOLD,
406-
"color": Theme.Colors.TEXT_PRIMARY,
407393
"font_family": "Roboto",
408394
"selectable": True,
409395
}

aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/ai_card.py

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"""
77

88
import flet as ft
9-
from app.components.frontend.controls import LabelText, PrimaryText
9+
from app.components.frontend.controls import LabelText, PrimaryText, ServiceCard
1010
from app.components.frontend.controls.tech_badge import TechBadge
1111
from app.services.system.models import ComponentStatus
1212

@@ -90,19 +90,6 @@ def _create_metric_container(
9090
expand=True,
9191
)
9292

93-
def _create_left_section(self) -> ft.Container:
94-
"""Create the left section with tech badge."""
95-
return ft.Container(
96-
content=ft.Column(
97-
[
98-
self._create_technology_badge(),
99-
],
100-
spacing=0,
101-
),
102-
width=200,
103-
padding=ft.padding.all(16),
104-
)
105-
10693
def _create_technology_badge(self) -> ft.Container:
10794
"""Create technology badge for AI service."""
10895
primary_color, _, _ = get_status_colors(self.component_data)
@@ -243,24 +230,12 @@ def _create_metrics_section(self) -> ft.Container:
243230
def build(self) -> ft.Container:
244231
"""Build and return the complete AI service card."""
245232
# Get colors based on component status
246-
background_color, primary_color, border_color = get_status_colors(
247-
self.component_data
248-
)
233+
_, _, border_color = get_status_colors(self.component_data)
249234

250-
# Create clean 2-column layout
251-
content = ft.Row(
252-
[
253-
self._create_left_section(),
254-
ft.Container(
255-
width=1,
256-
height=160, # Adjust height to match content
257-
bgcolor=ft.Colors.with_opacity(0.1, ft.Colors.GREY_400),
258-
margin=ft.margin.symmetric(horizontal=16),
259-
),
260-
self._create_metrics_section(),
261-
],
262-
expand=True,
263-
vertical_alignment=ft.CrossAxisAlignment.START,
235+
# Use ServiceCard for consistent service card layout
236+
content = ServiceCard(
237+
left_content=self._create_technology_badge(),
238+
right_content=self._create_metrics_section(),
264239
)
265240

266241
return CardContainer(

aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/auth_card.py

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"""
77

88
import flet as ft
9-
from app.components.frontend.controls import LabelText, PrimaryText
9+
from app.components.frontend.controls import LabelText, PrimaryText, ServiceCard
1010
from app.components.frontend.controls.tech_badge import TechBadge
1111
from app.services.system.models import ComponentStatus
1212

@@ -54,19 +54,6 @@ def _create_metric_container(
5454
expand=True,
5555
)
5656

57-
def _create_left_section(self) -> ft.Container:
58-
"""Create the left section with just the tech badge."""
59-
return ft.Container(
60-
content=ft.Column(
61-
[
62-
self._create_technology_badge(),
63-
],
64-
spacing=0,
65-
),
66-
width=200,
67-
padding=ft.padding.all(16),
68-
)
69-
7057
def _create_technology_badge(self) -> ft.Container:
7158
"""Create technology badge for authentication service."""
7259
primary_color, _, _ = get_status_colors(self.component_data)
@@ -160,24 +147,12 @@ def _create_metrics_section(self) -> ft.Container:
160147
def build(self) -> ft.Container:
161148
"""Build and return the complete authentication card."""
162149
# Get colors based on component status
163-
background_color, primary_color, border_color = get_status_colors(
164-
self.component_data
165-
)
150+
_, _, border_color = get_status_colors(self.component_data)
166151

167-
# Create clean 2-column layout
168-
content = ft.Row(
169-
[
170-
self._create_left_section(),
171-
ft.Container(
172-
width=1,
173-
height=160, # Adjust height to match content
174-
bgcolor=ft.Colors.with_opacity(0.1, ft.Colors.GREY_400),
175-
margin=ft.margin.symmetric(horizontal=16),
176-
),
177-
self._create_metrics_section(),
178-
],
179-
expand=True,
180-
vertical_alignment=ft.CrossAxisAlignment.START,
152+
# Use ServiceCard for consistent service card layout
153+
content = ServiceCard(
154+
left_content=self._create_technology_badge(),
155+
right_content=self._create_metrics_section(),
181156
)
182157

183158
return CardContainer(

0 commit comments

Comments
 (0)