mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-15 22:22:51 +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 rightPanel3 from '@ali/iceluna-addon-2';
|
||||||
import rightPanel4 from '@ali/iceluna-addon-2';
|
import rightPanel4 from '@ali/iceluna-addon-2';
|
||||||
|
|
||||||
import PluginFactory from '../framework/plugin';
|
import PluginFactory from '../framework/pluginFactory';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
topBalloonIcon: PluginFactory(topBalloonIcon),
|
topBalloonIcon: PluginFactory(topBalloonIcon),
|
||||||
|
|||||||
@ -159,8 +159,7 @@ export default {
|
|||||||
pluginKey: 'rightPanel1',
|
pluginKey: 'rightPanel1',
|
||||||
type: 'Panel',
|
type: 'Panel',
|
||||||
props: {
|
props: {
|
||||||
title: 'panel1',
|
title: '样式'
|
||||||
icon: 'dengpao'
|
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
package: '@ali/iceluna-addon-2',
|
package: '@ali/iceluna-addon-2',
|
||||||
@ -172,7 +171,7 @@ export default {
|
|||||||
pluginKey: 'rightPanel2',
|
pluginKey: 'rightPanel2',
|
||||||
type: 'Panel',
|
type: 'Panel',
|
||||||
props: {
|
props: {
|
||||||
title: 'panel2',
|
title: '属性',
|
||||||
icon: 'dengpao'
|
icon: 'dengpao'
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
@ -185,8 +184,7 @@ export default {
|
|||||||
pluginKey: 'rightPanel3',
|
pluginKey: 'rightPanel3',
|
||||||
type: 'Panel',
|
type: 'Panel',
|
||||||
props: {
|
props: {
|
||||||
title: 'panel3',
|
title: '事件'
|
||||||
icon: 'dengpao'
|
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
package: '@ali/iceluna-addon-2',
|
package: '@ali/iceluna-addon-2',
|
||||||
@ -198,8 +196,7 @@ export default {
|
|||||||
pluginKey: 'rightPanel4',
|
pluginKey: 'rightPanel4',
|
||||||
type: 'Panel',
|
type: 'Panel',
|
||||||
props: {
|
props: {
|
||||||
title: 'panel4',
|
title: '数据'
|
||||||
icon: 'dengpao'
|
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
package: '@ali/iceluna-addon-2',
|
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;
|
disabled: boolean;
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
marked: boolean;
|
marked: boolean;
|
||||||
|
locked: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import Editor from './editor';
|
import Editor from './editor';
|
||||||
export { default as PluginFactory } from './plugin';
|
export { default as PluginFactory } from './pluginFactory';
|
||||||
export { default as EditorContext } from './context';
|
export { default as EditorContext } from './context';
|
||||||
|
|
||||||
import * as editorUtils from './utils';
|
import * as editorUtils from './utils';
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export interface InjectedPluginProps {
|
|||||||
i18n?: I18nFunction;
|
i18n?: I18nFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function plugin(
|
export default function pluginFactory(
|
||||||
Comp: React.ComponentType<PluginProps & InjectedPluginProps>
|
Comp: React.ComponentType<PluginProps & InjectedPluginProps>
|
||||||
): React.ComponentType<PluginProps> {
|
): React.ComponentType<PluginProps> {
|
||||||
class LowcodePlugin extends PureComponent<PluginProps> {
|
class LowcodePlugin extends PureComponent<PluginProps> {
|
||||||
@ -31,7 +31,6 @@ export default function plugin(
|
|||||||
|
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
if (isEmpty(props.config) || !props.config.pluginKey) {
|
if (isEmpty(props.config) || !props.config.pluginKey) {
|
||||||
console.warn('lowcode editor plugin has wrong config');
|
console.warn('lowcode editor plugin has wrong config');
|
||||||
return;
|
return;
|
||||||
@ -41,8 +40,10 @@ export default function plugin(
|
|||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
this.i18n = generateI18n(locale, messages);
|
this.i18n = generateI18n(locale, messages);
|
||||||
this.pluginKey = props.config.pluginKey;
|
this.pluginKey = props.config.pluginKey;
|
||||||
editor.plugins = editor.plugins || {};
|
editor.set('plugins', {
|
||||||
editor.plugins[this.pluginKey] = this;
|
...editor.plugins,
|
||||||
|
[this.pluginKey]: this
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
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() {
|
render() {
|
||||||
const { config } = this.props;
|
const { config } = this.props;
|
||||||
return <Comp ref={this.ref} i18n={this.i18n} editor={this.editor} config={config} {...config.pluginProps} />;
|
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 IntlMessageFormat from 'intl-messageformat';
|
||||||
import keymaster from 'keymaster';
|
import keymaster from 'keymaster';
|
||||||
import _isEmpty from 'lodash/isEmpty';
|
|
||||||
import { EditorConfig, LocaleType, I18nMessages, I18nFunction, ShortCutsConfig } from './definitions';
|
import { EditorConfig, LocaleType, I18nMessages, I18nFunction, ShortCutsConfig } from './definitions';
|
||||||
import Editor from './editor';
|
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 isEmpty = _isEmpty;
|
||||||
|
export const throttle = _throttle;
|
||||||
|
export const debounce = _debounce;
|
||||||
|
|
||||||
|
import _serialize from 'serialize-javascript';
|
||||||
|
export const serialize = _serialize;
|
||||||
|
|
||||||
const ENV = {
|
const ENV = {
|
||||||
TBE: 'TBE',
|
TBE: 'TBE',
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
// import Skeleton from '@ali/lowcode-engine-skeleton';
|
// import Skeleton from '@ali/lowcode-engine-skeleton';
|
||||||
|
import { HashRouter as Router, Route } from 'react-router-dom';
|
||||||
import Skeleton from './skeleton';
|
import Skeleton from './skeleton';
|
||||||
import config from './config/skeleton';
|
import config from './config/skeleton';
|
||||||
import components from './config/components';
|
import components from './config/components';
|
||||||
@ -21,12 +22,20 @@ if (!ICE_CONTAINER) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
|
<Router>
|
||||||
|
<Route
|
||||||
|
path="/*"
|
||||||
|
component={props => (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
|
{...props}
|
||||||
{...(config.skeleton && config.skeleton.props)}
|
{...(config.skeleton && config.skeleton.props)}
|
||||||
config={config}
|
config={config}
|
||||||
utils={utils}
|
utils={utils}
|
||||||
constants={constants}
|
constants={constants}
|
||||||
components={components}
|
components={components}
|
||||||
/>,
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Router>,
|
||||||
ICE_CONTAINER
|
ICE_CONTAINER
|
||||||
);
|
);
|
||||||
|
|||||||
@ -14,6 +14,41 @@
|
|||||||
&.locked {
|
&.locked {
|
||||||
color: red !important;
|
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 {
|
i.next-icon {
|
||||||
&:before {
|
&:before {
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
|
|||||||
@ -45,6 +45,7 @@ export default class TopIcon extends PureComponent<TopIconProps> {
|
|||||||
disabled,
|
disabled,
|
||||||
locked
|
locked
|
||||||
})}
|
})}
|
||||||
|
data-tooltip={title}
|
||||||
id={id}
|
id={id}
|
||||||
style={style}
|
style={style}
|
||||||
onClick={disabled ? undefined : onClick}
|
onClick={disabled ? undefined : onClick}
|
||||||
|
|||||||
@ -22,6 +22,9 @@ let renderIdx = 0;
|
|||||||
export interface SkeletonProps {
|
export interface SkeletonProps {
|
||||||
components: PluginComponents;
|
components: PluginComponents;
|
||||||
config: EditorConfig;
|
config: EditorConfig;
|
||||||
|
history: object;
|
||||||
|
location: object;
|
||||||
|
match: object;
|
||||||
utils: Utils;
|
utils: Utils;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,20 +102,16 @@ export default class Skeleton extends PureComponent<SkeletonProps, SkeletonState
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { initReady, skeletonKey, __hasError } = this.state;
|
const { initReady, skeletonKey, __hasError } = this.state;
|
||||||
|
const { location, history, match } = this.props;
|
||||||
if (__hasError || !this.editor) {
|
if (__hasError || !this.editor) {
|
||||||
return 'error';
|
return 'error';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
|
||||||
<Router>
|
|
||||||
<Route
|
|
||||||
path="/*"
|
|
||||||
component={props => {
|
|
||||||
const { location, history, match } = props;
|
|
||||||
location.query = parseSearch(location.search);
|
location.query = parseSearch(location.search);
|
||||||
this.editor.set('location', location);
|
this.editor.set('location', location);
|
||||||
this.editor.set('history', history);
|
this.editor.set('history', history);
|
||||||
this.editor.set('match', match);
|
this.editor.set('match', match);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfigProvider>
|
<ConfigProvider>
|
||||||
<Loading tip="Loading" size="large" visible={!initReady} shape="fusion-reactor" fullScreen>
|
<Loading tip="Loading" size="large" visible={!initReady} shape="fusion-reactor" fullScreen>
|
||||||
@ -128,9 +127,5 @@ export default class Skeleton extends PureComponent<SkeletonProps, SkeletonState
|
|||||||
</Loading>
|
</Loading>
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
);
|
);
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Router>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import React, { PureComponent } from 'react';
|
|||||||
import Editor from '../../../framework/editor';
|
import Editor from '../../../framework/editor';
|
||||||
import { PluginConfig } from '../../../framework/definitions';
|
import { PluginConfig } from '../../../framework/definitions';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
import AreaManager from '../../../framework/areaManager';
|
||||||
|
|
||||||
export interface CenterAreaProps {
|
export interface CenterAreaProps {
|
||||||
editor: Editor;
|
editor: Editor;
|
||||||
@ -12,18 +13,33 @@ export default class CenterArea extends PureComponent<CenterAreaProps> {
|
|||||||
static displayName = 'LowcodeCenterArea';
|
static displayName = 'LowcodeCenterArea';
|
||||||
|
|
||||||
private editor: Editor;
|
private editor: Editor;
|
||||||
private config: Array<PluginConfig>;
|
private areaManager: AreaManager;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.editor = props.editor;
|
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() {
|
render() {
|
||||||
|
const visiblePluginList = this.areaManager.getVisiblePluginList();
|
||||||
return (
|
return (
|
||||||
<div className="lowcode-center-area">
|
<div className="lowcode-center-area">
|
||||||
{this.config.map(item => {
|
{visiblePluginList.map(item => {
|
||||||
const Comp = this.editor.components[item.pluginKey];
|
const Comp = this.editor.components[item.pluginKey];
|
||||||
return <Comp editor={this.editor} config={item} {...item.pluginProps} />;
|
return <Comp editor={this.editor} config={item} {...item.pluginProps} />;
|
||||||
})}
|
})}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import LeftPlugin from '../../components/LeftPlugin';
|
|||||||
import './index.scss';
|
import './index.scss';
|
||||||
import Editor from '../../../framework/editor';
|
import Editor from '../../../framework/editor';
|
||||||
import { PluginConfig } from '../../../framework/definitions';
|
import { PluginConfig } from '../../../framework/definitions';
|
||||||
|
import AreaManager from '../../../framework/areaManager';
|
||||||
|
|
||||||
export interface LeftAreaNavProps {
|
export interface LeftAreaNavProps {
|
||||||
editor: Editor;
|
editor: Editor;
|
||||||
@ -12,15 +13,29 @@ export default class LeftAreaNav extends PureComponent<LeftAreaNavProps> {
|
|||||||
static displayName = 'LowcodeLeftAreaNav';
|
static displayName = 'LowcodeLeftAreaNav';
|
||||||
|
|
||||||
private editor: Editor;
|
private editor: Editor;
|
||||||
private config: Array<PluginConfig>;
|
private areaManager: AreaManager;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.editor = props.editor;
|
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> => {
|
renderPluginList = (list: Array<PluginConfig> = []): Array<React.ReactElement> => {
|
||||||
return list.map((item, idx) => {
|
return list.map((item, idx) => {
|
||||||
@ -39,7 +54,8 @@ export default class LeftAreaNav extends PureComponent<LeftAreaNavProps> {
|
|||||||
render() {
|
render() {
|
||||||
const topList: Array<PluginConfig> = [];
|
const topList: Array<PluginConfig> = [];
|
||||||
const bottomList: 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';
|
const align = item.props && item.props.align === 'bottom' ? 'bottom' : 'top';
|
||||||
if (align === 'bottom') {
|
if (align === 'bottom') {
|
||||||
bottomList.push(item);
|
bottomList.push(item);
|
||||||
|
|||||||
@ -49,109 +49,4 @@
|
|||||||
overflow-y: auto;
|
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 React, { PureComponent } from 'react';
|
||||||
import { Tab } from '@alifd/next';
|
import { Tab, Badge, Icon } from '@alifd/next';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
import Editor from '../../../framework/editor';
|
import Editor from '../../../framework/editor';
|
||||||
|
import { transformToPromise } from '../../../framework/utils';
|
||||||
|
import AreaManager from '../../../framework/areaManager';
|
||||||
import { PluginConfig } from '../../../framework/definitions';
|
import { PluginConfig } from '../../../framework/definitions';
|
||||||
|
|
||||||
export interface RightAreaProps {
|
export interface RightAreaProps {
|
||||||
@ -16,24 +18,117 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
|
|||||||
static displayName = 'LowcodeRightArea';
|
static displayName = 'LowcodeRightArea';
|
||||||
|
|
||||||
private editor: Editor;
|
private editor: Editor;
|
||||||
private config: Array<PluginConfig>;
|
private areaManager: AreaManager;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.editor = props.editor;
|
this.editor = props.editor;
|
||||||
this.config = (this.editor.config.plugins && this.editor.config.plugins.rightArea) || [];
|
this.areaManager = new AreaManager(this.editor, 'rightArea');
|
||||||
this.state = {
|
this.state = {
|
||||||
activeKey: 'rightPanel1'
|
activeKey: ''
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTabChange = (key: string): void => {
|
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({
|
this.setState({
|
||||||
activeKey: key
|
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() {
|
render() {
|
||||||
|
const visiblePluginList = this.areaManager.getVisiblePluginList();
|
||||||
return (
|
return (
|
||||||
<div className="lowcode-right-area">
|
<div className="lowcode-right-area">
|
||||||
<Tab
|
<Tab
|
||||||
@ -44,13 +139,17 @@ export default class RightArea extends PureComponent<RightAreaProps, RightAreaSt
|
|||||||
}}
|
}}
|
||||||
activeKey={this.state.activeKey}
|
activeKey={this.state.activeKey}
|
||||||
lazyLoad={false}
|
lazyLoad={false}
|
||||||
onChange={this.handleTabChange}
|
onChange={this.handlePluginChange}
|
||||||
>
|
>
|
||||||
{this.config.map((item, idx) => {
|
{visiblePluginList.map((item, idx) => {
|
||||||
const Comp = this.editor.components[item.pluginKey];
|
const Comp = this.editor.components[item.pluginKey];
|
||||||
return (
|
return (
|
||||||
<Tab.Item key={item.pluginKey} title={item.props.title}>
|
<Tab.Item
|
||||||
<Comp editor={this.editor} config={item.config} {...item.pluginProps} />
|
key={item.pluginKey}
|
||||||
|
title={this.renderTabTitle(item)}
|
||||||
|
disabled={this.editor.pluginStatus[item.pluginKey].disabled}
|
||||||
|
>
|
||||||
|
<Comp editor={this.editor} config={item} {...item.pluginProps} />
|
||||||
</Tab.Item>
|
</Tab.Item>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
height: 48px;
|
height: 48px;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border-bottom: 1px solid #e8ebee;
|
border-bottom: 1px solid #e8ebee;
|
||||||
overflow: hidden;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
.divider {
|
.divider {
|
||||||
max-width: 0;
|
max-width: 0;
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import TopPlugin from '../../components/TopPlugin';
|
|||||||
import './index.scss';
|
import './index.scss';
|
||||||
import Editor from '../../../framework/index';
|
import Editor from '../../../framework/index';
|
||||||
import { PluginConfig } from '../../../framework/definitions';
|
import { PluginConfig } from '../../../framework/definitions';
|
||||||
|
import AreaManager from '../../../framework/areaManager';
|
||||||
|
|
||||||
const { Row, Col } = Grid;
|
const { Row, Col } = Grid;
|
||||||
|
|
||||||
@ -14,19 +15,28 @@ export interface TopAreaProps {
|
|||||||
export default class TopArea extends PureComponent<TopAreaProps> {
|
export default class TopArea extends PureComponent<TopAreaProps> {
|
||||||
static displayName = 'LowcodeTopArea';
|
static displayName = 'LowcodeTopArea';
|
||||||
|
|
||||||
|
private areaManager: AreaManager;
|
||||||
private editor: Editor;
|
private editor: Editor;
|
||||||
private config: Array<PluginConfig>;
|
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.editor = props.editor;
|
this.editor = props.editor;
|
||||||
this.config = (this.editor.config.plugins && this.editor.config.plugins.topArea) || [];
|
this.areaManager = new AreaManager(props.editor, 'topArea');
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {}
|
componentDidMount() {
|
||||||
componentWillUnmount() {}
|
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> => {
|
renderPluginList = (list: Array<PluginConfig> = []): Array<React.ReactElement> => {
|
||||||
return list.map((item, idx) => {
|
return list.map((item, idx) => {
|
||||||
@ -49,10 +59,10 @@ export default class TopArea extends PureComponent<TopAreaProps> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (!this.config) return null;
|
|
||||||
const leftList: Array<PluginConfig> = [];
|
const leftList: Array<PluginConfig> = [];
|
||||||
const rightList: 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';
|
const align = item.props && item.props.align === 'right' ? 'right' : 'left';
|
||||||
// 分隔符不允许相邻
|
// 分隔符不允许相邻
|
||||||
if (item.type === 'Divider') {
|
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