Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,31 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

---

## v26.05.12 (2026-05-31)

### Admin dashboard — responsive cards, fullscreen, navbar polish

- **Fullscreen / expand cards.** New reusable affordance: the **Bean Graph** and
**Log Viewer** cards gain a maximize button that expands them to fill the
viewport (Escape to exit) — ideal for exploring a large dependency graph or a
busy log stream. The expanded card re-parents to the document root so it sits
above the page (the ⌘K palette, toasts and the bean detail panel still layer
correctly on top).
- **Responsive sizing.** The dependency graph now scales with the viewport
(was a fixed 600px) and re-lays out on window resize / fullscreen toggle; the
log output grows with the window instead of a fixed 600px cap.
- **Bean Graph** also gains a **Reset view** control (clears pan/zoom).
- **Loggers** view: an **Effective Level Distribution** bar (share of each level)
and the table now scrolls within a viewport-relative height with a sticky header.
- **Metrics** view: the metric-list card now stretches to the full height of the
detail panel (was capped at 520px) and scrolls internally, so it uses the
available vertical space.
- **Navbar & sidebar.** The sidebar brand is now exactly the navbar height so the
two top bars line up across the split; the brand shows the pyfly wordmark only.
The navbar gains a live auto-refresh status pill and tidier, grouped controls.

---

## v26.05.11 (2026-05-31)

### Admin dashboard — loading skeletons & consistent empty states
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name = "pyfly"
# CalVer YY.MM.PATCH — package metadata uses PEP 440 normalized form (26.5.4);
# git tag, GitHub release and human-readable display use leading-zero form
# (v26.05.04) to match the Java/.NET/Go siblings.
version = "26.5.11"
version = "26.5.12"
description = "The official Python implementation of the Firefly Framework — DI, CQRS, EDA, hexagonal architecture, and more."
readme = "README.md"
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion src/pyfly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
# limitations under the License.
"""PyFly — Enterprise Python Framework."""

