mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 21:11:30 +08:00 
			
		
		
		
	basic support for custom widgets
This commit is contained in:
		
							parent
							
								
									8ae78a9e23
								
							
						
					
					
						commit
						173030e02e
					
				
							
								
								
									
										14
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										14
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "trilium", | ||||
|   "version": "0.40.5", | ||||
|   "version": "0.40.6", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
| @ -2079,9 +2079,9 @@ | ||||
|       "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" | ||||
|     }, | ||||
|     "dayjs": { | ||||
|       "version": "1.8.22", | ||||
|       "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.22.tgz", | ||||
|       "integrity": "sha512-N8IXfxBD62Y9cKTuuuSoOlCXRnnzaTj1vu91r855iq6FbY5cZqOZnW/95nUn6kJiR+W9PHHrLykEoQOe6fUKxQ==" | ||||
|       "version": "1.8.23", | ||||
|       "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.23.tgz", | ||||
|       "integrity": "sha512-NmYHMFONftoZbeOhVz6jfiXI4zSiPN6NoVWJgC0aZQfYVwzy/ZpESPHuCcI0B8BUMpSJQ08zenHDbofOLKq8hQ==" | ||||
|     }, | ||||
|     "debug": { | ||||
|       "version": "4.1.1", | ||||
| @ -2590,9 +2590,9 @@ | ||||
|       "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" | ||||
|     }, | ||||
|     "electron": { | ||||
|       "version": "9.0.0-beta.7", | ||||
|       "resolved": "https://registry.npmjs.org/electron/-/electron-9.0.0-beta.7.tgz", | ||||
|       "integrity": "sha512-IHWBLDUjlctyzSY1cXT9b2xdUFACiwWXV38WSkIbW4Ykd2fsNxn2ESRK/JUSby1oQZL6z4fUQRUOrg/gzuoV4Q==", | ||||
|       "version": "9.0.0-beta.9", | ||||
|       "resolved": "https://registry.npmjs.org/electron/-/electron-9.0.0-beta.9.tgz", | ||||
|       "integrity": "sha512-jVt+UL22S+uRiHkt2piAoVduL/n7UCTRKbp0c42kq1+Q36BVDu4j2HrePGX1Zilmnk91j8a6AqQ/x0dv6LkDnA==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "@electron/get": "^1.0.1", | ||||
|  | ||||
| @ -74,7 +74,7 @@ | ||||
|     "ws": "7.2.3" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "electron": "9.0.0-beta.7", | ||||
|     "electron": "9.0.0-beta.9", | ||||
|     "electron-builder": "22.4.1", | ||||
|     "electron-packager": "14.2.1", | ||||
|     "electron-rebuild": "1.10.1", | ||||
|  | ||||
| @ -67,6 +67,7 @@ import ProtectedSessionTypeWidget from "./widgets/type_widgets/protected_session | ||||
| import BookTypeWidget from "./widgets/type_widgets/book.js"; | ||||
| import contextMenu from "./services/context_menu.js"; | ||||
| import DesktopLayout from "./widgets/desktop_layout.js"; | ||||
| import bundleService from "./services/bundle.js"; | ||||
| 
 | ||||
| if (utils.isElectron()) { | ||||
|     require('electron').ipcRenderer.on('globalShortcut', async function(event, actionName) { | ||||
| @ -80,8 +81,12 @@ $('[data-toggle="tooltip"]').tooltip({ | ||||
| 
 | ||||
| macInit.init(); | ||||
| 
 | ||||
| appContext.setLayout(new DesktopLayout()); | ||||
| appContext.start(); | ||||
| bundleService.getWidgetBundlesByParent().then(widgetBundles => { | ||||
|     const desktopLayout = new DesktopLayout(widgetBundles); | ||||
| 
 | ||||
|     appContext.setLayout(desktopLayout); | ||||
|     appContext.start(); | ||||
| }); | ||||
| 
 | ||||
| noteTooltipService.setupGlobalTooltip(); | ||||
| 
 | ||||
|  | ||||
| @ -1,4 +1,3 @@ | ||||
| import server from "./server.js"; | ||||
| import treeCache from "./tree_cache.js"; | ||||
| import bundleService from "./bundle.js"; | ||||
| import DialogCommandExecutor from "./dialog_command_executor.js"; | ||||
| @ -18,10 +17,10 @@ class AppContext extends Component { | ||||
|     } | ||||
| 
 | ||||
|     async start() { | ||||
|         options.load(await server.get('options')); | ||||
| 
 | ||||
|         this.showWidgets(); | ||||
| 
 | ||||
|         await Promise.all([treeCache.initializedPromise, options.initializedPromise]); | ||||
| 
 | ||||
|         this.tabManager.loadTabs(); | ||||
| 
 | ||||
|         setTimeout(() => bundleService.executeStartupBundles(), 2000); | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| import ScriptContext from "./script_context.js"; | ||||
| import server from "./server.js"; | ||||
| import toastService from "./toast.js"; | ||||
| import treeCache from "./tree_cache.js"; | ||||
| 
 | ||||
| async function getAndExecuteBundle(noteId, originEntity = null) { | ||||
|     const bundle = await server.get('script/bundle/' + noteId); | ||||
| @ -29,8 +30,40 @@ async function executeStartupBundles() { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| async function getWidgetBundlesByParent() { | ||||
|     const scriptBundles = await server.get("script/widgets"); | ||||
| 
 | ||||
|     const byParent = {}; | ||||
| 
 | ||||
|     for (const bundle of scriptBundles) { | ||||
| 
 | ||||
|         let widget; | ||||
| 
 | ||||
|         try { | ||||
|             widget = await executeBundle(bundle); | ||||
|         } | ||||
|         catch (e) { | ||||
|             console.error("Widget initialization failed: ", e); | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         if (!widget.getParentWidget) { | ||||
|             console.log(`Custom widget does not have mandatory 'getParent()' method defined`); | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         const parentWidgetName = widget.getParentWidget(); | ||||
| 
 | ||||
|         byParent[parentWidgetName] = byParent[parentWidgetName] || []; | ||||
|         byParent[parentWidgetName].push(widget); | ||||
|     } | ||||
| 
 | ||||
|     return byParent; | ||||
| } | ||||
| 
 | ||||
| export default { | ||||
|     executeBundle, | ||||
|     getAndExecuteBundle, | ||||
|     executeStartupBundles | ||||
|     executeStartupBundles, | ||||
|     getWidgetBundlesByParent | ||||
| } | ||||
| @ -282,7 +282,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain | ||||
|      * @method | ||||
|      * @returns {NoteShort} active note (loaded into right pane) | ||||
|      */ | ||||
|     this.getActiveTabNote = appContext.tabManager.getActiveTabNote; | ||||
|     this.getActiveTabNote = () => appContext.tabManager.getActiveTabNote(); | ||||
| 
 | ||||
|     /** | ||||
|      * See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
 | ||||
| @ -296,7 +296,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain | ||||
|      * @method | ||||
|      * @returns {Promise<string|null>} returns note path of active note or null if there isn't active note | ||||
|      */ | ||||
|     this.getActiveTabNotePath = appContext.tabManager.getActiveTabNotePath; | ||||
|     this.getActiveTabNotePath = () => appContext.tabManager.getActiveTabNotePath(); | ||||
| 
 | ||||
|     /** | ||||
|      * @method | ||||
|  | ||||
| @ -1,8 +1,10 @@ | ||||
| import server from "./server.js"; | ||||
| 
 | ||||
| const loadListeners = []; | ||||
| 
 | ||||
| class Options { | ||||
|     constructor() { | ||||
|         this.initializedPromise = server.get('options').then(data => this.load(data)); | ||||
|     } | ||||
| 
 | ||||
|     load(arr) { | ||||
|         this.arr = arr; | ||||
|     } | ||||
|  | ||||
| @ -32,8 +32,6 @@ export default class TabManager extends Component { | ||||
|     async loadTabs() { | ||||
|         const openTabs = options.getJson('openTabs') || []; | ||||
| 
 | ||||
|         await treeCache.initializedPromise; | ||||
| 
 | ||||
|         // if there's notePath in the URL, make sure it's open and active
 | ||||
|         // (useful, among others, for opening clipped notes from clipper)
 | ||||
|         if (window.location.hash) { | ||||
|  | ||||
| @ -9,6 +9,8 @@ class BasicWidget extends Component { | ||||
|             style: '' | ||||
|         }; | ||||
|         this.classes = []; | ||||
| 
 | ||||
|         this.position = 0; | ||||
|     } | ||||
| 
 | ||||
|     id(id) { | ||||
| @ -87,6 +89,10 @@ class BasicWidget extends Component { | ||||
|         return this.$widget.is(":visible"); | ||||
|     } | ||||
| 
 | ||||
|     getPosition() { | ||||
|         return this.position; | ||||
|     } | ||||
| 
 | ||||
|     remove() { | ||||
|         if (this.$widget) { | ||||
|             this.$widget.remove(); | ||||
|  | ||||
| @ -36,6 +36,14 @@ export default class Component { | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     addChildren(components = []) { | ||||
|         for (const component of components) { | ||||
|             this.child(component); | ||||
|         } | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     /** @return {Promise} */ | ||||
|     handleEvent(name, data) { | ||||
|         return Promise.all([ | ||||
|  | ||||
| @ -99,6 +99,10 @@ const RIGHT_PANE_CSS = ` | ||||
| </style>`; | ||||
| 
 | ||||
| export default class DesktopLayout { | ||||
|     constructor(customWidgets) { | ||||
|         this.customWidgets = customWidgets; | ||||
|     } | ||||
| 
 | ||||
|     getRootWidget(appContext) { | ||||
|         appContext.mainTreeWidget = new NoteTreeWidget(); | ||||
| 
 | ||||
| @ -144,6 +148,7 @@ export default class DesktopLayout { | ||||
|                     .child(new TabCachingWidget(() => new NoteRevisionsWidget())) | ||||
|                     .child(new TabCachingWidget(() => new SimilarNotesWidget())) | ||||
|                     .child(new TabCachingWidget(() => new WhatLinksHereWidget())) | ||||
|                     .addChildren(this.customWidgets['right-pane']) | ||||
|                 ) | ||||
|                 .child(new SidePaneToggles().hideInZenMode()) | ||||
|             ); | ||||
|  | ||||
| @ -11,6 +11,17 @@ export default class FlexContainer extends BasicWidget { | ||||
|         this.attrs.style = `display: flex; flex-direction: ${direction};`; | ||||
| 
 | ||||
|         this.children = []; | ||||
| 
 | ||||
|         this.positionCounter = 10; | ||||
|     } | ||||
| 
 | ||||
|     child(component) { | ||||
|         super.child(component); | ||||
| 
 | ||||
|         component.position = this.positionCounter; | ||||
|         this.positionCounter += 10; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     doRender() { | ||||
|  | ||||
| @ -29,8 +29,8 @@ async function run(req) { | ||||
|     return { executionResult: result }; | ||||
| } | ||||
| 
 | ||||
| async function getStartupBundles() { | ||||
|     const notes = await attributeService.getNotesWithLabel("run", "frontendStartup"); | ||||
| async function getBundlesWithLabel(label, value) { | ||||
|     const notes = await attributeService.getNotesWithLabel(label, value); | ||||
| 
 | ||||
|     const bundles = []; | ||||
| 
 | ||||
| @ -45,6 +45,14 @@ async function getStartupBundles() { | ||||
|     return bundles; | ||||
| } | ||||
| 
 | ||||
| async function getStartupBundles() { | ||||
|     return await getBundlesWithLabel("run", "frontendStartup"); | ||||
| } | ||||
| 
 | ||||
| async function getWidgetBundles() { | ||||
|     return await getBundlesWithLabel("widget"); | ||||
| } | ||||
| 
 | ||||
| async function getRelationBundles(req) { | ||||
|     const noteId = req.params.noteId; | ||||
|     const note = await repository.getNote(noteId); | ||||
| @ -84,6 +92,7 @@ module.exports = { | ||||
|     exec, | ||||
|     run, | ||||
|     getStartupBundles, | ||||
|     getWidgetBundles, | ||||
|     getRelationBundles, | ||||
|     getBundle | ||||
| }; | ||||
| @ -225,6 +225,7 @@ function register(app) { | ||||
|     apiRoute(POST, '/api/script/exec', scriptRoute.exec); | ||||
|     apiRoute(POST, '/api/script/run/:noteId', scriptRoute.run); | ||||
|     apiRoute(GET, '/api/script/startup', scriptRoute.getStartupBundles); | ||||
|     apiRoute(GET, '/api/script/widgets', scriptRoute.getWidgetBundles); | ||||
|     apiRoute(GET, '/api/script/bundle/:noteId', scriptRoute.getBundle); | ||||
|     apiRoute(GET, '/api/script/relation/:noteId/:relationName', scriptRoute.getRelationBundles); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam