Browse Source

Merge "web: add projects page"

tags/3.4.0
Zuul 5 months ago
parent
commit
afa918bfcd
5 changed files with 132 additions and 4 deletions
  1. 2
    2
      web/src/App.test.jsx
  2. 4
    0
      web/src/api.js
  3. 109
    0
      web/src/pages/Projects.jsx
  4. 11
    2
      web/src/pages/Tenants.jsx
  5. 6
    0
      web/src/routes.js

+ 2
- 2
web/src/App.test.jsx View File

@@ -59,7 +59,7 @@ it('renders multi tenant', () => {
59 59
     const topMenuLinks = ReactTestUtils.scryRenderedComponentsWithType(
60 60
       application, Link)
61 61
     expect(topMenuLinks[0].props.to).toEqual('/t/openstack/status')
62
-    expect(topMenuLinks[1].props.to).toEqual('/t/openstack/jobs')
62
+    expect(topMenuLinks[1].props.to).toEqual('/t/openstack/projects')
63 63
     // Location should be /tenants
64 64
     expect(location.pathname).toEqual('/tenants')
65 65
     // Info should tell multi tenants
@@ -91,7 +91,7 @@ it('renders single tenant', () => {
91 91
     const topMenuLinks = ReactTestUtils.scryRenderedComponentsWithType(
92 92
       application, Link)
93 93
     expect(topMenuLinks[0].props.to).toEqual('/status')
94
-    expect(topMenuLinks[1].props.to).toEqual('/jobs')
94
+    expect(topMenuLinks[1].props.to).toEqual('/projects')
95 95
     // Location should be /status
96 96
     expect(location.pathname).toEqual('/status')
97 97
     // Info should tell white label tenant openstack

+ 4
- 0
web/src/api.js View File

@@ -128,6 +128,9 @@ function fetchBuilds (apiPrefix, queryString) {
128 128
   }
129 129
   return Axios.get(apiUrl + apiPrefix + path)
130 130
 }
131
+function fetchProjects (apiPrefix) {
132
+  return Axios.get(apiUrl + apiPrefix + 'projects')
133
+}
131 134
 function fetchJob (apiPrefix, jobName) {
132 135
   return Axios.get(apiUrl + apiPrefix + 'job/' + jobName)
133 136
 }
@@ -143,6 +146,7 @@ export {
143 146
   fetchStatus,
144 147
   fetchBuild,
145 148
   fetchBuilds,
149
+  fetchProjects,
146 150
   fetchJob,
147 151
   fetchJobs,
148 152
   fetchTenants,

+ 109
- 0
web/src/pages/Projects.jsx View File

@@ -0,0 +1,109 @@
1
+// Copyright 2018 Red Hat, Inc
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//      http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+import * as React from 'react'
16
+import PropTypes from 'prop-types'
17
+import { connect } from 'react-redux'
18
+import { Link } from 'react-router-dom'
19
+import { Table } from 'patternfly-react'
20
+
21
+import { fetchProjects } from '../api'
22
+
23
+
24
+class ProjectsPage extends React.Component {
25
+  static propTypes = {
26
+    tenant: PropTypes.object
27
+  }
28
+
29
+  state = {
30
+    projects: null
31
+  }
32
+
33
+  updateData () {
34
+    fetchProjects(this.props.tenant.apiPrefix).then(response => {
35
+      this.setState({projects: response.data})
36
+    })
37
+  }
38
+
39
+  componentDidMount () {
40
+    document.title = 'Zuul Projects'
41
+    if (this.props.tenant.name) {
42
+      this.updateData()
43
+    }
44
+  }
45
+
46
+  componentDidUpdate (prevProps) {
47
+    if (this.props.tenant.name !== prevProps.tenant.name) {
48
+      this.updateData()
49
+    }
50
+  }
51
+
52
+  render () {
53
+    const { projects } = this.state
54
+    if (!projects) {
55
+      return (<p>Loading...</p>)
56
+    }
57
+
58
+    const headerFormat = value => <Table.Heading>{value}</Table.Heading>
59
+    const cellFormat = (value) => (
60
+      <Table.Cell>{value}</Table.Cell>)
61
+    const cellProjectFormat = (value) => (
62
+      <Table.Cell>
63
+        {value}
64
+      </Table.Cell>)
65
+    const cellBuildFormat = (value) => (
66
+      <Table.Cell>
67
+        <Link to={this.props.tenant.linkPrefix + '/builds?project=' + value}>
68
+          builds
69
+        </Link>
70
+      </Table.Cell>)
71
+    const columns = []
72
+    const myColumns = ['name', 'connection', 'type', 'last builds']
73
+    myColumns.forEach(column => {
74
+      let formatter = cellFormat
75
+      let prop = column
76
+      if (column === 'name') {
77
+        formatter = cellProjectFormat
78
+      }
79
+      if (column === 'connection') {
80
+        prop = 'connection_name'
81
+      }
82
+      if (column === 'last builds') {
83
+        prop = 'name'
84
+        formatter = cellBuildFormat
85
+      }
86
+      columns.push({
87
+        header: {label: column,
88
+          formatters: [headerFormat]},
89
+        property: prop,
90
+        cell: {formatters: [formatter]}
91
+      })
92
+    })
93
+    return (
94
+      <Table.PfProvider
95
+        striped
96
+        bordered
97
+        hover
98
+        columns={columns}
99
+      >
100
+        <Table.Header/>
101
+        <Table.Body
102
+          rows={projects}
103
+          rowKey="name"
104
+        />
105
+      </Table.PfProvider>)
106
+  }
107
+}
108
+
109
+export default connect(state => ({tenant: state.tenant}))(ProjectsPage)

+ 11
- 2
web/src/pages/Tenants.jsx View File

@@ -47,18 +47,27 @@ class TenantsPage extends Refreshable {
47 47
     const cellFormat = (value) => (
48 48
       <Table.Cell>{value}</Table.Cell>)
49 49
     const columns = []
50
-    const myColumns = ['name', 'status', 'jobs', 'builds', 'projects', 'queue']
50
+    const myColumns = [
51
+      'name', 'status', 'projects', 'jobs', 'builds', 'projects count', 'queue']
51 52
     myColumns.forEach(column => {
53
+      let prop = column
54
+      if (column === 'projects count') {
55
+        prop = 'projects'
56
+      } else if (column === 'projects') {
57
+        prop = 'projects_link'
58
+      }
52 59
       columns.push({
53 60
         header: {label: column,
54 61
           formatters: [headerFormat]},
55
-        property: column,
62
+        property: prop,
56 63
         cell: {formatters: [cellFormat]}
57 64
       })
58 65
     })
59 66
     tenants.forEach(tenant => {
60 67
       tenant.status = (
61 68
         <Link to={'/t/' + tenant.name + '/status'}>Status</Link>)
69
+      tenant.projects_link = (
70
+        <Link to={'/t/' + tenant.name + '/projects'}>Projects</Link>)
62 71
       tenant.jobs = (
63 72
         <Link to={'/t/' + tenant.name + '/jobs'}>Jobs</Link>)
64 73
       tenant.builds = (

+ 6
- 0
web/src/routes.js View File

@@ -14,6 +14,7 @@
14 14
 
15 15
 import StatusPage from './pages/Status'
16 16
 import ChangeStatusPage from './pages/ChangeStatus'
17
+import ProjectsPage from './pages/Projects'
17 18
 import JobPage from './pages/Job'
18 19
 import JobsPage from './pages/Jobs'
19 20
 import BuildPage from './pages/Build'
@@ -32,6 +33,11 @@ const routes = () => [
32 33
     to: '/status',
33 34
     component: StatusPage
34 35
   },
36
+  {
37
+    title: 'Projects',
38
+    to: '/projects',
39
+    component: ProjectsPage
40
+  },
35 41
   {
36 42
     title: 'Jobs',
37 43
     to: '/jobs',

Loading…
Cancel
Save