@matdata/yasgui 5.17.0 → 5.19.0

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.
Files changed (59) hide show
  1. package/build/ts/src/Tab.js +7 -1
  2. package/build/ts/src/Tab.js.map +1 -1
  3. package/build/ts/src/TabContextMenu.d.ts +1 -0
  4. package/build/ts/src/TabContextMenu.js +42 -0
  5. package/build/ts/src/TabContextMenu.js.map +1 -1
  6. package/build/ts/src/TabSettingsModal.d.ts +2 -1
  7. package/build/ts/src/TabSettingsModal.js +44 -25
  8. package/build/ts/src/TabSettingsModal.js.map +1 -1
  9. package/build/ts/src/index.d.ts +6 -0
  10. package/build/ts/src/index.js +42 -0
  11. package/build/ts/src/index.js.map +1 -1
  12. package/build/ts/src/prefixUtils.d.ts +1 -0
  13. package/build/ts/src/prefixUtils.js +23 -0
  14. package/build/ts/src/prefixUtils.js.map +1 -0
  15. package/build/ts/src/queryManagement/QueryBrowser.d.ts +8 -0
  16. package/build/ts/src/queryManagement/QueryBrowser.js +283 -116
  17. package/build/ts/src/queryManagement/QueryBrowser.js.map +1 -1
  18. package/build/ts/src/queryManagement/QueryHistoryModal.d.ts +35 -0
  19. package/build/ts/src/queryManagement/QueryHistoryModal.js +266 -0
  20. package/build/ts/src/queryManagement/QueryHistoryModal.js.map +1 -0
  21. package/build/ts/src/queryManagement/WorkspaceSettingsForm.js +8 -5
  22. package/build/ts/src/queryManagement/WorkspaceSettingsForm.js.map +1 -1
  23. package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.d.ts +1 -0
  24. package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.js +33 -0
  25. package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.js.map +1 -1
  26. package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.d.ts +1 -0
  27. package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.js +3 -0
  28. package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.js.map +1 -1
  29. package/build/ts/src/queryManagement/backends/WorkspaceBackend.d.ts +1 -0
  30. package/build/ts/src/queryManagement/countManagedQueries.d.ts +2 -0
  31. package/build/ts/src/queryManagement/countManagedQueries.js +35 -0
  32. package/build/ts/src/queryManagement/countManagedQueries.js.map +1 -0
  33. package/build/ts/src/tabNavigationHistory.d.ts +3 -0
  34. package/build/ts/src/tabNavigationHistory.js +13 -0
  35. package/build/ts/src/tabNavigationHistory.js.map +1 -0
  36. package/build/ts/src/version.d.ts +1 -1
  37. package/build/ts/src/version.js +1 -1
  38. package/build/yasgui.min.css +1 -1
  39. package/build/yasgui.min.css.map +3 -3
  40. package/build/yasgui.min.js +245 -245
  41. package/build/yasgui.min.js.map +4 -4
  42. package/package.json +1 -1
  43. package/src/Tab.ts +10 -0
  44. package/src/TabContextMenu.ts +42 -0
  45. package/src/TabSettingsModal.ts +48 -29
  46. package/src/index.ts +50 -0
  47. package/src/prefixUtils.ts +26 -0
  48. package/src/queryManagement/QueryBrowser.scss +85 -0
  49. package/src/queryManagement/QueryBrowser.ts +429 -213
  50. package/src/queryManagement/QueryHistoryModal.scss +239 -0
  51. package/src/queryManagement/QueryHistoryModal.ts +346 -0
  52. package/src/queryManagement/WorkspaceSettingsForm.ts +8 -5
  53. package/src/queryManagement/backends/GitWorkspaceBackend.ts +39 -0
  54. package/src/queryManagement/backends/SparqlWorkspaceBackend.ts +5 -0
  55. package/src/queryManagement/backends/WorkspaceBackend.ts +8 -0
  56. package/src/queryManagement/countManagedQueries.ts +28 -0
  57. package/src/tabNavigationHistory.ts +17 -0
  58. package/src/themes.scss +44 -0
  59. package/src/version.ts +1 -1
@@ -15,6 +15,7 @@ import { getEndpointToAutoSwitch } from "./openManagedQuery";
15
15
  import { hashQueryText } from "./textHash";
16
16
  import { normalizeQueryFilename } from "./normalizeQueryFilename";
