Skip to content

Commit

Permalink
Merge branch 'master' into chore/js-lite-usage-reports
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto authored Nov 24, 2024
2 parents 1cc3dde + 96868a3 commit b29f04e
Show file tree
Hide file tree
Showing 37 changed files with 1,552 additions and 232 deletions.
23 changes: 22 additions & 1 deletion cypress/e2e/alerts.cy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { decideResponse } from '../fixtures/api/decide'
import { createInsight } from '../productAnalytics'
import { createInsight, createInsightWithBreakdown } from '../productAnalytics'

describe('Alerts', () => {
beforeEach(() => {
Expand Down Expand Up @@ -115,4 +115,25 @@ describe('Alerts', () => {
cy.reload()
cy.contains('Alert name').should('not.exist')
})

it('Should allow creating alerts on trends with breakdowns', () => {
createInsightWithBreakdown('insight with breakdown')
setInsightDisplayTypeAndSave('Bar chart')

createAlert('Alert name', '10', '20', 'increases by')
cy.reload()

// Check the alert has the same values as when it was created
cy.contains('Alerts').click()
cy.get('[data-attr=alert-list-item]').contains('Alert name').click()
cy.contains('any breakdown value').should('exist')
cy.get('[data-attr=alertForm-name]').should('have.value', 'Alert name')
cy.get('[data-attr=alertForm-lower-threshold').should('have.value', '10')
cy.get('[data-attr=alertForm-upper-threshold').should('have.value', '20')
cy.contains('Delete alert').click()
cy.wait(2000)

cy.reload()
cy.contains('Alert name').should('not.exist')
})
})
16 changes: 16 additions & 0 deletions cypress/productAnalytics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export const insight = {
}
})
},
applyBreakdown: (): void => {
cy.contains('Add breakdown').click()
cy.contains('Browser').click()
cy.wait(1000)
},
editName: (insightName: string): void => {
if (insightName) {
cy.get('[data-attr="top-bar-name"] button').click()
Expand Down Expand Up @@ -207,6 +212,17 @@ export function createInsight(insightName: string): Cypress.Chainable<string> {
})
}

export function createInsightWithBreakdown(insightName: string): Cypress.Chainable<string> {
savedInsights.createNewInsightOfType('TRENDS')
insight.applyBreakdown()
insight.editName(insightName)
insight.save()
// return insight id from the url
return cy.url().then((url) => {
return url.split('/').at(-1)
})
}

