Skip to content

Commit

Permalink
Release actions-ux-201012 (#2615)
Browse files Browse the repository at this point in the history
* remove legacy code & feature flag references

* ActionStepV2 refactor

* ActionEditV2 refactor

* fix backend tests

* fix more tests

* more fixes

* last fix

* address feedback
  • Loading branch information
paolodamico authored Dec 3, 2020
1 parent ce37a5b commit d6f3079
Show file tree
Hide file tree
Showing 14 changed files with 263 additions and 875 deletions.
8 changes: 4 additions & 4 deletions cypress/integration/funnels.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('Funnels', () => {
cy.get('[data-attr=trend-element-subject-0]').click()

// Double click: https://www.cypress.io/blog/2019/01/22/when-can-the-test-click/
cy.contains('Pageviews').click().click()
cy.contains('HogFlix homepage view').click().click()

cy.get('[data-attr=save-funnel-button]').click()

Expand All @@ -20,7 +20,7 @@ describe('Funnels', () => {
it('Apply date filter to funnel', () => {
cy.get('[data-attr=add-action-event-button]').click()
cy.get('[data-attr=trend-element-subject-0]').click()
cy.contains('Pageviews').click().click()
cy.contains('HogFlix homepage view').click().click()
cy.get('[data-attr=save-funnel-button]').click()

cy.get('[data-attr=date-filter]').click()
Expand All @@ -35,11 +35,11 @@ describe('Funnels', () => {
it('Add 2 actions to funnel', () => {
cy.get('[data-attr=add-action-event-button]').click()
cy.get('[data-attr=trend-element-subject-0]').click()
cy.contains('Pageviews').click().click()
cy.contains('HogFlix homepage view').click().click()

cy.get('[data-attr=add-action-event-button]').click()
cy.get('[data-attr=trend-element-subject-1]').click()
cy.contains('HogFlix homepage view').click().click()
cy.contains('HogFlix paid').click().click()

cy.get('[data-attr=save-funnel-button]').click()

Expand Down
6 changes: 3 additions & 3 deletions cypress/integration/trendsElements.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ describe('Trends actions & events', () => {

it('Add a pageview action filter', () => {
// when
cy.contains('Add action/event').click()
cy.contains('Add graph series').click()
cy.get('[data-attr=trend-element-subject-1]').click()
cy.contains('Pageviews').click()
cy.contains('HogFlix homepage view').click()

// then
cy.get('[data-attr=trend-line-graph]').should('exist')
Expand Down Expand Up @@ -118,7 +118,7 @@ describe('Trends actions & events', () => {

it('Save to dashboard', () => {
cy.get('[data-attr=save-to-dashboard-button]').click()
cy.get('.ant-input').type('Pageviews')
cy.get('.ant-input').type('Home page views')
cy.get('form > .ant-select > .ant-select-selector').click()
cy.get(':nth-child(1) > .ant-select-item-option-content').click()
cy.contains('Add panel to dashboard').click()
Expand Down
48 changes: 9 additions & 39 deletions frontend/src/models/actionsModel.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import { kea } from 'kea'
import api from 'lib/api'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'

const actionContains = (action, event) => {
return action.steps.filter((step) => step.event == event).length > 0
}

export const actionsModel = kea({
connect: {
values: [featureFlagLogic, ['featureFlags']],
},
loaders: ({ props }) => ({
actions: {
__default: [],
Expand All @@ -21,38 +13,16 @@ export const actionsModel = kea({
}),
selectors: ({ selectors }) => ({
actionsGrouped: [
() => [selectors.actions, selectors.featureFlags],
(actions, featureFlags) => {
if (featureFlags['actions-ux-201012']) {
// In this experiment we no longer group actions by type
return [
{
label: 'Select an action',
options: actions.map((action) => {
return { label: action.name, value: action.id }
}),
},
]
}

let data = [
{ label: 'Autocapture', options: [] },
{ label: 'Event', options: [] },
{ label: 'Pageview', options: [] },
() => [selectors.actions],
(actions) => {
return [
{
label: 'Select an action',
options: actions.map((action) => {
return { label: action.name, value: action.id }
}),
},
]
actions.forEach((action) => {
let format = { label: action.name, value: action.id }
if (actionContains(action, '$autocapture')) {
data[0].options.push(format)
}
if (actionContains(action, '$pageview')) {
data[2].options.push(format)
}
if (!actionContains(action, '$autocapture') && !actionContains(action, '$pageview')) {
data[1].options.push(format)
}
})
return data
},
],
}),
Expand Down
6 changes: 1 addition & 5 deletions frontend/src/scenes/actions/Action.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react'
import { ActionEdit } from './ActionEdit'
import { ActionEdit as ActionEditV2 } from './ActionEditV2'
import { useActions, useValues } from 'kea'
import { router } from 'kea-router'
import { userLogic } from 'scenes/userLogic'
Expand All @@ -9,7 +8,6 @@ import api from 'lib/api'
import { kea } from 'kea'
import { Spin } from 'antd'
import { hot } from 'react-hot-loader/root'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { PageHeader } from 'lib/components/PageHeader'
import { EventsTable } from 'scenes/events'

Expand Down Expand Up @@ -68,9 +66,7 @@ let actionLogic = kea({
})

function EditComponent(props) {
const { featureFlags } = useValues(featureFlagLogic)
const Component = featureFlags['actions-ux-201012'] ? ActionEditV2 : ActionEdit
return <Component {...props} />
return <ActionEdit {...props} />
}

export const Action = hot(_Action)
Expand Down
188 changes: 96 additions & 92 deletions frontend/src/scenes/actions/ActionEdit.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, { useState, Fragment } from 'react'
import React, { useState } from 'react'
import { uuid, Loading } from 'lib/utils'
import { Link } from 'lib/components/Link'
import { useValues, useActions } from 'kea'
import { actionEditLogic } from './actionEditLogic'
import './Actions.scss'
import { ActionStep } from './ActionStep'
import { Alert, Button, Card, Input } from 'antd'
import { SaveOutlined } from '@ant-design/icons'
import { Alert, Button, Col, Input, Row } from 'antd'
import { InfoCircleOutlined, PlusOutlined, SaveOutlined } from '@ant-design/icons'

// TODO: isEditor === false always
export function ActionEdit({ actionId, apiURL, onSave, user, isEditor, simmer, temporaryToken }) {
export function ActionEdit({ actionId, apiURL, onSave, user, simmer, temporaryToken }) {
let logic = actionEditLogic({
id: actionId,
apiURL,
Expand All @@ -25,85 +25,94 @@ export function ActionEdit({ actionId, apiURL, onSave, user, isEditor, simmer, t
return <Loading />
}

const newAction = () => {
setAction({ ...action, steps: [...action.steps, { isNew: uuid() }] })
}

const addGroup = (
<Button
onClick={() => {
setAction({ ...action, steps: [...action.steps, { isNew: uuid() }] })
}}
>
<Button onClick={newAction} size="small">
Add another match group
</Button>
)

return (
<Card style={{ marginTop: isEditor ? 8 : '' }}>
<div className="mt">
<div className="action-edit-container">
<form
onSubmit={(e) => {
e.preventDefault()
saveAction()
}}
>
<label>Action name:</label>
<Input
required
placeholder="For example: user signed up"
placeholder="e.g. user account created, purchase completed, movie watched"
value={action.name}
onChange={(e) => {
setAction({ ...action, name: e.target.value })
setEdited(e.target.value ? true : false)
}}
data-attr="edit-action-input"
/>
</div>

{action.count > -1 && (
<div>
<small className="text-muted">Matches {action.count} events</small>
</div>
)}

{!isEditor && <br />}
{action.count > -1 && (
<div>
<small className="text-muted">Matches {action.count} events</small>
</div>
)}

{action.steps.map((step, index) => (
<Fragment key={index}>
{index > 0 ? (
<div
style={{
textAlign: 'center',
fontSize: 13,
letterSpacing: 1,
opacity: 0.7,
margin: 8,
}}
>
OR
</div>
) : null}
<ActionStep
key={step.id || step.isNew}
step={step}
isEditor={isEditor}
actionId={action.id}
simmer={simmer}
isOnlyStep={action.steps.length === 1}
onDelete={() => {
setAction({ ...action, steps: action.steps.filter((s) => s.id != step.id) })
setEdited(true)
}}
onChange={(newStep) => {
setAction({
...action,
steps: action.steps.map((s) =>
(step.id && s.id == step.id) || (step.isNew && s.isNew === step.isNew)
? {
id: step.id,
isNew: step.isNew,
...newStep,
}
: s
),
})
setEdited(true)
}}
/>
</Fragment>
))}
<div className="match-group-section" style={{ overflow: 'visible' }}>
<h2 className="subtitle">Match groups</h2>
<div>
Your action will be triggered whenever <b>any of your match groups</b> are received.{' '}
<a href="https://posthog.com/docs/features/actions" target="_blank">
<InfoCircleOutlined />
</a>
</div>
<div style={{ textAlign: 'right', marginBottom: 12 }}>{addGroup}</div>

{!isEditor ? (
<Row gutter={[24, 24]}>
{action.steps.map((step, index) => (
<ActionStep
key={step.id || step.isNew}
identifier={step.id || step.isNew}
index={index}
step={step}
isEditor={false}
actionId={action.id}
simmer={simmer}
isOnlyStep={action.steps.length === 1}
onDelete={() => {
const identifier = step.id ? 'id' : 'isNew'
setAction({
...action,
steps: action.steps.filter((s) => s[identifier] !== step[identifier]),
})
setEdited(true)
}}
onChange={(newStep) => {
setAction({
...action,
steps: action.steps.map((s) =>
(step.id && s.id == step.id) || (step.isNew && s.isNew === step.isNew)
? {
id: step.id,
isNew: step.isNew,
...newStep,
}
: s
),
})
setEdited(true)
}}
/>
))}
<Col span={24} md={12}>
<div className="match-group-add-skeleton" onClick={newAction}>
<PlusOutlined style={{ fontSize: 28, color: '#666666' }} />
</div>
</Col>
</Row>
</div>
<div>
<div style={{ margin: '1rem 0' }}>
{user?.is_multi_tenancy && (
Expand Down Expand Up @@ -161,30 +170,25 @@ export function ActionEdit({ actionId, apiURL, onSave, user, isEditor, simmer, t
)}
</div>
</div>
) : (
<br />
)}

{errorActionId && (
<p className="text-danger">
Action with this name already exists.{' '}
<a href={apiURL + 'action/' + errorActionId}>Click here to edit.</a>
</p>
)}

<div>
{addGroup}
<Button
disabled={!edited}
data-attr="save-action-button"
className="float-right"
type="primary"
icon={<SaveOutlined />}
onClick={saveAction}
>
Save action
</Button>
</div>
</Card>
{errorActionId && (
<p className="text-danger">
Action with this name already exists.{' '}
<a href={apiURL + 'action/' + errorActionId}>Click here to edit.</a>
</p>
)}
<div>
<Button
disabled={!edited}
data-attr="save-action-button"
className="float-right"
type="primary"
icon={<SaveOutlined />}
onClick={saveAction}
>
Save action
</Button>
</div>
</form>
</div>
)
}
Loading

0 comments on commit d6f3079

Please sign in to comment.