Skip to content

Commit

Permalink
feat(schedule feature flags): add plain UI (#19071)
Browse files Browse the repository at this point in the history
  • Loading branch information
jurajmajerik authored Dec 7, 2023
1 parent 48a30c9 commit 158dae2
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 5 deletions.
1 change: 1 addition & 0 deletions frontend/src/lib/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export const FEATURE_FLAGS = {
NETWORK_PAYLOAD_CAPTURE: 'network-payload-capture', // owner: #team-replay
FEATURE_FLAG_COHORT_CREATION: 'feature-flag-cohort-creation', // owner: @neilkakkar #team-feature-success
INSIGHT_HORIZONTAL_CONTROLS: 'insight-horizontal-controls', // owner: @benjackwhite
SCHEDULED_CHANGES_FEATURE_FLAGS: 'scheduled-changes-feature-flags', // owner: @jurajmajerik #team-feature-success
ALWAYS_SHOW_SEEKBAR_PREVIEW: 'always-show-seekbar-preview', // owner: #team-replay
SESSION_REPLAY_MOBILE: 'session-replay-mobile', // owner: #team-replay
SESSION_REPLAY_IOS: 'session-replay-ios', // owner: #team-replay
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/scenes/feature-flags/FeatureFlag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import { featureFlagLogic } from './featureFlagLogic'
import { featureFlagPermissionsLogic } from './featureFlagPermissionsLogic'
import FeatureFlagProjects from './FeatureFlagProjects'
import { FeatureFlagReleaseConditions } from './FeatureFlagReleaseConditions'
import FeatureFlagSchedule from './FeatureFlagSchedule'
import { featureFlagsLogic, FeatureFlagsTab } from './featureFlagsLogic'
import { RecentFeatureFlagInsights } from './RecentFeatureFlagInsightsCard'

Expand Down Expand Up @@ -221,6 +222,14 @@ export function FeatureFlag({ id }: { id?: string } = {}): JSX.Element {
})
}

if (featureFlags[FEATURE_FLAGS.SCHEDULED_CHANGES_FEATURE_FLAGS]) {
tabs.push({
label: 'Schedule',
key: FeatureFlagsTab.SCHEDULE,
content: <FeatureFlagSchedule />,
})
}

