@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.
- package/build/ts/src/Tab.js +7 -1
- package/build/ts/src/Tab.js.map +1 -1
- package/build/ts/src/TabContextMenu.d.ts +1 -0
- package/build/ts/src/TabContextMenu.js +42 -0
- package/build/ts/src/TabContextMenu.js.map +1 -1
- package/build/ts/src/TabSettingsModal.d.ts +2 -1
- package/build/ts/src/TabSettingsModal.js +44 -25
- package/build/ts/src/TabSettingsModal.js.map +1 -1
- package/build/ts/src/index.d.ts +6 -0
- package/build/ts/src/index.js +42 -0
- package/build/ts/src/index.js.map +1 -1
- package/build/ts/src/prefixUtils.d.ts +1 -0
- package/build/ts/src/prefixUtils.js +23 -0
- package/build/ts/src/prefixUtils.js.map +1 -0
- package/build/ts/src/queryManagement/QueryBrowser.d.ts +8 -0
- package/build/ts/src/queryManagement/QueryBrowser.js +283 -116
- package/build/ts/src/queryManagement/QueryBrowser.js.map +1 -1
- package/build/ts/src/queryManagement/QueryHistoryModal.d.ts +35 -0
- package/build/ts/src/queryManagement/QueryHistoryModal.js +266 -0
- package/build/ts/src/queryManagement/QueryHistoryModal.js.map +1 -0
- package/build/ts/src/queryManagement/WorkspaceSettingsForm.js +8 -5
- package/build/ts/src/queryManagement/WorkspaceSettingsForm.js.map +1 -1
- package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.d.ts +1 -0
- package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.js +33 -0
- package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.js.map +1 -1
- package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.d.ts +1 -0
- package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.js +3 -0
- package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.js.map +1 -1
- package/build/ts/src/queryManagement/backends/WorkspaceBackend.d.ts +1 -0
- package/build/ts/src/queryManagement/countManagedQueries.d.ts +2 -0
- package/build/ts/src/queryManagement/countManagedQueries.js +35 -0
- package/build/ts/src/queryManagement/countManagedQueries.js.map +1 -0
- package/build/ts/src/tabNavigationHistory.d.ts +3 -0
- package/build/ts/src/tabNavigationHistory.js +13 -0
- package/build/ts/src/tabNavigationHistory.js.map +1 -0
- package/build/ts/src/version.d.ts +1 -1
- package/build/ts/src/version.js +1 -1
- package/build/yasgui.min.css +1 -1
- package/build/yasgui.min.css.map +3 -3
- package/build/yasgui.min.js +245 -245
- package/build/yasgui.min.js.map +4 -4
- package/package.json +1 -1
- package/src/Tab.ts +10 -0
- package/src/TabContextMenu.ts +42 -0
- package/src/TabSettingsModal.ts +48 -29
- package/src/index.ts +50 -0
- package/src/prefixUtils.ts +26 -0
- package/src/queryManagement/QueryBrowser.scss +85 -0
- package/src/queryManagement/QueryBrowser.ts +429 -213
- package/src/queryManagement/QueryHistoryModal.scss +239 -0
- package/src/queryManagement/QueryHistoryModal.ts +346 -0
- package/src/queryManagement/WorkspaceSettingsForm.ts +8 -5
- package/src/queryManagement/backends/GitWorkspaceBackend.ts +39 -0
- package/src/queryManagement/backends/SparqlWorkspaceBackend.ts +5 -0
- package/src/queryManagement/backends/WorkspaceBackend.ts +8 -0
- package/src/queryManagement/countManagedQueries.ts +28 -0
- package/src/tabNavigationHistory.ts +17 -0
- package/src/themes.scss +44 -0
- 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
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
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
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
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
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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
|
|
526
|
-
this.folderEntriesById.clear();
|
|
527
|
-
this.invalidateRenderCache();
|
|
528
|
-
yield this.refresh();
|
|
600
|
+
yield navigator.clipboard.writeText(uri);
|
|
529
601
|
}
|
|
530
|
-
catch (
|
|
531
|
-
window.
|
|
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
|
-
|
|
541
|
-
|
|
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
|
|
544
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
615
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
676
|
-
|
|
677
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
708
|
-
|
|
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();
|