__version__ = "26.05.11"
__version__ = "26.05.12"
145 changes: 132 additions & 13 deletions src/pyfly/admin/static/css/admin.css
Original file line number Diff line number Diff line change
Expand Up @@ -86,31 +86,38 @@ a:hover {
.admin-sidebar-brand {
display: flex;
align-items: center;
gap: 12px;
padding: 16px 20px;
gap: 10px;
padding: 0 20px;
/* Exactly the navbar height so the two top bars line up across the split. */
height: var(--admin-navbar-height);
flex-shrink: 0;
border-bottom: 1px solid var(--admin-border-subtle);
min-height: var(--admin-navbar-height);
overflow: hidden;
}

.admin-sidebar-brand img {
height: 36px;
height: 30px;
width: auto;
object-fit: contain;
flex-shrink: 0;
}

.admin-sidebar-brand-divider {
width: 1px;
height: 24px;
height: 22px;
background: var(--admin-border-subtle);
flex-shrink: 0;
}

.admin-sidebar-brand span {
font-family: var(--admin-font-mono);
font-size: 0.95rem;
font-size: 0.9rem;
font-weight: 600;
color: var(--admin-sidebar-text-active);
letter-spacing: -0.02em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.admin-sidebar-nav {
Expand Down Expand Up @@ -228,7 +235,7 @@ a:hover {
.admin-navbar-right {
display: flex;
align-items: center;
gap: 16px;
gap: 10px;
}

.admin-navbar-right .refresh-label {
Expand All @@ -237,6 +244,43 @@ a:hover {
color: var(--admin-text-muted);
}

/* Live auto-refresh status pill */
.navbar-status {
display: inline-flex;
align-items: center;
gap: 7px;
padding: 4px 11px;
border-radius: 999px;
background: var(--admin-bg-subtle);
border: 1px solid var(--admin-border-subtle);
font-family: var(--admin-font-mono);
font-size: 0.72rem;
color: var(--admin-text-secondary);
white-space: nowrap;
}

.navbar-status-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--admin-success);
animation: trend-pulse 2s infinite;
}

/* Thin separator between navbar control groups */
.navbar-divider {
width: 1px;
height: 22px;
background: var(--admin-border);
flex-shrink: 0;
}

@media (max-width: 768px) {
.navbar-status {
display: none;
}
}

.admin-content {
flex: 1;
overflow-y: auto;
Expand Down Expand Up @@ -753,7 +797,9 @@ a:hover {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 200;
/* Above fullscreen cards (1200) so a node's detail panel shows over an
expanded graph; still below the palette (1300) and toasts (1400). */
z-index: 1250;
opacity: 0;
transition: opacity 0.2s ease;
pointer-events: none;
Expand All @@ -774,7 +820,7 @@ a:hover {
background: var(--admin-surface);
border-left: 1px solid var(--admin-border);
box-shadow: -4px 0 24px rgba(0, 0, 0, 0.3);
z-index: 210;
z-index: 1260;
transform: translateX(100%);
transition: transform 0.25s ease;
display: flex;
Expand Down Expand Up @@ -835,7 +881,8 @@ a:hover {
position: fixed;
top: 16px;
right: 16px;
z-index: 1000;
/* Above fullscreen cards (1200) and the palette (1300). */
z-index: 1400;
display: flex;
flex-direction: column;
gap: 8px;
Expand Down Expand Up @@ -1613,12 +1660,21 @@ a:hover {
font-family: var(--admin-font-mono);
font-size: 0.8rem;
line-height: 1.8;
max-height: 600px;
/* Grow with the viewport instead of a fixed cap. */
max-height: calc(100vh - 360px);
min-height: 280px;
overflow-y: auto;
padding: 12px 16px;
border-top: 1px solid var(--admin-border);
}

/* In fullscreen the output fills the expanded card. */
.card-fullscreen .logfile-output {
max-height: none;
flex: 1;
min-height: 0;
}

.log-line {
padding: 2px 0;
display: flex;
Expand Down Expand Up @@ -1794,7 +1850,8 @@ body.wallboard-mode .admin-content {
.cmd-palette-overlay {
position: fixed;
inset: 0;
z-index: 500;
/* Above fullscreen cards (1200) so ⌘K works while a card is expanded. */
z-index: 1300;
display: flex;
align-items: flex-start;
justify-content: center;
Expand Down Expand Up @@ -1928,18 +1985,25 @@ body.wallboard-mode .admin-content {
.metrics-split {
display: flex;
gap: 16px;
align-items: flex-start;
/* Stretch so the metric-list card matches the detail card's height and the
list uses the full available vertical space (scrolls internally). */
align-items: stretch;
}

.metrics-list-panel {
width: 300px;
min-width: 300px;
flex-shrink: 0;
display: flex;
flex-direction: column;
}

.metrics-detail-panel {
flex: 1;
min-width: 0;
/* A height floor so the split (and the list beside it) isn't tiny before a
metric is selected; it grows with the detail content. */
min-height: 460px;
}

@media (max-width: 768px) {
Expand Down Expand Up @@ -2103,3 +2167,58 @@ body.wallboard-mode .admin-content {
color: var(--admin-text-muted);
font-size: 0.72rem;
}

/* ── Fullscreen / Expand cards ──────────────────────────────────── */
.card-fs-btn {
color: var(--admin-text-muted);
}

.card-fs-btn-floating {
position: absolute;
top: 10px;
right: 10px;
z-index: 5;
background: var(--admin-surface);
border: 1px solid var(--admin-border);
}

.card-fs-btn-floating:hover {
background: var(--admin-surface-hover);
color: var(--admin-text);
}

.card-fullscreen {
/* !important beats the inline position:relative the floating-button
anchor sets on the card, so fullscreen always pins to the viewport. */
position: fixed !important;
inset: 0;
z-index: 1200;
margin: 0 !important;
border-radius: 0;
display: flex;
flex-direction: column;
box-shadow: var(--admin-shadow-lg);
}

/* The body region grows to fill the fullscreen card. */
.card-fullscreen > .admin-card-body {
flex: 1;
min-height: 0;
}

/* Dim/lock the page behind a fullscreen card. */
body.has-fullscreen {
overflow: hidden;
}

/* Bean dependency graph: viewport-relative height, fills the card in fullscreen. */
.bean-graph-body {
height: min(72vh, 820px);
min-height: 440px;
}

.card-fullscreen .bean-graph-body {
height: auto;
flex: 1;
min-height: 0;
}
22 changes: 17 additions & 5 deletions src/pyfly/admin/static/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,21 @@ function renderNavbar() {

navbar.appendChild(left);

// Right: refresh label + theme toggle
// Right: live status pill + search + controls
const right = document.createElement('div');
right.className = 'admin-navbar-right';

const refreshLabel = document.createElement('span');
refreshLabel.className = 'refresh-label';
refreshLabel.textContent = `refresh: ${settings.refreshInterval / 1000}s`;
right.appendChild(refreshLabel);
// Live auto-refresh indicator (pulsing dot + interval).
const statusPill = document.createElement('span');
statusPill.className = 'navbar-status';
statusPill.title = `Auto-refresh every ${settings.refreshInterval / 1000}s`;
const statusDot = document.createElement('span');
statusDot.className = 'navbar-status-dot';
statusPill.appendChild(statusDot);
const statusText = document.createElement('span');
statusText.textContent = `Live · ${settings.refreshInterval / 1000}s`;
statusPill.appendChild(statusText);
right.appendChild(statusPill);

// Command palette trigger (⌘K)
const searchBtn = document.createElement('button');
Expand All @@ -137,6 +144,11 @@ function renderNavbar() {
searchBtn.addEventListener('click', () => commandPalette && commandPalette.open());
right.appendChild(searchBtn);

// Divider between the search group and the icon controls.
const navDivider = document.createElement('span');
navDivider.className = 'navbar-divider';
right.appendChild(navDivider);

// Theme toggle button
const themeBtn = document.createElement('button');
themeBtn.className = 'theme-toggle';
Expand Down
Loading
Loading