Browse Source

Merge "web: switch jobs list to a tree view"

tags/3.7.0
Zuul 2 months ago
parent
commit
52877b3b26
2 changed files with 75 additions and 45 deletions
  1. 70
    45
      web/src/containers/jobs/Jobs.jsx
  2. 5
    0
      web/src/index.css

+ 70
- 45
web/src/containers/jobs/Jobs.jsx View File

@@ -16,7 +16,7 @@ import * as React from 'react'
16 16
 import PropTypes from 'prop-types'
17 17
 import { connect } from 'react-redux'
18 18
 import { Link } from 'react-router-dom'
19
-import { Table } from 'patternfly-react'
19
+import { TreeView } from 'patternfly-react'
20 20
 
21 21
 
22 22
 class JobsList extends React.Component {
@@ -28,53 +28,78 @@ class JobsList extends React.Component {
28 28
   render () {
29 29
     const { jobs } = this.props
30 30
 
31
-    const headerFormat = value => <Table.Heading>{value}</Table.Heading>
32
-    const cellFormat = (value) => (
33
-      <Table.Cell>{value}</Table.Cell>)
34
-    const cellJobFormat = (value) => (
35
-      <Table.Cell>
36
-        <Link to={this.props.tenant.linkPrefix + '/job/' + value}>
37
-          {value}
38
-        </Link>
39
-      </Table.Cell>)
40
-    const cellBuildFormat = (value) => (
41
-      <Table.Cell>
42
-        <Link to={this.props.tenant.linkPrefix + '/builds?job_name=' + value}>
43
-          builds
44
-        </Link>
45
-      </Table.Cell>)
46
-    const columns = []
47
-    const myColumns = ['name', 'description', 'Last builds']
48
-    myColumns.forEach(column => {
49
-      let formatter = cellFormat
50
-      let prop = column
51
-      if (column === 'name') {
52
-        formatter = cellJobFormat
31
+    const linkPrefix = this.props.tenant.linkPrefix + '/job/'
32
+
33
+    // job index map
34
+    const jobMap = {}
35
+    // nodes contains the tree data
36
+    const nodes = []
37
+    // visited contains individual node
38
+    const visited = {}
39
+    // getNode returns the tree node and visit each parents
40
+    const getNode = function (job) {
41
+      if (!visited[job.name]) {
42
+        // Collect parents
43
+        let parents = []
44
+        if (job.variants) {
45
+          for (let jobVariant of job.variants) {
46
+            if (jobVariant.parent &&
47
+                parents.indexOf(jobVariant.parent) === -1) {
48
+              parents.push(jobVariant.parent)
49
+            }
50
+          }
51
+        }
52
+        visited[job.name] = {
53
+          text: (
54
+            <React.Fragment>
55
+              <Link to={linkPrefix + job.name}>{job.name}</Link>
56
+              {job.description && (
57
+                <span style={{marginLeft: '10px'}}>{job.description}</span>
58
+              )}
59
+            </React.Fragment>),
60
+          icon: 'fa fa-cube',
61
+          state: {
62
+            expanded: true,
63
+          },
64
+          parents: parents,
65
+        }
66
+        // Visit parent recursively
67
+        for (let parent of parents) {
68
+          getNode(jobMap[parent])
69
+        }
70
+      }
71
+      return visited[job.name]
72
+    }
73
+    // index job list
74
+    for (let job of jobs) {
75
+      jobMap[job.name] = job
76
+    }
77
+    // process job list
78
+    for (let job of jobs) {
79
+      const jobNode = getNode(job)
80
+      let attached = false
81
+      // add tree node to each parent and expand the parent
82
+      for (let parent of jobNode.parents) {
83
+        const parentNode = visited[parent]
84
+        if (!parentNode) {
85
+          console.log('Job ', job.name, ' parent ', parent, ' does not exist!')
86
+          continue
87
+        }
88
+        if (!parentNode.nodes) {
89
+          parentNode.nodes = []
90
+        }
91
+        parentNode.nodes.push(jobNode)
92
+        attached = true
53 93
       }
54
-      if (column === 'Last builds') {
55
-        prop = 'name'
56
-        formatter = cellBuildFormat
94
+      // else add node at the tree root
95
+      if (!attached || jobNode.parents.length === 0) {
96
+        nodes.push(jobNode)
57 97
       }
58
-      columns.push({
59
-        header: {label: column,
60
-          formatters: [headerFormat]},
61
-        property: prop,
62
-        cell: {formatters: [formatter]}
63
-      })
64
-    })
98
+    }
65 99
     return (
66
-      <Table.PfProvider
67
-        striped
68
-        bordered
69
-        hover
70
-        columns={columns}
71
-        >
72
-        <Table.Header/>
73
-        <Table.Body
74
-          rows={jobs}
75
-          rowKey="name"
76
-          />
77
-      </Table.PfProvider>
100
+      <div className='tree-view-container'>
101
+        <TreeView nodes={nodes} />
102
+      </div>
78 103
     )
79 104
   }
80 105
 }

+ 5
- 0
web/src/index.css View File

@@ -130,3 +130,8 @@ p.zuulstreamline {
130 130
     margin: 0px 0px;
131 131
     line-height: 1.4;
132 132
 }
133
+
134
+/* Job Tree View group gap */
135
+div.tree-view-container ul.list-group {
136
+  margin: 0px 0px;
137
+}

Loading…
Cancel
Save