diff --git a/cypress/e2e/cohorts.cy.ts b/cypress/e2e/cohorts.cy.ts
index 29bdcae4d4c47..267b579e79021 100644
--- a/cypress/e2e/cohorts.cy.ts
+++ b/cypress/e2e/cohorts.cy.ts
@@ -52,5 +52,24 @@ describe('Cohorts', () => {
cy.url().should('include', '/cohorts/')
cy.get('[data-attr="cohort-name"]').should('have.value', 'Test Cohort')
})
+
+ // back into cohort
+ cy.get('tbody').contains('Test Cohort').click()
+
+ // duplicate cohort (dynamic)
+ cy.get('[data-attr="more-button"]').click()
+ cy.get('.Popover__content').contains('Duplicate as dynamic cohort').click()
+ cy.get('.Toastify__toast-body').contains('View cohort').click()
+
+ // duplicate cohort (static)
+ cy.get('[data-attr="more-button"]').click()
+ cy.get('.Popover__content').contains('Duplicate as static cohort').click()
+ cy.get('.Toastify__toast-body').contains('View cohort').click()
+
+ // delete cohort
+ cy.get('[data-attr="more-button"]').click()
+ cy.get('.Popover__content').contains('Delete cohort').click()
+ cy.clickNavMenu('cohorts')
+ cy.get('tbody').should('not.have.text', 'Test Cohort (dynamic copy) (static copy)')
})
})
diff --git a/frontend/src/scenes/cohorts/CohortEdit.tsx b/frontend/src/scenes/cohorts/CohortEdit.tsx
index 9fafa06e5f105..878104df2349d 100644
--- a/frontend/src/scenes/cohorts/CohortEdit.tsx
+++ b/frontend/src/scenes/cohorts/CohortEdit.tsx
@@ -26,12 +26,13 @@ import { Query } from '~/queries/Query/Query'
import { pluralize } from 'lib/utils'
import { LemonDivider } from '@posthog/lemon-ui'
import { AndOrFilterSelect } from '~/queries/nodes/InsightViz/PropertyGroupFilters/AndOrFilterSelect'
+import { More } from 'lib/lemon-ui/LemonButton/More'
export function CohortEdit({ id }: CohortLogicProps): JSX.Element {
const logicProps = { id }
const logic = cohortEditLogic(logicProps)
- const { deleteCohort, setOuterGroupsType, setQuery, duplicateToStaticCohort } = useActions(logic)
- const { cohort, cohortLoading, cohortMissing, query, duplicatedStaticCohortLoading } = useValues(logic)
+ const { deleteCohort, setOuterGroupsType, setQuery, duplicateCohort } = useActions(logic)
+ const { cohort, cohortLoading, cohortMissing, query, duplicatedCohortLoading } = useValues(logic)
const { hasAvailableFeature } = useValues(userLogic)
const isNewCohort = cohort.id === 'new' || cohort.id === undefined
@@ -57,33 +58,53 @@ export function CohortEdit({ id }: CohortLogicProps): JSX.Element {
Cancel
) : (
- {
- deleteCohort()
- }}
- disabled={cohortLoading}
- >
- Delete
-
- )}
- {!isNewCohort && !cohort.is_static && (
- <>
-
-
- Duplicate as static cohort
-
- >
+
+ {!cohort.is_static && (
+ <>
+ duplicateCohort(false)}
+ fullWidth
+ disabledReason={
+ cohort.is_calculating
+ ? 'Cohort is still calculating'
+ : undefined
+ }
+ loading={duplicatedCohortLoading}
+ >
+ Duplicate as dynamic cohort
+
+ duplicateCohort(true)}
+ fullWidth
+ disabledReason={
+ cohort.is_calculating
+ ? 'Cohort is still calculating'
+ : undefined
+ }
+ loading={duplicatedCohortLoading}
+ >
+ Duplicate as static cohort
+
+
+ >
+ )}
+ {
+ deleteCohort()
+ }}
+ >
+ Delete cohort
+
+ >
+ }
+ />
)}
+
([
criteriaIndex,
}),
setQuery: (query: Node) => ({ query }),
- duplicateToStaticCohort: true,
+ duplicateCohort: (asStatic: boolean) => ({ asStatic }),
}),
reducers(({ props }) => ({
@@ -253,17 +253,24 @@ export const cohortEditLogic = kea([
},
},
],
- duplicatedStaticCohort: [
+ duplicatedCohort: [
null as CohortType | null,
{
- duplicateToStaticCohort: async (_, breakpoint) => {
+ duplicateCohort: async ({ asStatic }: { asStatic: boolean }, breakpoint) => {
+ let cohort: CohortType
try {
await breakpoint(200)
- const cohort = await api.cohorts.duplicate(values.cohort.id)
+ if (asStatic) {
+ cohort = await api.cohorts.duplicate(values.cohort.id)
+ } else {
+ const data = { ...values.cohort }
+ data.name += ' (dynamic copy)'
+ cohort = await api.cohorts.create(data)
+ }
lemonToast.success(
'Cohort duplicated. Please wait up to a few minutes for it to be calculated',
{
- toastId: `cohort-duplicated-${values.cohort.id}`,
+ toastId: `cohort-duplicated-${cohort.id}`,
button: {
label: 'View cohort',
action: () => {