@@ -26,6 +26,7 @@ import {
2626 useGetSegmentsQuery ,
2727 useUpdateSegmentMutation ,
2828} from 'common/services/useSegment'
29+ import { useUpdateCohortMutation } from 'common/services/useCohort'
2930import Utils from 'common/utils/utils'
3031import AssociatedSegmentOverrides from 'components/segments/AssociatedSegmentOverrides'
3132import CohortSegmentDetail from 'components/segments/CohortSegmentDetail'
@@ -146,6 +147,8 @@ const CreateSegment: FC<CreateSegmentType> = ({
146147 const [ segment , setSegment ] = useState ( _segment || defaultSegment )
147148 // A cohort owns its segment's rules, and the API rejects updating one.
148149 const isCohortManaged = ! ! _segment ?. cohort
150+ // CSV cohorts swap the rules form for the synchronisation detail view.
151+ const isCsvCohort = _segment ?. cohort ?. source_type === 'csv'
149152 const isReadOnly = readOnly || isCohortManaged
150153 const readOnlyMessage = isCohortManaged
151154 ? 'This segment is managed by a cohort. Its rules follow the cohort membership and cannot be edited.'
@@ -193,6 +196,8 @@ const CreateSegment: FC<CreateSegmentType> = ({
193196 } ,
194197 ] = useUpdateSegmentMutation ( )
195198 const [ createChangeRequest ] = useCreateProjectChangeRequestMutation ( { } )
199+ const [ updateCohort , { isLoading : isSavingCohortMetadata } ] =
200+ useUpdateCohortMutation ( )
196201 const isSaving = creating || updating
197202 const [ showDescriptions , setShowDescriptions ] = useState ( false )
198203 const [ tab , setTab ] = useState ( UserTabs . RULES )
@@ -300,6 +305,27 @@ const CreateSegment: FC<CreateSegmentType> = ({
300305
301306 const [ valueChanged , setValueChanged ] = useState ( false )
302307 const [ metadataValueChanged , setMetadataValueChanged ] = useState ( false )
308+
309+ // A managed segment rejects direct updates; its metadata is saved through
310+ // the cohort instead.
311+ const saveCohortMetadata = async ( ) => {
312+ if ( ! _segment ?. cohort ) {
313+ return
314+ }
315+ try {
316+ await updateCohort ( {
317+ cohortId : _segment . cohort . id ,
318+ environmentApiKey : _segment . cohort . environment_api_key ,
319+ metadata,
320+ projectId : Number ( projectId ) ,
321+ segmentId : _segment . id ,
322+ } ) . unwrap ( )
323+ setMetadataValueChanged ( false )
324+ toast ( 'Updated segment' )
325+ } catch ( error : any ) {
326+ toast ( error ?. data ?. metadata ?. [ 0 ] || 'Error updating segment' , 'danger' )
327+ }
328+ }
303329 const onClosing = useCallback ( ( ) => {
304330 return new Promise < boolean > ( ( resolve ) => {
305331 if ( valueChanged ) {
@@ -549,6 +575,16 @@ const CreateSegment: FC<CreateSegmentType> = ({
549575 />
550576 }
551577 />
578+ { isCsvCohort && metadataValueChanged && ! readOnly && (
579+ < div className = 'text-right' >
580+ < Button
581+ disabled = { isSavingCohortMetadata }
582+ onClick = { saveCohortMetadata }
583+ >
584+ { isSavingCohortMetadata ? 'Saving...' : 'Save Changes' }
585+ </ Button >
586+ </ div >
587+ ) }
552588 </ FormGroup >
553589 )
554590
@@ -570,33 +606,42 @@ const CreateSegment: FC<CreateSegmentType> = ({
570606 >
571607 < TabItem tabLabel = 'General' isDirty = { valueChanged } >
572608 < div className = 'my-4' >
573- < CreateSegmentRulesTabForm
574- is4Eyes = { is4Eyes }
575- onCreateChangeRequest = { onCreateChangeRequest }
576- save = { save }
577- condensed = { condensed }
578- segmentsLimitAlert = { segmentsLimitAlert }
579- name = { name }
580- setName = { setName }
581- setValueChanged = { setValueChanged }
582- description = { description }
583- setDescription = { setDescription }
584- identity = { identity }
585- readOnly = { isReadOnly }
586- readOnlyMessage = { readOnlyMessage }
587- showDescriptions = { showDescriptions }
588- setShowDescriptions = { setShowDescriptions }
589- allWarnings = { allWarnings }
590- rulesEl = { rulesEl }
591- isEdit = { isEdit }
592- segment = { segment }
593- isSaving = { isSaving }
594- isValid = { isValid }
595- isLimitReached = { isLimitReached }
596- onCancel = { handleCancel }
597- topLevelRuleType = { topLevelRuleType }
598- setTopLevelRuleType = { setTopLevelRuleType }
599- />
609+ { isCsvCohort && _segment ? (
610+ < CohortSegmentDetail
611+ hideHeader
612+ projectId = { projectId }
613+ segment = { _segment }
614+ readOnly = { readOnly }
615+ />
616+ ) : (
617+ < CreateSegmentRulesTabForm
618+ is4Eyes = { is4Eyes }
619+ onCreateChangeRequest = { onCreateChangeRequest }
620+ save = { save }
621+ condensed = { condensed }
622+ segmentsLimitAlert = { segmentsLimitAlert }
623+ name = { name }
624+ setName = { setName }
625+ setValueChanged = { setValueChanged }
626+ description = { description }
627+ setDescription = { setDescription }
628+ identity = { identity }
629+ readOnly = { isReadOnly }
630+ readOnlyMessage = { readOnlyMessage }
631+ showDescriptions = { showDescriptions }
632+ setShowDescriptions = { setShowDescriptions }
633+ allWarnings = { allWarnings }
634+ rulesEl = { rulesEl }
635+ isEdit = { isEdit }
636+ segment = { segment }
637+ isSaving = { isSaving }
638+ isValid = { isValid }
639+ isLimitReached = { isLimitReached }
640+ onCancel = { handleCancel }
641+ topLevelRuleType = { topLevelRuleType }
642+ setTopLevelRuleType = { setTopLevelRuleType }
643+ />
644+ ) }
600645 </ div >
601646 </ TabItem >
602647 < TabItem tabLabel = { segment . feature ? 'Feature' : 'Features' } >
@@ -651,10 +696,65 @@ const CreateSegment: FC<CreateSegmentType> = ({
651696 >
652697 { /* Horizontal padding comes from the surrounding tab-item. */ }
653698 < div className = { className || 'my-3' } >
699+ { isCsvCohort && _segment ? (
700+ < CohortSegmentDetail
701+ projectId = { projectId }
702+ segment = { _segment }
703+ readOnly = { readOnly }
704+ />
705+ ) : (
706+ < CreateSegmentRulesTabForm
707+ save = { save }
708+ is4Eyes = { is4Eyes }
709+ onCreateChangeRequest = { onCreateChangeRequest }
710+ condensed = { condensed }
711+ segmentsLimitAlert = { segmentsLimitAlert }
712+ name = { name }
713+ setName = { setName }
714+ setValueChanged = { setValueChanged }
715+ description = { description }
716+ setDescription = { setDescription }
717+ identity = { identity }
718+ readOnly = { isReadOnly }
719+ readOnlyMessage = { readOnlyMessage }
720+ showDescriptions = { showDescriptions }
721+ setShowDescriptions = { setShowDescriptions }
722+ allWarnings = { allWarnings }
723+ rulesEl = { rulesEl }
724+ isEdit = { isEdit }
725+ segment = { segment }
726+ isSaving = { isSaving }
727+ isValid = { isValid }
728+ isLimitReached = { isLimitReached }
729+ onCancel = { handleCancel }
730+ topLevelRuleType = { topLevelRuleType }
731+ setTopLevelRuleType = { setTopLevelRuleType }
732+ />
733+ ) }
734+ </ div >
735+ </ TabItem >
736+ < TabItem
737+ tabLabelString = 'Custom Fields'
738+ tabLabel = {
739+ < Row className = 'justify-content-center' > Custom Fields</ Row >
740+ }
741+ >
742+ < div className = { className || 'my-3' } > { MetadataTab } </ div >
743+ </ TabItem >
744+ </ Tabs >
745+ ) }
746+ { ! ( isEdit && ! condensed ) &&
747+ ! ( metadataEnable && segmentContentType ?. id ) && (
748+ < div className = { className || 'my-3 mx-4' } >
749+ { isCsvCohort && _segment ? (
750+ < CohortSegmentDetail
751+ projectId = { projectId }
752+ segment = { _segment }
753+ readOnly = { readOnly }
754+ />
755+ ) : (
654756 < CreateSegmentRulesTabForm
655757 save = { save }
656- is4Eyes = { is4Eyes }
657- onCreateChangeRequest = { onCreateChangeRequest }
658758 condensed = { condensed }
659759 segmentsLimitAlert = { segmentsLimitAlert }
660760 name = { name }
@@ -678,46 +778,7 @@ const CreateSegment: FC<CreateSegmentType> = ({
678778 topLevelRuleType = { topLevelRuleType }
679779 setTopLevelRuleType = { setTopLevelRuleType }
680780 />
681- </ div >
682- </ TabItem >
683- < TabItem
684- tabLabelString = 'Custom Fields'
685- tabLabel = {
686- < Row className = 'justify-content-center' > Custom Fields</ Row >
687- }
688- >
689- < div className = { className || 'my-3' } > { MetadataTab } </ div >
690- </ TabItem >
691- </ Tabs >
692- ) }
693- { ! ( isEdit && ! condensed ) &&
694- ! ( metadataEnable && segmentContentType ?. id ) && (
695- < div className = { className || 'my-3 mx-4' } >
696- < CreateSegmentRulesTabForm
697- save = { save }
698- condensed = { condensed }
699- segmentsLimitAlert = { segmentsLimitAlert }
700- name = { name }
701- setName = { setName }
702- setValueChanged = { setValueChanged }
703- description = { description }
704- setDescription = { setDescription }
705- identity = { identity }
706- readOnly = { isReadOnly }
707- readOnlyMessage = { readOnlyMessage }
708- showDescriptions = { showDescriptions }
709- setShowDescriptions = { setShowDescriptions }
710- allWarnings = { allWarnings }
711- rulesEl = { rulesEl }
712- isEdit = { isEdit }
713- segment = { segment }
714- isSaving = { isSaving }
715- isValid = { isValid }
716- isLimitReached = { isLimitReached }
717- onCancel = { handleCancel }
718- topLevelRuleType = { topLevelRuleType }
719- setTopLevelRuleType = { setTopLevelRuleType }
720- />
781+ ) }
721782 </ div >
722783 ) }
723784 </ >
@@ -802,17 +863,6 @@ const LoadingCreateSegment: FC<LoadingCreateSegmentType> = (props) => {
802863 )
803864 }
804865
805- // CSV cohort segments have no editable rules; show the sync detail view.
806- if ( segmentData ?. cohort ?. source_type === 'csv' ) {
807- return (
808- < CohortSegmentDetail
809- projectId = { props . projectId }
810- segment = { segmentData }
811- readOnly = { props . readOnly }
812- />
813- )
814- }
815-
816866 return (
817867 < CreateSegment
818868 { ...props }
0 commit comments