Started refactring
This commit is contained in:
parent
322d662011
commit
a3be6dd6b9
1
cloned_repos/mtn6
Submodule
1
cloned_repos/mtn6
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 456de12cca56c09bc1881660b163ac3b5dff593a
|
||||
37
config.json
Normal file
37
config.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"check_interval_seconds": 60,
|
||||
"projects": {
|
||||
"mtn6": {
|
||||
"name": "Mountain Top 6 (MTN6)",
|
||||
"repo_url": "http://192.168.5.191:3000/LCI/MTN6",
|
||||
"repo_dir": "./cloned_repos/mtn6",
|
||||
"branch": "main",
|
||||
"manifest_csv": "./manifests/MTN6 Equipment Manifest REV6(Conveyor List).csv",
|
||||
"scada_views_dir": "MTN6_SCADA/com.inductiveautomation.perspective/views/Detailed-Views",
|
||||
"drawing_texts_dir": "./extracted_texts/mtn6",
|
||||
"pdf_source_dir": "./pdfs/mtn6",
|
||||
"csv_cols": {
|
||||
"alias": "Alias",
|
||||
"panel": "Control Panel",
|
||||
"eq_type": "Equipment Type",
|
||||
"conv_type": "Type of Conveyor"
|
||||
}
|
||||
},
|
||||
"another_project": {
|
||||
"name": "Another Example Project",
|
||||
"repo_url": "http://example.com/git/another_project.git",
|
||||
"repo_dir": "./cloned_repos/another",
|
||||
"branch": "develop",
|
||||
"manifest_csv": "./manifests/another_manifest.csv",
|
||||
"scada_views_dir": "perspective/views/Area51",
|
||||
"drawing_texts_dir": "./extracted_texts/another",
|
||||
"pdf_source_dir": null,
|
||||
"csv_cols": {
|
||||
"alias": "DeviceTag",
|
||||
"panel": "Cabinet ID",
|
||||
"eq_type": "Description",
|
||||
"conv_type": "Category"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -52,11 +52,29 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<!-- Added Navigation -->
|
||||
<nav class="nav nav-pills">
|
||||
<a class="nav-link active" aria-current="page" href="/">SCADA Progress</a>
|
||||
<a class="nav-link" href="/drawings">Drawing Progress</a>
|
||||
<a class="nav-link" href="/conflicts">Conflicts</a>
|
||||
<!-- Project Selector -->
|
||||
<div class="row mb-3 align-items-center">
|
||||
<div class="col-auto">
|
||||
<label for="projectSelector" class="col-form-label">Project:</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select class="form-select" id="projectSelector">
|
||||
{% if projects %}
|
||||
{% for project in projects %}
|
||||
<option value="{{ project.id }}">{{ project.name }}</option>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<option value="" disabled>No projects configured</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Tabs -->
|
||||
<nav class="nav nav-pills mb-3">
|
||||
<a class="nav-link active" data-target-section="scada" href="#">SCADA Progress</a>
|
||||
<a class="nav-link" data-target-section="drawings" href="#">Drawing Progress</a>
|
||||
<a class="nav-link" data-target-section="conflicts" href="#">Conflicts</a>
|
||||
</nav>
|
||||
|
||||
<!-- SCADA Content Section -->
|
||||
@ -111,7 +129,7 @@
|
||||
|
||||
<!-- Status Bar -->
|
||||
<div class="status-bar">
|
||||
<span id="status-message">Initializing...</span> | Last Commit: <span id="last-commit">N/A</span>
|
||||
<span id="status-project"></span> <span id="status-message">Initializing...</span> | Last Commit: <span id="last-commit">N/A</span>
|
||||
</div>
|
||||
|
||||
<!-- Bootstrap Modal for Details -->
|
||||
@ -149,12 +167,28 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
// --- Global State Variables ---
|
||||
let chartInstancesScada = {}; // Separate instances for SCADA
|
||||
let chartInstancesDrawing = {}; // Separate instances for Drawing
|
||||
let progressDetailsData = {}; // Stores the raw data from SSE (shared)
|
||||
let previousCommitHash = null; // Single hash for the whole page
|
||||
let chartInstancesScada = {};
|
||||
let chartInstancesDrawing = {};
|
||||
let progressDetailsData = {}; // Stores the raw data from SSE for the current project
|
||||
let previousCommitHash = null;
|
||||
let detailsModalInstance = null;
|
||||
let currentVisibleSection = 'scada'; // Track visible section: 'scada', 'drawing', 'conflicts'
|
||||
let currentVisibleSection = 'scada';
|
||||
let currentProjectId = null; // Added
|
||||
let eventSource = null; // Added: Holds the current SSE connection
|
||||
|
||||
// --- DOM Elements ---
|
||||
const projectSelector = document.getElementById('projectSelector');
|
||||
const statusMessageElement = document.getElementById('status-message');
|
||||
const statusProjectElement = document.getElementById('status-project');
|
||||
const lastCommitElement = document.getElementById('last-commit');
|
||||
const scadaPanelsContainer = document.getElementById('scada-panels-progress');
|
||||
const drawingPanelsContainer = document.getElementById('drawing-panels-progress');
|
||||
const conflictsPanelContainer = document.getElementById('panels-conflicts');
|
||||
const overallScadaCanvas = document.getElementById('overall-scada-chart-canvas');
|
||||
const overallDrawingCanvas = document.getElementById('overall-drawing-chart-canvas');
|
||||
const overallScadaText = document.getElementById('overall-scada-text');
|
||||
const overallDrawingText = document.getElementById('overall-drawing-text');
|
||||
const conflictCountBadge = document.getElementById('conflict-count');
|
||||
|
||||
// --- Chart Configurations ---
|
||||
const scadaChartLabels = ['Found in SCADA', 'Not Found in SCADA'];
|
||||
@ -197,32 +231,64 @@
|
||||
}
|
||||
}
|
||||
|
||||
// --- UI Reset Function --- NEW
|
||||
function resetUIForNewProject() {
|
||||
console.log(`Resetting UI for project: ${currentProjectId}`);
|
||||
|
||||
// Clear status bar
|
||||
statusMessageElement.textContent = 'Loading data...';
|
||||
lastCommitElement.textContent = 'N/A';
|
||||
statusProjectElement.textContent = projectSelector.options[projectSelector.selectedIndex]?.text || '' ;
|
||||
|
||||
// Clear overall text
|
||||
overallScadaText.textContent = 'Found in SCADA: 0/0 (0%)';
|
||||
overallDrawingText.textContent = 'Found in Drawing: 0/0 (0%)';
|
||||
|
||||
// Clear panel containers
|
||||
scadaPanelsContainer.innerHTML = '<p>Loading panel data...</p>';
|
||||
drawingPanelsContainer.innerHTML = '<p>Loading panel data...</p>';
|
||||
conflictsPanelContainer.innerHTML = '<p>Loading conflict data...</p>';
|
||||
if (conflictCountBadge) conflictCountBadge.textContent = '0';
|
||||
|
||||
// Destroy existing charts
|
||||
Object.values(chartInstancesScada).forEach(chart => chart.destroy());
|
||||
Object.values(chartInstancesDrawing).forEach(chart => chart.destroy());
|
||||
chartInstancesScada = {};
|
||||
chartInstancesDrawing = {};
|
||||
|
||||
// Reset shared data (important!)
|
||||
progressDetailsData = {};
|
||||
previousCommitHash = null;
|
||||
|
||||
// Ensure the correct section is displayed (default to SCADA)
|
||||
showSection('scada'); // Will also update nav pills
|
||||
}
|
||||
|
||||
// --- Core UI Update Functions (One for each section) ---
|
||||
|
||||
function updateUIScadaCore(data) {
|
||||
console.log("Running core SCADA UI redraw logic for commit:", data.last_commit);
|
||||
progressDetailsData = data.progress; // Update shared raw data
|
||||
progressDetailsData = data.progress || {}; // Use empty object if progress is missing
|
||||
|
||||
// --- Overall SCADA Chart ---
|
||||
const overallData = progressDetailsData.overall;
|
||||
const overallTotal = overallData.total_csv;
|
||||
const overallFoundScada = overallData.found_both + overallData.found_scada_only;
|
||||
const overallNotFoundScada = overallData.found_drawing_only + overallData.missing_both;
|
||||
const overallData = progressDetailsData.overall || {};
|
||||
const overallTotal = overallData.total_csv || 0;
|
||||
const overallFoundScada = (overallData.found_both || 0) + (overallData.found_scada_only || 0);
|
||||
const overallNotFoundScada = (overallData.found_drawing_only || 0) + (overallData.missing_both || 0);
|
||||
const overallPercentageFound = overallTotal > 0 ? ((overallFoundScada / overallTotal) * 100).toFixed(1) : 0;
|
||||
const overallChartCounts = [overallFoundScada, overallNotFoundScada];
|
||||
|
||||
document.getElementById('overall-scada-text').textContent = `Found in SCADA: ${overallFoundScada}/${overallTotal} (${overallPercentageFound}%)`;
|
||||
overallScadaText.textContent = `Found in SCADA: ${overallFoundScada}/${overallTotal} (${overallPercentageFound}%)`;
|
||||
|
||||
// --- Only update/create chart if section is visible ---
|
||||
const isSectionVisible = (currentVisibleSection === 'scada');
|
||||
if (isSectionVisible) {
|
||||
const overallScadaCanvas = document.getElementById('overall-scada-chart-canvas');
|
||||
if (isSectionVisible && overallScadaCanvas) {
|
||||
if (chartInstancesScada['overall']) {
|
||||
if (JSON.stringify(chartInstancesScada['overall'].data.datasets[0].data) !== JSON.stringify(overallChartCounts)) {
|
||||
chartInstancesScada['overall'].data.datasets[0].data = overallChartCounts;
|
||||
chartInstancesScada['overall'].update('none');
|
||||
}
|
||||
} else if (overallScadaCanvas) {
|
||||
} else {
|
||||
console.log("Creating overall SCADA chart (visible).");
|
||||
const ctxOverall = overallScadaCanvas.getContext('2d');
|
||||
chartInstancesScada['overall'] = new Chart(ctxOverall, createChartConfig(overallChartCounts, overallTotal, 'scada', 'overall'));
|
||||
@ -237,37 +303,35 @@
|
||||
}
|
||||
|
||||
// --- SCADA Panel Charts ---
|
||||
const panelsContainer = document.getElementById('scada-panels-progress');
|
||||
const panelsData = progressDetailsData.panels || {};
|
||||
updatePanelCharts(panelsContainer, panelsData, chartInstancesScada, 'scada');
|
||||
updatePanelCharts(scadaPanelsContainer, panelsData, chartInstancesScada, 'scada');
|
||||
|
||||
console.log("Finished SCADA UI core redraw.");
|
||||
}
|
||||
|
||||
function updateUIDrawingCore(data) {
|
||||
console.log("Running core Drawing UI redraw logic for commit:", data.last_commit);
|
||||
progressDetailsData = data.progress; // Update shared raw data
|
||||
progressDetailsData = data.progress || {}; // Use empty object
|
||||
|
||||
// --- Overall Drawing Chart ---
|
||||
const overallData = progressDetailsData.overall;
|
||||
const overallTotal = overallData.total_csv;
|
||||
const overallFoundDrawing = overallData.found_both + overallData.found_drawing_only;
|
||||
const overallNotFoundDrawing = overallData.found_scada_only + overallData.missing_both;
|
||||
const overallData = progressDetailsData.overall || {};
|
||||
const overallTotal = overallData.total_csv || 0;
|
||||
const overallFoundDrawing = (overallData.found_both || 0) + (overallData.found_drawing_only || 0);
|
||||
const overallNotFoundDrawing = (overallData.found_scada_only || 0) + (overallData.missing_both || 0);
|
||||
const overallPercentageFound = overallTotal > 0 ? ((overallFoundDrawing / overallTotal) * 100).toFixed(1) : 0;
|
||||
const overallChartCounts = [overallFoundDrawing, overallNotFoundDrawing];
|
||||
|
||||
document.getElementById('overall-drawing-text').textContent = `Found in Drawing: ${overallFoundDrawing}/${overallTotal} (${overallPercentageFound}%)`;
|
||||
overallDrawingText.textContent = `Found in Drawing: ${overallFoundDrawing}/${overallTotal} (${overallPercentageFound}%)`;
|
||||
|
||||
// --- Only update/create chart if section is visible ---
|
||||
const isSectionVisible = (currentVisibleSection === 'drawings');
|
||||
if (isSectionVisible) {
|
||||
const overallDrawingCanvas = document.getElementById('overall-drawing-chart-canvas');
|
||||
if (isSectionVisible && overallDrawingCanvas) {
|
||||
if (chartInstancesDrawing['overall']) {
|
||||
if (JSON.stringify(chartInstancesDrawing['overall'].data.datasets[0].data) !== JSON.stringify(overallChartCounts)) {
|
||||
chartInstancesDrawing['overall'].data.datasets[0].data = overallChartCounts;
|
||||
chartInstancesDrawing['overall'].update('none');
|
||||
}
|
||||
} else if (overallDrawingCanvas) {
|
||||
} else {
|
||||
console.log("Creating overall drawing chart (visible).");
|
||||
const ctxOverall = overallDrawingCanvas.getContext('2d');
|
||||
chartInstancesDrawing['overall'] = new Chart(ctxOverall, createChartConfig(overallChartCounts, overallTotal, 'drawing', 'overall'));
|
||||
@ -282,27 +346,25 @@
|
||||
}
|
||||
|
||||
// --- Drawing Panel Charts (call updatePanelCharts, which also checks visibility/destroys) ---
|
||||
const panelsContainer = document.getElementById('drawing-panels-progress');
|
||||
const panelsData = progressDetailsData.panels || {};
|
||||
console.log(`[updateUIDrawingCore] Found drawing panels container:`, panelsContainer ? panelsContainer.id : 'Not Found'); // Added Log
|
||||
updatePanelCharts(panelsContainer, panelsData, chartInstancesDrawing, 'drawings'); // Changed context to plural 'drawings'
|
||||
updatePanelCharts(drawingPanelsContainer, panelsData, chartInstancesDrawing, 'drawings'); // Changed context to plural 'drawings'
|
||||
|
||||
console.log("Finished Drawing UI core redraw.");
|
||||
}
|
||||
|
||||
function updateUIConflictsCore(data) {
|
||||
console.log("Running core Conflicts UI redraw logic for commit:", data.last_commit);
|
||||
progressDetailsData = data.progress; // Update shared raw data
|
||||
progressDetailsData = data.progress || {}; // Use empty object
|
||||
|
||||
const panelsContainer = document.getElementById('panels-conflicts');
|
||||
panelsContainer.innerHTML = ''; // Clear previous
|
||||
conflictsPanelContainer.innerHTML = ''; // Clear previous
|
||||
|
||||
const panelsData = progressDetailsData.panels;
|
||||
const panelsData = progressDetailsData.panels || {};
|
||||
let totalConflicts = 0;
|
||||
let panelsWithConflicts = 0;
|
||||
|
||||
if (!panelsData || Object.keys(panelsData).length === 0) {
|
||||
panelsContainer.innerHTML = '<p class="text-center fst-italic">No panel data available yet.</p>';
|
||||
if (Object.keys(panelsData).length === 0) {
|
||||
conflictsPanelContainer.innerHTML = '<p class="text-center fst-italic">No panel data available yet.</p>';
|
||||
} else {
|
||||
const sortedPanels = Object.keys(panelsData).sort();
|
||||
sortedPanels.forEach(panelName => {
|
||||
@ -315,7 +377,7 @@
|
||||
const panelHeader = document.createElement('h4');
|
||||
panelHeader.className = 'mt-4 mb-2';
|
||||
panelHeader.textContent = `${panelName} (${conflictsList.length} conflicts)`;
|
||||
panelsContainer.appendChild(panelHeader);
|
||||
conflictsPanelContainer.appendChild(panelHeader);
|
||||
|
||||
const table = document.createElement('table');
|
||||
table.className = 'table table-sm table-striped table-hover table-bordered';
|
||||
@ -332,24 +394,27 @@
|
||||
row.insertCell().textContent = item.equipment_type || 'N/A';
|
||||
row.insertCell().textContent = item.conveyor_type || 'N/A';
|
||||
});
|
||||
panelsContainer.appendChild(table);
|
||||
conflictsPanelContainer.appendChild(table);
|
||||
}
|
||||
});
|
||||
if (panelsWithConflicts === 0) {
|
||||
panelsContainer.innerHTML = '<p class="text-center fst-italic">No conflicts found across all panels.</p>';
|
||||
conflictsPanelContainer.innerHTML = '<p class="text-center fst-italic">No conflicts found across all panels.</p>';
|
||||
}
|
||||
}
|
||||
// Update total count badge
|
||||
const countBadge = document.getElementById('conflict-count');
|
||||
if (countBadge) {
|
||||
countBadge.textContent = totalConflicts;
|
||||
countBadge.style.display = totalConflicts > 0 ? 'inline-block' : 'none';
|
||||
if (conflictCountBadge) {
|
||||
conflictCountBadge.textContent = totalConflicts;
|
||||
conflictCountBadge.style.display = totalConflicts > 0 ? 'inline-block' : 'none';
|
||||
}
|
||||
console.log("Finished Conflicts UI core redraw.");
|
||||
}
|
||||
|
||||
// --- Generic Panel Chart Update Logic ---
|
||||
function updatePanelCharts(panelsContainer, panelsData, chartInstances, context) { // context: 'scada' or 'drawing'
|
||||
if (!panelsContainer) {
|
||||
console.error(`[updatePanelCharts] Invalid container provided for context: ${context}`);
|
||||
return;
|
||||
}
|
||||
const incomingPanelNames = new Set(Object.keys(panelsData).sort());
|
||||
const existingInstanceNames = new Set(Object.keys(chartInstances).filter(k => k !== 'overall'));
|
||||
|
||||
@ -374,44 +439,56 @@
|
||||
|
||||
incomingPanelNames.forEach(panelName => {
|
||||
const panel = panelsData[panelName];
|
||||
const panelTotal = panel.total;
|
||||
const panelTotal = panel.total || 0;
|
||||
let panelChartCounts;
|
||||
if (context === 'scada') {
|
||||
panelChartCounts = [panel.found_both + panel.found_scada_only, panel.found_drawing_only + panel.missing_both];
|
||||
panelChartCounts = [(panel.found_both || 0) + (panel.found_scada_only || 0), (panel.found_drawing_only || 0) + (panel.missing_both || 0)];
|
||||
} else { // drawing
|
||||
panelChartCounts = [panel.found_both + panel.found_drawing_only, panel.found_scada_only + panel.missing_both];
|
||||
panelChartCounts = [(panel.found_both || 0) + (panel.found_drawing_only || 0), (panel.found_scada_only || 0) + (panel.missing_both || 0)];
|
||||
}
|
||||
|
||||
// --- Only update/create chart if section is visible ---
|
||||
if (isSectionVisible) {
|
||||
let canvas = document.getElementById(`chart-${context}-${panelName}`);
|
||||
let chartContainer = document.getElementById(`chart-container-${context}-${panelName}`);
|
||||
|
||||
if (chartInstances[panelName]) {
|
||||
// Update existing chart if data changed
|
||||
if (JSON.stringify(chartInstances[panelName].data.datasets[0].data) !== JSON.stringify(panelChartCounts)) {
|
||||
console.log(`Updating ${context} chart data for panel (visible): ${panelName}`);
|
||||
chartInstances[panelName].data.datasets[0].data = panelChartCounts;
|
||||
chartInstances[panelName].update('none');
|
||||
}
|
||||
} else {
|
||||
let canvas = document.getElementById(`chart-${context}-${panelName}`); // Use context in ID
|
||||
if (canvas) {
|
||||
console.log(`Recreating ${context} chart instance for panel (visible): ${panelName}`);
|
||||
const ctx = canvas.getContext('2d');
|
||||
chartInstances[panelName] = new Chart(ctx, createChartConfig(panelChartCounts, panelTotal, context, panelName));
|
||||
} else {
|
||||
// Create new chart instance and potentially elements
|
||||
if (!chartContainer) {
|
||||
console.log(`Creating new ${context} panel elements and chart (visible) for: ${panelName}`);
|
||||
const chartContainer = document.createElement('div');
|
||||
chartContainer.id = `chart-container-${context}-${panelName}`; // Use context in ID
|
||||
chartContainer = document.createElement('div');
|
||||
chartContainer.id = `chart-container-${context}-${panelName}`;
|
||||
chartContainer.className = 'chart-container';
|
||||
const label = document.createElement('span');
|
||||
label.className = 'chart-label'; label.textContent = panelName;
|
||||
canvas = document.createElement('canvas'); // Reassign canvas variable
|
||||
canvas.id = `chart-${context}-${panelName}`; // Use context in ID
|
||||
label.className = 'chart-label';
|
||||
label.textContent = panelName;
|
||||
canvas = document.createElement('canvas');
|
||||
canvas.id = `chart-${context}-${panelName}`;
|
||||
canvas.className = 'panel-chart-canvas';
|
||||
chartContainer.appendChild(label);
|
||||
chartContainer.appendChild(canvas);
|
||||
// Added Log before append
|
||||
console.log(`[updatePanelCharts] Appending chartContainer (${chartContainer.id}) to panelsContainer (${panelsContainer ? panelsContainer.id : 'null'})`);
|
||||
panelsContainer.appendChild(chartContainer); // Append to the main panels progress div
|
||||
panelsContainer.appendChild(chartContainer);
|
||||
} else if (!canvas) {
|
||||
console.warn(`Container for ${context}-${panelName} exists, but canvas is missing. Recreating canvas.`);
|
||||
canvas = document.createElement('canvas');
|
||||
canvas.id = `chart-${context}-${panelName}`;
|
||||
canvas.className = 'panel-chart-canvas';
|
||||
chartContainer.appendChild(canvas); // Append to existing container
|
||||
}
|
||||
|
||||
if (canvas) {
|
||||
console.log(`Creating new ${context} chart instance for panel (visible): ${panelName}`);
|
||||
const ctx = canvas.getContext('2d');
|
||||
chartInstances[panelName] = new Chart(ctx, createChartConfig(panelChartCounts, panelTotal, context, panelName));
|
||||
} else {
|
||||
console.error(`Failed to get or create canvas for ${context}-${panelName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -424,14 +501,15 @@
|
||||
}
|
||||
|
||||
existingInstanceNames.forEach(panelName => {
|
||||
if (!incomingPanelNames.has(panelName)) {
|
||||
console.log(`Removing ${context} panel elements and chart for: ${panelName}`);
|
||||
// Ensure chart is destroyed before removing element
|
||||
const shouldRemove = !incomingPanelNames.has(panelName) || !isSectionVisible;
|
||||
if (shouldRemove) {
|
||||
const reason = !isSectionVisible ? 'section hidden' : 'data removed';
|
||||
console.log(`Removing ${context} panel elements and chart for: ${panelName} (Reason: ${reason})`);
|
||||
if (chartInstances[panelName]) {
|
||||
chartInstances[panelName].destroy();
|
||||
delete chartInstances[panelName];
|
||||
}
|
||||
const chartElement = document.getElementById(`chart-container-${context}-${panelName}`); // Use context
|
||||
const chartElement = document.getElementById(`chart-container-${context}-${panelName}`);
|
||||
if (chartElement) {
|
||||
chartElement.remove();
|
||||
}
|
||||
@ -445,6 +523,9 @@
|
||||
const colors = context === 'scada' ? scadaChartColors : drawingChartColors;
|
||||
const datasetLabel = context === 'scada' ? 'SCADA Match' : 'Drawing Match';
|
||||
|
||||
// Get the actual total count for percentage calculation
|
||||
const chartTotal = (identifier === 'overall' && progressDetailsData.overall) ? (progressDetailsData.overall.total_csv || 0) : total;
|
||||
|
||||
return {
|
||||
type: 'pie',
|
||||
data: {
|
||||
@ -469,10 +550,7 @@
|
||||
if (label) label += ': ';
|
||||
const value = ctxTooltip.parsed;
|
||||
if (value !== null) label += value;
|
||||
// Use overallTotal for overall chart, panelTotal otherwise (How to get panelTotal here? Needs rethinking)
|
||||
// Workaround: Don't show percentage on panel tooltips for now
|
||||
const chartTotal = (identifier === 'overall' && progressDetailsData.overall) ? progressDetailsData.overall.total_csv : null;
|
||||
if (chartTotal && chartTotal > 0) {
|
||||
if (chartTotal > 0) {
|
||||
label += ` (${((value / chartTotal) * 100).toFixed(1)}%)`;
|
||||
}
|
||||
return label;
|
||||
@ -486,11 +564,12 @@
|
||||
|
||||
// --- Wrapper function called by debouncer (Handles all sections) ---
|
||||
function processUpdate(data) {
|
||||
console.log("Processing update for commit:", data.last_commit);
|
||||
console.log(`Processing update for project ${currentProjectId}, commit:`, data.last_commit);
|
||||
|
||||
// Always update status bar and commit hash text immediately
|
||||
document.getElementById('status-message').textContent = data.status;
|
||||
document.getElementById('last-commit').textContent = data.last_commit || 'N/A';
|
||||
// Always update status bar immediately
|
||||
statusMessageElement.textContent = data.status || 'Status unavailable';
|
||||
lastCommitElement.textContent = data.last_commit || 'N/A';
|
||||
statusProjectElement.textContent = projectSelector.options[projectSelector.selectedIndex]?.text || '' ;
|
||||
|
||||
// *** Strict Check: Only proceed if commit hash has changed ***
|
||||
if (data.last_commit && data.last_commit !== previousCommitHash) {
|
||||
@ -521,10 +600,10 @@
|
||||
: (context === 'scada' ? 'Not Found in SCADA' : 'Not Found in Drawing');
|
||||
|
||||
if (identifier === '__overall__') {
|
||||
sourceData = progressDetailsData.overall;
|
||||
sourceData = progressDetailsData?.overall;
|
||||
panelNameDisplay = "Overall";
|
||||
} else {
|
||||
sourceData = progressDetailsData.panels ? progressDetailsData.panels[identifier] : null;
|
||||
sourceData = progressDetailsData?.panels?.[identifier];
|
||||
panelNameDisplay = identifier;
|
||||
}
|
||||
|
||||
@ -581,7 +660,7 @@
|
||||
// --- Trigger update for the now-visible section ---
|
||||
// The update function will check visibility internally before drawing charts.
|
||||
if (progressDetailsData && Object.keys(progressDetailsData).length > 0) {
|
||||
const updateData = { progress: progressDetailsData }; // Pass existing data
|
||||
const updateData = { progress: progressDetailsData, last_commit: previousCommitHash }; // Pass existing data
|
||||
console.log(`Calling update function for now-visible section: ${sectionId}`);
|
||||
// Use setTimeout to ensure DOM update (display: block) is processed first
|
||||
if (sectionId === 'scada') {
|
||||
@ -636,26 +715,92 @@
|
||||
showSection('scada');
|
||||
});
|
||||
|
||||
// --- Connect to SSE stream (Single connection) ---
|
||||
console.log("Initializing SSE connection...");
|
||||
const eventSource = new EventSource("/stream");
|
||||
|
||||
eventSource.onmessage = function(event) {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
debouncedProcessUpdate(data); // Call the single debounced processor
|
||||
} catch (error) {
|
||||
console.error("Error parsing SSE data:", error);
|
||||
document.getElementById('status-message').textContent = 'Error processing update from server.';
|
||||
// --- SSE Connection Handling --- NEW/MODIFIED
|
||||
function connectSSE(projectId) {
|
||||
if (!projectId) {
|
||||
console.error("No project ID provided for SSE connection.");
|
||||
statusMessageElement.textContent = 'No project selected.';
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
eventSource.onerror = function(err) {
|
||||
console.error("EventSource failed:", err);
|
||||
document.getElementById('status-message').textContent = 'Connection to server lost. Retrying...';
|
||||
};
|
||||
// Close existing connection if open
|
||||
if (eventSource) {
|
||||
console.log(`Closing previous SSE connection for project ${currentProjectId}`);
|
||||
eventSource.close();
|
||||
eventSource = null;
|
||||
}
|
||||
|
||||
console.log("SSE handler set up.");
|
||||
currentProjectId = projectId;
|
||||
console.log(`Initializing SSE connection for project: ${projectId}...`);
|
||||
resetUIForNewProject(); // Reset UI elements before connecting
|
||||
|
||||
const url = `/stream/${projectId}`;
|
||||
eventSource = new EventSource(url);
|
||||
|
||||
eventSource.onopen = function() {
|
||||
console.log(`SSE connection opened successfully for ${projectId} at ${url}`);
|
||||
statusMessageElement.textContent = 'Connected, waiting for data...';
|
||||
};
|
||||
|
||||
eventSource.onmessage = function(event) {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
debouncedProcessUpdate(data); // Call the debounced processor
|
||||
} catch (error) {
|
||||
console.error("Error parsing SSE data:", error, "Data:", event.data);
|
||||
statusMessageElement.textContent = 'Error processing update from server.';
|
||||
}
|
||||
};
|
||||
|
||||
eventSource.onerror = function(err) {
|
||||
console.error(`EventSource failed for ${projectId}:`, err);
|
||||
statusMessageElement.textContent = 'Connection to server lost or error. Retrying...';
|
||||
// EventSource attempts reconnection automatically, but we might want
|
||||
// to implement custom backoff or notification logic here.
|
||||
// If the error is fatal (e.g., 404), we might want to stop retrying.
|
||||
if (eventSource.readyState === EventSource.CLOSED) {
|
||||
console.log(`SSE connection permanently closed for ${projectId}.`);
|
||||
// Maybe disable UI or show persistent error?
|
||||
}
|
||||
};
|
||||
|
||||
console.log(`SSE handler set up for ${projectId}.`);
|
||||
}
|
||||
|
||||
// --- Initialization --- MODIFIED
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log("DOM Loaded, setting up...");
|
||||
|
||||
// Setup Navigation Tabs
|
||||
document.querySelectorAll('.nav-link[data-target-section]').forEach(link => {
|
||||
link.addEventListener('click', (event) => {
|
||||
event.preventDefault(); // Prevent page reload/hash change
|
||||
const sectionId = link.getAttribute('data-target-section');
|
||||
showSection(sectionId);
|
||||
});
|
||||
});
|
||||
|
||||
// Setup Project Selector
|
||||
if (projectSelector) {
|
||||
projectSelector.addEventListener('change', (event) => {
|
||||
const selectedProjectId = event.target.value;
|
||||
console.log("Project selection changed to:", selectedProjectId);
|
||||
connectSSE(selectedProjectId);
|
||||
});
|
||||
|
||||
// Initial Connection
|
||||
const initialProjectId = projectSelector.value; // Get value of the pre-selected option
|
||||
if (initialProjectId) {
|
||||
connectSSE(initialProjectId);
|
||||
} else {
|
||||
console.warn("No initial project selected or no projects available.");
|
||||
statusMessageElement.textContent = 'Please select a project.';
|
||||
}
|
||||
} else {
|
||||
console.error("Project selector element not found.");
|
||||
statusMessageElement.textContent = 'Error: Project selector missing.';
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user