mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 04:51:31 +08:00 
			
		
		
		
	Merge branch 'stable'
This commit is contained in:
		
						commit
						05d2f4fe96
					
				
							
								
								
									
										1
									
								
								db/migrations/0214__fix_root_children_ordering.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								db/migrations/0214__fix_root_children_ordering.sql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | UPDATE branches SET notePosition = notePosition - 999899999 WHERE parentNoteId = 'root' AND notePosition > 999999999; | ||||||
							
								
								
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,12 +1,12 @@ | |||||||
| { | { | ||||||
|   "name": "trilium", |   "name": "trilium", | ||||||
|   "version": "0.60.2-beta", |   "version": "0.60.4", | ||||||
|   "lockfileVersion": 2, |   "lockfileVersion": 2, | ||||||
|   "requires": true, |   "requires": true, | ||||||
|   "packages": { |   "packages": { | ||||||
|     "": { |     "": { | ||||||
|       "name": "trilium", |       "name": "trilium", | ||||||
|       "version": "0.60.2-beta", |       "version": "0.60.4", | ||||||
|       "hasInstallScript": true, |       "hasInstallScript": true, | ||||||
|       "license": "AGPL-3.0-only", |       "license": "AGPL-3.0-only", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
|   "name": "trilium", |   "name": "trilium", | ||||||
|   "productName": "Trilium Notes", |   "productName": "Trilium Notes", | ||||||
|   "description": "Trilium Notes", |   "description": "Trilium Notes", | ||||||
|   "version": "0.60.2-beta", |   "version": "0.60.4", | ||||||
|   "license": "AGPL-3.0-only", |   "license": "AGPL-3.0-only", | ||||||
|   "main": "electron.js", |   "main": "electron.js", | ||||||
|   "bin": { |   "bin": { | ||||||
|  | |||||||
| @ -33,13 +33,7 @@ paths: | |||||||
|           content: |           content: | ||||||
|             application/json; charset=utf-8: |             application/json; charset=utf-8: | ||||||
|               schema: |               schema: | ||||||
|                 properties: |                 $ref: '#/components/schemas/NoteWithBranch' | ||||||
|                   note: |  | ||||||
|                     $ref: '#/components/schemas/Note' |  | ||||||
|                     description: Created note |  | ||||||
|                   branch: |  | ||||||
|                     $ref: '#/components/schemas/Branch' |  | ||||||
|                     description: Created branch |  | ||||||
|         default: |         default: | ||||||
|           description: unexpected error |           description: unexpected error | ||||||
|           content: |           content: | ||||||
| @ -291,6 +285,29 @@ paths: | |||||||
|             application/json; charset=utf-8: |             application/json; charset=utf-8: | ||||||
|               schema: |               schema: | ||||||
|                 $ref: '#/components/schemas/Error' |                 $ref: '#/components/schemas/Error' | ||||||
|  |   /notes/{noteId}/import: | ||||||
|  |     parameters: | ||||||
|  |       - name: noteId | ||||||
|  |         in: path | ||||||
|  |         required: true | ||||||
|  |         schema: | ||||||
|  |           $ref: '#/components/schemas/EntityId' | ||||||
|  |     post: | ||||||
|  |       description: Imports ZIP file into a given note. | ||||||
|  |       operationId: importZip | ||||||
|  |       responses: | ||||||
|  |         '201': | ||||||
|  |           description: note created | ||||||
|  |           content: | ||||||
|  |             application/json; charset=utf-8: | ||||||
|  |               schema: | ||||||
|  |                 $ref: '#/components/schemas/NoteWithBranch' | ||||||
|  |         default: | ||||||
|  |           description: unexpected error | ||||||
|  |           content: | ||||||
|  |             application/json; charset=utf-8: | ||||||
|  |               schema: | ||||||
|  |                 $ref: '#/components/schemas/Error' | ||||||
|   /notes/{noteId}/note-revision: |   /notes/{noteId}/note-revision: | ||||||
|     parameters: |     parameters: | ||||||
|       - name: noteId |       - name: noteId | ||||||
| @ -852,6 +869,13 @@ components: | |||||||
|         utcDateModified: |         utcDateModified: | ||||||
|           $ref: '#/components/schemas/UtcDateTime' |           $ref: '#/components/schemas/UtcDateTime' | ||||||
|           readOnly: true |           readOnly: true | ||||||
|  |     NoteWithBranch: | ||||||
|  |       type: object | ||||||
|  |       properties: | ||||||
|  |         note: | ||||||
|  |           $ref: '#/components/schemas/Note' | ||||||
|  |         branch: | ||||||
|  |           $ref: '#/components/schemas/Branch' | ||||||
|     Attribute: |     Attribute: | ||||||
|       type: object |       type: object | ||||||
|       description: Attribute (Label, Relation) is a key-value record attached to a note. |       description: Attribute (Label, Relation) is a key-value record attached to a note. | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ const v = require("./validators"); | |||||||
| const searchService = require("../services/search/services/search"); | const searchService = require("../services/search/services/search"); | ||||||
| const SearchContext = require("../services/search/search_context"); | const SearchContext = require("../services/search/search_context"); | ||||||
| const zipExportService = require("../services/export/zip"); | const zipExportService = require("../services/export/zip"); | ||||||
|  | const zipImportService = require("../services/import/zip"); | ||||||
| 
 | 
 | ||||||
| function register(router) { | function register(router) { | ||||||
|     eu.route(router, 'get', '/etapi/notes', (req, res, next) => { |     eu.route(router, 'get', '/etapi/notes', (req, res, next) => { | ||||||
| @ -141,11 +142,21 @@ function register(router) { | |||||||
|         // (e.g. branchIds are not seen in UI), that we export "note export" instead.
 |         // (e.g. branchIds are not seen in UI), that we export "note export" instead.
 | ||||||
|         const branch = note.getParentBranches()[0]; |         const branch = note.getParentBranches()[0]; | ||||||
| 
 | 
 | ||||||
|         console.log(note.getParentBranches()); |  | ||||||
| 
 |  | ||||||
|         zipExportService.exportToZip(taskContext, branch, format, res); |         zipExportService.exportToZip(taskContext, branch, format, res); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     eu.route(router, 'post' ,'/etapi/notes/:noteId/import', (req, res, next) => { | ||||||
|  |         const note = eu.getAndCheckNote(req.params.noteId); | ||||||
|  |         const taskContext = new TaskContext('no-progress-reporting'); | ||||||
|  | 
 | ||||||
|  |         zipImportService.importZip(taskContext, req.body, note).then(importedNote => { | ||||||
|  |             res.status(201).json({ | ||||||
|  |                 note: mappers.mapNoteToPojo(importedNote), | ||||||
|  |                 branch: mappers.mapBranchToPojo(importedNote.getBranches()[0]), | ||||||
|  |             }); | ||||||
|  |         }); // we need better error handling here, async errors won't be properly processed.
 | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|     eu.route(router, 'post' ,'/etapi/notes/:noteId/note-revision', (req, res, next) => { |     eu.route(router, 'post' ,'/etapi/notes/:noteId/note-revision', (req, res, next) => { | ||||||
|         const note = eu.getAndCheckNote(req.params.noteId); |         const note = eu.getAndCheckNote(req.params.noteId); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -230,6 +230,15 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     async runActiveNoteCommand(params) { | ||||||
|  |         if (this.isNoteContext(params.ntxId)) { | ||||||
|  |             // make sure that script is saved before running it #4028
 | ||||||
|  |             await this.spacedUpdate.updateNowIfNecessary(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return await this.parent.triggerCommand('runActiveNote', params); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     async printActiveNoteEvent() { |     async printActiveNoteEvent() { | ||||||
|         if (!this.noteContext.isActive()) { |         if (!this.noteContext.isActive()) { | ||||||
|             return; |             return; | ||||||
|  | |||||||
| @ -93,11 +93,11 @@ export default class NoteIconWidget extends NoteContextAwareWidget { | |||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         this.$iconCategory = this.$widget.find("select[name='icon-category']"); |         this.$iconCategory = this.$widget.find("select[name='icon-category']"); | ||||||
|         this.$iconCategory.on('change', () => this.renderFilteredDropdown()); |         this.$iconCategory.on('change', () => this.renderDropdown()); | ||||||
|         this.$iconCategory.on('click', e => e.stopPropagation()); |         this.$iconCategory.on('click', e => e.stopPropagation()); | ||||||
| 
 | 
 | ||||||
|         this.$iconSearch = this.$widget.find("input[name='icon-search']"); |         this.$iconSearch = this.$widget.find("input[name='icon-search']"); | ||||||
|         this.$iconSearch.on('input', () => this.renderFilteredDropdown()); |         this.$iconSearch.on('input', () => this.renderDropdown()); | ||||||
| 
 | 
 | ||||||
|         this.$notePathList = this.$widget.find(".note-path-list"); |         this.$notePathList = this.$widget.find(".note-path-list"); | ||||||
|         this.$widget.on('show.bs.dropdown', async () => { |         this.$widget.on('show.bs.dropdown', async () => { | ||||||
| @ -140,15 +140,9 @@ export default class NoteIconWidget extends NoteContextAwareWidget { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     renderFilteredDropdown() { |     async renderDropdown() { | ||||||
|         const categoryId = parseInt(this.$iconCategory.find('option:selected').val()); |         const iconToCount = await this.getIconToCountMap(); | ||||||
|         const search = this.$iconSearch.val(); |         const {icons} = (await import('./icon_list.js')).default; | ||||||
| 
 |  | ||||||
|         this.renderDropdown(categoryId, search); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     async renderDropdown(categoryId, search) { |  | ||||||
|         const iconToCountPromise = this.getIconToCountMap(); |  | ||||||
| 
 | 
 | ||||||
|         this.$iconList.empty(); |         this.$iconList.empty(); | ||||||
| 
 | 
 | ||||||
| @ -164,9 +158,8 @@ export default class NoteIconWidget extends NoteContextAwareWidget { | |||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const {icons} = (await import('./icon_list.js')).default; |         const categoryId = parseInt(this.$iconCategory.find('option:selected').val()); | ||||||
| 
 |         const search = this.$iconSearch.val().trim().toLowerCase(); | ||||||
|         search = search?.trim()?.toLowerCase(); |  | ||||||
| 
 | 
 | ||||||
|         const filteredIcons = icons.filter(icon => { |         const filteredIcons = icons.filter(icon => { | ||||||
|             if (categoryId && icon.category_id !== categoryId) { |             if (categoryId && icon.category_id !== categoryId) { | ||||||
| @ -182,8 +175,6 @@ export default class NoteIconWidget extends NoteContextAwareWidget { | |||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         const iconToCount = await iconToCountPromise; |  | ||||||
| 
 |  | ||||||
|         filteredIcons.sort((a, b) => { |         filteredIcons.sort((a, b) => { | ||||||
|             const countA = iconToCount[a.className] || 0; |             const countA = iconToCount[a.className] || 0; | ||||||
|             const countB = iconToCount[b.className] || 0; |             const countB = iconToCount[b.className] || 0; | ||||||
| @ -199,9 +190,12 @@ export default class NoteIconWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async getIconToCountMap() { |     async getIconToCountMap() { | ||||||
|         const {iconClassToCountMap} = await server.get('other/icon-usage'); |         if (!this.iconToCountCache) { | ||||||
|  |             this.iconToCountCache = server.get('other/icon-usage'); | ||||||
|  |             setTimeout(() => this.iconToCountCache = null, 20000); // invalidate cache after 20 seconds
 | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         return iconClassToCountMap; |         return (await this.iconToCountCache).iconClassToCountMap; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     renderIcon(icon) { |     renderIcon(icon) { | ||||||
|  | |||||||
| @ -285,6 +285,8 @@ export default class ExcalidrawTypeWidget extends TypeWidget { | |||||||
|         }) |         }) | ||||||
| 
 | 
 | ||||||
|         const content = { |         const content = { | ||||||
|  |             type: "excalidraw", | ||||||
|  |             version: 2, | ||||||
|             _meta: "This note has type `canvas`. It uses excalidraw and stores an exported svg alongside.", |             _meta: "This note has type `canvas`. It uses excalidraw and stores an exported svg alongside.", | ||||||
|             elements, // excalidraw
 |             elements, // excalidraw
 | ||||||
|             appState, // excalidraw
 |             appState, // excalidraw
 | ||||||
|  | |||||||
| @ -185,14 +185,8 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | |||||||
|     async doRefresh(note) { |     async doRefresh(note) { | ||||||
|         const noteComplement = await froca.getNoteComplement(note.noteId); |         const noteComplement = await froca.getNoteComplement(note.noteId); | ||||||
| 
 | 
 | ||||||
|         await this.spacedUpdate.allowUpdateWithoutChange(() => { |         await this.spacedUpdate.allowUpdateWithoutChange(() => | ||||||
|             // https://github.com/zadam/trilium/issues/3914 
 |             this.watchdog.editor.setData(noteComplement.content || "")); | ||||||
|             // todo: quite hacky, but it works. remove it if ckeditor has fixed it.
 |  | ||||||
|             this.$editor.trigger('focus'); |  | ||||||
|             this.$editor.trigger('blur') |  | ||||||
|                      |  | ||||||
|             this.watchdog.editor.setData(noteComplement.content || ""); |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     getData() { |     getData() { | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ const build = require('./build'); | |||||||
| const packageJson = require('../../package'); | const packageJson = require('../../package'); | ||||||
| const {TRILIUM_DATA_DIR} = require('./data_dir'); | const {TRILIUM_DATA_DIR} = require('./data_dir'); | ||||||
| 
 | 
 | ||||||
| const APP_DB_VERSION = 213; | const APP_DB_VERSION = 214; | ||||||
| const SYNC_VERSION = 29; | const SYNC_VERSION = 29; | ||||||
| const CLIPPER_PROTOCOL_VERSION = "1.0"; | const CLIPPER_PROTOCOL_VERSION = "1.0"; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1 +1 @@ | |||||||
| module.exports = { buildDate:"2023-06-08T22:46:52+02:00", buildRevision: "6e69cafe5419e8efcc6f652647f9227dbcfa1e18" }; | module.exports = { buildDate:"2023-06-19T23:26:50+02:00", buildRevision: "5905950c17791ce0eb278e010c2c8b3450fdb447" }; | ||||||
|  | |||||||
| @ -26,11 +26,13 @@ const fs = require("fs"); | |||||||
| function getNewNotePosition(parentNote) { | function getNewNotePosition(parentNote) { | ||||||
|     if (parentNote.isLabelTruthy('newNotesOnTop')) { |     if (parentNote.isLabelTruthy('newNotesOnTop')) { | ||||||
|         const minNotePos = parentNote.getChildBranches() |         const minNotePos = parentNote.getChildBranches() | ||||||
|  |             .filter(branch => branch.noteId !== '_hidden') // has "always last" note position
 | ||||||
|             .reduce((min, note) => Math.min(min, note.notePosition), 0); |             .reduce((min, note) => Math.min(min, note.notePosition), 0); | ||||||
| 
 | 
 | ||||||
|         return minNotePos - 10; |         return minNotePos - 10; | ||||||
|     } else { |     } else { | ||||||
|         const maxNotePos = parentNote.getChildBranches() |         const maxNotePos = parentNote.getChildBranches() | ||||||
|  |             .filter(branch => branch.noteId !== '_hidden') // has "always last" note position
 | ||||||
|             .reduce((max, note) => Math.max(max, note.notePosition), 0); |             .reduce((max, note) => Math.max(max, note.notePosition), 0); | ||||||
| 
 | 
 | ||||||
|         return maxNotePos + 10; |         return maxNotePos + 10; | ||||||
|  | |||||||
| @ -19,20 +19,22 @@ class NoteFlatTextExp extends Expression { | |||||||
| 
 | 
 | ||||||
|         /** |         /** | ||||||
|          * @param {BNote} note |          * @param {BNote} note | ||||||
|          * @param {string[]} tokens |          * @param {string[]} remainingTokens - tokens still needed to be found in the path towards root | ||||||
|          * @param {string[]} path |          * @param {string[]} takenPath - path so far taken towards from candidate note towards the root. | ||||||
|  |          *                               It contains the suffix fragment of the full note path. | ||||||
|          */ |          */ | ||||||
|         const searchDownThePath = (note, tokens, path) => { |         const searchPathTowardsRoot = (note, remainingTokens, takenPath) => { | ||||||
|             if (tokens.length === 0) { |             if (remainingTokens.length === 0) { | ||||||
|                 const retPath = this.getNotePath(note, path); |                 // we're done, just build the result
 | ||||||
|  |                 const resultPath = this.getNotePath(note, takenPath); | ||||||
| 
 | 
 | ||||||
|                 if (retPath) { |                 if (resultPath) { | ||||||
|                     const noteId = retPath[retPath.length - 1]; |                     const noteId = resultPath[resultPath.length - 1]; | ||||||
| 
 | 
 | ||||||
|                     if (!resultNoteSet.hasNoteId(noteId)) { |                     if (!resultNoteSet.hasNoteId(noteId)) { | ||||||
|                         // we could get here from multiple paths, the first one wins because the paths
 |                         // we could get here from multiple paths, the first one wins because the paths
 | ||||||
|                         // are sorted by importance
 |                         // are sorted by importance
 | ||||||
|                         executionContext.noteIdToNotePath[noteId] = retPath; |                         executionContext.noteIdToNotePath[noteId] = resultPath; | ||||||
| 
 | 
 | ||||||
|                         resultNoteSet.add(becca.notes[noteId]); |                         resultNoteSet.add(becca.notes[noteId]); | ||||||
|                     } |                     } | ||||||
| @ -42,22 +44,23 @@ class NoteFlatTextExp extends Expression { | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (note.parents.length === 0 || note.noteId === 'root') { |             if (note.parents.length === 0 || note.noteId === 'root') { | ||||||
|  |                 // we've reached root, but there are still remaining tokens -> this candidate note produced no result
 | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             const foundAttrTokens = []; |             const foundAttrTokens = []; | ||||||
| 
 | 
 | ||||||
|             for (const token of tokens) { |             for (const token of remainingTokens) { | ||||||
|                 if (note.type.includes(token) || note.mime.includes(token)) { |                 if (note.type.includes(token) || note.mime.includes(token)) { | ||||||
|                     foundAttrTokens.push(token); |                     foundAttrTokens.push(token); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             for (const attribute of note.ownedAttributes) { |             for (const attribute of note.getOwnedAttributes()) { | ||||||
|                 const normalizedName = utils.normalize(attribute.name); |                 const normalizedName = utils.normalize(attribute.name); | ||||||
|                 const normalizedValue = utils.normalize(attribute.value); |                 const normalizedValue = utils.normalize(attribute.value); | ||||||
| 
 | 
 | ||||||
|                 for (const token of tokens) { |                 for (const token of remainingTokens) { | ||||||
|                     if (normalizedName.includes(token) || normalizedValue.includes(token)) { |                     if (normalizedName.includes(token) || normalizedValue.includes(token)) { | ||||||
|                         foundAttrTokens.push(token); |                         foundAttrTokens.push(token); | ||||||
|                     } |                     } | ||||||
| @ -68,19 +71,19 @@ class NoteFlatTextExp extends Expression { | |||||||
|                 const title = utils.normalize(beccaService.getNoteTitle(note.noteId, parentNote.noteId)); |                 const title = utils.normalize(beccaService.getNoteTitle(note.noteId, parentNote.noteId)); | ||||||
|                 const foundTokens = foundAttrTokens.slice(); |                 const foundTokens = foundAttrTokens.slice(); | ||||||
| 
 | 
 | ||||||
|                 for (const token of tokens) { |                 for (const token of remainingTokens) { | ||||||
|                     if (title.includes(token)) { |                     if (title.includes(token)) { | ||||||
|                         foundTokens.push(token); |                         foundTokens.push(token); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 if (foundTokens.length > 0) { |                 if (foundTokens.length > 0) { | ||||||
|                     const remainingTokens = tokens.filter(token => !foundTokens.includes(token)); |                     const newRemainingTokens = remainingTokens.filter(token => !foundTokens.includes(token)); | ||||||
| 
 | 
 | ||||||
|                     searchDownThePath(parentNote, remainingTokens, [...path, note.noteId]); |                     searchPathTowardsRoot(parentNote, newRemainingTokens, [note.noteId, ...takenPath]); | ||||||
|                 } |                 } | ||||||
|                 else { |                 else { | ||||||
|                     searchDownThePath(parentNote, tokens, [...path, note.noteId]); |                     searchPathTowardsRoot(parentNote, remainingTokens, [note.noteId, ...takenPath]); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -90,7 +93,7 @@ class NoteFlatTextExp extends Expression { | |||||||
|         for (const note of candidateNotes) { |         for (const note of candidateNotes) { | ||||||
|             // autocomplete should be able to find notes by their noteIds as well (only leafs)
 |             // autocomplete should be able to find notes by their noteIds as well (only leafs)
 | ||||||
|             if (this.tokens.length === 1 && note.noteId.toLowerCase() === this.tokens[0]) { |             if (this.tokens.length === 1 && note.noteId.toLowerCase() === this.tokens[0]) { | ||||||
|                 searchDownThePath(note, [], []); |                 searchPathTowardsRoot(note, [], [note.noteId]); | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @ -123,7 +126,7 @@ class NoteFlatTextExp extends Expression { | |||||||
|                 if (foundTokens.length > 0) { |                 if (foundTokens.length > 0) { | ||||||
|                     const remainingTokens = this.tokens.filter(token => !foundTokens.includes(token)); |                     const remainingTokens = this.tokens.filter(token => !foundTokens.includes(token)); | ||||||
| 
 | 
 | ||||||
|                     searchDownThePath(parentNote, remainingTokens, [note.noteId]); |                     searchPathTowardsRoot(parentNote, remainingTokens, [note.noteId]); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -131,14 +134,22 @@ class NoteFlatTextExp extends Expression { | |||||||
|         return resultNoteSet; |         return resultNoteSet; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     getNotePath(note, path) { |     /** | ||||||
|         if (path.length === 0) { |      * @param {BNote} note | ||||||
|  |      * @param {string[]} takenPath | ||||||
|  |      * @returns {string[]} | ||||||
|  |      */ | ||||||
|  |     getNotePath(note, takenPath) { | ||||||
|  |         if (takenPath.length === 0) { | ||||||
|  |             throw new Error("Path is not expected to be empty."); | ||||||
|  |         } else if (takenPath.length === 1 && takenPath[0] === note.noteId) { | ||||||
|             return note.getBestNotePath(); |             return note.getBestNotePath(); | ||||||
|         } else { |         } else { | ||||||
|             const closestNoteId = path[0]; |             // this note is the closest to root containing the last matching token(s), thus completing the requirements
 | ||||||
|             const closestNoteBestNotePath = becca.getNote(closestNoteId).getBestNotePath(); |             // what's in this note's predecessors does not matter, thus we'll choose the best note path
 | ||||||
|  |             const topMostMatchingTokenNotePath = becca.getNote(takenPath[0]).getBestNotePath(); | ||||||
| 
 | 
 | ||||||
|             return [...closestNoteBestNotePath, ...path.slice(1)]; |             return [...topMostMatchingTokenNotePath, ...takenPath.slice(1)]; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -10,7 +10,6 @@ const becca = require('../../../becca/becca'); | |||||||
| const beccaService = require('../../../becca/becca_service'); | const beccaService = require('../../../becca/becca_service'); | ||||||
| const utils = require('../../utils'); | const utils = require('../../utils'); | ||||||
| const log = require('../../log'); | const log = require('../../log'); | ||||||
| const scriptService = require("../../script"); |  | ||||||
| const hoistedNoteService = require("../../hoisted_note"); | const hoistedNoteService = require("../../hoisted_note"); | ||||||
| 
 | 
 | ||||||
| function searchFromNote(note) { | function searchFromNote(note) { | ||||||
| @ -73,6 +72,7 @@ function searchFromRelation(note, relationName) { | |||||||
|         return []; |         return []; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     const scriptService = require("../../script"); // to avoid circular dependency
 | ||||||
|     const result = scriptService.executeNote(scriptNote, {originEntity: note}); |     const result = scriptService.executeNote(scriptNote, {originEntity: note}); | ||||||
| 
 | 
 | ||||||
|     if (!Array.isArray(result)) { |     if (!Array.isArray(result)) { | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ const ws = require('./ws'); | |||||||
| const taskContexts = {}; | const taskContexts = {}; | ||||||
| 
 | 
 | ||||||
| class TaskContext { | class TaskContext { | ||||||
|     constructor(taskId, taskType = null, data = null) { |     constructor(taskId, taskType = null, data = {}) { | ||||||
|         this.taskId = taskId; |         this.taskId = taskId; | ||||||
|         this.taskType = taskType; |         this.taskType = taskType; | ||||||
|         this.data = data; |         this.data = data; | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								test-etapi/import-zip.http
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								test-etapi/import-zip.http
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | POST {{triliumHost}}/etapi/notes/root/import | ||||||
|  | Authorization: {{authToken}} | ||||||
|  | Content-Type: application/octet-stream | ||||||
|  | Content-Transfer-Encoding: binary | ||||||
|  | 
 | ||||||
|  | < ../db/demo.zip | ||||||
|  | 
 | ||||||
|  | > {% | ||||||
|  |     client.assert(response.status === 201); | ||||||
|  |     client.assert(response.body.note.title == "Trilium Demo"); | ||||||
|  |     client.assert(response.body.branch.parentNoteId == "root"); | ||||||
|  | %} | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam