viberadar 0.3.189 → 0.3.190

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3782,29 +3782,61 @@ function openProbeUploadModal() {
3782
3782
  overlay = document.createElement('div');
3783
3783
  overlay.id = 'probeUploadOverlay';
3784
3784
  overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.6);display:flex;align-items:center;justify-content:center;z-index:9999';
3785
+
3786
+ const tabStyle = (active) => `padding:7px 16px;font-size:13px;cursor:pointer;border:none;background:none;border-bottom:2px solid ${active ? 'var(--blue)' : 'transparent'};color:${active ? 'var(--blue)' : 'var(--muted)'};transition:all 0.15s`;
3787
+ const inputStyle = `width:100%;box-sizing:border-box;padding:8px 12px;border-radius:6px;border:1px solid var(--border);background:var(--bg);color:var(--text);font-size:13px`;
3788
+
3785
3789
  overlay.innerHTML = `
3786
- <div style="background:var(--bg-card);border:1px solid var(--border);border-radius:12px;padding:24px 28px;width:480px;max-width:90vw">
3787
- <h3 style="margin:0 0 4px;font-size:16px;color:var(--text)">📤 Загрузить тест</h3>
3788
- <div style="font-size:12px;color:var(--muted);margin-bottom:20px">Файл сохранится в <code>e2e/</code> и появится в списке проверок</div>
3789
-
3790
- <div id="probeUploadDrop" style="border:2px dashed var(--border);border-radius:8px;padding:32px 20px;text-align:center;cursor:pointer;transition:border-color 0.2s" onclick="document.getElementById('probeUploadInput').click()">
3791
- <div style="font-size:24px;margin-bottom:8px">📁</div>
3792
- <div style="font-size:13px;color:var(--muted)">Нажмите или перетащите <code>.spec.ts</code> файл</div>
3793
- <div id="probeUploadFileName" style="margin-top:8px;font-size:12px;color:var(--blue)"></div>
3794
- <input id="probeUploadInput" type="file" accept=".ts" style="display:none">
3790
+ <div style="background:var(--bg-card);border:1px solid var(--border);border-radius:12px;padding:24px 28px;width:560px;max-width:95vw;max-height:90vh;overflow-y:auto">
3791
+ <h3 style="margin:0 0 16px;font-size:16px;color:var(--text)">📤 Импорт теста</h3>
3792
+
3793
+ <div style="display:flex;gap:0;border-bottom:1px solid var(--border);margin-bottom:20px">
3794
+ <button id="tabFile" style="${tabStyle(true)}" onclick="probeUploadSwitchTab('file')">📁 Файл</button>
3795
+ <button id="tabPaste" style="${tabStyle(false)}" onclick="probeUploadSwitchTab('paste')">📋 Вставить код</button>
3796
+ </div>
3797
+
3798
+ <!-- TAB: file -->
3799
+ <div id="tabFileContent">
3800
+ <div id="probeUploadDrop" style="border:2px dashed var(--border);border-radius:8px;padding:28px 20px;text-align:center;cursor:pointer;transition:border-color 0.2s" onclick="document.getElementById('probeUploadInput').click()">
3801
+ <div style="font-size:24px;margin-bottom:8px">📁</div>
3802
+ <div style="font-size:13px;color:var(--muted)">Нажмите или перетащите <code>.spec.ts</code> файл</div>
3803
+ <div id="probeUploadFileName" style="margin-top:8px;font-size:12px;color:var(--blue)"></div>
3804
+ <input id="probeUploadInput" type="file" accept=".ts" style="display:none">
3805
+ </div>
3806
+ </div>
3807
+
3808
+ <!-- TAB: paste -->
3809
+ <div id="tabPasteContent" style="display:none">
3810
+ <label style="font-size:12px;color:var(--muted);display:block;margin-bottom:4px">Имя файла <span style="color:var(--dim)">(например: my-test.spec.ts)</span></label>
3811
+ <input id="probeUploadPasteName" type="text" placeholder="my-test.spec.ts" style="${inputStyle};margin-bottom:12px">
3812
+ <label style="font-size:12px;color:var(--muted);display:block;margin-bottom:4px">Код теста</label>
3813
+ <textarea id="probeUploadPasteCode" placeholder="Вставьте содержимое .spec.ts файла…"
3814
+ style="${inputStyle};height:240px;resize:vertical;font-family:'SFMono-Regular',Consolas,monospace;font-size:12px;line-height:1.5;white-space:pre"></textarea>
3795
3815
  </div>
3796
3816
 
3797
3817
  <div id="probeUploadErr" style="display:none;margin-top:12px;padding:8px 12px;border-radius:6px;background:rgba(248,81,73,0.1);color:var(--red);font-size:12px"></div>
3798
- <div id="probeUploadOk" style="display:none;margin-top:12px;padding:8px 12px;border-radius:6px;background:rgba(63,185,80,0.1);color:var(--green);font-size:12px"></div>
3818
+ <div id="probeUploadOk" style="display:none;margin-top:12px;padding:8px 12px;border-radius:6px;background:rgba(63,185,80,0.1);color:var(--green);font-size:12px"></div>
3799
3819
  <div style="display:flex;gap:10px;justify-content:flex-end;margin-top:20px">
3800
3820
  <button onclick="document.getElementById('probeUploadOverlay').remove()" style="padding:6px 16px;border-radius:6px;border:1px solid var(--border);background:var(--bg);color:var(--text);cursor:pointer;font-size:13px">Отмена</button>
3801
3821
  <button id="probeUploadSave" disabled style="padding:6px 16px;border-radius:6px;border:1px solid var(--blue);background:var(--blue);color:#fff;cursor:pointer;font-size:13px;opacity:0.5">Загрузить</button>
3802
3822
  </div>
3803
3823
  </div>`;
