Merge branch 'v/0.8.0' of gitlab.alibaba-inc.com:ali-lowcode/ali-lowcode-engine into v/0.8.0

This commit is contained in:
jianfang.rjf 2020-03-30 16:27:04 +08:00
commit 8ed28215ad
27 changed files with 104 additions and 809 deletions

View File

@ -32,6 +32,7 @@
"resolveJsonModule": true,
// skip type checking of declaration files
"skipLibCheck": true,
"outDir": "lib"
},
"exclude": ["**/test", "**/lib", "**/es", "node_modules"]
}

View File

@ -1,7 +1,7 @@
{
"lerna": "2.11.0",
"version": "independent",
"npmClient": "yarn",
"npmClient": "tyarn",
"registry": "http://registry.npm.alibaba-inc.com",
"useWorkspaces": true,
"packages": [

View File

@ -1,14 +1,34 @@
{
"private": true,
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/css-modules-typescript-loader",
"**/@alife/theme-lowcode-*"
]
},
"scripts": {
"build": "lerna run build",
"clean": "rm -rf ./packages/*/lib ./packages/*/es ./packages/*/dist ./packages/*/build",
"commit": "git-cz",
"pub": "lerna publish",
"setup": "./scripts/setup.sh",
"start": "./scripts/start.sh",
"build": "lerna run build",
"test": "lerna run test",
"test:snapshot": "lerna run test:snapshot",
"pub": "lerna publish",
"commit": "git-cz"
"test:snapshot": "lerna run test:snapshot"
},
"lint-staged": {
"*.{tsx,ts}": [
"eslint --quiet",
"git add"
]
},
"config": {
"commitizen": {
"path": "node_modules/cz-conventional-changelog"
}
},
"devDependencies": {
"@ali/lowcode-config": "^2.0.5",
@ -26,25 +46,7 @@
"tslib": "^1.9.3",
"typescript": "^3.2.2"
},
"engines" : { "node" : "^10" },
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/css-modules-typescript-loader",
"**/@alife/theme-lowcode-*"
]
},
"lint-staged": {
"*.{tsx,ts}": [
"eslint --quiet",
"git add"
]
},
"config": {
"commitizen": {
"path": "node_modules/cz-conventional-changelog"
}
"engines": {
"node": "^10"
}
}

View File

