Commit d6620bc0 authored by DarkForst's avatar DarkForst

core UI change

parent eef3f0aa
.pos_end{
display: flex;
align-items: center;
justify-content: flex-end;
}
export const algoData = [
{
id: 'recentlyUsed',
name: '最近使用',
isDir: true,
children: [
{
id: 10,
defSource: 2,
docUrl: '',
ioType: 0,
up: 148,
down: 11,
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_1',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
engineType: 0,
isComposite: false,
sequence: 0,
owner: 'system',
description: '组件描述信息',
name: '算法组件1',
parentId: 'recentlyUsed',
isBranch: false,
social: {
defSource: 2,
isEnabled: true,
docUrl: '#',
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_1',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
owner: 'system',
description: '组件描述信息',
name: '算法组件1',
id: 10,
},
},
{
id: 11,
defSource: 2,
docUrl: '',
ioType: 0,
up: 148,
down: 11,
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_2',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
engineType: 0,
isComposite: false,
sequence: 0,
owner: 'system',
description: '组件描述信息',
name: '算法组件2',
parentId: 'recentlyUsed',
isBranch: false,
social: {
defSource: 2,
isEnabled: true,
docUrl: '#',
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_2',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
owner: 'system',
description: '组件描述信息',
name: '算法组件2',
id: 11,
},
},
{
id: 12,
defSource: 2,
docUrl: '',
ioType: 0,
up: 148,
down: 11,
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_3',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
engineType: 0,
isComposite: false,
sequence: 0,
owner: 'system',
description: '组件描述信息',
name: '算法组件3',
parentId: 'recentlyUsed',
isBranch: false,
social: {
defSource: 2,
isEnabled: true,
docUrl: '#',
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_3',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
owner: 'system',
description: '组件描述信息',
name: '算法组件3',
id: 12,
},
},
],
},
{
name: '数据读写',
id: 21,
category: 'source',
isDir: true,
children: [
{
defSource: 2,
docUrl: '',
ioType: 0,
up: 148,
down: 11,
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'odps_source',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
engineType: 0,
isComposite: false,
sequence: 0,
owner: 'system',
description: '组件描述信息',
name: '读数据表',
id: 100,
parentId: 'recentlyUsed',
isBranch: false,
social: {
defSource: 2,
isEnabled: true,
docUrl: '#',
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'odps_source',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
owner: 'system',
description: '组件描述信息',
name: '读数据表',
id: 100,
},
},
],
isBranch: true,
isExpanded: false,
codeName: 'source',
parentId: 'platformAlgo',
},
{
name: '统计分析',
id: 22,
category: 'analytics',
isDir: true,
children: [],
isBranch: true,
isExpanded: false,
codeName: 'analytics',
parentId: 'platformAlgo',
},
{
name: '算法',
id: 23,
category: 'ai_algo',
isDir: true,
children: [],
isBranch: true,
isExpanded: false,
codeName: 'algorithm',
parentId: 'platformAlgo',
},
{
name: '预测',
id: 24,
category: 'predict',
isDir: true,
children: [],
isBranch: true,
isExpanded: false,
codeName: 'predict',
parentId: 'platformAlgo',
},
{
name: '评估',
id: 25,
category: 'evaluation',
isDir: true,
children: [],
isBranch: true,
isExpanded: false,
codeName: 'evaluation',
parentId: 'platformAlgo',
},
]
export const searchByKeyword = async (keyword: string) => {
return Array(10)
.fill(null)
.map((i, idx) => {
return {
defSource: 2,
docUrl: '',
ioType: 0,
up: 148,
down: 11,
iconType: 1,
isDir: false,
isDisabled: false,
author: 'demo author',
codeName: `${keyword}${idx}`,
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
engineType: 0,
isComposite: false,
sequence: 0,
owner: 'system',
description: '组件描述信息',
name: `${keyword}__${idx}`,
id: idx,
parentId: 'recentlyUsed',
isBranch: false,
social: {
defSource: 2,
isEnabled: true,
docUrl: '#',
iconType: 1,
isDisabled: false,
author: 'demo author',
name: `${keyword}-${idx}`,
codeName: `${keyword}${idx}`,
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
owner: 'system',
description: '组件描述信息',
id: idx,
},
}
})
}
This diff is collapsed.
/* eslint-disable no-param-reassign */ /* eslint-disable no-param-reassign */
import { useCallback, useState } from 'react' import { useCallback, useState } from 'react'
import { algoData, searchByKeyword } from '@/mock/algo' import { algoData, searchByKeyword } from '@/services/algo'
export namespace Res { export namespace Res {
export interface Data { export interface Data {
...@@ -70,16 +70,16 @@ function dfs( ...@@ -70,16 +70,16 @@ function dfs(
export default () => { export default () => {
const [keyword, setKeyword] = useState<string>('') // 搜索关键字 const [keyword, setKeyword] = useState<string>('') // 搜索关键字
const [loading, setLoading] = useState<boolean>(false) // 加载状态 const [loading, setLoading] = useState<boolean>(false) // 加载状态
const [componentTreeNodes, setComponentTreeNodes] = useState<any[]>([]) const [componentApplications, setComponentApplications] = useState<any[]>([])
const [searchList, setSearchList] = useState<any[]>([]) // 搜索结果列表 const [searchList, setSearchList] = useState<any[]>([]) // 搜索结果列表
// 加载组件 // 加载组件
const loadComponentNodes = useCallback(() => { const loadComponentApplications = useCallback(() => {
setLoading(true) setLoading(true)
const load = async () => { const load = async () => {
try { try {
if (algoData) { if (algoData) {
setComponentTreeNodes(algoData) setComponentApplications(algoData)
} }
} finally { } finally {
setLoading(false) setLoading(false)
...@@ -112,12 +112,12 @@ export default () => { ...@@ -112,12 +112,12 @@ export default () => {
// 状态 // 状态
keyword, keyword,
loading, loading,
componentTreeNodes, componentApplications,
searchList, searchList,
// 方法 // 方法
setKeyword, setKeyword,
loadComponentNodes, loadComponentApplications, // 应用组件
search, search,
} }
} }
export const COMMONLY_USED = {
VARIATE: 'COMMONLY_USED_VARIATE', // 变量
} // 通用组件
export const SCENE_DISPLAY = {
EQUIPMENT: 'SCENE_DISPLAY_EQUIPMENT', // 设备触发
TIME: 'SCENE_DISPLAY_TIME', // 时间触发
MANUAL: 'SCENE_DISPLAY_MANUAL', // 手动触发
} // 场景触发
export const SIGN_OPERATION = {
RELATION: 'SIGN_OPERATION_RELATION', // 关系运算
LOGICAL: 'SIGN_OPERATION_LOGICAL', // 逻辑运算
CONDITION: 'SIGN_OPERATION_CONDITION', // 条件判断
} // 运算符号
export const MOTION_OPERATION = {
EQUIPMENT: 'MOTION_OPERATION_EQUIPMENT', // 设备触发
TIME: 'MOTION_OPERATION_TIME', // 时间触发
MANUAL: 'MOTION_OPERATION_MANUAL', // 手动触发
} // 运动符号
export const COMPONENTS_TYPE = {
COMMONLY_USED: 'COMMONLY_USED', // 通用组件
SCENE_DISPLAY: 'SCENE_DISPLAY', // 场景触发
SIGN_OPERATION: 'SIGN_OPERATION', // 运算符号
MOTION_OPERATION: 'MOTION_OPERATION', // 运动符号
APPLICATION: 'APPLICATION' // 应用组件
}
import { useMemo } from 'react'
import {} from '../components-type'
interface NodeParams {
name: string
x: number
y: number
}
const useCreateNode = ({ name, x, y }: NodeParams) => {
const id = `${Date.now()}`
return {
id,
name,
inPorts: [
{
tableName: 'germany_credit_data',
sequence: 1,
description: '输入',
id: id + '_in',
}
],
outPorts: [
{
tableName: 'germany_credit_data',
sequence: 1,
description: '输出',
id: id + '_out',
}
],
positionX: x,
positionY: y,
category: 'source',
groupId: 0,
}
}
export default useCreateNode
import {
COMPONENTS_TYPE,
COMMONLY_USED,
SCENE_DISPLAY,
SIGN_OPERATION,
MOTION_OPERATION
} from '@/pages/common/components-type'
export const componentsData = [
{
id: COMPONENTS_TYPE.COMMONLY_USED,
name: '通用组件',
isDir: true,
children: [
{
id: COMMONLY_USED.VARIATE,
name: '变量',
}
],
},
{
id: COMPONENTS_TYPE.SCENE_DISPLAY,
name: '场景触发',
isDir: true,
children: [
{
id: SCENE_DISPLAY.EQUIPMENT,
name: '设备触发',
},
{
id: SCENE_DISPLAY.TIME,
name: '时间触发',
},
{
id: SCENE_DISPLAY.MANUAL,
name: '手动按钮',
}
],
},
{
id: COMPONENTS_TYPE.SIGN_OPERATION,
name: '运算符号',
isDir: true,
children: [
{
id: SIGN_OPERATION.RELATION,
name: '关系运算',
},
{
id: SIGN_OPERATION.LOGICAL,
name: '逻辑运算',
},
{
id: SIGN_OPERATION.CONDITION,
name: '条件判断',
}
],
},
{
id: COMPONENTS_TYPE.MOTION_OPERATION,
name: '运动符号',
isDir: true,
children: [
{
id: MOTION_OPERATION.EQUIPMENT,
name: '设备触发',
},
{
id: MOTION_OPERATION.TIME,
name: '时间触发',
},
{
id: MOTION_OPERATION.MANUAL,
name: '手动触发',
}
],
},
{
id: COMPONENTS_TYPE.APPLICATION,
name: '应用组件',
isDir: true,
children: [],
}
]
export const applicationTemplate = () => {
return {
id: 10,
defSource: 2,
docUrl: '',
ioType: 0,
up: 148,
down: 11,
iconType: 1,
author: 'demo author',
codeName: 'algo_1',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
engineType: 0,
owner: 'system',
description: '组件描述信息',
name: '算法组件1',
parentId: 'recentlyUsed',
isBranch: false,
social: {
defSource: 2,
isEnabled: true,
docUrl: '#',
iconType: 1,
author: 'demo author',
codeName: 'algo_1',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
owner: 'system',
description: '组件描述信息',
name: '算法组件1',
id: 10,
},
}
}
...@@ -38,6 +38,13 @@ ...@@ -38,6 +38,13 @@
flex-grow: 1; flex-grow: 1;
} }
} }
.@{ant-prefix}-tree-switcher {
width: 10px;
}
.@{ant-prefix}-tree-switcher .@{ant-prefix}-tree-switcher-icon{
display: none;
}
} }
} }
......
import React, { useCallback } from 'react' import React, { useCallback, useMemo } from 'react'
import { useModel } from 'umi' import { useModel } from 'umi'
import { Tree } from 'antd' import { Tree } from 'antd'
import { FolderFilled, FolderOpenFilled } from '@ant-design/icons' import { FolderFilled, FolderOpenFilled } from '@ant-design/icons'
import { NodeTitle } from './node-title' import { NodeTitle } from './node-title'
import styles from './index.less' import styles from './index.less'
import { componentsData, applicationTemplate } from './componentTreeNodes'
const { DirectoryTree, TreeNode } = Tree const { DirectoryTree, TreeNode } = Tree
...@@ -12,13 +13,13 @@ const FolderIcon = ({ expanded }: { expanded: boolean }) => { ...@@ -12,13 +13,13 @@ const FolderIcon = ({ expanded }: { expanded: boolean }) => {
} }
export const CategoryTree = () => { export const CategoryTree = () => {
const { componentTreeNodes } = useModel('guide-algo-component') const { componentApplications } = useModel('guide-algo-component')
const renderTree = useCallback( const renderTree = useCallback(
(treeList: any[] = [], searchKey: string = '') => { (treeList: any[] = [], searchKey: string = '') => {
return treeList.map((item) => { return treeList.map((item) => {
const { isDir, id, children } = item const { isDir, id, children } = item
const key = id.toString() const key = id.toString();
const title = <NodeTitle node={item} searchKey={searchKey} /> const title = <NodeTitle node={item} searchKey={searchKey} />
if (isDir) { if (isDir) {
...@@ -48,18 +49,23 @@ export const CategoryTree = () => { ...@@ -48,18 +49,23 @@ export const CategoryTree = () => {
[], [],
) )
const treeList = componentTreeNodes.filter((node) => node.status !== 4) const applicationsTreeData = useMemo(() => {
// 根据模板生成应用组件数据格式
const applicationsData = componentApplications?.map(applicationTemplate /* 模板方法 */);
return componentApplications?.map(applicationTemplate);
}, [componentApplications])
// console.log('componentsData', componentsData, renderTree(componentsData))
return ( return (
<div className={styles.list}> <div className={styles.list}>
<DirectoryTree <DirectoryTree
showIcon={true} showIcon={true}
selectable={false} selectable={false}
autoExpandParent={true} defaultExpandAll
className={styles.tree} className={styles.tree}
defaultExpandedKeys={['recentlyUsed']}
> >
{renderTree(treeList)} {renderTree(componentsData)}
</DirectoryTree> </DirectoryTree>
</div> </div>
) )
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
.node { .node {
display: flex; display: flex;
height: 30px; height: 30px;
padding-left: 20px; padding-left: 10px;
font-size: 12px; font-size: 12px;
line-height: 30px; line-height: 30px;
......
...@@ -6,6 +6,7 @@ import { DatabaseFilled, ReadOutlined } from '@ant-design/icons' ...@@ -6,6 +6,7 @@ import { DatabaseFilled, ReadOutlined } from '@ant-design/icons'
import marked from 'marked' import marked from 'marked'
import { useSafeSetHTML } from '@/pages/common/hooks/useSafeSetHtml' import { useSafeSetHTML } from '@/pages/common/hooks/useSafeSetHtml'
import { DRAGGABLE_ALGO_COMPONENT } from '@/constants/graph' import { DRAGGABLE_ALGO_COMPONENT } from '@/constants/graph'
import {COMPONENTS_TYPE} from './componentTreeNodes'
import styles from './node-title.less' import styles from './node-title.less'
marked.setOptions({ marked.setOptions({
...@@ -61,13 +62,13 @@ const InnerNodeTitle = (props: Props) => { ...@@ -61,13 +62,13 @@ const InnerNodeTitle = (props: Props) => {
connectDragSource, connectDragSource,
} = props } = props
const { name = '', isDir } = node const { name = '', isDir } = node
const [visible, setVisible] = useState<boolean>(false) // const [visible, setVisible] = useState<boolean>(false)
const onMouseIn = useCallback(() => { // const onMouseIn = useCallback(() => {
setVisible(true) // setVisible(true)
}, []) // }, [])
const onMouseOut = useCallback(() => { // const onMouseOut = useCallback(() => {
setVisible(false) // setVisible(false)
}, []) // }, [])
// 文件夹 // 文件夹
if (isDir) { if (isDir) {
...@@ -98,8 +99,8 @@ const InnerNodeTitle = (props: Props) => { ...@@ -98,8 +99,8 @@ const InnerNodeTitle = (props: Props) => {
return ( return (
<div <div
className={styles.nodeTitleWrapper} className={styles.nodeTitleWrapper}
onMouseEnter={onMouseIn} // onMouseEnter={onMouseIn}
onMouseLeave={onMouseOut} // onMouseLeave={onMouseOut}
> >
{connectDragPreview( {connectDragPreview(
connectDragSource( connectDragSource(
...@@ -109,19 +110,19 @@ const InnerNodeTitle = (props: Props) => { ...@@ -109,19 +110,19 @@ const InnerNodeTitle = (props: Props) => {
</div>, </div>,
), ),
)} )}
{visible && ( {/*{visible && (*/}
<Popover {/* <Popover*/}
visible={true} {/* visible={true}*/}
title={name} {/* title={name}*/}
placement="right" {/* placement="right"*/}
content={<Document node={node} />} {/* content={<Document node={node} />}*/}
key="description" {/* key="description"*/}
> {/* >*/}
<a className={styles.doc}> {/* <a className={styles.doc}>*/}
<ReadOutlined /> 文档 {/* <ReadOutlined /> 文档*/}
</a> {/* </a>*/}
</Popover> {/* </Popover>*/}
)} {/*)}*/}
</div> </div>
) )
} }
......
...@@ -6,10 +6,10 @@ import { SearchResultList } from './search-result-list' ...@@ -6,10 +6,10 @@ import { SearchResultList } from './search-result-list'
import styles from './index.less' import styles from './index.less'
export const ComponentTree = () => { export const ComponentTree = () => {
const { keyword, loadComponentNodes } = useModel('guide-algo-component') const { keyword, loadComponentApplications } = useModel('guide-algo-component')
useMount(() => { useMount(() => {
loadComponentNodes() loadComponentApplications()
}) })
return ( return (
......
...@@ -13,7 +13,7 @@ export const ComponentSourceTree: React.FC<Props> = (props) => { ...@@ -13,7 +13,7 @@ export const ComponentSourceTree: React.FC<Props> = (props) => {
return ( return (
<div className={classNames(className, styles.componentSourceTree)}> <div className={classNames(className, styles.componentSourceTree)}>
<div className={styles.component}> <div className={styles.component}>
<SearchInput /> {/*<SearchInput />*/}
<ComponentTree /> <ComponentTree />
</div> </div>
</div> </div>
......
...@@ -16,18 +16,18 @@ export const ComponentTreePanel: React.FC<Props> = (props) => { ...@@ -16,18 +16,18 @@ export const ComponentTreePanel: React.FC<Props> = (props) => {
return ( return (
<div className={classNames(className, styles.nodeSourceTreeContainer)}> <div className={classNames(className, styles.nodeSourceTreeContainer)}>
<div className={styles.tabWrapper}> {/*<div className={styles.tabWrapper}>*/}
<div {/* <div*/}
className={classNames(styles.tab, { {/* className={classNames(styles.tab, {*/}
[styles.active]: activeTab === 'component', {/* [styles.active]: activeTab === 'component',*/}
})} {/* })}*/}
onClick={() => { {/* onClick={() => {*/}
setActiveTab('component') {/* setActiveTab('component')*/}
}} {/* }}*/}
> {/* >*/}
组件库 {/* 组件库*/}
</div> {/* </div>*/}
</div> {/*</div>*/}
<div className={styles.tabContentWrapper}> <div className={styles.tabContentWrapper}>
<ComponentSourceTree <ComponentSourceTree
className={classNames({ [styles.hide]: activeTab !== 'component' })} className={classNames({ [styles.hide]: activeTab !== 'component' })}
......
import React from 'react'
import CN from 'classnames'
import commonStyle from '@/common/style.less'
import styles from './style.less'
import { Button } from 'antd'
const Index = () => {
return (
<div className={CN(commonStyle.pos_end, styles.canvas_action)}>
<Button size="small">sss</Button>
<Button size="small">sssss</Button>
<Button size="small">sssss</Button>
<Button size="small">sssss</Button>
</div>
)
}
export default Index
.canvas_action{
padding-right: 10px;
}
@import (reference) '~antd/es/style/themes/default.less';
.bottomToolbar {
position: absolute;
right: 0;
bottom: 0;
left: 0;
z-index: 199;
height: 40px;
font-size: 12px;
background-color: #fff;
box-shadow: 0 0 16px -5px rgba(0, 0, 0, 0.2);
user-select: none;
.itemList {
color: rgba(0, 0, 0, 0.65);
text-align: center;
list-style-type: none;
.item {
display: inline-flex;
align-items: center;
height: 40px;
margin: 0 10px;
padding: 0;
line-height: 40px;
cursor: pointer;
a {
display: inline-flex;
align-items: center;
color: rgba(0, 0, 0, 0.65);
&:hover {
text-decoration: none;
}
&:focus {
text-decoration: none;
outline: none;
}
}
&.disabled {
color: #ccc;
cursor: default;
a {
color: #ccc;
cursor: default;
}
}
&:hover {
color: #1890ff;
a {
color: #1890ff;
}
}
:global {
& .anticon {
margin-right: 4px;
font-size: 16px;
}
}
}
}
}
.menu {
padding: 4px 0;
:global {
.@{ant-prefix}-menu-item {
min-width: 110px;
height: 32px;
margin: 0 !important;
padding: 0 12px;
font-size: 12px;
line-height: 32px;
a::before {
display: none;
}
&-selected {
color: rgba(0, 0, 0, 0.65);
background-color: #fff !important;
}
&:hover {
color: rgba(0, 0, 0, 0.65);
background-color: #f5f5f5;
}
:local {
.label {
display: flex;
align-items: center;
justify-content: space-between;
&:hover {
color: rgba(0, 0, 0, 0.65);
}
.icon {
margin: 0;
color: rgba(0, 0, 0, 0.65);
&:hover {
color: #1890ff;
}
}
}
}
}
}
}
.menuPopover {
:global {
.@{ant-prefix}-popover-inner {
background-color: transparent;
box-shadow: none;
&-content {
padding: 0 4px;
}
}
}
}
.popover {
:global {
.@{ant-prefix}-popover-inner-content {
padding: 5px 12px;
font-size: 12px;
}
}
}
import React, { useCallback, useEffect, useState } from 'react'
import { Popover } from 'antd'
import {
CloudUploadOutlined,
LogoutOutlined,
PlayCircleOutlined,
} from '@ant-design/icons'
import classNames from 'classnames'
import { useObservableState } from '@/common/hooks/useObservableState'
import { useExperimentGraph } from '@/pages/rx-models/experiment-graph'
import styles from './bottom-toolbar.less'
interface Props {
experimentId: string
}
export const BottomToolbar: React.FC<Props> = (props) => {
const { experimentId } = props
const expGraph = useExperimentGraph(experimentId)
const [running] = useObservableState(expGraph.running$)
const [preparingRun, setPreparingRun] = useState(false)
const [preparingStop, setPreparingStop] = useState(false)
// running 的值发生变化,说明运行或停止按钮的操作产生了作用
useEffect(() => {
setPreparingRun(false)
setPreparingStop(false)
}, [running])
// 运行实验
const onRunExperiment = useCallback(() => {
setPreparingRun(true)
expGraph.runGraph().then((res: any) => {
if (!res.success) {
setPreparingRun(false)
}
})
}, [expGraph])
// 停止运行
const onStopRunExperiment = useCallback(() => {
setPreparingStop(true)
expGraph.stopRunGraph().then((res: any) => {
if (!res.success) {
setPreparingStop(false)
}
})
}, [expGraph])
const runningConfigs = [
{
content: '运行',
tip: '依次运行本实验的每个组件',
icon: PlayCircleOutlined,
disabled: preparingRun,
clickHandler: onRunExperiment,
},
{
content: '停止',
tip: '停止运行实验',
icon: LogoutOutlined,
disabled: preparingStop,
clickHandler: onStopRunExperiment,
},
]
const runningConfig = runningConfigs[Number(!!running)]
const RunningIcon = runningConfig.icon
return (
<div className={styles.bottomToolbar}>
<ul className={styles.itemList}>
{/* 部署 */}
<li className={styles.item}>
<CloudUploadOutlined />
<span>部署</span>
</li>
{/* 运行/停止 */}
<Popover content={runningConfig.tip} overlayClassName={styles.popover}>
<li
className={classNames(styles.item, {
[styles.disabled]: runningConfig.disabled,
})}
onClick={runningConfig.clickHandler}
>
<RunningIcon />
<span>{runningConfig.content}</span>
</li>
</Popover>
</ul>
</div>
)
}
...@@ -31,6 +31,7 @@ export const CanvasContent: React.FC<Props> = (props) => { ...@@ -31,6 +31,7 @@ export const CanvasContent: React.FC<Props> = (props) => {
const [, dropRef] = useDrop({ const [, dropRef] = useDrop({
accept: [DRAGGABLE_ALGO_COMPONENT, DRAGGABLE_MODEL], accept: [DRAGGABLE_ALGO_COMPONENT, DRAGGABLE_MODEL],
drop: (item: any, monitor) => { drop: (item: any, monitor) => {
console.log('drop', item, monitor)
const currentMouseOffset = monitor.getClientOffset() const currentMouseOffset = monitor.getClientOffset()
const sourceMouseOffset = monitor.getInitialClientOffset() const sourceMouseOffset = monitor.getInitialClientOffset()
const sourceElementOffset = monitor.getInitialSourceClientOffset() const sourceElementOffset = monitor.getInitialSourceClientOffset()
...@@ -75,6 +76,8 @@ export const CanvasContent: React.FC<Props> = (props) => { ...@@ -75,6 +76,8 @@ export const CanvasContent: React.FC<Props> = (props) => {
[expGraph], [expGraph],
) )
console.log('expGraph', expGraph)
return ( return (
<div <div
ref={(elem) => { ref={(elem) => {
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
@import (reference) '../common/style/x6-overwrite'; @import (reference) '../common/style/x6-overwrite';
.canvasToolbar { .canvasToolbar {
display: flex;
justify-content: space-between;
background-color: #f7f9fb; background-color: #f7f9fb;
.x6-toolbar-overwrite(); .x6-toolbar-overwrite();
...@@ -66,4 +68,5 @@ ...@@ -66,4 +68,5 @@
} }
} }
} }
} }
...@@ -10,11 +10,12 @@ import { ...@@ -10,11 +10,12 @@ import {
import { useObservableState } from '@/common/hooks/useObservableState' import { useObservableState } from '@/common/hooks/useObservableState'
import { RxInput } from '@/component/rx-component/rx-input' import { RxInput } from '@/component/rx-component/rx-input'
import { showModal } from '@/component/modal' import { showModal } from '@/component/modal'
import { addNodeGroup } from '@/mock/graph' import { addNodeGroup } from '@/services/graph'
import { BehaviorSubject } from 'rxjs' import { BehaviorSubject } from 'rxjs'
import { useExperimentGraph } from '@/pages/rx-models/experiment-graph' import { useExperimentGraph } from '@/pages/rx-models/experiment-graph'
import { formatGroupInfoToNodeMeta } from '@/pages/rx-models/graph-util' import { formatGroupInfoToNodeMeta } from '@/pages/rx-models/graph-util'
import styles from './canvas-toolbar.less' import styles from './canvas-toolbar.less'
import CanvasAction from '@/pages/components/canvas-action'
const { Item, Group } = Toolbar const { Item, Group } = Toolbar
interface Props { interface Props {
...@@ -49,9 +50,9 @@ export const CanvasToolbar: React.FC<Props> = (props) => { ...@@ -49,9 +50,9 @@ export const CanvasToolbar: React.FC<Props> = (props) => {
expGraph.toggleSelectionEnabled() expGraph.toggleSelectionEnabled()
setSelectionEnabled((enabled) => !enabled) setSelectionEnabled((enabled) => !enabled)
break break
case Operations.RUN_SELECTED: // case Operations.RUN_SELECTED:
expGraph.runGraph() // expGraph.runGraph()
break // break
case Operations.NEW_GROUP: { case Operations.NEW_GROUP: {
const value$ = new BehaviorSubject('') const value$ = new BehaviorSubject('')
const modal = showModal({ const modal = showModal({
...@@ -154,15 +155,16 @@ export const CanvasToolbar: React.FC<Props> = (props) => { ...@@ -154,15 +155,16 @@ export const CanvasToolbar: React.FC<Props> = (props) => {
icon={<UngroupOutlined />} icon={<UngroupOutlined />}
/> />
</Group> </Group>
<Group> {/*<Group>*/}
<Item {/* <Item*/}
name={Operations.RUN_SELECTED} {/* name={Operations.RUN_SELECTED}*/}
disabled={!activeNodeInstance} {/* disabled={!activeNodeInstance}*/}
tooltip="执行选择节点" {/* tooltip="执行选择节点"*/}
icon={<PlaySquareOutlined />} {/* icon={<PlaySquareOutlined />}*/}
/> {/* />*/}
</Group> {/*</Group>*/}
</Toolbar> </Toolbar>
<CanvasAction/>
</div> </div>
) )
} }
...@@ -56,13 +56,13 @@ export const NodeContextMenu: React.FC<Props> = (props) => { ...@@ -56,13 +56,13 @@ export const NodeContextMenu: React.FC<Props> = (props) => {
<Menu hasIcon={true}> <Menu hasIcon={true}>
<Menu.Item onClick={onNodeCopy} icon={<CopyOutlined />} text="复制" /> <Menu.Item onClick={onNodeCopy} icon={<CopyOutlined />} text="复制" />
<Menu.Item onClick={onNodeDel} icon={<DeleteOutlined />} text="删除" /> <Menu.Item onClick={onNodeDel} icon={<DeleteOutlined />} text="删除" />
<Menu.Item disabled={true} icon={<EditOutlined />} text="重命名" /> {/*<Menu.Item disabled={true} icon={<EditOutlined />} text="重命名" />*/}
<Menu.Divider /> {/*<Menu.Divider />*/}
<Menu.Item {/*<Menu.Item*/}
onClick={onGraphRun} {/* onClick={onGraphRun}*/}
icon={<PlaySquareOutlined />} {/* icon={<PlaySquareOutlined />}*/}
text="执行" {/* text="执行"*/}
/> {/*/>*/}
</Menu> </Menu>
</div> </div>
) )
......
...@@ -6,7 +6,6 @@ import { ...@@ -6,7 +6,6 @@ import {
} from '@/pages/rx-models/experiment-graph' } from '@/pages/rx-models/experiment-graph'
import { CanvasContent } from './canvas-content' import { CanvasContent } from './canvas-content'
import { CanvasToolbar } from './canvas-toolbar' import { CanvasToolbar } from './canvas-toolbar'
import { BottomToolbar } from './bottom-toolbar'
import styles from './index.less' import styles from './index.less'
...@@ -32,12 +31,11 @@ export const DAGCanvas: React.FC<Props> = (props) => { ...@@ -32,12 +31,11 @@ export const DAGCanvas: React.FC<Props> = (props) => {
return ( return (
<div className={classNames(styles.dagContainer, className)}> <div className={classNames(styles.dagContainer, className)}>
{/*<CanvasToolbar experimentId={experimentId} />*/} <CanvasToolbar experimentId={experimentId} />
<CanvasContent <CanvasContent
experimentId={experimentId} experimentId={experimentId}
className={styles.canvasContent} className={styles.canvasContent}
/> />
{/*<BottomToolbar experimentId={experimentId} />*/}
</div> </div>
) )
} }
...@@ -28,8 +28,8 @@ import { ...@@ -28,8 +28,8 @@ import {
formatGraphData, formatGraphData,
formatNodeInfoToNodeMeta, formatNodeInfoToNodeMeta,
} from './graph-util' } from './graph-util'
import { queryGraph, addNode, copyNode } from '@/mock/graph' import { queryGraph, addNode, copyNode } from '@/services/graph'
import { queryGraphStatus, runGraph, stopGraphRun } from '@/mock/status' import { queryGraphStatus, runGraph, stopGraphRun } from '@/services/status'
export function parseStatus(data: NExecutionStatus.ExecutionStatus) { export function parseStatus(data: NExecutionStatus.ExecutionStatus) {
const { execInfo, instStatus } = data const { execInfo, instStatus } = data
...@@ -448,7 +448,7 @@ class ExperimentGraph extends GraphCore<BaseNode, BaseEdge> { ...@@ -448,7 +448,7 @@ class ExperimentGraph extends GraphCore<BaseNode, BaseEdge> {
onSelectNodes(nodes: BaseNode[]) { onSelectNodes(nodes: BaseNode[]) {
const selectedNodes: X6DemoNode[] = nodes.filter( const selectedNodes: X6DemoNode[] = nodes.filter(
(cell) => cell.isNode() && !cell.isGroup(), (cell) => cell.isNode() && !cell?.isGroup(),
) as X6DemoNode[] ) as X6DemoNode[]
const selectedGroups: X6DemoGroupNode[] = nodes.filter( const selectedGroups: X6DemoGroupNode[] = nodes.filter(
(cell) => cell.isNode() && cell.isGroup(), (cell) => cell.isNode() && cell.isGroup(),
...@@ -689,7 +689,8 @@ class ExperimentGraph extends GraphCore<BaseNode, BaseEdge> { ...@@ -689,7 +689,8 @@ class ExperimentGraph extends GraphCore<BaseNode, BaseEdge> {
const pos = graph.clientToLocal(clientX, clientY) const pos = graph.clientToLocal(clientX, clientY)
const nodeRes = await addNode({ ...nodeMeta, ...pos }) const nodeRes = await addNode({ ...nodeMeta, ...pos })
this.updateExperimentGraph([nodeRes]) this.updateExperimentGraph([nodeRes])
const newNode = formatNodeInfoToNodeMeta(nodeRes as any) const newNode = formatNodeInfoToNodeMeta(nodeRes as any);
console.log('newNode', newNode)
this.addNode(newNode) this.addNode(newNode)
return { success: true } return { success: true }
} }
......
...@@ -34,16 +34,15 @@ export namespace NExperimentGraph { ...@@ -34,16 +34,15 @@ export namespace NExperimentGraph {
export interface Node { export interface Node {
outPorts: OutPort[] outPorts: OutPort[]
inPorts: InPort[] inPorts: InPort[]
catId: number
positionX: number positionX: number
positionY: number positionY: number
codeName: string codeName?: string
category: string category?: string
name: string name: string
id: string id: string
nodeInstanceId?: number nodeInstanceId?: number
groupId: number groupId?: number
status: number status?: number
} }
export interface Port { export interface Port {
......
export const algoData = [
{
id: 10,
defSource: 2,
docUrl: '',
ioType: 0,
up: 148,
down: 11,
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_1',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
engineType: 0,
isComposite: false,
sequence: 0,
owner: 'system',
description: '组件描述信息',
name: '算法组件1',
parentId: 'recentlyUsed',
isBranch: false,
social: {
defSource: 2,
isEnabled: true,
docUrl: '#',
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_1',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
owner: 'system',
description: '组件描述信息',
name: '算法组件1',
id: 10,
},
},
{
id: 11,
defSource: 2,
docUrl: '',
ioType: 0,
up: 148,
down: 11,
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_2',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
engineType: 0,
isComposite: false,
sequence: 0,
owner: 'system',
description: '组件描述信息',
name: '算法组件2',
parentId: 'recentlyUsed',
isBranch: false,
social: {
defSource: 2,
isEnabled: true,
docUrl: '#',
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_2',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
owner: 'system',
description: '组件描述信息',
name: '算法组件2',
id: 11,
},
},
{
id: 12,
defSource: 2,
docUrl: '',
ioType: 0,
up: 148,
down: 11,
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_3',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
engineType: 0,
isComposite: false,
sequence: 0,
owner: 'system',
description: '组件描述信息',
name: '算法组件3',
parentId: 'recentlyUsed',
isBranch: false,
social: {
defSource: 2,
isEnabled: true,
docUrl: '#',
iconType: 1,
isDisabled: false,
author: 'demo author',
codeName: 'algo_3',
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
owner: 'system',
description: '组件描述信息',
name: '算法组件3',
id: 12,
},
},
]
export const searchByKeyword = async (keyword: string) => {
return Array(10)
.fill(null)
.map((i, idx) => {
return {
defSource: 2,
docUrl: '',
ioType: 0,
up: 148,
down: 11,
iconType: 1,
isDir: false,
isDisabled: false,
author: 'demo author',
codeName: `${keyword}${idx}`,
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
engineType: 0,
isComposite: false,
sequence: 0,
owner: 'system',
description: '组件描述信息',
name: `${keyword}__${idx}`,
id: idx,
parentId: 'recentlyUsed',
isBranch: false,
social: {
defSource: 2,
isEnabled: true,
docUrl: '#',
iconType: 1,
isDisabled: false,
author: 'demo author',
name: `${keyword}-${idx}`,
codeName: `${keyword}${idx}`,
catId: 1,
lastModifyTime: '2020-08-25 15:43:39',
createdTime: '2015-04-16 13:38:11',
owner: 'system',
description: '组件描述信息',
id: idx,
},
}
})
}
import random from 'lodash/random'
interface NodeParams {
name: string
x: number
y: number
}
export const copyNode = ({ name, x, y }: NodeParams) => {
const id = `${Date.now()}`
return {
id,
name,
inPorts: [
{
tableName: 'germany_credit_data',
sequence: 1,
description: '输入1',
id: id + 100000,
},
{
tableName: 'germany_credit_data',
sequence: 2,
description: '输入2',
id: id + 200000,
},
],
outPorts: [
{
tableName: 'germany_credit_data',
sequence: 1,
description: '输出表1',
id: id + 300000,
},
{
tableName: 'germany_credit_data',
sequence: 2,
description: '输出表2',
id: id + 400000,
},
],
positionX: x + 200 + random(20, false),
positionY: y + random(10, false),
codeName: 'source_11111',
catId: 1,
nodeDefId: 111111,
category: 'source',
status: 3,
groupId: 0,
}
}
export const addNode = ({ name, x, y }: NodeParams) => {
const id = `${Date.now()}`
return {
id,
name,
inPorts: [
{
sequence: 1,
description: '输入',
id: id + '_in_1',
}
],
outPorts: [
{
sequence: 1,
description: '输出',
id: id + '_out_1',
}
],
positionX: x,
positionY: y,
}
}
export const queryGraph = (id: string) => {
return {
lang: 'zh_CN',
success: true,
data: initData,
Lang: 'zh_CN',
}
}
export const addNodeGroup = async (groupName: string) => {
return {
success: true,
data: {
group: {
name: groupName,
id: Date.now(),
},
},
}
}
const initData = {
nodes: [],
links: [],
}
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
"baseUrl": "./", "baseUrl": "./",
"strict": true, "strict": true,
"paths": { "paths": {
"@/*": ["src/*"], "@/*": ["./src/*"],
"@@/*": ["src/.umi/*"] "@@/*": ["src/.umi/*"]
}, },
"allowSyntheticDefaultImports": true "allowSyntheticDefaultImports": true
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment