Skip to content

Commit 3f74a30

Browse files
authored
Merge pull request #329 from developmentseed/render-org-teams
Stub org teams list
2 parents e8cf103 + f600b8b commit 3f74a30

File tree

4 files changed

+132
-1
lines changed

4 files changed

+132
-1
lines changed

cypress.config.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
const { defineConfig } = require('cypress')
22
const db = require('./src/lib/db')
33
const Team = require('./src/models/team')
4+
const Organization = require('./src/models/organization')
45
const TeamInvitation = require('./src/models/team-invitation')
6+
const { pick } = require('ramda')
57

68
const user1 = {
79
id: 1,
@@ -15,6 +17,7 @@ module.exports = defineConfig({
1517
on('task', {
1618
'db:reset': async () => {
1719
await db.raw('TRUNCATE TABLE team RESTART IDENTITY CASCADE')
20+
await db.raw('TRUNCATE TABLE organization RESTART IDENTITY CASCADE')
1821
return null
1922
},
2023
'db:seed': async () => {
@@ -42,6 +45,20 @@ module.exports = defineConfig({
4245
'db:seed:team-invitations': async (teamInvitations) => {
4346
return Promise.all(teamInvitations.map(TeamInvitation.create))
4447
},
48+
'db:seed:organizations': async (orgs) => {
49+
return Promise.all(
50+
orgs.map((org) =>
51+
Organization.create(pick(['name'], org), org.ownerId)
52+
)
53+
)
54+
},
55+
'db:seed:organization-teams': async ({ orgId, teams, managerId }) => {
56+
return Promise.all(
57+
teams.map((team) =>
58+
Organization.createOrgTeam(orgId, pick(['name'], team), managerId)
59+
)
60+
)
61+
},
4562
})
4663
},
4764
},

cypress/e2e/organizations.cy.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const user1 = {
2+
id: 1,
3+
display_name: 'User 1',
4+
}
5+
6+
const org1 = {
7+
id: 1,
8+
name: 'My org',
9+
ownerId: user1.id,
10+
}
11+
12+
const team1 = {
13+
name: 'Team 1',
14+
}
15+
16+
describe('Organization page', () => {
17+
before(() => {
18+
cy.task('db:reset')
19+
cy.task('db:seed:organizations', [org1])
20+
})
21+
22+
it('List organization teams', () => {
23+
cy.login(user1)
24+
25+
// Check state when no teams are available
26+
cy.visit('/organizations/1')
27+
cy.get('body').should('contain', 'This organization has no teams.')
28+
29+
// Seed org teams
30+
cy.task('db:seed:organization-teams', {
31+
orgId: org1.id,
32+
teams: [team1],
33+
managerId: user1.id,
34+
})
35+
36+
// Check state when teams are available
37+
cy.visit('/organizations/1')
38+
cy.get('body').should('contain', team1.name)
39+
})
40+
})

src/lib/org-api.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,28 @@ export async function getOrg(id) {
5656
}
5757
}
5858

59+
/**
60+
* getOrgTeams
61+
* Get list of teams from the API
62+
*
63+
* @param {integer} id
64+
* @returns {response}
65+
*/
66+
export async function getOrgTeams(id) {
67+
let res = await fetch(join(ORG_URL, `${id}`, 'teams'))
68+
69+
if (res.status === 200) {
70+
return res.json()
71+
}
72+
if (res.status === 401) {
73+
return { teams: [] }
74+
} else {
75+
const err = new Error('could not retrieve organization teams')
76+
err.status = res.status
77+
throw err
78+
}
79+
}
80+
5981
/**
6082
* getOrgStaff
6183
* get org staff

src/pages/organizations/[id]/index.js

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Router, { withRouter } from 'next/router'
33
import {
44
getOrg,
55
getOrgStaff,
6+
getOrgTeams,
67
getMembers,
78
addManager,
89
removeManager,
@@ -58,6 +59,7 @@ class Organization extends Component {
5859
this.state = {
5960
profileInfo: [],
6061
profileUserId: '',
62+
teams: [],
6163
members: [],
6264
managers: [],
6365
owners: [],
@@ -74,6 +76,7 @@ class Organization extends Component {
7476
async componentDidMount() {
7577
this.setState({ session: await getSession() })
7678
await this.getOrg()
79+
await this.getOrgTeams()
7780
await this.getOrgStaff()
7881
await this.getBadges()
7982
return this.getMembers(0)
@@ -177,6 +180,22 @@ class Organization extends Component {
177180
})
178181
}
179182
}
183+
async getOrgTeams() {
184+
const { id } = this.props
185+
try {
186+
const teams = await getOrgTeams(id)
187+
this.setState({
188+
teams,
189+
})
190+
} catch (e) {
191+
console.error(e)
192+
this.setState({
193+
error: e,
194+
teams: [],
195+
loading: false,
196+
})
197+
}
198+
}
180199

181200
renderStaff(owners, managers) {
182201
const columns = [{ key: 'name' }, { key: 'id' }, { key: 'role' }]
@@ -201,6 +220,32 @@ class Organization extends Component {
201220
)
202221
}
203222

223+
renderOrgTeams(teams) {
224+
const columns = [{ key: 'name' }, { key: 'id' }, { key: 'members' }]
225+
const teamRows = teams.map(({ name, id, members }) => {
226+
return {
227+
name,
228+
id,
229+
members: members.length,
230+
}
231+
})
232+
233+
return (
234+
<Table
235+
rows={teamRows}
236+
columns={columns}
237+
emptyPlaceHolder={
238+
this.state.loading ? 'Loading...' : 'This organization has no teams.'
239+
}
240+
onRowClick={(row) => {
241+
Router.push(
242+
join(URL, `/team?id=${row.id}`),
243+
join(URL, `/teams/${row.id}`)
244+
)
245+
}}
246+
/>
247+
)
248+
}
204249
async getBadges() {
205250
try {
206251
const { id: orgId } = this.props
@@ -277,7 +322,7 @@ class Organization extends Component {
277322
}
278323

279324
render() {
280-
const { org, members, managers, owners, error } = this.state
325+
const { org, members, managers, owners, error, teams } = this.state
281326
if (!org) return null
282327

283328
const userId = parseInt(this.state.session.user_id)
@@ -377,6 +422,13 @@ class Organization extends Component {
377422
</dl>
378423
</Card>
379424
</div>
425+
<div className='team__table'>
426+
<Section>
427+
<SectionHeader>Teams</SectionHeader>
428+
</Section>
429+
<div>{this.renderOrgTeams(teams)}</div>
430+
</div>
431+
380432
{isOrgPublic || isMemberOfOrg ? (
381433
<div className='team__table'>
382434
<Section>

0 commit comments

Comments
 (0)