mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-21 22:27:56 +01:00
Format all files with prettier
This commit is contained in:
parent
ae02780a1a
commit
cf29f4f953
4
packages/editor/src/@types/index.d.ts
vendored
4
packages/editor/src/@types/index.d.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
declare module "*.svg" {
|
declare module '*.svg' {
|
||||||
const content: any;
|
const content: any;
|
||||||
export default content;
|
export default content;
|
||||||
}
|
}
|
||||||
|
@ -5,26 +5,25 @@ import DE from './../../compiled-lang/de.json';
|
|||||||
import RU from './../../compiled-lang/ru.json';
|
import RU from './../../compiled-lang/ru.json';
|
||||||
import ZH from './../../compiled-lang/zh.json';
|
import ZH from './../../compiled-lang/zh.json';
|
||||||
|
|
||||||
|
|
||||||
class I18nMsg {
|
class I18nMsg {
|
||||||
static loadLocaleData(locale: string) {
|
static loadLocaleData(locale: string) {
|
||||||
switch (locale) {
|
switch (locale) {
|
||||||
case 'fr':
|
case 'fr':
|
||||||
return FR;
|
return FR;
|
||||||
case 'en':
|
case 'en':
|
||||||
return EN;
|
return EN;
|
||||||
case 'es':
|
case 'es':
|
||||||
return ES;
|
return ES;
|
||||||
case 'de':
|
case 'de':
|
||||||
return DE;
|
return DE;
|
||||||
case 'ru':
|
case 'ru':
|
||||||
return RU;
|
return RU;
|
||||||
case 'zh':
|
case 'zh':
|
||||||
return ZH;
|
return ZH;
|
||||||
default:
|
default:
|
||||||
return EN;
|
return EN;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default I18nMsg;
|
export default I18nMsg;
|
||||||
|
@ -48,9 +48,9 @@ class Events {
|
|||||||
if (!events) return this;
|
if (!events) return this;
|
||||||
|
|
||||||
const args = Array.isArray(eventArgs) ? eventArgs : [eventArgs];
|
const args = Array.isArray(eventArgs) ? eventArgs : [eventArgs];
|
||||||
events.forEach(((fn) => {
|
events.forEach((fn) => {
|
||||||
fn.apply(this, args);
|
fn.apply(this, args);
|
||||||
}));
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,25 +1,27 @@
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const ActionButton = styled.div`
|
const ActionButton = styled.div`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 0px 10px;
|
margin: 0px 10px;
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 10px 25px;
|
padding: 10px 25px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
min-width: 64px;
|
min-width: 64px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-radius: 9px;
|
border-radius: 9px;
|
||||||
color: white;
|
color: white;
|
||||||
background-color: #ffa800;
|
background-color: #ffa800;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
|
||||||
}
|
box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
|
||||||
|
border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default ActionButton;
|
export default ActionButton;
|
||||||
|
@ -3,29 +3,29 @@ import { times } from '../../size';
|
|||||||
import LogoTextBlackSvg from '../../../images/logo-text-black.svg';
|
import LogoTextBlackSvg from '../../../images/logo-text-black.svg';
|
||||||
|
|
||||||
export const StyledFooter = styled.div`
|
export const StyledFooter = styled.div`
|
||||||
height: ${times(10)};
|
height: ${times(10)};
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const StyledLogo = styled.div`
|
export const StyledLogo = styled.div`
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 20px;
|
left: 20px;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
background: url(${LogoTextBlackSvg}) no-repeat;
|
background: url(${LogoTextBlackSvg}) no-repeat;
|
||||||
width: 90px;
|
width: 90px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Notifier = styled.div`
|
export const Notifier = styled.div`
|
||||||
border: 1px solid rgb(241, 163, 39);
|
border: 1px solid rgb(241, 163, 39);
|
||||||
background-color: rgb(252, 235, 192);
|
background-color: rgb(252, 235, 192);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
padding: 5px 9px;
|
padding: 5px 9px;
|
||||||
color: back;
|
color: back;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
display: none;
|
display: none;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
`;
|
`;
|
||||||
|
@ -1,50 +1,50 @@
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
export const HeaderContainer = styled.div`
|
export const HeaderContainer = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 0px;
|
height: 0px;
|
||||||
background: #202020;
|
background: #202020;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ToolbarContainer = styled.div`
|
export const ToolbarContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ToolbarButton = styled.div`
|
export const ToolbarButton = styled.div`
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ToolbarButtonExt = styled(ToolbarButton)`
|
export const ToolbarButtonExt = styled(ToolbarButton)`
|
||||||
width: 40px;
|
width: 40px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const AccountButton = styled.div`
|
export const AccountButton = styled.div`
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ToolbarRightContainer = styled.div`
|
export const ToolbarRightContainer = styled.div`
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
`;
|
`;
|
||||||
|
@ -33,10 +33,12 @@
|
|||||||
"?": "ignore",
|
"?": "ignore",
|
||||||
">": "ignore",
|
">": "ignore",
|
||||||
"||": "ignore",
|
"||": "ignore",
|
||||||
"&&": "ignore"
|
"&&": "ignore",
|
||||||
|
"(": "ignore"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"object-curly-newline": "off",
|
||||||
"no-underscore-dangle": "off",
|
"no-underscore-dangle": "off",
|
||||||
"no-plusplus": "off",
|
"no-plusplus": "off",
|
||||||
"no-param-reassign": "off",
|
"no-param-reassign": "off",
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright [2021] [wisemapping]
|
* Copyright [2021] [wisemapping]
|
||||||
*
|
*
|
||||||
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
|
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
|
||||||
* It is basically the Apache License, Version 2.0 (the "License") plus the
|
* It is basically the Apache License, Version 2.0 (the "License") plus the
|
||||||
* "powered by wisemapping" text requirement on every single page;
|
* "powered by wisemapping" text requirement on every single page;
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the license at
|
* You may obtain a copy of the license at
|
||||||
*
|
*
|
||||||
* http://www.wisemapping.org/license
|
* http://www.wisemapping.org/license
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* 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 { $defined } from '@wisemapping/core-js';
|
import { $defined } from '@wisemapping/core-js';
|
||||||
import CommandContext from './CommandContext';
|
import CommandContext from './CommandContext';
|
||||||
|
|
||||||
|
@ -47,9 +47,9 @@ class CommandContext {
|
|||||||
|
|
||||||
if (result.length !== topicsIds.length) {
|
if (result.length !== topicsIds.length) {
|
||||||
const ids = designerTopics.map((topic) => topic.getId());
|
const ids = designerTopics.map((topic) => topic.getId());
|
||||||
throw new Error(`Could not find topic. Result:${result
|
throw new Error(
|
||||||
} Filter Criteria:${topicsIds
|
`Could not find topic. Result:${result} Filter Criteria:${topicsIds} Current Topics: [${ids}])`,
|
||||||
} Current Topics: [${ids}])`);
|
);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { $assert, $defined } from '@wisemapping/core-js';
|
import { $assert, $defined } from '@wisemapping/core-js';
|
||||||
import {
|
import { Point, CurvedLine, PolyLine, Line } from '@wisemapping/web2d';
|
||||||
Point, CurvedLine, PolyLine, Line,
|
|
||||||
} from '@wisemapping/web2d';
|
|
||||||
import { TopicShape } from './model/INodeModel';
|
import { TopicShape } from './model/INodeModel';
|
||||||
import RelationshipModel from './model/RelationshipModel';
|
import RelationshipModel from './model/RelationshipModel';
|
||||||
import Topic from './Topic';
|
import Topic from './Topic';
|
||||||
|
@ -33,7 +33,22 @@ class DesignerKeyboard extends Keyboard {
|
|||||||
|
|
||||||
private static _disabled: boolean;
|
private static _disabled: boolean;
|
||||||
|
|
||||||
private static excludeFromEditor = ['Enter', 'CapsLock', 'Escape', 'F1', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12'];
|
private static excludeFromEditor = [
|
||||||
|
'Enter',
|
||||||
|
'CapsLock',
|
||||||
|
'Escape',
|
||||||
|
'F1',
|
||||||
|
'F3',
|
||||||
|
'F4',
|
||||||
|
'F5',
|
||||||
|
'F6',
|
||||||
|
'F7',
|
||||||
|
'F8',
|
||||||
|
'F9',
|
||||||
|
'F10',
|
||||||
|
'F11',
|
||||||
|
'F12',
|
||||||
|
];
|
||||||
|
|
||||||
constructor(designer: Designer) {
|
constructor(designer: Designer) {
|
||||||
super();
|
super();
|
||||||
@ -53,9 +68,13 @@ class DesignerKeyboard extends Keyboard {
|
|||||||
private _registerEvents(designer: Designer) {
|
private _registerEvents(designer: Designer) {
|
||||||
// Try with the keyboard ..
|
// Try with the keyboard ..
|
||||||
const model = designer.getModel();
|
const model = designer.getModel();
|
||||||
this.addShortcut(['backspace', 'del'], () => { designer.deleteSelectedEntities(); });
|
this.addShortcut(['backspace', 'del'], () => {
|
||||||
|
designer.deleteSelectedEntities();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut('space', () => { designer.shrinkSelectedBranch(); });
|
this.addShortcut('space', () => {
|
||||||
|
designer.shrinkSelectedBranch();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut('f2', () => {
|
this.addShortcut('f2', () => {
|
||||||
const node = model.selectedTopic();
|
const node = model.selectedTopic();
|
||||||
@ -64,103 +83,128 @@ class DesignerKeyboard extends Keyboard {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addShortcut(['insert', 'tab', 'meta+enter'], () => { designer.createChildForSelectedNode(); });
|
this.addShortcut(['insert', 'tab', 'meta+enter'], () => {
|
||||||
|
designer.createChildForSelectedNode();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut('enter', () => { designer.createSiblingForSelectedNode(); });
|
this.addShortcut('enter', () => {
|
||||||
|
designer.createSiblingForSelectedNode();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['ctrl+z', 'meta+z'], () => { designer.undo(); });
|
this.addShortcut(['ctrl+z', 'meta+z'], () => {
|
||||||
|
designer.undo();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['ctrl+shift+z', 'meta+shift+z'], () => { designer.redo(); });
|
this.addShortcut(['ctrl+shift+z', 'meta+shift+z'], () => {
|
||||||
|
designer.redo();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['ctrl+c', 'meta+c'], () => { designer.copyToClipboard(); });
|
this.addShortcut(['ctrl+c', 'meta+c'], () => {
|
||||||
|
designer.copyToClipboard();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['ctrl+l', 'meta+l'], () => { designer.addLink(); });
|
this.addShortcut(['ctrl+l', 'meta+l'], () => {
|
||||||
|
designer.addLink();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['ctrl+k', 'meta+k'], () => { designer.addNote(); });
|
this.addShortcut(['ctrl+k', 'meta+k'], () => {
|
||||||
|
designer.addNote();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['ctrl+v', 'meta+v'], () => { designer.pasteClipboard(); });
|
this.addShortcut(['ctrl+v', 'meta+v'], () => {
|
||||||
|
designer.pasteClipboard();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['ctrl+a', 'meta+a'], () => { designer.selectAll(); });
|
this.addShortcut(['ctrl+a', 'meta+a'], () => {
|
||||||
|
designer.selectAll();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['ctrl+b', 'meta+b'], () => { designer.changeFontWeight(); });
|
this.addShortcut(['ctrl+b', 'meta+b'], () => {
|
||||||
|
designer.changeFontWeight();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['ctrl+s', 'meta+s'], () => { $(document).find('#save').trigger('click'); });
|
this.addShortcut(['ctrl+s', 'meta+s'], () => {
|
||||||
|
$(document).find('#save').trigger('click');
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['ctrl+i', 'meta+i'], () => { designer.changeFontStyle(); });
|
this.addShortcut(['ctrl+i', 'meta+i'], () => {
|
||||||
|
designer.changeFontStyle();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['ctrl+shift+a', 'meta+shift+a'], () => { designer.deselectAll(); });
|
this.addShortcut(['ctrl+shift+a', 'meta+shift+a'], () => {
|
||||||
|
designer.deselectAll();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['meta+=', 'ctrl+='], () => { designer.zoomIn(); });
|
this.addShortcut(['meta+=', 'ctrl+='], () => {
|
||||||
|
designer.zoomIn();
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(['meta+-', 'ctrl+-'], () => { designer.zoomOut(); });
|
this.addShortcut(['meta+-', 'ctrl+-'], () => {
|
||||||
|
designer.zoomOut();
|
||||||
|
});
|
||||||
|
|
||||||
const me = this;
|
const me = this;
|
||||||
this.addShortcut(
|
this.addShortcut('right', () => {
|
||||||
'right', () => {
|
const node = model.selectedTopic();
|
||||||
const node = model.selectedTopic();
|
if (node) {
|
||||||
if (node) {
|
if (node.isCentralTopic()) {
|
||||||
if (node.isCentralTopic()) {
|
me._goToSideChild(designer, node, 'RIGHT');
|
||||||
me._goToSideChild(designer, node, 'RIGHT');
|
} else if (node.getPosition().x < 0) {
|
||||||
} else if (node.getPosition().x < 0) {
|
me._goToParent(designer, node);
|
||||||
me._goToParent(designer, node);
|
} else if (!node.areChildrenShrunken()) {
|
||||||
} else if (!node.areChildrenShrunken()) {
|
me._goToChild(designer, node);
|
||||||
me._goToChild(designer, node);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const centralTopic = model.getCentralTopic();
|
|
||||||
me._goToNode(designer, centralTopic);
|
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
);
|
const centralTopic = model.getCentralTopic();
|
||||||
|
me._goToNode(designer, centralTopic);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(
|
this.addShortcut('left', () => {
|
||||||
'left', () => {
|
const node = model.selectedTopic();
|
||||||
const node = model.selectedTopic();
|
if (node) {
|
||||||
if (node) {
|
if (node.isCentralTopic()) {
|
||||||
if (node.isCentralTopic()) {
|
me._goToSideChild(designer, node, 'LEFT');
|
||||||
me._goToSideChild(designer, node, 'LEFT');
|
} else if (node.getPosition().x > 0) {
|
||||||
} else if (node.getPosition().x > 0) {
|
me._goToParent(designer, node);
|
||||||
me._goToParent(designer, node);
|
} else if (!node.areChildrenShrunken()) {
|
||||||
} else if (!node.areChildrenShrunken()) {
|
me._goToChild(designer, node);
|
||||||
me._goToChild(designer, node);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const centralTopic = model.getCentralTopic();
|
|
||||||
me._goToNode(designer, centralTopic);
|
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
);
|
const centralTopic = model.getCentralTopic();
|
||||||
|
me._goToNode(designer, centralTopic);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.addShortcut(
|
this.addShortcut('up', () => {
|
||||||
'up', () => {
|
const node = model.selectedTopic();
|
||||||
const node = model.selectedTopic();
|
if (node) {
|
||||||
if (node) {
|
if (!node.isCentralTopic()) {
|
||||||
if (!node.isCentralTopic()) {
|
me._goToBrother(designer, node, 'UP');
|
||||||
me._goToBrother(designer, node, 'UP');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const centralTopic = model.getCentralTopic();
|
|
||||||
me._goToNode(designer, centralTopic);
|
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
);
|
const centralTopic = model.getCentralTopic();
|
||||||
this.addShortcut(
|
me._goToNode(designer, centralTopic);
|
||||||
'down', () => {
|
}
|
||||||
const node = model.selectedTopic();
|
});
|
||||||
if (node) {
|
this.addShortcut('down', () => {
|
||||||
if (!node.isCentralTopic()) {
|
const node = model.selectedTopic();
|
||||||
me._goToBrother(designer, node, 'DOWN');
|
if (node) {
|
||||||
}
|
if (!node.isCentralTopic()) {
|
||||||
} else {
|
me._goToBrother(designer, node, 'DOWN');
|
||||||
const centralTopic = model.getCentralTopic();
|
|
||||||
me._goToNode(designer, centralTopic);
|
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
);
|
const centralTopic = model.getCentralTopic();
|
||||||
|
me._goToNode(designer, centralTopic);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$(document).on('keypress', (event) => {
|
$(document).on('keypress', (event) => {
|
||||||
// Needs to be ignored ?
|
// Needs to be ignored ?
|
||||||
if (DesignerKeyboard.isDisabled() || DesignerKeyboard.excludeFromEditor.includes(event.code)) {
|
if (
|
||||||
|
DesignerKeyboard.isDisabled() ||
|
||||||
|
DesignerKeyboard.excludeFromEditor.includes(event.code)
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,14 +233,14 @@ class DesignerKeyboard extends Keyboard {
|
|||||||
const { x } = node.getPosition();
|
const { x } = node.getPosition();
|
||||||
let dist = null;
|
let dist = null;
|
||||||
for (let i = 0; i < brothers.length; i++) {
|
for (let i = 0; i < brothers.length; i++) {
|
||||||
const sameSide = (x * brothers[i].getPosition().x) >= 0;
|
const sameSide = x * brothers[i].getPosition().x >= 0;
|
||||||
if (brothers[i] !== node && sameSide) {
|
if (brothers[i] !== node && sameSide) {
|
||||||
const brother = brothers[i];
|
const brother = brothers[i];
|
||||||
const brotherY = brother.getPosition().y;
|
const brotherY = brother.getPosition().y;
|
||||||
if (direction === 'DOWN' && brotherY > y) {
|
if (direction === 'DOWN' && brotherY > y) {
|
||||||
let distancia = y - brotherY;
|
let distancia = y - brotherY;
|
||||||
if (distancia < 0) {
|
if (distancia < 0) {
|
||||||
distancia *= (-1);
|
distancia *= -1;
|
||||||
}
|
}
|
||||||
if (dist == null || dist > distancia) {
|
if (dist == null || dist > distancia) {
|
||||||
dist = distancia;
|
dist = distancia;
|
||||||
@ -205,7 +249,7 @@ class DesignerKeyboard extends Keyboard {
|
|||||||
} else if (direction === 'UP' && brotherY < y) {
|
} else if (direction === 'UP' && brotherY < y) {
|
||||||
let distance = y - brotherY;
|
let distance = y - brotherY;
|
||||||
if (distance < 0) {
|
if (distance < 0) {
|
||||||
distance *= (-1);
|
distance *= -1;
|
||||||
}
|
}
|
||||||
if (dist == null || dist > distance) {
|
if (dist == null || dist > distance) {
|
||||||
dist = distance;
|
dist = distance;
|
||||||
|
@ -117,7 +117,7 @@ class DesignerModel extends Events {
|
|||||||
|
|
||||||
selectedTopic(): Topic | undefined {
|
selectedTopic(): Topic | undefined {
|
||||||
const topics = this.filterSelectedTopics();
|
const topics = this.filterSelectedTopics();
|
||||||
return (topics.length > 0) ? topics[0] : undefined;
|
return topics.length > 0 ? topics[0] : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
findTopicById(id: number): Topic | undefined {
|
findTopicById(id: number): Topic | undefined {
|
||||||
|
@ -85,7 +85,7 @@ class DesignerUndoManager {
|
|||||||
result = false;
|
result = false;
|
||||||
} else if (undoLength > 0) {
|
} else if (undoLength > 0) {
|
||||||
const command = this._undoQueue[undoLength - 1];
|
const command = this._undoQueue[undoLength - 1];
|
||||||
result = (this._baseId !== command.getId());
|
result = this._baseId !== command.getId();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ class DragConnector {
|
|||||||
// That's why i need to divide it by two...
|
// That's why i need to divide it by two...
|
||||||
const txborder = tpos.x + (topic.getSize().width / 2) * Math.sign(sPos.x);
|
const txborder = tpos.x + (topic.getSize().width / 2) * Math.sign(sPos.x);
|
||||||
const distance = (sPos.x - txborder) * Math.sign(sPos.x);
|
const distance = (sPos.x - txborder) * Math.sign(sPos.x);
|
||||||
return distance > 0 && (distance < DragConnector.MAX_VERTICAL_CONNECTION_TOLERANCE);
|
return distance > 0 && distance < DragConnector.MAX_VERTICAL_CONNECTION_TOLERANCE;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Assign a priority based on the distance:
|
// Assign a priority based on the distance:
|
||||||
@ -99,19 +99,34 @@ class DragConnector {
|
|||||||
|
|
||||||
const av = me._isVerticallyAligned(a.getSize(), aPos, sPos);
|
const av = me._isVerticallyAligned(a.getSize(), aPos, sPos);
|
||||||
const bv = me._isVerticallyAligned(b.getSize(), bPos, sPos);
|
const bv = me._isVerticallyAligned(b.getSize(), bPos, sPos);
|
||||||
return me._proximityWeight(av, a, sPos, currentConnection)
|
return (
|
||||||
- me._proximityWeight(bv, b, sPos, currentConnection);
|
me._proximityWeight(av, a, sPos, currentConnection) -
|
||||||
|
me._proximityWeight(bv, b, sPos, currentConnection)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
return topics;
|
return topics;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _proximityWeight(isAligned: boolean, target: Topic, sPos: Point, currentConnection: Topic): number {
|
private _proximityWeight(
|
||||||
|
isAligned: boolean,
|
||||||
|
target: Topic,
|
||||||
|
sPos: Point,
|
||||||
|
currentConnection: Topic,
|
||||||
|
): number {
|
||||||
const tPos = target.getPosition();
|
const tPos = target.getPosition();
|
||||||
return (isAligned ? 0 : 200) + Math.abs(tPos.x - sPos.x)
|
return (
|
||||||
+ Math.abs(tPos.y - sPos.y) + (currentConnection === target ? 0 : 100);
|
(isAligned ? 0 : 200) +
|
||||||
|
Math.abs(tPos.x - sPos.x) +
|
||||||
|
Math.abs(tPos.y - sPos.y) +
|
||||||
|
(currentConnection === target ? 0 : 100)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _isVerticallyAligned(targetSize: SizeType, targetPosition: Point, sourcePosition: Point): boolean {
|
private _isVerticallyAligned(
|
||||||
|
targetSize: SizeType,
|
||||||
|
targetPosition: Point,
|
||||||
|
sourcePosition: Point,
|
||||||
|
): boolean {
|
||||||
return Math.abs(sourcePosition.y - targetPosition.y) < targetSize.height / 2;
|
return Math.abs(sourcePosition.y - targetPosition.y) < targetSize.height / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,14 +59,14 @@ class DragManager {
|
|||||||
|
|
||||||
// Register mouse move listener ...
|
// Register mouse move listener ...
|
||||||
const mouseMoveListener = dragManager._buildMouseMoveListener(
|
const mouseMoveListener = dragManager._buildMouseMoveListener(
|
||||||
workspace, dragNode, dragManager,
|
workspace,
|
||||||
|
dragNode,
|
||||||
|
dragManager,
|
||||||
);
|
);
|
||||||
screen.addEvent('mousemove', mouseMoveListener);
|
screen.addEvent('mousemove', mouseMoveListener);
|
||||||
|
|
||||||
// Register mouse up listeners ...
|
// Register mouse up listeners ...
|
||||||
const mouseUpListener = dragManager._buildMouseUpListener(
|
const mouseUpListener = dragManager._buildMouseUpListener(workspace, dragNode, dragManager);
|
||||||
workspace, dragNode, dragManager,
|
|
||||||
);
|
|
||||||
screen.addEvent('mouseup', mouseUpListener);
|
screen.addEvent('mouseup', mouseUpListener);
|
||||||
|
|
||||||
// Change cursor.
|
// Change cursor.
|
||||||
|
@ -1,2 +1,7 @@
|
|||||||
type EditorRenderMode = 'viewonly' | 'edition-owner' | 'edition-editor' | 'edition-viewer' | 'showcase';
|
type EditorRenderMode =
|
||||||
|
| 'viewonly'
|
||||||
|
| 'edition-owner'
|
||||||
|
| 'edition-editor'
|
||||||
|
| 'edition-viewer'
|
||||||
|
| 'showcase';
|
||||||
export default EditorRenderMode;
|
export default EditorRenderMode;
|
||||||
|
@ -48,9 +48,9 @@ class Events {
|
|||||||
if (!events) return this;
|
if (!events) return this;
|
||||||
|
|
||||||
const args = Array.isArray(eventArgs) ? eventArgs : [eventArgs];
|
const args = Array.isArray(eventArgs) ? eventArgs : [eventArgs];
|
||||||
events.forEach(((fn) => {
|
events.forEach((fn) => {
|
||||||
fn.apply(this, args);
|
fn.apply(this, args);
|
||||||
}));
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,12 +25,11 @@ class Keyboard {
|
|||||||
addShortcut(shortcuts: string[] | string, callback: () => void) {
|
addShortcut(shortcuts: string[] | string, callback: () => void) {
|
||||||
const shortcutsArray = Array.isArray(shortcuts) ? shortcuts : [shortcuts];
|
const shortcutsArray = Array.isArray(shortcuts) ? shortcuts : [shortcuts];
|
||||||
shortcutsArray.forEach((shortcut) => {
|
shortcutsArray.forEach((shortcut) => {
|
||||||
$(document).bind('keydown', shortcut,
|
$(document).bind('keydown', shortcut, (e) => {
|
||||||
(e) => {
|
e.stopPropagation();
|
||||||
e.stopPropagation();
|
e.preventDefault();
|
||||||
e.preventDefault();
|
callback();
|
||||||
callback();
|
});
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,11 @@ class LocalStorageManager extends PersistenceManager {
|
|||||||
if (xml == null || this.forceLoad) {
|
if (xml == null || this.forceLoad) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: this.documentUrl.replace('{id}', mapId),
|
url: this.documentUrl.replace('{id}', mapId),
|
||||||
headers: { 'Content-Type': 'text/plain', Accept: 'application/xml', 'X-CSRF-Token': this.getCSRFToken() },
|
headers: {
|
||||||
|
'Content-Type': 'text/plain',
|
||||||
|
Accept: 'application/xml',
|
||||||
|
'X-CSRF-Token': this.getCSRFToken(),
|
||||||
|
},
|
||||||
type: 'get',
|
type: 'get',
|
||||||
dataType: 'text',
|
dataType: 'text',
|
||||||
async: false,
|
async: false,
|
||||||
|
@ -26,7 +26,7 @@ import Workspace from './Workspace';
|
|||||||
import SizeType from './SizeType';
|
import SizeType from './SizeType';
|
||||||
|
|
||||||
class MainTopic extends Topic {
|
class MainTopic extends Topic {
|
||||||
private INNER_RECT_ATTRIBUTES: { stroke: string; };
|
private INNER_RECT_ATTRIBUTES: { stroke: string };
|
||||||
|
|
||||||
constructor(model: NodeModel, options) {
|
constructor(model: NodeModel, options) {
|
||||||
super(model, options);
|
super(model, options);
|
||||||
|
@ -33,23 +33,20 @@ class MultilineTextEditor extends Events {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static _buildEditor() {
|
private static _buildEditor() {
|
||||||
const result = $('<div></div>')
|
const result = $('<div></div>').attr('id', 'textContainer').css({
|
||||||
.attr('id', 'textContainer')
|
display: 'none',
|
||||||
.css({
|
zIndex: '8',
|
||||||
display: 'none',
|
border: '0 none',
|
||||||
zIndex: '8',
|
});
|
||||||
border: '0 none',
|
|
||||||
});
|
|
||||||
|
|
||||||
const textareaElem = $('<textarea tabindex="-1" value="" wrap="off" ></textarea>')
|
const textareaElem = $('<textarea tabindex="-1" value="" wrap="off" ></textarea>').css({
|
||||||
.css({
|
border: '1px gray dashed',
|
||||||
border: '1px gray dashed',
|
background: 'rgba(98, 135, 167, .4)',
|
||||||
background: 'rgba(98, 135, 167, .4)',
|
outline: '0 none',
|
||||||
outline: '0 none',
|
resize: 'none',
|
||||||
resize: 'none',
|
overflow: 'hidden',
|
||||||
overflow: 'hidden',
|
padding: '2px 0px 2px 4px',
|
||||||
padding: '2px 0px 2px 4px',
|
});
|
||||||
});
|
|
||||||
|
|
||||||
result.append(textareaElem);
|
result.append(textareaElem);
|
||||||
return result;
|
return result;
|
||||||
|
@ -77,11 +77,10 @@ class NoteIcon extends Icon {
|
|||||||
}
|
}
|
||||||
const result = $('<div id="textPopoverNote"></div>').css({ padding: '5px' });
|
const result = $('<div id="textPopoverNote"></div>').css({ padding: '5px' });
|
||||||
|
|
||||||
const text = $('<div></div>').text(this._linksModel.getText())
|
const text = $('<div></div>').text(this._linksModel.getText()).css({
|
||||||
.css({
|
'white-space': 'pre-wrap',
|
||||||
'white-space': 'pre-wrap',
|
'word-wrap': 'break-word',
|
||||||
'word-wrap': 'break-word',
|
});
|
||||||
});
|
|
||||||
result.append(text);
|
result.append(text);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,6 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
type PositionType = { x: number, y: number };
|
type PositionType = { x: number; y: number };
|
||||||
|
|
||||||
export default PositionType;
|
export default PositionType;
|
||||||
|
@ -118,10 +118,7 @@ class Relationship extends ConnectionLine {
|
|||||||
this._line2d.setStroke(2);
|
this._line2d.setStroke(2);
|
||||||
const ctrlPoints = this._line2d.getControlPoints();
|
const ctrlPoints = this._line2d.getControlPoints();
|
||||||
if (!this._line2d.isDestControlPointCustom() && !this._line2d.isSrcControlPointCustom()) {
|
if (!this._line2d.isDestControlPointCustom() && !this._line2d.isSrcControlPointCustom()) {
|
||||||
const defaultPoints = Shape.calculateDefaultControlPoints(
|
const defaultPoints = Shape.calculateDefaultControlPoints(sourcePosition, targetPosition);
|
||||||
sourcePosition,
|
|
||||||
targetPosition,
|
|
||||||
);
|
|
||||||
ctrlPoints[0].x = defaultPoints[0].x;
|
ctrlPoints[0].x = defaultPoints[0].x;
|
||||||
ctrlPoints[0].y = defaultPoints[0].y;
|
ctrlPoints[0].y = defaultPoints[0].y;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class RESTPersistenceManager extends PersistenceManager {
|
|||||||
|
|
||||||
private clearTimeout;
|
private clearTimeout;
|
||||||
|
|
||||||
constructor(options: { documentUrl: string, revertUrl: string, lockUrl: string }) {
|
constructor(options: { documentUrl: string; revertUrl: string; lockUrl: string }) {
|
||||||
$assert(options.documentUrl, 'documentUrl can not be null');
|
$assert(options.documentUrl, 'documentUrl can not be null');
|
||||||
$assert(options.revertUrl, 'revertUrl can not be null');
|
$assert(options.revertUrl, 'revertUrl can not be null');
|
||||||
$assert(options.lockUrl, 'lockUrl can not be null');
|
$assert(options.lockUrl, 'lockUrl can not be null');
|
||||||
@ -60,78 +60,87 @@ class RESTPersistenceManager extends PersistenceManager {
|
|||||||
}, 10000);
|
}, 10000);
|
||||||
|
|
||||||
const persistence = this;
|
const persistence = this;
|
||||||
fetch(
|
fetch(`${this.documentUrl.replace('{id}', mapId)}?${query}`, {
|
||||||
`${this.documentUrl.replace('{id}', mapId)}?${query}`,
|
method: 'PUT',
|
||||||
{
|
// Blob helps to resuce the memory on large payload.
|
||||||
method: 'PUT',
|
body: new Blob([JSON.stringify(data)], { type: 'text/plain' }),
|
||||||
// Blob helps to resuce the memory on large payload.
|
headers: {
|
||||||
body: new Blob([JSON.stringify(data)], { type: 'text/plain' }),
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
headers: { 'Content-Type': 'application/json; charset=utf-8', Accept: 'application/json', 'X-CSRF-Token': this.getCSRFToken() },
|
Accept: 'application/json',
|
||||||
|
'X-CSRF-Token': this.getCSRFToken(),
|
||||||
},
|
},
|
||||||
).then(async (response: Response) => {
|
})
|
||||||
if (response.ok) {
|
.then(async (response: Response) => {
|
||||||
events.onSuccess();
|
if (response.ok) {
|
||||||
} else {
|
events.onSuccess();
|
||||||
console.log(`Saving error: ${response.status}`);
|
|
||||||
let userMsg;
|
|
||||||
if (response.status === 405) {
|
|
||||||
userMsg = { severity: 'SEVERE', message: $msg('SESSION_EXPIRED'), errorType: 'session-expired' };
|
|
||||||
} else {
|
} else {
|
||||||
const responseText = await response.text();
|
console.log(`Saving error: ${response.status}`);
|
||||||
const contentType = response.headers['Content-Type'];
|
let userMsg;
|
||||||
if (contentType != null && contentType.indexOf('application/json') !== -1) {
|
if (response.status === 405) {
|
||||||
let serverMsg = null;
|
userMsg = {
|
||||||
try {
|
severity: 'SEVERE',
|
||||||
serverMsg = JSON.parse(responseText);
|
message: $msg('SESSION_EXPIRED'),
|
||||||
serverMsg = serverMsg.globalSeverity ? serverMsg : null;
|
errorType: 'session-expired',
|
||||||
} catch (e) {
|
};
|
||||||
// Message could not be decoded ...
|
} else {
|
||||||
|
const responseText = await response.text();
|
||||||
|
const contentType = response.headers['Content-Type'];
|
||||||
|
if (contentType != null && contentType.indexOf('application/json') !== -1) {
|
||||||
|
let serverMsg = null;
|
||||||
|
try {
|
||||||
|
serverMsg = JSON.parse(responseText);
|
||||||
|
serverMsg = serverMsg.globalSeverity ? serverMsg : null;
|
||||||
|
} catch (e) {
|
||||||
|
// Message could not be decoded ...
|
||||||
|
}
|
||||||
|
userMsg = persistence._buildError(serverMsg);
|
||||||
}
|
}
|
||||||
userMsg = persistence._buildError(serverMsg);
|
|
||||||
}
|
}
|
||||||
|
this.triggerError(userMsg);
|
||||||
|
events.onError(userMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear event timeout ...
|
||||||
|
if (persistence.clearTimeout) {
|
||||||
|
clearTimeout(persistence.clearTimeout);
|
||||||
|
}
|
||||||
|
persistence.onSave = false;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
const userMsg: PersistenceError = {
|
||||||
|
severity: 'SEVERE',
|
||||||
|
message: $msg('SAVE_COULD_NOT_BE_COMPLETED'),
|
||||||
|
errorType: 'generic',
|
||||||
|
};
|
||||||
this.triggerError(userMsg);
|
this.triggerError(userMsg);
|
||||||
events.onError(userMsg);
|
events.onError(userMsg);
|
||||||
}
|
|
||||||
|
|
||||||
// Clear event timeout ...
|
// Clear event timeout ...
|
||||||
if (persistence.clearTimeout) {
|
if (persistence.clearTimeout) {
|
||||||
clearTimeout(persistence.clearTimeout);
|
clearTimeout(persistence.clearTimeout);
|
||||||
}
|
}
|
||||||
persistence.onSave = false;
|
persistence.onSave = false;
|
||||||
}).catch(() => {
|
});
|
||||||
const userMsg: PersistenceError = {
|
|
||||||
severity: 'SEVERE', message: $msg('SAVE_COULD_NOT_BE_COMPLETED'), errorType: 'generic',
|
|
||||||
};
|
|
||||||
this.triggerError(userMsg);
|
|
||||||
events.onError(userMsg);
|
|
||||||
|
|
||||||
// Clear event timeout ...
|
|
||||||
if (persistence.clearTimeout) {
|
|
||||||
clearTimeout(persistence.clearTimeout);
|
|
||||||
}
|
|
||||||
persistence.onSave = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
discardChanges(mapId: string) {
|
discardChanges(mapId: string) {
|
||||||
fetch(this.revertUrl.replace('{id}', mapId),
|
fetch(this.revertUrl.replace('{id}', mapId), {
|
||||||
{
|
method: 'POST',
|
||||||
method: 'POST',
|
headers: {
|
||||||
headers: { 'Content-Type': 'application/json; charset=utf-8', Accept: 'application/json', 'X-CSRF-Token': this.getCSRFToken() },
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
});
|
Accept: 'application/json',
|
||||||
|
'X-CSRF-Token': this.getCSRFToken(),
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
unlockMap(mapId: string): void {
|
unlockMap(mapId: string): void {
|
||||||
fetch(
|
fetch(this.lockUrl.replace('{id}', mapId), {
|
||||||
this.lockUrl.replace('{id}', mapId),
|
method: 'PUT',
|
||||||
{
|
headers: { 'Content-Type': 'text/plain', 'X-CSRF-Token': this.getCSRFToken() },
|
||||||
method: 'PUT',
|
body: 'false',
|
||||||
headers: { 'Content-Type': 'text/plain', 'X-CSRF-Token': this.getCSRFToken() },
|
});
|
||||||
body: 'false',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _buildError(jsonSeverResponse) {
|
private _buildError(jsonSeverResponse) {
|
||||||
@ -154,7 +163,11 @@ class RESTPersistenceManager extends PersistenceManager {
|
|||||||
url: `${this.documentUrl.replace('{id}', mapId)}/xml`,
|
url: `${this.documentUrl.replace('{id}', mapId)}/xml`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
async: false,
|
async: false,
|
||||||
headers: { 'Content-Type': 'text/plain', Accept: 'application/xml', 'X-CSRF-Token': this.getCSRFToken() },
|
headers: {
|
||||||
|
'Content-Type': 'text/plain',
|
||||||
|
Accept: 'application/xml',
|
||||||
|
'X-CSRF-Token': this.getCSRFToken(),
|
||||||
|
},
|
||||||
success(responseText) {
|
success(responseText) {
|
||||||
xml = responseText;
|
xml = responseText;
|
||||||
},
|
},
|
||||||
|
@ -18,9 +18,7 @@
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { $assert, $defined } from '@wisemapping/core-js';
|
import { $assert, $defined } from '@wisemapping/core-js';
|
||||||
|
|
||||||
import {
|
import { Rect, Image, Line, Text, Group, ElementClass, Point } from '@wisemapping/web2d';
|
||||||
Rect, Image, Line, Text, Group, ElementClass, Point,
|
|
||||||
} from '@wisemapping/web2d';
|
|
||||||
|
|
||||||
import NodeGraph from './NodeGraph';
|
import NodeGraph from './NodeGraph';
|
||||||
import TopicConfig from './TopicConfig';
|
import TopicConfig from './TopicConfig';
|
||||||
@ -177,10 +175,7 @@ abstract class Topic extends NodeGraph {
|
|||||||
getInnerShape(): ElementClass {
|
getInnerShape(): ElementClass {
|
||||||
if (!$defined(this._innerShape)) {
|
if (!$defined(this._innerShape)) {
|
||||||
// Create inner box.
|
// Create inner box.
|
||||||
this._innerShape = this._buildShape(
|
this._innerShape = this._buildShape(TopicConfig.INNER_RECT_ATTRIBUTES, this.getShapeType());
|
||||||
TopicConfig.INNER_RECT_ATTRIBUTES,
|
|
||||||
this.getShapeType(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update bgcolor ...
|
// Update bgcolor ...
|
||||||
const bgColor = this.getBackgroundColor();
|
const bgColor = this.getBackgroundColor();
|
||||||
@ -246,7 +241,9 @@ abstract class Topic extends NodeGraph {
|
|||||||
result.setStroke(1, 'solid', stokeColor);
|
result.setStroke(1, 'solid', stokeColor);
|
||||||
};
|
};
|
||||||
|
|
||||||
result.getSize = function getSize() { return this.size; };
|
result.getSize = function getSize() {
|
||||||
|
return this.size;
|
||||||
|
};
|
||||||
|
|
||||||
result.setPosition = () => {
|
result.setPosition = () => {
|
||||||
// Overwrite behaviour ...
|
// Overwrite behaviour ...
|
||||||
@ -279,10 +276,7 @@ abstract class Topic extends NodeGraph {
|
|||||||
|
|
||||||
getOuterShape(): ElementClass {
|
getOuterShape(): ElementClass {
|
||||||
if (!$defined(this._outerShape)) {
|
if (!$defined(this._outerShape)) {
|
||||||
const rect = this._buildShape(
|
const rect = this._buildShape(TopicConfig.OUTER_SHAPE_ATTRIBUTES, TopicShape.ROUNDED_RECT);
|
||||||
TopicConfig.OUTER_SHAPE_ATTRIBUTES,
|
|
||||||
TopicShape.ROUNDED_RECT,
|
|
||||||
);
|
|
||||||
rect.setPosition(-2, -3);
|
rect.setPosition(-2, -3);
|
||||||
rect.setOpacity(0);
|
rect.setOpacity(0);
|
||||||
this._outerShape = rect;
|
this._outerShape = rect;
|
||||||
@ -822,8 +816,8 @@ abstract class Topic extends NodeGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Point: references the center of the rect shape.!!!
|
* Point: references the center of the rect shape.!!!
|
||||||
*/
|
*/
|
||||||
setPosition(point: Point) {
|
setPosition(point: Point) {
|
||||||
$assert(point, 'position can not be null');
|
$assert(point, 'position can not be null');
|
||||||
// allowed param reassign to avoid risks of existing code relying in this side-effect
|
// allowed param reassign to avoid risks of existing code relying in this side-effect
|
||||||
@ -953,9 +947,9 @@ abstract class Topic extends NodeGraph {
|
|||||||
const targetParent = targetTopic.getModel().getParent();
|
const targetParent = targetTopic.getModel().getParent();
|
||||||
const sourceParent = sourceTopic.getModel().getParent();
|
const sourceParent = sourceTopic.getModel().getParent();
|
||||||
relationship.setVisibility(
|
relationship.setVisibility(
|
||||||
value
|
value &&
|
||||||
&& (targetParent == null || !targetParent.areChildrenShrunken())
|
(targetParent == null || !targetParent.areChildrenShrunken()) &&
|
||||||
&& (sourceParent == null || !sourceParent.areChildrenShrunken()),
|
(sourceParent == null || !sourceParent.areChildrenShrunken()),
|
||||||
fade,
|
fade,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1027,7 +1021,8 @@ abstract class Topic extends NodeGraph {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const oldSize = this.getSize();
|
const oldSize = this.getSize();
|
||||||
const hasSizeChanged = oldSize.width !== roundedSize.width || oldSize.height !== roundedSize.height;
|
const hasSizeChanged =
|
||||||
|
oldSize.width !== roundedSize.width || oldSize.height !== roundedSize.height;
|
||||||
if (hasSizeChanged || force) {
|
if (hasSizeChanged || force) {
|
||||||
NodeGraph.prototype.setSize.call(this, roundedSize);
|
NodeGraph.prototype.setSize.call(this, roundedSize);
|
||||||
|
|
||||||
@ -1259,10 +1254,13 @@ abstract class Topic extends NodeGraph {
|
|||||||
const iconGroupWith = iconGroup.getSize().width;
|
const iconGroupWith = iconGroup.getSize().width;
|
||||||
const topicWith = iconGroupWith + 2 * textIconSpacing + textWidth + padding * 2;
|
const topicWith = iconGroupWith + 2 * textIconSpacing + textWidth + padding * 2;
|
||||||
|
|
||||||
this.setSize({
|
this.setSize(
|
||||||
width: topicWith,
|
{
|
||||||
height: topicHeight,
|
width: topicWith,
|
||||||
}, false);
|
height: topicHeight,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
// Adjust all topic elements positions ...
|
// Adjust all topic elements positions ...
|
||||||
const yPosition = Math.round((topicHeight - textHeight) / 2);
|
const yPosition = Math.round((topicHeight - textHeight) / 2);
|
||||||
|
@ -65,9 +65,9 @@ class TopicEventDispatcher extends Events {
|
|||||||
// Open the new editor ...
|
// Open the new editor ...
|
||||||
const model = topic.getModel();
|
const model = topic.getModel();
|
||||||
if (
|
if (
|
||||||
model.getShapeType() !== TopicShape.IMAGE
|
model.getShapeType() !== TopicShape.IMAGE &&
|
||||||
&& !this._readOnly
|
!this._readOnly &&
|
||||||
&& eventType === TopicEvent.EDIT
|
eventType === TopicEvent.EDIT
|
||||||
) {
|
) {
|
||||||
this._multilineEditor.show(topic, options ? options.text : null);
|
this._multilineEditor.show(topic, options ? options.text : null);
|
||||||
this._activeEditor = this._multilineEditor;
|
this._activeEditor = this._multilineEditor;
|
||||||
|
@ -31,15 +31,15 @@ class AddFeatureToTopicCommand extends Command {
|
|||||||
private _featureModel: FeatureModel;
|
private _featureModel: FeatureModel;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @classdesc This command class handles do/undo of adding features to topics, e.g. an
|
* @classdesc This command class handles do/undo of adding features to topics, e.g. an
|
||||||
* icon or a note. For a reference of existing features, refer to {@link mindplot.TopicFeature}
|
* icon or a note. For a reference of existing features, refer to {@link mindplot.TopicFeature}
|
||||||
* @constructs
|
* @constructs
|
||||||
* @param {String} topicId the id of the topic
|
* @param {String} topicId the id of the topic
|
||||||
* @param {String} featureType the id of the feature type to add, e.g. "icon"
|
* @param {String} featureType the id of the feature type to add, e.g. "icon"
|
||||||
* @param {Object} attributes the attribute(s) of the respective feature model
|
* @param {Object} attributes the attribute(s) of the respective feature model
|
||||||
* @extends mindplot.Command
|
* @extends mindplot.Command
|
||||||
* @see mindplot.model.FeatureModel and subclasses
|
* @see mindplot.model.FeatureModel and subclasses
|
||||||
*/
|
*/
|
||||||
constructor(topicId: number, featureType: FeatureType, attributes: object) {
|
constructor(topicId: number, featureType: FeatureType, attributes: object) {
|
||||||
$assert($defined(topicId), 'topicId can not be null');
|
$assert($defined(topicId), 'topicId can not be null');
|
||||||
$assert(featureType, 'featureType can not be null');
|
$assert(featureType, 'featureType can not be null');
|
||||||
|
@ -24,8 +24,8 @@ class AddRelationshipCommand extends Command {
|
|||||||
private _model: RelationshipModel;
|
private _model: RelationshipModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc This command class handles do/undo of adding a relationship to a topic.
|
* @classdesc This command class handles do/undo of adding a relationship to a topic.
|
||||||
*/
|
*/
|
||||||
constructor(model: RelationshipModel) {
|
constructor(model: RelationshipModel) {
|
||||||
$assert(model, 'Relationship model can not be null');
|
$assert(model, 'Relationship model can not be null');
|
||||||
|
|
||||||
|
@ -31,7 +31,10 @@ class AddTopicCommand extends Command {
|
|||||||
*/
|
*/
|
||||||
constructor(models: NodeModel[], parentTopicsId: number[]) {
|
constructor(models: NodeModel[], parentTopicsId: number[]) {
|
||||||
$assert(models, 'models can not be null');
|
$assert(models, 'models can not be null');
|
||||||
$assert(parentTopicsId == null || parentTopicsId.length === models.length, 'parents and models must have the same size');
|
$assert(
|
||||||
|
parentTopicsId == null || parentTopicsId.length === models.length,
|
||||||
|
'parents and models must have the same size',
|
||||||
|
);
|
||||||
|
|
||||||
super();
|
super();
|
||||||
this._models = models;
|
this._models = models;
|
||||||
|
@ -46,14 +46,14 @@ class DeleteCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides abstract parent method
|
* Overrides abstract parent method
|
||||||
*/
|
*/
|
||||||
execute(commandContext: CommandContext) {
|
execute(commandContext: CommandContext) {
|
||||||
// If a parent has been selected for deletion, the children must be excluded from the delete ...
|
// If a parent has been selected for deletion, the children must be excluded from the delete ...
|
||||||
const topics = this._filterChildren(this._topicIds, commandContext);
|
const topics = this._filterChildren(this._topicIds, commandContext);
|
||||||
|
|
||||||
if (topics.length > 0) {
|
if (topics.length > 0) {
|
||||||
topics.forEach(((topic) => {
|
topics.forEach((topic) => {
|
||||||
// In case that it's editing text node, force close without update ...
|
// In case that it's editing text node, force close without update ...
|
||||||
topic.closeEditors();
|
topic.closeEditors();
|
||||||
|
|
||||||
@ -81,22 +81,22 @@ class DeleteCommand extends Command {
|
|||||||
|
|
||||||
// Finally, delete the topic from the workspace...
|
// Finally, delete the topic from the workspace...
|
||||||
commandContext.deleteTopic(topic);
|
commandContext.deleteTopic(topic);
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const rels = commandContext.findRelationships(this._relIds);
|
const rels = commandContext.findRelationships(this._relIds);
|
||||||
if (rels.length > 0) {
|
if (rels.length > 0) {
|
||||||
rels.forEach(((rel) => {
|
rels.forEach((rel) => {
|
||||||
this._deletedRelModel.push(rel.getModel().clone());
|
this._deletedRelModel.push(rel.getModel().clone());
|
||||||
commandContext.deleteRelationship(rel);
|
commandContext.deleteRelationship(rel);
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides abstract parent method
|
* Overrides abstract parent method
|
||||||
* @see {@link mindplot.Command.undoExecute}
|
* @see {@link mindplot.Command.undoExecute}
|
||||||
*/
|
*/
|
||||||
undoExecute(commandContext: CommandContext) {
|
undoExecute(commandContext: CommandContext) {
|
||||||
// Add all the topics ...
|
// Add all the topics ...
|
||||||
this._deletedTopicModels.forEach((model) => {
|
this._deletedTopicModels.forEach((model) => {
|
||||||
@ -104,7 +104,7 @@ class DeleteCommand extends Command {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Do they need to be connected ?
|
// Do they need to be connected ?
|
||||||
this._deletedTopicModels.forEach(((topicModel, index) => {
|
this._deletedTopicModels.forEach((topicModel, index) => {
|
||||||
const topics = commandContext.findTopics([topicModel.getId()]);
|
const topics = commandContext.findTopics([topicModel.getId()]);
|
||||||
|
|
||||||
const parentId = this._parentTopicIds[index];
|
const parentId = this._parentTopicIds[index];
|
||||||
@ -112,7 +112,7 @@ class DeleteCommand extends Command {
|
|||||||
const parentTopics = commandContext.findTopics([parentId]);
|
const parentTopics = commandContext.findTopics([parentId]);
|
||||||
commandContext.connect(topics[0], parentTopics[0]);
|
commandContext.connect(topics[0], parentTopics[0]);
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
|
||||||
// Add rebuild relationships ...
|
// Add rebuild relationships ...
|
||||||
this._deletedRelModel.forEach((model) => {
|
this._deletedRelModel.forEach((model) => {
|
||||||
@ -165,11 +165,10 @@ class DeleteCommand extends Command {
|
|||||||
result = result.concat(topic.getRelationships());
|
result = result.concat(topic.getRelationships());
|
||||||
|
|
||||||
const children = topic.getChildren();
|
const children = topic.getChildren();
|
||||||
const rels: (Relationship[])[] = children
|
const rels: Relationship[][] = children.map((t: Topic) => this._collectInDepthRelationships(t));
|
||||||
.map(((t: Topic) => this._collectInDepthRelationships(t)));
|
|
||||||
|
|
||||||
// flatten and concact
|
// flatten and concact
|
||||||
result = result.concat(([].concat(...rels)));
|
result = result.concat([].concat(...rels));
|
||||||
|
|
||||||
if (result.length > 0) {
|
if (result.length > 0) {
|
||||||
// Filter for unique ...
|
// Filter for unique ...
|
||||||
|
@ -31,9 +31,9 @@ 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.
|
* @classdesc This command class handles do/undo of dragging a topic to a new position.
|
||||||
* @constructs
|
* @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');
|
$assert(topicId, 'topicId must be defined');
|
||||||
super();
|
super();
|
||||||
|
@ -29,11 +29,15 @@ class GenericFunctionCommand extends Command {
|
|||||||
|
|
||||||
private _commandFunc: (topic: Topic, value: CommandTypes) => CommandTypes;
|
private _commandFunc: (topic: Topic, value: CommandTypes) => CommandTypes;
|
||||||
|
|
||||||
private _oldValues: (CommandTypes)[];
|
private _oldValues: CommandTypes[];
|
||||||
|
|
||||||
private _applied: boolean;
|
private _applied: boolean;
|
||||||
|
|
||||||
constructor(commandFunc: (topic: Topic, value: CommandTypes) => CommandTypes, topicsIds: number[], value: CommandTypes = undefined) {
|
constructor(
|
||||||
|
commandFunc: (topic: Topic, value: CommandTypes) => CommandTypes,
|
||||||
|
topicsIds: number[],
|
||||||
|
value: CommandTypes = undefined,
|
||||||
|
) {
|
||||||
$assert(commandFunc, 'commandFunc must be defined');
|
$assert(commandFunc, 'commandFunc must be defined');
|
||||||
$assert($defined(topicsIds), 'topicsIds must be defined');
|
$assert($defined(topicsIds), 'topicsIds must be defined');
|
||||||
|
|
||||||
@ -45,8 +49,8 @@ class GenericFunctionCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides abstract parent method
|
* Overrides abstract parent method
|
||||||
*/
|
*/
|
||||||
execute(commandContext: CommandContext) {
|
execute(commandContext: CommandContext) {
|
||||||
if (!this._applied) {
|
if (!this._applied) {
|
||||||
const topics = commandContext.findTopics(this._topicsIds);
|
const topics = commandContext.findTopics(this._topicsIds);
|
||||||
@ -68,9 +72,9 @@ class GenericFunctionCommand extends Command {
|
|||||||
if (this._applied) {
|
if (this._applied) {
|
||||||
const topics = commandContext.findTopics(this._topicsIds);
|
const topics = commandContext.findTopics(this._topicsIds);
|
||||||
|
|
||||||
topics.forEach(((topic: Topic, index: number) => {
|
topics.forEach((topic: Topic, index: number) => {
|
||||||
this._commandFunc(topic, this._oldValues[index]);
|
this._commandFunc(topic, this._oldValues[index]);
|
||||||
}));
|
});
|
||||||
|
|
||||||
this._applied = false;
|
this._applied = false;
|
||||||
this._oldValues = [];
|
this._oldValues = [];
|
||||||
|
@ -28,9 +28,9 @@ class RemoveFeatureFromTopicCommand extends Command {
|
|||||||
private _oldFeature: FeatureModel;
|
private _oldFeature: FeatureModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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
|
||||||
* a note. For a reference of existing features, refer to {@link mindplot.TopicFeature}.
|
* a note. For a reference of existing features, refer to {@link mindplot.TopicFeature}.
|
||||||
*/
|
*/
|
||||||
constructor(topicId: number, featureId: number) {
|
constructor(topicId: number, featureId: number) {
|
||||||
$assert($defined(topicId), 'topicId can not be null');
|
$assert($defined(topicId), 'topicId can not be null');
|
||||||
$assert(featureId, 'iconModel can not be null');
|
$assert(featureId, 'iconModel can not be null');
|
||||||
@ -42,8 +42,8 @@ class RemoveFeatureFromTopicCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides abstract parent method
|
* Overrides abstract parent method
|
||||||
*/
|
*/
|
||||||
execute(commandContext: CommandContext): void {
|
execute(commandContext: CommandContext): void {
|
||||||
const topic = commandContext.findTopics([this._topicId])[0];
|
const topic = commandContext.findTopics([this._topicId])[0];
|
||||||
const feature = topic.findFeatureById(this._featureId);
|
const feature = topic.findFeatureById(this._featureId);
|
||||||
@ -52,9 +52,9 @@ class RemoveFeatureFromTopicCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides abstract parent method
|
* Overrides abstract parent method
|
||||||
* @see {@link mindplot.Command.undoExecute}
|
* @see {@link mindplot.Command.undoExecute}
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
@ -29,7 +29,13 @@ class BinaryImageExporter extends Exporter {
|
|||||||
|
|
||||||
private adjustToFit: boolean;
|
private adjustToFit: boolean;
|
||||||
|
|
||||||
constructor(svgElement: Element, width: number, height: number, imgFormat: 'image/png' | 'image/jpeg', adjustToFit = true) {
|
constructor(
|
||||||
|
svgElement: Element,
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
imgFormat: 'image/png' | 'image/jpeg',
|
||||||
|
adjustToFit = true,
|
||||||
|
) {
|
||||||
super(imgFormat.split('/')[0], imgFormat);
|
super(imgFormat.split('/')[0], imgFormat);
|
||||||
this.svgElement = svgElement;
|
this.svgElement = svgElement;
|
||||||
this.adjustToFit = adjustToFit;
|
this.adjustToFit = adjustToFit;
|
||||||
@ -55,12 +61,12 @@ class BinaryImageExporter extends Exporter {
|
|||||||
if (this.adjustToFit) {
|
if (this.adjustToFit) {
|
||||||
// Size must match with SVG image size ...
|
// Size must match with SVG image size ...
|
||||||
const size = svgExporter.getImgSize();
|
const size = svgExporter.getImgSize();
|
||||||
width = (size.width * dpr);
|
width = size.width * dpr;
|
||||||
height = (size.height * dpr);
|
height = size.height * dpr;
|
||||||
} else {
|
} else {
|
||||||
// Use screensize as size ..
|
// Use screensize as size ..
|
||||||
width = (this.width * dpr);
|
width = this.width * dpr;
|
||||||
height = (this.height * dpr);
|
height = this.height * dpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Export size: ${width}:${height}`);
|
console.log(`Export size: ${width}:${height}`);
|
||||||
|
@ -77,7 +77,11 @@ class FreemindExporter extends Exporter {
|
|||||||
|
|
||||||
if (centralTopic) {
|
if (centralTopic) {
|
||||||
this.nodeMap.set(centralTopic.getId(), main);
|
this.nodeMap.set(centralTopic.getId(), main);
|
||||||
this.setTopicPropertiesToNode({ freemindNode: main, mindmapTopic: centralTopic, isRoot: true });
|
this.setTopicPropertiesToNode({
|
||||||
|
freemindNode: main,
|
||||||
|
mindmapTopic: centralTopic,
|
||||||
|
isRoot: true,
|
||||||
|
});
|
||||||
this.addNodeFromTopic(centralTopic, main);
|
this.addNodeFromTopic(centralTopic, main);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,9 +95,13 @@ class FreemindExporter extends Exporter {
|
|||||||
|
|
||||||
arrowlink.setDestination(destNode.getId());
|
arrowlink.setDestination(destNode.getId());
|
||||||
|
|
||||||
if (relationship.getEndArrow() && relationship.getEndArrow()) arrowlink.setEndarrow('Default');
|
if (relationship.getEndArrow() && relationship.getEndArrow()) {
|
||||||
|
arrowlink.setEndarrow('Default');
|
||||||
|
}
|
||||||
|
|
||||||
if (relationship.getStartArrow() && relationship.getStartArrow()) arrowlink.setStartarrow('Default');
|
if (relationship.getStartArrow() && relationship.getStartArrow()) {
|
||||||
|
arrowlink.setStartarrow('Default');
|
||||||
|
}
|
||||||
|
|
||||||
srcNode.setArrowlinkOrCloudOrEdge(arrowlink);
|
srcNode.setArrowlinkOrCloudOrEdge(arrowlink);
|
||||||
}
|
}
|
||||||
@ -110,7 +118,15 @@ class FreemindExporter extends Exporter {
|
|||||||
return Promise.resolve(formatXml);
|
return Promise.resolve(formatXml);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setTopicPropertiesToNode({ freemindNode, mindmapTopic, isRoot }: { freemindNode: FreeminNode; mindmapTopic: INodeModel; isRoot: boolean; }): void {
|
private setTopicPropertiesToNode({
|
||||||
|
freemindNode,
|
||||||
|
mindmapTopic,
|
||||||
|
isRoot,
|
||||||
|
}: {
|
||||||
|
freemindNode: FreeminNode;
|
||||||
|
mindmapTopic: INodeModel;
|
||||||
|
isRoot: boolean;
|
||||||
|
}): void {
|
||||||
freemindNode.setId(`ID_${mindmapTopic.getId()}`);
|
freemindNode.setId(`ID_${mindmapTopic.getId()}`);
|
||||||
|
|
||||||
const text = mindmapTopic.getText();
|
const text = mindmapTopic.getText();
|
||||||
@ -154,7 +170,11 @@ class FreemindExporter extends Exporter {
|
|||||||
const newNode: FreeminNode = this.objectFactory.createNode();
|
const newNode: FreeminNode = this.objectFactory.createNode();
|
||||||
this.nodeMap.set(currentTopic.getId(), newNode);
|
this.nodeMap.set(currentTopic.getId(), newNode);
|
||||||
|
|
||||||
this.setTopicPropertiesToNode({ freemindNode: newNode, mindmapTopic: currentTopic, isRoot: false });
|
this.setTopicPropertiesToNode({
|
||||||
|
freemindNode: newNode,
|
||||||
|
mindmapTopic: currentTopic,
|
||||||
|
isRoot: false,
|
||||||
|
});
|
||||||
|
|
||||||
destNode.setArrowlinkOrCloudOrEdge(newNode);
|
destNode.setArrowlinkOrCloudOrEdge(newNode);
|
||||||
|
|
||||||
@ -163,7 +183,7 @@ class FreemindExporter extends Exporter {
|
|||||||
const position: PositionNodeType = currentTopic.getPosition();
|
const position: PositionNodeType = currentTopic.getPosition();
|
||||||
if (position) {
|
if (position) {
|
||||||
const xPos: number = position.x;
|
const xPos: number = position.x;
|
||||||
newNode.setPosition((xPos < 0 ? 'left' : 'right'));
|
newNode.setPosition(xPos < 0 ? 'left' : 'right');
|
||||||
} else newNode.setPosition('left');
|
} else newNode.setPosition('left');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -193,28 +213,27 @@ class FreemindExporter extends Exporter {
|
|||||||
private addFeautreNode(freemindNode: FreeminNode, mindmapTopic: INodeModel): void {
|
private addFeautreNode(freemindNode: FreeminNode, mindmapTopic: INodeModel): void {
|
||||||
const branches: Array<FeatureModel> = mindmapTopic.getFeatures();
|
const branches: Array<FeatureModel> = mindmapTopic.getFeatures();
|
||||||
|
|
||||||
branches
|
branches.forEach((feature: FeatureModel) => {
|
||||||
.forEach((feature: FeatureModel) => {
|
const type = feature.getType();
|
||||||
const type = feature.getType();
|
|
||||||
|
|
||||||
if (type === 'link') {
|
if (type === 'link') {
|
||||||
const link = feature as LinkModel;
|
const link = feature as LinkModel;
|
||||||
freemindNode.setLink(link.getUrl());
|
freemindNode.setLink(link.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'note') {
|
if (type === 'note') {
|
||||||
const note = feature as NoteModel;
|
const note = feature as NoteModel;
|
||||||
const richcontent: Richcontent = this.buildRichcontent(note.getText(), 'NOTE');
|
const richcontent: Richcontent = this.buildRichcontent(note.getText(), 'NOTE');
|
||||||
freemindNode.setArrowlinkOrCloudOrEdge(richcontent);
|
freemindNode.setArrowlinkOrCloudOrEdge(richcontent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'icon') {
|
if (type === 'icon') {
|
||||||
const icon = feature as IconModel;
|
const icon = feature as IconModel;
|
||||||
const freemindIcon: Icon = new Icon();
|
const freemindIcon: Icon = new Icon();
|
||||||
freemindIcon.setBuiltin(icon.getIconType());
|
freemindIcon.setBuiltin(icon.getIconType());
|
||||||
freemindNode.setArrowlinkOrCloudOrEdge(freemindIcon);
|
freemindNode.setArrowlinkOrCloudOrEdge(freemindIcon);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private addEdgeNode(freemainMap: FreeminNode, mindmapTopic: INodeModel): void {
|
private addEdgeNode(freemainMap: FreeminNode, mindmapTopic: INodeModel): void {
|
||||||
@ -286,7 +305,9 @@ class FreemindExporter extends Exporter {
|
|||||||
const g: string = rgb[1].trim();
|
const g: string = rgb[1].trim();
|
||||||
const b: string = rgb[2].trim();
|
const b: string = rgb[2].trim();
|
||||||
|
|
||||||
result = `#${r.length === 1 ? `0${r}` : r}${g.length === 1 ? `0${g}` : g}${b.length === 1 ? `0${b}` : b}`;
|
result = `#${r.length === 1 ? `0${r}` : r}${g.length === 1 ? `0${g}` : g}${
|
||||||
|
b.length === 1 ? `0${b}` : b
|
||||||
|
}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -21,7 +21,13 @@ import SVGExporter from './SVGExporter';
|
|||||||
|
|
||||||
type imageType = 'svg' | 'png' | 'jpg';
|
type imageType = 'svg' | 'png' | 'jpg';
|
||||||
class ImageExpoterFactory {
|
class ImageExpoterFactory {
|
||||||
static create(type: imageType, svgElement: Element, width: number, height: number, adjustToFit = true): Exporter {
|
static create(
|
||||||
|
type: imageType,
|
||||||
|
svgElement: Element,
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
adjustToFit = true,
|
||||||
|
): Exporter {
|
||||||
let result: Exporter;
|
let result: Exporter;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'svg': {
|
case 'svg': {
|
||||||
|
@ -39,8 +39,7 @@ class SVGExporter extends Exporter {
|
|||||||
|
|
||||||
export(): Promise<string> {
|
export(): Promise<string> {
|
||||||
// Replace all images for in-line images ...
|
// Replace all images for in-line images ...
|
||||||
let svgTxt: string = new XMLSerializer()
|
let svgTxt: string = new XMLSerializer().serializeToString(this.svgElement);
|
||||||
.serializeToString(this.svgElement);
|
|
||||||
svgTxt = SVGExporter.prolog + svgTxt;
|
svgTxt = SVGExporter.prolog + svgTxt;
|
||||||
|
|
||||||
// Are namespace declared ?. Otherwise, force the declaration ...
|
// Are namespace declared ?. Otherwise, force the declaration ...
|
||||||
@ -59,39 +58,37 @@ class SVGExporter extends Exporter {
|
|||||||
svgDoc = this._normalizeToFit(svgDoc);
|
svgDoc = this._normalizeToFit(svgDoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = new XMLSerializer()
|
const result = new XMLSerializer().serializeToString(svgDoc);
|
||||||
.serializeToString(svgDoc);
|
|
||||||
|
|
||||||
return Promise.resolve(result);
|
return Promise.resolve(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _calcualteDimensions(): { minX: number, maxX: number, minY: number, maxY: number } {
|
private _calcualteDimensions(): { minX: number; maxX: number; minY: number; maxY: number } {
|
||||||
// Collect all group elements ...
|
// Collect all group elements ...
|
||||||
const rectElems = Array.from(document.querySelectorAll('g>rect'));
|
const rectElems = Array.from(document.querySelectorAll('g>rect'));
|
||||||
const translates: SizeType[] = rectElems
|
const translates: SizeType[] = rectElems.map((rect: Element) => {
|
||||||
.map((rect: Element) => {
|
const g = rect.parentElement;
|
||||||
const g = rect.parentElement;
|
const transformStr = g.getAttribute('transform');
|
||||||
const transformStr = g.getAttribute('transform');
|
|
||||||
|
|
||||||
// Looking to parse translate(220.00000,279.00000) scale(1.00000,1.00000)
|
// Looking to parse translate(220.00000,279.00000) scale(1.00000,1.00000)
|
||||||
const match = transformStr.match(SVGExporter.regexpTranslate);
|
const match = transformStr.match(SVGExporter.regexpTranslate);
|
||||||
let result: SizeType = { width: 0, height: 0 };
|
let result: SizeType = { width: 0, height: 0 };
|
||||||
if (match !== null) {
|
if (match !== null) {
|
||||||
result = { width: Number.parseFloat(match[1]), height: Number.parseFloat(match[2]) };
|
result = { width: Number.parseFloat(match[1]), height: Number.parseFloat(match[2]) };
|
||||||
|
|
||||||
// Add rect size ...
|
// Add rect size ...
|
||||||
if (result.width > 0) {
|
if (result.width > 0) {
|
||||||
const rectWidth = Number.parseFloat(rect.getAttribute('width'));
|
const rectWidth = Number.parseFloat(rect.getAttribute('width'));
|
||||||
result.width += rectWidth;
|
result.width += rectWidth;
|
||||||
}
|
|
||||||
|
|
||||||
if (result.height > 0) {
|
|
||||||
const rectHeight = Number.parseFloat(rect.getAttribute('height'));
|
|
||||||
result.height += rectHeight;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
});
|
if (result.height > 0) {
|
||||||
|
const rectHeight = Number.parseFloat(rect.getAttribute('height'));
|
||||||
|
result.height += rectHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
// Find max and mins ...
|
// Find max and mins ...
|
||||||
const widths = translates.map((t) => t.width).sort((a, b) => a - b);
|
const widths = translates.map((t) => t.width).sort((a, b) => a - b);
|
||||||
@ -104,14 +101,15 @@ class SVGExporter extends Exporter {
|
|||||||
const maxY = heights[heights.length - 1] + SVGExporter.padding;
|
const maxY = heights[heights.length - 1] + SVGExporter.padding;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
minX, maxX, minY, maxY,
|
minX,
|
||||||
|
maxX,
|
||||||
|
minY,
|
||||||
|
maxY,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getImgSize(): SizeType {
|
getImgSize(): SizeType {
|
||||||
const {
|
const { minX, maxX, minY, maxY } = this._calcualteDimensions();
|
||||||
minX, maxX, minY, maxY,
|
|
||||||
} = this._calcualteDimensions();
|
|
||||||
|
|
||||||
let width: number = maxX + Math.abs(minX);
|
let width: number = maxX + Math.abs(minX);
|
||||||
let height: number = maxY + Math.abs(minY);
|
let height: number = maxY + Math.abs(minY);
|
||||||
@ -127,9 +125,7 @@ class SVGExporter extends Exporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _normalizeToFit(document: Document): Document {
|
private _normalizeToFit(document: Document): Document {
|
||||||
const {
|
const { minX, maxX, minY, maxY } = this._calcualteDimensions();
|
||||||
minX, maxX, minY, maxY,
|
|
||||||
} = this._calcualteDimensions();
|
|
||||||
const svgElem = document.firstChild as Element;
|
const svgElem = document.firstChild as Element;
|
||||||
|
|
||||||
const width = maxX + Math.abs(minX);
|
const width = maxX + Math.abs(minX);
|
||||||
|
@ -39,22 +39,23 @@ class TxtExporter extends Exporter {
|
|||||||
|
|
||||||
private traverseBranch(indent: string, prefix: string, branches: INodeModel[]) {
|
private traverseBranch(indent: string, prefix: string, branches: INodeModel[]) {
|
||||||
let result = '';
|
let result = '';
|
||||||
branches
|
branches.forEach((node, index) => {
|
||||||
.forEach((node, index) => {
|
result = `${result}${indent}${prefix}${index + 1} ${
|
||||||
result = `${result}${indent}${prefix}${index + 1} ${node.getText() !== undefined ? node.getText() : ''}`;
|
node.getText() !== undefined ? node.getText() : ''
|
||||||
node.getFeatures().forEach((f) => {
|
}`;
|
||||||
const type = f.getType();
|
node.getFeatures().forEach((f) => {
|
||||||
if (type === 'link') {
|
const type = f.getType();
|
||||||
result = `${result}\n ${indent} [Link: ${(f as LinkModel).getUrl()}]`;
|
if (type === 'link') {
|
||||||
}
|
result = `${result}\n ${indent} [Link: ${(f as LinkModel).getUrl()}]`;
|
||||||
if (type === 'note') {
|
}
|
||||||
result = `${result}\n${indent} [Note: ${(f as NoteModel).getText()}]`;
|
if (type === 'note') {
|
||||||
}
|
result = `${result}\n${indent} [Note: ${(f as NoteModel).getText()}]`;
|
||||||
});
|
}
|
||||||
result = `${result}\n`;
|
|
||||||
|
|
||||||
result += this.traverseBranch(`\t${indent}`, `${prefix}${index + 1}.`, node.getChildren());
|
|
||||||
});
|
});
|
||||||
|
result = `${result}\n`;
|
||||||
|
|
||||||
|
result += this.traverseBranch(`\t${indent}`, `${prefix}${index + 1}.`, node.getChildren());
|
||||||
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,12 +29,10 @@ class WiseXMLExporter extends Exporter {
|
|||||||
|
|
||||||
export(): Promise<string> {
|
export(): Promise<string> {
|
||||||
const { mindmap } = this;
|
const { mindmap } = this;
|
||||||
const serializer = XMLSerializerFactory
|
const serializer = XMLSerializerFactory.createInstanceFromMindmap(mindmap);
|
||||||
.createInstanceFromMindmap(mindmap);
|
|
||||||
const document: Document = serializer.toXML(mindmap);
|
const document: Document = serializer.toXML(mindmap);
|
||||||
|
|
||||||
const xmlStr: string = new XMLSerializer()
|
const xmlStr: string = new XMLSerializer().serializeToString(document);
|
||||||
.serializeToString(document);
|
|
||||||
return Promise.resolve(xmlStr);
|
return Promise.resolve(xmlStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,11 +75,21 @@ export default class Arrowlink {
|
|||||||
arrowlinkElem.setAttribute('DESTINATION', this.DESTINATION);
|
arrowlinkElem.setAttribute('DESTINATION', this.DESTINATION);
|
||||||
arrowlinkElem.setAttribute('STARTARROW', this.STARTARROW);
|
arrowlinkElem.setAttribute('STARTARROW', this.STARTARROW);
|
||||||
|
|
||||||
if (this.COLOR) arrowlinkElem.setAttribute('COLOR', this.COLOR);
|
if (this.COLOR) {
|
||||||
if (this.ENDINCLINATION) arrowlinkElem.setAttribute('ENDINCLINATION', this.ENDINCLINATION);
|
arrowlinkElem.setAttribute('COLOR', this.COLOR);
|
||||||
if (this.ENDARROW) arrowlinkElem.setAttribute('ENDARROW', this.ENDARROW);
|
}
|
||||||
if (this.ID) arrowlinkElem.setAttribute('ID', this.ID);
|
if (this.ENDINCLINATION) {
|
||||||
if (this.STARTINCLINATION) arrowlinkElem.setAttribute('STARTINCLINATION', this.STARTINCLINATION);
|
arrowlinkElem.setAttribute('ENDINCLINATION', this.ENDINCLINATION);
|
||||||
|
}
|
||||||
|
if (this.ENDARROW) {
|
||||||
|
arrowlinkElem.setAttribute('ENDARROW', this.ENDARROW);
|
||||||
|
}
|
||||||
|
if (this.ID) {
|
||||||
|
arrowlinkElem.setAttribute('ID', this.ID);
|
||||||
|
}
|
||||||
|
if (this.STARTINCLINATION) {
|
||||||
|
arrowlinkElem.setAttribute('STARTINCLINATION', this.STARTINCLINATION);
|
||||||
|
}
|
||||||
|
|
||||||
return arrowlinkElem;
|
return arrowlinkElem;
|
||||||
}
|
}
|
||||||
|
@ -65,10 +65,7 @@ export default class Freemap {
|
|||||||
|
|
||||||
// Verify that the version attribute exists
|
// Verify that the version attribute exists
|
||||||
console.log(rootElem.getAttribute('version'));
|
console.log(rootElem.getAttribute('version'));
|
||||||
$assert(
|
$assert(rootElem.getAttribute('version') !== null, 'Freemind version not found');
|
||||||
rootElem.getAttribute('version') !== null,
|
|
||||||
'Freemind version not found',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Start the loading process...
|
// Start the loading process...
|
||||||
const version = rootElem.getAttribute('version') || '1.0.1';
|
const version = rootElem.getAttribute('version') || '1.0.1';
|
||||||
@ -81,9 +78,7 @@ export default class Freemap {
|
|||||||
|
|
||||||
const childNodes = Array.from(mainTopicElement.childNodes);
|
const childNodes = Array.from(mainTopicElement.childNodes);
|
||||||
const childsNodes = childNodes
|
const childsNodes = childNodes
|
||||||
.filter(
|
.filter((child: ChildNode) => child.nodeType === 1 && (child as Element).tagName === 'node')
|
||||||
(child: ChildNode) => child.nodeType === 1 && (child as Element).tagName === 'node',
|
|
||||||
)
|
|
||||||
.map((c) => c as Element);
|
.map((c) => c as Element);
|
||||||
|
|
||||||
childsNodes.forEach((child: Element) => {
|
childsNodes.forEach((child: Element) => {
|
||||||
@ -98,14 +93,16 @@ export default class Freemap {
|
|||||||
let element: Element;
|
let element: Element;
|
||||||
if (child.nodeType === 1) {
|
if (child.nodeType === 1) {
|
||||||
if (
|
if (
|
||||||
(child as Element).tagName === 'node'
|
(child as Element).tagName === 'node' ||
|
||||||
|| (child as Element).tagName === 'richcontent'
|
(child as Element).tagName === 'richcontent' ||
|
||||||
|| (child as Element).tagName === 'font'
|
(child as Element).tagName === 'font' ||
|
||||||
|| (child as Element).tagName === 'edge'
|
(child as Element).tagName === 'edge' ||
|
||||||
|| (child as Element).tagName === 'arrowlink'
|
(child as Element).tagName === 'arrowlink' ||
|
||||||
|| (child as Element).tagName === 'clud'
|
(child as Element).tagName === 'clud' ||
|
||||||
|| (child as Element).tagName === 'icon'
|
(child as Element).tagName === 'icon'
|
||||||
) element = child as Element;
|
) {
|
||||||
|
element = child as Element;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
@ -132,44 +129,78 @@ export default class Freemap {
|
|||||||
|
|
||||||
if (nodeElem.tagName === 'font') {
|
if (nodeElem.tagName === 'font') {
|
||||||
node = new Font();
|
node = new Font();
|
||||||
if (nodeElem.getAttribute('NAME')) node.setName(nodeElem.getAttribute('NAME'));
|
if (nodeElem.getAttribute('NAME')) {
|
||||||
if (nodeElem.getAttribute('BOLD')) node.setBold(nodeElem.getAttribute('BOLD'));
|
node.setName(nodeElem.getAttribute('NAME'));
|
||||||
if (nodeElem.getAttribute('ITALIC')) node.setItalic(nodeElem.getAttribute('ITALIC'));
|
}
|
||||||
if (nodeElem.getAttribute('SIZE')) node.setSize(nodeElem.getAttribute('SIZE'));
|
if (nodeElem.getAttribute('BOLD')) {
|
||||||
|
node.setBold(nodeElem.getAttribute('BOLD'));
|
||||||
|
}
|
||||||
|
if (nodeElem.getAttribute('ITALIC')) {
|
||||||
|
node.setItalic(nodeElem.getAttribute('ITALIC'));
|
||||||
|
}
|
||||||
|
if (nodeElem.getAttribute('SIZE')) {
|
||||||
|
node.setSize(nodeElem.getAttribute('SIZE'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeElem.tagName === 'edge') {
|
if (nodeElem.tagName === 'edge') {
|
||||||
node = new Edge();
|
node = new Edge();
|
||||||
if (nodeElem.getAttribute('COLOR')) node.setColor(nodeElem.getAttribute('COLOR'));
|
if (nodeElem.getAttribute('COLOR')) {
|
||||||
if (nodeElem.getAttribute('STYLE')) node.setStyle(nodeElem.getAttribute('STYLE'));
|
node.setColor(nodeElem.getAttribute('COLOR'));
|
||||||
if (nodeElem.getAttribute('WIDTH')) node.setWidth(nodeElem.getAttribute('WIDTH'));
|
}
|
||||||
|
if (nodeElem.getAttribute('STYLE')) {
|
||||||
|
node.setStyle(nodeElem.getAttribute('STYLE'));
|
||||||
|
}
|
||||||
|
if (nodeElem.getAttribute('WIDTH')) {
|
||||||
|
node.setWidth(nodeElem.getAttribute('WIDTH'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeElem.tagName === 'arrowlink') {
|
if (nodeElem.tagName === 'arrowlink') {
|
||||||
node = new Arrowlink();
|
node = new Arrowlink();
|
||||||
if (nodeElem.getAttribute('COLOR')) node.setColor(nodeElem.getAttribute('COLOR'));
|
if (nodeElem.getAttribute('COLOR')) {
|
||||||
if (nodeElem.getAttribute('DESTINATION')) node.setDestination(nodeElem.getAttribute('DESTINATION'));
|
node.setColor(nodeElem.getAttribute('COLOR'));
|
||||||
if (nodeElem.getAttribute('ENDARROW')) node.setEndarrow(nodeElem.getAttribute('ENDARROW'));
|
}
|
||||||
if (nodeElem.getAttribute('ENDINCLINATION')) node.setEndinclination(nodeElem.getAttribute('ENDINCLINATION'));
|
if (nodeElem.getAttribute('DESTINATION')) {
|
||||||
if (nodeElem.getAttribute('ID')) node.setId(nodeElem.getAttribute('ID'));
|
node.setDestination(nodeElem.getAttribute('DESTINATION'));
|
||||||
if (nodeElem.getAttribute('STARTARROW')) node.setStartarrow(nodeElem.getAttribute('STARTARROW'));
|
}
|
||||||
if (nodeElem.getAttribute('STARTINCLINATION')) node.setStartinclination(nodeElem.getAttribute('STARTINCLINATION'));
|
if (nodeElem.getAttribute('ENDARROW')) {
|
||||||
|
node.setEndarrow(nodeElem.getAttribute('ENDARROW'));
|
||||||
|
}
|
||||||
|
if (nodeElem.getAttribute('ENDINCLINATION')) {
|
||||||
|
node.setEndinclination(nodeElem.getAttribute('ENDINCLINATION'));
|
||||||
|
}
|
||||||
|
if (nodeElem.getAttribute('ID')) {
|
||||||
|
node.setId(nodeElem.getAttribute('ID'));
|
||||||
|
}
|
||||||
|
if (nodeElem.getAttribute('STARTARROW')) {
|
||||||
|
node.setStartarrow(nodeElem.getAttribute('STARTARROW'));
|
||||||
|
}
|
||||||
|
if (nodeElem.getAttribute('STARTINCLINATION')) {
|
||||||
|
node.setStartinclination(nodeElem.getAttribute('STARTINCLINATION'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeElem.tagName === 'cloud') {
|
if (nodeElem.tagName === 'cloud') {
|
||||||
node = new Cloud();
|
node = new Cloud();
|
||||||
if (nodeElem.getAttribute('COLOR')) node.setColor(nodeElem.getAttribute('COLOR'));
|
if (nodeElem.getAttribute('COLOR')) {
|
||||||
|
node.setColor(nodeElem.getAttribute('COLOR'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeElem.tagName === 'icon') {
|
if (nodeElem.tagName === 'icon') {
|
||||||
node = new Icon();
|
node = new Icon();
|
||||||
if (nodeElem.getAttribute('BUILTIN')) node.setBuiltin(nodeElem.getAttribute('BUILTIN'));
|
if (nodeElem.getAttribute('BUILTIN')) {
|
||||||
|
node.setBuiltin(nodeElem.getAttribute('BUILTIN'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeElem.tagName === 'richcontent') {
|
if (nodeElem.tagName === 'richcontent') {
|
||||||
node = new Richcontent();
|
node = new Richcontent();
|
||||||
|
|
||||||
if (nodeElem.getAttribute('TYPE')) node.setType(nodeElem.getAttribute('TYPE'));
|
if (nodeElem.getAttribute('TYPE')) {
|
||||||
|
node.setType(nodeElem.getAttribute('TYPE'));
|
||||||
|
}
|
||||||
if (nodeElem.firstChild && nodeElem.getElementsByTagName('html')) {
|
if (nodeElem.firstChild && nodeElem.getElementsByTagName('html')) {
|
||||||
const content = nodeElem.getElementsByTagName('html');
|
const content = nodeElem.getElementsByTagName('html');
|
||||||
const html = content[0] ? content[0].outerHTML : '';
|
const html = content[0] ? content[0].outerHTML : '';
|
||||||
|
@ -7,7 +7,9 @@ import Icon from './Icon';
|
|||||||
import Richcontent from './Richcontent';
|
import Richcontent from './Richcontent';
|
||||||
|
|
||||||
class Node {
|
class Node {
|
||||||
protected arrowlinkOrCloudOrEdge: Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this>;
|
protected arrowlinkOrCloudOrEdge: Array<
|
||||||
|
Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this
|
||||||
|
>;
|
||||||
|
|
||||||
protected BACKGROUND_COLOR: string;
|
protected BACKGROUND_COLOR: string;
|
||||||
|
|
||||||
@ -43,9 +45,14 @@ class Node {
|
|||||||
|
|
||||||
private centralTopic: boolean;
|
private centralTopic: boolean;
|
||||||
|
|
||||||
getArrowlinkOrCloudOrEdge(): Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | Node> {
|
getArrowlinkOrCloudOrEdge(): Array<
|
||||||
|
/* eslint-disable */
|
||||||
|
Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | Node
|
||||||
|
> {
|
||||||
if (!this.arrowlinkOrCloudOrEdge) {
|
if (!this.arrowlinkOrCloudOrEdge) {
|
||||||
this.arrowlinkOrCloudOrEdge = new Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this>();
|
this.arrowlinkOrCloudOrEdge = new Array<
|
||||||
|
Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this
|
||||||
|
>();
|
||||||
}
|
}
|
||||||
return this.arrowlinkOrCloudOrEdge;
|
return this.arrowlinkOrCloudOrEdge;
|
||||||
}
|
}
|
||||||
@ -118,7 +125,9 @@ class Node {
|
|||||||
return this.centralTopic;
|
return this.centralTopic;
|
||||||
}
|
}
|
||||||
|
|
||||||
setArrowlinkOrCloudOrEdge(value: Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this): void {
|
setArrowlinkOrCloudOrEdge(
|
||||||
|
value: Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this,
|
||||||
|
): void {
|
||||||
this.getArrowlinkOrCloudOrEdge().push(value);
|
this.getArrowlinkOrCloudOrEdge().push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,6 +277,6 @@ class Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Choise = Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | Node
|
export type Choise = Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | Node;
|
||||||
|
|
||||||
export default Node;
|
export default Node;
|
||||||
|
@ -26,7 +26,9 @@ export default class Richcontent {
|
|||||||
richcontentElem.setAttribute('TYPE', this.type);
|
richcontentElem.setAttribute('TYPE', this.type);
|
||||||
|
|
||||||
if (this.html) {
|
if (this.html) {
|
||||||
const htmlElement: DocumentFragment = document.createRange().createContextualFragment(this.html);
|
const htmlElement: DocumentFragment = document
|
||||||
|
.createRange()
|
||||||
|
.createContextualFragment(this.html);
|
||||||
richcontentElem.appendChild(htmlElement);
|
richcontentElem.appendChild(htmlElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,9 @@ export default class FreemindImporter extends Importer {
|
|||||||
const version: string = this.freemindMap.getVersion();
|
const version: string = this.freemindMap.getVersion();
|
||||||
|
|
||||||
if (!version || version.startsWith('freeplane')) {
|
if (!version || version.startsWith('freeplane')) {
|
||||||
throw new Error('You seems to be be trying to import a Freeplane map. FreePlane is not supported format.');
|
throw new Error(
|
||||||
|
'You seems to be be trying to import a Freeplane map. FreePlane is not supported format.',
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
const mapVersion: VersionNumber = new VersionNumber(version);
|
const mapVersion: VersionNumber = new VersionNumber(version);
|
||||||
if (mapVersion.isGreaterThan(FreemindConstant.SUPPORTED_FREEMIND_VERSION)) {
|
if (mapVersion.isGreaterThan(FreemindConstant.SUPPORTED_FREEMIND_VERSION)) {
|
||||||
@ -144,7 +146,11 @@ export default class FreemindImporter extends Importer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private convertNodeProperties(freeNode: FreemindNode, wiseTopic: NodeModel, centralTopic: boolean): void {
|
private convertNodeProperties(
|
||||||
|
freeNode: FreemindNode,
|
||||||
|
wiseTopic: NodeModel,
|
||||||
|
centralTopic: boolean,
|
||||||
|
): void {
|
||||||
const text: string = freeNode.getText();
|
const text: string = freeNode.getText();
|
||||||
if (text) {
|
if (text) {
|
||||||
if (!centralTopic && text.length > 100) {
|
if (!centralTopic && text.length > 100) {
|
||||||
@ -177,7 +183,12 @@ export default class FreemindImporter extends Importer {
|
|||||||
if (folded) wiseTopic.setChildrenShrunken(folded);
|
if (folded) wiseTopic.setChildrenShrunken(folded);
|
||||||
}
|
}
|
||||||
|
|
||||||
private convertChildNodes(freeParent: FreemindNode, wiseParent: NodeModel, mindmap: Mindmap, depth: number): void {
|
private convertChildNodes(
|
||||||
|
freeParent: FreemindNode,
|
||||||
|
wiseParent: NodeModel,
|
||||||
|
mindmap: Mindmap,
|
||||||
|
depth: number,
|
||||||
|
): void {
|
||||||
const freeChilden = freeParent.getArrowlinkOrCloudOrEdge();
|
const freeChilden = freeParent.getArrowlinkOrCloudOrEdge();
|
||||||
let currentWiseTopic: NodeModel = wiseParent;
|
let currentWiseTopic: NodeModel = wiseParent;
|
||||||
let order = 0;
|
let order = 0;
|
||||||
@ -206,7 +217,13 @@ export default class FreemindImporter extends Importer {
|
|||||||
|
|
||||||
// Convert node position...
|
// Convert node position...
|
||||||
const childrenCountSameSide = this.getChildrenCountSameSide(freeChilden, child);
|
const childrenCountSameSide = this.getChildrenCountSameSide(freeChilden, child);
|
||||||
const position: {x: number, y: number} = this.convertPosition(wiseParent, child, depth, norder, childrenCountSameSide);
|
const position: { x: number; y: number } = this.convertPosition(
|
||||||
|
wiseParent,
|
||||||
|
child,
|
||||||
|
depth,
|
||||||
|
norder,
|
||||||
|
childrenCountSameSide,
|
||||||
|
);
|
||||||
wiseChild.setPosition(position.x, position.y);
|
wiseChild.setPosition(position.x, position.y);
|
||||||
|
|
||||||
// Convert the rest of the node properties...
|
// Convert the rest of the node properties...
|
||||||
@ -239,7 +256,9 @@ export default class FreemindImporter extends Importer {
|
|||||||
const iconId: string = freeIcon.getBuiltin();
|
const iconId: string = freeIcon.getBuiltin();
|
||||||
const wiseIconId = FreemindIconConverter.toWiseId(iconId);
|
const wiseIconId = FreemindIconConverter.toWiseId(iconId);
|
||||||
if (wiseIconId) {
|
if (wiseIconId) {
|
||||||
const mindmapIcon: FeatureModel = FeatureModelFactory.createModel('icon', { id: wiseIconId });
|
const mindmapIcon: FeatureModel = FeatureModelFactory.createModel('icon', {
|
||||||
|
id: wiseIconId,
|
||||||
|
});
|
||||||
currentWiseTopic.addFeature(mindmapIcon);
|
currentWiseTopic.addFeature(mindmapIcon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,7 +282,9 @@ export default class FreemindImporter extends Importer {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'NOTE': {
|
case 'NOTE': {
|
||||||
const noteModel: FeatureModel = FeatureModelFactory.createModel('note', { text: text || FreemindConstant.EMPTY_NOTE });
|
const noteModel: FeatureModel = FeatureModelFactory.createModel('note', {
|
||||||
|
text: text || FreemindConstant.EMPTY_NOTE,
|
||||||
|
});
|
||||||
currentWiseTopic.addFeature(noteModel);
|
currentWiseTopic.addFeature(noteModel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -274,7 +295,9 @@ export default class FreemindImporter extends Importer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
const noteModel: FeatureModel = FeatureModelFactory.createModel('note', { text: text || FreemindConstant.EMPTY_NOTE });
|
const noteModel: FeatureModel = FeatureModelFactory.createModel('note', {
|
||||||
|
text: text || FreemindConstant.EMPTY_NOTE,
|
||||||
|
});
|
||||||
currentWiseTopic.addFeature(noteModel);
|
currentWiseTopic.addFeature(noteModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -381,7 +404,10 @@ export default class FreemindImporter extends Importer {
|
|||||||
|
|
||||||
// Font Size
|
// Font Size
|
||||||
if (font) {
|
if (font) {
|
||||||
const fontSize: number = ((!font.getSize() || parseInt(font.getSize(), 10) < 8) ? FreemindConstant.FONT_SIZE_NORMAL : parseInt(font.getSize(), 10));
|
const fontSize: number =
|
||||||
|
!font.getSize() || parseInt(font.getSize(), 10) < 8
|
||||||
|
? FreemindConstant.FONT_SIZE_NORMAL
|
||||||
|
: 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;
|
||||||
@ -414,11 +440,19 @@ export default class FreemindImporter extends Importer {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private convertPosition(wiseParent: NodeModel, freeChild: FreemindNode, depth: number, order: number, childrenCount: number): {x: number, y: number} {
|
private convertPosition(
|
||||||
let x: number = FreemindConstant.CENTRAL_TO_TOPIC_DISTANCE + ((depth - 1) * FreemindConstant.TOPIC_TO_TOPIC_DISTANCE);
|
wiseParent: NodeModel,
|
||||||
|
freeChild: FreemindNode,
|
||||||
|
depth: number,
|
||||||
|
order: number,
|
||||||
|
childrenCount: number,
|
||||||
|
): { x: number; y: number } {
|
||||||
|
let x: number =
|
||||||
|
FreemindConstant.CENTRAL_TO_TOPIC_DISTANCE +
|
||||||
|
(depth - 1) * FreemindConstant.TOPIC_TO_TOPIC_DISTANCE;
|
||||||
if (depth === 1) {
|
if (depth === 1) {
|
||||||
const side: string = freeChild.getPosition();
|
const side: string = 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();
|
||||||
x *= position.x < 0 ? 1 : -1;
|
x *= position.x < 0 ? 1 : -1;
|
||||||
@ -427,7 +461,7 @@ export default class FreemindImporter extends Importer {
|
|||||||
let y: number;
|
let y: number;
|
||||||
if (depth === 1) {
|
if (depth === 1) {
|
||||||
if (order % 2 === 0) {
|
if (order % 2 === 0) {
|
||||||
const multiplier = ((order + 1) - childrenCount) * 2;
|
const multiplier = (order + 1 - childrenCount) * 2;
|
||||||
y = multiplier * FreemindConstant.ROOT_LEVEL_TOPIC_HEIGHT;
|
y = multiplier * FreemindConstant.ROOT_LEVEL_TOPIC_HEIGHT;
|
||||||
} else {
|
} else {
|
||||||
const multiplier = (order - childrenCount) * 2;
|
const multiplier = (order - childrenCount) * 2;
|
||||||
@ -435,7 +469,11 @@ export default class FreemindImporter extends Importer {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const position = wiseParent.getPosition();
|
const position = wiseParent.getPosition();
|
||||||
y = Math.round(position.y - ((childrenCount / 2) * FreemindConstant.SECOND_LEVEL_TOPIC_HEIGHT - (order * FreemindConstant.SECOND_LEVEL_TOPIC_HEIGHT)));
|
y = Math.round(
|
||||||
|
position.y -
|
||||||
|
((childrenCount / 2) * FreemindConstant.SECOND_LEVEL_TOPIC_HEIGHT -
|
||||||
|
order * FreemindConstant.SECOND_LEVEL_TOPIC_HEIGHT),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export default abstract class Importer {
|
export default abstract class Importer {
|
||||||
abstract import(nameMap: string, description: string): Promise<string>;
|
abstract import(nameMap: string, description: string): Promise<string>;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,15 @@
|
|||||||
*/
|
*/
|
||||||
import Events from '../Events';
|
import Events from '../Events';
|
||||||
|
|
||||||
export type EventType = 'topicResize' | 'topicMoved' | 'childShrinked' | 'topicConnected' | 'topicAdded' | 'topicRemoved' | 'forceLayout' | 'topicDisconect';
|
export type EventType =
|
||||||
|
| 'topicResize'
|
||||||
|
| 'topicMoved'
|
||||||
|
| 'childShrinked'
|
||||||
|
| 'topicConnected'
|
||||||
|
| 'topicAdded'
|
||||||
|
| 'topicRemoved'
|
||||||
|
| 'forceLayout'
|
||||||
|
| 'topicDisconect';
|
||||||
class EventBus extends Events {
|
class EventBus extends Events {
|
||||||
// eslint-disable-next-line no-use-before-define
|
// eslint-disable-next-line no-use-before-define
|
||||||
static _instance: EventBus = new EventBus();
|
static _instance: EventBus = new EventBus();
|
||||||
|
@ -43,11 +43,11 @@ class EventBusDispatcher {
|
|||||||
EventBus.instance.addEvent('forceLayout', this._forceLayout.bind(this));
|
EventBus.instance.addEvent('forceLayout', this._forceLayout.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,9 +55,11 @@ class EventBusDispatcher {
|
|||||||
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.childNode.getId(), args.childNode.getOrder(),
|
args.parentNode.getId(),
|
||||||
|
args.childNode.getId(),
|
||||||
|
args.childNode.getOrder(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,13 +64,13 @@ class LayoutManager extends Events {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id
|
* @param id
|
||||||
* @param position
|
* @param position
|
||||||
* @throws will throw an error if id is null or undefined
|
* @throws will throw an error if id is null or undefined
|
||||||
* @throws will throw an error if position is null or undefined
|
* @throws will throw an error if position is null or undefined
|
||||||
* @throws will throw an error if the position's x property is null or undefined
|
* @throws will throw an error if the position's x property is null or undefined
|
||||||
* @throws will throw an error if the position's y property is null or undefined
|
* @throws will throw an error if the position's y property is null or undefined
|
||||||
*/
|
*/
|
||||||
moveNode(id: number, position: PositionType) {
|
moveNode(id: number, position: PositionType) {
|
||||||
$assert($defined(id), 'id cannot be null');
|
$assert($defined(id), 'id cannot be null');
|
||||||
$assert($defined(position), 'position cannot be null');
|
$assert($defined(position), 'position cannot be null');
|
||||||
@ -97,12 +97,12 @@ class LayoutManager extends Events {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id
|
* @param id
|
||||||
* @param size
|
* @param size
|
||||||
* @param position
|
* @param position
|
||||||
* @throws will throw an error if id is null or undefined
|
* @throws will throw an error if id is null or undefined
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
addNode(id: number, size: SizeType, position: PositionType) {
|
addNode(id: number, size: SizeType, position: PositionType) {
|
||||||
$assert($defined(id), 'id can not be null');
|
$assert($defined(id), 'id can not be null');
|
||||||
const result = this._layout.createNode(id, size, position, 'topic');
|
const result = this._layout.createNode(id, size, position, 'topic');
|
||||||
@ -126,7 +126,11 @@ class LayoutManager extends Events {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
predict(parentId: number, nodeId: number, position: PositionType): { order: number, position: PositionType } {
|
predict(
|
||||||
|
parentId: number,
|
||||||
|
nodeId: number,
|
||||||
|
position: PositionType,
|
||||||
|
): { order: number; position: PositionType } {
|
||||||
$assert($defined(parentId), 'parentId can not be null');
|
$assert($defined(parentId), 'parentId can not be null');
|
||||||
|
|
||||||
const parent = this._treeSet.find(parentId);
|
const parent = this._treeSet.find(parentId);
|
||||||
@ -179,14 +183,14 @@ class LayoutManager extends Events {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _flushEvents() {
|
private _flushEvents() {
|
||||||
this._events.forEach(((event) => {
|
this._events.forEach((event) => {
|
||||||
this.fireEvent('change', event);
|
this.fireEvent('change', event);
|
||||||
}));
|
});
|
||||||
this._events = [];
|
this._events = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _collectChanges(nodes: Node[]) {
|
private _collectChanges(nodes: Node[]) {
|
||||||
nodes.forEach(((node) => {
|
nodes.forEach((node) => {
|
||||||
if (node.hasOrderChanged() || node.hasPositionChanged()) {
|
if (node.hasOrderChanged() || node.hasPositionChanged()) {
|
||||||
// Find or create a event ...
|
// Find or create a event ...
|
||||||
const id = node.getId();
|
const id = node.getId();
|
||||||
@ -205,7 +209,7 @@ class LayoutManager extends Events {
|
|||||||
this._events.push(event);
|
this._events.push(event);
|
||||||
}
|
}
|
||||||
this._collectChanges(this._treeSet.getChildren(node));
|
this._collectChanges(this._treeSet.getChildren(node));
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,10 +186,12 @@ class Node {
|
|||||||
// 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 (
|
||||||
currentPos == null
|
currentPos == null ||
|
||||||
|| Math.abs(currentPos.x - position.x) > 2
|
Math.abs(currentPos.x - position.x) > 2 ||
|
||||||
|| Math.abs(currentPos.y - position.y) > 2
|
Math.abs(currentPos.y - position.y) > 2
|
||||||
) this._setProperty('position', position);
|
) {
|
||||||
|
this._setProperty('position', position);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_setProperty(key: string, value) {
|
_setProperty(key: string, value) {
|
||||||
@ -228,16 +230,11 @@ class Node {
|
|||||||
|
|
||||||
/** @return {String} returns id, order, position, size and shrink information */
|
/** @return {String} returns id, order, position, size and shrink information */
|
||||||
toString() {
|
toString() {
|
||||||
return (
|
return `[id:${this.getId()}, order:${this.getOrder()}, position: {${this.getPosition().x},${
|
||||||
`[id:${this.getId()
|
this.getPosition().y
|
||||||
}, order:${this.getOrder()
|
}}, size: {${this.getSize().width},${
|
||||||
}, position: {${this.getPosition().x
|
this.getSize().height
|
||||||
},${this.getPosition().y
|
}}, shrink:${this.areChildrenShrunken()}]`;
|
||||||
}}, size: {${this.getSize().width
|
|
||||||
},${this.getSize().height
|
|
||||||
}}, shrink:${this.areChildrenShrunken()
|
|
||||||
}]`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,12 +62,12 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param parentId
|
* @param parentId
|
||||||
* @param childId
|
* @param childId
|
||||||
* @throws will throw an error if parentId is null or undefined
|
* @throws will throw an error if parentId is null or undefined
|
||||||
* @throws will throw an error if childId is null or undefined
|
* @throws will throw an error if childId is null or undefined
|
||||||
* @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(parentId), 'parent can not be null');
|
||||||
$assert($defined(childId), 'child can not be null');
|
$assert($defined(childId), 'child can not be null');
|
||||||
@ -85,10 +85,10 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nodeId
|
* @param nodeId
|
||||||
* @throws will throw an error if nodeId is null or undefined
|
* @throws will throw an error if nodeId is null or undefined
|
||||||
* @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');
|
$assert($defined(nodeId), 'nodeId can not be null');
|
||||||
const node = this.find(nodeId);
|
const node = this.find(nodeId);
|
||||||
@ -100,12 +100,12 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id
|
* @param id
|
||||||
* @param validate
|
* @param validate
|
||||||
* @throws will throw an error if id is null or undefined
|
* @throws will throw an error if id is null or undefined
|
||||||
* @throws will throw an error if node cannot be found
|
* @throws will throw an error if node cannot be found
|
||||||
* @return node
|
* @return node
|
||||||
*/
|
*/
|
||||||
find(id: number, validate = true): Node {
|
find(id: number, validate = true): Node {
|
||||||
$assert($defined(id), 'id can not be null');
|
$assert($defined(id), 'id can not be null');
|
||||||
|
|
||||||
@ -143,20 +143,20 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @throws will throw an error if nodeId is null or undefined
|
* @throws will throw an error if nodeId is null or undefined
|
||||||
* @return children
|
* @return children
|
||||||
*/
|
*/
|
||||||
getChildren(node: Node): Node[] {
|
getChildren(node: Node): Node[] {
|
||||||
$assert(node, 'node cannot be null');
|
$assert(node, 'node cannot be null');
|
||||||
return node._children;
|
return node._children;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @throws will throw an error if node is null or undefined
|
* @throws will throw an error if node is null or undefined
|
||||||
* @return root node or the provided node, if it has no parent
|
* @return root node or the provided node, if it has no parent
|
||||||
*/
|
*/
|
||||||
getRootNode(node: Node) {
|
getRootNode(node: Node) {
|
||||||
$assert(node, 'node cannot be null');
|
$assert(node, 'node cannot be null');
|
||||||
const parent = this.getParent(node);
|
const parent = this.getParent(node);
|
||||||
@ -168,9 +168,9 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @throws will throw an error if node is null or undefined
|
* @throws will throw an error if node is null or undefined
|
||||||
* @return {Array} ancestors */
|
* @return {Array} ancestors */
|
||||||
getAncestors(node: Node): Node[] {
|
getAncestors(node: Node): Node[] {
|
||||||
$assert(node, 'node cannot be null');
|
$assert(node, 'node cannot be null');
|
||||||
return this._getAncestors(this.getParent(node), []);
|
return this._getAncestors(this.getParent(node), []);
|
||||||
@ -186,10 +186,10 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @throws will throw an error if node is null or undefined
|
* @throws will throw an error if node is null or undefined
|
||||||
* @return {Array} siblings
|
* @return {Array} siblings
|
||||||
*/
|
*/
|
||||||
getSiblings(node: Node): Node[] {
|
getSiblings(node: Node): Node[] {
|
||||||
$assert(node, 'node cannot be null');
|
$assert(node, 'node cannot be null');
|
||||||
if (!$defined(node._parent)) {
|
if (!$defined(node._parent)) {
|
||||||
@ -200,10 +200,10 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @throws will throw an error if node is null or undefined
|
* @throws will throw an error if node is null or undefined
|
||||||
* @return {Boolean} whether the node has a single path to a single leaf (no branching)
|
* @return {Boolean} whether the node has a single path to a single leaf (no branching)
|
||||||
*/
|
*/
|
||||||
hasSinglePathToSingleLeaf(node: Node): boolean {
|
hasSinglePathToSingleLeaf(node: Node): boolean {
|
||||||
$assert(node, 'node cannot be null');
|
$assert(node, 'node cannot be null');
|
||||||
return this._hasSinglePathToSingleLeaf(node);
|
return this._hasSinglePathToSingleLeaf(node);
|
||||||
@ -220,27 +220,27 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @return {Boolean} whether the node is the start of a subbranch */
|
* @return {Boolean} whether the node is the start of a subbranch */
|
||||||
isStartOfSubBranch(node: Node): boolean {
|
isStartOfSubBranch(node: Node): boolean {
|
||||||
return this.getSiblings(node).length > 0 && this.getChildren(node).length === 1;
|
return this.getSiblings(node).length > 0 && this.getChildren(node).length === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @throws will throw an error if node is null or undefined
|
* @throws will throw an error if node is null or undefined
|
||||||
* @return {Boolean} whether the node is a leaf
|
* @return {Boolean} whether the node is a leaf
|
||||||
*/
|
*/
|
||||||
isLeaf(node: Node): boolean {
|
isLeaf(node: Node): boolean {
|
||||||
$assert(node, 'node cannot be null');
|
$assert(node, 'node cannot be null');
|
||||||
return this.getChildren(node).length === 0;
|
return this.getChildren(node).length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @throws will throw an error if node is null or undefined
|
* @throws will throw an error if node is null or undefined
|
||||||
* @return parent
|
* @return parent
|
||||||
*/
|
*/
|
||||||
getParent(node: Node): Node {
|
getParent(node: Node): Node {
|
||||||
$assert(node, 'node cannot be null');
|
$assert(node, 'node cannot be null');
|
||||||
return node._parent;
|
return node._parent;
|
||||||
@ -271,8 +271,8 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param canvas
|
* @param canvas
|
||||||
*/
|
*/
|
||||||
plot(canvas) {
|
plot(canvas) {
|
||||||
const branches = this._rootNodes;
|
const branches = this._rootNodes;
|
||||||
for (let i = 0; i < branches.length; i++) {
|
for (let i = 0; i < branches.length; i++) {
|
||||||
@ -297,9 +297,7 @@ class RootedTreeSet {
|
|||||||
if (this._rootNodes.includes(node)) {
|
if (this._rootNodes.includes(node)) {
|
||||||
fillColor = '#000';
|
fillColor = '#000';
|
||||||
} else {
|
} else {
|
||||||
fillColor = node.isFree()
|
fillColor = node.isFree() ? '#abc' : '#c00';
|
||||||
? '#abc'
|
|
||||||
: '#c00';
|
|
||||||
}
|
}
|
||||||
rect.attr('fill', fillColor);
|
rect.attr('fill', fillColor);
|
||||||
|
|
||||||
@ -310,28 +308,20 @@ class RootedTreeSet {
|
|||||||
const rectSize = { width: rect.attr('width'), height: rect.attr('height') };
|
const rectSize = { width: rect.attr('width'), height: rect.attr('height') };
|
||||||
rect.click(() => {
|
rect.click(() => {
|
||||||
console.log(
|
console.log(
|
||||||
`[id:${node.getId()
|
`[id:${node.getId()}, order:${node.getOrder()}, position:(${rectPosition.x}, ${
|
||||||
}, order:${node.getOrder()
|
rectPosition.y
|
||||||
}, position:(${rectPosition.x
|
}), size:${rectSize.width},${rectSize.height}, freeDisplacement:(${
|
||||||
}, ${rectPosition.y
|
node.getFreeDisplacement().x
|
||||||
}), size:${rectSize.width
|
},${node.getFreeDisplacement().y})]`,
|
||||||
},${rectSize.height
|
|
||||||
}, freeDisplacement:(${node.getFreeDisplacement().x
|
|
||||||
},${node.getFreeDisplacement().y
|
|
||||||
})]`,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
text.click(() => {
|
text.click(() => {
|
||||||
console.log(
|
console.log(
|
||||||
`[id:${node.getId()
|
`[id:${node.getId()}, order:${node.getOrder()}, position:(${rectPosition.x},${
|
||||||
}, order:${node.getOrder()
|
rectPosition.y
|
||||||
}, position:(${rectPosition.x
|
}), size:${rectSize.width}x${rectSize.height}, freeDisplacement:(${
|
||||||
},${rectPosition.y
|
node.getFreeDisplacement().x
|
||||||
}), size:${rectSize.width
|
},${node.getFreeDisplacement().y})]`,
|
||||||
}x${rectSize.height
|
|
||||||
}, freeDisplacement:(${node.getFreeDisplacement().x
|
|
||||||
},${node.getFreeDisplacement().y
|
|
||||||
})]`,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -342,9 +332,9 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @param position
|
* @param position
|
||||||
*/
|
*/
|
||||||
updateBranchPosition(node: Node, position: PositionType): void {
|
updateBranchPosition(node: Node, position: PositionType): void {
|
||||||
const oldPos = node.getPosition();
|
const oldPos = node.getPosition();
|
||||||
node.setPosition(position);
|
node.setPosition(position);
|
||||||
@ -360,10 +350,10 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @param xOffset
|
* @param xOffset
|
||||||
* @param yOffset
|
* @param yOffset
|
||||||
*/
|
*/
|
||||||
shiftBranchPosition(node: Node, xOffset: number, yOffset: number): void {
|
shiftBranchPosition(node: Node, xOffset: number, yOffset: number): void {
|
||||||
const position = node.getPosition();
|
const position = node.getPosition();
|
||||||
node.setPosition({ x: position.x + xOffset, y: position.y + yOffset });
|
node.setPosition({ x: position.x + xOffset, y: position.y + yOffset });
|
||||||
@ -376,21 +366,21 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @param yOffset
|
* @param yOffset
|
||||||
* @return siblings in the offset (vertical) direction, i.e. with lower or higher order
|
* @return siblings in the offset (vertical) direction, i.e. with lower or higher order
|
||||||
*/
|
*/
|
||||||
getSiblingsInVerticalDirection(node: Node, yOffset: number): Node[] {
|
getSiblingsInVerticalDirection(node: Node, yOffset: number): Node[] {
|
||||||
// siblings with lower or higher order
|
// siblings with lower or higher order
|
||||||
// (depending on the direction of the offset and on the same side as their parent)
|
// (depending on the direction of the offset and on the same side as their parent)
|
||||||
const parent = this.getParent(node);
|
const parent = this.getParent(node);
|
||||||
const siblings = this.getSiblings(node).filter((sibling) => {
|
const siblings = this.getSiblings(node).filter((sibling) => {
|
||||||
const sameSide = node.getPosition().x > parent.getPosition().x
|
const sameSide =
|
||||||
? sibling.getPosition().x > parent.getPosition().x
|
node.getPosition().x > parent.getPosition().x
|
||||||
: sibling.getPosition().x < parent.getPosition().x;
|
? sibling.getPosition().x > parent.getPosition().x
|
||||||
const orderOK = yOffset < 0
|
: sibling.getPosition().x < parent.getPosition().x;
|
||||||
? sibling.getOrder() < node.getOrder()
|
const orderOK =
|
||||||
: sibling.getOrder() > node.getOrder();
|
yOffset < 0 ? sibling.getOrder() < node.getOrder() : sibling.getOrder() > node.getOrder();
|
||||||
return orderOK && sameSide;
|
return orderOK && sameSide;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -402,26 +392,27 @@ class RootedTreeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param node
|
* @param node
|
||||||
* @param yOffset
|
* @param yOffset
|
||||||
* @return branches of the root node on the same side as the given node's, in the given
|
* @return branches of the root node on the same side as the given node's, in the given
|
||||||
* vertical direction
|
* vertical direction
|
||||||
*/
|
*/
|
||||||
getBranchesInVerticalDirection(node: Node, yOffset: number): Node[] {
|
getBranchesInVerticalDirection(node: Node, yOffset: number): Node[] {
|
||||||
// direct descendants of the root that do not contain the node and are on the same side
|
// direct descendants of the root that do not contain the node and are on the same side
|
||||||
// and on the direction of the offset
|
// and on the direction of the offset
|
||||||
const rootNode = this.getRootNode(node);
|
const rootNode = this.getRootNode(node);
|
||||||
const branches = this.getChildren(rootNode)
|
const branches = this.getChildren(rootNode).filter((child) => this._find(node.getId(), child));
|
||||||
.filter(((child) => this._find(node.getId(), child)));
|
|
||||||
|
|
||||||
const branch = branches[0];
|
const branch = branches[0];
|
||||||
const result = this.getSiblings(branch).filter((sibling) => {
|
const result = this.getSiblings(branch).filter((sibling) => {
|
||||||
const sameSide = node.getPosition().x > rootNode.getPosition().x
|
const sameSide =
|
||||||
? sibling.getPosition().x > rootNode.getPosition().x
|
node.getPosition().x > rootNode.getPosition().x
|
||||||
: sibling.getPosition().x < rootNode.getPosition().x;
|
? sibling.getPosition().x > rootNode.getPosition().x
|
||||||
const sameDirection = yOffset < 0
|
: sibling.getPosition().x < rootNode.getPosition().x;
|
||||||
? sibling.getOrder() < branch.getOrder()
|
const sameDirection =
|
||||||
: sibling.getOrder() > branch.getOrder();
|
yOffset < 0
|
||||||
|
? sibling.getOrder() < branch.getOrder()
|
||||||
|
: sibling.getOrder() > branch.getOrder();
|
||||||
return sameSide && sameDirection;
|
return sameSide && sameDirection;
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
@ -28,11 +28,11 @@ class FeatureModel {
|
|||||||
private _attributes;
|
private _attributes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructs
|
* @constructs
|
||||||
* @param type
|
* @param type
|
||||||
* @throws will throw an exception if type is null or undefined
|
* @throws will throw an exception if type is null or undefined
|
||||||
* assigns a unique id and the given type to the new model
|
* assigns a unique id and the given type to the new model
|
||||||
*/
|
*/
|
||||||
constructor(type: FeatureType) {
|
constructor(type: FeatureType) {
|
||||||
$assert(type, 'type can not be null');
|
$assert(type, 'type can not be null');
|
||||||
this._id = FeatureModel._nextUUID();
|
this._id = FeatureModel._nextUUID();
|
||||||
|
@ -6,35 +6,38 @@ import FeatureModel from './FeatureModel';
|
|||||||
import FeatureType from './FeatureType';
|
import FeatureType from './FeatureType';
|
||||||
|
|
||||||
interface NodeById {
|
interface NodeById {
|
||||||
id: FeatureType,
|
id: FeatureType;
|
||||||
model: typeof FeatureModel;
|
model: typeof FeatureModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FeatureModelFactory {
|
class FeatureModelFactory {
|
||||||
static modelById: Array<NodeById> = [{
|
static modelById: Array<NodeById> = [
|
||||||
id: 'icon',
|
{
|
||||||
model: IconModel,
|
id: 'icon',
|
||||||
}, {
|
model: IconModel,
|
||||||
id: 'link',
|
},
|
||||||
model: LinkModel,
|
{
|
||||||
}, {
|
id: 'link',
|
||||||
id: 'note',
|
model: LinkModel,
|
||||||
model: NoteModel,
|
},
|
||||||
}];
|
{
|
||||||
|
id: 'note',
|
||||||
|
model: NoteModel,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
static createModel(type: FeatureType, attributes): FeatureModel {
|
static createModel(type: FeatureType, attributes): FeatureModel {
|
||||||
$assert(type, 'type can not be null');
|
$assert(type, 'type can not be null');
|
||||||
$assert(attributes, 'attributes can not be null');
|
$assert(attributes, 'attributes can not be null');
|
||||||
|
|
||||||
const { model: Model } = FeatureModelFactory.modelById
|
const { model: Model } = FeatureModelFactory.modelById.filter((elem) => elem.id === type)[0];
|
||||||
.filter((elem) => elem.id === type)[0];
|
|
||||||
return new Model(attributes);
|
return new Model(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id the feature metadata id
|
* @param id the feature metadata id
|
||||||
* @return {Boolean} returns true if the given id is contained in the metadata array
|
* @return {Boolean} returns true if the given id is contained in the metadata array
|
||||||
*/
|
*/
|
||||||
static isSupported(type: string): boolean {
|
static isSupported(type: string): boolean {
|
||||||
return FeatureModelFactory.modelById.some((elem) => elem.id === type);
|
return FeatureModelFactory.modelById.some((elem) => elem.id === type);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ abstract class IMindmap {
|
|||||||
|
|
||||||
abstract setDescription(value: string): void;
|
abstract setDescription(value: string): void;
|
||||||
|
|
||||||
abstract getId(): string
|
abstract getId(): string;
|
||||||
|
|
||||||
abstract setId(id: string): void;
|
abstract setId(id: string): void;
|
||||||
|
|
||||||
@ -58,10 +58,10 @@ abstract class IMindmap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param child
|
* @param child
|
||||||
* @throws will throw an error if child is null or undefined
|
* @throws will throw an error if child is null or undefined
|
||||||
* @throws will throw an error if child's parent cannot be found
|
* @throws will throw an error if child's parent cannot be found
|
||||||
*/
|
*/
|
||||||
disconnect(child: INodeModel): void {
|
disconnect(child: INodeModel): void {
|
||||||
const parent = child.getParent();
|
const parent = child.getParent();
|
||||||
$assert(child, 'Child can not be null.');
|
$assert(child, 'Child can not be null.');
|
||||||
@ -73,7 +73,7 @@ abstract class IMindmap {
|
|||||||
|
|
||||||
abstract hasAlreadyAdded(node): boolean;
|
abstract hasAlreadyAdded(node): boolean;
|
||||||
|
|
||||||
abstract createNode(type: NodeType, id: number)
|
abstract createNode(type: NodeType, id: number);
|
||||||
|
|
||||||
abstract createRelationship(fromNodeId: number, toNodeId: number): void;
|
abstract createRelationship(fromNodeId: number, toNodeId: number): void;
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ abstract class IMindmap {
|
|||||||
|
|
||||||
abstract deleteRelationship(relationship: RelationshipModel): void;
|
abstract deleteRelationship(relationship: RelationshipModel): void;
|
||||||
|
|
||||||
inspect():string {
|
inspect(): string {
|
||||||
let result = '';
|
let result = '';
|
||||||
result = '{ ';
|
result = '{ ';
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ abstract class IMindmap {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
copyTo(target:IMindmap) {
|
copyTo(target: IMindmap) {
|
||||||
const version = this.getVersion();
|
const version = this.getVersion();
|
||||||
target.setVersion(version);
|
target.setVersion(version);
|
||||||
|
|
||||||
|
@ -24,7 +24,8 @@ import Mindmap from './Mindmap';
|
|||||||
export type NodeModelType = 'CentralTopic' | 'MainTopic';
|
export type NodeModelType = 'CentralTopic' | 'MainTopic';
|
||||||
|
|
||||||
// regex taken from https://stackoverflow.com/a/34763398/58128
|
// regex taken from https://stackoverflow.com/a/34763398/58128
|
||||||
const parseJsObject = (str: string) => JSON.parse(str.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": '));
|
const parseJsObject = (str: string) =>
|
||||||
|
JSON.parse(str.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": '));
|
||||||
|
|
||||||
abstract class INodeModel {
|
abstract class INodeModel {
|
||||||
static MAIN_TOPIC_TO_MAIN_TOPIC_DISTANCE = 220;
|
static MAIN_TOPIC_TO_MAIN_TOPIC_DISTANCE = 220;
|
||||||
@ -90,7 +91,7 @@ abstract class INodeModel {
|
|||||||
this.putProperty('imageSize', `{width:${width},height:${height}}`);
|
this.putProperty('imageSize', `{width:${width},height:${height}}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getImageSize(): { width: number, height: number } {
|
getImageSize(): { width: number; height: number } {
|
||||||
const value = this.getProperty('imageSize') as string;
|
const value = this.getProperty('imageSize') as string;
|
||||||
let result;
|
let result;
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@ -120,9 +121,9 @@ abstract class INodeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lets the mindmap handle the disconnect node operation
|
* lets the mindmap handle the disconnect node operation
|
||||||
* @see mindplot.model.IMindmap.disconnect
|
* @see mindplot.model.IMindmap.disconnect
|
||||||
*/
|
*/
|
||||||
disconnect(): void {
|
disconnect(): void {
|
||||||
const mindmap = this.getMindmap();
|
const mindmap = this.getMindmap();
|
||||||
mindmap.disconnect(this);
|
mindmap.disconnect(this);
|
||||||
@ -233,10 +234,10 @@ abstract class INodeModel {
|
|||||||
abstract append(node): void;
|
abstract append(node): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lets the mindmap handle the connect node operation
|
* lets the mindmap handle the connect node operation
|
||||||
* @throws will throw an error if parent is null or undefined
|
* @throws will throw an error if parent is null or undefined
|
||||||
* @see mindplot.model.IMindmap.connect
|
* @see mindplot.model.IMindmap.connect
|
||||||
*/
|
*/
|
||||||
connectTo(parent: INodeModel) {
|
connectTo(parent: INodeModel) {
|
||||||
$assert(parent, 'parent can not be null');
|
$assert(parent, 'parent can not be null');
|
||||||
const mindmap = this.getMindmap();
|
const mindmap = this.getMindmap();
|
||||||
@ -244,9 +245,9 @@ abstract class INodeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param target
|
* @param target
|
||||||
* @return target
|
* @return target
|
||||||
*/
|
*/
|
||||||
copyTo(target: INodeModel): INodeModel {
|
copyTo(target: INodeModel): INodeModel {
|
||||||
const source = this;
|
const source = this;
|
||||||
// Copy properties ...
|
// Copy properties ...
|
||||||
@ -270,9 +271,9 @@ abstract class INodeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lets parent handle the delete node operation, or, if none defined, calls the mindmap to
|
* lets parent handle the delete node operation, or, if none defined, calls the mindmap to
|
||||||
* remove the respective branch
|
* remove the respective branch
|
||||||
*/
|
*/
|
||||||
deleteNode(): void {
|
deleteNode(): void {
|
||||||
const mindmap = this.getMindmap();
|
const mindmap = this.getMindmap();
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class IconModel extends FeatureModel {
|
|||||||
return this.getAttribute('id') as string;
|
return this.getAttribute('id') as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIconType(iconType: string):void {
|
setIconType(iconType: string): void {
|
||||||
$assert(iconType, 'iconType id can not be null');
|
$assert(iconType, 'iconType id can not be null');
|
||||||
this.setAttribute('id', iconType);
|
this.setAttribute('id', iconType);
|
||||||
}
|
}
|
||||||
|
@ -41,16 +41,20 @@ class LinkModel extends FeatureModel {
|
|||||||
// url format is already checked in LinkEditor.checkUrl
|
// url format is already checked in LinkEditor.checkUrl
|
||||||
static _fixUrl(url: string): string {
|
static _fixUrl(url: string): string {
|
||||||
let result = url;
|
let result = url;
|
||||||
if (!result.includes('http://') && !result.includes('https://') && !result.includes('mailto://')) {
|
if (
|
||||||
|
!result.includes('http://') &&
|
||||||
|
!result.includes('https://') &&
|
||||||
|
!result.includes('mailto://')
|
||||||
|
) {
|
||||||
result = `http://${result}`;
|
result = `http://${result}`;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} urlType the url type, either 'mail' or 'url'
|
* @param {String} urlType the url type, either 'mail' or 'url'
|
||||||
* @throws will throw an error if urlType is null or undefined
|
* @throws will throw an error if urlType is null or undefined
|
||||||
*/
|
*/
|
||||||
setUrlType(urlType) {
|
setUrlType(urlType) {
|
||||||
$assert(urlType, 'urlType can not be null');
|
$assert(urlType, 'urlType can not be null');
|
||||||
this.setAttribute('urlType', urlType);
|
this.setAttribute('urlType', urlType);
|
||||||
|
@ -75,10 +75,10 @@ class Mindmap extends IMindmap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {mindplot.model.NodeModel} nodeModel
|
* @param {mindplot.model.NodeModel} nodeModel
|
||||||
* @throws will throw an error if nodeModel is null, undefined or not a node model object
|
* @throws will throw an error if nodeModel is null, undefined or not a node model object
|
||||||
* @throws will throw an error if
|
* @throws will throw an error if
|
||||||
*/
|
*/
|
||||||
addBranch(nodeModel: INodeModel): void {
|
addBranch(nodeModel: INodeModel): void {
|
||||||
$assert(nodeModel && nodeModel.isNodeModel(), 'Add node must be invoked with model objects');
|
$assert(nodeModel && nodeModel.isNodeModel(), 'Add node must be invoked with model objects');
|
||||||
const branches = this.getBranches();
|
const branches = this.getBranches();
|
||||||
@ -93,14 +93,14 @@ class Mindmap extends IMindmap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nodeModel
|
* @param nodeModel
|
||||||
*/
|
*/
|
||||||
removeBranch(nodeModel: INodeModel): void {
|
removeBranch(nodeModel: INodeModel): void {
|
||||||
$assert(nodeModel && nodeModel.isNodeModel(), 'Remove node must be invoked with model objects');
|
$assert(nodeModel && nodeModel.isNodeModel(), 'Remove node must be invoked with model objects');
|
||||||
this._branches = this._branches.filter((b) => b !== nodeModel);
|
this._branches = this._branches.filter((b) => b !== nodeModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
getBranches():NodeModel[] {
|
getBranches(): NodeModel[] {
|
||||||
return this._branches;
|
return this._branches;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ class Mindmap extends IMindmap {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
createNode(type: NodeModelType = 'MainTopic', id?: number):NodeModel {
|
createNode(type: NodeModelType = 'MainTopic', id?: number): NodeModel {
|
||||||
return new NodeModel(type, this, id);
|
return new NodeModel(type, this, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,8 +141,8 @@ class Mindmap extends IMindmap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param relationship
|
* @param relationship
|
||||||
*/
|
*/
|
||||||
deleteRelationship(relationship: RelationshipModel) {
|
deleteRelationship(relationship: RelationshipModel) {
|
||||||
this._relationships = this._relationships.filter((r) => r !== relationship);
|
this._relationships = this._relationships.filter((r) => r !== relationship);
|
||||||
}
|
}
|
||||||
|
@ -49,18 +49,18 @@ class NodeModel extends INodeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param type
|
* @param type
|
||||||
* @param attributes
|
* @param attributes
|
||||||
* @return {mindplot.model.FeatureModel} the created feature model
|
* @return {mindplot.model.FeatureModel} the created feature model
|
||||||
*/
|
*/
|
||||||
createFeature(type: FeatureType, attributes): FeatureModel {
|
createFeature(type: FeatureType, attributes): FeatureModel {
|
||||||
return FeatureModelFactory.createModel(type, attributes);
|
return FeatureModelFactory.createModel(type, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param feature
|
* @param feature
|
||||||
* @throws will throw an error if feature is null or undefined
|
* @throws will throw an error if feature is null or undefined
|
||||||
*/
|
*/
|
||||||
addFeature(feature: FeatureModel) {
|
addFeature(feature: FeatureModel) {
|
||||||
$assert(feature, 'feature can not be null');
|
$assert(feature, 'feature can not be null');
|
||||||
this._features.push(feature);
|
this._features.push(feature);
|
||||||
@ -78,20 +78,20 @@ class NodeModel extends INodeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} type the feature type, e.g. icon or link
|
* @param {String} type the feature type, e.g. icon or link
|
||||||
* @throws will throw an error if type is null or undefined
|
* @throws will throw an error if type is null or undefined
|
||||||
*/
|
*/
|
||||||
findFeatureByType(type: string): FeatureModel[] {
|
findFeatureByType(type: string): FeatureModel[] {
|
||||||
$assert(type, 'type can not be null');
|
$assert(type, 'type can not be null');
|
||||||
return this._features.filter((feature) => feature.getType() === type);
|
return this._features.filter((feature) => feature.getType() === type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} id
|
* @param {String} id
|
||||||
* @throws will throw an error if id is null or undefined
|
* @throws will throw an error if id is null or undefined
|
||||||
* @throws will throw an error if feature could not be found
|
* @throws will throw an error if feature could not be found
|
||||||
* @return the feature with the given id
|
* @return the feature with the given id
|
||||||
*/
|
*/
|
||||||
findFeatureById(id: number): FeatureModel {
|
findFeatureById(id: number): FeatureModel {
|
||||||
$assert($defined(id), 'id can not be null');
|
$assert($defined(id), 'id can not be null');
|
||||||
const result = this._features.filter((feature) => feature.getId() === id);
|
const result = this._features.filter((feature) => feature.getId() === id);
|
||||||
@ -104,10 +104,10 @@ class NodeModel extends INodeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param key
|
* @param key
|
||||||
* @param value
|
* @param value
|
||||||
* @throws will throw an error if key is null or undefined
|
* @throws will throw an error if key is null or undefined
|
||||||
*/
|
*/
|
||||||
putProperty(key: string, value: string | number | boolean) {
|
putProperty(key: string, value: string | number | boolean) {
|
||||||
$defined(key, 'key can not be null');
|
$defined(key, 'key can not be null');
|
||||||
this._properties[key] = value;
|
this._properties[key] = value;
|
||||||
|
@ -108,8 +108,8 @@ class RelationshipModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a clone of the relationship model
|
* @return a clone of the relationship model
|
||||||
*/
|
*/
|
||||||
clone() {
|
clone() {
|
||||||
const result = new RelationshipModel(this._sourceTargetId, this._targetTopicId);
|
const result = new RelationshipModel(this._sourceTargetId, this._targetTopicId);
|
||||||
result._id = this._id;
|
result._id = this._id;
|
||||||
@ -122,14 +122,10 @@ class RelationshipModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {String} textual information about the relationship's source and target node
|
* @return {String} textual information about the relationship's source and target node
|
||||||
*/
|
*/
|
||||||
inspect(): string {
|
inspect(): string {
|
||||||
return (
|
return `(fromNode:${this.getFromNode()} , toNode: ${this.getToNode()})`;
|
||||||
`(fromNode:${this.getFromNode()
|
|
||||||
} , toNode: ${this.getToNode()
|
|
||||||
})`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static _nextUUID() {
|
static _nextUUID() {
|
||||||
|
@ -83,7 +83,7 @@ class Pela2TangoMigrator implements XMLMindmapSerializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _fixNodePosition(node: NodeModel, parentPosition: { x: number, y: number }): void {
|
private _fixNodePosition(node: NodeModel, parentPosition: { x: number; y: number }): void {
|
||||||
// Position was not required in previous versions. Try to synthesize one .
|
// Position was not required in previous versions. Try to synthesize one .
|
||||||
let position = node.getPosition();
|
let position = node.getPosition();
|
||||||
if (!position) {
|
if (!position) {
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
import Mindmap from '../model/Mindmap';
|
import Mindmap from '../model/Mindmap';
|
||||||
|
|
||||||
interface XMLMindmapSerializer {
|
interface XMLMindmapSerializer {
|
||||||
toXML(mindmap: Mindmap): Document;
|
toXML(mindmap: Mindmap): Document;
|
||||||
loadFromDom(dom: Document, mapId: string): Mindmap;
|
loadFromDom(dom: Document, mapId: string): Mindmap;
|
||||||
}
|
}
|
||||||
export default XMLMindmapSerializer;
|
export default XMLMindmapSerializer;
|
||||||
|
@ -14,9 +14,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 {
|
import { $defined, $assert, createDocument } from '@wisemapping/core-js';
|
||||||
$defined, $assert, createDocument,
|
|
||||||
} from '@wisemapping/core-js';
|
|
||||||
import ModelCodeName from './ModelCodeName';
|
import ModelCodeName from './ModelCodeName';
|
||||||
import Mindmap from '../model/Mindmap';
|
import Mindmap from '../model/Mindmap';
|
||||||
import FeatureModelFactory from '../model/FeatureModelFactory';
|
import FeatureModelFactory from '../model/FeatureModelFactory';
|
||||||
@ -99,11 +97,11 @@ class XMLSerializerBeta implements XMLMindmapSerializer {
|
|||||||
font += `${fontStyle || ''};`;
|
font += `${fontStyle || ''};`;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
$defined(fontFamily)
|
$defined(fontFamily) ||
|
||||||
|| $defined(fontSize)
|
$defined(fontSize) ||
|
||||||
|| $defined(fontColor)
|
$defined(fontColor) ||
|
||||||
|| $defined(fontWeight)
|
$defined(fontWeight) ||
|
||||||
|| $defined(fontStyle)
|
$defined(fontStyle)
|
||||||
) {
|
) {
|
||||||
parentTopic.setAttribute('fontStyle', font);
|
parentTopic.setAttribute('fontStyle', font);
|
||||||
}
|
}
|
||||||
@ -180,7 +178,8 @@ class XMLSerializerBeta implements XMLMindmapSerializer {
|
|||||||
// Is a wisemap?.
|
// Is a wisemap?.
|
||||||
$assert(
|
$assert(
|
||||||
documentElement.tagName === XMLSerializerBeta.MAP_ROOT_NODE,
|
documentElement.tagName === XMLSerializerBeta.MAP_ROOT_NODE,
|
||||||
`This seem not to be a map document. Root Tag: '${documentElement.tagName}',HTML:${dom.innerHTML
|
`This seem not to be a map document. Root Tag: '${documentElement.tagName}',HTML:${
|
||||||
|
dom.innerHTML
|
||||||
}, XML:,${new XMLSerializer().serializeToString(dom)}`,
|
}, XML:,${new XMLSerializer().serializeToString(dom)}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -202,9 +201,7 @@ class XMLSerializerBeta implements XMLMindmapSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_deserializeNode(domElem, mindmap) {
|
_deserializeNode(domElem, mindmap) {
|
||||||
const type = domElem.getAttribute('central') != null
|
const type = domElem.getAttribute('central') != null ? 'CentralTopic' : 'MainTopic';
|
||||||
? 'CentralTopic'
|
|
||||||
: 'MainTopic';
|
|
||||||
const topic = mindmap.createNode(type);
|
const topic = mindmap.createNode(type);
|
||||||
|
|
||||||
// Load attributes...
|
// Load attributes...
|
||||||
@ -275,10 +272,10 @@ class XMLSerializerBeta implements XMLMindmapSerializer {
|
|||||||
const child = children[i];
|
const child = children[i];
|
||||||
if (child.nodeType === 1) {
|
if (child.nodeType === 1) {
|
||||||
$assert(
|
$assert(
|
||||||
child.tagName === 'topic'
|
child.tagName === 'topic' ||
|
||||||
|| child.tagName === 'icon'
|
child.tagName === 'icon' ||
|
||||||
|| child.tagName === 'link'
|
child.tagName === 'link' ||
|
||||||
|| child.tagName === 'note',
|
child.tagName === 'note',
|
||||||
`Illegal node type:${child.tagName}`,
|
`Illegal node type:${child.tagName}`,
|
||||||
);
|
);
|
||||||
if (child.tagName === 'topic') {
|
if (child.tagName === 'topic') {
|
||||||
|
@ -24,7 +24,7 @@ import XMLSerializerTango from './XMLSerializerTango';
|
|||||||
import Mindmap from '../model/Mindmap';
|
import Mindmap from '../model/Mindmap';
|
||||||
import XMLMindmapSerializer from './XMLMindmapSerializer';
|
import XMLMindmapSerializer from './XMLMindmapSerializer';
|
||||||
|
|
||||||
const codeToSerializer: { codeName: string, serializer, migrator }[] = [
|
const codeToSerializer: { codeName: string; serializer; migrator }[] = [
|
||||||
{
|
{
|
||||||
codeName: ModelCodeName.BETA,
|
codeName: ModelCodeName.BETA,
|
||||||
serializer: XMLSerializerBeta,
|
serializer: XMLSerializerBeta,
|
||||||
@ -51,8 +51,7 @@ class XMLSerializerFactory {
|
|||||||
* mindplot.persistence.XMLSerializer_Tango} serializer corresponding to the mindmap's version
|
* mindplot.persistence.XMLSerializer_Tango} serializer corresponding to the mindmap's version
|
||||||
*/
|
*/
|
||||||
static createInstanceFromMindmap(mindmap: Mindmap) {
|
static createInstanceFromMindmap(mindmap: Mindmap) {
|
||||||
return XMLSerializerFactory
|
return XMLSerializerFactory.getSerializer(mindmap.getVersion());
|
||||||
.getSerializer(mindmap.getVersion());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,7 +82,7 @@ class XMLSerializerFactory {
|
|||||||
if (!found) {
|
if (!found) {
|
||||||
found = codeToSerializer[i].codeName === version;
|
found = codeToSerializer[i].codeName === version;
|
||||||
// eslint-disable-next-line new-cap
|
// eslint-disable-next-line new-cap
|
||||||
if (found) result = new (codeToSerializer[i].serializer)();
|
if (found) result = new codeToSerializer[i].serializer();
|
||||||
} else {
|
} else {
|
||||||
const { migrator } = codeToSerializer[i];
|
const { migrator } = codeToSerializer[i];
|
||||||
// eslint-disable-next-line new-cap
|
// eslint-disable-next-line new-cap
|
||||||
|
@ -60,8 +60,8 @@ class XMLSerializerTango implements XMLMindmapSerializer {
|
|||||||
const relationships = mindmap.getRelationships();
|
const relationships = mindmap.getRelationships();
|
||||||
relationships.forEach((relationship) => {
|
relationships.forEach((relationship) => {
|
||||||
if (
|
if (
|
||||||
mindmap.findNodeById(relationship.getFromNode()) !== null
|
mindmap.findNodeById(relationship.getFromNode()) !== null &&
|
||||||
&& mindmap.findNodeById(relationship.getToNode()) !== null
|
mindmap.findNodeById(relationship.getToNode()) !== null
|
||||||
) {
|
) {
|
||||||
// Isolated relationships are not persisted ....
|
// Isolated relationships are not persisted ....
|
||||||
const relationDom = XMLSerializerTango._relationshipToXML(document, relationship);
|
const relationDom = XMLSerializerTango._relationshipToXML(document, relationship);
|
||||||
@ -99,14 +99,15 @@ class XMLSerializerTango implements XMLMindmapSerializer {
|
|||||||
|
|
||||||
if (shape === TopicShape.IMAGE) {
|
if (shape === TopicShape.IMAGE) {
|
||||||
const size = topic.getImageSize();
|
const size = topic.getImageSize();
|
||||||
parentTopic.setAttribute(
|
parentTopic.setAttribute('image', `${size.width},${size.height}:${topic.getImageUrl()}`);
|
||||||
'image',
|
|
||||||
`${size.width},${size.height}:${topic.getImageUrl()}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((topic.areChildrenShrunken() && topic.getChildren().length > 0) && topic.getType() !== 'CentralTopic') {
|
if (
|
||||||
|
topic.areChildrenShrunken() &&
|
||||||
|
topic.getChildren().length > 0 &&
|
||||||
|
topic.getType() !== 'CentralTopic'
|
||||||
|
) {
|
||||||
parentTopic.setAttribute('shrink', 'true');
|
parentTopic.setAttribute('shrink', 'true');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,11 +133,11 @@ class XMLSerializerTango implements XMLMindmapSerializer {
|
|||||||
font += `${fontStyle || ''};`;
|
font += `${fontStyle || ''};`;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
$defined(fontFamily)
|
$defined(fontFamily) ||
|
||||||
|| $defined(fontSize)
|
$defined(fontSize) ||
|
||||||
|| $defined(fontColor)
|
$defined(fontColor) ||
|
||||||
|| $defined(fontWeight)
|
$defined(fontWeight) ||
|
||||||
|| $defined(fontStyle)
|
$defined(fontStyle)
|
||||||
) {
|
) {
|
||||||
parentTopic.setAttribute('fontStyle', font);
|
parentTopic.setAttribute('fontStyle', font);
|
||||||
}
|
}
|
||||||
@ -208,10 +209,7 @@ class XMLSerializerTango implements XMLMindmapSerializer {
|
|||||||
if (lineType === ConnectionLine.CURVED || lineType === ConnectionLine.SIMPLE_CURVED) {
|
if (lineType === ConnectionLine.CURVED || lineType === ConnectionLine.SIMPLE_CURVED) {
|
||||||
if ($defined(relationship.getSrcCtrlPoint())) {
|
if ($defined(relationship.getSrcCtrlPoint())) {
|
||||||
const srcPoint = relationship.getSrcCtrlPoint();
|
const srcPoint = relationship.getSrcCtrlPoint();
|
||||||
result.setAttribute(
|
result.setAttribute('srcCtrlPoint', `${Math.round(srcPoint.x)},${Math.round(srcPoint.y)}`);
|
||||||
'srcCtrlPoint',
|
|
||||||
`${Math.round(srcPoint.x)},${Math.round(srcPoint.y)}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if ($defined(relationship.getDestCtrlPoint())) {
|
if ($defined(relationship.getDestCtrlPoint())) {
|
||||||
const destPoint = relationship.getDestCtrlPoint();
|
const destPoint = relationship.getDestCtrlPoint();
|
||||||
@ -246,9 +244,7 @@ class XMLSerializerTango implements XMLMindmapSerializer {
|
|||||||
// Add all the topics nodes ...
|
// Add all the topics nodes ...
|
||||||
const childNodes = Array.from(rootElem.childNodes);
|
const childNodes = Array.from(rootElem.childNodes);
|
||||||
const topicsNodes = childNodes
|
const topicsNodes = childNodes
|
||||||
.filter(
|
.filter((child: ChildNode) => child.nodeType === 1 && (child as Element).tagName === 'topic')
|
||||||
(child: ChildNode) => child.nodeType === 1 && (child as Element).tagName === 'topic',
|
|
||||||
)
|
|
||||||
.map((c) => c as Element);
|
.map((c) => c as Element);
|
||||||
topicsNodes.forEach((child) => {
|
topicsNodes.forEach((child) => {
|
||||||
const topic = this._deserializeNode(child, mindmap);
|
const topic = this._deserializeNode(child, mindmap);
|
||||||
@ -488,16 +484,16 @@ class XMLSerializerTango implements XMLMindmapSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method ensures that the output String has only
|
* This method ensures that the output String has only
|
||||||
* valid XML unicode characters as specified by the
|
* valid XML unicode characters as specified by the
|
||||||
* XML 1.0 standard. For reference, please see
|
* XML 1.0 standard. For reference, please see
|
||||||
* <a href="http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char">the
|
* <a href="http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char">the
|
||||||
* standard</a>. This method will return an empty
|
* standard</a>. This method will return an empty
|
||||||
* String if the input is null or empty.
|
* String if the input is null or empty.
|
||||||
*
|
*
|
||||||
* @param in The String whose non-valid characters we want to remove.
|
* @param in The String whose non-valid characters we want to remove.
|
||||||
* @return The in String, stripped of non-valid characters.
|
* @return The in String, stripped of non-valid characters.
|
||||||
*/
|
*/
|
||||||
protected _rmXmlInv(str: string) {
|
protected _rmXmlInv(str: string) {
|
||||||
if (str == null || str === undefined) return null;
|
if (str == null || str === undefined) return null;
|
||||||
|
|
||||||
@ -505,12 +501,12 @@ class XMLSerializerTango implements XMLMindmapSerializer {
|
|||||||
for (let i = 0; i < str.length; i++) {
|
for (let i = 0; i < str.length; i++) {
|
||||||
const c = str.charCodeAt(i);
|
const c = str.charCodeAt(i);
|
||||||
if (
|
if (
|
||||||
c === 0x9
|
c === 0x9 ||
|
||||||
|| c === 0xa
|
c === 0xa ||
|
||||||
|| c === 0xd
|
c === 0xd ||
|
||||||
|| (c >= 0x20 && c <= 0xd7ff)
|
(c >= 0x20 && c <= 0xd7ff) ||
|
||||||
|| (c >= 0xe000 && c <= 0xfffd)
|
(c >= 0xe000 && c <= 0xfffd) ||
|
||||||
|| (c >= 0x10000 && c <= 0x10ffff)
|
(c >= 0x10000 && c <= 0x10ffff)
|
||||||
) {
|
) {
|
||||||
result += str.charAt(i);
|
result += str.charAt(i);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ class FloatingTip extends Events {
|
|||||||
|
|
||||||
if (this.addEvent) {
|
if (this.addEvent) {
|
||||||
Object.keys(options).forEach((option) => {
|
Object.keys(options).forEach((option) => {
|
||||||
if (options[option] instanceof Function && (/^on[A-Z]/).test(option)) {
|
if (options[option] instanceof Function && /^on[A-Z]/.test(option)) {
|
||||||
this.addEvent(option, options[option]);
|
this.addEvent(option, options[option]);
|
||||||
delete options[option];
|
delete options[option];
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,10 @@ export const parseXMLString = (xmlStr: string, mimeType: DOMParserSupportedType)
|
|||||||
return xmlDoc;
|
return xmlDoc;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const parseXMLFile = (filePath: fs.PathOrFileDescriptor, mimeType: DOMParserSupportedType) => {
|
export const parseXMLFile = (
|
||||||
|
filePath: fs.PathOrFileDescriptor,
|
||||||
|
mimeType: DOMParserSupportedType,
|
||||||
|
) => {
|
||||||
const stream = fs.readFileSync(filePath, { encoding: 'utf-8' });
|
const stream = fs.readFileSync(filePath, { encoding: 'utf-8' });
|
||||||
|
|
||||||
let content = stream.toString();
|
let content = stream.toString();
|
||||||
|
@ -7,9 +7,12 @@ import { parseXMLFile, setupBlob, exporterAssert } from './Helper';
|
|||||||
setupBlob();
|
setupBlob();
|
||||||
|
|
||||||
describe('SVG export test execution', () => {
|
describe('SVG export test execution', () => {
|
||||||
test.each(fs.readdirSync(path.resolve(__dirname, './input/'))
|
test.each(
|
||||||
.filter((f) => f.endsWith('.wxml'))
|
fs
|
||||||
.map((filename: string) => filename.split('.')[0]))('Exporting %p suite', async (testName: string) => {
|
.readdirSync(path.resolve(__dirname, './input/'))
|
||||||
|
.filter((f) => f.endsWith('.wxml'))
|
||||||
|
.map((filename: string) => filename.split('.')[0]),
|
||||||
|
)('Exporting %p suite', async (testName: string) => {
|
||||||
// Load SVG ...
|
// Load SVG ...
|
||||||
const svgPath = path.resolve(__dirname, `./input/${testName}.svg`);
|
const svgPath = path.resolve(__dirname, `./input/${testName}.svg`);
|
||||||
expect(fs.existsSync(svgPath)).toEqual(true);
|
expect(fs.existsSync(svgPath)).toEqual(true);
|
||||||
|
@ -15,7 +15,10 @@ export const parseXMLString = (xmlStr: string, mimeType: DOMParserSupportedType)
|
|||||||
return xmlDoc;
|
return xmlDoc;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const parseXMLFile = (filePath: fs.PathOrFileDescriptor, mimeType: DOMParserSupportedType) => {
|
export const parseXMLFile = (
|
||||||
|
filePath: fs.PathOrFileDescriptor,
|
||||||
|
mimeType: DOMParserSupportedType,
|
||||||
|
) => {
|
||||||
const stream = fs.readFileSync(filePath, { encoding: 'utf-8' });
|
const stream = fs.readFileSync(filePath, { encoding: 'utf-8' });
|
||||||
|
|
||||||
const content = stream.toString();
|
const content = stream.toString();
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
import MapsPage from '../pageObject/MapsPage';
|
import MapsPage from '../pageObject/MapsPage';
|
||||||
|
|
||||||
context('Maps Page', () => {
|
context('Maps Page', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.visit('/c/maps');
|
cy.visit('/c/maps');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load the maps page', () => {
|
it('should load the maps page', () => {
|
||||||
MapsPage.isLoaded();
|
MapsPage.isLoaded();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should open the create dialog', () => {
|
it('should open the create dialog', () => {
|
||||||
MapsPage.create();
|
MapsPage.create();
|
||||||
MapsPage.isCreateDialogVisible();
|
MapsPage.isCreateDialogVisible();
|
||||||
cy.matchImageSnapshot('maps-create');
|
cy.matchImageSnapshot('maps-create');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should match the snapshot', () => {
|
it('should match the snapshot', () => {
|
||||||
cy.matchImageSnapshot('maps');
|
cy.matchImageSnapshot('maps');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
export default class MapsPage {
|
export default class MapsPage {
|
||||||
static isLoaded() {
|
static isLoaded() {
|
||||||
return cy.findByTestId('create');
|
return cy.findByTestId('create');
|
||||||
}
|
}
|
||||||
|
|
||||||
static create() {
|
static create() {
|
||||||
return cy.findByTestId('create').click();
|
return cy.findByTestId('create').click();
|
||||||
}
|
}
|
||||||
|
|
||||||
static isCreateDialogVisible() {
|
static isCreateDialogVisible() {
|
||||||
//TODO move to findByText when the double create dialog issue is solved
|
//TODO move to findByText when the double create dialog issue is solved
|
||||||
return cy.findAllByText('Create a new mindmap');
|
return cy.findAllByText('Create a new mindmap');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin')
|
|||||||
* @type {Cypress.PluginConfig}
|
* @type {Cypress.PluginConfig}
|
||||||
*/
|
*/
|
||||||
module.exports = (on, config) => {
|
module.exports = (on, config) => {
|
||||||
// `on` is used to hook into various events Cypress emits
|
// `on` is used to hook into various events Cypress emits
|
||||||
// `config` is the resolved Cypress config
|
// `config` is the resolved Cypress config
|
||||||
addMatchImageSnapshotPlugin(on, config);
|
addMatchImageSnapshotPlugin(on, config);
|
||||||
};
|
};
|
||||||
|
@ -4,16 +4,16 @@ import '@testing-library/cypress/add-commands';
|
|||||||
// make matchImageSnapshot() call the real implementation only if CYPRESS_imageSnaphots is set
|
// make matchImageSnapshot() call the real implementation only if CYPRESS_imageSnaphots is set
|
||||||
// otherwise it calls a noop
|
// otherwise it calls a noop
|
||||||
if (Cypress.env('imageSnaphots')) {
|
if (Cypress.env('imageSnaphots')) {
|
||||||
addMatchImageSnapshotCommand({
|
addMatchImageSnapshotCommand({
|
||||||
failureThreshold: 0.001,
|
failureThreshold: 0.001,
|
||||||
failureThresholdType: 'percent',
|
failureThresholdType: 'percent',
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Cypress.Commands.add(
|
Cypress.Commands.add(
|
||||||
'matchImageSnapshot',
|
'matchImageSnapshot',
|
||||||
{
|
{
|
||||||
prevSubject: ['optional', 'element', 'window', 'document'],
|
prevSubject: ['optional', 'element', 'window', 'document'],
|
||||||
},
|
},
|
||||||
() => Promise.resolve()
|
() => Promise.resolve(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
12
packages/webapp/src/@types/index.d.ts
vendored
12
packages/webapp/src/@types/index.d.ts
vendored
@ -2,10 +2,10 @@ declare module '*.png';
|
|||||||
declare module '*.svg';
|
declare module '*.svg';
|
||||||
declare module '*.wxml';
|
declare module '*.wxml';
|
||||||
declare global {
|
declare global {
|
||||||
const isAuth: boolean;
|
const isAuth: boolean;
|
||||||
const mapId: number;
|
const mapId: number;
|
||||||
const userOptions: { zoom: string | number } | null;
|
const userOptions: { zoom: string | number } | null;
|
||||||
const mindmapLocked: boolean;
|
const mindmapLocked: boolean;
|
||||||
const mindmapLockedMsg: string;
|
const mindmapLockedMsg: string;
|
||||||
const mapTitle: string;
|
const mapTitle: string;
|
||||||
}
|
}
|
||||||
|
12
packages/webapp/src/@types/typings.d.ts
vendored
12
packages/webapp/src/@types/typings.d.ts
vendored
@ -10,10 +10,10 @@ type DateType = string | number | Date | Dayjs;
|
|||||||
|
|
||||||
// @Todo: review if there is a better support for this.
|
// @Todo: review if there is a better support for this.
|
||||||
declare module 'dayjs' {
|
declare module 'dayjs' {
|
||||||
interface Dayjs {
|
interface Dayjs {
|
||||||
fromNow(withoutSuffix?: boolean): string;
|
fromNow(withoutSuffix?: boolean): string;
|
||||||
from(compared: DateType, withoutSuffix?: boolean): string;
|
from(compared: DateType, withoutSuffix?: boolean): string;
|
||||||
toNow(withoutSuffix?: boolean): string;
|
toNow(withoutSuffix?: boolean): string;
|
||||||
to(compared: DateType, withoutSuffix?: boolean): string;
|
to(compared: DateType, withoutSuffix?: boolean): string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,78 +1,75 @@
|
|||||||
import Client from "../client";
|
import Client from '../client';
|
||||||
import CacheDecoratorClient from "../client/cache-decorator-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';
|
||||||
|
|
||||||
|
|
||||||
interface Config {
|
interface Config {
|
||||||
apiBaseUrl: string;
|
apiBaseUrl: string;
|
||||||
analyticsAccount?: string;
|
analyticsAccount?: string;
|
||||||
recaptcha2Enabled: boolean;
|
recaptcha2Enabled: boolean;
|
||||||
recaptcha2SiteKey?: string;
|
recaptcha2SiteKey?: string;
|
||||||
clientType: 'mock' | 'rest';
|
clientType: 'mock' | 'rest';
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppConfig {
|
class _AppConfig {
|
||||||
|
private defaultInstance: Config = {
|
||||||
|
apiBaseUrl: `${window.location.protocol}//${window.location.hostname}:${window.location.port}`,
|
||||||
|
clientType: 'mock',
|
||||||
|
recaptcha2Enabled: true,
|
||||||
|
recaptcha2SiteKey: '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI',
|
||||||
|
};
|
||||||
|
|
||||||
private defaultInstance: Config = {
|
isDevelopEnv(): boolean {
|
||||||
apiBaseUrl: `${window.location.protocol}//${window.location.hostname}:${window.location.port}`,
|
const config = this.getInstance();
|
||||||
clientType: 'mock',
|
return config.clientType === 'mock';
|
||||||
recaptcha2Enabled: true,
|
}
|
||||||
recaptcha2SiteKey: '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI'
|
|
||||||
|
private getInstance(): Config {
|
||||||
|
// Config can be inserted in the html page to define the global properties ...
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
let result = (window as any).serverconfig;
|
||||||
|
if (!result) {
|
||||||
|
result = this.defaultInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
isDevelopEnv(): boolean {
|
return result;
|
||||||
const config = this.getInstance();
|
}
|
||||||
return config.clientType === 'mock';
|
|
||||||
|
isRecaptcha2Enabled(): boolean {
|
||||||
|
const config = this.getInstance();
|
||||||
|
return config.recaptcha2Enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRecaptcha2SiteKey(): string | undefined {
|
||||||
|
const config = this.getInstance();
|
||||||
|
return config.recaptcha2SiteKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
getGoogleAnalyticsAccount(): string | undefined {
|
||||||
|
const config = this.getInstance();
|
||||||
|
return config.analyticsAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildClient(): Client {
|
||||||
|
const config = this.getInstance();
|
||||||
|
let result: Client;
|
||||||
|
if (config.clientType == 'rest') {
|
||||||
|
result = new RestClient(this.getBaseUrl());
|
||||||
|
console.log('Service using rest client. ' + JSON.stringify(config));
|
||||||
|
} else {
|
||||||
|
console.log('Warning:Service using mockservice client');
|
||||||
|
result = new MockClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getInstance(): Config {
|
// Wrap with a cache decorator ...
|
||||||
// Config can be inserted in the html page to define the global properties ...
|
return new CacheDecoratorClient(result);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
}
|
||||||
let result = (window as any).serverconfig;
|
|
||||||
if (!result) {
|
|
||||||
result = this.defaultInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
getBaseUrl(): string {
|
||||||
}
|
const config = this.getInstance();
|
||||||
|
return config.apiBaseUrl;
|
||||||
isRecaptcha2Enabled(): boolean {
|
}
|
||||||
const config = this.getInstance();
|
|
||||||
return config.recaptcha2Enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
getRecaptcha2SiteKey(): string | undefined {
|
|
||||||
const config = this.getInstance();
|
|
||||||
return config.recaptcha2SiteKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
getGoogleAnalyticsAccount(): string | undefined {
|
|
||||||
const config = this.getInstance();
|
|
||||||
return config.analyticsAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
buildClient(): Client {
|
|
||||||
|
|
||||||
const config = this.getInstance();
|
|
||||||
let result: Client;
|
|
||||||
if (config.clientType == 'rest') {
|
|
||||||
result = new RestClient(this.getBaseUrl());
|
|
||||||
console.log('Service using rest client. ' + JSON.stringify(config));
|
|
||||||
} else {
|
|
||||||
console.log('Warning:Service using mockservice client');
|
|
||||||
result = new MockClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap with a cache decorator ...
|
|
||||||
return new CacheDecoratorClient(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
getBaseUrl(): string {
|
|
||||||
const config = this.getInstance();
|
|
||||||
return config.apiBaseUrl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const AppConfig = new _AppConfig();
|
const AppConfig = new _AppConfig();
|
||||||
|
|
||||||
export default AppConfig;
|
export default AppConfig;
|
||||||
|
@ -7,91 +7,89 @@ import 'dayjs/locale/ru';
|
|||||||
import 'dayjs/locale/zh';
|
import 'dayjs/locale/zh';
|
||||||
|
|
||||||
export class Locale {
|
export class Locale {
|
||||||
code: LocaleCode;
|
code: LocaleCode;
|
||||||
label: string;
|
label: string;
|
||||||
message: Record<string, string>;
|
message: Record<string, string>;
|
||||||
|
|
||||||
constructor(code: LocaleCode, label: string, message: unknown) {
|
constructor(code: LocaleCode, label: string, message: unknown) {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.label = label;
|
this.label = label;
|
||||||
this.message = message as Record<string, string>;
|
this.message = message as Record<string, string>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default abstract class AppI18n {
|
export default abstract class AppI18n {
|
||||||
private static LOCAL_STORAGE_KEY = 'user.locale';
|
private static LOCAL_STORAGE_KEY = 'user.locale';
|
||||||
|
|
||||||
public static getUserLocale(): Locale {
|
public static getUserLocale(): Locale {
|
||||||
// @Todo Hack: Try page must not account info. Add this to avoid 403 errors.
|
// @Todo Hack: Try page must not account info. Add this to avoid 403 errors.
|
||||||
const isTryPage = window.location.href.endsWith('/try');
|
const isTryPage = window.location.href.endsWith('/try');
|
||||||
let result: Locale;
|
let result: Locale;
|
||||||
if (!isTryPage) {
|
if (!isTryPage) {
|
||||||
const account = fetchAccount();
|
const account = fetchAccount();
|
||||||
result = account?.locale ? account.locale : this.getDefaultLocale();
|
result = account?.locale ? account.locale : this.getDefaultLocale();
|
||||||
|
|
||||||
// If the local storage value is different, update ...
|
// If the local storage value is different, update ...
|
||||||
if (account?.locale && result.code !== localStorage.getItem(AppI18n.LOCAL_STORAGE_KEY)) {
|
if (account?.locale && result.code !== localStorage.getItem(AppI18n.LOCAL_STORAGE_KEY)) {
|
||||||
localStorage.setItem(AppI18n.LOCAL_STORAGE_KEY, result.code);
|
localStorage.setItem(AppI18n.LOCAL_STORAGE_KEY, result.code);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
result = this.getDefaultLocale();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
public static getBrowserLocale(): Locale {
|
||||||
result = this.getDefaultLocale();
|
let localeCode = (navigator.languages && navigator.languages[0]) || navigator.language;
|
||||||
}
|
|
||||||
return result;
|
// Just remove the variant ...
|
||||||
|
localeCode = localeCode.split('-')[0];
|
||||||
|
|
||||||
|
let result = Locales.EN;
|
||||||
|
try {
|
||||||
|
result = localeFromStr(localeCode);
|
||||||
|
} catch {
|
||||||
|
console.warn(`Unsupported languange code ${localeCode}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getBrowserLocale(): Locale {
|
return result;
|
||||||
let localeCode = (navigator.languages && navigator.languages[0]) || navigator.language;
|
}
|
||||||
|
|
||||||
// Just remove the variant ...
|
public static getDefaultLocale(): Locale {
|
||||||
localeCode = localeCode.split('-')[0];
|
// Fetch local from local storage ...
|
||||||
|
let result: Locale;
|
||||||
let result = Locales.EN;
|
const userLocaleCode: string = localStorage.getItem(AppI18n.LOCAL_STORAGE_KEY);
|
||||||
try {
|
if (userLocaleCode) {
|
||||||
result = localeFromStr(localeCode);
|
result = localeFromStr(userLocaleCode);
|
||||||
} catch {
|
|
||||||
console.warn(`Unsupported languange code ${localeCode}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getDefaultLocale(): Locale {
|
// Ok, use browser default ...
|
||||||
// Fetch local from local storage ...
|
if (!result) {
|
||||||
let result: Locale;
|
result = this.getBrowserLocale();
|
||||||
const userLocaleCode: string = localStorage.getItem(AppI18n.LOCAL_STORAGE_KEY);
|
|
||||||
if (userLocaleCode) {
|
|
||||||
result = localeFromStr(userLocaleCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ok, use browser default ...
|
|
||||||
if (!result) {
|
|
||||||
result = this.getBrowserLocale();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LocaleCode = 'en' | 'es' | 'fr' | 'de' | 'ru' | 'zh';
|
export type LocaleCode = 'en' | 'es' | 'fr' | 'de' | 'ru' | 'zh';
|
||||||
|
|
||||||
export const Locales = {
|
export const Locales = {
|
||||||
EN: new Locale('en', 'English', require('./../../compiled-lang/en.json')), // eslint-disable-line
|
EN: new Locale('en', 'English', require('./../../compiled-lang/en.json')), // eslint-disable-line
|
||||||
ES: new Locale('es', 'Español', require('./../../compiled-lang/es.json')), // eslint-disable-line
|
ES: new Locale('es', 'Español', require('./../../compiled-lang/es.json')), // eslint-disable-line
|
||||||
DE: new Locale('fr', 'Français', require('./../../compiled-lang/fr.json')), // eslint-disable-line
|
DE: new Locale('fr', 'Français', require('./../../compiled-lang/fr.json')), // eslint-disable-line
|
||||||
FR: new Locale('de', 'Deutsch', require('./../../compiled-lang/de.json')), // eslint-disable-line
|
FR: new Locale('de', 'Deutsch', require('./../../compiled-lang/de.json')), // eslint-disable-line
|
||||||
RU: new Locale('ru', 'Pусский', require('./../../compiled-lang/ru.json')), // eslint-disable-line
|
RU: new Locale('ru', 'Pусский', require('./../../compiled-lang/ru.json')), // eslint-disable-line
|
||||||
ZH: new Locale('zh', '中文 (简体)', require('./../../compiled-lang/zh.json')), // eslint-disable-line
|
ZH: new Locale('zh', '中文 (简体)', require('./../../compiled-lang/zh.json')), // eslint-disable-line
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const localeFromStr = (code: string): Locale => {
|
export const localeFromStr = (code: string): Locale => {
|
||||||
const locales: Locale[] = Object.values(Locales);
|
const locales: Locale[] = Object.values(Locales);
|
||||||
|
|
||||||
const result = locales.find((l) => l.code == code);
|
const result = locales.find((l) => l.code == code);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw `Language code could not be found in list of default supported: + ${code}`;
|
throw `Language code could not be found in list of default supported: + ${code}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
@ -1,143 +1,142 @@
|
|||||||
import { EditorRenderMode, Mindmap, PersistenceManager } from '@wisemapping/mindplot';
|
import { EditorRenderMode, Mindmap, PersistenceManager } from '@wisemapping/mindplot';
|
||||||
import Client, {
|
import Client, {
|
||||||
AccountInfo,
|
AccountInfo,
|
||||||
BasicMapInfo,
|
BasicMapInfo,
|
||||||
ChangeHistory,
|
ChangeHistory,
|
||||||
ImportMapInfo,
|
ImportMapInfo,
|
||||||
Label,
|
Label,
|
||||||
MapInfo,
|
MapInfo,
|
||||||
NewUser,
|
NewUser,
|
||||||
Permission,
|
Permission,
|
||||||
} from '..';
|
} from '..';
|
||||||
import { LocaleCode } from '../../app-i18n';
|
import { LocaleCode } from '../../app-i18n';
|
||||||
|
|
||||||
class CacheDecoratorClient implements Client {
|
class CacheDecoratorClient implements Client {
|
||||||
private client: Client;
|
private client: Client;
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSessionExpired(callback?: () => void): () => void {
|
onSessionExpired(callback?: () => void): () => void {
|
||||||
return this.client.onSessionExpired(callback);
|
return this.client.onSessionExpired(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchMindmap(id: number): Mindmap {
|
fetchMindmap(id: number): Mindmap {
|
||||||
return this.client.fetchMindmap(id);
|
return this.client.fetchMindmap(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteAccount(): Promise<void> {
|
deleteAccount(): Promise<void> {
|
||||||
return this.client.deleteAccount();
|
return this.client.deleteAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
importMap(model: ImportMapInfo): Promise<number> {
|
importMap(model: ImportMapInfo): Promise<number> {
|
||||||
return this.client.importMap(model);
|
return this.client.importMap(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
createMap(map: BasicMapInfo): Promise<number> {
|
createMap(map: BasicMapInfo): Promise<number> {
|
||||||
return this.client.createMap(map);
|
return this.client.createMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteMaps(ids: number[]): Promise<void> {
|
deleteMaps(ids: number[]): Promise<void> {
|
||||||
return this.client.deleteMaps(ids);
|
return this.client.deleteMaps(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteMap(id: number): Promise<void> {
|
deleteMap(id: number): Promise<void> {
|
||||||
return this.client.deleteMap(id);
|
return this.client.deleteMap(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void> {
|
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void> {
|
||||||
return this.client.renameMap(id, basicInfo);
|
return this.client.renameMap(id, basicInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchAllMaps(): Promise<MapInfo[]> {
|
fetchAllMaps(): Promise<MapInfo[]> {
|
||||||
return this.client.fetchAllMaps();
|
return this.client.fetchAllMaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchMapPermissions(id: number): Promise<Permission[]> {
|
fetchMapPermissions(id: number): Promise<Permission[]> {
|
||||||
return this.client.fetchMapPermissions(id);
|
return this.client.fetchMapPermissions(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> {
|
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> {
|
||||||
return this.client.addMapPermissions(id, message, permissions);
|
return this.client.addMapPermissions(id, message, permissions);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteMapPermission(id: number, email: string): Promise<void> {
|
deleteMapPermission(id: number, email: string): Promise<void> {
|
||||||
return this.client.deleteMapPermission(id, email);
|
return this.client.deleteMapPermission(id, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number> {
|
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number> {
|
||||||
return this.client.duplicateMap(id, basicInfo);
|
return this.client.duplicateMap(id, basicInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAccountLanguage(locale: LocaleCode): Promise<void> {
|
updateAccountLanguage(locale: LocaleCode): Promise<void> {
|
||||||
return this.client.updateAccountLanguage(locale);
|
return this.client.updateAccountLanguage(locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAccountPassword(pasword: string): Promise<void> {
|
updateAccountPassword(pasword: string): Promise<void> {
|
||||||
return this.client.updateAccountPassword(pasword);
|
return this.client.updateAccountPassword(pasword);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAccountInfo(firstname: string, lastname: string): Promise<void> {
|
updateAccountInfo(firstname: string, lastname: string): Promise<void> {
|
||||||
return this.client.updateAccountInfo(firstname, lastname);
|
return this.client.updateAccountInfo(firstname, lastname);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStarred(id: number, starred: boolean): Promise<void> {
|
updateStarred(id: number, starred: boolean): Promise<void> {
|
||||||
return this.client.updateStarred(id, starred);
|
return this.client.updateStarred(id, starred);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMapToPublic(id: number, isPublic: boolean): Promise<void> {
|
updateMapToPublic(id: number, isPublic: boolean): Promise<void> {
|
||||||
return this.client.updateMapToPublic(id, isPublic);
|
return this.client.updateMapToPublic(id, isPublic);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchLabels(): Promise<Label[]> {
|
fetchLabels(): Promise<Label[]> {
|
||||||
return this.client.fetchLabels();
|
return this.client.fetchLabels();
|
||||||
}
|
}
|
||||||
|
|
||||||
createLabel(title: string, color: string): Promise<number> {
|
createLabel(title: string, color: string): Promise<number> {
|
||||||
return this.client.createLabel(title, color);
|
return this.client.createLabel(title, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteLabel(id: number): Promise<void> {
|
deleteLabel(id: number): Promise<void> {
|
||||||
return this.client.deleteLabel(id);
|
return this.client.deleteLabel(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
addLabelToMap(labelId: number, mapId: number): Promise<void> {
|
addLabelToMap(labelId: number, mapId: number): Promise<void> {
|
||||||
return this.client.addLabelToMap(labelId, mapId);
|
return this.client.addLabelToMap(labelId, mapId);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteLabelFromMap(labelId: number, mapId: number): Promise<void> {
|
deleteLabelFromMap(labelId: number, mapId: number): Promise<void> {
|
||||||
return this.client.deleteLabelFromMap(labelId, mapId);
|
return this.client.deleteLabelFromMap(labelId, mapId);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchAccountInfo(): Promise<AccountInfo> {
|
fetchAccountInfo(): Promise<AccountInfo> {
|
||||||
return this.client.fetchAccountInfo();
|
return this.client.fetchAccountInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
registerNewUser(user: NewUser): Promise<void> {
|
registerNewUser(user: NewUser): Promise<void> {
|
||||||
return this.client.registerNewUser(user);
|
return this.client.registerNewUser(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
resetPassword(email: string): Promise<void> {
|
resetPassword(email: string): Promise<void> {
|
||||||
return this.client.resetPassword(email);
|
return this.client.resetPassword(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchHistory(id: number): Promise<ChangeHistory[]> {
|
fetchHistory(id: number): Promise<ChangeHistory[]> {
|
||||||
return this.client.fetchHistory(id);
|
return this.client.fetchHistory(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
revertHistory(id: number, cid: number): Promise<void> {
|
revertHistory(id: number, cid: number): Promise<void> {
|
||||||
return this.client.revertHistory(id, cid);
|
return this.client.revertHistory(id, cid);
|
||||||
}
|
}
|
||||||
|
|
||||||
buildPersistenceManager(mode: EditorRenderMode): PersistenceManager {
|
buildPersistenceManager(mode: EditorRenderMode): PersistenceManager {
|
||||||
return this.client.buildPersistenceManager(mode);
|
return this.client.buildPersistenceManager(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
removePersistenceManager(): void {
|
|
||||||
return this.client.removePersistenceManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
removePersistenceManager(): void {
|
||||||
|
return this.client.removePersistenceManager();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CacheDecoratorClient;
|
export default CacheDecoratorClient;
|
||||||
|
@ -2,117 +2,117 @@ import { EditorRenderMode, Mindmap, PersistenceManager } from '@wisemapping/mind
|
|||||||
import { Locale, LocaleCode } from '../app-i18n';
|
import { Locale, LocaleCode } from '../app-i18n';
|
||||||
|
|
||||||
export type NewUser = {
|
export type NewUser = {
|
||||||
email: string;
|
email: string;
|
||||||
firstname: string;
|
firstname: string;
|
||||||
lastname: string;
|
lastname: string;
|
||||||
password: string;
|
password: string;
|
||||||
recaptcha: string | null;
|
recaptcha: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ImportMapInfo = {
|
export type ImportMapInfo = {
|
||||||
title: string;
|
title: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
contentType?: string;
|
contentType?: string;
|
||||||
content?: ArrayBuffer | null | string;
|
content?: ArrayBuffer | null | string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Label = {
|
export type Label = {
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
color: string;
|
color: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Role = 'owner' | 'editor' | 'viewer';
|
export type Role = 'owner' | 'editor' | 'viewer';
|
||||||
|
|
||||||
export type MapInfo = {
|
export type MapInfo = {
|
||||||
id: number;
|
id: number;
|
||||||
starred: boolean;
|
starred: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
labels: Label[];
|
labels: Label[];
|
||||||
createdBy: string;
|
createdBy: string;
|
||||||
creationTime: string;
|
creationTime: string;
|
||||||
lastModificationBy: string;
|
lastModificationBy: string;
|
||||||
lastModificationTime: string;
|
lastModificationTime: string;
|
||||||
description: string;
|
description: string;
|
||||||
isPublic: boolean;
|
isPublic: boolean;
|
||||||
role: Role;
|
role: Role;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ChangeHistory = {
|
export type ChangeHistory = {
|
||||||
id: number;
|
id: number;
|
||||||
lastModificationBy: string;
|
lastModificationBy: string;
|
||||||
lastModificationTime: string;
|
lastModificationTime: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BasicMapInfo = {
|
export type BasicMapInfo = {
|
||||||
title: string;
|
title: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FieldError = {
|
export type FieldError = {
|
||||||
id: string;
|
id: string;
|
||||||
msg: string;
|
msg: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ErrorInfo = {
|
export type ErrorInfo = {
|
||||||
msg?: string;
|
msg?: string;
|
||||||
fields?: Map<string, string>;
|
fields?: Map<string, string>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AccountInfo = {
|
export type AccountInfo = {
|
||||||
firstname: string;
|
firstname: string;
|
||||||
lastname: string;
|
lastname: string;
|
||||||
email: string;
|
email: string;
|
||||||
locale?: Locale;
|
locale?: Locale;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Permission = {
|
export type Permission = {
|
||||||
name?: string;
|
name?: string;
|
||||||
email: string;
|
email: string;
|
||||||
role: Role;
|
role: Role;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Client {
|
interface Client {
|
||||||
deleteAccount(): Promise<void>;
|
deleteAccount(): Promise<void>;
|
||||||
importMap(model: ImportMapInfo): Promise<number>;
|
importMap(model: ImportMapInfo): Promise<number>;
|
||||||
createMap(map: BasicMapInfo): Promise<number>;
|
createMap(map: BasicMapInfo): Promise<number>;
|
||||||
deleteMaps(ids: number[]): Promise<void>;
|
deleteMaps(ids: number[]): Promise<void>;
|
||||||
deleteMap(id: number): Promise<void>;
|
deleteMap(id: number): Promise<void>;
|
||||||
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>;
|
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>;
|
||||||
fetchAllMaps(): Promise<MapInfo[]>;
|
fetchAllMaps(): Promise<MapInfo[]>;
|
||||||
|
|
||||||
fetchMapPermissions(id: number): Promise<Permission[]>;
|
fetchMapPermissions(id: number): Promise<Permission[]>;
|
||||||
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void>;
|
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void>;
|
||||||
deleteMapPermission(id: number, email: string): Promise<void>;
|
deleteMapPermission(id: number, email: string): Promise<void>;
|
||||||
|
|
||||||
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>;
|
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>;
|
||||||
|
|
||||||
updateAccountLanguage(locale: LocaleCode): Promise<void>;
|
updateAccountLanguage(locale: LocaleCode): Promise<void>;
|
||||||
updateAccountPassword(pasword: string): Promise<void>;
|
updateAccountPassword(pasword: string): Promise<void>;
|
||||||
updateAccountInfo(firstname: string, lastname: string): Promise<void>;
|
updateAccountInfo(firstname: string, lastname: string): Promise<void>;
|
||||||
|
|
||||||
updateStarred(id: number, starred: boolean): Promise<void>;
|
updateStarred(id: number, starred: boolean): Promise<void>;
|
||||||
updateMapToPublic(id: number, isPublic: boolean): Promise<void>;
|
updateMapToPublic(id: number, isPublic: boolean): Promise<void>;
|
||||||
|
|
||||||
createLabel(title: string, color: string): Promise<number>;
|
createLabel(title: string, color: string): Promise<number>;
|
||||||
fetchLabels(): Promise<Label[]>;
|
fetchLabels(): Promise<Label[]>;
|
||||||
deleteLabel(id: number): Promise<void>;
|
deleteLabel(id: number): Promise<void>;
|
||||||
addLabelToMap(labelId: number, mapId: number): Promise<void>;
|
addLabelToMap(labelId: number, mapId: number): Promise<void>;
|
||||||
deleteLabelFromMap(labelId: number, mapId: number): Promise<void>;
|
deleteLabelFromMap(labelId: number, mapId: number): Promise<void>;
|
||||||
fetchAccountInfo(): Promise<AccountInfo>;
|
fetchAccountInfo(): Promise<AccountInfo>;
|
||||||
|
|
||||||
registerNewUser(user: NewUser): Promise<void>;
|
registerNewUser(user: NewUser): Promise<void>;
|
||||||
resetPassword(email: string): Promise<void>;
|
resetPassword(email: 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>;
|
||||||
|
|
||||||
fetchMindmap(id: number): Mindmap;
|
fetchMindmap(id: number): Mindmap;
|
||||||
|
|
||||||
buildPersistenceManager(mode: EditorRenderMode): PersistenceManager;
|
buildPersistenceManager(mode: EditorRenderMode): PersistenceManager;
|
||||||
removePersistenceManager(): void;
|
removePersistenceManager(): void;
|
||||||
|
|
||||||
onSessionExpired(callback?: () => void): () => void;
|
onSessionExpired(callback?: () => void): () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Client;
|
export default Client;
|
||||||
|
@ -1,418 +1,425 @@
|
|||||||
import { Mindmap, MockPersistenceManager, PersistenceManager } from '@wisemapping/mindplot';
|
import { Mindmap, MockPersistenceManager, PersistenceManager } from '@wisemapping/mindplot';
|
||||||
import XMLSerializerTango from '@wisemapping/mindplot/src/components/persistence/XMLSerializerTango';
|
import XMLSerializerTango from '@wisemapping/mindplot/src/components/persistence/XMLSerializerTango';
|
||||||
import Client, {
|
import Client, {
|
||||||
AccountInfo,
|
AccountInfo,
|
||||||
BasicMapInfo,
|
BasicMapInfo,
|
||||||
ChangeHistory,
|
ChangeHistory,
|
||||||
ImportMapInfo,
|
ImportMapInfo,
|
||||||
Label,
|
Label,
|
||||||
MapInfo,
|
MapInfo,
|
||||||
NewUser,
|
NewUser,
|
||||||
Permission,
|
Permission,
|
||||||
} from '..';
|
} from '..';
|
||||||
import { LocaleCode, localeFromStr } from '../../app-i18n';
|
import { LocaleCode, localeFromStr } from '../../app-i18n';
|
||||||
import exampleMap from './example-map.wxml';
|
import exampleMap from './example-map.wxml';
|
||||||
|
|
||||||
const label1: Label = {
|
const label1: Label = {
|
||||||
id: 1,
|
id: 1,
|
||||||
title: 'label 1',
|
title: 'label 1',
|
||||||
color: 'black',
|
color: 'black',
|
||||||
}
|
};
|
||||||
|
|
||||||
const label2: Label = {
|
const label2: Label = {
|
||||||
id: 2,
|
id: 2,
|
||||||
title: 'label 2',
|
title: 'label 2',
|
||||||
color: 'green',
|
color: 'green',
|
||||||
}
|
};
|
||||||
|
|
||||||
const label3: Label = {
|
const label3: Label = {
|
||||||
id: 3,
|
id: 3,
|
||||||
title: 'label 3',
|
title: 'label 3',
|
||||||
color: 'red',
|
color: 'red',
|
||||||
}
|
};
|
||||||
|
|
||||||
class MockClient implements Client {
|
class MockClient implements Client {
|
||||||
private maps: MapInfo[] = [];
|
private maps: MapInfo[] = [];
|
||||||
private labels: Label[] = [];
|
private labels: Label[] = [];
|
||||||
private permissionsByMap: Map<number, Permission[]> = new Map();
|
private permissionsByMap: Map<number, Permission[]> = new Map();
|
||||||
private persistenceManager: PersistenceManager;
|
private persistenceManager: PersistenceManager;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// Remove, just for develop ....
|
// Remove, just for develop ....
|
||||||
function createMapInfo(
|
function createMapInfo(
|
||||||
id: number,
|
id: number,
|
||||||
starred: boolean,
|
starred: boolean,
|
||||||
title: string,
|
title: string,
|
||||||
labels: Label[],
|
labels: Label[],
|
||||||
creator: string,
|
creator: string,
|
||||||
creationTime: string,
|
creationTime: string,
|
||||||
modifiedByUser: string,
|
modifiedByUser: string,
|
||||||
modifiedTime: string,
|
modifiedTime: string,
|
||||||
description: string,
|
description: string,
|
||||||
isPublic: boolean,
|
isPublic: boolean,
|
||||||
role: 'owner' | 'viewer' | 'editor'
|
role: 'owner' | 'viewer' | 'editor',
|
||||||
): MapInfo {
|
): MapInfo {
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
title,
|
title,
|
||||||
labels,
|
labels,
|
||||||
createdBy: creator,
|
createdBy: creator,
|
||||||
creationTime,
|
creationTime,
|
||||||
lastModificationBy: modifiedByUser,
|
lastModificationBy: modifiedByUser,
|
||||||
lastModificationTime: modifiedTime,
|
lastModificationTime: modifiedTime,
|
||||||
starred,
|
starred,
|
||||||
description,
|
description,
|
||||||
isPublic,
|
isPublic,
|
||||||
role,
|
role,
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
this.maps = [
|
|
||||||
createMapInfo(
|
|
||||||
1,
|
|
||||||
true,
|
|
||||||
'El Mapa',
|
|
||||||
[],
|
|
||||||
'Paulo',
|
|
||||||
'2008-06-02T00:00:00Z',
|
|
||||||
'Berna',
|
|
||||||
'2008-06-02T00:00:00Z',
|
|
||||||
'',
|
|
||||||
true,
|
|
||||||
'owner'
|
|
||||||
),
|
|
||||||
createMapInfo(
|
|
||||||
11,
|
|
||||||
false,
|
|
||||||
'El Mapa3',
|
|
||||||
[label1, label2],
|
|
||||||
'Paulo3',
|
|
||||||
'2008-06-02T00:00:00Z',
|
|
||||||
'Berna',
|
|
||||||
'2008-06-02T00:00:00Z',
|
|
||||||
'',
|
|
||||||
false,
|
|
||||||
'editor'
|
|
||||||
),
|
|
||||||
createMapInfo(
|
|
||||||
12,
|
|
||||||
false,
|
|
||||||
'El Mapa3',
|
|
||||||
[label2, label3],
|
|
||||||
'Paulo3',
|
|
||||||
'2008-06-02T00:00:00Z',
|
|
||||||
'Berna',
|
|
||||||
'2008-06-02T00:00:00Z',
|
|
||||||
'',
|
|
||||||
false,
|
|
||||||
'editor'
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
this.labels = [label1, label2, label3];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSessionExpired(callback?: () => void): () => void {
|
this.maps = [
|
||||||
return callback;
|
createMapInfo(
|
||||||
}
|
1,
|
||||||
|
true,
|
||||||
|
'El Mapa',
|
||||||
|
[],
|
||||||
|
'Paulo',
|
||||||
|
'2008-06-02T00:00:00Z',
|
||||||
|
'Berna',
|
||||||
|
'2008-06-02T00:00:00Z',
|
||||||
|
'',
|
||||||
|
true,
|
||||||
|
'owner',
|
||||||
|
),
|
||||||
|
createMapInfo(
|
||||||
|
11,
|
||||||
|
false,
|
||||||
|
'El Mapa3',
|
||||||
|
[label1, label2],
|
||||||
|
'Paulo3',
|
||||||
|
'2008-06-02T00:00:00Z',
|
||||||
|
'Berna',
|
||||||
|
'2008-06-02T00:00:00Z',
|
||||||
|
'',
|
||||||
|
false,
|
||||||
|
'editor',
|
||||||
|
),
|
||||||
|
createMapInfo(
|
||||||
|
12,
|
||||||
|
false,
|
||||||
|
'El Mapa3',
|
||||||
|
[label2, label3],
|
||||||
|
'Paulo3',
|
||||||
|
'2008-06-02T00:00:00Z',
|
||||||
|
'Berna',
|
||||||
|
'2008-06-02T00:00:00Z',
|
||||||
|
'',
|
||||||
|
false,
|
||||||
|
'editor',
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
fetchMindmap(id: number): Mindmap {
|
this.labels = [label1, label2, label3];
|
||||||
const parser = new DOMParser();
|
}
|
||||||
const xmlDoc = parser.parseFromString(`
|
|
||||||
|
onSessionExpired(callback?: () => void): () => void {
|
||||||
|
return callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchMindmap(id: number): Mindmap {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const xmlDoc = parser.parseFromString(
|
||||||
|
`
|
||||||
<map name="${id}" version="tango">
|
<map name="${id}" version="tango">
|
||||||
<topic central="true" text="This is the map ${id}" id="1" fontStyle=";;#ffffff;;;"></topic>
|
<topic central="true" text="This is the map ${id}" id="1" fontStyle=";;#ffffff;;;"></topic>
|
||||||
</map>
|
</map>
|
||||||
`, 'text/xml');
|
`,
|
||||||
|
'text/xml',
|
||||||
|
);
|
||||||
|
|
||||||
const serializer = new XMLSerializerTango();
|
const serializer = new XMLSerializerTango();
|
||||||
return serializer.loadFromDom(xmlDoc, String(id));
|
return serializer.loadFromDom(xmlDoc, String(id));
|
||||||
|
}
|
||||||
|
deleteMapPermission(id: number, email: string): Promise<void> {
|
||||||
|
let perm = this.permissionsByMap.get(id) || [];
|
||||||
|
perm = perm.filter((p) => p.email != email);
|
||||||
|
this.permissionsByMap.set(id, perm);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> {
|
||||||
|
let perm = this.permissionsByMap.get(id) || [];
|
||||||
|
perm = perm.concat(permissions);
|
||||||
|
this.permissionsByMap.set(id, perm);
|
||||||
|
|
||||||
|
console.debug(`Message ${message}`);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchMapPermissions(id: number): Promise<Permission[]> {
|
||||||
|
let perm = this.permissionsByMap.get(id);
|
||||||
|
if (!perm) {
|
||||||
|
perm = [
|
||||||
|
{
|
||||||
|
name: 'Cosme Editor',
|
||||||
|
email: 'pepe@example.com',
|
||||||
|
role: 'editor',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Cosme Owner',
|
||||||
|
email: 'pepe2@example.com',
|
||||||
|
role: 'owner',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Cosme Viewer',
|
||||||
|
email: 'pepe3@example.com',
|
||||||
|
role: 'viewer',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
this.permissionsByMap.set(id, perm);
|
||||||
}
|
}
|
||||||
deleteMapPermission(id: number, email: string): Promise<void> {
|
return Promise.resolve(perm);
|
||||||
let perm = this.permissionsByMap.get(id) || [];
|
}
|
||||||
perm = perm.filter((p) => p.email != email);
|
|
||||||
this.permissionsByMap.set(id, perm);
|
deleteAccount(): Promise<void> {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateAccountInfo(firstname: string, lastname: string): Promise<void> {
|
||||||
|
console.log('firstname:' + firstname, +lastname);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateAccountPassword(pasword: string): Promise<void> {
|
||||||
|
console.log('password:' + pasword);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateAccountLanguage(locale: LocaleCode): Promise<void> {
|
||||||
|
localStorage.setItem('locale', locale);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
importMap(model: ImportMapInfo): Promise<number> {
|
||||||
|
console.log('model:' + model);
|
||||||
|
return Promise.resolve(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchAccountInfo(): Promise<AccountInfo> {
|
||||||
|
console.log('Fetch account info ...');
|
||||||
|
const locale: LocaleCode | null = localStorage.getItem('locale') as LocaleCode;
|
||||||
|
return Promise.resolve({
|
||||||
|
firstname: 'Costme',
|
||||||
|
lastname: 'Fulanito',
|
||||||
|
email: 'test@example.com',
|
||||||
|
locale: localeFromStr(locale),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteMaps(ids: number[]): Promise<void> {
|
||||||
|
ids.forEach((id) => this.deleteMap(id));
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
revertHistory(id: number, cid: number): Promise<void> {
|
||||||
|
console.log('model:' + id + cid);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
createMap(map: BasicMapInfo): Promise<number> {
|
||||||
|
throw new Error('Method not implemented.' + map);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchLabels(): Promise<Label[]> {
|
||||||
|
console.log('Fetching labels from server');
|
||||||
|
return Promise.resolve(this.labels);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMapToPublic(id: number, isPublic: boolean): Promise<void> {
|
||||||
|
const mapInfo = this.maps.find((m) => m.id == id);
|
||||||
|
if (mapInfo) {
|
||||||
|
mapInfo.isPublic = isPublic;
|
||||||
}
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> {
|
updateStarred(id: number, starred: boolean): Promise<void> {
|
||||||
let perm = this.permissionsByMap.get(id) || [];
|
const mapInfo = this.maps.find((m) => m.id == id);
|
||||||
perm = perm.concat(permissions);
|
if (!mapInfo) {
|
||||||
this.permissionsByMap.set(id, perm);
|
console.log(`Could not find the map iwth id ${id}`);
|
||||||
|
return Promise.reject();
|
||||||
console.debug(`Message ${message}`);
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
}
|
||||||
|
mapInfo.starred = starred;
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
fetchMapPermissions(id: number): Promise<Permission[]> {
|
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void> {
|
||||||
let perm = this.permissionsByMap.get(id);
|
const exists = this.maps.find((m) => m.title == basicInfo.title) != undefined;
|
||||||
if (!perm) {
|
if (!exists) {
|
||||||
perm = [
|
this.maps = this.maps.map((m) => {
|
||||||
{
|
const result = m;
|
||||||
name: 'Cosme Editor',
|
if (m.id == id) {
|
||||||
email: 'pepe@example.com',
|
result.description = basicInfo.description ? basicInfo.description : '';
|
||||||
role: 'editor',
|
result.title = basicInfo.title;
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Cosme Owner',
|
|
||||||
email: 'pepe2@example.com',
|
|
||||||
role: 'owner',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Cosme Viewer',
|
|
||||||
email: 'pepe3@example.com',
|
|
||||||
role: 'viewer',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
this.permissionsByMap.set(id, perm);
|
|
||||||
}
|
}
|
||||||
return Promise.resolve(perm);
|
return result;
|
||||||
}
|
});
|
||||||
|
return Promise.resolve();
|
||||||
|
} else {
|
||||||
|
const fieldErrors: Map<string, string> = new Map<string, string>();
|
||||||
|
fieldErrors.set('name', 'name already exists ');
|
||||||
|
|
||||||
deleteAccount(): Promise<void> {
|
return Promise.reject({
|
||||||
return Promise.resolve();
|
msg: 'Map already exists ...' + basicInfo.title,
|
||||||
|
fields: fieldErrors,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateAccountInfo(firstname: string, lastname: string): Promise<void> {
|
fetchHistory(id: number): Promise<ChangeHistory[]> {
|
||||||
console.log('firstname:' + firstname, +lastname);
|
console.log(`Fetching history for ${id}`);
|
||||||
return Promise.resolve();
|
const result = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
lastModificationBy: 'Paulo',
|
||||||
|
lastModificationTime: '2008-06-02T00:00:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
lastModificationBy: 'Paulo',
|
||||||
|
lastModificationTime: '2008-06-02T00:00:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
lastModificationBy: 'Paulo',
|
||||||
|
lastModificationTime: '2008-06-02T00:00:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
lastModificationBy: 'Paulo',
|
||||||
|
lastModificationTime: '2008-06-02T00:00:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
lastModificationBy: 'Paulo',
|
||||||
|
lastModificationTime: '2008-06-02T00:00:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
lastModificationBy: 'Paulo',
|
||||||
|
lastModificationTime: '2008-06-02T00:00:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
lastModificationBy: 'Paulo',
|
||||||
|
lastModificationTime: '2008-06-02T00:00:00Z',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return Promise.resolve(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number> {
|
||||||
|
const exists = this.maps.find((m) => m.title == basicInfo.title) != undefined;
|
||||||
|
if (!exists) {
|
||||||
|
const newMap: MapInfo = {
|
||||||
|
id: Math.random() * 1000,
|
||||||
|
description: String(basicInfo.description),
|
||||||
|
title: basicInfo.title,
|
||||||
|
starred: false,
|
||||||
|
createdBy: 'current user',
|
||||||
|
labels: [],
|
||||||
|
lastModificationTime: '2008-06-02T00:00:00Z',
|
||||||
|
lastModificationBy: 'Berna',
|
||||||
|
creationTime: '2008-06-02T00:00:00Z',
|
||||||
|
isPublic: false,
|
||||||
|
role: 'owner',
|
||||||
|
};
|
||||||
|
this.maps.push(newMap);
|
||||||
|
return Promise.resolve(newMap.id);
|
||||||
|
} else {
|
||||||
|
const fieldErrors: Map<string, string> = new Map<string, string>();
|
||||||
|
fieldErrors.set('name', 'name already exists ');
|
||||||
|
|
||||||
|
return Promise.reject({
|
||||||
|
msg: 'Maps name must be unique:' + basicInfo.title,
|
||||||
|
fields: fieldErrors,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateAccountPassword(pasword: string): Promise<void> {
|
createLabel(title: string, color: string): Promise<number> {
|
||||||
console.log('password:' + pasword);
|
const newId =
|
||||||
return Promise.resolve();
|
Math.max.apply(
|
||||||
|
Number,
|
||||||
|
this.labels.map((l) => l.id),
|
||||||
|
) + 1;
|
||||||
|
this.labels.push({
|
||||||
|
id: newId,
|
||||||
|
title,
|
||||||
|
color,
|
||||||
|
});
|
||||||
|
return newId;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteLabel(id: number): Promise<void> {
|
||||||
|
this.labels = this.labels.filter((l) => l.id != id);
|
||||||
|
this.maps = this.maps.map((m) => {
|
||||||
|
return {
|
||||||
|
...m,
|
||||||
|
labels: m.labels.filter((l) => l.id != id),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
addLabelToMap(labelId: number, mapId: number): Promise<void> {
|
||||||
|
const labelToAdd = this.labels.find((l) => l.id === labelId);
|
||||||
|
if (!labelToAdd) {
|
||||||
|
return Promise.reject({ msg: `unable to find label with id ${labelId}` });
|
||||||
}
|
}
|
||||||
|
const map = this.maps.find((m) => m.id === mapId);
|
||||||
updateAccountLanguage(locale: LocaleCode): Promise<void> {
|
if (!map) {
|
||||||
localStorage.setItem('locale', locale);
|
return Promise.reject({ msg: `unable to find map with id ${mapId}` });
|
||||||
return Promise.resolve();
|
|
||||||
}
|
}
|
||||||
|
map.labels.push(labelToAdd);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
importMap(model: ImportMapInfo): Promise<number> {
|
deleteLabelFromMap(labelId: number, mapId: number): Promise<void> {
|
||||||
console.log('model:' + model);
|
const map = this.maps.find((m) => m.id === mapId);
|
||||||
return Promise.resolve(10);
|
if (!map) {
|
||||||
|
return Promise.reject({ msg: `unable to find map with id ${mapId}` });
|
||||||
}
|
}
|
||||||
|
map.labels = map.labels.filter((l) => l.id !== labelId);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
fetchAccountInfo(): Promise<AccountInfo> {
|
deleteMap(id: number): Promise<void> {
|
||||||
console.log('Fetch account info ...');
|
this.maps = this.maps.filter((m) => m.id != id);
|
||||||
const locale: LocaleCode | null = localStorage.getItem('locale') as LocaleCode;
|
return Promise.resolve();
|
||||||
return Promise.resolve({
|
}
|
||||||
firstname: 'Costme',
|
|
||||||
lastname: 'Fulanito',
|
registerNewUser(user: NewUser): Promise<void> {
|
||||||
email: 'test@example.com',
|
console.log('user:' + user);
|
||||||
locale: localeFromStr(locale),
|
if (user.email == 'error@example.com') {
|
||||||
});
|
return Promise.reject({ msg: 'Unexpected error' });
|
||||||
}
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
deleteMaps(ids: number[]): Promise<void> {
|
fetchAllMaps(): Promise<MapInfo[]> {
|
||||||
ids.forEach((id) => this.deleteMap(id));
|
console.log('Fetching maps from server');
|
||||||
return Promise.resolve();
|
return Promise.resolve(this.maps);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetPassword(email: string): Promise<void> {
|
||||||
|
console.log('email:' + email);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
buildPersistenceManager(): PersistenceManager {
|
||||||
|
if (this.persistenceManager) {
|
||||||
|
return this.persistenceManager;
|
||||||
}
|
}
|
||||||
revertHistory(id: number, cid: number): Promise<void> {
|
const persistence: PersistenceManager = new MockPersistenceManager(exampleMap);
|
||||||
console.log('model:' + id + cid);
|
this.persistenceManager = persistence;
|
||||||
return Promise.resolve();
|
return persistence;
|
||||||
}
|
}
|
||||||
|
|
||||||
createMap(map: BasicMapInfo): Promise<number> {
|
removePersistenceManager(): void {
|
||||||
throw new Error('Method not implemented.' + map);
|
if (this.persistenceManager) {
|
||||||
}
|
delete this.persistenceManager;
|
||||||
|
|
||||||
fetchLabels(): Promise<Label[]> {
|
|
||||||
console.log('Fetching labels from server');
|
|
||||||
return Promise.resolve(this.labels);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateMapToPublic(id: number, isPublic: boolean): Promise<void> {
|
|
||||||
const mapInfo = this.maps.find((m) => m.id == id);
|
|
||||||
if (mapInfo) {
|
|
||||||
mapInfo.isPublic = isPublic;
|
|
||||||
}
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateStarred(id: number, starred: boolean): Promise<void> {
|
|
||||||
const mapInfo = this.maps.find((m) => m.id == id);
|
|
||||||
if (!mapInfo) {
|
|
||||||
console.log(`Could not find the map iwth id ${id}`);
|
|
||||||
return Promise.reject();
|
|
||||||
}
|
|
||||||
mapInfo.starred = starred;
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void> {
|
|
||||||
const exists = this.maps.find((m) => m.title == basicInfo.title) != undefined;
|
|
||||||
if (!exists) {
|
|
||||||
this.maps = this.maps.map((m) => {
|
|
||||||
const result = m;
|
|
||||||
if (m.id == id) {
|
|
||||||
result.description = basicInfo.description ? basicInfo.description : '';
|
|
||||||
result.title = basicInfo.title;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
return Promise.resolve();
|
|
||||||
} else {
|
|
||||||
const fieldErrors: Map<string, string> = new Map<string, string>();
|
|
||||||
fieldErrors.set('name', 'name already exists ');
|
|
||||||
|
|
||||||
return Promise.reject({
|
|
||||||
msg: 'Map already exists ...' + basicInfo.title,
|
|
||||||
fields: fieldErrors,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchHistory(id: number): Promise<ChangeHistory[]> {
|
|
||||||
console.log(`Fetching history for ${id}`);
|
|
||||||
const result = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
lastModificationBy: 'Paulo',
|
|
||||||
lastModificationTime: '2008-06-02T00:00:00Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
lastModificationBy: 'Paulo',
|
|
||||||
lastModificationTime: '2008-06-02T00:00:00Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
lastModificationBy: 'Paulo',
|
|
||||||
lastModificationTime: '2008-06-02T00:00:00Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
lastModificationBy: 'Paulo',
|
|
||||||
lastModificationTime: '2008-06-02T00:00:00Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
lastModificationBy: 'Paulo',
|
|
||||||
lastModificationTime: '2008-06-02T00:00:00Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
lastModificationBy: 'Paulo',
|
|
||||||
lastModificationTime: '2008-06-02T00:00:00Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
lastModificationBy: 'Paulo',
|
|
||||||
lastModificationTime: '2008-06-02T00:00:00Z',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return Promise.resolve(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number> {
|
|
||||||
const exists = this.maps.find((m) => m.title == basicInfo.title) != undefined;
|
|
||||||
if (!exists) {
|
|
||||||
const newMap: MapInfo = {
|
|
||||||
id: Math.random() * 1000,
|
|
||||||
description: String(basicInfo.description),
|
|
||||||
title: basicInfo.title,
|
|
||||||
starred: false,
|
|
||||||
createdBy: 'current user',
|
|
||||||
labels: [],
|
|
||||||
lastModificationTime: '2008-06-02T00:00:00Z',
|
|
||||||
lastModificationBy: 'Berna',
|
|
||||||
creationTime: '2008-06-02T00:00:00Z',
|
|
||||||
isPublic: false,
|
|
||||||
role: 'owner',
|
|
||||||
};
|
|
||||||
this.maps.push(newMap);
|
|
||||||
return Promise.resolve(newMap.id);
|
|
||||||
} else {
|
|
||||||
const fieldErrors: Map<string, string> = new Map<string, string>();
|
|
||||||
fieldErrors.set('name', 'name already exists ');
|
|
||||||
|
|
||||||
return Promise.reject({
|
|
||||||
msg: 'Maps name must be unique:' + basicInfo.title,
|
|
||||||
fields: fieldErrors,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createLabel(title: string, color: string): Promise<number> {
|
|
||||||
const newId = Math.max.apply(Number, this.labels.map(l => l.id)) + 1;
|
|
||||||
this.labels.push({
|
|
||||||
id: newId,
|
|
||||||
title,
|
|
||||||
color,
|
|
||||||
});
|
|
||||||
return newId;
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteLabel(id: number): Promise<void> {
|
|
||||||
this.labels = this.labels.filter((l) => l.id != id);
|
|
||||||
this.maps = this.maps.map(m => {
|
|
||||||
return {
|
|
||||||
...m,
|
|
||||||
labels: m.labels.filter((l) => l.id != id)
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
addLabelToMap(labelId: number, mapId: number): Promise<void> {
|
|
||||||
const labelToAdd = this.labels.find((l) => l.id === labelId);
|
|
||||||
if (!labelToAdd) {
|
|
||||||
return Promise.reject({ msg: `unable to find label with id ${labelId}` });
|
|
||||||
}
|
|
||||||
const map = this.maps.find((m) => m.id === mapId);
|
|
||||||
if (!map) {
|
|
||||||
return Promise.reject({ msg: `unable to find map with id ${mapId}` });
|
|
||||||
}
|
|
||||||
map.labels.push(labelToAdd);
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteLabelFromMap(labelId: number, mapId: number): Promise<void> {
|
|
||||||
const map = this.maps.find((m) => m.id === mapId);
|
|
||||||
if (!map) {
|
|
||||||
return Promise.reject({ msg: `unable to find map with id ${mapId}` });
|
|
||||||
}
|
|
||||||
map.labels = map.labels.filter((l) => l.id !== labelId);
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteMap(id: number): Promise<void> {
|
|
||||||
this.maps = this.maps.filter((m) => m.id != id);
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
registerNewUser(user: NewUser): Promise<void> {
|
|
||||||
console.log('user:' + user);
|
|
||||||
if (user.email == "error@example.com") {
|
|
||||||
return Promise.reject({ msg: "Unexpected error" });
|
|
||||||
}
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchAllMaps(): Promise<MapInfo[]> {
|
|
||||||
console.log('Fetching maps from server');
|
|
||||||
return Promise.resolve(this.maps);
|
|
||||||
}
|
|
||||||
|
|
||||||
resetPassword(email: string): Promise<void> {
|
|
||||||
console.log('email:' + email);
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
buildPersistenceManager(): PersistenceManager {
|
|
||||||
if (this.persistenceManager) {
|
|
||||||
return this.persistenceManager;
|
|
||||||
}
|
|
||||||
const persistence: PersistenceManager = new MockPersistenceManager(exampleMap);
|
|
||||||
this.persistenceManager = persistence;
|
|
||||||
return persistence;
|
|
||||||
}
|
|
||||||
|
|
||||||
removePersistenceManager(): void {
|
|
||||||
if (this.persistenceManager) {
|
|
||||||
delete this.persistenceManager;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MockClient;
|
export default MockClient;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,43 +3,45 @@ import { EditorRenderMode } from '@wisemapping/mindplot';
|
|||||||
import AppConfig from '../../classes/app-config';
|
import AppConfig from '../../classes/app-config';
|
||||||
|
|
||||||
class EditorOptionsBuilder {
|
class EditorOptionsBuilder {
|
||||||
static build(locale: string, mode: EditorRenderMode, hotkeys: boolean): EditorOptions {
|
static build(locale: string, mode: EditorRenderMode, hotkeys: boolean): EditorOptions {
|
||||||
|
let options: EditorOptions = {
|
||||||
|
enableKeyboardEvents: hotkeys,
|
||||||
|
locale: locale,
|
||||||
|
mode: mode,
|
||||||
|
};
|
||||||
|
|
||||||
let options: EditorOptions = {
|
if (!AppConfig.isDevelopEnv()) {
|
||||||
enableKeyboardEvents: hotkeys,
|
options = {
|
||||||
locale: locale,
|
zoom:
|
||||||
mode: mode,
|
global.userOptions?.zoom != undefined
|
||||||
};
|
? Number.parseFloat(global?.userOptions?.zoom as string)
|
||||||
|
: 0.8,
|
||||||
if (!AppConfig.isDevelopEnv()) {
|
locked: global.mindmapLocked,
|
||||||
options = {
|
lockedMsg: global.mindmapLockedMsg,
|
||||||
zoom: (global.userOptions?.zoom != undefined
|
mapTitle: global.mapTitle,
|
||||||
? Number.parseFloat(global?.userOptions?.zoom as string)
|
...options,
|
||||||
: 0.8),
|
};
|
||||||
locked: global.mindmapLocked,
|
} else {
|
||||||
lockedMsg: global.mindmapLockedMsg,
|
// Running in a development mode.
|
||||||
mapTitle: global.mapTitle,
|
console.log('Running editor in development mode');
|
||||||
...options
|
options = {
|
||||||
}
|
zoom: 0.8,
|
||||||
} else {
|
locked: false,
|
||||||
// Running in a development mode.
|
mapTitle: 'Develop Mindnap',
|
||||||
console.log('Running editor in development mode');
|
...options,
|
||||||
options = {
|
};
|
||||||
zoom: 0.8,
|
|
||||||
locked: false,
|
|
||||||
mapTitle: "Develop Mindnap",
|
|
||||||
...options
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
static loadMapId(): number {
|
static loadMapId(): number {
|
||||||
const result = !AppConfig.isDevelopEnv() ? global.mapId : 11;
|
const result = !AppConfig.isDevelopEnv() ? global.mapId : 11;
|
||||||
if (result === undefined) {
|
if (result === undefined) {
|
||||||
throw Error(`Could not resolve mapId. Map Id: global.mapId: ${result} , global.mapTitle: ${global.mapTitle}, global.lockSession: ${global.lockSession}`);
|
throw Error(
|
||||||
}
|
`Could not resolve mapId. Map Id: global.mapId: ${result} , global.mapTitle: ${global.mapTitle}, global.lockSession: ${global.lockSession}`,
|
||||||
return result;
|
);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export default EditorOptionsBuilder;
|
export default EditorOptionsBuilder;
|
||||||
|
@ -2,10 +2,10 @@ import withStyles from '@mui/styles/withStyles';
|
|||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
|
|
||||||
export const StyledAlert = withStyles({
|
export const StyledAlert = withStyles({
|
||||||
root: {
|
root: {
|
||||||
padding: '10px 15px',
|
padding: '10px 15px',
|
||||||
margin: '5px 0px ',
|
margin: '5px 0px ',
|
||||||
},
|
},
|
||||||
})(Alert);
|
})(Alert);
|
||||||
|
|
||||||
export default StyledAlert;
|
export default StyledAlert;
|
||||||
|
@ -2,46 +2,46 @@ import styled from 'styled-components';
|
|||||||
/* Footer */
|
/* Footer */
|
||||||
|
|
||||||
export const StyledFooter = styled.footer`
|
export const StyledFooter = styled.footer`
|
||||||
height: 250px;
|
height: 250px;
|
||||||
margin-top: 80px;
|
margin-top: 80px;
|
||||||
padding: 30px 40px 10px 50px;
|
padding: 30px 40px 10px 50px;
|
||||||
background-color: #f9a826;
|
background-color: #f9a826;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 200px 1fr 1fr 1fr 3fr;
|
grid-template-columns: 200px 1fr 1fr 1fr 3fr;
|
||||||
|
|
||||||
& a {
|
& a {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: white;
|
color: white;
|
||||||
word-wrap: nowrap;
|
word-wrap: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
& h4 {
|
& h4 {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: white;
|
color: white;
|
||||||
word-wrap: nowrap;
|
word-wrap: nowrap;
|
||||||
font-weight: 500px;
|
font-weight: 500px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > svg {
|
& > svg {
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
& div:nth-child(2) {
|
& div:nth-child(2) {
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
& div:nth-child(3) {
|
& div:nth-child(3) {
|
||||||
grid-column: 3;
|
grid-column: 3;
|
||||||
}
|
}
|
||||||
& div:nth-child(4) {
|
& div:nth-child(4) {
|
||||||
grid-column: 4;
|
grid-column: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
& div:nth-child(5) {
|
& div:nth-child(5) {
|
||||||
grid-column: 5;
|
grid-column: 5;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -1,83 +1,81 @@
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
export const StyledNav = styled.nav`
|
export const StyledNav = styled.nav`
|
||||||
height: 90px;
|
height: 90px;
|
||||||
|
position: sticky;
|
||||||
|
top: -16px;
|
||||||
|
z-index: 1;
|
||||||
|
-webkit-backface-visibility: hidden;
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
height: 16px;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: -16px;
|
}
|
||||||
z-index: 1;
|
|
||||||
-webkit-backface-visibility: hidden;
|
|
||||||
|
|
||||||
&::before,
|
&::before {
|
||||||
&::after {
|
top: 58px;
|
||||||
content: '';
|
box-shadow: 0 4px 10px 0 rgba(202, 34, 34, 0.05), 0 5px 30px 0 rgba(0, 0, 0, 0.05);
|
||||||
display: block;
|
}
|
||||||
height: 16px;
|
|
||||||
position: sticky;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before {
|
&::after {
|
||||||
top: 58px;
|
background: linear-gradient(white, rgba(255, 255, 255, 0.3));
|
||||||
box-shadow: 0 4px 10px 0 rgba(202, 34, 34, 0.05), 0 5px 30px 0 rgba(0, 0, 0, 0.05);
|
top: 0;
|
||||||
}
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
&::after {
|
.header-area-right2 {
|
||||||
background: linear-gradient(white, rgba(255, 255, 255, 0.3));
|
grid-column-start: 3;
|
||||||
top: 0;
|
text-align: right;
|
||||||
z-index: 2;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.header-area-right2 {
|
.header-area-right1 span,
|
||||||
grid-column-start: 3;
|
.header-area-right2 span {
|
||||||
text-align: right;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-area-right1 span,
|
.header-area-content-span {
|
||||||
.header-area-right2 span {
|
grid-column-start: 2;
|
||||||
font-size: 15px;
|
grid-column-end: 3;
|
||||||
}
|
text-align: right;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
.header-area-content-span {
|
.header-area-content-span {
|
||||||
grid-column-start: 2;
|
display: none;
|
||||||
grid-column-end: 3;
|
grid-column-start: 2;
|
||||||
text-align: right;
|
grid-column-end: 3;
|
||||||
font-size: 14px;
|
text-align: right;
|
||||||
padding: 10px;
|
font-size: 14px;
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@media only screen and (max-width: 600px) {
|
|
||||||
.header-area-content-span {
|
|
||||||
display: none;
|
|
||||||
grid-column-start: 2;
|
|
||||||
grid-column-end: 3;
|
|
||||||
text-align: right;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const StyledDiv = styled.nav`
|
export const StyledDiv = styled.nav`
|
||||||
background: white;
|
background: white;
|
||||||
height: 74px;
|
height: 74px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
margin-top: -16px;
|
margin-top: -16px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
grid-template-columns: 150px 1fr 160px 20px;
|
grid-template-columns: 150px 1fr 160px 20px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Logo = styled.span`
|
export const Logo = styled.span`
|
||||||
grid-column-start: 1;
|
grid-column-start: 1;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
|
|
||||||
.header-logo a {
|
.header-logo a {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -2,7 +2,7 @@ import MenuItem from '@mui/material/MenuItem';
|
|||||||
import withStyles from '@mui/styles/withStyles';
|
import withStyles from '@mui/styles/withStyles';
|
||||||
|
|
||||||
export const StyledMenuItem = withStyles({
|
export const StyledMenuItem = withStyles({
|
||||||
root: {
|
root: {
|
||||||
width: '300px',
|
width: '300px',
|
||||||
},
|
},
|
||||||
})(MenuItem);
|
})(MenuItem);
|
||||||
|
@ -3,23 +3,23 @@ import IconButton from '@mui/material/IconButton';
|
|||||||
import LabelTwoTone from '@mui/icons-material/LabelTwoTone';
|
import LabelTwoTone from '@mui/icons-material/LabelTwoTone';
|
||||||
|
|
||||||
export const StyledButton = styled(IconButton)`
|
export const StyledButton = styled(IconButton)`
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const NewLabelContainer = styled.div`
|
export const NewLabelContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const NewLabelColor = styled(LabelTwoTone)`
|
export const NewLabelColor = styled(LabelTwoTone)`
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const CreateLabel = styled.div`
|
export const CreateLabel = styled.div`
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
`;
|
`;
|
||||||
|
@ -5,25 +5,25 @@ import DialogTitle from '@mui/material/DialogTitle';
|
|||||||
import withStyles from '@mui/styles/withStyles';
|
import withStyles from '@mui/styles/withStyles';
|
||||||
|
|
||||||
export const StyledDialogContent = withStyles({
|
export const StyledDialogContent = withStyles({
|
||||||
root: {
|
root: {
|
||||||
padding: '0px 39px',
|
padding: '0px 39px',
|
||||||
},
|
},
|
||||||
})(DialogContent);
|
})(DialogContent);
|
||||||
|
|
||||||
export const StyledDialogTitle = withStyles({
|
export const StyledDialogTitle = withStyles({
|
||||||
root: {
|
root: {
|
||||||
padding: '39px 39px 10px 39px',
|
padding: '39px 39px 10px 39px',
|
||||||
},
|
},
|
||||||
})(DialogTitle);
|
})(DialogTitle);
|
||||||
|
|
||||||
export const StyledDialogActions = withStyles({
|
export const StyledDialogActions = withStyles({
|
||||||
root: {
|
root: {
|
||||||
padding: '39px 39px 39px 39px',
|
padding: '39px 39px 39px 39px',
|
||||||
},
|
},
|
||||||
})(DialogActions);
|
})(DialogActions);
|
||||||
|
|
||||||
export const StyledDialog = withStyles({
|
export const StyledDialog = withStyles({
|
||||||
root: {
|
root: {
|
||||||
borderRadius: '9px',
|
borderRadius: '9px',
|
||||||
},
|
},
|
||||||
})(Dialog);
|
})(Dialog);
|
||||||
|
@ -2,19 +2,19 @@ import createStyles from '@mui/styles/createStyles';
|
|||||||
import makeStyles from '@mui/styles/makeStyles';
|
import makeStyles from '@mui/styles/makeStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
export const useStyles = makeStyles(() =>
|
||||||
createStyles({
|
createStyles({
|
||||||
select: {
|
select: {
|
||||||
height: '40px',
|
height: '40px',
|
||||||
borderRadius: '9px',
|
borderRadius: '9px',
|
||||||
width: '300px',
|
width: '300px',
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
margin: '0px 40px',
|
margin: '0px 40px',
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
margin: '5px 0px',
|
margin: '5px 0px',
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
@ -2,14 +2,14 @@ import createStyles from '@mui/styles/createStyles';
|
|||||||
import makeStyles from '@mui/styles/makeStyles';
|
import makeStyles from '@mui/styles/makeStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
export const useStyles = makeStyles(() =>
|
||||||
createStyles({
|
createStyles({
|
||||||
textarea: {
|
textarea: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: '15px 15px',
|
padding: '15px 15px',
|
||||||
marging: '0px 10px',
|
marging: '0px 10px',
|
||||||
},
|
},
|
||||||
textDesc: {
|
textDesc: {
|
||||||
width: '150px',
|
width: '150px',
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
@ -2,9 +2,9 @@ import createStyles from '@mui/styles/createStyles';
|
|||||||
import makeStyles from '@mui/styles/makeStyles';
|
import makeStyles from '@mui/styles/makeStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
export const useStyles = makeStyles(() =>
|
||||||
createStyles({
|
createStyles({
|
||||||
paper: {
|
paper: {
|
||||||
maxWidth: '420px',
|
maxWidth: '420px',
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
@ -2,11 +2,11 @@ import createStyles from '@mui/styles/createStyles';
|
|||||||
import makeStyles from '@mui/styles/makeStyles';
|
import makeStyles from '@mui/styles/makeStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
export const useStyles = makeStyles(() =>
|
||||||
createStyles({
|
createStyles({
|
||||||
textarea: {
|
textarea: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: '15px 15px',
|
padding: '15px 15px',
|
||||||
marging: '0px 10px',
|
marging: '0px 10px',
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
@ -2,25 +2,25 @@ import createStyles from '@mui/styles/createStyles';
|
|||||||
import makeStyles from '@mui/styles/makeStyles';
|
import makeStyles from '@mui/styles/makeStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
export const useStyles = makeStyles(() =>
|
||||||
createStyles({
|
createStyles({
|
||||||
actionContainer: {
|
actionContainer: {
|
||||||
padding: '10px 0px',
|
padding: '10px 0px',
|
||||||
border: '1px solid rgba(0, 0, 0, 0.12)',
|
border: '1px solid rgba(0, 0, 0, 0.12)',
|
||||||
borderRadius: '8px 8px 0px 0px',
|
borderRadius: '8px 8px 0px 0px',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
textArea: {
|
textArea: {
|
||||||
width: '730px',
|
width: '730px',
|
||||||
margin: '5px 0px',
|
margin: '5px 0px',
|
||||||
padding: '10px',
|
padding: '10px',
|
||||||
},
|
},
|
||||||
listPaper: {
|
listPaper: {
|
||||||
maxHeight: 200,
|
maxHeight: 200,
|
||||||
overflowY: 'scroll',
|
overflowY: 'scroll',
|
||||||
},
|
},
|
||||||
paper: {
|
paper: {
|
||||||
width: '850px',
|
width: '850px',
|
||||||
minWidth: '850px',
|
minWidth: '850px',
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,7 @@ import FormGroup from '@mui/material/FormGroup';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
export const LabelListContainer = styled(FormGroup)`
|
export const LabelListContainer = styled(FormGroup)`
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
`;
|
`;
|
||||||
|
@ -8,8 +8,8 @@ export const LabelContainer = styled.div`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const LabelText = styled.span`
|
export const LabelText = styled.span`
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
`;
|
`;
|
||||||
|
@ -8,8 +8,8 @@ export const LabelContainer = styled.div`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const LabelText = styled.span`
|
export const LabelText = styled.span`
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
`;
|
`;
|
||||||
|
@ -4,108 +4,108 @@ import createStyles from '@mui/styles/createStyles';
|
|||||||
import makeStyles from '@mui/styles/makeStyles';
|
import makeStyles from '@mui/styles/makeStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles((theme: Theme) =>
|
export const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
root: {
|
root: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
},
|
||||||
|
paper: {
|
||||||
|
width: '100%',
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
minWidth: 750,
|
||||||
|
'& tr:nth-child(even)': {
|
||||||
|
background: 'white',
|
||||||
|
},
|
||||||
|
'& tr:nth-child(odd)': {
|
||||||
|
background: 'rgba(221, 221, 221, 0.35)',
|
||||||
|
},
|
||||||
|
// '&:hover tr': {
|
||||||
|
// backgroundColor: 'rgba(150, 150, 150, 0.7)',
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
headerCell: {
|
||||||
|
background: 'white',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: 'rgba(0, 0, 0, 0.44)',
|
||||||
|
border: 0,
|
||||||
|
},
|
||||||
|
bodyCell: {
|
||||||
|
border: '0px',
|
||||||
|
},
|
||||||
|
labelsCell: {
|
||||||
|
maxWidth: '300px',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textAlign: 'right',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
},
|
||||||
|
visuallyHidden: {
|
||||||
|
border: 0,
|
||||||
|
clip: 'rect(0 0 0 0)',
|
||||||
|
height: 1,
|
||||||
|
margin: -1,
|
||||||
|
overflow: 'hidden',
|
||||||
|
padding: 0,
|
||||||
|
position: 'absolute',
|
||||||
|
top: 20,
|
||||||
|
width: 1,
|
||||||
|
},
|
||||||
|
toolbar: {
|
||||||
|
display: 'flex',
|
||||||
|
borderBottom: '1px solid #cccccc',
|
||||||
|
padding: '0',
|
||||||
|
marging: '0',
|
||||||
|
},
|
||||||
|
toolbarActions: {
|
||||||
|
flexGrow: 1,
|
||||||
|
paddingLeft: '23px;',
|
||||||
|
},
|
||||||
|
toolbarListActions: {
|
||||||
|
flexGrow: 1,
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
borderRadius: 9,
|
||||||
|
backgroundColor: alpha(theme.palette.common.white, 0.15),
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: alpha(theme.palette.common.white, 0.25),
|
||||||
|
},
|
||||||
|
margin: '10px 0px',
|
||||||
|
width: '100%',
|
||||||
|
[theme.breakpoints.up('sm')]: {
|
||||||
|
marginLeft: theme.spacing(1),
|
||||||
|
width: 'auto',
|
||||||
|
},
|
||||||
|
float: 'right',
|
||||||
|
},
|
||||||
|
searchIcon: {
|
||||||
|
padding: '6px 0 0 5px',
|
||||||
|
height: '100%',
|
||||||
|
position: 'absolute',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
searchInputRoot: {
|
||||||
|
color: 'inherit',
|
||||||
|
},
|
||||||
|
toolbalLeft: {
|
||||||
|
float: 'right',
|
||||||
|
},
|
||||||
|
searchInputInput: {
|
||||||
|
// padding: theme.spacing(1, 1, 1, 0),
|
||||||
|
// vertical padding + font size from searchIcon
|
||||||
|
border: '1px solid #ffa800',
|
||||||
|
borderRadius: 4,
|
||||||
|
paddingLeft: `calc(1em + ${theme.spacing(4)})`,
|
||||||
|
transition: theme.transitions.create('width'),
|
||||||
|
width: '100%',
|
||||||
|
[theme.breakpoints.up('sm')]: {
|
||||||
|
width: '12ch',
|
||||||
|
'&:focus': {
|
||||||
|
width: '20ch',
|
||||||
},
|
},
|
||||||
paper: {
|
},
|
||||||
width: '100%',
|
},
|
||||||
marginBottom: theme.spacing(2),
|
}),
|
||||||
},
|
|
||||||
table: {
|
|
||||||
minWidth: 750,
|
|
||||||
'& tr:nth-child(even)': {
|
|
||||||
background: 'white',
|
|
||||||
},
|
|
||||||
'& tr:nth-child(odd)': {
|
|
||||||
background: 'rgba(221, 221, 221, 0.35)',
|
|
||||||
},
|
|
||||||
// '&:hover tr': {
|
|
||||||
// backgroundColor: 'rgba(150, 150, 150, 0.7)',
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
headerCell: {
|
|
||||||
background: 'white',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
color: 'rgba(0, 0, 0, 0.44)',
|
|
||||||
border: 0,
|
|
||||||
},
|
|
||||||
bodyCell: {
|
|
||||||
border: '0px',
|
|
||||||
},
|
|
||||||
labelsCell: {
|
|
||||||
maxWidth: '300px',
|
|
||||||
overflow: 'hidden',
|
|
||||||
textAlign: 'right',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
textOverflow: 'ellipsis'
|
|
||||||
},
|
|
||||||
visuallyHidden: {
|
|
||||||
border: 0,
|
|
||||||
clip: 'rect(0 0 0 0)',
|
|
||||||
height: 1,
|
|
||||||
margin: -1,
|
|
||||||
overflow: 'hidden',
|
|
||||||
padding: 0,
|
|
||||||
position: 'absolute',
|
|
||||||
top: 20,
|
|
||||||
width: 1,
|
|
||||||
},
|
|
||||||
toolbar: {
|
|
||||||
display: 'flex',
|
|
||||||
borderBottom: '1px solid #cccccc',
|
|
||||||
padding: '0',
|
|
||||||
marging: '0',
|
|
||||||
},
|
|
||||||
toolbarActions: {
|
|
||||||
flexGrow: 1,
|
|
||||||
paddingLeft: '23px;'
|
|
||||||
},
|
|
||||||
toolbarListActions: {
|
|
||||||
flexGrow: 1,
|
|
||||||
},
|
|
||||||
search: {
|
|
||||||
borderRadius: 9,
|
|
||||||
backgroundColor: alpha(theme.palette.common.white, 0.15),
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: alpha(theme.palette.common.white, 0.25),
|
|
||||||
},
|
|
||||||
margin: '10px 0px',
|
|
||||||
width: '100%',
|
|
||||||
[theme.breakpoints.up('sm')]: {
|
|
||||||
marginLeft: theme.spacing(1),
|
|
||||||
width: 'auto',
|
|
||||||
},
|
|
||||||
float: 'right',
|
|
||||||
},
|
|
||||||
searchIcon: {
|
|
||||||
padding: '6px 0 0 5px',
|
|
||||||
height: '100%',
|
|
||||||
position: 'absolute',
|
|
||||||
pointerEvents: 'none',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
},
|
|
||||||
searchInputRoot: {
|
|
||||||
color: 'inherit',
|
|
||||||
},
|
|
||||||
toolbalLeft: {
|
|
||||||
float: 'right',
|
|
||||||
},
|
|
||||||
searchInputInput: {
|
|
||||||
// padding: theme.spacing(1, 1, 1, 0),
|
|
||||||
// vertical padding + font size from searchIcon
|
|
||||||
border: '1px solid #ffa800',
|
|
||||||
borderRadius: 4,
|
|
||||||
paddingLeft: `calc(1em + ${theme.spacing(4)})`,
|
|
||||||
transition: theme.transitions.create('width'),
|
|
||||||
width: '100%',
|
|
||||||
[theme.breakpoints.up('sm')]: {
|
|
||||||
width: '12ch',
|
|
||||||
'&:focus': {
|
|
||||||
width: '20ch',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
|
@ -6,61 +6,61 @@ import makeStyles from '@mui/styles/makeStyles';
|
|||||||
const drawerWidth = 300;
|
const drawerWidth = 300;
|
||||||
|
|
||||||
export const useStyles = makeStyles((theme: Theme) =>
|
export const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
root: {
|
root: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
},
|
},
|
||||||
appBar: {
|
appBar: {
|
||||||
zIndex: theme.zIndex.drawer + 1,
|
zIndex: theme.zIndex.drawer + 1,
|
||||||
transition: theme.transitions.create(['width', 'margin'], {
|
transition: theme.transitions.create(['width', 'margin'], {
|
||||||
easing: theme.transitions.easing.sharp,
|
easing: theme.transitions.easing.sharp,
|
||||||
duration: theme.transitions.duration.leavingScreen,
|
duration: theme.transitions.duration.leavingScreen,
|
||||||
}),
|
}),
|
||||||
background: '#ffffff',
|
background: '#ffffff',
|
||||||
},
|
},
|
||||||
appBarShift: {
|
appBarShift: {
|
||||||
marginLeft: drawerWidth,
|
marginLeft: drawerWidth,
|
||||||
width: `calc(100% - ${drawerWidth}px)`,
|
width: `calc(100% - ${drawerWidth}px)`,
|
||||||
transition: theme.transitions.create(['width', 'margin'], {
|
transition: theme.transitions.create(['width', 'margin'], {
|
||||||
easing: theme.transitions.easing.sharp,
|
easing: theme.transitions.easing.sharp,
|
||||||
duration: theme.transitions.duration.enteringScreen,
|
duration: theme.transitions.duration.enteringScreen,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
newMapButton: {
|
newMapButton: {
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
minWidth: '130px',
|
minWidth: '130px',
|
||||||
},
|
},
|
||||||
importButton: {
|
importButton: {
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
minWidth: '130px',
|
minWidth: '130px',
|
||||||
},
|
},
|
||||||
rightButtonGroup: {
|
rightButtonGroup: {
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
flexGrow: 10,
|
flexGrow: 10,
|
||||||
textAlign: 'right',
|
textAlign: 'right',
|
||||||
minWidth: '280px',
|
minWidth: '280px',
|
||||||
},
|
},
|
||||||
drawer: {
|
drawer: {
|
||||||
width: drawerWidth,
|
width: drawerWidth,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
},
|
},
|
||||||
drawerOpen: {
|
drawerOpen: {
|
||||||
background: '#ffa800',
|
background: '#ffa800',
|
||||||
width: drawerWidth,
|
width: drawerWidth,
|
||||||
transition: theme.transitions.create('width', {
|
transition: theme.transitions.create('width', {
|
||||||
easing: theme.transitions.easing.sharp,
|
easing: theme.transitions.easing.sharp,
|
||||||
duration: theme.transitions.duration.enteringScreen,
|
duration: theme.transitions.duration.enteringScreen,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
toolbar: {
|
toolbar: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'flex-end',
|
justifyContent: 'flex-end',
|
||||||
minHeight: '44px',
|
minHeight: '44px',
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
padding: '24px 0px',
|
padding: '24px 0px',
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
@ -6,79 +6,82 @@ import { useSelector } from 'react-redux';
|
|||||||
import AppConfig from '../classes/app-config';
|
import AppConfig from '../classes/app-config';
|
||||||
import { RootState } from './rootReducer';
|
import { RootState } from './rootReducer';
|
||||||
|
|
||||||
|
|
||||||
export interface ClientStatus {
|
export interface ClientStatus {
|
||||||
state: 'healthy' | 'session-expired';
|
state: 'healthy' | 'session-expired';
|
||||||
msg?: string;
|
msg?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientState {
|
export interface ClientState {
|
||||||
instance: Client;
|
instance: Client;
|
||||||
status: ClientStatus;
|
status: ClientStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: ClientState = {
|
const initialState: ClientState = {
|
||||||
instance: AppConfig.buildClient(),
|
instance: AppConfig.buildClient(),
|
||||||
status: { state: 'healthy' },
|
status: { state: 'healthy' },
|
||||||
};
|
};
|
||||||
|
|
||||||
export const clientSlice = createSlice({
|
export const clientSlice = createSlice({
|
||||||
name: 'client',
|
name: 'client',
|
||||||
initialState: initialState,
|
initialState: initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
sessionExpired(state) {
|
sessionExpired(state) {
|
||||||
state.status = {
|
state.status = {
|
||||||
state: 'session-expired',
|
state: 'session-expired',
|
||||||
msg: 'Sessions has expired. You need to login again',
|
msg: 'Sessions has expired. You need to login again',
|
||||||
};
|
};
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
type MapLoadResult = {
|
type MapLoadResult = {
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
error: ErrorInfo | null;
|
error: ErrorInfo | null;
|
||||||
map: MapInfo | null;
|
map: MapInfo | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchMapById = (id: number): MapLoadResult => {
|
export const fetchMapById = (id: number): MapLoadResult => {
|
||||||
const client: Client = useSelector(activeInstance);
|
const client: Client = useSelector(activeInstance);
|
||||||
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, MapInfo[]>(`maps-${id}`, () => {
|
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, MapInfo[]>(`maps-${id}`, () => {
|
||||||
return client.fetchAllMaps();
|
return client.fetchAllMaps();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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;
|
||||||
let errorMsg: ErrorInfo = error;
|
let errorMsg: ErrorInfo = 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(error).length !== 0 ? error : null;
|
||||||
}
|
|
||||||
// Seach for object...
|
|
||||||
map = data?.find((m) => m.id == id);
|
|
||||||
if (!map && !errorMsg) {
|
|
||||||
errorMsg = { msg: `Map with id ${id} could not be found. Please, reflesh the page. Map: ${JSON.stringify(data)}` }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return { isLoading: isLoading, error: errorMsg, map: map };
|
// Seach for object...
|
||||||
|
map = data?.find((m) => m.id == id);
|
||||||
|
if (!map && !errorMsg) {
|
||||||
|
errorMsg = {
|
||||||
|
msg: `Map with id ${id} could not be found. Please, reflesh the page. Map: ${JSON.stringify(
|
||||||
|
data,
|
||||||
|
)}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { isLoading: isLoading, error: errorMsg, map: map };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchAccount = (): AccountInfo | undefined => {
|
export const fetchAccount = (): AccountInfo | undefined => {
|
||||||
const client: Client = useSelector(activeInstance);
|
const client: Client = useSelector(activeInstance);
|
||||||
const { data } = useQuery<unknown, ErrorInfo, AccountInfo>('account', () => {
|
const { data } = useQuery<unknown, ErrorInfo, AccountInfo>('account', () => {
|
||||||
return client.fetchAccountInfo();
|
return client.fetchAccountInfo();
|
||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const activeInstance = (state: RootState): Client => {
|
export const activeInstance = (state: RootState): Client => {
|
||||||
return state.client.instance;
|
return state.client.instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const activeInstanceStatus = (state: RootState): ClientStatus => {
|
export const activeInstanceStatus = (state: RootState): ClientStatus => {
|
||||||
return state.client.status;
|
return state.client.status;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const { sessionExpired } = clientSlice.actions;
|
export const { sessionExpired } = clientSlice.actions;
|
||||||
export default clientSlice.reducer;
|
export default clientSlice.reducer;
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
import { createSlice } from "@reduxjs/toolkit";
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
import { RootState } from "./rootReducer";
|
import { RootState } from './rootReducer';
|
||||||
|
|
||||||
export interface EditorState {
|
export interface EditorState {
|
||||||
hotkeysEnabled: boolean;
|
hotkeysEnabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: EditorState = {
|
const initialState: EditorState = {
|
||||||
hotkeysEnabled: true,
|
hotkeysEnabled: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const editorSlice = createSlice({
|
export const editorSlice = createSlice({
|
||||||
name: 'editor',
|
name: 'editor',
|
||||||
initialState: initialState,
|
initialState: initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
disableHotkeys(state) {
|
disableHotkeys(state) {
|
||||||
state.hotkeysEnabled = false;
|
state.hotkeysEnabled = false;
|
||||||
},
|
|
||||||
enableHotkeys(state) {
|
|
||||||
state.hotkeysEnabled = true;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
enableHotkeys(state) {
|
||||||
|
state.hotkeysEnabled = true;
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const hotkeysEnabled = (state: RootState): boolean => {
|
export const hotkeysEnabled = (state: RootState): boolean => {
|
||||||
return state.editor.hotkeysEnabled;
|
return state.editor.hotkeysEnabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const { disableHotkeys, enableHotkeys } = editorSlice.actions;
|
export const { disableHotkeys, enableHotkeys } = editorSlice.actions;
|
||||||
export default editorSlice.reducer;
|
export default editorSlice.reducer;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user