node-red-contrib-code-analyzer
Version:
A Node-RED package that provides a background service to detect debugging artifacts in function nodes across Node-RED flows. Features performance monitoring (CPU, memory, event loop), queue monitoring, and Slack alerting.
254 lines (238 loc) • 11.8 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Code Quality Dashboard - Node-RED Analyzer</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js"></script>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<style>
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.card-hover:hover {
transform: translateY(-2px);
transition: transform 0.2s ease-in-out;
}
.metric-card {
background: linear-gradient(145deg, #ffffff 0%, #f8fafc 100%);
border: 1px solid #e2e8f0;
}
.trend-up { color: #10b981; }
.trend-down { color: #ef4444; }
.trend-stable { color: #6b7280; }
.quality-excellent { color: #10b981; }
.quality-good { color: #84cc16; }
.quality-fair { color: #f59e0b; }
.quality-poor { color: #ef4444; }
.loading-spinner {
border: 4px solid #f3f4f6;
border-top: 4px solid #3b82f6;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.chart-container {
position: relative;
height: 300px;
}
/* Error highlighting styles for clickable errors */
.error-item:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transform: translateY(-1px);
}
.error-glyph-margin {
background: #dc2626;
}
.highlighted-line-error {
background: rgba(220, 38, 38, 0.2);
border: 1px solid #dc2626;
}
/* Navigation modal and toast animations */
@keyframes slideInFromTop {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.navigation-toast {
animation: slideInFromTop 0.3s ease-out;
}
</style>
</head>
<body class="bg-gray-50">
<!-- Header -->
<header class="gradient-bg shadow-lg">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center py-6">
<div class="flex items-center">
<i class="fas fa-chart-line text-white text-3xl mr-3"></i>
<div>
<h1 class="text-3xl font-bold text-white">Code Quality Dashboard</h1>
<p class="text-blue-100">Real-time Node-RED code analysis and metrics</p>
</div>
</div>
<div class="flex items-center space-x-4">
<div class="text-white text-right">
<div class="text-sm opacity-75">Last Updated</div>
<div id="lastUpdated" class="font-semibold">--</div>
</div>
<button id="refreshBtn" class="bg-white bg-opacity-20 hover:bg-opacity-30 text-white px-4 py-2 rounded-lg transition-colors">
<i class="fas fa-sync-alt mr-2"></i>Refresh
</button>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- Loading State -->
<div id="loadingState" class="flex justify-center items-center py-16">
<div class="text-center">
<div class="loading-spinner mx-auto mb-4"></div>
<p class="text-gray-600">Loading dashboard data...</p>
</div>
</div>
<!-- Dashboard Content -->
<div id="dashboardContent" class="hidden">
<!-- Overview Cards -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<!-- Overall Quality Score -->
<div class="metric-card rounded-lg shadow-lg p-6 card-hover">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-600">Overall Quality</p>
<p id="overallQuality" class="text-3xl font-bold">--</p>
<div id="qualityGrade" class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium mt-2">
<span id="gradeText">--</span>
</div>
</div>
<div class="h-12 w-12 bg-blue-100 rounded-lg flex items-center justify-center">
<i class="fas fa-award text-blue-600 text-xl"></i>
</div>
</div>
<div class="mt-4 flex items-center">
<i id="qualityTrend" class="fas fa-arrow-up text-sm mr-1"></i>
<span id="qualityChange" class="text-sm font-medium">--</span>
</div>
</div>
<!-- Technical Debt -->
<div class="metric-card rounded-lg shadow-lg p-6 card-hover">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-600">Technical Debt</p>
<p id="technicalDebt" class="text-3xl font-bold text-orange-600">--</p>
<p class="text-xs text-gray-500 mt-2">Issues per node ratio</p>
</div>
<div class="h-12 w-12 bg-orange-100 rounded-lg flex items-center justify-center">
<i class="fas fa-exclamation-triangle text-orange-600 text-xl"></i>
</div>
</div>
<div class="mt-4 flex items-center">
<span id="totalIssues" class="text-sm font-medium text-gray-700">-- total issues</span>
</div>
</div>
<!-- Flows Analyzed -->
<div class="metric-card rounded-lg shadow-lg p-6 card-hover">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-600">Flows Analyzed</p>
<p id="totalFlows" class="text-3xl font-bold text-green-600">--</p>
<p class="text-xs text-gray-500 mt-2">Active flows</p>
</div>
<div class="h-12 w-12 bg-green-100 rounded-lg flex items-center justify-center">
<i class="fas fa-project-diagram text-green-600 text-xl"></i>
</div>
</div>
<div class="mt-4 flex items-center">
<span id="totalNodes" class="text-sm font-medium text-gray-700">-- function nodes</span>
</div>
</div>
<!-- Complexity Score -->
<div class="metric-card rounded-lg shadow-lg p-6 card-hover">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-600">Avg Complexity</p>
<p id="avgComplexity" class="text-3xl font-bold text-purple-600">--</p>
<p class="text-xs text-gray-500 mt-2">Complexity metric</p>
</div>
<div class="h-12 w-12 bg-purple-100 rounded-lg flex items-center justify-center">
<i class="fas fa-brain text-purple-600 text-xl"></i>
</div>
</div>
<div class="mt-4 flex items-center">
<i id="complexityTrend" class="fas fa-arrow-up text-sm mr-1"></i>
<span id="complexityChange" class="text-sm font-medium">--</span>
</div>
</div>
</div>
<!-- Charts Row -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
<!-- Quality Trends Chart -->
<div class="bg-white rounded-lg shadow-lg p-6">
<div class="flex items-center justify-between mb-6">
<h3 class="text-lg font-semibold text-gray-900">Quality Trends (24h)</h3>
<div class="flex space-x-2">
<button class="trend-btn px-3 py-1 text-xs rounded-full bg-blue-100 text-blue-800" data-hours="24">24h</button>
<button class="trend-btn px-3 py-1 text-xs rounded-full bg-gray-100 text-gray-600" data-hours="168">7d</button>
</div>
</div>
<div class="chart-container">
<canvas id="qualityTrendChart"></canvas>
</div>
</div>
<!-- Performance Metrics Chart -->
<div class="bg-white rounded-lg shadow-lg p-6">
<div class="flex items-center justify-between mb-6">
<h3 class="text-lg font-semibold text-gray-900">System Performance</h3>
<select id="performanceMetricSelect" class="text-sm border border-gray-300 rounded px-2 py-1">
<option value="cpu">CPU Usage</option>
<option value="memory">Memory Usage</option>
</select>
</div>
<div class="chart-container">
<canvas id="performanceChart"></canvas>
</div>
</div>
</div>
<!-- Flow Analysis and Problematic Nodes -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Flow Quality Breakdown -->
<div class="bg-white rounded-lg shadow-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-6">Flow Quality Breakdown</h3>
<div id="flowsList" class="space-y-4">
<!-- Flow items will be populated here -->
</div>
</div>
<!-- Most Problematic Nodes -->
<div class="bg-white rounded-lg shadow-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-6">Most Problematic Nodes</h3>
<div id="problematicNodesList" class="space-y-4">
<!-- Problematic nodes will be populated here -->
</div>
</div>
</div>
<!-- Alerts Section -->
<div class="mt-8">
<div class="bg-white rounded-lg shadow-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-6">Recent Alerts</h3>
<div id="alertsList" class="space-y-3">
<!-- Alerts will be populated here -->
</div>
</div>
</div>
</div>
</main>
<script src="dashboard.js"></script>
</body>
</html>