]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20086 Migrating GitHub onboarding page to new design
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>
Tue, 8 Aug 2023 10:18:45 +0000 (12:18 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 14 Aug 2023 20:02:57 +0000 (20:02 +0000)
server/sonar-web/design-system/src/components/Text.tsx
server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreate.tsx
server/sonar-web/src/main/js/apps/create/project/Github/GitHubProjectCreateRenderer.tsx
server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx
server/sonar-web/src/main/js/apps/create/project/components/AlmRepoItem.tsx
server/sonar-web/src/main/js/apps/create/project/components/AlmSettingsInstanceDropdown.tsx
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx
server/sonar-web/src/main/js/components/devops-platform/AlmSettingsInstanceSelector.tsx
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index fb6664fc0381d7dbfbc83ce7b4597bfdaf7233e8..e17950ab7cdf7db07b411ca9cd2a248b20256357 100644 (file)
@@ -108,6 +108,12 @@ export const LightLabel = styled.span`
   color: ${themeColor('pageContentLight')};
 `;
 
+export const DarkLabel = styled.label`
+  color: ${themeColor('pageContentDark')};
+
+  ${tw`sw-body-sm-highlight`}
+`;
+
 export const LightPrimary = styled.span`
   color: ${themeContrast('primaryLight')};
 `;
index 4e625e2547f75e14ce6efd61fedb3f1be825ea13..364749c8c211ba8b628a1f2067b007f9c2b206eb 100644 (file)
@@ -31,8 +31,8 @@ import { getHostUrl } from '../../../../helpers/urls';
 import { GithubOrganization, GithubRepository } from '../../../../types/alm-integration';
 import { AlmKeys, AlmSettingsInstance } from '../../../../types/alm-settings';
 import { Paging } from '../../../../types/types';
-import GitHubProjectCreateRenderer from './GitHubProjectCreateRenderer';
 import { CreateProjectApiCallback } from '../types';
+import GitHubProjectCreateRenderer from './GitHubProjectCreateRenderer';
 
 interface Props {
   canAdmin: boolean;
@@ -52,7 +52,6 @@ interface State {
   repositories: GithubRepository[];
   searchQuery: string;
   selectedOrganization?: GithubOrganization;
-  selectedRepository?: GithubRepository;
   selectedAlmInstance?: AlmSettingsInstance;
 }
 
@@ -231,7 +230,6 @@ export default class GitHubProjectCreate extends React.Component<Props, State> {
   triggerSearch = (query: string) => {
     const { selectedOrganization } = this.state;
     if (selectedOrganization) {
-      this.setState({ selectedRepository: undefined });
       this.fetchRepositories({ organizationKey: selectedOrganization.key, query });
     }
   };
@@ -239,18 +237,11 @@ export default class GitHubProjectCreate extends React.Component<Props, State> {
   handleSelectOrganization = (key: string) => {
     this.setState(({ organizations }) => ({
       searchQuery: '',
-      selectedRepository: undefined,
       selectedOrganization: organizations.find((o) => o.key === key),
     }));
     this.fetchRepositories({ organizationKey: key });
   };
 
-  handleSelectRepository = (key: string) => {
-    this.setState(({ repositories }) => ({
-      selectedRepository: repositories?.find((r) => r.key === key),
-    }));
-  };
-
   handleSearch = (searchQuery: string) => {
     this.setState({ searchQuery });
     this.triggerSearch(searchQuery);
@@ -268,15 +259,15 @@ export default class GitHubProjectCreate extends React.Component<Props, State> {
     }
   };
 
-  handleImportRepository = () => {
-    const { selectedOrganization, selectedRepository, selectedAlmInstance } = this.state;
+  handleImportRepository = (repoKey: string) => {
+    const { selectedOrganization, selectedAlmInstance } = this.state;
 
-    if (selectedAlmInstance && selectedOrganization && selectedRepository) {
+    if (selectedAlmInstance && selectedOrganization && repoKey !== '') {
       this.props.onProjectSetupDone(
         setupGithubProjectCreation({
           almSetting: selectedAlmInstance.key,
           organization: selectedOrganization.key,
-          repositoryKey: selectedRepository.key,
+          repositoryKey: repoKey,
         })
       );
     }
@@ -304,7 +295,6 @@ export default class GitHubProjectCreate extends React.Component<Props, State> {
       repositories,
       searchQuery,
       selectedOrganization,
-      selectedRepository,
       selectedAlmInstance,
     } = this.state;
 
@@ -319,13 +309,11 @@ export default class GitHubProjectCreate extends React.Component<Props, State> {
         onLoadMore={this.handleLoadMore}
         onSearch={this.handleSearch}
         onSelectOrganization={this.handleSelectOrganization}
-        onSelectRepository={this.handleSelectRepository}
         organizations={organizations}
         repositoryPaging={repositoryPaging}
         searchQuery={searchQuery}
         repositories={repositories}
         selectedOrganization={selectedOrganization}
-        selectedRepository={selectedRepository}
         almInstances={almInstances}
         selectedAlmInstance={selectedAlmInstance}
         onSelectedAlmInstanceChange={this.onSelectedAlmInstanceChange}
index ec5442bb3e987c7d8ddd3ecb0b07ef7c3e6a4a54..44672b96a720871618084e43f1f730207c37e1cf 100644 (file)
  */
 /* eslint-disable react/no-unused-prop-types */
 
+import {
+  DarkLabel,
+  DeferredSpinner,
+  FlagMessage,
+  InputSearch,
+  InputSelect,
+  LightPrimary,
+  Link,
+  Title,
+} from 'design-system';
 import * as React from 'react';
 import { FormattedMessage } from 'react-intl';
-import { colors } from '../../../../app/theme';
-import Link from '../../../../components/common/Link';
 import ListFooter from '../../../../components/controls/ListFooter';
-import Radio from '../../../../components/controls/Radio';
-import SearchBox from '../../../../components/controls/SearchBox';
-import Select, { LabelValueSelectOption } from '../../../../components/controls/Select';
-import { Button } from '../../../../components/controls/buttons';
-import CheckIcon from '../../../../components/icons/CheckIcon';
-import QualifierIcon from '../../../../components/icons/QualifierIcon';
-import { Alert } from '../../../../components/ui/Alert';
-import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
+import { LabelValueSelectOption } from '../../../../components/controls/Select';
 import { translate } from '../../../../helpers/l10n';
 import { getBaseUrl } from '../../../../helpers/system';
-import { getProjectUrl } from '../../../../helpers/urls';
 import { GithubOrganization, GithubRepository } from '../../../../types/alm-integration';
 import { AlmKeys, AlmSettingsInstance } from '../../../../types/alm-settings';
-import { ComponentQualifier } from '../../../../types/component';
 import { Paging } from '../../../../types/types';
+import AlmRepoItem from '../components/AlmRepoItem';
 import AlmSettingsInstanceDropdown from '../components/AlmSettingsInstanceDropdown';
-import CreateProjectPageHeader from '../components/CreateProjectPageHeader';
 
 export interface GitHubProjectCreateRendererProps {
   canAdmin: boolean;
@@ -48,17 +47,15 @@ export interface GitHubProjectCreateRendererProps {
   loadingBindings: boolean;
   loadingOrganizations: boolean;
   loadingRepositories: boolean;
-  onImportRepository: () => void;
+  onImportRepository: (key: string) => void;
   onLoadMore: () => void;
   onSearch: (q: string) => void;
   onSelectOrganization: (key: string) => void;
-  onSelectRepository: (key: string) => void;
   organizations: GithubOrganization[];
   repositories?: GithubRepository[];
   repositoryPaging: Paging;
   searchQuery: string;
   selectedOrganization?: GithubOrganization;
-  selectedRepository?: GithubRepository;
   almInstances: AlmSettingsInstance[];
   selectedAlmInstance?: AlmSettingsInstance;
   onSelectedAlmInstanceChange: (instance: AlmSettingsInstance) => void;
@@ -69,89 +66,40 @@ function orgToOption({ key, name }: GithubOrganization) {
 }
 
 function renderRepositoryList(props: GitHubProjectCreateRendererProps) {
-  const {
-    loadingRepositories,
-    repositories,
-    repositoryPaging,
-    searchQuery,
-    selectedOrganization,
-    selectedRepository,
-  } = props;
-
-  const isChecked = (repository: GithubRepository) =>
-    !!repository.sqProjectKey ||
-    (!!selectedRepository && selectedRepository.key === repository.key);
-
-  const isDisabled = (repository: GithubRepository) =>
-    !!repository.sqProjectKey || loadingRepositories;
+  const { loadingRepositories, repositories, repositoryPaging, searchQuery, selectedOrganization } =
+    props;
 
   return (
     selectedOrganization &&
     repositories && (
-      <div className="boxed-group padded display-flex-wrap">
-        <div className="width-100">
-          <SearchBox
-            className="big-spacer-bottom"
+      <div>
+        <div className="sw-flex sw-items-center sw-mb-6">
+          <InputSearch
+            size="large"
             onChange={props.onSearch}
             placeholder={translate('onboarding.create_project.search_repositories')}
             value={searchQuery}
+            clearIconAriaLabel={translate('clear')}
           />
+          <DeferredSpinner loading={loadingRepositories} className="sw-ml-2" />
         </div>
 
         {repositories.length === 0 ? (
-          <div className="padded">
-            <DeferredSpinner loading={loadingRepositories}>
-              {translate('no_results')}
-            </DeferredSpinner>
+          <div className="sw-py-6 sw-px-2">
+            <LightPrimary className="sw-body-sm">{translate('no_results')}</LightPrimary>
           </div>
         ) : (
           repositories.map((r) => (
-            <Radio
-              className="spacer-top spacer-bottom padded create-project-github-repository"
+            <AlmRepoItem
               key={r.key}
-              checked={isChecked(r)}
-              disabled={isDisabled(r)}
-              value={r.key}
-              onCheck={props.onSelectRepository}
-            >
-              <div className="big overflow-hidden max-width-100" title={r.name}>
-                <div className="text-ellipsis">
-                  {r.sqProjectKey ? (
-                    <div className="display-flex-center max-width-100">
-                      <Link
-                        className="display-flex-center max-width-60"
-                        to={getProjectUrl(r.sqProjectKey)}
-                      >
-                        <QualifierIcon
-                          className="spacer-right"
-                          qualifier={ComponentQualifier.Project}
-                        />
-                        <span className="text-ellipsis">{r.name}</span>
-                      </Link>
-                      <em className="display-flex-center small big-spacer-left flex-0">
-                        <span className="text-muted-2">
-                          {translate('onboarding.create_project.repository_imported')}
-                        </span>
-                        <CheckIcon className="little-spacer-left" size={12} fill={colors.green} />
-                      </em>
-                    </div>
-                  ) : (
-                    r.name
-                  )}
-                </div>
-                {r.url && (
-                  <a
-                    className="notice small display-flex-center little-spacer-top"
-                    onClick={(e) => e.stopPropagation()}
-                    target="_blank"
-                    href={r.url}
-                    rel="noopener noreferrer"
-                  >
-                    {translate('onboarding.create_project.see_on_github')}
-                  </a>
-                )}
-              </div>
-            </Radio>
+              almKey={r.key}
+              almUrl={r.url}
+              almUrlText={translate('onboarding.create_project.see_on_github')}
+              almIconSrc={`${getBaseUrl()}/images/tutorials/github-actions.svg`}
+              sqProjectKey={r.sqProjectKey}
+              onImport={props.onImportRepository}
+              primaryTextNode={<span title={r.name}>{r.name}</span>}
+            />
           ))
         )}
 
@@ -161,6 +109,7 @@ function renderRepositoryList(props: GitHubProjectCreateRendererProps) {
             total={repositoryPaging.total}
             loadMore={props.onLoadMore}
             loading={loadingRepositories}
+            useMIUIButtons
           />
         </div>
       </div>
@@ -176,7 +125,6 @@ export default function GitHubProjectCreateRenderer(props: GitHubProjectCreateRe
     loadingOrganizations,
     organizations,
     selectedOrganization,
-    selectedRepository,
     almInstances,
     selectedAlmInstance,
   } = props;
@@ -186,33 +134,13 @@ export default function GitHubProjectCreateRenderer(props: GitHubProjectCreateRe
   }
 
   return (
-    <div>
-      <CreateProjectPageHeader
-        additionalActions={
-          selectedOrganization && (
-            <div className="display-flex-center pull-right">
-              <Button
-                className="button-large button-primary"
-                disabled={!selectedRepository}
-                onClick={props.onImportRepository}
-              >
-                {translate('onboarding.create_project.import_selected_repo')}
-              </Button>
-            </div>
-          )
-        }
-        title={
-          <span className="text-middle display-flex-center">
-            <img
-              alt="" // Should be ignored by screen readers
-              className="spacer-right"
-              height={24}
-              src={`${getBaseUrl()}/images/alm/github.svg`}
-            />
-            {translate('onboarding.create_project.github.title')}
-          </span>
-        }
-      />
+    <>
+      <header className="sw-mb-10">
+        <Title className="sw-mb-4">{translate('onboarding.create_project.github.title')}</Title>
+        <LightPrimary className="sw-body-sm">
+          {translate('onboarding.create_project.github.subtitle')}
+        </LightPrimary>
+      </header>
 
       <AlmSettingsInstanceDropdown
         almKey={AlmKeys.GitHub}
@@ -222,76 +150,73 @@ export default function GitHubProjectCreateRenderer(props: GitHubProjectCreateRe
       />
 
       {error && selectedAlmInstance && (
-        <div className="display-flex-justify-center">
-          <div className="boxed-group padded width-50 huge-spacer-top">
-            <h2 className="big-spacer-bottom">
-              {translate('onboarding.create_project.github.warning.title')}
-            </h2>
-            <Alert variant="warning">
-              {canAdmin ? (
-                <FormattedMessage
-                  id="onboarding.create_project.github.warning.message_admin"
-                  defaultMessage={translate(
-                    'onboarding.create_project.github.warning.message_admin'
-                  )}
-                  values={{
-                    link: (
-                      <Link to="/admin/settings?category=almintegration">
-                        {translate('onboarding.create_project.github.warning.message_admin.link')}
-                      </Link>
-                    ),
-                  }}
-                />
-              ) : (
-                translate('onboarding.create_project.github.warning.message')
-              )}
-            </Alert>
-          </div>
-        </div>
+        <FlagMessage variant="warning" className="sw-my-2">
+          <span>
+            {canAdmin ? (
+              <FormattedMessage
+                id="onboarding.create_project.github.warning.message_admin"
+                defaultMessage={translate('onboarding.create_project.github.warning.message_admin')}
+                values={{
+                  link: (
+                    <Link to="/admin/settings?category=almintegration">
+                      {translate('onboarding.create_project.github.warning.message_admin.link')}
+                    </Link>
+                  ),
+                }}
+              />
+            ) : (
+              translate('onboarding.create_project.github.warning.message')
+            )}
+          </span>
+        </FlagMessage>
       )}
 
-      {!error && (
-        <DeferredSpinner loading={loadingOrganizations}>
-          <div className="form-field">
-            <label htmlFor="github-choose-organization">
+      <DeferredSpinner loading={loadingOrganizations && !error}>
+        {!error && (
+          <div className="sw-flex sw-flex-col">
+            <DarkLabel htmlFor="github-choose-organization" className="sw-mb-2">
               {translate('onboarding.create_project.github.choose_organization')}
-            </label>
+            </DarkLabel>
             {organizations.length > 0 ? (
-              <Select
+              <InputSelect
+                className="sw-w-abs-300 sw-mb-9"
+                size="full"
+                isSearchable
                 inputId="github-choose-organization"
-                className="input-super-large"
                 options={organizations.map(orgToOption)}
                 onChange={({ value }: LabelValueSelectOption) => props.onSelectOrganization(value)}
                 value={selectedOrganization ? orgToOption(selectedOrganization) : null}
               />
             ) : (
               !loadingOrganizations && (
-                <Alert className="spacer-top" variant="error">
-                  {canAdmin ? (
-                    <FormattedMessage
-                      id="onboarding.create_project.github.no_orgs_admin"
-                      defaultMessage={translate('onboarding.create_project.github.no_orgs_admin')}
-                      values={{
-                        link: (
-                          <Link to="/admin/settings?category=almintegration">
-                            {translate(
-                              'onboarding.create_project.github.warning.message_admin.link'
-                            )}
-                          </Link>
-                        ),
-                      }}
-                    />
-                  ) : (
-                    translate('onboarding.create_project.github.no_orgs')
-                  )}
-                </Alert>
+                <FlagMessage variant="error" className="sw-mb-2">
+                  <span>
+                    {canAdmin ? (
+                      <FormattedMessage
+                        id="onboarding.create_project.github.no_orgs_admin"
+                        defaultMessage={translate('onboarding.create_project.github.no_orgs_admin')}
+                        values={{
+                          link: (
+                            <Link to="/admin/settings?category=almintegration">
+                              {translate(
+                                'onboarding.create_project.github.warning.message_admin.link'
+                              )}
+                            </Link>
+                          ),
+                        }}
+                      />
+                    ) : (
+                      translate('onboarding.create_project.github.no_orgs')
+                    )}
+                  </span>
+                </FlagMessage>
               )
             )}
           </div>
-        </DeferredSpinner>
-      )}
+        )}
+      </DeferredSpinner>
 
       {renderRepositoryList(props)}
-    </div>
+    </>
   );
 }
index 45b42c0e5d3957056f373b4394b579a94a261a50..00d7036e401df8ac62a4a11ef787d552d2c82615 100644 (file)
@@ -106,8 +106,8 @@ it('should show import project feature when the authentication is successfull',
   expect(screen.getByText('Github repo 1')).toBeInTheDocument();
   expect(screen.getByText('Github repo 2')).toBeInTheDocument();
 
-  repoItem = screen.getByRole('radio', {
-    name: 'Github repo 1',
+  repoItem = screen.getByRole('row', {
+    name: 'Github repo 1 onboarding.create_project.see_on_github onboarding.create_project.repository_imported',
   });
 
   expect(
@@ -120,16 +120,11 @@ it('should show import project feature when the authentication is successfull',
     '/dashboard?id=key123'
   );
 
-  repoItem = screen.getByRole('radio', {
-    name: 'Github repo 2',
+  repoItem = screen.getByRole('row', {
+    name: 'Github repo 2 onboarding.create_project.see_on_github onboarding.create_project.import',
   });
 
-  const importButton = screen.getByText('onboarding.create_project.import_selected_repo');
-
-  expect(repoItem).toBeInTheDocument();
-  expect(importButton).toBeDisabled();
-  await user.click(repoItem);
-  expect(importButton).toBeEnabled();
+  const importButton = screen.getByText('onboarding.create_project.import');
   await user.click(importButton);
 
   expect(
@@ -154,9 +149,7 @@ it('should show search filter when the authentication is successful', async () =
 
   await selectEvent.select(ui.organizationSelector.get(), [/org-1/]);
 
-  const inputSearch = screen.getByRole('searchbox', {
-    name: 'onboarding.create_project.search_repositories',
-  });
+  const inputSearch = screen.getByRole('searchbox');
   await user.click(inputSearch);
   await user.keyboard('search');
 
index e7850a2f1ecb462cdaf1ad038da4825701b13cee..08f0a44a77dfa09b5a2cae1b5195d25b8c0a0e5f 100644 (file)
@@ -58,9 +58,10 @@ export default function AlmRepoItem({
   return (
     <StyledCard
       key={almKey}
+      role="row"
       className={classNames('sw-flex sw-mb-2 sw-px-4', {
-        'sw-py-4': sqProjectKey,
-        'sw-py-2': !sqProjectKey,
+        'sw-py-4': sqProjectKey !== undefined,
+        'sw-py-2': sqProjectKey === undefined,
       })}
     >
       <div className="sw-w-[70%] sw-flex sw-mr-1">
@@ -87,7 +88,7 @@ export default function AlmRepoItem({
         </div>
       </div>
       <div className="sw-flex sw-justify-between sw-items-center sw-flex-1">
-        {almUrl && (
+        {almUrl !== undefined && (
           <div className="sw-flex sw-items-center">
             <Link
               className="sw-body-sm-highlight"
index b7c5c13c9c9fe5e1e47fdde974ee46434002bdb2..ce4e5dc4abac067985216623fbd2cb77e17bcc9c 100644 (file)
@@ -17,6 +17,8 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
+import { DarkLabel } from 'design-system';
 import * as React from 'react';
 import AlmSettingsInstanceSelector from '../../../../components/devops-platform/AlmSettingsInstanceSelector';
 import { hasMessage, translate, translateWithParameters } from '../../../../helpers/l10n';
@@ -42,15 +44,15 @@ export default function AlmSettingsInstanceDropdown(props: AlmSettingsInstanceDr
     : `alm.${almKey}`;
 
   return (
-    <div className="display-flex-column huge-spacer-bottom">
-      <label htmlFor="alm-config-selector" className="spacer-bottom">
+    <div className="sw-flex sw-flex-col">
+      <DarkLabel htmlFor="alm-config-selector" className="sw-mb-2">
         {translateWithParameters('alm.configuration.selector.label', translate(almKeyTranslation))}
-      </label>
+      </DarkLabel>
       <AlmSettingsInstanceSelector
         instances={almInstances}
         onChange={props.onChangeConfig}
         initialValue={selectedAlmInstance ? selectedAlmInstance.key : undefined}
-        classNames="abs-width-400"
+        className="sw-w-abs-400 sw-mb-9"
         inputId="alm-config-selector"
       />
     </div>
index a6aec18a440768d96d1f38b4e72d97642321352e..2c0c482303362c509d1d6f8ae3c37f2dc447705b 100644 (file)
@@ -31,8 +31,8 @@ import { translate } from '../../../../helpers/l10n';
 import { getGlobalSettingsUrl } from '../../../../helpers/urls';
 import {
   AlmSettingsInstance,
-  ProjectAlmBindingConfigurationErrors,
   ProjectAlmBindingConfigurationErrorScope,
+  ProjectAlmBindingConfigurationErrors,
   ProjectAlmBindingResponse,
 } from '../../../../types/alm-settings';
 import { ALM_INTEGRATION_CATEGORY } from '../../constants';
@@ -135,7 +135,7 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe
               instances={instances}
               onChange={(instance: AlmSettingsInstance) => props.onFieldChange('key', instance.key)}
               initialValue={formData.key}
-              classNames="abs-width-400 big-spacer-top it__configuration-name-select"
+              className="sw-w-abs-400 sw-mt-4 it__configuration-name-select"
               inputId="name"
             />
           </div>
index 04b764ef975423d4ac59780d6a799c64ee6419bb..19c7539dbd0b0d03398c35190e9aaeaca76a2dc1 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
+import { InputSelect, LabelValueSelectOption } from 'design-system';
 import * as React from 'react';
-import { components, OptionProps, SingleValueProps } from 'react-select';
+import { OptionProps, SingleValueProps, components } from 'react-select';
 import { translate } from '../../helpers/l10n';
 import { AlmSettingsInstance } from '../../types/alm-settings';
-import Select from '../controls/Select';
 
-function optionRenderer(props: OptionProps<AlmSettingsInstance, false>) {
-  return <components.Option {...props}>{customOptions(props.data)}</components.Option>;
+function optionRenderer(props: OptionProps<LabelValueSelectOption<AlmSettingsInstance>, false>) {
+  return <components.Option {...props}>{customOptions(props.data.value)}</components.Option>;
 }
 
-function singleValueRenderer(props: SingleValueProps<AlmSettingsInstance, false>) {
-  return <components.SingleValue {...props}>{customOptions(props.data)}</components.SingleValue>;
+function singleValueRenderer(
+  props: SingleValueProps<LabelValueSelectOption<AlmSettingsInstance>, false>
+) {
+  return (
+    <components.SingleValue {...props}>{customOptions(props.data.value)}</components.SingleValue>
+  );
 }
 
 function customOptions(instance: AlmSettingsInstance) {
@@ -42,36 +47,39 @@ function customOptions(instance: AlmSettingsInstance) {
   );
 }
 
+function orgToOption(alm: AlmSettingsInstance) {
+  return { value: alm, label: alm.key };
+}
+
 interface Props {
   instances: AlmSettingsInstance[];
   initialValue?: string;
   onChange: (instance: AlmSettingsInstance) => void;
-  classNames: string;
+  className: string;
   inputId: string;
 }
 
 export default function AlmSettingsInstanceSelector(props: Props) {
-  const { instances, initialValue, classNames, inputId } = props;
+  const { instances, initialValue, className, inputId } = props;
 
   return (
-    <Select
+    <InputSelect
       inputId={inputId}
-      className={classNames}
+      className={className}
       isClearable={false}
       isSearchable={false}
-      options={instances}
-      onChange={(inst) => {
-        if (inst) {
-          props.onChange(inst);
-        }
+      options={instances.map(orgToOption)}
+      onChange={(data: LabelValueSelectOption<AlmSettingsInstance>) => {
+        props.onChange(data.value);
       }}
       components={{
         Option: optionRenderer,
         SingleValue: singleValueRenderer,
       }}
       placeholder={translate('alm.configuration.selector.placeholder')}
-      getOptionValue={(opt) => opt.key}
-      value={instances.find((inst) => inst.key === initialValue) ?? null}
+      getOptionValue={(opt: LabelValueSelectOption<AlmSettingsInstance>) => opt.value.key}
+      value={instances.map(orgToOption).find((opt) => opt.value.key === initialValue) ?? null}
+      size="full"
     />
   );
 }
index df0c2cdfa2122d190b189b77f62cc199e65815ba..e8dab691458fd4e31b2c388b1d3b032fce396523 100644 (file)
@@ -3965,10 +3965,10 @@ onboarding.create_project.bitbucketcloud.title=Bitbucket Cloud project onboardin
 onboarding.create_project.bitbucketcloud.no_projects=No projects could be fetched from Bitbucket. Contact your system administrator, or {link}.
 onboarding.create_project.bitbucketcloud.link=See on Bitbucket
 onboarding.create_project.github.title=GitHub project onboarding
+onboarding.create_project.github.subtitle=Import repositories from one of your GitHub organizations
 onboarding.create_project.github.choose_organization=Choose organization
-onboarding.create_project.github.warning.title=Could not connect to GitHub
-onboarding.create_project.github.warning.message=Please contact an administrator to configure GitHub integration.
-onboarding.create_project.github.warning.message_admin=Please make sure the GitHub instance is correctly configured in the {link} to create a new project from a repository.
+onboarding.create_project.github.warning.message=Could not connect to GitHub. Please contact an administrator to configure GitHub integration.
+onboarding.create_project.github.warning.message_admin=Could not connect to GitHub. Please make sure the GitHub instance is correctly configured in the {link} to create a new project from a repository.
 onboarding.create_project.github.warning.message_admin.link=DevOps Platform integration settings
 onboarding.create_project.github.no_orgs=We couldn't load any organizations with your key. Contact an administrator.
 onboarding.create_project.github.no_orgs_admin=We couldn't load any organizations. Make sure the GitHub App is installed in at least one organization and check the GitHub instance configuration in the {link}.