mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	note image detail
This commit is contained in:
		| @@ -13,6 +13,7 @@ import NoteFull from "../entities/note_full.js"; | |||||||
| import noteDetailCode from './note_detail_code.js'; | import noteDetailCode from './note_detail_code.js'; | ||||||
| import noteDetailText from './note_detail_text.js'; | import noteDetailText from './note_detail_text.js'; | ||||||
| import noteDetailFile from './note_detail_file.js'; | import noteDetailFile from './note_detail_file.js'; | ||||||
|  | import noteDetailImage from './note_detail_image.js'; | ||||||
| import noteDetailSearch from './note_detail_search.js'; | import noteDetailSearch from './note_detail_search.js'; | ||||||
| import noteDetailRender from './note_detail_render.js'; | import noteDetailRender from './note_detail_render.js'; | ||||||
| import noteDetailRelationMap from './note_detail_relation_map.js'; | import noteDetailRelationMap from './note_detail_relation_map.js'; | ||||||
| @@ -45,6 +46,7 @@ const components = { | |||||||
|     'code': noteDetailCode, |     'code': noteDetailCode, | ||||||
|     'text': noteDetailText, |     'text': noteDetailText, | ||||||
|     'file': noteDetailFile, |     'file': noteDetailFile, | ||||||
|  |     'image': noteDetailImage, | ||||||
|     'search': noteDetailSearch, |     'search': noteDetailSearch, | ||||||
|     'render': noteDetailRender, |     'render': noteDetailRender, | ||||||
|     'relation-map': noteDetailRelationMap |     'relation-map': noteDetailRelationMap | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ import noteDetailService from "./note_detail.js"; | |||||||
|  |  | ||||||
| let codeEditor = null; | let codeEditor = null; | ||||||
|  |  | ||||||
| const $noteDetailCode = $('#note-detail-code'); | const $component = $('#note-detail-code'); | ||||||
| const $executeScriptButton = $("#execute-script-button"); | const $executeScriptButton = $("#execute-script-button"); | ||||||
|  |  | ||||||
| async function show() { | async function show() { | ||||||
| @@ -22,7 +22,7 @@ async function show() { | |||||||
|  |  | ||||||
|         CodeMirror.modeURL = 'libraries/codemirror/mode/%N/%N.js'; |         CodeMirror.modeURL = 'libraries/codemirror/mode/%N/%N.js'; | ||||||
|  |  | ||||||
|         codeEditor = CodeMirror($noteDetailCode[0], { |         codeEditor = CodeMirror($component[0], { | ||||||
|             value: "", |             value: "", | ||||||
|             viewportMargin: Infinity, |             viewportMargin: Infinity, | ||||||
|             indentUnit: 4, |             indentUnit: 4, | ||||||
| @@ -38,7 +38,7 @@ async function show() { | |||||||
|         onNoteChange(noteDetailService.noteChanged); |         onNoteChange(noteDetailService.noteChanged); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     $noteDetailCode.show(); |     $component.show(); | ||||||
|  |  | ||||||
|     const currentNote = noteDetailService.getCurrentNote(); |     const currentNote = noteDetailService.getCurrentNote(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import server from "./server.js"; | |||||||
| import protectedSessionHolder from "./protected_session_holder.js"; | import protectedSessionHolder from "./protected_session_holder.js"; | ||||||
| import noteDetailService from "./note_detail.js"; | import noteDetailService from "./note_detail.js"; | ||||||
|  |  | ||||||
| const $noteDetailFile = $('#note-detail-file'); | const $component = $('#note-detail-file'); | ||||||
|  |  | ||||||
| const $fileFileName = $("#file-filename"); | const $fileFileName = $("#file-filename"); | ||||||
| const $fileFileType = $("#file-filetype"); | const $fileFileType = $("#file-filetype"); | ||||||
| @@ -17,7 +17,7 @@ async function show() { | |||||||
|     const attributes = await server.get('notes/' + currentNote.noteId + '/attributes'); |     const attributes = await server.get('notes/' + currentNote.noteId + '/attributes'); | ||||||
|     const attributeMap = utils.toObject(attributes, l => [l.name, l.value]); |     const attributeMap = utils.toObject(attributes, l => [l.name, l.value]); | ||||||
|  |  | ||||||
|     $noteDetailFile.show(); |     $component.show(); | ||||||
|  |  | ||||||
|     $fileFileName.text(attributeMap.originalFileName); |     $fileFileName.text(attributeMap.originalFileName); | ||||||
|     $fileFileSize.text(attributeMap.fileSize + " bytes"); |     $fileFileSize.text(attributeMap.fileSize + " bytes"); | ||||||
|   | |||||||
| @@ -3,39 +3,20 @@ import server from "./server.js"; | |||||||
| import protectedSessionHolder from "./protected_session_holder.js"; | import protectedSessionHolder from "./protected_session_holder.js"; | ||||||
| import noteDetailService from "./note_detail.js"; | import noteDetailService from "./note_detail.js"; | ||||||
|  |  | ||||||
| const $noteDetailFile = $('#note-detail-file'); | const $component = $('#note-detail-image'); | ||||||
|  | const $imageView = $('#note-detail-image-view'); | ||||||
|  |  | ||||||
| const $fileFileName = $("#file-filename"); | const $imageDownload = $("#image-download"); | ||||||
| const $fileFileType = $("#file-filetype"); |  | ||||||
| const $fileFileSize = $("#file-filesize"); |  | ||||||
| const $fileDownload = $("#file-download"); |  | ||||||
| const $fileOpen = $("#file-open"); |  | ||||||
|  |  | ||||||
| async function show() { | async function show() { | ||||||
|     const currentNote = noteDetailService.getCurrentNote(); |     const currentNote = noteDetailService.getCurrentNote(); | ||||||
|  |  | ||||||
|     const attributes = await server.get('notes/' + currentNote.noteId + '/attributes'); |     $component.show(); | ||||||
|     const attributeMap = utils.toObject(attributes, l => [l.name, l.value]); |  | ||||||
|  |  | ||||||
|     $noteDetailFile.show(); |     $imageView.prop("src", `/api/images/${currentNote.noteId}/${currentNote.title}`); | ||||||
|  |  | ||||||
|     $fileFileName.text(attributeMap.originalFileName); |  | ||||||
|     $fileFileSize.text(attributeMap.fileSize + " bytes"); |  | ||||||
|     $fileFileType.text(currentNote.mime); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| $fileDownload.click(() => utils.download(getFileUrl())); | $imageDownload.click(() => utils.download(getFileUrl())); | ||||||
|  |  | ||||||
| $fileOpen.click(() => { |  | ||||||
|     if (utils.isElectron()) { |  | ||||||
|         const open = require("open"); |  | ||||||
|  |  | ||||||
|         open(getFileUrl()); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         window.location.href = getFileUrl(); |  | ||||||
|     } |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| function getFileUrl() { | function getFileUrl() { | ||||||
|     // electron needs absolute URL so we extract current host, port, protocol |     // electron needs absolute URL so we extract current host, port, protocol | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import linkService from "./link.js"; | |||||||
| import libraryLoader from "./library_loader.js"; | import libraryLoader from "./library_loader.js"; | ||||||
| import treeService from "./tree.js"; | import treeService from "./tree.js"; | ||||||
|  |  | ||||||
| const $noteDetailRelationMap = $("#note-detail-relation-map"); | const $component = $("#note-detail-relation-map"); | ||||||
| const $relationMapCanvas = $("#relation-map-canvas"); | const $relationMapCanvas = $("#relation-map-canvas"); | ||||||
| const $addChildNotesButton = $("#relation-map-add-child-notes"); | const $addChildNotesButton = $("#relation-map-add-child-notes"); | ||||||
| const $createChildNote = $("#relation-map-create-child-note"); | const $createChildNote = $("#relation-map-create-child-note"); | ||||||
| @@ -60,7 +60,7 @@ function loadMapData() { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function show() { | async function show() { | ||||||
|     $noteDetailRelationMap.show(); |     $component.show(); | ||||||
|  |  | ||||||
|     await libraryLoader.requireLibrary(libraryLoader.RELATION_MAP); |     await libraryLoader.requireLibrary(libraryLoader.RELATION_MAP); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import bundleService from "./bundle.js"; | |||||||
| import server from "./server.js"; | import server from "./server.js"; | ||||||
| import noteDetailService from "./note_detail.js"; | import noteDetailService from "./note_detail.js"; | ||||||
|  |  | ||||||
| const $noteDetailRender = $('#note-detail-render'); | const $component = $('#note-detail-render'); | ||||||
| const $noteDetailRenderHelp = $('#note-detail-render-help'); | const $noteDetailRenderHelp = $('#note-detail-render-help'); | ||||||
| const $noteDetailRenderContent = $('#note-detail-render-content'); | const $noteDetailRenderContent = $('#note-detail-render-content'); | ||||||
| const $renderButton = $('#render-button'); | const $renderButton = $('#render-button'); | ||||||
| @@ -14,7 +14,7 @@ async function render() { | |||||||
|         && attr.name === 'renderNote' |         && attr.name === 'renderNote' | ||||||
|         && !!attr.value); |         && !!attr.value); | ||||||
|  |  | ||||||
|     $noteDetailRender.show(); |     $component.show(); | ||||||
|  |  | ||||||
|     $noteDetailRenderContent.empty(); |     $noteDetailRenderContent.empty(); | ||||||
|     $noteDetailRenderContent.toggle(renderNotes.length > 0); |     $noteDetailRenderContent.toggle(renderNotes.length > 0); | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import noteDetailService from "./note_detail.js"; | import noteDetailService from "./note_detail.js"; | ||||||
|  |  | ||||||
| const $searchString = $("#search-string"); | const $searchString = $("#search-string"); | ||||||
| const $noteDetailSearch = $('#note-detail-search'); | const $component = $('#note-detail-search'); | ||||||
|  |  | ||||||
| function getContent() { | function getContent() { | ||||||
|     JSON.stringify({ |     JSON.stringify({ | ||||||
| @@ -10,7 +10,7 @@ function getContent() { | |||||||
| } | } | ||||||
|  |  | ||||||
| function show() { | function show() { | ||||||
|     $noteDetailSearch.show(); |     $component.show(); | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|         const json = JSON.parse(noteDetailService.getCurrentNote().content); |         const json = JSON.parse(noteDetailService.getCurrentNote().content); | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import noteDetailService from './note_detail.js'; | |||||||
| import utils from "./utils.js"; | import utils from "./utils.js"; | ||||||
| import infoService from "./info.js"; | import infoService from "./info.js"; | ||||||
|  |  | ||||||
| const $noteDetailText = $('#note-detail-text'); | const $component = $('#note-detail-text'); | ||||||
|  |  | ||||||
| const $markdownImportDialog = $('#markdown-import-dialog'); | const $markdownImportDialog = $('#markdown-import-dialog'); | ||||||
| const $markdownImportTextarea = $('#markdown-import-textarea'); | const $markdownImportTextarea = $('#markdown-import-textarea'); | ||||||
| @@ -18,7 +18,7 @@ async function show() { | |||||||
|         // textEditor might have been initialized during previous await so checking again |         // textEditor might have been initialized during previous await so checking again | ||||||
|         // looks like double initialization can freeze CKEditor pretty badly |         // looks like double initialization can freeze CKEditor pretty badly | ||||||
|         if (!textEditor) { |         if (!textEditor) { | ||||||
|             textEditor = await BalloonEditor.create($noteDetailText[0]); |             textEditor = await BalloonEditor.create($component[0]); | ||||||
|  |  | ||||||
|             onNoteChange(noteDetailService.noteChanged); |             onNoteChange(noteDetailService.noteChanged); | ||||||
|         } |         } | ||||||
| @@ -26,7 +26,7 @@ async function show() { | |||||||
|  |  | ||||||
|     textEditor.setData(noteDetailService.getCurrentNote().content); |     textEditor.setData(noteDetailService.getCurrentNote().content); | ||||||
|  |  | ||||||
|     $noteDetailText.show(); |     $component.show(); | ||||||
| } | } | ||||||
|  |  | ||||||
| function getContent() { | function getContent() { | ||||||
| @@ -42,7 +42,7 @@ function getContent() { | |||||||
| } | } | ||||||
|  |  | ||||||
| function focus() { | function focus() { | ||||||
|     $noteDetailText.focus(); |     $component.focus(); | ||||||
| } | } | ||||||
|  |  | ||||||
| function getEditor() { | function getEditor() { | ||||||
|   | |||||||
| @@ -6,19 +6,22 @@ const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR; | |||||||
| const fs = require('fs'); | const fs = require('fs'); | ||||||
|  |  | ||||||
| async function returnImage(req, res) { | async function returnImage(req, res) { | ||||||
|     const image = await repository.getImage(req.params.imageId); |     const image = await repository.getNote(req.params.noteId); | ||||||
|  |  | ||||||
|     if (!image) { |     if (!image) { | ||||||
|         return res.sendStatus(404); |         return res.sendStatus(404); | ||||||
|     } |     } | ||||||
|  |     else if (image.type !== 'image') { | ||||||
|  |         return res.sendStatus(400); | ||||||
|  |     } | ||||||
|     else if (image.data === null) { |     else if (image.data === null) { | ||||||
|         res.set('Content-Type', 'image/png'); |         res.set('Content-Type', 'image/png'); | ||||||
|         return res.send(fs.readFileSync(RESOURCE_DIR + '/db/image-deleted.png')); |         return res.send(fs.readFileSync(RESOURCE_DIR + '/db/image-deleted.png')); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     res.set('Content-Type', 'image/' + image.format); |     res.set('Content-Type', image.mime); | ||||||
|  |  | ||||||
|     res.send(image.data); |     res.send(image.content); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function uploadImage(req) { | async function uploadImage(req) { | ||||||
|   | |||||||
| @@ -144,7 +144,7 @@ function register(app) { | |||||||
|     apiRoute(GET, '/api/attributes/names', attributesRoute.getAttributeNames); |     apiRoute(GET, '/api/attributes/names', attributesRoute.getAttributeNames); | ||||||
|     apiRoute(GET, '/api/attributes/values/:attributeName', attributesRoute.getValuesForAttribute); |     apiRoute(GET, '/api/attributes/values/:attributeName', attributesRoute.getValuesForAttribute); | ||||||
|  |  | ||||||
|     route(GET, '/api/images/:imageId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage); |     route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage); | ||||||
|     route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware], imageRoute.uploadImage, apiResultHandler); |     route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware], imageRoute.uploadImage, apiResultHandler); | ||||||
|  |  | ||||||
|     apiRoute(GET, '/api/recent-changes', recentChangesApiRoute.getRecentChanges); |     apiRoute(GET, '/api/recent-changes', recentChangesApiRoute.getRecentChanges); | ||||||
|   | |||||||
| @@ -182,27 +182,6 @@ async function runAllChecks() { | |||||||
|             COUNT(*) > 1`, |             COUNT(*) > 1`, | ||||||
|         "Duplicate undeleted parent note <-> note relationship - parent note ID > note ID", errorList); |         "Duplicate undeleted parent note <-> note relationship - parent note ID > note ID", errorList); | ||||||
|  |  | ||||||
|     await runCheck(` |  | ||||||
|           SELECT  |  | ||||||
|             images.imageId |  | ||||||
|           FROM  |  | ||||||
|             images |  | ||||||
|             LEFT JOIN note_images ON note_images.imageId = images.imageId |  | ||||||
|           WHERE  |  | ||||||
|             note_images.noteImageId IS NULL`, |  | ||||||
|         "Image with no note relation", errorList); |  | ||||||
|  |  | ||||||
|     await runCheck(` |  | ||||||
|           SELECT  |  | ||||||
|             note_images.noteImageId |  | ||||||
|           FROM  |  | ||||||
|             note_images |  | ||||||
|             JOIN images USING(imageId) |  | ||||||
|           WHERE  |  | ||||||
|             note_images.isDeleted = 0 |  | ||||||
|             AND images.isDeleted = 1`, |  | ||||||
|         "Note image is not deleted while image is deleted for noteImageId", errorList); |  | ||||||
|  |  | ||||||
|     await runCheck(` |     await runCheck(` | ||||||
|           SELECT  |           SELECT  | ||||||
|             noteId |             noteId | ||||||
| @@ -232,8 +211,6 @@ async function runAllChecks() { | |||||||
|     await runSyncRowChecks("note_revisions", "noteRevisionId", errorList); |     await runSyncRowChecks("note_revisions", "noteRevisionId", errorList); | ||||||
|     await runSyncRowChecks("branches", "branchId", errorList); |     await runSyncRowChecks("branches", "branchId", errorList); | ||||||
|     await runSyncRowChecks("recent_notes", "branchId", errorList); |     await runSyncRowChecks("recent_notes", "branchId", errorList); | ||||||
|     await runSyncRowChecks("images", "imageId", errorList); |  | ||||||
|     await runSyncRowChecks("note_images", "noteImageId", errorList); |  | ||||||
|     await runSyncRowChecks("attributes", "attributeId", errorList); |     await runSyncRowChecks("attributes", "attributeId", errorList); | ||||||
|     await runSyncRowChecks("api_tokens", "apiTokenId", errorList); |     await runSyncRowChecks("api_tokens", "apiTokenId", errorList); | ||||||
|     await runSyncRowChecks("options", "name", errorList); |     await runSyncRowChecks("options", "name", errorList); | ||||||
|   | |||||||
| @@ -15,6 +15,8 @@ | |||||||
|  |  | ||||||
|         <% include file.ejs %> |         <% include file.ejs %> | ||||||
|  |  | ||||||
|  |         <% include image.ejs %> | ||||||
|  |  | ||||||
|         <% include relation_map.ejs %> |         <% include relation_map.ejs %> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								src/views/details/image.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/views/details/image.ejs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | <div id="note-detail-image" class="note-detail-component"> | ||||||
|  |     <img id="note-detail-image-view" /> | ||||||
|  |  | ||||||
|  |     <br/> | ||||||
|  |     <br/> | ||||||
|  |     <button id="file-download" class="btn btn-primary" type="button">Download</button> | ||||||
|  | </div> | ||||||
		Reference in New Issue
	
	Block a user