From dfa974fe6ba3af5a561b31506a1d76a3b5b54997 Mon Sep 17 00:00:00 2001 From: shankar Date: Thu, 28 Nov 2024 20:08:10 +0530 Subject: [PATCH] Remove study count showing on Activity column. Collapse Navigation bar by default. Show Active and Idle for router activity. Fixed card view count. Fixed card view router row info as per correct status. Show only one recent study on Activity column. Show router details on click of router id to expanded row. --- db-scripts/00-init-db.sh | 25 +++ {sql => db-scripts}/01-init.sql | 39 ++-- db-scripts/02-seed_common_data.sql | 34 ++++ db-scripts/03-seed_router_data_qa.sql | 49 +++++ deploy.sh | 142 +++++++++++++ docker-compose.yml | 73 ++++--- readme.txt | 22 +- router-dashboard/.env | 2 +- router-dashboard/.env.production | 2 + .../components/dashboard/DashboardLayout.tsx | 21 +- .../src/components/dashboard/Navbar.tsx | 4 +- .../components/dashboard/RouterTableRow.tsx | 62 +++++- router-dashboard/src/config/env.ts | 20 +- router-dashboard/src/data/mockData.ts | 9 + router-dashboard/src/services/api.service.ts | 9 +- router-dashboard/src/types/backend.ts | 4 + router-dashboard/src/types/index.ts | 6 + router-dashboard/src/utils/statusHelpers.ts | 29 --- sql/02-seed_data.sql | 105 ---------- ve-router-backend/.env | 12 +- ve-router-backend/src/config/config.ts | 19 +- .../src/repositories/RouterRepository.ts | 189 ++++++++++-------- .../src/services/DicomStudyService.ts | 2 +- ve-router-backend/src/types/index.ts | 29 +-- 24 files changed, 586 insertions(+), 322 deletions(-) create mode 100644 db-scripts/00-init-db.sh rename {sql => db-scripts}/01-init.sql (80%) create mode 100644 db-scripts/02-seed_common_data.sql create mode 100644 db-scripts/03-seed_router_data_qa.sql create mode 100644 deploy.sh create mode 100644 router-dashboard/.env.production delete mode 100644 sql/02-seed_data.sql diff --git a/db-scripts/00-init-db.sh b/db-scripts/00-init-db.sh new file mode 100644 index 0000000..582fed0 --- /dev/null +++ b/db-scripts/00-init-db.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Wait for MySQL to become available +echo "Waiting for MySQL to become healthy..." +until mysql -h "localhost" -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SHOW DATABASES;" &>/dev/null; do + echo "Waiting for MySQL..." + sleep 2 +done + +echo "MySQL is up and running!" + +# Run the initial common setup (always executed) +echo "Running 01-init.sql" +mysql -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE < /docker-entrypoint-initdb.d/01-init.sql + +echo "Running 02-seed_common_data.sql" +mysql -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE < /docker-entrypoint-initdb.d/02-seed_common_data.sql + +# Check the environment variable and execute environment-specific scripts +if [ "$ENVIRONMENT" != "production" ]; then + echo "Running 03-seed_router_data_qa.sql for QA (non-production)" + mysql -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE < /docker-entrypoint-initdb.d/03-seed_router_data_qa.sql +else + echo "Production environment detected. Skipping seeding data for QA (non-production)." +fi diff --git a/sql/01-init.sql b/db-scripts/01-init.sql similarity index 80% rename from sql/01-init.sql rename to db-scripts/01-init.sql index 86e092c..7fdc1f2 100644 --- a/sql/01-init.sql +++ b/db-scripts/01-init.sql @@ -8,6 +8,9 @@ CREATE TABLE IF NOT EXISTS routers ( router_id VARCHAR(10) UNIQUE NOT NULL, -- Unique router identifier facility VARCHAR(50) NOT NULL, router_alias VARCHAR(50) NOT NULL, + facility_aet VARCHAR(50) NOT NULL, + openvpn_ip VARCHAR(15) NOT NULL, + router_vm_primary_ip VARCHAR(15) NOT NULL, last_seen TIMESTAMP NOT NULL, vpn_status_code VARCHAR(50) NOT NULL, disk_status_code VARCHAR(50) NOT NULL, @@ -76,24 +79,24 @@ CREATE TABLE IF NOT EXISTS container_status ( ); -- DICOM study overview table with router_id as a string reference -CREATE TABLE IF NOT EXISTS dicom_study_overview ( - id INT AUTO_INCREMENT PRIMARY KEY, - router_id VARCHAR(10) NOT NULL, -- Matching VARCHAR(10) with the routers table - study_instance_uid VARCHAR(100) UNIQUE NOT NULL, - patient_id VARCHAR(50) NOT NULL, - patient_name VARCHAR(100) NOT NULL, - accession_number VARCHAR(50) NOT NULL, - study_date DATE NOT NULL, - modality VARCHAR(20) NOT NULL, - study_description VARCHAR(255), - series_instance_uid VARCHAR(100) NOT NULL, - procedure_code VARCHAR(50), - referring_physician_name VARCHAR(100), - study_status_code VARCHAR(50) NOT NULL DEFAULT 'NEW', -- Default value, ensure 'NEW' exists in status_type - association_id VARCHAR(50) NOT NULL DEFAULT 'NEW', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -); + CREATE TABLE IF NOT EXISTS dicom_study_overview ( + id INT AUTO_INCREMENT PRIMARY KEY, + router_id VARCHAR(10) NOT NULL, -- Matching VARCHAR(10) with the routers table + study_instance_uid VARCHAR(100) UNIQUE NOT NULL, + patient_id VARCHAR(50) NOT NULL, + patient_name VARCHAR(100) NOT NULL, + accession_number VARCHAR(50) NOT NULL, + study_date DATE NOT NULL, + modality VARCHAR(20) NOT NULL, + study_description VARCHAR(255), + series_instance_uid VARCHAR(100) NOT NULL, + procedure_code VARCHAR(50), + referring_physician_name VARCHAR(100), + study_status_code VARCHAR(50) NOT NULL DEFAULT 'NEW', -- Default value, ensure 'NEW' exists in status_type + association_id VARCHAR(50) NOT NULL DEFAULT 'NEW', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ); -- Create tables if they don't exist CREATE TABLE IF NOT EXISTS status_type ( diff --git a/db-scripts/02-seed_common_data.sql b/db-scripts/02-seed_common_data.sql new file mode 100644 index 0000000..c7e79bb --- /dev/null +++ b/db-scripts/02-seed_common_data.sql @@ -0,0 +1,34 @@ +-- Check if the procedure exists, and create it only if it does not +DROP PROCEDURE IF EXISTS `seed_common_router_data`; + +DELIMITER // + +CREATE PROCEDURE seed_common_router_data() +BEGIN + -- Insert Status Categories + INSERT INTO status_category (name, description) + VALUES + ('Network', 'Network related statuses'), + ('Disk', 'Disk related statuses'), + ('VPN', 'VPN connection statuses'), + ('License', 'License statuses'), + ('Container', 'Container related statuses') + ON DUPLICATE KEY UPDATE id = id; + + -- Insert Status Types + INSERT INTO status_type (category_id, name, code, description, severity) + VALUES + (1, 'Online', 'NET_ONLINE', 'System is online', 1), + (1, 'Offline', 'NET_OFFLINE', 'System is offline', 5), + (2, 'Normal', 'DISK_NORMAL', 'Disk usage is normal', 1), + (2, 'Warning', 'DISK_WARNING', 'Disk usage is high', 3), + (2, 'Critical', 'DISK_CRITICAL', 'Disk usage is critical', 5), + (3, 'Connected', 'VPN_CONNECTED', 'VPN is connected', 1), + (3, 'Disconnected', 'VPN_DISCONNECTED', 'VPN is disconnected', 5), + (5, 'Running', 'CONTAINER_RUNNING', 'Container is running', 1), + (5, 'Stopped', 'CONTAINER_STOPPED', 'Container is stopped', 5) + ON DUPLICATE KEY UPDATE id = id; + +END // + +DELIMITER ; diff --git a/db-scripts/03-seed_router_data_qa.sql b/db-scripts/03-seed_router_data_qa.sql new file mode 100644 index 0000000..a0f961a --- /dev/null +++ b/db-scripts/03-seed_router_data_qa.sql @@ -0,0 +1,49 @@ +-- Check if the procedure exists, and create it only if it does not +DROP PROCEDURE IF EXISTS `seed_router_data`; + +DELIMITER // + +CREATE PROCEDURE seed_router_data() +BEGIN + -- Insert Routers + INSERT INTO routers (router_id, facility, router_alias, facility_aet, openvpn_ip, router_vm_primary_ip, + last_seen, vpn_status_code, disk_status_code, app_status_code, license_status, free_disk, total_disk, disk_usage) + VALUES + ('RTR001', 'Main Hospital', 'MAIN_RAD', 'RTR_1', '10.8.0.101', '192.168.1.101', NOW(), 'VPN_CONNECTED', 'DISK_NORMAL', 'CONTAINER_RUNNING', 'active', 500000000000, 1000000000000, 50.00), + ('RTR002', 'Emergency Center', 'ER_RAD', 'RTR_2', '10.8.0.102', '192.168.1.102', NOW(), 'VPN_DISCONNECTED', 'DISK_WARNING', 'CONTAINER_RUNNING', 'active', 400000000000, 1000000000000, 60.00), + ('RTR003', 'Imaging Center', 'IMG_CENTER', 'RTR_3', '10.8.0.103', '192.168.1.103', NOW(), 'VPN_CONNECTED', 'DISK_NORMAL', 'CONTAINER_RUNNING', 'active', 600000000000, 1000000000000, 40.00) + ON DUPLICATE KEY UPDATE id = id; + + -- Store Router IDs + SET @router1_id = (SELECT id FROM routers WHERE router_id = 'RTR001'); + SET @router2_id = (SELECT id FROM routers WHERE router_id = 'RTR002'); + SET @router3_id = (SELECT id FROM routers WHERE router_id = 'RTR003'); + + -- Insert Container Status + INSERT INTO container_status (router_id, container_name, status_code, created_at, updated_at) + VALUES + (@router1_id, 'router-cstore-scp', 'CONTAINER_RUNNING', NOW(), NOW()), + (@router1_id, 'router-cstore-scu', 'CONTAINER_RUNNING', NOW(), NOW()), + (@router2_id, 'router-cstore-scp', 'CONTAINER_RUNNING', NOW(), NOW()), + (@router2_id, 'router-cstore-scu', 'CONTAINER_RUNNING', NOW(), NOW()), + (@router3_id, 'router-cstore-scp', 'CONTAINER_RUNNING', NOW(), NOW()) + ON DUPLICATE KEY UPDATE id = id; + + -- Insert DICOM Study Overview + INSERT INTO dicom_study_overview ( + router_id, study_instance_uid, patient_id, patient_name, + accession_number, study_date, modality, study_description, + series_instance_uid, procedure_code, referring_physician_name, + study_status_code + ) + VALUES + (@router1_id, '1.2.840.113619.2.55.3.283116435.276.1543707218.134', 'P1', 'John Doe', 'ACC1234', '2024-03-15', 'CT', 'Chest CT', '1.2.840.113619.2.55.3.283116435.276.1543707219.135', 'CT001', 'Dr. Smith', 'idle'), + (@router2_id, '1.2.840.113619.2.55.3.283116435.276.1543707218.136', 'P2', 'Jane Doe', 'ACC1235', '2024-03-15', 'MR', 'Brain MRI', '1.2.840.113619.2.55.3.283116435.276.1543707219.137', 'MR001', 'Dr. Johnson', 'idle') + ON DUPLICATE KEY UPDATE id = id; + +END // + +DELIMITER ; + +-- Automatically call the procedure after creation +CALL seed_router_data(); diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..f537041 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,142 @@ +#!/bin/bash + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Function to print colored messages +print_message() { + local color=$1 + local message=$2 + echo -e "${color}${message}${NC}" +} + +# Function to check if command was successful +check_status() { + if [ $? -eq 0 ]; then + print_message "$GREEN" "✔ Success: $1" + else + print_message "$RED" "✘ Error: $1" + exit 1 + fi +} + +# Default values +ENV="production" +SERVER_IP="" +FRONTEND_IP="" +DB_HOST="mysql" + +# Help message +show_help() { + echo "Usage: ./deploy.sh [OPTIONS]" + echo "Deploy the router dashboard application" + echo + echo "Options:" + echo " -s, --server-ip Server IP address (required)" + echo " -f, --frontend-ip Frontend IP address (defaults to server IP if not provided)" + echo " -d, --db-host Database host (defaults to mysql)" + echo " -e, --environment Environment (development/staging/production, defaults to production)" + echo " -h, --help Show this help message" + echo + echo "Example:" + echo " ./deploy.sh -s 192.168.1.100 -f 192.168.1.101 -e production" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -s|--server-ip) + SERVER_IP="$2" + shift 2 + ;; + -f|--frontend-ip) + FRONTEND_IP="$2" + shift 2 + ;; + -d|--db-host) + DB_HOST="$2" + shift 2 + ;; + -e|--environment) + ENV="$2" + shift 2 + ;; + -h|--help) + show_help + exit 0 + ;; + *) + print_message "$RED" "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +# Validate required parameters +if [ -z "$SERVER_IP" ]; then + print_message "$RED" "Error: Server IP is required" + show_help + exit 1 +fi + +# If frontend IP is not provided, use server IP +if [ -z "$FRONTEND_IP" ]; then + FRONTEND_IP=$SERVER_IP + print_message "$YELLOW" "Frontend IP not provided, using Server IP: $FRONTEND_IP" +fi + +# Export environment variables +export SERVER_IP +export FRONTEND_IP +export DB_HOST +export NODE_ENV=$ENV + +# Display deployment information +print_message "$GREEN" "\nDeployment Configuration:" +echo "Server IP: $SERVER_IP" +echo "Frontend IP: $FRONTEND_IP" +echo "Database Host: $DB_HOST" +echo "Environment: $ENV" +echo + +# Confirm deployment +read -p "Do you want to continue with deployment? (y/n) " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_message "$YELLOW" "Deployment cancelled" + exit 1 +fi + +# Start deployment +print_message "$GREEN" "\nStarting deployment..." + +# Pull latest changes +print_message "$YELLOW" "Pulling latest changes..." +git pull +check_status "Git pull" + +# Stop existing containers +print_message "$YELLOW" "Stopping existing containers..." +docker-compose down +check_status "Stopping containers" + +# Build containers +print_message "$YELLOW" "Building containers..." +docker-compose build +check_status "Building containers" + +# Start containers +print_message "$YELLOW" "Starting containers..." +docker-compose up -d +check_status "Starting containers" + +# Check container status +print_message "$YELLOW" "Checking container status..." +docker-compose ps +check_status "Container status check" + +print_message "$GREEN" "\nDeployment completed successfully!" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 5bbda1e..64957f8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,61 +5,86 @@ services: build: context: ./router-dashboard dockerfile: dockerfile + args: + - SERVER_IP=${SERVER_IP:-localhost} ports: - - "5173:5173" + - "${FRONTEND_PORT:-5173}:5173" environment: - - VITE_API_URL=${VITE_API_URL} + - SERVER_IP=${SERVER_IP:-localhost} + - FRONTEND_IP=${FRONTEND_IP:-localhost} + - VITE_API_URL=http://${SERVER_IP:-localhost}:${BACKEND_PORT:-3000}/api/v1 + - VITE_NODE_ENV=${NODE_ENV:-development} restart: always depends_on: backend: condition: service_healthy container_name: router_dashboard_frontend + networks: + - app_network + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "http://${SERVER_IP:-localhost}:5173"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s backend: build: context: ./ve-router-backend dockerfile: dockerfile ports: - - "3000:3000" + - "${BACKEND_PORT:-3000}:3000" environment: - - NODE_ENV=${NODE_ENV} - - DB_HOST=host.docker.internal - - DB_PORT=3306 - - DB_USER=ve_router_user - - DB_PASSWORD=ve_router_password - - DB_NAME=${DB_NAME} + - NODE_ENV=${NODE_ENV:-development} + - DB_HOST=${DB_HOST:-mysql} + - DB_PORT=${DB_PORT:-3306} + - DB_USER=${DB_USER:-ve_router_user} + - DB_PASSWORD=${DB_PASSWORD:-ve_router_password} + - DB_NAME=${DB_NAME:-ve_router_db} + - CORS_ORIGIN=http://${FRONTEND_IP:-localhost}:${FRONTEND_PORT:-5173},http://${SERVER_IP:-localhost}:${BACKEND_PORT:-3000} restart: always depends_on: mysql: - condition: service_healthy + condition: service_healthy healthcheck: - test: ["CMD", "nc", "-z", "localhost", "3000"] # Netcat check to see if port 3000 is open - interval: 30s # Check every 30 seconds - retries: 3 # Retry 3 times before marking unhealthy - start_period: 30s # Wait 30 seconds before starting health checks - timeout: 10s # Wait for 10 seconds for each health check to respond + test: ["CMD", "nc", "-z", "${SERVER_IP:-localhost}", "${BACKEND_PORT:-3000}"] + interval: 30s + retries: 3 + start_period: 30s + timeout: 10s + networks: + - app_network + container_name: router_dashboard_backend mysql: image: mysql:8.0 environment: - MYSQL_ROOT_PASSWORD: rootpassword - MYSQL_DATABASE: ve_router_db - MYSQL_USER: ve_router_user - MYSQL_PASSWORD: ve_router_password + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword} + MYSQL_DATABASE: ${DB_NAME:-ve_router_db} + MYSQL_USER: ${DB_USER:-ve_router_user} + MYSQL_PASSWORD: ${DB_PASSWORD:-ve_router_password} + ENVIRONMENT: ${NODE_ENV:-development} volumes: - mysql_data:/var/lib/mysql - # Correct paths for init scripts - - ./sql:/docker-entrypoint-initdb.d + - ./db-scripts:/docker-entrypoint-initdb.d:ro ports: - - "3306:3306" + - "${DB_PORT:-3306}:3306" command: --default-authentication-plugin=mysql_native_password restart: always healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "ve_router_user", "-pve_router_password"] + test: ["CMD", "mysqladmin", "ping", "-h", "${DB_HOST:-mysql}", "-u${DB_USER:-ve_router_user}", "-p${DB_PASSWORD:-ve_router_password}"] interval: 10s timeout: 5s retries: 5 start_period: 30s + networks: + - app_network + container_name: router_dashboard_mysql + +networks: + app_network: + driver: bridge volumes: - mysql_data: \ No newline at end of file + mysql_data: + name: router_dashboard_mysql_data \ No newline at end of file diff --git a/readme.txt b/readme.txt index 4854c08..a757553 100644 --- a/readme.txt +++ b/readme.txt @@ -15,4 +15,24 @@ user/password: ve_router_user/ve_router_password docker-compose down 7. Run below command to stop, remove and delete all the volumes Caution : if mysql has volumes then all the existing data will be erasesd -docker-compose down -v \ No newline at end of file +docker-compose down -v + +Deploy Instructions: + +1. Basic usage with just server IP: +./deploy.sh -s 192.168.1.100 +2.Specify different IPs for frontend and backend: +./deploy.sh -s 192.168.1.100 -f 192.168.1.101 +3.Specify environment: + ./deploy.sh -s 192.168.1.100 -e staging +4.Full configuration: +./deploy.sh -s 192.168.1.100 -f 192.168.1.101 -d mysql -e production +5.Run it with the help flag to see options: +./deploy.sh --help + +Important notes: + +In production, you should use HTTPS instead of HTTP +Make sure your firewall rules allow the necessary ports (3000, 5173, 3306) +Consider using a reverse proxy like Nginx in front of your services +The MySQL container is accessible to other containers through the service name "mysql" when using Docker networks \ No newline at end of file diff --git a/router-dashboard/.env b/router-dashboard/.env index 983a024..5132f4a 100644 --- a/router-dashboard/.env +++ b/router-dashboard/.env @@ -1,2 +1,2 @@ -VITE_API_URL=http://localhost:3000/api/v1 +VITE_API_URL=http://${SERVER_IP:-localhost}:3000/api/v1 VITE_NODE_ENV=development \ No newline at end of file diff --git a/router-dashboard/.env.production b/router-dashboard/.env.production new file mode 100644 index 0000000..f04b834 --- /dev/null +++ b/router-dashboard/.env.production @@ -0,0 +1,2 @@ +VITE_API_URL=http://${SERVER_IP}:3000/api/v1 +VITE_NODE_ENV=production \ No newline at end of file diff --git a/router-dashboard/src/components/dashboard/DashboardLayout.tsx b/router-dashboard/src/components/dashboard/DashboardLayout.tsx index 28815ca..0d4d707 100644 --- a/router-dashboard/src/components/dashboard/DashboardLayout.tsx +++ b/router-dashboard/src/components/dashboard/DashboardLayout.tsx @@ -36,11 +36,10 @@ const DashboardLayout: React.FC = () => { data = data.filter(router => { switch (activeFilter) { case 'active': - return router.routerActivity?.studies && - router.routerActivity.studies.length > 0; + return router.systemStatus.routerStatus === 'CONNECTED' && + router.routerActivity?.studies?.some(study => study.studyStatusCode === 'Active'); case 'critical': - return router.systemStatus.vpnStatus === 'VPN_DISCONNECTED' || - router.systemStatus.appStatus === 'DISK_CRITICAL' || + return router.systemStatus.routerStatus === 'DISCONNECTED' || router.diskStatus === 'DISK_CRITICAL'; case 'diskAlert': return router.diskUsage > 80; @@ -74,17 +73,18 @@ const DashboardLayout: React.FC = () => { return { total: routerData.length, active: routerData.filter(r => - r.routerActivity?.studies && - r.routerActivity.studies.length > 0 + r.systemStatus.routerStatus === 'CONNECTED' && // Router (VM, app, VPN) is up + r.routerActivity?.studies?.some(study => study.studyStatusCode === 'Active') // At least one study is active ).length, critical: routerData.filter(r => - r.systemStatus.vpnStatus === 'VPN_DISCONNECTED' || - r.systemStatus.appStatus === 'DISK_CRITICAL' || - r.diskStatus === 'DISK_CRITICAL' + r.systemStatus.routerStatus === 'DISCONNECTED' || // Router (VM, app, VPN) is down + r.diskStatus === 'DISK_CRITICAL' // Disk is critical ).length, - diskAlert: routerData.filter(r => r.diskUsage > 80).length + diskAlert: routerData.filter(r => r.diskUsage > 80).length // Disk usage alert }; }; + + const renderContent = () => { if (loading) { @@ -128,6 +128,7 @@ const DashboardLayout: React.FC = () => { activeFilter === 'active' ? 'ring-2 ring-blue-500' : '' }`} onClick={() => setActiveFilter('active')} + title="Study in transmit currently" >

