| 
									
										
										
										
											2018-03-27 22:42:46 -04:00
										 |  |  | import libraryLoader from "./library_loader.js"; | 
					
						
							| 
									
										
										
										
											2018-11-15 14:51:09 +01:00
										 |  |  | import treeService from './tree.js'; | 
					
						
							| 
									
										
										
										
											2019-11-06 22:58:32 +01:00
										 |  |  | import noteAutocompleteService from './note_autocomplete.js'; | 
					
						
							| 
									
										
										
										
											2019-12-04 21:21:07 +01:00
										 |  |  | import mimeTypesService from './mime_types.js'; | 
					
						
							| 
									
										
										
										
											2018-03-27 00:22:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 20:09:55 +01:00
										 |  |  | const mentionSetup = { | 
					
						
							|  |  |  |     feeds: [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             marker: '@', | 
					
						
							|  |  |  |             feed: queryText => { | 
					
						
							|  |  |  |                 return new Promise((res, rej) => { | 
					
						
							|  |  |  |                     noteAutocompleteService.autocompleteSource(queryText, rows => { | 
					
						
							|  |  |  |                         if (rows.length === 1 && rows[0].title === 'No results') { | 
					
						
							|  |  |  |                             rows = []; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         for (const row of rows) { | 
					
						
							|  |  |  |                             row.text = row.name = row.noteTitle; | 
					
						
							|  |  |  |                             row.id = '@' + row.text; | 
					
						
							|  |  |  |                             row.link = '#' + row.path; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         res(rows); | 
					
						
							|  |  |  |                     }); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             itemRenderer: item => { | 
					
						
							|  |  |  |                 const itemElement = document.createElement('span'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 itemElement.classList.add('mentions-item'); | 
					
						
							|  |  |  |                 itemElement.innerHTML = `${item.highlightedTitle} `; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 return itemElement; | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             minimumCharacters: 0 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  | class NoteDetailText { | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2019-05-08 19:55:24 +02:00
										 |  |  |      * @param {TabContext} ctx | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     constructor(ctx) { | 
					
						
							| 
									
										
										
										
											2019-05-01 23:06:18 +02:00
										 |  |  |         this.ctx = ctx; | 
					
						
							| 
									
										
										
										
											2019-05-08 19:55:24 +02:00
										 |  |  |         this.$component = ctx.$tabContent.find('.note-detail-text'); | 
					
						
							| 
									
										
										
										
											2019-06-30 19:41:26 +02:00
										 |  |  |         this.$editorEl = this.$component.find('.note-detail-text-editor'); | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |         this.textEditor = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.$component.on("dblclick", "img", e => { | 
					
						
							|  |  |  |             const $img = $(e.target); | 
					
						
							|  |  |  |             const src = $img.prop("src"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const match = src.match(/\/api\/images\/([A-Za-z0-9]+)\//); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (match) { | 
					
						
							|  |  |  |                 const noteId = match[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 treeService.activateNote(noteId); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 window.open(src, '_blank'); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-12-29 23:46:40 +01:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-27 00:22:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-12 12:58:55 +02:00
										 |  |  |     async render() { | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |         if (!this.textEditor) { | 
					
						
							|  |  |  |             await libraryLoader.requireLibrary(libraryLoader.CKEDITOR); | 
					
						
							| 
									
										
										
										
											2018-03-27 00:22:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 20:06:36 +01:00
										 |  |  |             const codeBlockLanguages = | 
					
						
							|  |  |  |                 (await mimeTypesService.getMimeTypes()) | 
					
						
							|  |  |  |                     .filter(mt => mt.enabled) | 
					
						
							|  |  |  |                     .map(mt => { | 
					
						
							|  |  |  |                         return { | 
					
						
							|  |  |  |                             language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"), | 
					
						
							|  |  |  |                             label: mt.title | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |             // CKEditor since version 12 needs the element to be visible before initialization. At the same time
 | 
					
						
							|  |  |  |             // we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
 | 
					
						
							|  |  |  |             // display of $component in both branches.
 | 
					
						
							|  |  |  |             this.$component.show(); | 
					
						
							| 
									
										
										
										
											2019-03-04 22:36:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |             // textEditor might have been initialized during previous await so checking again
 | 
					
						
							|  |  |  |             // looks like double initialization can freeze CKEditor pretty badly
 | 
					
						
							|  |  |  |             if (!this.textEditor) { | 
					
						
							| 
									
										
										
										
											2019-06-30 19:41:26 +02:00
										 |  |  |                 this.textEditor = await BalloonEditor.create(this.$editorEl[0], { | 
					
						
							| 
									
										
										
										
											2019-11-06 22:58:32 +01:00
										 |  |  |                     placeholder: "Type the content of your note here ...", | 
					
						
							| 
									
										
										
										
											2019-12-09 20:09:55 +01:00
										 |  |  |                     mention: mentionSetup, | 
					
						
							| 
									
										
										
										
											2019-12-04 21:21:07 +01:00
										 |  |  |                     codeBlock: { | 
					
						
							|  |  |  |                         languages: codeBlockLanguages | 
					
						
							| 
									
										
										
										
											2019-11-06 22:58:32 +01:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2018-03-27 00:22:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-29 23:46:40 +01:00
										 |  |  |                 if (glob.isDev) { | 
					
						
							|  |  |  |                     await import('../../libraries/ckeditor/inspector.js'); | 
					
						
							|  |  |  |                     CKEditorInspector.attach(this.textEditor); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-04 14:34:03 +02:00
										 |  |  |                 this.onNoteChange(() => this.ctx.noteChanged()); | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-08-28 15:03:23 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-03-27 00:22:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 22:35:24 +01:00
										 |  |  |         // lazy loading above can take time and tab might have been already switched to another note
 | 
					
						
							|  |  |  |         if (this.ctx.note && this.ctx.note.type === 'text') { | 
					
						
							|  |  |  |             this.textEditor.isReadOnly = await this.isReadOnly(); | 
					
						
							| 
									
										
										
										
											2018-03-27 00:22:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 22:35:24 +01:00
										 |  |  |             this.$component.show(); | 
					
						
							| 
									
										
										
										
											2018-03-27 00:22:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 22:35:24 +01:00
										 |  |  |             this.textEditor.setData(this.ctx.note.content); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-03-27 00:22:02 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |     getContent() { | 
					
						
							|  |  |  |         let content = this.textEditor.getData(); | 
					
						
							| 
									
										
										
										
											2018-03-27 00:22:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |         // if content is only tags/whitespace (typically <p> </p>), then just make it empty
 | 
					
						
							|  |  |  |         // this is important when setting new note to code
 | 
					
						
							|  |  |  |         if (jQuery(content).text().trim() === '' && !content.includes("<img")) { | 
					
						
							|  |  |  |             content = ''; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-01-27 13:10:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |         return content; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-01-27 13:10:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |     async isReadOnly() { | 
					
						
							| 
									
										
										
										
											2019-05-04 22:44:25 +02:00
										 |  |  |         const attributes = await this.ctx.attributes.getAttributes(); | 
					
						
							| 
									
										
										
										
											2018-03-27 00:22:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |         return attributes.some(attr => attr.type === 'label' && attr.name === 'readOnly'); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-27 00:22:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |     focus() { | 
					
						
							| 
									
										
										
										
											2019-11-09 17:45:22 +01:00
										 |  |  |         this.$editorEl.trigger('focus'); | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-03 16:05:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-25 19:11:42 +02:00
										 |  |  |     show() {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |     getEditor() { | 
					
						
							|  |  |  |         return this.textEditor; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-15 14:51:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |     onNoteChange(func) { | 
					
						
							|  |  |  |         this.textEditor.model.document.on('change:data', func); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-15 14:51:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  |     cleanup() { | 
					
						
							|  |  |  |         if (this.textEditor) { | 
					
						
							|  |  |  |             this.textEditor.setData(''); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-11-15 14:51:09 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     scrollToTop() { | 
					
						
							|  |  |  |         this.$component.scrollTop(0); | 
					
						
							| 
									
										
										
										
											2018-11-15 14:51:09 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-05-01 22:19:29 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default NoteDetailText |