Browse Source

ref(app-store-connect): Add new design changes (#26357)

Priscila Oliveira 3 years ago
parent
commit
d6b3b45573

+ 17 - 21
static/app/components/globalAppStoreConnectUpdateAlert/updateAlert.tsx

@@ -15,7 +15,7 @@ import {AppStoreConnectValidationData} from 'app/types/debugFiles';
 import {promptIsDismissed} from 'app/utils/promptIsDismissed';
 import withApi from 'app/utils/withApi';
 
-import {getAppConnectStoreUpdateAlertMessage} from './utils';
+import {appStoreConnectAlertMessage, getAppConnectStoreUpdateAlertMessage} from './utils';
 
 const APP_STORE_CONNECT_UPDATES = 'app_store_connect_updates';
 
@@ -77,28 +77,24 @@ function UpdateAlert({api, Wrapper, isCompact, project, organization, className}
       return null;
     }
 
-    if (appConnectValidationData.appstoreCredentialsValid === false) {
-      return (
-        <div>
-          {appConnectStoreUpdateAlertMessage}&nbsp;
-          {isCompact ? (
-            <Link to={projectSettingsLink}>
-              {t('Update it in the project settings to reconnect.')}
-            </Link>
-          ) : undefined}
-        </div>
-      );
-    }
-
-    const commonMessage = isCompact ? (
-      <Link to={`${projectSettingsLink}&revalidateItunesSession=true`}>
-        {t('Update it in the project settings to reconnect.')}
-      </Link>
-    ) : undefined;
-
     return (
       <div>
-        {appConnectStoreUpdateAlertMessage}&nbsp;{commonMessage}
+        {appConnectStoreUpdateAlertMessage}&nbsp;
+        {isCompact && (
+          <Link
+            to={
+              appConnectStoreUpdateAlertMessage ===
+              appStoreConnectAlertMessage.appStoreCredentialsInvalid
+                ? projectSettingsLink
+                : `${projectSettingsLink}&revalidateItunesSession=true`
+            }
+          >
+            {appConnectStoreUpdateAlertMessage ===
+            appStoreConnectAlertMessage.isTodayAfterItunesSessionRefreshAt
+              ? t('We recommend that you update it in the project settings.')
+              : t('Update it in the project settings to reconnect.')}
+          </Link>
+        )}
       </div>
     );
   }

+ 20 - 26
static/app/components/globalAppStoreConnectUpdateAlert/utils.tsx

@@ -1,17 +1,29 @@
 import moment from 'moment';
 
-import {t, tct} from 'app/locale';
+import {t} from 'app/locale';
 import {AppStoreConnectValidationData} from 'app/types/debugFiles';
 
+export const appStoreConnectAlertMessage = {
+  iTunesSessionInvalid: t(
+    'The iTunes session of your configured App Store Connect has expired.'
+  ),
+  appStoreCredentialsInvalid: t(
+    'The credentials of your configured App Store Connect are invalid.'
+  ),
+  isTodayAfterItunesSessionRefreshAt: t(
+    'The iTunes session of your configured App Store Connect will likely expire soon.'
+  ),
+};
+
 export function getAppConnectStoreUpdateAlertMessage(
   appConnectValidationData: AppStoreConnectValidationData
 ) {
   if (appConnectValidationData.itunesSessionValid === false) {
-    return t('The iTunes session of your configured App Store Connect has expired.');
+    return appStoreConnectAlertMessage.iTunesSessionInvalid;
   }
 
   if (appConnectValidationData.appstoreCredentialsValid === false) {
-    return t('The credentials of your configured App Store Connect are invalid.');
+    return appStoreConnectAlertMessage.appStoreCredentialsInvalid;
   }
 
   const itunesSessionRefreshAt = appConnectValidationData.itunesSessionRefreshAt;
@@ -20,31 +32,13 @@ export function getAppConnectStoreUpdateAlertMessage(
     return undefined;
   }
 
-  const foreseenDaysLeftForTheITunesSessionToExpire = moment(itunesSessionRefreshAt).diff(
-    moment(),
-    'days'
+  const isTodayAfterItunesSessionRefreshAt = moment().isAfter(
+    moment(itunesSessionRefreshAt)
   );
 
-  if (foreseenDaysLeftForTheITunesSessionToExpire === 0) {
-    return t(
-      'We recommend that you update the iTunes session of your configured App Store Connect as it will likely expire today.'
-    );
-  }
-
-  if (foreseenDaysLeftForTheITunesSessionToExpire === 1) {
-    return t(
-      'We recommend that you update the iTunes session of your configured App Store Connect as it will likely expire tomorrow.'
-    );
-  }
-
-  if (foreseenDaysLeftForTheITunesSessionToExpire <= 6) {
-    return tct(
-      'We recommend that you update the iTunes session of your configured App Store Connect as it will likely expire in [days] days.',
-      {
-        days: foreseenDaysLeftForTheITunesSessionToExpire,
-      }
-    );
+  if (!isTodayAfterItunesSessionRefreshAt) {
+    return undefined;
   }
 
-  return undefined;
+  return appStoreConnectAlertMessage.isTodayAfterItunesSessionRefreshAt;
 }

+ 0 - 49
static/app/components/modals/debugFileCustomRepository/appStoreConnect/accordion.tsx

@@ -1,49 +0,0 @@
-import React, {useState} from 'react';
-import styled from '@emotion/styled';
-
-import ListItem from 'app/components/list/listItem';
-import {Panel} from 'app/components/panels';
-import {IconChevron} from 'app/icons';
-import space from 'app/styles/space';
-
-type Props = {
-  summary: string;
-  children: React.ReactNode;
-  defaultExpanded?: boolean;
-};
-
-function Accordion({summary, defaultExpanded, children}: Props) {
-  const [isExpanded, setIsExpanded] = useState(!!defaultExpanded);
-
-  return (
-    <ListItem>
-      <StyledPanel>
-        <Summary onClick={() => setIsExpanded(!isExpanded)}>
-          {summary}
-          <IconChevron direction={isExpanded ? 'down' : 'right'} color="gray400" />
-        </Summary>
-        {isExpanded && <Details>{children}</Details>}
-      </StyledPanel>
-    </ListItem>
-  );
-}
-
-export default Accordion;
-
-const StyledPanel = styled(Panel)`
-  padding: ${space(1.5)};
-  margin-bottom: 0;
-`;
-
-const Summary = styled('div')`
-  display: grid;
-  grid-template-columns: 1fr max-content;
-  grid-gap: ${space(1)};
-  cursor: pointer;
-  padding-left: calc(${space(3)} + ${space(1)});
-  align-items: center;
-`;
-
-const Details = styled('div')`
-  padding-top: ${space(1.5)};
-`;

+ 0 - 246
static/app/components/modals/debugFileCustomRepository/appStoreConnect/appStoreCredentials/form.tsx

@@ -1,246 +0,0 @@
-import {Fragment, useState} from 'react';
-import styled from '@emotion/styled';
-
-import {addErrorMessage} from 'app/actionCreators/indicator';
-import {Client} from 'app/api';
-import Alert from 'app/components/alert';
-import {IconWarning} from 'app/icons';
-import {t} from 'app/locale';
-import {Organization, Project} from 'app/types';
-import Input from 'app/views/settings/components/forms/controls/input';
-import Textarea from 'app/views/settings/components/forms/controls/textarea';
-import Field from 'app/views/settings/components/forms/field';
-import SelectField from 'app/views/settings/components/forms/selectField';
-
-import Stepper from '../stepper';
-import StepActions from '../stepper/stepActions';
-import {
-  App,
-  AppStoreCredentialsData,
-  AppStoreCredentialsStepOneData,
-  AppStoreCredentialsStepTwoData,
-} from '../types';
-
-const steps = [t('Enter your credentials'), t('Choose an application')];
-
-type Props = {
-  api: Client;
-  orgSlug: Organization['slug'];
-  projectSlug: Project['slug'];
-  data: AppStoreCredentialsData;
-  onChange: (data: AppStoreCredentialsData) => void;
-  onSwitchToReadMode: () => void;
-  onCancel?: () => void;
-};
-
-function Form({
-  api,
-  orgSlug,
-  projectSlug,
-  data,
-  onChange,
-  onCancel,
-  onSwitchToReadMode,
-}: Props) {
-  const [activeStep, setActiveStep] = useState(0);
-  const [isLoading, setIsLoading] = useState(false);
-
-  const [appStoreApps, setAppStoreApps] = useState<App[]>([]);
-
-  const [stepOneData, setStepOneData] = useState<AppStoreCredentialsStepOneData>({
-    issuer: data.issuer,
-    keyId: data.keyId,
-    privateKey: data.privateKey,
-  });
-
-  const [stepTwoData, setStepTwoData] = useState<AppStoreCredentialsStepTwoData>({
-    app: data.app,
-  });
-
-  function isFormInvalid() {
-    switch (activeStep) {
-      case 0:
-        return Object.keys(stepOneData).some(key => !stepOneData[key]);
-      case 1:
-        return Object.keys(stepTwoData).some(key => !stepTwoData[key]);
-      default:
-        return false;
-    }
-  }
-
-  function goNext() {
-    setActiveStep(prevActiveStep => prevActiveStep + 1);
-  }
-
-  function handleGoBack() {
-    setActiveStep(prevActiveStep => prevActiveStep - 1);
-  }
-
-  function handleGoNext() {
-    checkAppStoreConnectCredentials();
-  }
-
-  function handleSave() {
-    const updatedData = {
-      ...stepOneData,
-      ...stepTwoData,
-    };
-
-    onChange(updatedData);
-    onSwitchToReadMode();
-  }
-
-  async function checkAppStoreConnectCredentials() {
-    setIsLoading(true);
-    try {
-      const response = await api.requestPromise(
-        `/projects/${orgSlug}/${projectSlug}/appstoreconnect/apps/`,
-        {
-          method: 'POST',
-          data: {
-            appconnectIssuer: stepOneData.issuer,
-            appconnectKey: stepOneData.keyId,
-            appconnectPrivateKey: stepOneData.privateKey,
-          },
-        }
-      );
-
-      setAppStoreApps(response.apps);
-      setStepTwoData({app: response.apps[0]});
-      setIsLoading(false);
-      goNext();
-    } catch {
-      setIsLoading(false);
-      addErrorMessage(
-        t(
-          'We could not establish a connection with App Store Connect. Please check the entered App Store Connect credentials.'
-        )
-      );
-    }
-  }
-
-  function renderStepContent(stepIndex: number) {
-    switch (stepIndex) {
-      case 0:
-        return (
-          <Fragment>
-            <Field
-              label={t('Issuer')}
-              inline={false}
-              flexibleControlStateSize
-              stacked
-              required
-            >
-              <Input
-                type="text"
-                name="issuer"
-                placeholder={t('Issuer')}
-                value={stepOneData.issuer}
-                onChange={e =>
-                  setStepOneData({
-                    ...stepOneData,
-                    issuer: e.target.value,
-                  })
-                }
-              />
-            </Field>
-            <Field
-              label={t('Key ID')}
-              inline={false}
-              flexibleControlStateSize
-              stacked
-              required
-            >
-              <Input
-                type="text"
-                name="keyId"
-                placeholder={t('Key Id')}
-                value={stepOneData.keyId}
-                onChange={e =>
-                  setStepOneData({
-                    ...stepOneData,
-                    keyId: e.target.value,
-                  })
-                }
-              />
-            </Field>
-            <Field
-              label={t('Private Key')}
-              inline={false}
-              flexibleControlStateSize
-              stacked
-              required
-            >
-              <Textarea
-                name="privateKey"
-                placeholder={t('Private Key')}
-                value={stepOneData.privateKey}
-                rows={5}
-                maxRows={5}
-                autosize
-                onChange={e =>
-                  setStepOneData({
-                    ...stepOneData,
-                    privateKey: e.target.value,
-                  })
-                }
-              />
-            </Field>
-          </Fragment>
-        );
-      case 1:
-        return (
-          <StyledSelectField
-            name="application"
-            label={t('App Store Connect Application')}
-            choices={appStoreApps.map(appStoreApp => [
-              appStoreApp.appId,
-              appStoreApp.name,
-            ])}
-            placeholder={t('Select application')}
-            onChange={appId => {
-              const selectedAppStoreApp = appStoreApps.find(
-                appStoreApp => appStoreApp.appId === appId
-              );
-              setStepTwoData({app: selectedAppStoreApp});
-            }}
-            value={stepTwoData.app?.appId ?? ''}
-            inline={false}
-            flexibleControlStateSize
-            stacked
-            required
-          />
-        );
-      default:
-        return (
-          <Alert type="error" icon={<IconWarning />}>
-            {t('This step could not be found.')}
-          </Alert>
-        );
-    }
-  }
-
-  return (
-    <Stepper
-      activeStep={activeStep}
-      steps={steps}
-      renderStepContent={index => renderStepContent(index)}
-      renderStepActions={index => (
-        <StepActions
-          onGoBack={index !== 0 ? handleGoBack : undefined}
-          onGoNext={index !== steps.length - 1 ? handleGoNext : undefined}
-          onCancel={onCancel}
-          onFinish={handleSave}
-          primaryButtonDisabled={isFormInvalid() || isLoading}
-          isLoading={isLoading}
-        />
-      )}
-    />
-  );
-}
-
-export default Form;
-
-const StyledSelectField = styled(SelectField)`
-  padding-right: 0;
-`;

+ 0 - 62
static/app/components/modals/debugFileCustomRepository/appStoreConnect/appStoreCredentials/index.tsx

@@ -1,62 +0,0 @@
-import {Client} from 'app/api';
-import {t} from 'app/locale';
-import {Organization, Project} from 'app/types';
-
-import Card from '../card';
-import CardItem from '../cardItem';
-import {AppStoreCredentialsData} from '../types';
-
-import Form from './form';
-
-type Props = {
-  api: Client;
-  orgSlug: Organization['slug'];
-  projectSlug: Project['slug'];
-  isUpdating: boolean;
-  data: AppStoreCredentialsData;
-  isEditing: boolean;
-  onChange: (data: AppStoreCredentialsData) => void;
-  onEdit: (isEditing: boolean) => void;
-  onReset: () => void;
-};
-
-function AppStoreCredentials({
-  data,
-  isUpdating,
-  onReset,
-  isEditing,
-  onEdit,
-  ...props
-}: Props) {
-  function handleSwitchToReadMode() {
-    onEdit(false);
-  }
-
-  function handleCancel() {
-    onEdit(false);
-    onReset();
-  }
-
-  if (isEditing) {
-    return (
-      <Form
-        {...props}
-        data={data}
-        onSwitchToReadMode={handleSwitchToReadMode}
-        onCancel={isUpdating ? handleCancel : undefined}
-      />
-    );
-  }
-
-  return (
-    <Card onEdit={() => onEdit(true)}>
-      {data.issuer && <CardItem label={t('Issuer')} value={data.issuer} />}
-      {data.keyId && <CardItem label={t('Key Id')} value={data.keyId} />}
-      {data.app?.name && (
-        <CardItem label={t('App Store Connect Application')} value={data.app?.name} />
-      )}
-    </Card>
-  );
-}
-
-export default AppStoreCredentials;

+ 0 - 51
static/app/components/modals/debugFileCustomRepository/appStoreConnect/card.tsx

@@ -1,51 +0,0 @@
-import styled from '@emotion/styled';
-
-import Button from 'app/components/button';
-import {IconEdit, IconLock} from 'app/icons';
-import {t} from 'app/locale';
-import space from 'app/styles/space';
-
-type Props = {
-  children: React.ReactNode;
-  onEdit: () => void;
-};
-
-function Card({children, onEdit}: Props) {
-  return (
-    <Wrapper>
-      <IconWrapper>
-        <IconLock size="lg" />
-      </IconWrapper>
-      <Content>{children}</Content>
-      <Action>
-        <Button icon={<IconEdit />} label={t('Edit')} size="small" onClick={onEdit} />
-      </Action>
-    </Wrapper>
-  );
-}
-
-export default Card;
-
-const Wrapper = styled('div')`
-  display: grid;
-  grid-template-columns: max-content 1fr max-content;
-  grid-gap: ${space(1)};
-`;
-
-const Content = styled('div')`
-  display: flex;
-  justify-content: center;
-  flex-direction: column;
-  font-size: ${p => p.theme.fontSizeMedium};
-`;
-
-const IconWrapper = styled('div')`
-  display: flex;
-  align-items: center;
-  padding: 0 ${space(1.5)};
-`;
-
-const Action = styled('div')`
-  display: flex;
-  align-items: center;
-`;

+ 0 - 25
static/app/components/modals/debugFileCustomRepository/appStoreConnect/cardItem.tsx

@@ -1,25 +0,0 @@
-import styled from '@emotion/styled';
-
-import space from 'app/styles/space';
-
-type Props = {
-  label: string;
-  value: string;
-};
-
-function CardItem({label, value}: Props) {
-  return (
-    <Wrapper>
-      <strong>{`${label}:`}</strong>
-      {value}
-    </Wrapper>
-  );
-}
-
-export default CardItem;
-
-const Wrapper = styled('div')`
-  display: grid;
-  grid-template-columns: max-content 1fr;
-  grid-gap: ${space(1)};
-`;

+ 462 - 196
static/app/components/modals/debugFileCustomRepository/appStoreConnect/index.tsx

@@ -1,6 +1,5 @@
-import {Fragment, useState} from 'react';
+import {Fragment, useEffect, useState} from 'react';
 import styled from '@emotion/styled';
-import isEqual from 'lodash/isEqual';
 
 import {addErrorMessage, addSuccessMessage} from 'app/actionCreators/indicator';
 import {ModalRenderProps} from 'app/actionCreators/modal';
@@ -8,18 +7,32 @@ import {Client} from 'app/api';
 import Alert from 'app/components/alert';
 import Button from 'app/components/button';
 import ButtonBar from 'app/components/buttonBar';
-import List from 'app/components/list';
-import {IconInfo, IconWarning} from 'app/icons';
-import {t} from 'app/locale';
-import space from 'app/styles/space';
+import {
+  appStoreConnectAlertMessage,
+  getAppConnectStoreUpdateAlertMessage,
+} from 'app/components/globalAppStoreConnectUpdateAlert/utils';
+import LoadingIndicator from 'app/components/loadingIndicator';
+import {AppStoreConnectContextProps} from 'app/components/projects/appStoreConnectContext';
+import {IconWarning} from 'app/icons';
+import {t, tct} from 'app/locale';
+import space, {ValidSize} from 'app/styles/space';
 import {Organization, Project} from 'app/types';
-import {AppStoreConnectValidationData} from 'app/types/debugFiles';
 import withApi from 'app/utils/withApi';
 
-import Accordion from './accordion';
-import AppStoreCredentials from './appStoreCredentials';
-import ItunesCredentials from './itunesCredentials';
-import {AppStoreCredentialsData, ItunesCredentialsData} from './types';
+import StepFifth from './stepFifth';
+import StepFour from './stepFour';
+import StepOne from './stepOne';
+import StepThree from './stepThree';
+import StepTwo from './stepTwo';
+import {
+  AppleStoreOrg,
+  AppStoreApp,
+  StepFifthData,
+  StepFourData,
+  StepOneData,
+  StepThreeData,
+  StepTwoData,
+} from './types';
 
 type IntialData = {
   appId: string;
@@ -38,17 +51,26 @@ type IntialData = {
   type: string;
 };
 
-type Props = Pick<ModalRenderProps, 'Body' | 'Footer' | 'closeModal'> & {
+type Props = Pick<ModalRenderProps, 'Header' | 'Body' | 'Footer' | 'closeModal'> & {
   api: Client;
   orgSlug: Organization['slug'];
   projectSlug: Project['slug'];
   onSubmit: (data: Record<string, any>) => void;
   revalidateItunesSession: boolean;
-  appStoreConnectValidationData?: AppStoreConnectValidationData;
+  appStoreConnectContext?: AppStoreConnectContextProps;
   initialData?: IntialData;
 };
 
+const steps = [
+  t('App Store Connect credentials'),
+  t('Choose an application'),
+  t('Enter iTunes credentials'),
+  t('Enter authentication code'),
+  t('Choose an organization'),
+];
+
 function AppStoreConnect({
+  Header,
   Body,
   Footer,
   closeModal,
@@ -58,258 +80,502 @@ function AppStoreConnect({
   projectSlug,
   onSubmit,
   revalidateItunesSession,
-  appStoreConnectValidationData,
+  appStoreConnectContext,
 }: Props) {
-  const isUpdating = !!initialData;
-  const appStoreCredentialsInvalid =
-    appStoreConnectValidationData?.appstoreCredentialsValid === false;
-  const itunesSessionInvalid =
-    appStoreConnectValidationData?.itunesSessionValid === false;
+  const shouldRevalidateItunesSession =
+    revalidateItunesSession &&
+    (appStoreConnectContext?.itunesSessionValid === false ||
+      appStoreConnectContext?.appstoreCredentialsValid === false);
 
   const [isLoading, setIsLoading] = useState(false);
-  const [isEditingAppStoreCredentials, setIsEditingAppStoreCredentials] = useState(
-    appStoreCredentialsInvalid || !isUpdating
-  );
-  const [isEditingItunesCredentials, setIsEditingItunesCredentials] = useState(
-    itunesSessionInvalid || !isUpdating
-  );
+  const [activeStep, setActiveStep] = useState(shouldRevalidateItunesSession ? 2 : 0);
+  const [appStoreApps, setAppStoreApps] = useState<AppStoreApp[]>([]);
+  const [appleStoreOrgs, setAppleStoreOrgs] = useState<AppleStoreOrg[]>([]);
+  const [useSms, setUseSms] = useState(false);
+  const [sessionContext, setSessionContext] = useState('');
 
-  const appStoreCredentialsInitialData = {
+  const [stepOneData, setStepOneData] = useState<StepOneData>({
     issuer: initialData?.appconnectIssuer,
     keyId: initialData?.appconnectKey,
     privateKey: initialData?.appconnectPrivateKey,
+  });
+
+  const [stepTwoData, setStepTwoData] = useState<StepTwoData>({
     app:
-      initialData?.appName && initialData?.appId
-        ? {
-            appId: initialData.appId,
-            name: initialData.appName,
-          }
+      initialData?.appId && initialData?.appName
+        ? {appId: initialData.appId, name: initialData.appName}
         : undefined,
-  };
+  });
 
-  const iTunesCredentialsInitialData = {
+  const [stepThreeData, setStepThreeData] = useState<StepThreeData>({
     username: initialData?.itunesUser,
     password: initialData?.itunesPassword,
+  });
+
+  const [stepFourData, setStepFourData] = useState<StepFourData>({
     authenticationCode: undefined,
+  });
+
+  const [stepFifthData, setStepFifthData] = useState<StepFifthData>({
     org:
-      initialData?.orgId && initialData?.orgName
-        ? {
-            organizationId: initialData.orgId,
-            name: initialData.appName,
-          }
+      initialData?.orgId && initialData?.name
+        ? {organizationId: initialData.orgId, name: initialData.name}
         : undefined,
-    useSms: undefined,
-    sessionContext: undefined,
-  };
-
-  const [
-    appStoreCredentialsData,
-    setAppStoreCredentialsData,
-  ] = useState<AppStoreCredentialsData>(appStoreCredentialsInitialData);
-
-  const [
-    iTunesCredentialsData,
-    setItunesCredentialsData,
-  ] = useState<ItunesCredentialsData>(iTunesCredentialsInitialData);
-
-  function isDataInvalid(data: Record<string, any>) {
-    return Object.keys(data).some(key => {
-      const value = data[key];
-
-      if (typeof value === 'string') {
-        return !value.trim();
-      }
+  });
 
-      return typeof value === 'undefined';
-    });
-  }
+  useEffect(() => {
+    if (shouldRevalidateItunesSession) {
+      handleStartItunesAuthentication();
+    }
+  }, [shouldRevalidateItunesSession]);
 
-  function isAppStoreCredentialsDataInvalid() {
-    return isDataInvalid(appStoreCredentialsData);
-  }
+  async function checkAppStoreConnectCredentials() {
+    setIsLoading(true);
+    try {
+      const response = await api.requestPromise(
+        `/projects/${orgSlug}/${projectSlug}/appstoreconnect/apps/`,
+        {
+          method: 'POST',
+          data: {
+            appconnectIssuer: stepOneData.issuer,
+            appconnectKey: stepOneData.keyId,
+            appconnectPrivateKey: stepOneData.privateKey,
+          },
+        }
+      );
 
-  function isItunesCredentialsDataInvalid() {
-    return isDataInvalid(iTunesCredentialsData);
+      setAppStoreApps(response.apps);
+      setStepTwoData({app: response.apps[0]});
+      setIsLoading(false);
+      goNext();
+    } catch (error) {
+      setIsLoading(false);
+      addErrorMessage(
+        t(
+          'We could not establish a connection with App Store Connect. Please check the entered App Store Connect credentials.'
+        )
+      );
+    }
   }
 
-  function isFormInvalid() {
-    if (!!initialData) {
-      const isAppStoreCredentialsDataTheSame = isEqual(
-        appStoreCredentialsData,
-        appStoreCredentialsInitialData
+  async function startTwoFactorAuthentication() {
+    setIsLoading(true);
+    try {
+      const response = await api.requestPromise(
+        `/projects/${orgSlug}/${projectSlug}/appstoreconnect/2fa/`,
+        {
+          method: 'POST',
+          data: {
+            code: stepFourData.authenticationCode,
+            useSms,
+            sessionContext,
+          },
+        }
       );
-
-      const isItunesCredentialsDataTheSame = isEqual(
-        iTunesCredentialsData,
-        iTunesCredentialsInitialData
+      setIsLoading(false);
+      const {organizations, sessionContext: newSessionContext} = response;
+      setStepFifthData({org: organizations[0]});
+      setAppleStoreOrgs(organizations);
+      setSessionContext(newSessionContext);
+      goNext();
+    } catch (error) {
+      setIsLoading(false);
+      addErrorMessage(
+        t('The two factor authentication failed. Please check the entered code.')
       );
-
-      if (!isAppStoreCredentialsDataTheSame && !isItunesCredentialsDataTheSame) {
-        return isAppStoreCredentialsDataInvalid() && isItunesCredentialsDataInvalid();
-      }
-
-      if (!isAppStoreCredentialsDataTheSame) {
-        return isAppStoreCredentialsDataInvalid();
-      }
-
-      if (!isItunesCredentialsDataTheSame) {
-        return isItunesCredentialsDataInvalid();
-      }
-
-      return isAppStoreCredentialsDataTheSame && isItunesCredentialsDataTheSame;
     }
-
-    return isAppStoreCredentialsDataInvalid() && isItunesCredentialsDataInvalid();
   }
 
-  async function handleSave() {
+  async function persistData() {
+    if (!stepTwoData.app || !stepFifthData.org || !stepThreeData.username) {
+      return;
+    }
+    setIsLoading(true);
+
     let endpoint = `/projects/${orgSlug}/${projectSlug}/appstoreconnect/`;
-    let successMessage = t('App Store Connect repository was successfully added');
+    let successMessage = t('App Store Connect repository was successfully added.');
     let errorMessage = t(
-      'An error occured while adding the App Store Connect repository'
+      'An error occured while adding the App Store Connect repository.'
     );
 
     if (!!initialData) {
       endpoint = `${endpoint}${initialData.id}/`;
-      successMessage = t('App Store Connect repository was successfully updated');
+      successMessage = t('App Store Connect repository was successfully updated.');
       errorMessage = t(
-        'An error occured while updating the App Store Connect repository'
+        'An error occured while updating the App Store Connect repository.'
       );
     }
 
-    setIsLoading(true);
     try {
       const response = await api.requestPromise(endpoint, {
         method: 'POST',
         data: {
-          appconnectIssuer: appStoreCredentialsData.issuer,
-          appconnectKey: appStoreCredentialsData.keyId,
-          appconnectPrivateKey: appStoreCredentialsData.privateKey,
-          appName: appStoreCredentialsData.app?.name,
-          appId: appStoreCredentialsData.app?.appId,
-          itunesUser: iTunesCredentialsData.username,
-          itunesPassword: iTunesCredentialsData.password,
-          orgId: iTunesCredentialsData.org?.organizationId,
-          orgName: iTunesCredentialsData.org?.name,
-          sessionContext: iTunesCredentialsData.sessionContext,
+          itunesUser: stepThreeData.username,
+          itunesPassword: stepThreeData.password,
+          appconnectIssuer: stepOneData.issuer,
+          appconnectKey: stepOneData.keyId,
+          appconnectPrivateKey: stepOneData.privateKey,
+          appName: stepTwoData.app.name,
+          appId: stepTwoData.app.appId,
+          orgId: stepFifthData.org.organizationId,
+          orgName: stepFifthData.org.name,
+          sessionContext,
         },
       });
       addSuccessMessage(successMessage);
-      setIsLoading(false);
       onSubmit(response);
       closeModal();
-    } catch {
+    } catch (error) {
       setIsLoading(false);
       addErrorMessage(errorMessage);
     }
   }
 
-  function handleEditAppStoreCredentials(isEditing: boolean) {
+  function isFormInvalid() {
+    switch (activeStep) {
+      case 0:
+        return Object.keys(stepOneData).some(key => !stepOneData[key]);
+      case 1:
+        return Object.keys(stepTwoData).some(key => !stepTwoData[key]);
+      case 2: {
+        return Object.keys(stepThreeData).some(key => !stepThreeData[key]);
+      }
+      case 3: {
+        return Object.keys(stepFourData).some(key => !stepFourData[key]);
+      }
+      case 4: {
+        return Object.keys(stepFifthData).some(key => !stepFifthData[key]);
+      }
+      default:
+        return false;
+    }
+  }
+
+  function goNext() {
+    setActiveStep(activeStep + 1);
+  }
+
+  async function handleStartItunesAuthentication(shouldGoNext = true) {
+    if (shouldGoNext) {
+      setIsLoading(true);
+    }
+    if (useSms) {
+      setUseSms(false);
+    }
+
+    try {
+      const response = await api.requestPromise(
+        `/projects/${orgSlug}/${projectSlug}/appstoreconnect/start/`,
+        {
+          method: 'POST',
+          data: {
+            itunesUser: stepThreeData.username,
+            itunesPassword: stepThreeData.password,
+          },
+        }
+      );
+
+      setSessionContext(response.sessionContext);
+
+      if (shouldGoNext) {
+        setIsLoading(false);
+        goNext();
+      }
+    } catch {
+      if (shouldGoNext) {
+        setIsLoading(false);
+      }
+      addErrorMessage(
+        t('The iTunes authentication failed. Please check the entered credentials.')
+      );
+    }
+  }
+
+  async function handleStartSmsAuthentication() {
+    if (!useSms) {
+      setUseSms(true);
+    }
+
+    try {
+      const response = await api.requestPromise(
+        `/projects/${orgSlug}/${projectSlug}/appstoreconnect/requestSms/`,
+        {
+          method: 'POST',
+          data: {sessionContext},
+        }
+      );
+
+      setSessionContext(response.sessionContext);
+    } catch {
+      addErrorMessage(t('An error occured while sending the SMS. Please try again'));
+    }
+  }
+
+  function handleGoBack() {
+    const newActiveStep = activeStep - 1;
+
+    switch (newActiveStep) {
+      case 3:
+        handleStartItunesAuthentication(false);
+        setStepFourData({authenticationCode: undefined});
+        break;
+      default:
+        break;
+    }
+
+    setActiveStep(newActiveStep);
+  }
+
+  function handleGoNext() {
+    switch (activeStep) {
+      case 0:
+        checkAppStoreConnectCredentials();
+        break;
+      case 1:
+        goNext();
+        break;
+      case 2:
+        handleStartItunesAuthentication();
+        break;
+      case 3:
+        startTwoFactorAuthentication();
+        break;
+      case 4:
+        persistData();
+        break;
+      default:
+        break;
+    }
+  }
+
+  function renderCurrentStep() {
+    switch (activeStep) {
+      case 0:
+        return <StepOne stepOneData={stepOneData} onSetStepOneData={setStepOneData} />;
+      case 1:
+        return (
+          <StepTwo
+            appStoreApps={appStoreApps}
+            stepTwoData={stepTwoData}
+            onSetStepTwoData={setStepTwoData}
+          />
+        );
+      case 2:
+        return (
+          <StepThree stepThreeData={stepThreeData} onSetStepOneData={setStepThreeData} />
+        );
+      case 3:
+        return (
+          <StepFour
+            stepFourData={stepFourData}
+            onSetStepFourData={setStepFourData}
+            onStartItunesAuthentication={handleStartItunesAuthentication}
+            onStartSmsAuthentication={handleStartSmsAuthentication}
+          />
+        );
+      case 4:
+        return (
+          <StepFifth
+            appleStoreOrgs={appleStoreOrgs}
+            stepFifthData={stepFifthData}
+            onSetStepFifthData={setStepFifthData}
+          />
+        );
+      default:
+        return (
+          <Alert type="error" icon={<IconWarning />}>
+            {t('This step could not be found.')}
+          </Alert>
+        );
+    }
+  }
+
+  function getAlerts() {
+    const alerts: React.ReactElement[] = [];
+
+    const appConnectStoreUpdateAlertMessage = getAppConnectStoreUpdateAlertMessage(
+      appStoreConnectContext ?? {}
+    );
+
     if (
-      !isEditing &&
-      isEditingAppStoreCredentials &&
-      isAppStoreCredentialsDataInvalid()
+      appConnectStoreUpdateAlertMessage ===
+        appStoreConnectAlertMessage.appStoreCredentialsInvalid &&
+      activeStep === 0
     ) {
-      setIsEditingItunesCredentials(true);
+      alerts.push(
+        <StyledAlert type="warning" icon={<IconWarning />}>
+          {t(
+            'Your App Store Connect credentials are invalid. To reconnect, update your credentials.'
+          )}
+        </StyledAlert>
+      );
     }
 
-    setIsEditingAppStoreCredentials(isEditing);
+    if (
+      appConnectStoreUpdateAlertMessage ===
+        appStoreConnectAlertMessage.iTunesSessionInvalid &&
+      activeStep < 3
+    ) {
+      alerts.push(
+        <StyledAlert type="warning" icon={<IconWarning />}>
+          {t(
+            'Your iTunes session has expired. To reconnect, sign in with your Apple ID and password.'
+          )}
+        </StyledAlert>
+      );
+    }
+
+    if (
+      appConnectStoreUpdateAlertMessage ===
+        appStoreConnectAlertMessage.iTunesSessionInvalid &&
+      activeStep === 3
+    ) {
+      alerts.push(
+        <StyledAlert type="warning" icon={<IconWarning />}>
+          {t('Enter your authentication code to re-validate your iTunes session.')}
+        </StyledAlert>
+      );
+    }
+
+    if (
+      !appConnectStoreUpdateAlertMessage &&
+      revalidateItunesSession &&
+      activeStep === 0
+    ) {
+      alerts.push(
+        <StyledAlert type="warning" icon={<IconWarning />}>
+          {t('Your iTunes session has already been re-validated.')}
+        </StyledAlert>
+      );
+    }
+
+    return alerts;
+  }
+
+  function renderBodyContent() {
+    const alerts = getAlerts();
+
+    return (
+      <Fragment>
+        {!!alerts.length && (
+          <Alerts marginBottom={activeStep === 3 ? 1.5 : 3}>
+            {alerts.map((alert, index) => (
+              <Fragment key={index}>{alert}</Fragment>
+            ))}
+          </Alerts>
+        )}
+        {renderCurrentStep()}
+      </Fragment>
+    );
   }
 
   return (
     <Fragment>
-      <Body>
-        {revalidateItunesSession && !itunesSessionInvalid && (
-          <StyledAlert type="warning" icon={<IconInfo />}>
-            {t('Your iTunes session has already been re-validated.')}
-          </StyledAlert>
-        )}
-        <StyledList symbol="colored-numeric">
-          <Accordion summary={t('App Store Connect credentials')} defaultExpanded>
-            {appStoreCredentialsInvalid && (
-              <StyledAlert type="warning" icon={<IconWarning />}>
-                {t(
-                  'Your App Store Connect credentials are invalid. To reconnect, update your credentials.'
-                )}
-              </StyledAlert>
-            )}
-            <AppStoreCredentials
-              api={api}
-              orgSlug={orgSlug}
-              projectSlug={projectSlug}
-              data={appStoreCredentialsData}
-              isUpdating={isUpdating}
-              isEditing={isEditingAppStoreCredentials}
-              onChange={setAppStoreCredentialsData}
-              onReset={() => setAppStoreCredentialsData(appStoreCredentialsInitialData)}
-              onEdit={handleEditAppStoreCredentials}
-            />
-          </Accordion>
-          <Accordion
-            summary={t('iTunes credentials')}
-            defaultExpanded={
-              isUpdating ||
-              itunesSessionInvalid ||
-              (isItunesCredentialsDataInvalid() && !isAppStoreCredentialsDataInvalid()) ||
-              (!isEditingItunesCredentials && !isItunesCredentialsDataInvalid())
-            }
-          >
-            {!revalidateItunesSession && itunesSessionInvalid && (
-              <StyledAlert type="warning" icon={<IconWarning />}>
-                {t(
-                  'Your iTunes session has expired. To reconnect, sign in with your Apple ID and password'
+      <Header closeButton>
+        <HeaderContent>
+          <NumericSymbol>{activeStep + 1}</NumericSymbol>
+          <HeaderContentTitle>{steps[activeStep]}</HeaderContentTitle>
+          <StepsOverview>
+            {tct('[currentStep] of [totalSteps]', {
+              currentStep: activeStep + 1,
+              totalSteps: steps.length,
+            })}
+          </StepsOverview>
+        </HeaderContent>
+      </Header>
+      {initialData && appStoreConnectContext?.isLoading !== false ? (
+        <Body>
+          <LoadingIndicator />
+        </Body>
+      ) : (
+        <Fragment>
+          <Body>{renderBodyContent()}</Body>
+          <Footer>
+            <ButtonBar gap={1}>
+              {activeStep !== 0 && <Button onClick={handleGoBack}>{t('Back')}</Button>}
+              <StyledButton
+                priority="primary"
+                onClick={handleGoNext}
+                disabled={
+                  isLoading ||
+                  isFormInvalid() ||
+                  (appStoreConnectContext
+                    ? appStoreConnectContext?.isLoading !== false
+                    : false)
+                }
+              >
+                {isLoading && (
+                  <LoadingIndicatorWrapper>
+                    <LoadingIndicator mini />
+                  </LoadingIndicatorWrapper>
                 )}
-              </StyledAlert>
-            )}
-            <ItunesCredentials
-              api={api}
-              orgSlug={orgSlug}
-              projectSlug={projectSlug}
-              data={iTunesCredentialsData}
-              isUpdating={isUpdating}
-              isEditing={isEditingItunesCredentials}
-              revalidateItunesSession={revalidateItunesSession && itunesSessionInvalid}
-              onChange={setItunesCredentialsData}
-              onReset={() => setItunesCredentialsData(iTunesCredentialsInitialData)}
-              onEdit={setIsEditingItunesCredentials}
-            />
-          </Accordion>
-        </StyledList>
-      </Body>
-      <Footer>
-        <ButtonBar gap={1.5}>
-          <Button onClick={closeModal}>{t('Cancel')}</Button>
-          <StyledButton
-            priority="primary"
-            onClick={handleSave}
-            disabled={isFormInvalid() || isLoading}
-          >
-            {t('Save')}
-          </StyledButton>
-        </ButtonBar>
-      </Footer>
+                {activeStep + 1 === steps.length
+                  ? initialData
+                    ? t('Update')
+                    : t('Save')
+                  : steps[activeStep + 1]}
+              </StyledButton>
+            </ButtonBar>
+          </Footer>
+        </Fragment>
+      )}
     </Fragment>
   );
 }
 
 export default withApi(AppStoreConnect);
 
-const StyledList = styled(List)`
-  grid-gap: ${space(2)};
-  & > li {
-    padding-left: 0;
-    :before {
-      z-index: 1;
-      left: 9px;
-      top: ${space(1.5)};
-    }
-  }
+const HeaderContent = styled('div')`
+  display: grid;
+  grid-template-columns: max-content max-content 1fr;
+  align-items: center;
+  grid-gap: ${space(1)};
+`;
+
+const NumericSymbol = styled('div')`
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 24px;
+  height: 24px;
+  font-weight: 700;
+  font-size: ${p => p.theme.fontSizeMedium};
+  background-color: ${p => p.theme.yellow300};
+`;
+
+const HeaderContentTitle = styled('div')`
+  font-weight: 700;
+  font-size: ${p => p.theme.fontSizeExtraLarge};
+`;
+
+const StepsOverview = styled('div')`
+  color: ${p => p.theme.gray300};
+  display: flex;
+  justify-content: flex-end;
+`;
+
+const LoadingIndicatorWrapper = styled('div')`
+  height: 100%;
+  position: absolute;
+  width: 100%;
+  top: 0;
+  left: 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
 `;
 
 const StyledButton = styled(Button)`
   position: relative;
 `;
 
+const Alerts = styled('div')<{marginBottom: ValidSize}>`
+  display: grid;
+  grid-gap: ${space(1.5)};
+  margin-bottom: ${p => space(p.marginBottom)};
+`;
+
 const StyledAlert = styled(Alert)`
-  margin: ${space(1)} 0 ${space(2)} 0;
+  margin: 0;
 `;

+ 0 - 367
static/app/components/modals/debugFileCustomRepository/appStoreConnect/itunesCredentials/form.tsx

@@ -1,367 +0,0 @@
-import {Fragment, useEffect, useState} from 'react';
-import styled from '@emotion/styled';
-
-import {addErrorMessage} from 'app/actionCreators/indicator';
-import {Client} from 'app/api';
-import Alert from 'app/components/alert';
-import Button from 'app/components/button';
-import ButtonBar from 'app/components/buttonBar';
-import {IconInfo, IconMobile, IconRefresh, IconWarning} from 'app/icons';
-import {t} from 'app/locale';
-import space from 'app/styles/space';
-import {Organization, Project} from 'app/types';
-import Input from 'app/views/settings/components/forms/controls/input';
-import Field from 'app/views/settings/components/forms/field';
-import SelectField from 'app/views/settings/components/forms/selectField';
-
-import Stepper from '../stepper';
-import StepActions from '../stepper/stepActions';
-import {
-  AppleStoreOrg,
-  ItunesCredentialsData,
-  ItunesCredentialsStepOneData,
-  ItunesCredentialsStepThreeData,
-  ItunesCredentialsStepTwoData,
-} from '../types';
-
-const steps = [
-  t('Enter your credentials'),
-  t('Enter your authentication code'),
-  t('Choose an organization'),
-];
-
-type Props = {
-  api: Client;
-  orgSlug: Organization['slug'];
-  projectSlug: Project['slug'];
-  data: ItunesCredentialsData;
-  revalidateItunesSession: boolean;
-  onChange: (data: ItunesCredentialsData) => void;
-  onSwitchToReadMode: () => void;
-  onCancel?: () => void;
-};
-
-function Form({
-  api,
-  orgSlug,
-  projectSlug,
-  data,
-  revalidateItunesSession,
-  onChange,
-  onSwitchToReadMode,
-  onCancel,
-}: Props) {
-  const [activeStep, setActiveStep] = useState(0);
-  const [isLoading, setIsLoading] = useState(false);
-  const [sessionContext, setSessionContext] = useState('');
-  const [useSms, setUseSms] = useState(false);
-  const [appStoreOrgs, setAppStoreOrgs] = useState<AppleStoreOrg[]>([]);
-
-  const [stepOneData, setSetpOneData] = useState<ItunesCredentialsStepOneData>({
-    username: data.username,
-    password: data.password,
-  });
-
-  const [stepTwoData, setStepTwoData] = useState<ItunesCredentialsStepTwoData>({
-    authenticationCode: data.authenticationCode,
-  });
-
-  const [stepThreeData, setStepThreeData] = useState<ItunesCredentialsStepThreeData>({
-    org: data.org,
-  });
-
-  useEffect(() => {
-    if (revalidateItunesSession) {
-      handleGoNext();
-    }
-  }, [revalidateItunesSession]);
-
-  function isFormInvalid() {
-    switch (activeStep) {
-      case 0:
-        return Object.keys(stepOneData).some(key => !stepOneData[key]);
-      case 1:
-        return Object.keys(stepTwoData).some(key => !stepTwoData[key]);
-      case 2:
-        return Object.keys(stepThreeData).some(key => !stepThreeData[key]);
-      default:
-        return false;
-    }
-  }
-
-  function goNext() {
-    setActiveStep(prevActiveStep => prevActiveStep + 1);
-  }
-
-  function handleGoBack() {
-    const newActiveStep = activeStep - 1;
-
-    switch (newActiveStep) {
-      case 1:
-        startItunesAuthentication(false);
-        setStepTwoData({authenticationCode: undefined});
-        break;
-      default:
-        break;
-    }
-
-    setActiveStep(newActiveStep);
-  }
-
-  function handleGoNext() {
-    switch (activeStep) {
-      case 0:
-        startItunesAuthentication();
-        break;
-      case 1:
-        startTwoFactorAuthentication();
-        break;
-      default:
-        break;
-    }
-  }
-
-  function handleSave() {
-    onChange({...stepOneData, ...stepTwoData, ...stepThreeData, sessionContext, useSms});
-    onSwitchToReadMode();
-  }
-
-  async function startItunesAuthentication(shouldGoNext = true) {
-    if (shouldGoNext) {
-      setIsLoading(true);
-    }
-    if (useSms) {
-      setUseSms(false);
-    }
-
-    try {
-      const response = await api.requestPromise(
-        `/projects/${orgSlug}/${projectSlug}/appstoreconnect/start/`,
-        {
-          method: 'POST',
-          data: {
-            itunesUser: stepOneData.username,
-            itunesPassword: stepOneData.password,
-          },
-        }
-      );
-
-      setSessionContext(response.sessionContext);
-
-      if (shouldGoNext) {
-        setIsLoading(false);
-        goNext();
-      }
-    } catch {
-      if (shouldGoNext) {
-        setIsLoading(false);
-      }
-      addErrorMessage(
-        t('The iTunes authentication failed. Please check the entered credentials.')
-      );
-    }
-  }
-
-  async function startTwoFactorAuthentication() {
-    setIsLoading(true);
-    try {
-      const response = await api.requestPromise(
-        `/projects/${orgSlug}/${projectSlug}/appstoreconnect/2fa/`,
-        {
-          method: 'POST',
-          data: {
-            code: stepTwoData.authenticationCode,
-            useSms,
-            sessionContext,
-          },
-        }
-      );
-      setIsLoading(false);
-      const {organizations, sessionContext: newSessionContext} = response;
-      setStepThreeData({org: organizations[0]});
-      setAppStoreOrgs(organizations);
-      setSessionContext(newSessionContext);
-      goNext();
-    } catch {
-      setIsLoading(false);
-      addErrorMessage(
-        t('The two factor authentication failed. Please check the entered code.')
-      );
-    }
-  }
-
-  async function startSmsAuthentication() {
-    if (!useSms) {
-      setUseSms(true);
-    }
-
-    try {
-      const response = await api.requestPromise(
-        `/projects/${orgSlug}/${projectSlug}/appstoreconnect/requestSms/`,
-        {
-          method: 'POST',
-          data: {sessionContext},
-        }
-      );
-
-      setSessionContext(response.sessionContext);
-    } catch {
-      addErrorMessage(t('An error occured while sending the SMS. Please try again'));
-    }
-  }
-
-  function renderStepContent(stepIndex: number) {
-    switch (stepIndex) {
-      case 0:
-        return (
-          <Fragment>
-            <Field
-              label={t('Username')}
-              inline={false}
-              flexibleControlStateSize
-              stacked
-              required
-            >
-              <Input
-                type="text"
-                name="username"
-                placeholder={t('Username')}
-                onChange={e => setSetpOneData({...stepOneData, username: e.target.value})}
-              />
-            </Field>
-            <Field
-              label={t('Password')}
-              inline={false}
-              flexibleControlStateSize
-              stacked
-              required
-            >
-              <Input
-                type="password"
-                name="password"
-                placeholder={t('Password')}
-                onChange={e => setSetpOneData({...stepOneData, password: e.target.value})}
-              />
-            </Field>
-          </Fragment>
-        );
-      case 1:
-        return (
-          <Fragment>
-            <StyledAlert type="info" icon={<IconInfo />}>
-              <AlertContent>
-                {t('Did not get a verification code?')}
-                <ButtonBar gap={1}>
-                  <Button
-                    size="small"
-                    title={t('Get a new verification code')}
-                    onClick={() => startItunesAuthentication(false)}
-                    icon={<IconRefresh />}
-                  >
-                    {t('Resend code')}
-                  </Button>
-                  <Button
-                    size="small"
-                    title={t('Get a text message with a code')}
-                    onClick={() => startSmsAuthentication()}
-                    icon={<IconMobile />}
-                  >
-                    {t('Text me')}
-                  </Button>
-                </ButtonBar>
-              </AlertContent>
-            </StyledAlert>
-            <Field
-              label={t('Two Factor authentication code')}
-              inline={false}
-              flexibleControlStateSize
-              stacked
-              required
-            >
-              <Input
-                type="text"
-                name="two-factor-authentication-code"
-                placeholder={t('Enter your code')}
-                value={stepTwoData.authenticationCode}
-                onChange={e =>
-                  setStepTwoData({
-                    ...setStepTwoData,
-                    authenticationCode: e.target.value,
-                  })
-                }
-              />
-            </Field>
-          </Fragment>
-        );
-      case 2:
-        return (
-          <StyledSelectField
-            name="organization"
-            label={t('iTunes Organization')}
-            choices={appStoreOrgs.map(appStoreOrg => [
-              appStoreOrg.organizationId,
-              appStoreOrg.name,
-            ])}
-            placeholder={t('Select organization')}
-            onChange={organizationId => {
-              const selectedAppStoreOrg = appStoreOrgs.find(
-                appStoreOrg => appStoreOrg.organizationId === organizationId
-              );
-              setStepThreeData({org: selectedAppStoreOrg});
-            }}
-            value={stepThreeData.org?.organizationId ?? ''}
-            inline={false}
-            flexibleControlStateSize
-            stacked
-            required
-          />
-        );
-      default:
-        return (
-          <Alert type="error" icon={<IconWarning />}>
-            {t('This step could not be found.')}
-          </Alert>
-        );
-    }
-  }
-
-  return (
-    <Stepper
-      activeStep={activeStep}
-      steps={steps}
-      renderStepContent={index => renderStepContent(index)}
-      renderStepActions={index => (
-        <StepActions
-          onGoBack={index !== 0 ? handleGoBack : undefined}
-          onGoNext={index !== steps.length - 1 ? handleGoNext : undefined}
-          onCancel={onCancel}
-          onFinish={handleSave}
-          primaryButtonDisabled={isFormInvalid() || isLoading}
-          isLoading={isLoading}
-        />
-      )}
-    />
-  );
-}
-
-export default Form;
-
-const StyledAlert = styled(Alert)`
-  display: grid;
-  grid-template-columns: max-content 1fr;
-  align-items: center;
-  span:nth-child(2) {
-    margin: 0;
-  }
-`;
-
-const AlertContent = styled('div')`
-  display: grid;
-  grid-template-columns: 1fr max-content;
-  align-items: center;
-  grid-gap: ${space(2)};
-`;
-
-const StyledSelectField = styled(SelectField)`
-  padding-right: 0;
-`;

+ 0 - 64
static/app/components/modals/debugFileCustomRepository/appStoreConnect/itunesCredentials/index.tsx

@@ -1,64 +0,0 @@
-import {Client} from 'app/api';
-import {t} from 'app/locale';
-import {Organization, Project} from 'app/types';
-
-import Card from '../card';
-import CardItem from '../cardItem';
-import {ItunesCredentialsData} from '../types';
-
-import Form from './form';
-
-type Props = {
-  api: Client;
-  orgSlug: Organization['slug'];
-  projectSlug: Project['slug'];
-  isUpdating: boolean;
-  isEditing: boolean;
-  revalidateItunesSession: boolean;
-  data: ItunesCredentialsData;
-  onChange: (data: ItunesCredentialsData) => void;
-  onEdit: (isEditing: boolean) => void;
-  onReset: () => void;
-};
-
-function ItunesCredentials({
-  data,
-  isUpdating,
-  onReset,
-  isEditing,
-  onEdit,
-  revalidateItunesSession,
-  ...props
-}: Props) {
-  function handleSwitchToReadMode() {
-    onEdit(false);
-  }
-
-  function handleCancel() {
-    onEdit(false);
-    onReset();
-  }
-
-  if (isEditing) {
-    return (
-      <Form
-        {...props}
-        revalidateItunesSession={revalidateItunesSession}
-        data={data}
-        onSwitchToReadMode={handleSwitchToReadMode}
-        onCancel={isUpdating ? handleCancel : undefined}
-      />
-    );
-  }
-
-  return (
-    <Card onEdit={() => onEdit(true)}>
-      {data.username && <CardItem label={t('User')} value={data.username} />}
-      {data.org?.name && (
-        <CardItem label={t('iTunes Organization')} value={data.org?.name} />
-      )}
-    </Card>
-  );
-}
-
-export default ItunesCredentials;

Some files were not shown because too many files changed in this diff