From 6d95edeb3b7c3aea57937cf96149afeae2c5a800 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 17 Jan 2025 16:07:37 +0100 Subject: [PATCH 1/2] ref(onboarding): Introduce project settings field to native platforms --- .../storeCrashReportsConfig.tsx | 74 +++++++++++++++++++ .../forms/projectSecurityAndPrivacyGroups.tsx | 8 ++ .../gettingStartedDocs/minidump/minidump.tsx | 13 +++- static/app/gettingStartedDocs/unity/unity.tsx | 12 ++- .../app/gettingStartedDocs/unreal/unreal.tsx | 10 +++ 5 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 static/app/components/onboarding/gettingStartedDoc/storeCrashReportsConfig.tsx diff --git a/static/app/components/onboarding/gettingStartedDoc/storeCrashReportsConfig.tsx b/static/app/components/onboarding/gettingStartedDoc/storeCrashReportsConfig.tsx new file mode 100644 index 00000000000000..f044081de4b80d --- /dev/null +++ b/static/app/components/onboarding/gettingStartedDoc/storeCrashReportsConfig.tsx @@ -0,0 +1,74 @@ +import styled from '@emotion/styled'; + +import {addErrorMessage} from 'sentry/actionCreators/indicator'; +import {hasEveryAccess} from 'sentry/components/acl/access'; +import Form from 'sentry/components/forms/form'; +import JsonForm from 'sentry/components/forms/jsonForm'; +import Panel from 'sentry/components/panels/panel'; +import Placeholder from 'sentry/components/placeholder'; +import projectSecurityAndPrivacyGroups from 'sentry/data/forms/projectSecurityAndPrivacyGroups'; +import ProjectsStore from 'sentry/stores/projectsStore'; +import type {Organization} from 'sentry/types/organization'; +import type {Project} from 'sentry/types/project'; +import {useDetailedProject} from 'sentry/utils/useDetailedProject'; + +interface StoreCrashReportsConfigProps { + organization: Organization; + projectSlug: Project['slug']; +} + +export function StoreCrashReportsConfig({ + projectSlug, + organization, +}: StoreCrashReportsConfigProps) { + const {data: project, isPending: isPendingProject} = useDetailedProject({ + orgSlug: organization.slug, + projectSlug, + }); + + if (isPendingProject) { + // 72px is the height of the form + return ; + } + + const storeCrashReportsField = projectSecurityAndPrivacyGroups + .flatMap(group => group.fields) + .find(field => field.name === 'storeCrashReports'); + + if (!project || !storeCrashReportsField) { + return null; + } + + return ( +
{ + // This will update our project global state + ProjectsStore.onUpdateSuccess(data); + }} + onSubmitError={() => addErrorMessage('Unable to save change')} + > + + + ); +} + +const StyledJsonForm = styled(JsonForm)` + ${Panel} { + margin-bottom: 0; + } +`; diff --git a/static/app/data/forms/projectSecurityAndPrivacyGroups.tsx b/static/app/data/forms/projectSecurityAndPrivacyGroups.tsx index 452676a38f3256..087b84a70adcc6 100644 --- a/static/app/data/forms/projectSecurityAndPrivacyGroups.tsx +++ b/static/app/data/forms/projectSecurityAndPrivacyGroups.tsx @@ -43,9 +43,11 @@ function hasProjectWriteAndOrgOverride({ function projectWriteAndOrgOverrideDisabledReason({ organization, name, + project, }: { name: string; organization: Organization; + project: Project; }) { if (hasOrgOverride({organization, name})) { return t( @@ -53,6 +55,10 @@ function projectWriteAndOrgOverrideDisabledReason({ ); } + if (!hasEveryAccess(['project:write'], {organization, project})) { + return t("You do not have permission to modify this project's setting."); + } + return null; } @@ -61,6 +67,8 @@ const formGroups: JsonFormObject[] = [ title: t('Security & Privacy'), fields: [ { + disabled: hasProjectWriteAndOrgOverride, + disabledReason: projectWriteAndOrgOverrideDisabledReason, name: 'storeCrashReports', type: 'select', label: t('Store Minidumps As Attachments'), diff --git a/static/app/gettingStartedDocs/minidump/minidump.tsx b/static/app/gettingStartedDocs/minidump/minidump.tsx index 00140f5dc47539..c749e67adafbd1 100644 --- a/static/app/gettingStartedDocs/minidump/minidump.tsx +++ b/static/app/gettingStartedDocs/minidump/minidump.tsx @@ -3,6 +3,7 @@ import {Fragment} from 'react'; import ExternalLink from 'sentry/components/links/externalLink'; import List from 'sentry/components/list'; import ListItem from 'sentry/components/list/listItem'; +import {StoreCrashReportsConfig} from 'sentry/components/onboarding/gettingStartedDoc/storeCrashReportsConfig'; import type { Docs, DocsParams, @@ -70,7 +71,17 @@ const onboarding: OnboardingConfig = { }, ], configure: () => [], - verify: () => [], + verify: params => [ + { + title: t('Further Settings'), + description: ( + + ), + }, + ], }; const docs: Docs = { diff --git a/static/app/gettingStartedDocs/unity/unity.tsx b/static/app/gettingStartedDocs/unity/unity.tsx index b0a8aa3a641b97..6751b00beaf6e3 100644 --- a/static/app/gettingStartedDocs/unity/unity.tsx +++ b/static/app/gettingStartedDocs/unity/unity.tsx @@ -4,6 +4,7 @@ import styled from '@emotion/styled'; import {Alert} from 'sentry/components/alert'; import ExternalLink from 'sentry/components/links/externalLink'; import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step'; +import {StoreCrashReportsConfig} from 'sentry/components/onboarding/gettingStartedDoc/storeCrashReportsConfig'; import type { Docs, OnboardingConfig, @@ -94,7 +95,7 @@ const onboarding: OnboardingConfig = { ), }, ], - verify: () => [ + verify: params => [ { type: StepType.VERIFY, description: t( @@ -130,6 +131,15 @@ const onboarding: OnboardingConfig = { ), }, + { + title: t('Further Settings'), + description: ( + + ), + }, ], }; diff --git a/static/app/gettingStartedDocs/unreal/unreal.tsx b/static/app/gettingStartedDocs/unreal/unreal.tsx index bb3570ca8db814..8c5de8938dfd80 100644 --- a/static/app/gettingStartedDocs/unreal/unreal.tsx +++ b/static/app/gettingStartedDocs/unreal/unreal.tsx @@ -4,6 +4,7 @@ import styled from '@emotion/styled'; import {Alert} from 'sentry/components/alert'; import ExternalLink from 'sentry/components/links/externalLink'; import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step'; +import {StoreCrashReportsConfig} from 'sentry/components/onboarding/gettingStartedDoc/storeCrashReportsConfig'; import type { Docs, DocsParams, @@ -210,6 +211,15 @@ const onboarding: OnboardingConfig = { ), }, + { + title: t('Further Settings'), + description: ( + + ), + }, ], }; From 2989057ce651b6ace907c9f86bbeb15b63238503 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Fri, 17 Jan 2025 16:26:11 +0100 Subject: [PATCH 2/2] fix tests --- .../app/gettingStartedDocs/minidump/minidump.spec.tsx | 11 +++++++++++ static/app/gettingStartedDocs/unity/unity.spec.tsx | 11 +++++++++++ static/app/gettingStartedDocs/unreal/unreal.spec.tsx | 11 +++++++++++ 3 files changed, 33 insertions(+) diff --git a/static/app/gettingStartedDocs/minidump/minidump.spec.tsx b/static/app/gettingStartedDocs/minidump/minidump.spec.tsx index 7b92a54edb0061..0103d6619b272c 100644 --- a/static/app/gettingStartedDocs/minidump/minidump.spec.tsx +++ b/static/app/gettingStartedDocs/minidump/minidump.spec.tsx @@ -1,10 +1,21 @@ +import {ProjectFixture} from 'sentry-fixture/project'; + import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout'; import {screen} from 'sentry-test/reactTestingLibrary'; import docs from './minidump'; +function renderMockRequests() { + MockApiClient.addMockResponse({ + url: '/organizations/org-slug/projects/', + body: [ProjectFixture()], + }); +} + describe('getting started with minidump', function () { it('renders gradle docs correctly', function () { + renderMockRequests(); + renderWithOnboardingLayout(docs); // Renders main headings diff --git a/static/app/gettingStartedDocs/unity/unity.spec.tsx b/static/app/gettingStartedDocs/unity/unity.spec.tsx index 35a5d86522899d..b13483ece0537b 100644 --- a/static/app/gettingStartedDocs/unity/unity.spec.tsx +++ b/static/app/gettingStartedDocs/unity/unity.spec.tsx @@ -1,11 +1,22 @@ +import {ProjectFixture} from 'sentry-fixture/project'; + import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout'; import {screen} from 'sentry-test/reactTestingLibrary'; import {textWithMarkupMatcher} from 'sentry-test/utils'; import docs from './unity'; +function renderMockRequests() { + MockApiClient.addMockResponse({ + url: '/organizations/org-slug/projects/', + body: [ProjectFixture()], + }); +} + describe('unity onboarding docs', function () { it('renders docs correctly', async function () { + renderMockRequests(); + renderWithOnboardingLayout(docs, { releaseRegistry: { 'sentry.dotnet.unity': { diff --git a/static/app/gettingStartedDocs/unreal/unreal.spec.tsx b/static/app/gettingStartedDocs/unreal/unreal.spec.tsx index 1183a45c7db3c7..4da828fefef537 100644 --- a/static/app/gettingStartedDocs/unreal/unreal.spec.tsx +++ b/static/app/gettingStartedDocs/unreal/unreal.spec.tsx @@ -1,10 +1,21 @@ +import {ProjectFixture} from 'sentry-fixture/project'; + import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout'; import {screen} from 'sentry-test/reactTestingLibrary'; import docs from './unreal'; +function renderMockRequests() { + MockApiClient.addMockResponse({ + url: '/organizations/org-slug/projects/', + body: [ProjectFixture()], + }); +} + describe('getting started with unreal', function () { it('renders docs correctly', function () { + renderMockRequests(); + renderWithOnboardingLayout(docs); // Renders main headings