Browse Source

ref(platform-categories): Split platform picker data from general definitions (#57358)

Relates to https://github.com/getsentry/sentry/issues/57047
ArthurKnaus 1 year ago
parent
commit
b5c83dfbac

+ 5 - 3
static/app/components/onboarding/frameworkSuggestionModal.tsx

@@ -20,7 +20,7 @@ import ListItem from 'sentry/components/list/listItem';
 import Panel from 'sentry/components/panels/panel';
 import Panel from 'sentry/components/panels/panel';
 import PanelBody from 'sentry/components/panels/panelBody';
 import PanelBody from 'sentry/components/panels/panelBody';
 import Radio from 'sentry/components/radio';
 import Radio from 'sentry/components/radio';
-import categoryList from 'sentry/data/platformCategories';
+import categoryList, {createablePlatforms} from 'sentry/data/platformPickerCategories';
 import platforms from 'sentry/data/platforms';
 import platforms from 'sentry/data/platforms';
 import {t} from 'sentry/locale';
 import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import {space} from 'sentry/styles/space';
@@ -156,7 +156,9 @@ export function FrameworkSuggestionModal({
 
 
   const frameworks = platforms.filter(
   const frameworks = platforms.filter(
     platform =>
     platform =>
-      platform.type === 'framework' && platform.language === selectedPlatform.key
+      createablePlatforms.has(platform.id) &&
+      platform.type === 'framework' &&
+      platform.language === selectedPlatform.key
   );
   );
 
 
   const [topFrameworks, otherFrameworks] = partition(frameworks, framework => {
   const [topFrameworks, otherFrameworks] = partition(frameworks, framework => {
@@ -271,7 +273,7 @@ export function FrameworkSuggestionModal({
                 (framework, index) => {
                 (framework, index) => {
                   const frameworkCategory =
                   const frameworkCategory =
                     categoryList.find(category => {
                     categoryList.find(category => {
-                      return category.platforms.includes(framework.id as never);
+                      return category.platforms?.has(framework.id);
                     })?.id ?? 'all';
                     })?.id ?? 'all';
 
 
                   return (
                   return (

+ 11 - 19
static/app/components/platformPicker.tsx

@@ -10,9 +10,9 @@ import NavTabs from 'sentry/components/navTabs';
 import SearchBar from 'sentry/components/searchBar';
 import SearchBar from 'sentry/components/searchBar';
 import {DEFAULT_DEBOUNCE_DURATION} from 'sentry/constants';
 import {DEFAULT_DEBOUNCE_DURATION} from 'sentry/constants';
 import categoryList, {
 import categoryList, {
-  deprecatedPlatforms,
+  createablePlatforms,
   filterAliases,
   filterAliases,
-} from 'sentry/data/platformCategories';
+} from 'sentry/data/platformPickerCategories';
 import platforms, {otherPlatform} from 'sentry/data/platforms';
 import platforms, {otherPlatform} from 'sentry/data/platforms';
 import {IconClose, IconProject} from 'sentry/icons';
 import {IconClose, IconProject} from 'sentry/icons';
 import {t, tct} from 'sentry/locale';
 import {t, tct} from 'sentry/locale';
@@ -20,14 +20,6 @@ import {space} from 'sentry/styles/space';
 import {Organization, PlatformIntegration, PlatformKey} from 'sentry/types';
 import {Organization, PlatformIntegration, PlatformKey} from 'sentry/types';
 import {trackAnalytics} from 'sentry/utils/analytics';
 import {trackAnalytics} from 'sentry/utils/analytics';
 
 
-export const PLATFORM_CATEGORIES: {
-  id: string;
-  name: string;
-  platforms?: PlatformKey[];
-}[] = [...JSON.parse(JSON.stringify(categoryList)), {id: 'all', name: t('All')}];
-
-const activePlatforms = platforms.filter(({id}) => !deprecatedPlatforms.has(id));
-
 const PlatformList = styled('div')`
 const PlatformList = styled('div')`
   display: grid;
   display: grid;
   gap: ${space(1)};
   gap: ${space(1)};
@@ -35,7 +27,11 @@ const PlatformList = styled('div')`
   margin-bottom: ${space(2)};
   margin-bottom: ${space(2)};
 `;
 `;
 
 
-export type Category = (typeof PLATFORM_CATEGORIES)[number]['id'];
+const selectablePlatforms = platforms.filter(platform =>
+  createablePlatforms.has(platform.id)
+);
+
+export type Category = (typeof categoryList)[number]['id'];
 
 
 export type Platform = PlatformIntegration & {
 export type Platform = PlatformIntegration & {
   category: Category;
   category: Category;
@@ -64,7 +60,7 @@ class PlatformPicker extends Component<PlatformPickerProps, State> {
   };
   };
 
 
   state: State = {
   state: State = {
-    category: this.props.defaultCategory ?? PLATFORM_CATEGORIES[0].id,
+    category: this.props.defaultCategory ?? categoryList[0].id,
     filter: this.props.noAutoFilter ? '' : (this.props.platform || '').split('-')[0],
     filter: this.props.noAutoFilter ? '' : (this.props.platform || '').split('-')[0],
   };
   };
 
 
@@ -81,14 +77,10 @@ class PlatformPicker extends Component<PlatformPickerProps, State> {
       filterAliases[platform.id as PlatformKey]?.some(alias => alias.includes(filter));
       filterAliases[platform.id as PlatformKey]?.some(alias => alias.includes(filter));
 
 
     const categoryMatch = (platform: PlatformIntegration) => {
     const categoryMatch = (platform: PlatformIntegration) => {
-      if (category === 'all') {
-        return true;
-      }
-
-      return (currentCategory?.platforms as undefined | string[])?.includes(platform.id);
+      return currentCategory?.platforms?.has(platform.id);
     };
     };
 
 
-    const filtered = activePlatforms
+    const filtered = selectablePlatforms
       .filter(this.state.filter ? subsetMatch : categoryMatch)
       .filter(this.state.filter ? subsetMatch : categoryMatch)
       .sort((a, b) => a.id.localeCompare(b.id));
       .sort((a, b) => a.id.localeCompare(b.id));
 
 
@@ -115,7 +107,7 @@ class PlatformPicker extends Component<PlatformPickerProps, State> {
       <Fragment>
       <Fragment>
         <NavContainer>
         <NavContainer>
           <CategoryNav>
           <CategoryNav>
-            {PLATFORM_CATEGORIES.map(({id, name}) => (
+            {categoryList.map(({id, name}) => (
               <ListLink
               <ListLink
                 key={id}
                 key={id}
                 onClick={(e: React.MouseEvent) => {
                 onClick={(e: React.MouseEvent) => {

+ 2 - 65
static/app/data/platformCategories.tsx

@@ -1,7 +1,5 @@
 // Mirrors src/sentry/utils/platform_categories.py
 // Mirrors src/sentry/utils/platform_categories.py
 // When changing this file, make sure to keep src/sentry/utils/platform_categories.py in sync.
 // When changing this file, make sure to keep src/sentry/utils/platform_categories.py in sync.
-
-import {t} from 'sentry/locale';
 import {PlatformKey} from 'sentry/types';
 import {PlatformKey} from 'sentry/types';
 
 
 export enum PlatformCategory {
 export enum PlatformCategory {
@@ -13,36 +11,6 @@ export enum PlatformCategory {
   OTHER,
   OTHER,
 }
 }
 
 
-export const popularPlatformCategories: PlatformKey[] = [
-  'javascript',
-  'javascript-react',
-  'javascript-nextjs',
-  'python-django',
-  'python',
-  'python-flask',
-  'python-fastapi',
-  'ruby-rails',
-  'node-express',
-  'php-laravel',
-  'java',
-  'java-spring-boot',
-  'dotnet',
-  'dotnet-aspnetcore',
-  'csharp',
-  'go',
-  'php',
-  'ruby',
-  'node',
-  'react-native',
-  'javascript-angular',
-  'javascript-vue',
-  'android',
-  'apple-ios',
-  'flutter',
-  'dart-flutter',
-  'unity',
-];
-
 export const frontend: PlatformKey[] = [
 export const frontend: PlatformKey[] = [
   'dart',
   'dart',
   'javascript',
   'javascript',
@@ -167,21 +135,6 @@ export const desktop: PlatformKey[] = [
   'unreal',
   'unreal',
 ];
 ];
 
 
-const categoryList = [
-  {id: 'popular', name: t('Popular'), platforms: popularPlatformCategories},
-  {id: 'browser', name: t('Browser'), platforms: frontend},
-  {id: 'server', name: t('Server'), platforms: backend},
-  {id: 'mobile', name: t('Mobile'), platforms: mobile},
-  {id: 'desktop', name: t('Desktop'), platforms: desktop},
-  {id: 'serverless', name: t('Serverless'), platforms: serverless},
-] as const;
-
-export const deprecatedPlatforms = new Set<PlatformKey>([
-  'node-serverlesscloud',
-  'python-pylons',
-  'python-pymongo',
-]);
-
 export const sourceMaps: PlatformKey[] = [
 export const sourceMaps: PlatformKey[] = [
   ...frontend,
   ...frontend,
   'react-native',
   'react-native',
@@ -189,11 +142,11 @@ export const sourceMaps: PlatformKey[] = [
   'electron',
   'electron',
 ];
 ];
 
 
-export const tracing = [
+export const tracing: PlatformKey[] = [
   'python-tracing',
   'python-tracing',
   'node-tracing',
   'node-tracing',
   'react-native-tracing',
   'react-native-tracing',
-] as const;
+];
 
 
 export const performance: PlatformKey[] = [
 export const performance: PlatformKey[] = [
   'bun',
   'bun',
@@ -379,19 +332,3 @@ export const replayOnboardingPlatforms: readonly PlatformKey[] = [
   'javascript-vue',
   'javascript-vue',
   'javascript',
   'javascript',
 ];
 ];
-
-/**
- * Additional aliases used for filtering in the platform picker
- */
-export const filterAliases: Partial<Record<PlatformKey, string[]>> = {
-  native: ['cpp', 'c++'],
-};
-
-export default categoryList;
-
-export type Platform = {
-  key: PlatformKey;
-  id?: string;
-  link?: string | null;
-  name?: string;
-};

+ 173 - 0
static/app/data/platformPickerCategories.tsx

@@ -0,0 +1,173 @@
+import {t} from 'sentry/locale';
+import {PlatformKey} from 'sentry/types';
+
+const popularPlatformCategories: Set<PlatformKey> = new Set([
+  'android',
+  'apple-ios',
+  'dotnet',
+  'dotnet-aspnetcore',
+  'flutter',
+  'go',
+  'java',
+  'java-spring-boot',
+  'javascript',
+  'javascript-angular',
+  'javascript-nextjs',
+  'javascript-react',
+  'javascript-vue',
+  'node',
+  'node-express',
+  'php',
+  'php-laravel',
+  'python',
+  'python-django',
+  'python-fastapi',
+  'python-flask',
+  'react-native',
+  'ruby-rails',
+  'ruby',
+  'unity',
+]);
+
+const browser: Set<PlatformKey> = new Set([
+  'dart',
+  'javascript',
+  'javascript-angular',
+  'javascript-ember',
+  'javascript-gatsby',
+  'javascript-nextjs',
+  'javascript-react',
+  'javascript-remix',
+  'javascript-svelte',
+  'javascript-sveltekit',
+  'javascript-vue',
+  'unity',
+]);
+
+const server: Set<PlatformKey> = new Set([
+  'bun',
+  'dotnet',
+  'dotnet-aspnet',
+  'dotnet-aspnetcore',
+  'elixir',
+  'go',
+  'go-http',
+  'java',
+  'java-log4j2',
+  'java-logback',
+  'java-spring',
+  'java-spring-boot',
+  'kotlin',
+  'native',
+  'node',
+  'node-connect',
+  'node-express',
+  'node-koa',
+  'php',
+  'php-laravel',
+  'php-symfony',
+  'python',
+  'python-aiohttp',
+  'python-asgi',
+  'python-bottle',
+  'python-celery',
+  'python-chalice',
+  'python-django',
+  'python-falcon',
+  'python-fastapi',
+  'python-flask',
+  'python-pyramid',
+  'python-quart',
+  'python-rq',
+  'python-sanic',
+  'python-starlette',
+  'python-tornado',
+  'python-tryton',
+  'python-wsgi',
+  'ruby',
+  'ruby-rack',
+  'ruby-rails',
+  'rust',
+]);
+
+const mobile: Set<PlatformKey> = new Set([
+  'android',
+  'apple-ios',
+  'capacitor',
+  'cordova',
+  'dotnet-maui',
+  'dotnet-xamarin',
+  'flutter',
+  'ionic',
+  'react-native',
+  'unity',
+  'unreal',
+]);
+
+const desktop: Set<PlatformKey> = new Set([
+  'apple-macos',
+  'dotnet',
+  'dotnet-maui',
+  'dotnet-winforms',
+  'dotnet-wpf',
+  'electron',
+  'flutter',
+  'java',
+  'kotlin',
+  'minidump',
+  'native',
+  'native-qt',
+  'unity',
+  'unreal',
+]);
+
+const serverless: Set<PlatformKey> = new Set([
+  'dotnet-awslambda',
+  'dotnet-gcpfunctions',
+  'node-awslambda',
+  'node-azurefunctions',
+  'node-gcpfunctions',
+  'python-awslambda',
+  'python-gcpfunctions',
+  'python-serverless',
+]);
+
+export const createablePlatforms: Set<PlatformKey> = new Set([
+  ...popularPlatformCategories,
+  ...browser,
+  ...server,
+  ...mobile,
+  ...desktop,
+  ...serverless,
+]);
+
+/**
+ * Additional aliases used for filtering in the platform picker
+ */
+export const filterAliases: Partial<Record<PlatformKey, string[]>> = {
+  native: ['cpp', 'c++'],
+};
+
+const categoryList = [
+  {id: 'popular', name: t('Popular'), platforms: popularPlatformCategories},
+  {id: 'browser', name: t('Browser'), platforms: browser},
+  {id: 'server', name: t('Server'), platforms: server},
+  {id: 'mobile', name: t('Mobile'), platforms: mobile},
+  {id: 'desktop', name: t('Desktop'), platforms: desktop},
+  {id: 'serverless', name: t('Serverless'), platforms: serverless},
+  {
+    id: 'all',
+    name: t('All'),
+    platforms: createablePlatforms,
+  },
+];
+
+export default categoryList;
+
+// TODO(aknaus): Drop in favour of PlatformIntegration
+export type Platform = {
+  key: PlatformKey;
+  id?: string;
+  link?: string | null;
+  name?: string;
+};

+ 2 - 2
static/app/views/onboarding/onboarding.tsx

@@ -12,7 +12,7 @@ import LogoSentry from 'sentry/components/logoSentry';
 import {OnboardingContext} from 'sentry/components/onboarding/onboardingContext';
 import {OnboardingContext} from 'sentry/components/onboarding/onboardingContext';
 import {useRecentCreatedProject} from 'sentry/components/onboarding/useRecentCreatedProject';
 import {useRecentCreatedProject} from 'sentry/components/onboarding/useRecentCreatedProject';
 import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
 import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
-import categoryList from 'sentry/data/platformCategories';
+import categoryList from 'sentry/data/platformPickerCategories';
 import platforms from 'sentry/data/platforms';
 import platforms from 'sentry/data/platforms';
 import {IconArrow} from 'sentry/icons';
 import {IconArrow} from 'sentry/icons';
 import {t} from 'sentry/locale';
 import {t} from 'sentry/locale';
@@ -116,7 +116,7 @@ function Onboarding(props: Props) {
 
 
       const frameworkCategory =
       const frameworkCategory =
         categoryList.find(category => {
         categoryList.find(category => {
-          return category.platforms.includes(platform.id as never);
+          return category.platforms?.has(platform.id);
         })?.id ?? 'all';
         })?.id ?? 'all';
 
 
       onboardingContext.setData({
       onboardingContext.setData({

+ 3 - 5
static/app/views/projectInstall/platform.tsx

@@ -14,10 +14,8 @@ import {
   platformProductAvailability,
   platformProductAvailability,
   ProductSolution,
   ProductSolution,
 } from 'sentry/components/onboarding/productSelection';
 } from 'sentry/components/onboarding/productSelection';
-import {
-  performance as performancePlatforms,
-  Platform,
-} from 'sentry/data/platformCategories';
+import {performance as performancePlatforms} from 'sentry/data/platformCategories';
+import {Platform} from 'sentry/data/platformPickerCategories';
 import platforms from 'sentry/data/platforms';
 import platforms from 'sentry/data/platforms';
 import {t} from 'sentry/locale';
 import {t} from 'sentry/locale';
 import ConfigStore from 'sentry/stores/configStore';
 import ConfigStore from 'sentry/stores/configStore';
@@ -141,7 +139,7 @@ export function ProjectInstallPlatform({location, params}: Props) {
   );
   );
 
 
   const platform: Platform = {
   const platform: Platform = {
-    key: currentPlatformKey as PlatformKey,
+    key: currentPlatformKey,
     id: currentPlatform?.id,
     id: currentPlatform?.id,
     name: currentPlatform?.name,
     name: currentPlatform?.name,
     link: currentPlatform?.link,
     link: currentPlatform?.link,

+ 1 - 1
static/app/views/projectInstall/platformDocHeader.tsx

@@ -6,7 +6,7 @@ import {Button} from 'sentry/components/button';
 import ButtonBar from 'sentry/components/buttonBar';
 import ButtonBar from 'sentry/components/buttonBar';
 import Confirm from 'sentry/components/confirm';
 import Confirm from 'sentry/components/confirm';
 import {useRecentCreatedProject} from 'sentry/components/onboarding/useRecentCreatedProject';
 import {useRecentCreatedProject} from 'sentry/components/onboarding/useRecentCreatedProject';
-import {Platform} from 'sentry/data/platformCategories';
+import {Platform} from 'sentry/data/platformPickerCategories';
 import {IconChevron} from 'sentry/icons/iconChevron';
 import {IconChevron} from 'sentry/icons/iconChevron';
 import {t} from 'sentry/locale';
 import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import {space} from 'sentry/styles/space';