diff options
author | Jeremy Davis <jeremy.davis@sonarsource.com> | 2019-10-24 17:49:18 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2019-11-06 10:04:29 +0100 |
commit | 7cb2dd55ce43a61c49b5ce390312cb3327ec565f (patch) | |
tree | ec48a0922cc81ec768f86cdb324801c56c672194 /server/sonar-web | |
parent | 22c6e4a22a6b07b41d61bae95c8b800452be1a77 (diff) | |
download | sonarqube-7cb2dd55ce43a61c49b5ce390312cb3327ec565f.tar.gz sonarqube-7cb2dd55ce43a61c49b5ce390312cb3327ec565f.zip |
Fixes from review
Diffstat (limited to 'server/sonar-web')
35 files changed, 618 insertions, 538 deletions
diff --git a/server/sonar-web/public/images/alm/azure.svg b/server/sonar-web/public/images/alm/azure.svg new file mode 100644 index 00000000000..a4350954295 --- /dev/null +++ b/server/sonar-web/public/images/alm/azure.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22.009 22"> + <path fill="#0078d7" d="M2.916 15.015v-7.25l19.093-3.758v13.446L16.62 21.92l-8.226-2.757V22l-5.478-6.985 13.216 1.728V5.052L9.812 0l.044 2.3-7.516 3L0 8.1v6.3z"/> +</svg>
\ No newline at end of file diff --git a/server/sonar-web/public/images/alm/bitbucket.svg b/server/sonar-web/public/images/alm/bitbucket.svg new file mode 100644 index 00000000000..984afdaa426 --- /dev/null +++ b/server/sonar-web/public/images/alm/bitbucket.svg @@ -0,0 +1,10 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="-361.924 -3545.014 58.441 52.551"> + <defs> + <linearGradient id="a" x1="1.086" x2=".469" y1=".138" y2=".788" gradientUnits="objectBoundingBox"> + <stop offset=".18" stop-color="#0052cc"/> + <stop offset="1" stop-color="#2684ff"/> + </linearGradient> + </defs> + <path fill="#2684ff" d="M-360.027-3545.013a1.872 1.872 0 0 0-1.871 2.172l7.947 48.253a2.547 2.547 0 0 0 2.49 2.125h38.133a1.872 1.872 0 0 0 1.872-1.573l7.949-48.8a1.872 1.872 0 0 0-1.872-2.172zm33.47 34.875h-12.171l-3.3-17.217h18.42z"/> + <path fill="url(#a)" d="M56.464 25.12H38.891l-2.949 17.217H23.771L9.4 59.4a2.537 2.537 0 0 0 1.638.618H49.18a1.872 1.872 0 0 0 1.872-1.573z" transform="translate(-362.499 -3552.476)"/> +</svg>
\ No newline at end of file diff --git a/server/sonar-web/public/images/alm/github.svg b/server/sonar-web/public/images/alm/github.svg new file mode 100644 index 00000000000..97c8f324e50 --- /dev/null +++ b/server/sonar-web/public/images/alm/github.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="-738.601 -3545.014 54.017 52.551"> + <path fill="#191717" fill-rule="evenodd" d="M-711.675-3545.014a26.975 26.975 0 0 0-8.59 52.53c1.322.165 1.817-.661 1.817-1.322v-4.625c-7.433 1.652-9.085-3.634-9.085-3.634-1.156-3.139-2.973-3.965-2.973-3.965-2.478-1.652.165-1.652.165-1.652 2.643.165 4.13 2.808 4.13 2.808 2.478 4.13 6.277 2.973 7.764 2.313a5.752 5.752 0 0 1 1.646-3.634c-5.947-.661-12.224-2.973-12.224-13.38a10.24 10.24 0 0 1 2.808-7.268 9.781 9.781 0 0 1 .33-6.938s2.313-.661 7.433 2.808a23.083 23.083 0 0 1 6.773-.826 30.4 30.4 0 0 1 6.773.826c5.121-3.469 7.433-2.808 7.433-2.808a10.343 10.343 0 0 1 .33 7.1 10.684 10.684 0 0 1 2.815 7.267c0 10.407-6.277 12.554-12.224 13.215.991.826 1.817 2.478 1.817 4.956v7.433c0 .661.5 1.487 1.817 1.322a26.976 26.976 0 0 0-8.755-52.526z"/> +</svg>
\ No newline at end of file diff --git a/server/sonar-web/src/main/js/app/styles/init/tables.css b/server/sonar-web/src/main/js/app/styles/init/tables.css index fc224d72663..a0bfecf7831 100644 --- a/server/sonar-web/src/main/js/app/styles/init/tables.css +++ b/server/sonar-web/src/main/js/app/styles/init/tables.css @@ -287,3 +287,15 @@ table.data.zebra.zebra-inversed > tbody > tr:nth-child(odd) { table#project-history tr > td { vertical-align: top; } + +table.fixed { + table-layout: fixed; +} + +table.fixed th.action-small { + width: 30px; +} + +table.fixed th.action { + width: 50px; +} diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AlmDefinitionFormField.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AlmDefinitionFormField.tsx index d462c0e829f..1e758a1671d 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AlmDefinitionFormField.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AlmDefinitionFormField.tsx @@ -24,48 +24,48 @@ import { AlmSettingsBinding } from '../../../../types/alm-settings'; export interface AlmDefinitionFormFieldProps<B extends AlmSettingsBinding> { autoFocus?: boolean; - formData: B; - help: boolean; + help?: React.ReactNode; id: string; - isTextArea: boolean; - maxLength: number; + isTextArea?: boolean; + maxLength?: number; onFieldChange: (id: keyof B, value: string) => void; propKey: keyof B; + value: string; } export function AlmDefinitionFormField<B extends AlmSettingsBinding>( props: AlmDefinitionFormFieldProps<B> ) { - const { autoFocus, formData, help, id, isTextArea, maxLength, onFieldChange, propKey } = props; + const { autoFocus, help, id, isTextArea, maxLength, onFieldChange, propKey, value } = props; return ( <div className="modal-field"> <label className="display-flex-center" htmlFor={id}> {translate('settings.pr_decoration.form', id)} <em className="mandatory spacer-right">*</em> - {help && <HelpTooltip overlay={translate('settings.pr_decoration.form', id, 'help')} />} + {help && <HelpTooltip overlay={help} placement="right" />} </label> {isTextArea ? ( <textarea className="settings-large-input" - id="privateKey" - maxLength={maxLength} + id={id} + maxLength={maxLength || 2000} onChange={e => onFieldChange(propKey, e.currentTarget.value)} required={true} rows={5} - value={String(formData[propKey])} + value={value} /> ) : ( <input autoFocus={autoFocus} className="input-super-large" id={id} - maxLength={maxLength} + maxLength={maxLength || 100} name={id} onChange={e => onFieldChange(propKey, e.currentTarget.value)} size={50} type="text" - value={String(formData[propKey])} + value={value} /> )} </div> diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureFormModal.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureFormModal.tsx index 07722a00cf5..6afe96824e2 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureFormModal.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureFormModal.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { translate } from 'sonar-ui-common/helpers/l10n'; import { AzureBindingDefinition } from '../../../../types/alm-settings'; import { AlmDefinitionFormField } from './AlmDefinitionFormField'; @@ -33,22 +34,19 @@ export default function AzureFormModal(props: AzureFormModalProps) { <> <AlmDefinitionFormField autoFocus={true} - formData={formData} - help={true} - id="name" - isTextArea={false} - maxLength={40} + help={translate('settings.pr_decoration.form.azure.name.help')} + id="azure.name" onFieldChange={onFieldChange} propKey="key" + value={formData.key} /> <AlmDefinitionFormField - formData={formData} - help={true} + help={translate('settings.pr_decoration.form.personal_access_token.help')} id="personal_access_token" isTextArea={true} - maxLength={2000} onFieldChange={onFieldChange} propKey="personalAccessToken" + value={formData.personalAccessToken} /> </> ); diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTabRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTabRenderer.tsx index 24d4039f794..5435f791243 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTabRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTabRenderer.tsx @@ -42,11 +42,9 @@ export default function AzureTabRenderer(props: AzureTabRendererProps) { <> <TabHeader alm={ALM_KEYS.AZURE} onCreate={props.onCreate} /> - {loading ? ( - <DeferredSpinner /> - ) : ( + <DeferredSpinner loading={loading}> <AzureTable definitions={definitions} onDelete={props.onDelete} onEdit={props.onEdit} /> - )} + </DeferredSpinner> {editedDefinition && ( <AlmPRDecorationFormModal diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTable.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTable.tsx index 11cfba29a46..066da515e1a 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTable.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/AzureTable.tsx @@ -33,29 +33,35 @@ export default function AzureTable(props: AzureTableProps) { const { definitions } = props; return ( - <table className="data zebra spacer-bottom"> + <table className="data zebra fixed spacer-bottom"> <thead> <tr> <th>{translate('settings.pr_decoration.table.column.name')}</th> - <th className="thin">{translate('settings.pr_decoration.table.column.edit')}</th> - <th className="thin">{translate('settings.pr_decoration.table.column.delete')}</th> + <th className="action-small text-center"> + {translate('settings.pr_decoration.table.column.edit')} + </th> + <th className="action text-center"> + {translate('settings.pr_decoration.table.column.delete')} + </th> </tr> </thead> <tbody> - {definitions.length < 1 ? ( + {definitions.length === 0 ? ( <tr> <td colSpan={3}>{translate('settings.pr_decoration.table.empty.azure')}</td> </tr> ) : ( definitions.map(definition => ( <tr key={definition.key}> - <td>{definition.key}</td> - <td> + <td className="nowrap hide-overflow" title={definition.key}> + {definition.key} + </td> + <td className="text-center"> <ButtonIcon onClick={() => props.onEdit(definition)}> <EditIcon /> </ButtonIcon> </td> - <td> + <td className="text-center"> <DeleteButton onClick={() => props.onDelete(definition.key)} /> </td> </tr> diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketFormModal.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketFormModal.tsx index 9484ceebf80..59058c93407 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketFormModal.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketFormModal.tsx @@ -18,6 +18,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { translate } from 'sonar-ui-common/helpers/l10n'; import { BitbucketBindingDefinition } from '../../../../types/alm-settings'; import { AlmDefinitionFormField } from './AlmDefinitionFormField'; @@ -33,31 +35,33 @@ export default function BitbucketFormModal(props: BitbucketFormModalProps) { <> <AlmDefinitionFormField autoFocus={true} - formData={formData} - help={true} - id="name" - isTextArea={false} - maxLength={40} + help={translate('settings.pr_decoration.form.url.bitbucket.name.help')} + id="bitbucket.name" + maxLength={100} onFieldChange={onFieldChange} propKey="key" + value={formData.key} /> <AlmDefinitionFormField - formData={formData} - help={false} + help={ + <FormattedMessage + defaultMessage={translate('settings.pr_decoration.form.url.bitbucket.help')} + id="settings.pr_decoration.form.url.bitbucket.help" + values={{ example: 'https://bitbucket-server.your-company.com' }} + /> + } id="url.bitbucket" - isTextArea={false} maxLength={2000} onFieldChange={onFieldChange} propKey="url" + value={formData.url} /> <AlmDefinitionFormField - formData={formData} - help={false} id="personal_access_token" isTextArea={true} - maxLength={2000} onFieldChange={onFieldChange} propKey="personalAccessToken" + value={formData.personalAccessToken} /> </> ); diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTabRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTabRenderer.tsx index 2f048c81ff8..c24b30b4120 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTabRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTabRenderer.tsx @@ -42,11 +42,9 @@ export default function BitbucketTabRenderer(props: BitbucketTabRendererProps) { <> <TabHeader alm={ALM_KEYS.BITBUCKET} onCreate={props.onCreate} /> - {loading ? ( - <DeferredSpinner /> - ) : ( + <DeferredSpinner loading={loading}> <BitbucketTable definitions={definitions} onDelete={props.onDelete} onEdit={props.onEdit} /> - )} + </DeferredSpinner> {editedDefinition && ( <AlmPRDecorationFormModal diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTable.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTable.tsx index 3183e625fb5..dc173e19788 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTable.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/BitbucketTable.tsx @@ -33,31 +33,39 @@ export default function BitbucketTable(props: BitbucketTableProps) { const { definitions } = props; return ( - <table className="data zebra spacer-bottom"> + <table className="data zebra fixed spacer-bottom"> <thead> <tr> <th>{translate('settings.pr_decoration.table.column.name')}</th> <th>{translate(`settings.pr_decoration.table.column.bitbucket.url`)}</th> - <th className="thin">{translate('settings.pr_decoration.table.column.edit')}</th> - <th className="thin">{translate('settings.pr_decoration.table.column.delete')}</th> + <th className="action-small text-center"> + {translate('settings.pr_decoration.table.column.edit')} + </th> + <th className="action text-center"> + {translate('settings.pr_decoration.table.column.delete')} + </th> </tr> </thead> <tbody> - {definitions.length < 1 ? ( + {definitions.length === 0 ? ( <tr> <td colSpan={4}>{translate('settings.pr_decoration.table.empty.bitbucket')}</td> </tr> ) : ( definitions.map(definition => ( <tr key={definition.key}> - <td>{definition.key}</td> - <td>{definition.url}</td> - <td> + <td className="nowrap hide-overflow" title={definition.key}> + {definition.key} + </td> + <td className="nowrap hide-overflow" title={definition.url}> + {definition.url} + </td> + <td className="text-center"> <ButtonIcon onClick={() => props.onEdit(definition)}> <EditIcon /> </ButtonIcon> </td> - <td> + <td className="text-center"> <DeleteButton onClick={() => props.onDelete(definition.key)} /> </td> </tr> diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubFormModal.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubFormModal.tsx index 728008eb947..a9d8a03eb6b 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubFormModal.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubFormModal.tsx @@ -18,6 +18,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { translate } from 'sonar-ui-common/helpers/l10n'; import { GithubBindingDefinition } from '../../../../types/alm-settings'; import { AlmDefinitionFormField } from './AlmDefinitionFormField'; @@ -33,40 +35,39 @@ export default function GithubFormModal(props: GithubFormModalProps) { <> <AlmDefinitionFormField autoFocus={true} - formData={formData} - help={true} - id="name" - isTextArea={false} - maxLength={40} + help={translate('settings.pr_decoration.form.github.name.help')} + id="github.name" onFieldChange={onFieldChange} propKey="key" + value={formData.key} /> <AlmDefinitionFormField - formData={formData} - help={false} + help={ + <FormattedMessage + defaultMessage={translate('settings.pr_decoration.form.url.github.help')} + id="settings.pr_decoration.form.url.github.help" + values={{ example: 'https://github.company.com/api/v3' }} + /> + } id="url.github" - isTextArea={false} maxLength={2000} onFieldChange={onFieldChange} propKey="url" + value={formData.url} /> <AlmDefinitionFormField - formData={formData} - help={false} id="app_id" - isTextArea={false} maxLength={80} onFieldChange={onFieldChange} propKey="appId" + value={formData.appId} /> <AlmDefinitionFormField - formData={formData} - help={false} id="private_key" isTextArea={true} - maxLength={2000} onFieldChange={onFieldChange} propKey="privateKey" + value={formData.privateKey} /> </> ); diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTabRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTabRenderer.tsx index 811178734e3..e135049b98d 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTabRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTabRenderer.tsx @@ -42,11 +42,9 @@ export default function GithubTabRenderer(props: GithubTabRendererProps) { <> <TabHeader alm={ALM_KEYS.GITHUB} onCreate={props.onCreate} /> - {loading ? ( - <DeferredSpinner /> - ) : ( + <DeferredSpinner loading={loading}> <GithubTable definitions={definitions} onDelete={props.onDelete} onEdit={props.onEdit} /> - )} + </DeferredSpinner> {editedDefinition && ( <AlmPRDecorationFormModal diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTable.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTable.tsx index f9d6db98f75..6c992dac1f8 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTable.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/GithubTable.tsx @@ -33,32 +33,48 @@ export default function GithubTable(props: GithubTableProps) { const { definitions } = props; return ( - <table className="data zebra spacer-bottom"> + <table className="data zebra fixed spacer-bottom"> <thead> <tr> <th>{translate('settings.pr_decoration.table.column.name')}</th> <th>{translate(`settings.pr_decoration.table.column.github.url`)}</th> <th>{translate('settings.pr_decoration.table.column.app_id')}</th> - <th className="thin">{translate('settings.pr_decoration.table.column.edit')}</th> - <th className="thin">{translate('settings.pr_decoration.table.column.delete')}</th> + <th className="action-small text-center"> + {translate('settings.pr_decoration.table.column.edit')} + </th> + <th className="action text-center"> + {translate('settings.pr_decoration.table.column.delete')} + </th> </tr> </thead> <tbody> - {definitions.map(definition => ( - <tr key={definition.key}> - <td>{definition.key}</td> - <td>{definition.url}</td> - <td>{definition.appId}</td> - <td> - <ButtonIcon onClick={() => props.onEdit(definition)}> - <EditIcon /> - </ButtonIcon> - </td> - <td> - <DeleteButton onClick={() => props.onDelete(definition.key)} /> - </td> + {definitions.length === 0 ? ( + <tr> + <td colSpan={5}>{translate('settings.pr_decoration.table.empty.github')}</td> </tr> - ))} + ) : ( + definitions.map(definition => ( + <tr key={definition.key}> + <td className="nowrap hide-overflow" title={definition.key}> + {definition.key} + </td> + <td className="nowrap hide-overflow" title={definition.url}> + {definition.url} + </td> + <td className="nowrap hide-overflow" title={definition.appId}> + {definition.appId} + </td> + <td className="text-center"> + <ButtonIcon onClick={() => props.onEdit(definition)}> + <EditIcon /> + </ButtonIcon> + </td> + <td className="text-center"> + <DeleteButton onClick={() => props.onDelete(definition.key)} /> + </td> + </tr> + )) + )} </tbody> </table> ); diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/PRDecorationTabs.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/PRDecorationTabs.tsx index 680fa4a6aab..2e006acec97 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/PRDecorationTabs.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/PRDecorationTabs.tsx @@ -22,7 +22,6 @@ import BoxedTabs from 'sonar-ui-common/components/controls/BoxedTabs'; import { translate } from 'sonar-ui-common/helpers/l10n'; import { getBaseUrl } from 'sonar-ui-common/helpers/urls'; import { AlmSettingsBindingDefinitions, ALM_KEYS } from '../../../../types/alm-settings'; -import { almName } from '../../utils'; import AzureTab from './AzureTab'; import BitbucketTab from './BitbucketTab'; import DeleteModal from './DeleteModal'; @@ -41,6 +40,12 @@ export interface PRDecorationTabsProps { projectCount?: number; } +export const almName = { + [ALM_KEYS.AZURE]: 'Azure DevOps Server', + [ALM_KEYS.BITBUCKET]: 'Bitbucket Server', + [ALM_KEYS.GITHUB]: 'Github Enterprise' +}; + export default function PRDecorationTabs(props: PRDecorationTabsProps) { const { definitionKeyForDeletion, definitions, currentAlm, loading, projectCount } = props; @@ -64,7 +69,7 @@ export default function PRDecorationTabs(props: PRDecorationTabsProps) { <img alt="github" className="spacer-right" - src={`${getBaseUrl()}/images/sonarcloud/github.svg`} + src={`${getBaseUrl()}/images/alm/github.svg`} width={16} /> {almName[ALM_KEYS.GITHUB]} @@ -78,7 +83,7 @@ export default function PRDecorationTabs(props: PRDecorationTabsProps) { <img alt="bitbucket" className="spacer-right" - src={`${getBaseUrl()}/images/sonarcloud/bitbucket.svg`} + src={`${getBaseUrl()}/images/alm/bitbucket.svg`} width={16} /> {almName[ALM_KEYS.BITBUCKET]} @@ -92,7 +97,7 @@ export default function PRDecorationTabs(props: PRDecorationTabsProps) { <img alt="azure" className="spacer-right" - src={`${getBaseUrl()}/images/sonarcloud/azure.svg`} + src={`${getBaseUrl()}/images/alm/azure.svg`} width={16} /> {almName[ALM_KEYS.AZURE]} diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/AlmDefinitionFormField-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/AlmDefinitionFormField-test.tsx index a30e8533ede..2d90411888e 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/AlmDefinitionFormField-test.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/AlmDefinitionFormField-test.tsx @@ -24,7 +24,7 @@ import { AlmDefinitionFormField, AlmDefinitionFormFieldProps } from '../AlmDefin it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot(); - expect(shallowRender({ help: true })).toMatchSnapshot(); + expect(shallowRender({ help: 'help' })).toMatchSnapshot(); expect(shallowRender({ isTextArea: true })).toMatchSnapshot(); }); @@ -45,13 +45,12 @@ it('should call onFieldChange', () => { function shallowRender(props: Partial<AlmDefinitionFormFieldProps<AlmSettingsBinding>> = {}) { return shallow( <AlmDefinitionFormField - formData={{ key: 'key' }} - help={false} id="key" isTextArea={false} maxLength={40} onFieldChange={jest.fn()} propKey="key" + value="key" {...props} /> ); diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AlmDefinitionFormField-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AlmDefinitionFormField-test.tsx.snap index 21d0c24cc8e..0d975f13e19 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AlmDefinitionFormField-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AlmDefinitionFormField-test.tsx.snap @@ -43,7 +43,8 @@ exports[`should render correctly 2`] = ` * </em> <HelpTooltip - overlay="settings.pr_decoration.form.key.help" + overlay="help" + placement="right" /> </label> <input @@ -76,7 +77,7 @@ exports[`should render correctly 3`] = ` </label> <textarea className="settings-large-input" - id="privateKey" + id="key" maxLength={40} onChange={[Function]} required={true} diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureFormModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureFormModal-test.tsx.snap index ec50eab5e05..4629360ad17 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureFormModal-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureFormModal-test.tsx.snap @@ -4,32 +4,19 @@ exports[`should render correctly 1`] = ` <Fragment> <AlmDefinitionFormField autoFocus={true} - formData={ - Object { - "key": "", - "personalAccessToken": "", - } - } - help={true} - id="name" - isTextArea={false} - maxLength={40} + help="settings.pr_decoration.form.azure.name.help" + id="azure.name" onFieldChange={[MockFunction]} propKey="key" + value="" /> <AlmDefinitionFormField - formData={ - Object { - "key": "", - "personalAccessToken": "", - } - } - help={true} + help="settings.pr_decoration.form.personal_access_token.help" id="personal_access_token" isTextArea={true} - maxLength={2000} onFieldChange={[MockFunction]} propKey="personalAccessToken" + value="" /> </Fragment> `; @@ -38,32 +25,19 @@ exports[`should render correctly 2`] = ` <Fragment> <AlmDefinitionFormField autoFocus={true} - formData={ - Object { - "key": "key", - "personalAccessToken": "asdf1234", - } - } - help={true} - id="name" - isTextArea={false} - maxLength={40} + help="settings.pr_decoration.form.azure.name.help" + id="azure.name" onFieldChange={[MockFunction]} propKey="key" + value="key" /> <AlmDefinitionFormField - formData={ - Object { - "key": "key", - "personalAccessToken": "asdf1234", - } - } - help={true} + help="settings.pr_decoration.form.personal_access_token.help" id="personal_access_token" isTextArea={true} - maxLength={2000} onFieldChange={[MockFunction]} propKey="personalAccessToken" + value="asdf1234" /> </Fragment> `; diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTabRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTabRenderer-test.tsx.snap index 769cf16ba05..8e5d8722a57 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTabRenderer-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTabRenderer-test.tsx.snap @@ -7,8 +7,15 @@ exports[`should render correctly 1`] = ` onCreate={[MockFunction]} /> <DeferredSpinner + loading={true} timeout={100} - /> + > + <AzureTable + definitions={Array []} + onDelete={[MockFunction]} + onEdit={[MockFunction]} + /> + </DeferredSpinner> </Fragment> `; @@ -18,11 +25,16 @@ exports[`should render correctly 2`] = ` alm="azure" onCreate={[MockFunction]} /> - <AzureTable - definitions={Array []} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - /> + <DeferredSpinner + loading={false} + timeout={100} + > + <AzureTable + definitions={Array []} + onDelete={[MockFunction]} + onEdit={[MockFunction]} + /> + </DeferredSpinner> </Fragment> `; @@ -32,11 +44,16 @@ exports[`should render correctly 3`] = ` alm="azure" onCreate={[MockFunction]} /> - <AzureTable - definitions={Array []} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - /> + <DeferredSpinner + loading={false} + timeout={100} + > + <AzureTable + definitions={Array []} + onDelete={[MockFunction]} + onEdit={[MockFunction]} + /> + </DeferredSpinner> <AlmPRDecorationFormModal bindingDefinition={ Object { diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTable-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTable-test.tsx.snap index 05b1adfd0be..167cec1a957 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTable-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/AzureTable-test.tsx.snap @@ -2,7 +2,7 @@ exports[`should render correctly 1`] = ` <table - className="data zebra spacer-bottom" + className="data zebra fixed spacer-bottom" > <thead> <tr> @@ -10,12 +10,12 @@ exports[`should render correctly 1`] = ` settings.pr_decoration.table.column.name </th> <th - className="thin" + className="action-small text-center" > settings.pr_decoration.table.column.edit </th> <th - className="thin" + className="action text-center" > settings.pr_decoration.table.column.delete </th> @@ -35,7 +35,7 @@ exports[`should render correctly 1`] = ` exports[`should render correctly 2`] = ` <table - className="data zebra spacer-bottom" + className="data zebra fixed spacer-bottom" > <thead> <tr> @@ -43,12 +43,12 @@ exports[`should render correctly 2`] = ` settings.pr_decoration.table.column.name </th> <th - className="thin" + className="action-small text-center" > settings.pr_decoration.table.column.edit </th> <th - className="thin" + className="action text-center" > settings.pr_decoration.table.column.delete </th> @@ -58,17 +58,24 @@ exports[`should render correctly 2`] = ` <tr key="key" > - <td> + <td + className="nowrap hide-overflow" + title="key" + > key </td> - <td> + <td + className="text-center" + > <ButtonIcon onClick={[Function]} > <EditIcon /> </ButtonIcon> </td> - <td> + <td + className="text-center" + > <DeleteButton onClick={[Function]} /> diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketFormModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketFormModal-test.tsx.snap index f1fb7f72c31..9b90ffbbaba 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketFormModal-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketFormModal-test.tsx.snap @@ -4,49 +4,37 @@ exports[`should render correctly 1`] = ` <Fragment> <AlmDefinitionFormField autoFocus={true} - formData={ - Object { - "key": "", - "personalAccessToken": "", - "url": "", - } - } - help={true} - id="name" - isTextArea={false} - maxLength={40} + help="settings.pr_decoration.form.url.bitbucket.name.help" + id="bitbucket.name" + maxLength={100} onFieldChange={[MockFunction]} propKey="key" + value="" /> <AlmDefinitionFormField - formData={ - Object { - "key": "", - "personalAccessToken": "", - "url": "", - } + help={ + <FormattedMessage + defaultMessage="settings.pr_decoration.form.url.bitbucket.help" + id="settings.pr_decoration.form.url.bitbucket.help" + values={ + Object { + "example": "https://bitbucket-server.your-company.com", + } + } + /> } - help={false} id="url.bitbucket" - isTextArea={false} maxLength={2000} onFieldChange={[MockFunction]} propKey="url" + value="" /> <AlmDefinitionFormField - formData={ - Object { - "key": "", - "personalAccessToken": "", - "url": "", - } - } - help={false} id="personal_access_token" isTextArea={true} - maxLength={2000} onFieldChange={[MockFunction]} propKey="personalAccessToken" + value="" /> </Fragment> `; @@ -55,49 +43,37 @@ exports[`should render correctly 2`] = ` <Fragment> <AlmDefinitionFormField autoFocus={true} - formData={ - Object { - "key": "key", - "personalAccessToken": "asdf1234", - "url": "http://bbs.enterprise.com", - } - } - help={true} - id="name" - isTextArea={false} - maxLength={40} + help="settings.pr_decoration.form.url.bitbucket.name.help" + id="bitbucket.name" + maxLength={100} onFieldChange={[MockFunction]} propKey="key" + value="key" /> <AlmDefinitionFormField - formData={ - Object { - "key": "key", - "personalAccessToken": "asdf1234", - "url": "http://bbs.enterprise.com", - } + help={ + <FormattedMessage + defaultMessage="settings.pr_decoration.form.url.bitbucket.help" + id="settings.pr_decoration.form.url.bitbucket.help" + values={ + Object { + "example": "https://bitbucket-server.your-company.com", + } + } + /> } - help={false} id="url.bitbucket" - isTextArea={false} maxLength={2000} onFieldChange={[MockFunction]} propKey="url" + value="http://bbs.enterprise.com" /> <AlmDefinitionFormField - formData={ - Object { - "key": "key", - "personalAccessToken": "asdf1234", - "url": "http://bbs.enterprise.com", - } - } - help={false} id="personal_access_token" isTextArea={true} - maxLength={2000} onFieldChange={[MockFunction]} propKey="personalAccessToken" + value="asdf1234" /> </Fragment> `; diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap index 033e8cb82ec..e8d9c8283b9 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap @@ -7,8 +7,15 @@ exports[`should render correctly 1`] = ` onCreate={[MockFunction]} /> <DeferredSpinner + loading={true} timeout={100} - /> + > + <BitbucketTable + definitions={Array []} + onDelete={[MockFunction]} + onEdit={[MockFunction]} + /> + </DeferredSpinner> </Fragment> `; @@ -18,11 +25,16 @@ exports[`should render correctly 2`] = ` alm="bitbucket" onCreate={[MockFunction]} /> - <BitbucketTable - definitions={Array []} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - /> + <DeferredSpinner + loading={false} + timeout={100} + > + <BitbucketTable + definitions={Array []} + onDelete={[MockFunction]} + onEdit={[MockFunction]} + /> + </DeferredSpinner> </Fragment> `; @@ -32,11 +44,16 @@ exports[`should render correctly 3`] = ` alm="bitbucket" onCreate={[MockFunction]} /> - <BitbucketTable - definitions={Array []} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - /> + <DeferredSpinner + loading={false} + timeout={100} + > + <BitbucketTable + definitions={Array []} + onDelete={[MockFunction]} + onEdit={[MockFunction]} + /> + </DeferredSpinner> <AlmPRDecorationFormModal bindingDefinition={ Object { diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTable-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTable-test.tsx.snap index 95b21970235..8af449d84b7 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTable-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/BitbucketTable-test.tsx.snap @@ -2,7 +2,7 @@ exports[`should render correctly 1`] = ` <table - className="data zebra spacer-bottom" + className="data zebra fixed spacer-bottom" > <thead> <tr> @@ -13,12 +13,12 @@ exports[`should render correctly 1`] = ` settings.pr_decoration.table.column.bitbucket.url </th> <th - className="thin" + className="action-small text-center" > settings.pr_decoration.table.column.edit </th> <th - className="thin" + className="action text-center" > settings.pr_decoration.table.column.delete </th> @@ -38,7 +38,7 @@ exports[`should render correctly 1`] = ` exports[`should render correctly 2`] = ` <table - className="data zebra spacer-bottom" + className="data zebra fixed spacer-bottom" > <thead> <tr> @@ -49,12 +49,12 @@ exports[`should render correctly 2`] = ` settings.pr_decoration.table.column.bitbucket.url </th> <th - className="thin" + className="action-small text-center" > settings.pr_decoration.table.column.edit </th> <th - className="thin" + className="action text-center" > settings.pr_decoration.table.column.delete </th> @@ -64,20 +64,30 @@ exports[`should render correctly 2`] = ` <tr key="key" > - <td> + <td + className="nowrap hide-overflow" + title="key" + > key </td> - <td> + <td + className="nowrap hide-overflow" + title="http://bbs.enterprise.com" + > http://bbs.enterprise.com </td> - <td> + <td + className="text-center" + > <ButtonIcon onClick={[Function]} > <EditIcon /> </ButtonIcon> </td> - <td> + <td + className="text-center" + > <DeleteButton onClick={[Function]} /> diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubFormModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubFormModal-test.tsx.snap index 9cdbcc5b7f3..61ea7a13a8b 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubFormModal-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubFormModal-test.tsx.snap @@ -4,68 +4,43 @@ exports[`should render correctly 1`] = ` <Fragment> <AlmDefinitionFormField autoFocus={true} - formData={ - Object { - "appId": "", - "key": "", - "privateKey": "", - "url": "", - } - } - help={true} - id="name" - isTextArea={false} - maxLength={40} + help="settings.pr_decoration.form.github.name.help" + id="github.name" onFieldChange={[MockFunction]} propKey="key" + value="" /> <AlmDefinitionFormField - formData={ - Object { - "appId": "", - "key": "", - "privateKey": "", - "url": "", - } + help={ + <FormattedMessage + defaultMessage="settings.pr_decoration.form.url.github.help" + id="settings.pr_decoration.form.url.github.help" + values={ + Object { + "example": "https://github.company.com/api/v3", + } + } + /> } - help={false} id="url.github" - isTextArea={false} maxLength={2000} onFieldChange={[MockFunction]} propKey="url" + value="" /> <AlmDefinitionFormField - formData={ - Object { - "appId": "", - "key": "", - "privateKey": "", - "url": "", - } - } - help={false} id="app_id" - isTextArea={false} maxLength={80} onFieldChange={[MockFunction]} propKey="appId" + value="" /> <AlmDefinitionFormField - formData={ - Object { - "appId": "", - "key": "", - "privateKey": "", - "url": "", - } - } - help={false} id="private_key" isTextArea={true} - maxLength={2000} onFieldChange={[MockFunction]} propKey="privateKey" + value="" /> </Fragment> `; @@ -74,68 +49,43 @@ exports[`should render correctly 2`] = ` <Fragment> <AlmDefinitionFormField autoFocus={true} - formData={ - Object { - "appId": "123456", - "key": "key", - "privateKey": "asdf1234", - "url": "http://github.enterprise.com", - } - } - help={true} - id="name" - isTextArea={false} - maxLength={40} + help="settings.pr_decoration.form.github.name.help" + id="github.name" onFieldChange={[MockFunction]} propKey="key" + value="key" /> <AlmDefinitionFormField - formData={ - Object { - "appId": "123456", - "key": "key", - "privateKey": "asdf1234", - "url": "http://github.enterprise.com", - } + help={ + <FormattedMessage + defaultMessage="settings.pr_decoration.form.url.github.help" + id="settings.pr_decoration.form.url.github.help" + values={ + Object { + "example": "https://github.company.com/api/v3", + } + } + /> } - help={false} id="url.github" - isTextArea={false} maxLength={2000} onFieldChange={[MockFunction]} propKey="url" + value="http://github.enterprise.com" /> <AlmDefinitionFormField - formData={ - Object { - "appId": "123456", - "key": "key", - "privateKey": "asdf1234", - "url": "http://github.enterprise.com", - } - } - help={false} id="app_id" - isTextArea={false} maxLength={80} onFieldChange={[MockFunction]} propKey="appId" + value="123456" /> <AlmDefinitionFormField - formData={ - Object { - "appId": "123456", - "key": "key", - "privateKey": "asdf1234", - "url": "http://github.enterprise.com", - } - } - help={false} id="private_key" isTextArea={true} - maxLength={2000} onFieldChange={[MockFunction]} propKey="privateKey" + value="asdf1234" /> </Fragment> `; diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTabRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTabRenderer-test.tsx.snap index 032b06c1f53..f37d1b20090 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTabRenderer-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTabRenderer-test.tsx.snap @@ -7,8 +7,15 @@ exports[`should render correctly 1`] = ` onCreate={[MockFunction]} /> <DeferredSpinner + loading={true} timeout={100} - /> + > + <GithubTable + definitions={Array []} + onDelete={[MockFunction]} + onEdit={[MockFunction]} + /> + </DeferredSpinner> </Fragment> `; @@ -18,11 +25,16 @@ exports[`should render correctly 2`] = ` alm="github" onCreate={[MockFunction]} /> - <GithubTable - definitions={Array []} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - /> + <DeferredSpinner + loading={false} + timeout={100} + > + <GithubTable + definitions={Array []} + onDelete={[MockFunction]} + onEdit={[MockFunction]} + /> + </DeferredSpinner> </Fragment> `; @@ -32,11 +44,16 @@ exports[`should render correctly 3`] = ` alm="github" onCreate={[MockFunction]} /> - <GithubTable - definitions={Array []} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - /> + <DeferredSpinner + loading={false} + timeout={100} + > + <GithubTable + definitions={Array []} + onDelete={[MockFunction]} + onEdit={[MockFunction]} + /> + </DeferredSpinner> <AlmPRDecorationFormModal bindingDefinition={ Object { diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTable-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTable-test.tsx.snap index 9284ab59d0f..e2180fa9773 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTable-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/GithubTable-test.tsx.snap @@ -2,7 +2,7 @@ exports[`should render correctly 1`] = ` <table - className="data zebra spacer-bottom" + className="data zebra fixed spacer-bottom" > <thead> <tr> @@ -16,24 +16,32 @@ exports[`should render correctly 1`] = ` settings.pr_decoration.table.column.app_id </th> <th - className="thin" + className="action-small text-center" > settings.pr_decoration.table.column.edit </th> <th - className="thin" + className="action text-center" > settings.pr_decoration.table.column.delete </th> </tr> </thead> - <tbody /> + <tbody> + <tr> + <td + colSpan={5} + > + settings.pr_decoration.table.empty.github + </td> + </tr> + </tbody> </table> `; exports[`should render correctly 2`] = ` <table - className="data zebra spacer-bottom" + className="data zebra fixed spacer-bottom" > <thead> <tr> @@ -47,12 +55,12 @@ exports[`should render correctly 2`] = ` settings.pr_decoration.table.column.app_id </th> <th - className="thin" + className="action-small text-center" > settings.pr_decoration.table.column.edit </th> <th - className="thin" + className="action text-center" > settings.pr_decoration.table.column.delete </th> @@ -62,23 +70,36 @@ exports[`should render correctly 2`] = ` <tr key="key" > - <td> + <td + className="nowrap hide-overflow" + title="key" + > key </td> - <td> + <td + className="nowrap hide-overflow" + title="http://github.enterprise.com" + > http://github.enterprise.com </td> - <td> + <td + className="nowrap hide-overflow" + title="123456" + > 123456 </td> - <td> + <td + className="text-center" + > <ButtonIcon onClick={[Function]} > <EditIcon /> </ButtonIcon> </td> - <td> + <td + className="text-center" + > <DeleteButton onClick={[Function]} /> diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/PRDecorationTabs-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/PRDecorationTabs-test.tsx.snap index 277eec9e944..410c129e995 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/PRDecorationTabs-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecoration/__tests__/__snapshots__/PRDecorationTabs-test.tsx.snap @@ -27,7 +27,7 @@ exports[`should render correctly 1`] = ` <img alt="github" className="spacer-right" - src="/images/sonarcloud/github.svg" + src="/images/alm/github.svg" width={16} /> Github Enterprise @@ -39,7 +39,7 @@ exports[`should render correctly 1`] = ` <img alt="bitbucket" className="spacer-right" - src="/images/sonarcloud/bitbucket.svg" + src="/images/alm/bitbucket.svg" width={16} /> Bitbucket Server @@ -51,7 +51,7 @@ exports[`should render correctly 1`] = ` <img alt="azure" className="spacer-right" - src="/images/sonarcloud/azure.svg" + src="/images/alm/azure.svg" width={16} /> Azure DevOps Server @@ -100,7 +100,7 @@ exports[`should render correctly 2`] = ` <img alt="github" className="spacer-right" - src="/images/sonarcloud/github.svg" + src="/images/alm/github.svg" width={16} /> Github Enterprise @@ -112,7 +112,7 @@ exports[`should render correctly 2`] = ` <img alt="bitbucket" className="spacer-right" - src="/images/sonarcloud/bitbucket.svg" + src="/images/alm/bitbucket.svg" width={16} /> Bitbucket Server @@ -124,7 +124,7 @@ exports[`should render correctly 2`] = ` <img alt="azure" className="spacer-right" - src="/images/sonarcloud/azure.svg" + src="/images/alm/azure.svg" width={16} /> Azure DevOps Server @@ -178,7 +178,7 @@ exports[`should render correctly 3`] = ` <img alt="github" className="spacer-right" - src="/images/sonarcloud/github.svg" + src="/images/alm/github.svg" width={16} /> Github Enterprise @@ -190,7 +190,7 @@ exports[`should render correctly 3`] = ` <img alt="bitbucket" className="spacer-right" - src="/images/sonarcloud/bitbucket.svg" + src="/images/alm/bitbucket.svg" width={16} /> Bitbucket Server @@ -202,7 +202,7 @@ exports[`should render correctly 3`] = ` <img alt="azure" className="spacer-right" - src="/images/sonarcloud/azure.svg" + src="/images/alm/azure.svg" width={16} /> Azure DevOps Server @@ -251,7 +251,7 @@ exports[`should render correctly 4`] = ` <img alt="github" className="spacer-right" - src="/images/sonarcloud/github.svg" + src="/images/alm/github.svg" width={16} /> Github Enterprise @@ -263,7 +263,7 @@ exports[`should render correctly 4`] = ` <img alt="bitbucket" className="spacer-right" - src="/images/sonarcloud/bitbucket.svg" + src="/images/alm/bitbucket.svg" width={16} /> Bitbucket Server @@ -275,7 +275,7 @@ exports[`should render correctly 4`] = ` <img alt="azure" className="spacer-right" - src="/images/sonarcloud/azure.svg" + src="/images/alm/azure.svg" width={16} /> Azure DevOps Server diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx index aae3dc9a12b..e5f40286a53 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx @@ -36,30 +36,24 @@ interface Props { interface State { formData: ProjectAlmBinding; - hasBinding: boolean; instances: AlmSettingsInstance[]; isValid: boolean; loading: boolean; + originalData?: ProjectAlmBinding; saving: boolean; success: boolean; } -const FIELDS_BY_ALM: { - [almKey: string]: Array<'repository' | 'repositoryKey' | 'repositorySlug'>; -} = { +const FIELDS_BY_ALM: { [almKey in ALM_KEYS]: Array<keyof T.Omit<ProjectAlmBinding, 'key'>> } = { [ALM_KEYS.AZURE]: [], - [ALM_KEYS.BITBUCKET]: ['repositoryKey', 'repositorySlug'], + [ALM_KEYS.BITBUCKET]: ['repository', 'slug'], [ALM_KEYS.GITHUB]: ['repository'] }; export default class PRDecorationBinding extends React.PureComponent<Props, State> { mounted = false; state: State = { - formData: { - key: '', - repository: '' - }, - hasBinding: false, + formData: { key: '' }, instances: [], isValid: false, loading: true, @@ -79,22 +73,18 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat fetchDefinitions = () => { const project = this.props.component.key; return Promise.all([getAlmSettings(project), this.getProjectBinding(project)]) - .then(([instances, data]) => { + .then(([instances, originalData]) => { if (this.mounted) { this.setState(({ formData }) => { - const newFormData = data || formData; + const newFormData = originalData || formData; return { formData: newFormData, - hasBinding: Boolean(data), instances, isValid: this.validateForm(newFormData), - loading: false + loading: false, + originalData }; }); - - if (!data && instances.length === 1) { - this.handleFieldChange('key', instances[0].key); - } } }) .catch(() => { @@ -104,7 +94,7 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat }); }; - getProjectBinding(project: string) { + getProjectBinding(project: string): Promise<ProjectAlmBinding | undefined> { return getProjectAlmBinding(project).catch((response: Response) => { if (response && response.status === 404) { return Promise.resolve(undefined); @@ -128,9 +118,10 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat this.setState({ formData: { key: '', - repository: '' + repository: '', + slug: '' }, - hasBinding: false, + originalData: undefined, saving: false, success: true }); @@ -142,7 +133,7 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat submitProjectAlmBinding( alm: ALM_KEYS, key: string, - almSpecificFields?: { repository?: string; repositoryKey?: string; repositorySlug?: string } + almSpecificFields?: T.Omit<ProjectAlmBinding, 'key'> ): Promise<void> { const almSetting = key; const project = this.props.component.key; @@ -157,12 +148,12 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat if (!almSpecificFields) { return Promise.reject(); } - const { repositoryKey = '', repositorySlug = '' } = almSpecificFields; + const { repository = '', slug = '' } = almSpecificFields; return setProjectBitbucketBinding({ almSetting, project, - repositoryKey, - repositorySlug + repository, + slug }); } case ALM_KEYS.GITHUB: { @@ -198,12 +189,12 @@ export default class PRDecorationBinding extends React.PureComponent<Props, Stat .then(() => { if (this.mounted) { this.setState({ - hasBinding: true, saving: false, success: true }); } }) + .then(this.fetchDefinitions) .catch(this.catchError); } }; diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx index db5aeb9d6e0..7a1eb479ada 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBindingRenderer.tsx @@ -31,19 +31,26 @@ import { AlmSettingsInstance, ALM_KEYS, ProjectAlmBinding } from '../../../../ty export interface PRDecorationBindingRendererProps { formData: ProjectAlmBinding; - hasBinding: boolean; instances: AlmSettingsInstance[]; isValid: boolean; loading: boolean; onFieldChange: (id: keyof ProjectAlmBinding, value: string) => void; onReset: () => void; onSubmit: () => void; + originalData?: ProjectAlmBinding; saving: boolean; success: boolean; } -function renderLabel(v: AlmSettingsInstance) { - return v.url ? `${v.key} — ${v.url}` : v.key; +function optionRenderer(instance: AlmSettingsInstance) { + return instance.url ? ( + <> + <span>{instance.key} — </span> + <span className="text-muted">{instance.url}</span> + </> + ) : ( + <span>{instance.key}</span> + ); } function renderField(props: { @@ -86,13 +93,20 @@ function renderField(props: { ); } +function isDataSame( + { key, repository = '', slug = '' }: ProjectAlmBinding, + { key: oKey = '', repository: oRepository = '', slug: oSlug = '' }: ProjectAlmBinding +) { + return key === oKey && repository === oRepository && slug === oSlug; +} + export default function PRDecorationBindingRenderer(props: PRDecorationBindingRendererProps) { const { - formData: { key, repository, repositoryKey, repositorySlug }, - hasBinding, + formData: { key, repository, slug }, instances, isValid, loading, + originalData, saving, success } = props; @@ -124,6 +138,8 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe const selected = key && instances.find(i => i.key === key); const alm = selected && selected.alm; + const isChanged = !isDataSame({ key, repository, slug }, originalData || { key: '' }); + return ( <div> <header className="page-header"> @@ -145,13 +161,21 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe <em className="mandatory spacer-right">*</em> </label> <Select + autosize={true} className="abs-width-400" clearable={false} id="name" - onChange={({ value }: { value: string }) => props.onFieldChange('key', value)} - options={instances.map(v => ({ value: v.key, label: renderLabel(v) }))} + menuContainerStyle={{ + maxWidth: '210%' /* Allow double the width of the select */, + width: 'auto' + }} + onChange={(instance: AlmSettingsInstance) => props.onFieldChange('key', instance.key)} + optionRenderer={optionRenderer} + options={instances} searchable={false} value={key} + valueKey="key" + valueRenderer={optionRenderer} /> </div> @@ -168,10 +192,10 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe </> ) }, - id: 'repository_key', + id: 'bitbucket.repository', onFieldChange: props.onFieldChange, - propKey: 'repositoryKey', - value: repositoryKey || '' + propKey: 'repository', + value: repository || '' })} {renderField({ help: true, @@ -184,10 +208,10 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe </> ) }, - id: 'repository_slug', + id: 'bitbucket.slug', onFieldChange: props.onFieldChange, - propKey: 'repositorySlug', - value: repositorySlug || '' + propKey: 'slug', + value: slug || '' })} </> )} @@ -196,7 +220,7 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe renderField({ help: true, helpParams: { example: 'SonarSource/sonarqube' }, - id: 'repository', + id: 'github.repository', onFieldChange: props.onFieldChange, propKey: 'repository', value: repository || '' @@ -204,10 +228,12 @@ export default function PRDecorationBindingRenderer(props: PRDecorationBindingRe <div className="display-flex-center"> <DeferredSpinner className="spacer-right" loading={saving} /> - <SubmitButton className="spacer-right" disabled={saving || !isValid}> - {translate('save')} - </SubmitButton> - {hasBinding && ( + {isChanged && ( + <SubmitButton className="spacer-right button-success" disabled={saving || !isValid}> + {translate('save')} + </SubmitButton> + )} + {originalData && ( <Button className="spacer-right" onClick={props.onReset}> {translate('reset_verb')} </Button> diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx index 54ee550816d..cf9904ebff3 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx @@ -64,23 +64,9 @@ it('should fill selects and fill formdata', async () => { const wrapper = shallowRender(); await waitAndUpdate(wrapper); - expect(wrapper.state().hasBinding).toBe(true); expect(wrapper.state().loading).toBe(false); expect(wrapper.state().formData).toEqual(formdata); -}); - -it('should preselect url and key if only 1 item', async () => { - const instances = [{ key: 'instance1', url: 'github.enterprise.com', alm: 'github' }]; - (getAlmSettings as jest.Mock).mockResolvedValueOnce(instances); - (getProjectAlmBinding as jest.Mock).mockRejectedValueOnce({ status: 404 }); - - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - - expect(wrapper.state().formData).toEqual({ - key: instances[0].key, - repository: '' - }); + expect(wrapper.state().originalData).toEqual(formdata); }); const formData = { @@ -97,63 +83,67 @@ it('should handle reset', async () => { await waitAndUpdate(wrapper); expect(deleteProjectAlmBinding).toBeCalledWith(PROJECT_KEY); - expect(wrapper.state().formData).toEqual({ key: '', repository: '' }); - expect(wrapper.state().hasBinding).toBe(false); + expect(wrapper.state().formData).toEqual({ key: '', repository: '', slug: '' }); + expect(wrapper.state().originalData).toBeUndefined(); }); -it('should handle submit to github, azure or bitbucket', async () => { - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); +describe('handleSubmit', () => { const instances = [ { key: 'github', alm: ALM_KEYS.GITHUB }, { key: 'azure', alm: ALM_KEYS.AZURE }, { key: 'bitbucket', alm: ALM_KEYS.BITBUCKET } ]; - // Github - const githubKey = 'github'; - const repository = 'repo/path'; - wrapper.setState({ formData: { key: githubKey, repository }, instances }); - wrapper.instance().handleSubmit(); - await waitAndUpdate(wrapper); - - expect(setProjectGithubBinding).toBeCalledWith({ - almSetting: githubKey, - project: PROJECT_KEY, - repository + it('should work for github', async () => { + const wrapper = shallowRender(); + await waitAndUpdate(wrapper); + const githubKey = 'github'; + const repository = 'repo/path'; + wrapper.setState({ formData: { key: githubKey, repository }, instances }); + wrapper.instance().handleSubmit(); + await waitAndUpdate(wrapper); + + expect(setProjectGithubBinding).toBeCalledWith({ + almSetting: githubKey, + project: PROJECT_KEY, + repository + }); + expect(wrapper.state().success).toBe(true); }); - expect(wrapper.state().hasBinding).toBe(true); - expect(wrapper.state().success).toBe(true); - - // azure - const azureKey = 'azure'; - wrapper.setState({ formData: { key: azureKey } }); - wrapper.instance().handleSubmit(); - await waitAndUpdate(wrapper); - expect(setProjectAzureBinding).toBeCalledWith({ - almSetting: azureKey, - project: PROJECT_KEY + it('should work for azure', async () => { + const wrapper = shallowRender(); + await waitAndUpdate(wrapper); + const azureKey = 'azure'; + wrapper.setState({ formData: { key: azureKey }, instances }); + wrapper.instance().handleSubmit(); + await waitAndUpdate(wrapper); + + expect(setProjectAzureBinding).toBeCalledWith({ + almSetting: azureKey, + project: PROJECT_KEY + }); + expect(wrapper.state().success).toBe(true); }); - expect(wrapper.state().hasBinding).toBe(true); - expect(wrapper.state().success).toBe(true); - - // bitbucket - const bitbucketKey = 'bitbucket'; - const repositoryKey = 'repoKey'; - const repositorySlug = 'repoSlug'; - wrapper.setState({ formData: { key: bitbucketKey, repositoryKey, repositorySlug } }); - wrapper.instance().handleSubmit(); - await waitAndUpdate(wrapper); - expect(setProjectBitbucketBinding).toBeCalledWith({ - almSetting: bitbucketKey, - project: PROJECT_KEY, - repositoryKey, - repositorySlug + it('should work for bitbucket', async () => { + const wrapper = shallowRender(); + await waitAndUpdate(wrapper); + const bitbucketKey = 'bitbucket'; + const repository = 'repoKey'; + const slug = 'repoSlug'; + wrapper.setState({ formData: { key: bitbucketKey, repository, slug }, instances }); + wrapper.instance().handleSubmit(); + await waitAndUpdate(wrapper); + + expect(setProjectBitbucketBinding).toBeCalledWith({ + almSetting: bitbucketKey, + project: PROJECT_KEY, + repository, + slug + }); + expect(wrapper.state().success).toBe(true); }); - expect(wrapper.state().hasBinding).toBe(true); - expect(wrapper.state().success).toBe(true); }); it('should handle failures gracefully', async () => { @@ -185,8 +175,7 @@ it('should handle field changes', async () => { wrapper.instance().handleFieldChange('key', 'instance2'); await waitAndUpdate(wrapper); expect(wrapper.state().formData).toEqual({ - key: 'instance2', - repository: '' + key: 'instance2' }); wrapper.instance().handleFieldChange('repository', repository); @@ -216,11 +205,9 @@ it('should validate form', async () => { expect(wrapper.instance().validateForm({ key: 'github', repository: '' })).toBe(false); expect(wrapper.instance().validateForm({ key: 'github', repository: 'asdf' })).toBe(true); - expect(wrapper.instance().validateForm({ key: 'bitbucket', repositoryKey: 'key' })).toBe(false); + expect(wrapper.instance().validateForm({ key: 'bitbucket', repository: 'key' })).toBe(false); expect( - wrapper - .instance() - .validateForm({ key: 'bitbucket', repositoryKey: 'key', repositorySlug: 'slug' }) + wrapper.instance().validateForm({ key: 'bitbucket', repository: 'key', slug: 'slug' }) ).toBe(true); }); diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx index bd26eabf33c..b49dddc5d50 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBindingRenderer-test.tsx @@ -82,9 +82,12 @@ it('should render multiple instances correctly', () => { key: 'i1', repository: 'account/repo' }, - hasBinding: true, instances, - loading: false + loading: false, + originalData: { + key: 'i1', + repository: 'account/repo' + } }) ).toMatchSnapshot(); }); @@ -111,13 +114,13 @@ function shallowRender(props: Partial<PRDecorationBindingRendererProps> = {}) { key: '', repository: '' }} - hasBinding={false} instances={[]} isValid={false} loading={true} onFieldChange={jest.fn()} onReset={jest.fn()} onSubmit={jest.fn()} + originalData={undefined} saving={false} success={false} {...props} diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBinding-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBinding-test.tsx.snap index 7e98cac6379..499ffbfa605 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBinding-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBinding-test.tsx.snap @@ -5,10 +5,8 @@ exports[`should render correctly 1`] = ` formData={ Object { "key": "", - "repository": "", } } - hasBinding={false} instances={Array []} isValid={false} loading={true} diff --git a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap index 9d704e6ba4f..ede66c1ee1e 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/PRDecorationBindingRenderer-test.tsx.snap @@ -33,20 +33,31 @@ exports[`should display action state correctly 1`] = ` </em> </label> <Select + autosize={true} className="abs-width-400" clearable={false} id="name" + menuContainerStyle={ + Object { + "maxWidth": "210%", + "width": "auto", + } + } onChange={[Function]} + optionRenderer={[Function]} options={ Array [ Object { - "label": "key — http://url.com", - "value": "key", + "alm": "github", + "key": "key", + "url": "http://url.com", }, ] } searchable={false} value="" + valueKey="key" + valueRenderer={[Function]} /> </div> <div @@ -57,12 +68,6 @@ exports[`should display action state correctly 1`] = ` loading={true} timeout={100} /> - <SubmitButton - className="spacer-right" - disabled={true} - > - save - </SubmitButton> </div> </form> </div> @@ -101,20 +106,31 @@ exports[`should display action state correctly 2`] = ` </em> </label> <Select + autosize={true} className="abs-width-400" clearable={false} id="name" + menuContainerStyle={ + Object { + "maxWidth": "210%", + "width": "auto", + } + } onChange={[Function]} + optionRenderer={[Function]} options={ Array [ Object { - "label": "key — http://url.com", - "value": "key", + "alm": "github", + "key": "key", + "url": "http://url.com", }, ] } searchable={false} value="" + valueKey="key" + valueRenderer={[Function]} /> </div> <div @@ -125,12 +141,6 @@ exports[`should display action state correctly 2`] = ` loading={false} timeout={100} /> - <SubmitButton - className="spacer-right" - disabled={true} - > - save - </SubmitButton> <span className="text-success" > @@ -177,20 +187,31 @@ exports[`should display action state correctly 3`] = ` </em> </label> <Select + autosize={true} className="abs-width-400" clearable={false} id="name" + menuContainerStyle={ + Object { + "maxWidth": "210%", + "width": "auto", + } + } onChange={[Function]} + optionRenderer={[Function]} options={ Array [ Object { - "label": "key — http://url.com", - "value": "key", + "alm": "github", + "key": "key", + "url": "http://url.com", }, ] } searchable={false} value="" + valueKey="key" + valueRenderer={[Function]} /> </div> <div @@ -201,12 +222,6 @@ exports[`should display action state correctly 3`] = ` loading={false} timeout={100} /> - <SubmitButton - className="spacer-right" - disabled={false} - > - save - </SubmitButton> </div> </form> </div> @@ -276,32 +291,45 @@ exports[`should render multiple instances correctly 1`] = ` </em> </label> <Select + autosize={true} className="abs-width-400" clearable={false} id="name" + menuContainerStyle={ + Object { + "maxWidth": "210%", + "width": "auto", + } + } onChange={[Function]} + optionRenderer={[Function]} options={ Array [ Object { - "label": "i1 — http://github.enterprise.com", - "value": "i1", + "alm": "github", + "key": "i1", + "url": "http://github.enterprise.com", }, Object { - "label": "i2 — http://github.enterprise.com", - "value": "i2", + "alm": "github", + "key": "i2", + "url": "http://github.enterprise.com", }, Object { - "label": "i3 — http://bbs.enterprise.com", - "value": "i3", + "alm": "bitbucket", + "key": "i3", + "url": "http://bbs.enterprise.com", }, Object { - "label": "i4", - "value": "i4", + "alm": "azure", + "key": "i4", }, ] } searchable={false} value="" + valueKey="key" + valueRenderer={[Function]} /> </div> <div @@ -312,12 +340,6 @@ exports[`should render multiple instances correctly 1`] = ` loading={false} timeout={100} /> - <SubmitButton - className="spacer-right" - disabled={true} - > - save - </SubmitButton> </div> </form> </div> @@ -356,32 +378,45 @@ exports[`should render multiple instances correctly 2`] = ` </em> </label> <Select + autosize={true} className="abs-width-400" clearable={false} id="name" + menuContainerStyle={ + Object { + "maxWidth": "210%", + "width": "auto", + } + } onChange={[Function]} + optionRenderer={[Function]} options={ Array [ Object { - "label": "i1 — http://github.enterprise.com", - "value": "i1", + "alm": "github", + "key": "i1", + "url": "http://github.enterprise.com", }, Object { - "label": "i2 — http://github.enterprise.com", - "value": "i2", + "alm": "github", + "key": "i2", + "url": "http://github.enterprise.com", }, Object { - "label": "i3 — http://bbs.enterprise.com", - "value": "i3", + "alm": "bitbucket", + "key": "i3", + "url": "http://bbs.enterprise.com", }, Object { - "label": "i4", - "value": "i4", + "alm": "azure", + "key": "i4", }, ] } searchable={false} value="i1" + valueKey="key" + valueRenderer={[Function]} /> </div> <div @@ -389,9 +424,9 @@ exports[`should render multiple instances correctly 2`] = ` > <label className="display-flex-center" - htmlFor="repository" + htmlFor="github.repository" > - settings.pr_decoration.binding.form.repository + settings.pr_decoration.binding.form.github.repository <em className="mandatory spacer-right" > @@ -400,8 +435,8 @@ exports[`should render multiple instances correctly 2`] = ` <HelpTooltip overlay={ <FormattedMessage - defaultMessage="settings.pr_decoration.binding.form.repository.help" - id="settings.pr_decoration.binding.form.repository.help" + defaultMessage="settings.pr_decoration.binding.form.github.repository.help" + id="settings.pr_decoration.binding.form.github.repository.help" values={ Object { "example": "SonarSource/sonarqube", @@ -414,9 +449,9 @@ exports[`should render multiple instances correctly 2`] = ` </label> <input className="input-super-large" - id="repository" + id="github.repository" maxLength={256} - name="repository" + name="github.repository" onChange={[Function]} type="text" value="account/repo" @@ -430,12 +465,6 @@ exports[`should render multiple instances correctly 2`] = ` loading={false} timeout={100} /> - <SubmitButton - className="spacer-right" - disabled={true} - > - save - </SubmitButton> <Button className="spacer-right" onClick={[MockFunction]} @@ -480,20 +509,31 @@ exports[`should render single instance correctly 1`] = ` </em> </label> <Select + autosize={true} className="abs-width-400" clearable={false} id="name" + menuContainerStyle={ + Object { + "maxWidth": "210%", + "width": "auto", + } + } onChange={[Function]} + optionRenderer={[Function]} options={ Array [ Object { - "label": "single — http://single.url", - "value": "single", + "alm": "github", + "key": "single", + "url": "http://single.url", }, ] } searchable={false} value="" + valueKey="key" + valueRenderer={[Function]} /> </div> <div @@ -504,12 +544,6 @@ exports[`should render single instance correctly 1`] = ` loading={false} timeout={100} /> - <SubmitButton - className="spacer-right" - disabled={true} - > - save - </SubmitButton> </div> </form> </div> diff --git a/server/sonar-web/src/main/js/apps/settings/utils.ts b/server/sonar-web/src/main/js/apps/settings/utils.ts index 72c3c0756e2..997b649e124 100644 --- a/server/sonar-web/src/main/js/apps/settings/utils.ts +++ b/server/sonar-web/src/main/js/apps/settings/utils.ts @@ -19,16 +19,9 @@ */ import { sanitize } from 'dompurify'; import { hasMessage, translate } from 'sonar-ui-common/helpers/l10n'; -import { ALM_KEYS } from '../../types/alm-settings'; export const DEFAULT_CATEGORY = 'general'; -export const almName = { - [ALM_KEYS.AZURE]: 'Azure DevOps Server', - [ALM_KEYS.BITBUCKET]: 'Bitbucket Server', - [ALM_KEYS.GITHUB]: 'Github Enterprise' -}; - export type DefaultSpecializedInputProps = T.Omit<DefaultInputProps, 'setting'> & { isDefault: boolean; name: string; diff --git a/server/sonar-web/src/main/js/types/alm-settings.ts b/server/sonar-web/src/main/js/types/alm-settings.ts index f2153fe214f..c7d6b5d6114 100644 --- a/server/sonar-web/src/main/js/types/alm-settings.ts +++ b/server/sonar-web/src/main/js/types/alm-settings.ts @@ -57,8 +57,7 @@ export interface GithubBindingDefinition extends AlmSettingsBinding { export interface ProjectAlmBinding { key: string; repository?: string; - repositoryKey?: string; - repositorySlug?: string; + slug?: string; } export interface AzureProjectAlmBinding { @@ -69,8 +68,8 @@ export interface AzureProjectAlmBinding { export interface BitbucketProjectAlmBinding { almSetting: string; project: string; - repositoryKey: string; - repositorySlug: string; + repository: string; + slug: string; } export interface GithubProjectAlmBinding { |