Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refactor feature flags #10234

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
85db00a
change featureFlagNew to featureFlag and replace org featureFlag
nickoferrall Sep 9, 2024
92b0e8d
check zoomTranscription flag works
nickoferrall Sep 9, 2024
a7bd7ed
update org feature flags
nickoferrall Sep 9, 2024
3fa2e08
refactor public teams flag
nickoferrall Sep 9, 2024
333c456
add feature flag to org and team
nickoferrall Sep 10, 2024
2059d00
refactor feature flags in client
nickoferrall Sep 10, 2024
93e9cb4
implement dataloader
nickoferrall Sep 10, 2024
e3adf02
add featureFlag to team
nickoferrall Sep 16, 2024
8a74299
update canAccessAISummary
nickoferrall Sep 16, 2024
4d64131
remove update org feature flag
nickoferrall Sep 16, 2024
17adb2b
remove update feature flag public mutation
nickoferrall Sep 16, 2024
c2c1b22
remove org and user feature flags
nickoferrall Sep 16, 2024
7eba48b
remove featureFlag references
nickoferrall Sep 16, 2024
4352f88
implement getFeatureFlags
nickoferrall Sep 16, 2024
d682ab1
implement get feature flags
nickoferrall Sep 16, 2024
4b0d699
remove user and org feature flag enums
nickoferrall Sep 16, 2024
2e335c7
merge with master
nickoferrall Sep 16, 2024
8a4d5ba
fux setMeetingSettings merge conflict error
nickoferrall Sep 16, 2024
0a40b4d
update migration order
nickoferrall Sep 17, 2024
e0b2dd9
Merge branch 'feat/apply-new-feature-flag-mutation' into feat/10099/f…
nickoferrall Sep 17, 2024
dfbf469
fix featureName
nickoferrall Sep 17, 2024
cb532b8
Merge branch 'feat/apply-new-feature-flag-mutation' into feat/10099/f…
nickoferrall Sep 20, 2024
4b165c7
update featureFlag references to use scope
nickoferrall Sep 20, 2024
39fa9e8
update addFeatureFlag to use scope
nickoferrall Sep 20, 2024
4cf3339
remove scope from gql featureFlag query
nickoferrall Sep 25, 2024
2e696de
fix ups - remove featureFlagScope graphql
nickoferrall Sep 30, 2024
e4190c3
use aliases consistently
nickoferrall Sep 30, 2024
df431b4
add getAllFeatureFlags private query
nickoferrall Sep 30, 2024
03551b8
remove scope from dataloader
nickoferrall Sep 30, 2024
f5ee24c
remove scope from dataloader calls
nickoferrall Sep 30, 2024
509f3a3
chore: migrate noaisummary flag (#10293)
nickoferrall Oct 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion codegen.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
"StartTrialSuccess": "./types/StartTrialSuccess#StartTrialSuccessSource",
"StripeFailPaymentPayload": "./mutations/stripeFailPayment#StripeFailPaymentPayloadSource",
"Team": "../../postgres/types/index#Team as TeamDB",
"UpdateOrgFeatureFlagSuccess": "./types/UpdateOrgFeatureFlagSuccess#UpdateOrgFeatureFlagSuccessSource",
"UpgradeToTeamTierSuccess": "./mutations/upgradeToTeamTier#UpgradeToTeamTierSuccessSource",
"User": "../../postgres/types/IUser#default as IUser",
"VerifyDomainSuccess": "./types/VerifyDomainSuccess#VerifyDomainSuccessSource"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,7 @@ const query = graphql`
}
}
organizations {
featureFlags {
aiTemplate
}
hasAITemplateFlag: featureFlag(featureName: "aiTemplate")
}
}
}
Expand Down Expand Up @@ -229,7 +227,7 @@ export const ActivityLibrary = (props: Props) => {
const data = usePreloadedQuery<ActivityLibraryQuery>(query, queryRef)
const {viewer} = data
const {availableTemplates, organizations} = viewer
const hasAITemplateFeatureFlag = !!organizations.find((org) => org.featureFlags.aiTemplate)
const hasAITemplateFeatureFlag = organizations.some((org) => org.hasAITemplateFlag)

const [isSearching, setIsSearching] = React.useState(true)
const [templateSearch, refetchTemplateSearch] = useRefetchableFragment<
Expand Down
9 changes: 3 additions & 6 deletions packages/client/components/DashNavList/DashNavListTeams.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ const DashNavListTeams = (props: Props) => {
id
name
tier
featureFlags {
publicTeams
}
hasPublicTeamsFlag: featureFlag(featureName: "publicTeams")
viewerTeams {
...DashNavListTeam @relay(mask: false)
}
Expand All @@ -43,9 +41,8 @@ const DashNavListTeams = (props: Props) => {
organizationRef
)
const [showModal, setShowModal] = useState(false)
const {publicTeams, viewerTeams, featureFlags} = organization
const publicTeamsEnabled = featureFlags?.publicTeams
const publicTeamsCount = publicTeamsEnabled ? publicTeams.length : 0
const {publicTeams, viewerTeams, hasPublicTeamsFlag} = organization
const publicTeamsCount = hasPublicTeamsFlag ? publicTeams.length : 0

const handleClose = () => {
setShowModal(false)
Expand Down
9 changes: 3 additions & 6 deletions packages/client/components/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,7 @@ const Dashboard = (props: Props) => {
...DashSidebar_viewer
...useNewFeatureSnackbar_viewer
overLimitCopy
featureFlags {
insights
}
hasInsightsFlag: featureFlag(featureName: "insights")
teams {
activeMeetings {
...useSnacksForNewMeetings_meetings
Expand All @@ -119,15 +117,14 @@ const Dashboard = (props: Props) => {
queryRef
)
const {viewer} = data
const {teams, featureFlags} = viewer
const {insights} = featureFlags
const {teams, hasInsightsFlag} = viewer
const activeMeetings = teams.flatMap((team) => team.activeMeetings).filter(Boolean)
const {isOpen, toggle, handleMenuClick} = useSidebar()
const isDesktop = useBreakpoint(Breakpoint.SIDEBAR_LEFT)
const overLimitCopy = viewer?.overLimitCopy
const meetingsDashRef = useRef<HTMLDivElement>(null)
useSnackNag(overLimitCopy)
useUsageSnackNag(insights)
useUsageSnackNag(hasInsightsFlag)
useSnacksForNewMeetings(activeMeetings)
useNewFeatureSnackbar(viewer)

Expand Down
6 changes: 2 additions & 4 deletions packages/client/components/RetroDiscussionThreadHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,12 @@ const RetroDiscussionThreadHeader = (props: Props) => {
const organization = useFragment(
graphql`
fragment RetroDiscussionThreadHeader_organization on Organization {
featureFlags {
zoomTranscription
}
hasZoomFlag: featureFlag(featureName: "zoomTranscription")
}
`,
organizationRef ?? null
)
const hasZoomFlag = organization?.featureFlags.zoomTranscription ?? false
const hasZoomFlag = organization?.hasZoomFlag ?? false

const handleHeaderClick = (header: 'discussion' | 'transcription') => {
if (showTranscription && header === 'transcription') return
Expand Down
7 changes: 2 additions & 5 deletions packages/client/components/RetroGroupPhase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ const RetroGroupPhase = (props: Props) => {
}
organization {
tier
featureFlags {
suggestGroups
}
hasSuggestGroupsFlag: featureFlag(featureName: "suggestGroups")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 nit on alias convention-- sometimes you have a suffix like publicTeamsEnabled, sometimes it's just the name of the feature aiTemplate and here we have a has prefix. no right or wrong, but always nice to set a convention for others to follow

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! I like the most explicit option of has[name]Flag, so I've updated all of them to follow that convention

}
}
`,
Expand All @@ -83,8 +81,7 @@ const RetroGroupPhase = (props: Props) => {
autogroupReflectionGroups,
resetReflectionGroups
} = meeting
const {featureFlags, tier} = organization
const {suggestGroups: hasSuggestGroupsFlag} = featureFlags
const {hasSuggestGroupsFlag, tier} = organization
const {openTooltip, closeTooltip, tooltipPortal, originRef} = useTooltip<HTMLDivElement>(
MenuPosition.UPPER_CENTER
)
Expand Down
9 changes: 3 additions & 6 deletions packages/client/components/StandardHubUserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@ const StandardHubUserMenu = (props: Props) => {
graphql`
fragment StandardHubUserMenu_viewer on User {
email
featureFlags {
insights
}
hasInsightsFlag: featureFlag(featureName: "insights")
organizations {
id
billingTier
Expand All @@ -54,8 +52,7 @@ const StandardHubUserMenu = (props: Props) => {
`,
viewerRef
)
const {email, featureFlags, organizations} = viewer
const {insights} = featureFlags
const {email, hasInsightsFlag, organizations} = viewer
const ownedFreeOrgs = organizations.filter((org) => org.billingTier === 'starter')
const showUpgradeCTA = ownedFreeOrgs.length > 0
const routeSuffix = ownedFreeOrgs.length === 1 ? `/${ownedFreeOrgs[0]!.id}` : ''
Expand Down Expand Up @@ -83,7 +80,7 @@ const StandardHubUserMenu = (props: Props) => {
</MenuItemLink>
}
/>
{insights && (
{hasInsightsFlag && (
<MenuItem
label={
<MenuItemLink to={'/usage'}>
Expand Down
11 changes: 4 additions & 7 deletions packages/client/components/TeamPromptMeeting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,14 @@ const TeamPromptMeeting = (props: Props) => {
}
}
organization {
featureFlags {
singleColumnStandups
}
hasSingleColumnStandupsFlag: featureFlag(featureName: "singleColumnStandups")
}
}
`,
meetingRef
)
const {phases, organization} = meeting
const {featureFlags} = organization
const {singleColumnStandups} = featureFlags
const {hasSingleColumnStandupsFlag} = organization
const atmosphere = useAtmosphere()
const {viewerId} = atmosphere

Expand Down Expand Up @@ -183,7 +180,7 @@ const TeamPromptMeeting = (props: Props) => {
<TeamPromptEditablePrompt meetingRef={meeting} />
<ErrorBoundary>
<ResponsesGridContainer>
<ResponsesGrid isSingleColumn={singleColumnStandups}>
<ResponsesGrid isSingleColumn={hasSingleColumnStandupsFlag}>
{transitioningStages.map((transitioningStage) => {
const {child: stage, onTransitionEnd, status} = transitioningStage
const {key, displayIdx} = stage
Expand All @@ -195,7 +192,7 @@ const TeamPromptMeeting = (props: Props) => {
onTransitionEnd={onTransitionEnd}
displayIdx={displayIdx}
stageRef={stage}
isSingleColumn={singleColumnStandups}
isSingleColumn={hasSingleColumnStandupsFlag}
/>
)
})}
Expand Down
3 changes: 0 additions & 3 deletions packages/client/modules/demo/DemoUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ export default class DemoUser {
viewerId: string
createdAt = new Date().toJSON()
email: string
featureFlags = {
azureDevOps: false
}
facilitatorUserId: string
facilitatorName: string
inactive = false
Expand Down
7 changes: 0 additions & 7 deletions packages/client/modules/demo/initDB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,13 +297,6 @@ const initDemoOrg = () => {
activeUserCount: 5,
inactiveUserCount: 0
},
featureFlags: {
zoomTranscription: false,
suggestGroups: false,
teamsLimit: false,
noPromptToJoinOrg: false,
publicTeams: false
},
showConversionModal: false
} as const
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,15 @@ const RetroTopic = (props: Props) => {
fragment RetroTopic_meeting on RetrospectiveMeeting {
id
organization {
featureFlags {
shareSummary
}
hasShareSummaryFlag: featureFlag(featureName: "shareSummary")
}
}
`,
meetingRef
)

const {id: meetingId} = meeting

const hasShareSummaryFeatureFlag = meeting.organization.featureFlags.shareSummary

const hasShareSummaryFlag = meeting.organization.hasShareSummaryFlag
const {reflectionGroup, discussion, id: stageId} = stage
const {commentCount, discussionSummary} = discussion
const {reflections, title, voteCount} = reflectionGroup
Expand Down Expand Up @@ -174,7 +170,7 @@ const RetroTopic = (props: Props) => {
{commentLinkLabel}
</AnchorIfEmail>
</td>
{hasShareSummaryFeatureFlag && (
{hasShareSummaryFlag && (
<td style={{padding: '10px'}}>
<ShareTopic
isEmail={isEmail}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@ const WholeMeetingSummary = (props: Props) => {
id
summary
organization {
featureFlags {
standupAISummary
noAISummary
}
hasStandupAISummaryFlag: featureFlag(featureName: "standupAISummary")
hasNoAISummaryFlag: featureFlag(featureName: "noAISummary")
}
... on RetrospectiveMeeting {
reflectionGroups(sortBy: voteCount) {
Expand All @@ -49,14 +47,14 @@ const WholeMeetingSummary = (props: Props) => {
const {summary: wholeMeetingSummary, reflectionGroups, organization} = meeting
const reflections = reflectionGroups?.flatMap((group) => group.reflections) // reflectionCount hasn't been calculated yet so check reflections length
const hasMoreThanOneReflection = reflections?.length && reflections.length > 1
if (!hasMoreThanOneReflection || organization.featureFlags.noAISummary || !hasAI) return null
if (!hasMoreThanOneReflection || organization.hasNoAISummaryFlag || !hasAI) return null
if (!wholeMeetingSummary) return <WholeMeetingSummaryLoading />
return <WholeMeetingSummaryResult meetingRef={meeting} />
} else if (meeting.__typename === 'TeamPromptMeeting') {
const {summary: wholeMeetingSummary, responses, organization} = meeting
if (
!organization.featureFlags.standupAISummary ||
organization.featureFlags.noAISummary ||
!organization.hasStandupAISummaryFlag ||
organization.hasNoAISummaryFlag ||
!hasAI ||
!responses ||
responses.length === 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,7 @@ const NewCheckInQuestion = (props: Props) => {
}
team {
organization {
featureFlags {
noAISummary
}
hasNoAISummaryFlag: featureFlag(featureName: "noAISummary")
}
}
}
Expand All @@ -103,7 +101,7 @@ const NewCheckInQuestion = (props: Props) => {
localPhase,
facilitatorUserId,
team: {
organization: {featureFlags}
organization: {hasNoAISummaryFlag}
}
} = meeting
const {checkInQuestion} = localPhase
Expand Down Expand Up @@ -228,8 +226,7 @@ const NewCheckInQuestion = (props: Props) => {
}
})
}
const showAiIcebreaker =
!featureFlags.noAISummary && isFacilitating && window.__ACTION__.hasOpenAI
const showAiIcebreaker = !hasNoAISummaryFlag && isFacilitating && window.__ACTION__.hasOpenAI

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ const OrgTeams = (props: Props) => {
fragment OrgTeams_organization on Organization {
id
isOrgAdmin
featureFlags {
publicTeams
}
hasPublicTeamsFlag: featureFlag(featureName: "publicTeams")
allTeams {
id
...OrgTeamsRow_team
Expand All @@ -37,8 +35,7 @@ const OrgTeams = (props: Props) => {
isOpen: isAddTeamDialogOpened
} = useDialogState()

const {allTeams, isOrgAdmin, featureFlags} = organization
const hasPublicTeamsFlag = featureFlags.publicTeams
const {allTeams, isOrgAdmin, hasPublicTeamsFlag} = organization
const showAllTeams = isOrgAdmin || hasPublicTeamsFlag
return (
<div className='max-w-4xl pb-4'>
Expand Down
8 changes: 2 additions & 6 deletions packages/client/mutations/EndRetrospectiveMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ graphql`
groupTitle
}
organization {
featureFlags {
noAISummary
}
hasNoAISummaryFlag: featureFlag(featureName: "noAISummary")
}
reflectionGroups(sortBy: voteCount) {
reflections {
Expand Down Expand Up @@ -129,9 +127,7 @@ export const endRetrospectiveTeamOnNext: OnNextHandler<
const reflections = reflectionGroups.flatMap((group) => group.reflections) // reflectionCount hasn't been calculated yet so check reflections length
const hasMoreThanOneReflection = reflections.length > 1
const hasOpenAISummary =
hasMoreThanOneReflection &&
!organization.featureFlags.noAISummary &&
window.__ACTION__.hasOpenAI
hasMoreThanOneReflection && !organization.hasNoAISummaryFlag && window.__ACTION__.hasOpenAI
const hasTeamHealth = phases.some((phase) => phase.phaseType === 'TEAM_HEALTH')
const pathname = `/new-summary/${meetingId}`
const search = new URLSearchParams()
Expand Down
6 changes: 2 additions & 4 deletions packages/client/mutations/LoginWithGoogleMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ const mutation = graphql`
}
isNewUser
user {
featureFlags {
signUpDestinationTeam
}
hasSignUpDestinationTeamFlag: featureFlag(featureName: "signUpDestinationTeam")
teams {
id
}
Expand Down Expand Up @@ -60,7 +58,7 @@ const LoginWithGoogleMutation: StandardMutation<TLoginWithGoogleMutation, Histor
const authToken = acceptTeamInvitation?.authToken ?? loginWithGoogle.authToken
atmosphere.setAuthToken(authToken)
const redirectPath =
isNewUser && user?.featureFlags.signUpDestinationTeam
isNewUser && user?.hasSignUpDestinationTeamFlag
? `/team/${user?.teams?.[0]?.id}`
: '/meetings'

Expand Down
6 changes: 2 additions & 4 deletions packages/client/mutations/SignUpWithPasswordMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ const mutation = graphql`
message
}
user {
featureFlags {
signUpDestinationTeam
}
hasSignUpDestinationTeamFlag: featureFlag(featureName: "signUpDestinationTeam")
teams {
id
}
Expand Down Expand Up @@ -58,7 +56,7 @@ const SignUpWithPasswordMutation: StandardMutation<
const authToken = acceptTeamInvitation?.authToken ?? signUpWithPassword.authToken
atmosphere.setAuthToken(authToken)

const redirectPath = user?.featureFlags.signUpDestinationTeam
const redirectPath = user?.hasSignUpDestinationTeamFlag
? `/team/${user?.teams?.[0]?.id}`
: '/meetings'

Expand Down
Loading
Loading