Skip to content

Commit

Permalink
Merge branch 'master' of github.com:PostHog/posthog into fix/clarify-…
Browse files Browse the repository at this point in the history
…conversion-time
  • Loading branch information
skoob13 committed Feb 11, 2025
2 parents ed3d709 + 305dc22 commit b7cbffc
Show file tree
Hide file tree
Showing 102 changed files with 1,511 additions and 452 deletions.
2 changes: 1 addition & 1 deletion ee/api/rbac/test/test_access_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ def test_query_counts_stable_when_listing_resources_including_access_control_inf
for i in range(10):
FeatureFlag.objects.create(team=self.team, created_by=self.other_user, key=f"flag-{i}")

baseline = 42 # This is a lot! There is currently an n+1 issue with the legacy access control system
baseline = 44 # This is a lot! There is currently an n+1 issue with the legacy access control system
with self.assertNumQueries(baseline + 6): # org, roles, preloaded permissions acs, preloaded acs for the list
self.client.get("/api/projects/@current/feature_flags/")

Expand Down
10 changes: 6 additions & 4 deletions ee/clickhouse/models/test/__snapshots__/test_cohort.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,9 @@
HAVING ifNull(equals(argMax(person_distinct_id_overrides.is_deleted, person_distinct_id_overrides.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__override ON equals(e.distinct_id, e__override.distinct_id)
WHERE and(equals(e.team_id, 99999), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('explicit_redacted_timestamp.999999', 6, 'UTC')), equals(e.event, 'signup'))
GROUP BY if(not(empty(e__override.distinct_id)), e__override.person_id, e.person_id)
HAVING ifNull(equals(min_timestamp, min_timestamp_with_condition), isNull(min_timestamp)
and isNull(min_timestamp_with_condition)))
HAVING and(ifNull(equals(min_timestamp, min_timestamp_with_condition), isNull(min_timestamp)
and isNull(min_timestamp_with_condition)), ifNull(notEquals(min_timestamp, fromUnixTimestamp(0)), isNotNull(min_timestamp)
or isNotNull(fromUnixTimestamp(0)))))
GROUP BY actor_id) AS source
ORDER BY source.id ASC
LIMIT 100 SETTINGS optimize_aggregation_in_order=1,
Expand Down Expand Up @@ -502,8 +503,9 @@
HAVING ifNull(equals(argMax(person_distinct_id_overrides.is_deleted, person_distinct_id_overrides.version), 0), 0) SETTINGS optimize_aggregation_in_order=1) AS e__override ON equals(e.distinct_id, e__override.distinct_id)
WHERE and(equals(e.team_id, 99999), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), toDateTime64('explicit_redacted_timestamp.999999', 6, 'UTC')), equals(e.event, 'signup'))
GROUP BY if(not(empty(e__override.distinct_id)), e__override.person_id, e.person_id)
HAVING ifNull(equals(min_timestamp, min_timestamp_with_condition), isNull(min_timestamp)
and isNull(min_timestamp_with_condition)))
HAVING and(ifNull(equals(min_timestamp, min_timestamp_with_condition), isNull(min_timestamp)
and isNull(min_timestamp_with_condition)), ifNull(notEquals(min_timestamp, fromUnixTimestamp(0)), isNotNull(min_timestamp)
or isNotNull(fromUnixTimestamp(0)))))
GROUP BY actor_id) AS source
ORDER BY source.id ASC
LIMIT 100 SETTINGS optimize_aggregation_in_order=1,
Expand Down
2 changes: 1 addition & 1 deletion ee/clickhouse/views/test/test_clickhouse_experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -1450,7 +1450,7 @@ def test_used_in_experiment_is_populated_correctly_for_feature_flag_list(self) -
).json()

