|
|
@@ -0,0 +1,536 @@
|
|
|
+import React from 'react'
|
|
|
+import cls from 'classnames'
|
|
|
+import i18n from 'i18next'
|
|
|
+import { Menu, Dropdown } from 'antd'
|
|
|
+import newEventActions from 'actions/newEvent'
|
|
|
+import treeActions from 'actions/tree'
|
|
|
+import newEventStores from 'stores/newEvent'
|
|
|
+import widgetStore from 'stores/widget'
|
|
|
+import treeStores from 'stores/tree'
|
|
|
+import { shallowEqualImmutable } from 'utils/utils'
|
|
|
+import getTypeIcon from 'utils/commons/getTypeIcon'
|
|
|
+import {
|
|
|
+ getEventBlockByBid,
|
|
|
+ getParentBlock,
|
|
|
+ getChildIndex,
|
|
|
+ getEventNodeById,
|
|
|
+ getActionBlockObjNode
|
|
|
+} from 'stores/funcs/newEvent'
|
|
|
+import {
|
|
|
+ nodeIsFunctionGroup,
|
|
|
+ nodeIsService,
|
|
|
+ nodeIsTransaction,
|
|
|
+ nodeIsIotMessage,
|
|
|
+ nodeIsDyTransaction,
|
|
|
+ nodeIsFunction
|
|
|
+} from 'stores/funcs/nodeType'
|
|
|
+import { getNodeIconByEnvs } from 'stores/funcs/tree'
|
|
|
+import {
|
|
|
+ isServerRootNode,
|
|
|
+ isChangedActionValid
|
|
|
+} from 'stores/funcs/event/methodUtils'
|
|
|
+import { getNodeTypeName, getFakeNodeIds } from 'stores/funcs/event/fakeNode'
|
|
|
+import { EVENT_BLOCK_TYPE, BLOCK_OP_TYPE } from 'const/const'
|
|
|
+import { specialActionObj, fakeNodeIds } from 'const/enum'
|
|
|
+import BlockEnable from '../BlockEnable'
|
|
|
+import ObjSelector from 'src/components/common/objSelector/ObjSelector'
|
|
|
+import TitleTip from 'src/components/common/titleTip/TitleTip'
|
|
|
+
|
|
|
+const MenuItem = Menu.Item
|
|
|
+
|
|
|
+export default class BlockActionObject extends React.Component {
|
|
|
+ constructor(props) {
|
|
|
+ super(props)
|
|
|
+ this.curEventNodeId = newEventStores.curEventNodeId
|
|
|
+ this.state = {
|
|
|
+ object: this.getObject()
|
|
|
+ }
|
|
|
+ this.objSelector = React.createRef()
|
|
|
+
|
|
|
+ this.onEventChange = this.onEventChange.bind(this)
|
|
|
+ this.genObjSelectConfig = this.genObjSelectConfig.bind(this)
|
|
|
+
|
|
|
+ this.onAddAction = this.onAddAction.bind(this)
|
|
|
+
|
|
|
+ this.shouldClearAction = this.shouldClearAction.bind(this)
|
|
|
+ this.dealChangeActionObject = this.dealChangeActionObject.bind(this)
|
|
|
+ this.onSelectObj = this.onSelectObj.bind(this)
|
|
|
+ this.onActionObjectSelect = this.onActionObjectSelect.bind(this)
|
|
|
+
|
|
|
+ this.getSpecialObjName = this.getSpecialObjName.bind(this)
|
|
|
+ this.getActionObjName = this.getActionObjName.bind(this)
|
|
|
+ this.getActionObjIcon = this.getActionObjIcon.bind(this)
|
|
|
+ this.getObject = this.getObject.bind(this)
|
|
|
+
|
|
|
+ this.jumpToNode = this.jumpToNode.bind(this)
|
|
|
+ this.objJumpBtn = this.objJumpBtn.bind(this)
|
|
|
+ }
|
|
|
+
|
|
|
+ shouldComponentUpdate(nextProps, nextState) {
|
|
|
+ return (
|
|
|
+ !shallowEqualImmutable(this.props, nextProps) ||
|
|
|
+ !shallowEqualImmutable(this.state, nextState)
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ componentDidUpdate(preProps) {
|
|
|
+ if (preProps.bid !== this.props.bid) {
|
|
|
+ this.setState({
|
|
|
+ object: this.getObject()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ componentDidMount() {
|
|
|
+ this.unsubscribe = newEventStores.listen(this.onEventChange)
|
|
|
+ }
|
|
|
+
|
|
|
+ componentWillUnmount() {
|
|
|
+ this.unsubscribe()
|
|
|
+ }
|
|
|
+
|
|
|
+ onEventChange(status) {
|
|
|
+ let obj = {}
|
|
|
+ if (status) {
|
|
|
+ if (
|
|
|
+ status.types.includes('curEventNodeId') &&
|
|
|
+ this.curEventNodeId !== status.data.curEventNodeId
|
|
|
+ ) {
|
|
|
+ this.curEventNodeId = status.data.curEventNodeId
|
|
|
+ }
|
|
|
+ if (
|
|
|
+ status.types.includes('reloadBlock') &&
|
|
|
+ this.props.bid === status.data.affectBlockId
|
|
|
+ ) {
|
|
|
+ obj.object = this.getObject()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (Object.keys(obj).length > 0) {
|
|
|
+ this.setState(obj)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ genObjSelectConfig() {
|
|
|
+ return {
|
|
|
+ srcId: this.curEventNodeId,
|
|
|
+ srcInStage: {
|
|
|
+ stage: true,
|
|
|
+ server: {
|
|
|
+ allow: [
|
|
|
+ 'service',
|
|
|
+ 'db',
|
|
|
+ 'data-live',
|
|
|
+ 'data-excel',
|
|
|
+ 'data-sharedService'
|
|
|
+ ],
|
|
|
+ forbidden: [
|
|
|
+ 'data-mallProduct',
|
|
|
+ 'data-mallOrder',
|
|
|
+ 'data-mallCart',
|
|
|
+ 'data-voteCandidate',
|
|
|
+ 'data-voteRecord',
|
|
|
+ 'data-dynamoDb',
|
|
|
+ 'data-cacheDb',
|
|
|
+ 'data-email',
|
|
|
+ 'data-sms'
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ srcInServer: {
|
|
|
+ stage: false,
|
|
|
+ server: true
|
|
|
+ },
|
|
|
+ srcFrom: 'actionObj'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onAddAction() {
|
|
|
+ let nodeId = this.props.eventNodeId || this.curEventNodeId
|
|
|
+ let parentBlock = getParentBlock(this.props.bid, nodeId)
|
|
|
+ if (parentBlock) {
|
|
|
+ let index = getChildIndex(parentBlock, this.props.bid)
|
|
|
+ if (index !== -1) {
|
|
|
+ newEventActions.addBlock({
|
|
|
+ type: EVENT_BLOCK_TYPE.ACTION,
|
|
|
+ parentBid: parentBlock.eventId ? parentBlock.eventId : parentBlock.ln,
|
|
|
+ index: index + 1
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ shouldClearAction(block, obj) {
|
|
|
+ let result = false
|
|
|
+ let nodeId = this.props.eventNodeId || this.curEventNodeId
|
|
|
+ let node = getEventNodeById(nodeId)
|
|
|
+ // 对象改变
|
|
|
+ let preObj = this.getBlockObj(block)
|
|
|
+ let preObject = getActionBlockObjNode({
|
|
|
+ obj: preObj,
|
|
|
+ nodeId
|
|
|
+ })
|
|
|
+ let curObject = getActionBlockObjNode({
|
|
|
+ obj: obj,
|
|
|
+ nodeId
|
|
|
+ })
|
|
|
+ if (
|
|
|
+ (!preObject && curObject) ||
|
|
|
+ (preObject && !curObject) ||
|
|
|
+ (!preObject && !curObject && block.op) ||
|
|
|
+ (preObject && curObject && preObject.type !== curObject.type)
|
|
|
+ ) {
|
|
|
+ result = true
|
|
|
+ }
|
|
|
+ // 处理服务为当前对象,且动作为设置返回结果的情况下,选择其他服务时,需要clear
|
|
|
+ let actionName
|
|
|
+ if (block.op === BLOCK_OP_TYPE.CALL) {
|
|
|
+ if (block.val && Array.isArray(block.val)) {
|
|
|
+ actionName = block.val[1]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (
|
|
|
+ !result &&
|
|
|
+ !isChangedActionValid({
|
|
|
+ rootNode: node,
|
|
|
+ blockNode: curObject,
|
|
|
+ blockObj: obj,
|
|
|
+ actionName
|
|
|
+ })
|
|
|
+ ) {
|
|
|
+ result = true
|
|
|
+ }
|
|
|
+ return result
|
|
|
+ }
|
|
|
+
|
|
|
+ dealChangeActionObject(block, obj) {
|
|
|
+ if (
|
|
|
+ block &&
|
|
|
+ (block.op === BLOCK_OP_TYPE.SET ||
|
|
|
+ block.op === BLOCK_OP_TYPE.CALL ||
|
|
|
+ block.op === BLOCK_OP_TYPE.LET ||
|
|
|
+ block.op === undefined)
|
|
|
+ ) {
|
|
|
+ if (this.shouldClearAction(block, obj)) {
|
|
|
+ block.op = undefined
|
|
|
+ block.val = ''
|
|
|
+ block.args = []
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onSelectObj(obj) {
|
|
|
+ let nodeId = this.props.eventNodeId || this.curEventNodeId
|
|
|
+ let curBlock = getEventBlockByBid(this.props.bid, nodeId)
|
|
|
+ if (curBlock) {
|
|
|
+ this.dealChangeActionObject(curBlock, obj)
|
|
|
+ this.setState(
|
|
|
+ {
|
|
|
+ object: obj
|
|
|
+ },
|
|
|
+ () => {
|
|
|
+ newEventActions.updateBlockProp({
|
|
|
+ nodeId,
|
|
|
+ blockId: this.props.bid,
|
|
|
+ prop: 'object',
|
|
|
+ value: obj,
|
|
|
+ trigger: true
|
|
|
+ })
|
|
|
+ // 更新部分obj的参数
|
|
|
+ let node = getActionBlockObjNode({ obj, nodeId })
|
|
|
+ newEventStores.reloadAction(node && node.id)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onActionObjectSelect(option) {
|
|
|
+ if (option) {
|
|
|
+ if (option.key === 'objSelector') {
|
|
|
+ this.objSelector && this.objSelector.current.componentNode.click()
|
|
|
+ } else {
|
|
|
+ this.onSelectObj(option.key)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ getSpecialObjName(obj) {
|
|
|
+ let name = obj
|
|
|
+ switch (obj) {
|
|
|
+ case 'curObj':
|
|
|
+ let nodeId = this.props.eventNodeId || this.curEventNodeId
|
|
|
+ let node = getEventNodeById(nodeId)
|
|
|
+ if (node) {
|
|
|
+ if (nodeIsService(node.type)) {
|
|
|
+ if (nodeIsTransaction(node.type)) {
|
|
|
+ name = i18n.t('EventView.jenga_action_block.curTransaction')
|
|
|
+ } else if (nodeIsIotMessage(node.type)) {
|
|
|
+ name = i18n.t('EventView.jenga_action_block.curIot')
|
|
|
+ } else {
|
|
|
+ name = i18n.t('EventView.jenga_action_block.curService')
|
|
|
+ }
|
|
|
+ } else if (nodeIsFunctionGroup(node.type)) {
|
|
|
+ name = i18n.t('EventView.jenga_action_block.curAction')
|
|
|
+ } else {
|
|
|
+ name = i18n.t('EventView.jenga_action_block.curObject')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break
|
|
|
+ default:
|
|
|
+ name = i18n.t('EventView.jenga_action_block.' + obj)
|
|
|
+ }
|
|
|
+ return name
|
|
|
+ }
|
|
|
+
|
|
|
+ getActionObjName(obj) {
|
|
|
+ if (obj === 'objSelector') {
|
|
|
+ return i18n.t('EventView.jenga_action_block.objSelector')
|
|
|
+ } else {
|
|
|
+ // 特殊且合法的对象
|
|
|
+ if (specialActionObj.indexOf(obj) >= 0) {
|
|
|
+ return this.actionObjList.indexOf(obj) >= 0
|
|
|
+ ? this.getSpecialObjName(obj)
|
|
|
+ : ''
|
|
|
+ } else if (fakeNodeIds.indexOf(obj) >= 0) {
|
|
|
+ return getNodeTypeName(obj)
|
|
|
+ } else {
|
|
|
+ let _obj = getEventNodeById(obj)
|
|
|
+ return _obj ? _obj.uis.name || _obj.type : ''
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ getActionObjIcon(obj) {
|
|
|
+ let nodeId = this.props.eventNodeId || this.curEventNodeId
|
|
|
+ let node = getActionBlockObjNode({ obj, nodeId })
|
|
|
+ let icon = null
|
|
|
+ let type = 'map'
|
|
|
+ if (node) {
|
|
|
+ if (node && node.type && widgetStore.widget[node.type]) {
|
|
|
+ icon = getNodeIconByEnvs(
|
|
|
+ node.type,
|
|
|
+ widgetStore.widget[node.type].icon,
|
|
|
+ node.envs
|
|
|
+ )
|
|
|
+ type = 'icon'
|
|
|
+ }
|
|
|
+ if (!icon) {
|
|
|
+ icon = getTypeIcon(node, treeStores.curCaseType)
|
|
|
+ type = 'map'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return { icon, type }
|
|
|
+ }
|
|
|
+
|
|
|
+ getBlockObj(block) {
|
|
|
+ let obj
|
|
|
+ if (block) {
|
|
|
+ if (block.isCurObj) {
|
|
|
+ obj = 'curObj'
|
|
|
+ } else {
|
|
|
+ switch (block.op) {
|
|
|
+ case BLOCK_OP_TYPE.SET:
|
|
|
+ if (block.args && block.args[0] && block.args[0].val) {
|
|
|
+ let _val = block.args[0].val
|
|
|
+ if (Array.isArray(_val) && _val[0]) {
|
|
|
+ obj = _val[0]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break
|
|
|
+ case BLOCK_OP_TYPE.CALL:
|
|
|
+ if (block.val && Array.isArray(block.val)) {
|
|
|
+ obj = block.val[0]
|
|
|
+ }
|
|
|
+ break
|
|
|
+ case BLOCK_OP_TYPE.LET:
|
|
|
+ if (block.args && block.args[0]) {
|
|
|
+ let tempBlock = block.args[0]
|
|
|
+ if (
|
|
|
+ tempBlock.op === BLOCK_OP_TYPE.CALL &&
|
|
|
+ tempBlock.val &&
|
|
|
+ Array.isArray(tempBlock.val)
|
|
|
+ ) {
|
|
|
+ obj = tempBlock.val[0]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break
|
|
|
+ default:
|
|
|
+ obj = block.val
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return obj
|
|
|
+ }
|
|
|
+
|
|
|
+ getObject() {
|
|
|
+ let _obj
|
|
|
+ let nodeId = this.props.eventNodeId || this.curEventNodeId
|
|
|
+ let curBlock = getEventBlockByBid(this.props.bid, nodeId)
|
|
|
+ if (curBlock) {
|
|
|
+ _obj = this.getBlockObj(curBlock)
|
|
|
+ }
|
|
|
+ return _obj
|
|
|
+ }
|
|
|
+
|
|
|
+ get actionObjList() {
|
|
|
+ let curNode = getEventNodeById(this.state.curEventNodeId)
|
|
|
+ if (nodeIsDyTransaction(curNode && curNode.type)) {
|
|
|
+ // dy事务无相关选项
|
|
|
+ return []
|
|
|
+ }
|
|
|
+ // 只有当前对象
|
|
|
+ return specialActionObj.slice(0, 1)
|
|
|
+ }
|
|
|
+
|
|
|
+ get fakeNodes() {
|
|
|
+ let fakeNodeIds = getFakeNodeIds() || []
|
|
|
+ if (isServerRootNode(getEventNodeById(this.state.curEventNodeId))) {
|
|
|
+ // 后台的伪对象
|
|
|
+ fakeNodeIds = fakeNodeIds.filter(nodeId => {
|
|
|
+ return nodeId === '$sobj_serverSys'
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 前台的伪对象
|
|
|
+ fakeNodeIds = fakeNodeIds.filter(nodeId => {
|
|
|
+ return nodeId !== '$sobj_serverSys'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return fakeNodeIds
|
|
|
+ }
|
|
|
+
|
|
|
+ jumpToNode(e) {
|
|
|
+ e && e.stopPropagation()
|
|
|
+ let nodeId = this.props.eventNodeId || this.curEventNodeId
|
|
|
+ let node = getActionBlockObjNode({
|
|
|
+ obj: this.state.object,
|
|
|
+ nodeId
|
|
|
+ })
|
|
|
+ if (node && this.state.object !== 'curObj') {
|
|
|
+ if (nodeIsFunctionGroup(node.type) || nodeIsService(node.type)) {
|
|
|
+ newEventActions.toggleEventView({
|
|
|
+ show: true,
|
|
|
+ nodeId: node.id,
|
|
|
+ mode: 'jenga'
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ if (newEventStores.showEventView) {
|
|
|
+ newEventActions.toggleEventView({ show: false })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ treeActions.selectNode(node.id)
|
|
|
+ // if (nodeIsFunction(node.type)) {
|
|
|
+ // newEventActions.addNavId(node)
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ objJumpBtn() {
|
|
|
+ let obj = this.state.object
|
|
|
+ if (obj !== 'curObj' && fakeNodeIds.indexOf(obj) === -1) {
|
|
|
+ let node = getActionBlockObjNode({
|
|
|
+ obj
|
|
|
+ })
|
|
|
+ if (
|
|
|
+ node &&
|
|
|
+ (nodeIsFunctionGroup(node.type) ||
|
|
|
+ nodeIsService(node.type) ||
|
|
|
+ nodeIsFunction(node.type))
|
|
|
+ ) {
|
|
|
+ return (
|
|
|
+ <button className="btn-clear btn-jump" onClick={this.jumpToNode} />
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null
|
|
|
+ }
|
|
|
+
|
|
|
+ render() {
|
|
|
+ let actionObjIconInfo = this.getActionObjIcon(this.state.object)
|
|
|
+ let actionObjMenu = () => {
|
|
|
+ let fakeNodes = this.fakeNodes
|
|
|
+ return (
|
|
|
+ <Menu
|
|
|
+ className="object-select-menu"
|
|
|
+ onClick={this.onActionObjectSelect}
|
|
|
+ >
|
|
|
+ <MenuItem key={'objSelector'}>
|
|
|
+ {this.getActionObjName('objSelector')}
|
|
|
+ </MenuItem>
|
|
|
+ <Menu.Divider />
|
|
|
+ {this.actionObjList.map(obj => {
|
|
|
+ return <MenuItem key={obj}>{this.getActionObjName(obj)}</MenuItem>
|
|
|
+ })}
|
|
|
+ {fakeNodes && fakeNodes.length > 0 ? <Menu.Divider /> : null}
|
|
|
+ {!fakeNodes || fakeNodes.length === 0
|
|
|
+ ? null
|
|
|
+ : fakeNodes.map(node => {
|
|
|
+ return (
|
|
|
+ <MenuItem key={node} className={'fake-node'}>
|
|
|
+ {this.getActionObjName(node)}
|
|
|
+ </MenuItem>
|
|
|
+ )
|
|
|
+ })}
|
|
|
+ </Menu>
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className="action-object f--h">
|
|
|
+ <BlockEnable bid={this.props.bid} isEnable={this.props.isEnable} />
|
|
|
+ <div className="object-wrap">
|
|
|
+ <div className="select-wrap f--hlc">
|
|
|
+ <Dropdown
|
|
|
+ trigger={['click']}
|
|
|
+ getPopupContainer={triggerNode => triggerNode.parentNode}
|
|
|
+ overlayClassName={'object-select-dropdown'}
|
|
|
+ overlay={actionObjMenu()}
|
|
|
+ >
|
|
|
+ <div className="object-select f--hlc">
|
|
|
+ <ObjSelector
|
|
|
+ ref={this.objSelector}
|
|
|
+ stopPropagation={true}
|
|
|
+ config={this.genObjSelectConfig()}
|
|
|
+ cb={this.onSelectObj}
|
|
|
+ />
|
|
|
+ {actionObjIconInfo.type === 'icon' ? (
|
|
|
+ <div
|
|
|
+ className="icon-svg f--hcc"
|
|
|
+ dangerouslySetInnerHTML={{
|
|
|
+ __html: actionObjIconInfo.icon
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ ) : actionObjIconInfo.icon ? (
|
|
|
+ <div className={cls('icon-type', actionObjIconInfo.icon)} />
|
|
|
+ ) : null}
|
|
|
+ <TitleTip nodeId={this.state.object} maxLength={4}>
|
|
|
+ <input
|
|
|
+ value={this.getActionObjName(this.state.object)}
|
|
|
+ readOnly={true}
|
|
|
+ className={cls('ant-dropdown-input', {
|
|
|
+ 'fake-node': fakeNodeIds.indexOf(this.state.object) >= 0
|
|
|
+ })}
|
|
|
+ placeholder={i18n.t(
|
|
|
+ 'EventView.jenga_action_block.selectObject'
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ </TitleTip>
|
|
|
+ {this.objJumpBtn()}
|
|
|
+ <div className="ant-dropdown-icon" />
|
|
|
+ </div>
|
|
|
+ </Dropdown>
|
|
|
+ </div>
|
|
|
+ <div className="add-action-block-wrap f--hcc">
|
|
|
+ <button
|
|
|
+ className="btn-clear btn-add-action-block"
|
|
|
+ onClick={this.onAddAction}
|
|
|
+ >
|
|
|
+ <div className="icon">
|
|
|
+ <span className="horizon" />
|
|
|
+ <span className="vertical" />
|
|
|
+ </div>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }
|
|
|
+}
|