From 08905a248d15a24bf8b4ef7ab247fe78dedb3c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Jasi=C5=84ski?= Date: Sun, 14 Jun 2026 19:01:41 +0200 Subject: [PATCH] feat(stage): add --nexus-only switch to run-stage.sh and execute premium creator edit layout polish --- run-stage.sh | 33 ++- .../Pages/CreatorEdit.razor | 20 +- .../Pages/CreatorEdit.razor.css | 270 ++++++++++-------- 3 files changed, 192 insertions(+), 131 deletions(-) diff --git a/run-stage.sh b/run-stage.sh index f923401..5da5195 100755 --- a/run-stage.sh +++ b/run-stage.sh @@ -4,11 +4,23 @@ # ------------------------------------------------------------- set -e +NEXUS_ONLY=false +for arg in "$@"; do + case $arg in + --nexus-only|-n) + NEXUS_ONLY=true + ;; + esac +done + ENV_FILE=".env.stage" TEMPLATE_FILE=".env.stage.template" COMPOSE_FILE="docker-compose.stage.yml" echo "🏁 Starting staging environment orchestration..." +if [ "$NEXUS_ONLY" = true ]; then + echo "ℹ️ Mode: --nexus-only (only the web/nexus application container will be modified)" +fi # 1. Create .env.stage if it doesn't exist if [ ! -f "$ENV_FILE" ]; then @@ -58,13 +70,24 @@ POSTGRES_PORT=${POSTGRES_PORT:-5438} WEB_PORT=${WEB_PORT:-5080} # 3. Stop any conflicting Docker Compose environments -echo "🧹 Stopping existing containers..." -docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down --remove-orphans || true -docker compose down --remove-orphans 2>/dev/null || true +if [ "$NEXUS_ONLY" = true ]; then + echo "🧹 Stopping and removing only the web (nexus) container..." + docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" stop web || true + docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" rm -f web || true +else + echo "🧹 Stopping existing containers..." + docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down --remove-orphans || true + docker compose down --remove-orphans 2>/dev/null || true +fi # 4. Build and start containers -echo "🚀 Building and starting staging containers..." -docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --build +if [ "$NEXUS_ONLY" = true ]; then + echo "🚀 Building and restarting only the web (nexus) container..." + docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --build web +else + echo "🚀 Building and starting staging containers..." + docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --build +fi # 5. Wait for Database to be healthy echo "⏳ Waiting for database (nexus-db-stage) to become healthy..." diff --git a/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor b/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor index 4633326..39e2c83 100644 --- a/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor +++ b/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor @@ -6,15 +6,18 @@
-

Rozdziały

+
+
- 1. Rozdział 1: Wprowadzenie do Zen Mode + 1. Rozdział 1: Wprowadzenie do Zen Mode
- - 2. Rozdział 2: Zabezpieczenia i Architektura + + 2. Rozdział 2: Zabezpieczenia i Architektura
@@ -22,8 +25,10 @@
-

Rozdział 1: Wprowadzenie do Zen Mode

-
+
+

Rozdział 1: Wprowadzenie do Zen Mode

