mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 03:29:02 +01:00 
			
		
		
		
	drag & drop multi file upload to note tree
This commit is contained in:
		
							parent
							
								
									b25deea21d
								
							
						
					
					
						commit
						936f85c09e
					
				| @ -13,6 +13,8 @@ const LABEL_DEFINITION = 'label-definition'; | |||||||
| const RELATION = 'relation'; | const RELATION = 'relation'; | ||||||
| const RELATION_DEFINITION = 'relation-definition'; | const RELATION_DEFINITION = 'relation-definition'; | ||||||
| 
 | 
 | ||||||
|  | const STRING_MIME_TYPES = ["application/x-javascript"]; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * This represents a Note which is a central object in the Trilium Notes project. |  * This represents a Note which is a central object in the Trilium Notes project. | ||||||
|  * |  * | ||||||
| @ -132,7 +134,9 @@ class Note extends Entity { | |||||||
| 
 | 
 | ||||||
|     /** @returns {boolean} true if the note has string content (not binary) */ |     /** @returns {boolean} true if the note has string content (not binary) */ | ||||||
|     isStringNote() { |     isStringNote() { | ||||||
|         return ["text", "code", "relation-map", "search"].includes(this.type) || this.mime.startsWith('text/'); |         return ["text", "code", "relation-map", "search"].includes(this.type) | ||||||
|  |             || this.mime.startsWith('text/') | ||||||
|  |             || STRING_MIME_TYPES.includes(this.mime); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** @returns {string} JS script environment - either "frontend" or "backend" */ |     /** @returns {string} JS script environment - either "frontend" or "backend" */ | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| import treeService from './tree.js'; | import treeService from './tree.js'; | ||||||
| import treeChangesService from './branches.js'; | import treeChangesService from './branches.js'; | ||||||
|  | import fileService from '../services/file.js'; | ||||||
| 
 | 
 | ||||||
| const dragAndDropSetup = { | const dragAndDropSetup = { | ||||||
|     autoExpandMS: 600, |     autoExpandMS: 600, | ||||||
| @ -32,23 +33,28 @@ const dragAndDropSetup = { | |||||||
|         return true; |         return true; | ||||||
|     }, |     }, | ||||||
|     dragEnter: (node, data) => true, // allow drop on any node
 |     dragEnter: (node, data) => true, // allow drop on any node
 | ||||||
|  |     dragOver: (node, data) => true, | ||||||
|     dragDrop: (node, data) => { |     dragDrop: (node, data) => { | ||||||
|         // This function MUST be defined to enable dropping of items on the tree.
 |         const dataTransfer = data.dataTransfer; | ||||||
|         // data.hitMode is 'before', 'after', or 'over'.
 |  | ||||||
| 
 | 
 | ||||||
|         const selectedNodes = treeService.getSelectedNodes(); |         if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { | ||||||
| 
 |             fileService.uploadFiles(node.data.noteId, dataTransfer.files); | ||||||
|         if (data.hitMode === "before") { |  | ||||||
|             treeChangesService.moveBeforeNode(selectedNodes, node); |  | ||||||
|         } |  | ||||||
|         else if (data.hitMode === "after") { |  | ||||||
|             treeChangesService.moveAfterNode(selectedNodes, node); |  | ||||||
|         } |  | ||||||
|         else if (data.hitMode === "over") { |  | ||||||
|             treeChangesService.moveToNode(selectedNodes, node); |  | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             throw new Error("Unknown hitMode=" + data.hitMode); |             // This function MUST be defined to enable dropping of items on the tree.
 | ||||||
|  |             // data.hitMode is 'before', 'after', or 'over'.
 | ||||||
|  | 
 | ||||||
|  |             const selectedNodes = treeService.getSelectedNodes(); | ||||||
|  | 
 | ||||||
|  |             if (data.hitMode === "before") { | ||||||
|  |                 treeChangesService.moveBeforeNode(selectedNodes, node); | ||||||
|  |             } else if (data.hitMode === "after") { | ||||||
|  |                 treeChangesService.moveAfterNode(selectedNodes, node); | ||||||
|  |             } else if (data.hitMode === "over") { | ||||||
|  |                 treeChangesService.moveToNode(selectedNodes, node); | ||||||
|  |             } else { | ||||||
|  |                 throw new Error("Unknown hitMode=" + data.hitMode); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -161,7 +161,7 @@ function registerEntrypoints() { | |||||||
| 
 | 
 | ||||||
|     $("#note-title").bind('keydown', 'return', () => $("#note-detail-text").focus()); |     $("#note-title").bind('keydown', 'return', () => $("#note-detail-text").focus()); | ||||||
| 
 | 
 | ||||||
|     $("#upload-file-button").click(fileService.uploadFile); |     $("#upload-file-button").click(fileService.openUploadFileDialog); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export default { | export default { | ||||||
|  | |||||||
| @ -2,32 +2,46 @@ import noteDetailService from "./note_detail.js"; | |||||||
| import treeService from "./tree.js"; | import treeService from "./tree.js"; | ||||||
| import server from "./server.js"; | import server from "./server.js"; | ||||||
| 
 | 
 | ||||||
| function uploadFile() { | function openUploadFileDialog() { | ||||||
|     $("#file-upload").trigger('click'); |     $("#file-upload").trigger('click'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | async function uploadFiles(parentNoteId, files) { | ||||||
|  |     let noteId; | ||||||
|  | 
 | ||||||
|  |     for (const file of files) { | ||||||
|  |         const formData = new FormData(); | ||||||
|  |         formData.append('upload', file); | ||||||
|  | 
 | ||||||
|  |         const resp = await $.ajax({ | ||||||
|  |             url: baseApiUrl + 'notes/' + parentNoteId + '/upload', | ||||||
|  |             headers: server.getHeaders(), | ||||||
|  |             data: formData, | ||||||
|  |             type: 'POST', | ||||||
|  |             contentType: false, // NEEDED, DON'T OMIT THIS
 | ||||||
|  |             processData: false, // NEEDED, DON'T OMIT THIS
 | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         noteId = resp.noteId; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     await treeService.reload(); | ||||||
|  | 
 | ||||||
|  |     await treeService.activateNote(noteId); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| $("#file-upload").change(async function() { | $("#file-upload").change(async function() { | ||||||
|     const formData = new FormData(); |     const files = Array.from(this.files); // clone since we'll reset it just below
 | ||||||
|     formData.append('upload', this.files[0]); |  | ||||||
| 
 | 
 | ||||||
|     // this is done to reset the field otherwise triggering import same file again would not work
 |     // this is done to reset the field otherwise triggering import same file again would not work
 | ||||||
|     // https://github.com/zadam/trilium/issues/388
 |     // https://github.com/zadam/trilium/issues/388
 | ||||||
|     $("#file-upload").val(''); |     $("#file-upload").val(''); | ||||||
| 
 | 
 | ||||||
|     const resp = await $.ajax({ |     const parentNoteId = noteDetailService.getCurrentNoteId(); | ||||||
|         url: baseApiUrl + 'notes/' + noteDetailService.getCurrentNoteId() + '/upload', |     await uploadFiles(parentNoteId, files); | ||||||
|         headers: server.getHeaders(), |  | ||||||
|         data: formData, |  | ||||||
|         type: 'POST', |  | ||||||
|         contentType: false, // NEEDED, DON'T OMIT THIS
 |  | ||||||
|         processData: false, // NEEDED, DON'T OMIT THIS
 |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     await treeService.reload(); |  | ||||||
| 
 |  | ||||||
|     await treeService.activateNote(resp.noteId); |  | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| export default { | export default { | ||||||
|     uploadFile |     openUploadFileDialog, | ||||||
|  |     uploadFiles | ||||||
| } | } | ||||||
| @ -27,8 +27,13 @@ async function show() { | |||||||
|     $fileSize.text((attributeMap.fileSize || "?") + " bytes"); |     $fileSize.text((attributeMap.fileSize || "?") + " bytes"); | ||||||
|     $fileType.text(currentNote.mime); |     $fileType.text(currentNote.mime); | ||||||
| 
 | 
 | ||||||
|     $previewRow.toggle(!!currentNote.noteContent.content); |     if (currentNote.noteContent && currentNote.noteContent.content) { | ||||||
|     $previewContent.text(currentNote.noteContent.content); |         $previewRow.show(); | ||||||
|  |         $previewContent.text(currentNote.noteContent.content); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         $previewRow.hide(); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| $downloadButton.click(() => utils.download(getFileUrl())); | $downloadButton.click(() => utils.download(getFileUrl())); | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								src/public/libraries/ckeditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/public/libraries/ckeditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -9,7 +9,7 @@ | |||||||
|         <div id="note-detail-text" class="note-detail-component" tabindex="10000"></div> |         <div id="note-detail-text" class="note-detail-component" tabindex="10000"></div> | ||||||
| 
 | 
 | ||||||
|         <div id="note-detail-code" class="note-detail-component"></div> |         <div id="note-detail-code" class="note-detail-component"></div> | ||||||
|         <input type="file" id="file-upload" style="display: none" /> |         <input type="file" id="file-upload" multiple style="display: none" /> | ||||||
| 
 | 
 | ||||||
|         <% include search.ejs %> |         <% include search.ejs %> | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam