mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
exposing blobs in APIs
This commit is contained in:
parent
5e1f81e53e
commit
0af6f91d21
@ -139,8 +139,7 @@ class Becca {
|
|||||||
|
|
||||||
/** @returns {BBlob|null} */
|
/** @returns {BBlob|null} */
|
||||||
getBlob(blobId) {
|
getBlob(blobId) {
|
||||||
const row = sql.getRow("SELECT *, LENGTH(content) AS contentLength " +
|
const row = sql.getRow("SELECT *, LENGTH(content) AS contentLength FROM blobs WHERE blobId = ?", [blobId]);
|
||||||
"FROM blob WHERE blobId = ?", [blobId]);
|
|
||||||
|
|
||||||
const BBlob = require("./entities/bblob"); // avoiding circular dependency problems
|
const BBlob = require("./entities/bblob"); // avoiding circular dependency problems
|
||||||
return row ? new BBlob(row) : null;
|
return row ? new BBlob(row) : null;
|
||||||
|
@ -212,15 +212,9 @@ class BNote extends AbstractBeccaEntity {
|
|||||||
return this._getContent();
|
return this._getContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {{contentLength, dateModified, utcDateModified}} */
|
/** @returns {{dateModified, utcDateModified}} */
|
||||||
getContentMetadata() {
|
getContentMetadata() {
|
||||||
return sql.getRow(`
|
return sql.getRow(`SELECT dateModified, utcDateModified FROM blobs WHERE blobId = ?`, [this.blobId]);
|
||||||
SELECT
|
|
||||||
LENGTH(content) AS contentLength,
|
|
||||||
dateModified,
|
|
||||||
utcDateModified
|
|
||||||
FROM blobs
|
|
||||||
WHERE blobId = ?`, [this.blobId]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {*} */
|
/** @returns {*} */
|
||||||
|
@ -207,6 +207,7 @@ class NoteContext extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {Promise<boolean>} */
|
||||||
async isReadOnly() {
|
async isReadOnly() {
|
||||||
if (this.viewScope.readOnlyTemporarilyDisabled) {
|
if (this.viewScope.readOnlyTemporarilyDisabled) {
|
||||||
return false;
|
return false;
|
||||||
@ -221,14 +222,13 @@ class NoteContext extends Component {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const noteComplement = await this.getNoteComplement();
|
const blob = await this.note.getBlob();
|
||||||
|
|
||||||
const sizeLimit = this.note.type === 'text'
|
const sizeLimit = this.note.type === 'text'
|
||||||
? options.getInt('autoReadonlySizeText')
|
? options.getInt('autoReadonlySizeText')
|
||||||
: options.getInt('autoReadonlySizeCode');
|
: options.getInt('autoReadonlySizeCode');
|
||||||
|
|
||||||
return noteComplement.content
|
return blob.contentLength > sizeLimit
|
||||||
&& noteComplement.content.length > sizeLimit
|
|
||||||
&& !this.note.hasLabel('autoReadOnlyDisabled');
|
&& !this.note.hasLabel('autoReadOnlyDisabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class FAttachment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param [opts.full=false] - force retrieval of the full note
|
* @param [opts.preview=false] - retrieve only first 10 000 characters for a preview
|
||||||
* @return {FBlob}
|
* @return {FBlob}
|
||||||
*/
|
*/
|
||||||
async getBlob(opts = {}) {
|
async getBlob(opts = {}) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
class FBlob {
|
export default class FBlob {
|
||||||
constructor(row) {
|
constructor(row) {
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
this.blobId = row.blobId;
|
this.blobId = row.blobId;
|
||||||
@ -8,6 +8,7 @@ class FBlob {
|
|||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
this.content = row.content;
|
this.content = row.content;
|
||||||
|
this.contentLength = row.contentLength;
|
||||||
|
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
this.dateModified = row.dateModified;
|
this.dateModified = row.dateModified;
|
||||||
|
@ -843,7 +843,7 @@ class FNote {
|
|||||||
/**
|
/**
|
||||||
* Get relations which target this note
|
* Get relations which target this note
|
||||||
*
|
*
|
||||||
* @returns {FNote[]}
|
* @returns {Promise<FNote[]>}
|
||||||
*/
|
*/
|
||||||
async getTargetRelationSourceNotes() {
|
async getTargetRelationSourceNotes() {
|
||||||
const targetRelations = this.getTargetRelations();
|
const targetRelations = this.getTargetRelations();
|
||||||
@ -851,14 +851,17 @@ class FNote {
|
|||||||
return await this.froca.getNotes(targetRelations.map(tr => tr.noteId));
|
return await this.froca.getNotes(targetRelations.map(tr => tr.noteId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @deprecated use getBlob() instead */
|
/**
|
||||||
|
* @deprecated use getBlob() instead
|
||||||
|
* @return {Promise<FBlob>}
|
||||||
|
*/
|
||||||
async getNoteComplement() {
|
async getNoteComplement() {
|
||||||
return this.getBlob({ full: true });
|
return this.getBlob();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param [opts.full=false] - force retrieval of the full note
|
* @param [opts.preview=false] - retrieve only first 10 000 characters for a preview
|
||||||
* @return {FBlob}
|
* @return {Promise<FBlob>}
|
||||||
*/
|
*/
|
||||||
async getBlob(opts = {}) {
|
async getBlob(opts = {}) {
|
||||||
return await this.froca.getBlob('notes', this.noteId, opts);
|
return await this.froca.getBlob('notes', this.noteId, opts);
|
||||||
|
@ -320,12 +320,13 @@ class Froca {
|
|||||||
return attachmentRow ? new FAttachment(this, attachmentRow) : null;
|
return attachmentRow ? new FAttachment(this, attachmentRow) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {Promise<FBlob>} */
|
||||||
async getBlob(entityType, entityId, opts = {}) {
|
async getBlob(entityType, entityId, opts = {}) {
|
||||||
opts.full = !!opts.full;
|
opts.preview = !!opts.preview;
|
||||||
const key = `${entityType}-${entityId}`;
|
const key = `${entityType}-${entityId}-${opts.preview}`;
|
||||||
|
|
||||||
if (!this.blobPromises[key]) {
|
if (!this.blobPromises[key]) {
|
||||||
this.blobPromises[key] = server.get(`${entityType}/${entityId}/blob?full=${opts.full}`)
|
this.blobPromises[key] = server.get(`${entityType}/${entityId}/blob?preview=${opts.preview}`)
|
||||||
.then(row => new FBlob(row))
|
.then(row => new FBlob(row))
|
||||||
.catch(e => console.error(`Cannot get blob for ${entityType} '${entityId}'`));
|
.catch(e => console.error(`Cannot get blob for ${entityType} '${entityId}'`));
|
||||||
|
|
||||||
|
@ -11,6 +11,11 @@ import treeService from "./tree.js";
|
|||||||
|
|
||||||
let idCounter = 1;
|
let idCounter = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {FNote} note
|
||||||
|
* @param {object} options
|
||||||
|
* @return {Promise<{type: string, $renderedContent: jQuery}>}
|
||||||
|
*/
|
||||||
async function getRenderedContent(note, options = {}) {
|
async function getRenderedContent(note, options = {}) {
|
||||||
options = Object.assign({
|
options = Object.assign({
|
||||||
trim: false,
|
trim: false,
|
||||||
@ -22,10 +27,10 @@ async function getRenderedContent(note, options = {}) {
|
|||||||
const $renderedContent = $('<div class="rendered-note-content">');
|
const $renderedContent = $('<div class="rendered-note-content">');
|
||||||
|
|
||||||
if (type === 'text') {
|
if (type === 'text') {
|
||||||
const noteComplement = await froca.getNoteComplement(note.noteId);
|
const blob = await note.getBlob({ preview: options.trim });
|
||||||
|
|
||||||
if (!utils.isHtmlEmpty(noteComplement.content)) {
|
if (!utils.isHtmlEmpty(blob.content)) {
|
||||||
$renderedContent.append($('<div class="ck-content">').html(trim(noteComplement.content, options.trim)));
|
$renderedContent.append($('<div class="ck-content">').html(trim(blob.content, options.trim)));
|
||||||
|
|
||||||
if ($renderedContent.find('span.math-tex').length > 0) {
|
if ($renderedContent.find('span.math-tex').length > 0) {
|
||||||
await libraryLoader.requireLibrary(libraryLoader.KATEX);
|
await libraryLoader.requireLibrary(libraryLoader.KATEX);
|
||||||
@ -108,8 +113,8 @@ async function getRenderedContent(note, options = {}) {
|
|||||||
else if (type === 'mermaid') {
|
else if (type === 'mermaid') {
|
||||||
await libraryLoader.requireLibrary(libraryLoader.MERMAID);
|
await libraryLoader.requireLibrary(libraryLoader.MERMAID);
|
||||||
|
|
||||||
const noteComplement = await froca.getNoteComplement(note.noteId);
|
const blob = await note.getBlob();
|
||||||
const content = noteComplement.content || "";
|
const content = blob.content || "";
|
||||||
|
|
||||||
$renderedContent
|
$renderedContent
|
||||||
.css("display", "flex")
|
.css("display", "flex")
|
||||||
@ -140,8 +145,8 @@ async function getRenderedContent(note, options = {}) {
|
|||||||
// make sure surrounding container has size of what is visible. Then image is shrinked to its boundaries
|
// make sure surrounding container has size of what is visible. Then image is shrinked to its boundaries
|
||||||
$renderedContent.css({height: "100%", width:"100%"});
|
$renderedContent.css({height: "100%", width:"100%"});
|
||||||
|
|
||||||
const noteComplement = await froca.getNoteComplement(note.noteId);
|
const blob = await note.getBlob();
|
||||||
const content = noteComplement.content || "";
|
const content = blob.content || "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const placeHolderSVG = "<svg />";
|
const placeHolderSVG = "<svg />";
|
||||||
|
@ -99,8 +99,8 @@ export default class MermaidWidget extends NoteContextAwareWidget {
|
|||||||
async renderSvg(cb) {
|
async renderSvg(cb) {
|
||||||
idCounter++;
|
idCounter++;
|
||||||
|
|
||||||
const noteComplement = await froca.getNoteComplement(this.noteId);
|
const blob = await this.note.getBlob();
|
||||||
const content = noteComplement.content || "";
|
const content = blob.content || "";
|
||||||
|
|
||||||
// this can't be promisified since in case of error this both calls callback with error SVG and throws exception
|
// this can't be promisified since in case of error this both calls callback with error SVG and throws exception
|
||||||
// with error details
|
// with error details
|
||||||
|
@ -19,18 +19,22 @@ export default class NoteContextAwareWidget extends BasicWidget {
|
|||||||
return this.noteId === noteId;
|
return this.noteId === noteId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {FNote|undefined} */
|
||||||
get note() {
|
get note() {
|
||||||
return this.noteContext?.note;
|
return this.noteContext?.note;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {string|undefined} */
|
||||||
get noteId() {
|
get noteId() {
|
||||||
return this.note?.noteId;
|
return this.note?.noteId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {string|undefined} */
|
||||||
get notePath() {
|
get notePath() {
|
||||||
return this.noteContext?.notePath;
|
return this.noteContext?.notePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {string} */
|
||||||
get hoistedNoteId() {
|
get hoistedNoteId() {
|
||||||
return this.noteContext?.hoistedNoteId;
|
return this.noteContext?.hoistedNoteId;
|
||||||
}
|
}
|
||||||
|
@ -143,9 +143,9 @@ export default class NoteTypeWidget extends NoteContextAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async confirmChangeIfContent() {
|
async confirmChangeIfContent() {
|
||||||
const noteComplement = await this.noteContext.getNoteComplement();
|
const blob = await this.note.getBlob();
|
||||||
|
|
||||||
if (!noteComplement.content || !noteComplement.content.trim().length) {
|
if (!blob.content || !blob.content.trim().length) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,9 +134,9 @@ export default class FilePropertiesWidget extends NoteContextAwareWidget {
|
|||||||
this.$fileName.text(attributeMap.originalFileName || "?");
|
this.$fileName.text(attributeMap.originalFileName || "?");
|
||||||
this.$fileType.text(note.mime);
|
this.$fileType.text(note.mime);
|
||||||
|
|
||||||
const noteComplement = await this.noteContext.getNoteComplement();
|
const blob = await this.note.getBlob();
|
||||||
|
|
||||||
this.$fileSize.text(`${noteComplement.contentLength} bytes`);
|
this.$fileSize.text(`${blob.contentLength} bytes`);
|
||||||
|
|
||||||
// open doesn't work for protected notes since it works through browser which isn't in protected session
|
// open doesn't work for protected notes since it works through browser which isn't in protected session
|
||||||
this.$openButton.toggle(!note.isProtected);
|
this.$openButton.toggle(!note.isProtected);
|
||||||
|
@ -116,10 +116,10 @@ export default class ImagePropertiesWidget extends NoteContextAwareWidget {
|
|||||||
|
|
||||||
this.$widget.show();
|
this.$widget.show();
|
||||||
|
|
||||||
const noteComplement = await this.noteContext.getNoteComplement();
|
const blob = await this.note.getBlob();
|
||||||
|
|
||||||
this.$fileName.text(attributeMap.originalFileName || "?");
|
this.$fileName.text(attributeMap.originalFileName || "?");
|
||||||
this.$fileSize.text(`${noteComplement.contentLength} bytes`);
|
this.$fileSize.text(`${blob.contentLength} bytes`);
|
||||||
this.$fileType.text(note.mime);
|
this.$fileType.text(note.mime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,23 +120,22 @@ export default class NoteInfoWidget extends NoteContextAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async refreshWithNote(note) {
|
async refreshWithNote(note) {
|
||||||
const noteComplement = await this.noteContext.getNoteComplement();
|
const metadata = await server.get(`notes/${this.noteId}/metadata`);
|
||||||
|
|
||||||
this.$noteId.text(note.noteId);
|
this.$noteId.text(note.noteId);
|
||||||
this.$dateCreated
|
this.$dateCreated
|
||||||
.text(noteComplement.dateCreated.substr(0, 16))
|
.text(metadata.dateCreated.substr(0, 16))
|
||||||
.attr("title", noteComplement.dateCreated);
|
.attr("title", metadata.dateCreated);
|
||||||
|
|
||||||
this.$dateModified
|
this.$dateModified
|
||||||
.text(noteComplement.combinedDateModified.substr(0, 16))
|
.text(metadata.combinedDateModified.substr(0, 16))
|
||||||
.attr("title", noteComplement.combinedDateModified);
|
.attr("title", metadata.combinedDateModified);
|
||||||
|
|
||||||
this.$type.text(note.type);
|
this.$type.text(note.type);
|
||||||
|
|
||||||
if (note.mime) {
|
if (note.mime) {
|
||||||
this.$mime.text(`(${note.mime})`);
|
this.$mime.text(`(${note.mime})`);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
this.$mime.empty();
|
this.$mime.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
|||||||
this.currentNoteId = note.noteId;
|
this.currentNoteId = note.noteId;
|
||||||
|
|
||||||
// get note from backend and put into canvas
|
// get note from backend and put into canvas
|
||||||
const noteComplement = await froca.getNoteComplement(note.noteId);
|
const blob = await note.getBlob();
|
||||||
|
|
||||||
// before we load content into excalidraw, make sure excalidraw has loaded
|
// before we load content into excalidraw, make sure excalidraw has loaded
|
||||||
while (!this.excalidrawRef || !this.excalidrawRef.current) {
|
while (!this.excalidrawRef || !this.excalidrawRef.current) {
|
||||||
@ -170,7 +170,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
|||||||
* note into this fresh note. Probably due to that this note-instance does not get
|
* note into this fresh note. Probably due to that this note-instance does not get
|
||||||
* newly instantiated?
|
* newly instantiated?
|
||||||
*/
|
*/
|
||||||
if (this.excalidrawRef.current && noteComplement.content?.trim() === "") {
|
if (this.excalidrawRef.current && blob.content?.trim() === "") {
|
||||||
const sceneData = {
|
const sceneData = {
|
||||||
elements: [],
|
elements: [],
|
||||||
appState: {
|
appState: {
|
||||||
@ -181,16 +181,16 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
|||||||
|
|
||||||
this.excalidrawRef.current.updateScene(sceneData);
|
this.excalidrawRef.current.updateScene(sceneData);
|
||||||
}
|
}
|
||||||
else if (this.excalidrawRef.current && noteComplement.content) {
|
else if (this.excalidrawRef.current && blob.content) {
|
||||||
// load saved content into excalidraw canvas
|
// load saved content into excalidraw canvas
|
||||||
let content;
|
let content;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
content = JSON.parse(noteComplement.content || "");
|
content = JSON.parse(blob.content || "");
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.error("Error parsing content. Probably note.type changed",
|
console.error("Error parsing content. Probably note.type changed",
|
||||||
"Starting with empty canvas"
|
"Starting with empty canvas"
|
||||||
, note, noteComplement, err);
|
, note, blob, err);
|
||||||
|
|
||||||
content = {
|
content = {
|
||||||
elements: [],
|
elements: [],
|
||||||
|
@ -69,12 +69,12 @@ export default class EditableCodeTypeWidget extends TypeWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async doRefresh(note) {
|
async doRefresh(note) {
|
||||||
const noteComplement = await this.noteContext.getNoteComplement();
|
const blob = await this.note.getBlob();
|
||||||
|
|
||||||
await this.spacedUpdate.allowUpdateWithoutChange(() => {
|
await this.spacedUpdate.allowUpdateWithoutChange(() => {
|
||||||
// CodeMirror breaks pretty badly on null so even though it shouldn't happen (guarded by consistency check)
|
// CodeMirror breaks pretty badly on null so even though it shouldn't happen (guarded by consistency check)
|
||||||
// we provide fallback
|
// we provide fallback
|
||||||
this.codeEditor.setValue(noteComplement.content || "");
|
this.codeEditor.setValue(blob.content || "");
|
||||||
this.codeEditor.clearHistory();
|
this.codeEditor.clearHistory();
|
||||||
|
|
||||||
let info = CodeMirror.findModeByMIME(note.mime);
|
let info = CodeMirror.findModeByMIME(note.mime);
|
||||||
|
@ -183,10 +183,10 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async doRefresh(note) {
|
async doRefresh(note) {
|
||||||
const noteComplement = await froca.getNoteComplement(note.noteId);
|
const blob = await note.getBlob();
|
||||||
|
|
||||||
await this.spacedUpdate.allowUpdateWithoutChange(() => {
|
await this.spacedUpdate.allowUpdateWithoutChange(() => {
|
||||||
this.watchdog.editor.setData(noteComplement.content || "");
|
this.watchdog.editor.setData(blob.content || "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ export default class FileTypeWidget extends TypeWidget {
|
|||||||
async doRefresh(note) {
|
async doRefresh(note) {
|
||||||
this.$widget.show();
|
this.$widget.show();
|
||||||
|
|
||||||
const noteComplement = await this.noteContext.getNoteComplement();
|
const blob = await this.note.getBlob();
|
||||||
|
|
||||||
this.$previewContent.empty().hide();
|
this.$previewContent.empty().hide();
|
||||||
this.$pdfPreview.attr('src', '').empty().hide();
|
this.$pdfPreview.attr('src', '').empty().hide();
|
||||||
@ -60,9 +60,9 @@ export default class FileTypeWidget extends TypeWidget {
|
|||||||
this.$videoPreview.hide();
|
this.$videoPreview.hide();
|
||||||
this.$audioPreview.hide();
|
this.$audioPreview.hide();
|
||||||
|
|
||||||
if (noteComplement.content) {
|
if (blob.content) {
|
||||||
this.$previewContent.show().scrollTop(0);
|
this.$previewContent.show().scrollTop(0);
|
||||||
this.$previewContent.text(noteComplement.content);
|
this.$previewContent.text(blob.content);
|
||||||
}
|
}
|
||||||
else if (note.mime === 'application/pdf') {
|
else if (note.mime === 'application/pdf') {
|
||||||
this.$pdfPreview.show().attr("src", openService.getUrlForDownload(`api/notes/${this.noteId}/open`));
|
this.$pdfPreview.show().attr("src", openService.getUrlForDownload(`api/notes/${this.noteId}/open`));
|
||||||
|
@ -27,9 +27,9 @@ export default class ReadOnlyCodeTypeWidget extends TypeWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async doRefresh(note) {
|
async doRefresh(note) {
|
||||||
const noteComplement = await this.noteContext.getNoteComplement();
|
const blob = await this.note.getBlob();
|
||||||
|
|
||||||
this.$content.text(noteComplement.content);
|
this.$content.text(blob.content);
|
||||||
}
|
}
|
||||||
|
|
||||||
async executeWithContentElementEvent({resolve, ntxId}) {
|
async executeWithContentElementEvent({resolve, ntxId}) {
|
||||||
|
@ -93,9 +93,9 @@ export default class ReadOnlyTextTypeWidget extends AbstractTextTypeWidget {
|
|||||||
// (see https://github.com/zadam/trilium/issues/1590 for example of such conflict)
|
// (see https://github.com/zadam/trilium/issues/1590 for example of such conflict)
|
||||||
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
|
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
|
||||||
|
|
||||||
const noteComplement = await froca.getNoteComplement(note.noteId);
|
const blob = await note.getBlob();
|
||||||
|
|
||||||
this.$content.html(noteComplement.content);
|
this.$content.html(blob.content);
|
||||||
|
|
||||||
this.$content.find("a.reference-link").each(async (_, el) => {
|
this.$content.find("a.reference-link").each(async (_, el) => {
|
||||||
const notePath = $(el).attr('href');
|
const notePath = $(el).attr('href');
|
||||||
|
@ -197,11 +197,11 @@ export default class RelationMapTypeWidget extends TypeWidget {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const noteComplement = await this.noteContext.getNoteComplement();
|
const blob = await this.note.getBlob();
|
||||||
|
|
||||||
if (noteComplement.content) {
|
if (blob.content) {
|
||||||
try {
|
try {
|
||||||
this.mapData = JSON.parse(noteComplement.content);
|
this.mapData = JSON.parse(blob.content);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Could not parse content: ", e);
|
console.log("Could not parse content: ", e);
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@ const utils = require("../../services/utils");
|
|||||||
const blobService = require("../../services/blob.js");
|
const blobService = require("../../services/blob.js");
|
||||||
|
|
||||||
function getAttachmentBlob(req) {
|
function getAttachmentBlob(req) {
|
||||||
const full = req.query.full === 'true';
|
const preview = req.query.preview === 'true';
|
||||||
|
|
||||||
return blobService.getBlobPojo('attachments', req.params.attachmentId, { full });
|
return blobService.getBlobPojo('attachments', req.params.attachmentId, { preview });
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAttachments(req) {
|
function getAttachments(req) {
|
||||||
|
@ -10,9 +10,9 @@ const becca = require("../../becca/becca");
|
|||||||
const blobService = require("../../services/blob.js");
|
const blobService = require("../../services/blob.js");
|
||||||
|
|
||||||
function getNoteRevisionBlob(req) {
|
function getNoteRevisionBlob(req) {
|
||||||
const full = req.query.full === 'true';
|
const preview = req.query.preview === 'true';
|
||||||
|
|
||||||
return blobService.getBlobPojo('note_revisions', req.params.noteRevisionId, { full });
|
return blobService.getBlobPojo('note_revisions', req.params.noteRevisionId, { preview });
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNoteRevisions(req) {
|
function getNoteRevisions(req) {
|
||||||
|
@ -6,7 +6,6 @@ const sql = require('../../services/sql');
|
|||||||
const utils = require('../../services/utils');
|
const utils = require('../../services/utils');
|
||||||
const log = require('../../services/log');
|
const log = require('../../services/log');
|
||||||
const TaskContext = require('../../services/task_context');
|
const TaskContext = require('../../services/task_context');
|
||||||
const fs = require('fs');
|
|
||||||
const becca = require("../../becca/becca");
|
const becca = require("../../becca/becca");
|
||||||
const ValidationError = require("../../errors/validation_error");
|
const ValidationError = require("../../errors/validation_error");
|
||||||
const NotFoundError = require("../../errors/not_found_error");
|
const NotFoundError = require("../../errors/not_found_error");
|
||||||
@ -18,31 +17,27 @@ function getNote(req) {
|
|||||||
throw new NotFoundError(`Note '${req.params.noteId}' has not been found.`);
|
throw new NotFoundError(`Note '${req.params.noteId}' has not been found.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const pojo = note.getPojo();
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
if (note.hasStringContent()) {
|
function getNoteBlob(req) {
|
||||||
pojo.content = note.getContent();
|
const preview = req.query.preview === 'true';
|
||||||
|
|
||||||
// FIXME: use blobs instead
|
return blobService.getBlobPojo('notes', req.params.noteId, { preview });
|
||||||
if (note.type === 'file' && pojo.content.length > 10000) {
|
}
|
||||||
pojo.content = `${pojo.content.substr(0, 10000)}\r\n\r\n... and ${pojo.content.length - 10000} more characters.`;
|
|
||||||
}
|
function getNoteMetadata(req) {
|
||||||
|
const note = becca.getNote(req.params.noteId);
|
||||||
|
if (!note) {
|
||||||
|
throw new NotFoundError(`Note '${req.params.noteId}' has not been found.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const contentMetadata = note.getContentMetadata();
|
const contentMetadata = note.getContentMetadata();
|
||||||
|
|
||||||
pojo.contentLength = contentMetadata.contentLength;
|
return {
|
||||||
|
dateCreated: note.dateCreated,
|
||||||
pojo.combinedUtcDateModified = note.utcDateModified > contentMetadata.utcDateModified ? note.utcDateModified : contentMetadata.utcDateModified;
|
combinedDateModified: note.utcDateModified > contentMetadata.utcDateModified ? note.dateModified : contentMetadata.dateModified
|
||||||
pojo.combinedDateModified = note.utcDateModified > contentMetadata.utcDateModified ? note.dateModified : contentMetadata.dateModified;
|
};
|
||||||
|
|
||||||
return pojo;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNoteBlob(req) {
|
|
||||||
const full = req.query.full === 'true';
|
|
||||||
|
|
||||||
return blobService.getBlobPojo('notes', req.params.noteId, { full });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNote(req) {
|
function createNote(req) {
|
||||||
@ -266,6 +261,7 @@ function convertNoteToAttachment(req) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
getNote,
|
getNote,
|
||||||
getNoteBlob,
|
getNoteBlob,
|
||||||
|
getNoteMetadata,
|
||||||
updateNoteData,
|
updateNoteData,
|
||||||
deleteNote,
|
deleteNote,
|
||||||
undeleteNote,
|
undeleteNote,
|
||||||
|
@ -113,6 +113,7 @@ function register(app) {
|
|||||||
|
|
||||||
apiRoute(GET, '/api/notes/:noteId', notesApiRoute.getNote);
|
apiRoute(GET, '/api/notes/:noteId', notesApiRoute.getNote);
|
||||||
apiRoute(GET, '/api/notes/:noteId/blob', notesApiRoute.getNoteBlob);
|
apiRoute(GET, '/api/notes/:noteId/blob', notesApiRoute.getNoteBlob);
|
||||||
|
apiRoute(GET, '/api/notes/:noteId/metadata', notesApiRoute.getNoteMetadata);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/data', notesApiRoute.updateNoteData);
|
apiRoute(PUT, '/api/notes/:noteId/data', notesApiRoute.updateNoteData);
|
||||||
apiRoute(DEL, '/api/notes/:noteId', notesApiRoute.deleteNote);
|
apiRoute(DEL, '/api/notes/:noteId', notesApiRoute.deleteNote);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/undelete', notesApiRoute.undeleteNote);
|
apiRoute(PUT, '/api/notes/:noteId/undelete', notesApiRoute.undeleteNote);
|
||||||
|
@ -2,7 +2,7 @@ const becca = require('../becca/becca');
|
|||||||
const NotFoundError = require("../errors/not_found_error");
|
const NotFoundError = require("../errors/not_found_error");
|
||||||
|
|
||||||
function getBlobPojo(entityName, entityId, opts = {}) {
|
function getBlobPojo(entityName, entityId, opts = {}) {
|
||||||
opts.full = !!opts.full;
|
opts.preview = !!opts.preview;
|
||||||
|
|
||||||
const entity = becca.getEntity(entityName, entityId);
|
const entity = becca.getEntity(entityName, entityId);
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ function getBlobPojo(entityName, entityId, opts = {}) {
|
|||||||
|
|
||||||
if (!entity.hasStringContent()) {
|
if (!entity.hasStringContent()) {
|
||||||
pojo.content = null;
|
pojo.content = null;
|
||||||
} else if (!opts.full && pojo.content.length > 10000) {
|
} else if (opts.preview && pojo.content.length > 10000) {
|
||||||
pojo.content = `${pojo.content.substr(0, 10000)}\r\n\r\n... and ${pojo.content.length - 10000} more characters.`;
|
pojo.content = `${pojo.content.substr(0, 10000)}\r\n\r\n... and ${pojo.content.length - 10000} more characters.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user