diff --git a/package-lock.json b/package-lock.json index fc4286d18..ea3fa65ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "trilium", - "version": "0.92.1-beta", + "version": "0.92.2-beta", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "trilium", - "version": "0.92.1-beta", + "version": "0.92.2-beta", "license": "AGPL-3.0-only", "dependencies": { "@braintree/sanitize-url": "7.1.1", @@ -20,10 +20,6 @@ "@mermaid-js/layout-elk": "0.1.7", "@mind-elixir/node-menu": "1.0.4", "@triliumnext/express-partial-content": "1.0.1", - "@types/js-yaml": "4.0.9", - "@types/leaflet": "1.9.16", - "@types/react-dom": "18.3.5", - "@types/swagger-ui-express": "4.1.8", "archiver": "7.0.1", "async-mutex": "0.5.0", "autocomplete.js": "0.38.1", @@ -141,12 +137,15 @@ "@types/html": "1.0.4", "@types/ini": "4.1.1", "@types/jquery": "3.5.32", + "@types/js-yaml": "4.0.9", "@types/jsdom": "21.1.7", + "@types/leaflet": "1.9.16", "@types/leaflet-gpx": "1.3.7", "@types/mime-types": "2.1.4", "@types/multer": "1.4.12", "@types/node": "22.13.5", "@types/react": "18.3.18", + "@types/react-dom": "18.3.5", "@types/safe-compare": "1.1.2", "@types/sanitize-html": "2.13.0", "@types/sax": "1.2.7", @@ -154,6 +153,7 @@ "@types/session-file-store": "1.2.5", "@types/source-map-support": "0.5.10", "@types/stream-throttle": "0.1.4", + "@types/swagger-ui-express": "4.1.8", "@types/tmp": "0.2.6", "@types/turndown": "5.0.5", "@types/ws": "8.5.14", @@ -171,7 +171,7 @@ "mini-css-extract-plugin": "2.9.2", "nodemon": "3.1.9", "postcss-loader": "8.1.1", - "prettier": "3.5.1", + "prettier": "3.5.2", "rcedit": "4.0.1", "rimraf": "6.0.1", "sass": "1.85.0", @@ -4009,6 +4009,7 @@ "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, "license": "MIT", "dependencies": { "@types/connect": "*", @@ -4071,6 +4072,7 @@ "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -4397,6 +4399,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "dev": true, "license": "MIT", "dependencies": { "@types/body-parser": "*", @@ -4409,6 +4412,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz", "integrity": "sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", @@ -4483,6 +4487,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true, "license": "MIT" }, "node_modules/@types/ini": { @@ -4505,7 +4510,9 @@ "node_modules/@types/js-yaml": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==" + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true, + "license": "MIT" }, "node_modules/@types/jsdom": { "version": "21.1.7", @@ -4548,6 +4555,7 @@ "version": "1.9.16", "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.16.tgz", "integrity": "sha512-wzZoyySUxkgMZ0ihJ7IaUIblG8Rdc8AbbZKLneyn+QjYsj5q1QU7TEKYqwTr10BGSzY5LI7tJk9Ifo+mEjdFRw==", + "dev": true, "license": "MIT", "dependencies": { "@types/geojson": "*" @@ -4592,6 +4600,7 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, "license": "MIT" }, "node_modules/@types/mime-types": { @@ -4632,24 +4641,28 @@ "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "dev": true, "license": "MIT" }, "node_modules/@types/qs": { "version": "6.9.17", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", + "dev": true, "license": "MIT" }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, "license": "MIT" }, "node_modules/@types/react": { "version": "18.3.18", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", + "dev": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -4660,6 +4673,7 @@ "version": "18.3.5", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", + "dev": true, "license": "MIT", "peerDependencies": { "@types/react": "^18.0.0" @@ -4715,6 +4729,7 @@ "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, "license": "MIT", "dependencies": { "@types/mime": "^1", @@ -4735,6 +4750,7 @@ "version": "1.15.7", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, "license": "MIT", "dependencies": { "@types/http-errors": "*", @@ -4784,6 +4800,7 @@ "version": "4.1.8", "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.8.tgz", "integrity": "sha512-AhZV8/EIreHFmBV5wAs0gzJUNq9JbbSXgJLQubCC0jtIo6prnI9MIRRxnU4MZX9RB9yXxF1V4R7jtLl/Wcj31g==", + "dev": true, "license": "MIT", "dependencies": { "@types/express": "*", @@ -7501,6 +7518,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, "license": "MIT" }, "node_modules/cytoscape": { @@ -8367,9 +8385,9 @@ } }, "node_modules/dompurify": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.3.tgz", - "integrity": "sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz", + "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -14432,9 +14450,9 @@ } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -14451,7 +14469,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -14638,9 +14656,9 @@ } }, "node_modules/prettier": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.1.tgz", - "integrity": "sha512-hPpFQvHwL3Qv5AdRvBFMhnKo4tYxp0ReXiPn2bxkiohEX6mBeBwEpBSQTkD458RaaDKQMYSp4hX4UtfUTA5wDw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz", + "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==", "dev": true, "license": "MIT", "bin": { @@ -18017,15 +18035,15 @@ } }, "node_modules/vite": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", - "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.1.tgz", + "integrity": "sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" + "postcss": "^8.5.2", + "rollup": "^4.30.1" }, "bin": { "vite": "bin/vite.js" diff --git a/package.json b/package.json index e6c9974d1..cf4adaf71 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "server:switch": "rimraf ./node_modules/better-sqlite3 && npm install", "electron:start": "cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron ./electron-main.ts --inspect=5858 .", "electron:start-no-dir": "cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_ENV=dev electron --inspect=5858 .", - "electron:start-nix": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./electron-main.ts --inspect=5858 .\"", + "electron:start-nix": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev nix-shell -p electron_34 --run \"electron ./electron-main.ts --inspect=5858 .\"", "electron:start-nix-no-dir": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./electron-main.ts --inspect=5858 .\"", "electron:start-prod": "npm run build:prepare-dist && cross-env TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron ./dist/electron-main.js --inspect=5858 .", "electron:start-prod-no-dir": "npm run build:prepare-dist && cross-env TRILIUM_ENV=dev electron --inspect=5858 .", @@ -70,10 +70,6 @@ "@mermaid-js/layout-elk": "0.1.7", "@mind-elixir/node-menu": "1.0.4", "@triliumnext/express-partial-content": "1.0.1", - "@types/js-yaml": "4.0.9", - "@types/leaflet": "1.9.16", - "@types/react-dom": "18.3.5", - "@types/swagger-ui-express": "4.1.8", "archiver": "7.0.1", "async-mutex": "0.5.0", "autocomplete.js": "0.38.1", @@ -188,12 +184,15 @@ "@types/html": "1.0.4", "@types/ini": "4.1.1", "@types/jquery": "3.5.32", + "@types/js-yaml": "4.0.9", "@types/jsdom": "21.1.7", + "@types/leaflet": "1.9.16", "@types/leaflet-gpx": "1.3.7", "@types/mime-types": "2.1.4", "@types/multer": "1.4.12", "@types/node": "22.13.5", "@types/react": "18.3.18", + "@types/react-dom": "18.3.5", "@types/safe-compare": "1.1.2", "@types/sanitize-html": "2.13.0", "@types/sax": "1.2.7", @@ -201,6 +200,7 @@ "@types/session-file-store": "1.2.5", "@types/source-map-support": "0.5.10", "@types/stream-throttle": "0.1.4", + "@types/swagger-ui-express": "4.1.8", "@types/tmp": "0.2.6", "@types/turndown": "5.0.5", "@types/ws": "8.5.14", @@ -218,7 +218,7 @@ "mini-css-extract-plugin": "2.9.2", "nodemon": "3.1.9", "postcss-loader": "8.1.1", - "prettier": "3.5.1", + "prettier": "3.5.2", "rcedit": "4.0.1", "rimraf": "6.0.1", "sass": "1.85.0", diff --git a/src/becca/entities/rows.ts b/src/becca/entities/rows.ts index ba9189190..b57801e1e 100644 --- a/src/becca/entities/rows.ts +++ b/src/becca/entities/rows.ts @@ -1,4 +1,5 @@ // TODO: Booleans should probably be numbers instead (as SQLite does not have booleans.); +// TODO: check against schema.sql which properties really are "optional" export interface AttachmentRow { attachmentId?: string; @@ -12,6 +13,8 @@ export interface AttachmentRow { dateModified?: string; utcDateModified?: string; utcDateScheduledForErasureSince?: string; + isDeleted?: boolean; + deleteId?: string; contentLength?: number; content?: Buffer | string; } diff --git a/src/public/app/components/app_context.ts b/src/public/app/components/app_context.ts index f54fd88fa..a6f69af64 100644 --- a/src/public/app/components/app_context.ts +++ b/src/public/app/components/app_context.ts @@ -288,6 +288,10 @@ type EventMappings = { showHighlightsListWidget: { noteId: string; }; + showSearchError: { + error: string; + }; + searchRefreshed: { ntxId?: string | null }; hoistedNoteChanged: { noteId: string; ntxId: string | null; @@ -365,6 +369,8 @@ class AppContext extends Component { layout?: Layout; noteTreeWidget?: NoteTreeWidget; + lastSearchString?: string; + constructor(isMainWindow: boolean) { super(); diff --git a/src/public/app/entities/fattachment.ts b/src/public/app/entities/fattachment.ts index 274c1bbdb..4774f87bd 100644 --- a/src/public/app/entities/fattachment.ts +++ b/src/public/app/entities/fattachment.ts @@ -19,18 +19,18 @@ export interface FAttachmentRow { class FAttachment { private froca: Froca; attachmentId!: string; - private ownerId!: string; + ownerId!: string; role!: string; mime!: string; title!: string; isProtected!: boolean; // TODO: Is this used? private dateModified!: string; utcDateModified!: string; - private utcDateScheduledForErasureSince!: string; + utcDateScheduledForErasureSince!: string; /** * optionally added to the entity */ - private contentLength!: number; + contentLength!: number; constructor(froca: Froca, row: FAttachmentRow) { /** @type {Froca} */ diff --git a/src/public/app/services/content_renderer.ts b/src/public/app/services/content_renderer.ts index 18aafdb4f..7064829fc 100644 --- a/src/public/app/services/content_renderer.ts +++ b/src/public/app/services/content_renderer.ts @@ -24,7 +24,8 @@ interface Options { const CODE_MIME_TYPES = new Set(["application/json"]); -async function getRenderedContent(this: {} | { ctx: string }, entity: FNote, options: Options = {}) { +async function getRenderedContent(this: {} | { ctx: string }, entity: FNote | FAttachment, options: Options = {}) { + options = Object.assign( { tooltip: false @@ -47,7 +48,7 @@ async function getRenderedContent(this: {} | { ctx: string }, entity: FNote, opt renderFile(entity, type, $renderedContent); } else if (type === "mermaid") { await renderMermaid(entity, $renderedContent); - } else if (type === "render") { + } else if (type === "render" && entity instanceof FNote) { const $content = $("
");
@@ -208,7 +209,7 @@ function renderFile(entity: FNote | FAttachment, type: string, $renderedContent:
$renderedContent.append($content);
}
-async function renderMermaid(note: FNote, $renderedContent: JQuery) {
+async function renderMermaid(note: FNote | FAttachment, $renderedContent: JQuery) {
await libraryLoader.requireLibrary(libraryLoader.MERMAID);
const blob = await note.getBlob();
diff --git a/src/public/app/services/link.ts b/src/public/app/services/link.ts
index 472f7d37a..9b3c779bb 100644
--- a/src/public/app/services/link.ts
+++ b/src/public/app/services/link.ts
@@ -70,7 +70,7 @@ interface CreateLinkOptions {
viewScope?: ViewScope;
}
-async function createLink(notePath: string, options: CreateLinkOptions = {}) {
+async function createLink(notePath: string | undefined, options: CreateLinkOptions = {}) {
if (!notePath || !notePath.trim()) {
logError("Missing note path");
diff --git a/src/public/app/services/load_results.ts b/src/public/app/services/load_results.ts
index 25f3b30ec..eabbcfc74 100644
--- a/src/public/app/services/load_results.ts
+++ b/src/public/app/services/load_results.ts
@@ -1,4 +1,4 @@
-import type { TaskRow } from "../../../becca/entities/rows.js";
+import type { TaskRow, AttachmentRow } from "../../../becca/entities/rows.js";
import type { AttributeType } from "../entities/fattribute.js";
import type { EntityChange } from "../server_types.js";
@@ -37,8 +37,6 @@ interface ContentNoteIdToComponentIdRow {
componentId: string;
}
-interface AttachmentRow {}
-
interface OptionRow {}
interface NoteReorderingRow {}
diff --git a/src/public/app/widgets/attachment_detail.js b/src/public/app/widgets/attachment_detail.ts
similarity index 92%
rename from src/public/app/widgets/attachment_detail.js
rename to src/public/app/widgets/attachment_detail.ts
index 8aa6b5824..a66ae95a1 100644
--- a/src/public/app/widgets/attachment_detail.js
+++ b/src/public/app/widgets/attachment_detail.ts
@@ -7,6 +7,8 @@ import imageService from "../services/image.js";
import linkService from "../services/link.js";
import contentRenderer from "../services/content_renderer.js";
import toastService from "../services/toast.js";
+import type FAttachment from "../entities/fattachment.js";
+import type { EventData } from "../components/app_context.js";
const TPL = `
;
+
+ constructor(attachment: FAttachment, isFullDetail: boolean) {
super();
this.contentSized();
@@ -140,7 +147,8 @@ export default class AttachmentDetailWidget extends BasicWidget {
this.$wrapper.addClass("scheduled-for-deletion");
const scheduledSinceTimestamp = utils.parseDate(utcDateScheduledForErasureSince)?.getTime();
- const intervalMs = options.getInt("eraseUnusedAttachmentsAfterSeconds") * 1000;
+ // use default value (30 days in seconds) from options_init as fallback, in case getInt returns null
+ const intervalMs = options.getInt("eraseUnusedAttachmentsAfterSeconds") || 2592000 * 1000;
const deletionTimestamp = scheduledSinceTimestamp + intervalMs;
const willBeDeletedInMs = deletionTimestamp - Date.now();
@@ -185,7 +193,7 @@ export default class AttachmentDetailWidget extends BasicWidget {
}
}
- async entitiesReloadedEvent({ loadResults }) {
+ async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
const attachmentRow = loadResults.getAttachmentRows().find((att) => att.attachmentId === this.attachment.attachmentId);
if (attachmentRow) {
diff --git a/src/public/app/widgets/buttons/attachments_actions.js b/src/public/app/widgets/buttons/attachments_actions.ts
similarity index 85%
rename from src/public/app/widgets/buttons/attachments_actions.js
rename to src/public/app/widgets/buttons/attachments_actions.ts
index 5ee51b9d9..efacf48fe 100644
--- a/src/public/app/widgets/buttons/attachments_actions.js
+++ b/src/public/app/widgets/buttons/attachments_actions.ts
@@ -8,6 +8,9 @@ import appContext from "../../components/app_context.js";
import openService from "../../services/open.js";
import utils from "../../services/utils.js";
import { Dropdown } from "bootstrap";
+import type attachmentsApiRoute from "../../../../routes/api/attachments.js"
+import type FAttachment from "../../entities/fattachment.js";
+import type AttachmentDetailWidget from "../attachment_detail.js";
const TPL = `
-
+
`;
export default class AttachmentDetailWidget extends BasicWidget {
- constructor(attachment, isFullDetail) {
+ attachment: FAttachment;
+ attachmentActionsWidget: AttachmentActionsWidget;
+ isFullDetail: boolean;
+ $wrapper!: JQuery