anotate ui phase 1
This commit is contained in:
173
TESTCASES/web/templates/annotation_dashboard.html
Normal file
173
TESTCASES/web/templates/annotation_dashboard.html
Normal file
@@ -0,0 +1,173 @@
|
||||
{% extends "base_layout.html" %}
|
||||
|
||||
{% block title %}Trade Annotation Dashboard{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mt-3">
|
||||
<!-- Left Sidebar - Controls -->
|
||||
<div class="col-md-2">
|
||||
{% include 'components/control_panel.html' %}
|
||||
</div>
|
||||
|
||||
<!-- Main Chart Area -->
|
||||
<div class="col-md-8">
|
||||
{% include 'components/chart_panel.html' %}
|
||||
</div>
|
||||
|
||||
<!-- Right Sidebar - Annotations & Training -->
|
||||
<div class="col-md-2">
|
||||
{% include 'components/annotation_list.html' %}
|
||||
{% include 'components/training_panel.html' %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Inference Simulation Modal -->
|
||||
<div class="modal fade" id="inferenceModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i class="fas fa-brain"></i>
|
||||
Inference Simulation
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% include 'components/inference_panel.html' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
// Initialize application state
|
||||
const appState = {
|
||||
currentSymbol: '{{ current_symbol }}',
|
||||
currentTimeframes: {{ timeframes | tojson }},
|
||||
annotations: {{ annotations | tojson }},
|
||||
pendingAnnotation: null,
|
||||
chartManager: null,
|
||||
annotationManager: null,
|
||||
timeNavigator: null,
|
||||
trainingController: null
|
||||
};
|
||||
|
||||
// Initialize components when DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Initialize chart manager
|
||||
appState.chartManager = new ChartManager('chart-container', appState.currentTimeframes);
|
||||
|
||||
// Initialize annotation manager
|
||||
appState.annotationManager = new AnnotationManager(appState.chartManager);
|
||||
|
||||
// Initialize time navigator
|
||||
appState.timeNavigator = new TimeNavigator(appState.chartManager);
|
||||
|
||||
// Initialize training controller
|
||||
appState.trainingController = new TrainingController();
|
||||
|
||||
// Load initial data
|
||||
loadInitialData();
|
||||
|
||||
// Setup keyboard shortcuts
|
||||
setupKeyboardShortcuts();
|
||||
});
|
||||
|
||||
function loadInitialData() {
|
||||
// Fetch initial chart data
|
||||
fetch('/api/chart-data', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
symbol: appState.currentSymbol,
|
||||
timeframes: appState.currentTimeframes,
|
||||
start_time: null,
|
||||
end_time: null
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
appState.chartManager.initializeCharts(data.chart_data);
|
||||
|
||||
// Load existing annotations
|
||||
appState.annotations.forEach(annotation => {
|
||||
appState.chartManager.addAnnotation(annotation);
|
||||
});
|
||||
} else {
|
||||
showError('Failed to load chart data: ' + data.error.message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
showError('Network error: ' + error.message);
|
||||
});
|
||||
}
|
||||
|
||||
function setupKeyboardShortcuts() {
|
||||
document.addEventListener('keydown', function(e) {
|
||||
// Arrow left - navigate backward
|
||||
if (e.key === 'ArrowLeft') {
|
||||
e.preventDefault();
|
||||
appState.timeNavigator.scrollBackward();
|
||||
}
|
||||
// Arrow right - navigate forward
|
||||
else if (e.key === 'ArrowRight') {
|
||||
e.preventDefault();
|
||||
appState.timeNavigator.scrollForward();
|
||||
}
|
||||
// Space - mark point (if chart is focused)
|
||||
else if (e.key === ' ' && e.target.tagName !== 'INPUT') {
|
||||
e.preventDefault();
|
||||
// Trigger mark at current crosshair position
|
||||
appState.annotationManager.markCurrentPosition();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
// Create toast notification
|
||||
const toast = document.createElement('div');
|
||||
toast.className = 'toast align-items-center text-white bg-danger border-0';
|
||||
toast.setAttribute('role', 'alert');
|
||||
toast.innerHTML = `
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">
|
||||
<i class="fas fa-exclamation-circle"></i>
|
||||
${message}
|
||||
</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Add to page and show
|
||||
document.body.appendChild(toast);
|
||||
const bsToast = new bootstrap.Toast(toast);
|
||||
bsToast.show();
|
||||
|
||||
// Remove after hidden
|
||||
toast.addEventListener('hidden.bs.toast', () => toast.remove());
|
||||
}
|
||||
|
||||
function showSuccess(message) {
|
||||
const toast = document.createElement('div');
|
||||
toast.className = 'toast align-items-center text-white bg-success border-0';
|
||||
toast.setAttribute('role', 'alert');
|
||||
toast.innerHTML = `
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
${message}
|
||||
</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(toast);
|
||||
const bsToast = new bootstrap.Toast(toast);
|
||||
bsToast.show();
|
||||
toast.addEventListener('hidden.bs.toast', () => toast.remove());
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user