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[]; };