3824
+
3804
3825
  document.body.appendChild(overlay);
3805
3826
  overlay.addEventListener('click', e => { if (e.target === overlay) overlay.remove(); });
3806
3827
 
3807
- // Drag & drop
3828
+ // Tab switching
3829
+ window.probeUploadSwitchTab = (tab) => {
3830
+ const isFile = tab === 'file';
3831
+ document.getElementById('tabFileContent').style.display = isFile ? '' : 'none';
3832
+ document.getElementById('tabPasteContent').style.display = isFile ? 'none' : '';
3833
+ const tabStyle = (active) => `padding:7px 16px;font-size:13px;cursor:pointer;border:none;background:none;border-bottom:2px solid ${active ? 'var(--blue)' : 'transparent'};color:${active ? 'var(--blue)' : 'var(--muted)'};transition:all 0.15s`;
3834
+ document.getElementById('tabFile').style.cssText = tabStyle(isFile);
3835
+ document.getElementById('tabPaste').style.cssText = tabStyle(!isFile);
3836
+ checkPasteReady();
3837
+ };
3838
+
3839
+ // File tab — drag & drop + file picker
3808
3840
  const dropZone = document.getElementById('probeUploadDrop');
3809
3841
  dropZone.addEventListener('dragover', e => { e.preventDefault(); dropZone.style.borderColor = 'var(--blue)'; });
3810
3842
  dropZone.addEventListener('dragleave', () => { dropZone.style.borderColor = 'var(--border)'; });
@@ -3812,33 +3844,73 @@ function openProbeUploadModal() {
3812
3844
  e.preventDefault();
3813
3845
  dropZone.style.borderColor = 'var(--border)';
3814
3846
  const file = e.dataTransfer?.files?.[0];
3815
- if (file) handleUploadFile(file);
3847
+ if (file) setUploadFile(file);
3816
3848
  });
3817
-
3818
3849
  let uploadFile = null;
3819
3850
  const input = document.getElementById('probeUploadInput');
