fix slot title

This commit is contained in:
kangwei 2020-05-06 19:56:23 +08:00
parent 4eee69763f
commit afd47a4e83
16 changed files with 109 additions and 55 deletions

View File

@ -1,6 +1,8 @@
// all this file for polyfill vision logic // all this file for polyfill vision logic
import { isValidElement } from 'react'; import { isValidElement } from 'react';
import { isSetterConfig } from '@ali/lowcode-types';
import { getSetter } from '@ali/lowcode-editor-core';
function getHotterFromSetter(setter) { function getHotterFromSetter(setter) {
return setter && (setter.Hotter || (setter.type && setter.type.Hotter)) || []; // eslint-disable-line return setter && (setter.Hotter || (setter.type && setter.type.Hotter)) || []; // eslint-disable-line
@ -40,6 +42,13 @@ export class Transducer {
setter = setter.props.setters[0]; setter = setter.props.setters[0];
} }
if (isSetterConfig(setter)) {
setter = setter.componentName;
}
if (typeof setter === 'string') {
setter = getSetter(setter);
}
this.setterTransducer = combineTransducer( this.setterTransducer = combineTransducer(
getTransducerFromSetter(setter), getTransducerFromSetter(setter),
getHotterFromSetter(setter), getHotterFromSetter(setter),

View File

@ -160,8 +160,9 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
private transformProps(props: any): any { private transformProps(props: any): any {
// FIXME! support PropsList // FIXME! support PropsList
return this.document.designer.transformProps(props, this, TransformStage.Init); const x = this.document.designer.transformProps(props, this, TransformStage.Init);
return x;
// TODO: run transducers in metadata.experimental // TODO: run transducers in metadata.experimental
} }
@ -183,19 +184,19 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
return this.isParental() && this.componentMeta.isContainer; return this.isParental() && this.componentMeta.isContainer;
} }
isRoot(): this is RootNode { isRoot(): boolean {
return this.document.rootNode == (this as any); return this.document.rootNode == (this as any);
} }
isPage(): this is PageNode { isPage(): boolean {
return this.isRoot() && this.componentName === 'Page'; return this.isRoot() && this.componentName === 'Page';
} }
isComponent(): this is ComponentNode { isComponent(): boolean {
return this.isRoot() && this.componentName === 'Component'; return this.isRoot() && this.componentName === 'Component';
} }
isSlot(): this is SlotNode { isSlot(): boolean {
return this._slotFor != null && this.componentName === 'Slot'; return this._slotFor != null && this.componentName === 'Slot';
} }
@ -225,8 +226,12 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
return; return;
} }
if (!this.isSlot() && this._parent) { if (this._parent) {
this._parent.children.delete(this); if (this.isSlot()) {
this._parent.removeSlot(this, false);
} else {
this._parent.children.delete(this);
}
} }
this._parent = parent; this._parent = parent;
@ -258,8 +263,12 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
* *
*/ */
remove() { remove() {
if (!this.isSlot() && this.parent) { if (this.parent) {
this.parent.children.delete(this, true); if (this.isSlot()) {
this.parent.removeSlot(this, true);
} else {
this.parent.children.delete(this, true);
}
} }
} }
@ -295,24 +304,13 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
return this.props.export(TransformStage.Serilize).props || null; return this.props.export(TransformStage.Serilize).props || null;
} }
@obx.val _slots: Node[] = [];
@computed hasSlots() { @computed hasSlots() {
for (const item of this.props) { return this._slots.length > 0;
if (item.type === 'slot') {
return true;
}
}
return false;
} }
@computed get slots() { get slots() {
// TODO: optimize recore/obx, array maked every time, donot as changed return this._slots;
const slots: Node[] = [];
this.props.forEach((item) => {
if (item.type === 'slot') {
slots.push(item.slotNode!);
}
});
return slots;
} }
@obx.ref private _conditionGroup: ExclusiveGroup | null = null; @obx.ref private _conditionGroup: ExclusiveGroup | null = null;
@ -542,6 +540,28 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
return comparePosition(this, otherNode); return comparePosition(this, otherNode);
} }
/**
* Slot节点
*/
removeSlot(slotNode: Node, purge = false): boolean {
const i = this._slots.indexOf(slotNode);
if (i < 0) {
return false;
}
const deleted = this._slots.splice(i, 1)[0];
if (purge) {
// should set parent null
deleted.internalSetParent(null);
deleted.purge();
}
return false;
}
addSlot(slotNode: Node) {
slotNode.internalSetParent(this as ParentalNode);
this._slots.push(slotNode);
}
private purged = false; private purged = false;
/** /**
* *

View File

@ -221,7 +221,7 @@ export class Prop implements IPropParent {
} else { } else {
const owner = this.props.owner; const owner = this.props.owner;
this._slotNode = owner.document.createNode<SlotNode>(slotSchema); this._slotNode = owner.document.createNode<SlotNode>(slotSchema);
this._slotNode.internalSetParent(owner as any); owner.addSlot(this._slotNode);
this._slotNode.internalSetSlotFor(this); this._slotNode.internalSetSlotFor(this);
} }
this.dispose(); this.dispose();

View File

@ -37,10 +37,13 @@ function injectVars(msg: string, params: any, locale: string): string {
});*/ });*/
} }
export function intl(data: any, params?: object): string { export function intl(data: any, params?: object): ReactNode {
if (!isI18nData(data)) { if (!isI18nData(data)) {
return data; return data;
} }
if (data.intl) {
return data.intl;
}
const locale = globalLocale.getLocale(); const locale = globalLocale.getLocale();
const tries = generateTryLocales(locale); const tries = generateTryLocales(locale);
let msg: string | undefined; let msg: string | undefined;

View File

@ -146,5 +146,8 @@
} }
} }
} }
>.lc-block-setter {
flex: 1;
}
} }
} }

View File

@ -70,13 +70,6 @@ export class SettingsMain {
this._settings = this.designer.createSettingEntry(this.editor, nodes); this._settings = this.designer.createSettingEntry(this.editor, nodes);
} }
onceOutlineVisible(fn: () => void): () => void {
this.emitter.on('outline-visible', fn);
return () => {
this.emitter.removeListener('outline-visible', fn);
};
}
purge() { purge() {
this.disposeListener(); this.disposeListener();
this.emitter.removeAllListeners(); this.emitter.removeAllListeners();

View File

@ -1,4 +1,5 @@
import { TransformedComponentMetadata, FieldConfig, SettingTarget } from '@ali/lowcode-types'; import { TransformedComponentMetadata, FieldConfig, SettingTarget } from '@ali/lowcode-types';
import { IconSlot } from '../icons/slot';
export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata { export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata {
const { componentName, configure = {} } = metadata; const { componentName, configure = {} } = metadata;
@ -80,7 +81,21 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
}); });
} }
// 通用设置 // 通用设置
const propsGroup = props || []; let propsGroup = props || [];
const basicInfo: any = {};
if (componentName === 'Slot') {
basicInfo.icon = IconSlot;
propsGroup = [{
name: '___title',
title: {
type: 'i18n',
'en-US': 'Slot Title',
'zh-CN': '插槽标题'
},
setter: 'StringSetter',
defaultValue: '插槽容器'
}]
}
/* /*
propsGroup.push({ propsGroup.push({
name: '#generals', name: '#generals',
@ -186,6 +201,9 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
title: { type: 'i18n', 'zh-CN': '是否渲染', 'en-US': 'Condition' }, title: { type: 'i18n', 'zh-CN': '是否渲染', 'en-US': 'Condition' },
setter: [{ setter: [{
componentName: 'BoolSetter', componentName: 'BoolSetter',
props: {
defaultValue: true,
}
}, { }, {
componentName: 'VariableSetter' componentName: 'VariableSetter'
}], }],
@ -243,6 +261,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
return { return {
...metadata, ...metadata,
...basicInfo,
configure: { configure: {
...configure, ...configure,
combined, combined,

View File

@ -2,9 +2,9 @@ import { createIntl } from '@ali/lowcode-editor-core';
import en_US from './en-US.json'; import en_US from './en-US.json';
import zh_CN from './zh-CN.json'; import zh_CN from './zh-CN.json';
const { intl, getLocale, setLocale } = createIntl({ const { intl, intlNode, getLocale, setLocale } = createIntl({
'en-US': en_US, 'en-US': en_US,
'zh-CN': zh_CN, 'zh-CN': zh_CN,
}); });
export { intl, getLocale, setLocale }; export { intl, intlNode, getLocale, setLocale };

View File

@ -122,7 +122,7 @@ export default class TreeNode {
return title; return title;
} }
if (isI18nData(title)) { if (isI18nData(title)) {
return intl(title); return intl(title) as string;
} }
return this.node.componentName; return this.node.componentName;
} }

View File

@ -4,7 +4,7 @@ import { observer, Title } from '@ali/lowcode-editor-core';
import { ExclusiveGroup } from '@ali/lowcode-designer'; import { ExclusiveGroup } from '@ali/lowcode-designer';
import TreeNode from '../tree-node'; import TreeNode from '../tree-node';
import TreeNodeView from './tree-node'; import TreeNodeView from './tree-node';
import { intl } from '../locale'; import { intlNode } from '../locale';
@observer @observer
export default class TreeBranches extends Component<{ export default class TreeBranches extends Component<{
@ -119,7 +119,7 @@ class TreeNodeSlots extends Component<{
data-id={treeNode.id} data-id={treeNode.id}
> >
<div className="tree-node-slots-title"> <div className="tree-node-slots-title">
<Title title={{ type: 'i18n', intl: intl('Slots') }} /> <Title title={{ type: 'i18n', intl: intlNode('Slots') }} />
</div> </div>
{treeNode.slots.map(tnode => ( {treeNode.slots.map(tnode => (
<TreeNodeView key={tnode.id} treeNode={tnode} /> <TreeNodeView key={tnode.id} treeNode={tnode} />

View File

@ -5,12 +5,11 @@ import { IconArrowRight } from '../icons/arrow-right';
import { IconEyeClose } from '../icons/eye-close'; import { IconEyeClose } from '../icons/eye-close';
import { IconLock } from '../icons/lock'; import { IconLock } from '../icons/lock';
import { IconUnlock } from '../icons/unlock'; import { IconUnlock } from '../icons/unlock';
import { intl } from '../locale'; import { intl, intlNode } from '../locale';
import TreeNode from '../tree-node'; import TreeNode from '../tree-node';
import { IconEye } from '../icons/eye'; import { IconEye } from '../icons/eye';
import { IconCond } from '../icons/cond'; import { IconCond } from '../icons/cond';
import { IconLoop } from '../icons/loop'; import { IconLoop } from '../icons/loop';
import { IconSlot } from '../icons/slot';
import { createIcon } from '@ali/lowcode-utils'; import { createIcon } from '@ali/lowcode-utils';
@observer @observer
@ -104,22 +103,21 @@ export default class TreeTitle extends Component<{
{node.slotFor && ( {node.slotFor && (
<a className="tree-node-tag slot"> <a className="tree-node-tag slot">
{/* todo: click redirect to prop */} {/* todo: click redirect to prop */}
<IconSlot /> <Tip>{intlNode('Slot for {prop}', { prop: node.slotFor.key })}</Tip>
<Tip>{intl('Slot for {prop}', { prop: node.slotFor.key })}</Tip>
</a> </a>
)} )}
{node.hasLoop() && ( {node.hasLoop() && (
<a className="tree-node-tag loop"> <a className="tree-node-tag loop">
{/* todo: click todo something */} {/* todo: click todo something */}
<IconLoop /> <IconLoop />
<Tip>{intl('Loop')}</Tip> <Tip>{intlNode('Loop')}</Tip>
</a> </a>
)} )}
{node.hasCondition() && !node.conditionGroup && ( {node.hasCondition() && !node.conditionGroup && (
<a className="tree-node-tag cond"> <a className="tree-node-tag cond">
{/* todo: click todo something */} {/* todo: click todo something */}
<IconCond /> <IconCond />
<Tip>{intl('Conditional')}</Tip> <Tip>{intlNode('Conditional')}</Tip>
</a> </a>
)} )}
</Fragment> </Fragment>

