mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-11 14:00:29 +00:00
Tighten hosted portal shell spacing
This commit is contained in:
@@ -183,6 +183,12 @@ Own canonical runtime payload shapes between backend and frontend.
|
||||
26. Keep storage chart identity canonical on that same shared API surface: the shared storage charts endpoint must key pool and physical-disk series by the resolved unified-resource `MetricsTarget.ResourceID`, not by canonical resource IDs or page-local aliases, so storage rows, focused summary cards, sticky summary shells, and detail charts all address the same history series in live and mock mode.
|
||||
27. Keep synthetic summary-chart fallback identity canonical on that same shared API surface: when `internal/api/router.go` has to synthesize mock summary history for infrastructure, workloads, or storage cards, it must derive the fallback from canonical `resourceType`, `resourceID`, and `metricType` ownership instead of raw min/max seed-prefix helpers, so range changes and runtime mock updates stay on one governed timeline.
|
||||
28. Keep workload-chart response identity canonical on that same shared API surface: `internal/api/router.go`, `internal/api/contract_test.go`, and workload summary consumers must emit provider-backed VM and system-container series under the same canonical workload IDs that workloads page rows use, while resolving history through the unified `MetricsTarget.ResourceID`, so hover and focus selection do not fall off for provider-backed rows.
|
||||
29. Keep the hosted account portal bootstrap intelligible without duplicate
|
||||
chrome. `internal/cloudcp/portal/page.go`, the maintained portal frontend
|
||||
bundle, and the shared portal styles may refine layout density, but the
|
||||
account/billing shell must remain understandable from the primary header,
|
||||
section title, and factual body content alone instead of depending on a
|
||||
second context-chip strip to restate the same scope.
|
||||
|
||||
## Forbidden Paths
|
||||
|
||||
|
||||
@@ -110,6 +110,11 @@ agreement, and cloud-specific enforcement rules.
|
||||
19. Add or change cloud plan presentation through `frontend-modern/src/pages/CloudPricing.tsx`
|
||||
20. Add contract tests where runtime and pricing need to stay aligned
|
||||
21. Add or change hosted browser org-context bootstrap through `frontend-modern/src/App.tsx`, `frontend-modern/src/AppLayout.tsx`, `frontend-modern/src/useAppRuntimeState.ts`, and `frontend-modern/src/utils/apiClient.ts`
|
||||
22. Keep the hosted account portal shell task-first and compact. Section
|
||||
headers, billing action rows, and the maintained portal bundle under
|
||||
`internal/cloudcp/portal/` may surface the facts an operator needs, but the
|
||||
shell should not spend vertical space on duplicate context-chip strips when
|
||||
the page header and section body already communicate that scope.
|
||||
|
||||
## Forbidden Paths
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"source_hash": "dee5325d02ca13ee1eb3b4ff7d09478406bbd5805999ced971f4b7f62700d7f0",
|
||||
"source_hash": "8cda796f9a573443304df3d61c11f26041c8cd7f050fc737b67e3c056cd09b6c",
|
||||
"build_inputs": [
|
||||
"package.json",
|
||||
"tsconfig.json",
|
||||
|
||||
+16
-9
@@ -81,6 +81,7 @@
|
||||
--warn: #9a6700;
|
||||
--warn-subtle: #fff8c5;
|
||||
--radius: 6px;
|
||||
--header-height: 49px;
|
||||
}
|
||||
*,
|
||||
*::before,
|
||||
@@ -89,6 +90,7 @@
|
||||
}
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
background: var(--bg);
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
@@ -118,15 +120,16 @@ header {
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
height: 48px;
|
||||
padding: 0 16px;
|
||||
height: var(--header-height);
|
||||
padding: 0 24px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--bg);
|
||||
background: var(--bg-subtle);
|
||||
}
|
||||
header .brand {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.header-account-chip {
|
||||
display: inline-flex;
|
||||
@@ -204,9 +207,9 @@ header .logout-btn:hover,
|
||||
font-size: 12px;
|
||||
}
|
||||
.main {
|
||||
max-width: 800px;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px 64px;
|
||||
padding: 0 32px 64px;
|
||||
}
|
||||
.portal-shell {
|
||||
display: flex;
|
||||
@@ -217,13 +220,13 @@ header .logout-btn:hover,
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
padding: 16px 0 12px;
|
||||
padding: 16px 0 0;
|
||||
font-size: 13px;
|
||||
color: var(--ink-secondary);
|
||||
}
|
||||
.portal-identity-bar h2 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
}
|
||||
@@ -234,7 +237,8 @@ header .logout-btn:hover,
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border-muted);
|
||||
margin-top: 8px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.portal-tab {
|
||||
@@ -293,7 +297,7 @@ header .logout-btn:hover,
|
||||
display: none !important;
|
||||
}
|
||||
.portal-content-panel {
|
||||
padding: 20px 0 0;
|
||||
padding: 16px 0 0;
|
||||
}
|
||||
.portal-section-header {
|
||||
display: flex;
|
||||
@@ -1591,6 +1595,9 @@ header .logout-btn:hover,
|
||||
background: #82181a;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
header {
|
||||
padding: 0 16px;
|
||||
}
|
||||
.main {
|
||||
padding: 0 16px 48px;
|
||||
}
|
||||
|
||||
+1
-4
@@ -2062,10 +2062,7 @@
|
||||
return '<article class="billing-action-row"><div class="billing-action-main"><div class="billing-action-copy"><h3>' + title + "</h3><p>" + description + '</p></div><div class="billing-action-meta">' + meta + '</div></div><div class="billing-action-cta"><button class="btn-secondary billing-action-button" type="button" id="' + id + '" data-account-billing-action="open-billing-panel" data-account-billing-panel="' + panelID + '" data-account-billing-focus="' + focusID + '" data-shell-target="billing">' + escapeHTML(actionLabel) + "</button></div></article>";
|
||||
}
|
||||
function renderSectionContextChips(chips) {
|
||||
if (!chips.length) return "";
|
||||
return '<div class="section-context-strip">' + chips.map(function(chip) {
|
||||
return '<span class="section-context-chip">' + escapeHTML(chip) + "</span>";
|
||||
}).join("") + "</div>";
|
||||
return "";
|
||||
}
|
||||
function attentionWorkspaces(workspaces) {
|
||||
var results = [];
|
||||
|
||||
@@ -192,6 +192,9 @@ describe('shell view', function() {
|
||||
expect(html).not.toContain('>Licenses<');
|
||||
expect(html).not.toContain('>Refunds<');
|
||||
expect(html).not.toContain('>Privacy<');
|
||||
expect(html).not.toContain('section-context-strip');
|
||||
expect(html).not.toContain('View roster');
|
||||
expect(html).not.toContain('Owner or admin required');
|
||||
});
|
||||
|
||||
it('defaults the authenticated hosted shell to workspaces', function() {
|
||||
|
||||
@@ -217,10 +217,7 @@ function renderBillingActionRow(
|
||||
}
|
||||
|
||||
function renderSectionContextChips(chips: string[]): string {
|
||||
if (!chips.length) return '';
|
||||
return '<div class="section-context-strip">' + chips.map(function(chip) {
|
||||
return '<span class="section-context-chip">' + escapeHTML(chip) + '</span>';
|
||||
}).join('') + '</div>';
|
||||
return '';
|
||||
}
|
||||
|
||||
function renderFactLine(className: string, facts: string[]): string {
|
||||
|
||||
@@ -38,11 +38,12 @@
|
||||
--warn: #9a6700;
|
||||
--warn-subtle: #fff8c5;
|
||||
--radius: 6px;
|
||||
--header-height: 49px;
|
||||
}
|
||||
|
||||
/* ── Reset ────────────────────────────────────────────────────── */
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
html { scroll-behavior: smooth; }
|
||||
html { scroll-behavior: smooth; background: var(--bg); }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
@@ -59,7 +60,7 @@ a { color: var(--accent); text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
[hidden] { display: none !important; }
|
||||
|
||||
/* ── Header ───────────────────────────────────────────────────── */
|
||||
/* ── Header (top bar) ─────────────────────────────────────────── */
|
||||
header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
@@ -68,16 +69,17 @@ header {
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
height: 48px;
|
||||
padding: 0 16px;
|
||||
height: var(--header-height);
|
||||
padding: 0 24px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--bg);
|
||||
background: var(--bg-subtle);
|
||||
}
|
||||
|
||||
header .brand {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.header-account-chip {
|
||||
@@ -158,9 +160,9 @@ header .logout-btn:hover,
|
||||
|
||||
/* ── Main container ───────────────────────────────────────────── */
|
||||
.main {
|
||||
max-width: 800px;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px 64px;
|
||||
padding: 0 32px 64px;
|
||||
}
|
||||
|
||||
/* ── Portal shell (signed-in) ─────────────────────────────────── */
|
||||
@@ -170,19 +172,19 @@ header .logout-btn:hover,
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
/* Identity bar — tighter, no padding top */
|
||||
/* ── Identity bar — compact page header ───────────────────────── */
|
||||
.portal-identity-bar {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
padding: 16px 0 12px;
|
||||
padding: 16px 0 0;
|
||||
font-size: 13px;
|
||||
color: var(--ink-secondary);
|
||||
}
|
||||
|
||||
.portal-identity-bar h2 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
}
|
||||
@@ -191,12 +193,13 @@ header .logout-btn:hover,
|
||||
color: var(--border);
|
||||
}
|
||||
|
||||
/* Tab navigation */
|
||||
/* ── Tab navigation ───────────────────────────────────────────── */
|
||||
.portal-tab-bar {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border-muted);
|
||||
margin-top: 8px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -229,7 +232,7 @@ header .logout-btn:hover,
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* Content panels — hide/show logic */
|
||||
/* ── Content panels — hide/show logic ─────────────────────────── */
|
||||
.portal-shell-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -263,7 +266,7 @@ header .logout-btn:hover,
|
||||
}
|
||||
|
||||
.portal-content-panel {
|
||||
padding: 20px 0 0;
|
||||
padding: 16px 0 0;
|
||||
}
|
||||
|
||||
/* ── Section headers ──────────────────────────────────────────── */
|
||||
@@ -1306,6 +1309,7 @@ header .logout-btn:hover,
|
||||
|
||||
/* ── Responsive ───────────────────────────────────────────────── */
|
||||
@media (max-width: 768px) {
|
||||
header { padding: 0 16px; }
|
||||
.main { padding: 0 16px 48px; }
|
||||
|
||||
.portal-tab-bar { overflow-x: auto; scrollbar-width: none; gap: 0; }
|
||||
|
||||
Reference in New Issue
Block a user