3820
- input.addEventListener('change', () => { if (input.files[0]) handleUploadFile(input.files[0]); });
3821
-
3822
- function handleUploadFile(file) {
3851
+ input.addEventListener('change', () => { if (input.files[0]) setUploadFile(input.files[0]); });
3852
+ function setUploadFile(file) {
3823
3853
  uploadFile = file;
3824
3854
  document.getElementById('probeUploadFileName').textContent = file.name;
3825
- document.getElementById('probeUploadSave').disabled = false;
3826
- document.getElementById('probeUploadSave').style.opacity = '1';
3855
+ setSubmitReady(true);
3856
+ }
3857
+
3858
+ // Paste tab — enable button when both fields filled
3859
+ function checkPasteReady() {
3860
+ const name = (document.getElementById('probeUploadPasteName')?.value || '').trim();
3861
+ const code = (document.getElementById('probeUploadPasteCode')?.value || '').trim();
3862
+ const tabVisible = document.getElementById('tabPasteContent')?.style.display !== 'none';
3863
+ if (tabVisible) setSubmitReady(!!(name && code));
3864
+ }
3865
+ document.getElementById('probeUploadPasteName').addEventListener('input', checkPasteReady);
3866
+ document.getElementById('probeUploadPasteCode').addEventListener('input', checkPasteReady);
3867
+
3868
+ // Auto-detect filename from `test(` or filename line in pasted code
3869
+ document.getElementById('probeUploadPasteCode').addEventListener('paste', (e) => {
3870
+ setTimeout(() => {
3871
+ const nameInput = document.getElementById('probeUploadPasteName');
3872
+ if (nameInput && !nameInput.value.trim()) {
3873
+ const code = document.getElementById('probeUploadPasteCode').value;
3874
+ // Try to extract filename from first comment like // auth-login.spec.ts
3875
+ const m = code.match(/\/\/\s*([\w.-]+\.spec\.ts)/);
3876
+ if (m) nameInput.value = m[1];
3877
+ }
3878
+ checkPasteReady();
3879
+ }, 0);
3880
+ });
3881
+
3882
+ function setSubmitReady(ready) {
3883
+ const btn = document.getElementById('probeUploadSave');
3884
+ if (!btn) return;
3885
+ btn.disabled = !ready;
3886
+ btn.style.opacity = ready ? '1' : '0.5';
3827
3887
  }
3828
3888
 
3889
+ // Submit
3829
3890
  document.getElementById('probeUploadSave').addEventListener('click', async () => {
3830
- if (!uploadFile) return;
3831
3891
  const btn = document.getElementById('probeUploadSave');
3832
3892
  const err = document.getElementById('probeUploadErr');
3833
- const ok = document.getElementById('probeUploadOk');
3893
+ const ok = document.getElementById('probeUploadOk');
3834
3894
  err.style.display = 'none'; ok.style.display = 'none';
3895
+
3896
+ const pasteVisible = document.getElementById('tabPasteContent').style.display !== 'none';
3897
+ let filename, content;
3898
+ if (pasteVisible) {
3899
+ filename = document.getElementById('probeUploadPasteName').value.trim();
3900
+ content = document.getElementById('probeUploadPasteCode').value;
3901
+ if (!filename.endsWith('.ts')) filename += '.ts';
3902
+ } else {
3903
+ if (!uploadFile) return;
3904
+ filename = uploadFile.name;
3905
+ content = await uploadFile.text();
3906
+ }
3907
+
3835
3908
  btn.disabled = true; btn.textContent = 'Загружаю…';
3836
3909
  try {
3837
- const content = await uploadFile.text();
3838
3910
  const res = await fetch('/api/probe/upload-test', {
3839
3911
  method: 'POST',
3840
3912
  headers: { 'Content-Type': 'application/json' },
3841
- body: JSON.stringify({ filename: uploadFile.name, content }),
3913
+ body: JSON.stringify({ filename, content }),
3842
3914
  });
3843
3915
  const data = await res.json();
3844
3916
  if (!res.ok) throw new Error(data.error || 'Ошибка загрузки');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viberadar",
3
- "version": "0.3.189",
3
+ "version": "0.3.190",
4
4
  "description": "Live module map with test coverage for vibecoding projects",
5
5
  "main": "./dist/cli.js",
6
6
  "bin": {