mirror of
https://github.com/OpenBMB/ChatDev.git
synced 2026-04-25 11:18:06 +00:00
feat: wrapping nodes with tooltip content
This commit is contained in:
parent
b3b7376ef2
commit
53870bd6f0
@ -1,6 +1,8 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { Handle, Position } from '@vue-flow/core'
|
||||
import RichTooltip from './RichTooltip.vue'
|
||||
import { helpContent } from '../utils/helpContent.js'
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
@ -15,11 +17,13 @@ const props = defineProps({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="start-node" :style="{ opacity: data.opacity ?? 1 }">
|
||||
<div class="start-node-bubble" title="Start Node"></div>
|
||||
<!-- Provide source handle at right -->
|
||||
<Handle id="source" type="source" :position="Position.Right" class="start-node-handle" />
|
||||
</div>
|
||||
<RichTooltip :content="helpContent.startNode" placement="right">
|
||||
<div class="start-node" :style="{ opacity: data.opacity ?? 1 }">
|
||||
<div class="start-node-bubble" title="Start Node"></div>
|
||||
<!-- Provide source handle at right -->
|
||||
<Handle id="source" type="source" :position="Position.Right" class="start-node-handle" />
|
||||
</div>
|
||||
</RichTooltip>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
import { computed, ref, nextTick, watch } from 'vue'
|
||||
import { BaseEdge, EdgeLabelRenderer, getBezierPath, getSmoothStepPath, MarkerType } from '@vue-flow/core'
|
||||
import { useVueFlow } from '@vue-flow/core'
|
||||
import RichTooltip from './RichTooltip.vue'
|
||||
import { getEdgeHelp } from '../utils/helpContent.js'
|
||||
|
||||
const { findNode } = useVueFlow()
|
||||
|
||||
@ -562,6 +564,8 @@ const labelStyle = computed(() => {
|
||||
|
||||
return s
|
||||
})
|
||||
|
||||
const edgeHelpContent = computed(() => getEdgeHelp(props.data))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -614,6 +618,23 @@ const labelStyle = computed(() => {
|
||||
:animated="false"
|
||||
class="nodrag nopan"
|
||||
/>
|
||||
<!-- Tooltip-enabled hover area at edge midpoint -->
|
||||
<EdgeLabelRenderer>
|
||||
<RichTooltip :content="edgeHelpContent" placement="top">
|
||||
<div
|
||||
:style="{
|
||||
position: 'absolute',
|
||||
transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
|
||||
pointerEvents: 'all',
|
||||
width: '20px',
|
||||
height: '20px',
|
||||
borderRadius: '50%',
|
||||
cursor: 'pointer'
|
||||
}"
|
||||
class="edge-tooltip-trigger"
|
||||
/>
|
||||
</RichTooltip>
|
||||
</EdgeLabelRenderer>
|
||||
<EdgeLabelRenderer v-if="edgeLabel">
|
||||
<div
|
||||
:key="edgeLabelKey"
|
||||
@ -649,4 +670,13 @@ const labelStyle = computed(() => {
|
||||
.animated-label {
|
||||
animation: label-pulse var(--label-anim-duration) infinite linear;
|
||||
}
|
||||
|
||||
.edge-tooltip-trigger {
|
||||
background: transparent;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.edge-tooltip-trigger:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -3,6 +3,8 @@ import { computed, ref, onMounted, onUnmounted, watch } from 'vue'
|
||||
import { Handle, Position } from '@vue-flow/core'
|
||||
import { getNodeStyles } from '../utils/colorUtils.js'
|
||||
import { spriteFetcher } from '../utils/spriteFetcher.js'
|
||||
import RichTooltip from './RichTooltip.vue'
|
||||
import { getNodeHelp } from '../utils/helpContent.js'
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
@ -37,6 +39,8 @@ const nodeDescription = computed(() => props.data?.description || '')
|
||||
const isActive = computed(() => props.isActive)
|
||||
const dynamicStyles = computed(() => getNodeStyles(nodeType.value))
|
||||
|
||||
const nodeHelpContent = computed(() => getNodeHelp(nodeType.value))
|
||||
|
||||
// Compute the current sprite path based on active state and walking frame
|
||||
const currentSprite = computed(() => {
|
||||
if (!props.sprite) return ''
|
||||
@ -83,40 +87,42 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="workflow-node-container">
|
||||
<div v-if="props.sprite" class="workflow-node-sprite">
|
||||
<img :src="currentSprite" :alt="`${nodeId} sprite`" class="node-sprite-image" />
|
||||
</div>
|
||||
<div
|
||||
class="workflow-node"
|
||||
:class="{ 'workflow-node-active': isActive }"
|
||||
:data-type="nodeType"
|
||||
:style="dynamicStyles"
|
||||
@mouseenter="$emit('hover', nodeId)"
|
||||
@mouseleave="$emit('leave', nodeId)"
|
||||
>
|
||||
<div class="workflow-node-header">
|
||||
<span class="workflow-node-type">{{ nodeType }}</span>
|
||||
<span class="workflow-node-id">{{ nodeId }}</span>
|
||||
</div>
|
||||
<div v-if="nodeDescription" class="workflow-node-description">
|
||||
{{ nodeDescription }}
|
||||
<RichTooltip :content="nodeHelpContent" placement="top">
|
||||
<div class="workflow-node-container">
|
||||
<div v-if="props.sprite" class="workflow-node-sprite">
|
||||
<img :src="currentSprite" :alt="`${nodeId} sprite`" class="node-sprite-image" />
|
||||
</div>
|
||||
<div
|
||||
class="workflow-node"
|
||||
:class="{ 'workflow-node-active': isActive }"
|
||||
:data-type="nodeType"
|
||||
:style="dynamicStyles"
|
||||
@mouseenter="$emit('hover', nodeId)"
|
||||
@mouseleave="$emit('leave', nodeId)"
|
||||
>
|
||||
<div class="workflow-node-header">
|
||||
<span class="workflow-node-type">{{ nodeType }}</span>
|
||||
<span class="workflow-node-id">{{ nodeId }}</span>
|
||||
</div>
|
||||
<div v-if="nodeDescription" class="workflow-node-description">
|
||||
{{ nodeDescription }}
|
||||
</div>
|
||||
|
||||
<Handle
|
||||
id="source"
|
||||
type="source"
|
||||
:position="Position.Right"
|
||||
class="workflow-node-handle"
|
||||
/>
|
||||
<Handle
|
||||
id="target"
|
||||
type="target"
|
||||
:position="Position.Left"
|
||||
class="workflow-node-handle"
|
||||
/>
|
||||
<Handle
|
||||
id="source"
|
||||
type="source"
|
||||
:position="Position.Right"
|
||||
class="workflow-node-handle"
|
||||
/>
|
||||
<Handle
|
||||
id="target"
|
||||
type="target"
|
||||
:position="Position.Left"
|
||||
class="workflow-node-handle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</RichTooltip>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@ -87,38 +87,46 @@
|
||||
>
|
||||
<!-- Pane context menu -->
|
||||
<template v-if="contextMenuType === 'pane'">
|
||||
<div
|
||||
class="context-menu-item"
|
||||
@click.stop="() => { hideContextMenu(); openCreateNodeModal(); }"
|
||||
>
|
||||
Create Node
|
||||
</div>
|
||||
<RichTooltip :content="helpContent.contextMenu.createNode" placement="right">
|
||||
<div
|
||||
class="context-menu-item"
|
||||
@click.stop="() => { hideContextMenu(); openCreateNodeModal(); }"
|
||||
>
|
||||
Create Node
|
||||
</div>
|
||||
</RichTooltip>
|
||||
</template>
|
||||
|
||||
<!-- Node context menu -->
|
||||
<template v-else-if="contextMenuType === 'node'">
|
||||
<div
|
||||
class="context-menu-item"
|
||||
@click.stop="() => { hideContextMenu(); onCopyNodeFromContext(); }"
|
||||
>
|
||||
Copy Node
|
||||
</div>
|
||||
<div
|
||||
class="context-menu-item"
|
||||
@click.stop="() => { hideContextMenu(); onDeleteNodeFromContext(); }"
|
||||
>
|
||||
Delete Node
|
||||
</div>
|
||||
<RichTooltip :content="helpContent.contextMenu.copyNode" placement="right">
|
||||
<div
|
||||
class="context-menu-item"
|
||||
@click.stop="() => { hideContextMenu(); onCopyNodeFromContext(); }"
|
||||
>
|
||||
Copy Node
|
||||
</div>
|
||||
</RichTooltip>
|
||||
<RichTooltip :content="helpContent.contextMenu.deleteNode" placement="right">
|
||||
<div
|
||||
class="context-menu-item"
|
||||
@click.stop="() => { hideContextMenu(); onDeleteNodeFromContext(); }"
|
||||
>
|
||||
Delete Node
|
||||
</div>
|
||||
</RichTooltip>
|
||||
</template>
|
||||
|
||||
<!-- Edge context menu -->
|
||||
<template v-else-if="contextMenuType === 'edge'">
|
||||
<div
|
||||
class="context-menu-item"
|
||||
@click.stop="() => { hideContextMenu(); onDeleteEdgeFromContext(); }"
|
||||
>
|
||||
Delete Edge
|
||||
</div>
|
||||
<RichTooltip :content="helpContent.contextMenu.deleteEdge" placement="right">
|
||||
<div
|
||||
class="context-menu-item"
|
||||
@click.stop="() => { hideContextMenu(); onDeleteEdgeFromContext(); }"
|
||||
>
|
||||
Delete Edge
|
||||
</div>
|
||||
</RichTooltip>
|
||||
</template>
|
||||
</div>
|
||||
</transition>
|
||||
@ -141,15 +149,21 @@
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="activeTab === 'graph'" class="editor-actions">
|
||||
<button @click="openCreateNodeModal" class="glass-button">
|
||||
<span>Create Node</span>
|
||||
</button>
|
||||
<button @click="openConfigureGraphModal" class="glass-button">
|
||||
<span>Configure Graph</span>
|
||||
</button>
|
||||
<button @click="goToLaunch" class="launch-button-primary">
|
||||
<span>Launch</span>
|
||||
</button>
|
||||
<RichTooltip :content="helpContent.contextMenu.createNodeButton" placement="bottom">
|
||||
<button @click="openCreateNodeModal" class="glass-button">
|
||||
<span>Create Node</span>
|
||||
</button>
|
||||
</RichTooltip>
|
||||
<RichTooltip :content="helpContent.contextMenu.configureGraph" placement="bottom">
|
||||
<button @click="openConfigureGraphModal" class="glass-button">
|
||||
<span>Configure Graph</span>
|
||||
</button>
|
||||
</RichTooltip>
|
||||
<RichTooltip :content="helpContent.contextMenu.launch" placement="bottom">
|
||||
<button @click="goToLaunch" class="launch-button-primary">
|
||||
<span>Launch</span>
|
||||
</button>
|
||||
</RichTooltip>
|
||||
|
||||
<div
|
||||
class="menu-container"
|
||||
@ -166,11 +180,21 @@
|
||||
</div>
|
||||
<transition name="fade">
|
||||
<div v-if="showMenu" class="menu-dropdown">
|
||||
<div @click="openRenameWorkflowModal" class="menu-item">Rename Workflow</div>
|
||||
<div @click="openCopyWorkflowModal" class="menu-item">Copy Workflow</div>
|
||||
<div @click="openManageVarsModal" class="menu-item">Manage Variables</div>
|
||||
<div @click="openManageMemoriesModal" class="menu-item">Manage Memories</div>
|
||||
<div @click="openCreateEdgeModal" class="menu-item">Create Edge</div>
|
||||
<RichTooltip :content="helpContent.contextMenu.renameWorkflow" placement="left">
|
||||
<div @click="openRenameWorkflowModal" class="menu-item">Rename Workflow</div>
|
||||
</RichTooltip>
|
||||
<RichTooltip :content="helpContent.contextMenu.copyWorkflow" placement="left">
|
||||
<div @click="openCopyWorkflowModal" class="menu-item">Copy Workflow</div>
|
||||
</RichTooltip>
|
||||
<RichTooltip :content="helpContent.contextMenu.manageVariables" placement="left">
|
||||
<div @click="openManageVarsModal" class="menu-item">Manage Variables</div>
|
||||
</RichTooltip>
|
||||
<RichTooltip :content="helpContent.contextMenu.manageMemories" placement="left">
|
||||
<div @click="openManageMemoriesModal" class="menu-item">Manage Memories</div>
|
||||
</RichTooltip>
|
||||
<RichTooltip :content="helpContent.contextMenu.createEdge" placement="left">
|
||||
<div @click="openCreateEdgeModal" class="menu-item">Create Edge</div>
|
||||
</RichTooltip>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
@ -270,8 +294,10 @@ import WorkflowNode from '../components/WorkflowNode.vue'
|
||||
import WorkflowEdge from '../components/WorkflowEdge.vue'
|
||||
import StartNode from '../components/StartNode.vue'
|
||||
import FormGenerator from '../components/FormGenerator.vue'
|
||||
import RichTooltip from '../components/RichTooltip.vue'
|
||||
import yaml from 'js-yaml'
|
||||
import { fetchYaml, fetchVueGraph, postVuegraphs, updateYaml, postYamlNameChange, postYamlCopy } from '../utils/apiFunctions'
|
||||
import { helpContent } from '../utils/helpContent.js'
|
||||
|
||||
const props = defineProps({
|
||||
workflowName: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user