From d639bc673fccd31b1617fe35e1a2886e0517ff48 Mon Sep 17 00:00:00 2001 From: Surbhi Date: Tue, 17 Dec 2024 15:06:14 -0500 Subject: [PATCH 1/7] onboarding product logic: --- frontend/src/lib/constants.tsx | 1 + .../src/scenes/onboarding/sdks/sdksLogic.tsx | 50 ++++++++++++++++--- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/frontend/src/lib/constants.tsx b/frontend/src/lib/constants.tsx index 4f5dab68b9942..3a0cf8a516bd9 100644 --- a/frontend/src/lib/constants.tsx +++ b/frontend/src/lib/constants.tsx @@ -156,6 +156,7 @@ export const FEATURE_FLAGS = { FF_DASHBOARD_TEMPLATES: 'ff-dashboard-templates', // owner: @EDsCODE ARTIFICIAL_HOG: 'artificial-hog', // owner: @Twixes CS_DASHBOARDS: 'cs-dashboards', // owner: @pauldambra + PRODUCT_ANALYTICS_ONBOARDING: 'product-analytics-onboarding', // owner: @surbhi PRODUCT_SPECIFIC_ONBOARDING: 'product-specific-onboarding', // owner: @raquelmsmith REDIRECT_SIGNUPS_TO_INSTANCE: 'redirect-signups-to-instance', // owner: @raquelmsmith APPS_AND_EXPORTS_UI: 'apps-and-exports-ui', // owner: @benjackwhite diff --git a/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx b/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx index ead691bb518e0..64120bb8572c8 100644 --- a/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx +++ b/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx @@ -2,7 +2,9 @@ import { actions, afterMount, connect, events, kea, listeners, path, reducers, s import { loaders } from 'kea-loaders' import { urlToAction } from 'kea-router' import api from 'lib/api' +import { FEATURE_FLAGS } from 'lib/constants' import { LemonSelectOptions } from 'lib/lemon-ui/LemonSelect/LemonSelect' +import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { liveEventsTableLogic } from 'scenes/activity/live/liveEventsTableLogic' import { HogQLQuery, NodeKind } from '~/queries/schema' @@ -39,10 +41,25 @@ Products that will often be installed in multiple places, eg. web and mobile */ export const multiInstallProducts = [ProductKey.PRODUCT_ANALYTICS, ProductKey.FEATURE_FLAGS] +const getOrderedSDKs = (sdks: SDK[]): SDK[] => { + return [ + ...sdks.filter((sdk) => sdk.key === 'html'), + ...sdks.filter((sdk) => sdk.key === 'javascript-web'), + ...sdks.filter((sdk) => !['html', 'javascript-web'].includes(sdk.key)), + ] +} + export const sdksLogic = kea([ path(['scenes', 'onboarding', 'sdks', 'sdksLogic']), connect({ - values: [onboardingLogic, ['productKey'], liveEventsTableLogic, ['eventHosts']], + values: [ + onboardingLogic, + ['productKey'], + liveEventsTableLogic, + ['eventHosts'], + featureFlagLogic, + ['featureFlags'], + ], }), actions({ setSourceFilter: (sourceFilter: string | null) => ({ sourceFilter }), @@ -173,7 +190,7 @@ export const sdksLogic = kea([ })), listeners(({ actions, values }) => ({ filterSDKs: () => { - const filteredSDks: SDK[] = allSDKs + let filteredSDks: SDK[] = allSDKs .filter((sdk) => { if (!values.sourceFilter || !sdk) { return true @@ -181,6 +198,13 @@ export const sdksLogic = kea([ return sdk.tags.includes(values.sourceFilter) }) .filter((sdk) => Object.keys(values.availableSDKInstructionsMap).includes(sdk.key)) + + if ( + values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_ONBOARDING] && + values.productKey === ProductKey.PRODUCT_ANALYTICS + ) { + filteredSDks = getOrderedSDKs(filteredSDks) + } actions.setSDKs(filteredSDks) actions.setSourceOptions(getSourceOptions(values.availableSDKInstructionsMap)) }, @@ -196,8 +220,16 @@ export const sdksLogic = kea([ actions.setSelectedSDK(null) actions.filterSDKs() }, - [onboardingLogic.actionTypes.setProductKey]: () => { - // TODO: This doesn't seem to run when the setProductKey action is called in onboardingLogic... + [onboardingLogic.actionTypes.setProductKey]: ({ productKey }) => { + // Set default source filter for Product Analytics + if ( + productKey === ProductKey.PRODUCT_ANALYTICS && + values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_ONBOARDING] + ) { + actions.setSourceFilter('Recommended') + } else { + actions.setSourceFilter(null) + } actions.resetSDKs() }, resetSDKs: () => { @@ -225,8 +257,14 @@ export const sdksLogic = kea([ afterMount(({ actions }) => { actions.loadSnippetEvents() }), - urlToAction(({ actions }) => ({ - '/onboarding/:productKey': (_productKey, { sdk }) => { + urlToAction(({ actions, values }) => ({ + '/onboarding/:productKey': (_product_key, { sdk }) => { + if ( + values.productKey === ProductKey.PRODUCT_ANALYTICS && + values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_ONBOARDING] + ) { + actions.setSourceFilter('Recommended') + } const matchedSDK = allSDKs.find((s) => s.key === sdk) if (matchedSDK) { actions.setSelectedSDK(matchedSDK) From 5ab27a5de93a461229804f9fc17a8ab2c2d765d0 Mon Sep 17 00:00:00 2001 From: Surbhi Date: Wed, 18 Dec 2024 17:56:10 -0500 Subject: [PATCH 2/7] updated experiment name and addressed other comments --- frontend/src/lib/constants.tsx | 2 +- .../src/scenes/onboarding/sdks/sdksLogic.tsx | 21 ++++++------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/frontend/src/lib/constants.tsx b/frontend/src/lib/constants.tsx index 3a0cf8a516bd9..fd0d0805137c5 100644 --- a/frontend/src/lib/constants.tsx +++ b/frontend/src/lib/constants.tsx @@ -156,7 +156,7 @@ export const FEATURE_FLAGS = { FF_DASHBOARD_TEMPLATES: 'ff-dashboard-templates', // owner: @EDsCODE ARTIFICIAL_HOG: 'artificial-hog', // owner: @Twixes CS_DASHBOARDS: 'cs-dashboards', // owner: @pauldambra - PRODUCT_ANALYTICS_ONBOARDING: 'product-analytics-onboarding', // owner: @surbhi + PRODUCT_ANALYTICS_MODIFIED_SDK_LIST: 'product-analytics-modified-sdk-list', // owner: @surbhi PRODUCT_SPECIFIC_ONBOARDING: 'product-specific-onboarding', // owner: @raquelmsmith REDIRECT_SIGNUPS_TO_INSTANCE: 'redirect-signups-to-instance', // owner: @raquelmsmith APPS_AND_EXPORTS_UI: 'apps-and-exports-ui', // owner: @benjackwhite diff --git a/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx b/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx index 64120bb8572c8..0ab2ef2fbffff 100644 --- a/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx +++ b/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx @@ -41,7 +41,7 @@ Products that will often be installed in multiple places, eg. web and mobile */ export const multiInstallProducts = [ProductKey.PRODUCT_ANALYTICS, ProductKey.FEATURE_FLAGS] -const getOrderedSDKs = (sdks: SDK[]): SDK[] => { +const getProductAnalyticsOrderedSDKs = (sdks: SDK[]): SDK[] => { return [ ...sdks.filter((sdk) => sdk.key === 'html'), ...sdks.filter((sdk) => sdk.key === 'javascript-web'), @@ -200,10 +200,10 @@ export const sdksLogic = kea([ .filter((sdk) => Object.keys(values.availableSDKInstructionsMap).includes(sdk.key)) if ( - values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_ONBOARDING] && + values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_MODIFIED_SDK_LIST] === 'test' && values.productKey === ProductKey.PRODUCT_ANALYTICS ) { - filteredSDks = getOrderedSDKs(filteredSDks) + filteredSDks = getProductAnalyticsOrderedSDKs(filteredSDks) } actions.setSDKs(filteredSDks) actions.setSourceOptions(getSourceOptions(values.availableSDKInstructionsMap)) @@ -220,17 +220,8 @@ export const sdksLogic = kea([ actions.setSelectedSDK(null) actions.filterSDKs() }, - [onboardingLogic.actionTypes.setProductKey]: ({ productKey }) => { - // Set default source filter for Product Analytics - if ( - productKey === ProductKey.PRODUCT_ANALYTICS && - values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_ONBOARDING] - ) { - actions.setSourceFilter('Recommended') - } else { - actions.setSourceFilter(null) - } - actions.resetSDKs() + [onboardingLogic.actionTypes.setProductKey]: () => { + // TODO: This doesn't seem to run when the setProductKey action is called in onboardingLogic... }, resetSDKs: () => { actions.filterSDKs() @@ -261,7 +252,7 @@ export const sdksLogic = kea([ '/onboarding/:productKey': (_product_key, { sdk }) => { if ( values.productKey === ProductKey.PRODUCT_ANALYTICS && - values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_ONBOARDING] + values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_MODIFIED_SDK_LIST] === 'test' ) { actions.setSourceFilter('Recommended') } From c2dc08d04718242e10b95ee754d3d1580d8073f8 Mon Sep 17 00:00:00 2001 From: Surbhi Date: Wed, 18 Dec 2024 19:06:09 -0500 Subject: [PATCH 3/7] placing back resetSDK on setProductKey action --- frontend/src/scenes/onboarding/sdks/sdksLogic.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx b/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx index 0ab2ef2fbffff..5664468692dd5 100644 --- a/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx +++ b/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx @@ -222,6 +222,7 @@ export const sdksLogic = kea([ }, [onboardingLogic.actionTypes.setProductKey]: () => { // TODO: This doesn't seem to run when the setProductKey action is called in onboardingLogic... + actions.resetSDKs() }, resetSDKs: () => { actions.filterSDKs() From 4b8948b9c312cbf08105c365bb2dc10699aedf07 Mon Sep 17 00:00:00 2001 From: Surbhi Date: Thu, 19 Dec 2024 16:45:38 -0500 Subject: [PATCH 4/7] role_at_org model changes and ui updates --- .../src/scenes/onboarding/sdks/sdksLogic.tsx | 5 +-- posthog/api/user.py | 12 +++++++ .../0533_user_role_at_organization.py | 31 +++++++++++++++++++ posthog/models/user.py | 13 ++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 posthog/migrations/0533_user_role_at_organization.py diff --git a/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx b/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx index 5664468692dd5..cd1ebd44066db 100644 --- a/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx +++ b/frontend/src/scenes/onboarding/sdks/sdksLogic.tsx @@ -6,6 +6,7 @@ import { FEATURE_FLAGS } from 'lib/constants' import { LemonSelectOptions } from 'lib/lemon-ui/LemonSelect/LemonSelect' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { liveEventsTableLogic } from 'scenes/activity/live/liveEventsTableLogic' +import { userLogic } from 'scenes/userLogic' import { HogQLQuery, NodeKind } from '~/queries/schema' import { hogql } from '~/queries/utils' @@ -14,7 +15,6 @@ import { ProductKey, SDK, SDKInstructionsMap } from '~/types' import { onboardingLogic } from '../onboardingLogic' import { allSDKs } from './allSDKs' import type { sdksLogicType } from './sdksLogicType' - /* To add SDK instructions for your product: 1. If needed, add a new ProductKey enum value in ~/types.ts @@ -59,6 +59,8 @@ export const sdksLogic = kea([ ['eventHosts'], featureFlagLogic, ['featureFlags'], + userLogic, + ['user'], ], }), actions({ @@ -198,7 +200,6 @@ export const sdksLogic = kea([ return sdk.tags.includes(values.sourceFilter) }) .filter((sdk) => Object.keys(values.availableSDKInstructionsMap).includes(sdk.key)) - if ( values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_MODIFIED_SDK_LIST] === 'test' && values.productKey === ProductKey.PRODUCT_ANALYTICS diff --git a/posthog/api/user.py b/posthog/api/user.py index 0610abf047df7..6375a4062ee74 100644 --- a/posthog/api/user.py +++ b/posthog/api/user.py @@ -94,6 +94,11 @@ class UserSerializer(serializers.ModelSerializer): notification_settings = serializers.DictField(required=False) scene_personalisation = ScenePersonalisationBasicSerializer(many=True, read_only=True) anonymize_data = ClassicBehaviorBooleanFieldSerializer() + role_at_organization = serializers.ChoiceField( + choices=User.ROLE_CHOICES, # Use the choices from User model + required=True, # Make it optional + # allow_null=True # Allow null values + ) class Meta: model = User @@ -128,6 +133,7 @@ class Meta: "scene_personalisation", "theme_mode", "hedgehog_config", + "role_at_organization", ] read_only_fields = [ @@ -250,6 +256,12 @@ def validate_is_staff(self, value: bool) -> bool: raise exceptions.PermissionDenied("You are not a staff user, contact your instance admin.") return value + # not sure if this is needed here + def validate_role_at_organization(self, value): + if value and value not in dict(User.ROLE_CHOICES): + raise serializers.ValidationError("Invalid role selected") + return value + def update(self, instance: "User", validated_data: Any) -> Any: # Update current_organization and current_team current_organization = validated_data.pop("set_current_organization", None) diff --git a/posthog/migrations/0533_user_role_at_organization.py b/posthog/migrations/0533_user_role_at_organization.py new file mode 100644 index 0000000000000..0760bf34f6dd3 --- /dev/null +++ b/posthog/migrations/0533_user_role_at_organization.py @@ -0,0 +1,31 @@ +# Generated by Django 4.2.15 on 2024-12-19 21:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("posthog", "0532_taxonomy_unique_on_project"), + ] + + operations = [ + migrations.AddField( + model_name="user", + name="role_at_organization", + field=models.CharField( + blank=True, + choices=[ + ("engineering", "Engineering"), + ("data", "Data"), + ("product", "Product Management"), + ("founder", "Founder"), + ("leadership", "Leadership"), + ("marketing", "Marketing"), + ("sales", "Sales / Success"), + ("other", "Other"), + ], + max_length=64, + null=True, + ), + ), + ] diff --git a/posthog/models/user.py b/posthog/models/user.py index 3b25009931c7c..3035bb016d9d2 100644 --- a/posthog/models/user.py +++ b/posthog/models/user.py @@ -172,6 +172,19 @@ class User(AbstractUser, UUIDClassicModel): # Remove unused attributes from `AbstractUser` username = None + ROLE_CHOICES = ( + ("engineering", "Engineering"), + ("data", "Data"), + ("product", "Product Management"), + ("founder", "Founder"), + ("leadership", "Leadership"), + ("marketing", "Marketing"), + ("sales", "Sales / Success"), + ("other", "Other"), + ) + + role_at_organization = models.CharField(max_length=64, choices=ROLE_CHOICES, null=True, blank=True) + objects: UserManager = UserManager() @property From dd59b7d675b532f5cb972ed7d119309212eb2bd0 Mon Sep 17 00:00:00 2001 From: Surbhi Date: Thu, 19 Dec 2024 18:00:24 -0500 Subject: [PATCH 5/7] user serializer udpates --- posthog/api/signup.py | 12 ++++++++---- posthog/api/user.py | 7 +------ posthog/migrations/max_migration.txt | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/posthog/api/signup.py b/posthog/api/signup.py index a781c7972b01f..18f0a80020ce0 100644 --- a/posthog/api/signup.py +++ b/posthog/api/signup.py @@ -111,6 +111,7 @@ def create(self, validated_data, **kwargs): create_team=self.create_team, is_staff=is_instance_first_user, is_email_verified=self.is_email_auto_verified(), + role_at_organization=role_at_organization, **validated_data, ) except IntegrityError: @@ -142,6 +143,7 @@ def enter_demo(self, validated_data) -> User: email = validated_data["email"] first_name = validated_data["first_name"] organization_name = validated_data["organization_name"] + role_at_organization = validated_data["role_at_organization"] # In the demo env, social signups gets staff privileges # - grep SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS for more info is_staff = self.is_social_signup @@ -152,7 +154,9 @@ def enter_demo(self, validated_data) -> User: self._organization, self._team, self._user, - ) = manager.ensure_account_and_save(email, first_name, organization_name, is_staff=is_staff) + ) = manager.ensure_account_and_save( + email, first_name, organization_name, role_at_organization, is_staff=is_staff + ) login( self.context["request"], @@ -209,8 +213,6 @@ def create(self, validated_data, **kwargs): user: Optional[User] = None is_new_user: bool = False - role_at_organization = validated_data.pop("role_at_organization", "") - if self.context["request"].user.is_authenticated: user = cast(User, self.context["request"].user) @@ -236,11 +238,13 @@ def create(self, validated_data, **kwargs): if not user: is_new_user = True try: + role = validated_data.pop("role_at_organization", "") user = User.objects.create_user( invite.target_email, validated_data.pop("password"), validated_data.pop("first_name"), is_email_verified=False, + role_at_organization=role, **validated_data, ) except IntegrityError: @@ -264,7 +268,7 @@ def create(self, validated_data, **kwargs): backend_processor="OrganizationInviteSignupSerializer", user_analytics_metadata=user.get_analytics_metadata(), org_analytics_metadata=user.organization.get_analytics_metadata() if user.organization else None, - role_at_organization=role_at_organization, + role_at_organization=role, referral_source="signed up from invite link", ) diff --git a/posthog/api/user.py b/posthog/api/user.py index 6375a4062ee74..bfbaf645db077 100644 --- a/posthog/api/user.py +++ b/posthog/api/user.py @@ -94,11 +94,7 @@ class UserSerializer(serializers.ModelSerializer): notification_settings = serializers.DictField(required=False) scene_personalisation = ScenePersonalisationBasicSerializer(many=True, read_only=True) anonymize_data = ClassicBehaviorBooleanFieldSerializer() - role_at_organization = serializers.ChoiceField( - choices=User.ROLE_CHOICES, # Use the choices from User model - required=True, # Make it optional - # allow_null=True # Allow null values - ) + role_at_organization = serializers.ChoiceField(choices=User.ROLE_CHOICES, required=True) class Meta: model = User @@ -256,7 +252,6 @@ def validate_is_staff(self, value: bool) -> bool: raise exceptions.PermissionDenied("You are not a staff user, contact your instance admin.") return value - # not sure if this is needed here def validate_role_at_organization(self, value): if value and value not in dict(User.ROLE_CHOICES): raise serializers.ValidationError("Invalid role selected") diff --git a/posthog/migrations/max_migration.txt b/posthog/migrations/max_migration.txt index 01fc03d62a8a0..739feb7d94868 100644 --- a/posthog/migrations/max_migration.txt +++ b/posthog/migrations/max_migration.txt @@ -1 +1 @@ -0532_taxonomy_unique_on_project +0533_user_role_at_organization From 7e5c7884155328858316fb580c3cee97565c5d7f Mon Sep 17 00:00:00 2001 From: Surbhi Date: Thu, 19 Dec 2024 19:03:50 -0500 Subject: [PATCH 6/7] ux updates --- frontend/src/scenes/onboarding/sdks/SDKs.tsx | 22 ++++++++++++++----- .../src/scenes/onboarding/sdks/sdksLogic.tsx | 20 +++++------------ frontend/src/scenes/userLogic.ts | 8 +++++++ frontend/src/types.ts | 1 + 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/frontend/src/scenes/onboarding/sdks/SDKs.tsx b/frontend/src/scenes/onboarding/sdks/SDKs.tsx index daf51779029f9..a21733c93c95b 100644 --- a/frontend/src/scenes/onboarding/sdks/SDKs.tsx +++ b/frontend/src/scenes/onboarding/sdks/SDKs.tsx @@ -1,11 +1,14 @@ import { IconArrowLeft, IconArrowRight, IconCheck } from '@posthog/icons' import { LemonButton, LemonCard, LemonDivider, LemonSelect, Spinner } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' +import { FEATURE_FLAGS } from 'lib/constants' import { useInterval } from 'lib/hooks/useInterval' import { useWindowSize } from 'lib/hooks/useWindowSize' +import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { useEffect } from 'react' import React from 'react' import { teamLogic } from 'scenes/teamLogic' +import { userLogic } from 'scenes/userLogic' import { InviteMembersButton } from '~/layout/navigation/TopBar/AccountPopover' import { SDKInstructionsMap } from '~/types' @@ -38,6 +41,8 @@ export function SDKs({ const { goToNextStep, completeOnboarding } = useActions(onboardingLogic) const [showListeningFor, setShowListeningFor] = React.useState(false) const [hasCheckedInstallation, setHasCheckedInstallation] = React.useState(false) + const { isUserTechnical } = useValues(userLogic) + const { featureFlags } = useValues(featureFlagLogic) const { width } = useWindowSize() @@ -66,8 +71,18 @@ export function SDKs({ } }, 2000) + const HelpCard = (): JSX.Element => ( + +

Need help with this step?

+

Invite a team member to help you get set up.

+ +
+ ) + return ( }> + {featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_MODIFIED_SDK_LIST] === 'test' && + isUserTechnical === false && }
))} - -