@ -1,21 +1,20 @@
import undoRedo from '@ali/lowcode-plugin-undo-redo';
import zhEn from '@ali/lowcode-plugin-zh-en';
import logo from '@ali/lowcode-plugin-sample-logo';
import SamplePreview from '@ali/lowcode-plugin-sample-preview';
import Designer from '@ali/lowcode-plugin-designer';
import SettingsPane from '@ali/lowcode-plugin-settings-pane';
import samplePreview from '@ali/lowcode-plugin-sample-preview';
import designer from '@ali/lowcode-plugin-designer';
import settingsPane from '@ali/lowcode-plugin-settings-pane';
import componentsPane from '@ali/lowcode-plugin-components-pane';
import OutlinePane from '@ali/lowcode-plugin-outline-pane';
import EventBindDialog from '@ali/lowcode-plugin-event-bind-dialog'
import { PluginFactory } from '@ali/lowcode-editor-core';
import outlinePane from '@ali/lowcode-plugin-outline-pane';
import eventBindDialog from '@ali/lowcode-plugin-event-bind-dialog'
export default {
undoRedo: PluginFactory(undoRedo),
zhEn: PluginFactory(zhEn),
designer: PluginFactory(Designer),
componentsPane: PluginFactory(componentsPane),
settingsPane: PluginFactory(SettingsPane),
outlinePane: PluginFactory(OutlinePane),
eventBindDialog:PluginFactory(EventBindDialog),
logo: PluginFactory(logo),
samplePreview: PluginFactory(SamplePreview)
undoRedo,
zhEn,
designer,
componentsPane,
settingsPane,
outlinePane,
eventBindDialog,
logo,
samplePreview
};

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -11,6 +11,8 @@ import {
PluginSet,
} from './definitions';
import pluginFactory from './pluginFactory';
import * as editorUtils from './utils';
const { registShortCuts, transformToPromise, unRegistShortCuts } = editorUtils;
@ -92,7 +94,10 @@ export default class Editor extends EventEmitter {
constructor(config: EditorConfig, components: PluginClassSet, utils?: Utils) {
super();
this.config = config;
this.components = components;
this.components = {};
Object.entries(components).forEach(([key, value]): void => {
this.components[key] = pluginFactory(value);
});
this.utils = { ...editorUtils, ...utils };
instance = this;
}

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,5 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": ["./src/"],
}

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,6 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"include": ["src/*.ts", "src/*.tsx"],
"exclude": ["node_modules", "build", "public"]
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]
}

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,129 +0,0 @@
import { Component, isValidElement, ReactElement, ReactNode } from 'react';
import { Dialog, Search, Input } from '@alifd/next';
import './style.less';
export default class EventDialog extends Component<{
dialigVisiable:?Boolean,
closeDialog:?()=>void,
submitDialog:?()=>void,
bindEventName:?String
}> {
private eventList : Array = [
{
name: 'getData',
},
{
name: 'deleteData',
},
{
name: 'initData',
},
{
name: 'editData',
},
{
name: 'submitData'
},
]
state = {
selectedEventName:'',
eventName:''
};
componentWillReceiveProps(nextProps){
this.setState({
eventName:nextProps.bindEventName
})
}
initEventName = () => {
const {bindEventName} = this.props;
let eventName = bindEventName;
this.eventList.map((item)=>{
if (item.name === eventName){
eventName = `${eventName}_new`;
}
})
this.setState({
eventName
})
}
onInputChange = (eventName:String) => {
this.setState({
eventName
})
}
onSelectItem = (eventName:String) => {
this.setState({
selectedEventName:eventName
})
// 为空是新建事件
if (eventName === ''){
this.initEventName()
}else{
this.setState({
selectedEventName:eventName,
eventName
})
}
}
onSearchEvent = (searchEventName:String) => {
}
onOk = () => {
this.props.submitDialog(this.state.eventName);
}
render() {
const { dialigVisiable, closeDialog} = this.props;
const {selectedEventName,eventName} = this.state;
return (
<Dialog visible={dialigVisiable} title="事件绑定" onClose={closeDialog} onCancel={closeDialog} onOk={this.onOk}>
<div className="event-dialog-body">
<div className="dialog-left-container">
<div className="dialog-small-title"></div>
<div className="dialog-left-context">
<ul className="event-type-container">
<li className="select-item"></li>
<li className="select-item select-item-active"></li>
</ul>
<div className="event-select-container">
<div>
<Search className="event-search-box" shape="simple" />
<ul className="event-list">
<li className="select-item" className={selectedEventName==''?'select-item select-item-active':'select-item'} onClick={()=>this.onSelectItem('')}></li>
{
this.eventList.map((item,index)=><li key={index} className={selectedEventName==item.name?'select-item select-item-active':'select-item'} onClick={()=>this.onSelectItem(item.name)}>{item.name}</li>)
}
</ul>
</div>
</div>
</div>
</div>
<div className="dialog-right-container">
<div className="dialog-small-title"></div>
<div className="event-input-container">
<Input style={{ width: '100%' }} value={eventName} onChange={this.onInputChange}/>
</div>
<div className="dialog-small-title"></div>
<Input.TextArea style={{ width: '100%', height: '319px' }} />
</div>
</div>
</Dialog>
);
}
}

View File

