diff --git a/static/app/views/settings/project/projectOwnership/modal.tsx b/static/app/views/settings/project/projectOwnership/modal.tsx index ca5d01d7ede52d..a47417d1fa1c82 100644 --- a/static/app/views/settings/project/projectOwnership/modal.tsx +++ b/static/app/views/settings/project/projectOwnership/modal.tsx @@ -183,8 +183,6 @@ function ProjectOwnershipModal({ organization={organization} project={project} initialText={ownership?.raw || ''} - urls={urls} - paths={paths} dateUpdated={ownership.lastUpdated} onCancel={onCancel} page="issue_details" diff --git a/static/app/views/settings/project/projectOwnership/ownerInput.tsx b/static/app/views/settings/project/projectOwnership/ownerInput.tsx index c474a1d4d151f6..aaf57d3393ade4 100644 --- a/static/app/views/settings/project/projectOwnership/ownerInput.tsx +++ b/static/app/views/settings/project/projectOwnership/ownerInput.tsx @@ -1,4 +1,4 @@ -import {Component, Fragment} from 'react'; +import {Fragment, useState} from 'react'; import styled from '@emotion/styled'; import {Button} from '@sentry/scraps/button'; @@ -12,20 +12,12 @@ import PanelBody from 'sentry/components/panels/panelBody'; import PanelHeader from 'sentry/components/panels/panelHeader'; import TimeSince from 'sentry/components/timeSince'; import {t} from 'sentry/locale'; -import MemberListStore from 'sentry/stores/memberListStore'; -import ProjectsStore from 'sentry/stores/projectsStore'; import type {IssueOwnership} from 'sentry/types/group'; -import type {Organization, Team} from 'sentry/types/organization'; +import type {Organization} from 'sentry/types/organization'; import type {Project} from 'sentry/types/project'; import {defined} from 'sentry/utils'; import {trackIntegrationAnalytics} from 'sentry/utils/integrationUtil'; -const defaultProps = { - urls: [] as string[], - paths: [] as string[], - disabled: false, -}; - type Props = { dateUpdated: string | null; initialText: string; @@ -36,44 +28,40 @@ type Props = { */ page: 'issue_details' | 'project_settings'; project: Project; + disabled?: boolean; onSave?: (ownership: IssueOwnership) => void; -} & typeof defaultProps; - -type State = { - error: null | { - raw: string[]; - }; - hasChanges: boolean; - text: string | null; }; -class OwnerInput extends Component { - static defaultProps = defaultProps; - - state: State = { - hasChanges: false, - text: null, - error: null, - }; +type InputError = {raw: string[]}; - parseError(error: State['error']) { - const text = error?.raw?.[0]; - if (!text) { - return null; - } +function parseError(error: InputError | null) { + const text = error?.raw?.[0]; + if (!text) { + return null; + } - if (text.startsWith('Invalid rule owners:')) { - return {text}; - } - return ( - - ); + if (text.startsWith('Invalid rule owners:')) { + return {text}; } + return ; +} - handleUpdateOwnership = () => { - const {organization, project, onSave, page, initialText} = this.props; - const {text} = this.state; - this.setState({error: null}); +function OwnerInput({ + dateUpdated, + disabled = false, + initialText, + onCancel, + onSave, + organization, + page, + project, +}: Props) { + const [hasChanges, setHasChanges] = useState(false); + const [text, setText] = useState(null); + const [error, setError] = useState(null); + + const handleUpdateOwnership = () => { + setError(null); const api = new Client(); const request = api.requestPromise( @@ -87,13 +75,9 @@ class OwnerInput extends Component { request .then(ownership => { addSuccessMessage(t('Updated issue ownership rules')); - this.setState( - { - hasChanges: false, - text, - }, - () => onSave?.(ownership) - ); + setHasChanges(false); + setText(text); + onSave?.(ownership); trackIntegrationAnalytics('project_ownership.saved', { page, organization, @@ -102,22 +86,22 @@ class OwnerInput extends Component { initialText.split('\n').filter(x => x).length, }); }) - .catch(error => { - this.setState({error: error.responseJSON}); - if (error.status === 403) { + .catch(caught => { + setError(caught.responseJSON); + if (caught.status === 403) { addErrorMessage( t( "You don't have permission to modify issue ownership rules for this project" ) ); } else if ( - error.status === 400 && - error.responseJSON.raw?.[0].startsWith('Invalid rule owners:') + caught.status === 400 && + caught.responseJSON.raw?.[0].startsWith('Invalid rule owners:') ) { addErrorMessage( t( 'Unable to save issue ownership rule changes: %s', - error.responseJSON.raw[0] + caught.responseJSON.raw[0] ) ); } else { @@ -128,109 +112,71 @@ class OwnerInput extends Component { return request; }; - mentionableUsers() { - return MemberListStore.getAll().map(member => ({ - id: member.id, - display: member.email, - email: member.email, - })); - } - - mentionableTeams() { - const {project} = this.props; - const projectWithTeams = ProjectsStore.getBySlug(project.slug); - if (!projectWithTeams) { - return []; - } - return projectWithTeams.teams.map((team: Team) => ({ - id: team.id, - display: `#${team.slug}`, - email: team.id, - })); - } - - handleChange = (e: React.ChangeEvent) => { - this.setState({ - hasChanges: true, - text: e.target.value, - }); - }; - - handleAddRule = (rule: string) => { - const {initialText} = this.props; - this.setState( - ({text}) => ({ - text: (text || initialText) + '\n' + rule, - }), - this.handleUpdateOwnership - ); + const handleChange = (e: React.ChangeEvent) => { + setHasChanges(true); + setText(e.target.value); }; - render() { - const {disabled, initialText, dateUpdated} = this.props; - const {hasChanges, text, error} = this.state; - - return ( - -
{ - if (e.metaKey && e.key === 'Enter') { - this.handleUpdateOwnership(); - } - }} - > - - - {t('Ownership Rules')} - - {dateUpdated && ( - - {t('Last Edited')} - - )} - - - - - - -
{this.parseError(error)}
- - - - -
-
-
- ); - } + return ( + +
{ + if (e.metaKey && e.key === 'Enter') { + handleUpdateOwnership(); + } + }} + > + + + {t('Ownership Rules')} + + {dateUpdated && ( + + {t('Last Edited')} + + )} + + + + + + +
{parseError(error)}
+ + + + +
+
+
+ ); } const TEXTAREA_PADDING = 4;