kamau1 commited on
Commit
71f7767
Β·
verified Β·
1 Parent(s): 78205e4

feat: UI API usage guide

Browse files
static/css/dashboard-simple.css CHANGED
@@ -515,3 +515,231 @@
515
  padding: 4px 6px;
516
  }
517
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
515
  padding: 4px 6px;
516
  }
517
  }
518
+
519
+ /* API Documentation Section */
520
+ .api-documentation-section {
521
+ margin-top: 60px;
522
+ padding: 40px 0;
523
+ background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
524
+ border-top: 1px solid #e2e8f0;
525
+ }
526
+
527
+ .api-docs-header {
528
+ text-align: center;
529
+ margin-bottom: 50px;
530
+ max-width: 800px;
531
+ margin-left: auto;
532
+ margin-right: auto;
533
+ padding: 0 20px;
534
+ }
535
+
536
+ .api-docs-header h2 {
537
+ font-size: 2.5rem;
538
+ font-weight: 700;
539
+ color: #1e293b;
540
+ margin-bottom: 16px;
541
+ background: linear-gradient(135deg, #2563eb, #1d4ed8);
542
+ -webkit-background-clip: text;
543
+ -webkit-text-fill-color: transparent;
544
+ background-clip: text;
545
+ }
546
+
547
+ .api-docs-header p {
548
+ font-size: 1.25rem;
549
+ color: #64748b;
550
+ line-height: 1.6;
551
+ }
552
+
553
+ .api-docs-grid {
554
+ display: grid;
555
+ grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
556
+ gap: 24px;
557
+ max-width: 1400px;
558
+ margin: 0 auto;
559
+ padding: 0 20px;
560
+ }
561
+
562
+ .api-docs-card {
563
+ background: white;
564
+ border-radius: 12px;
565
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
566
+ overflow: hidden;
567
+ transition: all 0.3s ease;
568
+ border: 1px solid #e2e8f0;
569
+ }
570
+
571
+ .api-docs-card:hover {
572
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
573
+ transform: translateY(-2px);
574
+ }
575
+
576
+ .api-docs-card-header {
577
+ display: flex;
578
+ justify-content: space-between;
579
+ align-items: center;
580
+ padding: 20px 24px;
581
+ background: linear-gradient(135deg, #f8fafc, #f1f5f9);
582
+ border-bottom: 1px solid #e2e8f0;
583
+ }
584
+
585
+ .api-docs-card-header h3 {
586
+ margin: 0;
587
+ font-size: 1.25rem;
588
+ font-weight: 600;
589
+ color: #1e293b;
590
+ }
591
+
592
+ .copy-btn {
593
+ background: #2563eb;
594
+ color: white;
595
+ border: none;
596
+ padding: 8px 16px;
597
+ border-radius: 6px;
598
+ font-size: 0.875rem;
599
+ font-weight: 500;
600
+ cursor: pointer;
601
+ transition: all 0.2s ease;
602
+ }
603
+
604
+ .copy-btn:hover {
605
+ background: #1d4ed8;
606
+ transform: scale(1.05);
607
+ }
608
+
609
+ .api-docs-card-content {
610
+ padding: 24px;
611
+ }
612
+
613
+ .api-endpoint {
614
+ display: flex;
615
+ align-items: center;
616
+ gap: 12px;
617
+ margin-bottom: 16px;
618
+ padding: 12px 16px;
619
+ background: #f1f5f9;
620
+ border-radius: 8px;
621
+ border-left: 4px solid #2563eb;
622
+ }
623
+
624
+ .endpoint-method {
625
+ background: #2563eb;
626
+ color: white;
627
+ padding: 4px 8px;
628
+ border-radius: 4px;
629
+ font-size: 0.75rem;
630
+ font-weight: 600;
631
+ letter-spacing: 0.05em;
632
+ }
633
+
634
+ .endpoint-url {
635
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
636
+ font-size: 0.875rem;
637
+ color: #1e293b;
638
+ word-break: break-all;
639
+ }
640
+
641
+ .code-block {
642
+ background: #1e293b;
643
+ color: #e2e8f0;
644
+ padding: 20px;
645
+ border-radius: 8px;
646
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
647
+ font-size: 0.875rem;
648
+ line-height: 1.6;
649
+ overflow-x: auto;
650
+ margin: 0;
651
+ white-space: pre-wrap;
652
+ word-wrap: break-word;
653
+ }
654
+
655
+ .api-docs-footer {
656
+ margin-top: 50px;
657
+ max-width: 1400px;
658
+ margin-left: auto;
659
+ margin-right: auto;
660
+ padding: 0 20px;
661
+ }
662
+
663
+ .api-docs-info-grid {
664
+ display: grid;
665
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
666
+ gap: 24px;
667
+ }
668
+
669
+ .api-info-card {
670
+ background: white;
671
+ padding: 24px;
672
+ border-radius: 12px;
673
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
674
+ border: 1px solid #e2e8f0;
675
+ }
676
+
677
+ .api-info-card h4 {
678
+ margin: 0 0 16px 0;
679
+ font-size: 1.125rem;
680
+ font-weight: 600;
681
+ color: #1e293b;
682
+ }
683
+
684
+ .api-info-card ul {
685
+ margin: 0;
686
+ padding: 0;
687
+ list-style: none;
688
+ }
689
+
690
+ .api-info-card li {
691
+ padding: 8px 0;
692
+ border-bottom: 1px solid #f1f5f9;
693
+ color: #475569;
694
+ line-height: 1.5;
695
+ }
696
+
697
+ .api-info-card li:last-child {
698
+ border-bottom: none;
699
+ }
700
+
701
+ .api-info-card strong {
702
+ color: #1e293b;
703
+ font-weight: 600;
704
+ }
705
+
706
+ /* Responsive Design for API Docs */
707
+ @media (max-width: 768px) {
708
+ .api-docs-header h2 {
709
+ font-size: 2rem;
710
+ }
711
+
712
+ .api-docs-header p {
713
+ font-size: 1.125rem;
714
+ }
715
+
716
+ .api-docs-grid {
717
+ grid-template-columns: 1fr;
718
+ padding: 0 16px;
719
+ }
720
+
721
+ .api-docs-card-header {
722
+ padding: 16px 20px;
723
+ flex-direction: column;
724
+ align-items: flex-start;
725
+ gap: 12px;
726
+ }
727
+
728
+ .api-docs-card-content {
729
+ padding: 20px;
730
+ }
731
+
732
+ .code-block {
733
+ font-size: 0.8rem;
734
+ padding: 16px;
735
+ }
736
+
737
+ .endpoint-url {
738
+ font-size: 0.8rem;
739
+ }
740
+
741
+ .api-docs-info-grid {
742
+ grid-template-columns: 1fr;
743
+ padding: 0 16px;
744
+ }
745
+ }
static/js/dashboard.js CHANGED
@@ -345,6 +345,57 @@ class MarineDashboard {
345
  }
346
  }
347
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  // Make dashboard instance globally available for sample image clicks
349
  let dashboard;
350
 
 
345
  }
