QCDevs commited on
Commit
cfe733b
·
verified ·
1 Parent(s): 19d59ff

Upload 2 files

Browse files
Files changed (2) hide show
  1. index.html +802 -0
  2. prometheus.yml +8 -20
index.html ADDED
@@ -0,0 +1,802 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Procrustes Analysis Web Server</title>
7
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
10
+ <style>
11
+ :root {
12
+ --sidebar-width: 280px;
13
+ --primary-color: #2563eb;
14
+ --sidebar-bg: #f8fafc;
15
+ --header-bg: #f1f5f9;
16
+ --border-color: #e2e8f0;
17
+ --text-primary: #1e293b;
18
+ --text-secondary: #64748b;
19
+ }
20
+
21
+ body {
22
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
23
+ color: var(--text-primary);
24
+ line-height: 1.6;
25
+ }
26
+
27
+ .wrapper {
28
+ display: flex;
29
+ width: 100%;
30
+ align-items: stretch;
31
+ }
32
+
33
+ #sidebar {
34
+ min-width: var(--sidebar-width);
35
+ max-width: var(--sidebar-width);
36
+ min-height: 100vh;
37
+ transition: all 0.3s ease-out;
38
+ background-color: var(--sidebar-bg);
39
+ border-right: 1px solid var(--border-color);
40
+ }
41
+
42
+ #sidebar.active {
43
+ margin-left: calc(-1 * var(--sidebar-width));
44
+ }
45
+
46
+ #content {
47
+ width: 100%;
48
+ padding: 2rem;
49
+ min-height: 100vh;
50
+ margin-left: 0;
51
+ transition: all 0.3s ease-out;
52
+ background-color: white;
53
+ padding-bottom: 4rem;
54
+ }
55
+
56
+ .sidebar-header {
57
+ padding: 1.5rem;
58
+ background: var(--header-bg);
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: space-between;
62
+ border-bottom: 1px solid var(--border-color);
63
+ }
64
+
65
+ #sidebarCollapse, #showSidebarBtn {
66
+ background: transparent;
67
+ border: none;
68
+ padding: 0.5rem;
69
+ color: var(--text-primary);
70
+ border-radius: 0.375rem;
71
+ display: flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ cursor: pointer;
75
+ transition: all 0.2s;
76
+ }
77
+
78
+ #sidebarCollapse:hover, #showSidebarBtn:hover {
79
+ background: rgba(0, 0, 0, 0.05);
80
+ transform: translateX(2px);
81
+ }
82
+
83
+ #sidebarCollapse i {
84
+ transition: transform 0.3s ease;
85
+ }
86
+
87
+ #sidebar.active #sidebarCollapse i {
88
+ transform: rotate(180deg);
89
+ }
90
+
91
+ #showSidebarBtn {
92
+ position: fixed;
93
+ left: 1.5rem;
94
+ top: 1.5rem;
95
+ z-index: 1000;
96
+ display: none;
97
+ background-color: white;
98
+ border: 1px solid var(--border-color);
99
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
100
+ }
101
+
102
+ #showSidebarBtn.show {
103
+ display: flex;
104
+ }
105
+
106
+ .sidebar-title {
107
+ margin: 0;
108
+ font-weight: 600;
109
+ color: var(--text-primary);
110
+ font-size: 1.125rem;
111
+ }
112
+
113
+ .components {
114
+ padding: 1.5rem 0;
115
+ }
116
+
117
+ .components a {
118
+ padding: 0.75rem 1.5rem;
119
+ display: flex;
120
+ align-items: center;
121
+ color: var(--text-secondary);
122
+ text-decoration: none;
123
+ transition: all 0.2s;
124
+ font-weight: 500;
125
+ }
126
+
127
+ .components a i {
128
+ margin-right: 0.75rem;
129
+ font-size: 1.25rem;
130
+ }
131
+
132
+ .components a:hover {
133
+ background: var(--header-bg);
134
+ color: var(--text-primary);
135
+ }
136
+
137
+ .components a.active {
138
+ background: var(--header-bg);
139
+ color: var(--primary-color);
140
+ border-right: 3px solid var(--primary-color);
141
+ }
142
+
143
+ .card {
144
+ border: 1px solid var(--border-color);
145
+ border-radius: 0.5rem;
146
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
147
+ }
148
+
149
+ .card-body {
150
+ padding: 1.5rem;
151
+ }
152
+
153
+ .form-label {
154
+ font-weight: 500;
155
+ color: var(--text-primary);
156
+ margin-bottom: 0.5rem;
157
+ }
158
+
159
+ .form-control, .form-select {
160
+ border-color: var(--border-color);
161
+ border-radius: 0.375rem;
162
+ padding: 0.625rem;
163
+ }
164
+
165
+ .form-control:focus, .form-select:focus {
166
+ border-color: var(--primary-color);
167
+ box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.1);
168
+ }
169
+
170
+ .btn-primary {
171
+ background-color: var(--primary-color);
172
+ border: none;
173
+ padding: 0.625rem 1.25rem;
174
+ font-weight: 500;
175
+ }
176
+
177
+ .btn-primary:hover {
178
+ background-color: #1d4ed8;
179
+ }
180
+
181
+ .btn-success, .btn-info {
182
+ font-weight: 500;
183
+ padding: 0.625rem 1.25rem;
184
+ }
185
+
186
+ .loading {
187
+ display: none;
188
+ align-items: center;
189
+ gap: 0.75rem;
190
+ padding: 1rem;
191
+ background-color: var(--sidebar-bg);
192
+ border-radius: 0.375rem;
193
+ }
194
+
195
+ .result-section {
196
+ display: none;
197
+ margin-top: 2rem;
198
+ }
199
+
200
+ .bg-light {
201
+ background-color: var(--sidebar-bg) !important;
202
+ border-radius: 0.375rem;
203
+ }
204
+
205
+ h2 {
206
+ font-weight: 600;
207
+ margin-bottom: 1.5rem;
208
+ color: var(--text-primary);
209
+ }
210
+
211
+ h5, h6 {
212
+ font-weight: 600;
213
+ color: var(--text-primary);
214
+ }
215
+
216
+ .footer {
217
+ position: fixed;
218
+ bottom: 0;
219
+ width: 100%;
220
+ background-color: var(--header-bg);
221
+ border-top: 1px solid var(--border-color);
222
+ padding: 1rem;
223
+ display: flex;
224
+ justify-content: space-between;
225
+ align-items: center;
226
+ z-index: 1000;
227
+ }
228
+
229
+ .footer .copyright {
230
+ color: var(--text-secondary);
231
+ font-size: 0.875rem;
232
+ }
233
+
234
+ .footer .status {
235
+ display: flex;
236
+ align-items: center;
237
+ gap: 0.75rem;
238
+ color: var(--text-secondary);
239
+ font-size: 0.875rem;
240
+ }
241
+
242
+ .footer .status .status-indicator {
243
+ width: 8px;
244
+ height: 8px;
245
+ border-radius: 50%;
246
+ }
247
+
248
+ .footer .status .status-details {
249
+ display: none;
250
+ position: absolute;
251
+ bottom: 100%;
252
+ right: 1rem;
253
+ background: white;
254
+ border: 1px solid var(--border-color);
255
+ border-radius: 0.5rem;
256
+ padding: 1rem;
257
+ box-shadow: 0 -4px 6px -1px rgba(0, 0, 0, 0.1);
258
+ min-width: 200px;
259
+ }
260
+
261
+ .footer .status:hover .status-details {
262
+ display: block;
263
+ }
264
+
265
+ .status-details div {
266
+ margin-bottom: 0.5rem;
267
+ }
268
+
269
+ .status-details .component {
270
+ display: flex;
271
+ align-items: center;
272
+ gap: 0.5rem;
273
+ }
274
+
275
+ .status-details .component-indicator {
276
+ width: 6px;
277
+ height: 6px;
278
+ border-radius: 50%;
279
+ }
280
+
281
+ .status-details .resources {
282
+ margin-top: 0.75rem;
283
+ padding-top: 0.75rem;
284
+ border-top: 1px solid var(--border-color);
285
+ }
286
+
287
+ /* Markdown content styling */
288
+ .section {
289
+ padding: 2rem;
290
+ }
291
+
292
+ .section table {
293
+ border-collapse: collapse;
294
+ margin: 1rem 0;
295
+ width: 100%;
296
+ }
297
+
298
+ .section table th,
299
+ .section table td {
300
+ border: 1px solid var(--border-color);
301
+ padding: 0.75rem;
302
+ text-align: left;
303
+ }
304
+
305
+ .section table th {
306
+ background-color: var(--header-bg);
307
+ font-weight: 600;
308
+ }
309
+
310
+ .section table tr:nth-child(even) {
311
+ background-color: var(--header-bg);
312
+ }
313
+
314
+ .section h1,
315
+ .section h2,
316
+ .section h3 {
317
+ color: var(--text-primary);
318
+ margin-top: 2rem;
319
+ margin-bottom: 1rem;
320
+ }
321
+
322
+ .section h1 {
323
+ font-size: 2rem;
324
+ border-bottom: 2px solid var(--border-color);
325
+ padding-bottom: 0.5rem;
326
+ }
327
+
328
+ .section h2 {
329
+ font-size: 1.5rem;
330
+ }
331
+
332
+ .section h3 {
333
+ font-size: 1.25rem;
334
+ }
335
+
336
+ .section p {
337
+ margin-bottom: 1rem;
338
+ line-height: 1.6;
339
+ }
340
+
341
+ .section ul,
342
+ .section ol {
343
+ margin-bottom: 1rem;
344
+ padding-left: 2rem;
345
+ }
346
+
347
+ .section li {
348
+ margin-bottom: 0.5rem;
349
+ }
350
+
351
+ .section code {
352
+ background-color: var(--header-bg);
353
+ padding: 0.2rem 0.4rem;
354
+ border-radius: 0.25rem;
355
+ font-family: monospace;
356
+ }
357
+
358
+ .section pre {
359
+ background-color: var(--header-bg);
360
+ padding: 1rem;
361
+ border-radius: 0.5rem;
362
+ overflow-x: auto;
363
+ margin: 1rem 0;
364
+ }
365
+
366
+ .section a {
367
+ color: var(--primary-color);
368
+ text-decoration: none;
369
+ }
370
+
371
+ .section a:hover {
372
+ text-decoration: underline;
373
+ }
374
+
375
+ /* Math equations */
376
+ .section .MathJax_Display {
377
+ overflow-x: auto;
378
+ max-width: 100%;
379
+ margin: 1em 0;
380
+ }
381
+
382
+ .section .MathJax {
383
+ font-size: 1.1em !important;
384
+ }
385
+
386
+ .section .math-block {
387
+ overflow-x: auto;
388
+ margin: 1em 0;
389
+ text-align: center;
390
+ }
391
+ </style>
392
+ <!-- MathJax Configuration -->
393
+ <script type="text/x-mathjax-config">
394
+ MathJax.Hub.Config({
395
+ tex2jax: {
396
+ inlineMath: [['$','$'], ['\\(','\\)']],
397
+ displayMath: [['$$','$$'], ['\\[','\\]']],
398
+ processEscapes: true,
399
+ processEnvironments: true
400
+ },
401
+ displayAlign: 'center',
402
+ "HTML-CSS": {
403
+ styles: {'.MathJax_Display': {"margin": 0}},
404
+ linebreaks: { automatic: true }
405
+ }
406
+ });
407
+ </script>
408
+
409
+ <!-- MathJax Loading -->
410
+ <script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>
411
+ </head>
412
+ <body>
413
+ <button type="button" id="showSidebarBtn" class="btn">
414
+ <i class="bi bi-chevron-right"></i>
415
+ </button>
416
+
417
+ <div class="wrapper">
418
+ <!-- Sidebar -->
419
+ <nav id="sidebar">
420
+ <div class="sidebar-header">
421
+ <h5 class="sidebar-title">Procrustes Server</h5>
422
+ <button type="button" id="sidebarCollapse" class="btn">
423
+ <i class="bi bi-chevron-left"></i>
424
+ </button>
425
+ </div>
426
+
427
+ <div class="components">
428
+ <a href="#about" class="nav-link" data-section="about">
429
+ <i class="bi bi-book"></i> About Procrustes
430
+ </a>
431
+ <a href="#tools" class="nav-link" data-section="tools">
432
+ <i class="bi bi-tools"></i> Procrustes Tools
433
+ </a>
434
+ <a href="#contact" class="nav-link" data-section="contact">
435
+ <i class="bi bi-envelope"></i> Contact
436
+ </a>
437
+ </div>
438
+ </nav>
439
+
440
+ <!-- Page Content -->
441
+ <div id="content">
442
+ <!-- About Section -->
443
+ <div id="about" class="section" style="display: none;">
444
+ <h2>About Procrustes Analysis</h2>
445
+ <div id="about-content">Loading...</div>
446
+ </div>
447
+
448
+ <!-- Tools Section -->
449
+ <div id="tools" class="section">
450
+ <h2>Procrustes Analysis Tools</h2>
451
+ <div class="card">
452
+ <div class="card-body">
453
+ <form id="uploadForm" enctype="multipart/form-data">
454
+ <div class="mb-3">
455
+ <label for="algorithm" class="form-label">Select Algorithm</label>
456
+ <select class="form-select" id="algorithm" name="algorithm" required>
457
+ <option value="orthogonal">orthogonal</option>
458
+ <option value="rotational">rotational</option>
459
+ <option value="permutation">permutation</option>
460
+ <!-- <option value="generalized">generalized</option> -->
461
+ <option value="generic">generic</option>
462
+ <!-- <option value="kopt_heuristic_single">kopt_heuristic_single</option> -->
463
+ <!-- <option value="kopt_heuristic_double">kopt_heuristic_double</option> -->
464
+ <option value="orthogonal_2sided">orthogonal_2sided</option>
465
+ <option value="permutation_2sided">permutation_2sided</option>
466
+ <option value="softassign">softassign</option>
467
+ <option value="symmetric">symmetric</option>
468
+ </select>
469
+ </div>
470
+
471
+ <div class="mb-3">
472
+ <label for="parameters" class="form-label">Additional Parameters (JSON format)</label>
473
+ <textarea class="form-control font-monospace" id="parameters" name="parameters" rows="10"></textarea>
474
+ </div>
475
+
476
+ <div class="mb-3">
477
+ <label for="file1" class="form-label">First Matrix (NPZ/Excel/TXT)</label>
478
+ <input type="file" class="form-control" id="file1" name="file1" accept=".npz,.xlsx,.xls,.txt" required>
479
+ </div>
480
+
481
+ <div class="mb-3">
482
+ <label for="file2" class="form-label">Second Matrix (NPZ/Excel/TXT)</label>
483
+ <input type="file" class="form-control" id="file2" name="file2" accept=".npz,.xlsx,.xls,.txt" required>
484
+ </div>
485
+
486
+ <button type="submit" class="btn btn-primary">Analyze</button>
487
+ </form>
488
+
489
+ <div class="loading mt-3">
490
+ <div class="spinner-border text-primary" role="status">
491
+ <span class="visually-hidden">Loading...</span>
492
+ </div>
493
+ <span class="ms-2">Processing...</span>
494
+ </div>
495
+ </div>
496
+ </div>
497
+
498
+ <div id="resultSection" class="result-section">
499
+ <div class="card">
500
+ <div class="card-body">
501
+ <h5 class="card-title">Results</h5>
502
+ <p>Procrustes Error: <span id="error" class="fw-bold"></span></p>
503
+
504
+ <div class="mb-3">
505
+ <h6>Transformation Matrix:</h6>
506
+ <div id="transformationMatrix" class="bg-light p-3 mb-3" style="font-family: monospace;">
507
+ </div>
508
+ </div>
509
+
510
+ <div class="mb-3">
511
+ <h6>Transformed Array:</h6>
512
+ <div id="transformedArray" class="bg-light p-3 mb-3" style="font-family: monospace;">
513
+ </div>
514
+ </div>
515
+
516
+ <div class="mb-3">
517
+ <label class="form-label">Download Format</label>
518
+ <select class="form-select" id="downloadFormat">
519
+ <option value="npz">NPZ</option>
520
+ <option value="xlsx">Excel</option>
521
+ <option value="txt">TXT</option>
522
+ </select>
523
+ </div>
524
+
525
+ <div class="btn-group">
526
+ <button class="btn btn-success" onclick="downloadResult('transformation')">
527
+ Download Transformation Matrix
528
+ </button>
529
+ <button class="btn btn-info" onclick="downloadResult('new_array')">
530
+ Download Transformed Array
531
+ </button>
532
+ </div>
533
+ </div>
534
+ </div>
535
+ </div>
536
+ </div>
537
+
538
+ <!-- Contact Section -->
539
+ <div id="contact" class="section" style="display: none;">
540
+ <h2>Contact Information</h2>
541
+ <div id="contact-content">Loading...</div>
542
+ </div>
543
+ </div>
544
+ </div>
545
+
546
+ <!-- Footer -->
547
+ <div class="footer">
548
+ <div class="copyright">
549
+ &copy; Copyright 2017-2024, The QC-Devs Community.
550
+ </div>
551
+ <div class="status">
552
+ <div class="status-indicator"></div>
553
+ <span>Server Status: </span>
554
+ <span id="serverStatus">Loading...</span>
555
+ <div class="status-details">
556
+ <div><strong>Components:</strong></div>
557
+ <div class="component">
558
+ <div class="component-indicator"></div>
559
+ <span>Flask</span>
560
+ </div>
561
+ <div class="component">
562
+ <div class="component-indicator"></div>
563
+ <span>Celery</span>
564
+ </div>
565
+ <div class="component">
566
+ <div class="component-indicator"></div>
567
+ <span>Redis</span>
568
+ </div>
569
+ <div class="resources">
570
+ <div><strong>Resources:</strong></div>
571
+ <div>CPU: <span id="cpuStatus">-</span>%</div>
572
+ <div>Memory: <span id="memoryStatus">-</span>%</div>
573
+ <div>Disk: <span id="diskStatus">-</span>%</div>
574
+ </div>
575
+ </div>
576
+ </div>
577
+ </div>
578
+
579
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
580
+ <script>
581
+ let resultData = null;
582
+
583
+ // Sidebar toggle functionality
584
+ const sidebar = document.getElementById('sidebar');
585
+ const content = document.getElementById('content');
586
+ const sidebarCollapse = document.getElementById('sidebarCollapse');
587
+ const showSidebarBtn = document.getElementById('showSidebarBtn');
588
+
589
+ function toggleSidebar() {
590
+ sidebar.classList.toggle('active');
591
+ content.classList.toggle('active');
592
+ showSidebarBtn.classList.toggle('show', sidebar.classList.contains('active'));
593
+ }
594
+
595
+ sidebarCollapse.addEventListener('click', toggleSidebar);
596
+ showSidebarBtn.addEventListener('click', toggleSidebar);
597
+
598
+ function showSection(sectionId) {
599
+ // Hide all sections
600
+ document.querySelectorAll('.section').forEach(section => {
601
+ section.style.display = 'none';
602
+ });
603
+
604
+ // Remove active class from all nav links
605
+ document.querySelectorAll('.nav-link').forEach(link => {
606
+ link.classList.remove('active');
607
+ });
608
+
609
+ // Show selected section
610
+ const section = document.getElementById(sectionId);
611
+ if (section) {
612
+ section.style.display = 'block';
613
+ // Add active class to corresponding nav link
614
+ const navLink = document.querySelector(`.nav-link[data-section="${sectionId}"]`);
615
+ if (navLink) {
616
+ navLink.classList.add('active');
617
+ }
618
+ }
619
+ }
620
+
621
+ // Handle navigation clicks
622
+ document.querySelectorAll('.nav-link').forEach(link => {
623
+ link.addEventListener('click', (e) => {
624
+ e.preventDefault();
625
+ const sectionId = link.getAttribute('data-section');
626
+ showSection(sectionId);
627
+ });
628
+ });
629
+
630
+ // Show tools section by default
631
+ document.addEventListener('DOMContentLoaded', function() {
632
+ showSection('tools');
633
+ loadMarkdownContent();
634
+ checkServerStatus();
635
+ setInterval(checkServerStatus, 30000);
636
+ });
637
+
638
+ function formatMatrix(matrix) {
639
+ // Return the matrix as is, without formatting
640
+ return matrix;
641
+ }
642
+
643
+ async function updateDefaultParams() {
644
+ const algorithm = document.getElementById('algorithm').value;
645
+ try {
646
+ const response = await fetch(`/get_default_params/${algorithm}`);
647
+ const data = await response.json();
648
+ document.getElementById('parameters').value = JSON.stringify(data, null, 2);
649
+ } catch (error) {
650
+ console.error('Error fetching default parameters:', error);
651
+ }
652
+ }
653
+
654
+ document.getElementById('algorithm').addEventListener('change', updateDefaultParams);
655
+ updateDefaultParams();
656
+
657
+ document.getElementById('uploadForm').addEventListener('submit', async (e) => {
658
+ e.preventDefault();
659
+ console.log('Form submitted');
660
+
661
+ const formData = new FormData(e.target);
662
+ const loading = document.querySelector('.loading');
663
+ const resultSection = document.getElementById('resultSection');
664
+
665
+ loading.style.display = 'block';
666
+ resultSection.style.display = 'none';
667
+
668
+ try {
669
+ console.log('Sending request...');
670
+ const response = await fetch('/upload', {
671
+ method: 'POST',
672
+ body: formData
673
+ });
674
+
675
+ console.log('Response received');
676
+ const data = await response.json();
677
+ console.log('Response data:', data);
678
+
679
+ if (response.ok) {
680
+ resultData = data;
681
+ console.log('Setting error:', data.error);
682
+ document.getElementById('error').textContent = data.error.toFixed(6);
683
+
684
+ console.log('Setting transformation matrix');
685
+ const transformationElem = document.getElementById('transformationMatrix');
686
+ transformationElem.textContent = JSON.stringify(data.transformation, null, 2);
687
+
688
+ console.log('Setting transformed array');
689
+ const transformedArrayElem = document.getElementById('transformedArray');
690
+ transformedArrayElem.textContent = JSON.stringify(data.new_array, null, 2);
691
+
692
+ resultSection.style.display = 'block';
693
+ } else {
694
+ console.error('Error response:', data);
695
+ alert(data.error || 'An error occurred');
696
+ }
697
+ } catch (error) {
698
+ console.error('Error in request:', error);
699
+ alert('An error occurred while processing the request');
700
+ } finally {
701
+ loading.style.display = 'none';
702
+ }
703
+ });
704
+
705
+ async function downloadResult(type) {
706
+ if (!resultData) return;
707
+
708
+ const format = document.getElementById('downloadFormat').value;
709
+ const formData = new FormData();
710
+ formData.append('data', JSON.stringify(
711
+ type === 'transformation' ? resultData.transformation : resultData.new_array
712
+ ));
713
+ formData.append('format', format);
714
+
715
+ try {
716
+ const response = await fetch('/download', {
717
+ method: 'POST',
718
+ body: formData
719
+ });
720
+
721
+ if (response.ok) {
722
+ const blob = await response.blob();
723
+ const url = window.URL.createObjectURL(blob);
724
+ const a = document.createElement('a');
725
+ a.href = url;
726
+ a.download = `procrustes_${type}.${format}`;
727
+ document.body.appendChild(a);
728
+ a.click();
729
+ window.URL.revokeObjectURL(url);
730
+ a.remove();
731
+ } else {
732
+ const data = await response.json();
733
+ alert(data.error || 'An error occurred during download');
734
+ }
735
+ } catch (error) {
736
+ alert('An error occurred while downloading the file');
737
+ }
738
+ }
739
+
740
+ // Server status check
741
+ async function checkServerStatus() {
742
+ try {
743
+ const response = await fetch('/status');
744
+ const data = await response.json();
745
+ const statusElem = document.getElementById('serverStatus');
746
+ const indicator = document.querySelector('.status-indicator');
747
+
748
+ // Update main status
749
+ statusElem.textContent = data.status === 'ok' ? 'Running' :
750
+ data.status === 'degraded' ? 'Degraded' : 'Error';
751
+
752
+ // Update indicator color
753
+ indicator.style.backgroundColor =
754
+ data.status === 'ok' ? '#22c55e' : // green
755
+ data.status === 'degraded' ? '#f59e0b' : // orange
756
+ '#ef4444'; // red
757
+
758
+ // Update components
759
+ const components = document.querySelectorAll('.component');
760
+ Object.entries(data.components).forEach((component, index) => {
761
+ const [name, status] = component;
762
+ components[index].querySelector('.component-indicator').style.backgroundColor =
763
+ status ? '#22c55e' : '#ef4444';
764
+ });
765
+ } catch (error) {
766
+ const statusElem = document.getElementById('serverStatus');
767
+ const indicator = document.querySelector('.status-indicator');
768
+ statusElem.textContent = 'Offline';
769
+ indicator.style.backgroundColor = '#ef4444'; // red
770
+
771
+ // Set all components to red when offline
772
+ const components = document.querySelectorAll('.component');
773
+ components.forEach(comp => {
774
+ comp.querySelector('.component-indicator').style.backgroundColor = '#ef4444';
775
+ });
776
+ }
777
+ }
778
+
779
+ // Load markdown content and add MathJax support
780
+ async function loadMarkdownContent() {
781
+ try {
782
+ // Load about content
783
+ const aboutResponse = await fetch('/md/about.md');
784
+ const aboutData = await aboutResponse.json();
785
+ document.getElementById('about-content').innerHTML = aboutData.html;
786
+
787
+ // Load contact content
788
+ const contactResponse = await fetch('/md/contacts.md');
789
+ const contactData = await contactResponse.json();
790
+ document.getElementById('contact-content').innerHTML = contactData.html;
791
+
792
+ // Retypeset math
793
+ if (window.MathJax && window.MathJax.Hub) {
794
+ window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub]);
795
+ }
796
+ } catch (error) {
797
+ console.error('Error loading markdown content:', error);
798
+ }
799
+ }
800
+ </script>
801
+ </body>
802
+ </html>
prometheus.yml CHANGED
@@ -1,20 +1,8 @@
1
- global:
2
- scrape_interval: 15s
3
- evaluation_interval: 15s
4
-
5
- scrape_configs:
6
- - job_name: 'prometheus'
7
- static_configs:
8
- - targets: ['localhost:9090']
9
-
10
- - job_name: 'flask'
11
- static_configs:
12
- - targets: ['web:8000']
13
-
14
- - job_name: 'redis'
15
- static_configs:
16
- - targets: ['redis-exporter:9121']
17
-
18
- - job_name: 'flower'
19
- static_configs:
20
- - targets: ['flower:5555']
 
1
+ apiVersion: 1
2
+
3
+ datasources:
4
+ - name: Prometheus
5
+ type: prometheus
6
+ access: proxy
7
+ url: http://prometheus:9090
8
+ isDefault: true