mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
ancillary type widget
This commit is contained in:
parent
b1e2b5ba8e
commit
520ffecd36
@ -146,8 +146,7 @@ class BNoteAncillary extends AbstractBeccaEntity {
|
|||||||
isProtected: !!this.isProtected,
|
isProtected: !!this.isProtected,
|
||||||
contentCheckSum: this.contentCheckSum,
|
contentCheckSum: this.contentCheckSum,
|
||||||
isDeleted: false,
|
isDeleted: false,
|
||||||
utcDateModified: this.utcDateModified,
|
utcDateModified: this.utcDateModified
|
||||||
content: this.content,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,14 +166,12 @@ class BNoteRevision extends AbstractBeccaEntity {
|
|||||||
utcDateLastEdited: this.utcDateLastEdited,
|
utcDateLastEdited: this.utcDateLastEdited,
|
||||||
utcDateCreated: this.utcDateCreated,
|
utcDateCreated: this.utcDateCreated,
|
||||||
utcDateModified: this.utcDateModified,
|
utcDateModified: this.utcDateModified,
|
||||||
content: this.content,
|
|
||||||
contentLength: this.contentLength
|
contentLength: this.contentLength
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getPojoToSave() {
|
getPojoToSave() {
|
||||||
const pojo = this.getPojo();
|
const pojo = this.getPojo();
|
||||||
delete pojo.content; // not getting persisted
|
|
||||||
delete pojo.contentLength; // not getting persisted
|
delete pojo.contentLength; // not getting persisted
|
||||||
|
|
||||||
if (pojo.isProtected) {
|
if (pojo.isProtected) {
|
||||||
|
@ -117,11 +117,19 @@ export default class RootCommandExecutor extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async showNoteSourceEvent() {
|
async showNoteSourceCommand() {
|
||||||
const notePath = appContext.tabManager.getActiveContextNotePath();
|
const notePath = appContext.tabManager.getActiveContextNotePath();
|
||||||
|
|
||||||
if (notePath) {
|
if (notePath) {
|
||||||
await appContext.tabManager.openContextWithNote(notePath, { activate: true, viewMode: 'source' });
|
await appContext.tabManager.openContextWithNote(notePath, { activate: true, viewMode: 'source' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async showNoteAncillariesCommand() {
|
||||||
|
const notePath = appContext.tabManager.getActiveContextNotePath();
|
||||||
|
|
||||||
|
if (notePath) {
|
||||||
|
await appContext.tabManager.openContextWithNote(notePath, { activate: true, viewMode: 'ancillaries' });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ const TPL = `
|
|||||||
<a data-trigger-command="renderActiveNote" class="dropdown-item render-note-button"><kbd data-command="renderActiveNote"></kbd> Re-render note</a>
|
<a data-trigger-command="renderActiveNote" class="dropdown-item render-note-button"><kbd data-command="renderActiveNote"></kbd> Re-render note</a>
|
||||||
<a data-trigger-command="findInText" class="dropdown-item find-in-text-button">Search in note <kbd data-command="findInText"></a>
|
<a data-trigger-command="findInText" class="dropdown-item find-in-text-button">Search in note <kbd data-command="findInText"></a>
|
||||||
<a data-trigger-command="showNoteSource" class="dropdown-item show-source-button"><kbd data-command="showNoteSource"></kbd> Note source</a>
|
<a data-trigger-command="showNoteSource" class="dropdown-item show-source-button"><kbd data-command="showNoteSource"></kbd> Note source</a>
|
||||||
|
<a data-trigger-command="showNoteAncillaries" class="dropdown-item show-source-button"><kbd data-command="showNoteAncillaries"></kbd> Note ancillaries</a>
|
||||||
<a data-trigger-command="openNoteExternally" class="dropdown-item open-note-externally-button"><kbd data-command="openNoteExternally"></kbd> Open note externally</a>
|
<a data-trigger-command="openNoteExternally" class="dropdown-item open-note-externally-button"><kbd data-command="openNoteExternally"></kbd> Open note externally</a>
|
||||||
<a class="dropdown-item import-files-button">Import files</a>
|
<a class="dropdown-item import-files-button">Import files</a>
|
||||||
<a class="dropdown-item export-note-button">Export note</a>
|
<a class="dropdown-item export-note-button">Export note</a>
|
||||||
|
@ -12,7 +12,8 @@ export default class MermaidExportButton extends NoteContextAwareWidget {
|
|||||||
isEnabled() {
|
isEnabled() {
|
||||||
return super.isEnabled()
|
return super.isEnabled()
|
||||||
&& this.note?.type === 'mermaid'
|
&& this.note?.type === 'mermaid'
|
||||||
&& this.note.isContentAvailable();
|
&& this.note.isContentAvailable()
|
||||||
|
&& this.noteContext?.viewScope.viewMode === 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
|
@ -36,7 +36,8 @@ export default class MermaidWidget extends NoteContextAwareWidget {
|
|||||||
isEnabled() {
|
isEnabled() {
|
||||||
return super.isEnabled()
|
return super.isEnabled()
|
||||||
&& this.note?.type === 'mermaid'
|
&& this.note?.type === 'mermaid'
|
||||||
&& this.note.isContentAvailable();
|
&& this.note.isContentAvailable()
|
||||||
|
&& this.noteContext?.viewScope.viewMode === 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
|
@ -27,6 +27,7 @@ import NoteMapTypeWidget from "./type_widgets/note_map.js";
|
|||||||
import WebViewTypeWidget from "./type_widgets/web_view.js";
|
import WebViewTypeWidget from "./type_widgets/web_view.js";
|
||||||
import DocTypeWidget from "./type_widgets/doc.js";
|
import DocTypeWidget from "./type_widgets/doc.js";
|
||||||
import ContentWidgetTypeWidget from "./type_widgets/content_widget.js";
|
import ContentWidgetTypeWidget from "./type_widgets/content_widget.js";
|
||||||
|
import AncillariesTypeWidget from "./type_widgets/ancillaries.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="note-detail">
|
<div class="note-detail">
|
||||||
@ -61,7 +62,8 @@ const typeWidgetClasses = {
|
|||||||
'noteMap': NoteMapTypeWidget,
|
'noteMap': NoteMapTypeWidget,
|
||||||
'webView': WebViewTypeWidget,
|
'webView': WebViewTypeWidget,
|
||||||
'doc': DocTypeWidget,
|
'doc': DocTypeWidget,
|
||||||
'contentWidget': ContentWidgetTypeWidget
|
'contentWidget': ContentWidgetTypeWidget,
|
||||||
|
'ancillaries': AncillariesTypeWidget
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class NoteDetailWidget extends NoteContextAwareWidget {
|
export default class NoteDetailWidget extends NoteContextAwareWidget {
|
||||||
@ -189,6 +191,8 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
|
|||||||
|
|
||||||
if (type === 'text' && this.noteContext.viewScope.viewMode === 'source') {
|
if (type === 'text' && this.noteContext.viewScope.viewMode === 'source') {
|
||||||
type = 'readOnlyCode';
|
type = 'readOnlyCode';
|
||||||
|
} else if (this.noteContext.viewScope.viewMode === 'ancillaries') {
|
||||||
|
type = 'ancillaries';
|
||||||
} else if (type === 'text' && await this.noteContext.isReadOnly()) {
|
} else if (type === 'text' && await this.noteContext.isReadOnly()) {
|
||||||
type = 'readOnlyText';
|
type = 'readOnlyText';
|
||||||
} else if ((type === 'code' || type === 'mermaid') && await this.noteContext.isReadOnly()) {
|
} else if ((type === 'code' || type === 'mermaid') && await this.noteContext.isReadOnly()) {
|
||||||
|
@ -460,7 +460,9 @@ export default class TabRowWidget extends BasicWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateTitle($tab, title) {
|
updateTitle($tab, title) {
|
||||||
$tab.find('.note-tab-title').text(title);
|
$tab.attr("title", title)
|
||||||
|
$tab.find('.note-tab-title')
|
||||||
|
.text(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTabById(ntxId) {
|
getTabById(ntxId) {
|
||||||
|
79
src/public/app/widgets/type_widgets/ancillaries.js
Normal file
79
src/public/app/widgets/type_widgets/ancillaries.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import TypeWidget from "./type_widget.js";
|
||||||
|
import server from "../../services/server.js";
|
||||||
|
|
||||||
|
const TPL = `
|
||||||
|
<div class="note-ancillaries note-detail-printable">
|
||||||
|
<style>
|
||||||
|
.note-ancillaries {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ancillary-content {
|
||||||
|
max-height: 400px;
|
||||||
|
background: var(--accented-background-color);
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ancillary-details th {
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="alert alert-info" style="margin: 10px 0 10px 0; padding: 20px;">
|
||||||
|
Note ancillaries are pieces of data attached to a given note, providing ancillary support.
|
||||||
|
This view is useful for diagnostics.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="note-ancillary-list"></div>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
export default class AncillariesTypeWidget extends TypeWidget {
|
||||||
|
static getType() { return "ancillaries"; }
|
||||||
|
|
||||||
|
doRender() {
|
||||||
|
this.$widget = $(TPL);
|
||||||
|
this.$list = this.$widget.find('.note-ancillary-list');
|
||||||
|
|
||||||
|
super.doRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
async doRefresh(note) {
|
||||||
|
this.$list.empty();
|
||||||
|
|
||||||
|
const ancillaries = await server.get(`notes/${this.noteId}/ancillaries?includeContent=true`);
|
||||||
|
|
||||||
|
if (ancillaries.length === 0) {
|
||||||
|
this.$list.html("<strong>This note has no ancillaries.</strong>");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ancillary of ancillaries) {
|
||||||
|
this.$list.append(
|
||||||
|
$('<div class="note-ancillary-wrapper">')
|
||||||
|
.append(
|
||||||
|
$('<h4>').append($('<span class="ancillary-name">').text(ancillary.name))
|
||||||
|
)
|
||||||
|
.append(
|
||||||
|
$('<table class="ancillary-details">')
|
||||||
|
.append(
|
||||||
|
$('<tr>')
|
||||||
|
.append($('<th>').text('Length:'))
|
||||||
|
.append($('<td>').text(ancillary.contentLength))
|
||||||
|
.append($('<th>').text('MIME:'))
|
||||||
|
.append($('<td>').text(ancillary.mime))
|
||||||
|
.append($('<th>').text('Date modified:'))
|
||||||
|
.append($('<td>').text(ancillary.utcDateModified))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.append(
|
||||||
|
$('<pre class="ancillary-content">')
|
||||||
|
.text(ancillary.content)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -127,6 +127,36 @@ function setNoteTypeMime(req) {
|
|||||||
note.save();
|
note.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getNoteAncillaries(req) {
|
||||||
|
const includeContent = req.query.includeContent === 'true';
|
||||||
|
const {noteId} = req.params;
|
||||||
|
|
||||||
|
const note = becca.getNote(noteId);
|
||||||
|
|
||||||
|
if (!note) {
|
||||||
|
throw new NotFoundError(`Note '${noteId}' doesn't exist.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const noteAncillaries = note.getNoteAncillaries();
|
||||||
|
|
||||||
|
return noteAncillaries.map(ancillary => {
|
||||||
|
const pojo = ancillary.getPojo();
|
||||||
|
|
||||||
|
if (includeContent && utils.isStringNote(null, ancillary.mime)) {
|
||||||
|
pojo.content = ancillary.getContent()?.toString();
|
||||||
|
pojo.contentLength = pojo.content.length;
|
||||||
|
|
||||||
|
const MAX_ANCILLARY_LENGTH = 1_000_000;
|
||||||
|
|
||||||
|
if (pojo.content.length > MAX_ANCILLARY_LENGTH) {
|
||||||
|
pojo.content = pojo.content.substring(0, MAX_ANCILLARY_LENGTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pojo;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function saveNoteAncillary(req) {
|
function saveNoteAncillary(req) {
|
||||||
const {noteId, name} = req.params;
|
const {noteId, name} = req.params;
|
||||||
const {mime, content} = req.body;
|
const {mime, content} = req.body;
|
||||||
@ -354,5 +384,6 @@ module.exports = {
|
|||||||
getDeleteNotesPreview,
|
getDeleteNotesPreview,
|
||||||
uploadModifiedFile,
|
uploadModifiedFile,
|
||||||
forceSaveNoteRevision,
|
forceSaveNoteRevision,
|
||||||
|
getNoteAncillaries,
|
||||||
saveNoteAncillary
|
saveNoteAncillary
|
||||||
};
|
};
|
||||||
|
@ -126,6 +126,7 @@ function register(app) {
|
|||||||
apiRoute(PUT, '/api/notes/:noteId/sort-children', notesApiRoute.sortChildNotes);
|
apiRoute(PUT, '/api/notes/:noteId/sort-children', notesApiRoute.sortChildNotes);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectNote);
|
apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectNote);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/type', notesApiRoute.setNoteTypeMime);
|
apiRoute(PUT, '/api/notes/:noteId/type', notesApiRoute.setNoteTypeMime);
|
||||||
|
apiRoute(GET, '/api/notes/:noteId/ancillaries', notesApiRoute.getNoteAncillaries);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/ancillaries/:name', notesApiRoute.saveNoteAncillary);
|
apiRoute(PUT, '/api/notes/:noteId/ancillaries/:name', notesApiRoute.saveNoteAncillary);
|
||||||
apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions);
|
apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions);
|
||||||
apiRoute(DELETE, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.eraseAllNoteRevisions);
|
apiRoute(DELETE, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.eraseAllNoteRevisions);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user