smallstonesk
4 years ago
9 changed files with 246 additions and 23 deletions
@ -0,0 +1,96 @@ |
|||
import { Graph } from '@antv/x6'; |
|||
import merge from 'lodash.merge'; |
|||
import { parseQuery } from '../../utils'; |
|||
import { modifyGraph, ActionType, IModifyGraphAction } from '../../api'; |
|||
|
|||
const { projectId } = parseQuery(); |
|||
const memQueue: IModifyGraphAction[] = []; |
|||
|
|||
const validate = (type: string, data: any) => { |
|||
if (type === 'node') { |
|||
return true; |
|||
} else if (type === 'edge') { |
|||
const { source, target } = data; |
|||
return source.cell && target.cell; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
const enqueue = (type: string, actionType: ActionType, data: any) => { |
|||
|
|||
if (!validate(type, data)) { |
|||
return; |
|||
} |
|||
|
|||
const foundIndex = memQueue.findIndex(item => item.type === type && item.actionType === actionType); |
|||
if (foundIndex > -1) { |
|||
const deleted = memQueue.splice(foundIndex, 1)[0]; |
|||
data = merge(deleted, data); |
|||
} |
|||
memQueue.push({ type, actionType, data }); |
|||
}; |
|||
|
|||
let modifyActionTimer = -1; |
|||
const save = (flowChart: Graph, type: string, actionType: ActionType, data: any) => { |
|||
enqueue(type, actionType, data); |
|||
clearTimeout(modifyActionTimer); |
|||
modifyActionTimer = setTimeout(() => { |
|||
const pushedActions = memQueue.slice(0); |
|||
if(pushedActions.length > 0) { |
|||
flowChart.trigger('graph:change:modify'); |
|||
modifyGraph(projectId, memQueue).then(res => { |
|||
memQueue.splice(0, pushedActions.length); |
|||
flowChart.trigger('graph:modified', {success: true}); |
|||
}).catch(err => { |
|||
flowChart.trigger('graph:modified', {success: true, error: err}); |
|||
}); |
|||
} |
|||
}, 100); |
|||
}; |
|||
|
|||
type ActionEventMap = {[key: string]: string[]}; |
|||
const NODE_ACTION_EVENT_MAP: ActionEventMap = { |
|||
create: ['node:added'], |
|||
remove: ['node:removed'], |
|||
update: [ |
|||
'node:moved', |
|||
'node:resized', |
|||
'node:rotated', |
|||
'node:change:ports', |
|||
'node:change:attrs', |
|||
'node:change:data', |
|||
'node:change:zIndex' |
|||
] |
|||
}; |
|||
|
|||
const EDGE_ACTION_EVENT_MAP: ActionEventMap = { |
|||
create: ['edge:connected'], |
|||
remove: ['edge:removed'], |
|||
update: [ |
|||
'edge:moved', |
|||
] |
|||
}; |
|||
|
|||
export const registerServerStorage = (flowChart: Graph) => { |
|||
|
|||
Object.keys(NODE_ACTION_EVENT_MAP).forEach((actionType) => { |
|||
const events = NODE_ACTION_EVENT_MAP[actionType]; |
|||
events.forEach(event => { |
|||
flowChart.on(event, (args: any) => { |
|||
console.log('node event:', event, 'args:', args); |
|||
save(flowChart, 'node', actionType as ActionType, args.node.toJSON()); |
|||
}); |
|||
}); |
|||
}); |
|||
|
|||
Object.keys(EDGE_ACTION_EVENT_MAP).forEach((actionType) => { |
|||
const events = EDGE_ACTION_EVENT_MAP[actionType]; |
|||
events.forEach(event => { |
|||
flowChart.on(event, (args: any) => { |
|||
console.log('edge event:', event, 'args:', args); |
|||
save(flowChart, 'edge', actionType as ActionType, args.edge.toJSON()); |
|||
}); |
|||
}); |
|||
}); |
|||
}; |
@ -0,0 +1,69 @@ |
|||
import React, { useEffect, useState } from 'react'; |
|||
|
|||
import styles from './index.module.less'; |
|||
|
|||
import { Graph } from '@antv/x6'; |
|||
|
|||
enum Status { |
|||
pending = 0, |
|||
syncing = 1, |
|||
successful = 2, |
|||
failed = 3 |
|||
} |
|||
|
|||
interface IProps { |
|||
flowChart: Graph |
|||
} |
|||
|
|||
const STATUS_TEXT_MAP = { |
|||
[Status.pending]: '', |
|||
[Status.syncing]: { |
|||
color: '#999', |
|||
text: '正在保存...' |
|||
}, |
|||
[Status.successful]: { |
|||
color: '#999', |
|||
text: '所有更改已保存' |
|||
}, |
|||
[Status.failed]: { |
|||
color: '#EC5B56', |
|||
text: '同步失败,进入离线模式' |
|||
} |
|||
}; |
|||
|
|||
const ModifyStatus: React.FC<IProps> = (props) => { |
|||
|
|||
const {flowChart} = props; |
|||
const [status, setStatus] = useState<Status>(Status.pending); |
|||
|
|||
useEffect(() => { |
|||
flowChart.on('graph:change:modify', () => { |
|||
setStatus(Status.syncing); |
|||
}); |
|||
flowChart.on('graph:modified', (res: any) => { |
|||
const {success} = res; |
|||
if(success) { |
|||
setStatus(Status.successful); |
|||
} else { |
|||
setStatus(Status.failed); |
|||
} |
|||
}); |
|||
return () => { |
|||
flowChart.off('graph:change:modify'); |
|||
flowChart.off('graph:modified'); |
|||
}; |
|||
}, []); |
|||
|
|||
if(status === Status.pending) { |
|||
return null; |
|||
} else { |
|||
const {color, text} = STATUS_TEXT_MAP[status]; |
|||
return ( |
|||
<div className={styles.modifyStatusContainer}> |
|||
<span style={{color}}>{text}</span> |
|||
</div> |
|||
); |
|||
} |
|||
}; |
|||
|
|||
export default ModifyStatus; |
Loading…
Reference in new issue