diff --git a/packages/mindplot/src/components/ConnectionLine.ts b/packages/mindplot/src/components/ConnectionLine.ts index cc223f4f..1131ecfd 100644 --- a/packages/mindplot/src/components/ConnectionLine.ts +++ b/packages/mindplot/src/components/ConnectionLine.ts @@ -72,7 +72,7 @@ class ConnectionLine { protected _createLine(lineTypeParam: number, defaultStyle: number): Line { const lineType = $defined(lineTypeParam) ? lineTypeParam : defaultStyle; this._lineType = lineType; - let line = null; + let line: ConnectionLine; switch (lineType) { case ConnectionLine.POLYLINE: line = new PolyLine(); @@ -82,7 +82,7 @@ class ConnectionLine { break; case ConnectionLine.SIMPLE_CURVED: line = new CurvedLine(); - line.setStyle(CurvedLine.SIMPLE_LINE); + (line as CurvedLine).setStyle(CurvedLine.SIMPLE_LINE); break; default: line = new Line(); @@ -141,7 +141,7 @@ class ConnectionLine { y -= offset; const connector = targetTopic.getShrinkConnector(); - if ($defined(connector)) { + if (connector) { if (Math.sign(targetPosition.x) > 0) { x = targetTopicSize.width; connector.setPosition(x, y); diff --git a/packages/mindplot/src/components/DesignerUndoManager.ts b/packages/mindplot/src/components/DesignerUndoManager.ts index f81934be..7078585c 100644 --- a/packages/mindplot/src/components/DesignerUndoManager.ts +++ b/packages/mindplot/src/components/DesignerUndoManager.ts @@ -32,7 +32,7 @@ class DesignerUndoManager { this._baseId = 0; } - enqueue(command: Command) { + enqueue(command: Command): void { $assert(command, 'Command can not be null'); const { length } = this._undoQueue; if (command.getDiscardDuplicated() && length > 0) { @@ -47,20 +47,23 @@ class DesignerUndoManager { this._redoQueue = []; } - execUndo(commandContext: CommandContext) { + execUndo(commandContext: CommandContext): void { if (this._undoQueue.length > 0) { const command = this._undoQueue.pop(); - this._redoQueue.push(command); - - command.undoExecute(commandContext); + if (command) { + this._redoQueue.push(command); + command.undoExecute(commandContext); + } } } - execRedo(commandContext) { + execRedo(commandContext: CommandContext): void { if (this._redoQueue.length > 0) { const command = this._redoQueue.pop(); - this._undoQueue.push(command); - command.execute(commandContext); + if (command) { + this._undoQueue.push(command); + command.execute(commandContext); + } } } @@ -68,7 +71,7 @@ class DesignerUndoManager { return { undoSteps: this._undoQueue.length, redoSteps: this._redoQueue.length }; } - markAsChangeBase() { + markAsChangeBase(): void { const undoLength = this._undoQueue.length; if (undoLength > 0) { const command = this._undoQueue[undoLength - 1]; @@ -78,7 +81,7 @@ class DesignerUndoManager { } } - hasBeenChanged() { + hasBeenChanged(): boolean { let result = true; const undoLength = this._undoQueue.length; if (undoLength === 0 && this._baseId === 0) { diff --git a/packages/mindplot/src/components/LocalStorageManager.ts b/packages/mindplot/src/components/LocalStorageManager.ts index b62d3091..e090e0e5 100644 --- a/packages/mindplot/src/components/LocalStorageManager.ts +++ b/packages/mindplot/src/components/LocalStorageManager.ts @@ -48,20 +48,27 @@ class LocalStorageManager extends PersistenceManager { loadMapDom(mapId: string): Promise { let result: Promise; - let localStorate; + let localStorate: string | null = null; if (!this.readOnly) { localStorate = localStorage.getItem(`${mapId}-xml`); } if (localStorate == null || this.forceLoad) { const url = this.documentUrl.replace('{id}', mapId); + const csrfToken = this.getCSRFToken(); result = fetch(url, { method: 'get', - headers: { - 'Content-Type': 'text/plain', - Accept: 'application/xml', - 'X-CSRF-Token': this.getCSRFToken(), - }, + headers: + csrfToken != null + ? { + 'Content-Type': 'text/plain', + Accept: 'application/xml', + 'X-CSRF-Token': csrfToken, + } + : { + 'Content-Type': 'text/plain', + Accept: 'application/xml', + }, }) .then((response: Response) => { if (!response.ok) { diff --git a/packages/mindplot/src/components/RelationshipPivot.ts b/packages/mindplot/src/components/RelationshipPivot.ts index fc42bca6..9067af26 100644 --- a/packages/mindplot/src/components/RelationshipPivot.ts +++ b/packages/mindplot/src/components/RelationshipPivot.ts @@ -34,7 +34,7 @@ class RelationshipPivot { private _onTopicClick: (event: MouseEvent) => void; - private _sourceTopic: Topic; + private _sourceTopic: Topic | null; private _pivot: CurvedLine; @@ -46,8 +46,8 @@ class RelationshipPivot { this._workspace = workspace; this._designer = designer; - this._mouseMoveEvent = this._mouseMove.bind(this); - this._onClickEvent = this._cleanOnMouseClick.bind(this); + this._mouseMoveEvent = this.mouseMoveHandler.bind(this); + this._onClickEvent = this.cleanOnMouseClick.bind(this); this._onTopicClick = this._connectOnFocus.bind(this); } @@ -57,40 +57,38 @@ class RelationshipPivot { this.dispose(); this._sourceTopic = sourceTopic; - if (sourceTopic != null) { - this._workspace.enableWorkspaceEvents(false); + this._workspace.enableWorkspaceEvents(false); - const sourcePos = sourceTopic.getPosition(); - const strokeColor = Relationship.getStrokeColor(); + const sourcePos = sourceTopic.getPosition(); + const strokeColor = Relationship.getStrokeColor(); - this._pivot = new CurvedLine(); - this._pivot.setStyle(CurvedLine.SIMPLE_LINE); + this._pivot = new CurvedLine(); + this._pivot.setStyle(CurvedLine.SIMPLE_LINE); - const fromPos = this._calculateFromPosition(sourcePos); - this._pivot.setFrom(fromPos.x, fromPos.y); + const fromPos = this._calculateFromPosition(sourcePos); + this._pivot.setFrom(fromPos.x, fromPos.y); - this._pivot.setTo(targetPos.x, targetPos.y); - this._pivot.setStroke(2, 'solid', strokeColor); - this._pivot.setDashed(4, 2); + this._pivot.setTo(targetPos.x, targetPos.y); + this._pivot.setStroke(2, 'solid', strokeColor); + this._pivot.setDashed(4, 2); - this._startArrow = new Arrow(); - this._startArrow.setStrokeColor(strokeColor); - this._startArrow.setStrokeWidth(2); - this._startArrow.setFrom(sourcePos.x, sourcePos.y); + this._startArrow = new Arrow(); + this._startArrow.setStrokeColor(strokeColor); + this._startArrow.setStrokeWidth(2); + this._startArrow.setFrom(sourcePos.x, sourcePos.y); - this._workspace.append(this._pivot); - this._workspace.append(this._startArrow); + this._workspace.append(this._pivot); + this._workspace.append(this._startArrow); - this._workspace.addEvent('mousemove', this._mouseMoveEvent); - this._workspace.addEvent('click', this._onClickEvent); + this._workspace.addEvent('mousemove', this._mouseMoveEvent); + this._workspace.addEvent('click', this._onClickEvent); - // Register focus events on all topics ... - const model = this._designer.getModel(); - const topics = model.getTopics(); - topics.forEach((topic) => { - topic.addEvent('ontfocus', this._onTopicClick); - }); - } + // Register focus events on all topics ... + const model = this._designer.getModel(); + const topics = model.getTopics(); + topics.forEach((topic) => { + topic.addEvent('ontfocus', this._onTopicClick); + }); } dispose(): void { @@ -117,12 +115,12 @@ class RelationshipPivot { } } - _mouseMove(event: MouseEvent): boolean { + private mouseMoveHandler(event: MouseEvent): boolean { const screen = this._workspace.getScreenManager(); const pos = screen.getWorkspaceMousePosition(event); // Leave the arrow a couple of pixels away from the cursor. - const sourcePosition = this._sourceTopic.getPosition(); + const sourcePosition = this._sourceTopic!.getPosition(); const gapDistance = Math.sign(pos.x - sourcePosition.x) * 5; const sPos = this._calculateFromPosition(pos); @@ -139,7 +137,7 @@ class RelationshipPivot { return false; } - _cleanOnMouseClick(event: MouseEvent): void { + private cleanOnMouseClick(event: MouseEvent): void { // The user clicks on a desktop on in other element that is not a node. this.dispose(); event.stopPropagation(); @@ -147,8 +145,8 @@ class RelationshipPivot { private _calculateFromPosition(toPosition: Point): Point { // Calculate origin position ... - let sourcePosition = this._sourceTopic.getPosition(); - if (this._sourceTopic.getType() === 'CentralTopic') { + let sourcePosition = this._sourceTopic!.getPosition(); + if (this._sourceTopic!.getType() === 'CentralTopic') { sourcePosition = Shape.workoutIncomingConnectionPoint(this._sourceTopic, toPosition); } const controlPoint = Shape.calculateDefaultControlPoints(sourcePosition, toPosition); @@ -164,8 +162,8 @@ class RelationshipPivot { const mindmap = this._designer.getMindmap(); // Avoid circular connections ... - if (targetTopic.getId() !== sourceTopic.getId()) { - const relModel = mindmap.createRelationship(targetTopic.getId(), sourceTopic.getId()); + if (targetTopic.getId() !== sourceTopic!.getId()) { + const relModel = mindmap.createRelationship(targetTopic.getId(), sourceTopic!.getId()); this._designer.getActionDispatcher().addRelationship(relModel); } this.dispose(); diff --git a/packages/mindplot/src/components/RestPersistenceManager.ts b/packages/mindplot/src/components/RestPersistenceManager.ts index 91dce1cf..c0c8f227 100644 --- a/packages/mindplot/src/components/RestPersistenceManager.ts +++ b/packages/mindplot/src/components/RestPersistenceManager.ts @@ -59,22 +59,28 @@ class RESTPersistenceManager extends PersistenceManager { }, 10000); const persistence = this; + const crfs = this.getCSRFToken(); fetch(`${this.documentUrl.replace('{id}', mapId)}?${query}`, { method: 'PUT', // Blob helps to resuce the memory on large payload. body: new Blob([JSON.stringify(data)], { type: 'text/plain' }), - headers: { - 'Content-Type': 'application/json; charset=utf-8', - Accept: 'application/json', - 'X-CSRF-Token': this.getCSRFToken(), - }, + headers: crfs + ? { + 'Content-Type': 'application/json; charset=utf-8', + Accept: 'application/json', + 'X-CSRF-Token': crfs, + } + : { + 'Content-Type': 'application/json; charset=utf-8', + Accept: 'application/json', + }, }) .then(async (response: Response) => { if (response.ok) { events.onSuccess(); } else { console.log(`Saving error: ${response.status}`); - let userMsg; + let userMsg: PersistenceError | null = null; if (response.status === 405) { userMsg = { severity: 'SEVERE', @@ -85,18 +91,20 @@ class RESTPersistenceManager extends PersistenceManager { const responseText = await response.text(); const contentType = response.headers['Content-Type']; if (contentType != null && contentType.indexOf('application/json') !== -1) { - let serverMsg = null; + let serverMsg: null | { globalSeverity: string } = null; try { serverMsg = JSON.parse(responseText); - serverMsg = serverMsg.globalSeverity ? serverMsg : null; + serverMsg = serverMsg && serverMsg.globalSeverity ? serverMsg : null; } catch (e) { // Message could not be decoded ... } userMsg = persistence._buildError(serverMsg); } } - this.triggerError(userMsg); - events.onError(userMsg); + if (userMsg) { + this.triggerError(userMsg); + events.onError(userMsg); + } } // Clear event timeout ... @@ -123,21 +131,36 @@ class RESTPersistenceManager extends PersistenceManager { } } - discardChanges(mapId: string) { + discardChanges(mapId: string): void { + const csrfToken = this.getCSRFToken(); + fetch(this.revertUrl.replace('{id}', mapId), { method: 'POST', - headers: { - 'Content-Type': 'application/json; charset=utf-8', - Accept: 'application/json', - 'X-CSRF-Token': this.getCSRFToken(), - }, + headers: csrfToken + ? { + 'Content-Type': 'application/json; charset=utf-8', + Accept: 'application/json', + 'X-CSRF-Token': csrfToken, + } + : { + 'Content-Type': 'application/json; charset=utf-8', + Accept: 'application/json', + }, }); } unlockMap(mapId: string): void { + const csrfToken = this.getCSRFToken(); fetch(this.lockUrl.replace('{id}', mapId), { method: 'PUT', - headers: { 'Content-Type': 'text/plain', 'X-CSRF-Token': this.getCSRFToken() }, + headers: csrfToken + ? { + 'Content-Type': 'text/plain', + 'X-CSRF-Token': csrfToken, + } + : { + 'Content-Type': 'text/plain', + }, body: 'false', }); } @@ -158,13 +181,19 @@ class RESTPersistenceManager extends PersistenceManager { loadMapDom(mapId: string): Promise { const url = `${this.documentUrl.replace('{id}', mapId)}/xml`; + const csrfToken = this.getCSRFToken(); return fetch(url, { method: 'get', - headers: { - 'Content-Type': 'text/plain', - Accept: 'application/xml', - 'X-CSRF-Token': this.getCSRFToken(), - }, + headers: csrfToken + ? { + 'Content-Type': 'text/plain', + Accept: 'application/xml', + 'X-CSRF-Token': csrfToken, + } + : { + 'Content-Type': 'text/plain', + Accept: 'application/xml', + }, }) .then((response: Response) => { if (!response.ok) { diff --git a/packages/mindplot/src/components/commands/AddTopicCommand.ts b/packages/mindplot/src/components/commands/AddTopicCommand.ts index e94386cf..8b5f6a3b 100644 --- a/packages/mindplot/src/components/commands/AddTopicCommand.ts +++ b/packages/mindplot/src/components/commands/AddTopicCommand.ts @@ -23,7 +23,7 @@ import NodeModel from '../model/NodeModel'; class AddTopicCommand extends Command { private _models: NodeModel[]; - private _parentsIds: number[]; + private _parentsIds: number[] | null; /** * @classdesc This command class handles do/undo of adding one or multiple topics to @@ -42,14 +42,13 @@ class AddTopicCommand extends Command { } execute(commandContext: CommandContext) { - const me = this; this._models.forEach((model, index) => { // Add a new topic ... const topic = commandContext.createTopic(model); // Connect to topic ... if (this._parentsIds) { - const parentId = me._parentsIds[index]; + const parentId = this._parentsIds[index]; if ($defined(parentId)) { const parentTopic = commandContext.findTopics([parentId])[0]; commandContext.connect(topic, parentTopic); diff --git a/packages/mindplot/src/components/commands/RemoveFeatureFromTopicCommand.ts b/packages/mindplot/src/components/commands/RemoveFeatureFromTopicCommand.ts index 234c24b9..242b8248 100644 --- a/packages/mindplot/src/components/commands/RemoveFeatureFromTopicCommand.ts +++ b/packages/mindplot/src/components/commands/RemoveFeatureFromTopicCommand.ts @@ -38,7 +38,6 @@ class RemoveFeatureFromTopicCommand extends Command { super(); this._topicId = topicId; this._featureId = featureId; - this._oldFeature = null; } /** @@ -48,7 +47,6 @@ class RemoveFeatureFromTopicCommand extends Command { const topic = commandContext.findTopics([this._topicId])[0]; const feature = topic.findFeatureById(this._featureId); topic.removeFeature(feature); - this._oldFeature = feature; } /** @@ -58,7 +56,6 @@ class RemoveFeatureFromTopicCommand extends Command { undoExecute(commandContext: CommandContext) { const topic = commandContext.findTopics([this._topicId])[0]; topic.addFeature(this._oldFeature); - this._oldFeature = null; } } diff --git a/packages/mindplot/src/components/export/BinaryImageExporter.ts b/packages/mindplot/src/components/export/BinaryImageExporter.ts index b573a40b..ba98b8e2 100644 --- a/packages/mindplot/src/components/export/BinaryImageExporter.ts +++ b/packages/mindplot/src/components/export/BinaryImageExporter.ts @@ -77,7 +77,7 @@ class BinaryImageExporter extends Exporter { const img = new Image(); const result = new Promise((resolve) => { img.onload = () => { - const ctx = canvas.getContext('2d'); + const ctx = canvas.getContext('2d')!; // Scale for retina ... ctx.scale(dpr, dpr); ctx.drawImage(img, 0, 0); diff --git a/packages/mindplot/src/components/export/FreemindExporter.ts b/packages/mindplot/src/components/export/FreemindExporter.ts index c9f669aa..e7a31b5d 100644 --- a/packages/mindplot/src/components/export/FreemindExporter.ts +++ b/packages/mindplot/src/components/export/FreemindExporter.ts @@ -22,7 +22,7 @@ import Font from './freemind/Font'; class FreemindExporter extends Exporter { private mindmap: Mindmap; - private nodeMap: Map = null; + private nodeMap: Map; private version: VersionNumber = FreemindConstant.SUPPORTED_FREEMIND_VERSION; @@ -87,13 +87,16 @@ class FreemindExporter extends Exporter { const relationships: Array = this.mindmap.getRelationships(); relationships.forEach((relationship: RelationshipModel) => { - const srcNode: FreeminNode = this.nodeMap.get(relationship.getFromNode()); - const destNode: FreeminNode = this.nodeMap.get(relationship.getToNode()); + const srcNode: FreeminNode | undefined = this.nodeMap.get(relationship.getFromNode()); + const destNode: FreeminNode | undefined = this.nodeMap.get(relationship.getToNode()); if (srcNode && destNode) { const arrowlink: Arrowlink = this.objectFactory.crateArrowlink(); - arrowlink.setDestination(destNode.getId()); + const idRel = destNode.getId(); + if (idRel) { + arrowlink.setDestination(idRel); + } if (relationship.getEndArrow() && relationship.getEndArrow()) { arrowlink.setEndarrow('Default'); @@ -287,7 +290,10 @@ class FreemindExporter extends Exporter { if (fontNodeNeeded) { if (!font.getSize()) { - font.setSize(FreemindExporter.wisweToFreeFontSize.get(8).toString()); + const size = FreemindExporter.wisweToFreeFontSize.get(8); + if (size) { + font.setSize(size.toString()); + } } freemindNode.setArrowlinkOrCloudOrEdge(font); } diff --git a/packages/mindplot/src/components/import/FreemindImporter.ts b/packages/mindplot/src/components/import/FreemindImporter.ts index 50aa621a..eca43a0a 100644 --- a/packages/mindplot/src/components/import/FreemindImporter.ts +++ b/packages/mindplot/src/components/import/FreemindImporter.ts @@ -19,6 +19,7 @@ import NoteModel from '../model/NoteModel'; import FeatureModelFactory from '../model/FeatureModelFactory'; import FeatureModel from '../model/FeatureModel'; import XMLSerializerFactory from '../persistence/XMLSerializerFactory'; +import { off } from 'process'; export default class FreemindImporter extends Importer { private mindmap: Mindmap; @@ -98,50 +99,57 @@ export default class FreemindImporter extends Importer { // Fix dest ID const destId: string = relationship.getDestCtrlPoint(); - const destTopic: NodeModel = this.nodesmap.get(destId); - relationship.setDestCtrlPoint(destTopic.getId()); + const destTopic: NodeModel | undefined = this.nodesmap.get(destId); + if (destTopic) { + relationship.setDestCtrlPoint(destTopic.getId()); + } // Fix src ID const srcId: string = relationship.getSrcCtrlPoint(); - const srcTopic: NodeModel = this.nodesmap.get(srcId); - relationship.setSrcCtrlPoint(srcTopic.getId()); + const srcTopic: NodeModel | undefined = this.nodesmap.get(srcId); + if (srcTopic) { + relationship.setSrcCtrlPoint(srcTopic.getId()); + } mapRelaitonship.push(relationship); }); } private fixRelationshipControlPoints(relationship: RelationshipModel): void { - const srcTopic: NodeModel = this.nodesmap.get(relationship.getToNode().toString()); - const destNode: NodeModel = this.nodesmap.get(relationship.getFromNode().toString()); + const srcTopic: NodeModel | undefined = this.nodesmap.get(relationship.getToNode().toString()); + const destNode: NodeModel | undefined = this.nodesmap.get( + relationship.getFromNode().toString(), + ); + if (srcTopic && destNode) { + // Fix x coord + const srcCtrlPoint: string = relationship.getSrcCtrlPoint(); + if (srcCtrlPoint) { + const coords = srcTopic.getPosition(); + if (coords.x < 0) { + const x = coords.x * -1; + relationship.setSrcCtrlPoint(`${x},${coords.y}`); - // Fix x coord - const srcCtrlPoint: string = relationship.getSrcCtrlPoint(); - if (srcCtrlPoint) { - const coords = srcTopic.getPosition(); - if (coords.x < 0) { - const x = coords.x * -1; - relationship.setSrcCtrlPoint(`${x},${coords.y}`); - - // Fix coord - if (srcTopic.getOrder() && srcTopic.getOrder() % 2 !== 0) { - const y = coords.y * -1; - relationship.setSrcCtrlPoint(`${coords.x},${y}`); + // Fix coord + if (srcTopic.getOrder() && srcTopic.getOrder() % 2 !== 0) { + const y = coords.y * -1; + relationship.setSrcCtrlPoint(`${coords.x},${y}`); + } } } - } - const destCtrlPoint: string = relationship.getDestCtrlPoint(); - if (destCtrlPoint) { - const coords = destNode.getPosition(); + const destCtrlPoint: string = relationship.getDestCtrlPoint(); + if (destCtrlPoint) { + const coords = destNode.getPosition(); - if (coords.x < 0) { - const x = coords.x * -1; - relationship.setDestCtrlPoint(`${x},${coords.y}`); - } + if (coords.x < 0) { + const x = coords.x * -1; + relationship.setDestCtrlPoint(`${x},${coords.y}`); + } - if (destNode.getOrder() && destNode.getOrder() % 2 !== 0) { - const y = coords.y * -1; - relationship.setDestCtrlPoint(`${coords.x},${y}`); + if (destNode.getOrder() && destNode.getOrder() % 2 !== 0) { + const y = coords.y * -1; + relationship.setDestCtrlPoint(`${coords.x},${y}`); + } } } } @@ -169,7 +177,7 @@ export default class FreemindImporter extends Importer { } // Check for style... - const fontStyle = this.generateFontStyle(freeNode, null); + const fontStyle = this.generateFontStyle(freeNode, undefined); if (fontStyle && fontStyle !== ';;;;') wiseTopic.setFontStyle(fontStyle); // Is there any link... @@ -200,7 +208,10 @@ export default class FreemindImporter extends Importer { const wiseId = this.getIdNode(child); const wiseChild = mindmap.createNode('MainTopic', wiseId); - this.nodesmap.set(child.getId(), wiseChild); + const id = child.getId(); + if (id !== null) { + this.nodesmap.set(id, wiseChild); + } let norder: number; if (depth !== 1) { @@ -347,7 +358,7 @@ export default class FreemindImporter extends Importer { this.idDefault++; idFreeToIdWise = this.idDefault; } else { - idFreeToIdWise = parseInt(id.split('_').pop(), 10); + idFreeToIdWise = parseInt(id.split('_').pop()!, 10); } } else { this.idDefault++; @@ -398,7 +409,10 @@ export default class FreemindImporter extends Importer { // Font family if (font) { - fontStyle.push(font.getName()); + const name = font.getName(); + if (name) { + fontStyle.push(name); + } } fontStyle.push(';'); @@ -485,6 +499,6 @@ export default class FreemindImporter extends Importer { private html2Text(content: string): string { const temporalDivElement = document.createElement('div'); temporalDivElement.innerHTML = content; - return temporalDivElement.textContent.trim() || temporalDivElement.innerText.trim() || ''; + return temporalDivElement.textContent?.trim() || temporalDivElement.innerText.trim() || ''; } }