mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	various widget refactorings
This commit is contained in:
		| @@ -35,7 +35,7 @@ import treeCache from './tree_cache.js'; | |||||||
| import noteTooltipService from './note_tooltip.js'; | import noteTooltipService from './note_tooltip.js'; | ||||||
| import protectedSessionService from './protected_session.js'; | import protectedSessionService from './protected_session.js'; | ||||||
| import dateNotesService from './date_notes.js'; | import dateNotesService from './date_notes.js'; | ||||||
| import StandardWidget from '../widgets/standard_widget.js'; | import StandardWidget from '../widgets/collapsible_widget.js'; | ||||||
| import ws from "./ws.js"; | import ws from "./ws.js"; | ||||||
| import hoistedNoteService from "./hoisted_note.js"; | import hoistedNoteService from "./hoisted_note.js"; | ||||||
| import appContext from "./app_context.js"; | import appContext from "./app_context.js"; | ||||||
|   | |||||||
| @@ -24,26 +24,10 @@ | |||||||
|  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||||||
|  * OTHER DEALINGS IN THE SOFTWARE. |  * OTHER DEALINGS IN THE SOFTWARE. | ||||||
|  */ |  */ | ||||||
| (function (root, factory) { | window.Springy = function() { | ||||||
|     if (typeof define === 'function' && define.amd) { | 	const Springy = {}; | ||||||
|         // AMD. Register as an anonymous module. |  | ||||||
|         define(function () { |  | ||||||
|             return (root.returnExportsGlobal = factory()); |  | ||||||
|         }); |  | ||||||
|     } else if (typeof exports === 'object') { |  | ||||||
|         // Node. Does not work with strict CommonJS, but |  | ||||||
|         // only CommonJS-like enviroments that support module.exports, |  | ||||||
|         // like Node. |  | ||||||
|         module.exports = factory(); |  | ||||||
|     } else { |  | ||||||
|         // Browser globals |  | ||||||
|         root.Springy = factory(); |  | ||||||
|     } |  | ||||||
| }(this, function() { |  | ||||||
|  |  | ||||||
| 	var Springy = {}; | 	const Graph = Springy.Graph = function () { | ||||||
|  |  | ||||||
| 	var Graph = Springy.Graph = function() { |  | ||||||
| 		this.nodeSet = {}; | 		this.nodeSet = {}; | ||||||
| 		this.nodes = []; | 		this.nodes = []; | ||||||
| 		this.edges = []; | 		this.edges = []; | ||||||
| @@ -54,25 +38,25 @@ | |||||||
| 		this.eventListeners = []; | 		this.eventListeners = []; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	var Node = Springy.Node = function(id, data) { | 	const Node = Springy.Node = function (id, data) { | ||||||
| 		this.id = id; | 		this.id = id; | ||||||
| 		this.data = (data !== undefined) ? data : {}; | 		this.data = (data !== undefined) ? data : {}; | ||||||
|  |  | ||||||
| 	// Data fields used by layout algorithm in this file: | 		// Data fields used by layout algorithm in this file: | ||||||
| 	// this.data.mass | 		// this.data.mass | ||||||
| 	// Data used by default renderer in springyui.js | 		// Data used by default renderer in springyui.js | ||||||
| 	// this.data.label | 		// this.data.label | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	var Edge = Springy.Edge = function(id, source, target, data) { | 	const Edge = Springy.Edge = function (id, source, target, data) { | ||||||
| 		this.id = id; | 		this.id = id; | ||||||
| 		this.source = source; | 		this.source = source; | ||||||
| 		this.target = target; | 		this.target = target; | ||||||
| 		this.data = (data !== undefined) ? data : {}; | 		this.data = (data !== undefined) ? data : {}; | ||||||
|  |  | ||||||
| 	// Edge data field used by layout alorithm | 		// Edge data field used by layout alorithm | ||||||
| 	// this.data.length | 		// this.data.length | ||||||
| 	// this.data.type | 		// this.data.type | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Graph.prototype.addNode = function(node) { | 	Graph.prototype.addNode = function(node) { | ||||||
| @@ -89,15 +73,15 @@ | |||||||
| 	Graph.prototype.addNodes = function() { | 	Graph.prototype.addNodes = function() { | ||||||
| 		// accepts variable number of arguments, where each argument | 		// accepts variable number of arguments, where each argument | ||||||
| 		// is a string that becomes both node identifier and label | 		// is a string that becomes both node identifier and label | ||||||
| 		for (var i = 0; i < arguments.length; i++) { | 		for (let i = 0; i < arguments.length; i++) { | ||||||
| 			var name = arguments[i]; | 			const name = arguments[i]; | ||||||
| 			var node = new Node(name, {label:name}); | 			const node = new Node(name, {label: name}); | ||||||
| 			this.addNode(node); | 			this.addNode(node); | ||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Graph.prototype.addEdge = function(edge) { | 	Graph.prototype.addEdge = function(edge) { | ||||||
| 		var exists = false; | 		let exists = false; | ||||||
| 		this.edges.forEach(function(e) { | 		this.edges.forEach(function(e) { | ||||||
| 			if (edge.id === e.id) { exists = true; } | 			if (edge.id === e.id) { exists = true; } | ||||||
| 		}); | 		}); | ||||||
| @@ -129,30 +113,30 @@ | |||||||
| 	Graph.prototype.addEdges = function() { | 	Graph.prototype.addEdges = function() { | ||||||
| 		// accepts variable number of arguments, where each argument | 		// accepts variable number of arguments, where each argument | ||||||
| 		// is a triple [nodeid1, nodeid2, attributes] | 		// is a triple [nodeid1, nodeid2, attributes] | ||||||
| 		for (var i = 0; i < arguments.length; i++) { | 		for (let i = 0; i < arguments.length; i++) { | ||||||
| 			var e = arguments[i]; | 			const e = arguments[i]; | ||||||
| 			var node1 = this.nodeSet[e[0]]; | 			const node1 = this.nodeSet[e[0]]; | ||||||
| 			if (node1 == undefined) { | 			if (node1 == undefined) { | ||||||
| 				throw new TypeError("invalid node name: " + e[0]); | 				throw new TypeError("invalid node name: " + e[0]); | ||||||
| 			} | 			} | ||||||
| 			var node2 = this.nodeSet[e[1]]; | 			const node2 = this.nodeSet[e[1]]; | ||||||
| 			if (node2 == undefined) { | 			if (node2 == undefined) { | ||||||
| 				throw new TypeError("invalid node name: " + e[1]); | 				throw new TypeError("invalid node name: " + e[1]); | ||||||
| 			} | 			} | ||||||
| 			var attr = e[2]; | 			const attr = e[2]; | ||||||
|  |  | ||||||
| 			this.newEdge(node1, node2, attr); | 			this.newEdge(node1, node2, attr); | ||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Graph.prototype.newNode = function(data) { | 	Graph.prototype.newNode = function(data) { | ||||||
| 		var node = new Node(this.nextNodeId++, data); | 		const node = new Node(this.nextNodeId++, data); | ||||||
| 		this.addNode(node); | 		this.addNode(node); | ||||||
| 		return node; | 		return node; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Graph.prototype.newEdge = function(source, target, data) { | 	Graph.prototype.newEdge = function(source, target, data) { | ||||||
| 		var edge = new Edge(this.nextEdgeId++, source, target, data); | 		const edge = new Edge(this.nextEdgeId++, source, target, data); | ||||||
| 		this.addEdge(edge); | 		this.addEdge(edge); | ||||||
| 		return edge; | 		return edge; | ||||||
| 	}; | 	}; | ||||||
| @@ -210,7 +194,7 @@ | |||||||
| 			delete this.nodeSet[node.id]; | 			delete this.nodeSet[node.id]; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		for (var i = this.nodes.length - 1; i >= 0; i--) { | 		for (let i = this.nodes.length - 1; i >= 0; i--) { | ||||||
| 			if (this.nodes[i].id === node.id) { | 			if (this.nodes[i].id === node.id) { | ||||||
| 				this.nodes.splice(i, 1); | 				this.nodes.splice(i, 1); | ||||||
| 			} | 			} | ||||||
| @@ -221,7 +205,7 @@ | |||||||
|  |  | ||||||
| 	// removes edges associated with a given node | 	// removes edges associated with a given node | ||||||
| 	Graph.prototype.detachNode = function(node) { | 	Graph.prototype.detachNode = function(node) { | ||||||
| 		var tmpEdges = this.edges.slice(); | 		const tmpEdges = this.edges.slice(); | ||||||
| 		tmpEdges.forEach(function(e) { | 		tmpEdges.forEach(function(e) { | ||||||
| 			if (e.source.id === node.id || e.target.id === node.id) { | 			if (e.source.id === node.id || e.target.id === node.id) { | ||||||
| 				this.removeEdge(e); | 				this.removeEdge(e); | ||||||
| @@ -233,17 +217,17 @@ | |||||||
|  |  | ||||||
| 	// remove a node and it's associated edges from the graph | 	// remove a node and it's associated edges from the graph | ||||||
| 	Graph.prototype.removeEdge = function(edge) { | 	Graph.prototype.removeEdge = function(edge) { | ||||||
| 		for (var i = this.edges.length - 1; i >= 0; i--) { | 		for (let i = this.edges.length - 1; i >= 0; i--) { | ||||||
| 			if (this.edges[i].id === edge.id) { | 			if (this.edges[i].id === edge.id) { | ||||||
| 				this.edges.splice(i, 1); | 				this.edges.splice(i, 1); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		for (var x in this.adjacency) { | 		for (const x in this.adjacency) { | ||||||
| 			for (var y in this.adjacency[x]) { | 			for (const y in this.adjacency[x]) { | ||||||
| 				var edges = this.adjacency[x][y]; | 				const edges = this.adjacency[x][y]; | ||||||
|  |  | ||||||
| 				for (var j=edges.length - 1; j>=0; j--) { | 				for (let j = edges.length - 1; j >= 0; j--) { | ||||||
| 					if (this.adjacency[x][y][j].id === edge.id) { | 					if (this.adjacency[x][y][j].id === edge.id) { | ||||||
| 						this.adjacency[x][y].splice(j, 1); | 						this.adjacency[x][y].splice(j, 1); | ||||||
| 					} | 					} | ||||||
| @@ -276,28 +260,28 @@ | |||||||
| 	} | 	} | ||||||
| 	*/ | 	*/ | ||||||
| 	Graph.prototype.merge = function(data) { | 	Graph.prototype.merge = function(data) { | ||||||
| 		var nodes = []; | 		const nodes = []; | ||||||
| 		data.nodes.forEach(function(n) { | 		data.nodes.forEach(function(n) { | ||||||
| 			nodes.push(this.addNode(new Node(n.id, n.data))); | 			nodes.push(this.addNode(new Node(n.id, n.data))); | ||||||
| 		}, this); | 		}, this); | ||||||
|  |  | ||||||
| 		data.edges.forEach(function(e) { | 		data.edges.forEach(function(e) { | ||||||
| 			var from = nodes[e.from]; | 			const from = nodes[e.from]; | ||||||
| 			var to = nodes[e.to]; | 			const to = nodes[e.to]; | ||||||
|  |  | ||||||
| 			var id = (e.directed) | 			let id = (e.directed) | ||||||
| 				? (id = e.type + "-" + from.id + "-" + to.id) | 				? (e.type + "-" + from.id + "-" + to.id) | ||||||
| 				: (from.id < to.id) // normalise id for non-directed edges | 				: (from.id < to.id) // normalise id for non-directed edges | ||||||
| 					? e.type + "-" + from.id + "-" + to.id | 					? e.type + "-" + from.id + "-" + to.id | ||||||
| 					: e.type + "-" + to.id + "-" + from.id; | 					: e.type + "-" + to.id + "-" + from.id; | ||||||
|  |  | ||||||
| 			var edge = this.addEdge(new Edge(id, from, to, e.data)); | 			const edge = this.addEdge(new Edge(id, from, to, e.data)); | ||||||
| 			edge.data.type = e.type; | 			edge.data.type = e.type; | ||||||
| 		}, this); | 		}, this); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Graph.prototype.filterNodes = function(fn) { | 	Graph.prototype.filterNodes = function(fn) { | ||||||
| 		var tmpNodes = this.nodes.slice(); | 		const tmpNodes = this.nodes.slice(); | ||||||
| 		tmpNodes.forEach(function(n) { | 		tmpNodes.forEach(function(n) { | ||||||
| 			if (!fn(n)) { | 			if (!fn(n)) { | ||||||
| 				this.removeNode(n); | 				this.removeNode(n); | ||||||
| @@ -306,7 +290,7 @@ | |||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Graph.prototype.filterEdges = function(fn) { | 	Graph.prototype.filterEdges = function(fn) { | ||||||
| 		var tmpEdges = this.edges.slice(); | 		const tmpEdges = this.edges.slice(); | ||||||
| 		tmpEdges.forEach(function(e) { | 		tmpEdges.forEach(function(e) { | ||||||
| 			if (!fn(e)) { | 			if (!fn(e)) { | ||||||
| 				this.removeEdge(e); | 				this.removeEdge(e); | ||||||
| @@ -326,9 +310,10 @@ | |||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	// ----------- | 	// ----------- | ||||||
| 	var Layout = Springy.Layout = {}; | 	const Layout = Springy.Layout = {}; | ||||||
| 	Layout.ForceDirected = function(graph, stiffness, repulsion, damping, minEnergyThreshold, maxSpeed) { | 	Layout.ForceDirected = function(graph, stopCheckerCallback, stiffness, repulsion, damping, minEnergyThreshold, maxSpeed) { | ||||||
| 		this.graph = graph; | 		this.graph = graph; | ||||||
|  | 		this.stopCheckerCallback = stopCheckerCallback || (() => false); | ||||||
| 		this.stiffness = stiffness; // spring stiffness constant | 		this.stiffness = stiffness; // spring stiffness constant | ||||||
| 		this.repulsion = repulsion; // repulsion constant | 		this.repulsion = repulsion; // repulsion constant | ||||||
| 		this.damping = damping; // velocity damping factor | 		this.damping = damping; // velocity damping factor | ||||||
| @@ -341,7 +326,7 @@ | |||||||
|  |  | ||||||
| 	Layout.ForceDirected.prototype.point = function(node) { | 	Layout.ForceDirected.prototype.point = function(node) { | ||||||
| 		if (!(node.id in this.nodePoints)) { | 		if (!(node.id in this.nodePoints)) { | ||||||
| 			var mass = (node.data.mass !== undefined) ? node.data.mass : 1.0; | 			const mass = (node.data.mass !== undefined) ? node.data.mass : 1.0; | ||||||
| 			this.nodePoints[node.id] = new Layout.ForceDirected.Point(Vector.random(), mass); | 			this.nodePoints[node.id] = new Layout.ForceDirected.Point(Vector.random(), mass); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -350,11 +335,11 @@ | |||||||
|  |  | ||||||
| 	Layout.ForceDirected.prototype.spring = function(edge) { | 	Layout.ForceDirected.prototype.spring = function(edge) { | ||||||
| 		if (!(edge.id in this.edgeSprings)) { | 		if (!(edge.id in this.edgeSprings)) { | ||||||
| 			var length = (edge.data.length !== undefined) ? edge.data.length : 1.0; | 			const length = (edge.data.length !== undefined) ? edge.data.length : 1.0; | ||||||
|  |  | ||||||
| 			var existingSpring = false; | 			let existingSpring = false; | ||||||
|  |  | ||||||
| 			var from = this.graph.getEdges(edge.source, edge.target); | 			const from = this.graph.getEdges(edge.source, edge.target); | ||||||
| 			from.forEach(function(e) { | 			from.forEach(function(e) { | ||||||
| 				if (existingSpring === false && e.id in this.edgeSprings) { | 				if (existingSpring === false && e.id in this.edgeSprings) { | ||||||
| 					existingSpring = this.edgeSprings[e.id]; | 					existingSpring = this.edgeSprings[e.id]; | ||||||
| @@ -365,8 +350,8 @@ | |||||||
| 				return new Layout.ForceDirected.Spring(existingSpring.point1, existingSpring.point2, 0.0, 0.0); | 				return new Layout.ForceDirected.Spring(existingSpring.point1, existingSpring.point2, 0.0, 0.0); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			var to = this.graph.getEdges(edge.target, edge.source); | 			const to = this.graph.getEdges(edge.target, edge.source); | ||||||
| 			from.forEach(function(e){ | 			to.forEach(function(e){ | ||||||
| 				if (existingSpring === false && e.id in this.edgeSprings) { | 				if (existingSpring === false && e.id in this.edgeSprings) { | ||||||
| 					existingSpring = this.edgeSprings[e.id]; | 					existingSpring = this.edgeSprings[e.id]; | ||||||
| 				} | 				} | ||||||
| @@ -386,7 +371,7 @@ | |||||||
|  |  | ||||||
| 	// callback should accept two arguments: Node, Point | 	// callback should accept two arguments: Node, Point | ||||||
| 	Layout.ForceDirected.prototype.eachNode = function(callback) { | 	Layout.ForceDirected.prototype.eachNode = function(callback) { | ||||||
| 		var t = this; | 		const t = this; | ||||||
| 		this.graph.nodes.forEach(function(n){ | 		this.graph.nodes.forEach(function(n){ | ||||||
| 			callback.call(t, n, t.point(n)); | 			callback.call(t, n, t.point(n)); | ||||||
| 		}); | 		}); | ||||||
| @@ -394,7 +379,7 @@ | |||||||
|  |  | ||||||
| 	// callback should accept two arguments: Edge, Spring | 	// callback should accept two arguments: Edge, Spring | ||||||
| 	Layout.ForceDirected.prototype.eachEdge = function(callback) { | 	Layout.ForceDirected.prototype.eachEdge = function(callback) { | ||||||
| 		var t = this; | 		const t = this; | ||||||
| 		this.graph.edges.forEach(function(e){ | 		this.graph.edges.forEach(function(e){ | ||||||
| 			callback.call(t, e, t.spring(e)); | 			callback.call(t, e, t.spring(e)); | ||||||
| 		}); | 		}); | ||||||
| @@ -402,7 +387,7 @@ | |||||||
|  |  | ||||||
| 	// callback should accept one argument: Spring | 	// callback should accept one argument: Spring | ||||||
| 	Layout.ForceDirected.prototype.eachSpring = function(callback) { | 	Layout.ForceDirected.prototype.eachSpring = function(callback) { | ||||||
| 		var t = this; | 		const t = this; | ||||||
| 		this.graph.edges.forEach(function(e){ | 		this.graph.edges.forEach(function(e){ | ||||||
| 			callback.call(t, t.spring(e)); | 			callback.call(t, t.spring(e)); | ||||||
| 		}); | 		}); | ||||||
| @@ -413,12 +398,11 @@ | |||||||
| 	Layout.ForceDirected.prototype.applyCoulombsLaw = function() { | 	Layout.ForceDirected.prototype.applyCoulombsLaw = function() { | ||||||
| 		this.eachNode(function(n1, point1) { | 		this.eachNode(function(n1, point1) { | ||||||
| 			this.eachNode(function(n2, point2) { | 			this.eachNode(function(n2, point2) { | ||||||
| 				if (point1 !== point2) | 				if (point1 !== point2) { | ||||||
| 				{ | 					const d = point1.p.subtract(point2.p); | ||||||
| 					var d = point1.p.subtract(point2.p); | 					const distance = d.magnitude() + 0.1; // avoid massive forces at small distances (and divide by zero) | ||||||
| 					var distance = d.magnitude() + 0.1; // avoid massive forces at small distances (and divide by zero) |  | ||||||
|  |  | ||||||
| 					var direction = d.normalise(); | 					const direction = d.normalise(); | ||||||
|  |  | ||||||
| 					// apply force to each end point | 					// apply force to each end point | ||||||
| 					point1.applyForce(direction.multiply(this.repulsion).divide(distance * distance * distance * 0.5)); | 					point1.applyForce(direction.multiply(this.repulsion).divide(distance * distance * distance * 0.5)); | ||||||
| @@ -430,9 +414,9 @@ | |||||||
|  |  | ||||||
| 	Layout.ForceDirected.prototype.applyHookesLaw = function() { | 	Layout.ForceDirected.prototype.applyHookesLaw = function() { | ||||||
| 		this.eachSpring(function(spring){ | 		this.eachSpring(function(spring){ | ||||||
| 			var d = spring.point2.p.subtract(spring.point1.p); // the direction of the spring | 			const d = spring.point2.p.subtract(spring.point1.p); // the direction of the spring | ||||||
| 			var displacement = spring.length - d.magnitude(); | 			const displacement = spring.length - d.magnitude(); | ||||||
| 			var direction = d.normalise(); | 			const direction = d.normalise(); | ||||||
|  |  | ||||||
| 			// apply force to each end point | 			// apply force to each end point | ||||||
| 			spring.point1.applyForce(direction.multiply(spring.k * displacement * -0.5)); | 			spring.point1.applyForce(direction.multiply(spring.k * displacement * -0.5)); | ||||||
| @@ -442,7 +426,7 @@ | |||||||
|  |  | ||||||
| 	Layout.ForceDirected.prototype.attractToCentre = function() { | 	Layout.ForceDirected.prototype.attractToCentre = function() { | ||||||
| 		this.eachNode(function(node, point) { | 		this.eachNode(function(node, point) { | ||||||
| 			var direction = point.p.multiply(-1.0); | 			const direction = point.p.multiply(-1.0); | ||||||
| 			point.applyForce(direction.multiply(this.repulsion / 50.0)); | 			point.applyForce(direction.multiply(this.repulsion / 50.0)); | ||||||
| 		}); | 		}); | ||||||
| 	}; | 	}; | ||||||
| @@ -470,9 +454,9 @@ | |||||||
|  |  | ||||||
| 	// Calculate the total kinetic energy of the system | 	// Calculate the total kinetic energy of the system | ||||||
| 	Layout.ForceDirected.prototype.totalEnergy = function(timestep) { | 	Layout.ForceDirected.prototype.totalEnergy = function(timestep) { | ||||||
| 		var energy = 0.0; | 		let energy = 0.0; | ||||||
| 		this.eachNode(function(node, point) { | 		this.eachNode(function(node, point) { | ||||||
| 			var speed = point.v.magnitude(); | 			const speed = point.v.magnitude(); | ||||||
| 			energy += 0.5 * point.m * speed * speed; | 			energy += 0.5 * point.m * speed * speed; | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
| @@ -484,7 +468,7 @@ | |||||||
| 	 * In case it's running then the call is ignored, and none of the callbacks passed is ever executed. | 	 * In case it's running then the call is ignored, and none of the callbacks passed is ever executed. | ||||||
| 	 */ | 	 */ | ||||||
| 	Layout.ForceDirected.prototype.start = function(onRenderStop) { | 	Layout.ForceDirected.prototype.start = function(onRenderStop) { | ||||||
| 		var t = this; | 		const t = this; | ||||||
|  |  | ||||||
| 		if (this._started) return; | 		if (this._started) return; | ||||||
| 		this._started = true; | 		this._started = true; | ||||||
| @@ -493,6 +477,10 @@ | |||||||
| 		function step() { | 		function step() { | ||||||
| 			t.tick(0.03); | 			t.tick(0.03); | ||||||
|  |  | ||||||
|  | 			if (t.stopCheckerCallback()) { | ||||||
|  | 				onRenderStop(); | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			// stop simulation when energy of the system goes below a threshold | 			// stop simulation when energy of the system goes below a threshold | ||||||
| 			if (t._stop || t.totalEnergy() < t.minEnergyThreshold) { | 			if (t._stop || t.totalEnergy() < t.minEnergyThreshold) { | ||||||
| 				t._started = false; | 				t._started = false; | ||||||
| @@ -519,11 +507,11 @@ | |||||||
|  |  | ||||||
| 	// Find the nearest point to a particular position | 	// Find the nearest point to a particular position | ||||||
| 	Layout.ForceDirected.prototype.nearest = function(pos) { | 	Layout.ForceDirected.prototype.nearest = function(pos) { | ||||||
| 		var min = {node: null, point: null, distance: null}; | 		let min = {node: null, point: null, distance: null}; | ||||||
| 		var t = this; | 		const t = this; | ||||||
| 		this.graph.nodes.forEach(function(n){ | 		this.graph.nodes.forEach(function(n){ | ||||||
| 			var point = t.point(n); | 			const point = t.point(n); | ||||||
| 			var distance = point.p.subtract(pos).magnitude(); | 			const distance = point.p.subtract(pos).magnitude(); | ||||||
|  |  | ||||||
| 			if (min.distance === null || distance < min.distance) { | 			if (min.distance === null || distance < min.distance) { | ||||||
| 				min = {node: n, point: point, distance: distance}; | 				min = {node: n, point: point, distance: distance}; | ||||||
| @@ -535,8 +523,8 @@ | |||||||
|  |  | ||||||
| 	// returns [bottomleft, topright] | 	// returns [bottomleft, topright] | ||||||
| 	Layout.ForceDirected.prototype.getBoundingBox = function() { | 	Layout.ForceDirected.prototype.getBoundingBox = function() { | ||||||
| 		var bottomleft = new Vector(-2,-2); | 		const bottomleft = new Vector(-2, -2); | ||||||
| 		var topright = new Vector(2,2); | 		const topright = new Vector(2, 2); | ||||||
|  |  | ||||||
| 		this.eachNode(function(n, point) { | 		this.eachNode(function(n, point) { | ||||||
| 			if (point.p.x < bottomleft.x) { | 			if (point.p.x < bottomleft.x) { | ||||||
| @@ -553,14 +541,14 @@ | |||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
| 		var padding = topright.subtract(bottomleft).multiply(0.07); // ~5% padding | 		const padding = topright.subtract(bottomleft).multiply(0.07); // ~5% padding | ||||||
|  |  | ||||||
| 		return {bottomleft: bottomleft.subtract(padding), topright: topright.add(padding)}; | 		return {bottomleft: bottomleft.subtract(padding), topright: topright.add(padding)}; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  |  | ||||||
| 	// Vector | 	// Vector | ||||||
| 	var Vector = Springy.Vector = function(x, y) { | 	const Vector = Springy.Vector = function(x, y) { | ||||||
| 		this.x = x; | 		this.x = x; | ||||||
| 		this.y = y; | 		this.y = y; | ||||||
| 	}; | 	}; | ||||||
| @@ -629,10 +617,8 @@ | |||||||
| 	/** | 	/** | ||||||
| 	 * Renderer handles the layout rendering loop | 	 * Renderer handles the layout rendering loop | ||||||
| 	 */ | 	 */ | ||||||
| 	var Renderer = Springy.Renderer = function(layout, onRenderStop) { | 	const Renderer = Springy.Renderer = function (layout) { | ||||||
| 		this.layout = layout; | 		this.layout = layout; | ||||||
| 		this.onRenderStop = onRenderStop; |  | ||||||
|  |  | ||||||
| 		this.layout.graph.addGraphListener(this); | 		this.layout.graph.addGraphListener(this); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| @@ -657,8 +643,8 @@ | |||||||
| 		this.layout.stop(); | 		this.layout.stop(); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	var isEmpty = function(obj) { | 	const isEmpty = function(obj) { | ||||||
| 		for (var k in obj) { | 		for (const k in obj) { | ||||||
| 			if (obj.hasOwnProperty(k)) { | 			if (obj.hasOwnProperty(k)) { | ||||||
| 				return false; | 				return false; | ||||||
| 			} | 			} | ||||||
| @@ -667,4 +653,4 @@ | |||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|   return Springy; |   return Springy; | ||||||
| })); | }(); | ||||||
|   | |||||||
| @@ -29,6 +29,7 @@ import protectedSessionHolder from "./protected_session_holder.js"; | |||||||
| import bundleService from "./bundle.js"; | import bundleService from "./bundle.js"; | ||||||
| import DialogEventComponent from "./dialog_events.js"; | import DialogEventComponent from "./dialog_events.js"; | ||||||
| import Entrypoints from "./entrypoints.js"; | import Entrypoints from "./entrypoints.js"; | ||||||
|  | import CalendarWidget from "../widgets/calendar.js"; | ||||||
|  |  | ||||||
| class AppContext { | class AppContext { | ||||||
|     constructor() { |     constructor() { | ||||||
| @@ -98,6 +99,7 @@ class AppContext { | |||||||
|  |  | ||||||
|         const rightPaneWidgets = [ |         const rightPaneWidgets = [ | ||||||
|             new NoteInfoWidget(this), |             new NoteInfoWidget(this), | ||||||
|  |             new TabCachingWidget(this, () => new CalendarWidget(this)), | ||||||
|             new TabCachingWidget(this, () => new AttributesWidget(this)), |             new TabCachingWidget(this, () => new AttributesWidget(this)), | ||||||
|             new TabCachingWidget(this, () => new LinkMapWidget(this)), |             new TabCachingWidget(this, () => new LinkMapWidget(this)), | ||||||
|             new TabCachingWidget(this, () => new NoteRevisionsWidget(this)), |             new TabCachingWidget(this, () => new NoteRevisionsWidget(this)), | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ import treeCache from './tree_cache.js'; | |||||||
| import noteTooltipService from './note_tooltip.js'; | import noteTooltipService from './note_tooltip.js'; | ||||||
| import protectedSessionService from './protected_session.js'; | import protectedSessionService from './protected_session.js'; | ||||||
| import dateNotesService from './date_notes.js'; | import dateNotesService from './date_notes.js'; | ||||||
| import CollapsibleWidget from '../widgets/standard_widget.js'; | import CollapsibleWidget from '../widgets/collapsible_widget.js'; | ||||||
| import ws from "./ws.js"; | import ws from "./ws.js"; | ||||||
| import hoistedNoteService from "./hoisted_note.js"; | import hoistedNoteService from "./hoisted_note.js"; | ||||||
| import appContext from "./app_context.js"; | import appContext from "./app_context.js"; | ||||||
|   | |||||||
| @@ -19,7 +19,8 @@ export default class LinkMap { | |||||||
|         this.options = Object.assign({ |         this.options = Object.assign({ | ||||||
|             maxDepth: 10, |             maxDepth: 10, | ||||||
|             maxNotes: 30, |             maxNotes: 30, | ||||||
|             zoom: 1.0 |             zoom: 1.0, | ||||||
|  |             stopCheckerCallback: () => false | ||||||
|         }, options); |         }, options); | ||||||
|  |  | ||||||
|         this.$linkMapContainer = $linkMapContainer; |         this.$linkMapContainer = $linkMapContainer; | ||||||
| @@ -30,6 +31,10 @@ export default class LinkMap { | |||||||
|         await libraryLoader.requireLibrary(libraryLoader.LINK_MAP); |         await libraryLoader.requireLibrary(libraryLoader.LINK_MAP); | ||||||
|  |  | ||||||
|         jsPlumb.ready(() => { |         jsPlumb.ready(() => { | ||||||
|  |             if (this.options.stopCheckerCallback()) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             this.initJsPlumbInstance(); |             this.initJsPlumbInstance(); | ||||||
|  |  | ||||||
|             this.initPanZoom(); |             this.initPanZoom(); | ||||||
| @@ -43,6 +48,10 @@ export default class LinkMap { | |||||||
|  |  | ||||||
|         this.cleanup(); |         this.cleanup(); | ||||||
|  |  | ||||||
|  |         if (this.options.stopCheckerCallback()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         const links = await server.post(`notes/${this.note.noteId}/link-map`, { |         const links = await server.post(`notes/${this.note.noteId}/link-map`, { | ||||||
|             maxNotes: this.options.maxNotes, |             maxNotes: this.options.maxNotes, | ||||||
|             maxDepth: this.options.maxDepth |             maxDepth: this.options.maxDepth | ||||||
| @@ -63,6 +72,7 @@ export default class LinkMap { | |||||||
|  |  | ||||||
|         const layout = new Springy.Layout.ForceDirected( |         const layout = new Springy.Layout.ForceDirected( | ||||||
|             graph, |             graph, | ||||||
|  |             this.options.stopCheckerCallback, | ||||||
|             // param explanation here: https://github.com/dhotson/springy/issues/58 |             // param explanation here: https://github.com/dhotson/springy/issues/58 | ||||||
|             400.0, // Spring stiffness |             400.0, // Spring stiffness | ||||||
|             600.0, // Node repulsion |             600.0, // Node repulsion | ||||||
| @@ -122,6 +132,10 @@ export default class LinkMap { | |||||||
|             return $noteBox; |             return $noteBox; | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  |         if (this.options.stopCheckerCallback()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         this.renderer = new Springy.Renderer(layout); |         this.renderer = new Springy.Renderer(layout); | ||||||
|         await this.renderer.start(500); |         await this.renderer.start(500); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -461,7 +461,7 @@ async function duplicateNote(noteId, parentNoteId) { | |||||||
|  |  | ||||||
|     await ws.waitForMaxKnownSyncId(); |     await ws.waitForMaxKnownSyncId(); | ||||||
|  |  | ||||||
|     await activateNote(note.noteId); |     await appContext.activateOrOpenNote(note.noteId); | ||||||
|  |  | ||||||
|     const origNote = await treeCache.getNote(noteId); |     const origNote = await treeCache.getNote(noteId); | ||||||
|     toastService.showMessage(`Note "${origNote.title}" has been duplicated`); |     toastService.showMessage(`Note "${origNote.title}" has been duplicated`); | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import utils from "../services/utils.js"; | import utils from "../services/utils.js"; | ||||||
| import linkService from "../services/link.js"; | import linkService from "../services/link.js"; | ||||||
| import ws from "../services/ws.js"; | import ws from "../services/ws.js"; | ||||||
| import CollapsibleWidget from "./standard_widget.js"; | import CollapsibleWidget from "./collapsible_widget.js"; | ||||||
|  |  | ||||||
| class AttributesWidget extends CollapsibleWidget { | class AttributesWidget extends CollapsibleWidget { | ||||||
|     getWidgetTitle() { return "Attributes"; } |     getWidgetTitle() { return "Attributes"; } | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import CollapsibleWidget from "./standard_widget.js"; | import CollapsibleWidget from "./collapsible_widget.js"; | ||||||
| import libraryLoader from "../services/library_loader.js"; | import libraryLoader from "../services/library_loader.js"; | ||||||
| import utils from "../services/utils.js"; | import utils from "../services/utils.js"; | ||||||
| import dateNoteService from "../services/date_notes.js"; | import dateNoteService from "../services/date_notes.js"; | ||||||
| @@ -10,7 +10,7 @@ const TPL = ` | |||||||
|   <div class="calendar-header"> |   <div class="calendar-header"> | ||||||
|     <button class="calendar-btn bx bx-left-arrow-alt" data-calendar-toggle="previous"></button> |     <button class="calendar-btn bx bx-left-arrow-alt" data-calendar-toggle="previous"></button> | ||||||
|  |  | ||||||
|     <div class="calendar-header__label" data-calendar-label="month"> |     <div class="calendar-header-label" data-calendar-label="month"> | ||||||
|       March 2017 |       March 2017 | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
| @@ -29,45 +29,29 @@ class CalendarWidget extends CollapsibleWidget { | |||||||
|  |  | ||||||
|     async isEnabled() { |     async isEnabled() { | ||||||
|         return await super.isEnabled() |         return await super.isEnabled() | ||||||
|             && await this.tabContext.note.hasLabel("dateNote"); |             && this.tabContext.note.hasOwnedLabel("dateNote"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async doRenderBody() { |     async doRenderBody() { | ||||||
|         await libraryLoader.requireLibrary(libraryLoader.CALENDAR_WIDGET); |         await libraryLoader.requireLibrary(libraryLoader.CALENDAR_WIDGET); | ||||||
|  |  | ||||||
|         this.$body.html(TPL); |         this.$body.html(TPL); | ||||||
|     } |  | ||||||
|  |  | ||||||
|     async refreshWithNote() { |         this.$month = this.$body.find('[data-calendar-area="month"]'); | ||||||
|         this.init(this.$body, await this.tabContext.note.getLabelValue("dateNote")); |         this.$next = this.$body.find('[data-calendar-toggle="next"]'); | ||||||
|     } |         this.$previous = this.$body.find('[data-calendar-toggle="previous"]'); | ||||||
|  |         this.$label = this.$body.find('[data-calendar-label="month"]'); | ||||||
|     init($el, activeDate) { |  | ||||||
|         this.activeDate = new Date(activeDate + "T12:00:00"); // attaching time fixes local timezone handling |  | ||||||
|         this.todaysDate = new Date(); |  | ||||||
|         this.date = new Date(this.activeDate.getTime()); |  | ||||||
|  |  | ||||||
|         this.$month = $el.find('[data-calendar-area="month"]'); |  | ||||||
|         this.$next = $el.find('[data-calendar-toggle="next"]'); |  | ||||||
|         this.$previous = $el.find('[data-calendar-toggle="previous"]'); |  | ||||||
|  |  | ||||||
|         this.$next.on('click', () => { |         this.$next.on('click', () => { | ||||||
|             this.clearCalendar(); |  | ||||||
|             this.date.setMonth(this.date.getMonth() + 1); |             this.date.setMonth(this.date.getMonth() + 1); | ||||||
|             this.createMonth(); |             this.createMonth(); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         this.$previous.on('click', () => { |         this.$previous.on('click', () => { | ||||||
|             this.clearCalendar(); |  | ||||||
|             this.date.setMonth(this.date.getMonth() - 1); |             this.date.setMonth(this.date.getMonth() - 1); | ||||||
|             this.createMonth(); |             this.createMonth(); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         this.$label = $el.find('[data-calendar-label="month"]'); |  | ||||||
|  |  | ||||||
|         this.date.setDate(1); |  | ||||||
|         this.createMonth(); |  | ||||||
|  |  | ||||||
|         this.$body.on('click', '.calendar-date', async ev => { |         this.$body.on('click', '.calendar-date', async ev => { | ||||||
|             const date = $(ev.target).closest('.calendar-date').attr('data-calendar-date'); |             const date = $(ev.target).closest('.calendar-date').attr('data-calendar-date'); | ||||||
|  |  | ||||||
| @@ -82,6 +66,19 @@ class CalendarWidget extends CollapsibleWidget { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async refreshWithNote(note) { | ||||||
|  |         this.init(this.$body, note.getOwnedLabelValue("dateNote")); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     init($el, activeDate) { | ||||||
|  |         this.activeDate = new Date(activeDate + "T12:00:00"); // attaching time fixes local timezone handling | ||||||
|  |         this.todaysDate = new Date(); | ||||||
|  |         this.date = new Date(this.activeDate.getTime()); | ||||||
|  |         this.date.setDate(1); | ||||||
|  |  | ||||||
|  |         this.createMonth(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     createDay(dateNotesForMonth, num, day) { |     createDay(dateNotesForMonth, num, day) { | ||||||
|         const $newDay = $('<a>') |         const $newDay = $('<a>') | ||||||
|             .addClass("calendar-date") |             .addClass("calendar-date") | ||||||
| @@ -113,7 +110,7 @@ class CalendarWidget extends CollapsibleWidget { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         $newDay.append($date); |         $newDay.append($date); | ||||||
|         this.$month.append($newDay); |         return $newDay; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     isEqual(a, b) { |     isEqual(a, b) { | ||||||
| @@ -126,14 +123,19 @@ class CalendarWidget extends CollapsibleWidget { | |||||||
|         const month = utils.formatDateISO(this.date).substr(0, 7); |         const month = utils.formatDateISO(this.date).substr(0, 7); | ||||||
|         const dateNotesForMonth = await server.get('date-notes/notes-for-month/' + month); |         const dateNotesForMonth = await server.get('date-notes/notes-for-month/' + month); | ||||||
|  |  | ||||||
|  |         this.$month.empty(); | ||||||
|  |  | ||||||
|         const currentMonth = this.date.getMonth(); |         const currentMonth = this.date.getMonth(); | ||||||
|         while (this.date.getMonth() === currentMonth) { |         while (this.date.getMonth() === currentMonth) { | ||||||
|             this.createDay( |             const $day = this.createDay( | ||||||
|                 dateNotesForMonth, |                 dateNotesForMonth, | ||||||
|                 this.date.getDate(), |                 this.date.getDate(), | ||||||
|                 this.date.getDay(), |                 this.date.getDay(), | ||||||
|                 this.date.getFullYear() |                 this.date.getFullYear() | ||||||
|             ); |             ); | ||||||
|  |  | ||||||
|  |             this.$month.append($day); | ||||||
|  |  | ||||||
|             this.date.setDate(this.date.getDate() + 1); |             this.date.setDate(this.date.getDate() + 1); | ||||||
|         } |         } | ||||||
|         // while loop trips over and day is at 30/31, bring it back |         // while loop trips over and day is at 30/31, bring it back | ||||||
| @@ -159,10 +161,6 @@ class CalendarWidget extends CollapsibleWidget { | |||||||
|             'December' |             'December' | ||||||
|         ][monthIndex]; |         ][monthIndex]; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     clearCalendar() { |  | ||||||
|         this.$month.html(''); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| export default CalendarWidget; | export default CalendarWidget; | ||||||
| @@ -1,4 +1,3 @@ | |||||||
| import utils from "../services/utils.js"; |  | ||||||
| import TabAwareWidget from "./tab_aware_widget.js"; | import TabAwareWidget from "./tab_aware_widget.js"; | ||||||
|  |  | ||||||
| const WIDGET_TPL = ` | const WIDGET_TPL = ` | ||||||
| @@ -21,7 +20,7 @@ const WIDGET_TPL = ` | |||||||
| </div> | </div> | ||||||
| `; | `; | ||||||
|  |  | ||||||
| class CollapsibleWidget extends TabAwareWidget { | export default class CollapsibleWidget extends TabAwareWidget { | ||||||
|     getWidgetTitle() { return "Untitled widget"; } |     getWidgetTitle() { return "Untitled widget"; } | ||||||
|  |  | ||||||
|     getHeaderActions() { return []; } |     getHeaderActions() { return []; } | ||||||
| @@ -30,7 +29,7 @@ class CollapsibleWidget extends TabAwareWidget { | |||||||
|  |  | ||||||
|     getMaxHeight() { return null; } |     getMaxHeight() { return null; } | ||||||
|  |  | ||||||
|     render() { |     doRender() { | ||||||
|         this.$widget = $(WIDGET_TPL); |         this.$widget = $(WIDGET_TPL); | ||||||
|         this.$widget.find('[data-target]').attr('data-target', "#" + this.componentId); |         this.$widget.find('[data-target]').attr('data-target', "#" + this.componentId); | ||||||
|  |  | ||||||
| @@ -69,23 +68,15 @@ class CollapsibleWidget extends TabAwareWidget { | |||||||
|         this.$headerActions = this.$widget.find('.widget-header-actions'); |         this.$headerActions = this.$widget.find('.widget-header-actions'); | ||||||
|         this.$headerActions.append(...this.getHeaderActions()); |         this.$headerActions.append(...this.getHeaderActions()); | ||||||
|  |  | ||||||
|         this.initialized = this.renderBody(); |         this.initialized = this.doRenderBody(); | ||||||
|  |  | ||||||
|         return this.$widget; |         return this.$widget; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async renderBody() { |  | ||||||
|         await this.doRenderBody(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** for overriding */ |     /** for overriding */ | ||||||
|     async doRenderBody() {} |     async doRenderBody() {} | ||||||
|  |  | ||||||
|     isExpanded() { |     isExpanded() { | ||||||
|         return this.$bodyWrapper.hasClass("show"); |         return this.$bodyWrapper.hasClass("show"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     cleanup() {} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| export default CollapsibleWidget; |  | ||||||
| @@ -1,9 +1,9 @@ | |||||||
| import CollapsibleWidget from "./standard_widget.js"; | import CollapsibleWidget from "./collapsible_widget.js"; | ||||||
| import linkService from "../services/link.js"; | import linkService from "../services/link.js"; | ||||||
| import server from "../services/server.js"; | import server from "../services/server.js"; | ||||||
| import treeCache from "../services/tree_cache.js"; | import treeCache from "../services/tree_cache.js"; | ||||||
|  |  | ||||||
| class EditedNotesWidget extends CollapsibleWidget { | export default class EditedNotesWidget extends CollapsibleWidget { | ||||||
|     getWidgetTitle() { return "Edited notes on this day"; } |     getWidgetTitle() { return "Edited notes on this day"; } | ||||||
|  |  | ||||||
|     getHelp() { |     getHelp() { | ||||||
| @@ -19,8 +19,7 @@ class EditedNotesWidget extends CollapsibleWidget { | |||||||
|             && await this.tabContext.note.hasLabel("dateNote"); |             && await this.tabContext.note.hasLabel("dateNote"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async refreshWithNote() { |     async refreshWithNote(note) { | ||||||
|         const note = this.tabContext.note; |  | ||||||
|         // remember which title was when we found the similar notes |         // remember which title was when we found the similar notes | ||||||
|         this.title = note.title; |         this.title = note.title; | ||||||
|         let editedNotes = await server.get('edited-notes/' + await note.getLabelValue("dateNote")); |         let editedNotes = await server.get('edited-notes/' + await note.getLabelValue("dateNote")); | ||||||
| @@ -54,5 +53,3 @@ class EditedNotesWidget extends CollapsibleWidget { | |||||||
|         this.$body.empty().append($list); |         this.$body.empty().append($list); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| export default EditedNotesWidget; |  | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| import CollapsibleWidget from "./standard_widget.js"; | import CollapsibleWidget from "./collapsible_widget.js"; | ||||||
|  |  | ||||||
| let linkMapContainerIdCtr = 1; | let linkMapContainerIdCtr = 1; | ||||||
|  |  | ||||||
| @@ -28,7 +28,7 @@ class LinkMapWidget extends CollapsibleWidget { | |||||||
|         return [$showFullButton]; |         return [$showFullButton]; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async refreshWithNote() { |     async refreshWithNote(note) { | ||||||
|         this.$body.css('opacity', 0); |         this.$body.css('opacity', 0); | ||||||
|         this.$body.html(TPL); |         this.$body.html(TPL); | ||||||
|  |  | ||||||
| @@ -38,9 +38,10 @@ class LinkMapWidget extends CollapsibleWidget { | |||||||
|  |  | ||||||
|         const LinkMapServiceClass = (await import('../services/link_map.js')).default; |         const LinkMapServiceClass = (await import('../services/link_map.js')).default; | ||||||
|  |  | ||||||
|         this.linkMapService = new LinkMapServiceClass(this.tabContext.note, $linkMapContainer, { |         this.linkMapService = new LinkMapServiceClass(note, $linkMapContainer, { | ||||||
|             maxDepth: 1, |             maxDepth: 1, | ||||||
|             zoom: 0.6 |             zoom: 0.6, | ||||||
|  |             stopCheckerCallback: () => this.noteId !== note.noteId // stop when current note is not what was originally requested | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         await this.linkMapService.render(); |         await this.linkMapService.render(); | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import CollapsibleWidget from "./standard_widget.js"; | import CollapsibleWidget from "./collapsible_widget.js"; | ||||||
|  |  | ||||||
| const TPL = ` | const TPL = ` | ||||||
| <table class="note-info-widget-table"> | <table class="note-info-widget-table"> | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import server from "../services/server.js"; | import server from "../services/server.js"; | ||||||
| import CollapsibleWidget from "./standard_widget.js"; | import CollapsibleWidget from "./collapsible_widget.js"; | ||||||
|  |  | ||||||
| const TPL = ` | const TPL = ` | ||||||
| <ul class="note-revision-list" style="max-height: 150px; overflow: auto;"> | <ul class="note-revision-list" style="max-height: 150px; overflow: auto;"> | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import CollapsibleWidget from "./standard_widget.js"; | import CollapsibleWidget from "./collapsible_widget.js"; | ||||||
| import linkService from "../services/link.js"; | import linkService from "../services/link.js"; | ||||||
| import server from "../services/server.js"; | import server from "../services/server.js"; | ||||||
| import treeCache from "../services/tree_cache.js"; | import treeCache from "../services/tree_cache.js"; | ||||||
|   | |||||||
| @@ -43,10 +43,22 @@ export default class TabAwareWidget extends BasicWidget { | |||||||
|         this.refresh(); |         this.refresh(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     refresh() { |     async isEnabled() { | ||||||
|         if (this.note) { |         return !!this.note; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async refresh() { | ||||||
|  |         if (await this.isEnabled()) { | ||||||
|  |             const start = Date.now(); | ||||||
|  |  | ||||||
|             this.toggle(true); |             this.toggle(true); | ||||||
|             this.refreshWithNote(this.note, this.notePath); |             await this.refreshWithNote(this.note, this.notePath); | ||||||
|  |  | ||||||
|  |             const end = Date.now(); | ||||||
|  |  | ||||||
|  |             if (end - start > 10) { | ||||||
|  |                 console.log(`Refresh of ${this.componentId} took ${end-start}ms`); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             this.toggle(false); |             this.toggle(false); | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import CollapsibleWidget from "./standard_widget.js"; | import CollapsibleWidget from "./collapsible_widget.js"; | ||||||
| import linkService from "../services/link.js"; | import linkService from "../services/link.js"; | ||||||
|  |  | ||||||
| class WhatLinksHereWidget extends CollapsibleWidget { | class WhatLinksHereWidget extends CollapsibleWidget { | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ | |||||||
|   padding: 0 0.5rem 0.5rem 0.5rem; |   padding: 0 0.5rem 0.5rem 0.5rem; | ||||||
| } | } | ||||||
|  |  | ||||||
| .calendar-widget .calendar-header__label { | .calendar-widget .calendar-header-label { | ||||||
|   font-weight: bold; |   font-weight: bold; | ||||||
|   text-align: center; |   text-align: center; | ||||||
|   width: 100%; |   width: 100%; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user