return (
<>
<div className="feature-flag">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ interface FeatureFlagReadOnlyProps {
readOnly?: boolean
isSuper?: boolean
excludeTitle?: boolean
usageContext?: string
}

export function FeatureFlagReleaseConditions({
readOnly,
isSuper,
excludeTitle,
usageContext,
}: FeatureFlagReadOnlyProps): JSX.Element {
const logic = usageContext === 'schedule' ? featureFlagLogic({ id: 'schedule' }) : featureFlagLogic

const { showGroupsOptions, aggregationLabel } = useValues(groupsModel)
const {
aggregationTargetName,
Expand All @@ -47,14 +51,14 @@ export function FeatureFlagReleaseConditions({
computeBlastRadiusPercentage,
affectedUsers,
totalUsers,
} = useValues(featureFlagLogic)
} = useValues(logic)
const {
setAggregationGroupTypeIndex,
updateConditionSet,
duplicateConditionSet,
removeConditionSet,
addConditionSet,
} = useActions(featureFlagLogic)
} = useActions(logic)
const { cohortsById } = useValues(cohortsModel)

const filterGroups: FeatureFlagGroupType[] = isSuper
Expand Down
86 changes: 86 additions & 0 deletions frontend/src/scenes/feature-flags/FeatureFlagSchedule.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { LemonButton, LemonCheckbox, LemonDivider, LemonSelect, LemonTable } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { DatePicker } from 'lib/components/DatePicker'
import { createdAtColumn, createdByColumn } from 'lib/lemon-ui/LemonTable/columnUtils'
import { useEffect } from 'react'

import { featureFlagLogic } from './featureFlagLogic'
import { FeatureFlagReleaseConditions } from './FeatureFlagReleaseConditions'

const logic = featureFlagLogic({ id: 'schedule' })
export const DAYJS_FORMAT = 'MMMM DD, YYYY h:mm A'

const columns = [createdByColumn() as any, createdAtColumn() as any]

export default function FeatureFlagSchedule(): JSX.Element {
const { featureFlag, scheduledChanges, scheduleChangeType, scheduleDateMarker } = useValues(logic)
const { setFeatureFlag, loadScheduledChanges, setScheduleDateMarker, setScheduleChangeType } = useActions(logic)

useEffect(() => {
loadScheduledChanges()
}, [])

return (
<div>
<h3 className="l3">Add a scheduled change</h3>
<div className="mb-6">Automatically change flag properties at a future point in time.</div>
<div className="inline-flex gap-10 mb-8">
<div>
<div className="font-semibold leading-6 h-6 mb-1">Change type</div>
<LemonSelect
className="w-50"
placeholder="Select variant"
value={scheduleChangeType}
onChange={(value) => setScheduleChangeType(value)}
options={[
{ label: 'Add a condition', value: 'add_condition' },
{ label: 'Change status', value: 'change_status' },
]}
/>
</div>
<div>
<div className="font-semibold leading-6 h-6 mb-1">Date and time</div>
<DatePicker
value={scheduleDateMarker}
onChange={(value) => setScheduleDateMarker(value)}
className="h-10 w-60"
allowClear={false}
showTime
showSecond={false}
format={DAYJS_FORMAT}
/>
</div>
</div>

<div className="space-y-4">
{scheduleChangeType === 'add_condition' && <FeatureFlagReleaseConditions usageContext="schedule" />}
{scheduleChangeType === 'change_status' && (
<>
<div className="border rounded p-4">
<LemonCheckbox
id="flag-enabled-checkbox"
label="Enable feature flag"
onChange={(value) => {
featureFlag.active = value
setFeatureFlag(featureFlag)
}}
checked={featureFlag.active}
/>
</div>
</>
)}
<div className="flex items-center justify-end">
<LemonButton type="primary">Schedule</LemonButton>
</div>
<LemonDivider className="" />
</div>
<LemonTable
className="mt-8"
loading={false}
dataSource={scheduledChanges}
columns={columns}
emptyState="You do not have any scheduled changes"
/>
</div>
)
}
26 changes: 23 additions & 3 deletions frontend/src/scenes/feature-flags/featureFlagLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export function validateFeatureFlagKey(key: string): string | undefined {
}

export interface FeatureFlagLogicProps {
id: number | 'new' | 'link'
id: number | 'new' | 'link' | 'schedule'
}

// KLUDGE: Payloads are returned in a <variant-key>: <payload> mapping.
Expand Down Expand Up @@ -230,6 +230,8 @@ export const featureFlagLogic = kea<featureFlagLogicType>([
generateUsageDashboard: true,
enrichUsageDashboard: true,
setCopyDestinationProject: (id: number | null) => ({ id }),
setScheduleDateMarker: (dateMarker: any) => ({ dateMarker }),
setScheduleChangeType: (changeType: string | null) => ({ changeType }),
}),
forms(({ actions, values }) => ({
featureFlag: {
Expand Down Expand Up @@ -482,11 +484,23 @@ export const featureFlagLogic = kea<featureFlagLogicType>([
setCopyDestinationProject: (_, { id }) => id,
},
],
scheduleDateMarker: [
null as any,
{
setScheduleDateMarker: (_, { dateMarker }) => dateMarker,
},
],
scheduleChangeType: [
'add_condition' as string | null,
{
setScheduleChangeType: (_, { changeType }) => changeType,
},
],
}),
loaders(({ values, props, actions }) => ({
featureFlag: {
loadFeatureFlag: async () => {
if (props.id && props.id !== 'new' && props.id !== 'link') {
if (props.id && props.id !== 'new' && props.id !== 'link' && props.id !== 'schedule') {
try {
const retrievedFlag: FeatureFlagType = await api.featureFlags.get(props.id)
return variantKeyToIndexFeatureFlagPayloads(retrievedFlag)
Expand Down Expand Up @@ -587,7 +601,7 @@ export const featureFlagLogic = kea<featureFlagLogicType>([
null as CohortType | null,
{
createStaticCohort: async () => {
if (props.id && props.id !== 'new' && props.id !== 'link') {
if (props.id && props.id !== 'new' && props.id !== 'link' && props.id !== 'schedule') {
return (await api.featureFlags.createStaticCohort(props.id)).cohort
}
return null
Expand Down Expand Up @@ -627,6 +641,12 @@ export const featureFlagLogic = kea<featureFlagLogicType>([
}
},
},
scheduledChanges: {
__default: [] as any,
loadScheduledChanges: async () => {
return []
},
},
})),
listeners(({ actions, values, props }) => ({
submitNewDashboardSuccessWithResult: async ({ result }) => {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/scenes/feature-flags/featureFlagsLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export enum FeatureFlagsTab {
USAGE = 'usage',
PERMISSIONS = 'permissions',
PROJECTS = 'projects',
SCHEDULE = 'schedule',
}

export interface FeatureFlagsFilters {
Expand Down

0 comments on commit 158dae2

Please sign in to comment.