wellwatch-analytics / index.html
zanape's picture
dropdown meny should fill the page, not necessary with titble above dropdown
2bb7e71 verified
Raw
History Blame Contribute Delete
16.3 kB
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Well Production Dashboard</title>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<custom-navbar></custom-navbar>
<div class="header-container">
<h1>FluidMagic SPD Welltest Converter</h1>
<div class="intro-section">
<img src="{{ url_for('static', filename='spd_image.png') }}" alt="Intro Image" class="intro-image">
<p class="intro-text">
This application allows for reading of welltest data from IMS database with correct SPD tags to get measured actual production rates.
The welltest data is converted to consistent well stream compositions and corresponding PVT properties using the FluidMagic library.
Select a facility and well to view test results and production charts.
by curtesy of the Equinor SPD and FluidMagic PVT groups.
</p>
</div>
<div class="select-row">
<div class="select-group">
<label for="gov_fcty_name">Facility</label>
<select id="gov_fcty_name" class="form-select">
<option value="">Select Facility</option>
{% for f in fac_codes %}
<option value="{{ f }}">{{ f }}</option>
{% endfor %}
</select>
</div>
<div class="select-group">
<label for="well_select">Well</label>
<select id="well_select" class="form-select" disabled>
<option value="">Select a facility first</option>
</select>
</div>
</div>
</div>
<div class="content-row">
<div class="table-container" id="test_results">
<div class="results-placeholder">
<div class="placeholder-text">
<i class="fas fa-table"></i> Select a well to view test results
</div>
</div>
</div>
<div class="chart-container" id="plot">
<div class="chart-placeholder">
<div class="placeholder-text">
<i class="fas fa-chart-line"></i> Select a well to view production chart
</div>
</div>
</div>
</div>
<script src="components/navbar.js"></script>
<script>
const facilitySelect = document.getElementById('gov_fcty_name');
const wellSelect = document.getElementById('well_select');
const resultsDiv = document.getElementById('test_results');
const plotDiv = document.getElementById('plot');
// Format numbers to 1 decimal place
const formatNumber = (num) => {
if (num === null || num === undefined) return '';
return Number(num).toFixed(1);
};
// When facility changes → fetch wells
facilitySelect.addEventListener('change', function() {
const selectedFacility = this.value;
if (!selectedFacility) {
wellSelect.innerHTML = '<option value="">-- Select a facility first --</option>';
wellSelect.disabled = true;
resultsDiv.innerHTML = '';
plotDiv.innerHTML = '';
return;
}
fetch(`/api/get_wellnames?facility=${encodeURIComponent(selectedFacility)}`)
.then(response => response.json())
.then(data => {
wellSelect.innerHTML = '';
if (data.length === 0) {
wellSelect.innerHTML = '<option value="">No wells found</option>';
wellSelect.disabled = true;
} else {
wellSelect.innerHTML = '<option value="">-- Select Well --</option>';
data.forEach(f => {
const option = document.createElement('option');
option.value = f;
option.textContent = f;
wellSelect.appendChild(option);
});
wellSelect.disabled = false;
}
})
.catch(err => {
console.error('Error fetching wells:', err);
wellSelect.innerHTML = '<option value="">Error loading wells</option>';
wellSelect.disabled = true;
});
});
// When well changes → fetch test results & update table + plot
wellSelect.addEventListener('change', function() {
const facility = facilitySelect.value;
const well = this.value;
if (!well) {
resultsDiv.innerHTML = '';
plotDiv.innerHTML = '';
return;
}
resultsDiv.innerHTML = '<p>Loading test results...</p>';
plotDiv.innerHTML = '';
fetch(`/api/get_test_results?facility=${encodeURIComponent(facility)}&well=${encodeURIComponent(well)}`)
.then(response => response.json())
.then(data => {
if (!data || data.length === 0) {
resultsDiv.innerHTML = '<p>No test results found.</p>';
plotDiv.innerHTML = '';
return;
}
// Build table
let html = `
<h2>Test Results for Well: ${well}</h2>
<table>
<tr>
<th>TEST_START_DATE</th>
<th>TEST_END_DATE</th>
<th>OIL_RATE</th>
<th>GAS_RATE</th>
<th>WATER_RATE</th>
<th>WHP</th>
<th>WHT</th>
<th>AVG_DOWNHOLE_PRESS</th>
<th>AVG_DOWNHOLE_TEMP</th>
<th>Separator Avg Oil Rate [Sm3/d]</th>
<th>Separator Avg Oil Rate Actual [m3/d]</th>
</tr>
`;
const dates = [];
const oilRates = [];
const oilSepRates = [];
data.forEach(row => {
html += `
<tr>
<td>${row.TEST_START_DATE || ''}</td>
<td>${row.TEST_END_DATE || ''}</td>
<td>${formatNumber(row.OIL_RATE)}</td>
<td>${formatNumber(row.GAS_RATE)}</td>
<td>${formatNumber(row.WATER_RATE)}</td>
<td>${formatNumber(row.WHP)}</td>
<td>${formatNumber(row.WHT)}</td>
<td>${formatNumber(row.AVG_DOWNHOLE_PRESS)}</td>
<td>${formatNumber(row.AVG_DOWNHOLE_TEMP)}</td>
<td>${formatNumber(row['Separator Avg Oil Rate'])}</td>
<td>${formatNumber(row['Separator Avg Oil Rate Actual'])}</td>
</tr>
`;
const date = row.TEST_START_DATE || row.TEST_END_DATE;
if (date) {
dates.push(date);
oilRates.push(row.OIL_RATE || 0);
oilSepRates.push(row['Separator Avg Oil Rate Actual'] || 0);
}
});
html += '</table>';
resultsDiv.innerHTML = html;
// Plotly chart
const traces = [
{
x: dates,
y: oilRates,
mode: 'lines+markers',
name: 'Oil Rate',
line: { shape: 'spline' }
},
{
x: dates,
y: oilSepRates,
mode: 'lines+markers',
name: 'Oil Separator Rate',
line: { shape: 'spline' }
}
];
const layout = {
title: `Production Rates for ${well}`,
xaxis: { title: 'Test Date' },
yaxis: { title: 'Rate' },
legend: { orientation: 'h', y: -0.2 }
};
Plotly.newPlot('plot', traces, layout, { responsive: true });
})
.catch(err => {
console.error('Error fetching test results:', err);
resultsDiv.innerHTML = '<p>Error loading test results</p>';
plotDiv.innerHTML = '';
});
});
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Well Production Dashboard</title>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<custom-navbar></custom-navbar>
<div class="header-container">
<h1>FluidMagic SPD Welltest Converter</h1>
<div class="intro-section">
<img src="{{ url_for('static', filename='spd_image.png') }}" alt="Intro Image" class="intro-image">
<p class="intro-text">
This application allows for reading of welltest data from IMS database with correct SPD tags to get measured actual production rates.
The welltest data is converted to consistent well stream compositions and corresponding PVT properties using the FluidMagic library.
Select a facility and well to view test results and production charts.
by curtesy of the Equinor SPD and FluidMagic PVT groups.
</p>
</div>
<div class="select-row">
<div class="select-group">
<label for="gov_fcty_name">Facility</label>
<select id="gov_fcty_name" class="form-select">
<option value="">Select Facility</option>
{% for f in fac_codes %}
<option value="{{ f }}">{{ f }}</option>
{% endfor %}
</select>
</div>
<div class="select-group">
<label for="well_select">Well</label>
<select id="well_select" class="form-select" disabled>
<option value="">Select a facility first</option>
</select>
</div>
</div>
</div>
<div class="content-row">
<div class="table-container" id="test_results">
<div class="results-placeholder">
<div class="placeholder-text">
<i class="fas fa-table"></i> Select a well to view test results
</div>
</div>
</div>
<div class="chart-container" id="plot">
<div class="chart-placeholder">
<div class="placeholder-text">
<i class="fas fa-chart-line"></i> Select a well to view production chart
</div>
</div>
</div>
</div>
<script src="components/navbar.js"></script>
<script>
const facilitySelect = document.getElementById('gov_fcty_name');
const wellSelect = document.getElementById('well_select');
const resultsDiv = document.getElementById('test_results');
const plotDiv = document.getElementById('plot');
// Format numbers to 1 decimal place
const formatNumber = (num) => {
if (num === null || num === undefined) return '';
return Number(num).toFixed(1);
};
// When facility changes → fetch wells
facilitySelect.addEventListener('change', function() {
const selectedFacility = this.value;
if (!selectedFacility) {
wellSelect.innerHTML = '<option value="">-- Select a facility first --</option>';
wellSelect.disabled = true;
resultsDiv.innerHTML = '';
plotDiv.innerHTML = '';
return;
}
fetch(`/api/get_wellnames?facility=${encodeURIComponent(selectedFacility)}`)
.then(response => response.json())
.then(data => {
wellSelect.innerHTML = '';
if (data.length === 0) {
wellSelect.innerHTML = '<option value="">No wells found</option>';
wellSelect.disabled = true;
} else {
wellSelect.innerHTML = '<option value="">-- Select Well --</option>';
data.forEach(f => {
const option = document.createElement('option');
option.value = f;
option.textContent = f;
wellSelect.appendChild(option);
});
wellSelect.disabled = false;
}
})
.catch(err => {
console.error('Error fetching wells:', err);
wellSelect.innerHTML = '<option value="">Error loading wells</option>';
wellSelect.disabled = true;
});
});
// When well changes → fetch test results & update table + plot
wellSelect.addEventListener('change', function() {
const facility = facilitySelect.value;
const well = this.value;
if (!well) {
resultsDiv.innerHTML = '';
plotDiv.innerHTML = '';
return;
}
resultsDiv.innerHTML = '<p>Loading test results...</p>';
plotDiv.innerHTML = '';
fetch(`/api/get_test_results?facility=${encodeURIComponent(facility)}&well=${encodeURIComponent(well)}`)
.then(response => response.json())
.then(data => {
if (!data || data.length === 0) {
resultsDiv.innerHTML = '<p>No test results found.</p>';
plotDiv.innerHTML = '';
return;
}
// Build table
let html = `
<h2>Test Results for Well: ${well}</h2>
<table>
<tr>
<th>TEST_START_DATE</th>
<th>TEST_END_DATE</th>
<th>OIL_RATE</th>
<th>GAS_RATE</th>
<th>WATER_RATE</th>
<th>WHP</th>
<th>WHT</th>
<th>AVG_DOWNHOLE_PRESS</th>
<th>AVG_DOWNHOLE_TEMP</th>
<th>Separator Avg Oil Rate [Sm3/d]</th>
<th>Separator Avg Oil Rate Actual [m3/d]</th>
</tr>
`;
const dates = [];
const oilRates = [];
const oilSepRates = [];
data.forEach(row => {
html += `
<tr>
<td>${row.TEST_START_DATE || ''}</td>
<td>${row.TEST_END_DATE || ''}</td>
<td>${formatNumber(row.OIL_RATE)}</td>
<td>${formatNumber(row.GAS_RATE)}</td>
<td>${formatNumber(row.WATER_RATE)}</td>
<td>${formatNumber(row.WHP)}</td>
<td>${formatNumber(row.WHT)}</td>
<td>${formatNumber(row.AVG_DOWNHOLE_PRESS)}</td>
<td>${formatNumber(row.AVG_DOWNHOLE_TEMP)}</td>
<td>${formatNumber(row['Separator Avg Oil Rate'])}</td>
<td>${formatNumber(row['Separator Avg Oil Rate Actual'])}</td>
</tr>
`;
const date = row.TEST_START_DATE || row.TEST_END_DATE;
if (date) {
dates.push(date);
oilRates.push(row.OIL_RATE || 0);
oilSepRates.push(row['Separator Avg Oil Rate Actual'] || 0);
}
});
html += '</table>';
resultsDiv.innerHTML = html;
// Plotly chart
const traces = [
{
x: dates,
y: oilRates,
mode: 'lines+markers',
name: 'Oil Rate',
line: { shape: 'spline' }
},
{
x: dates,
y: oilSepRates,
mode: 'lines+markers',
name: 'Oil Separator Rate',
line: { shape: 'spline' }
}
];
const layout = {
title: `Production Rates for ${well}`,
xaxis: { title: 'Test Date' },
yaxis: { title: 'Rate' },
legend: { orientation: 'h', y: -0.2 }
};
Plotly.newPlot('plot', traces, layout, { responsive: true });
})
.catch(err => {
console.error('Error fetching test results:', err);
resultsDiv.innerHTML = '<p>Error loading test results</p>';
plotDiv.innerHTML = '';
});
});
</script>
</body>
</html>