Need help with this step?

-

Invite a team member to help you get set up.

- -
+ {(featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_MODIFIED_SDK_LIST] !== 'test' || + isUserTechnical !== false) && }
{selectedSDK && productKey && !!sdkInstructionMap[selectedSDK.key] && (
([ featureFlagLogic, ['featureFlags'], userLogic, - ['user'], + ['user', 'isUserTechnical'], ], }), actions({ @@ -202,7 +202,8 @@ export const sdksLogic = kea([ .filter((sdk) => Object.keys(values.availableSDKInstructionsMap).includes(sdk.key)) if ( values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_MODIFIED_SDK_LIST] === 'test' && - values.productKey === ProductKey.PRODUCT_ANALYTICS + values.productKey === ProductKey.PRODUCT_ANALYTICS && + values.isUserTechnical === false ) { filteredSDks = getProductAnalyticsOrderedSDKs(filteredSDks) } @@ -250,18 +251,7 @@ export const sdksLogic = kea([ afterMount(({ actions }) => { actions.loadSnippetEvents() }), - urlToAction(({ actions, values }) => ({ - '/onboarding/:productKey': (_product_key, { sdk }) => { - if ( - values.productKey === ProductKey.PRODUCT_ANALYTICS && - values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_MODIFIED_SDK_LIST] === 'test' - ) { - actions.setSourceFilter('Recommended') - } - const matchedSDK = allSDKs.find((s) => s.key === sdk) - if (matchedSDK) { - actions.setSelectedSDK(matchedSDK) - } - }, + urlToAction(() => ({ + '/onboarding/:productKey': () => {}, })), ]) diff --git a/frontend/src/scenes/userLogic.ts b/frontend/src/scenes/userLogic.ts index a3adad1c6f50e..1be225985cf3e 100644 --- a/frontend/src/scenes/userLogic.ts +++ b/frontend/src/scenes/userLogic.ts @@ -250,6 +250,14 @@ export const userLogic = kea([ return user?.theme_mode || 'light' }, ], + + isUserTechnical: [ + (s) => [s.user], + (user) => { + const technicalRoles = ['engineering', 'founder'] + return user?.role_at_organization && technicalRoles.includes(user.role_at_organization) + }, + ], }), afterMount(({ actions }) => { const preloadedUser = getAppContext()?.current_user diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 514caa3635726..146502663108d 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -288,6 +288,7 @@ export interface UserType extends UserBaseType { scene_personalisation?: SceneDashboardChoice[] theme_mode?: UserTheme | null hedgehog_config?: Partial + role_at_organization?: string } export type HedgehogColorOptions = From a80c01cecaff48b32be769ec2edc8e483880419a Mon Sep 17 00:00:00 2001 From: Surbhi Date: Fri, 20 Dec 2024 10:11:08 -0500 Subject: [PATCH 7/7] moving logic to selectors --- frontend/src/scenes/onboarding/sdks/SDKs.tsx | 12 +++--------- .../src/scenes/onboarding/sdks/sdksLogic.tsx | 16 +++++++++++----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/frontend/src/scenes/onboarding/sdks/SDKs.tsx b/frontend/src/scenes/onboarding/sdks/SDKs.tsx index a21733c93c95b..70a0a26693c00 100644 --- a/frontend/src/scenes/onboarding/sdks/SDKs.tsx +++ b/frontend/src/scenes/onboarding/sdks/SDKs.tsx @@ -1,14 +1,11 @@ import { IconArrowLeft, IconArrowRight, IconCheck } from '@posthog/icons' import { LemonButton, LemonCard, LemonDivider, LemonSelect, Spinner } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' -import { FEATURE_FLAGS } from 'lib/constants' import { useInterval } from 'lib/hooks/useInterval' import { useWindowSize } from 'lib/hooks/useWindowSize' -import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { useEffect } from 'react' import React from 'react' import { teamLogic } from 'scenes/teamLogic' -import { userLogic } from 'scenes/userLogic' import { InviteMembersButton } from '~/layout/navigation/TopBar/AccountPopover' import { SDKInstructionsMap } from '~/types' @@ -41,8 +38,7 @@ export function SDKs({ const { goToNextStep, completeOnboarding } = useActions(onboardingLogic) const [showListeningFor, setShowListeningFor] = React.useState(false) const [hasCheckedInstallation, setHasCheckedInstallation] = React.useState(false) - const { isUserTechnical } = useValues(userLogic) - const { featureFlags } = useValues(featureFlagLogic) + const { isUserInNonTechnicalTest } = useValues(sdksLogic) const { width } = useWindowSize() @@ -81,8 +77,7 @@ export function SDKs({ return ( }> - {featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_MODIFIED_SDK_LIST] === 'test' && - isUserTechnical === false && } + {isUserInNonTechnicalTest && }
))} - {(featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_MODIFIED_SDK_LIST] !== 'test' || - isUserTechnical !== false) && } + {!isUserInNonTechnicalTest && }
{selectedSDK && productKey && !!sdkInstructionMap[selectedSDK.key] && (
([ return combinedSnippetAndLiveEventsHosts }, ], + isUserInNonTechnicalTest: [ + (s) => [s.productKey, s.featureFlags, s.isUserTechnical], + (productKey, featureFlags, isUserTechnical): boolean => { + return ( + productKey === ProductKey.PRODUCT_ANALYTICS && + featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_MODIFIED_SDK_LIST] === 'test' && + isUserTechnical === false + ) + }, + ], }), loaders(({ actions }) => ({ hasSnippetEvents: [ @@ -200,11 +210,7 @@ export const sdksLogic = kea([ return sdk.tags.includes(values.sourceFilter) }) .filter((sdk) => Object.keys(values.availableSDKInstructionsMap).includes(sdk.key)) - if ( - values.featureFlags[FEATURE_FLAGS.PRODUCT_ANALYTICS_MODIFIED_SDK_LIST] === 'test' && - values.productKey === ProductKey.PRODUCT_ANALYTICS && - values.isUserTechnical === false - ) { + if (values.isUserInNonTechnicalTest) { filteredSDks = getProductAnalyticsOrderedSDKs(filteredSDks) } actions.setSDKs(filteredSDks)