Jethro85 commited on
Commit ·
bdb2e55
1
Parent(s): b2a55ac
log to supabase
Browse files- app/static/js/attacks.js +2 -0
- app/static/js/main.js +47 -0
- app/templates/base.html +26 -4
- app/templates/learning.html +7 -1
app/static/js/attacks.js
CHANGED
|
@@ -68,6 +68,8 @@ class AttackSimulator {
|
|
| 68 |
}
|
| 69 |
}
|
| 70 |
|
|
|
|
|
|
|
| 71 |
switchTab(attackType) {
|
| 72 |
// Update tab buttons
|
| 73 |
document.querySelectorAll('.attack-tab').forEach(tab => {
|
|
|
|
| 68 |
}
|
| 69 |
}
|
| 70 |
|
| 71 |
+
|
| 72 |
+
|
| 73 |
switchTab(attackType) {
|
| 74 |
// Update tab buttons
|
| 75 |
document.querySelectorAll('.attack-tab').forEach(tab => {
|
app/static/js/main.js
CHANGED
|
@@ -22,6 +22,7 @@ async function initIdentity() {
|
|
| 22 |
} catch {}
|
| 23 |
}
|
| 24 |
initIdentity();
|
|
|
|
| 25 |
|
| 26 |
function identify(user) {
|
| 27 |
userContext = { ...userContext, ...{
|
|
@@ -87,6 +88,23 @@ class DPSGDExplorer {
|
|
| 87 |
// Add view toggle listeners
|
| 88 |
document.getElementById('view-epochs')?.addEventListener('click', () => this.switchView('epochs'));
|
| 89 |
document.getElementById('view-iterations')?.addEventListener('click', () => this.switchView('iterations'));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
}
|
| 91 |
|
| 92 |
initializeSliders() {
|
|
@@ -484,6 +502,14 @@ tab.addEventListener('click', () => {
|
|
| 484 |
try {
|
| 485 |
console.log('Starting training with parameters:', this.getParameters()); // Debug log
|
| 486 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 487 |
const response = await fetch('/api/train', {
|
| 488 |
method: 'POST',
|
| 489 |
headers: {
|
|
@@ -496,6 +522,17 @@ tab.addEventListener('click', () => {
|
|
| 496 |
|
| 497 |
if (!response.ok) {
|
| 498 |
throw new Error(data.error || 'Unknown error occurred');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 499 |
}
|
| 500 |
|
| 501 |
console.log('Received training data:', data); // Debug log
|
|
@@ -504,6 +541,13 @@ tab.addEventListener('click', () => {
|
|
| 504 |
this.updateCharts(data);
|
| 505 |
this.updateResults(data);
|
| 506 |
} catch (error) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 507 |
console.error('Training error:', error);
|
| 508 |
// Show error message to user
|
| 509 |
const errorMessage = document.createElement('div');
|
|
@@ -516,6 +560,9 @@ tab.addEventListener('click', () => {
|
|
| 516 |
errorMessage.remove();
|
| 517 |
}, 5000);
|
| 518 |
} finally {
|
|
|
|
|
|
|
|
|
|
| 519 |
this.stopTraining();
|
| 520 |
}
|
| 521 |
}
|
|
|
|
| 22 |
} catch {}
|
| 23 |
}
|
| 24 |
initIdentity();
|
| 25 |
+
track('page_view', { path: location.pathname, title: document.title });
|
| 26 |
|
| 27 |
function identify(user) {
|
| 28 |
userContext = { ...userContext, ...{
|
|
|
|
| 88 |
// Add view toggle listeners
|
| 89 |
document.getElementById('view-epochs')?.addEventListener('click', () => this.switchView('epochs'));
|
| 90 |
document.getElementById('view-iterations')?.addEventListener('click', () => this.switchView('iterations'));
|
| 91 |
+
|
| 92 |
+
document.getElementById('dataset-select')?.addEventListener('change', (e) => {
|
| 93 |
+
track('dataset_change', { dataset: e.target.value });
|
| 94 |
+
});
|
| 95 |
+
|
| 96 |
+
document.getElementById('model-select')?.addEventListener('change', (e) => {
|
| 97 |
+
track('model_change', { model_architecture: e.target.value });
|
| 98 |
+
});
|
| 99 |
+
document.getElementById('preset-high-privacy')?.addEventListener('click', () => {
|
| 100 |
+
track('preset_apply', { preset: 'high-privacy' });
|
| 101 |
+
});
|
| 102 |
+
document.getElementById('preset-balanced')?.addEventListener('click', () => {
|
| 103 |
+
track('preset_apply', { preset: 'balanced' });
|
| 104 |
+
});
|
| 105 |
+
document.getElementById('preset-high-utility')?.addEventListener('click', () => {
|
| 106 |
+
track('preset_apply', { preset: 'high-utility' });
|
| 107 |
+
});
|
| 108 |
}
|
| 109 |
|
| 110 |
initializeSliders() {
|
|
|
|
| 502 |
try {
|
| 503 |
console.log('Starting training with parameters:', this.getParameters()); // Debug log
|
| 504 |
|
| 505 |
+
// === Analytics: training started ===
|
| 506 |
+
try {
|
| 507 |
+
track('train_start', {
|
| 508 |
+
...this.getParameters(),
|
| 509 |
+
view: this.currentView
|
| 510 |
+
});
|
| 511 |
+
} catch (e) {}
|
| 512 |
+
|
| 513 |
const response = await fetch('/api/train', {
|
| 514 |
method: 'POST',
|
| 515 |
headers: {
|
|
|
|
| 522 |
|
| 523 |
if (!response.ok) {
|
| 524 |
throw new Error(data.error || 'Unknown error occurred');
|
| 525 |
+
// === Analytics: training succeeded ===
|
| 526 |
+
try {
|
| 527 |
+
track('train_success', {
|
| 528 |
+
trainer_type: data.trainer_type,
|
| 529 |
+
dataset: data.dataset,
|
| 530 |
+
model_architecture: data.model_architecture,
|
| 531 |
+
final_metrics: data.final_metrics,
|
| 532 |
+
privacy_budget: data.privacy_budget,
|
| 533 |
+
epochs: this.getParameters().epochs
|
| 534 |
+
});
|
| 535 |
+
} catch (e) {}
|
| 536 |
}
|
| 537 |
|
| 538 |
console.log('Received training data:', data); // Debug log
|
|
|
|
| 541 |
this.updateCharts(data);
|
| 542 |
this.updateResults(data);
|
| 543 |
} catch (error) {
|
| 544 |
+
// === Analytics: training failed ===
|
| 545 |
+
try {
|
| 546 |
+
track('train_error', {
|
| 547 |
+
message: error.message || 'unknown',
|
| 548 |
+
params: this.getParameters()
|
| 549 |
+
});
|
| 550 |
+
} catch (e) {}
|
| 551 |
console.error('Training error:', error);
|
| 552 |
// Show error message to user
|
| 553 |
const errorMessage = document.createElement('div');
|
|
|
|
| 560 |
errorMessage.remove();
|
| 561 |
}, 5000);
|
| 562 |
} finally {
|
| 563 |
+
try {
|
| 564 |
+
track('train_end', { ended_at: Date.now() });
|
| 565 |
+
} catch (e) {}
|
| 566 |
this.stopTraining();
|
| 567 |
}
|
| 568 |
}
|
app/templates/base.html
CHANGED
|
@@ -24,9 +24,27 @@
|
|
| 24 |
</div>
|
| 25 |
<nav>
|
| 26 |
<ul class="nav-list">
|
| 27 |
-
<li
|
| 28 |
-
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
</ul>
|
| 31 |
</nav>
|
| 32 |
</div>
|
|
@@ -45,4 +63,8 @@
|
|
| 45 |
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
| 46 |
{% block extra_scripts %}{% endblock %}
|
| 47 |
</body>
|
| 48 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
</div>
|
| 25 |
<nav>
|
| 26 |
<ul class="nav-list">
|
| 27 |
+
<li>
|
| 28 |
+
<a href="{{ url_for('main.attacks') }}"
|
| 29 |
+
class="nav-link {% if request.endpoint == 'main.attacks' %}active{% endif %}"
|
| 30 |
+
data-track="nav_attacks">
|
| 31 |
+
Privacy Attacks
|
| 32 |
+
</a>
|
| 33 |
+
</li>
|
| 34 |
+
<li>
|
| 35 |
+
<a href="{{ url_for('main.learning') }}"
|
| 36 |
+
class="nav-link {% if request.endpoint == 'main.learning' %}active{% endif %}"
|
| 37 |
+
data-track="nav_learning">
|
| 38 |
+
Learning Hub
|
| 39 |
+
</a>
|
| 40 |
+
</li>
|
| 41 |
+
<li>
|
| 42 |
+
<a href="{{ url_for('main.index') }}"
|
| 43 |
+
class="nav-link {% if request.endpoint == 'main.index' %}active{% endif %}"
|
| 44 |
+
data-track="nav_playground">
|
| 45 |
+
Playground
|
| 46 |
+
</a>
|
| 47 |
+
</li>
|
| 48 |
</ul>
|
| 49 |
</nav>
|
| 50 |
</div>
|
|
|
|
| 63 |
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
| 64 |
{% block extra_scripts %}{% endblock %}
|
| 65 |
</body>
|
| 66 |
+
</html>
|
| 67 |
+
|
| 68 |
+
<a ... class="nav-link" data-track="nav_attacks">Privacy Attacks</a>
|
| 69 |
+
<a ... class="nav-link" data-track="nav_learning">Learning Hub</a>
|
| 70 |
+
<a ... class="nav-link" data-track="nav_playground">Playground</a>
|
app/templates/learning.html
CHANGED
|
@@ -254,8 +254,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 254 |
// Show selected content
|
| 255 |
const stepName = step.getAttribute('data-step');
|
| 256 |
document.getElementById(`${stepName}-content`).classList.add('active');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
});
|
| 258 |
});
|
| 259 |
});
|
| 260 |
</script>
|
| 261 |
-
{% endblock %}
|
|
|
|
|
|
| 254 |
// Show selected content
|
| 255 |
const stepName = step.getAttribute('data-step');
|
| 256 |
document.getElementById(`${stepName}-content`).classList.add('active');
|
| 257 |
+
|
| 258 |
+
// ✅ Analytics
|
| 259 |
+
if (typeof track === 'function') {
|
| 260 |
+
track('learning_step_open', { step: stepName });
|
| 261 |
+
}
|
| 262 |
});
|
| 263 |
});
|
| 264 |
});
|
| 265 |
</script>
|
| 266 |
+
{% endblock %}
|
| 267 |
+
|