-
-
-
- Segment Overrides{' '}
-
-
- }
- place='top'
+ (
+ <>
+
+ Segment Overrides{' '}
+
+
- {
- Constants.strings
- .SEGMENT_OVERRIDES_DESCRIPTION
- }
-
-
-
- {({
- permission:
- manageSegmentOverrides,
- }) =>
- !this.state
- .showCreateSegment &&
- !!manageSegmentOverrides &&
- !this.props.disableCreate && (
-
-
-
- )
- }
-
- {!this.state.showCreateSegment &&
- !noPermissions && (
-
- )}
-
- {this.props.segmentOverrides ? (
-
- {({
- permission:
- manageSegmentOverrides,
- }) => {
- const isReadOnly =
- !manageSegmentOverrides
- return (
- <>
-
-
-
- this.setState({
- showCreateSegment,
- })
- }
- readOnly={isReadOnly}
- is4Eyes={is4Eyes}
- showEditSegment
- showCreateSegment={
- this.state
- .showCreateSegment
- }
- feature={projectFlag.id}
- projectId={
- this.props.projectId
- }
- multivariateOptions={
- multivariate_options
- }
- environmentId={
- this.props
- .environmentId
- }
- value={
- this.props
- .segmentOverrides
- }
- controlValue={
- initial_value
- }
- onChange={(v) => {
- this.setState({
- segmentsChanged: true,
- })
- this.props.updateSegments(
- v,
- )
- }}
- />
- >
- )
- }}
-
- ) : (
-
-
-
- )}
- {!this.state.showCreateSegment && (
-
- )}
- {!this.state.showCreateSegment && (
-
-
- {is4Eyes && isVersioned
- ? `This will create a change request ${
- isVersioned
- ? 'with any value and segment override changes '
- : ''
- }for the environment`
- : 'This will update the segment overrides for the environment'}{' '}
-
+ This feature is in{' '}
+
{
- _.find(
- project.environments,
- {
- api_key:
- this.props
- .environmentId,
- },
- ).name
+ matchingReleasePipeline?.name
}
-
-
-
-
{' '}
+ release pipeline and no
+ segment overrides can be
+ created
+
+ >
+ )}
+ >
+
+
+
+
+ Segment Overrides{' '}
+
+
}
+ place='top'
>
- {({
- permission:
- savePermission,
- }) => (
-
+
+
+ {({
+ permission:
+ manageSegmentOverrides,
+ }) =>
+ !this.state
+ .showCreateSegment &&
+ !!manageSegmentOverrides &&
+ !this.props
+ .disableCreate && (
+
+
+
+ )
+ }
+
+ {!this.state
+ .showCreateSegment &&
+ !noPermissions && (
+
+ )}
+
+ {this.props.segmentOverrides ? (
+
+ {({
+ permission:
+ manageSegmentOverrides,
+ }) => {
+ const isReadOnly =
+ !manageSegmentOverrides
+ return (
+ <>
+
+
+
+ this.setState({
+ showCreateSegment,
+ })
+ }
+ readOnly={isReadOnly}
+ is4Eyes={is4Eyes}
+ showEditSegment
+ showCreateSegment={
+ this.state
+ .showCreateSegment
+ }
+ feature={
+ projectFlag.id
+ }
+ projectId={
+ this.props.projectId
+ }
+ multivariateOptions={
+ multivariate_options
+ }
+ environmentId={
+ this.props
+ .environmentId
+ }
+ value={
+ this.props
+ .segmentOverrides
+ }
+ controlValue={
+ initial_value
+ }
+ onChange={(v) => {
+ this.setState({
+ segmentsChanged: true,
+ })
+ this.props.updateSegments(
+ v,
)
+ }}
+ />
+ >
+ )
+ }}
+
+ ) : (
+
+
+
+ )}
+ {!this.state
+ .showCreateSegment && (
+
+ )}
+ {!this.state
+ .showCreateSegment && (
+
+
+ {is4Eyes && isVersioned
+ ? `This will create a change request ${
+ isVersioned
+ ? 'with any value and segment override changes '
+ : ''
+ }for the environment`
+ : 'This will update the segment overrides for the environment'}{' '}
+
+ {
+ _.find(
+ project.environments,
+ {
+ api_key:
+ this.props
+ .environmentId,
+ },
+ ).name
+ }
+
+
+
+
+ {({
+ permission:
+ savePermission,
+ }) => (
+
+ {({
+ permission:
+ manageSegmentsOverrides,
+ }) => {
+ if (
+ isVersioned &&
+ is4Eyes
+ ) {
+ return Utils.renderWithPermission(
+ savePermission,
+ Utils.getManageFeaturePermissionDescription(
+ is4Eyes,
+ identity,
+ ),
+
+ saveFeatureSegments(
+ false,
+ )
+ }
+ type='button'
+ data-test='update-feature-segments-btn'
+ id='update-feature-segments-btn'
+ disabled={
+ isSaving ||
+ !name ||
+ invalid ||
+ !savePermission
+ }
+ >
+ {isSaving
+ ? existingChangeRequest
+ ? 'Updating Change Request'
+ : 'Creating Change Request'
+ : existingChangeRequest
+ ? 'Update Change Request'
+ : 'Create Change Request'}
+ ,
+ )
+ }
- return Utils.renderWithPermission(
- manageSegmentsOverrides,
- Constants.environmentPermissions(
- 'Manage segment overrides',
- ),
- <>
- {!is4Eyes &&
- isVersioned && (
- <>
-
- saveFeatureSegments(
- true,
- )
- }
- className='mr-2'
- type='button'
- data-test='create-change-request'
- id='create-change-request-btn'
- disabled={
- isSaving ||
- !name ||
- invalid ||
- !savePermission
- }
- >
- {isSaving
- ? existingChangeRequest
- ? 'Updating Change Request'
- : 'Scheduling Update'
- : existingChangeRequest
- ? 'Update Change Request'
- : 'Schedule Update'}
-
- >
- )}
-
- saveFeatureSegments(
- false,
- )
- }
- type='button'
- data-test='update-feature-segments-btn'
- id='update-feature-segments-btn'
- disabled={
- isSaving ||
- !name ||
- invalid ||
- !manageSegmentsOverrides
- }
- >
- {isSaving
- ? 'Updating'
- : 'Update Segment Overrides'}
-
- >,
- )
- }}
-
- )}
-
+ return Utils.renderWithPermission(
+ manageSegmentsOverrides,
+ Constants.environmentPermissions(
+ 'Manage segment overrides',
+ ),
+ <>
+ {!is4Eyes &&
+ isVersioned && (
+ <>
+
+ saveFeatureSegments(
+ true,
+ )
+ }
+ className='mr-2'
+ type='button'
+ data-test='create-change-request'
+ id='create-change-request-btn'
+ disabled={
+ isSaving ||
+ !name ||
+ invalid ||
+ !savePermission
+ }
+ >
+ {isSaving
+ ? existingChangeRequest
+ ? 'Updating Change Request'
+ : 'Scheduling Update'
+ : existingChangeRequest
+ ? 'Update Change Request'
+ : 'Schedule Update'}
+
+ >
+ )}
+
+ saveFeatureSegments(
+ false,
+ )
+ }
+ type='button'
+ data-test='update-feature-segments-btn'
+ id='update-feature-segments-btn'
+ disabled={
+ isSaving ||
+ !name ||
+ invalid ||
+ !manageSegmentsOverrides
+ }
+ >
+ {isSaving
+ ? 'Updating'
+ : 'Update Segment Overrides'}
+
+ >,
+ )
+ }}
+
+ )}
+
+
-
- )}
-
+ )}
+
+
)}
diff --git a/frontend/web/components/release-pipelines/FeatureInPipelineGuard.tsx b/frontend/web/components/release-pipelines/FeatureInPipelineGuard.tsx
new file mode 100644
index 000000000000..57959ea196ad
--- /dev/null
+++ b/frontend/web/components/release-pipelines/FeatureInPipelineGuard.tsx
@@ -0,0 +1,48 @@
+import React, { useMemo } from 'react'
+import { useGetReleasePipelinesQuery } from 'common/services/useReleasePipelines'
+import { ReleasePipeline } from 'common/types/responses'
+
+interface FeatureInPipelineGuardProps {
+ projectId: number
+ featureId: number
+ children: React.ReactNode
+ renderFallback: (matchingReleasePipeline: ReleasePipeline) => React.ReactNode
+ skip?: boolean
+}
+
+const FeatureInPipelineGuard: React.FC
= ({
+ children,
+ featureId,
+ projectId,
+ renderFallback,
+ skip = false,
+}) => {
+ const { data: releasePipelines } = useGetReleasePipelinesQuery(
+ {
+ projectId,
+ },
+ {
+ skip: skip || !projectId || !featureId,
+ },
+ )
+
+ const matchingReleasePipeline = useMemo(() => {
+ if (!featureId || !releasePipelines?.results) {
+ return undefined
+ }
+
+ return releasePipelines.results.find((pipeline) =>
+ pipeline.features?.includes(featureId),
+ )
+ }, [releasePipelines, featureId])
+
+ const isFeatureInReleasePipeline = !!matchingReleasePipeline?.id
+
+ if (!isFeatureInReleasePipeline) {
+ return <>{children}>
+ }
+
+ return <>{renderFallback(matchingReleasePipeline)}>
+}
+
+export default FeatureInPipelineGuard