Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
94 changes: 94 additions & 0 deletions frontend/web/components/modals/CreateDuplicateSegmentModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React, { FC, FormEvent, useState } from 'react'
import { Segment, SegmentRule } from 'common/types/responses'
import ProjectProvider from 'common/providers/ProjectProvider'
import InputGroup from 'components/base/forms/InputGroup'
import Utils from 'common/utils/utils'
import Button from 'components/base/forms/Button'
import ModalHR from './ModalHR'

type CreateDuplicateSegmentType = {
segment: Segment
cb: (segment: Omit<Segment, 'id' | 'uuid'>) => void
}

const CreateDuplicateSegmentModal: FC<CreateDuplicateSegmentType> = ({
cb,
segment,
}) => {
const [challenge, setChallenge] = useState()

function removeIds(rules: SegmentRule[]): SegmentRule[] {
return rules.map(rule => ({
conditions: rule.conditions.map(({ delete: del, description, operator, property, value }) => ({
delete: del,
description,
operator,
property,
value,
})),
delete: rule.delete,
rules: removeIds(rule.rules),
type: rule.type,
}));
}

const submit = (e: FormEvent) => {
e.preventDefault()
if (challenge) {
const newSegment: Omit<Segment, 'id' | 'uuid'> = {
description: segment.description,
metadata: segment.metadata,
name: challenge,
project: segment.project,
rules: removeIds(segment.rules),
...(segment.feature && { feature: segment.feature }),
}
closeModal()
console.log(newSegment)
cb(newSegment)
}
}

return (
<ProjectProvider>
{() => (
<form id='confirm-duplicate-segment-modal' onSubmit={submit}>
<div className='modal-body'>
<p>
This will create a copy of <strong>{segment.name}</strong>, including all its rules and configuration.
You can modify the duplicate without affecting the original segment.
</p>
<InputGroup
className='mb-0'
inputProps={{
className: 'full-width',
name: 'new-segment-name',
}}
title='Please enter a name for the new segment'
placeholder='new_segment_name'
onChange={(e: InputEvent) => {
setChallenge(Utils.safeParseEventValue(e))
}}
/>
</div>
<ModalHR />
<div className='modal-footer'>
<Button className='mr-2' onClick={closeModal} theme='secondary'>
Cancel
</Button>
<Button
id='confirm-duplicate-segment-btn'
disabled={!challenge}
type='submit'
>
Duplicate
</Button>
</div>
</form>

)}
</ProjectProvider>
)
}

export default CreateDuplicateSegmentModal
46 changes: 45 additions & 1 deletion frontend/web/components/pages/SegmentsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Constants from 'common/constants'
import useSearchThrottle from 'common/useSearchThrottle'
import { Environment, Segment } from 'common/types/responses'
import {
useCreateSegmentMutation,
useDeleteSegmentMutation,
useGetSegmentsQuery,
} from 'common/services/useSegment'
Expand All @@ -14,6 +15,7 @@ import API from 'project/api'
import Button from 'components/base/forms/Button'
import ConfirmRemoveSegment from 'components/modals/ConfirmRemoveSegment'
import CreateSegmentModal from 'components/modals/CreateSegment'
import CreateDuplicateSegmentModal from 'components/modals/CreateDuplicateSegmentModal'
import PanelSearch from 'components/PanelSearch'
import JSONReference from 'components/JSONReference'
import ConfigProvider from 'common/providers/ConfigProvider'
Expand All @@ -28,6 +30,7 @@ import InfoMessage from 'components/InfoMessage'
import { withRouter } from 'react-router-dom'

import CodeHelp from 'components/CodeHelp'

type SegmentsPageType = {
router: RouterChildContext['router']
match: {
Expand Down Expand Up @@ -67,6 +70,8 @@ const SegmentsPage: FC<SegmentsPageType> = (props) => {
})
const [removeSegment, { isLoading: isRemoving }] = useDeleteSegmentMutation()

const [createSegment, { isLoading: isCreating }] = useCreateSegmentMutation()

const segmentsLimitAlert = Utils.calculateRemainingLimitsPercentage(
ProjectStore.getTotalSegments(),
ProjectStore.getMaxSegmentsAllowed(),
Expand Down Expand Up @@ -114,6 +119,14 @@ const SegmentsPage: FC<SegmentsPageType> = (props) => {
)
}

const duplicateSegment = (segment: Segment, cb: (newSegment: Omit<Segment, "id" | "uuid">) => void) => {
openModal(
'Duplicate Segment',
<CreateDuplicateSegmentModal segment={segment} cb={cb} />,
'p-0',
)
}

const { permission: manageSegmentsPermission } = useHasPermission({
id: projectId,
level: 'project',
Expand Down Expand Up @@ -222,7 +235,7 @@ const SegmentsPage: FC<SegmentsPageType> = (props) => {
<div>
{Utils.displayLimitAlert('segments', segmentsLimitAlert.percentage)}
<div>
<FormGroup className={classNames({ 'opacity-50': isRemoving })}>
<FormGroup className={classNames({ 'opacity-50': isRemoving || isCreating })}>
<PanelSearch
filterElement={
<div className='text-right me-2'>
Expand Down Expand Up @@ -284,6 +297,37 @@ const SegmentsPage: FC<SegmentsPageType> = (props) => {
</div>
</Flex>
<div className='table-column'>
<Button
disabled={!manageSegmentsPermission}
data-test={`new-button-${i}`}
onClick={() => {
const segment = find(segments, { id })
if (segment) {
duplicateSegment(segment, (newSegment) => {
createSegment({ projectId, segment: newSegment })
.then((res) => {
toast(
<div>
Duplicated Segment:{' '}
<strong>{segment.name}</strong>
</div>,
)
})
.catch((error) => {
toast(
<div>
Failed to duplicate segment:{' '}
<strong>{segment.name}</strong>
</div>,
)
})
})
}
}}
className='btn btn-with-icon me-2'
>
<Icon name='copy' width={20} fill='#656D7B' />
</Button>
<Button
disabled={!manageSegmentsPermission}
data-test={`remove-segment-btn-${i}`}
Expand Down