diff --git a/apps/client/src/services/froca_updater.ts b/apps/client/src/services/froca_updater.ts index b528047ed..50826b5a5 100644 --- a/apps/client/src/services/froca_updater.ts +++ b/apps/client/src/services/froca_updater.ts @@ -35,8 +35,10 @@ async function processEntityChanges(entityChanges: EntityChange[]) { loadResults.addOption(attributeEntity.name); } else if (ec.entityName === "attachments") { processAttachment(loadResults, ec); - } else if (ec.entityName === "blobs" || ec.entityName === "etapi_tokens") { + } else if (ec.entityName === "blobs") { // NOOP - these entities are handled at the backend level and don't require frontend processing + } else if (ec.entityName === "etapi_tokens") { + loadResults.hasEtapiTokenChanges = true; } else { throw new Error(`Unknown entityName '${ec.entityName}'`); } @@ -77,9 +79,7 @@ async function processEntityChanges(entityChanges: EntityChange[]) { noteAttributeCache.invalidate(); } - // TODO: Remove after porting the file - // @ts-ignore - const appContext = (await import("../components/app_context.js")).default as any; + const appContext = (await import("../components/app_context.js")).default; await appContext.triggerEvent("entitiesReloaded", { loadResults }); } } diff --git a/apps/client/src/services/load_results.ts b/apps/client/src/services/load_results.ts index 5f9db2db7..ef70b76cd 100644 --- a/apps/client/src/services/load_results.ts +++ b/apps/client/src/services/load_results.ts @@ -1,4 +1,4 @@ -import type { AttachmentRow } from "@triliumnext/commons"; +import type { AttachmentRow, EtapiTokenRow } from "@triliumnext/commons"; import type { AttributeType } from "../entities/fattribute.js"; import type { EntityChange } from "../server_types.js"; @@ -53,6 +53,7 @@ type EntityRowMappings = { options: OptionRow; revisions: RevisionRow; note_reordering: NoteReorderingRow; + etapi_tokens: EtapiTokenRow; }; export type EntityRowNames = keyof EntityRowMappings; @@ -68,6 +69,7 @@ export default class LoadResults { private contentNoteIdToComponentId: ContentNoteIdToComponentIdRow[]; private optionNames: string[]; private attachmentRows: AttachmentRow[]; + public hasEtapiTokenChanges: boolean = false; constructor(entityChanges: EntityChange[]) { const entities: Record> = {}; @@ -215,7 +217,8 @@ export default class LoadResults { this.revisionRows.length === 0 && this.contentNoteIdToComponentId.length === 0 && this.optionNames.length === 0 && - this.attachmentRows.length === 0 + this.attachmentRows.length === 0 && + !this.hasEtapiTokenChanges ); } diff --git a/apps/client/src/widgets/type_widgets/options/etapi.tsx b/apps/client/src/widgets/type_widgets/options/etapi.tsx index ebd497ccc..2309c2c12 100644 --- a/apps/client/src/widgets/type_widgets/options/etapi.tsx +++ b/apps/client/src/widgets/type_widgets/options/etapi.tsx @@ -10,6 +10,7 @@ import toast from "../../../services/toast"; import dialog from "../../../services/dialog"; import { formatDateTime } from "../../../utils/formatters"; import ActionButton from "../../react/ActionButton"; +import useTriliumEvent from "../../react/hooks"; type RenameTokenCallback = (tokenId: string, oldName: string) => Promise; type DeleteTokenCallback = (tokenId: string, name: string ) => Promise; @@ -22,6 +23,11 @@ export default function EtapiSettings() { } useEffect(refreshTokens, []); + useTriliumEvent("entitiesReloaded", ({loadResults}) => { + if (loadResults.hasEtapiTokenChanges) { + refreshTokens(); + } + }); const createTokenCallback = useCallback(async () => { const tokenName = await dialog.prompt({ @@ -42,34 +48,7 @@ export default function EtapiSettings() { message: t("etapi.token_created_message"), defaultValue: authToken }); - - refreshTokens(); - }, []); - - const renameTokenCallback = useCallback(async (tokenId: string, oldName: string) => { - const tokenName = await dialog.prompt({ - title: t("etapi.rename_token_title"), - message: t("etapi.rename_token_message"), - defaultValue: oldName - }); - - if (!tokenName?.trim()) { - return; - } - - await server.patch(`etapi-tokens/${tokenId}`, { name: tokenName }); - - refreshTokens(); - }, []); - - const deleteTokenCallback = useCallback(async (tokenId: string, name: string) => { - if (!(await dialog.confirm(t("etapi.delete_token_confirmation", { name })))) { - return; - } - - await server.remove(`etapi-tokens/${tokenId}`); - refreshTokens(); - }, []); + }, []); return ( @@ -92,15 +71,37 @@ export default function EtapiSettings() {
{t("etapi.existing_tokens")}
- +
) } -function TokenList({ tokens, renameCallback, deleteCallback }: { tokens: EtapiToken[], renameCallback: RenameTokenCallback, deleteCallback: DeleteTokenCallback }) { +function TokenList({ tokens }: { tokens: EtapiToken[] }) { if (!tokens.length) { return
{t("etapi.no_tokens_yet")}
; } + + const renameCallback = useCallback(async (tokenId: string, oldName: string) => { + const tokenName = await dialog.prompt({ + title: t("etapi.rename_token_title"), + message: t("etapi.rename_token_message"), + defaultValue: oldName + }); + + if (!tokenName?.trim()) { + return; + } + + await server.patch(`etapi-tokens/${tokenId}`, { name: tokenName }); + }, []); + + const deleteCallback = useCallback(async (tokenId: string, name: string) => { + if (!(await dialog.confirm(t("etapi.delete_token_confirmation", { name })))) { + return; + } + + await server.remove(`etapi-tokens/${tokenId}`); + }, []); return (