From 2828b39f4872762c6d85115a43bd21534f9465bc Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 16 Mar 2025 00:45:46 +0200 Subject: [PATCH] chore(client/ts): port some more files --- src/public/app/components/entrypoints.ts | 2 +- src/public/app/services/branches.ts | 2 +- .../{search_result.js => search_result.ts} | 27 ++++++++------ .../{shared_info.js => shared_info.ts} | 16 ++++++--- .../{shared_switch.js => shared_switch.ts} | 19 +++++++--- .../widgets/{sql_result.js => sql_result.ts} | 7 +++- ..._table_schemas.js => sql_table_schemas.ts} | 18 ++++++++-- src/public/app/widgets/switch.ts | 2 +- ...le_bar_buttons.js => title_bar_buttons.ts} | 0 .../type_widgets/{empty.js => empty.ts} | 14 +++++--- .../type_widgets/{image.js => image.ts} | 20 +++++++---- .../type_widgets/{render.js => render.ts} | 12 +++++-- ...tatus.js => watched_file_update_status.ts} | 36 ++++++++++++++----- 13 files changed, 125 insertions(+), 50 deletions(-) rename src/public/app/widgets/{search_result.js => search_result.ts} (75%) rename src/public/app/widgets/{shared_info.js => shared_info.ts} (82%) rename src/public/app/widgets/{shared_switch.js => shared_switch.ts} (76%) rename src/public/app/widgets/{sql_result.js => sql_result.ts} (89%) rename src/public/app/widgets/{sql_table_schemas.js => sql_table_schemas.ts} (84%) rename src/public/app/widgets/{title_bar_buttons.js => title_bar_buttons.ts} (100%) rename src/public/app/widgets/type_widgets/{empty.js => empty.ts} (92%) rename src/public/app/widgets/type_widgets/{image.js => image.ts} (82%) rename src/public/app/widgets/type_widgets/{render.js => render.ts} (78%) rename src/public/app/widgets/{watched_file_update_status.js => watched_file_update_status.ts} (71%) diff --git a/src/public/app/components/entrypoints.ts b/src/public/app/components/entrypoints.ts index 69651de17..d4c8b600e 100644 --- a/src/public/app/components/entrypoints.ts +++ b/src/public/app/components/entrypoints.ts @@ -13,7 +13,7 @@ import { t } from "../services/i18n.js"; import type FNote from "../entities/fnote.js"; // TODO: Move somewhere else nicer. -export type SqlExecuteResults = unknown[]; +export type SqlExecuteResults = string[][][]; // TODO: Deduplicate with server. interface SqlExecuteResponse { diff --git a/src/public/app/services/branches.ts b/src/public/app/services/branches.ts index 18bae3529..b6f562f7c 100644 --- a/src/public/app/services/branches.ts +++ b/src/public/app/services/branches.ts @@ -252,7 +252,7 @@ async function cloneNoteToBranch(childNoteId: string, parentBranchId: string, pr } } -async function cloneNoteToParentNote(childNoteId: string, parentNoteId: string, prefix: string) { +async function cloneNoteToParentNote(childNoteId: string, parentNoteId: string, prefix?: string) { const resp = await server.put(`notes/${childNoteId}/clone-to-note/${parentNoteId}`, { prefix: prefix }); diff --git a/src/public/app/widgets/search_result.js b/src/public/app/widgets/search_result.ts similarity index 75% rename from src/public/app/widgets/search_result.js rename to src/public/app/widgets/search_result.ts index d18efff18..d1f72f08b 100644 --- a/src/public/app/widgets/search_result.js +++ b/src/public/app/widgets/search_result.ts @@ -1,6 +1,8 @@ import { t } from "../services/i18n.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js"; import NoteListRenderer from "../services/note_list_renderer.js"; +import type FNote from "../entities/fnote.js"; +import type { EventData } from "../components/app_context.js"; const TPL = `
@@ -11,32 +13,37 @@ const TPL = ` min-height: 0; overflow: auto; } - + .search-result-widget .note-list { padding: 10px; } - + .search-no-results, .search-not-executed-yet { margin: 20px; padding: 20px; } - +
${t("search_result.no_notes_found")}
- +
${t("search_result.search_not_executed")}
- +
`; export default class SearchResultWidget extends NoteContextAwareWidget { + + private $content!: JQuery; + private $noResults!: JQuery; + private $notExecutedYet!: JQuery; + isEnabled() { - return super.isEnabled() && this.note.type === "search"; + return super.isEnabled() && this.note?.type === "search"; } doRender() { @@ -47,7 +54,7 @@ export default class SearchResultWidget extends NoteContextAwareWidget { this.$notExecutedYet = this.$widget.find(".search-not-executed-yet"); } - async refreshWithNote(note) { + async refreshWithNote(note: FNote) { this.$content.empty(); this.$noResults.toggle(note.getChildNoteIds().length === 0 && !!note.searchResultsLoaded); this.$notExecutedYet.toggle(!note.searchResultsLoaded); @@ -56,7 +63,7 @@ export default class SearchResultWidget extends NoteContextAwareWidget { await noteListRenderer.renderList(); } - searchRefreshedEvent({ ntxId }) { + searchRefreshedEvent({ ntxId }: EventData<"searchRefreshed">) { if (!this.isNoteContext(ntxId)) { return; } @@ -64,8 +71,8 @@ export default class SearchResultWidget extends NoteContextAwareWidget { this.refresh(); } - notesReloadedEvent({ noteIds }) { - if (noteIds.includes(this.noteId)) { + notesReloadedEvent({ noteIds }: EventData<"notesReloaded">) { + if (this.noteId && noteIds.includes(this.noteId)) { this.refresh(); } } diff --git a/src/public/app/widgets/shared_info.js b/src/public/app/widgets/shared_info.ts similarity index 82% rename from src/public/app/widgets/shared_info.js rename to src/public/app/widgets/shared_info.ts index e80a5d760..64b5c568f 100644 --- a/src/public/app/widgets/shared_info.js +++ b/src/public/app/widgets/shared_info.ts @@ -2,6 +2,8 @@ import NoteContextAwareWidget from "./note_context_aware_widget.js"; import options from "../services/options.js"; import attributeService from "../services/attributes.js"; import { t } from "../services/i18n.js"; +import type FNote from "../entities/fnote.js"; +import type { EventData } from "../components/app_context.js"; const TPL = ` `; export default class SharedInfoWidget extends NoteContextAwareWidget { + + private $sharedLink!: JQuery; + private $sharedText!: JQuery; + isEnabled() { - return super.isEnabled() && this.noteId !== "_share" && this.note.hasAncestor("_share"); + return super.isEnabled() && this.noteId !== "_share" && this.note?.hasAncestor("_share"); } doRender() { @@ -29,7 +35,7 @@ export default class SharedInfoWidget extends NoteContextAwareWidget { this.contentSized(); } - async refreshWithNote(note) { + async refreshWithNote(note: FNote) { const syncServerHost = options.get("syncServerHost"); let link; @@ -53,7 +59,7 @@ export default class SharedInfoWidget extends NoteContextAwareWidget { this.$sharedLink.attr("href", link).text(link); } - getShareId(note) { + getShareId(note: FNote) { if (note.hasOwnedLabel("shareRoot")) { return ""; } @@ -61,8 +67,8 @@ export default class SharedInfoWidget extends NoteContextAwareWidget { return note.getOwnedLabelValue("shareAlias") || note.noteId; } - entitiesReloadedEvent({ loadResults }) { - if (loadResults.getAttributeRows().find((attr) => attr.name.startsWith("_share") && attributeService.isAffecting(attr, this.note))) { + entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { + if (loadResults.getAttributeRows().find((attr) => attr.name?.startsWith("_share") && attributeService.isAffecting(attr, this.note))) { this.refresh(); } else if (loadResults.getBranchRows().find((branch) => branch.noteId === this.noteId)) { this.refresh(); diff --git a/src/public/app/widgets/shared_switch.js b/src/public/app/widgets/shared_switch.ts similarity index 76% rename from src/public/app/widgets/shared_switch.js rename to src/public/app/widgets/shared_switch.ts index 90d2e7e9e..20e954efa 100644 --- a/src/public/app/widgets/shared_switch.js +++ b/src/public/app/widgets/shared_switch.ts @@ -5,10 +5,15 @@ import utils from "../services/utils.js"; import syncService from "../services/sync.js"; import dialogService from "../services/dialog.js"; import { t } from "../services/i18n.js"; +import type FNote from "../entities/fnote.js"; +import type { EventData } from "../components/app_context.js"; export default class SharedSwitchWidget extends SwitchWidget { + isEnabled() { - return super.isEnabled() && !["root", "_share", "_hidden"].includes(this.noteId) && !this.noteId.startsWith("_options"); + return super.isEnabled() + && !["root", "_share", "_hidden"].includes(this.noteId ?? "") + && !this.noteId?.startsWith("_options"); } doRender() { @@ -25,19 +30,23 @@ export default class SharedSwitchWidget extends SwitchWidget { } async switchOn() { + if (!this.noteId) { + return; + } + await branchService.cloneNoteToParentNote(this.noteId, "_share"); syncService.syncNow(true); } async switchOff() { - const shareBranch = this.note.getParentBranches().find((b) => b.parentNoteId === "_share"); + const shareBranch = this.note?.getParentBranches().find((b) => b.parentNoteId === "_share"); if (!shareBranch) { return; } - if (this.note.getParentBranches().length === 1) { + if (this.note?.getParentBranches().length === 1) { if (!(await dialogService.confirm(t("shared_switch.shared-branch")))) { return; } @@ -48,7 +57,7 @@ export default class SharedSwitchWidget extends SwitchWidget { syncService.syncNow(true); } - async refreshWithNote(note) { + async refreshWithNote(note: FNote) { const isShared = note.hasAncestor("_share"); const canBeUnshared = isShared && note.getParentBranches().find((b) => b.parentNoteId === "_share"); const switchDisabled = isShared && !canBeUnshared; @@ -64,7 +73,7 @@ export default class SharedSwitchWidget extends SwitchWidget { } } - entitiesReloadedEvent({ loadResults }) { + entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { if (loadResults.getBranchRows().find((b) => b.noteId === this.noteId)) { this.refresh(); } diff --git a/src/public/app/widgets/sql_result.js b/src/public/app/widgets/sql_result.ts similarity index 89% rename from src/public/app/widgets/sql_result.js rename to src/public/app/widgets/sql_result.ts index 7fcbff440..a75dcb9c4 100644 --- a/src/public/app/widgets/sql_result.js +++ b/src/public/app/widgets/sql_result.ts @@ -1,3 +1,4 @@ +import type { EventData } from "../components/app_context.js"; import { t } from "../services/i18n.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js"; @@ -21,6 +22,10 @@ const TPL = ` `; export default class SqlResultWidget extends NoteContextAwareWidget { + + private $resultContainer!: JQuery; + private $noRowsAlert!: JQuery; + isEnabled() { return this.note && this.note.mime === "text/x-sqlite;schema=trilium" && super.isEnabled(); } @@ -32,7 +37,7 @@ export default class SqlResultWidget extends NoteContextAwareWidget { this.$noRowsAlert = this.$widget.find(".sql-query-no-rows"); } - async sqlQueryResultsEvent({ ntxId, results }) { + async sqlQueryResultsEvent({ ntxId, results }: EventData<"sqlQueryResults">) { if (!this.isNoteContext(ntxId)) { return; } diff --git a/src/public/app/widgets/sql_table_schemas.js b/src/public/app/widgets/sql_table_schemas.ts similarity index 84% rename from src/public/app/widgets/sql_table_schemas.js rename to src/public/app/widgets/sql_table_schemas.ts index e5fafb01f..e21fc8abc 100644 --- a/src/public/app/widgets/sql_table_schemas.js +++ b/src/public/app/widgets/sql_table_schemas.ts @@ -1,6 +1,7 @@ import { t } from "../services/i18n.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js"; import server from "../services/server.js"; +import type FNote from "../entities/fnote.js"; const TPL = `
@@ -38,7 +39,19 @@ const TPL = `
`; +interface SchemaResponse { + name: string; + columns: { + name: string; + type: string; + }[]; +} + export default class SqlTableSchemasWidget extends NoteContextAwareWidget { + + private tableSchemasShown?: boolean; + private $sqlConsoleTableSchemas!: JQuery; + isEnabled() { return this.note && this.note.mime === "text/x-sqlite;schema=trilium" && super.isEnabled(); } @@ -50,14 +63,14 @@ export default class SqlTableSchemasWidget extends NoteContextAwareWidget { this.$sqlConsoleTableSchemas = this.$widget.find(".sql-table-schemas"); } - async refreshWithNote(note) { + async refreshWithNote(note: FNote) { if (this.tableSchemasShown) { return; } this.tableSchemasShown = true; - const tableSchema = await server.get("sql/schema"); + const tableSchema = await server.get("sql/schema"); for (const table of tableSchema) { const $tableLink = $(' - + `; export default class WatchedFileUpdateStatusWidget extends NoteContextAwareWidget { + + private $filePath!: JQuery; + private $fileLastModified!: JQuery; + private $fileUploadButton!: JQuery; + private $ignoreThisChangeButton!: JQuery; + isEnabled() { const { entityType, entityId } = this.getEntity(); - return super.isEnabled() && !!fileWatcher.getFileModificationStatus(entityType, entityId); + return super.isEnabled() + && !!entityType + && !!entityId + && !!fileWatcher.getFileModificationStatus(entityType, entityId); } doRender() { @@ -43,7 +54,9 @@ export default class WatchedFileUpdateStatusWidget extends NoteContextAwareWidge filePath: this.$filePath.text() }); - fileWatcher.fileModificationUploaded(entityType, entityId); + if (entityType && entityId) { + fileWatcher.fileModificationUploaded(entityType, entityId); + } this.refresh(); }); @@ -51,13 +64,18 @@ export default class WatchedFileUpdateStatusWidget extends NoteContextAwareWidge this.$ignoreThisChangeButton.on("click", () => { const { entityType, entityId } = this.getEntity(); - fileWatcher.ignoreModification(entityType, entityId); + if (entityType && entityId) { + fileWatcher.ignoreModification(entityType, entityId); + } this.refresh(); }); } - async refreshWithNote(note) { + async refreshWithNote(note: FNote) { const { entityType, entityId } = this.getEntity(); + if (!entityType || !entityId) { + return; + } const status = fileWatcher.getFileModificationStatus(entityType, entityId); this.$filePath.text(status.filePath); @@ -71,7 +89,7 @@ export default class WatchedFileUpdateStatusWidget extends NoteContextAwareWidge const { viewScope } = this.noteContext; - if (viewScope.viewMode === "attachments" && viewScope.attachmentId) { + if (viewScope?.viewMode === "attachments" && viewScope.attachmentId) { return { entityType: "attachments", entityId: viewScope.attachmentId @@ -84,7 +102,7 @@ export default class WatchedFileUpdateStatusWidget extends NoteContextAwareWidge } } - openedFileUpdatedEvent(data) { + openedFileUpdatedEvent(data: EventData<"openedFileUpdated">) { console.log(data); const { entityType, entityId } = this.getEntity();