LPX55 commited on
Commit
be3fa20
·
verified ·
1 Parent(s): 3387712

🐳 12/03 - 06:31 - Create a json view in editor to allow direct editing of contents

Browse files
Files changed (1) hide show
  1. editor.html +122 -0
editor.html CHANGED
@@ -146,6 +146,18 @@
146
  Grid
147
  </button>
148
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
149
  </div>
150
 
151
  <div class="flex items-center gap-2">
@@ -258,6 +270,8 @@
258
  ];
259
  this.currentSlide = 0;
260
  this.previewIndex = 0;
 
 
261
 
262
  this.init();
263
  }
@@ -397,10 +411,53 @@
397
  `).join('');
398
  }
399
 
 
 
 
 
 
 
 
 
 
 
 
400
  renderEditor() {
401
  const slide = this.slides[this.currentSlide];
402
  const form = document.getElementById('edit-form');
403
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
  let html = `
405
  <div class="grid grid-cols-2 gap-4">
406
  <div class="col-span-2">
@@ -531,6 +588,71 @@
531
  this.updatePreview();
532
  }
533
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
534
  updatePreview() {
535
  const slide = this.slides[this.currentSlide];
536
  const preview = document.getElementById('slide-preview');
 
146
  Grid
147
  </button>
148
  </div>
149
+
150
+ <!-- View Toggle -->
151
+ <div class="flex items-center gap-1 bg-indigo-50 rounded-lg p-1 ml-4">
152
+ <button onclick="editor.setViewMode('visual')" id="view-visual" class="view-btn active px-3 py-1.5 rounded-md text-sm font-medium text-indigo-700 flex items-center gap-1">
153
+ <i data-lucide="eye" class="w-4 h-4"></i>
154
+ Visual
155
+ </button>
156
+ <button onclick="editor.setViewMode('json')" id="view-json" class="view-btn px-3 py-1.5 rounded-md text-sm font-medium text-gray-600 flex items-center gap-1">
157
+ <i data-lucide="code" class="w-4 h-4"></i>
158
+ JSON
159
+ </button>
160
+ </div>
161
  </div>
162
 
163
  <div class="flex items-center gap-2">
 
270
  ];
271
  this.currentSlide = 0;
272
  this.previewIndex = 0;
273
+ this.viewMode = 'visual';
274
+ this.jsonError = null;
275
 
276
  this.init();
277
  }
 
411
  `).join('');
412
  }
413
 
414
+ setViewMode(mode) {
415
+ this.viewMode = mode;
416
+ document.querySelectorAll('.view-btn').forEach(btn => {
417
+ btn.classList.remove('active', 'bg-white', 'shadow-sm', 'text-indigo-700');
418
+ btn.classList.add('text-gray-600');
419
+ });
420
+ document.getElementById(`view-${mode}`).classList.add('active', 'bg-white', 'shadow-sm', 'text-indigo-700');
421
+ document.getElementById(`view-${mode}`).classList.remove('text-gray-600');
422
+ this.renderEditor();
423
+ }
424
+
425
  renderEditor() {
426
  const slide = this.slides[this.currentSlide];
427
  const form = document.getElementById('edit-form');
428
 
429
+ // JSON View Mode
430
+ if (this.viewMode === 'json') {
431
+ form.innerHTML = `
432
+ <div class="space-y-4">
433
+ <div class="flex items-center justify-between">
434
+ <div>
435
+ <h3 class="text-sm font-semibold text-gray-900">JSON Editor</h3>
436
+ <p class="text-xs text-gray-500 mt-1">Edit the raw JSON data for this slide</p>
437
+ </div>
438
+ <button onclick="editor.formatJSON()" class="px-3 py-1.5 text-xs font-medium text-indigo-600 bg-indigo-50 rounded-lg hover:bg-indigo-100 transition-colors flex items-center gap-1">
439
+ <i data-lucide="sparkles" class="w-3 h-3"></i>
440
+ Format
441
+ </button>
442
+ </div>
443
+ <div class="relative">
444
+ <textarea id="json-editor"
445
+ oninput="editor.validateJSON(this.value)"
446
+ class="w-full h-96 px-4 py-3 font-mono text-xs leading-relaxed border ${this.jsonError ? 'border-red-300 focus:ring-red-500 focus:border-red-500' : 'border-gray-300 focus:ring-indigo-500 focus:border-indigo-500'} rounded-lg outline-none resize-none"
447
+ spellcheck="false">${JSON.stringify(slide, null, 2)}</textarea>
448
+ ${this.jsonError ? `<div class="absolute bottom-3 left-3 right-3 px-3 py-2 bg-red-50 border border-red-200 rounded-lg text-xs text-red-600 flex items-center gap-2"><i data-lucide="alert-circle" class="w-4 h-4"></i>${this.jsonError}</div>` : ''}
449
+ </div>
450
+ <button onclick="editor.applyJSON()" class="w-full py-3 px-4 bg-indigo-600 text-white rounded-lg font-medium hover:bg-indigo-700 transition-colors flex items-center justify-center gap-2">
451
+ <i data-lucide="save" class="w-4 h-4"></i>
452
+ Apply Changes
453
+ </button>
454
+ </div>
455
+ `;
456
+ lucide.createIcons();
457
+ return;
458
+ }
459
+
460
+ // Visual View Mode
461
  let html = `
