Null point check enforcement

This commit is contained in:
Paulo Gustavo Veiga 2022-11-29 21:48:53 -08:00
parent d3159d8a20
commit 74a50dd639
10 changed files with 176 additions and 123 deletions

View File

@ -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);

View File

@ -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,28 +47,31 @@ class DesignerUndoManager {
this._redoQueue = [];
}
execUndo(commandContext: CommandContext) {
execUndo(commandContext: CommandContext): void {
if (this._undoQueue.length > 0) {
const command = this._undoQueue.pop();
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();
if (command) {
this._undoQueue.push(command);
command.execute(commandContext);
}
}
}
buildEvent() {
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) {

View File

@ -48,19 +48,26 @@ class LocalStorageManager extends PersistenceManager {
loadMapDom(mapId: string): Promise<Document> {
let result: Promise<Document>;
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: {
headers:
csrfToken != null
? {
'Content-Type': 'text/plain',
Accept: 'application/xml',
'X-CSRF-Token': csrfToken,
}
: {
'Content-Type': 'text/plain',
Accept: 'application/xml',
'X-CSRF-Token': this.getCSRFToken(),
},
})
.then((response: Response) => {

View File

@ -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,7 +57,6 @@ class RelationshipPivot {
this.dispose();
this._sourceTopic = sourceTopic;
if (sourceTopic != null) {
this._workspace.enableWorkspaceEvents(false);
const sourcePos = sourceTopic.getPosition();
@ -91,7 +90,6 @@ class RelationshipPivot {
topic.addEvent('ontfocus', this._onTopicClick);
});
}
}
dispose(): void {
const workspace = this._workspace;
@ -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();

View File

@ -59,14 +59,20 @@ 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: {
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',
'X-CSRF-Token': this.getCSRFToken(),
},
})
.then(async (response: Response) => {
@ -74,7 +80,7 @@ class RESTPersistenceManager extends PersistenceManager {
events.onSuccess();
} else {
console.log(`Saving error: ${response.status}`);
let userMsg;
let userMsg: PersistenceError | null = null;
if (response.status === 405) {
userMsg = {
severity: 'SEVERE',
@ -85,19 +91,21 @@ 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);
}
}
if (userMsg) {
this.triggerError(userMsg);
events.onError(userMsg);
}
}
// Clear event timeout ...
if (persistence.clearTimeout) {
@ -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: {
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',
'X-CSRF-Token': this.getCSRFToken(),
},
});
}
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,12 +181,18 @@ class RESTPersistenceManager extends PersistenceManager {
loadMapDom(mapId: string): Promise<Document> {
const url = `${this.documentUrl.replace('{id}', mapId)}/xml`;
const csrfToken = this.getCSRFToken();
return fetch(url, {
method: 'get',
headers: {
headers: csrfToken
? {
'Content-Type': 'text/plain',
Accept: 'application/xml',
'X-CSRF-Token': csrfToken,
}
: {
'Content-Type': 'text/plain',
Accept: 'application/xml',
'X-CSRF-Token': this.getCSRFToken(),
},
})
.then((response: Response) => {

View File

@ -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);

View File

@ -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;
}
}

View File

@ -77,7 +77,7 @@ class BinaryImageExporter extends Exporter {
const img = new Image();
const result = new Promise<string>((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);

View File

@ -22,7 +22,7 @@ import Font from './freemind/Font';
class FreemindExporter extends Exporter {
private mindmap: Mindmap;
private nodeMap: Map<number, FreeminNode> = null;
private nodeMap: Map<number, FreeminNode>;
private version: VersionNumber = FreemindConstant.SUPPORTED_FREEMIND_VERSION;
@ -87,13 +87,16 @@ class FreemindExporter extends Exporter {
const relationships: Array<RelationshipModel> = 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);
}

View File

@ -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,22 +99,28 @@ export default class FreemindImporter extends Importer {
// Fix dest ID
const destId: string = relationship.getDestCtrlPoint();
const destTopic: NodeModel = this.nodesmap.get(destId);
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);
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) {
@ -145,6 +152,7 @@ export default class FreemindImporter extends Importer {
}
}
}
}
private convertNodeProperties(
freeNode: FreemindNode,
@ -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() || '';
}
}