diff --git a/packages/editor/src/config/components.js b/packages/editor/src/config/components.js index 938c7c842..b834c7fba 100644 --- a/packages/editor/src/config/components.js +++ b/packages/editor/src/config/components.js @@ -8,7 +8,7 @@ import rightPanel2 from '@ali/iceluna-addon-2'; import rightPanel3 from '@ali/iceluna-addon-2'; import rightPanel4 from '@ali/iceluna-addon-2'; -import PluginFactory from '../framework/plugin'; +import PluginFactory from '../framework/pluginFactory'; export default { topBalloonIcon: PluginFactory(topBalloonIcon), diff --git a/packages/editor/src/config/skeleton.js b/packages/editor/src/config/skeleton.js index 7c59d154b..d01f86973 100644 --- a/packages/editor/src/config/skeleton.js +++ b/packages/editor/src/config/skeleton.js @@ -159,8 +159,7 @@ export default { pluginKey: 'rightPanel1', type: 'Panel', props: { - title: 'panel1', - icon: 'dengpao' + title: '样式' }, config: { package: '@ali/iceluna-addon-2', @@ -172,7 +171,7 @@ export default { pluginKey: 'rightPanel2', type: 'Panel', props: { - title: 'panel2', + title: '属性', icon: 'dengpao' }, config: { @@ -185,8 +184,7 @@ export default { pluginKey: 'rightPanel3', type: 'Panel', props: { - title: 'panel3', - icon: 'dengpao' + title: '事件' }, config: { package: '@ali/iceluna-addon-2', @@ -198,8 +196,7 @@ export default { pluginKey: 'rightPanel4', type: 'Panel', props: { - title: 'panel4', - icon: 'dengpao' + title: '数据' }, config: { package: '@ali/iceluna-addon-2', diff --git a/packages/editor/src/framework/areaManager.ts b/packages/editor/src/framework/areaManager.ts new file mode 100644 index 000000000..f65b25de6 --- /dev/null +++ b/packages/editor/src/framework/areaManager.ts @@ -0,0 +1,31 @@ +import Editor from './index'; +import { PluginConfig, PluginStatus } from './definitions'; +import { clone, deepEqual } from './utils'; + +export default class AreaManager { + private pluginStatus: PluginStatus; + private config: Array; + constructor(private editor: Editor, private area: string) { + this.config = (editor && editor.config && editor.config.plugins && editor.config.plugins[this.area]) || []; + this.pluginStatus = clone(editor.pluginStatus); + } + + isPluginStatusUpdate(): boolean { + const { pluginStatus } = this.editor; + const isUpdate = this.config.some( + item => !deepEqual(pluginStatus[item.pluginKey], this.pluginStatus[item.pluginKey]) + ); + this.pluginStatus = clone(pluginStatus); + return isUpdate; + } + + getVisiblePluginList(): Array { + return this.config.filter(item => { + return !this.pluginStatus[item.pluginKey] || this.pluginStatus[item.pluginKey].visible; + }); + } + + getPluginConfig(): Array { + return this.config; + } +} diff --git a/packages/editor/src/framework/definitions.ts b/packages/editor/src/framework/definitions.ts index e406cd6fa..e43d85d4c 100644 --- a/packages/editor/src/framework/definitions.ts +++ b/packages/editor/src/framework/definitions.ts @@ -125,5 +125,6 @@ export interface PluginStatus { disabled: boolean; visible: boolean; marked: boolean; + locked: boolean; }; } diff --git a/packages/editor/src/framework/index.ts b/packages/editor/src/framework/index.ts index 547d9db52..be8b55d0a 100644 --- a/packages/editor/src/framework/index.ts +++ b/packages/editor/src/framework/index.ts @@ -1,5 +1,5 @@ import Editor from './editor'; -export { default as PluginFactory } from './plugin'; +export { default as PluginFactory } from './pluginFactory'; export { default as EditorContext } from './context'; import * as editorUtils from './utils'; diff --git a/packages/editor/src/framework/plugin.tsx b/packages/editor/src/framework/pluginFactory.tsx similarity index 84% rename from packages/editor/src/framework/plugin.tsx rename to packages/editor/src/framework/pluginFactory.tsx index c89a386bb..c5b038013 100644 --- a/packages/editor/src/framework/plugin.tsx +++ b/packages/editor/src/framework/pluginFactory.tsx @@ -14,7 +14,7 @@ export interface InjectedPluginProps { i18n?: I18nFunction; } -export default function plugin( +export default function pluginFactory( Comp: React.ComponentType ): React.ComponentType { class LowcodePlugin extends PureComponent { @@ -31,7 +31,6 @@ export default function plugin( constructor(props, context) { super(props, context); - if (isEmpty(props.config) || !props.config.pluginKey) { console.warn('lowcode editor plugin has wrong config'); return; @@ -41,8 +40,10 @@ export default function plugin( this.editor = editor; this.i18n = generateI18n(locale, messages); this.pluginKey = props.config.pluginKey; - editor.plugins = editor.plugins || {}; - editor.plugins[this.pluginKey] = this; + editor.set('plugins', { + ...editor.plugins, + [this.pluginKey]: this + }); } componentWillUnmount() { @@ -52,6 +53,14 @@ export default function plugin( } } + open = () => { + return this.ref && this.ref.open && this.ref.open(); + }; + + close = () => { + return this.ref && this.ref.close && this.ref.close(); + }; + render() { const { config } = this.props; return ; diff --git a/packages/editor/src/framework/utils.ts b/packages/editor/src/framework/utils.ts index dd6ace7d4..22b556e4c 100644 --- a/packages/editor/src/framework/utils.ts +++ b/packages/editor/src/framework/utils.ts @@ -1,10 +1,24 @@ import IntlMessageFormat from 'intl-messageformat'; import keymaster from 'keymaster'; -import _isEmpty from 'lodash/isEmpty'; import { EditorConfig, LocaleType, I18nMessages, I18nFunction, ShortCutsConfig } from './definitions'; import Editor from './editor'; +import _pick from 'lodash/pick'; +import _deepEqual from 'lodash/isEqualWith'; +import _clone from 'lodash/cloneDeep'; +import _isEmpty from 'lodash/isEmpty'; +import _throttle from 'lodash/throttle'; +import _debounce from 'lodash/debounce'; + +export const pick = _pick; +export const deepEqual = _deepEqual; +export const clone = _clone; export const isEmpty = _isEmpty; +export const throttle = _throttle; +export const debounce = _debounce; + +import _serialize from 'serialize-javascript'; +export const serialize = _serialize; const ENV = { TBE: 'TBE', diff --git a/packages/editor/src/index.tsx b/packages/editor/src/index.tsx index 1716f05a8..b0c5fee5a 100644 --- a/packages/editor/src/index.tsx +++ b/packages/editor/src/index.tsx @@ -1,6 +1,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; // import Skeleton from '@ali/lowcode-engine-skeleton'; +import { HashRouter as Router, Route } from 'react-router-dom'; import Skeleton from './skeleton'; import config from './config/skeleton'; import components from './config/components'; @@ -21,12 +22,20 @@ if (!ICE_CONTAINER) { } ReactDOM.render( - , + + ( + + )} + /> + , ICE_CONTAINER ); diff --git a/packages/editor/src/skeleton/components/TopIcon/index.scss b/packages/editor/src/skeleton/components/TopIcon/index.scss index a75e4cbd5..67622fb64 100644 --- a/packages/editor/src/skeleton/components/TopIcon/index.scss +++ b/packages/editor/src/skeleton/components/TopIcon/index.scss @@ -14,6 +14,41 @@ &.locked { color: red !important; } + &:hover { + background-color: $color-brand1-1; + color: $color-brand1-6; + &:before { + content: attr(data-tooltip); + display: block; + height: auto; + width: auto; + position: absolute; + left: 50%; + transform: translate(-50%, 0); + bottom: -35px; + line-height: 18px; + font-size: 12px; + white-space: nowrap; + padding: 6px 8px; + border-radius: 4px; + background: rgba(0, 0, 0, 0.75); + color: #fff; + z-index: 100; + } + &:after { + content: ''; + display: block; + position: absolute; + left: 50%; + transform: translate(-50%, 0); + bottom: -5px; + border: 5px solid transparent; + border-bottom-color: rgba(0, 0, 0, 0.75); + opacity: 1; + visibility: visible; + z-index: 100; + } + } i.next-icon { &:before { font-size: 17px; diff --git a/packages/editor/src/skeleton/components/TopIcon/index.tsx b/packages/editor/src/skeleton/components/TopIcon/index.tsx index afd1955f5..64d27a6d7 100644 --- a/packages/editor/src/skeleton/components/TopIcon/index.tsx +++ b/packages/editor/src/skeleton/components/TopIcon/index.tsx @@ -45,6 +45,7 @@ export default class TopIcon extends PureComponent { disabled, locked })} + data-tooltip={title} id={id} style={style} onClick={disabled ? undefined : onClick} diff --git a/packages/editor/src/skeleton/index.tsx b/packages/editor/src/skeleton/index.tsx index f0c606f21..b721c36bb 100644 --- a/packages/editor/src/skeleton/index.tsx +++ b/packages/editor/src/skeleton/index.tsx @@ -22,6 +22,9 @@ let renderIdx = 0; export interface SkeletonProps { components: PluginComponents; config: EditorConfig; + history: object; + location: object; + match: object; utils: Utils; } @@ -99,38 +102,30 @@ export default class Skeleton extends PureComponent - { - const { location, history, match } = props; - location.query = parseSearch(location.search); - this.editor.set('location', location); - this.editor.set('history', history); - this.editor.set('match', match); - return ( - - -
- -
- - - - -
-
-
-
- ); - }} - /> - + + +
+ +
+ + + + +
+
+
+
); } } diff --git a/packages/editor/src/skeleton/layouts/CenterArea/index.tsx b/packages/editor/src/skeleton/layouts/CenterArea/index.tsx index 11b0e3161..95748c593 100644 --- a/packages/editor/src/skeleton/layouts/CenterArea/index.tsx +++ b/packages/editor/src/skeleton/layouts/CenterArea/index.tsx @@ -3,6 +3,7 @@ import React, { PureComponent } from 'react'; import Editor from '../../../framework/editor'; import { PluginConfig } from '../../../framework/definitions'; import './index.scss'; +import AreaManager from '../../../framework/areaManager'; export interface CenterAreaProps { editor: Editor; @@ -12,18 +13,33 @@ export default class CenterArea extends PureComponent { static displayName = 'LowcodeCenterArea'; private editor: Editor; - private config: Array; + private areaManager: AreaManager; constructor(props) { super(props); this.editor = props.editor; - this.config = (this.editor.config && this.editor.config.plugins && this.editor.config.plugins.centerArea) || []; + this.areaManager = new AreaManager(this.editor, 'centerArea'); } + componentDidMount() { + this.editor.on('skeleton.update', this.handleSkeletonUpdate); + } + componentWillUnmount() { + this.editor.off('skeleton.update', this.handleSkeletonUpdate); + } + + handleSkeletonUpdate = (): void => { + // 当前区域插件状态改变是更新区域 + if (this.areaManager.isPluginStatusUpdate()) { + this.forceUpdate(); + } + }; + render() { + const visiblePluginList = this.areaManager.getVisiblePluginList(); return (
- {this.config.map(item => { + {visiblePluginList.map(item => { const Comp = this.editor.components[item.pluginKey]; return ; })} diff --git a/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx b/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx index a792d91ea..10ea81f0b 100644 --- a/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx +++ b/packages/editor/src/skeleton/layouts/LeftArea/nav.tsx @@ -3,6 +3,7 @@ import LeftPlugin from '../../components/LeftPlugin'; import './index.scss'; import Editor from '../../../framework/editor'; import { PluginConfig } from '../../../framework/definitions'; +import AreaManager from '../../../framework/areaManager'; export interface LeftAreaNavProps { editor: Editor; @@ -12,15 +13,29 @@ export default class LeftAreaNav extends PureComponent { static displayName = 'LowcodeLeftAreaNav'; private editor: Editor; - private config: Array; + private areaManager: AreaManager; constructor(props) { super(props); this.editor = props.editor; - this.config = (this.editor.config.plugins && this.editor.config.plugins.leftArea) || []; + this.areaManager = new AreaManager(this.editor, 'leftArea'); } - handlePluginClick = item => {}; + componentDidMount() { + this.editor.on('skeleton.update', this.handleSkeletonUpdate); + } + componentWillUnmount() { + this.editor.off('skeleton.update', this.handleSkeletonUpdate); + } + + handleSkeletonUpdate = (): void => { + // 当前区域插件状态改变是更新区域 + if (this.areaManager.isPluginStatusUpdate()) { + this.forceUpdate(); + } + }; + + handlePluginClick = (item: PluginConfig): void => {}; renderPluginList = (list: Array = []): Array => { return list.map((item, idx) => { @@ -39,7 +54,8 @@ export default class LeftAreaNav extends PureComponent { render() { const topList: Array = []; const bottomList: Array = []; - this.config.forEach(item => { + const visiblePluginList = this.areaManager.getVisiblePluginList(); + visiblePluginList.forEach(item => { const align = item.props && item.props.align === 'bottom' ? 'bottom' : 'top'; if (align === 'bottom') { bottomList.push(item); diff --git a/packages/editor/src/skeleton/layouts/RightArea/index.scss b/packages/editor/src/skeleton/layouts/RightArea/index.scss index 120ef4f11..fd05f5644 100644 --- a/packages/editor/src/skeleton/layouts/RightArea/index.scss +++ b/packages/editor/src/skeleton/layouts/RightArea/index.scss @@ -49,109 +49,4 @@ overflow-y: auto; } } - //组件 - .select-comp { - padding: 10px 16px; - line-height: 16px; - color: #989a9c; - & > span { - font-size: 12px; - line-height: 16px; - font-weight: 400; - } - & > .btn-wrap, - & > .next-btn { - width: auto; - margin: 0 5px; - float: right; - } - } - - .unselected { - padding: 60px 0; - text-align: center; - } - //右侧属性面板样式调整; - .offset-56 { - padding-left: 56px; - margin-bottom: 16px; - overflow: hidden; - } - .fixedSpan.next-form-item { - & > .next-form-item-label { - width: 56px; - flex: none; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - } - & > .next-form-item-control { - padding-right: 24px; - } - } - .fixedSpan.next-form-item, - .offset-56 .next-form-item { - display: flex; - & > .next-form-item-control { - width: auto; - flex: 1; - max-width: none; - .next-input, - .next-select, - .next-radio-group, - .next-number-picker, - .luna-reactnode-btn, - .luna-monaco-button button, - .luna-object-button button { - width: 100%; - } - .next-number-picker { - width: 100%; - .next-after { - padding-right: 5px; - } - } - .next-radio-group { - display: flex; - label { - flex: 1; - text-align: center; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - } - } - } - } - .topSpan.next-form-item { - margin-bottom: 4px; - & > .next-form-item-control { - padding-right: 24px; - .next-input, - .next-select, - .next-radio-group, - .next-number-picker, - .luna-reactnode-btn, - .luna-monaco-button button, - .luna-object-button button { - width: 100%; - } - .next-number-picker { - width: 100%; - .next-after { - padding-right: 5px; - } - } - .next-radio-group { - display: flex; - label { - flex: 1; - text-align: center; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - } - } - } - } } diff --git a/packages/editor/src/skeleton/layouts/RightArea/index.tsx b/packages/editor/src/skeleton/layouts/RightArea/index.tsx index 4f288d08d..77b0fda0b 100644 --- a/packages/editor/src/skeleton/layouts/RightArea/index.tsx +++ b/packages/editor/src/skeleton/layouts/RightArea/index.tsx @@ -1,7 +1,9 @@ import React, { PureComponent } from 'react'; -import { Tab } from '@alifd/next'; +import { Tab, Badge, Icon } from '@alifd/next'; import './index.scss'; import Editor from '../../../framework/editor'; +import { transformToPromise } from '../../../framework/utils'; +import AreaManager from '../../../framework/areaManager'; import { PluginConfig } from '../../../framework/definitions'; export interface RightAreaProps { @@ -16,24 +18,117 @@ export default class RightArea extends PureComponent; + private areaManager: AreaManager; constructor(props) { super(props); this.editor = props.editor; - this.config = (this.editor.config.plugins && this.editor.config.plugins.rightArea) || []; + this.areaManager = new AreaManager(this.editor, 'rightArea'); this.state = { - activeKey: 'rightPanel1' + activeKey: '' }; } - handleTabChange = (key: string): void => { - this.setState({ - activeKey: key - }); + componentDidMount() { + this.editor.on('skeleton.update', this.handleSkeletonUpdate); + this.editor.on('rightNav.change', this.handlePluginChange); + const visiblePluginList = this.areaManager.getVisiblePluginList(); + const defaultKey = (visiblePluginList[0] && visiblePluginList[0].pluginKey) || ''; + this.handlePluginChange(defaultKey, true); + } + componentWillUnmount() { + this.editor.off('skeleton.update', this.handleSkeletonUpdate); + this.editor.off('rightNav.change', this.handlePluginChange); + } + + handleSkeletonUpdate = (): void => { + // 当前区域插件状态改变是更新区域 + if (this.areaManager.isPluginStatusUpdate()) { + const pluginStatus = this.editor.pluginStatus; + const activeKey = this.state.activeKey; + if (pluginStatus[activeKey] && pluginStatus[activeKey].visible) { + this.forceUpdate(); + } else { + const currentPlugin = this.editor.plugins[activeKey]; + if (currentPlugin) { + transformToPromise(currentPlugin.close()).then(() => { + this.setState( + { + activeKey: '' + }, + () => { + const visiblePluginList = this.areaManager.getVisiblePluginList(); + const firstPlugin = visiblePluginList && visiblePluginList[0]; + if (firstPlugin) { + this.handlePluginChange(firstPlugin.pluginKey); + } + } + ); + }); + } + } + } + }; + + handlePluginChange = (key: string, isinit?: boolean): void => { + const activeKey = this.state.activeKey; + const plugins = this.editor.plugins || {}; + const openPlugin = () => { + if (!plugins[key]) { + console.error(`plugin ${key} has not regist in the editor`); + return; + } + transformToPromise(plugins[key].open()).then(() => { + this.editor.set('rightNav', key); + this.setState({ + activeKey: key + }); + }); + }; + if (key === activeKey && !isinit) return; + if (activeKey && plugins[activeKey]) { + transformToPromise(plugins[activeKey].close()).then(() => { + openPlugin(); + }); + } else { + openPlugin(); + } + }; + + renderTabTitle = (config: PluginConfig): React.ReactElement => { + const { icon, title } = config.props || {}; + const pluginStatus = this.editor.pluginStatus[config.pluginKey]; + const { marked, disabled, locked } = pluginStatus; + const active = this.state.activeKey === config.pluginKey; + + const renderTitle = (): React.ReactElement => ( +
+ {!!icon && ( + + )} + {title} +
+ ); + if (marked) { + return {renderTitle()}; + } + return renderTitle(); }; render() { + const visiblePluginList = this.areaManager.getVisiblePluginList(); return (
- {this.config.map((item, idx) => { + {visiblePluginList.map((item, idx) => { const Comp = this.editor.components[item.pluginKey]; return ( - - + + ); })} diff --git a/packages/editor/src/skeleton/layouts/TopArea/index.scss b/packages/editor/src/skeleton/layouts/TopArea/index.scss index 783d48092..98af961da 100644 --- a/packages/editor/src/skeleton/layouts/TopArea/index.scss +++ b/packages/editor/src/skeleton/layouts/TopArea/index.scss @@ -6,7 +6,6 @@ height: 48px; background-color: #ffffff; border-bottom: 1px solid #e8ebee; - overflow: hidden; user-select: none; .divider { max-width: 0; diff --git a/packages/editor/src/skeleton/layouts/TopArea/index.tsx b/packages/editor/src/skeleton/layouts/TopArea/index.tsx index 7d5138508..df8828a9d 100644 --- a/packages/editor/src/skeleton/layouts/TopArea/index.tsx +++ b/packages/editor/src/skeleton/layouts/TopArea/index.tsx @@ -4,6 +4,7 @@ import TopPlugin from '../../components/TopPlugin'; import './index.scss'; import Editor from '../../../framework/index'; import { PluginConfig } from '../../../framework/definitions'; +import AreaManager from '../../../framework/areaManager'; const { Row, Col } = Grid; @@ -14,19 +15,28 @@ export interface TopAreaProps { export default class TopArea extends PureComponent { static displayName = 'LowcodeTopArea'; + private areaManager: AreaManager; private editor: Editor; - private config: Array; constructor(props) { super(props); this.editor = props.editor; - this.config = (this.editor.config.plugins && this.editor.config.plugins.topArea) || []; + this.areaManager = new AreaManager(props.editor, 'topArea'); } - componentDidMount() {} - componentWillUnmount() {} + componentDidMount() { + this.editor.on('skeleton.update', this.handleSkeletonUpdate); + } + componentWillUnmount() { + this.editor.off('skeleton.update', this.handleSkeletonUpdate); + } - handlePluginStatusChange = () => {}; + handleSkeletonUpdate = (): void => { + // 当前区域插件状态改变是更新区域 + if (this.areaManager.isPluginStatusUpdate()) { + this.forceUpdate(); + } + }; renderPluginList = (list: Array = []): Array => { return list.map((item, idx) => { @@ -49,10 +59,10 @@ export default class TopArea extends PureComponent { }; render() { - if (!this.config) return null; const leftList: Array = []; const rightList: Array = []; - this.config.forEach(item => { + const visiblePluginList = this.areaManager.getVisiblePluginList(); + visiblePluginList.forEach(item => { const align = item.props && item.props.align === 'right' ? 'right' : 'left'; // 分隔符不允许相邻 if (item.type === 'Divider') { diff --git a/packages/editor/src/skeleton/skeleton.tsx b/packages/editor/src/skeleton/skeleton.tsx new file mode 100644 index 000000000..7fdec576f --- /dev/null +++ b/packages/editor/src/skeleton/skeleton.tsx @@ -0,0 +1,138 @@ +import React, { PureComponent } from 'react'; + +import { HashRouter as Router, Route } from 'react-router-dom'; +import { Loading, ConfigProvider } from '@alifd/next'; + +import Editor from '../framework/editor'; +import { EditorConfig, Utils, PluginComponents } from '../framework/definitions'; +import { comboEditorConfig, parseSearch } from '../framework/utils'; + +import defaultConfig from './config/skeleton'; +import skeletonUtils from './config/utils'; + +import TopArea from './layouts/TopArea'; +import LeftArea from './layouts/LeftArea'; +import CenterArea from './layouts/CenterArea'; +import RightArea from './layouts/RightArea'; + +import './global.scss'; + +let renderIdx = 0; + +export interface SkeletonProps { + components: PluginComponents; + config: EditorConfig; + utils: Utils; +} + +export interface SkeletonState { + initReady: boolean; + skeletonKey: string; + __hasError?: boolean; +} + +export default class Skeleton extends PureComponent { + static displayName = 'LowcodeEditorSkeleton'; + + static getDerivedStateFromError() { + return { + __hasError: true + }; + } + + private editor: Editor; + + constructor(props) { + super(props); + + this.state = { + initReady: false, + skeletonKey: `skeleton${renderIdx}` + }; + + this.init(); + } + + componentWillUnmount() { + this.editor && this.editor.destroy(); + } + + componentDidCatch(err) { + console.error(err); + } + + init = (isReset: boolean = false): void => { + if (this.editor) { + this.editor.destroy(); + } + const { utils, config, components } = this.props; + debugger; + const editor = (this.editor = new Editor(comboEditorConfig(defaultConfig, config), components, { + ...skeletonUtils, + ...utils + })); + window.__ctx = { + editor, + appHelper: editor + }; + editor.once('editor.reset', () => { + this.setState({ + initReady: false + }); + editor.emit('editor.beforeReset'); + this.init(true); + }); + + this.editor.init().then(() => { + this.setState( + { + initReady: true, + //刷新IDE时生成新的skeletonKey保证插件生命周期重新执行 + skeletonKey: isReset ? `skeleton${++renderIdx}` : this.state.skeletonKey + }, + () => { + editor.emit('editor.ready'); + isReset && editor.emit('ide.afterReset'); + } + ); + }); + }; + + render() { + const { initReady, skeletonKey, __hasError } = this.state; + if (__hasError || !this.editor) { + return 'error'; + } + + return ( + + { + const { location, history, match } = props; + location.query = parseSearch(location.search); + this.editor.set('location', location); + this.editor.set('history', history); + this.editor.set('match', match); + console.log('&&&&&&&&&&'); + return ( + + +
+ +
+ + + + +
+
+
+
+ ); + }} + /> +
+ ); + } +}