mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 21:11:30 +08:00 
			
		
		
		
	New Note_Map features
This commit is contained in:
		
							parent
							
								
									b3c247c7dc
								
							
						
					
					
						commit
						3a4da07b39
					
				| @ -1,11 +1,12 @@ | |||||||
| import libraryLoader from '../services/library_loader.js'; | import libraryLoader from "../services/library_loader.js"; | ||||||
| import server from '../services/server.js'; | import server from "../services/server.js"; | ||||||
| import attributeService from '../services/attributes.js'; | import attributeService from "../services/attributes.js"; | ||||||
| import hoistedNoteService from '../services/hoisted_note.js'; | import hoistedNoteService from "../services/hoisted_note.js"; | ||||||
| import appContext from '../components/app_context.js'; | import appContext from "../components/app_context.js"; | ||||||
| import NoteContextAwareWidget from './note_context_aware_widget.js'; | import NoteContextAwareWidget from "./note_context_aware_widget.js"; | ||||||
| import linkContextMenuService from '../menus/link_context_menu.js'; | import linkContextMenuService from "../menus/link_context_menu.js"; | ||||||
| import utils from '../services/utils.js'; | import utils from "../services/utils.js"; | ||||||
|  | import { t } from "../services/i18n.js"; | ||||||
| 
 | 
 | ||||||
| const esc = utils.escapeHtml; | const esc = utils.escapeHtml; | ||||||
| 
 | 
 | ||||||
