Add string validation

This commit is contained in:
Paulo Gustavo Veiga 2023-01-13 22:33:17 -08:00
parent 1cf42269b7
commit 0194407c7c
76 changed files with 697 additions and 755 deletions

View File

@ -1,7 +1,7 @@
version: '3' version: '3'
services: services:
e2e: e2e:
image: cypress/included:12.3.0 image: cypress/included:12.2.0
container_name: wisemapping-integration-tests container_name: wisemapping-integration-tests
entrypoint: '/bin/sh -c "yarn install && yarn build && yarn test:integration"' entrypoint: '/bin/sh -c "yarn install && yarn build && yarn test:integration"'
working_dir: /e2e working_dir: /e2e

View File

@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", "baseUrl": "."
"module": "ES6", "module": "ES6",
}, },
"exclude": ["node_modules"] "exclude": ["node_modules"]

View File

@ -3,7 +3,7 @@
"src/**/*" "src/**/*"
], ],
"compilerOptions": { "compilerOptions": {
"jsx": "react", "jsx": "react-jsx",
"outDir": "./dist/", "outDir": "./dist/",
"sourceMap": true, "sourceMap": true,
"noImplicitAny": false, "noImplicitAny": false,
@ -13,8 +13,8 @@
"target": "es6", "target": "es6",
"allowJs": true, "allowJs": true,
"esModuleInterop": true, "esModuleInterop": true,
"declaration": true,
"strictNullChecks": false, "strictNullChecks": false,
"declaration": true,
"rootDirs": [ "rootDirs": [
"src", "src",
], ],

View File

@ -35,8 +35,6 @@ class ConnectionLine {
protected _sourceTopic: Topic; protected _sourceTopic: Topic;
protected _lineType: LineType;
protected _line: Line; protected _line: Line;
private _type: LineType; private _type: LineType;
@ -50,7 +48,7 @@ class ConnectionLine {
this._sourceTopic = sourceNode; this._sourceTopic = sourceNode;
this._type = type; this._type = type;
this._line = this.createLine(type); this._line = this.createLine(type);
this.updateColor(); this._color = this.updateColor();
} }
private _getCtrlPoints(sourceNode: Topic, targetNode: Topic) { private _getCtrlPoints(sourceNode: Topic, targetNode: Topic) {
@ -64,7 +62,6 @@ class ConnectionLine {
} }
protected createLine(lineType: LineType): ConnectionLine { protected createLine(lineType: LineType): ConnectionLine {
this._lineType = lineType;
let line: ConnectionLine; let line: ConnectionLine;
switch (lineType) { switch (lineType) {
case LineType.POLYLINE_MIDDLE: case LineType.POLYLINE_MIDDLE:
@ -88,7 +85,7 @@ class ConnectionLine {
return line; return line;
} }
private updateColor(): void { private updateColor(): string {
// In case that the main topic has changed the color, overwrite the main topic definiton. // In case that the main topic has changed the color, overwrite the main topic definiton.
let color = this._targetTopic.getConnectionColor(); let color = this._targetTopic.getConnectionColor();
if (this._targetTopic.isCentralTopic()) { if (this._targetTopic.isCentralTopic()) {
@ -96,7 +93,7 @@ class ConnectionLine {
} }
this._color = color; this._color = color;
switch (this._lineType) { switch (this._type) {
case LineType.POLYLINE_MIDDLE: case LineType.POLYLINE_MIDDLE:
this._line.setStroke(1, 'solid', color, 1); this._line.setStroke(1, 'solid', color, 1);
break; break;
@ -112,8 +109,9 @@ class ConnectionLine {
this._line.setFill(color, 1); this._line.setFill(color, 1);
break; break;
default: default:
throw new Error(`Unexpected line type. ${this._lineType}`); throw new Error(`Unexpected line type. ${this._type}`);
} }
return color;
} }
setVisibility(value: boolean, fade = 0): void { setVisibility(value: boolean, fade = 0): void {
@ -207,7 +205,7 @@ class ConnectionLine {
} }
getLineType(): number { getLineType(): number {
return this._lineType; return this._type;
} }
getLine(): Line { getLine(): Line {

View File

@ -58,7 +58,7 @@ import { TopicShapeType } from './model/INodeModel';
import { LineType } from './ConnectionLine'; import { LineType } from './ConnectionLine';
class Designer extends Events { class Designer extends Events {
private _mindmap: Mindmap; private _mindmap: Mindmap | null;
private _options: DesignerOptions; private _options: DesignerOptions;
@ -70,13 +70,13 @@ class Designer extends Events {
_eventBussDispatcher: EventBusDispatcher; _eventBussDispatcher: EventBusDispatcher;
private _dragManager: DragManager; private _dragManager!: DragManager;
private _relPivot: RelationshipPivot; private _relPivot: RelationshipPivot;
private _clipboard: NodeModel[]; private _clipboard: NodeModel[];
private _cleanScreen: () => void; private _cleanScreen!: () => void;
constructor(options: DesignerOptions, divElement: JQuery) { constructor(options: DesignerOptions, divElement: JQuery) {
super(); super();
@ -133,6 +133,7 @@ class Designer extends Events {
// Hack: There are static reference to designer variable. Needs to be reviewed. // Hack: There are static reference to designer variable. Needs to be reviewed.
globalThis.designer = this; globalThis.designer = this;
this._mindmap = null;
} }
private _registerWheelEvents(): void { private _registerWheelEvents(): void {
@ -539,7 +540,6 @@ class Designer extends Events {
} }
loadMap(mindmap: Mindmap): Promise<void> { loadMap(mindmap: Mindmap): Promise<void> {
$assert(mindmap, 'mindmapModel can not be null');
this._mindmap = mindmap; this._mindmap = mindmap;
this._workspace.enableQueueRender(true); this._workspace.enableQueueRender(true);
@ -587,7 +587,7 @@ class Designer extends Events {
} }
getMindmap(): Mindmap { getMindmap(): Mindmap {
return this._mindmap; return this._mindmap!;
} }
undo(): void { undo(): void {

View File

@ -16,7 +16,6 @@
* limitations under the License. * limitations under the License.
*/ */
import { Text, Group, ElementClass, Point } from '@wisemapping/web2d'; import { Text, Group, ElementClass, Point } from '@wisemapping/web2d';
import { $assert } from '@wisemapping/core-js';
import Icon from './Icon'; import Icon from './Icon';
import IconGroup from './IconGroup'; import IconGroup from './IconGroup';
@ -28,17 +27,15 @@ import ActionDispatcher from './ActionDispatcher';
class EmojiCharIcon implements Icon { class EmojiCharIcon implements Icon {
private element: ElementClass; private element: ElementClass;
private group: IconGroup; private _group: IconGroup | null;
private iconModel: SvgIconModel; private _iconModel: SvgIconModel;
private topic: Topic; private _topic: Topic;
constructor(topic: Topic, iconModel: SvgIconModel, readOnly: boolean) { constructor(topic: Topic, iconModel: SvgIconModel, readOnly: boolean) {
$assert(iconModel, 'iconModel can not be null'); this._iconModel = iconModel;
$assert(topic, 'topic can not be null'); this._topic = topic;
this.iconModel = iconModel;
this.topic = topic;
this.element = new Group({ this.element = new Group({
width: 90, width: 90,
@ -57,6 +54,7 @@ class EmojiCharIcon implements Icon {
if (!readOnly) { if (!readOnly) {
this.element.setCursor('pointer'); this.element.setCursor('pointer');
} }
this._group = null;
} }
getElement(): ElementClass { getElement(): ElementClass {
@ -64,19 +62,19 @@ class EmojiCharIcon implements Icon {
} }
setGroup(group: IconGroup) { setGroup(group: IconGroup) {
this.group = group; this._group = group;
} }
getGroup(): IconGroup { getGroup(): IconGroup {
return this.group; return this._group!;
} }
getSize(): SizeType { getSize(): SizeType {
return this.group.getSize(); return this._group!.getSize();
} }
getPosition(): Point { getPosition(): Point {
return this.group.getPosition(); return this._group!.getPosition();
} }
addEvent(type: string, fnc: (e: object) => void): void { addEvent(type: string, fnc: (e: object) => void): void {
@ -85,12 +83,12 @@ class EmojiCharIcon implements Icon {
remove() { remove() {
const actionDispatcher = ActionDispatcher.getInstance(); const actionDispatcher = ActionDispatcher.getInstance();
const featureId = this.iconModel.getId(); const featureId = this._iconModel.getId();
actionDispatcher.removeFeatureFromTopic(this.topic.getId(), featureId); actionDispatcher.removeFeatureFromTopic(this._topic.getId(), featureId);
} }
getModel(): SvgIconModel { getModel(): SvgIconModel {
return this.iconModel; return this._iconModel;
} }
} }

View File

@ -8,7 +8,7 @@ interface Icon {
setGroup(group: IconGroup): Group; setGroup(group: IconGroup): Group;
getGroup(): IconGroup; getGroup(): IconGroup | null;
getSize(): SizeType; getSize(): SizeType;

View File

@ -36,14 +36,11 @@ class IconGroup {
private _removeTip: IconGroupRemoveTip; private _removeTip: IconGroupRemoveTip;
private _iconSize: SizeType; private _iconSize: SizeType | null;
private _topicId: number; private _topicId: number;
constructor(topicId: number, iconSize: number) { constructor(topicId: number, iconSize: number) {
$assert($defined(topicId), 'topicId can not be null');
$assert($defined(iconSize), 'iconSize can not be null');
this._topicId = topicId; this._topicId = topicId;
this._icons = []; this._icons = [];
this._group = new Group({ this._group = new Group({
@ -57,6 +54,7 @@ class IconGroup {
this._removeTip = new IconGroupRemoveTip(this._group); this._removeTip = new IconGroupRemoveTip(this._group);
this.seIconSize(iconSize, iconSize); this.seIconSize(iconSize, iconSize);
this._registerListeners(); this._registerListeners();
this._iconSize = null;
} }
setPosition(x: number, y: number): void { setPosition(x: number, y: number): void {
@ -142,8 +140,6 @@ class IconGroup {
} }
private _removeIcon(icon: Icon) { private _removeIcon(icon: Icon) {
$assert(icon, 'icon can not be null');
this._removeTip.close(0); this._removeTip.close(0);
this._group.removeChild(icon.getElement()); this._group.removeChild(icon.getElement());
@ -174,11 +170,13 @@ class IconGroup {
} }
private _resize(iconsLength: number) { private _resize(iconsLength: number) {
if (this._iconSize) {
this._group.setSize(iconsLength * this._iconSize.width, this._iconSize.height); this._group.setSize(iconsLength * this._iconSize.width, this._iconSize.height);
const iconSize = ImageIcon.SIZE + IconGroup.ICON_PADDING * 2; const iconSize = ImageIcon.SIZE + IconGroup.ICON_PADDING * 2;
this._group.setCoordSize(iconsLength * iconSize, iconSize); this._group.setCoordSize(iconsLength * iconSize, iconSize);
} }
}
private _positionIcon(icon: Icon, order: number) { private _positionIcon(icon: Icon, order: number) {
const iconSize = ImageIcon.SIZE + IconGroup.ICON_PADDING * 2; const iconSize = ImageIcon.SIZE + IconGroup.ICON_PADDING * 2;

View File

@ -14,6 +14,7 @@ class IconGroupRemoveTip {
constructor(group: Group) { constructor(group: Group) {
$assert(group, 'group can not be null'); $assert(group, 'group can not be null');
this._group = group; this._group = group;
this._activeIcon = null;
} }
show(topicId: number, icon: ImageIcon) { show(topicId: number, icon: ImageIcon) {

View File

@ -25,13 +25,14 @@ import Icon from './Icon';
abstract class ImageIcon implements Icon { abstract class ImageIcon implements Icon {
private _image: Image; private _image: Image;
private _group: IconGroup; private _group: IconGroup | null;
constructor(url: string) { constructor(url: string) {
$assert(url, 'image url can not be null'); $assert(url, 'image url can not be null');
this._image = new Image(); this._image = new Image();
this._image.setHref(url); this._image.setHref(url);
this._image.setSize(ImageIcon.SIZE, ImageIcon.SIZE); this._image.setSize(ImageIcon.SIZE, ImageIcon.SIZE);
this._group = null;
} }
getElement(): ElementClass { getElement(): ElementClass {
@ -42,7 +43,7 @@ abstract class ImageIcon implements Icon {
this._group = group; this._group = group;
} }
getGroup(): IconGroup { getGroup(): IconGroup | null {
return this._group; return this._group;
} }

View File

@ -43,9 +43,9 @@ export type MindplotWebComponentInterface = {
class MindplotWebComponent extends HTMLElement { class MindplotWebComponent extends HTMLElement {
private _shadowRoot: ShadowRoot; private _shadowRoot: ShadowRoot;
private _designer: Designer; private _designer: Designer | null;
private saveRequired: boolean; private _saveRequired: boolean;
private _isLoaded: boolean; private _isLoaded: boolean;
@ -62,12 +62,15 @@ class MindplotWebComponent extends HTMLElement {
wrapper.setAttribute('id', 'mindplot'); wrapper.setAttribute('id', 'mindplot');
this._shadowRoot.appendChild(wrapper); this._shadowRoot.appendChild(wrapper);
this._isLoaded = false;
this._saveRequired = false;
this._designer = null;
} }
/** /**
* @returns the designer * @returns the designer
*/ */
getDesigner(): Designer { getDesigner(): Designer | null {
return this._designer; return this._designer;
} }
@ -124,24 +127,24 @@ class MindplotWebComponent extends HTMLElement {
} }
setSaveRequired(value: boolean) { setSaveRequired(value: boolean) {
this.saveRequired = value; this._saveRequired = value;
} }
getSaveRequired() { getSaveRequired() {
return this.saveRequired; return this._saveRequired;
} }
loadMap(id: string): Promise<void> { loadMap(id: string): Promise<void> {
const instance = PersistenceManager.getInstance(); const instance = PersistenceManager.getInstance();
return instance.load(id).then((mindmap) => this._designer.loadMap(mindmap)); return instance.load(id).then((mindmap) => this._designer!.loadMap(mindmap));
} }
save(saveHistory: boolean) { save(saveHistory: boolean) {
if (!saveHistory && !this.getSaveRequired()) return; if (!saveHistory && !this.getSaveRequired()) return;
console.log('Saving...'); console.log('Saving...');
// Load map content ... // Load map content ...
const mindmap = this._designer.getMindmap(); const mindmap = this._designer!.getMindmap();
const mindmapProp = this._designer.getMindmapProperties(); const mindmapProp = this._designer!.getMindmapProperties();
// Display save message .. // Display save message ..
if (saveHistory) { if (saveHistory) {
@ -166,7 +169,7 @@ class MindplotWebComponent extends HTMLElement {
} }
unlockMap() { unlockMap() {
const mindmap = this._designer.getMindmap(); const mindmap = this._designer!.getMindmap();
const persistenceManager = PersistenceManager.getInstance(); const persistenceManager = PersistenceManager.getInstance();
// If the map could not be loaded, partial map load could happen. // If the map could not be loaded, partial map load could happen.

View File

@ -256,31 +256,35 @@ class MultitTextEditor {
// eslint-disable-next-line no-use-before-define // eslint-disable-next-line no-use-before-define
private static instance: MultitTextEditor = new MultitTextEditor(); private static instance: MultitTextEditor = new MultitTextEditor();
private component: EditorComponent | null; private _component: EditorComponent | null;
constructor() {
this._component = null;
}
static getInstance(): MultitTextEditor { static getInstance(): MultitTextEditor {
return MultitTextEditor.instance; return MultitTextEditor.instance;
} }
isActive(): boolean { isActive(): boolean {
return this.component !== null; return this._component !== null;
} }
show(topic: Topic, textOverwrite?: string): void { show(topic: Topic, textOverwrite?: string): void {
// Is it active ? // Is it active ?
if (this.component) { if (this._component) {
console.error('Editor was already displayed. Please, clouse it'); console.error('Editor was already displayed. Please, clouse it');
this.component.close(false); this._component.close(false);
} }
// Create a new instance // Create a new instance
this.component = new EditorComponent(topic); this._component = new EditorComponent(topic);
this.component.show(textOverwrite); this._component.show(textOverwrite);
} }
close(update: boolean): void { close(update: boolean): void {
if (this.component) { if (this._component) {
this.component.close(update); this._component.close(update);
this.component = null; this._component = null;
} }
} }
} }

View File

@ -46,7 +46,7 @@ abstract class NodeGraph {
this._options = options; this._options = options;
this._mouseEvents = true; this._mouseEvents = true;
this.setModel(nodeModel); this._model = nodeModel;
this._onFocus = false; this._onFocus = false;
this._size = { width: 50, height: 20 }; this._size = { width: 50, height: 20 };
} }
@ -70,7 +70,6 @@ abstract class NodeGraph {
} }
get2DElement(): ElementClass { get2DElement(): ElementClass {
$assert(this._elem2d, 'NodeGraph has not been initialized properly');
return this._elem2d; return this._elem2d;
} }
@ -118,7 +117,7 @@ abstract class NodeGraph {
return this._model; return this._model;
} }
setModel(model: NodeModel) { setModel(model: NodeModel): void {
$assert(model, 'Model can not be null'); $assert(model, 'Model can not be null');
this._model = model; this._model = model;
} }

View File

@ -36,7 +36,7 @@ class ControlPivotLine {
private _pivotType: PivotType; private _pivotType: PivotType;
private _workspace: Workspace; private _workspace: Workspace | null;
private _relationship: Relationship; private _relationship: Relationship;
@ -93,6 +93,9 @@ class ControlPivotLine {
this._mouseMoveHandler = (e: MouseEvent) => this.mouseMoveHandler(e); this._mouseMoveHandler = (e: MouseEvent) => this.mouseMoveHandler(e);
this._mouseUpHandler = () => this.mouseUpHandler(); this._mouseUpHandler = () => this.mouseUpHandler();
this._mouseDownHandler = (event: MouseEvent) => this.mouseDownHandler(event); this._mouseDownHandler = (event: MouseEvent) => this.mouseDownHandler(event);
this._isVisible = false;
this._workspace = null;
} }
private mouseDownHandler(event: MouseEvent) { private mouseDownHandler(event: MouseEvent) {
@ -153,7 +156,7 @@ class ControlPivotLine {
} }
private mouseMoveHandler(event: MouseEvent) { private mouseMoveHandler(event: MouseEvent) {
const screen = this._workspace.getScreenManager(); const screen = this._workspace!.getScreenManager();
const mousePosition = screen.getWorkspaceMousePosition(event); const mousePosition = screen.getWorkspaceMousePosition(event);
// Update relatioship position ... // Update relatioship position ...
@ -213,8 +216,6 @@ class RelationshipControlPoints {
private _relationship: Relationship; private _relationship: Relationship;
private _relationshipLinePositions: [PositionType, PositionType];
constructor(relationship: Relationship) { constructor(relationship: Relationship) {
this._relationship = relationship; this._relationship = relationship;
const startControlLine = new ControlPivotLine( const startControlLine = new ControlPivotLine(
@ -278,10 +279,6 @@ class RelationshipControlPoints {
getControlPointPosition(pivotType: PivotType): PositionType { getControlPointPosition(pivotType: PivotType): PositionType {
return this._pivotLines[pivotType].getPosition(); return this._pivotLines[pivotType].getPosition();
} }
getRelationshipPosition(index: number): PositionType {
return { ...this._relationshipLinePositions[index] };
}
} }
export default RelationshipControlPoints; export default RelationshipControlPoints;

View File

@ -32,7 +32,7 @@ class RelationshipPivot {
private _onClickEvent: (event: MouseEvent) => void; private _onClickEvent: (event: MouseEvent) => void;
private _onTopicClick: (event: MouseEvent) => void; private _onTopicClick: (event: MouseEvent, targetTopic: Topic) => void;
private _sourceTopic: Topic | null; private _sourceTopic: Topic | null;
@ -49,6 +49,7 @@ class RelationshipPivot {
this._mouseMoveEvent = this.mouseMoveHandler.bind(this); this._mouseMoveEvent = this.mouseMoveHandler.bind(this);
this._onClickEvent = this.cleanOnMouseClick.bind(this); this._onClickEvent = this.cleanOnMouseClick.bind(this);
this._onTopicClick = this._connectOnFocus.bind(this); this._onTopicClick = this._connectOnFocus.bind(this);
this._sourceTopic = null;
} }
start(sourceTopic: Topic, targetPos: Point) { start(sourceTopic: Topic, targetPos: Point) {
@ -156,7 +157,7 @@ class RelationshipPivot {
return Shape.calculateRelationShipPointCoordinates(sourceTopic, point); return Shape.calculateRelationShipPointCoordinates(sourceTopic, point);
} }
private _connectOnFocus(event: string, targetTopic: Topic): void { private _connectOnFocus(event: MouseEvent, targetTopic: Topic): void {
const sourceTopic = this._sourceTopic; const sourceTopic = this._sourceTopic;
const mindmap = this._designer.getMindmap(); const mindmap = this._designer.getMindmap();

View File

@ -39,6 +39,7 @@ class RESTPersistenceManager extends PersistenceManager {
this.documentUrl = options.documentUrl; this.documentUrl = options.documentUrl;
this.revertUrl = options.revertUrl; this.revertUrl = options.revertUrl;
this.lockUrl = options.lockUrl; this.lockUrl = options.lockUrl;
this.onSave = false;
} }
saveMapXml(mapId: string, mapXml: Document, pref: string, saveHistory: boolean, events): void { saveMapXml(mapId: string, mapXml: Document, pref: string, saveHistory: boolean, events): void {

View File

@ -52,6 +52,7 @@ class ScreenManager {
event.preventDefault(); event.preventDefault();
}, },
); );
this._scale = 1;
} }
/** /**
@ -65,7 +66,6 @@ class ScreenManager {
} }
setScale(scale: number) { setScale(scale: number) {
$assert(scale, 'Screen scale can not be null');
this._scale = scale; this._scale = scale;
} }

View File

@ -157,7 +157,6 @@ class StandaloneActionDispatcher extends ActionDispatcher {
this.execute(command); this.execute(command);
} }
/** */
changeBackgroundColorToTopic(topicsIds: number[], color: string | undefined) { changeBackgroundColorToTopic(topicsIds: number[], color: string | undefined) {
const commandFunc = (topic: Topic, value: string | undefined) => { const commandFunc = (topic: Topic, value: string | undefined) => {
const result = topic.getBackgroundColor(); const result = topic.getBackgroundColor();

View File

@ -67,11 +67,11 @@ abstract class Topic extends NodeGraph {
private _text: Text | null; private _text: Text | null;
private _iconsGroup: IconGroup; private _iconsGroup!: IconGroup;
private _connector: ShirinkConnector; private _connector!: ShirinkConnector;
private _outgoingLine: ConnectionLine | null; private _outgoingLine!: ConnectionLine | null;
constructor(model: NodeModel, options: NodeOption) { constructor(model: NodeModel, options: NodeOption) {
super(model, options); super(model, options);
@ -83,7 +83,7 @@ abstract class Topic extends NodeGraph {
// Position a topic .... // Position a topic ....
const pos = model.getPosition(); const pos = model.getPosition();
if (pos != null && this.isCentralTopic()) { if (pos && this.isCentralTopic()) {
this.setPosition(pos); this.setPosition(pos);
} }
@ -121,7 +121,7 @@ abstract class Topic extends NodeGraph {
protected redrawShapeType() { protected redrawShapeType() {
const oldInnerShape = this.getInnerShape(); const oldInnerShape = this.getInnerShape();
if (oldInnerShape != null) { if (oldInnerShape) {
this._removeInnerShape(); this._removeInnerShape();
// Create a new one ... // Create a new one ...
@ -208,7 +208,7 @@ abstract class Topic extends NodeGraph {
} }
getInnerShape(): ElementClass { getInnerShape(): ElementClass {
if (!$defined(this._innerShape)) { if (!this._innerShape) {
// Create inner box. // Create inner box.
this._innerShape = this._buildShape(TopicConfig.INNER_RECT_ATTRIBUTES, this.getShapeType()); this._innerShape = this._buildShape(TopicConfig.INNER_RECT_ATTRIBUTES, this.getShapeType());
@ -285,16 +285,17 @@ abstract class Topic extends NodeGraph {
private getOrBuildIconGroup(): Group { private getOrBuildIconGroup(): Group {
if (!this._iconsGroup) { if (!this._iconsGroup) {
this._iconsGroup = this._buildIconGroup(); const iconGroup = this._buildIconGroup();
const group = this.get2DElement(); const group = this.get2DElement();
group.append(this._iconsGroup.getNativeElement()); group.append(iconGroup.getNativeElement());
this._iconsGroup.moveToFront(); iconGroup.moveToFront();
this._iconsGroup = iconGroup;
} }
return this._iconsGroup; return this._iconsGroup;
} }
private getIconGroup(): IconGroup { private getIconGroup(): IconGroup | null {
return this._iconsGroup; return this._iconsGroup;
} }
@ -351,7 +352,7 @@ abstract class Topic extends NodeGraph {
// Removing the icon from UI // Removing the icon from UI
const iconGroup = this.getIconGroup(); const iconGroup = this.getIconGroup();
if ($defined(iconGroup)) { if (iconGroup) {
iconGroup.removeIconByModel(featureModel); iconGroup.removeIconByModel(featureModel);
} }
this.redraw(); this.redraw();
@ -837,7 +838,7 @@ abstract class Topic extends NodeGraph {
setBranchVisibility(value: boolean): void { setBranchVisibility(value: boolean): void {
let current: Topic = this; let current: Topic = this;
let parent: Topic | null = this; let parent: Topic | null = this;
while (parent != null && !parent.isCentralTopic()) { while (parent && !parent.isCentralTopic()) {
current = parent; current = parent;
parent = current.getParent(); parent = current.getParent();
} }
@ -896,8 +897,8 @@ abstract class Topic extends NodeGraph {
const sourceParent = sourceTopic.getModel().getParent(); const sourceParent = sourceTopic.getModel().getParent();
relationship.setVisibility( relationship.setVisibility(
value && value &&
(targetParent == null || !targetParent.areChildrenShrunken()) && (!targetParent || !targetParent.areChildrenShrunken()) &&
(sourceParent == null || !sourceParent.areChildrenShrunken()), (!sourceParent || !sourceParent.areChildrenShrunken()),
fade, fade,
); );
}); });
@ -1242,7 +1243,7 @@ abstract class Topic extends NodeGraph {
// Force the repaint in case that the main topic color has changed. // Force the repaint in case that the main topic color has changed.
if (this.getParent()) { if (this.getParent()) {
this._connector.setColor(borderColor); this._connector!.setColor(borderColor);
if (this.getParent()?.isCentralTopic()) { if (this.getParent()?.isCentralTopic()) {
this._outgoingLine?.redraw(); this._outgoingLine?.redraw();

View File

@ -33,7 +33,7 @@ class Workspace {
private _eventsEnabled: boolean; private _eventsEnabled: boolean;
private _visibleAreaSize: SizeType; private _visibleAreaSize!: SizeType;
private _renderQueue: Element2D[]; private _renderQueue: Element2D[];
@ -61,8 +61,9 @@ class Workspace {
workspace.addItAsChildTo(divContainer); workspace.addItAsChildTo(divContainer);
this.setZoom(zoom, true); this.setZoom(zoom, true);
this._renderQueue = []; this._renderQueue = [];
this._eventsEnabled = false;
this._queueRenderEnabled = false;
} }
private _adjustWorkspace(): void { private _adjustWorkspace(): void {
@ -163,11 +164,11 @@ class Workspace {
} }
} }
addEvent(type: string, listener: (event: Event) => void): void { addEvent(type: string, listener: (event: MouseEvent) => void): void {
this._workspace.addEvent(type, listener); this._workspace.addEvent(type, listener);
} }
removeEvent(type: string, listener: (event: Event) => void): void { removeEvent(type: string, listener: (event: MouseEvent) => void): void {
$assert(type, 'type can not be null'); $assert(type, 'type can not be null');
$assert(listener, 'listener can not be null'); $assert(listener, 'listener can not be null');
this._workspace.removeEvent(type, listener); this._workspace.removeEvent(type, listener);

View File

@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { $assert, $defined } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import Point from '@wisemapping/web2d'; import Point from '@wisemapping/web2d';
import Command from '../Command'; import Command from '../Command';
import CommandContext from '../CommandContext'; import CommandContext from '../CommandContext';
@ -30,18 +30,10 @@ class DragTopicCommand extends Command {
private _order: number; private _order: number;
/**
* @classdesc This command class handles do/undo of dragging a topic to a new position.
* @constructs
*/
constructor(topicId: number, position: Point, order: number, parentTopic: Topic) { constructor(topicId: number, position: Point, order: number, parentTopic: Topic) {
$assert(topicId, 'topicId must be defined');
super(); super();
this._topicsId = topicId; this._topicsId = topicId;
if ($defined(parentTopic)) { this._parentId = parentTopic ? parentTopic.getId() : null;
this._parentId = parentTopic.getId();
}
this._position = position; this._position = position;
this._order = order; this._order = order;
@ -59,7 +51,7 @@ class DragTopicCommand extends Command {
const origPosition = topic.getPosition(); const origPosition = topic.getPosition();
// Disconnect topic .. // Disconnect topic ..
if ($defined(origParentTopic)) { if (origParentTopic) {
commandContext.disconnect(topic); commandContext.disconnect(topic);
} }

View File

@ -15,37 +15,28 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { $assert, $defined } from '@wisemapping/core-js';
import Command from '../Command'; import Command from '../Command';
import CommandContext from '../CommandContext'; import CommandContext from '../CommandContext';
import Topic from '../Topic'; import Topic from '../Topic';
type CommandTypes = string | object | boolean | number | undefined; class GenericFunctionCommand<T> extends Command {
private _value: T;
class GenericFunctionCommand extends Command {
private _value: CommandTypes;
private _topicsIds: number[]; private _topicsIds: number[];
private _commandFunc: (topic: Topic, value: CommandTypes) => CommandTypes; private _commandFunc: (topic: Topic, value: T) => T;
private _oldValues: CommandTypes[]; private _oldValues: T[];
private _applied: boolean; private _applied: boolean;
constructor( constructor(commandFunc: (topic: Topic, value: T) => T, topicsIds: number[], value: T) {
commandFunc: (topic: Topic, value: CommandTypes) => CommandTypes,
topicsIds: number[],
value: CommandTypes,
) {
$assert(commandFunc, 'commandFunc must be defined');
$assert($defined(topicsIds), 'topicsIds must be defined');
super(); super();
this._value = value; this._value = value;
this._topicsIds = topicsIds; this._topicsIds = topicsIds;
this._commandFunc = commandFunc; this._commandFunc = commandFunc;
this._oldValues = []; this._oldValues = [];
this._applied = false;
} }
/** /**

View File

@ -25,7 +25,7 @@ class RemoveFeatureFromTopicCommand extends Command {
private _featureId: number; private _featureId: number;
private _oldFeature: FeatureModel; private _oldFeature: FeatureModel | null;
/** /**
* @classdesc This command handles do/undo of removing a feature from a topic, e.g. an icon or * @classdesc This command handles do/undo of removing a feature from a topic, e.g. an icon or
@ -38,6 +38,7 @@ class RemoveFeatureFromTopicCommand extends Command {
super(); super();
this._topicId = topicId; this._topicId = topicId;
this._featureId = featureId; this._featureId = featureId;
this._oldFeature = null;
} }
/** /**
@ -56,7 +57,7 @@ class RemoveFeatureFromTopicCommand extends Command {
*/ */
undoExecute(commandContext: CommandContext) { undoExecute(commandContext: CommandContext) {
const topic = commandContext.findTopics([this._topicId])[0]; const topic = commandContext.findTopics([this._topicId])[0];
topic.addFeature(this._oldFeature); topic.addFeature(this._oldFeature!);
} }
} }

View File

@ -22,11 +22,11 @@ import Font from './freemind/Font';
class FreemindExporter extends Exporter { class FreemindExporter extends Exporter {
private mindmap: Mindmap; private mindmap: Mindmap;
private nodeMap: Map<number, FreeminNode>; private nodeMap!: Map<number, FreeminNode>;
private version: VersionNumber = FreemindConstant.SUPPORTED_FREEMIND_VERSION; private version: VersionNumber = FreemindConstant.SUPPORTED_FREEMIND_VERSION;
private objectFactory: ObjectFactory; private objectFactory!: ObjectFactory;
private static wisweToFreeFontSize: Map<number, number> = new Map<number, number>(); private static wisweToFreeFontSize: Map<number, number> = new Map<number, number>();

View File

@ -1,43 +1,43 @@
export default class Arrowlink { export default class Arrowlink {
protected COLOR: string; protected COLOR: string | undefined;
protected DESTINATION: string; protected DESTINATION: string | undefined;
protected ENDARROW: string; protected ENDARROW: string | undefined;
protected ENDINCLINATION: string; protected ENDINCLINATION: string | undefined;
protected ID: string; protected ID: string | undefined;
protected STARTARROW: string; protected STARTARROW: string | undefined;
protected STARTINCLINATION: string; protected STARTINCLINATION: string | undefined;
getColor(): string { getColor(): string | undefined {
return this.COLOR; return this.COLOR;
} }
getDestination(): string { getDestination(): string | undefined {
return this.DESTINATION; return this.DESTINATION;
} }
getEndarrow(): string { getEndarrow(): string | undefined {
return this.ENDARROW; return this.ENDARROW;
} }
getEndInclination(): string { getEndInclination(): string | undefined {
return this.ENDINCLINATION; return this.ENDINCLINATION;
} }
getId(): string { getId(): string | undefined {
return this.ID; return this.ID;
} }
getStartarrow(): string { getStartarrow(): string | undefined {
return this.STARTARROW; return this.STARTARROW;
} }
getStartinclination(): string { getStartinclination(): string | undefined {
return this.STARTINCLINATION; return this.STARTINCLINATION;
} }
@ -72,8 +72,12 @@ export default class Arrowlink {
toXml(document: Document): HTMLElement { toXml(document: Document): HTMLElement {
const arrowlinkElem = document.createElement('arrowlink'); const arrowlinkElem = document.createElement('arrowlink');
if (this.DESTINATION) {
arrowlinkElem.setAttribute('DESTINATION', this.DESTINATION); arrowlinkElem.setAttribute('DESTINATION', this.DESTINATION);
}
if (this.STARTARROW) {
arrowlinkElem.setAttribute('STARTARROW', this.STARTARROW); arrowlinkElem.setAttribute('STARTARROW', this.STARTARROW);
}
if (this.COLOR) { if (this.COLOR) {
arrowlinkElem.setAttribute('COLOR', this.COLOR); arrowlinkElem.setAttribute('COLOR', this.COLOR);

View File

@ -1,7 +1,7 @@
export default class Cloud { export default class Cloud {
protected COLOR: string; protected COLOR: string | undefined;
getColor(): string { getColor(): string | undefined {
return this.COLOR; return this.COLOR;
} }
@ -12,8 +12,9 @@ export default class Cloud {
toXml(document: Document): HTMLElement { toXml(document: Document): HTMLElement {
// Set node attributes // Set node attributes
const cloudElem = document.createElement('cloud'); const cloudElem = document.createElement('cloud');
if (this.COLOR) {
cloudElem.setAttribute('COLOR', this.COLOR); cloudElem.setAttribute('COLOR', this.COLOR);
}
return cloudElem; return cloudElem;
} }

View File

@ -1,19 +1,36 @@
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export default class Edge { export default class Edge {
protected COLOR: string; protected COLOR: string | undefined;
protected STYLE: string; protected STYLE: string | undefined;
protected WIDTH: string; protected WIDTH: string | undefined;
getColor(): string { getColor(): string | undefined {
return this.COLOR; return this.COLOR;
} }
getStyle(): string { getStyle(): string | undefined {
return this.STYLE; return this.STYLE;
} }
getWidth(): string { getWidth(): string | undefined {
return this.WIDTH; return this.WIDTH;
} }
@ -32,10 +49,15 @@ export default class Edge {
toXml(document: Document): HTMLElement { toXml(document: Document): HTMLElement {
// Set node attributes // Set node attributes
const edgeElem = document.createElement('edge'); const edgeElem = document.createElement('edge');
if (this.COLOR) {
edgeElem.setAttribute('COLOR', this.COLOR); edgeElem.setAttribute('COLOR', this.COLOR);
if (this.STYLE) edgeElem.setAttribute('STYLE', this.STYLE); }
if (this.WIDTH) edgeElem.setAttribute('WIDTH', this.WIDTH); if (this.STYLE) {
edgeElem.setAttribute('STYLE', this.STYLE);
}
if (this.WIDTH) {
edgeElem.setAttribute('WIDTH', this.WIDTH);
}
return edgeElem; return edgeElem;
} }

View File

@ -1,11 +1,11 @@
export default class Font { export default class Font {
protected BOLD?: string; protected BOLD: string | undefined;
protected ITALIC?: string; protected ITALIC: string | undefined;
protected NAME?: string; protected NAME: string | undefined;
protected SIZE: string; protected SIZE: string | undefined;
getBold(): string | undefined { getBold(): string | undefined {
return this.BOLD; return this.BOLD;
@ -19,7 +19,7 @@ export default class Font {
return this.NAME; return this.NAME;
} }
getSize(): string { getSize(): string | undefined {
return this.SIZE; return this.SIZE;
} }

View File

@ -1,21 +1,21 @@
import Parameters from './Parameters'; import Parameters from './Parameters';
export default class Hook { export default class Hook {
protected PARAMETERS: Parameters; protected PARAMETERS: Parameters | undefined;
protected TEXT: string; protected TEXT: string | undefined;
protected NAME: string; protected NAME: string | undefined;
getParameters(): Parameters { getParameters(): Parameters | undefined {
return this.PARAMETERS; return this.PARAMETERS;
} }
getText(): string { getText(): string | undefined {
return this.TEXT; return this.TEXT;
} }
getName(): string { getName(): string | undefined {
return this.NAME; return this.NAME;
} }

View File

@ -1,7 +1,7 @@
export default class Icon { export default class Icon {
protected BUILTIN: string; protected BUILTIN: string | undefined;
getBuiltin(): string { getBuiltin(): string | undefined {
return this.BUILTIN; return this.BUILTIN;
} }
@ -12,8 +12,9 @@ export default class Icon {
toXml(document: Document): HTMLElement { toXml(document: Document): HTMLElement {
// Set node attributes // Set node attributes
const iconElem = document.createElement('icon'); const iconElem = document.createElement('icon');
if (this.BUILTIN) {
iconElem.setAttribute('BUILTIN', this.BUILTIN); iconElem.setAttribute('BUILTIN', this.BUILTIN);
}
return iconElem; return iconElem;
} }

View File

@ -8,15 +8,15 @@ import Node, { Choise } from './Node';
import Richcontent from './Richcontent'; import Richcontent from './Richcontent';
export default class Freemap { export default class Freemap {
protected node: Node; protected node: Node | undefined;
protected version: string; protected version: string | undefined;
getNode(): Node { getNode(): Node | undefined {
return this.node; return this.node;
} }
getVersion(): string { getVersion(): string | undefined {
return this.version; return this.version;
} }
@ -38,7 +38,7 @@ export default class Freemap {
document.appendChild(mapElem); document.appendChild(mapElem);
// Create main node // Create main node
const mainNode: Node = this.node; const mainNode: Node = this.node!;
mainNode.setCentralTopic(true); mainNode.setCentralTopic(true);
const mainNodeElem = mainNode.toXml(document); const mainNodeElem = mainNode.toXml(document);
mapElem.appendChild(mainNodeElem); mapElem.appendChild(mainNodeElem);

View File

@ -7,43 +7,43 @@ import Icon from './Icon';
import Richcontent from './Richcontent'; import Richcontent from './Richcontent';
class Node { class Node {
protected arrowlinkOrCloudOrEdge: Array< protected arrowlinkOrCloudOrEdge:
Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this | Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this>
>; | undefined;
protected BACKGROUND_COLOR: string; protected BACKGROUND_COLOR: string | undefined;
protected COLOR: string; protected COLOR: string | undefined;
protected FOLDED: string; protected FOLDED: string | undefined;
protected ID: string; protected ID: string | undefined;
protected LINK: string; protected LINK: string | undefined;
protected POSITION: string; protected POSITION: string | undefined;
protected STYLE: string; protected STYLE: string | undefined;
protected TEXT: string; protected TEXT: string | undefined;
protected CREATED: string; protected CREATED: string | undefined;
protected MODIFIED: string; protected MODIFIED: string | undefined;
protected HGAP: string; protected HGAP: string | undefined;
protected VGAP: string; protected VGAP: string | undefined;
protected WCOORDS: string; protected WCOORDS: string | undefined;
protected WORDER: string; protected WORDER: string | undefined;
protected VSHIFT: string; protected VSHIFT: string | undefined;
protected ENCRYPTED_CONTENT: string; protected ENCRYPTED_CONTENT: string | undefined;
private centralTopic: boolean; private centralTopic = false;
getArrowlinkOrCloudOrEdge(): Array< getArrowlinkOrCloudOrEdge(): Array<
/* eslint-disable */ /* eslint-disable */
@ -57,67 +57,67 @@ class Node {
return this.arrowlinkOrCloudOrEdge; return this.arrowlinkOrCloudOrEdge;
} }
getBackgroundColor(): string { getBackgroundColor(): string | undefined {
return this.BACKGROUND_COLOR; return this.BACKGROUND_COLOR;
} }
getColor(): string { getColor(): string | undefined {
return this.COLOR; return this.COLOR;
} }
getFolded(): string { getFolded(): string | undefined {
return this.FOLDED; return this.FOLDED;
} }
getId(): string | null { getId(): string | undefined {
return this.ID; return this.ID;
} }
getLink(): string { getLink(): string | undefined {
return this.LINK; return this.LINK;
} }
getPosition(): string { getPosition(): string | undefined {
return this.POSITION; return this.POSITION;
} }
getStyle(): string { getStyle(): string | undefined {
return this.STYLE; return this.STYLE;
} }
getText(): string { getText(): string | undefined {
return this.TEXT; return this.TEXT;
} }
getCreated(): string { getCreated(): string | undefined {
return this.CREATED; return this.CREATED;
} }
getModified(): string { getModified(): string | undefined {
return this.MODIFIED; return this.MODIFIED;
} }
getHgap(): string { getHgap(): string | undefined {
return this.HGAP; return this.HGAP;
} }
getVgap(): string { getVgap(): string | undefined {
return this.VGAP; return this.VGAP;
} }
getWcoords(): string { getWcoords(): string | undefined {
return this.WCOORDS; return this.WCOORDS;
} }
getWorder(): string { getWorder(): string | undefined {
return this.WORDER; return this.WORDER;
} }
getVshift(): string { getVshift(): string | undefined {
return this.VSHIFT; return this.VSHIFT;
} }
getEncryptedContent(): string { getEncryptedContent(): string | undefined {
return this.ENCRYPTED_CONTENT; return this.ENCRYPTED_CONTENT;
} }

View File

@ -1,7 +1,7 @@
export default class Parameters { export default class Parameters {
protected REMINDUSERAT: number; protected REMINDUSERAT: number | undefined;
getReminduserat(): number { getReminduserat(): number | undefined {
return this.REMINDUSERAT; return this.REMINDUSERAT;
} }

View File

@ -1,13 +1,13 @@
export default class Richcontent { export default class Richcontent {
protected html: string; protected html: string | undefined;
protected type: string; protected type: string | undefined;
getHtml(): string { getHtml(): string | undefined {
return this.html; return this.html;
} }
getType(): string { getType(): string | undefined {
return this.type; return this.type;
} }
@ -22,9 +22,9 @@ export default class Richcontent {
toXml(document: Document): HTMLElement { toXml(document: Document): HTMLElement {
// Set node attributes // Set node attributes
const richcontentElem = document.createElement('richcontent'); const richcontentElem = document.createElement('richcontent');
if (this.type) {
richcontentElem.setAttribute('TYPE', this.type); richcontentElem.setAttribute('TYPE', this.type);
}
if (this.html) { if (this.html) {
const htmlElement: DocumentFragment = document const htmlElement: DocumentFragment = document
.createRange() .createRange()

View File

@ -6,7 +6,6 @@ import NodeModel from '../model/NodeModel';
import FreemindConstant from '../export/freemind/FreemindConstant'; import FreemindConstant from '../export/freemind/FreemindConstant';
import FreemindMap from '../export/freemind/Map'; import FreemindMap from '../export/freemind/Map';
import FreemindNode, { Choise } from '../export/freemind/Node'; import FreemindNode, { Choise } from '../export/freemind/Node';
import FreemindFont from '../export/freemind/Font';
import FreemindEdge from '../export/freemind/Edge'; import FreemindEdge from '../export/freemind/Edge';
import FreemindIcon from '../export/freemind/Icon'; import FreemindIcon from '../export/freemind/Icon';
import FreemindHook from '../export/freemind/Hook'; import FreemindHook from '../export/freemind/Hook';
@ -21,15 +20,15 @@ import XMLSerializerFactory from '../persistence/XMLSerializerFactory';
import { TopicShapeType } from '../model/INodeModel'; import { TopicShapeType } from '../model/INodeModel';
export default class FreemindImporter extends Importer { export default class FreemindImporter extends Importer {
private mindmap: Mindmap; private mindmap!: Mindmap;
private freemindInput: string; private freemindInput: string;
private freemindMap: FreemindMap; private freemindMap!: FreemindMap;
private nodesmap: Map<string, NodeModel>; private nodesmap!: Map<string, NodeModel>;
private relationship: Array<RelationshipModel>; private relationship!: Array<RelationshipModel>;
private idDefault = 0; private idDefault = 0;
@ -47,7 +46,7 @@ export default class FreemindImporter extends Importer {
const freemindDoc = parser.parseFromString(this.freemindInput, 'application/xml'); const freemindDoc = parser.parseFromString(this.freemindInput, 'application/xml');
this.freemindMap = new FreemindMap().loadFromDom(freemindDoc); this.freemindMap = new FreemindMap().loadFromDom(freemindDoc);
const version: string = this.freemindMap.getVersion(); const version: string | undefined = this.freemindMap.getVersion();
if (!version || version.startsWith('freeplane')) { if (!version || version.startsWith('freeplane')) {
throw new Error( throw new Error(
@ -60,10 +59,10 @@ export default class FreemindImporter extends Importer {
} }
} }
const freeNode: FreemindNode = this.freemindMap.getNode(); const freeNode = this.freemindMap.getNode()!;
this.mindmap.setVersion(FreemindConstant.CODE_VERSION); this.mindmap.setVersion(FreemindConstant.CODE_VERSION);
const wiseTopicId = this.getIdNode(this.freemindMap.getNode()); const wiseTopicId = this.getIdNode(freeNode);
const wiseTopic = this.mindmap.createNode('CentralTopic'); const wiseTopic = this.mindmap.createNode('CentralTopic');
wiseTopic.setPosition(0, 0); wiseTopic.setPosition(0, 0);
wiseTopic.setId(wiseTopicId); wiseTopic.setId(wiseTopicId);
@ -158,7 +157,7 @@ export default class FreemindImporter extends Importer {
wiseTopic: NodeModel, wiseTopic: NodeModel,
centralTopic: boolean, centralTopic: boolean,
): void { ): void {
const text: string = freeNode.getText(); const text = freeNode.getText();
if (text) { if (text) {
if (!centralTopic && text.length > 100) { if (!centralTopic && text.length > 100) {
wiseTopic.setText(text.replace(/([^\n]{1,100})\s/g, '$1\n')); wiseTopic.setText(text.replace(/([^\n]{1,100})\s/g, '$1\n'));
@ -167,7 +166,7 @@ export default class FreemindImporter extends Importer {
} }
} }
const bgColor: string = freeNode.getBackgroundColor(); const bgColor = freeNode.getBackgroundColor();
if (bgColor) { if (bgColor) {
wiseTopic.setBackgroundColor(bgColor); wiseTopic.setBackgroundColor(bgColor);
} }
@ -186,7 +185,7 @@ export default class FreemindImporter extends Importer {
// } // }
// Is there any link... // Is there any link...
const url: string = freeNode.getLink(); const url = freeNode.getLink();
if (url) { if (url) {
const link: FeatureModel = FeatureModelFactory.createModel('link', { url }); const link: FeatureModel = FeatureModelFactory.createModel('link', { url });
wiseTopic.addFeature(link); wiseTopic.addFeature(link);
@ -214,7 +213,7 @@ export default class FreemindImporter extends Importer {
const wiseChild = mindmap.createNode('MainTopic', wiseId); const wiseChild = mindmap.createNode('MainTopic', wiseId);
const id = child.getId(); const id = child.getId();
if (id !== null) { if (id !== undefined) {
this.nodesmap.set(id, wiseChild); this.nodesmap.set(id, wiseChild);
} }
@ -269,7 +268,8 @@ export default class FreemindImporter extends Importer {
if (child instanceof FreemindIcon) { if (child instanceof FreemindIcon) {
const freeIcon: FreemindIcon = child as FreemindIcon; const freeIcon: FreemindIcon = child as FreemindIcon;
const iconId: string = freeIcon.getBuiltin(); const iconId = freeIcon.getBuiltin();
if (iconId) {
const wiseIconId = FreemindIconConverter.toWiseId(iconId); const wiseIconId = FreemindIconConverter.toWiseId(iconId);
if (wiseIconId) { if (wiseIconId) {
const mindmapIcon: FeatureModel = FeatureModelFactory.createModel('icon', { const mindmapIcon: FeatureModel = FeatureModelFactory.createModel('icon', {
@ -278,12 +278,13 @@ export default class FreemindImporter extends Importer {
currentWiseTopic.addFeature(mindmapIcon); currentWiseTopic.addFeature(mindmapIcon);
} }
} }
}
if (child instanceof FreemindHook) { if (child instanceof FreemindHook) {
const hook: FreemindHook = child as FreemindHook; const hook: FreemindHook = child as FreemindHook;
const mindmapNote: NoteModel = new NoteModel({ text: '' }); const mindmapNote: NoteModel = new NoteModel({ text: '' });
let textNote: string = hook.getText(); let textNote = hook.getText();
if (!textNote) { if (!textNote) {
textNote = FreemindConstant.EMPTY_NOTE; textNote = FreemindConstant.EMPTY_NOTE;
mindmapNote.setText(textNote); mindmapNote.setText(textNote);
@ -294,8 +295,8 @@ export default class FreemindImporter extends Importer {
if (child instanceof FreemindRichcontent) { if (child instanceof FreemindRichcontent) {
const type = child.getType(); const type = child.getType();
const html = child.getHtml(); const html = child.getHtml();
if (html) {
const text = this.html2Text(html); const text = this.html2Text(html);
switch (type) { switch (type) {
case 'NOTE': { case 'NOTE': {
const noteModel: FeatureModel = FeatureModelFactory.createModel('note', { const noteModel: FeatureModel = FeatureModelFactory.createModel('note', {
@ -318,32 +319,33 @@ export default class FreemindImporter extends Importer {
} }
} }
} }
}
if (child instanceof FreemindArrowLink) { if (child instanceof FreemindArrowLink) {
const arrow: FreemindArrowLink = child as FreemindArrowLink; const arrow: FreemindArrowLink = child as FreemindArrowLink;
const relationship: RelationshipModel = new RelationshipModel(0, 0); const relationship: RelationshipModel = new RelationshipModel(0, 0);
const destId: string = arrow.getDestination(); const destId = arrow.getDestination();
relationship.setSrcCtrlPoint(destId); relationship.setSrcCtrlPoint(destId);
relationship.setDestCtrlPoint(freeParent.getId()); relationship.setDestCtrlPoint(freeParent.getId());
const endinclination: string = arrow.getEndInclination(); const endinclination = arrow.getEndInclination();
if (endinclination) { if (endinclination) {
const inclination: Array<string> = endinclination.split(';'); const inclination: Array<string> = endinclination.split(';');
relationship.setDestCtrlPoint(`${inclination[0]},${inclination[1]}`); relationship.setDestCtrlPoint(`${inclination[0]},${inclination[1]}`);
} }
const startinclination: string = arrow.getStartinclination(); const startinclination = arrow.getStartinclination();
if (startinclination) { if (startinclination) {
const inclination: Array<string> = startinclination.split(';'); const inclination: Array<string> = startinclination.split(';');
relationship.setSrcCtrlPoint(`${inclination[0]},${inclination[1]}`); relationship.setSrcCtrlPoint(`${inclination[0]},${inclination[1]}`);
} }
const endarrow: string = arrow.getEndarrow(); const endarrow = arrow.getEndarrow();
if (endarrow) { if (endarrow) {
relationship.setEndArrow(endarrow.toLowerCase() !== 'none'); relationship.setEndArrow(endarrow.toLowerCase() !== 'none');
} }
const startarrow: string = arrow.getStartarrow(); const startarrow = arrow.getStartarrow();
if (startarrow) { if (startarrow) {
relationship.setStartArrow(startarrow.toLowerCase() !== 'none'); relationship.setStartArrow(startarrow.toLowerCase() !== 'none');
} }
@ -375,7 +377,7 @@ export default class FreemindImporter extends Importer {
private getChildrenCountSameSide(freeChilden: Array<Choise>, freeChild: FreemindNode): number { private getChildrenCountSameSide(freeChilden: Array<Choise>, freeChild: FreemindNode): number {
let result = 0; let result = 0;
let childSide: string = freeChild.getPosition(); let childSide = freeChild.getPosition();
if (!childSide) { if (!childSide) {
childSide = FreemindConstant.POSITION_RIGHT; childSide = FreemindConstant.POSITION_RIGHT;
@ -410,55 +412,54 @@ export default class FreemindImporter extends Importer {
return result; return result;
} }
private generateFontStyle(node: FreemindNode, font: FreemindFont | undefined): string { // private generateFontStyle(node: FreemindNode, font: FreemindFont | undefined): string {
const fontStyle: Array<string> = []; // const fontStyle: Array<string> = [];
// Font family // // Font family
if (font) { // if (font) {
const name = font.getName(); // const name = font.getName();
if (name) { // if (name) {
fontStyle.push(name); // fontStyle.push(name);
} // }
} // }
fontStyle.push(';'); // fontStyle.push(';');
// Font Size // // Font Size
if (font) { // if (font) {
const fontSize: number = // const size = font.getSize();
!font.getSize() || parseInt(font.getSize(), 10) < 8 // const fontSize: number =
? FreemindConstant.FONT_SIZE_NORMAL // !size || parseInt(size, 10) < 8 ? FreemindConstant.FONT_SIZE_NORMAL : parseInt(size, 10);
: parseInt(font.getSize(), 10); // let wiseFontSize: number = FreemindConstant.FONT_SIZE_SMALL;
let wiseFontSize: number = FreemindConstant.FONT_SIZE_SMALL; // if (fontSize >= 24) {
if (fontSize >= 24) { // wiseFontSize = FreemindConstant.FONT_SIZE_HUGE;
wiseFontSize = FreemindConstant.FONT_SIZE_HUGE; // }
} // if (fontSize >= 16) {
if (fontSize >= 16) { // wiseFontSize = FreemindConstant.FONT_SIZE_LARGE;
wiseFontSize = FreemindConstant.FONT_SIZE_LARGE; // }
} // if (fontSize >= 8) {
if (fontSize >= 8) { // wiseFontSize = FreemindConstant.FONT_SIZE_NORMAL;
wiseFontSize = FreemindConstant.FONT_SIZE_NORMAL; // }
} // fontStyle.push(wiseFontSize.toString());
fontStyle.push(wiseFontSize.toString()); // }
} // fontStyle.push(';');
fontStyle.push(';');
// Font Color // // Font Color
const color: string = node.getColor(); // const color = node.getColor();
if (color && color !== '') { // if (color && color !== '') {
fontStyle.push(color); // fontStyle.push(color);
} // }
fontStyle.push(';'); // fontStyle.push(';');
// Font Italic // // Font Italic
if (font) { // if (font) {
const hasItalic = Boolean(font.getItalic()); // const hasItalic = Boolean(font.getItalic());
fontStyle.push(hasItalic ? FreemindConstant.ITALIC : ''); // fontStyle.push(hasItalic ? FreemindConstant.ITALIC : '');
} // }
fontStyle.push(';'); // fontStyle.push(';');
const result: string = fontStyle.join(''); // const result: string = fontStyle.join('');
return result; // return result;
} // }
private convertPosition( private convertPosition(
wiseParent: NodeModel, wiseParent: NodeModel,
@ -471,7 +472,7 @@ export default class FreemindImporter extends Importer {
FreemindConstant.CENTRAL_TO_TOPIC_DISTANCE + FreemindConstant.CENTRAL_TO_TOPIC_DISTANCE +
(depth - 1) * FreemindConstant.TOPIC_TO_TOPIC_DISTANCE; (depth - 1) * FreemindConstant.TOPIC_TO_TOPIC_DISTANCE;
if (depth === 1) { if (depth === 1) {
const side: string = freeChild.getPosition(); const side = freeChild.getPosition();
x *= side && FreemindConstant.POSITION_LEFT === side ? -1 : 1; x *= side && FreemindConstant.POSITION_LEFT === side ? -1 : 1;
} else { } else {
const position = wiseParent.getPosition(); const position = wiseParent.getPosition();

View File

@ -1,12 +1,9 @@
import Mindmap from '../model/Mindmap';
import XMLSerializerFactory from '../persistence/XMLSerializerFactory'; import XMLSerializerFactory from '../persistence/XMLSerializerFactory';
import Importer from './Importer'; import Importer from './Importer';
export default class WisemappingImporter extends Importer { export default class WisemappingImporter extends Importer {
private wisemappingInput: string; private wisemappingInput: string;
private mindmap: Mindmap;
constructor(map: string) { constructor(map: string) {
super(); super();
this.wisemappingInput = map; this.wisemappingInput = map;
@ -17,11 +14,11 @@ export default class WisemappingImporter extends Importer {
const wiseDoc = parser.parseFromString(this.wisemappingInput, 'application/xml'); const wiseDoc = parser.parseFromString(this.wisemappingInput, 'application/xml');
const serialize = XMLSerializerFactory.createInstanceFromDocument(wiseDoc); const serialize = XMLSerializerFactory.createInstanceFromDocument(wiseDoc);
this.mindmap = serialize.loadFromDom(wiseDoc, nameMap); const mindmap = serialize.loadFromDom(wiseDoc, nameMap);
this.mindmap.setDescription(description); mindmap.setDescription(description);
const mindmapToXml = serialize.toXML(this.mindmap); const mindmapToXml = serialize.toXML(mindmap);
const xmlStr = new XMLSerializer().serializeToString(mindmapToXml); const xmlStr = new XMLSerializer().serializeToString(mindmapToXml);
return Promise.resolve(xmlStr); return Promise.resolve(xmlStr);

View File

@ -22,10 +22,11 @@ import EventBus from './EventBus';
import LayoutManager from './LayoutManager'; import LayoutManager from './LayoutManager';
class EventBusDispatcher { class EventBusDispatcher {
private _layoutManager: LayoutManager; private _layoutManager: LayoutManager | null;
constructor() { constructor() {
this.registerBusEvents(); this.registerBusEvents();
this._layoutManager = null;
} }
setLayoutManager(layoutManager: LayoutManager) { setLayoutManager(layoutManager: LayoutManager) {
@ -44,19 +45,19 @@ class EventBusDispatcher {
} }
private _topicResizeEvent(args: { node: Topic; size: SizeType }) { private _topicResizeEvent(args: { node: Topic; size: SizeType }) {
this._layoutManager.updateNodeSize(args.node.getId(), args.size); this._layoutManager!.updateNodeSize(args.node.getId(), args.size);
} }
private _topicMoved(args: { node: Topic; position: PositionType }) { private _topicMoved(args: { node: Topic; position: PositionType }) {
this._layoutManager.moveNode(args.node.getId(), args.position); this._layoutManager!.moveNode(args.node.getId(), args.position);
} }
private _topicDisconect(node: Topic) { private _topicDisconect(node: Topic) {
this._layoutManager.disconnectNode(node.getId()); this._layoutManager!.disconnectNode(node.getId());
} }
private _topicConnected(args: { parentNode: Topic; childNode: Topic }) { private _topicConnected(args: { parentNode: Topic; childNode: Topic }) {
this._layoutManager.connectNode( this._layoutManager!.connectNode(
args.parentNode.getId(), args.parentNode.getId(),
args.childNode.getId(), args.childNode.getId(),
args.childNode.getOrder(), args.childNode.getOrder(),
@ -64,27 +65,27 @@ class EventBusDispatcher {
} }
private _childShrinked(node: Topic) { private _childShrinked(node: Topic) {
this._layoutManager.updateShrinkState(node.getId(), node.areChildrenShrunken()); this._layoutManager!.updateShrinkState(node.getId(), node.areChildrenShrunken());
} }
private _topicAdded(node: Topic) { private _topicAdded(node: Topic) {
// Central topic must not be added twice ... // Central topic must not be added twice ...
if (node.getId() !== 0) { if (node.getId() !== 0) {
this._layoutManager.addNode(node.getId(), { width: 10, height: 10 }, node.getPosition()); this._layoutManager!.addNode(node.getId(), { width: 10, height: 10 }, node.getPosition());
this._layoutManager.updateShrinkState(node.getId(), node.areChildrenShrunken()); this._layoutManager!.updateShrinkState(node.getId(), node.areChildrenShrunken());
} }
} }
private _topicRemoved(node: Topic) { private _topicRemoved(node: Topic) {
this._layoutManager.removeNode(node.getId()); this._layoutManager!.removeNode(node.getId());
} }
private _forceLayout() { private _forceLayout() {
this._layoutManager.layout(true); this._layoutManager!.layout(true);
} }
getLayoutManager() { getLayoutManager(): LayoutManager {
return this._layoutManager; return this._layoutManager!;
} }
} }

View File

@ -24,21 +24,17 @@ class Node {
private _id: number; private _id: number;
// eslint-disable-next-line no-use-before-define // eslint-disable-next-line no-use-before-define
_parent: Node | null; _parent!: Node | null;
private _sorter: ChildrenSorterStrategy; private _sorter: ChildrenSorterStrategy;
private _properties; private _properties;
// eslint-disable-next-line no-use-before-define // eslint-disable-next-line no-use-before-define
_children: Node[]; _children!: Node[];
constructor(id: number, size: SizeType, position: PositionType, sorter: ChildrenSorterStrategy) { constructor(id: number, size: SizeType, position: PositionType, sorter: ChildrenSorterStrategy) {
$assert(typeof id === 'number' && Number.isFinite(id), 'id can not be null'); $assert(typeof id === 'number' && Number.isFinite(id), 'id can not be null');
$assert(size, 'size can not be null');
$assert(position, 'position can not be null');
$assert(sorter, 'sorter can not be null');
this._id = id; this._id = id;
this._sorter = sorter; this._sorter = sorter;
this._properties = {}; this._properties = {};
@ -49,7 +45,7 @@ class Node {
} }
/** */ /** */
getId() { getId(): number {
return this._id; return this._id;
} }
@ -74,7 +70,7 @@ class Node {
} }
/** */ /** */
setShrunken(value) { setShrunken(value: boolean) {
this._setProperty('shrink', value); this._setProperty('shrink', value);
} }
@ -132,31 +128,27 @@ class Node {
} }
/** */ /** */
hasSizeChanged() { hasSizeChanged(): boolean {
return this._isPropertyChanged('size'); return this._isPropertyChanged('size');
} }
/** */ /** */
getPosition() { getPosition(): PositionType {
return this._getProperty('position'); return this._getProperty('position');
} }
/** */ /** */
setSize(size) { setSize(size: SizeType) {
$assert($defined(size), 'Size can not be null'); $assert($defined(size), 'Size can not be null');
this._setProperty('size', { ...size }); this._setProperty('size', { ...size });
} }
/** */ /** */
getSize() { getSize(): SizeType {
return this._getProperty('size'); return this._getProperty('size');
} }
/** */ setFreeDisplacement(displacement: PositionType) {
setFreeDisplacement(displacement) {
$assert($defined(displacement), 'Position can not be null');
$assert($defined(displacement.x), 'x can not be null');
$assert($defined(displacement.y), 'y can not be null');
const oldDisplacement = this.getFreeDisplacement(); const oldDisplacement = this.getFreeDisplacement();
const newDisplacement = { const newDisplacement = {
x: oldDisplacement.x + displacement.x, x: oldDisplacement.x + displacement.x,
@ -177,12 +169,7 @@ class Node {
return freeDisplacement || { x: 0, y: 0 }; return freeDisplacement || { x: 0, y: 0 };
} }
/** */
setPosition(position: PositionType) { setPosition(position: PositionType) {
$assert($defined(position), 'Position can not be null');
$assert($defined(position.x), 'x can not be null');
$assert($defined(position.y), 'y can not be null');
// This is a performance improvement to avoid movements that really could be avoided. // This is a performance improvement to avoid movements that really could be avoided.
const currentPos = this.getPosition(); const currentPos = this.getPosition();
if ( if (
@ -213,7 +200,7 @@ class Node {
this._properties[key] = prop; this._properties[key] = prop;
} }
_getProperty(key) { _getProperty(key: string) {
const prop = this._properties[key]; const prop = this._properties[key];
return $defined(prop) ? prop.value : null; return $defined(prop) ? prop.value : null;
} }
@ -229,7 +216,7 @@ class Node {
} }
/** @return {String} returns id, order, position, size and shrink information */ /** @return {String} returns id, order, position, size and shrink information */
toString() { toString(): string {
return `[id:${this.getId()}, order:${this.getOrder()}, position: {${this.getPosition().x},${ return `[id:${this.getId()}, order:${this.getOrder()}, position: {${this.getPosition().x},${
this.getPosition().y this.getPosition().y
}}, size: {${this.getSize().width},${ }}, size: {${this.getSize().width},${

View File

@ -15,21 +15,20 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { $assert, $defined } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import PositionType from '../PositionType'; import PositionType from '../PositionType';
import Node from './Node'; import Node from './Node';
class RootedTreeSet { class RootedTreeSet {
private _rootNodes: Node[]; private _rootNodes: Node[];
protected _children: Node[]; protected _children!: Node[];
constructor() { constructor() {
this._rootNodes = []; this._rootNodes = [];
} }
setRoot(root: Node) { setRoot(root: Node) {
$assert(root, 'root can not be null');
this._rootNodes.push(this._decodate(root)); this._rootNodes.push(this._decodate(root));
} }
@ -43,7 +42,6 @@ class RootedTreeSet {
} }
add(node: Node) { add(node: Node) {
$assert(node, 'node can not be null');
if (this.find(node.getId(), false)) { if (this.find(node.getId(), false)) {
throw new Error(`node already exits with this id. Id:${node.getId()}: ${this.dump()}`); throw new Error(`node already exits with this id. Id:${node.getId()}: ${this.dump()}`);
} }
@ -56,7 +54,6 @@ class RootedTreeSet {
* @throws will throw an error if nodeId is null or undefined * @throws will throw an error if nodeId is null or undefined
*/ */
remove(nodeId: number) { remove(nodeId: number) {
$assert($defined(nodeId), 'nodeId can not be null');
const node = this.find(nodeId); const node = this.find(nodeId);
this._rootNodes = this._rootNodes.filter((n) => n !== node); this._rootNodes = this._rootNodes.filter((n) => n !== node);
} }
@ -69,9 +66,6 @@ class RootedTreeSet {
* @throws will throw an error if node with id childId is already a child of parent * @throws will throw an error if node with id childId is already a child of parent
*/ */
connect(parentId: number, childId: number) { connect(parentId: number, childId: number) {
$assert($defined(parentId), 'parent can not be null');
$assert($defined(childId), 'child can not be null');
const parent = this.find(parentId); const parent = this.find(parentId);
const child = this.find(childId, true); const child = this.find(childId, true);
$assert( $assert(
@ -90,7 +84,6 @@ class RootedTreeSet {
* @throws will throw an error if node is not connected * @throws will throw an error if node is not connected
*/ */
disconnect(nodeId: number) { disconnect(nodeId: number) {
$assert($defined(nodeId), 'nodeId can not be null');
const node = this.find(nodeId); const node = this.find(nodeId);
$assert(node._parent, 'Node is not connected'); $assert(node._parent, 'Node is not connected');
@ -107,8 +100,6 @@ class RootedTreeSet {
* @return node * @return node
*/ */
find(id: number, validate = true): Node { find(id: number, validate = true): Node {
$assert($defined(id), 'id can not be null');
const graphs = this._rootNodes; const graphs = this._rootNodes;
let result: Node | null = null; let result: Node | null = null;
for (let i = 0; i < graphs.length; i++) { for (let i = 0; i < graphs.length; i++) {

View File

@ -35,8 +35,6 @@ class NodeModel extends INodeModel {
private _parent: NodeModel | null; private _parent: NodeModel | null;
constructor(type: NodeModelType, mindmap: Mindmap, id?: number) { constructor(type: NodeModelType, mindmap: Mindmap, id?: number) {
$assert(type, 'Node type can not be null');
$assert(mindmap, 'mindmap can not be null');
super(mindmap); super(mindmap);
this._properties = {}; this._properties = {};
@ -46,6 +44,7 @@ class NodeModel extends INodeModel {
this._children = []; this._children = [];
this._features = []; this._features = [];
this._parent = null;
} }
/** /**

View File

@ -20,7 +20,6 @@ import Mindmap from '../model/Mindmap';
import FeatureModelFactory from '../model/FeatureModelFactory'; import FeatureModelFactory from '../model/FeatureModelFactory';
import NodeModel from '../model/NodeModel'; import NodeModel from '../model/NodeModel';
import XMLMindmapSerializer from './XMLMindmapSerializer'; import XMLMindmapSerializer from './XMLMindmapSerializer';
import FeatureModel from '../model/FeatureModel';
class XMLSerializerBeta implements XMLMindmapSerializer { class XMLSerializerBeta implements XMLMindmapSerializer {
private static MAP_ROOT_NODE = 'map'; private static MAP_ROOT_NODE = 'map';
@ -297,12 +296,6 @@ class XMLSerializerBeta implements XMLMindmapSerializer {
return topic; return topic;
} }
private _deserializeIcon(domElem: Element): FeatureModel {
let icon = domElem.getAttribute('id');
icon = icon ? icon.replace('images/', 'icons/legacy/') : 'missing';
return FeatureModelFactory.createModel('icon', { id: icon });
}
_deserializeLink(domElem: Element) { _deserializeLink(domElem: Element) {
return FeatureModelFactory.createModel('link', { url: domElem.getAttribute('url') }); return FeatureModelFactory.createModel('link', { url: domElem.getAttribute('url') });
} }

View File

@ -33,6 +33,10 @@ class XMLSerializerTango implements XMLMindmapSerializer {
private _idsMap: Record<number, Element>; private _idsMap: Record<number, Element>;
constructor() {
this._idsMap = {};
}
toXML(mindmap: Mindmap): Document { toXML(mindmap: Mindmap): Document {
$assert(mindmap, 'Can not save a null mindmap'); $assert(mindmap, 'Can not save a null mindmap');
@ -242,7 +246,6 @@ class XMLSerializerTango implements XMLMindmapSerializer {
`This seem not to be a map document. Found tag: ${rootElem.tagName}`, `This seem not to be a map document. Found tag: ${rootElem.tagName}`,
); );
this._idsMap = {};
// Start the loading process ... // Start the loading process ...
const version = rootElem.getAttribute('version') || 'pela'; const version = rootElem.getAttribute('version') || 'pela';
const mindmap = new Mindmap(mapId, version); const mindmap = new Mindmap(mapId, version);

View File

@ -20,9 +20,7 @@ import SizeType from '../SizeType';
import Topic from '../Topic'; import Topic from '../Topic';
class LineTopicShape extends Line { class LineTopicShape extends Line {
private _topic: Topic; private _size: SizeType | null;
private _size: SizeType;
constructor(topic: Topic) { constructor(topic: Topic) {
const stokeColor = topic.getConnectionColor(); const stokeColor = topic.getConnectionColor();
@ -30,7 +28,7 @@ class LineTopicShape extends Line {
strokeColor: stokeColor, strokeColor: stokeColor,
strokeWidth: 1, strokeWidth: 1,
}); });
this._topic = topic; this._size = null;
} }
setSize(width: number, height: number): void { setSize(width: number, height: number): void {
@ -39,7 +37,7 @@ class LineTopicShape extends Line {
super.setTo(width, height); super.setTo(width, height);
} }
getSize() { getSize(): SizeType | null {
return this._size; return this._size;
} }

View File

@ -83,12 +83,12 @@ class SymmetricTestSuite extends TestSuite {
'Symmetry is not respected', 'Symmetry is not respected',
); );
$assert( $assert(
manager.find(8).getPosition().y - manager.find(1).getPosition().y == manager.find(8).getPosition().y - manager.find(1).getPosition().y ===
-(manager.find(11).getPosition().y - manager.find(1).getPosition().y), -(manager.find(11).getPosition().y - manager.find(1).getPosition().y),
'Symmetry is not respected', 'Symmetry is not respected',
); );
$assert( $assert(
manager.find(9).getPosition().y - manager.find(1).getPosition().y == manager.find(9).getPosition().y - manager.find(1).getPosition().y ===
-(manager.find(11).getPosition().y - manager.find(1).getPosition().y), -(manager.find(11).getPosition().y - manager.find(1).getPosition().y),
'Symmetry is not respected', 'Symmetry is not respected',
); );
@ -136,20 +136,20 @@ class SymmetricTestSuite extends TestSuite {
this._plotPrediction(graph1, prediction1a); this._plotPrediction(graph1, prediction1a);
$assert( $assert(
prediction1a.position.x < manager.find(9).getPosition().x && prediction1a.position.x < manager.find(9).getPosition().x &&
prediction1a.position.y == manager.find(9).getPosition().y, prediction1a.position.y === manager.find(9).getPosition().y,
'Prediction incorrectly positioned', 'Prediction incorrectly positioned',
); );
$assert(prediction1a.order == 0, 'Prediction order should be 0'); $assert(prediction1a.order === 0, 'Prediction order should be 0');
console.log('\tAdded as child of node 1 and dropped at (155, -90):'); console.log('\tAdded as child of node 1 and dropped at (155, -90):');
const prediction1b = manager.predict(1, null, { x: -155, y: -90 }); const prediction1b = manager.predict(1, null, { x: -155, y: -90 });
this._plotPrediction(graph1, prediction1b); this._plotPrediction(graph1, prediction1b);
$assert( $assert(
prediction1b.position.x > manager.find(1).getPosition().x && prediction1b.position.x > manager.find(1).getPosition().x &&
prediction1b.position.y == manager.find(1).getPosition().y, prediction1b.position.y === manager.find(1).getPosition().y,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction1b.order == 0, 'Prediction order should be 0'); $assert(prediction1b.order === 0, 'Prediction order should be 0');
// Graph 2 // Graph 2
const graph2 = manager.plot('testSymmetricPredict2', { width: 1000, height: 400 }); const graph2 = manager.plot('testSymmetricPredict2', { width: 1000, height: 400 });
@ -161,10 +161,10 @@ class SymmetricTestSuite extends TestSuite {
// Prediction calculator error // Prediction calculator error
$assert( $assert(
prediction2d.position.y < manager.find(7).getPosition().y && prediction2d.position.y < manager.find(7).getPosition().y &&
prediction2d.position.x == manager.find(7).getPosition().x, prediction2d.position.x === manager.find(7).getPosition().x,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction2d.order == 0, 'Prediction order should be 0'); $assert(prediction2d.order === 0, 'Prediction order should be 0');
console.log('\tAdded as child of node 5 and dropped at (375, 15):'); console.log('\tAdded as child of node 5 and dropped at (375, 15):');
const prediction2a = manager.predict(5, null, { x: 375, y: 15 }); const prediction2a = manager.predict(5, null, { x: 375, y: 15 });
@ -173,10 +173,10 @@ class SymmetricTestSuite extends TestSuite {
$assert( $assert(
prediction2a.position.y > manager.find(7).getPosition().y && prediction2a.position.y > manager.find(7).getPosition().y &&
prediction2a.position.y < manager.find(8).getPosition().y && prediction2a.position.y < manager.find(8).getPosition().y &&
prediction2a.position.x == manager.find(7).getPosition().x, prediction2a.position.x === manager.find(7).getPosition().x,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction2a.order == 1, 'Prediction order should be 1'); $assert(prediction2a.order === 1, 'Prediction order should be 1');
console.log('\tAdded as child of node 5 and dropped at (375, 45):'); console.log('\tAdded as child of node 5 and dropped at (375, 45):');
const prediction2b = manager.predict(5, null, { x: 375, y: 45 }); const prediction2b = manager.predict(5, null, { x: 375, y: 45 });
@ -184,20 +184,20 @@ class SymmetricTestSuite extends TestSuite {
$assert( $assert(
prediction2b.position.y > manager.find(8).getPosition().y && prediction2b.position.y > manager.find(8).getPosition().y &&
prediction2b.position.y < manager.find(11).getPosition().y && prediction2b.position.y < manager.find(11).getPosition().y &&
prediction2b.position.x == manager.find(7).getPosition().x, prediction2b.position.x === manager.find(7).getPosition().x,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction2b.order == 2, 'Prediction order should be 2'); $assert(prediction2b.order === 2, 'Prediction order should be 2');
console.log('\tAdded as child of node 5 and dropped at (375, 45):'); console.log('\tAdded as child of node 5 and dropped at (375, 45):');
const prediction2c = manager.predict(5, null, { x: 375, y: 65 }); const prediction2c = manager.predict(5, null, { x: 375, y: 65 });
this._plotPrediction(graph2, prediction2c); this._plotPrediction(graph2, prediction2c);
$assert( $assert(
prediction2c.position.y > manager.find(11).getPosition().y && prediction2c.position.y > manager.find(11).getPosition().y &&
prediction2c.position.x == manager.find(11).getPosition().x, prediction2c.position.x === manager.find(11).getPosition().x,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction2c.order == 3, 'Prediction order should be 3'); $assert(prediction2c.order === 3, 'Prediction order should be 3');
// Graph 3 // Graph 3
const graph3 = manager.plot('testSymmetricPredict3', { width: 1000, height: 400 }); const graph3 = manager.plot('testSymmetricPredict3', { width: 1000, height: 400 });
@ -208,20 +208,20 @@ class SymmetricTestSuite extends TestSuite {
$assert( $assert(
prediction3a.position.y > manager.find(5).getPosition().y && prediction3a.position.y > manager.find(5).getPosition().y &&
prediction3a.position.y < manager.find(6).getPosition().y && prediction3a.position.y < manager.find(6).getPosition().y &&
prediction3a.position.x == manager.find(5).getPosition().x, prediction3a.position.x === manager.find(5).getPosition().x,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction3a.order == 2, 'Prediction order should be 2'); $assert(prediction3a.order === 2, 'Prediction order should be 2');
console.log('\tAdded as child of node 3 and dropped at (255, 110):'); console.log('\tAdded as child of node 3 and dropped at (255, 110):');
const prediction3b = manager.predict(3, null, { x: 255, y: 110 }); const prediction3b = manager.predict(3, null, { x: 255, y: 110 });
this._plotPrediction(graph3, prediction3b); this._plotPrediction(graph3, prediction3b);
$assert( $assert(
prediction3b.position.y > manager.find(6).getPosition().y && prediction3b.position.y > manager.find(6).getPosition().y &&
prediction3b.position.x == manager.find(6).getPosition().x, prediction3b.position.x === manager.find(6).getPosition().x,
'Prediction incorrectly positioned', 'Prediction incorrectly positioned',
); );
$assert(prediction3b.order == 3, 'Prediction order should be 3'); $assert(prediction3b.order === 3, 'Prediction order should be 3');
// Graph 4 // Graph 4
console.log('\tAdded as child of node 2 and dropped at (-260, 0):'); console.log('\tAdded as child of node 2 and dropped at (-260, 0):');
@ -231,10 +231,10 @@ class SymmetricTestSuite extends TestSuite {
$assert( $assert(
prediction4.position.y > manager.find(9).getPosition().y && prediction4.position.y > manager.find(9).getPosition().y &&
prediction4.position.y < manager.find(10).getPosition().y && prediction4.position.y < manager.find(10).getPosition().y &&
prediction4.position.x == manager.find(9).getPosition().x, prediction4.position.x === manager.find(9).getPosition().x,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction4.order == 1, 'Prediction order should be 1'); $assert(prediction4.order === 1, 'Prediction order should be 1');
// Graph 5 // Graph 5
console.log('\tPredict nodes added with no position:'); console.log('\tPredict nodes added with no position:');
@ -242,40 +242,40 @@ class SymmetricTestSuite extends TestSuite {
const prediction5a = manager.predict(1, null, null); const prediction5a = manager.predict(1, null, null);
this._plotPrediction(graph5, prediction5a); this._plotPrediction(graph5, prediction5a);
$assert( $assert(
prediction5a.position.y == manager.find(1).getPosition().y && prediction5a.position.y === manager.find(1).getPosition().y &&
prediction5a.position.x > manager.find(1).getPosition().x, prediction5a.position.x > manager.find(1).getPosition().x,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction5a.order == 0, 'Prediction order should be 0'); $assert(prediction5a.order === 0, 'Prediction order should be 0');
const prediction5b = manager.predict(2, null, null); const prediction5b = manager.predict(2, null, null);
this._plotPrediction(graph5, prediction5b); this._plotPrediction(graph5, prediction5b);
$assert( $assert(
prediction5b.position.y > manager.find(10).getPosition().y && prediction5b.position.y > manager.find(10).getPosition().y &&
prediction5b.position.x < manager.find(2).getPosition().x && prediction5b.position.x < manager.find(2).getPosition().x &&
prediction5b.position.x == manager.find(10).getPosition().x, prediction5b.position.x === manager.find(10).getPosition().x,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction5b.order == 2, 'Prediction order should be 2'); $assert(prediction5b.order === 2, 'Prediction order should be 2');
const prediction5c = manager.predict(3, null, null); const prediction5c = manager.predict(3, null, null);
this._plotPrediction(graph5, prediction5c); this._plotPrediction(graph5, prediction5c);
$assert( $assert(
prediction5c.position.y > manager.find(6).getPosition().y && prediction5c.position.y > manager.find(6).getPosition().y &&
prediction5c.position.x > manager.find(3).getPosition().x && prediction5c.position.x > manager.find(3).getPosition().x &&
prediction5c.position.x == manager.find(6).getPosition().x, prediction5c.position.x === manager.find(6).getPosition().x,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction5c.order == 3, 'Prediction order should be 3'); $assert(prediction5c.order === 3, 'Prediction order should be 3');
const prediction5d = manager.predict(10, null, null); const prediction5d = manager.predict(10, null, null);
this._plotPrediction(graph5, prediction5d); this._plotPrediction(graph5, prediction5d);
$assert( $assert(
prediction5d.position.y == manager.find(10).getPosition().y && prediction5d.position.y === manager.find(10).getPosition().y &&
prediction5d.position.x < manager.find(10).getPosition().x, prediction5d.position.x < manager.find(10).getPosition().x,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction5d.order == 0, 'Prediction order should be 0'); $assert(prediction5d.order === 0, 'Prediction order should be 0');
console.log('OK!\n\n'); console.log('OK!\n\n');
} }
@ -295,54 +295,54 @@ class SymmetricTestSuite extends TestSuite {
const prediction1a = manager.predict(1, 2, { x: -250, y: -20 }); const prediction1a = manager.predict(1, 2, { x: -250, y: -20 });
this._plotPrediction(graph1, prediction1a); this._plotPrediction(graph1, prediction1a);
$assert( $assert(
prediction1a.position.x == manager.find(2).getPosition().x && prediction1a.position.x === manager.find(2).getPosition().x &&
prediction1a.position.y == manager.find(2).getPosition().y, prediction1a.position.y === manager.find(2).getPosition().y,
'Prediction position should be the same as node 2', 'Prediction position should be the same as node 2',
); );
$assert( $assert(
prediction1a.order == manager.find(2).getOrder(), prediction1a.order === manager.find(2).getOrder(),
'Predicition order should be the same as node 2', 'Predicition order should be the same as node 2',
); );
const prediction1b = manager.predict(1, 2, { x: -250, y: 20 }); const prediction1b = manager.predict(1, 2, { x: -250, y: 20 });
this._plotPrediction(graph1, prediction1b); this._plotPrediction(graph1, prediction1b);
$assert( $assert(
prediction1b.position.x == manager.find(2).getPosition().x && prediction1b.position.x === manager.find(2).getPosition().x &&
prediction1b.position.y == manager.find(2).getPosition().y, prediction1b.position.y === manager.find(2).getPosition().y,
'Prediction position should be the same as node 2', 'Prediction position should be the same as node 2',
); );
$assert( $assert(
prediction1b.order == manager.find(2).getOrder(), prediction1b.order === manager.find(2).getOrder(),
'Predicition order should be the same as node 2', 'Predicition order should be the same as node 2',
); );
const prediction1c = manager.predict(0, 2, { x: -100, y: -20 }); const prediction1c = manager.predict(0, 2, { x: -100, y: -20 });
this._plotPrediction(graph1, prediction1c); this._plotPrediction(graph1, prediction1c);
$assert( $assert(
prediction1c.position.x == manager.find(1).getPosition().x && prediction1c.position.x === manager.find(1).getPosition().x &&
prediction1c.position.y < manager.find(1).getPosition().y, prediction1c.position.y < manager.find(1).getPosition().y,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction1c.order == 1, 'Prediction order should be 1'); $assert(prediction1c.order === 1, 'Prediction order should be 1');
const prediction1d = manager.predict(0, 2, { x: -100, y: 20 }); const prediction1d = manager.predict(0, 2, { x: -100, y: 20 });
this._plotPrediction(graph1, prediction1d); this._plotPrediction(graph1, prediction1d);
$assert( $assert(
prediction1d.position.x == manager.find(1).getPosition().x && prediction1d.position.x === manager.find(1).getPosition().x &&
prediction1d.position.y > manager.find(1).getPosition().y, prediction1d.position.y > manager.find(1).getPosition().y,
'Prediction is incorrectly positioned', 'Prediction is incorrectly positioned',
); );
$assert(prediction1d.order == 3, 'Prediction order should be 3'); $assert(prediction1d.order === 3, 'Prediction order should be 3');
const prediction1e = manager.predict(1, 2, { x: -250, y: 0 }); const prediction1e = manager.predict(1, 2, { x: -250, y: 0 });
this._plotPrediction(graph1, prediction1e); this._plotPrediction(graph1, prediction1e);
$assert( $assert(
prediction1e.position.x == manager.find(2).getPosition().x && prediction1e.position.x === manager.find(2).getPosition().x &&
prediction1e.position.y == manager.find(2).getPosition().y, prediction1e.position.y === manager.find(2).getPosition().y,
'Prediction position should be the same as node 2', 'Prediction position should be the same as node 2',
); );
$assert( $assert(
prediction1e.order == manager.find(2).getOrder(), prediction1e.order === manager.find(2).getOrder(),
'Predicition order should be the same as node 2', 'Predicition order should be the same as node 2',
); );

View File

@ -197,7 +197,7 @@ unencrypted.]]></text>
<topic position="1100,26" order="0" text="but it can't encrypted" shape="line" id="1190504719"/> <topic position="1100,26" order="0" text="but it can't encrypted" shape="line" id="1190504719"/>
<topic position="1190,51" order="1" text="unless you have some UDP SSL thing" shape="line" id="878085542"/> <topic position="1190,51" order="1" text="unless you have some UDP SSL thing" shape="line" id="878085542"/>
</topic> </topic>
<topic position="-1190,76" order="3" shape="line" id="252326982" bgColor="undefined"> <topic position="-1190,76" order="3" shape="line" id="252326982">
<text><![CDATA[Egerstad said the process of snooping on the traffic is trivial. The problem is not with Tor, which <text><![CDATA[Egerstad said the process of snooping on the traffic is trivial. The problem is not with Tor, which
still works as intended, but with users' expectations: the Tor system is designed to merely still works as intended, but with users' expectations: the Tor system is designed to merely
anonymize Internet traffic and does not perform end-to-end anonymize Internet traffic and does not perform end-to-end

View File

@ -320,7 +320,7 @@
</topic> </topic>
</topic> </topic>
<topic position="1190,2" order="1" text="Spin-offs" shape="line" id="309"> <topic position="1190,2" order="1" text="Spin-offs" shape="line" id="309">
<topic position="-1190,-10" order="0" text="undefined" shape="line" id="300"/> <topic position="-1190,-10" order="0" shape="line" id="300"/>
</topic> </topic>
<topic position="1280,27" order="2" text="Industry contracts" shape="line" id="310"> <topic position="1280,27" order="2" text="Industry contracts" shape="line" id="310">
<topic position="-1280,-35" order="0" text="Industry revenue per staff " shape="line" id="297"/> <topic position="-1280,-35" order="0" text="Industry revenue per staff " shape="line" id="297"/>
@ -330,7 +330,7 @@
per 1,000 researchers [contracts/researchers]]]></text> per 1,000 researchers [contracts/researchers]]]></text>
</topic> </topic>
<topic position="-1460,15" order="2" text="Share of industry income from foreign companies" shape="line" id="307"/> <topic position="-1460,15" order="2" text="Share of industry income from foreign companies" shape="line" id="307"/>
<topic position="-1550,40" order="3" text="undefined" shape="line" id="90"/> <topic position="-1550,40" order="3" shape="line" id="90"/>
<topic position="-1640,65" order="4" text="Difficulties faced by research organization in collaborating with SMEs" shape="line" id="311"/> <topic position="-1640,65" order="4" text="Difficulties faced by research organization in collaborating with SMEs" shape="line" id="311"/>
</topic> </topic>
</topic> </topic>

View File

@ -3,7 +3,7 @@
<topic position="-200,-50" order="1" shape="rectangle" id="5" bgColor="#cccccc"> <topic position="-200,-50" order="1" shape="rectangle" id="5" bgColor="#cccccc">
<text><![CDATA[Baraloto et al. 2010. Functional trait variation and sampling strategies in species-rich plant <text><![CDATA[Baraloto et al. 2010. Functional trait variation and sampling strategies in species-rich plant
communities]]></text> communities]]></text>
<topic position="-200,-350" order="1" text="undefined" shape="line" id="6"/> <topic position="-200,-350" order="1" shape="line" id="6"/>
<topic position="290,-150" order="0" shape="line" id="7"> <topic position="290,-150" order="0" shape="line" id="7">
<text><![CDATA[However, the fast pace of <text><![CDATA[However, the fast pace of
development of plant trait meta-analyses also suggests that development of plant trait meta-analyses also suggests that
@ -46,7 +46,6 @@ tb.]]></text>
failed to accurately estimate the variance of trait values. This failed to accurately estimate the variance of trait values. This
indicates that in situations where accurate estimation of plotlevel indicates that in situations where accurate estimation of plotlevel
variance is desired, complete censuses are essential.]]></text> variance is desired, complete censuses are essential.]]></text>
<note><![CDATA[undefined]]></note>
</topic> </topic>
<topic position="830,0" order="6" shape="line" id="15"> <topic position="830,0" order="6" shape="line" id="15">
<text><![CDATA[We suggest that, in these studies, <text><![CDATA[We suggest that, in these studies,
@ -104,9 +103,9 @@ construir classificações mais detalhadas e com mais dados confiáveis.
colonization groups based on the timing of seedling, sapling, and colonization groups based on the timing of seedling, sapling, and
tree recruitment in secondary forests.]]></text> tree recruitment in secondary forests.]]></text>
</topic> </topic>
<topic position="740,-12" order="5" text="undefined" shape="line" id="27"/> <topic position="740,-12" order="5" shape="line" id="27"/>
<topic position="830,13" order="6" text="undefined" shape="line" id="28"/> <topic position="830,13" order="6" shape="line" id="28"/>
<topic position="920,38" order="7" text="undefined" shape="line" id="29"/> <topic position="920,38" order="7" shape="line" id="29"/>
<topic position="1010,63" order="8" shape="line" id="30"> <topic position="1010,63" order="8" shape="line" id="30">
<text><![CDATA[Classifying functional types <text><![CDATA[Classifying functional types
based on functional traits with low plasticity, such as wood density based on functional traits with low plasticity, such as wood density

View File

@ -1,17 +1,17 @@
<map name="freeMind_resources" version="tango"> <map name="freeMind_resources" version="tango">
<topic central="true" text="FreeMind Resources" id="1330730879"> <topic central="true" text="FreeMind Resources" id="1330730879">
<topic position="200,-100" order="0" text="Application" shape="line" id="906353570" bgColor="undefined"> <topic position="200,-100" order="0" text="Application" shape="line" id="906353570">
<topic position="200,-50" order="0" text="What is it?" shape="line" id="293234618" bgColor="undefined"> <topic position="200,-50" order="0" text="What is it?" shape="line" id="293234618">
<topic position="200,-50" order="0" text="A Freeware (as in free beer) Mindmapping tool coded in Java" shape="line" id="666230517"/> <topic position="200,-50" order="0" text="A Freeware (as in free beer) Mindmapping tool coded in Java" shape="line" id="666230517"/>
<topic position="-290,-75" order="0" text="Expects Java 1.4 or above on client machine" shape="line" id="339571721"/> <topic position="-290,-75" order="0" text="Expects Java 1.4 or above on client machine" shape="line" id="339571721"/>
</topic> </topic>
<topic position="-290,-125" order="0" text="How to do?" shape="line" id="39960632" bgColor="undefined"> <topic position="-290,-125" order="0" text="How to do?" shape="line" id="39960632">
<topic position="290,-162" order="0" text="Install it" shape="line" id="904501221"> <topic position="290,-162" order="0" text="Install it" shape="line" id="904501221">
<topic position="-290,-212" order="0" text="Links" shape="line" id="1911559485"> <topic position="-290,-212" order="0" text="Links" shape="line" id="1911559485">
<topic position="290,-237" order="0" text="Download the Java Runtime Environment (at least J2RE1.4)" shape="line" id="1031016126" bgColor="undefined"> <topic position="290,-237" order="0" text="Download the Java Runtime Environment (at least J2RE1.4)" shape="line" id="1031016126">
<link url="http://java.sun.com/j2se" urlType="url"/> <link url="http://java.sun.com/j2se" urlType="url"/>
</topic> </topic>
<topic position="380,-212" order="1" text="Download the Application" shape="line" id="1612101865" bgColor="undefined"> <topic position="380,-212" order="1" text="Download the Application" shape="line" id="1612101865">
<link url="http://freemind.sourceforge.net/wiki/index.php/Main_Page#Download_and_install" urlType="url"/> <link url="http://freemind.sourceforge.net/wiki/index.php/Main_Page#Download_and_install" urlType="url"/>
</topic> </topic>
</topic> </topic>
@ -64,12 +64,12 @@ Ctrl + F in your browser?]]></note>
</topic> </topic>
</topic> </topic>
</topic> </topic>
<topic position="-290,-37" order="0" text="Applet Browser" shape="line" id="1647062097" bgColor="undefined"> <topic position="-290,-37" order="0" text="Applet Browser" shape="line" id="1647062097">
<topic position="290,-62" order="0" text="What is it?" shape="rounded rectangle" id="287577997" bgColor="undefined"> <topic position="290,-62" order="0" text="What is it?" shape="rounded rectangle" id="287577997">
<topic position="-290,-87" order="0" text="A Java applet based browser " shape="line" id="1855944960"/> <topic position="-290,-87" order="0" text="A Java applet based browser " shape="line" id="1855944960"/>
<topic position="-380,-62" order="1" text="Expects Java 1.4 or above on client machine" shape="line" id="300344325"/> <topic position="-380,-62" order="1" text="Expects Java 1.4 or above on client machine" shape="line" id="300344325"/>
</topic> </topic>
<topic position="380,-37" order="1" text="How to do?" shape="line" shrink="true" id="1254385465" bgColor="undefined"> <topic position="380,-37" order="1" text="How to do?" shape="line" shrink="true" id="1254385465">
<topic position="-380,-62" order="0" text="See examples" shape="line" id="1491154453"> <topic position="-380,-62" order="0" text="See examples" shape="line" id="1491154453">
<topic position="380,-87" order="0" text="Public Maps" shape="line" id="1082166644"> <topic position="380,-87" order="0" text="Public Maps" shape="line" id="1082166644">
<link url="http://freemind.sourceforge.net/PublicMaps.html" urlType="url"/> <link url="http://freemind.sourceforge.net/PublicMaps.html" urlType="url"/>
@ -101,8 +101,8 @@ site.]]></text>
</topic> </topic>
</topic> </topic>
</topic> </topic>
<topic position="-380,-12" order="1" text="Flash Browser" shape="line" id="866838286" bgColor="undefined"> <topic position="-380,-12" order="1" text="Flash Browser" shape="line" id="866838286">
<topic position="380,-37" order="0" text="What is it?" shape="line" id="1079211058" bgColor="undefined"> <topic position="380,-37" order="0" text="What is it?" shape="line" id="1079211058">
<topic position="-380,-74" order="0" text="A browser which uses Shockwave Flash" shape="line" id="1719479201"/> <topic position="-380,-74" order="0" text="A browser which uses Shockwave Flash" shape="line" id="1719479201"/>
<topic position="-470,-49" order="1" text="Does not require Java 1.4 or above on client machine" shape="line" id="838930706"/> <topic position="-470,-49" order="1" text="Does not require Java 1.4 or above on client machine" shape="line" id="838930706"/>
<topic position="-560,-24" order="2" text="Expects Flash Player on client machine" shape="line" id="961870575"> <topic position="-560,-24" order="2" text="Expects Flash Player on client machine" shape="line" id="961870575">
@ -110,7 +110,7 @@ site.]]></text>
<topic position="650,-24" order="1" text="Recommend Flash Player 8" shape="line" id="913615141"/> <topic position="650,-24" order="1" text="Recommend Flash Player 8" shape="line" id="913615141"/>
</topic> </topic>
</topic> </topic>
<topic position="470,-12" order="1" text="How to do?" shape="line" id="1824115095" bgColor="undefined"> <topic position="470,-12" order="1" text="How to do?" shape="line" id="1824115095">
<topic position="-470,-37" order="0" text="See examples" shape="line" id="1242194014"> <topic position="-470,-37" order="0" text="See examples" shape="line" id="1242194014">
<topic position="470,-62" order="0" text="Hardware Support for Linux" shape="line" id="1249980290"> <topic position="470,-62" order="0" text="Hardware Support for Linux" shape="line" id="1249980290">
<link url="http://eric.lavar.de/comp/linux/hw/" urlType="url"/> <link url="http://eric.lavar.de/comp/linux/hw/" urlType="url"/>

View File

@ -2,19 +2,19 @@
<topic central="true" id="704795576"> <topic central="true" id="704795576">
<text><![CDATA[Writing an Essay <text><![CDATA[Writing an Essay
With FreeMind]]></text> With FreeMind]]></text>
<topic position="200,-200" order="0" text="Getting Started" shape="line" shrink="true" id="60307947" bgColor="undefined"> <topic position="200,-200" order="0" text="Getting Started" shape="line" shrink="true" id="60307947">
<topic position="200,-150" order="0" shape="line" id="484974719" bgColor="undefined"> <topic position="200,-150" order="0" shape="line" id="484974719">
<text><![CDATA[The first thing you'll want to do is to create a new FreeMind file for your essay. Select File->New <text><![CDATA[The first thing you'll want to do is to create a new FreeMind file for your essay. Select File->New
on the menu, and a blank file will appear. on the menu, and a blank file will appear.
]]></text> ]]></text>
</topic> </topic>
<topic position="-290,-250" order="0" shape="line" id="1072554383" bgColor="undefined"> <topic position="-290,-250" order="0" shape="line" id="1072554383">
<text><![CDATA[Next, click in the centre of the map, and replace the text there with the essay title you have <text><![CDATA[Next, click in the centre of the map, and replace the text there with the essay title you have
chosen. It's good to have the question you're answering before you the whole time, so you can chosen. It's good to have the question you're answering before you the whole time, so you can
immediately see how your ideas relate to immediately see how your ideas relate to
it.]]></text> it.]]></text>
</topic> </topic>
<topic position="-380,-225" order="1" shape="line" id="1631286703" bgColor="undefined"> <topic position="-380,-225" order="1" shape="line" id="1631286703">
<text><![CDATA[<!-- <text><![CDATA[<!--
p { margin-top: 0 } p { margin-top: 0 }
--> -->
@ -28,22 +28,22 @@ it.]]></text>
(When you're a bit more familiar with FreeMind, you'll find it quicker to use the Shortcut Keys -- you can also use Alt + Shift + Left, or Alt + Shift + Right to move between maps.)]]></text> (When you're a bit more familiar with FreeMind, you'll find it quicker to use the Shortcut Keys -- you can also use Alt + Shift + Left, or Alt + Shift + Right to move between maps.)]]></text>
</topic> </topic>
<topic position="-470,-200" order="2" text="You're now ready to start work on the essay." shape="line" id="538231078" bgColor="undefined"/> <topic position="-470,-200" order="2" text="You're now ready to start work on the essay." shape="line" id="538231078"/>
</topic> </topic>
<topic position="-290,-62" order="0" text="The process of research" shape="line" shrink="true" id="1886958546" bgColor="undefined"> <topic position="-290,-62" order="0" text="The process of research" shape="line" shrink="true" id="1886958546">
<topic position="290,-124" order="0" shape="line" id="499702363" bgColor="undefined"> <topic position="290,-124" order="0" shape="line" id="499702363">
<text><![CDATA[If a question is worth asking at all (and be generous to your teachers, and assume that their <text><![CDATA[If a question is worth asking at all (and be generous to your teachers, and assume that their
question is!), then it's not going to have the kind of answer that you can just make up on the spot. question is!), then it's not going to have the kind of answer that you can just make up on the spot.
It will require It will require
research.]]></text> research.]]></text>
</topic> </topic>
<topic position="380,-99" order="1" text="Research requires both finding things out about the world, and hard thinking." shape="line" id="1374284784" bgColor="undefined"/> <topic position="380,-99" order="1" text="Research requires both finding things out about the world, and hard thinking." shape="line" id="1374284784"/>
<topic position="470,-74" order="2" shape="line" id="1038997740" bgColor="undefined"> <topic position="470,-74" order="2" shape="line" id="1038997740">
<text><![CDATA[FreeMind helps you with both aspects of research. FreeMind helps you to capture all the new <text><![CDATA[FreeMind helps you with both aspects of research. FreeMind helps you to capture all the new
information you need for your essay, and also to order your information you need for your essay, and also to order your
thoughts.]]></text> thoughts.]]></text>
</topic> </topic>
<topic position="560,-49" order="3" text="FreeMind does this by facilitating:" shape="line" id="1522470300" bgColor="undefined"> <topic position="560,-49" order="3" text="FreeMind does this by facilitating:" shape="line" id="1522470300">
<topic position="-560,-99" order="0" text="Taking Notes" shape="line" id="1963065372"> <topic position="-560,-99" order="0" text="Taking Notes" shape="line" id="1963065372">
<link url="http://#Freemind_Link_513978291" urlType="url"/> <link url="http://#Freemind_Link_513978291" urlType="url"/>
</topic> </topic>
@ -57,7 +57,7 @@ thoughts.]]></text>
<link url="http://#Freemind_Link_341601142" urlType="url"/> <link url="http://#Freemind_Link_341601142" urlType="url"/>
</topic> </topic>
</topic> </topic>
<topic position="650,-24" order="4" text="When you've made your outline you can" shape="line" id="759053646" bgColor="undefined"> <topic position="650,-24" order="4" text="When you've made your outline you can" shape="line" id="759053646">
<topic position="-650,-61" order="0" text="Print your map" shape="line" id="996906209"/> <topic position="-650,-61" order="0" text="Print your map" shape="line" id="996906209"/>
<topic position="-740,-36" order="1" text="Export to your wordprocessor" shape="line" id="1501502447"> <topic position="-740,-36" order="1" text="Export to your wordprocessor" shape="line" id="1501502447">
<link url="http://#Freemind_Link_877777095" urlType="url"/> <link url="http://#Freemind_Link_877777095" urlType="url"/>
@ -67,8 +67,8 @@ thoughts.]]></text>
</topic> </topic>
</topic> </topic>
</topic> </topic>
<topic position="-380,-37" order="1" text="Planning an Essay" shape="line" shrink="true" id="1034561457" bgColor="undefined"> <topic position="-380,-37" order="1" text="Planning an Essay" shape="line" shrink="true" id="1034561457">
<topic position="380,-87" order="0" text="Brainstorming" shape="line" shrink="true" id="1" bgColor="undefined"> <topic position="380,-87" order="0" text="Brainstorming" shape="line" shrink="true" id="1">
<topic position="-380,-162" order="0" shape="line" id="1420002558"> <topic position="-380,-162" order="0" shape="line" id="1420002558">
<text><![CDATA[Brainstorming is a way of trying to geting all your ideas about a topic down on paper as quickly as <text><![CDATA[Brainstorming is a way of trying to geting all your ideas about a topic down on paper as quickly as
possible.]]></text> possible.]]></text>
@ -83,18 +83,18 @@ later.]]></text>
<topic position="-740,-62" order="4" text="Pressing Insert adds another idea as a subidea of the one you've currently selected." shape="line" id="1371557121"/> <topic position="-740,-62" order="4" text="Pressing Insert adds another idea as a subidea of the one you've currently selected." shape="line" id="1371557121"/>
<topic position="-830,-37" order="5" text="(The imagination you'll have to supply yourself!)" shape="line" id="443781940"/> <topic position="-830,-37" order="5" text="(The imagination you'll have to supply yourself!)" shape="line" id="443781940"/>
</topic> </topic>
<topic position="470,-62" order="1" text="Taking Notes" shape="line" shrink="true" id="513978291" bgColor="undefined"> <topic position="470,-62" order="1" text="Taking Notes" shape="line" shrink="true" id="513978291">
<topic position="-470,-124" order="0" shape="line" id="709453371" bgColor="undefined"> <topic position="-470,-124" order="0" shape="line" id="709453371">
<text><![CDATA[Different people take notes in different ways. Whichever way you take notes, you should find <text><![CDATA[Different people take notes in different ways. Whichever way you take notes, you should find
FreeMind FreeMind
helpful.]]></text> helpful.]]></text>
</topic> </topic>
<topic position="-560,-99" order="1" shape="line" id="249608113" bgColor="undefined"> <topic position="-560,-99" order="1" shape="line" id="249608113">
<text><![CDATA[One good way of using FreeMind is to add one node per book or article you read. Name the node a <text><![CDATA[One good way of using FreeMind is to add one node per book or article you read. Name the node a
short version of the article title. short version of the article title.
]]></text> ]]></text>
</topic> </topic>
<topic position="-650,-74" order="2" shape="line" shrink="true" id="1470413282" bgColor="undefined"> <topic position="-650,-74" order="2" shape="line" shrink="true" id="1470413282">
<text><![CDATA[Then add your notes on the article as a node note. To insert a note, go to the View menu, and <text><![CDATA[Then add your notes on the article as a node note. To insert a note, go to the View menu, and
select "Show Note Window". You can then add your notes select "Show Note Window". You can then add your notes
below.]]></text> below.]]></text>
@ -104,8 +104,8 @@ helpful to hide it after you've added your note, by selecting "Show Note Window"
menu.]]></text> menu.]]></text>
</topic> </topic>
</topic> </topic>
<topic position="-740,-49" order="3" text="Don't forget to take full references for all the quotations you use. " shape="line" id="1226928695" bgColor="undefined"/> <topic position="-740,-49" order="3" text="Don't forget to take full references for all the quotations you use. " shape="line" id="1226928695"/>
<topic position="-830,-24" order="4" text="FreeMind can also do some clever things with web links and email addresses." shape="line" shrink="true" id="1195317986" bgColor="undefined"> <topic position="-830,-24" order="4" text="FreeMind can also do some clever things with web links and email addresses." shape="line" shrink="true" id="1195317986">
<topic position="830,-86" order="0" shape="line" id="1167090962"> <topic position="830,-86" order="0" shape="line" id="1167090962">
<text><![CDATA[If you're researching on the web, then FreeMind can automatically link your note to the web page <text><![CDATA[If you're researching on the web, then FreeMind can automatically link your note to the web page
you're writing about. you're writing about.
@ -132,7 +132,7 @@ address.]]></text>
</topic> </topic>
</topic> </topic>
</topic> </topic>
<topic position="560,-37" order="2" text="Sifting and organising your ideas" shape="line" shrink="true" id="331016293" bgColor="undefined"> <topic position="560,-37" order="2" text="Sifting and organising your ideas" shape="line" shrink="true" id="331016293">
<topic position="-560,-124" order="0" shape="line" id="136989740"> <topic position="-560,-124" order="0" shape="line" id="136989740">
<text><![CDATA[After you've done a bit of brainstorming, and have written all the ideas you can think of, it's time <text><![CDATA[After you've done a bit of brainstorming, and have written all the ideas you can think of, it's time
to start sorting your ideas to start sorting your ideas
@ -174,7 +174,7 @@ menu, and call the new one it something like "Essay_Outline v1".
]]></text> ]]></text>
</topic> </topic>
</topic> </topic>
<topic position="650,-12" order="3" text="Outlining" shape="line" shrink="true" id="341601142" bgColor="undefined"> <topic position="650,-12" order="3" text="Outlining" shape="line" shrink="true" id="341601142">
<topic position="-650,-87" order="0" text="Now you know what your main point is, you can write an outline of the argument of the essay." shape="line" id="190098699"/> <topic position="-650,-87" order="0" text="Now you know what your main point is, you can write an outline of the argument of the essay." shape="line" id="190098699"/>
<topic position="-740,-62" order="1" text="The point of producing an outline is to work out how you will argue for your essay's main claim." shape="line" id="132833105"/> <topic position="-740,-62" order="1" text="The point of producing an outline is to work out how you will argue for your essay's main claim." shape="line" id="132833105"/>
<topic position="-830,-37" order="2" shape="line" id="1132818589"> <topic position="-830,-37" order="2" shape="line" id="1132818589">
@ -237,14 +237,14 @@ point.]]></text>
</topic> </topic>
</topic> </topic>
</topic> </topic>
<topic position="-470,-12" order="2" text="From Outline to Finished Work" shape="line" shrink="true" id="1755853195" bgColor="undefined"> <topic position="-470,-12" order="2" text="From Outline to Finished Work" shape="line" shrink="true" id="1755853195">
<topic position="470,-74" order="0" shape="line" id="1449950809" bgColor="undefined"> <topic position="470,-74" order="0" shape="line" id="1449950809">
<text><![CDATA[Writing the outline of your essay is the hard part. Once you have a good outline, it's much easier <text><![CDATA[Writing the outline of your essay is the hard part. Once you have a good outline, it's much easier
to write a good essay or a good to write a good essay or a good
presentation.]]></text> presentation.]]></text>
</topic> </topic>
<topic position="560,-49" order="1" text="You'll probably find it easier to to the actual writing of the essay in your wordprocessor." shape="line" id="1607766784" bgColor="undefined"/> <topic position="560,-49" order="1" text="You'll probably find it easier to to the actual writing of the essay in your wordprocessor." shape="line" id="1607766784"/>
<topic position="650,-24" order="2" text="Exporting your outline to your Wordprocessor" shape="line" shrink="true" id="877777095" bgColor="undefined"> <topic position="650,-24" order="2" text="Exporting your outline to your Wordprocessor" shape="line" shrink="true" id="877777095">
<topic position="-650,-99" order="0" shape="line" shrink="true" id="1821901940"> <topic position="-650,-99" order="0" shape="line" shrink="true" id="1821901940">
<text><![CDATA[FreeMind currently exports much better to OpenOffice than to Microsoft Word. So if you don't yet <text><![CDATA[FreeMind currently exports much better to OpenOffice than to Microsoft Word. So if you don't yet
have OpenOffice, it's well worth downloading it (it's have OpenOffice, it's well worth downloading it (it's
@ -280,7 +280,7 @@ wordprocessor as
normal.]]></text> normal.]]></text>
</topic> </topic>
</topic> </topic>
<topic position="740,1" order="3" text="Making a presentation" shape="line" shrink="true" id="781772166" bgColor="undefined"> <topic position="740,1" order="3" text="Making a presentation" shape="line" shrink="true" id="781772166">
<topic position="-740,-74" order="0" text="FreeMind also provides a good way of outlining PowerPoint presentations." shape="line" id="1714771405"/> <topic position="-740,-74" order="0" text="FreeMind also provides a good way of outlining PowerPoint presentations." shape="line" id="1714771405"/>
<topic position="-830,-49" order="1" text="You'll need OpenOffice again." shape="line" id="233010529"/> <topic position="-830,-49" order="1" text="You'll need OpenOffice again." shape="line" id="233010529"/>
<topic position="-920,-24" order="2" text="Follow the instructions above to export your outline to OpenOffice." shape="line" id="1394183501"/> <topic position="-920,-24" order="2" text="Follow the instructions above to export your outline to OpenOffice." shape="line" id="1394183501"/>
@ -296,50 +296,50 @@ best
results.]]></text> results.]]></text>
</topic> </topic>
</topic> </topic>
<topic position="830,26" order="4" text="Things to check before you submit your essay" shape="line" shrink="true" id="1657086138" bgColor="undefined"> <topic position="830,26" order="4" text="Things to check before you submit your essay" shape="line" shrink="true" id="1657086138">
<topic position="-830,-111" order="0" shape="line" id="1855894453"> <topic position="-830,-111" order="0" shape="line" id="1855894453">
<text><![CDATA[(This advice doesn't tell you anything about how to use FreeMind, but it may help you get a better <text><![CDATA[(This advice doesn't tell you anything about how to use FreeMind, but it may help you get a better
mark in your mark in your
essay!)]]></text> essay!)]]></text>
</topic> </topic>
<topic position="-920,-86" order="1" text="Does my essay have a main claim?" shape="line" id="1803078302" bgColor="undefined"> <topic position="-920,-86" order="1" text="Does my essay have a main claim?" shape="line" id="1803078302">
<note><![CDATA[Another way of asking this question is can you sum up in a sentence what the main point is that your essay is making?) If you don't have a main claim (or don't know what your main claim is!), then your essay will not get a good mark. You are assessed on the quality of the argument you put forward for your main claim, and in order to be able to do this we (and you) need to know what your main claim is.]]></note> <note><![CDATA[Another way of asking this question is can you sum up in a sentence what the main point is that your essay is making?) If you don't have a main claim (or don't know what your main claim is!), then your essay will not get a good mark. You are assessed on the quality of the argument you put forward for your main claim, and in order to be able to do this we (and you) need to know what your main claim is.]]></note>
</topic> </topic>
<topic position="-1010,-61" order="2" text="Does my main claim provide a full answer the question that I have been asked?" shape="line" id="107276913" bgColor="undefined"> <topic position="-1010,-61" order="2" text="Does my main claim provide a full answer the question that I have been asked?" shape="line" id="107276913">
<note><![CDATA[You must be honest with yourself at this point: if you suspect that you haven't fully answered the question, then you must either (a) revise your answer so that you do have a full answer to the question, or (b) provide an argument for why it is that the angle you want to bring to the question is legitimate (for example, explain why it is legitimate to focus on just one aspect of the question).]]></note> <note><![CDATA[You must be honest with yourself at this point: if you suspect that you haven't fully answered the question, then you must either (a) revise your answer so that you do have a full answer to the question, or (b) provide an argument for why it is that the angle you want to bring to the question is legitimate (for example, explain why it is legitimate to focus on just one aspect of the question).]]></note>
</topic> </topic>
<topic position="-1100,-36" order="3" text="Have I made it obvious what my main claim is?" shape="line" id="1628680821" bgColor="undefined"> <topic position="-1100,-36" order="3" text="Have I made it obvious what my main claim is?" shape="line" id="1628680821">
<note><![CDATA[You should state what your main claim is in at least two places, first in the introduction, and second in the conclusion. (The bits in between should be devoted to arguing for your main claim).]]></note> <note><![CDATA[You should state what your main claim is in at least two places, first in the introduction, and second in the conclusion. (The bits in between should be devoted to arguing for your main claim).]]></note>
</topic> </topic>
<topic position="-1190,-11" order="4" text="Do I have an argument for my main claim?" shape="line" id="927542090" bgColor="undefined"> <topic position="-1190,-11" order="4" text="Do I have an argument for my main claim?" shape="line" id="927542090">
<note><![CDATA[What reasons have you put forward as to why a reasonable (but sceptical) person should accept that your main claim is true? If you don't have any reasons (but merely a gut intuition) then you need to go back and revise, and find some arguments.]]></note> <note><![CDATA[What reasons have you put forward as to why a reasonable (but sceptical) person should accept that your main claim is true? If you don't have any reasons (but merely a gut intuition) then you need to go back and revise, and find some arguments.]]></note>
</topic> </topic>
<topic position="-1280,14" order="5" text="Is my argument for my main claim sound?" shape="line" id="337592890" bgColor="undefined"> <topic position="-1280,14" order="5" text="Is my argument for my main claim sound?" shape="line" id="337592890">
<note><![CDATA[Does your main claim follow logically from the supporting reasons you put forward? And are those supporting reasons themselves true (or at least plausibly true)?]]></note> <note><![CDATA[Does your main claim follow logically from the supporting reasons you put forward? And are those supporting reasons themselves true (or at least plausibly true)?]]></note>
</topic> </topic>
<topic position="-1370,39" order="6" text="Do I have an introduction which provides an overview of the structure of my argument?" shape="line" id="1338320981" bgColor="undefined"> <topic position="-1370,39" order="6" text="Do I have an introduction which provides an overview of the structure of my argument?" shape="line" id="1338320981">
<note><![CDATA[It is not enough e.g. to say that “I will be looking at arguments on both sides of this issue and coming to a conclusion”. You should tell us which arguments you will be looking at, whatyour evaluation of each of these arguments will be, and howthis analysis justifies the overall main claim you will be making. There are two reasons to give an overview of the structure of your argument: (a) it makes it much easier for the reader to grasp what you are saying, and why; (b) writing a summary of the structure of your argument is a good way of testing that you do in fact have a coherent argument.]]></note> <note><![CDATA[It is not enough e.g. to say that “I will be looking at arguments on both sides of this issue and coming to a conclusion”. You should tell us which arguments you will be looking at, whatyour evaluation of each of these arguments will be, and howthis analysis justifies the overall main claim you will be making. There are two reasons to give an overview of the structure of your argument: (a) it makes it much easier for the reader to grasp what you are saying, and why; (b) writing a summary of the structure of your argument is a good way of testing that you do in fact have a coherent argument.]]></note>
</topic> </topic>
<topic position="-1460,64" order="7" text="What reasons might a reasonable person have for doubting my main claim?" shape="line" id="1521390030" bgColor="undefined"> <topic position="-1460,64" order="7" text="What reasons might a reasonable person have for doubting my main claim?" shape="line" id="1521390030">
<note><![CDATA[Remember that in any academic debate, anything worth saying will be disputed. If you can't think of any reasons why someone might doubt your main claim, it's likely that you are in the grip of a dogmatic certainty that you are right. This is not good: your essay will come across as a rant, which is the last thing you want.]]></note> <note><![CDATA[Remember that in any academic debate, anything worth saying will be disputed. If you can't think of any reasons why someone might doubt your main claim, it's likely that you are in the grip of a dogmatic certainty that you are right. This is not good: your essay will come across as a rant, which is the last thing you want.]]></note>
</topic> </topic>
<topic position="-1550,89" order="8" text="Have I responded to these reasons for doubting my main claim in a convincing way?" shape="line" id="1843933327" bgColor="undefined"> <topic position="-1550,89" order="8" text="Have I responded to these reasons for doubting my main claim in a convincing way?" shape="line" id="1843933327">
<note><![CDATA[To be convincing, you might show that the doubts, while reasonable, are not well founded; or you could make your main claim more specific or nuanced in deference to them.]]></note> <note><![CDATA[To be convincing, you might show that the doubts, while reasonable, are not well founded; or you could make your main claim more specific or nuanced in deference to them.]]></note>
</topic> </topic>
<topic position="-1640,114" order="9" text="Is there any material in my essay which might seem irrelevant to establishing my main point?" shape="line" id="982795475" bgColor="undefined"> <topic position="-1640,114" order="9" text="Is there any material in my essay which might seem irrelevant to establishing my main point?" shape="line" id="982795475">
<note><![CDATA[If there is, then either delete this material, or explain why this material is after all relevant.]]></note> <note><![CDATA[If there is, then either delete this material, or explain why this material is after all relevant.]]></note>
</topic> </topic>
<topic position="-1730,139" order="10" text="Have I fully acknowledged all my sources, and marked all quotations as quotations?" shape="line" id="606334721" bgColor="undefined"> <topic position="-1730,139" order="10" text="Have I fully acknowledged all my sources, and marked all quotations as quotations?" shape="line" id="606334721">
<note><![CDATA[If not then you are guilty of plagiarism. This is a serious offence, and you are likely to fail your course..]]></note> <note><![CDATA[If not then you are guilty of plagiarism. This is a serious offence, and you are likely to fail your course..]]></note>
</topic> </topic>
</topic> </topic>
</topic> </topic>
<topic position="-560,13" order="3" text="About this map" shape="line" shrink="true" id="854745518" bgColor="undefined"> <topic position="-560,13" order="3" text="About this map" shape="line" shrink="true" id="854745518">
<topic position="560,-24" order="0" text="Version 0.1, Jan 2 2008" shape="line" id="1464926185" bgColor="undefined"/> <topic position="560,-24" order="0" text="Version 0.1, Jan 2 2008" shape="line" id="1464926185"/>
<topic position="650,1" order="1" text="James Wilson" shape="line" id="1351075037" bgColor="undefined"> <topic position="650,1" order="1" text="James Wilson" shape="line" id="1351075037">
<link url="http://mailto:j.g.wilson@peak.keele.ac.uk" urlType="mail"/> <link url="http://mailto:j.g.wilson@peak.keele.ac.uk" urlType="mail"/>
</topic> </topic>
<topic position="740,26" order="2" text="Notes on this map" shape="line" id="1843583599" bgColor="undefined"> <topic position="740,26" order="2" text="Notes on this map" shape="line" id="1843583599">
<note><![CDATA[This map is intended to help someone who has to write an argumentative essay in a subject such as history or philosophy to write better essays with the help of FreeMind. Copyright for this map resides with the author. Released under the Creative Commons Attribution-ShareAlike licence v.2.00. http://creativecommons.org/licenses/by-sa/2.0/uk/ <note><![CDATA[This map is intended to help someone who has to write an argumentative essay in a subject such as history or philosophy to write better essays with the help of FreeMind. Copyright for this map resides with the author. Released under the Creative Commons Attribution-ShareAlike licence v.2.00. http://creativecommons.org/licenses/by-sa/2.0/uk/

View File

@ -2,15 +2,22 @@
"compilerOptions": { "compilerOptions": {
"outDir": "./dist/", "outDir": "./dist/",
"sourceMap": true, "sourceMap": true,
"noImplicitAny": false,
"module": "amd", "module": "amd",
"moduleResolution": "node", "moduleResolution": "node",
"target": "ES2020", "target": "es6",
"allowJs": true, "allowJs": true,
"strict": true,
"esModuleInterop": true, "esModuleInterop": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"declaration": true, "declaration": true,
"strictNullChecks": true, "strictNullChecks": true,
"noImplicitAny": false,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"strictFunctionTypes": true,
"rootDirs": [ "rootDirs": [
"src", "src",
] ]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

@ -7,7 +7,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="<%=PUBLIC_URL%>/favicon.ico" /> <link rel="icon" href="<%=PUBLIC_URL%>/favicon.ico" />
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;600&display=swap" rel="stylesheet" onload="if(media!='all')media='all'" media="none"/> <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;600&display=swap" rel="stylesheet" rel="preload"/>
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />

View File

@ -1,3 +1,20 @@
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { ReactElement, Suspense, useEffect } from 'react'; import React, { ReactElement, Suspense, useEffect } from 'react';
import { FormattedMessage, IntlProvider } from 'react-intl'; import { FormattedMessage, IntlProvider } from 'react-intl';
import { Route, Routes, BrowserRouter as Router, useNavigate } from 'react-router-dom'; import { Route, Routes, BrowserRouter as Router, useNavigate } from 'react-router-dom';
@ -22,12 +39,14 @@ const EditorPage = React.lazy(() => import('./components/editor-page'));
const MapsPage = React.lazy(() => import('./components/maps-page')); const MapsPage = React.lazy(() => import('./components/maps-page'));
// Google Analytics Initialization. // Google Analytics Initialization.
ReactGA.initialize([ const trackingId = AppConfig.getGoogleAnalyticsAccount();
if (trackingId) {
ReactGA.initialize([
{ {
trackingId: AppConfig.getGoogleAnalyticsAccount(), trackingId: trackingId,
}, },
]); ]);
}
const queryClient = new QueryClient({ const queryClient = new QueryClient({
defaultOptions: { defaultOptions: {
queries: { queries: {

View File

@ -17,7 +17,6 @@
*/ */
import Client from '../client'; import Client from '../client';
import CacheDecoratorClient from '../client/cache-decorator-client';
import MockClient from '../client/mock-client'; import MockClient from '../client/mock-client';
import RestClient from '../client/rest-client'; import RestClient from '../client/rest-client';
@ -91,8 +90,7 @@ class _AppConfig {
result = new MockClient(); result = new MockClient();
} }
// Wrap with a cache decorator ... return result;
return new CacheDecoratorClient(result);
} }
getBaseUrl(): string { getBaseUrl(): string {

View File

@ -57,8 +57,8 @@ export default abstract class AppI18n {
public static getDefaultLocale(): Locale { public static getDefaultLocale(): Locale {
// Fetch local from local storage ... // Fetch local from local storage ...
let result: Locale; let result: Locale | null = null;
const userLocaleCode: string = localStorage.getItem(AppI18n.LOCAL_STORAGE_KEY); const userLocaleCode: string | null = localStorage.getItem(AppI18n.LOCAL_STORAGE_KEY);
if (userLocaleCode) { if (userLocaleCode) {
result = localeFromStr(userLocaleCode); result = localeFromStr(userLocaleCode);
} }

View File

@ -1,143 +0,0 @@
import Client, {
AccountInfo,
BasicMapInfo,
ChangeHistory,
ImportMapInfo,
Label,
MapInfo,
NewUser,
Permission,
Oauth2CallbackResult,
ForgotPasswordResult,
} from '..';
import { LocaleCode } from '../../app-i18n';
class CacheDecoratorClient implements Client {
private client: Client;
constructor(client: Client) {
this.client = client;
}
processGoogleCallback(code: string): Promise<Oauth2CallbackResult> {
return this.client.processGoogleCallback(code);
}
confirmAccountSync(email: string, code: string): Promise<void> {
return this.client.confirmAccountSync(email, code);
}
fetchStarred(id: number): Promise<boolean> {
return this.client.fetchStarred(id);
}
onSessionExpired(callback?: () => void): () => void {
return this.client.onSessionExpired(callback);
}
deleteAccount(): Promise<void> {
return this.client.deleteAccount();
}
importMap(model: ImportMapInfo): Promise<number> {
return this.client.importMap(model);
}
createMap(map: BasicMapInfo): Promise<number> {
return this.client.createMap(map);
}
deleteMaps(ids: number[]): Promise<void> {
return this.client.deleteMaps(ids);
}
deleteMap(id: number): Promise<void> {
return this.client.deleteMap(id);
}
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void> {
return this.client.renameMap(id, basicInfo);
}
fetchAllMaps(): Promise<MapInfo[]> {
return this.client.fetchAllMaps();
}
fetchMapPermissions(id: number): Promise<Permission[]> {
return this.client.fetchMapPermissions(id);
}
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> {
return this.client.addMapPermissions(id, message, permissions);
}
deleteMapPermission(id: number, email: string): Promise<void> {
return this.client.deleteMapPermission(id, email);
}
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number> {
return this.client.duplicateMap(id, basicInfo);
}
updateAccountLanguage(locale: LocaleCode): Promise<void> {
return this.client.updateAccountLanguage(locale);
}
updateAccountPassword(pasword: string): Promise<void> {
return this.client.updateAccountPassword(pasword);
}
updateAccountInfo(firstname: string, lastname: string): Promise<void> {
return this.client.updateAccountInfo(firstname, lastname);
}
updateStarred(id: number, starred: boolean): Promise<void> {
return this.client.updateStarred(id, starred);
}
updateMapToPublic(id: number, isPublic: boolean): Promise<void> {
return this.client.updateMapToPublic(id, isPublic);
}
fetchLabels(): Promise<Label[]> {
return this.client.fetchLabels();
}
createLabel(title: string, color: string): Promise<number> {
return this.client.createLabel(title, color);
}
deleteLabel(id: number): Promise<void> {
return this.client.deleteLabel(id);
}
addLabelToMap(labelId: number, mapId: number): Promise<void> {
return this.client.addLabelToMap(labelId, mapId);
}
deleteLabelFromMap(labelId: number, mapId: number): Promise<void> {
return this.client.deleteLabelFromMap(labelId, mapId);
}
fetchAccountInfo(): Promise<AccountInfo> {
return this.client.fetchAccountInfo();
}
registerNewUser(user: NewUser): Promise<void> {
return this.client.registerNewUser(user);
}
resetPassword(email: string): Promise<ForgotPasswordResult> {
return this.client.resetPassword(email);
}
fetchHistory(id: number): Promise<ChangeHistory[]> {
return this.client.fetchHistory(id);
}
revertHistory(id: number, cid: number): Promise<void> {
return this.client.revertHistory(id, cid);
}
}
export default CacheDecoratorClient;

View File

@ -118,12 +118,12 @@ interface Client {
registerNewUser(user: NewUser): Promise<void>; registerNewUser(user: NewUser): Promise<void>;
resetPassword(email: string): Promise<ForgotPasswordResult>; resetPassword(email: string): Promise<ForgotPasswordResult>;
processGoogleCallback(code: string): Promise<Oauth2CallbackResult>; processGoogleCallback(code: string): Promise<Oauth2CallbackResult>;
confirmAccountSync(email: string, code: string): Promise<void>; confirmAccountSync(email: string, code?: string): Promise<void>;
fetchHistory(id: number): Promise<ChangeHistory[]>; fetchHistory(id: number): Promise<ChangeHistory[]>;
revertHistory(id: number, cid: number): Promise<void>; revertHistory(id: number, cid: number): Promise<void>;
onSessionExpired(callback?: () => void): () => void; onSessionExpired(callback?: () => void): (() => void) | undefined;
} }
export default Client; export default Client;

View File

@ -128,10 +128,10 @@ class MockClient implements Client {
} }
fetchStarred(id: number): Promise<boolean> { fetchStarred(id: number): Promise<boolean> {
return Promise.resolve(this.maps.find((m) => m.id == id).starred); return Promise.resolve(Boolean(this.maps.find((m) => m.id == id)?.starred));
} }
onSessionExpired(callback?: () => void): () => void { onSessionExpired(callback?: () => void): (() => void) | undefined {
return callback; return callback;
} }

View File

@ -1,32 +0,0 @@
/* eslint-disable react/display-name */
import React, { ComponentType, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import Client from '../../classes/client';
import ClientHealthSentinel from '../../classes/client/client-health-sentinel';
import { activeInstance, sessionExpired } from '../../redux/clientSlice';
function withSessionExpirationHandling<T>(Component: ComponentType<T>) {
return (hocProps: T): React.ReactElement => {
const client: Client = useSelector(activeInstance);
const dispatch = useDispatch();
useEffect(() => {
if (client) {
client.onSessionExpired(() => {
dispatch(sessionExpired());
});
} else {
console.warn('Session expiration wont be handled because could not find client');
}
}, []);
return (
<>
<ClientHealthSentinel />
<Component {...hocProps} />
</>
);
};
}
export default withSessionExpirationHandling;

View File

@ -0,0 +1,10 @@
import React from 'react';
import { getCsrfToken, getCsrfTokenParameter } from '../../../utils';
const CSRFInput = (): React.ReactElement => {
const token = getCsrfToken();
const tokenParam = getCsrfTokenParameter();
return <>{token && tokenParam && <input type="hidden" value={token} name={tokenParam} />}</>;
};
export default CSRFInput;

View File

@ -1,3 +1,20 @@
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react'; import React from 'react';
import { css } from '@emotion/react'; import { css } from '@emotion/react';
import { Button } from '@mui/material'; import { Button } from '@mui/material';

View File

@ -1,3 +1,20 @@
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react'; import React from 'react';
import { useTheme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles';
import { containerStyle, lineStyle, textStyle } from './style'; import { containerStyle, lineStyle, textStyle } from './style';

View File

@ -2,7 +2,7 @@ import { css, SerializedStyles } from '@emotion/react';
export const containerStyle = ( export const containerStyle = (
responsive: boolean, responsive: boolean,
maxWidth: number, maxWidth: number | undefined,
breakPointDownMd: string, breakPointDownMd: string,
): SerializedStyles => { ): SerializedStyles => {
return css([ return css([

View File

@ -26,19 +26,23 @@ import {
} from '@wisemapping/editor'; } from '@wisemapping/editor';
import { IntlProvider } from 'react-intl'; import { IntlProvider } from 'react-intl';
import AppI18n, { Locales } from '../../classes/app-i18n'; import AppI18n, { Locales } from '../../classes/app-i18n';
import { useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { hotkeysEnabled } from '../../redux/editorSlice'; import { hotkeysEnabled } from '../../redux/editorSlice';
import ReactGA from 'react-ga4'; import ReactGA from 'react-ga4';
import { useFetchAccount, useFetchMapById } from '../../redux/clientSlice'; import {
useFetchAccount,
useFetchMapById,
activeInstance,
sessionExpired,
} from '../../redux/clientSlice';
import EditorOptionsBuilder from './EditorOptionsBuilder'; import EditorOptionsBuilder from './EditorOptionsBuilder';
import { useTheme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles';
import MapInfoImpl from '../../classes/editor-map-info'; import MapInfoImpl from '../../classes/editor-map-info';
import { MapInfo } from '@wisemapping/editor'; import { MapInfo } from '@wisemapping/editor';
import { activeInstance } from '../../redux/clientSlice';
import Client from '../../classes/client'; import Client from '../../classes/client';
import AppConfig from '../../classes/app-config'; import AppConfig from '../../classes/app-config';
import exampleMap from '../../classes/client/mock-client/example-map.wxml'; import exampleMap from '../../classes/client/mock-client/example-map.wxml';
import withSessionExpirationHandling from '../HOCs/withSessionExpirationHandling'; import ClientHealthSentinel from '../common/client-health-sentinel';
const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => { const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => {
let persistenceManager: PersistenceManager; let persistenceManager: PersistenceManager;
@ -72,6 +76,7 @@ const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => {
export type EditorPropsType = { export type EditorPropsType = {
isTryMode: boolean; isTryMode: boolean;
}; };
type ActionType = type ActionType =
| 'open' | 'open'
| 'share' | 'share'
@ -98,6 +103,17 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
const userLocale = AppI18n.getUserLocale(); const userLocale = AppI18n.getUserLocale();
const theme = useTheme(); const theme = useTheme();
const client: Client = useSelector(activeInstance); const client: Client = useSelector(activeInstance);
const dispatch = useDispatch();
useEffect(() => {
if (client) {
client.onSessionExpired(() => {
dispatch(sessionExpired());
});
} else {
console.warn('Session expiration wont be handled because could not find client');
}
}, []);
useEffect(() => { useEffect(() => {
ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: `Map Editor` }); ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: `Map Editor` });
@ -163,6 +179,7 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
defaultLocale={Locales.EN.code} defaultLocale={Locales.EN.code}
messages={userLocale.message as Record<string, string>} messages={userLocale.message as Record<string, string>}
> >
<ClientHealthSentinel />
<Editor <Editor
onAction={setActiveDialog} onAction={setActiveDialog}
options={options} options={options}
@ -197,4 +214,4 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
); );
}; };
export default withSessionExpirationHandling(EditorPage); export default EditorPage;

View File

@ -15,9 +15,9 @@ import ReactGA from 'react-ga4';
import { Link as RouterLink } from 'react-router-dom'; import { Link as RouterLink } from 'react-router-dom';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import { getCsrfToken, getCsrfTokenParameter } from '../../utils';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Button } from '@mui/material'; import { Button } from '@mui/material';
import CSRFInput from '../common/csrf-input';
const ForgotPassword = () => { const ForgotPassword = () => {
const [email, setEmail] = useState<string>(''); const [email, setEmail] = useState<string>('');
@ -84,7 +84,7 @@ const ForgotPassword = () => {
<GlobalError error={error} /> <GlobalError error={error} />
<form onSubmit={handleOnSubmit}> <form onSubmit={handleOnSubmit}>
<input type="hidden" value={getCsrfToken()} name={getCsrfTokenParameter()} /> <CSRFInput />
<Input <Input
type="email" type="email"
name="email" name="email"

View File

@ -11,10 +11,10 @@ import Typography from '@mui/material/Typography';
import FormControl from '@mui/material/FormControl'; import FormControl from '@mui/material/FormControl';
import Link from '@mui/material/Link'; import Link from '@mui/material/Link';
import ReactGA from 'react-ga4'; import ReactGA from 'react-ga4';
import { getCsrfToken, getCsrfTokenParameter } from '../../utils';
import Separator from '../common/separator'; import Separator from '../common/separator';
import GoogleButton from '../common/google-button'; import GoogleButton from '../common/google-button';
import AppConfig from '../../classes/app-config'; import AppConfig from '../../classes/app-config';
import CSRFInput from '../common/csrf-input';
const LoginError = () => { const LoginError = () => {
// @Todo: This must be reviewed to be based on navigation state. // @Todo: This must be reviewed to be based on navigation state.
@ -70,7 +70,7 @@ const LoginPage = (): React.ReactElement => {
<FormControl> <FormControl>
<form action="/c/perform-login" method="POST"> <form action="/c/perform-login" method="POST">
<input type="hidden" value={getCsrfToken()} name={getCsrfTokenParameter()} /> <CSRFInput />
<Input <Input
name="username" name="username"
type="email" type="email"
@ -121,7 +121,12 @@ const LoginPage = (): React.ReactElement => {
defaultMessage: 'Sign in with Google', defaultMessage: 'Sign in with Google',
})} })}
onClick={() => { onClick={() => {
window.location.href = AppConfig.getGoogleOauth2Url(); const authUrl = AppConfig.getGoogleOauth2Url();
if (authUrl) {
window.location.href = authUrl;
} else {
console.log('GoogleOauth2Url is not configured.');
}
}} }}
/> />
</FormContainer> </FormContainer>

View File

@ -89,7 +89,7 @@ const ImportDialog = ({ onClose }: CreateProps): React.ReactElement => {
const extensionFile = file.name.split('.').pop(); const extensionFile = file.name.split('.').pop();
const extensionAccept = ['wxml', 'mm']; const extensionAccept = ['wxml', 'mm'];
if (!extensionAccept.includes(extensionFile)) { if (!extensionAccept.includes(extensionFile!)) {
setErrorFile({ setErrorFile({
error: true, error: true,
message: intl.formatMessage( message: intl.formatMessage(
@ -108,8 +108,8 @@ const ImportDialog = ({ onClose }: CreateProps): React.ReactElement => {
model.contentType = 'application/xml'; model.contentType = 'application/xml';
const fileContent = event?.target?.result; const fileContent = event?.target?.result;
const mapConent: string = const mapConent: string | undefined =
typeof fileContent === 'string' ? fileContent : fileContent.toString(); typeof fileContent === 'string' ? fileContent : fileContent?.toString();
try { try {
const importer: Importer = TextImporterFactory.create(extensionFile, mapConent); const importer: Importer = TextImporterFactory.create(extensionFile, mapConent);

View File

@ -1,3 +1,20 @@
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { FormattedMessage, useIntl } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
@ -19,13 +36,11 @@ const LabelDialog = ({ mapsId, onClose }: MultiDialogProps): React.ReactElement
const client: Client = useSelector(activeInstance); const client: Client = useSelector(activeInstance);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
// TODO: pass down map data instead of using query?
const { data } = useQuery<unknown, ErrorInfo, MapInfo[]>('maps', () => { const { data } = useQuery<unknown, ErrorInfo, MapInfo[]>('maps', () => {
return client.fetchAllMaps(); return client.fetchAllMaps();
}); });
const [error, setError] = React.useState<ErrorInfo>(); const [error, setError] = React.useState<ErrorInfo>();
const maps = data?.filter((m) => mapsId.includes(m.id));
const maps = data.filter((m) => mapsId.includes(m.id));
const changeLabelMutation = useMutation< const changeLabelMutation = useMutation<
void, void,
@ -44,11 +59,9 @@ const LabelDialog = ({ mapsId, onClose }: MultiDialogProps): React.ReactElement
const handleChangesInLabels = (label: Label, checked: boolean) => { const handleChangesInLabels = (label: Label, checked: boolean) => {
setError(undefined); setError(undefined);
changeLabelMutation.mutate({ if (maps) {
maps, changeLabelMutation.mutate({ maps, label, checked });
label, }
checked,
});
}; };
return ( return (
@ -66,10 +79,15 @@ const LabelDialog = ({ mapsId, onClose }: MultiDialogProps): React.ReactElement
paperCss={classes.paper} paperCss={classes.paper}
error={error} error={error}
> >
{maps && (
<> <>
<Typography variant="body2" marginTop="10px" css={classes.title as Interpolation<Theme>}> <Typography
variant="body2"
marginTop="10px"
css={classes.title as Interpolation<Theme>}
>
<FormattedMessage id="label.add-for" defaultMessage="Editing labels for " /> <FormattedMessage id="label.add-for" defaultMessage="Editing labels for " />
{maps.length > 1 ? ( {maps && maps.length > 1 ? (
<FormattedMessage <FormattedMessage
id="label.maps-count" id="label.maps-count"
defaultMessage="{count} maps" defaultMessage="{count} maps"
@ -81,6 +99,7 @@ const LabelDialog = ({ mapsId, onClose }: MultiDialogProps): React.ReactElement
</Typography> </Typography>
<LabelSelector onChange={handleChangesInLabels} maps={maps} /> <LabelSelector onChange={handleChangesInLabels} maps={maps} />
</> </>
)}
</BaseDialog> </BaseDialog>
</div> </div>
); );

View File

@ -1,3 +1,20 @@
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { ErrorInfo, ReactElement, useEffect } from 'react'; import React, { ErrorInfo, ReactElement, useEffect } from 'react';
import Drawer from '@mui/material/Drawer'; import Drawer from '@mui/material/Drawer';
import AppBar from '@mui/material/AppBar'; import AppBar from '@mui/material/AppBar';
@ -200,7 +217,7 @@ const MapsPage = (): ReactElement => {
); );
const container = document !== undefined ? () => document.body : undefined; const container = document !== undefined ? () => document.body : undefined;
const label = labels.find((l) => l.id === labelToDelete);
return ( return (
<IntlProvider <IntlProvider
locale={userLocale.code} locale={userLocale.code}
@ -210,7 +227,7 @@ const MapsPage = (): ReactElement => {
<div css={classes.root}> <div css={classes.root}>
<AppBar <AppBar
position="fixed" position="fixed"
css={[classes.appBar, open && classes.appBarShift]} css={[classes.appBar, classes.appBarShift]}
variant="outlined" variant="outlined"
elevation={0} elevation={0}
> >
@ -321,14 +338,14 @@ const MapsPage = (): ReactElement => {
<MapsList filter={filter} /> <MapsList filter={filter} />
</main> </main>
</div> </div>
{labelToDelete && ( {label && labelToDelete && (
<LabelDeleteConfirm <LabelDeleteConfirm
onClose={() => setLabelToDelete(null)} onClose={() => setLabelToDelete(null)}
onConfirm={() => { onConfirm={() => {
handleLabelDelete(labelToDelete); handleLabelDelete(labelToDelete);
setLabelToDelete(null); setLabelToDelete(null);
}} }}
label={labels.find((l) => l.id === labelToDelete)} label={label}
/> />
)} )}
</IntlProvider> </IntlProvider>

View File

@ -20,7 +20,7 @@ const RegistrationCallbackPage = (): React.ReactElement => {
const client: Client = useSelector(activeInstance); const client: Client = useSelector(activeInstance);
const [showError, setShowError] = useState(false); const [showError, setShowError] = useState(false);
const [callbackResult, setCallbackResult] = useState<Oauth2CallbackResult>(undefined); const [callbackResult, setCallbackResult] = useState<Oauth2CallbackResult>();
const navigate = useNavigate(); const navigate = useNavigate();
useEffect(() => { useEffect(() => {
@ -37,6 +37,10 @@ const RegistrationCallbackPage = (): React.ReactElement => {
useEffect(() => { useEffect(() => {
const googleOauthCode = new URLSearchParams(window.location.search).get('code'); const googleOauthCode = new URLSearchParams(window.location.search).get('code');
if (!googleOauthCode) {
throw new Error(`Missing code definition: ${window.location.search}`);
}
client client
.processGoogleCallback(googleOauthCode) .processGoogleCallback(googleOauthCode)
.then((result) => { .then((result) => {
@ -54,8 +58,13 @@ const RegistrationCallbackPage = (): React.ReactElement => {
}, []); }, []);
const confirmAccountSynching = () => { const confirmAccountSynching = () => {
const callback = callbackResult;
if (!callback) {
throw new Error(`callbackResult can not be null`);
}
client client
.confirmAccountSync(callbackResult.email, callbackResult.syncCode) .confirmAccountSync(callback.email, callback.syncCode)
.then(() => { .then(() => {
navigate('/c/maps/'); navigate('/c/maps/');
}) })

View File

@ -69,7 +69,12 @@ const RegistrationForm = () => {
const maxFormWidth = 350; const maxFormWidth = 350;
const handleRegisterWithGoogleClick = () => { const handleRegisterWithGoogleClick = () => {
window.location.href = AppConfig.getGoogleOauth2Url(); const url = AppConfig.getGoogleOauth2Url();
if (url) {
window.location.href = url;
} else {
console.error('Auth callback url is null');
}
}; };
return ( return (

View File

@ -55,7 +55,7 @@ export const clientSlice = createSlice({
type MapLoadResult = { type MapLoadResult = {
isLoading: boolean; isLoading: boolean;
error: ErrorInfo | null; error: ErrorInfo | null;
map: MapInfo | null; map: MapInfo | undefined;
}; };
export const useFetchMapById = (id: number): MapLoadResult => { export const useFetchMapById = (id: number): MapLoadResult => {
@ -65,12 +65,12 @@ export const useFetchMapById = (id: number): MapLoadResult => {
}); });
// If the map can not be loaded, create an error object. // If the map can not be loaded, create an error object.
let map: MapInfo; let map: MapInfo | undefined;
let errorMsg: ErrorInfo = error; let errorMsg: ErrorInfo | null = error;
if (!isLoading) { if (!isLoading) {
// Sanitize error structure ... // Sanitize error structure ...
if (errorMsg) { if (errorMsg) {
errorMsg = Object.keys(error).length !== 0 ? error : null; errorMsg = Object.keys(errorMsg).length !== 0 ? error : null;
} }
// Seach for object... // Seach for object...
map = data?.find((m) => m.id == id); map = data?.find((m) => m.id == id);

View File

@ -1,18 +0,0 @@
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": false,
"module": "amd",
"moduleResolution": "node",
"strict": false,
"target": "es6",
"allowJs": true,
"esModuleInterop": true,
"declaration": true,
"jsx": "react-jsx",
"jsxImportSource": "@emotion/react"
}
}

View File

@ -6,7 +6,7 @@ export const getCsrfToken = (): string | null => {
return meta.getAttribute('content'); return meta.getAttribute('content');
}; };
export const getCsrfTokenParameter = (): string => { export const getCsrfTokenParameter = (): string | null => {
const meta = document.head.querySelector('meta[name="_csrf_parameter"]'); const meta = document.head.querySelector('meta[name="_csrf_parameter"]');
if (!meta) { if (!meta) {
return ''; return '';

View File

@ -1,15 +1,27 @@
{ {
"include": [
"src/**/*"
],
"compilerOptions": { "compilerOptions": {
"jsx": "react-jsx",
"outDir": "./dist/", "outDir": "./dist/",
"sourceMap": true, "sourceMap": true,
"noImplicitAny": false, "noImplicitAny": false,
"module": "es6", "module": "amd",
"moduleResolution": "node",
"strict": false,
"target": "es6", "target": "es6",
"allowJs": true, "allowJs": true,
"esModuleInterop": true, "esModuleInterop": true,
"jsx": "react-jsx", "declaration": true,
"jsxImportSource": "@emotion/react" "strictNullChecks": true,
"rootDirs": [
"src",
],
"jsxImportSource": "@emotion/react",
"resolveJsonModule": true
}, },
"exclude": ["node_modules"] "exclude": [
} "node_modules"
]
}