This commit is contained in:
Paulo Gustavo Veiga 2022-11-24 02:13:14 -08:00
parent bccd26aad6
commit 506797b8a7
15 changed files with 108 additions and 96 deletions

View File

@ -48,7 +48,12 @@ abstract class ActionDispatcher extends Events {
abstract deleteEntities(topicsIds: number[], relIds: number[]): void;
abstract dragTopic(topicId: number, position: Point, order: number, parentTopic: Topic): void;
abstract dragTopic(
topicId: number,
position: Point,
order: number | null,
parentTopic: Topic | null,
): void;
abstract moveTopic(topicId: number, position: Point): void;

View File

@ -53,7 +53,6 @@ class CentralTopic extends Topic {
this.setPosition(zeroPoint);
}
/** */
getShrinkConnector() {
return null;
}

View File

@ -87,7 +87,7 @@ class Designer extends Events {
// Set up i18n location ...
console.log(`Editor location: ${options.locale}`);
Messages.init(options.locale);
Messages.init(options.locale ? options.locale : 'en');
this._options = options;
@ -263,7 +263,10 @@ class Designer extends Events {
} else {
$assert(targetTopic, 'Could not find a topic to connect');
}
topic.connectTo(targetTopic, this._workspace);
if (targetTopic) {
topic.connectTo(targetTopic, this._workspace);
}
}
topic.addEvent('ontblur', () => {
@ -521,7 +524,7 @@ class Designer extends Events {
const parentTopic = topic.getOutgoingConnectedTopic();
const siblingModel = this._createSiblingModel(topic);
if (siblingModel) {
if (siblingModel && parentTopic) {
// Hack: if parent is central topic, add node below not on opposite side.
// This should be done in the layout
if (parentTopic.getType() === 'CentralTopic') {
@ -724,7 +727,7 @@ class Designer extends Events {
);
// Build relationship line ....
const result = new Relationship(sourceTopic, targetTopic, model);
const result = new Relationship(sourceTopic!, targetTopic!, model);
const me = this;
result.addEvent('ontblur', () => {

View File

@ -37,8 +37,7 @@ export function buildDesigner(options: DesignerOptions): Designer {
// Configure default persistence manager ...
const persistence = options.persistenceManager;
$assert(persistence, 'persistence must be defined');
PersistenceManager.init(persistence);
PersistenceManager.init(persistence!);
// If not manager was specifed, use the readonly one.
const widgetManager = options.widgetManager ? options.widgetManager : new ReadOnlyWidgetManager();

View File

@ -24,7 +24,7 @@ export type DesignerOptions = {
zoom: number;
mode: EditorRenderMode;
mapId?: string;
divContainer?: HTMLElement;
divContainer: HTMLElement;
container: string;
persistenceManager?: PersistenceManager;
widgetManager?: WidgetManager;
@ -36,7 +36,7 @@ class OptionsBuilder {
static buildOptions(options: DesignerOptions): DesignerOptions {
$assert(options.persistenceManager, 'persistence must be defined');
const defaultOptions: DesignerOptions = {
const defaultOptions = {
mode: 'edition-owner',
zoom: 0.85,
saveOnLoad: true,

View File

@ -108,8 +108,6 @@ class DragTopic {
}
connectTo(parent: Topic) {
$assert(parent, 'Parent connection node can not be null.');
// Where it should be connected ?
const predict = this._layoutManager.predict(
parent.getId(),
@ -178,8 +176,8 @@ class DragTopic {
const position = this.getPosition();
if (!this.isFreeLayoutOn()) {
let order = null;
let parent = null;
let order: number | null = null;
let parent: Topic | null = null;
const isDragConnected = this.isConnected();
if (isDragConnected) {
const targetTopic = this.getConnectedToTopic();

View File

@ -23,9 +23,9 @@ import ActionDispatcher from './ActionDispatcher';
import Topic from './Topic';
class MultilineTextEditor extends Events {
private _topic: Topic;
private _topic: Topic | null;
private _containerElem: JQuery;
private _containerElem: JQuery<HTMLElement> | null;
constructor() {
super();
@ -54,7 +54,7 @@ class MultilineTextEditor extends Events {
private _registerEvents(containerElem: JQuery) {
const textareaElem = this._getTextareaElem();
textareaElem.on('keydown', (event) => {
textareaElem?.on('keydown', (event) => {
switch (event.code) {
case 'Escape':
this.close(false);
@ -85,12 +85,12 @@ class MultilineTextEditor extends Events {
event.stopPropagation();
});
textareaElem.on('keypress', (event) => {
textareaElem?.on('keypress', (event) => {
event.stopPropagation();
});
textareaElem.on('keyup', (event) => {
const text = this._getTextareaElem().val();
textareaElem?.on('keyup', (event) => {
const text = this._getTextareaElem()?.val();
this.fireEvent('input', [event, text]);
this._adjustEditorSize();
});
@ -117,22 +117,22 @@ class MultilineTextEditor extends Events {
maxLineLength = Math.max(line.length, maxLineLength);
});
textElem.attr('cols', maxLineLength);
textElem.attr('rows', lines.length);
textElem?.attr('cols', maxLineLength);
textElem?.attr('rows', lines.length);
this._containerElem.css({
this._containerElem?.css({
width: `${maxLineLength + 2}em`,
height: textElem.height(),
height: textElem?.height() || 0,
});
}
}
isVisible(): boolean {
return $defined(this._containerElem) && this._containerElem.css('display') === 'block';
return this._containerElem !== null && this._containerElem.css('display') === 'block';
}
private _updateModel() {
if (this._topic.getText() !== this._getTextAreaText()) {
if (this._topic && this._topic.getText() !== this._getTextAreaText()) {
const text = this._getTextAreaText();
const topicId = this._topic.getId();
@ -167,36 +167,39 @@ class MultilineTextEditor extends Events {
private _showEditor(defaultText: string) {
const topic = this._topic;
if (topic && this._containerElem) {
// Hide topic text ...
topic.getTextShape().setVisibility(false);
// Hide topic text ...
topic.getTextShape().setVisibility(false);
// Set Editor Style
const nodeText = topic.getTextShape();
const fontStyle = nodeText.getFontStyle();
fontStyle.size = nodeText.getHtmlFontSize();
fontStyle.color = nodeText.getColor();
this._setStyle(fontStyle);
// Set Editor Style
const nodeText = topic.getTextShape();
const fontStyle = nodeText.getFontStyle();
fontStyle.size = nodeText.getHtmlFontSize();
fontStyle.color = nodeText.getColor();
this._setStyle(fontStyle);
// Set editor's initial size
// Position the editor and set the size...
const textShape = topic.getTextShape();
// Set editor's initial size
// Position the editor and set the size...
const textShape = topic.getTextShape();
this._containerElem.css('display', 'block');
this._containerElem.css('display', 'block');
let { top, left } = textShape.getNativePosition();
// Adjust padding top position ...
top -= 4;
left -= 4;
this._containerElem.offset({ top, left });
let { top, left } = textShape.getNativePosition();
// Adjust padding top position ...
top -= 4;
left -= 4;
this._containerElem.offset({ top, left });
// Set editor's initial text ...
const text = $defined(defaultText) ? defaultText : topic.getText();
this._setText(text);
// Set editor's initial text ...
const text = $defined(defaultText) ? defaultText : topic.getText();
this._setText(text);
// Set the element focus and select the current text ...
const inputElem = this._getTextareaElem();
this._positionCursor(inputElem, !$defined(defaultText));
// Set the element focus and select the current text ...
const inputElem = this._getTextareaElem();
if (inputElem) {
this._positionCursor(inputElem, !$defined(defaultText));
}
}
}
private _setStyle(fontStyle) {
@ -223,22 +226,22 @@ class MultilineTextEditor extends Events {
fontWeight: fontStyle.weight,
color: fontStyle.color,
};
inputField.css(style);
this._containerElem.css(style);
inputField?.css(style);
this._containerElem?.css(style);
}
private _setText(text: string): void {
const textareaElem = this._getTextareaElem();
textareaElem.val(text);
textareaElem?.val(text);
this._adjustEditorSize();
}
private _getTextAreaText(): string {
return this._getTextareaElem().val() as string;
return this._getTextareaElem()?.val() as string;
}
private _getTextareaElem(): JQuery<HTMLTextAreaElement> {
return this._containerElem.find('textarea');
private _getTextareaElem(): JQuery<HTMLTextAreaElement> | null {
return this._containerElem ? this._containerElem.find('textarea') : null;
}
private _positionCursor(textareaElem: JQuery<HTMLTextAreaElement>, selectText: boolean) {
@ -259,7 +262,7 @@ class MultilineTextEditor extends Events {
}
// Remove it form the screen ...
this._containerElem.remove();
this._containerElem?.remove();
this._containerElem = null;
}

View File

@ -54,7 +54,7 @@ abstract class PersistenceManager {
protected getCSRFToken(): string | null {
const meta = document.head.querySelector('meta[name="_csrf"]');
let result = null;
let result: string | null = null;
if (meta) {
result = meta.getAttribute('content');
}

View File

@ -85,7 +85,7 @@ class ScreenManager {
}
}
fireEvent(type: string, event: UIEvent = null) {
fireEvent(type: string, event?: UIEvent): void {
if (type === 'click') {
this._clickEvents.forEach((listener) => {
listener(type, event);

View File

@ -15,7 +15,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import $ from 'jquery';
import { $assert, $defined } from '@wisemapping/core-js';
import { Rect, Image, Line, Text, Group, ElementClass, Point } from '@wisemapping/web2d';
@ -147,7 +146,7 @@ abstract class Topic extends NodeGraph {
// Move connector to front
const connector = this.getShrinkConnector();
if ($defined(connector)) {
if (connector) {
connector.moveToFront();
}
}
@ -508,7 +507,7 @@ abstract class Topic extends NodeGraph {
}
}
private _setText(text: string, updateModel?: boolean) {
private _setText(text: string | null, updateModel?: boolean) {
const textShape = this.getTextShape();
textShape.setText(text == null ? TopicStyle.defaultText(this) : text);
@ -520,7 +519,7 @@ abstract class Topic extends NodeGraph {
setText(text: string) {
// Avoid empty nodes ...
if (!text || $.trim(text).length === 0) {
if (!text || text.trim().length === 0) {
this._setText(null, true);
} else {
this._setText(text, true);
@ -531,11 +530,8 @@ abstract class Topic extends NodeGraph {
getText(): string {
const model = this.getModel();
let result = model.getText();
if (!$defined(result)) {
result = TopicStyle.defaultText(this);
}
return result;
const text = model.getText();
return text || TopicStyle.defaultText(this);
}
setBackgroundColor(color: string): void {
@ -622,7 +618,7 @@ abstract class Topic extends NodeGraph {
}
const shrinkConnector = this.getShrinkConnector();
if ($defined(shrinkConnector)) {
if (shrinkConnector) {
shrinkConnector.addToWorkspace(group);
}
@ -706,7 +702,7 @@ abstract class Topic extends NodeGraph {
EventBus.instance.fireEvent('childShrinked', model);
}
getShrinkConnector(): ShirinkConnector | undefined {
getShrinkConnector(): ShirinkConnector | null {
let result = this._connector;
if (this._connector == null) {
this._connector = new ShirinkConnector(this);
@ -849,10 +845,10 @@ abstract class Topic extends NodeGraph {
.map((node) => node.getOutgoingLine());
}
getOutgoingConnectedTopic(): Topic {
getOutgoingConnectedTopic(): Topic | null {
let result = null;
const line = this.getOutgoingLine();
if ($defined(line)) {
if (line) {
result = line.getTargetTopic();
}
return result;
@ -875,7 +871,7 @@ abstract class Topic extends NodeGraph {
setBranchVisibility(value: boolean): void {
let current: Topic = this;
let parent: Topic = this;
let parent: Topic | null = this;
while (parent != null && !parent.isCentralTopic()) {
current = parent;
parent = current.getParent();
@ -905,7 +901,7 @@ abstract class Topic extends NodeGraph {
this._relationships.forEach((r) => r.moveToBack());
const connector = this.getShrinkConnector();
if ($defined(connector)) {
if (connector) {
connector.moveToBack();
}
@ -916,7 +912,7 @@ abstract class Topic extends NodeGraph {
moveToFront(): void {
this.get2DElement().moveToFront();
const connector = this.getShrinkConnector();
if ($defined(connector)) {
if (connector) {
connector.moveToFront();
}
// Update relationship lines
@ -951,7 +947,7 @@ abstract class Topic extends NodeGraph {
if (this.getIncomingLines().length > 0) {
const connector = this.getShrinkConnector();
if ($defined(connector)) {
if (connector) {
connector.setVisibility(value, fade);
}
}
@ -970,7 +966,7 @@ abstract class Topic extends NodeGraph {
elem.setOpacity(opacity);
const connector = this.getShrinkConnector();
if ($defined(connector)) {
if (connector) {
connector.setOpacity(opacity);
}
const textShape = this.getTextShape();
@ -1132,7 +1128,7 @@ abstract class Topic extends NodeGraph {
// Display connection node...
const connector = targetTopic.getShrinkConnector();
if ($defined(connector)) {
if (connector) {
connector.setVisibility(true);
}
@ -1190,9 +1186,10 @@ abstract class Topic extends NodeGraph {
EventBus.instance.fireEvent('topicAdded', this.getModel());
}
if (this.getModel().isConnected()) {
const outgoingTopic = this.getOutgoingConnectedTopic();
if (this.getModel().isConnected() && outgoingTopic) {
EventBus.instance.fireEvent('topicConnected', {
parentNode: this.getOutgoingConnectedTopic().getModel(),
parentNode: outgoingTopic.getModel(),
childNode: this.getModel(),
});
}
@ -1212,7 +1209,7 @@ abstract class Topic extends NodeGraph {
// Is the node already connected ?
const targetTopic = this.getOutgoingConnectedTopic();
if ($defined(targetTopic)) {
if (targetTopic) {
result.connectTo(targetTopic);
result.setVisibility(false);
}
@ -1265,19 +1262,18 @@ abstract class Topic extends NodeGraph {
}
private _flatten2DElements(topic: Topic): (Topic | Relationship)[] {
let result = [];
const result: (Topic | Relationship)[] = [];
const children = topic.getChildren();
children.forEach((child) => {
result.push(child);
result.push(child.getOutgoingLine());
const relationships = child.getRelationships();
result = result.concat(relationships);
result.push(...relationships);
if (!child.areChildrenShrunken()) {
const innerChilds = this._flatten2DElements(child);
result = result.concat(innerChilds);
result.push(...innerChilds);
}
});
return result;

View File

@ -18,7 +18,12 @@ abstract class WidgetManager {
return this._instance;
}
private createTooltip(mindmapElement, title: string, linkModel: LinkModel, noteModel: NoteModel) {
private createTooltip(
mindmapElement,
title: string,
linkModel?: LinkModel,
noteModel?: NoteModel,
) {
const webcomponentShadowRoot = $($('#mindmap-comp')[0].shadowRoot);
let tooltip = webcomponentShadowRoot.find('#mindplot-svg-tooltip');
if (!tooltip.length) {
@ -97,7 +102,11 @@ abstract class WidgetManager {
abstract showEditorForLink(topic: Topic, linkModel: LinkModel, linkIcon: LinkIcon): void;
abstract showEditorForNote(topic: Topic, noteModel: NoteModel, noteIcon: NoteIcon): void;
abstract showEditorForNote(
topic: Topic,
noteModel: NoteModel | null,
noteIcon: NoteIcon | null,
): void;
}
export default WidgetManager;

View File

@ -137,10 +137,10 @@ class DeleteCommand extends Command {
this._deletedRelModel = [];
}
private _filterChildren(topicIds: number[], commandContext: CommandContext) {
private _filterChildren(topicIds: number[], commandContext: CommandContext): Topic[] {
const topics = commandContext.findTopics(topicIds);
const result = [];
const result: Topic[] = [];
topics.forEach((topic: Topic) => {
let parent = topic.getParent();
let found = false;

View File

@ -28,7 +28,7 @@ abstract class ChildrenSorterStrategy {
abstract detach(treeSet: RootedTreeSet, node: Node): void;
abstract predict(treeSet: RootedTreeSet, parent, node: Node, position: PositionType);
abstract predict(treeSet: RootedTreeSet, parent, node: Node | null, position: PositionType);
abstract verify(treeSet: RootedTreeSet, node: Node);

View File

@ -128,8 +128,8 @@ class LayoutManager extends Events {
predict(
parentId: number,
nodeId: number,
position: PositionType,
nodeId: number | null,
position: PositionType | null,
): { order: number; position: PositionType } {
$assert($defined(parentId), 'parentId can not be null');
@ -194,7 +194,7 @@ class LayoutManager extends Events {
if (node.hasOrderChanged() || node.hasPositionChanged()) {
// Find or create a event ...
const id = node.getId();
let event: ChangeEvent = this._events.find((e) => e.getId() === id);
let event: ChangeEvent | undefined = this._events.find((e) => e.getId() === id);
if (!event) {
event = new ChangeEvent(id);
}

View File

@ -66,11 +66,11 @@ abstract class INodeModel {
this.putProperty('type', type);
}
setText(text: string): void {
setText(text: string | null): void {
this.putProperty('text', text);
}
getText(): string | undefined {
getText(): string | null {
return this.getProperty('text') as string;
}
@ -290,7 +290,7 @@ abstract class INodeModel {
abstract getProperty(key: string): number | string | boolean;
abstract putProperty(key: string, value: number | string | boolean): void;
abstract putProperty(key: string, value: number | string | boolean | null): void;
abstract setParent(parent: INodeModel): void;