@ -1,408 +0,0 @@
import { Component, isValidElement, ReactElement, ReactNode } from 'react';
import { Radio, Menu, Table, Icon, Dialog } from '@alifd/next';
import { SettingField } from './main';
import nativeEvents from './native-events';
import './style.less';
import EventDialog from './event-dialog';
const { SubMenu, Item, Group, Divider } = Menu;
const RadioGroup = Radio.Group;
const EVENT_CONTENTS = {
COMPONENT_EVENT: 'componentEvent',
NATIVE_EVENT: 'nativeEvent',
LIFE_CYCLE_EVENT: 'lifeCycleEvent',
};
const DEFINITION_EVENT_TYPE = {
EVENTS: 'events',
NATIVE_EVENTS: 'nativeEvents',
LIFE_CYCLE_EVENT: 'lifeCycleEvent',
};
export default class EventsSetter extends Component<{
value: any[];
onChange: (eventList: any[]) => void;
}> {
state = {
showEventList: false,
eventBtns: [],
eventList: [],
selectType: null,
nativeEventList: [],
lifeCycleEventList: [],
eventDataList: this.props.value || [],
isShowEventDialog: false,
bindEventName: '',
relatedEventName: '',
};
static getDerivedStateFromProps(nextProps, prevState) {
const { value } = nextProps;
if (value !== prevState.eventDataList) {
return {
value,
};
}
return null;
}
componentDidMount() {
this.initEventBtns();
this.initEventList();
}
/**
*
*/
initEventBtns() {
const { definition } = this.props;
let isRoot = false;
let isCustom = false;
let eventBtns = [];
definition.map(item => {
if (item.type === DEFINITION_EVENT_TYPE.LIFE_CYCLE_EVENT) {
isRoot = true;
}
if (item.type === DEFINITION_EVENT_TYPE.EVENTS) {
isCustom = true;
}
});
if (isRoot) {
eventBtns = [
{
value: EVENT_CONTENTS.LIFE_CYCLE_EVENT,
label: '生命周期',
},
];
} else if (isCustom) {
eventBtns = [
{
value: EVENT_CONTENTS.COMPONENT_EVENT,
label: '组件自带事件',
},
];
} else {
eventBtns = [
{
value: EVENT_CONTENTS.NATIVE_EVENT,
label: '原生事件',
},
];
}
this.setState({
eventBtns,
});
}
initEventList() {
const { definition } = this.props;
let nativeEventList = [];
definition.map(item => {
if (item.type === DEFINITION_EVENT_TYPE.EVENTS) {
this.checkEventListStatus(item.list, DEFINITION_EVENT_TYPE.EVENTS);
this.setState({
eventList: item.list,
});
}
if (item.type === DEFINITION_EVENT_TYPE.NATIVE_EVENTS) {
this.checkEventListStatus(
item.list,
DEFINITION_EVENT_TYPE.NATIVE_EVENTS,
);
nativeEventList = item.list;
}
if (item.type === DEFINITION_EVENT_TYPE.LIFE_CYCLE_EVENT) {
this.checkEventListStatus(
item.list,
DEFINITION_EVENT_TYPE.LIFE_CYCLE_EVENT,
);
this.setState({
lifeCycleEventList: item.list,
});
}
});
if (nativeEventList.length == 0) {
nativeEventList = nativeEvents;
this.setState({
nativeEventList,
});
}
}
checkEventListStatus = (eventList: Array, eventType: String) => {
const { eventDataList } = this.state;
if (
eventType === DEFINITION_EVENT_TYPE.EVENTS ||
eventType === DEFINITION_EVENT_TYPE.LIFE_CYCLE_EVENT
) {
eventList.map(item => {
item.disabled = false;
eventDataList.map(eventDataItem => {
if (item.name === eventDataItem.name) {
item.disabled = true;
}
});
});
} else if (eventType === DEFINITION_EVENT_TYPE.NATIVE_EVENTS) {
eventDataList.map(eventDataItem => {
eventList.map(item => {
item.eventList.map(eventItem => {
if (eventItem.name === eventDataItem.name) {
item.disabled = true;
} else {
item.disabled = false;
}
});
});
});
}
};
/**
*
*/
renderEventInfoCell = (value, index, record) => {
let eventTagText = '';
if (record.type === EVENT_CONTENTS.NATIVE_EVENT) {
eventTagText = '原';
} else if (record.type === EVENT_CONTENTS.COMPONENT_EVENT) {
eventTagText = '组';
} else if (record.type === EVENT_CONTENTS.LIFE_CYCLE_EVENT) {
eventTagText = '生';
}
return (
<div>
<div className="event-cell">
<div className="event-type-tag">{eventTagText}</div>
{record.name}
</div>
<div className="event-cell" style={{ marginTop: '8px' }}>
<Icon type="attachment" size="small" className="related-icon" />
<span className="related-event-name">
{record.relatedEventName || ''}
</span>
</div>
</div>
);
};
/**
*
*/
renderEventOperateCell = (eventName: String) => {
return (
<div>
<Icon
type="set"
className="event-operate-icon"
style={{ marginLeft: '5px', marginRight: '4px' }}
onClick={() => this.openDialog(eventName)}
/>
<Icon
type="ashbin"
className="event-operate-icon"
onClick={() => this.openDeleteEventDialog(eventName)}
/>
</div>
);
};
updateEventListStatus = (eventName: String, unDisabled: boolean) => {
const { eventList, nativeEventList, lifeCycleEventList } = this.state;
eventList.map(item => {
if (item.name === eventName) {
item.disabled = !unDisabled;
}
});
lifeCycleEventList.map(item => {
if (item.name === eventName) {
item.disabled = !unDisabled;
}
});
nativeEventList.map(item => {
item.eventList.map(itemData => {
if (itemData.name === eventName) {
itemData.disabled = !unDisabled;
}
});
});
};
onRadioChange = value => {
this.setState({
selectType: value,
});
};
onEventMenuClick = (eventName: String) => {
const { selectType, eventDataList } = this.state;
eventDataList.push({
type: selectType,
name: eventName,
});
this.setState({
eventDataList,
});
this.updateEventListStatus(eventName);
this.closeEventMenu();
this.openDialog(eventName);
};
closeEventMenu = () => {
if (this.state.selectType !== null) {
this.setState({
selectType: null,
});
}
};
openDeleteEventDialog = (eventName: String) => {
this.deleteEvent(eventName);
// Dialog.confirm({
// title: '删除事件',
// content: '确定删除当前事件吗',
// onOk: () => this.deleteEvent(eventName),
// });
};
deleteEvent = (eventName: String) => {
const { eventDataList } = this.state;
eventDataList.map((item, index) => {
if (item.name === eventName) {
eventDataList.splice(index, 1);
}
});
this.setState({
eventDataList,
});
this.updateEventListStatus(eventName, true);
};
openDialog = (bindEventName: String) => {
this.setState({
isShowEventDialog: true,
bindEventName,
});
};
closeDialog = () => {
this.setState({
isShowEventDialog: false,
});
};
submitDialog = (relatedEventName: String) => {
const { bindEventName, eventDataList } = this.state;
eventDataList.map(item => {
if (item.name === bindEventName) {
item.relatedEventName = relatedEventName;
}
});
this.props.onChange(eventDataList);
this.closeDialog();
};
render() {
const {
eventBtns,
eventList,
nativeEventList,
lifeCycleEventList,
selectType,
eventDataList,
isShowEventDialog,
bindEventName,
} = this.state;
let showEventList =
lifeCycleEventList.length > 0 ? lifeCycleEventList : eventList;
return (
<div className="lc-block-setter event-body" onClick={this.closeEventMenu}>
<div className="event-title">
{
eventBtns.length>1 ?<span></span>:<span></span>
}
</div>
<RadioGroup
dataSource={eventBtns}
shape="button"
size="medium"
value={selectType}
onChange={this.onRadioChange}
style={{ width: '100%' }}
/>
{selectType && selectType != EVENT_CONTENTS.NATIVE_EVENT && (
<Menu
defaultOpenKeys="sub-menu"
className="event-menu"
onItemClick={this.onEventMenuClick}
>
{showEventList.map((item, index) => (
<Item
key={item.name}
helper={item.description}
disabled={item.disabled}
>
{item.name}
</Item>
))}
</Menu>
)}
{selectType && selectType === EVENT_CONTENTS.NATIVE_EVENT && (
<Menu
defaultOpenKeys="sub-menu"
className="event-menu"
onItemClick={this.onEventMenuClick}
>
{nativeEventList.map((item, index) => (
<Group label={item.name} key={index}>
{item.eventList.map(item => (
<Item key={item.name} disabled={item.disabled}>
{item.name}
</Item>
))}
</Group>
))}
</Menu>
)}
<div className="event-table">
<Table dataSource={eventDataList} size="small">
<Table.Column title="已有事件" cell={this.renderEventInfoCell} />
<Table.Column
title="操作"
dataIndex="name"
cell={this.renderEventOperateCell}
width={70}
/>
</Table>
</div>
<EventDialog
dialigVisiable={isShowEventDialog}
closeDialog={this.closeDialog}
submitDialog={this.submitDialog}
bindEventName={bindEventName}
></EventDialog>
</div>
);
}
}

