Skip to content

Commit 802eadd

Browse files
committed
feat(entities-plugins): datakit bottom-up auto layout
1 parent 70f1d34 commit 802eadd

File tree

6 files changed

+225
-162
lines changed

6 files changed

+225
-162
lines changed

packages/entities/entities-plugins/src/components/free-form/Datakit/flow-editor/FlowCanvas.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,13 @@
7474
</template>
7575

7676
<script setup lang="ts">
77-
import { AddIcon, AutoLayoutIcon, RemoveIcon, FullscreenIcon } from '@kong/icons'
77+
import { AddIcon, AutoLayoutIcon, FullscreenIcon, RemoveIcon } from '@kong/icons'
7878
import { KTooltip } from '@kong/kongponents'
7979
import { Background } from '@vue-flow/background'
8080
import { ControlButton, Controls } from '@vue-flow/controls'
8181
import { VueFlow } from '@vue-flow/core'
82-
import type { NodeMouseEvent } from '@vue-flow/core'
8382
import { useElementBounding, useEventListener, useTimeoutFn } from '@vueuse/core'
84-
import { computed, nextTick, ref, useTemplateRef } from 'vue'
83+
import { computed, ref, useTemplateRef } from 'vue'
8584
8685
import useI18n from '../../../../composables/useI18n'
8786
import { DK_DATA_TRANSFER_MIME_TYPE } from '../constants'
@@ -95,6 +94,7 @@ import '@vue-flow/controls/dist/style.css'
9594
import '@vue-flow/core/dist/style.css'
9695
import '@vue-flow/core/dist/theme-default.css'
9796
97+
import type { NodeMouseEvent } from '@vue-flow/core'
9898
import type { Component } from 'vue'
9999
100100
import type { DragPayload, NodePhase } from '../types'
@@ -203,9 +203,9 @@ function onDrop(e: DragEvent) {
203203
propertiesPanelOpen.value = true
204204
}
205205
206-
function onClickAutoLayout() {
207-
autoLayout()
208-
nextTick(() => fitView())
206+
async function onClickAutoLayout() {
207+
await autoLayout()
208+
setTimeout(() => fitView(), 0) // Have to use `setTimeout` here
209209
}
210210
211211
type ControlAction = 'zoom_in' | 'zoom_out' | 'fit_view' | 'auto_layout'

packages/entities/entities-plugins/src/components/free-form/Datakit/flow-editor/FlowPanels.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,18 +243,18 @@ watch(
243243
setPendingFitView(false)
244244
245245
// Wait for VueFlow internal layout measurements. nextTick does not work here.
246-
setTimeout(() => {
246+
setTimeout(async () => {
247247
if (pendingLayout) {
248-
requestFlow.value?.autoLayout(false)
249-
responseFlow.value?.autoLayout(false)
248+
await requestFlow.value?.autoLayout(false)
249+
await responseFlow.value?.autoLayout(false)
250250
commit('*')
251251
252252
if (pendingLayout === 'clearHistory')
253253
clear()
254254
}
255255
256256
if (pendingFitView) {
257-
fitView()
257+
setTimeout(() => fitView(), 0) // Have to use `setTimeout` here
258258
}
259259
}, 0)
260260
},

packages/entities/entities-plugins/src/components/free-form/Datakit/flow-editor/composables/useBranchLayout.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ export function useBranchLayout({ phase, readonly, flowId }: { phase: NodePhase,
179179
})
180180

181181
const pendingGroupLayouts = new Map<GroupId, GroupLayout>()
182-
const pendingParentUpdates = new Set<GroupId>()
182+
const pendingParentUpdates = new Map<GroupId, { commit: boolean }>()
183183
let layoutFlushPromise: Promise<void> | undefined
184184

185185
/**
@@ -200,7 +200,7 @@ export function useBranchLayout({ phase, readonly, flowId }: { phase: NodePhase,
200200
* - Any member node lacks valid dimensions
201201
* - The calculated bounds are invalid (infinite values)
202202
*/
203-
function calculateGroupLayout(group: GroupInstance): GroupLayout | undefined {
203+
function calculateGroupLayout(group: GroupInstance, commit = true): GroupLayout | undefined {
204204
if (group.phase !== phase) return undefined
205205

206206
const members = getGroupMembers(group).filter(member => member.phase === phase && !member.hidden)
@@ -260,6 +260,7 @@ export function useBranchLayout({ phase, readonly, flowId }: { phase: NodePhase,
260260
width: Math.round(paddedWidth),
261261
height: Math.round(paddedHeight),
262262
},
263+
commit,
263264
}
264265
}
265266

@@ -269,39 +270,39 @@ export function useBranchLayout({ phase, readonly, flowId }: { phase: NodePhase,
269270
return
270271
}
271272

272-
const applied: Array<{ id: GroupId, changed: boolean }> = []
273-
let hasChanges = false
273+
const applied: Array<{ id: GroupId, changed: boolean, commit: boolean }> = []
274+
let scheduleCommit = false
274275

275276
pendingGroupLayouts.forEach((layout, id) => {
276277
const changed = setGroupLayout(id, layout, false)
277-
applied.push({ id, changed })
278-
if (changed && !hasChanges) {
279-
hasChanges = true
278+
applied.push({ id, changed, commit: layout.commit })
279+
if (layout.commit && changed && !scheduleCommit) {
280+
scheduleCommit = true
280281
}
281282
})
282283

283284
pendingGroupLayouts.clear()
284285
layoutFlushPromise = undefined
285286

286-
for (const { id, changed } of applied) {
287+
for (const { id, changed, commit } of applied) {
287288
if (!changed) continue
288289
const group = groupMapById.value.get(id)
289290
if (!group) continue
290291
const parent = memberGroupMap.value.get(group.ownerId)
291292
if (parent) {
292-
pendingParentUpdates.add(parent.id)
293+
pendingParentUpdates.set(parent.id, { commit })
293294
}
294295
}
295296

296297
if (pendingParentUpdates.size > 0) {
297298
const parentIds = Array.from(pendingParentUpdates)
298299
pendingParentUpdates.clear()
299-
for (const parentId of parentIds) {
300-
updateGroupLayout(parentId)
300+
for (const [parentId, { commit }] of parentIds) {
301+
updateGroupLayout(parentId, commit)
301302
}
302303
}
303304

304-
if (hasChanges) {
305+
if (scheduleCommit) {
305306
commit('*')
306307
}
307308
}
@@ -323,11 +324,11 @@ export function useBranchLayout({ phase, readonly, flowId }: { phase: NodePhase,
323324
*
324325
* @param groupId - The ID of the group to update.
325326
*/
326-
function updateGroupLayout(groupId: GroupId) {
327+
function updateGroupLayout(groupId: GroupId, commit = true) {
327328
const group = groupMapById.value.get(groupId)
328329
if (!group) return
329330

330-
const layout = calculateGroupLayout(group)
331+
const layout = calculateGroupLayout(group, commit)
331332
if (!layout) return
332333

333334
pendingGroupLayouts.set(groupId, layout)
@@ -473,6 +474,7 @@ export function useBranchLayout({ phase, readonly, flowId }: { phase: NodePhase,
473474

474475
return {
475476
groupMapById,
477+
groupsByOwner,
476478
memberGroupMap,
477479
groupNodes,
478480
branchEdges,

packages/entities/entities-plugins/src/components/free-form/Datakit/flow-editor/node/node.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
ConfigNodeType,
1111
IOMeta,
1212
NextMeta,
13+
GroupInstance,
1314
} from '../../types'
1415

1516
import { createI18n } from '@kong-ui-public/i18n'
@@ -222,3 +223,6 @@ export const isNodeId = (id?: string): id is NodeId =>
222223

223224
export const isFieldId = (id?: string): id is FieldId =>
224225
!!id?.startsWith('field:')
226+
227+
export const isGroupInstance = (obj: NodeInstance | GroupInstance): obj is GroupInstance =>
228+
Object.prototype.hasOwnProperty.call(obj, 'ownerId')

0 commit comments

Comments
 (0)