Active Routers

{summary.active}

diff --git a/router-dashboard/src/components/dashboard/Navbar.tsx b/router-dashboard/src/components/dashboard/Navbar.tsx index e38a22b..b3928db 100644 --- a/router-dashboard/src/components/dashboard/Navbar.tsx +++ b/router-dashboard/src/components/dashboard/Navbar.tsx @@ -22,8 +22,8 @@ interface Tab { } const Navbar: React.FC = ({ activeTab, onTabChange }) => { - const [isCollapsed, setIsCollapsed] = useState(false); - const [isPinned, setIsPinned] = useState(true); + const [isCollapsed, setIsCollapsed] = useState(true); + const [isPinned, setIsPinned] = useState(false); const [isHovered, setIsHovered] = useState(false); const tabs: Tab[] = [ diff --git a/router-dashboard/src/components/dashboard/RouterTableRow.tsx b/router-dashboard/src/components/dashboard/RouterTableRow.tsx index a534524..6c2c2ce 100644 --- a/router-dashboard/src/components/dashboard/RouterTableRow.tsx +++ b/router-dashboard/src/components/dashboard/RouterTableRow.tsx @@ -2,13 +2,13 @@ import React from 'react'; import { ChevronRight, ChevronDown } from 'lucide-react'; import { RouterData } from '../../types'; -import { STATUS_COLORS, formatStatus, getStatusColor, getVMStatus, getSystemStatus } from '../../utils/statusHelpers'; +import { STATUS_COLORS, formatStatus, getStatusColor} from '../../utils/statusHelpers'; interface RouterTableRowProps { router: RouterData; expandedRows: Set; timeLeft: { [key: string]: number }; - onToggleExpansion: (id: number, section: 'activity' | 'status' | 'disk') => void; + onToggleExpansion: (id: number, section: 'router_details' |'activity' | 'status' | 'disk') => void; onExpandedContentHover: (id: number, section: 'activity' | 'status' | 'disk') => void; } @@ -41,6 +41,32 @@ export const RouterTableRow: React.FC = ({ return 'bg-green-500'; }; + const renderRouterDetailsPanel = () => ( +
onExpandedContentHover(router.id, 'router_details')} + > +
+
+
+

Router Details

+ +
+
+
+
Facility AET: {router.facilityAET}
+
OpenVPN IP: {router.openvpnIp}
+
Router VM Primary IP: {router.routerVmPrimaryIp}
+
+
+
+ +
+ ); + const renderActivityPanel = () => (
= ({

VM Status

- - {formatStatus(getVMStatus(router.lastSeen))} + + {formatStatus(router.systemStatus.vmStatus)}
@@ -156,7 +182,19 @@ export const RouterTableRow: React.FC = ({ {router.slNo} - {router.routerId} + + + {router.routerAlias} {router.facility} @@ -169,7 +207,8 @@ export const RouterTableRow: React.FC = ({ ) : ( )} - View Activity ({router.routerActivity.studies.length} studies) + + {router?.routerActivity?.studies?.[0]?.studyStatusCode || "Idle"} @@ -182,8 +221,8 @@ export const RouterTableRow: React.FC = ({ ) : ( )} - - {formatStatus(router.systemStatus.vpnStatus)} + + {formatStatus(router.systemStatus.routerStatus)} @@ -212,6 +251,13 @@ export const RouterTableRow: React.FC = ({ {/* Expandable Panels */} + {expandedRows.has(`${router.id}-router_details`) && ( + + + {renderRouterDetailsPanel()} + + + )} {expandedRows.has(`${router.id}-activity`) && ( diff --git a/router-dashboard/src/config/env.ts b/router-dashboard/src/config/env.ts index 7d59074..d26bf01 100644 --- a/router-dashboard/src/config/env.ts +++ b/router-dashboard/src/config/env.ts @@ -1,12 +1,12 @@ // src/config/env.ts interface Config { - apiUrl: string; - environment: string; - } - - const config: Config = { - apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:3000/api/v1', - environment: import.meta.env.VITE_NODE_ENV || 'development', - }; - - export default config; \ No newline at end of file + apiUrl: string; + environment: string; +} + +const config: Config = { + apiUrl: import.meta.env.VITE_API_URL, + environment: import.meta.env.VITE_NODE_ENV || 'development', +}; + +export default config; \ No newline at end of file diff --git a/router-dashboard/src/data/mockData.ts b/router-dashboard/src/data/mockData.ts index e2c08ce..a37d6cf 100644 --- a/router-dashboard/src/data/mockData.ts +++ b/router-dashboard/src/data/mockData.ts @@ -21,6 +21,9 @@ export const MOCK_ROUTERS: RouterData[] = [ routerId: 'RTR001', facility: 'City Hospital', routerAlias: 'Main-Router-1', + facilityAET: 'RTR_1', + openvpnIp: '10.8.0.101', + routerVmPrimaryIp: '192.168.0.101', lastSeen: '2024-03-07T14:30:00Z', diskStatus: 'Normal', diskUsage: 45, @@ -64,6 +67,9 @@ export const MOCK_ROUTERS: RouterData[] = [ routerId: 'RTR002', facility: 'Medical Center', routerAlias: 'Emergency-Router', + facilityAET: 'RTR_2', + openvpnIp: '10.8.0.102', + routerVmPrimaryIp: '192.168.0.102', lastSeen: '2024-03-07T14:25:00Z', diskStatus: 'Critical', diskUsage: 92, @@ -97,6 +103,9 @@ export const MOCK_ROUTERS: RouterData[] = [ routerId: 'RTR003', facility: 'Imaging Center', routerAlias: 'Radiology-Router', + facilityAET: 'RTR_3', + openvpnIp: '10.8.0.103', + routerVmPrimaryIp: '192.168.0.103', lastSeen: '2024-03-07T14:20:00Z', diskStatus: 'Warning', diskUsage: 78, diff --git a/router-dashboard/src/services/api.service.ts b/router-dashboard/src/services/api.service.ts index 4de683d..6c69f00 100644 --- a/router-dashboard/src/services/api.service.ts +++ b/router-dashboard/src/services/api.service.ts @@ -58,6 +58,9 @@ class ApiService { routerId: router.routerId, // Changed from router.router_id facility: router.facility, routerAlias: router.routerAlias, // Changed from router.router_alias + facilityAET: router.facilityAET, // Changed from router.facility_aet + openvpnIp: router.openvpnIp, // Changed from router.openvpn_ip + routerVmPrimaryIp: router.routerVmPrimaryIp, // Changed from router.router_vm_primary_ip lastSeen: router.lastSeen, // Changed from router.last_seen diskStatus: router.diskStatus, // Changed from router.disk_status_code diskUsage: router.diskUsage || 0, // Changed from router.disk_usage @@ -72,13 +75,17 @@ class ApiService { patientName: study.patientName, studyDate: study.studyDate, modality: study.modality, - studyDescription: study.studyDescription + studyDescription: study.studyDescription, + studyStatusCode: study.studyStatusCode + })) : [] }, systemStatus: { vpnStatus: router.systemStatus?.vpnStatus || 'unknown', appStatus: router.systemStatus?.appStatus || 'unknown', + vmStatus: router.systemStatus?.vmStatus || 'unknown', + routerStatus: router.systemStatus?.routerStatus || 'unknown', vms: Array.isArray(router.systemStatus?.vms) ? router.systemStatus.vms.map((vm: any) => ({ id: vm.id, diff --git a/router-dashboard/src/types/backend.ts b/router-dashboard/src/types/backend.ts index 6c6980b..95c378f 100644 --- a/router-dashboard/src/types/backend.ts +++ b/router-dashboard/src/types/backend.ts @@ -7,6 +7,7 @@ export interface BackendStudy { study_date: string; modality: string; study_description: string; + study_status_code: string; } export interface BackendVM { @@ -21,6 +22,9 @@ export interface BackendStudy { router_id: string; facility: string; router_alias: string; + facility_aet: string; + openvpn_ip: string; + router_vm_primary_ip: string; last_seen: string; disk_status_code: string; disk_usage: number; diff --git a/router-dashboard/src/types/index.ts b/router-dashboard/src/types/index.ts index adb7cd7..656b69a 100644 --- a/router-dashboard/src/types/index.ts +++ b/router-dashboard/src/types/index.ts @@ -7,6 +7,7 @@ export interface Study { studyDate: string; modality: string; studyDescription: string; + studyStatusCode: string; } export interface VM { @@ -27,6 +28,9 @@ export interface RouterData { routerId: string; facility: string; routerAlias: string; + facilityAET: string; + openvpnIp: string; + routerVmPrimaryIp: string; lastSeen: string; diskStatus: string; diskUsage: number; @@ -38,6 +42,8 @@ export interface RouterData { systemStatus: { vpnStatus: string; appStatus: string; + vmStatus: string; + routerStatus: string; vms: VM[]; containers: Container[]; }; diff --git a/router-dashboard/src/utils/statusHelpers.ts b/router-dashboard/src/utils/statusHelpers.ts index c4fda2f..c3a2fb7 100644 --- a/router-dashboard/src/utils/statusHelpers.ts +++ b/router-dashboard/src/utils/statusHelpers.ts @@ -49,32 +49,3 @@ export const formatStatus = (status: string): string => { return getStatus(getStatusAfterUnderscore(status)); }; -export const getVMStatus = (lastSeen: string | number | Date) => { - const currentTime = new Date(); - const lastSeenTime = new Date(lastSeen); - - // Use getTime() to get timestamps in milliseconds - const diffInMinutes = (currentTime.getTime() - lastSeenTime.getTime()) / (1000 * 60); - - return diffInMinutes > 1 ? 'NET_ONLINE' : 'NET_ONLINE'; //demo purpose returning only online -}; - -export const getSystemStatus = (lastSeen: string | number | Date, vpnStatus: string, appStatus:string) => { - const vmStatus = getVMStatus(lastSeen); - - const expectedStatuses = { - VPN_CONNECTED: 'VPN_CONNECTED', - CONTAINER_RUNNING: 'CONTAINER_RUNNING', - NET_ONLINE: 'NET_ONLINE', - }; - - if ( - vpnStatus === expectedStatuses.VPN_CONNECTED && - appStatus === expectedStatuses.CONTAINER_RUNNING && - vmStatus === expectedStatuses.NET_ONLINE - ) { - return 'CONNECTED'; - } - return 'DISCONNECTED'; - -}; \ No newline at end of file diff --git a/sql/02-seed_data.sql b/sql/02-seed_data.sql deleted file mode 100644 index 9a8ffa7..0000000 --- a/sql/02-seed_data.sql +++ /dev/null @@ -1,105 +0,0 @@ -DELIMITER // - -CREATE PROCEDURE seed_complete_router_system() -BEGIN - DECLARE done INT DEFAULT 0; - DECLARE table_name VARCHAR(64); - DECLARE table_cursor CURSOR FOR - SELECT table_name - FROM information_schema.tables - WHERE table_schema = DATABASE() - AND table_name IN ( - 'auth_log', 'user_sessions', 'user_router_access', 'users', - 'container_status_history', 'router_status_history', - 'container_status', 'dicom_study_overview', - 'router_settings_history', 'router_settings', - 'routers', 'status_type', 'status_category' - ); - - DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; - - -- Disable foreign key checks - SET FOREIGN_KEY_CHECKS=0; - - -- Truncate all tables dynamically - OPEN table_cursor; - truncate_loop: LOOP - FETCH table_cursor INTO table_name; - IF done THEN - LEAVE truncate_loop; - END IF; - - SET @query = CONCAT('TRUNCATE TABLE ', table_name); - PREPARE stmt FROM @query; - EXECUTE stmt; - DEALLOCATE PREPARE stmt; - END LOOP; - CLOSE table_cursor; - - -- Re-enable foreign key checks - SET FOREIGN_KEY_CHECKS=1; - - -- Insert Status Categories - INSERT INTO status_category (name, description) - VALUES - ('Network', 'Network related statuses'), - ('Disk', 'Disk related statuses'), - ('VPN', 'VPN connection statuses'), - ('License', 'License statuses'), - ('Container', 'Container related statuses') - ON DUPLICATE KEY UPDATE id = id; - - -- Insert Status Types - INSERT INTO status_type (category_id, name, code, description, severity) - VALUES - (1, 'Online', 'NET_ONLINE', 'System is online', 1), - (1, 'Offline', 'NET_OFFLINE', 'System is offline', 5), - (2, 'Normal', 'DISK_NORMAL', 'Disk usage is normal', 1), - (2, 'Warning', 'DISK_WARNING', 'Disk usage is high', 3), - (2, 'Critical', 'DISK_CRITICAL', 'Disk usage is critical', 5), - (3, 'Connected', 'VPN_CONNECTED', 'VPN is connected', 1), - (3, 'Disconnected', 'VPN_DISCONNECTED', 'VPN is disconnected', 5), - (5, 'Running', 'CONTAINER_RUNNING', 'Container is running', 1), - (5, 'Stopped', 'CONTAINER_STOPPED', 'Container is stopped', 5) - ON DUPLICATE KEY UPDATE id = id; - - -- Insert Routers - INSERT INTO routers (router_id, facility, router_alias, last_seen, vpn_status_code, disk_status_code, app_status_code, license_status, free_disk, total_disk, disk_usage) - VALUES - ('RTR001', 'Main Hospital', 'MAIN_RAD', NOW(), 'VPN_CONNECTED', 'DISK_NORMAL', 'CONTAINER_RUNNING', 'active', 500000000000, 1000000000000, 50.00), - ('RTR002', 'Emergency Center', 'ER_RAD', NOW(), 'VPN_CONNECTED', 'DISK_WARNING', 'CONTAINER_RUNNING', 'active', 400000000000, 1000000000000, 60.00), - ('RTR003', 'Imaging Center', 'IMG_CENTER', NOW(), 'VPN_CONNECTED', 'DISK_NORMAL', 'CONTAINER_RUNNING', 'active', 600000000000, 1000000000000, 40.00) - ON DUPLICATE KEY UPDATE id = id; - - -- Store Router IDs - SET @router1_id = (SELECT id FROM routers WHERE router_id = 'RTR001'); - SET @router2_id = (SELECT id FROM routers WHERE router_id = 'RTR002'); - SET @router3_id = (SELECT id FROM routers WHERE router_id = 'RTR003'); - - -- Insert Container Status - INSERT INTO container_status (router_id, container_name, status_code, created_at, updated_at) - VALUES - (1, 'router-cstore-scp', 'CONTAINER_RUNNING', NOW(), NOW()), - (1, 'router-cstore-scu', 'CONTAINER_RUNNING', NOW(), NOW()), - (2, 'router-cstore-scp', 'CONTAINER_RUNNING', NOW(), NOW()), - (2, 'router-cstore-scu', 'CONTAINER_RUNNING', NOW(), NOW()), - (3, 'router-cstore-scp', 'CONTAINER_RUNNING', NOW(), NOW()) - ON DUPLICATE KEY UPDATE id = id; - - -- Insert DICOM Study Overview - INSERT INTO dicom_study_overview ( - router_id, study_instance_uid, patient_id, patient_name, - accession_number, study_date, modality, study_description, - series_instance_uid, procedure_code, referring_physician_name - ) - VALUES - (@router1_id, '1.2.840.113619.2.55.3.283116435.276.1543707218.134', 'P1', 'John Doe', 'ACC1234', '2024-03-15', 'CT', 'Chest CT', '1.2.840.113619.2.55.3.283116435.276.1543707219.135', 'CT001', 'Dr. Smith'), - (@router2_id, '1.2.840.113619.2.55.3.283116435.276.1543707218.136', 'P2', 'Jane Doe', 'ACC1235', '2024-03-15', 'MR', 'Brain MRI', '1.2.840.113619.2.55.3.283116435.276.1543707219.137', 'MR001', 'Dr. Johnson') - ON DUPLICATE KEY UPDATE id = id; - -END // - -DELIMITER ; - --- Automatically call the procedure after creation -CALL seed_complete_router_system(); \ No newline at end of file diff --git a/ve-router-backend/.env b/ve-router-backend/.env index 913657a..382874f 100644 --- a/ve-router-backend/.env +++ b/ve-router-backend/.env @@ -1,15 +1,13 @@ - # Server Configuration -NODE_ENV=development +NODE_ENV=production PORT=3000 -CORS_ORIGIN=http://localhost:5173,http://localhost:3000 - +CORS_ORIGIN=http://${FRONTEND_IP}:5173,http://${SERVER_IP}:3000 # Database Configuration -DB_HOST=localhost +DB_HOST=${DB_HOST} DB_PORT=3306 -DB_USER=root -DB_PASSWORD=rootpassword +DB_USER=ve_router_user +DB_PASSWORD=ve_router_password DB_NAME=ve_router_db DB_CONNECTION_LIMIT=10 diff --git a/ve-router-backend/src/config/config.ts b/ve-router-backend/src/config/config.ts index b4312b0..0c51e86 100644 --- a/ve-router-backend/src/config/config.ts +++ b/ve-router-backend/src/config/config.ts @@ -1,22 +1,20 @@ // src/config/config.ts import dotenv from 'dotenv'; -// Initialize dotenv at the very start dotenv.config(); const config = { env: process.env.NODE_ENV || 'development', server: { port: parseInt(process.env.PORT || '3000', 10), - // Update this to include your frontend URL - corsOrigin: process.env.CORS_ORIGIN?.split(',') || ['http://localhost:5173', 'http://localhost:3000'], + corsOrigin: process.env.CORS_ORIGIN?.split(',') || ['*'], // In production, replace with actual domains apiPrefix: '/api/v1' }, db: { host: process.env.DB_HOST || 'localhost', port: parseInt(process.env.DB_PORT || '3306', 10), - user: process.env.DB_USER || 'root', - password: process.env.DB_PASSWORD || '', // Make sure this is getting the password + user: process.env.DB_USER || 've_router_user', + password: process.env.DB_PASSWORD || 've_router_password', database: process.env.DB_NAME || 've_router_db', connectionLimit: parseInt(process.env.DB_CONNECTION_LIMIT || '10', 10) }, @@ -26,13 +24,4 @@ const config = { } }; -// Add this for debugging -console.log('Database Config:', { - host: config.db.host, - user: config.db.user, - database: config.db.database, - // Don't log the password -}); - -export default config; - +export default config; \ No newline at end of file diff --git a/ve-router-backend/src/repositories/RouterRepository.ts b/ve-router-backend/src/repositories/RouterRepository.ts index 0cefefd..e8231d9 100644 --- a/ve-router-backend/src/repositories/RouterRepository.ts +++ b/ve-router-backend/src/repositories/RouterRepository.ts @@ -11,65 +11,65 @@ export class RouterRepository { // src/repositories/RouterRepository.ts // src/repositories/RouterRepository.ts -async updateVMs(routerId: string, vms: VMUpdate[]): Promise { - console.log('Repository: Starting VM update for router:', routerId); - const connection = await this.pool.getConnection(); - - try { - await connection.beginTransaction(); - console.log('Started transaction'); + async updateVMs(routerId: string, vms: VMUpdate[]): Promise { + console.log('Repository: Starting VM update for router:', routerId); + const connection = await this.pool.getConnection(); + + try { + await connection.beginTransaction(); + console.log('Started transaction'); - // First verify router exists - const [routers] = await connection.query( - 'SELECT id FROM routers WHERE router_id = ?', - [routerId] - ); - console.log('Router query result:', routers); + // First verify router exists + const [routers] = await connection.query( + 'SELECT id FROM routers WHERE router_id = ?', + [routerId] + ); + console.log('Router query result:', routers); - if (!Array.isArray(routers) || routers.length === 0) { - throw new Error(`Router ${routerId} not found`); - } + if (!Array.isArray(routers) || routers.length === 0) { + throw new Error(`Router ${routerId} not found`); + } - // Log each VM update - for (const vm of vms) { - console.log(`Processing VM ${vm.vm_number}`); - const [result]: any = await connection.query( - `UPDATE vm_details - SET status_code = ?, - updated_at = CURRENT_TIMESTAMP - WHERE router_id = ? AND vm_number = ?`, - [vm.status_code, routerId, vm.vm_number] - ); - console.log('Update result:', result); + // Log each VM update + for (const vm of vms) { + console.log(`Processing VM ${vm.vm_number}`); + const [result]: any = await connection.query( + `UPDATE vm_details + SET status_code = ?, + updated_at = CURRENT_TIMESTAMP + WHERE router_id = ? AND vm_number = ?`, + [vm.status_code, routerId, vm.vm_number] + ); + console.log('Update result:', result); - if (!result.affectedRows) { - console.log('No rows affected, attempting insert'); - await connection.query( - `INSERT INTO vm_details (router_id, vm_number, status_code) - VALUES (?, ?, ?)`, - [routerId, vm.vm_number, vm.status_code] - ); - } - } + if (!result.affectedRows) { + console.log('No rows affected, attempting insert'); + await connection.query( + `INSERT INTO vm_details (router_id, vm_number, status_code) + VALUES (?, ?, ?)`, + [routerId, vm.vm_number, vm.status_code] + ); + } + } - await connection.commit(); - console.log('Transaction committed'); + await connection.commit(); + console.log('Transaction committed'); - const [updatedVMs] = await connection.query( - `SELECT * FROM vm_details WHERE router_id = ? ORDER BY vm_number`, - [routerId] - ); - return updatedVMs; + const [updatedVMs] = await connection.query( + `SELECT * FROM vm_details WHERE router_id = ? ORDER BY vm_number`, + [routerId] + ); + return updatedVMs; - } catch (err) { - console.error('Repository error:', err); - await connection.rollback(); - throw err; - } finally { - connection.release(); - console.log('Connection released'); + } catch (err) { + console.error('Repository error:', err); + await connection.rollback(); + throw err; + } finally { + connection.release(); + console.log('Connection released'); + } } -} private async getRouterStudies(routerId: number): Promise { try { @@ -81,10 +81,12 @@ async updateVMs(routerId: string, vms: VMUpdate[]): Promise { patient_name as patientName, DATE_FORMAT(study_date, '%Y-%m-%d') as studyDate, modality, - study_description as studyDescription + study_description as studyDescription, + CONCAT(UPPER(SUBSTRING(study_status_code, 1, 1)), LOWER(SUBSTRING(study_status_code, 2))) as studyStatusCode FROM dicom_study_overview WHERE router_id = ? - ORDER BY study_date DESC`, + ORDER BY updated_at DESC + LIMIT 1`, [routerId] ); return rows as Study[]; @@ -126,32 +128,52 @@ async updateVMs(routerId: string, vms: VMUpdate[]): Promise { } } -private async getRouterContainers(routerId: number): Promise { - try { + private async getRouterContainers(routerId: number): Promise { + try { - // Then use this to query vm_details - const [rows] = await pool.query( - `SELECT - container_name, - status_code - FROM container_status - WHERE router_id = ?`, - [routerId] - ); - - logger.info(`Containers for router ${routerId}:`, rows); - return rows as Container[]; - } catch (error) { - logger.error(`Error fetching Containers for router ${routerId}:`, error); - return []; + // Then use this to query vm_details + const [rows] = await pool.query( + `SELECT + container_name, + status_code + FROM container_status + WHERE router_id = ?`, + [routerId] + ); + + logger.info(`Containers for router ${routerId}:`, rows); + return rows as Container[]; + } catch (error) { + logger.error(`Error fetching Containers for router ${routerId}:`, error); + return []; + } } -} + + private async calculateVMStatus (lastSeen: string | number | Date): Promise { + const currentTime = new Date(); + const lastSeenTime = new Date(lastSeen); + + // Use getTime() to get timestamps in milliseconds + const diffInMinutes = (currentTime.getTime() - lastSeenTime.getTime()) / (1000 * 60); + + return diffInMinutes > 1 ? 'NET_OFFLINE' : 'NET_ONLINE'; + }; + + private async calculateSystemStatus (vpnStatus: string, appStatus: string, vmStatus: string): Promise { + return vpnStatus === 'VPN_CONNECTED' && appStatus === 'CONTAINER_RUNNING' && vmStatus === 'NET_ONLINE' ? 'CONNECTED' : 'DISCONNECTED'; + }; private async transformDatabaseRouter(dbRouter: any, index: number): Promise { try { const studies = await this.getRouterStudies(dbRouter.id); - const vms = await this.getRouterVMs(dbRouter.id); + //const vms = await this.getRouterVMs(dbRouter.id); + const vms:VM[] = []; const containers = await this.getRouterContainers(dbRouter.id); + const lastSeen = new Date(dbRouter.last_seen).toISOString(); + const vpnStatus = dbRouter.vpn_status_code.toString(); + const appStatus = dbRouter.app_status_code.toString(); + const vmStatus = await this.calculateVMStatus(lastSeen); + const routerStatus = await this.calculateSystemStatus(vpnStatus, appStatus, vmStatus); return { id: dbRouter.id, @@ -159,7 +181,10 @@ private async getRouterContainers(routerId: number): Promise { routerId: dbRouter.router_id, facility: dbRouter.facility, routerAlias: dbRouter.router_alias, - lastSeen: new Date(dbRouter.last_seen).toISOString(), + facilityAET: dbRouter.facility_aet, + openvpnIp: dbRouter.openvpn_ip, + routerVmPrimaryIp: dbRouter.router_vm_primary_ip, + lastSeen: lastSeen, diskStatus: dbRouter.disk_status_code, diskUsage: parseFloat(dbRouter.disk_usage), freeDisk: parseInt(dbRouter.free_disk), @@ -168,8 +193,10 @@ private async getRouterContainers(routerId: number): Promise { studies }, systemStatus: { - vpnStatus: dbRouter.vpn_status_code, - appStatus: dbRouter.app_status_code, + vpnStatus: vpnStatus, + appStatus: appStatus, + vmStatus: vmStatus, + routerStatus: routerStatus, vms, containers } @@ -233,14 +260,17 @@ private async getRouterContainers(routerId: number): Promise { async create(router: Partial): Promise { const [result] = await pool.query( `INSERT INTO routers ( - router_id, facility, router_alias, last_seen, - vpn_status_code, disk_status_code, app_status_code, + router_id, facility, router_alias, facility_aet, openvpn_ip, router_vm_primary_ip, + last_seen, vpn_status_code, disk_status_code, app_status_code, license_status, free_disk, total_disk, disk_usage - ) VALUES (?, ?, ?, NOW(), ?, ?, ?, 'inactive', ?, ?, ?)`, + ) VALUES (?, ?, ?, ?, ?, ?, NOW(), ?, ?, ?, 'inactive', ?, ?, ?)`, [ router.routerId, router.facility, router.routerAlias, + router.facilityAET, + router.openvpnIp, + router.routerVmPrimaryIp, router.systemStatus?.vpnStatus || 'unknown', router.diskStatus || 'unknown', router.systemStatus?.appStatus || 'unknown', @@ -259,6 +289,9 @@ private async getRouterContainers(routerId: number): Promise { if (router.routerId) updates.router_id = router.routerId; if (router.facility) updates.facility = router.facility; if (router.routerAlias) updates.router_alias = router.routerAlias; + if (router.facilityAET) updates.facility_aet = router.facilityAET; + if (router.openvpnIp) updates.openvpn_ip = router.openvpnIp; + if (router.routerVmPrimaryIp) updates.router_vm_primary_ip = router.routerVmPrimaryIp; if (router.diskStatus) updates.disk_status_code = router.diskStatus; if (router.systemStatus?.vpnStatus) updates.vpn_status_code = router.systemStatus?.vpnStatus; diff --git a/ve-router-backend/src/services/DicomStudyService.ts b/ve-router-backend/src/services/DicomStudyService.ts index b5127fc..f3d5387 100644 --- a/ve-router-backend/src/services/DicomStudyService.ts +++ b/ve-router-backend/src/services/DicomStudyService.ts @@ -46,7 +46,7 @@ export class DicomStudyService { } } - // Commented, currently this field is inserted with active/idle + // Commented below, currently this field is inserted with active/idle // Validate status code //const isValidStatus = await this.isValidStatusCode(studyData.study_status_code); //if (!isValidStatus) { diff --git a/ve-router-backend/src/types/index.ts b/ve-router-backend/src/types/index.ts index 668bfc9..39a876f 100644 --- a/ve-router-backend/src/types/index.ts +++ b/ve-router-backend/src/types/index.ts @@ -1,21 +1,26 @@ // src/types/index.ts export interface RouterData { - id: number; // maps to backend 'id' - slNo: number; // maps to backend 'slNo' - routerId: string; // maps to backend 'router_id' - facility: string; // maps to backend 'facility' - routerAlias: string; // maps to backend 'router_alias' - lastSeen: string; // maps to backend 'last_seen' - diskStatus: string; // maps to backend 'disk_status_code' - diskUsage: number; // maps to backend 'disk_usage' - freeDisk: number; // maps to backend 'free_disk' - totalDisk: number; // maps to backend 'total_disk' + id: number; // maps to backend 'id' + slNo: number; // maps to backend 'slNo' + routerId: string; // maps to backend 'router_id' + facility: string; // maps to backend 'facility' + routerAlias: string; // maps to backend 'router_alias' + facilityAET: string; // maps to backend 'facility_aet' + openvpnIp: string; // maps to backend 'openvpn_ip' + routerVmPrimaryIp: string; // maps to backend 'router_vm_primary_ip' + lastSeen: string; // maps to backend 'last_seen' + diskStatus: string; // maps to backend 'disk_status_code' + diskUsage: number; // maps to backend 'disk_usage' + freeDisk: number; // maps to backend 'free_disk' + totalDisk: number; // maps to backend 'total_disk' routerActivity: { studies: Study[]; }; systemStatus: { - vpnStatus: string; // maps to backend 'vpn_status_code' - appStatus: string; // maps to backend 'app_status_code' + vpnStatus: string; // maps to backend 'vpn_status_code' + appStatus: string; // maps to backend 'app_status_code' + vmStatus: string; // router machine status + routerStatus: string; // overall operational status of the router vms: VM[]; containers: Container[]; };