View File

@ -4,6 +4,6 @@
"outDir": "lib" "outDir": "lib"
}, },
"include": [ "include": [
"./src/" "./src/",
] ]
} }

View File

@ -6,7 +6,7 @@ class Slot extends Component {
componentName: 'Slot', componentName: 'Slot',
configure: { configure: {
props: [{ props: [{
name: '___title___', name: '___title',
title: { title: {
type: 'i18n', type: 'i18n',
'en-US': 'Slot Title', 'en-US': 'Slot Title',
@ -15,7 +15,7 @@ class Slot extends Component {
setter: 'StringSetter', setter: 'StringSetter',
defaultValue: '插槽容器' defaultValue: '插槽容器'
}, { }, {
name: '___params___', name: '___params',
title: { title: {
type: 'i18n', type: 'i18n',
'en-US': 'Slot Params', 'en-US': 'Slot Params',

View File

@ -237,7 +237,7 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
} }
} }
if (collapse || collapsed || fieldCollapsed) { if (collapse || collapsed || fieldCollapsed || extraProps.display === DISPLAY_TYPE.ENTRY) {
extraProps.defaultCollapsed = true; extraProps.defaultCollapsed = true;
} }
function isDisabled(field: Field) { function isDisabled(field: Field) {
@ -287,10 +287,14 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
if (slotName && initialValue === true) { if (slotName && initialValue === true) {
initialFn = (field: any, value: any) => { initialFn = (field: any, value: any) => {
if (isJSSlot(value)) { if (isJSSlot(value)) {
return value; return {
title: slotTitle || title,
...value,
};
} }
return { return {
type: 'JSSlot', type: 'JSSlot',
title: slotTitle || title,
value: initialChildren, value: initialChildren,
}; };
}; };
@ -351,10 +355,14 @@ export function upgradePropConfig(config: OldPropConfig, addInitial: AddIntial)
componentName: 'SlotSetter', componentName: 'SlotSetter',
initialValue: (field: any, value: any) => { initialValue: (field: any, value: any) => {
if (isJSSlot(value)) { if (isJSSlot(value)) {
return value; return {
title: slotTitle || title,
...value,
};
} }
return { return {
type: 'JSSlot', type: 'JSSlot',
title: slotTitle || title,
value: value == null ? initialChildren : value, value: value == null ? initialChildren : value,
}; };
}, },

View File

@ -2,11 +2,12 @@ import { Component } from 'react';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { fromJS, Iterable, Map as IMMap } from 'immutable'; import { fromJS, Iterable, Map as IMMap } from 'immutable';
import logger from '@ali/vu-logger'; import logger from '@ali/vu-logger';
import { uniqueId, cloneDeep, isDataEqual, combineInitial, Transducer } from '@ali/ve-utils'; import { cloneDeep, isDataEqual, combineInitial, Transducer } from '@ali/ve-utils';
import I18nUtil from '@ali/ve-i18n-util'; import I18nUtil from '@ali/ve-i18n-util';
import { getSetter } from '@ali/lowcode-editor-core'; import { getSetter } from '@ali/lowcode-editor-core';
import { editor } from './editor'; import { editor } from './editor';
import { OldPropConfig, DISPLAY_TYPE } from './bundle/upgrade-metadata'; import { OldPropConfig, DISPLAY_TYPE } from './bundle/upgrade-metadata';
import { uniqueId } from '@ali/lowcode-utils';
type IPropConfig = OldPropConfig; type IPropConfig = OldPropConfig;
@ -108,7 +109,7 @@ export default class Prop implements IVariableSettable {
this.parent = parent; this.parent = parent;
} }
this.id = uniqueId(null as any, 'prop', 'engine-prop'); this.id = uniqueId('prop');
if (typeof config.setter === 'string') { if (typeof config.setter === 'string') {
config.setter = getSetter(config.setter)?.component as any; config.setter = getSetter(config.setter)?.component as any;