diff --git a/package-lock.json b/package-lock.json index b46584fcb..04d2b4082 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,6 +91,7 @@ "vue": "3.5.13", "vue-axios": "^3.5.2", "vue-facing-decorator": "3.0.4", + "vue-markdown-render": "^2.2.1", "vue-picture-cropper": "^0.7.0", "vue-qrcode-reader": "^5.5.3", "vue-router": "^4.5.0", @@ -107,6 +108,7 @@ "@types/js-yaml": "^4.0.9", "@types/leaflet": "^1.9.8", "@types/luxon": "^3.4.2", + "@types/markdown-it": "^14.1.2", "@types/node": "^20.14.11", "@types/node-fetch": "^2.6.12", "@types/ramda": "^0.29.11", @@ -10159,6 +10161,12 @@ "@types/geojson": "*" } }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true + }, "node_modules/@types/luxon": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.7.1.tgz", @@ -10166,6 +10174,22 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true + }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", @@ -32895,6 +32919,61 @@ "vue": "^3.0.0" } }, + "node_modules/vue-markdown-render": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vue-markdown-render/-/vue-markdown-render-2.2.1.tgz", + "integrity": "sha512-XkYnC0PMdbs6Vy6j/gZXSvCuOS0787Se5COwXlepRqiqPiunyCIeTPQAO2XnB4Yl04EOHXwLx5y6IuszMWSgyQ==", + "dependencies": { + "markdown-it": "^13.0.2" + }, + "peerDependencies": { + "vue": "^3.3.4" + } + }, + "node_modules/vue-markdown-render/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/vue-markdown-render/node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/vue-markdown-render/node_modules/markdown-it": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.2.tgz", + "integrity": "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/vue-markdown-render/node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, + "node_modules/vue-markdown-render/node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, "node_modules/vue-picture-cropper": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/vue-picture-cropper/-/vue-picture-cropper-0.7.0.tgz", diff --git a/package.json b/package.json index 03290fe0e..5ed49dbef 100644 --- a/package.json +++ b/package.json @@ -136,7 +136,6 @@ "*.{js,ts,vue,css,json,yml,yaml}": "eslint --fix || true", "*.{md,markdown,mdc}": "markdownlint-cli2 --fix" }, - "dependencies": { "@capacitor-community/electron": "^5.0.1", "@capacitor-community/sqlite": "6.0.2", @@ -221,6 +220,7 @@ "vue": "3.5.13", "vue-axios": "^3.5.2", "vue-facing-decorator": "3.0.4", + "vue-markdown-render": "^2.2.1", "vue-picture-cropper": "^0.7.0", "vue-qrcode-reader": "^5.5.3", "vue-router": "^4.5.0", @@ -237,6 +237,7 @@ "@types/js-yaml": "^4.0.9", "@types/leaflet": "^1.9.8", "@types/luxon": "^3.4.2", + "@types/markdown-it": "^14.1.2", "@types/node": "^20.14.11", "@types/node-fetch": "^2.6.12", "@types/ramda": "^0.29.11", diff --git a/src/assets/styles/tailwind.css b/src/assets/styles/tailwind.css index f6457ff3a..7785f0958 100644 --- a/src/assets/styles/tailwind.css +++ b/src/assets/styles/tailwind.css @@ -22,4 +22,24 @@ .dialog { @apply bg-white p-4 rounded-lg w-full max-w-lg; } + + /* Markdown content styling to restore list elements */ + .markdown-content ul { + @apply list-disc list-inside ml-4; + } + + .markdown-content ol { + @apply list-decimal list-inside ml-4; + } + + .markdown-content li { + @apply mb-1; + } + + .markdown-content ul ul, + .markdown-content ol ol, + .markdown-content ul ol, + .markdown-content ol ul { + @apply ml-4 mt-1; + } } \ No newline at end of file diff --git a/src/components/ActivityListItem.vue b/src/components/ActivityListItem.vue index 39dfcffaa..33b50d024 100644 --- a/src/components/ActivityListItem.vue +++ b/src/components/ActivityListItem.vue @@ -80,7 +80,10 @@
@@ -258,11 +261,13 @@ import { NOTIFY_UNKNOWN_PERSON, } from "@/constants/notifications"; import { TIMEOUTS } from "@/utils/notify"; +import VueMarkdown from "vue-markdown-render"; @Component({ components: { EntityIcon, ProjectIcon, + VueMarkdown, }, }) export default class ActivityListItem extends Vue { @@ -303,6 +308,14 @@ export default class ActivityListItem extends Vue { return `${claim?.description || ""}`; } + get truncatedDescription(): string { + const desc = this.description; + if (desc.length <= 300) { + return desc; + } + return desc.substring(0, 300) + "..."; + } + private displayAmount(code: string, amt: number) { return `${amt} ${this.currencyShortWordForCode(code, amt === 1)}`; } diff --git a/src/views/ClaimView.vue b/src/views/ClaimView.vue index f594dc9b5..756468c49 100644 --- a/src/views/ClaimView.vue +++ b/src/views/ClaimView.vue @@ -79,7 +79,10 @@