mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-17 07:13:01 +00:00
complete object-setter
This commit is contained in:
parent
a0e9531c03
commit
f37743327b
@ -205,6 +205,9 @@ export default class Prop implements IPropParent {
|
|||||||
if (this.type === 'list') {
|
if (this.type === 'list') {
|
||||||
return this.size === other.size ? 1 : 2;
|
return this.size === other.size ? 1 : 2;
|
||||||
}
|
}
|
||||||
|
if (this.type === 'map') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// 'literal' | 'map' | 'expression' | 'slot'
|
// 'literal' | 'map' | 'expression' | 'slot'
|
||||||
return this.code === other.code ? 0 : 2;
|
return this.code === other.code ? 0 : 2;
|
||||||
@ -286,25 +289,12 @@ export default class Prop implements IPropParent {
|
|||||||
*/
|
*/
|
||||||
get(path: string | number, stash = true): Prop | null {
|
get(path: string | number, stash = true): Prop | null {
|
||||||
const type = this._type;
|
const type = this._type;
|
||||||
// todo: support list get
|
|
||||||
if (type !== 'map' && type !== 'list' && type !== 'unset' && !stash) {
|
if (type !== 'map' && type !== 'list' && type !== 'unset' && !stash) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const maps = type === 'map' ? this.maps : null;
|
const maps = type === 'map' ? this.maps : null;
|
||||||
const items = type === 'list' ? this.items : null;
|
const items = type === 'list' ? this.items : null;
|
||||||
let prop: any;
|
|
||||||
if (type === 'list') {
|
|
||||||
if (isValidArrayIndex(path, this.size)) {
|
|
||||||
prop = items![path];
|
|
||||||
}
|
|
||||||
} else if (type === 'map') {
|
|
||||||
prop = maps?.get(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prop) {
|
|
||||||
return prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
let entry = path;
|
let entry = path;
|
||||||
let nest = '';
|
let nest = '';
|
||||||
@ -314,7 +304,11 @@ export default class Prop implements IPropParent {
|
|||||||
nest = path.slice(i + 1);
|
nest = path.slice(i + 1);
|
||||||
if (nest) {
|
if (nest) {
|
||||||
entry = path.slice(0, i);
|
entry = path.slice(0, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let prop: any;
|
||||||
if (type === 'list') {
|
if (type === 'list') {
|
||||||
if (isValidArrayIndex(entry, this.size)) {
|
if (isValidArrayIndex(entry, this.size)) {
|
||||||
prop = items![entry];
|
prop = items![entry];
|
||||||
@ -324,10 +318,7 @@ export default class Prop implements IPropParent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (prop) {
|
if (prop) {
|
||||||
return prop.get(nest, stash);
|
return nest ? prop.get(nest, stash) : prop;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stash) {
|
if (stash) {
|
||||||
@ -549,7 +540,7 @@ export function isProp(obj: any): obj is Prop {
|
|||||||
return obj && obj.isProp;
|
return obj && obj.isProp;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidArrayIndex(key: any, limit = -1): key is number {
|
export function isValidArrayIndex(key: any, limit = -1): key is number {
|
||||||
const n = parseFloat(String(key));
|
const n = parseFloat(String(key));
|
||||||
return n >= 0 && Math.floor(n) === n && isFinite(n) && (limit < 0 || n < limit);
|
return n >= 0 && Math.floor(n) === n && isFinite(n) && (limit < 0 || n < limit);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,7 +81,7 @@ export default class Props implements IPropParent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export(serialize = false): { props?: PropsMap | PropsList; extras?: object} {
|
export(serialize = false): { props?: PropsMap | PropsList; extras?: object } {
|
||||||
if (this.items.length < 1) {
|
if (this.items.length < 1) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -132,9 +132,11 @@ export default class Props implements IPropParent {
|
|||||||
/**
|
/**
|
||||||
* 根据 path 路径查询属性
|
* 根据 path 路径查询属性
|
||||||
*
|
*
|
||||||
* @useStash 如果没有则临时生成一个
|
* @param stash 如果没有则临时生成一个
|
||||||
*/
|
*/
|
||||||
query(path: string, useStash: boolean = true): Prop | null {
|
query(path: string, stash = true): Prop | null {
|
||||||
|
return this.get(path, stash);
|
||||||
|
// todo: future support list search
|
||||||
let matchedLength = 0;
|
let matchedLength = 0;
|
||||||
let firstMatched = null;
|
let firstMatched = null;
|
||||||
if (this.items) {
|
if (this.items) {
|
||||||
@ -165,7 +167,7 @@ export default class Props implements IPropParent {
|
|||||||
if (firstMatched) {
|
if (firstMatched) {
|
||||||
ret = firstMatched.get(path.slice(matchedLength + 1), true);
|
ret = firstMatched.get(path.slice(matchedLength + 1), true);
|
||||||
}
|
}
|
||||||
if (!ret && useStash) {
|
if (!ret && stash) {
|
||||||
return this.stash.get(path);
|
return this.stash.get(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,10 +176,26 @@ export default class Props implements IPropParent {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取某个属性, 如果不存在,临时获取一个待写入
|
* 获取某个属性, 如果不存在,临时获取一个待写入
|
||||||
* @param useStash 强制
|
* @param stash 强制
|
||||||
*/
|
*/
|
||||||
get(name: string, useStash = false): Prop | null {
|
get(path: string, stash = false): Prop | null {
|
||||||
return this.maps.get(name) || (useStash && this.stash.get(name)) || null;
|
let entry = path;
|
||||||
|
let nest = '';
|
||||||
|
const i = path.indexOf('.');
|
||||||
|
if (i > 0) {
|
||||||
|
nest = path.slice(i + 1);
|
||||||
|
if (nest) {
|
||||||
|
entry = path.slice(0, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const prop = this.maps.get(entry) || (stash && this.stash.get(entry)) || null;
|
||||||
|
|
||||||
|
if (prop) {
|
||||||
|
return nest ? prop.get(nest, stash) : prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -137,6 +137,8 @@ export class ListSetter extends Component<ArraySetterProps, ArraySetterState> {
|
|||||||
// check is ObjectSetter then check if show columns
|
// check is ObjectSetter then check if show columns
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.info(this.state.items);
|
||||||
|
|
||||||
const { items } = this.state;
|
const { items } = this.state;
|
||||||
const scrollToLast = this.scrollToLast;
|
const scrollToLast = this.scrollToLast;
|
||||||
this.scrollToLast = false;
|
this.scrollToLast = false;
|
||||||
@ -265,7 +267,7 @@ export default class ArraySetter extends Component<{
|
|||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
this.pipe.show((e as any).target);
|
this.pipe.show((e as any).target, field.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon type="edit" />
|
<Icon type="edit" />
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export default class ObjectSetter extends Component<{
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// form
|
// form
|
||||||
return <FormSetter />;
|
return <FormSetter {...props} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,13 +77,19 @@ class RowSetter extends Component<RowSetterProps> {
|
|||||||
this.items = items;
|
this.items = items;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor) {
|
|
||||||
if (typeof descriptor === 'function') {
|
|
||||||
let firstRun: boolean = true;
|
let firstRun: boolean = true;
|
||||||
field.onEffect(() => {
|
field.onEffect(() => {
|
||||||
const state = {
|
let state: any = {};
|
||||||
descriptor: descriptor(field),
|
if (descriptor) {
|
||||||
};
|
if (typeof descriptor === 'function') {
|
||||||
|
state.descriptor = descriptor(field);
|
||||||
|
} else {
|
||||||
|
state.descriptor = field.getPropValue(descriptor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.descriptor = field.title;
|
||||||
|
}
|
||||||
|
|
||||||
if (firstRun) {
|
if (firstRun) {
|
||||||
firstRun = false;
|
firstRun = false;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
@ -91,17 +97,6 @@ class RowSetter extends Component<RowSetterProps> {
|
|||||||
this.setState(state);
|
this.setState(state);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
this.state = {
|
|
||||||
descriptor,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// todo: onEffect change field.name
|
|
||||||
this.state = {
|
|
||||||
descriptor: field.title || `项目 ${field.name}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(_: any, nextState: any) {
|
shouldComponentUpdate(_: any, nextState: any) {
|
||||||
@ -114,7 +109,7 @@ class RowSetter extends Component<RowSetterProps> {
|
|||||||
private pipe: any;
|
private pipe: any;
|
||||||
render() {
|
render() {
|
||||||
const items = this.items;
|
const items = this.items;
|
||||||
const { field, primaryButton } = this.props;
|
const { field, primaryButton, config } = this.props;
|
||||||
|
|
||||||
if (!this.pipe) {
|
if (!this.pipe) {
|
||||||
this.pipe = (this.context as PopupPipe).create({ width: 320 });
|
this.pipe = (this.context as PopupPipe).create({ width: 320 });
|
||||||
@ -127,7 +122,7 @@ class RowSetter extends Component<RowSetterProps> {
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|
||||||
this.pipe.send(<FormSetter key={field.id} />, title);
|
this.pipe.send(<FormSetter key={field.id} field={field} config={config} />, title);
|
||||||
|
|
||||||
if (items) {
|
if (items) {
|
||||||
return (
|
return (
|
||||||
@ -135,7 +130,7 @@ class RowSetter extends Component<RowSetterProps> {
|
|||||||
<div
|
<div
|
||||||
className="lc-setter-object-row-edit"
|
className="lc-setter-object-row-edit"
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
this.pipe.show((e as any).target);
|
this.pipe.show((e as any).target, field.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon size="small" type="edit" />
|
<Icon size="small" type="edit" />
|
||||||
@ -149,7 +144,7 @@ class RowSetter extends Component<RowSetterProps> {
|
|||||||
<Button
|
<Button
|
||||||
type={primaryButton === false ? 'normal' : 'primary'}
|
type={primaryButton === false ? 'normal' : 'primary'}
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
this.pipe.show((e as any).target);
|
this.pipe.show((e as any).target, field.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon type="edit" />
|
<Icon type="edit" />
|
||||||
@ -159,9 +154,30 @@ class RowSetter extends Component<RowSetterProps> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// form-field setter
|
interface FormSetterProps {
|
||||||
class FormSetter extends Component<{}> {
|
field: SettingField;
|
||||||
|
config: ObjectSetterConfig;
|
||||||
|
}
|
||||||
|
class FormSetter extends Component<FormSetterProps> {
|
||||||
|
private items: SettingField[];
|
||||||
|
constructor(props: RowSetterProps) {
|
||||||
|
super(props);
|
||||||
|
const { config, field } = props;
|
||||||
|
this.items = (config.items || []).map(conf => field.createField(conf));
|
||||||
|
|
||||||
|
// TODO: extraConfig for custom fields
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return 'yes';
|
const { field } = this.props;
|
||||||
|
return (
|
||||||
|
<div className="lc-setter-object lc-block-setter">
|
||||||
|
{this.items.map((item, index) => createSettingFieldView(item, field, index))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -200,7 +200,8 @@ export class SettingField implements SettingTarget {
|
|||||||
}
|
}
|
||||||
// initial self properties
|
// initial self properties
|
||||||
this._name = name;
|
this._name = name;
|
||||||
this.title = title || String(name);
|
// make this reactive
|
||||||
|
this.title = title || (typeof name === 'number' ? `项目 ${name}` : name);
|
||||||
this.setter = setter;
|
this.setter = setter;
|
||||||
this.extraProps = {
|
this.extraProps = {
|
||||||
...rest,
|
...rest,
|
||||||
|
|||||||
@ -26,10 +26,11 @@ export class PopupPipe {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
show: (target: Element) => {
|
show: (target: Element, actionKey?: string) => {
|
||||||
this.currentId = id;
|
this.currentId = id;
|
||||||
this.popup({
|
this.popup({
|
||||||
...props,
|
...props,
|
||||||
|
actionKey,
|
||||||
content: sendContent,
|
content: sendContent,
|
||||||
title: sendTitle,
|
title: sendTitle,
|
||||||
}, target);
|
}, target);
|
||||||
@ -55,7 +56,7 @@ export class PopupPipe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class PopupService extends Component<{ safeId?: string }> {
|
export default class PopupService extends Component<{ actionKey?: string; safeId?: string }> {
|
||||||
private popupPipe = new PopupPipe();
|
private popupPipe = new PopupPipe();
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
@ -63,10 +64,11 @@ export default class PopupService extends Component<{ safeId?: string }> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { children, actionKey, safeId } = this.props;
|
||||||
return (
|
return (
|
||||||
<PopupContext.Provider value={this.popupPipe}>
|
<PopupContext.Provider value={this.popupPipe}>
|
||||||
{this.props.children}
|
{children}
|
||||||
<PopupContent safeId={this.props.safeId} />
|
<PopupContent key={'pop' + actionKey} safeId={safeId} />
|
||||||
</PopupContext.Provider>
|
</PopupContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -100,7 +102,7 @@ export class PopupContent extends PureComponent<{ safeId?: string }> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { content, visible, width, title, pos } = this.state;
|
const { content, visible, width, title, pos, actionKey } = this.state;
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -116,7 +118,6 @@ export class PopupContent extends PureComponent<{ safeId?: string }> {
|
|||||||
className="lc-ballon"
|
className="lc-ballon"
|
||||||
align="l"
|
align="l"
|
||||||
id={this.props.safeId}
|
id={this.props.safeId}
|
||||||
safeId={this.props.safeId}
|
|
||||||
safeNode={id}
|
safeNode={id}
|
||||||
visible={visible}
|
visible={visible}
|
||||||
style={{ width }}
|
style={{ width }}
|
||||||
@ -135,7 +136,7 @@ export class PopupContent extends PureComponent<{ safeId?: string }> {
|
|||||||
shouldUpdatePosition
|
shouldUpdatePosition
|
||||||
>
|
>
|
||||||
<div className="lc-ballon-title">{title}</div>
|
<div className="lc-ballon-title">{title}</div>
|
||||||
<div className="lc-ballon-content"><PopupService safeId={id}>{content}</PopupService></div>
|
<div className="lc-ballon-content"><PopupService actionKey={actionKey} safeId={id}>{content}</PopupService></div>
|
||||||
</Balloon>
|
</Balloon>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user