mirror of
https://github.com/zadam/trilium.git
synced 2025-10-27 16:26:31 +01:00
127 lines
4.8 KiB
TypeScript
127 lines
4.8 KiB
TypeScript
import { useEffect, useState, useCallback } from "preact/hooks";
|
|
import { t } from "../../services/i18n";
|
|
import Modal from "../react/Modal";
|
|
import ReactBasicWidget from "../react/ReactBasicWidget";
|
|
import "./bulk_actions.css";
|
|
import { BulkActionAffectedNotes } from "@triliumnext/commons";
|
|
import server from "../../services/server";
|
|
import FormCheckbox from "../react/FormCheckbox";
|
|
import Button from "../react/Button";
|
|
import bulk_action from "../../services/bulk_action";
|
|
import toast from "../../services/toast";
|
|
import RenameNoteBulkAction from "../bulk_actions/note/rename_note";
|
|
import FNote from "../../entities/fnote";
|
|
import froca from "../../services/froca";
|
|
import useTriliumEvent from "../react/hooks";
|
|
|
|
function BulkActionComponent() {
|
|
const [ selectedOrActiveNoteIds, setSelectedOrActiveNoteIds ] = useState<string[]>();
|
|
const [ bulkActionNote, setBulkActionNote ] = useState<FNote | null>();
|
|
const [ includeDescendants, setIncludeDescendants ] = useState(false);
|
|
const [ affectedNoteCount, setAffectedNoteCount ] = useState(0);
|
|
const [ existingActions, setExistingActions ] = useState<RenameNoteBulkAction[]>([]);
|
|
const [ shown, setShown ] = useState(false);
|
|
|
|
useTriliumEvent("openBulkActionsDialog", async ({ selectedOrActiveNoteIds }) => {
|
|
setSelectedOrActiveNoteIds(selectedOrActiveNoteIds);
|
|
setBulkActionNote(await froca.getNote("_bulkAction"));
|
|
setShown(true);
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (!selectedOrActiveNoteIds || !bulkActionNote) return;
|
|
|
|
server.post<BulkActionAffectedNotes>("bulk-action/affected-notes", {
|
|
noteIds: selectedOrActiveNoteIds,
|
|
includeDescendants
|
|
}).then(({ affectedNoteCount }) => setAffectedNoteCount(affectedNoteCount));
|
|
}, [ selectedOrActiveNoteIds, includeDescendants, bulkActionNote ]);
|
|
|
|
const refreshExistingActions = useCallback(() => {
|
|
if (!bulkActionNote) return;
|
|
setExistingActions(bulk_action.parseActions(bulkActionNote));
|
|
}, [bulkActionNote]);
|
|
|
|
useEffect(() => {
|
|
refreshExistingActions();
|
|
}, [refreshExistingActions]);
|
|
|
|
useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
|
|
if (loadResults.getAttributeRows().find((row) =>
|
|
row.type === "label" && row.name === "action" && row.noteId === "_bulkAction")) {
|
|
refreshExistingActions();
|
|
}
|
|
}, shown);
|
|
|
|
return (
|
|
<Modal
|
|
className="bulk-actions-dialog"
|
|
size="xl"
|
|
title={t("bulk_actions.bulk_actions")}
|
|
footer={<Button text={t("bulk_actions.execute_bulk_actions")} primary />}
|
|
show={shown}
|
|
onSubmit={async () => {
|
|
await server.post("bulk-action/execute", {
|
|
noteIds: selectedOrActiveNoteIds,
|
|
includeDescendants
|
|
});
|
|
|
|
toast.showMessage(t("bulk_actions.bulk_actions_executed"), 3000);
|
|
setShown(false);
|
|
}}
|
|
onHidden={() => setShown(false)}
|
|
>
|
|
<h4>{t("bulk_actions.affected_notes")}: <span>{affectedNoteCount}</span></h4>
|
|
<FormCheckbox
|
|
name="include-descendants" label={t("bulk_actions.include_descendants")}
|
|
currentValue={includeDescendants} onChange={setIncludeDescendants}
|
|
/>
|
|
|
|
<h4>{t("bulk_actions.available_actions")}</h4>
|
|
<AvailableActionsList />
|
|
|
|
<h4>{t("bulk_actions.chosen_actions")}</h4>
|
|
<ExistingActionsList existingActions={existingActions} />
|
|
</Modal>
|
|
)
|
|
}
|
|
|
|
function AvailableActionsList() {
|
|
return <table class="bulk-available-action-list">
|
|
{bulk_action.ACTION_GROUPS.map((actionGroup) => {
|
|
return (
|
|
<tr>
|
|
<td>{ actionGroup.title }:</td>
|
|
{actionGroup.actions.map(({ actionName, actionTitle }) =>
|
|
<Button
|
|
size="small"
|
|
text={actionTitle}
|
|
onClick={() => bulk_action.addAction("_bulkAction", actionName)}
|
|
/>
|
|
)}
|
|
</tr>
|
|
);
|
|
})}
|
|
</table>;
|
|
}
|
|
|
|
function ExistingActionsList({ existingActions }: { existingActions?: RenameNoteBulkAction[] }) {
|
|
return (
|
|
<table class="bulk-existing-action-list">
|
|
{ existingActions
|
|
? existingActions
|
|
.map(action => action.doRender())
|
|
.filter(renderedAction => renderedAction !== null)
|
|
: <p>{t("bulk_actions.none_yet")}</p>
|
|
}
|
|
</table>
|
|
);
|
|
}
|
|
|
|
export default class BulkActionsDialog extends ReactBasicWidget {
|
|
|
|
get component() {
|
|
return <BulkActionComponent />
|
|
}
|
|
|
|
} |