17
17
  import SaveManagedQueryModal from "./SaveManagedQueryModal";
18
+ import QueryHistoryModal from "./QueryHistoryModal";
18
19
  import "./QueryBrowser.scss";
19
20
  export default class QueryBrowser {
20
21
  entrySignature(entry) {
@@ -176,6 +177,7 @@ export default class QueryBrowser {
176
177
  removeClass(this.rootEl, "open");
177
178
  this.rootEl.setAttribute("aria-hidden", "true");
178
179
  this.rootEl.style.display = "none";
180
+ this.closeQueryContextMenu();
179
181
  if (this.openerEl) {
180
182
  this.openerEl.focus();
181
183
  this.openerEl = undefined;
@@ -477,79 +479,142 @@ export default class QueryBrowser {
477
479
  tab.setManagedQueryMetadata(managedMetadata);
478
480
  });
479
481
  }
480
- addQueryRowActions(row, backend, entry) {
481
- const actions = document.createElement("span");
482
- addClass(actions, "yasgui-query-browser__actions");
483
- if (entry.kind === "folder") {
484
- if (backend.renameFolder) {
485
- const renameBtn = document.createElement("button");
486
- renameBtn.type = "button";
487
- addClass(renameBtn, "yasgui-query-browser__action");
488
- renameBtn.textContent = "Rename";
489
- renameBtn.setAttribute("aria-label", `Rename folder ${entry.label}`);
490
- renameBtn.addEventListener("click", (e) => __awaiter(this, void 0, void 0, function* () {
491
- e.preventDefault();
492
- e.stopPropagation();
493
- const next = window.prompt("Rename folder", entry.label);
494
- if (!next)
495
- return;
496
- const trimmed = next.trim();
497
- if (!trimmed || trimmed === entry.label)
498
- return;
499
- try {
500
- yield backend.renameFolder(entry.id, trimmed);
501
- this.folderEntriesById.clear();
502
- this.invalidateRenderCache();
503
- yield this.refresh();
504
- }
505
- catch (err) {
506
- window.alert(asWorkspaceBackendError(err).message);
507
- }
508
- }));
509
- actions.appendChild(renameBtn);
482
+ closeQueryContextMenu() {
483
+ if (this.queryContextMenuEl) {
484
+ this.queryContextMenuEl.remove();
485
+ this.queryContextMenuEl = undefined;
486
+ }
487
+ if (this.queryContextMenuCleanup) {
488
+ this.queryContextMenuCleanup();
489
+ this.queryContextMenuCleanup = undefined;
490
+ }
491
+ }
492
+ startInlineRename(row, currentLabel) {
493
+ return new Promise((resolve) => {
494
+ const labelEl = row.querySelector(".yasgui-query-browser__tree-label");
495
+ if (!labelEl) {
496
+ resolve(null);
497
+ return;
510
498
  }
511
- if (backend.deleteFolder) {
512
- const deleteBtn = document.createElement("button");
513
- deleteBtn.type = "button";
514
- addClass(deleteBtn, "yasgui-query-browser__action");
515
- addClass(deleteBtn, "yasgui-query-browser__action--danger");
516
- deleteBtn.textContent = "Delete";
517
- deleteBtn.setAttribute("aria-label", `Delete folder ${entry.label}`);
518
- deleteBtn.addEventListener("click", (e) => __awaiter(this, void 0, void 0, function* () {
499
+ const input = document.createElement("input");
500
+ input.type = "text";
501
+ input.value = currentLabel;
502
+ addClass(input, "yasgui-query-browser__rename-input");
503
+ let settled = false;
504
+ const finish = (value) => {
505
+ if (settled)
506
+ return;
507
+ settled = true;
508
+ input.remove();
509
+ labelEl.style.display = "";
510
+ resolve(value);
511
+ };
512
+ input.addEventListener("click", (e) => e.stopPropagation());
513
+ input.addEventListener("keydown", (e) => {
514
+ e.stopPropagation();
515
+ if (e.key === "Enter") {
519
516
  e.preventDefault();
520
- e.stopPropagation();
521
- const ok = window.confirm(`Delete folder '${entry.label}' and everything inside it? This cannot be undone.`);
522
- if (!ok)
523
- return;
517
+ finish(input.value.trim() || null);
518
+ }
519
+ else if (e.key === "Escape") {
520
+ e.preventDefault();
521
+ finish(null);
522
+ }
523
+ });
524
+ input.addEventListener("blur", () => finish(null));
525
+ labelEl.style.display = "none";
526
+ labelEl.insertAdjacentElement("afterend", input);
527
+ input.focus();
528
+ input.select();
529
+ });
530
+ }
531
+ showInlineConfirm(row, message) {
532
+ return new Promise((resolve) => {
533
+ const savedChildren = Array.from(row.childNodes);
534
+ while (row.firstChild)
535
+ row.removeChild(row.firstChild);
536
+ const confirmEl = document.createElement("span");
537
+ addClass(confirmEl, "yasgui-query-browser__inline-confirm");
538
+ confirmEl.textContent = message;
539
+ confirmEl.addEventListener("click", (e) => e.stopPropagation());
540
+ const yes = document.createElement("button");
541
+ yes.type = "button";
542
+ yes.textContent = "Yes";
543
+ addClass(yes, "yasgui-query-browser__inline-confirm-btn");
544
+ addClass(yes, "yasgui-query-browser__inline-confirm-btn--danger");
545
+ const no = document.createElement("button");
546
+ no.type = "button";
547
+ no.textContent = "No";
548
+ addClass(no, "yasgui-query-browser__inline-confirm-btn");
549
+ let settled = false;
550
+ const finish = (value) => {
551
+ if (settled)
552
+ return;
553
+ settled = true;
554
+ while (row.firstChild)
555
+ row.removeChild(row.firstChild);
556
+ for (const child of savedChildren)
557
+ row.appendChild(child);
558
+ resolve(value);
559
+ };
560
+ yes.addEventListener("click", (e) => {
561
+ e.stopPropagation();
562
+ finish(true);
563
+ });
564
+ no.addEventListener("click", (e) => {
565
+ e.stopPropagation();
566
+ finish(false);
567
+ });
568
+ row.appendChild(confirmEl);
569
+ row.appendChild(document.createTextNode(" "));
570
+ row.appendChild(yes);
571
+ row.appendChild(document.createTextNode(" "));
572
+ row.appendChild(no);
573
+ no.focus();
574
+ });
575
+ }
576
+ openQueryContextMenu(event, backend, entry, row) {
577
+ event.preventDefault();
578
+ event.stopPropagation();
579
+ this.closeQueryContextMenu();
580
+ const menu = document.createElement("ul");
581
+ addClass(menu, "yasgui-query-browser__context-menu");
582
+ const makeItem = (label, handler, isDanger = false) => {
583
+ const li = document.createElement("li");
584
+ addClass(li, "yasgui-query-browser__context-menu-item");
585
+ if (isDanger)
586
+ addClass(li, "yasgui-query-browser__context-menu-item--danger");
587
+ li.textContent = label;
588
+ li.addEventListener("click", (e) => __awaiter(this, void 0, void 0, function* () {
589
+ e.stopPropagation();
590
+ this.closeQueryContextMenu();
591
+ yield handler();
592
+ }));
593
+ return li;
594
+ };
595
+ if (backend.getQueryUri) {
596
+ const uri = backend.getQueryUri(entry.id);
597
+ if (uri) {
598
+ menu.appendChild(makeItem("Copy URI", () => __awaiter(this, void 0, void 0, function* () {
524
599
  try {
525
- yield backend.deleteFolder(entry.id);
526
- this.folderEntriesById.clear();
527
- this.invalidateRenderCache();
528
- yield this.refresh();
600
+ yield navigator.clipboard.writeText(uri);
529
601
  }
530
- catch (err) {
531
- window.alert(asWorkspaceBackendError(err).message);
602
+ catch (_a) {
603
+ window.prompt("Copy this URI:", uri);
532
604
  }
533
- }));
534
- actions.appendChild(deleteBtn);
605
+ })));
535
606
  }
536
- if (actions.childElementCount > 0)
537
- row.appendChild(actions);
538
- return;
539
607
  }
540
- if (entry.kind !== "query")
541
- return;
608
+ menu.appendChild(makeItem("History", () => __awaiter(this, void 0, void 0, function* () {
609
+ if (!this.queryHistoryModal)
610
+ this.queryHistoryModal = new QueryHistoryModal(this.yasgui);
611
+ yield this.queryHistoryModal.show(this.selectedWorkspaceId, backend, backend.type, entry.id, entry.label);
612
+ })));
542
613
  if (backend.renameQuery) {
543
- const renameBtn = document.createElement("button");
544
- renameBtn.type = "button";
545
- addClass(renameBtn, "yasgui-query-browser__action");
546
- renameBtn.textContent = "Rename";
547
- renameBtn.setAttribute("aria-label", `Rename ${entry.label}`);
548
- renameBtn.addEventListener("click", (e) => __awaiter(this, void 0, void 0, function* () {
614
+ const renameQuery = backend.renameQuery.bind(backend);
615
+ menu.appendChild(makeItem("Rename", () => __awaiter(this, void 0, void 0, function* () {
549
616
  var _a, _b, _c, _d, _e, _f, _g;
550
- e.preventDefault();
551
- e.stopPropagation();
552
- const next = window.prompt("Rename query", entry.label);
617
+ const next = yield this.startInlineRename(row, entry.label);
553
618
  if (!next)
554
619
  return;
555
620
  const trimmed = next.trim();
@@ -566,12 +631,8 @@ export default class QueryBrowser {
566
631
  const newPath = folderPrefix ? `${folderPrefix}/${newFilename}` : newFilename;
567
632
  return { oldPath: entry.id, newPath };
568
633
  })();
569
- const originalText = renameBtn.textContent;
570
- renameBtn.disabled = true;
571
- renameBtn.textContent = "Renaming…";
572
- addClass(renameBtn, "loading");
573
634
  try {
574
- yield backend.renameQuery(entry.id, trimmed);
635
+ yield renameQuery(entry.id, trimmed);
575
636
  if (gitRenameInfo && gitRenameInfo.newPath && gitRenameInfo.oldPath) {
576
637
  for (const tab of Object.values(this.yasgui._tabs)) {
577
638
  const meta = (_b = (_a = tab).getManagedQueryMetadata) === null || _b === void 0 ? void 0 : _b.call(_a);
@@ -602,24 +663,14 @@ export default class QueryBrowser {
602
663
  yield this.refresh();
603
664
  }
604
665
  catch (err) {
605
- renameBtn.disabled = false;
606
- renameBtn.textContent = originalText || "Rename";
607
- removeClass(renameBtn, "loading");
608
- window.alert(asWorkspaceBackendError(err).message);
666
+ this.setStatus(asWorkspaceBackendError(err).message);
609
667
  }
610
- }));
611
- actions.appendChild(renameBtn);
668
+ })));
612
669
  }
613
670
  if (backend.moveQuery) {
614
- const moveBtn = document.createElement("button");
615
- moveBtn.type = "button";
616
- addClass(moveBtn, "yasgui-query-browser__action");
617
- moveBtn.textContent = "Move";
618
- moveBtn.setAttribute("aria-label", `Move ${entry.label} to a different folder`);
619
- moveBtn.addEventListener("click", (e) => __awaiter(this, void 0, void 0, function* () {
671
+ const moveQuery = backend.moveQuery.bind(backend);
672
+ menu.appendChild(makeItem("Move", () => __awaiter(this, void 0, void 0, function* () {
620
673
  var _a, _b, _c, _d, _e;
621
- e.preventDefault();
622
- e.stopPropagation();
623
674
  const currentFolderPath = entry.parentId || "";
624
675
  if (!this.folderPickerModal)
625
676
  this.folderPickerModal = new SaveManagedQueryModal(this.yasgui);
@@ -628,12 +679,8 @@ export default class QueryBrowser {
628
679
  return;
629
680
  if (newFolderPath === currentFolderPath)
630
681
  return;
631
- const originalText = moveBtn.textContent;
632
- moveBtn.disabled = true;
633
- moveBtn.textContent = "Moving…";
634
- addClass(moveBtn, "loading");
635
682
  try {
636
- const newQueryId = yield backend.moveQuery(entry.id, newFolderPath);
683
+ const newQueryId = yield moveQuery(entry.id, newFolderPath);
637
684
  if (backend.type === "git" && newQueryId !== entry.id) {
638
685
  for (const tab of Object.values(this.yasgui._tabs)) {
639
686
  const meta = (_b = (_a = tab).getManagedQueryMetadata) === null || _b === void 0 ? void 0 : _b.call(_a);
@@ -663,50 +710,170 @@ export default class QueryBrowser {
663
710
  yield this.refresh();
664
711
  }
665
712
  catch (err) {
666
- moveBtn.disabled = false;
667
- moveBtn.textContent = originalText || "Move";
668
- removeClass(moveBtn, "loading");
669
- window.alert(asWorkspaceBackendError(err).message);
713
+ this.setStatus(asWorkspaceBackendError(err).message);
670
714
  }
671
- }));
672
- actions.appendChild(moveBtn);
715
+ })));
673
716
  }
674
717
  if (backend.deleteQuery) {
675
- const deleteBtn = document.createElement("button");
676
- deleteBtn.type = "button";
677
- addClass(deleteBtn, "yasgui-query-browser__action");
678
- addClass(deleteBtn, "yasgui-query-browser__action--danger");
679
- deleteBtn.textContent = "Delete";
680
- deleteBtn.setAttribute("aria-label", `Delete ${entry.label}`);
681
- deleteBtn.addEventListener("click", (e) => __awaiter(this, void 0, void 0, function* () {
682
- e.preventDefault();
683
- e.stopPropagation();
684
- const ok = window.confirm(`Delete '${entry.label}'? This cannot be undone.`);
718
+ const deleteQuery = backend.deleteQuery.bind(backend);
719
+ menu.appendChild(makeItem("Delete", () => __awaiter(this, void 0, void 0, function* () {
720
+ const ok = yield this.showInlineConfirm(row, `Delete '${entry.label}'?`);
685
721
  if (!ok)
686
722
  return;
687
- const originalText = deleteBtn.textContent;
688
- deleteBtn.disabled = true;
689
- deleteBtn.textContent = "Deleting…";
690
- addClass(deleteBtn, "loading");
691
723
  try {
692
- yield backend.deleteQuery(entry.id);
724
+ yield deleteQuery(entry.id);
693
725
  this.queryPreviewById.delete(entry.id);
694
726
  this.folderEntriesById.clear();
695
727
  this.invalidateRenderCache();
696
728
  yield this.refresh();
697
729
  }
698
730
  catch (err) {
699
- deleteBtn.disabled = false;
700
- deleteBtn.textContent = originalText || "Delete";
701
- removeClass(deleteBtn, "loading");
702
- window.alert(asWorkspaceBackendError(err).message);
731
+ this.setStatus(asWorkspaceBackendError(err).message);
703
732
  }
733
+ }), true));
734
+ }
735
+ if (!menu.childElementCount)
736
+ return;
737
+ this.rootEl.appendChild(menu);
738
+ this.queryContextMenuEl = menu;
739
+ const VIEWPORT_PADDING = 4;
740
+ menu.style.position = "fixed";
741
+ menu.style.zIndex = "10001";
742
+ menu.style.left = `${event.clientX}px`;
743
+ menu.style.top = `${event.clientY}px`;
744
+ requestAnimationFrame(() => {
745
+ const rect = menu.getBoundingClientRect();
746
+ if (rect.right > window.innerWidth - VIEWPORT_PADDING) {
747
+ menu.style.left = `${Math.max(VIEWPORT_PADDING, event.clientX - rect.width)}px`;
748
+ }
749
+ if (rect.bottom > window.innerHeight - VIEWPORT_PADDING) {
750
+ menu.style.top = `${Math.max(VIEWPORT_PADDING, event.clientY - rect.height)}px`;
751
+ }
752
+ });
753
+ const onOutsideClick = (e) => {
754
+ if (!this.queryContextMenuEl)
755
+ return;
756
+ if (!menu.contains(e.target))
757
+ this.closeQueryContextMenu();
758
+ };
759
+ const onEsc = (e) => {
760
+ if (e.key === "Escape") {
761
+ e.stopPropagation();
762
+ this.closeQueryContextMenu();
763
+ }
764
+ };
765
+ requestAnimationFrame(() => {
766
+ document.addEventListener("click", onOutsideClick);
767
+ document.addEventListener("keydown", onEsc);
768
+ });
769
+ this.queryContextMenuCleanup = () => {
770
+ document.removeEventListener("click", onOutsideClick);
771
+ document.removeEventListener("keydown", onEsc);
772
+ };
773
+ }
774
+ openFolderContextMenu(event, backend, entry, row) {
775
+ event.preventDefault();
776
+ event.stopPropagation();
777
+ this.closeQueryContextMenu();
778
+ const menu = document.createElement("ul");
779
+ addClass(menu, "yasgui-query-browser__context-menu");
780
+ const makeItem = (label, handler, isDanger = false) => {
781
+ const li = document.createElement("li");
782
+ addClass(li, "yasgui-query-browser__context-menu-item");
783
+ if (isDanger)
784
+ addClass(li, "yasgui-query-browser__context-menu-item--danger");
785
+ li.textContent = label;
786
+ li.addEventListener("click", (e) => __awaiter(this, void 0, void 0, function* () {
787
+ e.stopPropagation();
788
+ this.closeQueryContextMenu();
789
+ yield handler();
704
790
  }));
705
- actions.appendChild(deleteBtn);
791
+ return li;
792
+ };
793
+ if (backend.renameFolder) {
794
+ menu.appendChild(makeItem("Rename", () => __awaiter(this, void 0, void 0, function* () {
795
+ const next = yield this.startInlineRename(row, entry.label);
796
+ if (!next)
797
+ return;
798
+ const trimmed = next.trim();
799
+ if (!trimmed || trimmed === entry.label)
800
+ return;
801
+ try {
802
+ yield backend.renameFolder(entry.id, trimmed);
803
+ this.folderEntriesById.clear();
804
+ this.invalidateRenderCache();
805
+ yield this.refresh();
806
+ }
807
+ catch (err) {
808
+ this.setStatus(asWorkspaceBackendError(err).message);
809
+ }
810
+ })));
706
811
  }
707
- if (actions.childElementCount > 0) {
708
- row.appendChild(actions);
812
+ if (backend.deleteFolder) {
813
+ menu.appendChild(makeItem("Delete", () => __awaiter(this, void 0, void 0, function* () {
814
+ const ok = yield this.showInlineConfirm(row, `Delete folder '${entry.label}' and everything inside it?`);
815
+ if (!ok)
816
+ return;
817
+ try {
818
+ yield backend.deleteFolder(entry.id);
819
+ this.folderEntriesById.clear();
820
+ this.invalidateRenderCache();
821
+ yield this.refresh();
822
+ }
823
+ catch (err) {
824
+ this.setStatus(asWorkspaceBackendError(err).message);
825
+ }
826
+ }), true));
709
827
  }
828
+ if (!menu.childElementCount)
829
+ return;
830
+ this.rootEl.appendChild(menu);
831
+ this.queryContextMenuEl = menu;
832
+ const VIEWPORT_PADDING = 4;
833
+ menu.style.position = "fixed";
834
+ menu.style.zIndex = "10001";
835
+ menu.style.left = `${event.clientX}px`;
836
+ menu.style.top = `${event.clientY}px`;
837
+ requestAnimationFrame(() => {
838
+ const rect = menu.getBoundingClientRect();
839
+ if (rect.right > window.innerWidth - VIEWPORT_PADDING) {
840
+ menu.style.left = `${Math.max(VIEWPORT_PADDING, event.clientX - rect.width)}px`;
841
+ }
842
+ if (rect.bottom > window.innerHeight - VIEWPORT_PADDING) {
843
+ menu.style.top = `${Math.max(VIEWPORT_PADDING, event.clientY - rect.height)}px`;
844
+ }
845
+ });
846
+ const onOutsideClick = (e) => {
847
+ if (!this.queryContextMenuEl)
848
+ return;
849
+ if (!menu.contains(e.target))
850
+ this.closeQueryContextMenu();
851
+ };
852
+ const onEsc = (e) => {
853
+ if (e.key === "Escape") {
854
+ e.stopPropagation();
855
+ this.closeQueryContextMenu();
856
+ }
857
+ };
858
+ requestAnimationFrame(() => {
859
+ document.addEventListener("click", onOutsideClick);
860
+ document.addEventListener("keydown", onEsc);
861
+ });
862
+ this.queryContextMenuCleanup = () => {
863
+ document.removeEventListener("click", onOutsideClick);
864
+ document.removeEventListener("keydown", onEsc);
865
+ };
866
+ }
867
+ addQueryRowActions(row, backend, entry) {
868
+ if (entry.kind === "folder") {
869
+ row.addEventListener("contextmenu", (e) => this.openFolderContextMenu(e, backend, entry, row), {
870
+ passive: false,
871
+ });
872
+ return;
873
+ }
874
+ if (entry.kind !== "query")
875
+ return;
876
+ row.addEventListener("contextmenu", (e) => this.openQueryContextMenu(e, backend, entry, row), { passive: false });
710
877
  }
711
878
  renderFlatEntries(backend, entries) {
712
879
  this.clearList();