diff --git a/apps/client/src/widgets/react/Column.tsx b/apps/client/src/widgets/react/Column.tsx
index 12b8ac9e5..8fd70bf38 100644
--- a/apps/client/src/widgets/react/Column.tsx
+++ b/apps/client/src/widgets/react/Column.tsx
@@ -1,14 +1,16 @@
import type { ComponentChildren } from "preact";
+import { CSSProperties } from "preact/compat";
interface ColumnProps {
md?: number;
children: ComponentChildren;
className?: string;
+ style?: CSSProperties;
}
-export default function Column({ md, children, className }: ColumnProps) {
+export default function Column({ md, children, className, style }: ColumnProps) {
return (
-
+
{children}
)
diff --git a/apps/client/src/widgets/type_widgets/content_widget.tsx b/apps/client/src/widgets/type_widgets/content_widget.tsx
index e3ff15330..d4f6978b9 100644
--- a/apps/client/src/widgets/type_widgets/content_widget.tsx
+++ b/apps/client/src/widgets/type_widgets/content_widget.tsx
@@ -21,8 +21,6 @@ import RevisionsSnapshotIntervalOptions from "./options/other/revisions_snapshot
import RevisionSnapshotsLimitOptions from "./options/other/revision_snapshots_limit.js";
import NetworkConnectionsOptions from "./options/other/network_connections.js";
import HtmlImportTagsOptions from "./options/other/html_import_tags.js";
-import VacuumDatabaseOptions from "./options/advanced/vacuum_database.js";
-import DatabaseAnonymizationOptions from "./options/advanced/database_anonymization.js";
import BackendLogWidget from "./content/backend_log.js";
import AttachmentErasureTimeoutOptions from "./options/other/attachment_erasure_timeout.js";
import RibbonOptions from "./options/appearance/ribbon.js";
diff --git a/apps/client/src/widgets/type_widgets/options/advanced.tsx b/apps/client/src/widgets/type_widgets/options/advanced.tsx
index 643ff7bb3..b16dca89d 100644
--- a/apps/client/src/widgets/type_widgets/options/advanced.tsx
+++ b/apps/client/src/widgets/type_widgets/options/advanced.tsx
@@ -1,15 +1,18 @@
-import { DatabaseCheckIntegrityResponse } from "@triliumnext/commons";
+import { AnonymizedDbResponse, DatabaseAnonymizeResponse, DatabaseCheckIntegrityResponse } from "@triliumnext/commons";
import { t } from "../../../services/i18n";
import server from "../../../services/server";
import toast from "../../../services/toast";
import Button from "../../react/Button";
import FormText from "../../react/FormText";
import OptionsSection from "./components/OptionsSection"
+import Column from "../../react/Column";
+import { useEffect, useState } from "preact/hooks";
export default function AdvancedSettings() {
return <>
+
>;
}
@@ -69,6 +72,91 @@ function DatabaseIntegrityOptions() {
)
}
+function DatabaseAnonymizationOptions() {
+ const [ existingAnonymizedDatabases, setExistingAnonymizedDatabases ] = useState
([]);
+
+ function refreshAnonymizedDatabase() {
+ server.get("database/anonymized-databases").then(setExistingAnonymizedDatabases);
+ }
+
+ useEffect(refreshAnonymizedDatabase, []);
+
+ return (
+
+ {t("database_anonymization.choose_anonymization")}
+
+
+ {
+ toast.showMessage(t("database_anonymization.creating_fully_anonymized_database"));
+ const resp = await server.post("database/anonymize/full");
+
+ if (!resp.success) {
+ toast.showError(t("database_anonymization.error_creating_anonymized_database"));
+ } else {
+ toast.showMessage(t("database_anonymization.successfully_created_fully_anonymized_database", { anonymizedFilePath: resp.anonymizedFilePath }), 10000);
+ refreshAnonymizedDatabase();
+ }
+ }}
+ />
+ {
+ toast.showMessage(t("database_anonymization.creating_lightly_anonymized_database"));
+ const resp = await server.post("database/anonymize/light");
+
+ if (!resp.success) {
+ toast.showError(t("database_anonymization.error_creating_anonymized_database"));
+ } else {
+ toast.showMessage(t("database_anonymization.successfully_created_lightly_anonymized_database", { anonymizedFilePath: resp.anonymizedFilePath }), 10000);
+ refreshAnonymizedDatabase();
+ }
+ }}
+ />
+
+
+
+
+
+ )
+}
+
+function DatabaseAnonymizationOption({ title, description, buttonText, buttonClick }: { title: string, description: string, buttonText: string, buttonClick: () => void }) {
+ return (
+
+ {title}
+ {description}
+
+
+ )
+}
+
+function ExistingAnonymizedDatabases({ databases }: { databases: AnonymizedDbResponse[] }) {
+ if (!databases.length) {
+ return {t("database_anonymization.no_anonymized_database_yet")}
+ }
+
+ return (
+
+
+ {t("database_anonymization.existing_anonymized_databases")} |
+
+
+ {databases.map(({ filePath }) => (
+
+ {filePath} |
+
+ ))}
+
+
+ )
+}
+
function VacuumDatabaseOptions() {
return (
diff --git a/apps/client/src/widgets/type_widgets/options/advanced/database_anonymization.ts b/apps/client/src/widgets/type_widgets/options/advanced/database_anonymization.ts
deleted file mode 100644
index edef0e4d4..000000000
--- a/apps/client/src/widgets/type_widgets/options/advanced/database_anonymization.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-import OptionsWidget from "../options_widget.js";
-import toastService from "../../../../services/toast.js";
-import server from "../../../../services/server.js";
-import { t } from "../../../../services/i18n.js";
-import type { OptionMap } from "@triliumnext/commons";
-
-const TPL = /*html*/`
-
-
-
-
${t("database_anonymization.title")}
-
-
-
${t("database_anonymization.choose_anonymization")}
-
-
-
${t("database_anonymization.full_anonymization")}
-
-
${t("database_anonymization.full_anonymization_description")}
-
-
-
-
-
${t("database_anonymization.light_anonymization")}
-
-
${t("database_anonymization.light_anonymization_description")}
-
-
-
-
-
-
-
-
-
- ${t("database_anonymization.existing_anonymized_databases")} |
-
-
-
-
-
`;
-
-// TODO: Deduplicate with server
-interface AnonymizeResponse {
- success: boolean;
- anonymizedFilePath: string;
-}
-
-interface AnonymizedDbResponse {
- filePath: string;
-}
-
-export default class DatabaseAnonymizationOptions extends OptionsWidget {
-
- private $anonymizeFullButton!: JQuery;
- private $anonymizeLightButton!: JQuery;
- private $existingAnonymizedDatabases!: JQuery;
-
- doRender() {
- this.$widget = $(TPL);
- this.$anonymizeFullButton = this.$widget.find(".anonymize-full-button");
- this.$anonymizeLightButton = this.$widget.find(".anonymize-light-button");
- this.$anonymizeFullButton.on("click", async () => {
- toastService.showMessage(t("database_anonymization.creating_fully_anonymized_database"));
-
- const resp = await server.post("database/anonymize/full");
-
- if (!resp.success) {
- toastService.showError(t("database_anonymization.error_creating_anonymized_database"));
- } else {
- toastService.showMessage(t("database_anonymization.successfully_created_fully_anonymized_database", { anonymizedFilePath: resp.anonymizedFilePath }), 10000);
- }
-
- this.refresh();
- });
-
- this.$anonymizeLightButton.on("click", async () => {
- toastService.showMessage(t("database_anonymization.creating_lightly_anonymized_database"));
-
- const resp = await server.post("database/anonymize/light");
-
- if (!resp.success) {
- toastService.showError(t("database_anonymization.error_creating_anonymized_database"));
- } else {
- toastService.showMessage(t("database_anonymization.successfully_created_lightly_anonymized_database", { anonymizedFilePath: resp.anonymizedFilePath }), 10000);
- }
-
- this.refresh();
- });
-
- this.$existingAnonymizedDatabases = this.$widget.find(".existing-anonymized-databases");
- }
-
- optionsLoaded(options: OptionMap) {
- server.get("database/anonymized-databases").then((anonymizedDatabases) => {
- this.$existingAnonymizedDatabases.empty();
-
- if (!anonymizedDatabases.length) {
- anonymizedDatabases = [{ filePath: t("database_anonymization.no_anonymized_database_yet") }];
- }
-
- for (const { filePath } of anonymizedDatabases) {
- this.$existingAnonymizedDatabases.append($("").append($("").text(filePath)));
- }
- });
- }
-}
diff --git a/apps/server/src/services/anonymization.ts b/apps/server/src/services/anonymization.ts
index bcc614c1f..6950be72d 100644
--- a/apps/server/src/services/anonymization.ts
+++ b/apps/server/src/services/anonymization.ts
@@ -5,6 +5,7 @@ import dateUtils from "./date_utils.js";
import Database from "better-sqlite3";
import sql from "./sql.js";
import path from "path";
+import { AnonymizedDbResponse, DatabaseAnonymizeResponse } from "@triliumnext/commons";
function getFullAnonymizationScript() {
// we want to delete all non-builtin attributes because they can contain sensitive names and values
@@ -73,7 +74,7 @@ async function createAnonymizedCopy(type: "full" | "light") {
return {
success: true,
anonymizedFilePath: anonymizedFile
- };
+ } satisfies DatabaseAnonymizeResponse;
}
function getExistingAnonymizedDatabases() {
@@ -87,7 +88,7 @@ function getExistingAnonymizedDatabases() {
.map((fileName) => ({
fileName: fileName,
filePath: path.resolve(dataDir.ANONYMIZED_DB_DIR, fileName)
- }));
+ })) satisfies AnonymizedDbResponse[];
}
export default {
diff --git a/packages/commons/src/lib/server_api.ts b/packages/commons/src/lib/server_api.ts
index ce520db83..543246f8f 100644
--- a/packages/commons/src/lib/server_api.ts
+++ b/packages/commons/src/lib/server_api.ts
@@ -67,3 +67,13 @@ export interface DatabaseCheckIntegrityResponse {
integrity_check: string;
}[];
}
+
+export interface DatabaseAnonymizeResponse {
+ success: boolean;
+ anonymizedFilePath: string;
+}
+
+export interface AnonymizedDbResponse {
+ filePath: string;
+ fileName: string;
+}
|