View File

@ -1,56 +0,0 @@
export default [
{
category: 'commonlyEvent',
name: '常用事件',
eventList: [
{ name: 'onClick' },
{ name: 'onChange' },
{ name: 'onInput' },
{ name: 'onSelect' },
{ name: 'onSubmit' },
{ name: 'onReset' },
{ name: 'onFocus' },
{ name: 'onBlur' },
{ name: 'onScroll' },
{ name: 'onLoad' },
{ name: 'onError' },
],
},
{
category: 'keybordEvent',
name: '键盘事件',
eventList: [{ name: 'onKeyDown' }, { name: 'onKeyPress' }, { name: 'onKeyUp' }],
},
{
category: 'mouseEvent',
name: '鼠标事件',
eventList: [
{ name: 'onDoubleClick' },
{ name: 'onDrag' },
{ name: 'onDragEnd' },
{ name: 'onDragEnter' },
{ name: 'onDragExit' },
{ name: 'onDragLeave' },
{ name: 'onDragOver' },
{ name: 'onDragStart' },
{ name: 'onDrop' },
{ name: 'onMouseDown' },
{ name: 'onMouseEnter' },
{ name: 'onMouseLeave' },
{ name: 'onMouseMove' },
{ name: 'onMouseOut' },
{ name: 'onMouseOver' },
{ name: 'onMouseUp' },
],
},
{
category: 'animateEvent',
name: '动画事件',
eventList: [
{ name: 'onAnimationStart' },
{ name: 'onAnimationEnd' },
{ name: 'onAnimationItration' },
{ name: 'onTransitionEnd' },
],
},
];

