dippoo commited on
Commit
1dc4764
·
1 Parent(s): 85988f2

Add bulk caption paste feature to training UI

Browse files
Files changed (1) hide show
  1. src/content_engine/api/ui.html +43 -0
src/content_engine/api/ui.html CHANGED
@@ -1309,8 +1309,17 @@ select { cursor: pointer; }
1309
  <div class="caption-toolbar">
1310
  <span style="font-size:12px;color:var(--text-secondary)">Captions per image (improves LoRA quality)</span>
1311
  <button class="btn btn-secondary btn-small" onclick="autoCaptionAll()">Auto-fill from trigger word</button>
 
1312
  <button class="btn btn-secondary btn-small" onclick="clearTrainImages()">Clear all</button>
1313
  </div>
 
 
 
 
 
 
 
 
1314
  <div id="caption-editor" class="caption-editor"></div>
1315
  </div>
1316
 
@@ -1944,6 +1953,40 @@ function autoCaptionAll() {
1944
  toast(`Applied "${trigger}" to ${trainImageFiles.length} images`, 'success');
1945
  }
1946
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1947
  function clearTrainImages() {
1948
  trainImageFiles = [];
1949
  trainCaptions = {};
 
1309
  <div class="caption-toolbar">
1310
  <span style="font-size:12px;color:var(--text-secondary)">Captions per image (improves LoRA quality)</span>
1311
  <button class="btn btn-secondary btn-small" onclick="autoCaptionAll()">Auto-fill from trigger word</button>
1312
+ <button class="btn btn-secondary btn-small" onclick="toggleBulkCaptions()">Bulk Paste</button>
1313
  <button class="btn btn-secondary btn-small" onclick="clearTrainImages()">Clear all</button>
1314
  </div>
1315
+ <div id="bulk-caption-area" style="display:none;margin:8px 0">
1316
+ <textarea id="bulk-caption-text" style="width:100%;height:200px;font-size:12px;padding:8px;border-radius:6px;border:1px solid var(--border);background:var(--bg-primary);color:var(--text-primary);resize:vertical;font-family:inherit" placeholder="Paste numbered captions, one per line. They map to images in order.&#10;&#10;1. ohwx woman, portrait, natural lighting, smiling&#10;2. ohwx woman, full body, outdoor, park&#10;3. ohwx woman, close-up, studio lighting&#10;..."></textarea>
1317
+ <div style="display:flex;gap:8px;margin-top:6px">
1318
+ <button class="btn btn-primary btn-small" onclick="applyBulkCaptions()">Apply to images</button>
1319
+ <button class="btn btn-secondary btn-small" onclick="toggleBulkCaptions()">Cancel</button>
1320
+ <span style="font-size:11px;color:var(--text-secondary);align-self:center">Accepts: "1. text", "1) text", or plain lines</span>
1321
+ </div>
1322
+ </div>
1323
  <div id="caption-editor" class="caption-editor"></div>
1324
  </div>
1325
 
 
1953
  toast(`Applied "${trigger}" to ${trainImageFiles.length} images`, 'success');
1954
  }
1955
 
1956
+ function toggleBulkCaptions() {
1957
+ const area = document.getElementById('bulk-caption-area');
1958
+ area.style.display = area.style.display === 'none' ? 'block' : 'none';
1959
+ }
1960
+
1961
+ function applyBulkCaptions() {
1962
+ const raw = document.getElementById('bulk-caption-text').value.trim();
1963
+ if (!raw) { toast('Paste captions first', 'error'); return; }
1964
+ if (trainImageFiles.length === 0) { toast('Upload images first', 'error'); return; }
1965
+
1966
+ // Parse lines: strip numbering like "1. ", "1) ", "1: ", or plain lines
1967
+ const lines = raw.split('\n')
1968
+ .map(l => l.trim())
1969
+ .filter(l => l.length > 0)
1970
+ .map(l => l.replace(/^\d+[\.\)\:\-]\s*/, ''));
1971
+
1972
+ const count = Math.min(lines.length, trainImageFiles.length);
1973
+ const textareas = document.querySelectorAll('#caption-editor textarea');
1974
+
1975
+ for (let i = 0; i < count; i++) {
1976
+ trainCaptions[trainImageFiles[i].name] = lines[i];
1977
+ if (textareas[i]) textareas[i].value = lines[i];
1978
+ }
1979
+
1980
+ document.getElementById('bulk-caption-area').style.display = 'none';
1981
+ document.getElementById('bulk-caption-text').value = '';
1982
+ toast(`Applied captions to ${count} of ${trainImageFiles.length} images`, 'success');
1983
+ if (lines.length > trainImageFiles.length) {
1984
+ toast(`${lines.length - trainImageFiles.length} extra captions ignored (more captions than images)`, 'warning');
1985
+ } else if (lines.length < trainImageFiles.length) {
1986
+ toast(`${trainImageFiles.length - lines.length} images have no caption yet`, 'warning');
1987
+ }
1988
+ }
1989
+
1990
  function clearTrainImages() {
1991
  trainImageFiles = [];
1992
  trainCaptions = {};