feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
#!/usr/bin/env bash
set -euo pipefail
2026-05-07 11:50:10 +08:00
export MSYS_NO_PATHCONV = 1
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
SCRIPT_DIR = " $( cd " $( dirname " ${ BASH_SOURCE [0] } " ) " && pwd ) "
2026-05-06 17:43:47 +08:00
ENV_FILE = " $SCRIPT_DIR /.env "
ENV_EXAMPLE_FILE = " $SCRIPT_DIR /.env.example "
MODE = " ${ 1 :- all } "
feat: refactor monolithic App.vue into modular Vue component architecture
- Extract 711-line App.vue into 15+ focused files across 5 directories
- Add data layer (icons, metrics, policies, auditTrail, requests)
- Add composables (useNavigation, useRequests, useChat, useToast)
- Add layout components (SidebarRail, TopBar, FilterBar)
- Add shared components (PanelHead, InfoRow, ToastNotification)
- Add business component (RequestTable) and 5 view components
- Extract global CSS to assets/styles/global.css
- Add start.sh with WSL/Windows cross-platform support
- Add .gitignore for node_modules, dist, and IDE dirs
2026-04-28 17:20:52 +08:00
2026-05-06 17:43:47 +08:00
RED = '\033[0;31m'
GREEN = '\033[0;32m'
YELLOW = '\033[1;33m'
NC = '\033[0m'
info( ) { echo -e " ${ GREEN } [INFO] ${ NC } $* " ; }
warn( ) { echo -e " ${ YELLOW } [WARN] ${ NC } $* " ; }
error( ) { echo -e " ${ RED } [ERROR] ${ NC } $* " ; exit 1; }
if [ ! -f " $ENV_FILE " ] ; then
if [ -f " $ENV_EXAMPLE_FILE " ] ; then
warn ".env not found. Creating it from .env.example"
cp " $ENV_EXAMPLE_FILE " " $ENV_FILE "
else
error ".env and .env.example are both missing."
fi
fi
set -a
. " $ENV_FILE "
set +a
SERVER_STARTUP_TIMEOUT = " ${ SERVER_STARTUP_TIMEOUT :- 300 } "
SETUP_COMPLETED = " ${ SETUP_COMPLETED :- false } "
2026-05-07 11:50:10 +08:00
server_probe_url( ) {
echo " http:// ${ SERVER_HOST :- 127 .0.0.1 } : ${ SERVER_PORT :- 8000 } ${ API_V1_PREFIX :- /api/v1 } /health "
}
server_smoke_url( ) {
echo " http:// ${ SERVER_HOST :- 127 .0.0.1 } : ${ SERVER_PORT :- 8000 } ${ API_V1_PREFIX :- /api/v1 } /employees/meta "
}
server_probe_python( ) {
if [ -x " $SCRIPT_DIR /server/.venv/Scripts/python.exe " ] ; then
echo " $SCRIPT_DIR /server/.venv/Scripts/python.exe "
return 0
fi
if [ -x " $SCRIPT_DIR /server/.venv/bin/python " ] ; then
echo " $SCRIPT_DIR /server/.venv/bin/python "
return 0
fi
return 1
}
probe_server_health( ) {
local probe_url = " ${ 1 :- $( server_probe_url) } "
local probe_python = ""
if probe_python = " $( server_probe_python) " ; then
" $probe_python " -c "import json, sys, urllib.request; data = json.load(urllib.request.urlopen(sys.argv[1], timeout=2)); raise SystemExit(0 if data.get('status') == 'ok' else 1)" " $probe_url " >/dev/null 2>& 1
return $?
fi
if command -v curl >/dev/null 2>& 1; then
curl --silent --fail --max-time 2 " $probe_url " | grep -q '"status"[[:space:]]*:[[:space:]]*"ok"'
return $?
fi
return 1
}
probe_server_smoke( ) {
local probe_url = " ${ 1 :- $( server_smoke_url) } "
local probe_python = ""
if probe_python = " $( server_probe_python) " ; then
" $probe_python " -c "import sys, urllib.request; response = urllib.request.urlopen(sys.argv[1], timeout=3); raise SystemExit(0 if response.status == 200 else 1)" " $probe_url " >/dev/null 2>& 1
return $?
fi
if command -v curl >/dev/null 2>& 1; then
curl --silent --fail --max-time 3 " $probe_url " >/dev/null 2>& 1
return $?
fi
return 1
}
probe_server_ready( ) {
local health_url = " ${ 1 :- $( server_probe_url) } "
local smoke_url = " ${ 2 :- $( server_smoke_url) } "
probe_server_health " $health_url " && probe_server_smoke " $smoke_url "
}
2026-05-06 17:43:47 +08:00
prepare_web( ) {
info "Preparing web dependencies..."
(
cd " $SCRIPT_DIR /web "
./start.sh deps
)
}
prepare_server( ) {
info "Preparing server dependencies..."
(
cd " $SCRIPT_DIR /server "
./start.sh deps
)
}
start_web( ) {
prepare_web
cd " $SCRIPT_DIR /web "
exec ./start.sh start
}
start_server( ) {
prepare_server
cd " $SCRIPT_DIR /server "
exec ./start.sh start
}
start_setup_web( ) {
warn "Initial setup is not completed. Starting web only."
warn "Finish the setup form first. After setup is saved, run ./start.sh again to launch FastAPI as well."
prepare_web
cd " $SCRIPT_DIR /web "
exec ./start.sh start
}
start_all( ) {
local server_pid = ""
2026-05-07 11:50:10 +08:00
local started_server = false
local probe_url = ""
local smoke_url = ""
2026-05-06 17:43:47 +08:00
prepare_server
cleanup( ) {
2026-05-07 11:50:10 +08:00
if [ " $started_server " = true ] && [ -n " $server_pid " ] && kill -0 " $server_pid " 2>/dev/null; then
2026-05-06 17:43:47 +08:00
warn "Stopping FastAPI server..."
kill " $server_pid " 2>/dev/null || true
wait " $server_pid " 2>/dev/null || true
fi
}
trap cleanup EXIT INT TERM
2026-05-07 11:50:10 +08:00
probe_url = " $( server_probe_url) "
smoke_url = " $( server_smoke_url) "
if probe_server_ready " $probe_url " " $smoke_url " ; then
warn " FastAPI is already ready at $probe_url . Reusing the existing backend process. "
elif probe_server_health " $probe_url " ; then
error " An existing backend process is responding at $probe_url , but the smoke check failed at $smoke_url . Stop the old FastAPI process and rerun ./start.sh. "
else
info "Starting FastAPI server..."
(
cd " $SCRIPT_DIR /server "
./start.sh start
) &
server_pid = $!
started_server = true
fi
2026-05-06 17:43:47 +08:00
2026-05-07 11:50:10 +08:00
wait_for_server_ready( ) {
2026-05-06 17:43:47 +08:00
local attempt = 1
local max_attempts = " $SERVER_STARTUP_TIMEOUT "
2026-05-07 11:50:10 +08:00
info "Waiting for FastAPI readiness before starting the web frontend..."
2026-05-06 17:43:47 +08:00
while [ " $attempt " -le " $max_attempts " ] ; do
2026-05-07 11:50:10 +08:00
if probe_server_ready " $probe_url " " $smoke_url " ; then
info "FastAPI is ready. Starting web frontend next."
2026-05-06 17:43:47 +08:00
return 0
fi
2026-05-07 11:50:10 +08:00
if [ " $started_server " = true ] && ! kill -0 " $server_pid " 2>/dev/null; then
if probe_server_ready " $probe_url " " $smoke_url " ; then
warn " FastAPI is already available at $probe_url . Continuing with the existing process. "
started_server = false
server_pid = ""
return 0
fi
wait " $server_pid " 2>/dev/null || true
error "FastAPI process exited before becoming ready. Run ./server/start.sh start directly to inspect the backend error."
2026-05-06 17:43:47 +08:00
fi
sleep 1
attempt = $(( attempt + 1 ))
done
2026-05-07 11:50:10 +08:00
if probe_server_health " $probe_url " ; then
error " FastAPI answered health checks at $probe_url , but the smoke check failed at $smoke_url . The running backend is stale or incompatible. "
fi
error " FastAPI did not become ready within ${ SERVER_STARTUP_TIMEOUT } s. Inspect server/logs/app.log. "
2026-05-06 17:43:47 +08:00
}
2026-05-07 11:50:10 +08:00
wait_for_server_ready
2026-05-06 17:43:47 +08:00
2026-05-07 11:50:10 +08:00
prepare_web
2026-05-06 17:43:47 +08:00
info "Starting web frontend..."
cd " $SCRIPT_DIR /web "
./start.sh start
}
case " $MODE " in
web)
start_web
; ;
server)
start_server
; ;
all)
if [ " $SETUP_COMPLETED " = "true" ] ; then
start_all
else
start_setup_web
fi
; ;
*)
error " Unknown mode: $MODE . Use one of: web, server, all "
; ;
esac