View File

@ -1,155 +0,0 @@
.event-body {
padding: 0 10px 0 10px;
position: relative;
min-height: 450px;
.event-title {
height: 30px;
line-height: 30px;
margin-bottom: 10px;
}
.next-radio-group {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.next-radio-group label {
-webkit-box-flex: 1;
-webkit-flex: auto;
-ms-flex: auto;
flex: auto;
text-align: center;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.event-cell {
padding-left: 25px;
position: relative;
font-size: 12px;
}
.event-type-tag {
position: absolute;
width: 20px;
height: 20px;
left: 0px;
top: -2px;
border-radius: 50%;
line-height: 20px;
text-align: center;
color: #ffffff;
background-color: #2077ff;
}
.related-icon {
margin-right: 5px;
}
.related-event-name {
color: #2077ff;
cursor: pointer;
}
.event-menu {
max-height: 300px;
width: 230px;
overflow-x: hidden;
position: absolute;
top: 67px;
left: 10px;
z-index: 10;
}
.event-table {
margin-top: 20px;
}
.event-operate-icon {
cursor: pointer;
}
.event-operate-icon:hover {
color: #0079f2;
}
}
.event-dialog-body {
width: 800px;
height: 450px;
.dialog-small-title {
font-weight: 700;
margin-bottom: 8px;
color: rgba(0, 0, 0);
}
.dialog-left-container {
float: left;
.dialog-left-context {
width: 268px;
height: 392px;
border: 1px solid rgba(31, 56, 88, .3);
border-radius: 3px;
.event-type-container {
width: 110px;
height: 390px;
border-right: 1px solid rgba(31, 56, 88, .3);
float: left;
}
.select-item {
font-size: 12px;
height: 28px;
line-height: 28px;
padding: 0 30px 0 12px;
cursor: pointer;
position: relative;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.select-item-active {
background: rgba(31, 56, 88, .06);
}
.event-select-container {
width: 156px;
float: left;
.event-search-box {
width: 135px;
margin: 10px;
}
}
.event-list {
overflow-y: auto;
overflow-x: hidden;
height: 342px;
}
}
}
.dialog-right-container {
width: 530px;
padding-left: 20px;
float: left;
.event-input-container {
margin-bottom: 20px;
}
}
}

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {},
"compilerOptions": {
"outDir": "lib"
},
"include": [
"./src/"
]

View File

@ -37,7 +37,8 @@
"baseUrl": "./packages",
"paths": {
"@ali/lowcode-*": ["./*/src"]
}
},
"outDir": "lib"
},
"exclude": ["**/test", "**/lib", "**/es", "node_modules"]
}