Skip to content

Commit ef831a8

Browse files
committed
feat(flow): add shared flow edge,node,guide components & hook
1 parent 104fadd commit ef831a8

File tree

20 files changed

+1037
-0
lines changed

20 files changed

+1037
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<template>
2+
<div class="custom-height-resizer" @mousedown="handleMouseDown">
3+
<slot name="icon"></slot>
4+
</div>
5+
</template>
6+
7+
<script setup lang="ts">
8+
import { onUnmounted } from 'vue'
9+
10+
const props = withDefaults(
11+
defineProps<{
12+
modelValue: number
13+
min?: number
14+
max?: number
15+
/**
16+
* Whether the resizer is forward or not
17+
*/
18+
isForward?: boolean
19+
}>(),
20+
{
21+
min: 40,
22+
},
23+
)
24+
const emit = defineEmits<{
25+
(e: 'update:modelValue', value: number): void
26+
(e: 'resize', value: number): void
27+
}>()
28+
29+
let lastYPosition = 0
30+
31+
function setWidth(width: number) {
32+
emit('update:modelValue', width)
33+
}
34+
35+
const resize = (event: MouseEvent) => {
36+
const max = props.max || Number.MAX_SAFE_INTEGER
37+
const offset = Math.floor(event.pageY) - lastYPosition
38+
let targetHeight = props.modelValue + (props.isForward ? offset : -offset)
39+
if (targetHeight <= props.min) {
40+
targetHeight = props.min
41+
} else if (targetHeight >= max) {
42+
targetHeight = max
43+
}
44+
setWidth(targetHeight)
45+
lastYPosition = Math.floor(event.pageY)
46+
}
47+
48+
const handleMouseUp = () => {
49+
window.removeEventListener('mousemove', resize)
50+
window.removeEventListener('mouseup', handleMouseUp)
51+
emit('resize', props.modelValue)
52+
}
53+
54+
const handleMouseDown = (event: MouseEvent) => {
55+
lastYPosition = Math.floor(event.pageY)
56+
window.addEventListener('mousemove', resize)
57+
window.addEventListener('mouseup', handleMouseUp)
58+
event.preventDefault()
59+
}
60+
61+
onUnmounted(() => {
62+
window.removeEventListener('mousemove', resize)
63+
window.removeEventListener('mouseup', handleMouseUp)
64+
})
65+
</script>
66+
67+
<style lang="scss">
68+
.custom-height-resizer {
69+
display: flex;
70+
align-items: center;
71+
justify-content: center;
72+
width: 100%;
73+
height: 8px;
74+
z-index: 1;
75+
padding-left: 16px;
76+
padding-right: 16px;
77+
cursor: row-resize;
78+
}
79+
</style>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { FlowConnectionStatus } from '../types'
2+
import { useFlowLocale } from './useFlowLocale'
3+
4+
export default (): {
5+
statusOptList: Array<{ value: FlowConnectionStatus; label: string }>
6+
statusLabelMap: Partial<Record<FlowConnectionStatus, string>>
7+
getActionStatusLabel: (status?: FlowConnectionStatus) => string
8+
} => {
9+
const { t } = useFlowLocale()
10+
const statusLabelMap: Partial<Record<FlowConnectionStatus, string>> = {
11+
[FlowConnectionStatus.Connected]: t('flow.actionAvailable'),
12+
[FlowConnectionStatus.Disconnected]: t('flow.actionUnavailable'),
13+
[FlowConnectionStatus.Connecting]: t('flow.connecting'),
14+
[FlowConnectionStatus.Inconsistent]: t('flow.inconsistent'),
15+
}
16+
const statusOptList = (Object.entries(statusLabelMap) as [FlowConnectionStatus, string][]).map(
17+
([key, value]) => ({
18+
value: key,
19+
label: value,
20+
}),
21+
)
22+
const getActionStatusLabel = (status?: FlowConnectionStatus) => {
23+
return status ? statusLabelMap[status] || t('flow.disconnected') : ''
24+
}
25+
26+
return {
27+
statusLabelMap,
28+
statusOptList,
29+
getActionStatusLabel,
30+
}
31+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { Edge, Node } from '@vue-flow/core'
2+
import { createRandomString } from '@emqx/shared-ui-utils'
3+
import { NodeType } from '../types'
4+
import { useFlowLocale } from './useFlowLocale'
5+
6+
export const fallbackEdgeStyle = { stroke: '#bbb', strokeDasharray: '5 5' }
7+
8+
export default (): {
9+
allGuideFlowData: Array<Node | Edge>
10+
idFallback: string
11+
idFallbackEdge: string
12+
} => {
13+
const { t } = useFlowLocale()
14+
const idSource = createRandomString()
15+
const idProcessing = createRandomString()
16+
const idSink = createRandomString()
17+
const idFallback = createRandomString()
18+
const idFallbackEdge = createRandomString()
19+
const allGuideFlowData: Array<Node | Edge> = [
20+
{
21+
id: idSource,
22+
label: t('flow.guideSourceNodeLabel'),
23+
data: { type: NodeType.Source, desc: t('flow.guideSourceNodeDesc') },
24+
type: 'guide',
25+
position: { x: 90, y: 90 },
26+
},
27+
{
28+
id: idProcessing,
29+
label: t('flow.guideProcessingNodeLabel'),
30+
data: { type: NodeType.Processing, desc: t('flow.guideProcessingNodeDesc') },
31+
type: 'guide',
32+
position: { x: 290, y: 90 },
33+
},
34+
{
35+
id: idSink,
36+
label: t('flow.guideSinkNodeLabel'),
37+
data: { type: NodeType.Sink, desc: t('flow.guideSinkNodeDesc') },
38+
type: 'guide',
39+
position: { x: 490, y: 90 },
40+
},
41+
{
42+
id: idFallback,
43+
label: t('flow.guideFallbackNodeLabel'),
44+
data: { type: NodeType.Fallback, desc: t('flow.guideFallbackNodeDesc') },
45+
type: 'guide',
46+
position: { x: 690, y: 90 },
47+
},
48+
{
49+
id: createRandomString(),
50+
source: idSource,
51+
target: idProcessing,
52+
},
53+
{
54+
id: createRandomString(),
55+
source: idProcessing,
56+
target: idSink,
57+
},
58+
{
59+
id: idFallbackEdge,
60+
source: idSink,
61+
target: idFallback,
62+
style: fallbackEdgeStyle,
63+
},
64+
]
65+
66+
return {
67+
allGuideFlowData,
68+
idFallback,
69+
idFallbackEdge,
70+
}
71+
}

0 commit comments

Comments
 (0)