export function duplicateDashboardFromMenu(duplicateTiles = false): void {
cy.contains('.LemonButton', 'Duplicate').click()
if (duplicateTiles) {
Expand Down
8 changes: 8 additions & 0 deletions docker/clickhouse/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,14 @@
</replica>
</shard>
</posthog>
<posthog_single_shard>
<shard>
<replica>
<host>localhost</host>
<port>9000</port>
</replica>
</shard>
</posthog_single_shard>
</remote_servers>

<!-- The list of hosts allowed to use in URL-related storage engines and table functions.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/services/make.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import {
IconDatabase,
IconDecisionTree,
IconFeatures,
IconGraph,
IconHelmet,
IconMap,
IconMessage,
IconPieChart,
IconRewindPlay,
IconStack,
IconTestTube,
IconToggle,
IconTrends,
} from '@posthog/icons'
import { LemonBanner, LemonButton, Link } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
Expand Down Expand Up @@ -40,7 +41,7 @@ const PRODUCTS = [
{
name: 'Product analytics',
slug: 'product-analytics',
icon: <IconTrends className="text-brand-blue h-5 w-5" />,
icon: <IconGraph className="text-[#2F80FA] h-5 w-5" />,
},
{
name: 'Web analytics',
Expand All @@ -55,7 +56,12 @@ const PRODUCTS = [
{
name: 'Feature flags',
slug: 'feature-flags',
icon: <IconToggle className="text-success h-5 w-5" />,
icon: <IconToggle className="text-[#30ABC6] h-5 w-5" />,
},
{
name: 'Experiments',
slug: 'experiments',
icon: <IconTestTube className="text-[#B62AD9] h-5 w-5" />,
},
{
name: 'Surveys',
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/components/Alerts/AlertsButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function AlertsButton({ insight, insightLogicProps, text, ...props }: Ale
onClick={() => push(urls.insightAlerts(insight.short_id!))}
disabledReason={
!areAlertsSupportedForInsight(insight.query)
? 'Alerts are only available for trends without breakdowns. Change the insight representation to add alerts.'
? 'Alerts are only available for trends. Change the insight representation to add alerts.'
: undefined
}
{...props}
Expand Down
10 changes: 2 additions & 8 deletions frontend/src/lib/components/Alerts/insightAlertsLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import api from 'lib/api'
import { insightVizDataLogic } from 'scenes/insights/insightVizDataLogic'

import { AlertConditionType, GoalLine, InsightThresholdType } from '~/queries/schema'
import { getBreakdown, isInsightVizNode, isTrendsQuery } from '~/queries/utils'
import { isInsightVizNode, isTrendsQuery } from '~/queries/utils'
import { InsightLogicProps } from '~/types'

import type { insightAlertsLogicType } from './insightAlertsLogicType'
Expand All @@ -16,13 +16,7 @@ export interface InsightAlertsLogicProps {
}

export const areAlertsSupportedForInsight = (query?: Record<string, any> | null): boolean => {
return (
!!query &&
isInsightVizNode(query) &&
isTrendsQuery(query.source) &&
query.source.trendsFilter !== null &&
!getBreakdown(query.source)
)
return !!query && isInsightVizNode(query) && isTrendsQuery(query.source) && query.source.trendsFilter !== null
}

export const insightAlertsLogic = kea<insightAlertsLogicType>([
Expand Down
26 changes: 23 additions & 3 deletions frontend/src/lib/components/Alerts/views/EditAlertModal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { LemonCheckbox, LemonInput, LemonSegmentedButton, LemonSelect, SpinnerOverlay } from '@posthog/lemon-ui'
import {
LemonBanner,
LemonCheckbox,
LemonInput,
LemonSegmentedButton,
LemonSelect,
SpinnerOverlay,
} from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { Form, Group } from 'kea-forms'
import { AlertStateIndicator } from 'lib/components/Alerts/views/ManageAlertsModal'
Expand Down Expand Up @@ -85,7 +92,7 @@ export function EditAlertModal({
const { setAlertFormValue } = useActions(formLogic)

const trendsLogic = trendsDataLogic({ dashboardItemId: insightShortId })
const { alertSeries, isNonTimeSeriesDisplay } = useValues(trendsLogic)
const { alertSeries, isNonTimeSeriesDisplay, isBreakdownValid } = useValues(trendsLogic)

const creatingNewAlert = alertForm.id === undefined

Expand Down Expand Up @@ -138,6 +145,12 @@ export function EditAlertModal({
<div className="space-y-6">
<h3>Definition</h3>
<div className="space-y-5">
{isBreakdownValid && (
<LemonBanner type="warning">
For trends with breakdown, the alert will fire if any of the breakdown
values breaches the threshold.
</LemonBanner>
)}
<div className="flex gap-4 items-center">
<div>When</div>
<Group name={['config']}>
Expand All @@ -146,9 +159,16 @@ export function EditAlertModal({
fullWidth
data-attr="alertForm-series-index"
options={alertSeries?.map(({ event }, index) => ({
label: `${alphabet[index]} - ${event}`,
label: isBreakdownValid
? 'any breakdown value'
: `${alphabet[index]} - ${event}`,
value: index,
}))}
disabledReason={
isBreakdownValid &&
`For trends with breakdown, the alert will fire if any of the breakdown
values breaches the threshold.`
}
/>
</LemonField>
</Group>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { IconCheck, IconX } from '@posthog/icons'
import { Link } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { router } from 'kea-router'
import { LemonButton } from 'lib/lemon-ui/LemonButton'
Expand Down Expand Up @@ -85,8 +86,12 @@ export function ManageAlertsModal(props: ManageAlertsModalProps): JSX.Element {
<div className="mb-4">
With alerts, PostHog will monitor your insight and notify you when certain conditions are met. We do
not evaluate alerts in real-time, but rather on a schedule (hourly, daily...). Please note that
alerts are in alpha and may not be fully reliable.
alerts are in alpha and may not be fully reliable. <br />
<Link to={urls.alerts()} target="_blank">
View all your alerts here
</Link>
</div>

{alerts.length ? (
<div className="space-y-2">
<div>
Expand Down
18 changes: 6 additions & 12 deletions frontend/src/scenes/settings/environment/AddMembersModal.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { IconPlus } from '@posthog/icons'
import { LemonButton, LemonModal, LemonSelect, LemonSelectOption } from '@posthog/lemon-ui'
import { useValues } from 'kea'
import { useActions, useValues } from 'kea'
import { Form } from 'kea-forms'
import { upgradeModalLogic } from 'lib/components/UpgradeModal/upgradeModalLogic'
import { usersLemonSelectOptions } from 'lib/components/UserSelectItem'
import { TeamMembershipLevel } from 'lib/constants'
import { LemonField } from 'lib/lemon-ui/LemonField'
import { LemonInputSelect } from 'lib/lemon-ui/LemonInputSelect/LemonInputSelect'
import { membershipLevelToName, teamMembershipLevelIntegers } from 'lib/utils/permissioning'
import { useState } from 'react'
import { teamLogic } from 'scenes/teamLogic'
import { userLogic } from 'scenes/userLogic'

Expand All @@ -17,24 +16,19 @@ import { AvailableFeature } from '~/types'
import { teamMembersLogic } from './teamMembersLogic'

export function AddMembersModalWithButton({ disabledReason }: { disabledReason: string | null }): JSX.Element {
const { addableMembers, allMembersLoading } = useValues(teamMembersLogic)
const { addableMembers, allMembersLoading, isAddMembersModalOpen } = useValues(teamMembersLogic)
const { openAddMembersModal, closeAddMembersModal } = useActions(teamMembersLogic)
const { currentTeam } = useValues(teamLogic)
const { guardAvailableFeature } = useValues(upgradeModalLogic)
const { hasAvailableFeature } = useValues(userLogic)

const [isVisible, setIsVisible] = useState(false)

function closeModal(): void {
setIsVisible(false)
}

return (
<>
<LemonButton
type="primary"
data-attr="add-project-members-button"
onClick={() =>
guardAvailableFeature(AvailableFeature.PROJECT_BASED_PERMISSIONING, () => setIsVisible(true), {
guardAvailableFeature(AvailableFeature.PROJECT_BASED_PERMISSIONING, () => openAddMembersModal(), {
isGrandfathered:
!hasAvailableFeature(AvailableFeature.PROJECT_BASED_PERMISSIONING) &&
currentTeam?.access_control,
Expand All @@ -45,7 +39,7 @@ export function AddMembersModalWithButton({ disabledReason }: { disabledReason:
>
Add members to project
</LemonButton>
<LemonModal title="" onClose={closeModal} isOpen={isVisible} simple>
<LemonModal title="" onClose={closeAddMembersModal} isOpen={isAddMembersModalOpen} simple>
<Form logic={teamMembersLogic} formKey="addMembers" enableFormOnSubmit>
<LemonModal.Header>
<h3>{`Adding members${currentTeam?.name ? ` to project ${currentTeam.name}` : ''}`}</h3>
Expand Down Expand Up @@ -76,7 +70,7 @@ export function AddMembersModalWithButton({ disabledReason }: { disabledReason:
</LemonField>
</LemonModal.Content>
<LemonModal.Footer>
<LemonButton type="secondary" onClick={closeModal}>
<LemonButton type="secondary" onClick={closeAddMembersModal}>
Cancel
</LemonButton>
<LemonButton type="primary" data-attr="add-project-members-submit" htmlType="submit">
Expand Down
19 changes: 17 additions & 2 deletions frontend/src/scenes/settings/environment/teamMembersLogic.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { actions, afterMount, kea, listeners, path, selectors } from 'kea'
import { actions, afterMount, kea, listeners, path, reducers, selectors } from 'kea'
import { forms } from 'kea-forms'
import { loaders } from 'kea-loaders'
import api from 'lib/api'
Expand Down Expand Up @@ -27,8 +27,19 @@ export const teamMembersLogic = kea<teamMembersLogicType>([
user,
newLevel,
}),
openAddMembersModal: true,
closeAddMembersModal: true,
}),
loaders(({ values }) => ({
reducers({
isAddMembersModalOpen: [
false,
{
openAddMembersModal: () => true,
closeAddMembersModal: () => false,
},
],
}),
loaders(({ actions, values }) => ({
explicitMembers: {
__default: [] as ExplicitTeamMemberType[],
loadMembers: async () => {
Expand All @@ -46,6 +57,7 @@ export const teamMembersLogic = kea<teamMembersLogicType>([
lemonToast.success(
`Added ${newMembers.length} member${newMembers.length !== 1 ? 's' : ''} to the project.`
)
actions.closeAddMembersModal()
return [...values.explicitMembers, ...newMembers]
},
removeMember: async ({ member }: { member: BaseMemberType }) => {
Expand Down Expand Up @@ -176,6 +188,9 @@ export const teamMembersLogic = kea<teamMembersLogicType>([
)
actions.loadMembers()
},
closeAddMembersModal: () => {
actions.resetAddMembers()
},
})),
afterMount(({ actions }) => {
actions.loadMembers()
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/scenes/surveys/surveyViewViz.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export function UsersStackedBar({ surveyUserStats }: { surveyUserStats: SurveyUs
{[
{
count: seen,
label: 'Shown',
label: 'Unanswered',
classes: `rounded-l ${dismissed === 0 && sent === 0 ? 'rounded-r' : ''}`,
style: { backgroundColor: '#1D4AFF', width: `${seenPercentage}%` },
},
Expand Down Expand Up @@ -135,7 +135,7 @@ export function UsersStackedBar({ surveyUserStats }: { surveyUserStats: SurveyUs
<div className="w-full flex justify-center">
<div className="flex items-center">
{[
{ count: seen, label: 'Viewed', style: { backgroundColor: '#1D4AFF' } },
{ count: seen, label: 'Unanswered', style: { backgroundColor: '#1D4AFF' } },
{ count: dismissed, label: 'Dismissed', style: { backgroundColor: '#E3A506' } },
{ count: sent, label: 'Submitted', style: { backgroundColor: '#529B08' } },
].map(
Expand Down
16 changes: 15 additions & 1 deletion frontend/src/scenes/trends/trendsDataLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,16 @@ import {
BREAKDOWN_OTHER_STRING_LABEL,
} from 'scenes/insights/utils'

import { EventsNode, InsightQueryNode, LifecycleQuery, MathType, TrendsFilter, TrendsQuery } from '~/queries/schema'
import {
BreakdownFilter,
EventsNode,
InsightQueryNode,
LifecycleQuery,
MathType,
TrendsFilter,
TrendsQuery,
} from '~/queries/schema'
import { isValidBreakdown } from '~/queries/utils'
import {
ChartDisplayType,
CountPerActorMathType,
Expand Down Expand Up @@ -124,6 +133,11 @@ export const trendsDataLogic = kea<trendsDataLogicType>([
},
],

isBreakdownValid: [
(s) => [s.breakdownFilter],
(breakdownFilter: BreakdownFilter | null) => isValidBreakdown(breakdownFilter),
],

indexedResults: [
(s) => [s.results, s.display, s.lifecycleFilter],
(results, display, lifecycleFilter): IndexedTrendResult[] => {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@
"pmtiles": "^2.11.0",
"postcss": "^8.4.31",
"postcss-preset-env": "^9.3.0",
"posthog-js": "1.187.2",
"posthog-js": "1.188.0",
"posthog-js-lite": "3.0.0",
"prettier": "^2.8.8",
"prop-types": "^15.7.2",
Expand Down
Loading

0 comments on commit b29f04e

Please sign in to comment.