+
+
ID: @ChapterId
@@ -42,7 +47,7 @@
@@ -57,7 +62,6 @@ private async Task FetchContent() { - // Tutaj trafia Twoja logika wyciągania zawartości z edytora Milkdown await Task.CompletedTask; } } diff --git a/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor.css b/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor.css index 3e2c092..4b60b84 100644 --- a/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor.css +++ b/src/NexusReader.UI.Shared/Pages/CreatorEdit.razor.css @@ -1,150 +1,179 @@ /* ========================================================================== - NEXUSREADER CREATOR EDIT MODE - PREMIUM SAAS CORE STYLES + NEXUSREADER CREATOR EDIT MODE - HIGH-FIDELITY SAAS PREMIUM DESIGN OVERRIDE ========================================================================== */ -/* 1. MASTER WRAPPER (Zgładzenie globalnego scrolla przeglądarki) */ +/* 1. ARCHITECTURAL BOUNDARY CONTROL */ .creator-edit-fullscreen-wrapper { width: 100% !important; max-width: 100% !important; - height: calc(100vh - 4rem) !important; /* Sztywne cięcie pod wysokość topbaru platformy */ + height: calc(100vh - 4rem) !important; margin: 0 !important; padding: 0 !important; display: flex !important; - overflow: hidden !important; /* Całkowity zakaz scrollowania okna głównego */ - background-color: var(--bg-base); + overflow: hidden !important; + background-color: #121214; box-sizing: border-box; } -/* 2. MATTE CHAPTERS SIDEBAR (Luksusowy panel boczny) */ +/* Dynamic theme bridge mapping for Warm Paper mode */ +.theme-light .creator-edit-fullscreen-wrapper { + background-color: #f4f1ea; +} + +/* 2. UNIFIED SIDEBAR DESIGN (Eliminating layout color fragmentation) */ .chapters-sidebar { - width: 290px !important; + width: 300px !important; flex-shrink: 0; - background-color: #141417 !important; /* Matowy głęboki antracyt z readera */ - border-right: 1px solid rgba(255, 255, 255, 0.05) !important; + background-color: #16161a !important; + border-right: 1px solid rgba(255, 255, 255, 0.04) !important; display: flex; flex-direction: column; - padding: 2rem 1.25rem !important; + padding: 2.5rem 1.5rem !important; box-sizing: border-box; } .theme-light .chapters-sidebar { - background-color: #ede9df !important; /* Dopasowanie do motywu Warm Paper */ - border-right: 1px solid var(--border) !important; + background-color: #eae6db !important; /* Rich warm tone that remains fully cohesive with warm paper base */ + border-right: 1px solid #dcd7cc !important; } -.chapters-sidebar h2 { - font-size: 0.85rem; +.sidebar-meta-header h2 { + font-size: 0.8rem; font-weight: 700; text-transform: uppercase; - letter-spacing: 1.5px; - color: var(--text-muted); - margin: 0 0 1.5rem 0; - padding-left: 0.5rem; + letter-spacing: 2px; + color: #a1a1aa; + margin: 0 0 1.75rem 0; +} + +.theme-light .sidebar-meta-header h2 { + color: #78716c; } .chapters-list-wrapper { display: flex; flex-direction: column; - gap: 4px; + gap: 6px; } -/* Elementy listy rozdziałów */ +/* Premium Navigation Links */ .chapter-item { + position: relative; display: flex; align-items: center; gap: 12px; - padding: 12px 14px !important; - border-radius: 8px; - color: var(--text-muted); + padding: 12px 16px !important; + border-radius: 10px; + color: #a1a1aa; font-size: 0.95rem; cursor: pointer; - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); - border-left: 3px solid transparent !important; + transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); +} + +.theme-light .chapter-item { + color: #78716c; } .chapter-item i.chapter-icon { - font-size: 0.9rem; - color: var(--text-muted); + font-size: 0.95rem; + color: #71717a; + transition: color 0.25s ease; } -/* Aktywny stan unifikacji wizualnej */ +/* Active Indicator Node Alignment */ .chapter-item.active { - background-color: rgba(0, 255, 153, 0.04) !important; - color: var(--accent) !important; + background-color: rgba(0, 255, 153, 0.05) !important; + color: #00ff99 !important; font-weight: 600; - border-left: 3px solid var(--accent) !important; -} - -.chapter-item.active i.chapter-icon { - color: var(--accent) !important; } .theme-light .chapter-item.active { background-color: rgba(16, 185, 129, 0.06) !important; + color: #10b981 !important; +} + +.chapter-item.active i.chapter-icon { + color: inherit !important; } .chapter-item:hover:not(.active) { background-color: rgba(255, 255, 255, 0.02); - color: var(--text-main); + color: #ffffff; } -/* 3. WORKSPACE CORE (Główna oś edytora) */ +.theme-light .chapter-item:hover:not(.active) { + background-color: rgba(0, 0, 0, 0.02); + color: #2d2a26; +} + +/* 3. WORKSPACE METRICS (Zen presentation spacing) */ .editor-workspace-area { flex-grow: 1; display: flex; flex-direction: column; height: 100%; - padding: 2.5rem 3.5rem 2rem 3.5rem !important; /* Odpowiedni, dostojny margines Zen Mode */ + padding: 3rem 4rem 2.5rem 4rem !important; /* Generous padding context for premium scale */ box-sizing: border-box; overflow: hidden; } -/* Nagłówek i ID bez ryzyka kolizji */ .editor-header-row { display: flex; justify-content: space-between; align-items: center; - margin-bottom: 1.5rem; + margin-bottom: 2rem; flex-shrink: 0; width: 100%; } .editor-workspace-area h1.chapter-title { - font-size: 2.2rem; + font-size: 2.4rem; font-weight: 700; - color: var(--text-main); + color: #ffffff; margin: 0; - letter-spacing: -0.5px; + letter-spacing: -0.75px; +} + +.theme-light .editor-workspace-area h1.chapter-title { + color: #2d2a26; } .chapter-id-badge { font-family: 'Azeret Mono', monospace; - font-size: 0.75rem; - color: var(--text-muted); - background: rgba(255, 255, 255, 0.03); - padding: 5px 12px; - border-radius: 6px; - border: 1px solid rgba(255, 255, 255, 0.08); - white-space: nowrap; + font-size: 0.72rem; + color: #71717a; + background: #1a1a1e; + padding: 6px 14px; + border-radius: 8px; + border: 1px solid rgba(255, 255, 255, 0.05); + letter-spacing: 0.2px; } .theme-light .chapter-id-badge { - background: rgba(0, 0, 0, 0.02); - border: 1px solid var(--border); + background: #ffffff; + color: #78716c; + border: 1px solid #dcd7cc; } -/* 4. PREMIUM CANVAS CARD (Rozciąganie Flex na 100% wysokości) */ +/* 4. ELEVATED EDITOR CANVAS CARD (Introducing layered shadow mechanics) */ .editor-canvas-card { - background-color: var(--bg-surface) !important; - border: 1px solid var(--border) !important; - border-radius: 16px; - padding: 2.5rem !important; + background-color: #1a1a1e !important; + border: 1px solid rgba(255, 255, 255, 0.04) !important; + border-radius: 20px; + padding: 3rem !important; display: flex; flex-direction: column; - flex-grow: 1; /* Wymusza rozciągnięcie do samego paska stopki */ + flex-grow: 1; overflow: hidden; box-sizing: border-box; - box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15); + /* Soft diffuse structural shadows mimicking actual surface elevation */ + box-shadow: 0 20px 50px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(0, 0, 0, 0.2); +} + +.theme-light .editor-canvas-card { + background-color: #ffffff !important; + border: 1px solid #dcd7cc !important; + box-shadow: 0 20px 50px rgba(45, 42, 38, 0.04), 0 4px 12px rgba(45, 42, 38, 0.02); } .milkdown-premium-container { @@ -155,8 +184,7 @@ width: 100%; } -/* --- DEEP SELECTORS DLA PROSEMIRROR (MILKDOWN RENDER) --- */ - +/* DEEP MOUNTING COMPONENT INTEROP */ ::deep .milkdown { background: transparent !important; box-shadow: none !important; @@ -169,51 +197,32 @@ } ::deep .ProseMirror { - color: var(--text-main) !important; + color: #e4e1d9 !important; background-color: transparent !important; - font-family: inherit !important; - font-size: 1.1rem !important; - line-height: 1.75 !important; + font-size: 1.15rem !important; + line-height: 1.8 !important; flex-grow: 1; - overflow-y: auto !important; /* Scroll pojawia się TYLKO na tekście rozdziału */ - padding-right: 15px !important; + overflow-y: auto !important; + padding-right: 24px !important; outline: none !important; box-sizing: border-box; width: 100%; } -/* Kontekst zaznaczenia zunifikowany z readerem */ +.theme-light ::deep .ProseMirror { + color: #2d2a26 !important; +} + +/* Precise matching text selection token */ ::deep .ProseMirror ::selection { - background-color: rgba(0, 255, 153, 0.25) !important; - color: inherit !important; + background-color: rgba(0, 255, 153, 0.2) !important; } .theme-light ::deep .ProseMirror ::selection { - background-color: rgba(16, 185, 129, 0.2) !important; + background-color: rgba(16, 185, 129, 0.18) !important; } -/* Popover / dymek formatowania zintegrowany z czytnikiem */ -::deep .milkdown .popover, -::deep .milkdown-popover, -::deep .prosemirror-bubble-menu { - background-color: #1e1e22 !important; - border: 1px solid rgba(255, 255, 255, 0.08) !important; - border-radius: 12px !important; - padding: 6px 10px !important; - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5) !important; - display: flex !important; - align-items: center !important; - gap: 12px !important; -} - -.theme-light ::deep .milkdown .popover, -.theme-light ::deep .prosemirror-bubble-menu { - background-color: #ffffff !important; - border: 1px solid var(--border) !important; - box-shadow: 0 10px 30px rgba(45, 42, 38, 0.06) !important; -} - -/* Customowy, dyskretny scrollbar dla tekstu książki */ +/* Core webkit custom scrollbar mapping */ ::deep .ProseMirror::-webkit-scrollbar { width: 6px; } @@ -221,71 +230,96 @@ background: transparent; } ::deep .ProseMirror::-webkit-scrollbar-thumb { - background: var(--border); - border-radius: 3px; + background: rgba(255, 255, 255, 0.08); + border-radius: 4px; } -/* 5. FIXED FOOTER BAR (Zintegrowany dół pancernej karty) */ +.theme-light ::deep .ProseMirror::-webkit-scrollbar-thumb { + background: #dcd7cc; +} + +/* 5. SEAMLESS INTEGRATED ACTIONS FOOTER BAR */ .editor-footer-bar { display: flex; justify-content: space-between; align-items: center; - margin-top: 1.5rem; - padding-top: 1.25rem; - border-top: 1px solid var(--border); - flex-shrink: 0; /* Gwarancja, że pasek nigdy nie ucieknie poza kartę */ + margin-top: 2rem; + padding-top: 1.5rem; + border-top: 1px solid rgba(255, 255, 255, 0.04); + flex-shrink: 0; width: 100%; } -/* Status zapisu w chmurze z pulsującą diodą akcentową */ +.theme-light .editor-footer-bar { + border-top: 1px solid #dcd7cc; +} + +/* Telemetry cloud synchronization line */ .cloud-status-container { display: flex; align-items: center; - gap: 10px; + gap: 12px; } .cloud-status-pulse { - width: 8px; - height: 8px; - background-color: var(--accent); + width: 7px; + height: 7px; + background-color: #00ff99; border-radius: 50%; display: inline-block; - box-shadow: 0 0 10px var(--accent); - position: relative; + box-shadow: 0 0 10px rgba(0, 255, 153, 0.8); +} + +.theme-light .cloud-status-pulse { + background-color: #10b981; + box-shadow: 0 0 10px rgba(16, 185, 129, 0.6); } .cloud-status-text { font-family: 'Azeret Mono', monospace; - font-size: 0.85rem; - color: var(--text-muted); + font-size: 0.82rem; + color: #71717a; + letter-spacing: 0.1px; } -/* Przycisk akcji premium */ +/* Premium Tactile Operational Button Trigger */ .btn-nexus-premium { - background-color: var(--accent) !important; + background-color: #00ff99 !important; color: #121214 !important; font-weight: 700; - font-size: 0.95rem; - padding: 10px 22px; + font-size: 0.9rem; + letter-spacing: -0.1px; + padding: 11px 24px; border: none !important; - border-radius: 8px; + border-radius: 10px; cursor: pointer; display: inline-flex; align-items: center; gap: 10px; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); - box-shadow: 0 4px 14px var(--accent-glow); + box-shadow: 0 4px 20px rgba(0, 255, 153, 0.15); } .theme-light .btn-nexus-premium { + background-color: #10b981 !important; color: #ffffff !important; + box-shadow: 0 4px 20px rgba(16, 185, 129, 0.15); +} + +.btn-nexus-premium i { + font-size: 0.85rem; + transition: transform 0.2s ease; } .btn-nexus-premium:hover { transform: translateY(-1px); - box-shadow: 0 6px 20px var(--accent-glow); + box-shadow: 0 8px 24px rgba(0, 255, 153, 0.3); } -.btn-nexus-premium:active { - transform: translateY(0); +.theme-light .btn-nexus-premium:hover { + box-shadow: 0 8px 24px rgba(16, 185, 129, 0.3); +} + +.btn-nexus-premium:hover i { + transform: translateX(3px); }