From 4fc015c6dc313a1b013152cb4dba76e4b01cbe0f Mon Sep 17 00:00:00 2001 From: Paulo Gustavo Veiga Date: Fri, 17 Feb 2023 13:25:57 -0800 Subject: [PATCH] Add storybook theme tests --- .../mindplot/cypress/e2e/connection.test.js | 11 ++ packages/mindplot/cypress/e2e/topic.test.js | 6 +- .../connection-classic.snap.png | Bin 0 -> 22295 bytes .../connection-prism.snap.png | Bin 0 -> 25407 bytes .../topic.test.js/topic-shape-none.snap.png | Bin 0 -> 13493 bytes .../src/components/ActionDispatcher.ts | 5 +- packages/mindplot/src/components/Designer.ts | 25 ++-- .../mindplot/src/components/DesignerModel.ts | 4 +- .../mindplot/src/components/EventBusType.ts | 30 ++++ .../src/components/EventDispatcher.ts | 73 ++++++++++ packages/mindplot/src/components/Events.ts | 69 --------- .../src/components/MultilineTextEditor.ts | 6 +- .../components/StandaloneActionDispatcher.ts | 2 +- packages/mindplot/src/components/Topic.ts | 16 +-- .../src/components/TopicEventDispatcher.ts | 26 ++-- .../src/components/layout/EventBus.ts | 21 +-- .../components/layout/EventBusDispatcher.ts | 29 ++-- .../src/components/layout/LayoutEventType.ts | 20 +++ .../src/components/layout/LayoutManager.ts | 5 +- .../src/components/model/ThemeType.ts | 2 +- .../src/components/theme/ThemeFactory.ts | 5 +- .../src/stories/Connection.stories.ts | 30 ++++ .../storybook/src/stories/Connection.ts | 136 ++++++++++++++++++ .../storybook/src/stories/Topic.stories.ts | 17 +++ .../mindplot/storybook/src/stories/Topic.ts | 8 ++ 25 files changed, 400 insertions(+), 146 deletions(-) create mode 100644 packages/mindplot/cypress/e2e/connection.test.js create mode 100644 packages/mindplot/cypress/snapshots/connection.test.js/connection-classic.snap.png create mode 100644 packages/mindplot/cypress/snapshots/connection.test.js/connection-prism.snap.png create mode 100644 packages/mindplot/cypress/snapshots/topic.test.js/topic-shape-none.snap.png create mode 100644 packages/mindplot/src/components/EventBusType.ts create mode 100644 packages/mindplot/src/components/EventDispatcher.ts delete mode 100644 packages/mindplot/src/components/Events.ts create mode 100644 packages/mindplot/src/components/layout/LayoutEventType.ts create mode 100644 packages/mindplot/storybook/src/stories/Connection.stories.ts create mode 100644 packages/mindplot/storybook/src/stories/Connection.ts diff --git a/packages/mindplot/cypress/e2e/connection.test.js b/packages/mindplot/cypress/e2e/connection.test.js new file mode 100644 index 00000000..700fc7b2 --- /dev/null +++ b/packages/mindplot/cypress/e2e/connection.test.js @@ -0,0 +1,11 @@ +context('Connection suite', () => { + it('classic theme', () => { + cy.visit('/iframe.html?args=&id=mindplot-connection--classic&viewMode=story'); + cy.matchImageSnapshot('connection-classic'); + }); + + it('classic prism', () => { + cy.visit('/iframe.html?args=&id=mindplot-connection--prism&viewMode=story'); + cy.matchImageSnapshot('connection-prism'); + }); +}); diff --git a/packages/mindplot/cypress/e2e/topic.test.js b/packages/mindplot/cypress/e2e/topic.test.js index cef9a7df..b5f69642 100644 --- a/packages/mindplot/cypress/e2e/topic.test.js +++ b/packages/mindplot/cypress/e2e/topic.test.js @@ -33,4 +33,8 @@ context('Topic suite', () => { cy.visit('/iframe.html?args=&id=mindplot-topic--shape-ellipse&viewMode=story'); cy.matchImageSnapshot('topic-shape-ellipse'); }); -}); + it('topic none line', () => { + cy.visit('/iframe.html?args=&id=mindplot-topic--shape-none&viewMode=story'); + cy.matchImageSnapshot('topic-shape-none'); + }); +}); \ No newline at end of file diff --git a/packages/mindplot/cypress/snapshots/connection.test.js/connection-classic.snap.png b/packages/mindplot/cypress/snapshots/connection.test.js/connection-classic.snap.png new file mode 100644 index 0000000000000000000000000000000000000000..e1685fb97d7cafac7217fc916cd155c9258fd693 GIT binary patch literal 22295 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 literal 0 HcmV?d00001 diff --git a/packages/mindplot/cypress/snapshots/connection.test.js/connection-prism.snap.png b/packages/mindplot/cypress/snapshots/connection.test.js/connection-prism.snap.png new file mode 100644 index 0000000000000000000000000000000000000000..ee3524fbf955ef50939892b60170aef787de3102 GIT binary patch literal 25407 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 QcVxJk|8mHr!iW_44?(&sH~;_u literal 0 HcmV?d00001 diff --git a/packages/mindplot/cypress/snapshots/topic.test.js/topic-shape-none.snap.png b/packages/mindplot/cypress/snapshots/topic.test.js/topic-shape-none.snap.png new file mode 100644 index 0000000000000000000000000000000000000000..8e9c7195c84899a862d20f484877468513919127 GIT binary patch literal 13493 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 { private static _instance: ActionDispatcher; private _commandContext: CommandContext; diff --git a/packages/mindplot/src/components/Designer.ts b/packages/mindplot/src/components/Designer.ts index b45130f3..c71c42ed 100644 --- a/packages/mindplot/src/components/Designer.ts +++ b/packages/mindplot/src/components/Designer.ts @@ -20,7 +20,7 @@ import $ from 'jquery'; import { $assert, $defined } from '@wisemapping/core-js'; import Messages, { $msg } from './Messages'; -import Events from './Events'; +import EventDispispatcher from './EventDispatcher'; import StandaloneActionDispatcher from './StandaloneActionDispatcher'; import CommandContext from './CommandContext'; @@ -37,7 +37,7 @@ import DragManager from './DragManager'; import RelationshipPivot from './RelationshipPivot'; import Relationship from './Relationship'; -import TopicEventDispatcher, { TopicEvent } from './TopicEventDispatcher'; +import TopicEventDispatcher from './TopicEventDispatcher'; import TopicFactory from './TopicFactory'; import EventBus from './layout/EventBus'; @@ -62,8 +62,11 @@ import ImageExpoterFactory from './export/ImageExporterFactory'; import PositionType from './PositionType'; import ThemeType from './model/ThemeType'; import ThemeFactory from './theme/ThemeFactory'; +import ChangeEvent from './layout/ChangeEvent'; -class Designer extends Events { +type DesignerEventType = 'modelUpdate' | 'onfocus' | 'onblur' | 'loadSuccess'; + +class Designer extends EventDispispatcher { private _mindmap: Mindmap | null; private _options: DesignerOptions; @@ -159,14 +162,9 @@ class Designer extends Events { return this._actionDispatcher; } - addEvent(type: string, listener): Events { - if (type === TopicEvent.EDIT || type === TopicEvent.CLICK) { - const editor = TopicEventDispatcher.getInstance(); - editor.addEvent(type, listener); - } else { - super.addEvent(type, listener); - } - return this; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + addEvent(type: DesignerEventType, listener: (event: (args?: any) => void) => void): void { + super.addEvent(type, listener); } private _registerMouseEvents() { @@ -619,7 +617,8 @@ class Designer extends Events { // Init layout manager ... const size = { width: 25, height: 25 }; const layoutManager = new LayoutManager(mindmap.getCentralTopic().getId(), size); - layoutManager.addEvent('change', (event) => { + + layoutManager.addEvent('change', (event: ChangeEvent) => { const id = event.getId(); const topic = this.getModel().findTopicById(id); if (topic) { @@ -627,6 +626,7 @@ class Designer extends Events { topic.setOrder(event.getOrder()); } }); + this._eventBussDispatcher.setLayoutManager(layoutManager); // Building node graph ... @@ -652,6 +652,7 @@ class Designer extends Events { // Enable workspace drag events ... this._canvas.registerEvents(); + // Finally, sort the map ... EventBus.instance.fireEvent('forceLayout'); this.fireEvent('loadSuccess'); diff --git a/packages/mindplot/src/components/DesignerModel.ts b/packages/mindplot/src/components/DesignerModel.ts index f59bb4e8..04f2f3ed 100644 --- a/packages/mindplot/src/components/DesignerModel.ts +++ b/packages/mindplot/src/components/DesignerModel.ts @@ -18,12 +18,11 @@ import { $assert } from '@wisemapping/core-js'; import CentralTopic from './CentralTopic'; import { DesignerOptions } from './DesignerOptionsBuilder'; -import Events from './Events'; import Relationship from './Relationship'; import Topic from './Topic'; import { $notify } from './model/ToolbarNotifier'; -class DesignerModel extends Events { +class DesignerModel { private _zoom: number; private _topics: Topic[]; @@ -31,7 +30,6 @@ class DesignerModel extends Events { private _relationships: Relationship[]; constructor(options: DesignerOptions) { - super(); this._zoom = options.zoom; this._topics = []; this._relationships = []; diff --git a/packages/mindplot/src/components/EventBusType.ts b/packages/mindplot/src/components/EventBusType.ts new file mode 100644 index 00000000..a99f9e7a --- /dev/null +++ b/packages/mindplot/src/components/EventBusType.ts @@ -0,0 +1,30 @@ +/* + * Copyright [2021] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export type EventBusType = + | 'topicResize' + | 'topicMoved' + | 'forceLayout' + | 'childShrinked' + | 'topicConnected' + | 'topicAdded' + | 'topicRemoved' + | 'topicDisconect' + | 'modelUpdate'; + +export default EventBusType; diff --git a/packages/mindplot/src/components/EventDispatcher.ts b/packages/mindplot/src/components/EventDispatcher.ts new file mode 100644 index 00000000..f353cae6 --- /dev/null +++ b/packages/mindplot/src/components/EventDispatcher.ts @@ -0,0 +1,73 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* + * Copyright [2021] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class EventDispispatcher { + private _handlerByType: Map void)[]>; + + constructor() { + this._handlerByType = new Map(); + } + + private static _normalizeEventName(value: K): K { + return String(value).replace(/^on([A-Z])/, (_full, first) => first.toLowerCase()) as K; + } + + addEvent(typeName: T, fn: (args?: any) => void, internal?: boolean): void { + const type = EventDispispatcher._normalizeEventName(typeName); + + let events = this._handlerByType.get(type); + // Add function had not been added yet + events = events || []; + if (events && !events.includes(fn)) { + events.push(fn); + this._handlerByType.set(type, events); + } + + // Mark reference ... + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + fn.internal = Boolean(internal); + } + + fireEvent(typeName: T, arg?: any): void { + const type = EventDispispatcher._normalizeEventName(typeName); + const events = this._handlerByType.get(type); + if (events) { + const args: any = arg ? [arg] : []; + events.forEach((fn) => { + fn.apply(this, args); + }); + } + } + + removeEvent(typeName: T, fn: (...args: any) => void): void { + const type = EventDispispatcher._normalizeEventName(typeName); + const events = this._handlerByType.get(type); + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + if (events && !fn.internal) { + const index = events.indexOf(fn); + if (index !== -1) { + events.splice(index, 1); + } + } + } +} + +export default EventDispispatcher; diff --git a/packages/mindplot/src/components/Events.ts b/packages/mindplot/src/components/Events.ts deleted file mode 100644 index 67ba0c8e..00000000 --- a/packages/mindplot/src/components/Events.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright [2021] [wisemapping] - * - * Licensed under WiseMapping Public License, Version 1.0 (the "License"). - * It is basically the Apache License, Version 2.0 (the "License") plus the - * "powered by wisemapping" text requirement on every single page; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the license at - * - * http://www.wisemapping.org/license - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -class Events { - protected _handlerByType; - - constructor() { - this._handlerByType = {}; - } - - static _normalizeEventName(string: string) { - return string.replace(/^on([A-Z])/, (_full, first) => first.toLowerCase()); - } - - addEvent(typeName: string, fn?, internal?: boolean): Events { - const type = Events._normalizeEventName(typeName); - - // Add function had not been added yet - const funByType = this._handlerByType[type] ? this._handlerByType[type] : []; - if (!funByType.includes(fn)) { - funByType.push(fn); - this._handlerByType[type] = funByType; - } - - // Mark reference ... - fn.internal = Boolean(internal); - return this; - } - - fireEvent(typeName: string, eventArgs?): Events { - const type = Events._normalizeEventName(typeName); - const events = this._handlerByType[type]; - if (!events) return this; - - const args = Array.isArray(eventArgs) ? eventArgs : [eventArgs]; - events.forEach((fn) => { - // Execute our of the main thread... - fn.apply(this, args); - }); - return this; - } - - removeEvent(typeName: string, fn?): Events { - const type = Events._normalizeEventName(typeName); - const events = this._handlerByType[type]; - if (events && !fn.internal) { - const index = events.indexOf(fn); - if (index !== -1) events.splice(index, 1); - } - return this; - } -} - -export default Events; diff --git a/packages/mindplot/src/components/MultilineTextEditor.ts b/packages/mindplot/src/components/MultilineTextEditor.ts index 1c69233f..fcd32297 100644 --- a/packages/mindplot/src/components/MultilineTextEditor.ts +++ b/packages/mindplot/src/components/MultilineTextEditor.ts @@ -20,11 +20,13 @@ import { FontStyle } from '@wisemapping/web2d/src/components/peer/svg/FontPeer'; import $ from 'jquery'; import ActionDispatcher from './ActionDispatcher'; -import Events from './Events'; +import EventDispatcher from './EventDispatcher'; import EventBus from './layout/EventBus'; import Topic from './Topic'; -class EditorComponent extends Events { +type EditorEventType = 'input'; + +class EditorComponent extends EventDispatcher { private _topic: Topic; private _oldText: string | undefined; diff --git a/packages/mindplot/src/components/StandaloneActionDispatcher.ts b/packages/mindplot/src/components/StandaloneActionDispatcher.ts index 5d1e1702..0875a9e4 100644 --- a/packages/mindplot/src/components/StandaloneActionDispatcher.ts +++ b/packages/mindplot/src/components/StandaloneActionDispatcher.ts @@ -55,7 +55,7 @@ class StandaloneActionDispatcher extends ActionDispatcher { this._actionRunner = new DesignerActionRunner(commandContext, this); } - addTopics(models: NodeModel[], parentTopicsId: number[] | null) { + addTopics(models: NodeModel[], parentTopicsId: number[] | null): void { const command = new AddTopicCommand(models, parentTopicsId); this.execute(command); } diff --git a/packages/mindplot/src/components/Topic.ts b/packages/mindplot/src/components/Topic.ts index 14cc0cb2..a72105c0 100644 --- a/packages/mindplot/src/components/Topic.ts +++ b/packages/mindplot/src/components/Topic.ts @@ -27,7 +27,7 @@ import EventBus from './layout/EventBus'; import ShirinkConnector from './ShrinkConnector'; import ActionDispatcher from './ActionDispatcher'; -import TopicEventDispatcher, { TopicEvent } from './TopicEventDispatcher'; +import TopicEventDispatcher from './TopicEventDispatcher'; import { TopicShapeType } from './model/INodeModel'; import NodeModel from './model/NodeModel'; import Relationship from './Relationship'; @@ -528,7 +528,7 @@ abstract class Topic extends NodeGraph { } const eventDispatcher = me._getTopicEventDispatcher(); - eventDispatcher.process(TopicEvent.CLICK, me); + eventDispatcher.process('clicknode', me); event.stopPropagation(); }); } @@ -594,7 +594,7 @@ abstract class Topic extends NodeGraph { getShrinkConnector(): ShirinkConnector | null { let result = this._connector; - if (this._connector == null) { + if (!this._connector) { this._connector = new ShirinkConnector(this); this._connector.setVisibility(false); result = this._connector; @@ -693,11 +693,8 @@ abstract class Topic extends NodeGraph { * Point: references the center of the rect shape.!!! */ setPosition(point: PositionType): void { - $assert(point, 'position can not be null'); // allowed param reassign to avoid risks of existing code relying in this side-effect - // eslint-disable-next-line no-param-reassign point.x = Math.ceil(point.x); - // eslint-disable-next-line no-param-reassign point.y = Math.ceil(point.y); // Update model's position ... @@ -721,7 +718,6 @@ abstract class Topic extends NodeGraph { this.invariant(); } - /** */ getOutgoingLine(): ConnectionLine | null { return this._outgoingLine; } @@ -959,7 +955,7 @@ abstract class Topic extends NodeGraph { this.redraw(); } - connectTo(targetTopic: Topic, workspace: Canvas): void { + connectTo(targetTopic: Topic, canvas: Canvas): void { // Connect Graphical Nodes ... targetTopic.append(this); this._parent = targetTopic; @@ -971,10 +967,10 @@ abstract class Topic extends NodeGraph { // Create a connection line ... const outgoingLine = this.createConnectionLine(targetTopic); - outgoingLine.setVisibility(false); + // outgoingLine.setVisibility(false); this._outgoingLine = outgoingLine; - workspace.append(outgoingLine); + canvas.append(outgoingLine); // Update figure is necessary. this.updateTopicShape(targetTopic); diff --git a/packages/mindplot/src/components/TopicEventDispatcher.ts b/packages/mindplot/src/components/TopicEventDispatcher.ts index e22743f7..3c2ef9f9 100644 --- a/packages/mindplot/src/components/TopicEventDispatcher.ts +++ b/packages/mindplot/src/components/TopicEventDispatcher.ts @@ -15,20 +15,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import Events from './Events'; +import EventDispispatcher from './EventDispatcher'; import Topic from './Topic'; import MultitTextEditor from './MultilineTextEditor'; -const TopicEvent = { - EDIT: 'editnode', - CLICK: 'clicknode', -}; +type TopicEventType = 'editnode' | 'clicknode'; -class TopicEventDispatcher extends Events { +class TopicEventDispatcher extends EventDispispatcher { private _readOnly: boolean; // eslint-disable-next-line no-use-before-define - static _instance: TopicEventDispatcher; + private static _instance: TopicEventDispatcher; constructor(readOnly: boolean) { super(); @@ -43,10 +40,10 @@ class TopicEventDispatcher extends Events { } show(topic: Topic, textOverwrite?: string): void { - this.process(TopicEvent.EDIT, topic, textOverwrite); + this.process('editnode', topic, textOverwrite); } - process(eventType: string, topic: Topic, textOverwrite?: string): void { + process(eventType: TopicEventType, topic: Topic, textOverwrite?: string): void { // Close all previous open editor .... const editor = MultitTextEditor.getInstance(); if (editor.isActive()) { @@ -55,7 +52,7 @@ class TopicEventDispatcher extends Events { // Open the new editor ... const model = topic.getModel(); - if (!this._readOnly && eventType === TopicEvent.EDIT) { + if (!this._readOnly && eventType === 'editnode') { editor.show(topic, textOverwrite); } else { this.fireEvent(eventType, { model, readOnly: this._readOnly }); @@ -66,8 +63,13 @@ class TopicEventDispatcher extends Events { return MultitTextEditor.getInstance().isActive(); } - static configure(readOnly: boolean): void { + static configure(readOnly: boolean): TopicEventDispatcher { + if (this._instance) { + throw new Error('events already initialized'); + } + this._instance = new TopicEventDispatcher(readOnly); + return this._instance; } static getInstance(): TopicEventDispatcher { @@ -77,6 +79,4 @@ class TopicEventDispatcher extends Events { return this._instance; } } - -export { TopicEvent }; export default TopicEventDispatcher; diff --git a/packages/mindplot/src/components/layout/EventBus.ts b/packages/mindplot/src/components/layout/EventBus.ts index f5727e36..16184510 100644 --- a/packages/mindplot/src/components/layout/EventBus.ts +++ b/packages/mindplot/src/components/layout/EventBus.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ /* * Copyright [2021] [wisemapping] * @@ -15,18 +16,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import Events from '../Events'; +import EventDispispatcher from '../EventDispatcher'; +import { EventBusType } from '../EventBusType'; -export type EventType = - | 'topicResize' - | 'topicMoved' - | 'childShrinked' - | 'topicConnected' - | 'topicAdded' - | 'topicRemoved' - | 'forceLayout' - | 'topicDisconect'; -class EventBus extends Events { +class EventBus extends EventDispispatcher { // eslint-disable-next-line no-use-before-define static _instance: EventBus = new EventBus(); @@ -34,11 +27,11 @@ class EventBus extends Events { return this._instance; } - fireEvent(type: EventType, eventArgs?: unknown[] | unknown): Events { - return super.fireEvent(type, eventArgs); + fireEvent(type: EventBusType, arg?: any): void { + return super.fireEvent(type, arg); } - addEvent(type: EventType, fn?, internal?: boolean): Events { + addEvent(type: EventBusType, fn: (arg?: any) => void, internal?: boolean): void { return super.addEvent(type, fn, internal); } } diff --git a/packages/mindplot/src/components/layout/EventBusDispatcher.ts b/packages/mindplot/src/components/layout/EventBusDispatcher.ts index d73045a3..c9cd7fcd 100644 --- a/packages/mindplot/src/components/layout/EventBusDispatcher.ts +++ b/packages/mindplot/src/components/layout/EventBusDispatcher.ts @@ -45,15 +45,15 @@ class EventBusDispatcher { } private _topicResizeEvent(args: { node: Topic; size: SizeType }) { - this._layoutManager!.updateNodeSize(args.node.getId(), args.size); + this.getLayoutManager().updateNodeSize(args.node.getId(), args.size); } private _topicMoved(args: { node: Topic; position: PositionType }) { - this._layoutManager!.moveNode(args.node.getId(), args.position); + this.getLayoutManager().moveNode(args.node.getId(), args.position); } private _topicDisconect(node: Topic) { - this._layoutManager!.disconnectNode(node.getId()); + this.getLayoutManager().disconnectNode(node.getId()); } private _topicConnected(args: { parentNode: Topic; childNode: Topic }) { @@ -64,28 +64,31 @@ class EventBusDispatcher { ); } + getLayoutManager(): LayoutManager { + if (!this._layoutManager) { + throw new Error('Layout not initialized'); + } + return this._layoutManager; + } + private _childShrinked(node: Topic) { - this._layoutManager!.updateShrinkState(node.getId(), node.areChildrenShrunken()); + this.getLayoutManager().updateShrinkState(node.getId(), node.areChildrenShrunken()); } private _topicAdded(node: Topic) { // Central topic must not be added twice ... if (node.getId() !== 0) { - this._layoutManager!.addNode(node.getId(), { width: 10, height: 10 }, node.getPosition()); - this._layoutManager!.updateShrinkState(node.getId(), node.areChildrenShrunken()); + this.getLayoutManager().addNode(node.getId(), { width: 10, height: 10 }, node.getPosition()); + this.getLayoutManager().updateShrinkState(node.getId(), node.areChildrenShrunken()); } } private _topicRemoved(node: Topic) { - this._layoutManager!.removeNode(node.getId()); + this.getLayoutManager().removeNode(node.getId()); } - private _forceLayout() { - this._layoutManager!.layout(true); - } - - getLayoutManager(): LayoutManager { - return this._layoutManager!; + private _forceLayout(): void { + this.getLayoutManager().layout(true); } } diff --git a/packages/mindplot/src/components/layout/LayoutEventType.ts b/packages/mindplot/src/components/layout/LayoutEventType.ts new file mode 100644 index 00000000..fa88ac77 --- /dev/null +++ b/packages/mindplot/src/components/layout/LayoutEventType.ts @@ -0,0 +1,20 @@ +/* + * Copyright [2021] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +type LayoutEventType = 'change' | 'forceLayout'; + +export default LayoutEventType; diff --git a/packages/mindplot/src/components/layout/LayoutManager.ts b/packages/mindplot/src/components/layout/LayoutManager.ts index 297c6e20..5e048439 100644 --- a/packages/mindplot/src/components/layout/LayoutManager.ts +++ b/packages/mindplot/src/components/layout/LayoutManager.ts @@ -16,15 +16,16 @@ * limitations under the License. */ import { $assert, $defined } from '@wisemapping/core-js'; -import Events from '../Events'; +import EventDispispatcher from '../EventDispatcher'; import RootedTreeSet from './RootedTreeSet'; import OriginalLayout from './OriginalLayout'; import ChangeEvent from './ChangeEvent'; import SizeType from '../SizeType'; import Node from './Node'; import PositionType from '../PositionType'; +import LayoutEventType from './LayoutEventType'; -class LayoutManager extends Events { +class LayoutManager extends EventDispispatcher { private _treeSet: RootedTreeSet; private _layout: OriginalLayout; diff --git a/packages/mindplot/src/components/model/ThemeType.ts b/packages/mindplot/src/components/model/ThemeType.ts index e3c171a5..1878efc6 100644 --- a/packages/mindplot/src/components/model/ThemeType.ts +++ b/packages/mindplot/src/components/model/ThemeType.ts @@ -15,6 +15,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -type ThemeType = 'classic' | 'prism'; +type ThemeType = 'classic' | 'prism' | 'dark-prism'; export default ThemeType; diff --git a/packages/mindplot/src/components/theme/ThemeFactory.ts b/packages/mindplot/src/components/theme/ThemeFactory.ts index 4dee6af6..8f842bd7 100644 --- a/packages/mindplot/src/components/theme/ThemeFactory.ts +++ b/packages/mindplot/src/components/theme/ThemeFactory.ts @@ -1,11 +1,10 @@ import NodeModel from '../model/NodeModel'; +import ThemeType from '../model/ThemeType'; import ClassicTheme from './ClassicTheme'; import DarkPrismTheme from './DarkPrismTheme'; import PrismTheme from './PrismTheme'; import Theme from './Theme'; -type ThemeId = 'prism' | 'classic' | 'dark-prism'; - class ThemeFactory { private static prismTheme = new PrismTheme(); @@ -13,7 +12,7 @@ class ThemeFactory { private static classicTheme = new ClassicTheme(); - static createById(id: ThemeId): Theme { + static createById(id: ThemeType): Theme { let result: Theme; switch (id) { case 'classic': diff --git a/packages/mindplot/storybook/src/stories/Connection.stories.ts b/packages/mindplot/storybook/src/stories/Connection.stories.ts new file mode 100644 index 00000000..fabeef54 --- /dev/null +++ b/packages/mindplot/storybook/src/stories/Connection.stories.ts @@ -0,0 +1,30 @@ +import { Story, Meta } from '@storybook/html'; +import createConnection, { TopicArgs } from './Connection'; + +export default { + title: 'Mindplot/Connection', + // More on argTypes: https://storybook.js.org/docs/html/api/argtypes + argTypes: { + shapeType: { + options: ['none', 'rectangle', 'rounded rectangle', 'elipse', 'line'], + control: { type: 'select' }, + }, + }, +} as Meta; + +const Template: Story = (args: TopicArgs) => createConnection(args); + +export const Classic = Template.bind({}); +Classic.args = { + theme: 'classic', +}; + +export const Prism = Template.bind({}); +Prism.args = { + theme: 'prism', +}; + +export const DarkPrism = Template.bind({}); +DarkPrism.args = { + theme: 'dark-prism', +}; diff --git a/packages/mindplot/storybook/src/stories/Connection.ts b/packages/mindplot/storybook/src/stories/Connection.ts new file mode 100644 index 00000000..dd8c6f23 --- /dev/null +++ b/packages/mindplot/storybook/src/stories/Connection.ts @@ -0,0 +1,136 @@ +import $ from 'jquery'; + +import { Mindmap, Topic } from '../../../src'; +import NodeModel from '../../../src/components/model/NodeModel'; +import CentralTopic from '../../../src/components/CentralTopic'; +import Canvas from '../../../src/components/Canvas'; +import ScreenManager from '../../../src/components/ScreenManager'; +import TopicEventDispatcher from '../../../src/components/TopicEventDispatcher'; +import ThemeType from '../../../src/components/model/ThemeType'; +import MainTopic from '../../../src/components/MainTopic'; +import EventBusDispatcher from '../../../src/components/layout/EventBusDispatcher'; +import LayoutManager from '../../../src/components/layout/LayoutManager'; +import ChangeEvent from '../../../src/components/layout/ChangeEvent'; +import EventBus from '../../../src/components/layout/EventBus'; + +const registerRefreshHook = (topics: Topic[]) => { + // Trigger a redraw after the node is added ... + if (globalThis.observer) { + globalThis.observer.disconnect(); + } + + globalThis.observer = new MutationObserver(() => { + // Relayout... + topics.forEach((t) => t.redraw()); + EventBus.instance.fireEvent('forceLayout'); + }); + globalThis.observer.observe(document.getElementById('root')!, { childList: true }); +}; + +export type TopicArgs = { + readOnly?: boolean; + theme?: ThemeType; +}; + +const createConnection = ({ theme = undefined, readOnly = true }: TopicArgs) => { + // Build basic container ... + const divElem = document.createElement('div'); + const jqueryDiv = $(divElem); + jqueryDiv.css({ + height: '600px', + width: '800px', + backgroundColor: 'gray', + }); + + // Initialize designer helpers ... + const screenManager = new ScreenManager(divElem); + const canvas = new Canvas(screenManager, 0.7, readOnly); + TopicEventDispatcher.configure(readOnly); + + // Register event propagation .. + const mindmap = new Mindmap(); + const central = new NodeModel('CentralTopic', mindmap); + central.setText('Central Topic'); + mindmap.addBranch(central); + + // Add Children ... + const child1 = new NodeModel('MainTopic', mindmap); + child1.setOrder(0); + child1.setText('This is child one !\nwith other line'); + child1.setPosition(100, 100); + + const child2 = new NodeModel('MainTopic', mindmap); + child2.setOrder(1); + child2.setPosition(100, -100); + + const child3 = new NodeModel('MainTopic', mindmap); + child3.setOrder(0); + child3.setPosition(-100, 100); + + const child4 = new NodeModel('MainTopic', mindmap); + child4.setOrder(1); + child4.setPosition(-100, -100); + + const subchild1 = new NodeModel('MainTopic', mindmap); + subchild1.setOrder(0); + subchild1.setPosition(300, 80); + + const subchild2 = new NodeModel('MainTopic', mindmap); + subchild2.setOrder(1); + subchild2.setPosition(300, 120); + + // Theme ... + if (theme) { + mindmap.setTheme(theme); + } + + // Create and add to canvas.. + const centralTopic = new CentralTopic(central, { readOnly }); + + const child1Topic = new MainTopic(child1, { readOnly }); + const child2Topic = new MainTopic(child2, { readOnly }); + const child3Topic = new MainTopic(child3, { readOnly }); + const child4Topic = new MainTopic(child4, { readOnly }); + const subchild1Topic = new MainTopic(subchild1, { readOnly }); + const subchild2Topic = new MainTopic(subchild2, { readOnly }); + const topics = [ + child1Topic, + child2Topic, + child3Topic, + child4Topic, + centralTopic, + subchild1Topic, + subchild2Topic, + ]; + + // Configure event dispatcher ... + const dispatcher = new EventBusDispatcher(); + const size = { width: 25, height: 25 }; + const layoutManager = new LayoutManager(mindmap.getCentralTopic().getId(), size); + dispatcher.setLayoutManager(layoutManager); + layoutManager.addEvent('change', (event: ChangeEvent) => { + const id = event.getId(); + const topic = topics.filter((t) => t.getModel().getId() === id)[0]; + + topic.setPosition(event.getPosition()); + topic.setOrder(event.getOrder()); + }); + + // Add to canvas ... + topics.forEach((t) => canvas.append(t)); + + // Connect nodes ... + child1Topic.connectTo(centralTopic, canvas); + child2Topic.connectTo(centralTopic, canvas); + child3Topic.connectTo(centralTopic, canvas); + child4Topic.connectTo(centralTopic, canvas); + subchild1Topic.connectTo(child1Topic, canvas); + subchild2Topic.connectTo(child1Topic, canvas); + + // Register refresh hook .. + registerRefreshHook(topics); + + return divElem; +}; + +export default createConnection; diff --git a/packages/mindplot/storybook/src/stories/Topic.stories.ts b/packages/mindplot/storybook/src/stories/Topic.stories.ts index eef2bc82..ef0af565 100644 --- a/packages/mindplot/storybook/src/stories/Topic.stories.ts +++ b/packages/mindplot/storybook/src/stories/Topic.stories.ts @@ -21,6 +21,7 @@ export default { noteText: { control: 'text' }, linkText: { control: 'text' }, eicon: { control: 'multi-select', options: ['❤️', '🌈', '🖇️'] }, + theme: { control: 'select', options: ['classic', 'prism', 'dark-prism'] }, }, } as Meta; @@ -83,3 +84,19 @@ ShapeNone.args = { eicon: ['🌈'], shapeType: 'none', }; + +export const ThemeClassic = Template.bind({}); +ThemeClassic.args = { + text: 'Theme Classic', + eicon: ['🌈'], + shapeType: 'none', + theme: 'classic', +}; + +export const ThemePrime = Template.bind({}); +ThemePrime.args = { + text: 'Theme Prime', + eicon: ['🌈'], + shapeType: 'none', + theme: 'prism', +}; diff --git a/packages/mindplot/storybook/src/stories/Topic.ts b/packages/mindplot/storybook/src/stories/Topic.ts index 1545cbec..0e2bf47a 100644 --- a/packages/mindplot/storybook/src/stories/Topic.ts +++ b/packages/mindplot/storybook/src/stories/Topic.ts @@ -8,6 +8,7 @@ import ScreenManager from '../../../src/components/ScreenManager'; import EmojiIconModel from '../../../src/components/model/EmojiIconModel'; import TopicEventDispatcher from '../../../src/components/TopicEventDispatcher'; import { TopicShapeType } from '../../../src/components/model/INodeModel'; +import ThemeType from '../../../src/components/model/ThemeType'; const registerRefreshHook = (topic: Topic) => { // Trigger a redraw after the node is added ... @@ -34,6 +35,7 @@ export type TopicArgs = { noteText?: string; linkText?: string; eicon?: string[]; + theme?: ThemeType; }; const createTopic = ({ @@ -47,6 +49,7 @@ const createTopic = ({ noteText = undefined, linkText = undefined, eicon = undefined, + theme = undefined, readOnly = true, }: TopicArgs) => { // Build basic container ... @@ -92,6 +95,11 @@ const createTopic = ({ }); } + // Theme ... + if (theme) { + mindmap.setTheme(theme); + } + // Create topic UI element ... mindmap.addBranch(model); const centralTopic = new CentralTopic(model, { readOnly });