mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-14 13:03:07 +00:00
daily tag
This commit is contained in:
parent
baa6adb199
commit
8eb0851e4c
@ -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),
|
||||
|
||||
@ -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',
|
||||
|
||||
31
packages/editor/src/framework/areaManager.ts
Normal file
31
packages/editor/src/framework/areaManager.ts
Normal file
@ -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<PluginConfig>;
|
||||
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<PluginConfig> {
|
||||
return this.config.filter(item => {
|
||||
return !this.pluginStatus[item.pluginKey] || this.pluginStatus[item.pluginKey].visible;
|
||||
});
|
||||
}
|
||||
|
||||
getPluginConfig(): Array<PluginConfig> {
|
||||
return this.config;
|
||||
}
|
||||
}
|
||||
@ -125,5 +125,6 @@ export interface PluginStatus {
|
||||
disabled: boolean;
|
||||
visible: boolean;
|
||||
marked: boolean;
|
||||
locked: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -14,7 +14,7 @@ export interface InjectedPluginProps {
|
||||
i18n?: I18nFunction;
|
||||
}
|
||||
|
||||
export default function plugin(
|
||||
export default function pluginFactory(
|
||||
Comp: React.ComponentType<PluginProps & InjectedPluginProps>
|
||||
): React.ComponentType<PluginProps> {
|
||||
class LowcodePlugin extends PureComponent<PluginProps> {
|
||||
@ -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 <Comp ref={this.ref} i18n={this.i18n} editor={this.editor} config={config} {...config.pluginProps} />;
|
||||
@ -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',
|
||||
|
||||
@ -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(
|
||||
<Skeleton
|
||||
{...(config.skeleton && config.skeleton.props)}
|
||||
config={config}
|
||||
utils={utils}
|
||||
constants={constants}
|
||||
components={components}
|
||||
/>,
|
||||
<Router>
|
||||
<Route
|
||||
path="/*"
|
||||
component={props => (
|
||||
<Skeleton
|
||||
{...props}
|
||||
{...(config.skeleton && config.skeleton.props)}
|
||||
config={config}
|
||||
utils={utils}
|
||||
constants={constants}
|
||||
components={components}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Router>,
|
||||
ICE_CONTAINER
|
||||
);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -45,6 +45,7 @@ export default class TopIcon extends PureComponent<TopIconProps> {
|
||||
disabled,
|
||||
locked
|
||||
})}
|
||||
data-tooltip={title}
|
||||
id={id}
|
||||
style={style}
|
||||
onClick={disabled ? undefined : onClick}
|
||||
|
||||
@ -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<SkeletonProps, SkeletonState
|
||||
|
||||
render() {
|
||||
const { initReady, skeletonKey, __hasError } = this.state;
|
||||
const { location, history, match } = this.props;
|
||||
if (__hasError || !this.editor) {
|
||||
return 'error';
|
||||
}
|
||||
|
||||
location.query = parseSearch(location.search);
|
||||
this.editor.set('location', location);
|
||||
this.editor.set('history', history);
|
||||
this.editor.set('match', match);
|
||||
|
||||
return (
|
||||
<Router>
|
||||
<Route
|
||||
path="/*"
|
||||
component={props => {
|
||||
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 (
|
||||
<ConfigProvider>
|
||||
<Loading tip="Loading" size="large" visible={!initReady} shape="fusion-reactor" fullScreen>
|
||||
<div className="lowcode-editor" key={skeletonKey}>
|
||||
<TopArea editor={this.editor} />
|
||||
<div className="lowcode-main-content">
|
||||
<LeftArea.Nav editor={this.editor} />
|
||||
<LeftArea.Panel editor={this.editor} />
|
||||
<CenterArea editor={this.editor} />
|
||||
<RightArea editor={this.editor} />
|
||||
</div>
|
||||
</div>
|
||||
</Loading>
|
||||
</ConfigProvider>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Router>
|
||||
<ConfigProvider>
|
||||
<Loading tip="Loading" size="large" visible={!initReady} shape="fusion-reactor" fullScreen>
|
||||
<div className="lowcode-editor" key={skeletonKey}>
|
||||
<TopArea editor={this.editor} />
|
||||
<div className="lowcode-main-content">
|
||||
<LeftArea.Nav editor={this.editor} />
|
||||
<LeftArea.Panel editor={this.editor} />
|
||||
<CenterArea editor={this.editor} />
|
||||
<RightArea editor={this.editor} />
|
||||
</div>
|
||||
</div>
|
||||
</Loading>
|
||||
</ConfigProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<CenterAreaProps> {
|
||||
static displayName = 'LowcodeCenterArea';
|
||||
|
||||
private editor: Editor;
|
||||
private config: Array<PluginConfig>;
|
||||
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 (
|
||||
<div className="lowcode-center-area">
|
||||
{this.config.map(item => {
|
||||
{visiblePluginList.map(item => {
|
||||
const Comp = this.editor.components[item.pluginKey];
|
||||
return <Comp editor={this.editor} config={item} {...item.pluginProps} />;
|
||||
})}
|
||||
|
||||
@ -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<LeftAreaNavProps> {
|
||||
static displayName = 'LowcodeLeftAreaNav';
|
||||
|
||||
private editor: Editor;
|
||||
private config: Array<PluginConfig>;
|
||||
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<PluginConfig> = []): Array<React.ReactElement> => {
|
||||
return list.map((item, idx) => {
|
||||
@ -39,7 +54,8 @@ export default class LeftAreaNav extends PureComponent<LeftAreaNavProps> {
|
||||
render() {
|
||||
const topList: Array<PluginConfig> = [];
|
||||
const bottomList: Array<PluginConfig> = [];
|
||||
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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<RightAreaProps, RightAreaSt
|
||||
static displayName = 'LowcodeRightArea';
|
||||
|
||||
private editor: Editor;
|
||||
private config: Array<PluginConfig>;
|
||||
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 => (
|
||||
<div
|
||||
className={`right-addon-title ${active ? 'active' : ''} ${locked ? 'locked' : ''} ${
|
||||
disabled ? 'disabled' : ''
|
||||
}`}
|
||||
>
|
||||
{!!icon && (
|
||||
<Icon
|
||||
type={icon}
|
||||
style={{
|
||||
marginRight: 2,
|
||||
fontSize: '14px',
|
||||
lineHeight: '14px',
|
||||
verticalAlign: 'top'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{title}
|
||||
</div>
|
||||
);
|
||||
if (marked) {
|
||||
return <Badge dot>{renderTitle()}</Badge>;
|
||||
}
|
||||
return renderTitle();
|
||||
};
|
||||
|
||||
render() {
|
||||
const visiblePluginList = this.areaManager.getVisiblePluginList();
|
||||
return (
|
||||
<div className="lowcode-right-area">
|
||||
<Tab
|
||||
@ -44,13 +139,17 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
|
||||
}}
|
||||
activeKey={this.state.activeKey}
|
||||
lazyLoad={false}
|
||||
onChange={this.handleTabChange}
|
||||
onChange={this.handlePluginChange}
|
||||
>
|
||||
{this.config.map((item, idx) => {
|
||||
{visiblePluginList.map((item, idx) => {
|
||||
const Comp = this.editor.components[item.pluginKey];
|
||||
return (
|
||||
<Tab.Item key={item.pluginKey} title={item.props.title}>
|
||||
<Comp editor={this.editor} config={item.config} {...item.pluginProps} />
|
||||
<Tab.Item
|
||||
key={item.pluginKey}
|
||||
title={this.renderTabTitle(item)}
|
||||
disabled={this.editor.pluginStatus[item.pluginKey].disabled}
|
||||
>
|
||||
<Comp editor={this.editor} config={item} {...item.pluginProps} />
|
||||
</Tab.Item>
|
||||
);
|
||||
})}
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
height: 48px;
|
||||
background-color: #ffffff;
|
||||
border-bottom: 1px solid #e8ebee;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
.divider {
|
||||
max-width: 0;
|
||||
|
||||
@ -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<TopAreaProps> {
|
||||
static displayName = 'LowcodeTopArea';
|
||||
|
||||
private areaManager: AreaManager;
|
||||
private editor: Editor;
|
||||
private config: Array<PluginConfig>;
|
||||
|
||||
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<PluginConfig> = []): Array<React.ReactElement> => {
|
||||
return list.map((item, idx) => {
|
||||
@ -49,10 +59,10 @@ export default class TopArea extends PureComponent<TopAreaProps> {
|
||||
};
|
||||
|
||||
render() {
|
||||
if (!this.config) return null;
|
||||
const leftList: Array<PluginConfig> = [];
|
||||
const rightList: Array<PluginConfig> = [];
|
||||
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') {
|
||||
|
||||
138
packages/editor/src/skeleton/skeleton.tsx
Normal file
138
packages/editor/src/skeleton/skeleton.tsx
Normal file
@ -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<SkeletonProps, SkeletonState> {
|
||||
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 (
|
||||
<Router>
|
||||
<Route
|
||||
path="/*"
|
||||
component={props => {
|
||||
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 (
|
||||
<ConfigProvider>
|
||||
<Loading tip="Loading" size="large" visible={!initReady} shape="fusion-reactor" fullScreen>
|
||||
<div className="lowcode-editor" key={skeletonKey}>
|
||||
<TopArea editor={this.editor} />
|
||||
<div className="lowcode-main-content">
|
||||
<LeftArea.Nav editor={this.editor} />
|
||||
<LeftArea.Panel editor={this.editor} />
|
||||
<CenterArea editor={this.editor} />
|
||||
<RightArea editor={this.editor} />
|
||||
</div>
|
||||
</div>
|
||||
</Loading>
|
||||
</ConfigProvider>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user