346
  }
347
 
348
+ // Global function for copy to clipboard (used by API docs)
349
+ window.copyToClipboard = function(elementId) {
350
+ const element = document.getElementById(elementId);
351
+ if (!element) {
352
+ console.error('Element not found:', elementId);
353
+ return;
354
+ }
355
+
356
+ const text = element.textContent;
357
+
358
+ if (navigator.clipboard && navigator.clipboard.writeText) {
359
+ navigator.clipboard.writeText(text).then(() => {
360
+ window.MarineAPI.utils.showNotification('Code copied to clipboard!', 'success');
361
+ }).catch(err => {
362
+ console.error('Failed to copy text: ', err);
363
+ fallbackCopyTextToClipboard(text);
364
+ });
365
+ } else {
366
+ fallbackCopyTextToClipboard(text);
367
+ }
368
+ };
369
+
370
+ // Fallback copy function for older browsers
371
+ function fallbackCopyTextToClipboard(text) {
372
+ const textArea = document.createElement("textarea");
373
+ textArea.value = text;
374
+
375
+ // Avoid scrolling to bottom
376
+ textArea.style.top = "0";
377
+ textArea.style.left = "0";
378
+ textArea.style.position = "fixed";
379
+
380
+ document.body.appendChild(textArea);
381
+ textArea.focus();
382
+ textArea.select();
383
+
384
+ try {
385
+ const successful = document.execCommand('copy');
386
+ if (successful) {
387
+ window.MarineAPI.utils.showNotification('Code copied to clipboard!', 'success');
388
+ } else {
389
+ window.MarineAPI.utils.showNotification('Failed to copy code', 'error');
390
+ }
391
+ } catch (err) {
392
+ console.error('Fallback: Oops, unable to copy', err);
393
+ window.MarineAPI.utils.showNotification('Failed to copy code', 'error');
394
+ }
395
+
396
+ document.body.removeChild(textArea);
397
+ }
398
+
399
  // Make dashboard instance globally available for sample image clicks
