Skip to content

Commit c0f3143

Browse files
committed
Graph view: fix temporary layout error when cycle points enter n-window
1 parent 84e7a91 commit c0f3143

File tree

2 files changed

+28
-33
lines changed

2 files changed

+28
-33
lines changed

src/views/Graph.vue

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,19 @@ export function convertTree (map) {
350350
}))
351351
}
352352
353+
/**
354+
* Get the nodes binned by cycle point
355+
*
356+
* @param {Node[]} nodes - The graph nodes
357+
* @returns {{ [dateTime: string]: Object[] }=} mapping of cycle points to nodes
358+
*/
359+
export function getCyclesToNodes (nodes) {
360+
return nodes.reduce((x, y) => {
361+
(x[y.tokens.cycle] ||= []).push(y)
362+
return x
363+
}, {})
364+
}
365+
353366
export default {
354367
name: 'Graph',
355368
@@ -451,7 +464,6 @@ export default {
451464
// supports loading graph when component is mounted and autoRefresh is off.
452465
// true if page is loading for the first time and nodeDimensions are yet to be calculated
453466
initialLoad: true,
454-
cycleArrayStore: [],
455467
}
456468
},
457469
@@ -500,11 +512,11 @@ export default {
500512
return this.allParentLookUp.size ? this.getTree() : [{ name: 'No families', disabled: true }]
501513
},
502514
/**
503-
* Gets the array of cycles for use in vuetify toolbar drop down
504-
* @returns {String[]} array containing nested structure of families
515+
* Gets the array of cycles
516+
* @returns {string[]}
505517
*/
506-
treeDropDownCycle () {
507-
return this.cycleArrayStore.map((name) => ({ name }))
518+
cycles () {
519+
return this.workflows[0]?.children.map(({ tokens }) => tokens.cycle) || []
508520
},
509521
/**
510522
* Object for looking up family ancestors
@@ -671,7 +683,7 @@ export default {
671683
action: 'select-tree',
672684
value: this.collapseCycle,
673685
key: 'collapseCycle',
674-
items: this.treeDropDownCycle,
686+
items: this.cycles.map((name) => ({ name })),
675687
},
676688
{
677689
title: 'Collapse by family',
@@ -887,19 +899,6 @@ export default {
887899
return ret
888900
},
889901
890-
/**
891-
* Get the nodes binned by cycle point
892-
*
893-
* @param {Node[]} nodes - The graph nodes
894-
* @returns {{ [dateTime: string]: Object[] }=} mapping of cycle points to nodes
895-
*/
896-
getCycles (nodes) {
897-
return nodes.reduce((x, y) => {
898-
(x[y.tokens.cycle] ||= []).push(y)
899-
return x
900-
}, {})
901-
},
902-
903902
/**
904903
* Recursive function that adds a subgraph to the dot code
905904
*
@@ -989,7 +988,7 @@ export default {
989988
}
990989
},
991990
992-
getDotCode (nodeDimensions, nodes, edges, cycles) {
991+
getDotCode (nodeDimensions, nodes, edges, cyclesToNodes) {
993992
// return GraphViz dot code for the given nodes, edges and dimensions
994993
const ret = ['digraph {']
995994
let spacing = this.spacing
@@ -1034,8 +1033,7 @@ export default {
10341033
}
10351034
10361035
const graphSections = {}
1037-
for (const cycle of Object.keys(cycles)) {
1038-
const indexSearch = cycles[cycle]
1036+
for (const [cycle, indexSearch] of Object.entries(cyclesToNodes)) {
10391037
if (indexSearch.length && !this.collapseCycle.includes(cycle)) {
10401038
for (const task of indexSearch) {
10411039
const section = graphSections[task.node.firstParent.id] ??= []
@@ -1162,7 +1160,7 @@ export default {
11621160
11631161
// ----------------------------------------
11641162
for (const family of this.collapseFamily) {
1165-
for (const cycle of this.cycleArrayStore) {
1163+
for (const cycle of this.cycles) {
11661164
// ...get the node from the index...
11671165
const famNode = this.cylcTree.$index[
11681166
this.workflows[0].tokens.clone({ cycle, task: family }).id
@@ -1259,8 +1257,7 @@ export default {
12591257
return
12601258
}
12611259
1262-
const cycles = this.getCycles(nodes)
1263-
this.cycleArrayStore = this.workflows[0].children.map(child => child.tokens.cycle)
1260+
const cyclesToNodes = getCyclesToNodes(nodes)
12641261
// compute the graph ID
12651262
const graphID = this.hashGraph(nodes, edges)
12661263
if (this.graphID === graphID) {
@@ -1305,7 +1302,7 @@ export default {
13051302
13061303
// layout the graph
13071304
try {
1308-
await this.layout(nodes, edges, nodeDimensions, cycles)
1305+
await this.layout(nodes, edges, nodeDimensions, cyclesToNodes)
13091306
} catch (e) {
13101307
// something went wrong, allow the layout to retry later
13111308
this.graphID = null
@@ -1349,9 +1346,9 @@ export default {
13491346
* @param {Map<string, Edge>} edges
13501347
* @param {{ [id: string]: SVGRect }} nodeDimensions
13511348
*/
1352-
async layout (nodes, edges, nodeDimensions, cycles) {
1349+
async layout (nodes, edges, nodeDimensions, cyclesToNodes) {
13531350
// generate the GraphViz dot code
1354-
const dotCode = this.getDotCode(nodeDimensions, nodes, edges, cycles)
1351+
const dotCode = this.getDotCode(nodeDimensions, nodes, edges, cyclesToNodes)
13551352
13561353
// run the layout algorithm
13571354
const jsonString = (await this.graphviz).layout(dotCode, 'json')

tests/unit/views/graph.vue.spec.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { mount } from '@vue/test-utils'
1717
import { createStore } from 'vuex'
1818
import sinon from 'sinon'
1919
import storeOptions from '@/store/options'
20-
import Graph, { childArray } from '@/views/Graph.vue'
20+
import Graph, { childArray, getCyclesToNodes } from '@/views/Graph.vue'
2121
import User from '@/model/User.model'
2222
import WorkflowService from '@/services/workflow.service'
2323
import { Tokens } from '@/utils/uid'
@@ -60,10 +60,8 @@ describe('Graph view', () => {
6060
))
6161
}
6262

63-
it('gets cycles', async () => {
64-
const wrapper = mountFunction()
65-
66-
expect(wrapper.vm.getCycles(nodes)).toMatchObject(
63+
it('gets cycles-to-nodes mapping', () => {
64+
expect(getCyclesToNodes(nodes)).toMatchObject(
6765
{
6866
1: [
6967
{

0 commit comments

Comments
 (0)