mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 11:39:01 +01:00 
			
		
		
		
	Merge branch 'develop' into feat_add-link-to-swagger-ui
This commit is contained in:
		
						commit
						4df76fafe1
					
				
							
								
								
									
										8
									
								
								.github/actions/build-electron/action.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/actions/build-electron/action.yml
									
									
									
									
										vendored
									
									
								
							| @ -18,7 +18,7 @@ runs: | ||||
|     # Certificate setup | ||||
|     - name: Import Apple certificates | ||||
|       if: inputs.os == 'macos' | ||||
|       uses: apple-actions/import-codesign-certs@v2 | ||||
|       uses: apple-actions/import-codesign-certs@v3 | ||||
|       with: | ||||
|         p12-file-base64: ${{ env.APPLE_APP_CERTIFICATE_BASE64 }} | ||||
|         p12-password: ${{ env.APPLE_APP_CERTIFICATE_PASSWORD }} | ||||
| @ -27,7 +27,7 @@ runs: | ||||
| 
 | ||||
|     - name: Install Installer certificate | ||||
|       if: inputs.os == 'macos' | ||||
|       uses: apple-actions/import-codesign-certs@v2 | ||||
|       uses: apple-actions/import-codesign-certs@v3 | ||||
|       with: | ||||
|         p12-file-base64: ${{ env.APPLE_INSTALLER_CERTIFICATE_BASE64 }} | ||||
|         p12-password: ${{ env.APPLE_INSTALLER_CERTIFICATE_PASSWORD }} | ||||
| @ -180,7 +180,7 @@ runs: | ||||
|           dmg_file=$(find out -name "*.dmg" -print -quit) | ||||
|           if [ -n "$dmg_file" ]; then | ||||
|             echo "Found DMG: $dmg_file" | ||||
|             cp "$dmg_file" "upload/TriliumNextNotes-${{ github.ref_name }}-darwin-${{ inputs.arch }}.dmg" | ||||
|             cp "$dmg_file" "upload/TriliumNextNotes-${{ github.ref_name }}-macos-${{ inputs.arch }}.dmg" | ||||
|           else | ||||
|             echo "Warning: No DMG file found" | ||||
|           fi | ||||
| @ -190,7 +190,7 @@ runs: | ||||
|           zip_file=$(find out -name "*.zip" -print -quit) | ||||
|           if [ -n "$zip_file" ]; then | ||||
|             echo "Found ZIP: $zip_file" | ||||
|             cp "$zip_file" "upload/TriliumNextNotes-${{ github.ref_name }}-darwin-${{ inputs.arch }}.zip" | ||||
|             cp "$zip_file" "upload/TriliumNextNotes-${{ github.ref_name }}-macos-${{ inputs.arch }}.zip" | ||||
|           else | ||||
|             echo "Warning: No ZIP file found" | ||||
|           fi | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										155
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										155
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -154,6 +154,7 @@ | ||||
|         "@types/session-file-store": "1.2.5", | ||||
|         "@types/source-map-support": "0.5.10", | ||||
|         "@types/stream-throttle": "0.1.4", | ||||
|         "@types/supertest": "6.0.2", | ||||
|         "@types/swagger-ui-express": "4.1.8", | ||||
|         "@types/tmp": "0.2.6", | ||||
|         "@types/turndown": "5.0.5", | ||||
| @ -177,6 +178,7 @@ | ||||
|         "rimraf": "6.0.1", | ||||
|         "sass": "1.85.1", | ||||
|         "sass-loader": "16.0.5", | ||||
|         "supertest": "7.0.0", | ||||
|         "swagger-jsdoc": "6.2.8", | ||||
|         "tslib": "2.8.1", | ||||
|         "tsx": "4.19.3", | ||||
| @ -4089,6 +4091,13 @@ | ||||
|         "@types/express": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/cookiejar": { | ||||
|       "version": "2.1.5", | ||||
|       "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", | ||||
|       "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/d3": { | ||||
|       "version": "7.4.3", | ||||
|       "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", | ||||
| @ -4597,6 +4606,13 @@ | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/methods": { | ||||
|       "version": "1.1.4", | ||||
|       "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", | ||||
|       "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/@types/mime": { | ||||
|       "version": "1.3.5", | ||||
|       "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", | ||||
| @ -4797,6 +4813,30 @@ | ||||
|         "@types/node": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/superagent": { | ||||
|       "version": "8.1.9", | ||||
|       "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", | ||||
|       "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/cookiejar": "^2.1.5", | ||||
|         "@types/methods": "^1.1.4", | ||||
|         "@types/node": "*", | ||||
|         "form-data": "^4.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/supertest": { | ||||
|       "version": "6.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", | ||||
|       "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/methods": "^1.1.4", | ||||
|         "@types/superagent": "^8.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/swagger-ui-express": { | ||||
|       "version": "4.1.8", | ||||
|       "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.8.tgz", | ||||
| @ -5631,6 +5671,13 @@ | ||||
|       "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/asap": { | ||||
|       "version": "2.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", | ||||
|       "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/asar": { | ||||
|       "version": "3.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz", | ||||
| @ -7017,6 +7064,16 @@ | ||||
|         "node": ">=0.10.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/component-emitter": { | ||||
|       "version": "1.3.1", | ||||
|       "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", | ||||
|       "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "funding": { | ||||
|         "url": "https://github.com/sponsors/sindresorhus" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/compress-commons": { | ||||
|       "version": "6.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", | ||||
| @ -7184,6 +7241,13 @@ | ||||
|       "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/cookiejar": { | ||||
|       "version": "2.1.4", | ||||
|       "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", | ||||
|       "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/core-util-is": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", | ||||
| @ -8320,6 +8384,17 @@ | ||||
|       "integrity": "sha512-g8GWBkJLiIDRJfRXEdrd1wMXpNyGId2DkbfuwFahSb4OCvn717hyRJtAcEDISfp3zkwEhZ4Y4woHPA6DeyB3Fw==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/dezalgo": { | ||||
|       "version": "1.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", | ||||
|       "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", | ||||
|       "dev": true, | ||||
|       "license": "ISC", | ||||
|       "dependencies": { | ||||
|         "asap": "^2.0.0", | ||||
|         "wrappy": "1" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/dir-compare": { | ||||
|       "version": "4.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz", | ||||
| @ -10043,6 +10118,13 @@ | ||||
|         "node": ">= 6" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/fast-safe-stringify": { | ||||
|       "version": "2.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", | ||||
|       "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", | ||||
|       "dev": true, | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/fast-uri": { | ||||
|       "version": "3.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", | ||||
| @ -10408,6 +10490,21 @@ | ||||
|         "node": ">= 6" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/formidable": { | ||||
|       "version": "3.5.2", | ||||
|       "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.2.tgz", | ||||
|       "integrity": "sha512-Jqc1btCy3QzRbJaICGwKcBfGWuLADRerLzDqi2NwSt/UkXLsHJw2TVResiaoBufHVHy9aSgClOHCeJsSsFLTbg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "dezalgo": "^1.0.4", | ||||
|         "hexoid": "^2.0.0", | ||||
|         "once": "^1.4.0" | ||||
|       }, | ||||
|       "funding": { | ||||
|         "url": "https://ko-fi.com/tunnckoCore/commissions" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/forwarded": { | ||||
|       "version": "0.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", | ||||
| @ -10970,6 +11067,16 @@ | ||||
|         "node": ">=18.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/hexoid": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-2.0.0.tgz", | ||||
|       "integrity": "sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">=8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/history": { | ||||
|       "version": "4.10.1", | ||||
|       "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", | ||||
| @ -16888,6 +16995,54 @@ | ||||
|         "node": ">= 8.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/superagent": { | ||||
|       "version": "9.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", | ||||
|       "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "component-emitter": "^1.3.0", | ||||
|         "cookiejar": "^2.1.4", | ||||
|         "debug": "^4.3.4", | ||||
|         "fast-safe-stringify": "^2.1.1", | ||||
|         "form-data": "^4.0.0", | ||||
|         "formidable": "^3.5.1", | ||||
|         "methods": "^1.1.2", | ||||
|         "mime": "2.6.0", | ||||
|         "qs": "^6.11.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=14.18.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/superagent/node_modules/mime": { | ||||
|       "version": "2.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", | ||||
|       "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "bin": { | ||||
|         "mime": "cli.js" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=4.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/supertest": { | ||||
|       "version": "7.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.0.0.tgz", | ||||
|       "integrity": "sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==", | ||||
|       "dev": true, | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "methods": "^1.1.2", | ||||
|         "superagent": "^9.0.1" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=14.18.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/supports-color": { | ||||
|       "version": "7.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", | ||||
|  | ||||
							
								
								
									
										11
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								package.json
									
									
									
									
									
								
							| @ -44,10 +44,11 @@ | ||||
|     "docs:build": "npm run docs:build-backend && npm run docs:build-frontend", | ||||
|     "build:webpack": "tsx node_modules/webpack/bin/webpack.js -c webpack.config.ts", | ||||
|     "build:prepare-dist": "npm run build:webpack && rimraf ./dist && tsc && tsx ./bin/copy-dist.ts", | ||||
|     "test": "npm run test:server && npm run test:client", | ||||
|     "test:server": "cross-env TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest", | ||||
|     "test:client": "cross-env TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest --root src/public/app", | ||||
|     "test:coverage": "cross-env TRILIUM_DATA_DIR=./integration-tests/db vitest --coverage", | ||||
|     "test": "npm run client:test && npm run server:test", | ||||
|     "server:test": "cross-env TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest", | ||||
|     "server:coverage": "cross-env TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest --coverage", | ||||
|     "client:test": "cross-env TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest --root src/public/app", | ||||
|     "client:coverage": "cross-env TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest --root src/public/app --coverage", | ||||
|     "test:playwright": "playwright test", | ||||
|     "test:integration-edit-db": "cross-env TRILIUM_INTEGRATION_TEST=edit TRILIUM_PORT=8081 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts", | ||||
|     "test:integration-mem-db": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts", | ||||
| @ -203,6 +204,7 @@ | ||||
|     "@types/session-file-store": "1.2.5", | ||||
|     "@types/source-map-support": "0.5.10", | ||||
|     "@types/stream-throttle": "0.1.4", | ||||
|     "@types/supertest": "6.0.2", | ||||
|     "@types/swagger-ui-express": "4.1.8", | ||||
|     "@types/tmp": "0.2.6", | ||||
|     "@types/turndown": "5.0.5", | ||||
| @ -226,6 +228,7 @@ | ||||
|     "rimraf": "6.0.1", | ||||
|     "sass": "1.85.1", | ||||
|     "sass-loader": "16.0.5", | ||||
|     "supertest": "7.0.0", | ||||
|     "swagger-jsdoc": "6.2.8", | ||||
|     "tslib": "2.8.1", | ||||
|     "tsx": "4.19.3", | ||||
|  | ||||
| @ -203,7 +203,7 @@ function renderFile(entity: FNote | FAttachment, type: string, $renderedContent: | ||||
|         // open doesn't work for protected notes since it works through a browser which isn't in protected session
 | ||||
|         $openButton.toggle(!entity.isProtected); | ||||
| 
 | ||||
|         $content.append($('<div style="display: flex; justify-content: space-evenly; margin-top: 5px;">').append($downloadButton).append($openButton)); | ||||
|         $content.append($('<footer class="file-footer">').append($downloadButton).append($openButton)); | ||||
|     } | ||||
| 
 | ||||
|     $renderedContent.append($content); | ||||
|  | ||||
| @ -9,7 +9,7 @@ interface CreateNewTasksOpts { | ||||
| export async function createNewTask({ parentNoteId, title }: CreateNewTasksOpts) { | ||||
|     await server.post(`tasks`, { | ||||
|         parentNoteId, | ||||
|         title | ||||
|         title: title.trim() | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -2,6 +2,9 @@ import { defineConfig } from "vitest/config"; | ||||
| 
 | ||||
| export default defineConfig({ | ||||
|     test: { | ||||
|         environment: "happy-dom" | ||||
|         environment: "happy-dom", | ||||
|         coverage: { | ||||
|             reporter: [ "text", "html" ] | ||||
|         } | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @ -20,6 +20,10 @@ const TPL = ` | ||||
|     .note-list-widget.full-height .note-list-widget-content { | ||||
|         height: 100%; | ||||
|     } | ||||
| 
 | ||||
|     .note-list-widget video { | ||||
|         height: 100%; | ||||
|     } | ||||
|     </style> | ||||
| 
 | ||||
|     <div class="note-list-widget-content"> | ||||
|  | ||||
| @ -63,7 +63,7 @@ export default class NoteWrapperWidget extends FlexContainer<BasicWidget> { | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         if (note.type === "file" && note.mime === "application/pdf") { | ||||
|         if (note.type === "file" && (note.mime === "application/pdf" || note.mime.startsWith("video/"))) { | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -22,6 +22,10 @@ const TPL = ` | ||||
|             padding: 0; | ||||
|         } | ||||
| 
 | ||||
|         .note-split.full-content-width .note-detail-file[data-preview-type="video"] { | ||||
|             overflow: hidden; | ||||
|         } | ||||
| 
 | ||||
|         .file-preview-content { | ||||
|             background-color: var(--accented-background-color); | ||||
|             padding: 15px; | ||||
| @ -29,6 +33,11 @@ const TPL = ` | ||||
|             overflow: auto; | ||||
|             margin: 10px; | ||||
|         } | ||||
| 
 | ||||
|         .note-detail-file > .video-preview { | ||||
|             width: 100%; | ||||
|             height: 100%; | ||||
|         } | ||||
|     </style> | ||||
| 
 | ||||
|     <div class="file-preview-too-big alert alert-info hidden-ext"> | ||||
| @ -85,6 +94,8 @@ export default class FileTypeWidget extends TypeWidget { | ||||
|         this.$videoPreview.hide(); | ||||
|         this.$audioPreview.hide(); | ||||
| 
 | ||||
|         let previewType: string; | ||||
| 
 | ||||
|         if (blob?.content) { | ||||
|             this.$previewContent.show().scrollTop(0); | ||||
|             const trimmedContent = blob.content.substring(0, TEXT_MAX_NUM_CHARS); | ||||
| @ -92,23 +103,30 @@ export default class FileTypeWidget extends TypeWidget { | ||||
|                 this.$previewTooBig.removeClass("hidden-ext"); | ||||
|             } | ||||
|             this.$previewContent.text(trimmedContent); | ||||
|             previewType = "text"; | ||||
|         } else if (note.mime === "application/pdf") { | ||||
|             this.$pdfPreview.show().attr("src", openService.getUrlForDownload(`api/notes/${this.noteId}/open`)); | ||||
|             previewType = "pdf"; | ||||
|         } else if (note.mime.startsWith("video/")) { | ||||
|             this.$videoPreview | ||||
|                 .show() | ||||
|                 .attr("src", openService.getUrlForDownload(`api/notes/${this.noteId}/open-partial`)) | ||||
|                 .attr("type", this.note?.mime ?? "") | ||||
|                 .css("width", this.$widget.width() ?? 0); | ||||
|             previewType = "video"; | ||||
|         } else if (note.mime.startsWith("audio/")) { | ||||
|             this.$audioPreview | ||||
|                 .show() | ||||
|                 .attr("src", openService.getUrlForDownload(`api/notes/${this.noteId}/open-partial`)) | ||||
|                 .attr("type", this.note?.mime ?? "") | ||||
|                 .css("width", this.$widget.width() ?? 0); | ||||
|             previewType = "audio"; | ||||
|         } else { | ||||
|             this.$previewNotAvailable.show(); | ||||
|             previewType = "not-available"; | ||||
|         } | ||||
| 
 | ||||
|         this.$widget.attr("data-preview-type", previewType ?? ""); | ||||
|     } | ||||
| 
 | ||||
|     async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { | ||||
|  | ||||
| @ -6,6 +6,7 @@ import * as taskService from "../../services/tasks.js"; | ||||
| import type { EventData } from "../../components/app_context.js"; | ||||
| import dayjs from "dayjs"; | ||||
| import calendarTime from "dayjs/plugin/calendar.js"; | ||||
| import { t } from "../../services/i18n.js"; | ||||
| dayjs.extend(calendarTime); | ||||
| 
 | ||||
| const TPL = ` | ||||
| @ -25,7 +26,7 @@ const TPL = ` | ||||
|             padding: 10px; | ||||
|         } | ||||
| 
 | ||||
|         .note-detail-task-list header { | ||||
|         .note-detail-task-list > header { | ||||
|             position: sticky; | ||||
|             top: 0; | ||||
|             z-index: 100; | ||||
| @ -59,15 +60,23 @@ const TPL = ` | ||||
|             transition: background 250ms ease-in-out; | ||||
|         } | ||||
| 
 | ||||
|         .note-detail-task-list .task-container li > header { | ||||
|             display: flex; | ||||
|             flex-wrap: wrap; | ||||
|             justify-content: flex-end; | ||||
|             align-items: center; | ||||
|         } | ||||
| 
 | ||||
|         .note-detail-task-list .task-container li .check { | ||||
|             margin-right: 0.5em; | ||||
|         } | ||||
| 
 | ||||
|         .note-detail-task-list .task-container li .title { | ||||
|             flex-grow: 1; | ||||
|         } | ||||
| 
 | ||||
|         .note-detail-task-list .task-container li .due-date { | ||||
|             float: right; | ||||
|             font-size: 0.9rem; | ||||
|             margin-top: 0.1rem; | ||||
|             vertical-align: middle; | ||||
|         } | ||||
| 
 | ||||
|         .note-detail-task-list .task-container li.overdue .due-date { | ||||
| @ -81,6 +90,7 @@ function buildTasks(tasks: FTask[]) { | ||||
|     let html = ''; | ||||
| 
 | ||||
|     const now = dayjs(); | ||||
|     const dateFormat = "DD-MM-YYYY"; | ||||
|     for (const task of tasks) { | ||||
|         const classes = ["task"]; | ||||
| 
 | ||||
| @ -89,14 +99,25 @@ function buildTasks(tasks: FTask[]) { | ||||
|         } | ||||
| 
 | ||||
|         html += `<li class="${classes.join(" ")}" data-task-id="${task.taskId}">`; | ||||
|         html += "<header>"; | ||||
|         html += '<span class="title">'; | ||||
|         html += `<input type="checkbox" class="check" ${task.isDone ? "checked" : ""} />`; | ||||
|         html += task.title; | ||||
|         html += `${task.title}</span>`; | ||||
|         html += '</span>'; | ||||
|         if (task.dueDate) { | ||||
|             html += `<span class="due-date">`; | ||||
|             html += `<span class="bx bx-calendar"></span> `; | ||||
|             html += dayjs(task.dueDate).calendar(); | ||||
|             html += dayjs(task.dueDate).calendar(null, { | ||||
|                 sameDay: `[${t("tasks.due.today")}]`, | ||||
|                 nextDay: `[${t("tasks.due.tomorrow")}]`, | ||||
|                 nextWeek: "dddd", | ||||
|                 lastDay: `[${t("tasks.due.yesterday")}]`, | ||||
|                 lastWeek: dateFormat, | ||||
|                 sameElse: dateFormat | ||||
|             }); | ||||
|             html += "</span>"; | ||||
|         } | ||||
|         html += "</header>"; | ||||
|         html += `<div class="edit-container"></div>`; | ||||
|         html += `</li>`; | ||||
|     } | ||||
| @ -142,20 +163,19 @@ export default class TaskListWidget extends TypeWidget { | ||||
|         }); | ||||
| 
 | ||||
|         this.$taskContainer.on("click", "li", (e) => { | ||||
|             const $target = $(e.target); | ||||
| 
 | ||||
|             // Don't collapse when clicking on an inside element such as the due date dropdown.
 | ||||
|             if (e.currentTarget !== e.target) { | ||||
|             if ((e.target as HTMLElement).tagName === "INPUT") { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             const $target = $(e.target); | ||||
| 
 | ||||
|             // Clear existing edit containers.
 | ||||
|             const $existingContainers = this.$taskContainer.find(".edit-container"); | ||||
| 
 | ||||
|             $existingContainers.html(""); | ||||
| 
 | ||||
|             // Add the new edit container.
 | ||||
|             const $editContainer = $target.find(".edit-container"); | ||||
|             const $editContainer = $target.closest("li").find(".edit-container"); | ||||
|             const task = this.#getCorrespondingTask($target); | ||||
|             if (task) { | ||||
|                 $editContainer.html(buildEditContainer(task)); | ||||
| @ -183,7 +203,11 @@ export default class TaskListWidget extends TypeWidget { | ||||
|     } | ||||
| 
 | ||||
|     #getCorrespondingTask($target: JQuery<HTMLElement>) { | ||||
|         const taskId = $target.closest("li")[0].dataset.taskId; | ||||
|         const $parentEl = $target.closest("li"); | ||||
|         if (!$parentEl.length) { | ||||
|             return; | ||||
|         } | ||||
|         const taskId = $parentEl[0].dataset.taskId; | ||||
|         if (!taskId) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @ -1685,3 +1685,14 @@ body.zen .note-title-widget input { | ||||
|     font-size: 1rem !important; | ||||
|     background: transparent !important; | ||||
| } | ||||
| 
 | ||||
| /* Content renderer */ | ||||
| 
 | ||||
| footer.file-footer { | ||||
|     display: flex; | ||||
|     justify-content: center; | ||||
| } | ||||
| 
 | ||||
| footer.file-footer button { | ||||
|     margin: 5px; | ||||
| } | ||||
| @ -1560,6 +1560,10 @@ div.bookmark-folder-widget .note-link .bx { | ||||
|     border-bottom-color: var(--card-border-color); | ||||
| } | ||||
| 
 | ||||
| .note-list-wrapper .note-book-card footer.file-footer { | ||||
|     border: 1px solid var(--card-border-color); | ||||
| } | ||||
| 
 | ||||
| .note-list-wrapper .note-book-card .note-book-header .note-icon { | ||||
|     font-size: 17px; | ||||
|     vertical-align: text-bottom; | ||||
| @ -1610,7 +1614,8 @@ div.bookmark-folder-widget .note-link .bx { | ||||
| 
 | ||||
| .note-list-wrapper .note-book-card .note-book-content.type-canvas .rendered-content, | ||||
| .note-list-wrapper .note-book-card .note-book-content.type-mindMap .rendered-content, | ||||
| .note-list-wrapper .note-book-card .note-book-content.type-code .rendered-content { | ||||
| .note-list-wrapper .note-book-card .note-book-content.type-code .rendered-content, | ||||
| .note-list-wrapper .note-book-card .note-book-content.type-video .rendered-content { | ||||
|     padding: 0; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1675,5 +1675,12 @@ | ||||
|   "time_selector": { | ||||
|     "invalid_input": "The entered time value is not a valid number.", | ||||
|     "minimum_input": "The entered time value needs to be at least {{minimumSeconds}} seconds." | ||||
|   }, | ||||
|   "tasks": { | ||||
|     "due": { | ||||
|       "today": "Today", | ||||
|       "tomorrow": "Tomorrow", | ||||
|       "yesterday": "Yesterday" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -1678,5 +1678,12 @@ | ||||
|     "redirect_bare_domain_description": "Redirecționează utilizatorii anonimi către pagina de partajare în locul paginii de autentificare", | ||||
|     "redirect_bare_domain": "Redirecționează domeniul principal la pagina de partajare", | ||||
|     "check_share_root": "Verificare stare pagină partajată principală" | ||||
|   }, | ||||
|   "tasks": { | ||||
|     "due": { | ||||
|       "today": "Azi", | ||||
|       "tomorrow": "Mâine", | ||||
|       "yesterday": "Ieri" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										34
									
								
								src/share/routes.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/share/routes.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| import { beforeAll, beforeEach, describe, expect, it } from "vitest"; | ||||
| import supertest from "supertest"; | ||||
| import { initializeTranslations } from "../services/i18n.js"; | ||||
| import type { Application, Request, Response, NextFunction } from "express"; | ||||
| 
 | ||||
| let app: Application; | ||||
| 
 | ||||
| describe("Share API test", () => { | ||||
|     let cannotSetHeadersCount = 0; | ||||
| 
 | ||||
|     beforeAll(async () => { | ||||
|         initializeTranslations(); | ||||
|         app = (await import("../app.js")).default; | ||||
|         app.use((err: any, req: Request, res: Response, next: NextFunction) => { | ||||
|             if (err.message.includes("Cannot set headers after they are sent to the client")) { | ||||
|                 cannotSetHeadersCount++; | ||||
|             } | ||||
| 
 | ||||
|             next(); | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     beforeEach(() => { | ||||
|         cannotSetHeadersCount = 0; | ||||
|     }); | ||||
| 
 | ||||
|     it("requests password for password-protected share", async () => { | ||||
|         await supertest(app) | ||||
|             .get("/share/YjlPRj2E9fOV") | ||||
|             .expect("WWW-Authenticate", 'Basic realm="User Visible Realm", charset="UTF-8"'); | ||||
|         expect(cannotSetHeadersCount).toBe(0); | ||||
|     }); | ||||
| 
 | ||||
| }); | ||||
| @ -87,7 +87,6 @@ function checkNoteAccess(noteId: string, req: Request, res: Response) { | ||||
|     const header = req.header("Authorization"); | ||||
| 
 | ||||
|     if (!header?.startsWith("Basic ")) { | ||||
|         requestCredentials(res); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -19,7 +19,9 @@ export default defineConfig({ | ||||
|     test: { | ||||
|         exclude: [...configDefaults.exclude, ...customExcludes], | ||||
|         coverage: { | ||||
|             exclude: [...coverageConfigDefaults.exclude, ...customExcludes] | ||||
|             reporter: [ "text", "html" ], | ||||
|             include: ["src/**"], | ||||
|             exclude: ["src/public/**"] | ||||
|         } | ||||
|     } | ||||
| }); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Elian Doran
						Elian Doran