From 110e246a1c73c38c8782b2ba7e4438f4c1bbbd68 Mon Sep 17 00:00:00 2001 From: Justin Visser Date: Thu, 19 Feb 2026 20:07:08 +0100 Subject: [PATCH] Added run state front end support Updated scholars layout to match dashboard --- README.md | 11 + frontend/src/app/providers.ts | 4 + frontend/src/components/layout/AppNav.vue | 26 +- frontend/src/pages/DashboardPage.vue | 139 ++++- frontend/src/pages/RunsPage.vue | 62 ++- frontend/src/pages/ScholarsPage.vue | 564 +++++++++++--------- frontend/src/stores/auth.ts | 5 + frontend/src/stores/run_status.test.ts | 176 ++++++ frontend/src/stores/run_status.ts | 264 +++++++++ tests/integration/test_multi_user_schema.py | 128 +++++ 10 files changed, 1095 insertions(+), 284 deletions(-) create mode 100644 frontend/src/stores/run_status.test.ts create mode 100644 frontend/src/stores/run_status.ts diff --git a/README.md b/README.md index 9ee3ccb..4489432 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,17 @@ docker compose -f docker-compose.yml -f docker-compose.dev.yml down - `CONTRIBUTING.md`: contribution policy and merge checklist. - `scripts/check_no_generated_artifacts.sh`: tracked-artifact guard used by CI. +## Data Model Notes + +- Scholar tracking is user-scoped: each account can track the same Scholar ID independently. +- Publications are shared/global records deduplicated by Scholar cluster ID and normalized fingerprint. +- Per-account visibility and read state is stored on scholar-publication links, not on the global publication row. + +## Name Search Status + +- Scholar name search is intentionally WIP in the UI. +- Current Google Scholar behavior often redirects name-search traffic to login/challenge flows, so production onboarding should use direct Scholar ID/profile URL adds. + ## Environment Variables (Complete Reference) Notes: diff --git a/frontend/src/app/providers.ts b/frontend/src/app/providers.ts index d55bbb3..50a60e1 100644 --- a/frontend/src/app/providers.ts +++ b/frontend/src/app/providers.ts @@ -1,5 +1,6 @@ import { setCsrfTokenProvider } from "@/lib/api/client"; import { useAuthStore } from "@/stores/auth"; +import { useRunStatusStore } from "@/stores/run_status"; import { useThemeStore } from "@/stores/theme"; import { useUserSettingsStore } from "@/stores/user_settings"; @@ -12,9 +13,12 @@ export async function bootstrapAppProviders(): Promise { await auth.bootstrapSession(); const userSettings = useUserSettingsStore(); + const runStatus = useRunStatusStore(); if (auth.isAuthenticated) { await userSettings.bootstrap(); + await runStatus.bootstrap(); } else { userSettings.reset(); + runStatus.reset(); } } diff --git a/frontend/src/components/layout/AppNav.vue b/frontend/src/components/layout/AppNav.vue index 997687c..1e07d9c 100644 --- a/frontend/src/components/layout/AppNav.vue +++ b/frontend/src/components/layout/AppNav.vue @@ -2,11 +2,14 @@ import { computed } from "vue"; import { useRouter } from "vue-router"; +import RunStatusBadge from "@/components/patterns/RunStatusBadge.vue"; import AppButton from "@/components/ui/AppButton.vue"; import { useAuthStore } from "@/stores/auth"; +import { useRunStatusStore } from "@/stores/run_status"; import { useUserSettingsStore } from "@/stores/user_settings"; const auth = useAuthStore(); +const runStatus = useRunStatusStore(); const userSettings = useUserSettingsStore(); const router = useRouter(); @@ -28,6 +31,21 @@ const links = computed(() => { return userSettings.isPageVisible(item.id); }); }); +const navRunStatus = computed(() => { + if (runStatus.isLikelyRunning) { + return "running"; + } + return "idle"; +}); +const navRunText = computed(() => { + const label = navRunStatus.value + .replaceAll("_", " ") + .split(" ") + .filter((segment) => segment.length > 0) + .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)) + .join(" "); + return `State: ${label}`; +}); async function onLogout(): Promise { await auth.logout(); @@ -53,7 +71,13 @@ async function onLogout(): Promise {
-

{{ auth.user?.email }}

+
+ {{ navRunText }} + +
Logout
diff --git a/frontend/src/pages/DashboardPage.vue b/frontend/src/pages/DashboardPage.vue index cd66c32..d6bf8d3 100644 --- a/frontend/src/pages/DashboardPage.vue +++ b/frontend/src/pages/DashboardPage.vue @@ -1,8 +1,7 @@