From 0d645e0543b1507c278e6a17b69a7f38be21f835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raimondas=20Rimkevi=C4=8Dius?= Date: Sun, 26 Apr 2026 03:25:05 +0300 Subject: [PATCH 01/24] feat: redesign UI as a classic Windows wizard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the flat material card layout with a Windows-style wizard shell while keeping the existing navy/green brand palette. Layout changes: - New WizardLayout.vue: navy header, dark step-sidebar (1→2→3→4 with dot/check indicators), white content pane, classic grey footer bar - routes.js switched from MainLayout to WizardLayout Page changes (all use new .wiz-page chrome — header band + scrollable body + sticky Back/Next nav bar): - LoginPage: provider-row cards (GitHub / GitLab) with hover highlight - ReposPage: flat bordered list rows replacing the card grid - ExtractPage: two-panel config layout (folder tree | destination), separate "Extracting…" state with StatusPoller, reset flow - app.scss: shared .wiz-page utility classes --- frontend/src/css/app.scss | 59 ++++++ frontend/src/layouts/WizardLayout.vue | 255 ++++++++++++++++++++++++++ frontend/src/pages/ExtractPage.vue | 237 +++++++++++++++++------- frontend/src/pages/LoginPage.vue | 144 +++++++++++---- frontend/src/pages/ReposPage.vue | 150 +++++++++++---- frontend/src/router/routes.js | 2 +- 6 files changed, 706 insertions(+), 141 deletions(-) create mode 100644 frontend/src/layouts/WizardLayout.vue diff --git a/frontend/src/css/app.scss b/frontend/src/css/app.scss index 5da4a0f..e5fea7a 100644 --- a/frontend/src/css/app.scss +++ b/frontend/src/css/app.scss @@ -1 +1,60 @@ // app global css / scss goes here + +// ── Shared wizard page chrome ────────────────────────────────────── +// Every page inside WizardLayout uses these classes for a consistent +// header / scrollable-body / footer-nav structure. + +.wiz-page { + display: flex; + flex-direction: column; + height: 100%; + + // Step label + title + description banner at the top of the content pane + &__head { + flex-shrink: 0; + padding: 32px 40px 24px; + border-bottom: 1px solid #e0e0e0; + background: #fafafa; + } + + &__step-label { + font-size: 11px; + font-weight: 600; + letter-spacing: 1px; + text-transform: uppercase; + color: #888; + margin-bottom: 6px; + } + + &__title { + font-size: 22px; + font-weight: 700; + color: $primary; + margin: 0 0 6px; + } + + &__desc { + font-size: 13px; + color: #555; + margin: 0; + max-width: 560px; + } + + // Scrollable content area + &__body { + flex: 1; + overflow-y: auto; + padding: 28px 40px; + } + + // Back / Next navigation bar pinned to the bottom of the content pane + &__nav { + flex-shrink: 0; + display: flex; + justify-content: flex-end; + gap: 8px; + padding: 12px 40px; + border-top: 1px solid #e0e0e0; + background: #f5f5f5; + } +} diff --git a/frontend/src/layouts/WizardLayout.vue b/frontend/src/layouts/WizardLayout.vue new file mode 100644 index 0000000..3139054 --- /dev/null +++ b/frontend/src/layouts/WizardLayout.vue @@ -0,0 +1,255 @@ + + + + + diff --git a/frontend/src/pages/ExtractPage.vue b/frontend/src/pages/ExtractPage.vue index 600f925..ebd6423 100644 --- a/frontend/src/pages/ExtractPage.vue +++ b/frontend/src/pages/ExtractPage.vue @@ -1,44 +1,108 @@ + + diff --git a/frontend/src/pages/ExtractOptionsPage.vue b/frontend/src/pages/ExtractOptionsPage.vue new file mode 100644 index 0000000..9c50f59 --- /dev/null +++ b/frontend/src/pages/ExtractOptionsPage.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/frontend/src/pages/ExtractPathsPage.vue b/frontend/src/pages/ExtractPathsPage.vue new file mode 100644 index 0000000..884671d --- /dev/null +++ b/frontend/src/pages/ExtractPathsPage.vue @@ -0,0 +1,187 @@ + + + + + diff --git a/frontend/src/pages/ExtractProgressPage.vue b/frontend/src/pages/ExtractProgressPage.vue new file mode 100644 index 0000000..0e7d6f7 --- /dev/null +++ b/frontend/src/pages/ExtractProgressPage.vue @@ -0,0 +1,346 @@ + + + + + diff --git a/frontend/src/router/routes.js b/frontend/src/router/routes.js index 6025bd3..b47c975 100644 --- a/frontend/src/router/routes.js +++ b/frontend/src/router/routes.js @@ -5,11 +5,16 @@ const routes = [ children: [ { path: '', redirect: '/welcome' }, { path: '/welcome', component: () => import('pages/WelcomePage.vue') }, - { path: '/login', component: () => import('pages/LoginPage.vue') }, + { path: '/login', component: () => import('pages/LoginPage.vue') }, { path: '/auth/github', component: () => import('pages/AuthCallback.vue') }, { path: '/auth/gitlab', component: () => import('pages/AuthCallback.vue') }, { path: '/repos', component: () => import('pages/ReposPage.vue'), meta: { requiresAuth: true } }, - { path: '/extract', component: () => import('pages/ExtractPage.vue'), meta: { requiresAuth: true } }, + // /extract → always land on the first extract sub-step + { path: '/extract', redirect: '/extract/paths' }, + { path: '/extract/paths', component: () => import('pages/ExtractPathsPage.vue'), meta: { requiresAuth: true } }, + { path: '/extract/options', component: () => import('pages/ExtractOptionsPage.vue'), meta: { requiresAuth: true } }, + { path: '/extract/progress', component: () => import('pages/ExtractProgressPage.vue'), meta: { requiresAuth: true } }, + { path: '/extract/finish', component: () => import('pages/ExtractFinishPage.vue'), meta: { requiresAuth: true } }, ], }, { path: '/:catchAll(.*)*', component: () => import('pages/ErrorNotFound.vue') }, diff --git a/frontend/src/stores/repos.js b/frontend/src/stores/repos.js index 67309b4..5a0107a 100644 --- a/frontend/src/stores/repos.js +++ b/frontend/src/stores/repos.js @@ -12,9 +12,18 @@ export const useReposStore = defineStore('repos', () => { const search = ref('') const selectedSource = ref(null) const selectedTarget = ref(null) - const sourceTree = ref([]) - const sourcePath = ref('') - const targetPath = ref('src') + const sourceTree = ref([]) + const sourcePath = ref('') + const sourceBranch = ref('') + const sourceBranches = ref([]) + const targetPath = ref('src') + const targetBranch = ref('') + const targetBranches = ref([]) + const generateProjectFile = ref(false) + const extractRunId = ref('') + const extractRunUrl = ref('') + const extractStatus = ref(null) // null | 'running' | 'done' | 'error' + const extractResult = ref(null) const filtered = computed(() => search.value @@ -91,7 +100,16 @@ export const useReposStore = defineStore('repos', () => { selectedTarget, sourceTree, sourcePath, + sourceBranch, + sourceBranches, targetPath, + targetBranch, + targetBranches, + generateProjectFile, + extractRunId, + extractRunUrl, + extractStatus, + extractResult, filtered, loadRepos, loadMore, From 13da0b472352fea3d90b1bf5396b54fc21fa53f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raimondas=20Rimkevi=C4=8Dius?= Date: Mon, 27 Apr 2026 00:58:23 +0300 Subject: [PATCH 24/24] feat: make BIOS boot buttons interactive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DEL during POST → Award-style BIOS Setup Utility screen - 2-column menu (12 entries), arrow-key navigation - Any of Esc / F10 / Enter exits and resumes boot from cdboot F12 during POST → Boot Device Priority menu - CD-ROM / Hard Disk / Floppy, arrow-key selection - CD-ROM / Floppy → resume normal cdboot sequence - Hard Disk → shows 'DISK BOOT FAILURE' screen for 2.8 s, then automatically falls back to CD-ROM boot Any key during cdboot → skips 'Press any key' wait and immediately jumps to the Winders 98 start screen Internal: go() now stores timer IDs; cancelAll() clears them so entering a sub-screen properly cancels the scheduled phases. keydown listener added on mount, removed on unmount. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/components/BootSequence.vue | 359 +++++++++++++++++++++-- 1 file changed, 340 insertions(+), 19 deletions(-) diff --git a/frontend/src/components/BootSequence.vue b/frontend/src/components/BootSequence.vue index 0075cb3..c8a27df 100644 --- a/frontend/src/components/BootSequence.vue +++ b/frontend/src/components/BootSequence.vue @@ -6,7 +6,6 @@
- + +
+
+ ROM PCI/ISA BIOS (2A59G529) + CMOS SETUP UTILITY — AWARD SOFTWARE, INC. +
+ +
+
+
{{ item }}
+
+ +
+ Esc : Quit + ↑ ↓ → ← : Select Item + Enter / F10 : Save & Exit +
+
+ +
+ Time : {{ setupTime }} + Date : {{ setupDate }} + Base Memory : 640K + Ext Memory : 523264K +
+
+ + +
+
+
Boot Device Priority
+
+
+ {{ bootMenuDeviceIdx === i ? '►' : ' ' }} + {{ dev.label }} +
+
+
↑ ↓ Select    Enter Boot    Esc Cancel
+
+
+ + +
+
DISK BOOT FAILURE, INSERT SYSTEM DISK AND PRESS ENTER
+
Switching to CD-ROM boot…
+
+
@@ -223,7 +397,9 @@ onMounted(() => { background: #000; overflow: hidden; - &.boot-phase--bsod { background: #0000AA; } + &.boot-phase--bsod { background: #0000AA; } + &.boot-phase--bios-setup { background: #0000AA; } + &.boot-phase--hdd-error { background: #000; } } @keyframes boot-flicker { @@ -236,9 +412,7 @@ onMounted(() => { .boot-overlay { animation: boot-flicker 0.25s steps(1) forwards; } // ── Shared line-reveal ───────────────────────────────────────── -@keyframes line-appear { - to { opacity: 1; } -} +@keyframes line-appear { to { opacity: 1; } } .boot-line { opacity: 0; @@ -250,20 +424,16 @@ onMounted(() => { // ── BIOS POST ────────────────────────────────────────────────── .bios-screen { - position: relative; // anchor for the logo + position: relative; padding: 18px 36px; font-size: 13px; line-height: 1.65; color: #aaaaaa; } -.bios-line { - &--header { color: #ffffff; } -} +.bios-line { &--header { color: #ffffff; } } // ── BIOS logo (top-right corner) ─────────────────────────────── -// 80×50 canvas drawn at native resolution, scaled to 240×150 via CSS. -// image-rendering: pixelated keeps each logical pixel a hard block — no blur. .bios-logo { position: absolute; top: 18px; @@ -271,7 +441,158 @@ onMounted(() => { width: 240px; height: 150px; image-rendering: pixelated; - image-rendering: crisp-edges; // Firefox + image-rendering: crisp-edges; +} + +// ── BIOS Setup Utility ───────────────────────────────────────── +.setup-screen { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + font-family: 'Courier New', Courier, monospace; + font-size: 13px; + line-height: 1.5; + background: #0000AA; +} + +.setup-topbar { + flex-shrink: 0; + background: #AAAAAA; + color: #000; + display: flex; + justify-content: space-between; + padding: 2px 8px; + font-size: 12px; +} + +.setup-body { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 20px; +} + +.setup-menu { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0; + border: 1px solid #AAAAAA; + width: min(680px, 100%); + + &__item { + padding: 3px 16px; + color: #FFFFFF; + white-space: nowrap; + cursor: default; + + // Divide left and right columns + &:nth-child(odd) { border-right: 1px solid #555599; } + + &--active { + background: #AAAAAA; + color: #000080; + } + } +} + +.setup-hints { + display: flex; + gap: 24px; + margin-top: 12px; + color: #FFFF55; + font-size: 11px; +} + +.setup-botbar { + flex-shrink: 0; + background: #AAAAAA; + color: #000; + display: flex; + justify-content: space-around; + padding: 2px 8px; + font-size: 12px; +} + +// ── Boot Device Menu ─────────────────────────────────────────── +.bootmenu-screen { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background: #000; +} + +.bootmenu-box { + font-family: 'Courier New', Courier, monospace; + font-size: 13px; + color: #CCCCCC; + border: 1px solid #666; + min-width: 320px; + padding: 0; +} + +.bootmenu-title { + background: #0000AA; + color: #FFFF55; + padding: 4px 14px; + font-weight: bold; + letter-spacing: 0.5px; +} + +.bootmenu-line { + border: none; + border-top: 1px solid #444; +} + +.bootmenu-item { + display: flex; + align-items: center; + gap: 8px; + padding: 4px 14px; + color: #CCCCCC; + cursor: default; + + &__arrow { width: 10px; flex-shrink: 0; color: #FFFF55; } + + &--active { + background: #0000AA; + color: #FFFFFF; + } +} + +.bootmenu-hint { + padding: 4px 14px; + font-size: 11px; + color: #888; +} + +// ── HDD boot failure ─────────────────────────────────────────── +.hdd-error-screen { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + padding: 40px 60px; + font-family: 'Courier New', Courier, monospace; +} + +.hdd-error-msg { + font-size: 14px; + color: #cccccc; + margin-bottom: 20px; +} + +.hdd-error-fallback { + font-size: 13px; + color: #888888; + + @keyframes blink-fallback { 50% { opacity: 0; } } + animation: blink-fallback 1s step-end infinite; } // ── CD boot ────────────────────────────────────────────────────