Skip to content

Commit 7134bbb

Browse files
authored
chore: refactor teams query in organization (#11085)
1 parent 4205b6e commit 7134bbb

File tree

13 files changed

+49
-104
lines changed

13 files changed

+49
-104
lines changed

Diff for: packages/client/components/DashNavList/DashNavList.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ const DashNavList = (props: Props) => {
3030
id
3131
name
3232
tier
33-
viewerTeams {
33+
teams {
3434
id
35+
isViewerOnTeam
3536
}
3637
}
3738
`,
@@ -63,7 +64,7 @@ const DashNavList = (props: Props) => {
6364
</Tooltip>
6465
</div>
6566
<DashNavListTeams onClick={onClick} organizationRef={org} />
66-
{org.viewerTeams.length === 0 && <EmptyTeams organizationRef={org} />}
67+
{!org.teams.some((team) => team.isViewerOnTeam) && <EmptyTeams organizationRef={org} />}
6768
</div>
6869
))}
6970
</div>

Diff for: packages/client/components/DashNavList/DashNavListTeams.tsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,19 @@ const DashNavListTeams = (props: Props) => {
2929
id
3030
name
3131
tier
32-
viewerTeams {
32+
teams {
3333
...DashNavListTeam @relay(mask: false)
34-
}
35-
publicTeams {
3634
...PublicTeamsModal_team
35+
isViewerOnTeam
3736
}
3837
}
3938
`,
4039
organizationRef
4140
)
4241
const [showModal, setShowModal] = useState(false)
43-
const {publicTeams, viewerTeams} = organization
42+
const allTeams = organization.teams
43+
const viewerTeams = allTeams.filter((team) => team.isViewerOnTeam)
44+
const publicTeams = allTeams.filter((team) => !team.isViewerOnTeam)
4445
const publicTeamsCount = publicTeams.length
4546

4647
const handleClose = () => {

Diff for: packages/client/components/DashNavList/EmptyTeams.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,17 @@ const EmptyTeams = (props: Props) => {
1919
fragment EmptyTeams_organization on Organization {
2020
id
2121
name
22-
publicTeams {
22+
teams {
2323
id
24+
isViewerOnTeam
2425
...PublicTeamsModal_team
2526
}
2627
}
2728
`,
2829
organizationRef
2930
)
30-
const {id: orgId, publicTeams} = organization
31+
const {id: orgId, teams} = organization
32+
const publicTeams = teams.filter((team) => !team.isViewerOnTeam)
3133
const hasPublicTeams = publicTeams.length > 0
3234

3335
const viewer = useClientQuery<EmptyTeamsQuery>(
@@ -90,4 +92,5 @@ const EmptyTeams = (props: Props) => {
9092
</>
9193
)
9294
}
95+
9396
export default EmptyTeams

Diff for: packages/client/components/DashNavList/PublicTeamsModal.tsx

+8-1
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,20 @@ const PublicTeamsModal = (props: Props) => {
2424
graphql`
2525
fragment PublicTeamsModal_team on Team @relay(plural: true) {
2626
id
27+
lastMetAt
2728
...PublicTeamItem_team
2829
}
2930
`,
3031
teamsRef
3132
)
3233
const publicTeamsCount = publicTeams.length
3334

35+
const sortedTeams = [...publicTeams].sort((a, b) => {
36+
if (!a.lastMetAt) return 1
37+
if (!b.lastMetAt) return -1
38+
return new Date(b.lastMetAt).getTime() - new Date(a.lastMetAt).getTime()
39+
})
40+
3441
return (
3542
<Dialog isOpen={isOpen} onClose={onClose}>
3643
<DialogContent className='z-10 flex flex-col pr-0'>
@@ -40,7 +47,7 @@ const PublicTeamsModal = (props: Props) => {
4047
<span className='font-semibold'>{orgName}</span>
4148
</DialogDescription>
4249
<div className='overflow-auto pr-6'>
43-
{publicTeams.map((team) => (
50+
{sortedTeams.map((team) => (
4451
<Fragment key={team.id}>
4552
<hr className='my-2 border-t border-slate-300' />
4653
<PublicTeamItem teamRef={team} />

Diff for: packages/client/modules/newTeam/components/NewTeamForm/NewTeamForm.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ const NewTeamForm = (props: Props) => {
125125
lockedAt
126126
name
127127
tier
128-
allTeams {
128+
teams {
129129
name
130130
...NewTeamForm_teams @relay(mask: false)
131131
}
@@ -143,7 +143,7 @@ const NewTeamForm = (props: Props) => {
143143
const [inviteAll, setInviteAll] = useState(false)
144144
const disableFields = !!lockedSelectedOrg && !isNewOrg
145145
const selectedOrg = organizations.find((org) => org.id === orgId)
146-
const selectedOrgTeamMemberEmails = selectedOrg?.allTeams.flatMap(({teamMembers}) =>
146+
const selectedOrgTeamMemberEmails = selectedOrg?.teams.flatMap(({teamMembers}) =>
147147
teamMembers.filter(({isSelf}) => !isSelf).map(({user}) => user.email)
148148
)
149149
const uniqueEmailsFromSelectedOrg = Array.from(new Set(selectedOrgTeamMemberEmails))
@@ -164,7 +164,7 @@ const NewTeamForm = (props: Props) => {
164164
let teamNames: string[] = []
165165
if (!isNewOrg) {
166166
if (selectedOrg) {
167-
teamNames = selectedOrg.allTeams.map((team) => team.name)
167+
teamNames = selectedOrg.teams.map((team) => team.name)
168168
}
169169
}
170170
return teamNameValidation(teamName, teamNames)

Diff for: packages/client/modules/teamDashboard/components/EditTeamName/EditableTeamName.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const EditableTeamName = (props: Props) => {
2828
teamId: id
2929
teamName: name
3030
organization {
31-
allTeams {
31+
teams {
3232
id
3333
name
3434
}
@@ -38,7 +38,7 @@ const EditableTeamName = (props: Props) => {
3838
teamRef
3939
)
4040
const {teamName, teamId, organization} = team
41-
const {allTeams: teams} = organization
41+
const {teams} = organization
4242

4343
const handleSubmit = (rawName: string) => {
4444
if (submitting) return

Diff for: packages/client/modules/userDashboard/components/OrgTeams/OrgTeams.tsx

+6-9
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,16 @@ const OrgTeams = (props: Props) => {
2222
fragment OrgTeams_organization on Organization {
2323
id
2424
tier
25-
allTeams {
25+
teams {
2626
id
2727
name
2828
lastMetAt
2929
teamMembers {
3030
id
3131
}
32+
isViewerOnTeam
3233
...OrgTeamsRow_team
3334
}
34-
viewerTeams {
35-
id
36-
}
3735
allTeamsCount
3836
}
3937
`,
@@ -48,10 +46,9 @@ const OrgTeams = (props: Props) => {
4846

4947
const [sortBy, setSortBy] = useState<SortField>('lastMetAt')
5048
const [sortDirection, setSortDirection] = useState<SortDirection>('desc')
51-
52-
const {allTeams, tier, viewerTeams, allTeamsCount} = organization
53-
const showingAllTeams = allTeams.length === allTeamsCount
54-
const viewerTeamCount = viewerTeams.length
49+
const {teams, allTeamsCount, tier} = organization
50+
const showingAllTeams = teams.length === allTeamsCount
51+
const viewerTeamCount = teams.length
5552

5653
const handleSort = (field: SortField) => {
5754
if (sortBy === field) {
@@ -62,7 +59,7 @@ const OrgTeams = (props: Props) => {
6259
}
6360
}
6461

65-
const sortedTeams = [...allTeams].sort((a, b) => {
62+
const sortedTeams = [...teams].sort((a, b) => {
6663
const direction = sortDirection === 'asc' ? 1 : -1
6764
if (sortBy === 'name') {
6865
return direction * a.name.localeCompare(b.name)

Diff for: packages/client/mutations/ArchiveTeamMutation.ts

+1-5
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@ graphql`
3131
id
3232
}
3333
organization {
34-
allTeams {
35-
id
36-
}
37-
viewerTeams {
34+
teams {
3835
id
3936
}
4037
}
@@ -106,7 +103,6 @@ export const archiveTeamTeamUpdater: SharedUpdater<ArchiveTeamMutation_team$data
106103
const orgs = viewer.getLinkedRecords('organizations')!
107104
orgs.forEach((org) => {
108105
safeRemoveNodeFromArray(teamId, org, 'teams')
109-
safeRemoveNodeFromArray(teamId, org, 'allTeams')
110106
})
111107

112108
const notification = payload.getLinkedRecord('notification')

Diff for: packages/client/mutations/DowngradeToStarterMutation.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ graphql`
88
organization {
99
tier
1010
billingTier
11-
viewerTeams {
11+
teams {
1212
isPaid
1313
tier
1414
}

Diff for: packages/client/mutations/fragments/PublicTeamsFrag.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,9 @@ graphql`
77
id
88
}
99
organization {
10-
allTeams {
11-
id
12-
}
13-
viewerTeams {
14-
id
15-
}
16-
publicTeams {
10+
teams {
1711
id
12+
isViewerOnTeam
1813
}
1914
}
2015
}

Diff for: packages/client/mutations/fragments/UpgradeToTeamTierFrag.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ graphql`
1919
periodStart
2020
updatedAt
2121
lockedAt
22-
viewerTeams {
22+
teams {
2323
isPaid
2424
tier
2525
}

Diff for: packages/server/graphql/public/typeDefs/Organization.graphql

+4-12
Original file line numberDiff line numberDiff line change
@@ -48,25 +48,17 @@ type Organization {
4848
activeTeamCount: Int!
4949

5050
"""
51-
All the teams in the organization. If the viewer is not a billing lead, org admin, super user, or they do not have the publicTeams flag, return the teams they are a member of.
51+
Teams in the organization that the viewer has access to.
52+
For org admins/super users: all teams in the org (viewer's teams first).
53+
For regular users: teams the viewer is on plus public teams.
5254
"""
53-
allTeams: [Team!]!
55+
teams: [Team!]!
5456

5557
"""
5658
The count of all teams in the organization
5759
"""
5860
allTeamsCount: Int!
5961

60-
"""
61-
all the teams the viewer is on in the organization
62-
"""
63-
viewerTeams: [Team!]!
64-
65-
"""
66-
all the teams that the viewer does not belong to that are in the organization. Only visible if the org has the publicTeams flag set to true.
67-
"""
68-
publicTeams: [Team!]!
69-
7062
"""
7163
THe datetime the current billing cycle ends
7264
"""

Diff for: packages/server/graphql/public/types/Organization.ts

+8-55
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
getUserId,
33
isSuperUser,
4-
isTeamMember,
54
isUserBillingLeader,
65
isUserOrgAdmin
76
} from '../../../utils/authorization'
@@ -53,20 +52,20 @@ const Organization: OrganizationResolvers = {
5352
return getActiveTeamCountByOrgIds(orgId)
5453
},
5554

56-
allTeams: async ({id: orgId}, _args, {dataLoader, authToken}) => {
55+
teams: async ({id: orgId}, _args, {dataLoader, authToken}) => {
5756
const viewerId = getUserId(authToken)
58-
const [allTeamsOnOrg, isOrgAdmin] = await Promise.all([
57+
const [teamsInOrg, isOrgAdmin] = await Promise.all([
5958
dataLoader.get('teamsByOrgIds').load(orgId),
60-
dataLoader.get('organizations').loadNonNull(orgId),
6159
isUserOrgAdmin(viewerId, orgId, dataLoader)
6260
])
63-
const sortedTeamsOnOrg = allTeamsOnOrg.sort((a, b) => a.name.localeCompare(b.name))
61+
const sortedTeams = teamsInOrg.sort((a, b) => a.name.localeCompare(b.name))
62+
6463
if (isOrgAdmin || isSuperUser(authToken)) {
65-
const viewerTeams = sortedTeamsOnOrg.filter((team) => authToken.tms.includes(team.id))
66-
const otherTeams = sortedTeamsOnOrg.filter((team) => !authToken.tms.includes(team.id))
67-
return [...viewerTeams, ...otherTeams]
64+
// Org admins and super users can see all teams
65+
return sortedTeams
6866
} else {
69-
return sortedTeamsOnOrg.filter((team) => authToken.tms.includes(team.id))
67+
// Regular users can see teams they're on plus public teams
68+
return sortedTeams.filter((team) => team.isPublic || authToken.tms.includes(team.id))
7069
}
7170
},
7271

@@ -75,52 +74,6 @@ const Organization: OrganizationResolvers = {
7574
return allTeamsOnOrg?.length ?? 0
7675
},
7776

78-
viewerTeams: async ({id: orgId}, _args, {dataLoader, authToken}) => {
79-
const allTeamsOnOrg = await dataLoader.get('teamsByOrgIds').load(orgId)
80-
return allTeamsOnOrg
81-
.filter((team) => authToken.tms.includes(team.id))
82-
.sort((a, b) => a.name.localeCompare(b.name))
83-
},
84-
85-
publicTeams: async ({id: orgId}, _args, {dataLoader, authToken}) => {
86-
const allTeamsOnOrg = await dataLoader.get('teamsByOrgIds').load(orgId)
87-
const publicTeams = allTeamsOnOrg.filter(
88-
(team) => (team.isPublic || isSuperUser(authToken)) && !isTeamMember(authToken, team.id)
89-
)
90-
91-
const teamsWithMeetingData = await Promise.all(
92-
publicTeams.map(async (team) => {
93-
const [completedMeetings, activeMeetings] = await Promise.all([
94-
dataLoader.get('completedMeetingsByTeamId').load(team.id),
95-
dataLoader.get('activeMeetingsByTeamId').load(team.id)
96-
])
97-
98-
const allMeetingDates = [
99-
...completedMeetings.map((meeting) => new Date(meeting.endedAt || meeting.createdAt)),
100-
...activeMeetings.map((meeting) => new Date(meeting.createdAt))
101-
]
102-
103-
const lastMetAt =
104-
allMeetingDates.length > 0
105-
? new Date(Math.max(...allMeetingDates.map((date) => date.getTime())))
106-
: null
107-
108-
return {
109-
...team,
110-
lastMetAt
111-
}
112-
})
113-
)
114-
115-
// Show teams who met most recently first
116-
return teamsWithMeetingData.sort((a, b) => {
117-
if (!a.lastMetAt && !b.lastMetAt) return 0
118-
if (!a.lastMetAt) return 1
119-
if (!b.lastMetAt) return -1
120-
return b.lastMetAt.getTime() - a.lastMetAt.getTime()
121-
})
122-
},
123-
12477
viewerOrganizationUser: async ({id: orgId}, _args, {dataLoader, authToken}) => {
12578
const viewerId = getUserId(authToken)
12679
return dataLoader.get('organizationUsersByUserIdOrgId').load({userId: viewerId, orgId})

0 commit comments

Comments
 (0)