| @@ -24,7 +24,7 @@ const HelpLink = ({ | |||
| <a | |||
| href={link} | |||
| target='_blank' | |||
| className='mr-1 flex h-6 w-6 items-center justify-center' | |||
| className='mr-1 flex h-6 w-6 items-center justify-center rounded-md hover:bg-state-base-hover' | |||
| > | |||
| <RiBookOpenLine className='h-4 w-4 text-gray-500' /> | |||
| </a> | |||
| @@ -0,0 +1,54 @@ | |||
| import { memo } from 'react' | |||
| import { useTranslation } from 'react-i18next' | |||
| import { RiCrosshairLine } from '@remixicon/react' | |||
| import type { XYPosition } from 'reactflow' | |||
| import { useReactFlow, useStoreApi } from 'reactflow' | |||
| import TooltipPlus from '@/app/components/base/tooltip' | |||
| import { useNodesSyncDraft } from '@/app/components/workflow-app/hooks' | |||
| type NodePositionProps = { | |||
| nodePosition: XYPosition, | |||
| nodeWidth?: number | null, | |||
| nodeHeight?: number | null, | |||
| } | |||
| const NodePosition = ({ | |||
| nodePosition, | |||
| nodeWidth, | |||
| nodeHeight, | |||
| }: NodePositionProps) => { | |||
| const { t } = useTranslation() | |||
| const reactflow = useReactFlow() | |||
| const store = useStoreApi() | |||
| const { doSyncWorkflowDraft } = useNodesSyncDraft() | |||
| if (!nodePosition || !nodeWidth || !nodeHeight) return null | |||
| const workflowContainer = document.getElementById('workflow-container') | |||
| const { transform } = store.getState() | |||
| const zoom = transform[2] | |||
| const { clientWidth, clientHeight } = workflowContainer! | |||
| const { setViewport } = reactflow | |||
| return ( | |||
| <TooltipPlus | |||
| popupContent={t('workflow.panel.moveToThisNode')} | |||
| > | |||
| <div | |||
| className='mr-1 flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-state-base-hover' | |||
| onClick={() => { | |||
| setViewport({ | |||
| x: (clientWidth - 400 - nodeWidth * zoom) / 2 - nodePosition.x * zoom, | |||
| y: (clientHeight - nodeHeight * zoom) / 2 - nodePosition.y * zoom, | |||
| zoom: transform[2], | |||
| }) | |||
| doSyncWorkflowDraft() | |||
| }} | |||
| > | |||
| <RiCrosshairLine className='h-4 w-4 text-text-tertiary' /> | |||
| </div> | |||
| </TooltipPlus> | |||
| ) | |||
| } | |||
| export default memo(NodePosition) | |||
| @@ -16,6 +16,7 @@ import { useTranslation } from 'react-i18next' | |||
| import NextStep from './components/next-step' | |||
| import PanelOperator from './components/panel-operator' | |||
| import HelpLink from './components/help-link' | |||
| import NodePosition from './components/node-position' | |||
| import { | |||
| DescriptionInput, | |||
| TitleInput, | |||
| @@ -55,6 +56,9 @@ const BasePanel: FC<BasePanelProps> = ({ | |||
| id, | |||
| data, | |||
| children, | |||
| position, | |||
| width, | |||
| height, | |||
| }) => { | |||
| const { t } = useTranslation() | |||
| const { showMessageLogModal } = useAppStore(useShallow(state => ({ | |||
| @@ -150,6 +154,7 @@ const BasePanel: FC<BasePanelProps> = ({ | |||
| </Tooltip> | |||
| ) | |||
| } | |||
| <NodePosition nodePosition={position} nodeWidth={width} nodeHeight={height}></NodePosition> | |||
| <HelpLink nodeType={data.type} /> | |||
| <PanelOperator id={id} data={data} showHelpLink={false} /> | |||
| <div className='mx-3 h-3.5 w-[1px] bg-divider-regular' /> | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'Blöcke organisieren', | |||
| change: 'Ändern', | |||
| optional: '(optional)', | |||
| moveToThisNode: 'Bewege zu diesem Knoten', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -300,6 +300,7 @@ const translation = { | |||
| addNextStep: 'Add the next block in this workflow', | |||
| selectNextStep: 'Select Next Block', | |||
| runThisStep: 'Run this step', | |||
| moveToThisNode: 'Move to this node', | |||
| checklist: 'Checklist', | |||
| checklistTip: 'Make sure all issues are resolved before publishing', | |||
| checklistResolved: 'All issues are resolved', | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'Organizar bloques', | |||
| change: 'Cambiar', | |||
| optional: '(opcional)', | |||
| moveToThisNode: 'Mueve a este nodo', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'سازماندهی بلوکها', | |||
| change: 'تغییر', | |||
| optional: '(اختیاری)', | |||
| moveToThisNode: 'به این گره بروید', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'Organiser les blocs', | |||
| change: 'Modifier', | |||
| optional: '(facultatif)', | |||
| moveToThisNode: 'Déplacer vers ce nœud', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -314,6 +314,7 @@ const translation = { | |||
| organizeBlocks: 'ब्लॉक्स को व्यवस्थित करें', | |||
| change: 'बदलें', | |||
| optional: '(वैकल्पिक)', | |||
| moveToThisNode: 'इस नोड पर जाएं', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -317,6 +317,7 @@ const translation = { | |||
| organizeBlocks: 'Organizza blocchi', | |||
| change: 'Cambia', | |||
| optional: '(opzionale)', | |||
| moveToThisNode: 'Sposta a questo nodo', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -307,6 +307,7 @@ const translation = { | |||
| organizeBlocks: 'ノード整理', | |||
| change: '変更', | |||
| optional: '(任意)', | |||
| moveToThisNode: 'このノードに移動する', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: '블록 정리', | |||
| change: '변경', | |||
| optional: '(선택사항)', | |||
| moveToThisNode: '이 노드로 이동', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'Organizuj bloki', | |||
| change: 'Zmień', | |||
| optional: '(opcjonalne)', | |||
| moveToThisNode: 'Przenieś do tego węzła', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'Organizar blocos', | |||
| change: 'Mudar', | |||
| optional: '(opcional)', | |||
| moveToThisNode: 'Mova-se para este nó', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'Organizează blocurile', | |||
| change: 'Schimbă', | |||
| optional: '(opțional)', | |||
| moveToThisNode: 'Mutați la acest nod', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'Организовать блоки', | |||
| change: 'Изменить', | |||
| optional: '(необязательно)', | |||
| moveToThisNode: 'Перейдите к этому узлу', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -739,6 +739,7 @@ const translation = { | |||
| checklistResolved: 'Vse težave so odpravljene', | |||
| addNextStep: 'Dodajanje naslednjega bloka v ta potek dela', | |||
| change: 'Spremeniti', | |||
| moveToThisNode: 'Premakni se na to vozlišče', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'จัดระเบียบบล็อก', | |||
| change: 'เปลี่ยน', | |||
| optional: '(ไม่บังคับ)', | |||
| moveToThisNode: 'ย้ายไปที่โหนดนี้', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'Blokları Düzenle', | |||
| change: 'Değiştir', | |||
| optional: '(isteğe bağlı)', | |||
| moveToThisNode: 'Bu düğüme geç', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'Організувати блоки', | |||
| change: 'Змінити', | |||
| optional: '(необов\'язково)', | |||
| moveToThisNode: 'Перемістіть до цього вузла', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: 'Tổ chức các khối', | |||
| change: 'Thay đổi', | |||
| optional: '(tùy chọn)', | |||
| moveToThisNode: 'Di chuyển đến nút này', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -307,6 +307,7 @@ const translation = { | |||
| organizeBlocks: '整理节点', | |||
| change: '更改', | |||
| optional: '(选填)', | |||
| moveToThisNode: '定位至此节点', | |||
| }, | |||
| nodes: { | |||
| common: { | |||
| @@ -302,6 +302,7 @@ const translation = { | |||
| organizeBlocks: '整理節點', | |||
| change: '更改', | |||
| optional: '(選擇性)', | |||
| moveToThisNode: '定位至此節點', | |||
| }, | |||
| nodes: { | |||
| common: { | |||