| @ -23,12 +24,12 @@ const TPL = `<div class="note-map-widget" style="position: relative;"> | |||||||
|             z-index: 10; /* should be below dropdown (note actions) */ |             z-index: 10; /* should be below dropdown (note actions) */ | ||||||
|         } |         } | ||||||
|          |          | ||||||
|          |  | ||||||
|         .map-type-switcher button.bx { |         .map-type-switcher button.bx { | ||||||
|             font-size: 130%; |             font-size: 130%; | ||||||
|             padding: 1px 10px 1px 10px; |             padding: 1px 10px 1px 10px; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         /* Style Ui Element to Drag Nodes */ | ||||||
|         .fixnodes-type-switcher { |         .fixnodes-type-switcher { | ||||||
|             position: absolute;  |             position: absolute;  | ||||||
|             top: 10px;  |             top: 10px;  | ||||||
| @ -37,6 +38,7 @@ const TPL = `<div class="note-map-widget" style="position: relative;"> | |||||||
|             border-radius:0.2rem; |             border-radius:0.2rem; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         /* Start of styling the slider */ | ||||||
|             input[type="range"] { |             input[type="range"] { | ||||||
|    |    | ||||||
|             /* removing default appearance */ |             /* removing default appearance */ | ||||||
| @ -49,7 +51,7 @@ const TPL = `<div class="note-map-widget" style="position: relative;"> | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         /* Track: webkit browsers */ |         /* Changing slider tracker */ | ||||||
|         input[type="range"]::-webkit-slider-runnable-track { |         input[type="range"]::-webkit-slider-runnable-track { | ||||||
|         height: 6px; |         height: 6px; | ||||||
|         background: #ccc; |         background: #ccc; | ||||||
| @ -57,7 +59,7 @@ const TPL = `<div class="note-map-widget" style="position: relative;"> | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         /* Thumb: webkit */ |         /* Changing Slider Thumb*/ | ||||||
|         input[type="range"]::-webkit-slider-thumb { |         input[type="range"]::-webkit-slider-thumb { | ||||||
|         /* removing default appearance */ |         /* removing default appearance */ | ||||||
|         -webkit-appearance: none; |         -webkit-appearance: none; | ||||||
| @ -69,12 +71,17 @@ const TPL = `<div class="note-map-widget" style="position: relative;"> | |||||||
|         background-color: #661822; |         background-color: #661822; | ||||||
|         border-radius: 50%; |         border-radius: 50%; | ||||||
| 
 | 
 | ||||||
|  |         /* End of styling the slider */ | ||||||
|  | 
 | ||||||
|     </style> |     </style> | ||||||
|      |      | ||||||
|     <div class="btn-group btn-group-sm map-type-switcher" role="group"> |     <div class="btn-group btn-group-sm map-type-switcher" role="group"> | ||||||
|       <button type="button" class="btn bx bx-network-chart" title="Link Map" data-type="link"></button> |       <button type="button" class="btn bx bx-network-chart" title="${t("note-map.button-link-map")}" data-type="link"></button> | ||||||
|       <button type="button" class="btn bx bx-sitemap" title="Tree map" data-type="tree"></button> |       <button type="button" class="btn bx bx-sitemap" title="${t("note-map.button-tree-map")}" data-type="tree"></button> | ||||||
|     </div> |     </div> | ||||||
|  | 
 | ||||||
|  |     <! UI for dragging Notes and link force > | ||||||
|  | 
 | ||||||
|      <div class=" btn-group-sm fixnodes-type-switcher" role="group"> |      <div class=" btn-group-sm fixnodes-type-switcher" role="group"> | ||||||
|       <button type="button" class="btn bx bx-expand" title="Fixation" data-type="moveable"></button> |       <button type="button" class="btn bx bx-expand" title="Fixation" data-type="moveable"></button> | ||||||
|       <input type="range" class=" slider" min="1" title="Link distance" max="100" value="40" > |       <input type="range" class=" slider" min="1" title="Link distance" max="100" value="40" > | ||||||
| @ -89,7 +96,7 @@ const TPL = `<div class="note-map-widget" style="position: relative;"> | |||||||
| export default class NoteMapWidget extends NoteContextAwareWidget { | export default class NoteMapWidget extends NoteContextAwareWidget { | ||||||
|     constructor(widgetMode) { |     constructor(widgetMode) { | ||||||
|         super(); |         super(); | ||||||
|         this.fixNodes = false; //sets a variable to fix the nodes when dragged
 |         this.fixNodes = false; // needed to save the status of the UI element. Is set later in the code
 | ||||||
|         this.widgetMode = widgetMode; // 'type' or 'ribbon'
 |         this.widgetMode = widgetMode; // 'type' or 'ribbon'
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -99,65 +106,59 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|         const documentStyle = window.getComputedStyle(document.documentElement); |         const documentStyle = window.getComputedStyle(document.documentElement); | ||||||
|         this.themeStyle = documentStyle.getPropertyValue('--theme-style')?.trim(); |         this.themeStyle = documentStyle.getPropertyValue('--theme-style')?.trim(); | ||||||
| 
 | 
 | ||||||
|         this.$container = this.$widget.find('.note-map-container'); |         this.$container = this.$widget.find(".note-map-container"); | ||||||
|         this.$styleResolver = this.$widget.find('.style-resolver'); |         this.$styleResolver = this.$widget.find('.style-resolver'); | ||||||
| 
 | 
 | ||||||
|         new ResizeObserver(() => this.setDimensions()).observe(this.$container[0]); |         new ResizeObserver(() => this.setDimensions()).observe(this.$container[0]); | ||||||
| 
 | 
 | ||||||
|         this.$widget.find('.map-type-switcher button').on('click', async e => { |         this.$widget.find(".map-type-switcher button").on("click",  async e => { | ||||||
|             const type = $(e.target).closest('button').attr('data-type'); |             const type = $(e.target).closest("button").attr("data-type"); | ||||||
|  | 
 | ||||||
|             await attributeService.setLabel(this.noteId, 'mapType', type); |             await attributeService.setLabel(this.noteId, 'mapType', type); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         // Code for the fix node after Dragging. Later in the script is more to fix the nodes in the canvas. This code here is to control the ui element
 |         // Reading the status of the Drag nodes Ui element. Changing it´s color when activated. Reading Force value of the link distance.
 | ||||||
| 
 | 
 | ||||||
|         this.$widget.find('.fixnodes-type-switcher').on('click', async event => { |         this.$widget.find('.fixnodes-type-switcher').on('click', async event => { | ||||||
|             this.fixNodes = !this.fixNodes; |             this.fixNodes = !this.fixNodes; | ||||||
|             console.log(this.fixNodes); |  | ||||||
|             event.target.style.backgroundColor = this.fixNodes ? '#661822' : 'transparent'; |             event.target.style.backgroundColor = this.fixNodes ? '#661822' : 'transparent'; | ||||||
|             let Distancevalue1 = 40; |  | ||||||
|             this.$widget.find('.fixnodes-type-switcher input').on('change', async e => { |  | ||||||
|                 Distancevalue1 = e.target.closest('input').value; |  | ||||||
| 
 |  | ||||||
|                 return e.target.closest('input').value; |  | ||||||
|             }); |  | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         super.doRender(); |         super.doRender(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     setDimensions() { |     setDimensions() { | ||||||
|         if (!this.graph) { |         if (!this.graph) { // no graph has been even rendered
 | ||||||
|             // no graph has been even rendered
 |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const $parent = this.$widget.parent(); |         const $parent = this.$widget.parent(); | ||||||
| 
 | 
 | ||||||
|         this.graph.height($parent.height()).width($parent.width()); |         this.graph | ||||||
|  |             .height($parent.height()) | ||||||
|  |             .width($parent.width()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async refreshWithNote(note) { |     async refreshWithNote(note) { | ||||||
|         this.$widget.show(); |         this.$widget.show(); | ||||||
| 
 | 
 | ||||||
|         this.css = { |         this.css = { | ||||||
|             fontFamily: this.$container.css('font-family'), |             fontFamily: this.$container.css("font-family"), | ||||||
|             textColor: this.rgb2hex(this.$container.css('color')), |             textColor: this.rgb2hex(this.$container.css("color")), | ||||||
|             mutedTextColor: this.rgb2hex(this.$styleResolver.css('color')) |             mutedTextColor: this.rgb2hex(this.$styleResolver.css("color")) | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         this.mapType = this.note.getLabelValue('mapType') === 'tree' ? 'tree' : 'link'; |         this.mapType = this.note.getLabelValue("mapType") === "tree" ? "tree" : "link"; | ||||||
| 
 | 
 | ||||||
|         await libraryLoader.requireLibrary(libraryLoader.FORCE_GRAPH); |         await libraryLoader.requireLibrary(libraryLoader.FORCE_GRAPH); | ||||||
| 
 | 
 | ||||||
|         //Variablen for hoverfeature
 |         //variables for the hover effekt. We have to save the neighbours of a hovered node in a set. Also we need to save the links as well as the hovered node itself
 | ||||||
| 
 | 
 | ||||||
|         let hoverNode = null; |         let hoverNode = null; | ||||||
|         const highlightLinks = new Set(); |         const highlightLinks = new Set(); | ||||||
|         const neighbours = new Set(); |         const neighbours = new Set(); | ||||||
| 
 | 
 | ||||||
|         this.graph = ForceGraph()(this.$container[0]) |         this.graph = ForceGraph()(this.$container[0]) | ||||||
| 
 |  | ||||||
|             .width(this.$container.width()) |             .width(this.$container.width()) | ||||||
|             .height(this.$container.height()) |             .height(this.$container.height()) | ||||||
|             .onZoom(zoom => this.setZoomLevel(zoom.k)) |             .onZoom(zoom => this.setZoomLevel(zoom.k)) | ||||||
| @ -174,37 +175,39 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|                     node.fy = null; |                     node.fy = null; | ||||||
|                 } |                 } | ||||||
|             }) |             }) | ||||||
|             //saves the hovered node in a variable to  paint it then yellow in the if clause of the .nodeCanvasObject function
 |             //check if hovered and set the hovernode variable, saving the hovered node object into it. Clear links variable everytime you hover. Without clearing links will stay highlighted
 | ||||||
|             .onNodeHover(node => { |             .onNodeHover(node => { | ||||||
|                 hoverNode = node || null; |                 hoverNode = node || null; | ||||||
|                 highlightLinks.clear(); |                 highlightLinks.clear(); | ||||||
|             }) |             }) | ||||||
|             // set link width to show connections on hover.
 |              | ||||||
|  |             // set link width to immitate a highlight effekt. Checking the condition if any links are saved in the previous defined set highlightlinks
 | ||||||
|             .linkWidth(link => (highlightLinks.has(link) ? 3 : 0.4)) |             .linkWidth(link => (highlightLinks.has(link) ? 3 : 0.4)) | ||||||
|             .linkColor(link => (highlightLinks.has(link) ? 'white' : this.css.mutedTextColor)) |             .linkColor(link => (highlightLinks.has(link) ? 'white' : this.css.mutedTextColor)) | ||||||
|             //Code for painting the node when hovered
 |             .linkDirectionalArrowLength(4) | ||||||
|  |             .linkDirectionalArrowRelPos(0.95) | ||||||
|  | 
 | ||||||
|  |             // main code for highlighting hovered nodes and neighbours. here we "style" the nodes. the nodes are rendered several hundred times per second.
 | ||||||
|             .nodeCanvasObject((node, ctx) => { |             .nodeCanvasObject((node, ctx) => { | ||||||
|                 if (hoverNode == node) { |                 if (hoverNode == node) { //paint only hovered node
 | ||||||
|                     this.paintNode(node, '#661822', ctx); |                     this.paintNode(node, '#661822', ctx); | ||||||
|                     neighbours.clear(); |                     neighbours.clear(); //clearing neighbours or the effect would be maintained after hovering is over
 | ||||||
|                     for (const link of data.links) { |                     for (const link of data.links) { //check if node is part of a link in the canvas, if so add it´s neighbours and related links to the previous defined variables to paint the nodes
 | ||||||
|                         if (link.source.id == node.id || link.target.id == node.id) { |                         if (link.source.id == node.id || link.target.id == node.id) { | ||||||
|                             neighbours.add(link.source); |                             neighbours.add(link.source); | ||||||
|                             neighbours.add(link.target); |                             neighbours.add(link.target); | ||||||
|                             highlightLinks.add(link); |                             highlightLinks.add(link); | ||||||
|                             neighbours.delete(node); |                             neighbours.delete(node); | ||||||
|                             console.log(data); |  | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } else if (neighbours.has(node) && hoverNode != null) { |                 } else if (neighbours.has(node) && hoverNode != null) { //paint neighbours
 | ||||||
|                     this.paintNode(node, '#9d6363', ctx); |                     this.paintNode(node, '#9d6363', ctx); | ||||||
|                 } else { |                 } else { | ||||||
|                     this.paintNode(node, this.getColorForNode(node), ctx); |                     this.paintNode(node, this.getColorForNode(node), ctx); //paint rest of nodes in canvas
 | ||||||
|                 } |                 } | ||||||
|             }) |             }) | ||||||
|             .nodePointerAreaPaint((node, ctx) => | 
 | ||||||
|                 this.paintNode(node, this.getColorForNode(node), ctx) |             .nodePointerAreaPaint((node, ctx) => this.paintNode(node, this.getColorForNode(node), ctx)) | ||||||
|             ) |  | ||||||
|             .nodePointerAreaPaint((node, color, ctx) => { |             .nodePointerAreaPaint((node, color, ctx) => { | ||||||
|                 ctx.fillStyle = color; |                 ctx.fillStyle = color; | ||||||
|                 ctx.beginPath(); |                 ctx.beginPath(); | ||||||
| @ -214,37 +217,28 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|             .nodeLabel(node => esc(node.name)) |             .nodeLabel(node => esc(node.name)) | ||||||
|             .maxZoom(7) |             .maxZoom(7) | ||||||
|             .warmupTicks(30) |             .warmupTicks(30) | ||||||
|             .linkDirectionalArrowLength(4) |  | ||||||
|             .linkDirectionalArrowRelPos(0.95) |  | ||||||
| 
 |  | ||||||
|             //Julien Code Ende
 |  | ||||||
| 
 |  | ||||||
|             .onNodeClick(node => appContext.tabManager.getActiveContext().setNote(node.id)) |             .onNodeClick(node => appContext.tabManager.getActiveContext().setNote(node.id)) | ||||||
|             .onNodeRightClick((node, e) => linkContextMenuService.openContextMenu(node.id, e)); |             .onNodeRightClick((node, e) => linkContextMenuService.openContextMenu(node.id, e)); | ||||||
| 
 | 
 | ||||||
|         if (this.mapType === 'link') { |         if (this.mapType === 'link') { | ||||||
|             this.graph |             this.graph | ||||||
|                 .linkLabel( |                 .linkLabel(l => `${esc(l.source.name)} - <strong>${esc(l.name)}</strong> - ${esc(l.target.name)}`) | ||||||
|                     l => |  | ||||||
|                         `${esc(l.source.name)} - <strong>${esc(l.name)}</strong> - ${esc( |  | ||||||
|                             l.target.name |  | ||||||
|                         )}` |  | ||||||
|                 ) |  | ||||||
|                 .linkCanvasObject((link, ctx) => this.paintLink(link, ctx)) |                 .linkCanvasObject((link, ctx) => this.paintLink(link, ctx)) | ||||||
|                 .linkCanvasObjectMode(() => 'after'); |                 .linkCanvasObjectMode(() => "after"); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const mapRootNoteId = this.getMapRootNoteId(); |         const mapRootNoteId = this.getMapRootNoteId(); | ||||||
|         const data = await this.loadNotesAndRelations(mapRootNoteId); |         const data = await this.loadNotesAndRelations(mapRootNoteId); | ||||||
|  | 
 | ||||||
|         const nodeLinkRatio = data.nodes.length / data.links.length; |         const nodeLinkRatio = data.nodes.length / data.links.length; | ||||||
|         const magnifiedRatio = Math.pow(nodeLinkRatio, 1.5); |         const magnifiedRatio = Math.pow(nodeLinkRatio, 1.5); | ||||||
|         const charge = -20 / magnifiedRatio; |         const charge = -20 / magnifiedRatio; | ||||||
|         const boundedCharge = Math.min(-3, charge); |         const boundedCharge = Math.min(-3, charge); | ||||||
|         let Distancevalue = 40; // Feature für liveänderungen in note_map wie link distance
 |         let distancevalue = 40; // default value for the link force of the nodes
 | ||||||
| 
 | 
 | ||||||
|         this.$widget.find('.fixnodes-type-switcher input').on('change', async e => { |         this.$widget.find('.fixnodes-type-switcher input').on('change', async e => { | ||||||
|             Distancevalue = e.target.closest('input').value; |             distancevalue = e.target.closest('input').value; | ||||||
|             this.graph.d3Force('link').distance(Distancevalue); |             this.graph.d3Force('link').distance(distancevalue); | ||||||
| 
 | 
 | ||||||
|             this.renderData(data); |             this.renderData(data); | ||||||
|         }); |         }); | ||||||
| @ -252,6 +246,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|         this.graph.d3Force('center').strength(0.2); |         this.graph.d3Force('center').strength(0.2); | ||||||
|         this.graph.d3Force('charge').strength(boundedCharge); |         this.graph.d3Force('charge').strength(boundedCharge); | ||||||
|         this.graph.d3Force('charge').distanceMax(1000); |         this.graph.d3Force('charge').distanceMax(1000); | ||||||
|  | 
 | ||||||
|         this.renderData(data); |         this.renderData(data); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -260,7 +255,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|             return this.noteId; |             return this.noteId; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let mapRootNoteId = this.note.getLabelValue('mapRootNoteId'); |         let mapRootNoteId = this.note.getLabelValue("mapRootNoteId"); | ||||||
| 
 | 
 | ||||||
|         if (mapRootNoteId === 'hoisted') { |         if (mapRootNoteId === 'hoisted') { | ||||||
|             mapRootNoteId = hoistedNoteService.getHoistedNoteId(); |             mapRootNoteId = hoistedNoteService.getHoistedNoteId(); | ||||||
| @ -282,7 +277,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     generateColorFromString(str) { |     generateColorFromString(str) { | ||||||
|         if (this.themeStyle === 'dark') { |         if (this.themeStyle === "dark") { | ||||||
|             str = `0${str}`; // magic lightning modifier
 |             str = `0${str}`; // magic lightning modifier
 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -293,19 +288,18 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
| 
 | 
 | ||||||
|         let color = '#'; |         let color = '#'; | ||||||
|         for (let i = 0; i < 3; i++) { |         for (let i = 0; i < 3; i++) { | ||||||
|             const value = (hash >> (i * 8)) & 0xff; |             const value = (hash >> (i * 8)) & 0xFF; | ||||||
| 
 | 
 | ||||||
|             color += `00${value.toString(16)}`.substr(-2); |             color += (`00${value.toString(16)}`).substr(-2); | ||||||
|         } |         } | ||||||
|         return color; |         return color; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     rgb2hex(rgb) { |     rgb2hex(rgb) { | ||||||
|         return `#${rgb |         return `#${rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/) | ||||||
|             .match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/) |  | ||||||
|             .slice(1) |             .slice(1) | ||||||
|             .map(n => parseInt(n, 10).toString(16).padStart(2, '0')) |             .map(n => parseInt(n, 10).toString(16).padStart(2, '0')) | ||||||
|             .join('')}`;
 |             .join('')}` | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     setZoomLevel(level) { |     setZoomLevel(level) { | ||||||
| @ -313,18 +307,17 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     paintNode(node, color, ctx) { |     paintNode(node, color, ctx) { | ||||||
|         const { x, y } = node; |         const {x, y} = node; | ||||||
|         const size = this.noteIdToSizeMap[node.id]; |         const size = this.noteIdToSizeMap[node.id]; | ||||||
| 
 | 
 | ||||||
|         ctx.fillStyle = color; |         ctx.fillStyle = color; | ||||||
|         ctx.beginPath(); |         ctx.beginPath(); | ||||||
|         ctx.arc(x, y, size * 0.8, 0, 2 * Math.PI, false); |         ctx.arc(x, y, size*0.8, 0, 2 * Math.PI, false); | ||||||
|         ctx.fill(); |         ctx.fill(); | ||||||
| 
 | 
 | ||||||
|         const toRender = |         const toRender = this.zoomLevel > 2 | ||||||
|             this.zoomLevel > 2 || |             || (this.zoomLevel > 1 && size > 6) | ||||||
|             (this.zoomLevel > 1 && size > 6) || |             || (this.zoomLevel > 0.3 && size > 10); | ||||||
|             (this.zoomLevel > 0.3 && size > 10); |  | ||||||
| 
 | 
 | ||||||
|         if (!toRender) { |         if (!toRender) { | ||||||
|             return; |             return; | ||||||
| @ -349,16 +342,16 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         ctx.font = `2px ${this.css.fontFamily}`; |         ctx.font = `3px ${this.css.fontFamily}`; | ||||||
|         ctx.textAlign = 'center'; |         ctx.textAlign = 'center'; | ||||||
|         ctx.textBaseline = 'middle'; |         ctx.textBaseline = 'middle'; | ||||||
|         ctx.fillStyle = this.css.mutedTextColor; |         ctx.fillStyle = this.css.mutedTextColor; | ||||||
| 
 | 
 | ||||||
|         const { source, target } = link; |         const {source, target} = link; | ||||||
| 
 | 
 | ||||||
|         const x = (source.x + target.x) / 2; |         const x = (source.x + target.x) / 2; | ||||||
|         const y = (source.y + target.y) / 2; |         const y = (source.y + target.y) / 2; | ||||||
|         console.log(x); | 
 | ||||||
|         ctx.save(); |         ctx.save(); | ||||||
|         ctx.translate(x, y); |         ctx.translate(x, y); | ||||||
| 
 | 
 | ||||||
| @ -384,6 +377,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|         this.calculateNodeSizes(resp); |         this.calculateNodeSizes(resp); | ||||||
| 
 | 
 | ||||||
|         const links = this.getGroupedLinks(resp.links); |         const links = this.getGroupedLinks(resp.links); | ||||||
|  | 
 | ||||||
|         this.nodes = resp.notes.map(([noteId, title, type, color]) => ({ |         this.nodes = resp.notes.map(([noteId, title, type, color]) => ({ | ||||||
|             id: noteId, |             id: noteId, | ||||||
|             name: title, |             name: title, | ||||||
| @ -397,7 +391,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|                 id: `${link.sourceNoteId}-${link.targetNoteId}`, |                 id: `${link.sourceNoteId}-${link.targetNoteId}`, | ||||||
|                 source: link.sourceNoteId, |                 source: link.sourceNoteId, | ||||||
|                 target: link.targetNoteId, |                 target: link.targetNoteId, | ||||||
|                 name: link.names.join(', ') |                 name: link.names.join(", ") | ||||||
|             })) |             })) | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
| @ -418,7 +412,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|                     sourceNoteId: link.sourceNoteId, |                     sourceNoteId: link.sourceNoteId, | ||||||
|                     targetNoteId: link.targetNoteId, |                     targetNoteId: link.targetNoteId, | ||||||
|                     names: [link.name] |                     names: [link.name] | ||||||
|                 }; |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -429,7 +423,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|         this.noteIdToSizeMap = {}; |         this.noteIdToSizeMap = {}; | ||||||
| 
 | 
 | ||||||
|         if (this.mapType === 'tree') { |         if (this.mapType === 'tree') { | ||||||
|             const { noteIdToDescendantCountMap } = resp; |             const {noteIdToDescendantCountMap} = resp; | ||||||
| 
 | 
 | ||||||
|             for (const noteId in noteIdToDescendantCountMap) { |             for (const noteId in noteIdToDescendantCountMap) { | ||||||
|                 this.noteIdToSizeMap[noteId] = 4; |                 this.noteIdToSizeMap[noteId] = 4; | ||||||
| @ -440,22 +434,19 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|                     this.noteIdToSizeMap[noteId] += 1 + Math.round(Math.log(count) / Math.log(1.5)); |                     this.noteIdToSizeMap[noteId] += 1 + Math.round(Math.log(count) / Math.log(1.5)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } else if (this.mapType === 'link') { |         } | ||||||
|  |         else if (this.mapType === 'link') { | ||||||
|             const noteIdToLinkCount = {}; |             const noteIdToLinkCount = {}; | ||||||
| 
 | 
 | ||||||
|             for (const link of resp.links) { |             for (const link of resp.links) { | ||||||
|                 noteIdToLinkCount[link.targetNoteId] = |                 noteIdToLinkCount[link.targetNoteId] = 1 + (noteIdToLinkCount[link.targetNoteId] || 0); | ||||||
|                     1 + (noteIdToLinkCount[link.targetNoteId] || 0); |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             for (const [noteId] of resp.notes) { |             for (const [noteId] of resp.notes) { | ||||||
|                 this.noteIdToSizeMap[noteId] = 4; |                 this.noteIdToSizeMap[noteId] = 4; | ||||||
| 
 | 
 | ||||||
|                 if (noteId in noteIdToLinkCount) { |                 if (noteId in noteIdToLinkCount) { | ||||||
|                     this.noteIdToSizeMap[noteId] += Math.min( |                     this.noteIdToSizeMap[noteId] += Math.min(Math.pow(noteIdToLinkCount[noteId], 0.5), 15); | ||||||
|                         Math.pow(noteIdToLinkCount[noteId], 0.5), |  | ||||||
|                         15 |  | ||||||
|                     ); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -463,19 +454,21 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
| 
 | 
 | ||||||
|     renderData(data) { |     renderData(data) { | ||||||
|         this.graph.graphData(data); |         this.graph.graphData(data); | ||||||
|  | 
 | ||||||
|         if (this.widgetMode === 'ribbon' && this.note?.type !== 'search') { |         if (this.widgetMode === 'ribbon' && this.note?.type !== 'search') { | ||||||
|             setTimeout(() => { |             setTimeout(() => { | ||||||
|                 this.setDimensions(); |                 this.setDimensions(); | ||||||
| 
 | 
 | ||||||
|                 const subGraphNoteIds = this.getSubGraphConnectedToCurrentNote(data); |                 const subGraphNoteIds = this.getSubGraphConnectedToCurrentNote(data); | ||||||
| 
 | 
 | ||||||
|                 this.graph.zoomToFit(400, 50, node => subGraphNoteIds.has(node.id)); // zoomed immer doof, ggf ausklammern
 |                 this.graph.zoomToFit(400, 50, node => subGraphNoteIds.has(node.id)); | ||||||
| 
 | 
 | ||||||
|                 if (subGraphNoteIds.size < 30) { |                 if (subGraphNoteIds.size < 30) { | ||||||
|                     this.graph.d3VelocityDecay(0.4); |                     this.graph.d3VelocityDecay(0.4); | ||||||
|                 } |                 } | ||||||
|             }, 1000); |             }, 1000); | ||||||
|         } else { |         } | ||||||
|  |         else { | ||||||
|             if (data.nodes.length > 1) { |             if (data.nodes.length > 1) { | ||||||
|                 setTimeout(() => { |                 setTimeout(() => { | ||||||
|                     this.setDimensions(); |                     this.setDimensions(); | ||||||
| @ -483,7 +476,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|                     const noteIdsWithLinks = this.getNoteIdsWithLinks(data); |                     const noteIdsWithLinks = this.getNoteIdsWithLinks(data); | ||||||
| 
 | 
 | ||||||
|                     if (noteIdsWithLinks.size > 0) { |                     if (noteIdsWithLinks.size > 0) { | ||||||
|                         this.graph.zoomToFit(400, 30, node => noteIdsWithLinks.has(node.id)); // zoomed immer doof, ggf ausklammern
 |                         this.graph.zoomToFit(400, 30, node => noteIdsWithLinks.has(node.id)); | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     if (noteIdsWithLinks.size < 30) { |                     if (noteIdsWithLinks.size < 30) { | ||||||
| @ -518,8 +511,8 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|             return map; |             return map; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const linksBySource = getGroupedLinks(data.links, 'source'); |         const linksBySource = getGroupedLinks(data.links, "source"); | ||||||
|         const linksByTarget = getGroupedLinks(data.links, 'target'); |         const linksByTarget = getGroupedLinks(data.links, "target"); | ||||||
| 
 | 
 | ||||||
|         const subGraphNoteIds = new Set(); |         const subGraphNoteIds = new Set(); | ||||||
| 
 | 
 | ||||||
| @ -547,17 +540,13 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|         this.$container.html(''); |         this.$container.html(''); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     entitiesReloadedEvent({ loadResults }) { |     entitiesReloadedEvent({loadResults}) { | ||||||
|         if ( |         if (loadResults.getAttributeRows(this.componentId).find( | ||||||
|             loadResults |  | ||||||
|                 .getAttributeRows(this.componentId) |  | ||||||
|                 .find( |  | ||||||
|             attr => |             attr => | ||||||
|                         attr.type === 'label' && |                 attr.type === 'label' | ||||||
|                         ['mapType', 'mapRootNoteId'].includes(attr.name) && |                 && ['mapType', 'mapRootNoteId'].includes(attr.name) | ||||||
|                         attributeService.isAffecting(attr, this.note) |                 && attributeService.isAffecting(attr, this.note) | ||||||
|                 ) |         )) { | ||||||
|         ) { |  | ||||||
|             this.refresh(); |             this.refresh(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 juju
						juju