462
  <div class="grid grid-cols-2 gap-4">
463
  <div class="col-span-2">
 
588
  this.updatePreview();
589
  }
590
 
591
+ validateJSON(jsonString) {
592
+ try {
593
+ JSON.parse(jsonString);
594
+ this.jsonError = null;
595
+ document.getElementById('json-editor').classList.remove('border-red-300', 'focus:ring-red-500', 'focus:border-red-500');
596
+ document.getElementById('json-editor').classList.add('border-gray-300', 'focus:ring-indigo-500', 'focus:border-indigo-500');
597
+ } catch (err) {
598
+ this.jsonError = err.message;
599
+ document.getElementById('json-editor').classList.add('border-red-300', 'focus:ring-red-500', 'focus:border-red-500');
600
+ document.getElementById('json-editor').classList.remove('border-gray-300', 'focus:ring-indigo-500', 'focus:border-indigo-500');
601
+ }
602
+ // Re-render to show/hide error message
603
+ const textarea = document.getElementById('json-editor');
604
+ const cursorPosition = textarea.selectionStart;
605
+ this.renderEditor();
606
+ // Restore cursor position
607
+ const newTextarea = document.getElementById('json-editor');
608
+ if (newTextarea) {
609
+ newTextarea.focus();
610
+ newTextarea.setSelectionRange(cursorPosition, cursorPosition);
611
+ }
612
+ }
613
+
614
+ formatJSON() {
615
+ const textarea = document.getElementById('json-editor');
616
+ try {
617
+ const parsed = JSON.parse(textarea.value);
618
+ textarea.value = JSON.stringify(parsed, null, 2);
619
+ this.jsonError = null;
620
+ this.renderEditor();
621
+ } catch (err) {
622
+ this.jsonError = err.message;
623
+ this.renderEditor();
624
+ }
625
+ }
626
+
627
+ applyJSON() {
628
+ const textarea = document.getElementById('json-editor');
629
+ try {
630
+ const parsed = JSON.parse(textarea.value);
631
+ // Preserve the ID
632
+ parsed.id = this.slides[this.currentSlide].id;
633
+ this.slides[this.currentSlide] = parsed;
634
+ this.jsonError = null;
635
+ this.renderSlidesList();
636
+ this.updatePreview();
637
+ // Show success feedback
638
+ const btn = document.querySelector('button[onclick="editor.applyJSON()"]');
639
+ const originalText = btn.innerHTML;
640
+ btn.innerHTML = '<i data-lucide="check" class="w-4 h-4"></i> Saved!';
641
+ btn.classList.add('bg-green-600', 'hover:bg-green-700');
642
+ btn.classList.remove('bg-indigo-600', 'hover:bg-indigo-700');
643
+ lucide.createIcons();
644
+ setTimeout(() => {
645
+ btn.innerHTML = originalText;
646
+ btn.classList.remove('bg-green-600', 'hover:bg-green-700');
647
+ btn.classList.add('bg-indigo-600', 'hover:bg-indigo-700');
648
+ lucide.createIcons();
649
+ }, 2000);
650
+ } catch (err) {
651
+ this.jsonError = err.message;
652
+ this.renderEditor();
653
+ }
654
+ }
655
+
656
  updatePreview() {
657
  const slide = this.slides[this.currentSlide];
658
  const preview = document.getElementById('slide-preview');