mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-08-09 01:32:29 +08:00
Merge pull request #1462 from TriliumNext/port_dialogs
Port dialogs to ts
This commit is contained in:
commit
7f87318f8f
@ -364,6 +364,12 @@ type EventMappings = {
|
|||||||
textTypeWidget: EditableTextTypeWidget;
|
textTypeWidget: EditableTextTypeWidget;
|
||||||
text: string;
|
text: string;
|
||||||
};
|
};
|
||||||
|
openBulkActionsDialog: {
|
||||||
|
selectedOrActiveNoteIds: string[];
|
||||||
|
};
|
||||||
|
cloneNoteIdsTo: {
|
||||||
|
noteIds: string[];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type EventListener<T extends EventNames> = {
|
export type EventListener<T extends EventNames> = {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import appContext from "./app_context.js";
|
import appContext, { type EventData } from "./app_context.js";
|
||||||
import noteCreateService from "../services/note_create.js";
|
import noteCreateService from "../services/note_create.js";
|
||||||
import treeService from "../services/tree.js";
|
import treeService from "../services/tree.js";
|
||||||
import hoistedNoteService from "../services/hoisted_note.js";
|
import hoistedNoteService from "../services/hoisted_note.js";
|
||||||
@ -14,23 +14,19 @@ export default class MainTreeExecutors extends Component {
|
|||||||
return appContext.noteTreeWidget;
|
return appContext.noteTreeWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
async cloneNotesToCommand() {
|
async cloneNotesToCommand({ selectedOrActiveNoteIds }: EventData<"cloneNotesTo">) {
|
||||||
if (!this.tree) {
|
if (!this.tree) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedOrActiveNoteIds = this.tree.getSelectedOrActiveNodes().map((node) => node.data.noteId);
|
|
||||||
|
|
||||||
this.triggerCommand("cloneNoteIdsTo", { noteIds: selectedOrActiveNoteIds });
|
this.triggerCommand("cloneNoteIdsTo", { noteIds: selectedOrActiveNoteIds });
|
||||||
}
|
}
|
||||||
|
|
||||||
async moveNotesToCommand() {
|
async moveNotesToCommand({ selectedOrActiveBranchIds }: EventData<"moveNotesTo">) {
|
||||||
if (!this.tree) {
|
if (!this.tree) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedOrActiveBranchIds = this.tree.getSelectedOrActiveNodes().map((node) => node.data.branchId);
|
|
||||||
|
|
||||||
this.triggerCommand("moveBranchIdsTo", { branchIds: selectedOrActiveBranchIds });
|
this.triggerCommand("moveBranchIdsTo", { branchIds: selectedOrActiveBranchIds });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,6 @@ import appContext from "../../components/app_context.js";
|
|||||||
import { t } from "../../services/i18n.js";
|
import { t } from "../../services/i18n.js";
|
||||||
import { Modal } from "bootstrap";
|
import { Modal } from "bootstrap";
|
||||||
|
|
||||||
let branchId;
|
|
||||||
|
|
||||||
const TPL = `<div class="branch-prefix-dialog modal fade mx-auto" tabindex="-1" role="dialog">
|
const TPL = `<div class="branch-prefix-dialog modal fade mx-auto" tabindex="-1" role="dialog">
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
<form class="branch-prefix-form">
|
<form class="branch-prefix-form">
|
||||||
@ -38,61 +36,70 @@ const TPL = `<div class="branch-prefix-dialog modal fade mx-auto" tabindex="-1"
|
|||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
export default class BranchPrefixDialog extends BasicWidget {
|
export default class BranchPrefixDialog extends BasicWidget {
|
||||||
|
private modal!: Modal;
|
||||||
|
private $form!: JQuery<HTMLElement>;
|
||||||
|
private $treePrefixInput!: JQuery<HTMLElement>;
|
||||||
|
private $noteTitle!: JQuery<HTMLElement>;
|
||||||
|
private branchId: string | null = null;
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.modal = Modal.getOrCreateInstance(this.$widget);
|
this.modal = Modal.getOrCreateInstance(this.$widget[0]);
|
||||||
this.$form = this.$widget.find(".branch-prefix-form");
|
this.$form = this.$widget.find(".branch-prefix-form");
|
||||||
this.$treePrefixInput = this.$widget.find(".branch-prefix-input");
|
this.$treePrefixInput = this.$widget.find(".branch-prefix-input");
|
||||||
this.$noteTitle = this.$widget.find(".branch-prefix-note-title");
|
this.$noteTitle = this.$widget.find(".branch-prefix-note-title");
|
||||||
|
|
||||||
this.$form.on("submit", () => {
|
this.$form.on("submit", () => {
|
||||||
this.savePrefix();
|
this.savePrefix();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$widget.on("shown.bs.modal", () => this.$treePrefixInput.trigger("focus"));
|
this.$widget.on("shown.bs.modal", () => this.$treePrefixInput.trigger("focus"));
|
||||||
}
|
}
|
||||||
|
|
||||||
async refresh(notePath) {
|
async refresh(notePath: string) {
|
||||||
const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
|
const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
|
||||||
|
|
||||||
if (!noteId || !parentNoteId) {
|
if (!noteId || !parentNoteId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
branchId = await froca.getBranchId(parentNoteId, noteId);
|
const newBranchId = await froca.getBranchId(parentNoteId, noteId);
|
||||||
const branch = froca.getBranch(branchId);
|
if (!newBranchId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.branchId = newBranchId;
|
||||||
|
|
||||||
|
const branch = froca.getBranch(this.branchId);
|
||||||
if (!branch || branch.noteId === "root") {
|
if (!branch || branch.noteId === "root") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentNote = await froca.getNote(branch.parentNoteId);
|
const parentNote = await froca.getNote(branch.parentNoteId);
|
||||||
|
if (!parentNote || parentNote.type === "search") {
|
||||||
if (parentNote.type === "search") {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$treePrefixInput.val(branch.prefix);
|
this.$treePrefixInput.val(branch.prefix || "");
|
||||||
|
|
||||||
const noteTitle = await treeService.getNoteTitle(noteId);
|
const noteTitle = await treeService.getNoteTitle(noteId);
|
||||||
|
|
||||||
this.$noteTitle.text(` - ${noteTitle}`);
|
this.$noteTitle.text(` - ${noteTitle}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async editBranchPrefixEvent() {
|
async editBranchPrefixEvent() {
|
||||||
const notePath = appContext.tabManager.getActiveContextNotePath();
|
const notePath = appContext.tabManager.getActiveContextNotePath();
|
||||||
|
if (!notePath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await this.refresh(notePath);
|
await this.refresh(notePath);
|
||||||
|
|
||||||
utils.openDialog(this.$widget);
|
utils.openDialog(this.$widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
async savePrefix() {
|
async savePrefix() {
|
||||||
const prefix = this.$treePrefixInput.val();
|
const prefix = this.$treePrefixInput.val();
|
||||||
|
|
||||||
await server.put(`branches/${branchId}/set-prefix`, { prefix: prefix });
|
await server.put(`branches/${this.branchId}/set-prefix`, { prefix: prefix });
|
||||||
|
|
||||||
this.modal.hide();
|
this.modal.hide();
|
||||||
|
|
@ -5,6 +5,8 @@ import utils from "../../services/utils.js";
|
|||||||
import server from "../../services/server.js";
|
import server from "../../services/server.js";
|
||||||
import toastService from "../../services/toast.js";
|
import toastService from "../../services/toast.js";
|
||||||
import { t } from "../../services/i18n.js";
|
import { t } from "../../services/i18n.js";
|
||||||
|
import type { EventData } from "../../components/app_context.js";
|
||||||
|
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="bulk-actions-dialog modal mx-auto" tabindex="-1" role="dialog">
|
<div class="bulk-actions-dialog modal mx-auto" tabindex="-1" role="dialog">
|
||||||
@ -67,6 +69,13 @@ const TPL = `
|
|||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
export default class BulkActionsDialog extends BasicWidget {
|
export default class BulkActionsDialog extends BasicWidget {
|
||||||
|
private $includeDescendants!: JQuery<HTMLElement>;
|
||||||
|
private $affectedNoteCount!: JQuery<HTMLElement>;
|
||||||
|
private $availableActionList!: JQuery<HTMLElement>;
|
||||||
|
private $existingActionList!: JQuery<HTMLElement>;
|
||||||
|
private $executeButton!: JQuery<HTMLElement>;
|
||||||
|
private selectedOrActiveNoteIds: string[] | null = null;
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.$includeDescendants = this.$widget.find(".include-descendants");
|
this.$includeDescendants = this.$widget.find(".include-descendants");
|
||||||
@ -79,9 +88,11 @@ export default class BulkActionsDialog extends BasicWidget {
|
|||||||
|
|
||||||
this.$widget.on("click", "[data-action-add]", async (event) => {
|
this.$widget.on("click", "[data-action-add]", async (event) => {
|
||||||
const actionName = $(event.target).attr("data-action-add");
|
const actionName = $(event.target).attr("data-action-add");
|
||||||
|
if (!actionName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await bulkActionService.addAction("_bulkAction", actionName);
|
await bulkActionService.addAction("_bulkAction", actionName);
|
||||||
|
|
||||||
await this.refresh();
|
await this.refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -93,7 +104,6 @@ export default class BulkActionsDialog extends BasicWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
toastService.showMessage(t("bulk_actions.bulk_actions_executed"), 3000);
|
toastService.showMessage(t("bulk_actions.bulk_actions_executed"), 3000);
|
||||||
|
|
||||||
utils.closeActiveDialog();
|
utils.closeActiveDialog();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -101,21 +111,28 @@ export default class BulkActionsDialog extends BasicWidget {
|
|||||||
async refresh() {
|
async refresh() {
|
||||||
this.renderAvailableActions();
|
this.renderAvailableActions();
|
||||||
|
|
||||||
|
if (!this.selectedOrActiveNoteIds) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { affectedNoteCount } = await server.post("bulk-action/affected-notes", {
|
const { affectedNoteCount } = await server.post("bulk-action/affected-notes", {
|
||||||
noteIds: this.selectedOrActiveNoteIds,
|
noteIds: this.selectedOrActiveNoteIds,
|
||||||
includeDescendants: this.$includeDescendants.is(":checked")
|
includeDescendants: this.$includeDescendants.is(":checked")
|
||||||
});
|
}) as { affectedNoteCount: number };
|
||||||
|
|
||||||
this.$affectedNoteCount.text(affectedNoteCount);
|
this.$affectedNoteCount.text(affectedNoteCount);
|
||||||
|
|
||||||
const bulkActionNote = await froca.getNote("_bulkAction");
|
const bulkActionNote = await froca.getNote("_bulkAction");
|
||||||
|
if (!bulkActionNote) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const actions = bulkActionService.parseActions(bulkActionNote);
|
const actions = bulkActionService.parseActions(bulkActionNote);
|
||||||
|
|
||||||
this.$existingActionList.empty();
|
this.$existingActionList.empty();
|
||||||
|
|
||||||
if (actions.length > 0) {
|
if (actions.length > 0) {
|
||||||
this.$existingActionList.append(...actions.map((action) => action.render()));
|
this.$existingActionList.append(...actions.map((action) => action.render()).filter((action) => action !== null));
|
||||||
} else {
|
} else {
|
||||||
this.$existingActionList.append($("<p>").text(t("bulk_actions.none_yet")));
|
this.$existingActionList.append($("<p>").text(t("bulk_actions.none_yet")));
|
||||||
}
|
}
|
||||||
@ -138,7 +155,7 @@ export default class BulkActionsDialog extends BasicWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entitiesReloadedEvent({ loadResults }) {
|
entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
|
||||||
// only refreshing deleted attrs, otherwise components update themselves
|
// only refreshing deleted attrs, otherwise components update themselves
|
||||||
if (loadResults.getAttributeRows().find((row) => row.type === "label" && row.name === "action" && row.noteId === "_bulkAction" && row.isDeleted)) {
|
if (loadResults.getAttributeRows().find((row) => row.type === "label" && row.name === "action" && row.noteId === "_bulkAction" && row.isDeleted)) {
|
||||||
// this may be triggered from e.g., sync without open widget, then no need to refresh the widget
|
// this may be triggered from e.g., sync without open widget, then no need to refresh the widget
|
||||||
@ -148,12 +165,11 @@ export default class BulkActionsDialog extends BasicWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async openBulkActionsDialogEvent({ selectedOrActiveNoteIds }) {
|
async openBulkActionsDialogEvent({ selectedOrActiveNoteIds }: EventData<"openBulkActionsDialog">) {
|
||||||
this.selectedOrActiveNoteIds = selectedOrActiveNoteIds;
|
this.selectedOrActiveNoteIds = selectedOrActiveNoteIds;
|
||||||
this.$includeDescendants.prop("checked", false);
|
this.$includeDescendants.prop("checked", false);
|
||||||
|
|
||||||
await this.refresh();
|
await this.refresh();
|
||||||
|
|
||||||
utils.openDialog(this.$widget);
|
utils.openDialog(this.$widget);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,6 +7,8 @@ import branchService from "../../services/branches.js";
|
|||||||
import appContext from "../../components/app_context.js";
|
import appContext from "../../components/app_context.js";
|
||||||
import BasicWidget from "../basic_widget.js";
|
import BasicWidget from "../basic_widget.js";
|
||||||
import { t } from "../../services/i18n.js";
|
import { t } from "../../services/i18n.js";
|
||||||
|
import type { EventData } from "../../components/app_context.js";
|
||||||
|
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="clone-to-dialog modal mx-auto" tabindex="-1" role="dialog">
|
<div class="clone-to-dialog modal mx-auto" tabindex="-1" role="dialog">
|
||||||
@ -48,10 +50,14 @@ const TPL = `
|
|||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
export default class CloneToDialog extends BasicWidget {
|
export default class CloneToDialog extends BasicWidget {
|
||||||
|
private $form!: JQuery<HTMLElement>;
|
||||||
|
private $noteAutoComplete!: JQuery<HTMLElement>;
|
||||||
|
private $clonePrefix!: JQuery<HTMLElement>;
|
||||||
|
private $noteList!: JQuery<HTMLElement>;
|
||||||
|
private clonedNoteIds: string[] | null = null;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.clonedNoteIds = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
@ -66,7 +72,6 @@ export default class CloneToDialog extends BasicWidget {
|
|||||||
|
|
||||||
if (notePath) {
|
if (notePath) {
|
||||||
this.$widget.modal("hide");
|
this.$widget.modal("hide");
|
||||||
|
|
||||||
this.cloneNotesTo(notePath);
|
this.cloneNotesTo(notePath);
|
||||||
} else {
|
} else {
|
||||||
logError(t("clone_to.no_path_to_clone_to"));
|
logError(t("clone_to.no_path_to_clone_to"));
|
||||||
@ -76,9 +81,9 @@ export default class CloneToDialog extends BasicWidget {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async cloneNoteIdsToEvent({ noteIds }) {
|
async cloneNoteIdsToEvent({ noteIds }: EventData<"cloneNoteIdsTo">) {
|
||||||
if (!noteIds || noteIds.length === 0) {
|
if (!noteIds || noteIds.length === 0) {
|
||||||
noteIds = [appContext.tabManager.getActiveContextNoteId()];
|
noteIds = [appContext.tabManager.getActiveContextNoteId() ?? ""];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.clonedNoteIds = [];
|
this.clonedNoteIds = [];
|
||||||
@ -90,14 +95,14 @@ export default class CloneToDialog extends BasicWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
utils.openDialog(this.$widget);
|
utils.openDialog(this.$widget);
|
||||||
|
|
||||||
this.$noteAutoComplete.val("").trigger("focus");
|
this.$noteAutoComplete.val("").trigger("focus");
|
||||||
|
|
||||||
this.$noteList.empty();
|
this.$noteList.empty();
|
||||||
|
|
||||||
for (const noteId of this.clonedNoteIds) {
|
for (const noteId of this.clonedNoteIds) {
|
||||||
const note = await froca.getNote(noteId);
|
const note = await froca.getNote(noteId);
|
||||||
|
if (!note) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
this.$noteList.append($("<li>").text(note.title));
|
this.$noteList.append($("<li>").text(note.title));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,15 +110,29 @@ export default class CloneToDialog extends BasicWidget {
|
|||||||
noteAutocompleteService.showRecentNotes(this.$noteAutoComplete);
|
noteAutocompleteService.showRecentNotes(this.$noteAutoComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
async cloneNotesTo(notePath) {
|
async cloneNotesTo(notePath: string) {
|
||||||
const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
|
const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
|
||||||
|
if (!noteId || !parentNoteId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const targetBranchId = await froca.getBranchId(parentNoteId, noteId);
|
const targetBranchId = await froca.getBranchId(parentNoteId, noteId);
|
||||||
|
if (!targetBranchId || !this.clonedNoteIds) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (const cloneNoteId of this.clonedNoteIds) {
|
for (const cloneNoteId of this.clonedNoteIds) {
|
||||||
await branchService.cloneNoteToBranch(cloneNoteId, targetBranchId, this.$clonePrefix.val());
|
await branchService.cloneNoteToBranch(cloneNoteId, targetBranchId, this.$clonePrefix.val() as string);
|
||||||
|
|
||||||
const clonedNote = await froca.getNote(cloneNoteId);
|
const clonedNote = await froca.getNote(cloneNoteId);
|
||||||
const targetNote = await froca.getBranch(targetBranchId).getNote();
|
const targetBranch = froca.getBranch(targetBranchId);
|
||||||
|
if (!clonedNote || !targetBranch) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const targetNote = await targetBranch.getNote();
|
||||||
|
if (!targetNote) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
toastService.showMessage(t("clone_to.note_cloned", { clonedTitle: clonedNote.title, targetTitle: targetNote.title }));
|
toastService.showMessage(t("clone_to.note_cloned", { clonedTitle: clonedNote.title, targetTitle: targetNote.title }));
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user