# TODO: Make sure permission bool doesn't cause n + 1
with self.assertNumQueries(17):
with self.assertNumQueries(19):
response = self.client.get(f"/api/projects/{self.team.id}/feature_flags")
self.assertEqual(response.status_code, status.HTTP_200_OK)
result = response.json()
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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 @@ -8,6 +8,8 @@ import {
LemonSelect,
LemonSelectProps,
LemonTable,
LemonTag,
Tooltip,
} from '@posthog/lemon-ui'
import { BindLogic, useActions, useAsyncActions, useValues } from 'kea'
import { PayGateMini } from 'lib/components/PayGateMini/PayGateMini'
Expand Down Expand Up @@ -136,8 +138,12 @@ function AccessControlObjectUsers(): JSX.Element | null {
key: 'level',
title: 'Level',
width: 0,
render: function LevelRender(_, { access_level, organization_member }) {
return (
render: function LevelRender(_, { access_level, organization_member, resource }) {
return resource === 'organization' ? (
<Tooltip title="Organization owners and admins have access to all resources in the organization">
<LemonTag type="muted">Organization admin</LemonTag>
</Tooltip>
) : (
<div className="my-1">
<SimplLevelComponent
size="small"
Expand All @@ -154,8 +160,8 @@ function AccessControlObjectUsers(): JSX.Element | null {
{
key: 'remove',
width: 0,
render: (_, { organization_member }) => {
return (
render: (_, { organization_member, resource }) => {
return resource === 'organization' ? null : (
<RemoveAccessButton
subject="member"
onConfirm={() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { actions, afterMount, connect, kea, key, listeners, path, props, selecto
import { loaders } from 'kea-loaders'
import api from 'lib/api'
import { upgradeModalLogic } from 'lib/components/UpgradeModal/upgradeModalLogic'
import { OrganizationMembershipLevel } from 'lib/constants'
import { toSentenceCase } from 'lib/utils'
import posthog from 'posthog-js'
import { membersLogic } from 'scenes/organization/membersLogic'
Expand Down Expand Up @@ -156,6 +157,7 @@ export const accessControlLogic = kea<accessControlLogicType>([
return props.resource as AccessControlResourceType
},
],

endpoint: [
() => [(_, props) => props],
(props): string => {
Expand All @@ -166,6 +168,7 @@ export const accessControlLogic = kea<accessControlLogicType>([
return `api/projects/@current/${props.resource}s/${props.resource_id}/access_controls`
},
],

humanReadableResource: [
() => [(_, props) => props],
(props): string => {
Expand Down Expand Up @@ -213,6 +216,7 @@ export const accessControlLogic = kea<accessControlLogicType>([
return options
},
],

accessControlDefault: [
(s) => [s.accessControls, s.accessControlDefaultLevel],
(accessControls, accessControlDefaultLevel): AccessControlTypeProject => {
Expand All @@ -227,12 +231,39 @@ export const accessControlLogic = kea<accessControlLogicType>([
},
],

organizationAdmins: [
(s) => [s.sortedMembers],
(members): OrganizationMemberType[] => {
return members?.filter((member) => member.level >= OrganizationMembershipLevel.Admin) ?? []
},
],

organizationAdminsAsAccessControlMembers: [
(s) => [s.organizationAdmins],
(organizationAdmins): AccessControlTypeMember[] => {
return organizationAdmins.map((admin) => ({
organization_member: admin.id,
access_level: 'admin',
created_by: null,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
resource: 'organization',
}))
},
],

accessControlMembers: [
(s) => [s.accessControls],
(accessControls): AccessControlTypeMember[] => {
return (accessControls?.access_controls || []).filter(
(accessControl) => !!accessControl.organization_member
) as AccessControlTypeMember[]
(s) => [s.accessControls, s.organizationAdminsAsAccessControlMembers],
(accessControls, organizationAdminsAsAccessControlMembers): AccessControlTypeMember[] => {
const members = (accessControls?.access_controls || [])
.filter((accessControl) => !!accessControl.organization_member)
.filter(
(accessControl) =>
!organizationAdminsAsAccessControlMembers.some(
(admin) => admin.organization_member === accessControl.organization_member
)
) as AccessControlTypeMember[]
return organizationAdminsAsAccessControlMembers.concat(members)
},
],

Expand Down Expand Up @@ -267,11 +298,13 @@ export const accessControlLogic = kea<accessControlLogicType>([
],

addableMembers: [
(s) => [s.sortedMembers, s.accessControlMembers],
(members, accessControlMembers): any[] => {
(s) => [s.sortedMembers, s.accessControlMembers, s.organizationAdmins],
(members, accessControlMembers, organizationAdmins): any[] => {
return members
? members.filter(
(member) => !accessControlMembers.find((ac) => ac.organization_member === member.id)
(member) =>
!accessControlMembers.find((ac) => ac.organization_member === member.id) &&
!organizationAdmins.find((admin) => admin.id === member.id)
)
: []
},
Expand Down
1 change: 0 additions & 1 deletion frontend/src/lib/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,6 @@ export const FEATURE_FLAGS = {
SETTINGS_SESSION_TABLE_VERSION: 'settings-session-table-version', // owner: @robbie-c
INSIGHT_FUNNELS_USE_UDF: 'insight-funnels-use-udf', // owner: @aspicer #team-product-analytics
INSIGHT_FUNNELS_USE_UDF_TRENDS: 'insight-funnels-use-udf-trends', // owner: @aspicer #team-product-analytics
FIRST_TIME_FOR_USER_MATH: 'first-time-for-user-math', // owner: @skoob13 #team-product-analytics
MULTITAB_EDITOR: 'multitab-editor', // owner: @EDsCODE #team-data-warehouse
BATCH_EXPORTS_POSTHOG_HTTP: 'posthog-http-batch-exports',
DATA_MODELING: 'data-modeling', // owner: @EDsCODE #team-data-warehouse
Expand Down
19 changes: 10 additions & 9 deletions frontend/src/lib/lemon-ui/LemonField/LemonField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ export type LemonPureFieldProps = {
htmlFor?: string
}

const LemonFieldError = ({ error }: { error: string }): JSX.Element => {
return (
<div className="text-danger flex items-center gap-1 text-sm">
<IconErrorOutline className="text-xl shrink-0" /> {error}
</div>
)
}

const LemonPureField = ({
label,
info,
Expand Down Expand Up @@ -66,15 +74,7 @@ const LemonPureField = ({
) : null}
{children}
{help ? <div className="text-secondary text-xs">{help}</div> : null}
{typeof error === 'string' ? (
renderError ? (
renderError(error)
) : (
<div className="text-danger flex items-center gap-1 text-sm">
<IconErrorOutline className="text-xl shrink-0" /> {error}
</div>
)
) : null}
{typeof error === 'string' ? renderError ? renderError(error) : <LemonFieldError error={error} /> : null}
</div>
)
}
Expand Down Expand Up @@ -113,3 +113,4 @@ export const LemonField = ({

/** A field without Kea form functionality. Within a form use `LemonField`. */
LemonField.Pure = LemonPureField
LemonField.Error = LemonFieldError
2 changes: 1 addition & 1 deletion frontend/src/lib/lemon-ui/LemonInput/LemonInput.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
background-color: inherit;
}

.Field--error &,
.Field--error &:not(.ignore-error-border),
&.LemonInput--status-danger {
border-color: var(--danger) !important; // The error border overrides hover/focus higlighting
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ export function InsightDisplayConfig(): JSX.Element {
((isTrends || isStickiness) && !(display && NON_TIME_SERIES_DISPLAY_TYPES.includes(display)))
const showSmoothing =
isTrends && !isValidBreakdown(breakdownFilter) && (!display || display === ChartDisplayType.ActionsLineGraph)
const showMultipleYAxesConfig = isTrends || isStickiness
const showAlertThresholdLinesConfig = isTrends

const { showValuesOnSeries, mightContainFractionalNumbers } = useValues(trendsDataLogic(insightProps))

Expand All @@ -89,8 +91,10 @@ export function InsightDisplayConfig(): JSX.Element {
...(supportsValueOnSeries ? [{ label: () => <ValueOnSeriesFilter /> }] : []),
...(supportsPercentStackView ? [{ label: () => <PercentStackViewFilter /> }] : []),
...(hasLegend ? [{ label: () => <ShowLegendFilter /> }] : []),
{ label: () => <ShowAlertThresholdLinesFilter /> },
{ label: () => <ShowMultipleYAxesFilter /> },
...(showAlertThresholdLinesConfig
? [{ label: () => <ShowAlertThresholdLinesFilter /> }]
: []),
...(showMultipleYAxesConfig ? [{ label: () => <ShowMultipleYAxesFilter /> }] : []),
],
},
]
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/queries/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4200,6 +4200,9 @@
"additionalProperties": false,
"description": "Sync with plugin-server/src/types.ts",
"properties": {
"cohort_name": {
"type": "string"
},
"key": {
"const": "id",
"type": "string"
Expand Down Expand Up @@ -6112,6 +6115,10 @@
},
"searchQuery": {
"type": "string"
},
"status": {
"enum": ["archived", "active", "resolved", "pending_release", "all"],
"type": "string"
}
},
"required": ["dateRange", "kind"],
Expand Down Expand Up @@ -13304,6 +13311,9 @@
"showLegend": {
"type": "boolean"
},
"showMultipleYAxes": {
"type": "boolean"
},
"showValuesOnSeries": {
"type": "boolean"
},
Expand Down Expand Up @@ -13352,6 +13362,9 @@
"show_legend": {
"type": "boolean"
},
"show_multiple_y_axes": {
"type": "boolean"
},
"show_values_on_series": {
"type": "boolean"
}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/queries/schema/schema-general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,7 @@ export type StickinessFilter = {
display?: StickinessFilterLegacy['display']
showLegend?: StickinessFilterLegacy['show_legend']
showValuesOnSeries?: StickinessFilterLegacy['show_values_on_series']
showMultipleYAxes?: StickinessFilterLegacy['show_multiple_y_axes']
hiddenLegendIndexes?: integer[]
stickinessCriteria?: {
operator: StickinessOperator
Expand Down Expand Up @@ -1652,6 +1653,7 @@ export interface ErrorTrackingQuery extends DataNode<ErrorTrackingQueryResponse>
issueId?: ErrorTrackingIssue['id']
orderBy?: 'last_seen' | 'first_seen' | 'occurrences' | 'users' | 'sessions'
dateRange: DateRange
status?: ErrorTrackingIssue['status'] | 'all'
assignee?: ErrorTrackingIssueAssignee | null
filterGroup?: PropertyGroupFilter
filterTestAccounts?: boolean
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/queries/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ export const getYAxisScaleType = (query: InsightQueryNode): string | undefined =
export const getShowMultipleYAxes = (query: InsightQueryNode): boolean | undefined => {
if (isTrendsQuery(query)) {
return query.trendsFilter?.showMultipleYAxes
} else if (isStickinessQuery(query)) {
return query.stickinessFilter?.showMultipleYAxes
}
return undefined
}
Expand Down
4 changes: 1 addition & 3 deletions frontend/src/scenes/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ import { GlobalModals } from '~/layout/GlobalModals'
import { breadcrumbsLogic } from '~/layout/navigation/Breadcrumbs/breadcrumbsLogic'
import { Navigation } from '~/layout/navigation-3000/Navigation'
import { themeLogic } from '~/layout/navigation-3000/themeLogic'
import { actionsModel } from '~/models/actionsModel'
import { cohortsModel } from '~/models/cohortsModel'

import type { appLogicType } from './AppType'
import { preflightLogic } from './PreflightCheck/preflightLogic'
Expand All @@ -28,7 +26,7 @@ window.process = MOCK_NODE_PROCESS

export const appLogic = kea<appLogicType>([
path(['scenes', 'App']),
connect([teamLogic, organizationLogic, actionsModel, cohortsModel]),
connect([teamLogic, organizationLogic]),
actions({
enableDelayedSpinner: true,
ignoreFeatureFlags: true,
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/scenes/billing/billing-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ export const convertAmountToUsage = (
let totalAmount = parseFloat(tier.unit_amount_usd)
let flatFee = parseFloat(tier.flat_amount_usd || '0')
for (const addonTiers of allAddonsTiers) {
totalAmount += parseFloat(addonTiers[index].unit_amount_usd)
flatFee += parseFloat(addonTiers[index].flat_amount_usd || '0')
totalAmount += parseFloat(addonTiers[index]?.unit_amount_usd || '0')
flatFee += parseFloat(addonTiers[index]?.flat_amount_usd || '0')
}
return {
...tier,
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/scenes/dashboard/DashboardCollaborators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ export function DashboardCollaboration({ dashboardId }: { dashboardId: Dashboard

return (
<PayGateMini feature={AvailableFeature.ADVANCED_PERMISSIONS}>
{newAccessControl && (
<LemonBanner type="warning" className="mb-4">
We've upgraded our access control system but this dashboard is using a legacy version that can't be
automatically upgraded. Please reach out to support if you're interested in migrating to the new
system.
</LemonBanner>
)}
{(!canEditDashboard || !canRestrictDashboard) && (
<LemonBanner type="info" className="mb-4">
{canEditDashboard
Expand Down
14 changes: 9 additions & 5 deletions frontend/src/scenes/error-tracking/ErrorTrackingFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ const errorTrackingDateOptions = dateMapping.filter((dm) => dm.key != 'Yesterday

export const ErrorTrackingFilters = (): JSX.Element => {
return (
<div className="flex flex-1 items-center gap-2">
<DateRange />
<UniversalSearch />
<FilterGroup />
<InternalAccounts />
<div className="space-y-1">
<div className="flex gap-2 items-center">
<UniversalSearch />
<InternalAccounts />
</div>
<div className="flex gap-2">
<DateRange />
<FilterGroup />
</div>
</div>
)
}
Expand Down
Loading

0 comments on commit b7cbffc

Please sign in to comment.