mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-14 21:12:53 +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') {
|
||||
return this.size === other.size ? 1 : 2;
|
||||
}
|
||||
if (this.type === 'map') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 'literal' | 'map' | 'expression' | 'slot'
|
||||
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 {
|
||||
const type = this._type;
|
||||
// todo: support list get
|
||||
if (type !== 'map' && type !== 'list' && type !== 'unset' && !stash) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const maps = type === 'map' ? this.maps : 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 nest = '';
|
||||
@ -314,22 +304,23 @@ export default class Prop implements IPropParent {
|
||||
nest = path.slice(i + 1);
|
||||
if (nest) {
|
||||
entry = path.slice(0, i);
|
||||
|
||||
if (type === 'list') {
|
||||
if (isValidArrayIndex(entry, this.size)) {
|
||||
prop = items![entry];
|
||||
}
|
||||
} else if (type === 'map') {
|
||||
prop = maps?.get(entry);
|
||||
}
|
||||
|
||||
if (prop) {
|
||||
return prop.get(nest, stash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let prop: any;
|
||||
if (type === 'list') {
|
||||
if (isValidArrayIndex(entry, this.size)) {
|
||||
prop = items![entry];
|
||||
}
|
||||
} else if (type === 'map') {
|
||||
prop = maps?.get(entry);
|
||||
}
|
||||
|
||||
if (prop) {
|
||||
return nest ? prop.get(nest, stash) : prop;
|
||||
}
|
||||
|
||||
if (stash) {
|
||||
if (!this.stash) {
|
||||
this.stash = new PropStash(this.props, item => {
|
||||
@ -549,7 +540,7 @@ export function isProp(obj: any): obj is Prop {
|
||||
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));
|
||||
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) {
|
||||
return {};
|
||||
}
|
||||
@ -126,15 +126,17 @@ export default class Props implements IPropParent {
|
||||
});
|
||||
}
|
||||
|
||||
return { props, extras };
|
||||
return { props, extras };
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 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 firstMatched = null;
|
||||
if (this.items) {
|
||||
@ -165,7 +167,7 @@ export default class Props implements IPropParent {
|
||||
if (firstMatched) {
|
||||
ret = firstMatched.get(path.slice(matchedLength + 1), true);
|
||||
}
|
||||
if (!ret && useStash) {
|
||||
if (!ret && stash) {
|
||||
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 {
|
||||
return this.maps.get(name) || (useStash && this.stash.get(name)) || null;
|
||||
get(path: string, stash = false): Prop | 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
|
||||
}
|
||||
|
||||
console.info(this.state.items);
|
||||
|
||||
const { items } = this.state;
|
||||
const scrollToLast = this.scrollToLast;
|
||||
this.scrollToLast = false;
|
||||
@ -265,7 +267,7 @@ export default class ArraySetter extends Component<{
|
||||
return (
|
||||
<Button
|
||||
onClick={e => {
|
||||
this.pipe.show((e as any).target);
|
||||
this.pipe.show((e as any).target, field.id);
|
||||
}}
|
||||
>
|
||||
<Icon type="edit" />
|
||||
|
||||
@ -25,7 +25,7 @@ export default class ObjectSetter extends Component<{
|
||||
}
|
||||
} else {
|
||||
// form
|
||||
return <FormSetter />;
|
||||
return <FormSetter {...props} />;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -77,31 +77,26 @@ class RowSetter extends Component<RowSetterProps> {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
if (descriptor) {
|
||||
if (typeof descriptor === 'function') {
|
||||
let firstRun: boolean = true;
|
||||
field.onEffect(() => {
|
||||
const state = {
|
||||
descriptor: descriptor(field),
|
||||
};
|
||||
if (firstRun) {
|
||||
firstRun = false;
|
||||
this.state = state;
|
||||
} else {
|
||||
this.setState(state);
|
||||
}
|
||||
});
|
||||
let firstRun: boolean = true;
|
||||
field.onEffect(() => {
|
||||
let state: any = {};
|
||||
if (descriptor) {
|
||||
if (typeof descriptor === 'function') {
|
||||
state.descriptor = descriptor(field);
|
||||
} else {
|
||||
state.descriptor = field.getPropValue(descriptor);
|
||||
}
|
||||
} else {
|
||||
this.state = {
|
||||
descriptor,
|
||||
};
|
||||
state.descriptor = field.title;
|
||||
}
|
||||
} else {
|
||||
// todo: onEffect change field.name
|
||||
this.state = {
|
||||
descriptor: field.title || `项目 ${field.name}`,
|
||||
};
|
||||
}
|
||||
|
||||
if (firstRun) {
|
||||
firstRun = false;
|
||||
this.state = state;
|
||||
} else {
|
||||
this.setState(state);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
shouldComponentUpdate(_: any, nextState: any) {
|
||||
@ -114,7 +109,7 @@ class RowSetter extends Component<RowSetterProps> {
|
||||
private pipe: any;
|
||||
render() {
|
||||
const items = this.items;
|
||||
const { field, primaryButton } = this.props;
|
||||
const { field, primaryButton, config } = this.props;
|
||||
|
||||
if (!this.pipe) {
|
||||
this.pipe = (this.context as PopupPipe).create({ width: 320 });
|
||||
@ -127,7 +122,7 @@ class RowSetter extends Component<RowSetterProps> {
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
this.pipe.send(<FormSetter key={field.id} />, title);
|
||||
this.pipe.send(<FormSetter key={field.id} field={field} config={config} />, title);
|
||||
|
||||
if (items) {
|
||||
return (
|
||||
@ -135,7 +130,7 @@ class RowSetter extends Component<RowSetterProps> {
|
||||
<div
|
||||
className="lc-setter-object-row-edit"
|
||||
onClick={e => {
|
||||
this.pipe.show((e as any).target);
|
||||
this.pipe.show((e as any).target, field.id);
|
||||
}}
|
||||
>
|
||||
<Icon size="small" type="edit" />
|
||||
@ -149,7 +144,7 @@ class RowSetter extends Component<RowSetterProps> {
|
||||
<Button
|
||||
type={primaryButton === false ? 'normal' : 'primary'}
|
||||
onClick={e => {
|
||||
this.pipe.show((e as any).target);
|
||||
this.pipe.show((e as any).target, field.id);
|
||||
}}
|
||||
>
|
||||
<Icon type="edit" />
|
||||
@ -159,9 +154,30 @@ class RowSetter extends Component<RowSetterProps> {
|
||||
}
|
||||
}
|
||||
|
||||
// form-field setter
|
||||
class FormSetter extends Component<{}> {
|
||||
interface FormSetterProps {
|
||||
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() {
|
||||
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
|
||||
this._name = name;
|
||||
this.title = title || String(name);
|
||||
// make this reactive
|
||||
this.title = title || (typeof name === 'number' ? `项目 ${name}` : name);
|
||||
this.setter = setter;
|
||||
this.extraProps = {
|
||||
...rest,
|
||||
|
||||
@ -26,10 +26,11 @@ export class PopupPipe {
|
||||
});
|
||||
}
|
||||
},
|
||||
show: (target: Element) => {
|
||||
show: (target: Element, actionKey?: string) => {
|
||||
this.currentId = id;
|
||||
this.popup({
|
||||
...props,
|
||||
actionKey,
|
||||
content: sendContent,
|
||||
title: sendTitle,
|
||||
}, 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();
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -63,10 +64,11 @@ export default class PopupService extends Component<{ safeId?: string }> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children, actionKey, safeId } = this.props;
|
||||
return (
|
||||
<PopupContext.Provider value={this.popupPipe}>
|
||||
{this.props.children}
|
||||
<PopupContent safeId={this.props.safeId} />
|
||||
{children}
|
||||
<PopupContent key={'pop' + actionKey} safeId={safeId} />
|
||||
</PopupContext.Provider>
|
||||
);
|
||||
}
|
||||
@ -100,7 +102,7 @@ export class PopupContent extends PureComponent<{ safeId?: string }> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { content, visible, width, title, pos } = this.state;
|
||||
const { content, visible, width, title, pos, actionKey } = this.state;
|
||||
if (!visible) {
|
||||
return null;
|
||||
}
|
||||
@ -116,7 +118,6 @@ export class PopupContent extends PureComponent<{ safeId?: string }> {
|
||||
className="lc-ballon"
|
||||
align="l"
|
||||
id={this.props.safeId}
|
||||
safeId={this.props.safeId}
|
||||
safeNode={id}
|
||||
visible={visible}
|
||||
style={{ width }}
|
||||
@ -135,7 +136,7 @@ export class PopupContent extends PureComponent<{ safeId?: string }> {
|
||||
shouldUpdatePosition
|
||||
>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user