400
  let dashboard;
401
 
templates/dashboard.html CHANGED
@@ -165,6 +165,195 @@
165
  </div>
166
  </div>
167
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  </div>
169
  {% endblock %}
170
 
 
165
  </div>
166
  </div>
167
  </div>
168
+
169
+ <!-- API Documentation Section -->
170
+ <div class="api-documentation-section">
171
+ <div class="api-docs-header">
172
+ <h2>API Documentation</h2>
173
+ <p>Integrate marine species identification into your applications with our REST API</p>
174
+ </div>
175
+
176
+ <div class="api-docs-grid">
177
+ <!-- Quick Start -->
178
+ <div class="api-docs-card">
179
+ <div class="api-docs-card-header">
180
+ <h3>πŸš€ Quick Start</h3>
181
+ </div>
182
+ <div class="api-docs-card-content">
183
+ <div class="api-endpoint">
184
+ <div class="endpoint-method">POST</div>
185
+ <div class="endpoint-url">https://seamo-ai-fishapi.hf.space/api/v1/identify</div>
186
+ </div>
187
+ <p>Upload an image and get species identification results with bounding boxes and confidence scores.</p>
188
+ </div>
189
+ </div>
190
+
191
+ <!-- cURL Example -->
192
+ <div class="api-docs-card">
193
+ <div class="api-docs-card-header">
194
+ <h3>πŸ“‘ cURL</h3>
195
+ <button class="copy-btn" onclick="copyToClipboard('curl-code')">Copy</button>
196
+ </div>
197
+ <div class="api-docs-card-content">
198
+ <pre class="code-block" id="curl-code">curl -X POST "https://seamo-ai-fishapi.hf.space/api/v1/identify" \
199
+ -H "Content-Type: multipart/form-data" \
200
+ -F "file=@your_image.jpg" \
201
+ -F "confidence_threshold=0.25" \
202
+ -F "iou_threshold=0.45"</pre>
203
+ </div>
204
+ </div>
205
+
206
+ <!-- Python Example -->
207
+ <div class="api-docs-card">
208
+ <div class="api-docs-card-header">
209
+ <h3>🐍 Python</h3>
210
+ <button class="copy-btn" onclick="copyToClipboard('python-code')">Copy</button>
211
+ </div>
212
+ <div class="api-docs-card-content">
213
+ <pre class="code-block" id="python-code">import requests
214
+
215
+ url = "https://seamo-ai-fishapi.hf.space/api/v1/identify"
216
+
217
+ with open("your_image.jpg", "rb") as f:
218
+ files = {"file": f}
219
+ data = {
220
+ "confidence_threshold": 0.25,
221
+ "iou_threshold": 0.45
222
+ }
223
+
224
+ response = requests.post(url, files=files, data=data)
225
+ result = response.json()
226
+
227
+ print(f"Found {len(result['detections'])} species")
228
+ for detection in result['detections']:
229
+ print(f"- {detection['class_name']}: {detection['confidence']:.2%}")</pre>
230
+ </div>
231
+ </div>
232
+
233
+ <!-- JavaScript Example -->
234
+ <div class="api-docs-card">
235
+ <div class="api-docs-card-header">
236
+ <h3>🟨 JavaScript</h3>
237
+ <button class="copy-btn" onclick="copyToClipboard('js-code')">Copy</button>
238
+ </div>
239
+ <div class="api-docs-card-content">
240
+ <pre class="code-block" id="js-code">const formData = new FormData();
241
+ formData.append('file', fileInput.files[0]);
242
+ formData.append('confidence_threshold', '0.25');
243
+ formData.append('iou_threshold', '0.45');
244
+
245
+ fetch('https://seamo-ai-fishapi.hf.space/api/v1/identify', {
246
+ method: 'POST',
247
+ body: formData
248
+ })
249
+ .then(response => response.json())
250
+ .then(data => {
251
+ console.log(`Found ${data.detections.length} species`);
252
+ data.detections.forEach(detection => {
253
+ console.log(`${detection.class_name}: ${(detection.confidence * 100).toFixed(1)}%`);
254
+ });
255
+ })
256
+ .catch(error => console.error('Error:', error));</pre>
257
+ </div>
258
+ </div>
259
+
260
+ <!-- .NET C# Example -->
261
+ <div class="api-docs-card">
262
+ <div class="api-docs-card-header">
263
+ <h3>πŸ”· C# (.NET)</h3>
264
+ <button class="copy-btn" onclick="copyToClipboard('dotnet-code')">Copy</button>
265
+ </div>
266
+ <div class="api-docs-card-content">
267
+ <pre class="code-block" id="dotnet-code">using System;
268
+ using System.IO;
269
+ using System.Net.Http;
270
+ using System.Threading.Tasks;
271
+
272
+ var client = new HttpClient();
273
+ var form = new MultipartFormDataContent();
274
+
275
+ // Add image file
276
+ var fileContent = new ByteArrayContent(File.ReadAllBytes("your_image.jpg"));
277
+ fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg");
278
+ form.Add(fileContent, "file", "your_image.jpg");
279
+
280
+ // Add parameters
281
+ form.Add(new StringContent("0.25"), "confidence_threshold");
282
+ form.Add(new StringContent("0.45"), "iou_threshold");
283
+
284
+ var response = await client.PostAsync(
285
+ "https://seamo-ai-fishapi.hf.space/api/v1/identify",
286
+ form
287
+ );
288
+
289
+ var result = await response.Content.ReadAsStringAsync();
290
+ Console.WriteLine(result);</pre>
291
+ </div>
292
+ </div>
293
+
294
+ <!-- Response Format -->
295
+ <div class="api-docs-card">
296
+ <div class="api-docs-card-header">
297
+ <h3>πŸ“‹ Response Format</h3>
298
+ <button class="copy-btn" onclick="copyToClipboard('response-code')">Copy</button>
299
+ </div>
300
+ <div class="api-docs-card-content">
301
+ <pre class="code-block" id="response-code">{
302
+ "success": true,
303
+ "detections": [
304
+ {
305
+ "class_name": "Red Snapper",
306
+ "confidence": 0.89,
307
+ "bbox": [120, 80, 340, 280],
308
+ "class_id": 42
309
+ }
310
+ ],
311
+ "processing_time": 1.23,
312
+ "image_info": {
313
+ "width": 800,
314
+ "height": 600,
315
+ "format": "JPEG"
316
+ },
317
+ "model_info": {
318
+ "name": "marina-benthic-33k",
319
+ "version": "v1.0",
320
+ "total_classes": 691
321
+ }
322
+ }</pre>
323
+ </div>
324
+ </div>
325
+ </div>
326
+
327
+ <!-- Additional Information -->
328
+ <div class="api-docs-footer">
329
+ <div class="api-docs-info-grid">
330
+ <div class="api-info-card">
331
+ <h4>πŸ“Š Parameters</h4>
332
+ <ul>
333
+ <li><strong>file</strong> (required): Image file (JPG, PNG, WebP)</li>
334
+ <li><strong>confidence_threshold</strong>: Min confidence (0.0-1.0, default: 0.25)</li>
335
+ <li><strong>iou_threshold</strong>: IoU threshold (0.0-1.0, default: 0.45)</li>
336
+ </ul>
337
+ </div>
338
+ <div class="api-info-card">
339
+ <h4>πŸ”— Additional Endpoints</h4>
340
+ <ul>
341
+ <li><strong>GET /health</strong>: API health status</li>
342
+ <li><strong>GET /api/v1/species</strong>: List all supported species</li>
343
+ <li><strong>GET /docs</strong>: Interactive Swagger documentation</li>
344
+ </ul>
345
+ </div>
346
+ <div class="api-info-card">
347
+ <h4>⚑ Rate Limits</h4>
348
+ <ul>
349
+ <li><strong>Free tier</strong>: 100 requests/hour</li>
350
+ <li><strong>Max file size</strong>: 10MB</li>
351
+ <li><strong>Supported formats</strong>: JPEG, PNG, WebP</li>
352
+ </ul>
353
+ </div>
354
+ </div>
355
+ </div>
356
+ </div>
357
  </div>
358
  {% endblock %}
359