mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
note image detail
This commit is contained in:
parent
d0d2a7fe47
commit
21e952a7f0
@ -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>
|
Loading…
x
Reference in New Issue
Block a user