feat: Add new api routes and updated chart
All checks were successful
Build Docker / BuildImage (push) Successful in 34s

This commit is contained in:
2024-12-05 15:35:09 +11:00
parent e995df2e05
commit 7aebf2b92f
16 changed files with 248 additions and 71 deletions

View File

@@ -47,68 +47,178 @@
</header>
<section style="margin-top: 50px;margin-bottom: 50px;max-width: 100vw;overflow: hidden;">
<div class="text-center">
<h1>Current Vault Contents</h1>
<h1 data-bs-toggle="tooltip" data-bss-tooltip="" id="chart-header" title="Toggle per token view" style="border-bottom: 5px dashed var(--bs-body-color);width: fit-content;margin: auto;margin-bottom: 20px;">Current Vault Contents</h1>
<div class="text-center" id="data-table"></div>
<div id="pie-chart" style="margin: auto;"><script type="text/javascript">
window.onload = function () {
google.charts.load('current', {
packages: ['corechart']
});
google.charts.load('current', { packages: ['corechart'] });
// Set a callback to run when the API is loaded.
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
// Create data array from Flask data passed into the template
var data = new google.visualization.DataTable();
data.addColumn('string', 'Token');
data.addColumn('number', 'Value');
data.addColumn({ type: 'string', role: 'tooltip', 'p': { 'html': true } });
data.addRows([
{% for token, value, name in pie_chart %}
['{{ token }}', {{ value }}, '{{name}}'],
{% endfor %}
]);
// Set chart options
var options = {
pieSliceText: 'label',
legend: {
position: 'right',
textStyle: {
color: 'white'
}
},
backgroundColor: '#212529',
};
var chart = new google.visualization.PieChart(document.getElementById('pie-chart'));
function resizeChart() {
// Dynamically adjust the chart size to the container
var width = window.innerWidth * 0.8;
var height = window.innerHeight * 0.5;
// If the width is less than 600 px use full width
if (width < 700) {
chart.draw(data, options);
}
else {
chart.draw(data, {
...options,
width: width,
height: height
});
}
}
resizeChart();
window.addEventListener('resize', resizeChart);
}
let isPerTokenView = false; // Track the current view state
let chart; // Declare the chart instance globally to reuse it
let options = {
pieSliceText: 'label',
tooltip: { isHtml: false },
legend: {
position: 'right',
textStyle: { color: 'white' }
},
backgroundColor: '#212529',
};
</script></div><a class="btn btn-secondary" role="button" href="https://www.coingecko.com/en/portfolios/public/vault" target="_blank">View on Coingecko</a>
async function fetchData(apiUrl) {
try {
const response = await fetch(apiUrl);
if (!response.ok) throw new Error('Failed to fetch data from API');
return await response.json();
} catch (error) {
console.error('Error fetching data:', error);
return null;
}
}
function transformDataForChart(data) {
const chartData = [];
for (const token in data) {
if (token !== 'total') {
chartData.push([
token, // Label for the chart
data[token].value, // Value for the chart
data[token].tooltip, // Tooltip for the chart
]);
}
}
return chartData;
}
async function drawChart() {
const apiUrl = '/api/v1/vault';
const data = await fetchData(apiUrl);
if (!data) return; // Exit if data fetch fails
const chartDataTable = new google.visualization.DataTable();
chartDataTable.addColumn('string', 'Token');
chartDataTable.addColumn('number', 'Value');
chartDataTable.addColumn({ type: 'string', role: 'tooltip', 'p': { 'html': false } });
chartDataTable.addRows(transformDataForChart(data));
chart = new google.visualization.PieChart(document.getElementById('pie-chart'));
resizeAndDraw(chart, chartDataTable, options);
updateText(true);
populateTable(data);
}
function updateText(isVault) {
let headerText = document.getElementById('chart-header');
if (isVault) {
headerText.innerText = 'Current Vault Contents';
} else {
headerText.innerText = 'Current Per Token Holding';
}
}
function populateTable(data) {
const tableContainer = document.getElementById('data-table');
tableContainer.innerHTML = ''; // Clear previous table data
// Create table elements
const table = document.createElement('table');
table.style.margin = 'auto';
table.style.borderCollapse = 'collapse';
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');
// Create table header
const headerRow = document.createElement('tr');
['Name', 'Amount', 'Value'].forEach(headerText => {
const th = document.createElement('th');
th.textContent = headerText;
th.style.border = '1px solid #ccc';
th.style.padding = '8px 20px';
th.style.backgroundColor = '#333';
th.style.color = 'white';
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
// Create table rows
for (const token in data) {
if (token !== 'total') {
const row = document.createElement('tr');
const nameCell = document.createElement('td');
nameCell.textContent = data[token].name;
nameCell.style.border = '1px solid #ccc';
nameCell.style.padding = '8px 20px';
const amountCell = document.createElement('td');
amountCell.textContent = `${data[token].amount} ${token}`;
amountCell.style.border = '1px solid #ccc';
amountCell.style.padding = '8px 20px';
const valueCell = document.createElement('td');
valueCell.textContent = data[token].value;
valueCell.style.border = '1px solid #ccc';
valueCell.style.padding = '8px 20px';
row.appendChild(nameCell);
row.appendChild(amountCell);
row.appendChild(valueCell);
tbody.appendChild(row);
}
}
table.appendChild(thead);
table.appendChild(tbody);
tableContainer.appendChild(table);
}
async function toggleChart() {
isPerTokenView = !isPerTokenView;
const apiUrl = isPerTokenView ? '/api/v1/token' : '/api/v1/vault';
const data = await fetchData(apiUrl);
if (!data) return; // Exit if data fetch fails
const chartDataTable = new google.visualization.DataTable();
chartDataTable.addColumn('string', 'Token');
chartDataTable.addColumn('number', 'Value');
chartDataTable.addColumn({ type: 'string', role: 'tooltip', 'p': { 'html': false } });
chartDataTable.addRows(transformDataForChart(data));
resizeAndDraw(chart, chartDataTable, options);
updateText(!isPerTokenView);
populateTable(data);
}
function resizeAndDraw(chart, chartDataTable, options) {
function resizeChart() {
const width = window.innerWidth * 0.8;
const height = window.innerHeight * 0.5;
const dynamicOptions = { ...options };
if (width >= 700) {
dynamicOptions.width = width;
dynamicOptions.height = height;
}
chart.draw(chartDataTable, dynamicOptions);
}
resizeChart();
window.addEventListener('resize', resizeChart);
}
// Set button event listener
document.getElementById('chart-header').addEventListener('click', toggleChart);
};
</script>
</div><a class="btn btn-secondary" role="button" href="https://www.coingecko.com/en/portfolios/public/vault" target="_blank" style="margin: 10px;">View on Coingecko</a>
</div>
</section>
<section>
@@ -189,6 +299,7 @@
</div>
</footer>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/bs-init.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
</body>