mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	ancillary type widget
This commit is contained in:
		| @@ -146,8 +146,7 @@ class BNoteAncillary extends AbstractBeccaEntity { | ||||
|             isProtected: !!this.isProtected, | ||||
|             contentCheckSum: this.contentCheckSum, | ||||
|             isDeleted: false, | ||||
|             utcDateModified: this.utcDateModified, | ||||
|             content: this.content, | ||||
|             utcDateModified: this.utcDateModified | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -166,14 +166,12 @@ class BNoteRevision extends AbstractBeccaEntity { | ||||
|             utcDateLastEdited: this.utcDateLastEdited, | ||||
|             utcDateCreated: this.utcDateCreated, | ||||
|             utcDateModified: this.utcDateModified, | ||||
|             content: this.content, | ||||
|             contentLength: this.contentLength | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     getPojoToSave() { | ||||
|         const pojo = this.getPojo(); | ||||
|         delete pojo.content; // not getting persisted | ||||
|         delete pojo.contentLength; // not getting persisted | ||||
|  | ||||
|         if (pojo.isProtected) { | ||||
|   | ||||
| @@ -117,11 +117,19 @@ export default class RootCommandExecutor extends Component { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     async showNoteSourceEvent() { | ||||
|     async showNoteSourceCommand() { | ||||
|         const notePath = appContext.tabManager.getActiveContextNotePath(); | ||||
|  | ||||
|         if (notePath) { | ||||
|             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="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="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 class="dropdown-item import-files-button">Import files</a> | ||||
|         <a class="dropdown-item export-note-button">Export note</a> | ||||
|   | ||||
| @@ -12,7 +12,8 @@ export default class MermaidExportButton extends NoteContextAwareWidget { | ||||
|     isEnabled() { | ||||
|         return super.isEnabled() | ||||
|             && this.note?.type === 'mermaid' | ||||
|             && this.note.isContentAvailable(); | ||||
|             && this.note.isContentAvailable() | ||||
|             && this.noteContext?.viewScope.viewMode === 'default'; | ||||
|     } | ||||
|  | ||||
|     doRender() { | ||||
|   | ||||
| @@ -36,7 +36,8 @@ export default class MermaidWidget extends NoteContextAwareWidget { | ||||
|     isEnabled() { | ||||
|         return super.isEnabled() | ||||
|             && this.note?.type === 'mermaid' | ||||
|             && this.note.isContentAvailable(); | ||||
|             && this.note.isContentAvailable() | ||||
|             && this.noteContext?.viewScope.viewMode === 'default'; | ||||
|     } | ||||
|  | ||||
|     doRender() { | ||||
|   | ||||
| @@ -27,6 +27,7 @@ import NoteMapTypeWidget from "./type_widgets/note_map.js"; | ||||
| import WebViewTypeWidget from "./type_widgets/web_view.js"; | ||||
| import DocTypeWidget from "./type_widgets/doc.js"; | ||||
| import ContentWidgetTypeWidget from "./type_widgets/content_widget.js"; | ||||
| import AncillariesTypeWidget from "./type_widgets/ancillaries.js"; | ||||
|  | ||||
| const TPL = ` | ||||
| <div class="note-detail"> | ||||
| @@ -61,7 +62,8 @@ const typeWidgetClasses = { | ||||
|     'noteMap': NoteMapTypeWidget, | ||||
|     'webView': WebViewTypeWidget, | ||||
|     'doc': DocTypeWidget, | ||||
|     'contentWidget': ContentWidgetTypeWidget | ||||
|     'contentWidget': ContentWidgetTypeWidget, | ||||
|     'ancillaries': AncillariesTypeWidget | ||||
| }; | ||||
|  | ||||
| export default class NoteDetailWidget extends NoteContextAwareWidget { | ||||
| @@ -189,6 +191,8 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { | ||||
|  | ||||
|         if (type === 'text' && this.noteContext.viewScope.viewMode === 'source') { | ||||
|             type = 'readOnlyCode'; | ||||
|         } else if (this.noteContext.viewScope.viewMode === 'ancillaries') { | ||||
|             type = 'ancillaries'; | ||||
|         } else if (type === 'text' && await this.noteContext.isReadOnly()) { | ||||
|             type = 'readOnlyText'; | ||||
|         } else if ((type === 'code' || type === 'mermaid') && await this.noteContext.isReadOnly()) { | ||||
|   | ||||
| @@ -460,7 +460,9 @@ export default class TabRowWidget extends BasicWidget { | ||||
|     } | ||||
|  | ||||
|     updateTitle($tab, title) { | ||||
|         $tab.find('.note-tab-title').text(title); | ||||
|         $tab.attr("title", title) | ||||
|         $tab.find('.note-tab-title') | ||||
|             .text(title); | ||||
|     } | ||||
|  | ||||
|     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(); | ||||
| } | ||||
|  | ||||
| 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) { | ||||
|     const {noteId, name} = req.params; | ||||
|     const {mime, content} = req.body; | ||||
| @@ -354,5 +384,6 @@ module.exports = { | ||||
|     getDeleteNotesPreview, | ||||
|     uploadModifiedFile, | ||||
|     forceSaveNoteRevision, | ||||
|     getNoteAncillaries, | ||||
|     saveNoteAncillary | ||||
| }; | ||||
|   | ||||
| @@ -126,6 +126,7 @@ function register(app) { | ||||
|     apiRoute(PUT, '/api/notes/:noteId/sort-children', notesApiRoute.sortChildNotes); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectNote); | ||||
|     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(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions); | ||||
|     apiRoute(DELETE, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.eraseAllNoteRevisions); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user