Skip to content

Commit

Permalink
fix: Prevent "Create Segment" button from disappearing when deleting …
Browse files Browse the repository at this point in the history
…the last segment (#4314)
  • Loading branch information
kyle-ssg authored Jul 12, 2024
1 parent f8babe8 commit cd121e8
Showing 1 changed file with 133 additions and 187 deletions.
320 changes: 133 additions & 187 deletions frontend/web/components/pages/SegmentsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import PageTitle from 'components/PageTitle'
import Switch from 'components/Switch'
import { setModalTitle } from 'components/modals/base/ModalDefault'
import classNames from 'classnames'
import InfoMessage from 'components/InfoMessage';

const CodeHelp = require('../../components/CodeHelp')
type SegmentsPageType = {
Expand All @@ -36,23 +37,6 @@ type SegmentsPageType = {
}
}

const HowToUseSegmentsMessage = () => (
<div className='mt-2'>
<p className='alert alert-info'>
In order to use segments, please set the segment_operators remote config
value.{' '}
<Button
theme='text'
target='_blank'
href='https://docs.flagsmith.com/deployment/overview#running-flagsmith-on-flagsmith'
>
Learn about self hosting
</Button>
.
</p>
</div>
)

const SegmentsPage: FC<SegmentsPageType> = (props) => {
const { projectId } = props.match.params
const environmentId =
Expand All @@ -72,7 +56,6 @@ const SegmentsPage: FC<SegmentsPageType> = (props) => {
q: search,
})
const [removeSegment, { isLoading: isRemoving }] = useDeleteSegmentMutation()
const hasHadResults = useRef(false)

const segmentsLimitAlert = Utils.calculateRemainingLimitsPercentage(
ProjectStore.getTotalSegments(),
Expand Down Expand Up @@ -155,11 +138,6 @@ const SegmentsPage: FC<SegmentsPageType> = (props) => {
</Tooltip>
)
}

if (data?.results.length) {
hasHadResults.current = true
}

const segments = data?.results
return (
<div
Expand All @@ -169,26 +147,23 @@ const SegmentsPage: FC<SegmentsPageType> = (props) => {
>
<PageTitle
cta={
segments && (segments.length || searchInput) ? (
<>
{renderWithPermission(
manageSegmentsPermission,
'Manage segments',
<Button
disabled={
hasNoOperators ||
!manageSegmentsPermission ||
segmentsLimitAlert.percentage >= 100
}
id='show-create-segment-btn'
data-test='show-create-segment-btn'
onClick={newSegment}
>
Create Segment
</Button>,
)}
</>
) : null
<>
{renderWithPermission(
manageSegmentsPermission,
'Manage segments',
<Button
disabled={
!manageSegmentsPermission ||
segmentsLimitAlert.percentage >= 100
}
id='show-create-segment-btn'
data-test='show-create-segment-btn'
onClick={newSegment}
>
Create Segment
</Button>,
)}
</>
}
title={'Segments'}
>
Expand All @@ -212,164 +187,135 @@ const SegmentsPage: FC<SegmentsPageType> = (props) => {
</Button>
</PageTitle>
<div className='segments-page'>
{isLoading && !hasHadResults.current && !segments && !searchInput && (
{isLoading && !segments && !searchInput && (
<div className='centered-container'>
<Loader />
</div>
)}
{(!isLoading || segments || searchInput) && (
<div>
{Utils.displayLimitAlert('segments', segmentsLimitAlert.percentage)}
{hasHadResults.current ||
(segments && (segments.length || searchInput)) ? (
<div>
{hasNoOperators && <HowToUseSegmentsMessage />}

<FormGroup className={classNames({ 'opacity-50': isRemoving })}>
<PanelSearch
filterElement={
<div className='text-right me-2'>
<label className='me-2'>Include Feature-Specific</label>
<Switch onChange={setShowFeatureSpecific} />
</div>
<div>
<FormGroup className={classNames({ 'opacity-50': isRemoving })}>
<PanelSearch
filterElement={
<div className='text-right me-2'>
<label className='me-2'>Include Feature-Specific</label>
<Switch onChange={setShowFeatureSpecific} />
</div>
}
renderSearchWithNoResults
className='no-pad'
id='segment-list'
title=' '
renderFooter={() => (
<JSONReference
className='mx-2 mt-4'
title={'Segments'}
json={segments}
/>
)}
items={sortBy(segments, (v) => {
return `${v.feature ? 'a' : 'z'}${v.name}`
})}
renderRow={(
{ description, feature, id, name }: Segment,
i: number,
) => {
if (preselect.current === `${id}`) {
editSegment(preselect.current, !manageSegmentsPermission)
preselect.current = null
}
renderSearchWithNoResults
className='no-pad'
id='segment-list'
title='Segments'
renderFooter={() => (
<JSONReference
className='mx-2 mt-4'
title={'Segments'}
json={segments}
/>
)}
items={sortBy(segments, (v) => {
return `${v.feature ? 'a' : 'z'}${v.name}`
})}
renderRow={(
{ description, feature, id, name }: Segment,
i: number,
) => {
if (preselect.current === `${id}`) {
editSegment(
preselect.current,
!manageSegmentsPermission,
)
preselect.current = null
}

// TODO: remove this check
// I'm leaving this here for now so that we can deploy the FE and
// API independently, but we should remove this once PR #3430 is
// merged and released.
if (feature && !showFeatureSpecific) {
return null
}
// TODO: remove this check
// I'm leaving this here for now so that we can deploy the FE and
// API independently, but we should remove this once PR #3430 is
// merged and released.
if (feature && !showFeatureSpecific) {
return null
}

return renderWithPermission(
manageSegmentsPermission,
'Manage segments',
<Row className='list-item clickable' key={id} space>
<Flex
className='table-column px-3'
onClick={
manageSegmentsPermission
? () =>
editSegment(id, !manageSegmentsPermission)
: undefined
}
return renderWithPermission(
manageSegmentsPermission,
'Manage segments',
<Row className='list-item clickable' key={id} space>
<Flex
className='table-column px-3'
onClick={
manageSegmentsPermission
? () => editSegment(id, !manageSegmentsPermission)
: undefined
}
>
<Row
data-test={`segment-${i}-name`}
className='font-weight-medium'
>
<Row
data-test={`segment-${i}-name`}
className='font-weight-medium'
>
{name}
{feature && (
<div className='chip chip--xs ml-2'>
Feature-Specific
</div>
)}
</Row>
<div className='list-item-subtitle mt-1'>
{description || 'No description'}
</div>
</Flex>
<div className='table-column'>
<Button
disabled={!manageSegmentsPermission}
data-test={`remove-segment-btn-${i}`}
onClick={() => {
const segment = find(segments, { id })
if (segment) {
confirmRemove(segment, () => {
removeSegment({ id, projectId }).then(
(res) => {
toast(
<div>
Removed Segment:{' '}
<strong>{segment.name}</strong>
</div>,
)
},
)
})
}
}}
className='btn btn-with-icon'
>
<Icon name='trash-2' width={20} fill='#656D7B' />
</Button>
{name}
{feature && (
<div className='chip chip--xs ml-2'>
Feature-Specific
</div>
)}
</Row>
<div className='list-item-subtitle mt-1'>
{description || 'No description'}
</div>
</Row>,
)
}}
paging={data}
nextPage={() => setPage(page + 1)}
prevPage={() => setPage(page - 1)}
goToPage={(page: number) => setPage(page)}
search={searchInput}
onChange={(e: any) => {
setSearchInput(Utils.safeParseEventValue(e))
}}
renderNoResults={<div className='text-center' />}
filterRow={() => true}
/>
</FormGroup>
</Flex>
<div className='table-column'>
<Button
disabled={!manageSegmentsPermission}
data-test={`remove-segment-btn-${i}`}
onClick={() => {
const segment = find(segments, { id })
if (segment) {
confirmRemove(segment, () => {
removeSegment({ id, projectId }).then(
(res) => {
toast(
<div>
Removed Segment:{' '}
<strong>{segment.name}</strong>
</div>,
)
},
)
})
}
}}
className='btn btn-with-icon'
>
<Icon name='trash-2' width={20} fill='#656D7B' />
</Button>
</div>
</Row>,
)
}}
paging={data}
nextPage={() => setPage(page + 1)}
prevPage={() => setPage(page - 1)}
goToPage={(page: number) => setPage(page)}
search={searchInput}
onChange={(e: any) => {
setSearchInput(Utils.safeParseEventValue(e))
}}
filterRow={() => true}
/>
</FormGroup>

<p>
Segments require you to identitfy users, setting traits will
add users to segments.
</p>
<FormGroup className='mt-4'>
<CodeHelp
title='Using segments'
snippets={Constants.codeHelp.USER_TRAITS(
environmentId || 'ENVIRONMENT_KEY',
)}
/>
</FormGroup>
</div>
) : (
<div>
<FormGroup className='text-center'>
{renderWithPermission(
manageSegmentsPermission,
'Manage segments',
<Button
disabled={!manageSegmentsPermission || hasNoOperators}
className='btn-lg btn-primary'
id='show-create-segment-btn'
data-test='show-create-segment-btn'
onClick={newSegment}
>
Create your first Segment
</Button>,
<InfoMessage>
Segments require you to identitfy users, setting traits will add
users to segments.
</InfoMessage>
<FormGroup className='mt-4'>
<CodeHelp
title='Using segments'
snippets={Constants.codeHelp.USER_TRAITS(
environmentId || 'ENVIRONMENT_KEY',
)}
</FormGroup>
{hasNoOperators && <HowToUseSegmentsMessage />}
</div>
)}
/>
</FormGroup>
</div>
</div>
)}
<FormGroup>
Expand Down

0 comments on commit cd121e8

Please sign in to comment.