Skip to content

Commit 50cb859

Browse files
authored
fix(auth): Disable the Save New Auth Token button while a request is already in-flight (#92313)
After clicking save: ![SCR-20250527-hoxm](https://github.com/user-attachments/assets/98f10a21-749a-4a7e-9853-43a31932b639) And when the save is complete: ![SCR-20250527-hoys](https://github.com/user-attachments/assets/02970395-c198-4f68-8211-609dc4e896b6)
1 parent fcaf6b6 commit 50cb859

File tree

2 files changed

+10
-37
lines changed

2 files changed

+10
-37
lines changed

static/app/views/settings/organizationAuthTokens/newAuthToken.spec.tsx

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,14 @@
1-
import {initializeOrg} from 'sentry-test/initializeOrg';
21
import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
32

43
import * as indicators from 'sentry/actionCreators/indicator';
5-
import OrganizationsStore from 'sentry/stores/organizationsStore';
64
import type {OrgAuthToken} from 'sentry/types/user';
7-
import {OrganizationAuthTokensNewAuthToken} from 'sentry/views/settings/organizationAuthTokens/newAuthToken';
5+
import OrganizationAuthTokensNewAuthToken from 'sentry/views/settings/organizationAuthTokens/newAuthToken';
86

97
describe('OrganizationAuthTokensNewAuthToken', function () {
108
const ENDPOINT = '/organizations/org-slug/org-auth-tokens/';
11-
const {organization, router} = initializeOrg();
12-
13-
const defaultProps = {
14-
organization,
15-
router,
16-
location: router.location,
17-
params: {orgId: organization.slug},
18-
routes: router.routes,
19-
route: {},
20-
routeParams: router.params,
21-
};
22-
23-
beforeEach(function () {
24-
OrganizationsStore.addOrReplace(organization);
25-
});
26-
27-
afterEach(function () {
28-
MockApiClient.clearMockResponses();
29-
});
309

3110
it('can create token', async function () {
32-
render(<OrganizationAuthTokensNewAuthToken {...defaultProps} />);
11+
render(<OrganizationAuthTokensNewAuthToken />);
3312

3413
const generatedToken: OrgAuthToken & {token: string} = {
3514
id: '1',
@@ -65,7 +44,7 @@ describe('OrganizationAuthTokensNewAuthToken', function () {
6544
it('handles API errors when creating token', async function () {
6645
jest.spyOn(indicators, 'addErrorMessage');
6746

68-
render(<OrganizationAuthTokensNewAuthToken {...defaultProps} />);
47+
render(<OrganizationAuthTokensNewAuthToken />);
6948

7049
const mock = MockApiClient.addMockResponse({
7150
url: ENDPOINT,
@@ -98,7 +77,7 @@ describe('OrganizationAuthTokensNewAuthToken', function () {
9877
it('handles missing_system_url_prefix API error when creating token', async function () {
9978
jest.spyOn(indicators, 'addErrorMessage');
10079

101-
render(<OrganizationAuthTokensNewAuthToken {...defaultProps} />);
80+
render(<OrganizationAuthTokensNewAuthToken />);
10281

10382
const mock = MockApiClient.addMockResponse({
10483
url: ENDPOINT,

static/app/views/settings/organizationAuthTokens/newAuthToken.tsx

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {useMutation, useQueryClient} from 'sentry/utils/queryClient';
2323
import type RequestError from 'sentry/utils/requestError/requestError';
2424
import useApi from 'sentry/utils/useApi';
2525
import {useNavigate} from 'sentry/utils/useNavigate';
26-
import withOrganization from 'sentry/utils/withOrganization';
26+
import useOrganization from 'sentry/utils/useOrganization';
2727
import NewTokenHandler from 'sentry/views/settings/components/newTokenHandler';
2828
import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
2929
import TextBlock from 'sentry/views/settings/components/text/textBlock';
@@ -57,7 +57,7 @@ function AuthTokenCreateForm({
5757
[navigate, organization.slug]
5858
);
5959

60-
const {mutate: submitToken} = useMutation<
60+
const {mutate: submitToken, isPending} = useMutation<
6161
CreateOrgAuthTokensResponse,
6262
RequestError,
6363
CreateTokenQueryVariables
@@ -102,13 +102,12 @@ function AuthTokenCreateForm({
102102
initialData={initialData}
103103
apiEndpoint={`/organizations/${organization.slug}/org-auth-tokens/`}
104104
onSubmit={({name}) => {
105-
submitToken({
106-
name,
107-
});
105+
submitToken({name});
108106
}}
109107
onCancel={handleGoBack}
110108
submitLabel={t('Create Auth Token')}
111109
requireChanges
110+
submitDisabled={isPending}
112111
>
113112
<TextField
114113
name="name"
@@ -130,11 +129,8 @@ function AuthTokenCreateForm({
130129
);
131130
}
132131

133-
export function OrganizationAuthTokensNewAuthToken({
134-
organization,
135-
}: {
136-
organization: Organization;
137-
}) {
132+
export default function OrganizationAuthTokensNewAuthToken() {
133+
const organization = useOrganization();
138134
const navigate = useNavigate();
139135
const [newToken, setNewToken] = useState<OrgAuthTokenWithToken | null>(null);
140136

@@ -182,8 +178,6 @@ export function OrganizationAuthTokensNewAuthToken({
182178
);
183179
}
184180

185-
export default withOrganization(OrganizationAuthTokensNewAuthToken);
186-
187181
const ScopeHelpText = styled('div')`
188182
color: ${p => p.theme.subText};
189183
`;

0 commit comments

Comments
 (0)