import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { PULL_REQUEST_DECORATION_BINDING_CATEGORY } from '../../../../apps/settings/components/AdditionalCategoryKeys';
+import { getProjectSettingsUrl } from '../../../../helpers/urls';
export interface ComponentNavProjectBindingErrorNotifProps {
component: T.Component;
if (component.configuration?.showSettings) {
action = (
- <Link
- to={{
- pathname: '/project/settings',
- query: { category: PULL_REQUEST_DECORATION_BINDING_CATEGORY, id: component.key }
- }}>
+ <Link to={getProjectSettingsUrl(component.key, PULL_REQUEST_DECORATION_BINDING_CATEGORY)}>
{translate('component_navigation.pr_deco.action.check_project_settings')}
</Link>
);
font-size: var(--hugeFontSize);
}
+.gigantic {
+ font-size: var(--giganticFontSize);
+}
+
.zero-font-size {
font-size: 0 !important;
}
import { Link } from 'react-router';
import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate } from 'sonar-ui-common/helpers/l10n';
+import { getGlobalSettingsUrl } from '../../../helpers/urls';
import { AlmKeys } from '../../../types/alm-settings';
import { ALM_INTEGRATION } from '../../settings/components/AdditionalCategoryKeys';
values={{
alm: translate('onboarding.alm', alm),
url: (
- <Link
- to={{
- pathname: '/admin/settings',
- query: { category: ALM_INTEGRATION }
- }}>
- {translate('settings.page')}
- </Link>
+ <Link to={getGlobalSettingsUrl(ALM_INTEGRATION)}>{translate('settings.page')}</Link>
)
}}
/>
import * as React from 'react';
import { connect } from 'react-redux';
import { IndexLink } from 'react-router';
+import { getGlobalSettingsUrl, getProjectSettingsUrl } from '../../../helpers/urls';
import { getAppState, getSettingsAppAllCategories, Store } from '../../../store/rootReducer';
import { getCategoryName } from '../utils';
import { ADDITIONAL_CATEGORIES } from './AdditionalCategories';
export function CategoriesList(props: CategoriesListProps) {
const { branchesEnabled, categories, component, defaultCategory, selectedCategory } = props;
- const pathname = component ? '/project/settings' : '/settings';
const categoriesWithName = categories
.filter(key => !CATEGORY_OVERRIDES[key.toLowerCase()])
return (
<ul className="side-tabs-menu">
- {sortedCategories.map(category => (
- <li key={category.key}>
- <IndexLink
- className={classNames({
- active: category.key.toLowerCase() === selectedCategory.toLowerCase()
- })}
- title={category.name}
- to={{
- pathname,
- query: {
- category: category.key !== defaultCategory ? category.key.toLowerCase() : undefined,
- id: component && component.key
- }
- }}>
- {category.name}
- </IndexLink>
- </li>
- ))}
+ {sortedCategories.map(c => {
+ const category = c.key !== defaultCategory ? c.key.toLowerCase() : undefined;
+ return (
+ <li key={c.key}>
+ <IndexLink
+ className={classNames({
+ active: c.key.toLowerCase() === selectedCategory.toLowerCase()
+ })}
+ title={c.name}
+ to={
+ component
+ ? getProjectSettingsUrl(component.key, category)
+ : getGlobalSettingsUrl(category)
+ }>
+ {c.name}
+ </IndexLink>
+ </li>
+ );
+ })}
</ul>
);
}
title="CAT_2_NAME"
to={
Object {
- "pathname": "/settings",
+ "pathname": "/admin/settings",
"query": Object {
"category": "cat_2",
- "id": undefined,
},
}
}
title="general"
to={
Object {
- "pathname": "/settings",
+ "pathname": "/admin/settings",
"query": Object {
"category": undefined,
- "id": undefined,
},
}
}
title="CAT_1_NAME"
to={
Object {
- "pathname": "/settings",
+ "pathname": "/admin/settings",
"query": Object {
"category": "cat_1",
- "id": undefined,
},
}
}
title="CAT_2_NAME"
to={
Object {
- "pathname": "/settings",
+ "pathname": "/admin/settings",
"query": Object {
"category": "cat_2",
- "id": undefined,
},
}
}
title="general"
to={
Object {
- "pathname": "/settings",
+ "pathname": "/admin/settings",
"query": Object {
"category": undefined,
- "id": undefined,
},
}
}
title="CAT_1_NAME"
to={
Object {
- "pathname": "/settings",
+ "pathname": "/admin/settings",
"query": Object {
"category": "cat_1",
- "id": undefined,
},
}
}
title="CAT_2_NAME"
to={
Object {
- "pathname": "/settings",
+ "pathname": "/admin/settings",
"query": Object {
"category": "cat_2",
- "id": undefined,
},
}
}
title="general"
to={
Object {
- "pathname": "/settings",
+ "pathname": "/admin/settings",
"query": Object {
"category": undefined,
- "id": undefined,
},
}
}
import MandatoryFieldMarker from 'sonar-ui-common/components/ui/MandatoryFieldMarker';
import MandatoryFieldsExplanation from 'sonar-ui-common/components/ui/MandatoryFieldsExplanation';
import { translate } from 'sonar-ui-common/helpers/l10n';
+import { getGlobalSettingsUrl } from '../../../../helpers/urls';
import {
AlmSettingsInstance,
ProjectAlmBindingConfigurationErrors,
)}
values={{
link: (
- <Link
- to={{
- pathname: '/admin/settings',
- query: {
- category: ALM_INTEGRATION,
- alm
- }
- }}>
+ <Link to={getGlobalSettingsUrl(ALM_INTEGRATION, { alm })}>
{translate(
'settings.pr_decoration.binding.check_configuration.failure.check_global_settings.link'
)}
selectedTutorial?: TutorialModes;
}
+const DEFAULT_ICON_SIZE = 80;
+const GH_ACTION_ICON_SIZE = 64;
+
+function renderButton(
+ mode: TutorialModes,
+ onSelectTutorial: (mode: TutorialModes) => void,
+ icon: React.ReactNode
+) {
+ return (
+ <button
+ className={`button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-${mode}`}
+ // Currently, OtherCI is the same tutorial as Manual. We might update it to its own stand-alone
+ // tutorial in the future.
+ onClick={() => onSelectTutorial(mode === TutorialModes.OtherCI ? TutorialModes.Manual : mode)}
+ type="button">
+ {icon}
+ <div className="medium big-spacer-top">
+ {translate('onboarding.tutorial.choose_method', mode)}
+ </div>
+ </button>
+ );
+}
+
export default function TutorialSelectionRenderer(props: TutorialSelectionRendererProps) {
const {
almBinding,
</h1>
</header>
- <div className="display-flex-justify-center">
- <button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-manual"
- onClick={() => props.onSelectTutorial(TutorialModes.Manual)}
- type="button">
+ <div className="display-flex-justify-center display-flex-wrap">
+ {renderButton(
+ TutorialModes.Manual,
+ props.onSelectTutorial,
<img
alt="" // Should be ignored by screen readers
- height={80}
+ height={DEFAULT_ICON_SIZE}
src={`${getBaseUrl()}/images/tutorials/manual.svg`}
/>
- <div className="medium big-spacer-top">
- {translate('onboarding.tutorial.choose_method.manual')}
- </div>
- </button>
-
- {showAzurePipelines && (
- <button
- className="button button-huge display-flex-column spacer-left spacer-right azure-pipelines"
- onClick={() => props.onSelectTutorial(TutorialModes.AzurePipelines)}
- type="button">
+ )}
+
+ {showAzurePipelines &&
+ renderButton(
+ TutorialModes.AzurePipelines,
+ props.onSelectTutorial,
<img
alt="" // Should be ignored by screen readers
- height={80}
+ height={DEFAULT_ICON_SIZE}
src={`${getBaseUrl()}/images/tutorials/azure-pipelines.svg`}
/>
- <div className="medium big-spacer-top">
- {translate('onboarding.tutorial.choose_method.azure_pipelines')}
- </div>
- </button>
- )}
+ )}
- {showBitbucketPipelines && (
- <button
- className="button button-huge display-flex-column spacer-left spacer-right bitbucket-pipelines"
- onClick={() => props.onSelectTutorial(TutorialModes.BitbucketPipelines)}
- type="button">
+ {showBitbucketPipelines &&
+ renderButton(
+ TutorialModes.BitbucketPipelines,
+ props.onSelectTutorial,
<img
alt="" // Should be ignored by screen readers
- height={80}
+ height={DEFAULT_ICON_SIZE}
src={`${getBaseUrl()}/images/alm/bitbucket.svg`}
/>
- <div className="medium big-spacer-top">
- {translate('onboarding.tutorial.choose_method.bitbucket_pipelines')}
- </div>
- </button>
- )}
+ )}
- {showGitHubActions && (
- <button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-github"
- onClick={() => props.onSelectTutorial(TutorialModes.GitHubActions)}
- type="button">
+ {showGitHubActions &&
+ renderButton(
+ TutorialModes.GitHubActions,
+ props.onSelectTutorial,
<img
alt="" // Should be ignored by screen readers
- height={64}
+ height={GH_ACTION_ICON_SIZE}
className="spacer-bottom spacer-top"
src={`${getBaseUrl()}/images/tutorials/github-actions.svg`}
/>
- <div className="medium big-spacer-top">
- {translate('onboarding.tutorial.choose_method.github_action')}
- </div>
- </button>
- )}
+ )}
- {showGitLabCICD && (
- <button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-gitlab"
- onClick={() => props.onSelectTutorial(TutorialModes.GitLabCI)}
- type="button">
+ {showGitLabCICD &&
+ renderButton(
+ TutorialModes.GitLabCI,
+ props.onSelectTutorial,
<img
alt="" // Should be ignored by screen readers
- height={80}
+ height={DEFAULT_ICON_SIZE}
src={`${getBaseUrl()}/images/alm/gitlab.svg`}
/>
- <div className="medium big-spacer-top">
- {translate('onboarding.tutorial.choose_method.gitlab_ci')}
- </div>
- </button>
- )}
+ )}
- {showJenkins && (
- <button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-jenkins"
- onClick={() => props.onSelectTutorial(TutorialModes.Jenkins)}
- type="button">
+ {showJenkins &&
+ renderButton(
+ TutorialModes.Jenkins,
+ props.onSelectTutorial,
<img
alt="" // Should be ignored by screen readers
- height={80}
+ height={DEFAULT_ICON_SIZE}
src={`${getBaseUrl()}/images/tutorials/jenkins.svg`}
/>
- <div className="medium big-spacer-top">
- {translate('onboarding.tutorial.choose_method.jenkins')}
- </div>
- </button>
+ )}
+
+ {renderButton(
+ TutorialModes.OtherCI,
+ props.onSelectTutorial,
+ <span
+ aria-disabled={true}
+ className="display-flex-center gigantic"
+ style={{ height: DEFAULT_ICON_SIZE }}>
+ …
+ </span>
)}
</div>
</div>
click(wrapper.find('button.tutorial-mode-manual'));
expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Manual);
- click(wrapper.find('button.tutorial-mode-github'));
+ click(wrapper.find('button.tutorial-mode-github-actions'));
expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.GitHubActions);
- click(wrapper.find('button.azure-pipelines'));
+ click(wrapper.find('button.tutorial-mode-azure-pipelines'));
expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.AzurePipelines);
});
click(wrapper.find('button.tutorial-mode-jenkins'));
expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Jenkins);
- click(wrapper.find('button.tutorial-mode-gitlab'));
+ click(wrapper.find('button.tutorial-mode-gitlab-ci'));
expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.GitLabCI);
click(wrapper.find('button.tutorial-mode-manual'));
click(wrapper.find('button.tutorial-mode-jenkins'));
expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Jenkins);
- click(wrapper.find('button.bitbucket-pipelines'));
+ click(wrapper.find('button.tutorial-mode-bitbucket-pipelines'));
expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.BitbucketPipelines);
click(wrapper.find('button.tutorial-mode-manual'));
projectBinding: mockProjectAzureBindingResponse()
});
- click(wrapper.find('button.azure-pipelines'));
+ click(wrapper.find('button.tutorial-mode-azure-pipelines'));
expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.AzurePipelines);
click(wrapper.find('button.tutorial-mode-manual'));
</h1>
</header>
<div
- className="display-flex-justify-center"
+ className="display-flex-justify-center display-flex-wrap"
>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-manual"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-manual"
onClick={[Function]}
type="button"
>
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right azure-pipelines"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-azure-pipelines"
onClick={[Function]}
type="button"
>
<div
className="medium big-spacer-top"
>
- onboarding.tutorial.choose_method.azure_pipelines
+ onboarding.tutorial.choose_method.azure-pipelines
+ </div>
+ </button>
+ <button
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-other-ci"
+ onClick={[Function]}
+ type="button"
+ >
+ <span
+ aria-disabled={true}
+ className="display-flex-center gigantic"
+ style={
+ Object {
+ "height": 80,
+ }
+ }
+ >
+ …
+ </span>
+ <div
+ className="medium big-spacer-top"
+ >
+ onboarding.tutorial.choose_method.other-ci
</div>
</button>
</div>
</h1>
</header>
<div
- className="display-flex-justify-center"
+ className="display-flex-justify-center display-flex-wrap"
>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-manual"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-manual"
onClick={[Function]}
type="button"
>
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-jenkins"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-jenkins"
onClick={[Function]}
type="button"
>
onboarding.tutorial.choose_method.jenkins
</div>
</button>
+ <button
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-other-ci"
+ onClick={[Function]}
+ type="button"
+ >
+ <span
+ aria-disabled={true}
+ className="display-flex-center gigantic"
+ style={
+ Object {
+ "height": 80,
+ }
+ }
+ >
+ …
+ </span>
+ <div
+ className="medium big-spacer-top"
+ >
+ onboarding.tutorial.choose_method.other-ci
+ </div>
+ </button>
</div>
</div>
</Fragment>
</h1>
</header>
<div
- className="display-flex-justify-center"
+ className="display-flex-justify-center display-flex-wrap"
>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-manual"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-manual"
onClick={[Function]}
type="button"
>
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right azure-pipelines"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-azure-pipelines"
onClick={[Function]}
type="button"
>
<div
className="medium big-spacer-top"
>
- onboarding.tutorial.choose_method.azure_pipelines
+ onboarding.tutorial.choose_method.azure-pipelines
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-github"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-github-actions"
onClick={[Function]}
type="button"
>
<div
className="medium big-spacer-top"
>
- onboarding.tutorial.choose_method.github_action
+ onboarding.tutorial.choose_method.github-actions
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-jenkins"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-jenkins"
onClick={[Function]}
type="button"
>
onboarding.tutorial.choose_method.jenkins
</div>
</button>
+ <button
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-other-ci"
+ onClick={[Function]}
+ type="button"
+ >
+ <span
+ aria-disabled={true}
+ className="display-flex-center gigantic"
+ style={
+ Object {
+ "height": 80,
+ }
+ }
+ >
+ …
+ </span>
+ <div
+ className="medium big-spacer-top"
+ >
+ onboarding.tutorial.choose_method.other-ci
+ </div>
+ </button>
</div>
</div>
</Fragment>
</h1>
</header>
<div
- className="display-flex-justify-center"
+ className="display-flex-justify-center display-flex-wrap"
>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-manual"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-manual"
onClick={[Function]}
type="button"
>
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-gitlab"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-gitlab-ci"
onClick={[Function]}
type="button"
>
<div
className="medium big-spacer-top"
>
- onboarding.tutorial.choose_method.gitlab_ci
+ onboarding.tutorial.choose_method.gitlab-ci
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-jenkins"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-jenkins"
onClick={[Function]}
type="button"
>
onboarding.tutorial.choose_method.jenkins
</div>
</button>
+ <button
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-other-ci"
+ onClick={[Function]}
+ type="button"
+ >
+ <span
+ aria-disabled={true}
+ className="display-flex-center gigantic"
+ style={
+ Object {
+ "height": 80,
+ }
+ }
+ >
+ …
+ </span>
+ <div
+ className="medium big-spacer-top"
+ >
+ onboarding.tutorial.choose_method.other-ci
+ </div>
+ </button>
</div>
</div>
</Fragment>
</h1>
</header>
<div
- className="display-flex-justify-center"
+ className="display-flex-justify-center display-flex-wrap"
>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-manual"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-manual"
onClick={[Function]}
type="button"
>
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right azure-pipelines"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-azure-pipelines"
onClick={[Function]}
type="button"
>
<div
className="medium big-spacer-top"
>
- onboarding.tutorial.choose_method.azure_pipelines
+ onboarding.tutorial.choose_method.azure-pipelines
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right bitbucket-pipelines"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-bitbucket-pipelines"
onClick={[Function]}
type="button"
>
<div
className="medium big-spacer-top"
>
- onboarding.tutorial.choose_method.bitbucket_pipelines
+ onboarding.tutorial.choose_method.bitbucket-pipelines
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-github"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-github-actions"
onClick={[Function]}
type="button"
>
<div
className="medium big-spacer-top"
>
- onboarding.tutorial.choose_method.github_action
+ onboarding.tutorial.choose_method.github-actions
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-gitlab"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-gitlab-ci"
onClick={[Function]}
type="button"
>
<div
className="medium big-spacer-top"
>
- onboarding.tutorial.choose_method.gitlab_ci
+ onboarding.tutorial.choose_method.gitlab-ci
</div>
</button>
<button
- className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-jenkins"
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-jenkins"
onClick={[Function]}
type="button"
>
onboarding.tutorial.choose_method.jenkins
</div>
</button>
+ <button
+ className="button button-huge display-flex-column spacer-left spacer-right huge-spacer-bottom tutorial-mode-other-ci"
+ onClick={[Function]}
+ type="button"
+ >
+ <span
+ aria-disabled={true}
+ className="display-flex-center gigantic"
+ style={
+ Object {
+ "height": 80,
+ }
+ }
+ >
+ …
+ </span>
+ <div
+ className="medium big-spacer-top"
+ >
+ onboarding.tutorial.choose_method.other-ci
+ </div>
+ </button>
</div>
</div>
</Fragment>
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { PULL_REQUEST_DECORATION_BINDING_CATEGORY } from '../../../apps/settings/components/AdditionalCategoryKeys';
+import { getProjectSettingsUrl } from '../../../helpers/urls';
+
+export interface DoneNextStepsProps {
+ component: T.Component;
+}
+
+export default function DoneNextSteps({ component }: DoneNextStepsProps) {
+ const tutorialsLink = (
+ <Link to={{ pathname: '/tutorials', query: { id: component.key } }}>
+ {translate(
+ 'onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.see_tutorials'
+ )}
+ </Link>
+ );
+ const isProjectAdmin = component.configuration?.showSettings;
+
+ return (
+ <>
+ <hr className="big-spacer-top big-spacer-bottom" />
+
+ <p>
+ <strong>{translate('onboarding.analysis.auto_refresh_after_analysis.done')}</strong>{' '}
+ {translate('onboarding.analysis.auto_refresh_after_analysis.auto_refresh')}
+ </p>
+ <p className="big-spacer-top">
+ {isProjectAdmin ? (
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.admin'
+ )}
+ id="onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.admin"
+ values={{
+ link_project_settings: (
+ <Link
+ to={getProjectSettingsUrl(
+ component.key,
+ PULL_REQUEST_DECORATION_BINDING_CATEGORY
+ )}>
+ {translate(
+ 'onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.project_settings'
+ )}
+ </Link>
+ ),
+ link_see_tutorials: tutorialsLink
+ }}
+ />
+ ) : (
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci'
+ )}
+ id="onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci"
+ values={{
+ link_see_tutorials: tutorialsLink
+ }}
+ />
+ )}
+ </p>
+ <p className="big-spacer-top">
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.analysis.auto_refresh_after_analysis.check_these_links'
+ )}
+ id="onboarding.analysis.auto_refresh_after_analysis.check_these_links"
+ values={{
+ link_branches: (
+ <Link
+ to="/documentation/branches/overview/"
+ target="_blank"
+ rel="noopener noreferrer">
+ {translate(
+ 'onboarding.analysis.auto_refresh_after_analysis.check_these_links.branches'
+ )}
+ </Link>
+ ),
+ link_pr_analysis: (
+ <Link
+ to="/documentation/analysis/pull-request/"
+ target="_blank"
+ rel="noopener noreferrer">
+ {translate(
+ 'onboarding.analysis.auto_refresh_after_analysis.check_these_links.pr_analysis'
+ )}
+ </Link>
+ )
+ }}
+ />
+ </p>
+ </>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { mockComponent } from '../../../../helpers/testMocks';
+import DoneNextSteps, { DoneNextStepsProps } from '../DoneNextSteps';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot('default');
+ expect(
+ shallowRender({ component: mockComponent({ configuration: { showSettings: true } }) })
+ ).toMatchSnapshot('project admin');
+});
+
+function shallowRender(props: Partial<DoneNextStepsProps> = {}) {
+ return shallow<DoneNextStepsProps>(<DoneNextSteps component={mockComponent()} {...props} />);
+}
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: default 1`] = `
+<Fragment>
+ <hr
+ className="big-spacer-top big-spacer-bottom"
+ />
+ <p>
+ <strong>
+ onboarding.analysis.auto_refresh_after_analysis.done
+ </strong>
+
+ onboarding.analysis.auto_refresh_after_analysis.auto_refresh
+ </p>
+ <p
+ className="big-spacer-top"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci"
+ id="onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci"
+ values={
+ Object {
+ "link_see_tutorials": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/tutorials",
+ "query": Object {
+ "id": "my-project",
+ },
+ }
+ }
+ >
+ onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.see_tutorials
+ </Link>,
+ }
+ }
+ />
+ </p>
+ <p
+ className="big-spacer-top"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.analysis.auto_refresh_after_analysis.check_these_links"
+ id="onboarding.analysis.auto_refresh_after_analysis.check_these_links"
+ values={
+ Object {
+ "link_branches": <Link
+ onlyActiveOnIndex={false}
+ rel="noopener noreferrer"
+ style={Object {}}
+ target="_blank"
+ to="/documentation/branches/overview/"
+ >
+ onboarding.analysis.auto_refresh_after_analysis.check_these_links.branches
+ </Link>,
+ "link_pr_analysis": <Link
+ onlyActiveOnIndex={false}
+ rel="noopener noreferrer"
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/pull-request/"
+ >
+ onboarding.analysis.auto_refresh_after_analysis.check_these_links.pr_analysis
+ </Link>,
+ }
+ }
+ />
+ </p>
+</Fragment>
+`;
+
+exports[`should render correctly: project admin 1`] = `
+<Fragment>
+ <hr
+ className="big-spacer-top big-spacer-bottom"
+ />
+ <p>
+ <strong>
+ onboarding.analysis.auto_refresh_after_analysis.done
+ </strong>
+
+ onboarding.analysis.auto_refresh_after_analysis.auto_refresh
+ </p>
+ <p
+ className="big-spacer-top"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.admin"
+ id="onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.admin"
+ values={
+ Object {
+ "link_project_settings": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/settings",
+ "query": Object {
+ "category": "pull_request_decoration_binding",
+ "id": "my-project",
+ },
+ }
+ }
+ >
+ onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.project_settings
+ </Link>,
+ "link_see_tutorials": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/tutorials",
+ "query": Object {
+ "id": "my-project",
+ },
+ }
+ }
+ >
+ onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.see_tutorials
+ </Link>,
+ }
+ }
+ />
+ </p>
+ <p
+ className="big-spacer-top"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.analysis.auto_refresh_after_analysis.check_these_links"
+ id="onboarding.analysis.auto_refresh_after_analysis.check_these_links"
+ values={
+ Object {
+ "link_branches": <Link
+ onlyActiveOnIndex={false}
+ rel="noopener noreferrer"
+ style={Object {}}
+ target="_blank"
+ to="/documentation/branches/overview/"
+ >
+ onboarding.analysis.auto_refresh_after_analysis.check_these_links.branches
+ </Link>,
+ "link_pr_analysis": <Link
+ onlyActiveOnIndex={false}
+ rel="noopener noreferrer"
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/pull-request/"
+ >
+ onboarding.analysis.auto_refresh_after_analysis.check_these_links.pr_analysis
+ </Link>,
+ }
+ }
+ />
+ </p>
+</Fragment>
+`;
}
const host = getHostUrl();
- const projectKey = component.key;
switch (languageConfig.buildTool) {
case BuildTools.Maven:
- return <JavaMaven host={host} projectKey={projectKey} token={token} />;
+ return <JavaMaven host={host} component={component} token={token} />;
case BuildTools.Gradle:
- return <JavaGradle host={host} projectKey={projectKey} token={token} />;
+ return <JavaGradle host={host} component={component} token={token} />;
case BuildTools.DotNet:
- return <DotNet host={host} projectKey={projectKey} token={token} />;
+ return <DotNet host={host} component={component} token={token} />;
case BuildTools.CFamily:
return languageConfig.os !== undefined ? (
- <ClangGCCCustom os={languageConfig.os} host={host} projectKey={projectKey} token={token} />
+ <ClangGCCCustom os={languageConfig.os} host={host} component={component} token={token} />
) : null;
case BuildTools.Other:
return languageConfig.os !== undefined ? (
- <Other host={host} os={languageConfig.os} projectKey={projectKey} token={token} />
+ <Other host={host} os={languageConfig.os} component={component} token={token} />
) : null;
default:
import ExecScanner from './ExecScanner';
export interface ClangGCCCustomProps {
+ component: T.Component;
host: string;
os: OSs;
- projectKey: string;
token: string;
}
export default function ClangGCCCustom(props: ClangGCCCustomProps) {
- const { os, host, projectKey, token } = props;
+ const { os, host, component, token } = props;
return (
<div>
<DownloadBuildWrapper os={os} />
<DownloadScanner os={os} />
<ExecBuildWrapper os={os} />
- <ExecScanner host={host} projectKey={projectKey} os={os} token={token} cfamily={true} />
+ <ExecScanner host={host} component={component} os={os} token={token} cfamily={true} />
</div>
);
}
import DotNetFramework from './DotNetFramework';
export interface DotNetProps {
+ component: T.Component;
host: string;
- projectKey: string;
token: string;
}
import DotNetExecute from './DotNetExecute';
export default function DotNetCore(props: DotNetProps) {
- const { host, projectKey, token } = props;
+ const { host, component, token } = props;
const commands = [
- `dotnet sonarscanner begin /k:"${projectKey}" /d:sonar.host.url="${host}" /d:sonar.login="${token}"`,
+ `dotnet sonarscanner begin /k:"${component.key}" /d:sonar.host.url="${host}" /d:sonar.login="${token}"`,
'dotnet build',
`dotnet sonarscanner end /d:sonar.login="${token}"`
];
<Alert className="spacer-top" variant="info">
{translate('onboarding.analysis.dotnetcore.global.text.path')}
</Alert>
- <DotNetExecute commands={commands} />
+ <DotNetExecute commands={commands} component={component} />
</div>
);
}
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../common/CodeSnippet';
import InstanceMessage from '../../../common/InstanceMessage';
+import DoneNextSteps from '../DoneNextSteps';
export interface DotNetExecuteProps {
commands: string[];
+ component: T.Component;
}
-export default function DotNetExecute({ commands }: DotNetExecuteProps) {
+export default function DotNetExecute({ commands, component }: DotNetExecuteProps) {
return (
<>
<h4 className="huge-spacer-top spacer-bottom">
}}
/>
</p>
+ <DoneNextSteps component={component} />
</>
);
}
import DotNetExecute from './DotNetExecute';
export default function DotNetFramework(props: DotNetProps) {
- const { host, projectKey, token } = props;
+ const { host, component, token } = props;
const commands = [
- `SonarScanner.MSBuild.exe begin /k:"${projectKey}" /d:sonar.host.url="${host}" /d:sonar.login="${token}"`,
+ `SonarScanner.MSBuild.exe begin /k:"${component.key}" /d:sonar.host.url="${host}" /d:sonar.login="${token}"`,
'MsBuild.exe /t:Rebuild',
`SonarScanner.MSBuild.exe end /d:sonar.login="${token}"`
];
</p>
</div>
- <DotNetExecute commands={commands} />
+ <DotNetExecute commands={commands} component={component} />
</div>
);
}
import InstanceMessage from '../../../common/InstanceMessage';
import { OSs } from '../../types';
import { quote } from '../../utils';
+import DoneNextSteps from '../DoneNextSteps';
export interface ExecScannerProps {
+ component: T.Component;
host: string;
os: OSs;
- projectKey: string;
token: string;
cfamily?: boolean;
}
export default function ExecScanner(props: ExecScannerProps) {
- const { host, os, projectKey, token, cfamily } = props;
+ const { host, os, component, token, cfamily } = props;
const q = quote(os);
const command = [
os === OSs.Windows ? 'sonar-scanner.bat' : 'sonar-scanner',
- '-D' + q(`sonar.projectKey=${projectKey}`),
+ '-D' + q(`sonar.projectKey=${component.key}`),
'-D' + q('sonar.sources=.'),
cfamily ? '-D' + q('sonar.cfamily.build-wrapper-output=bw-output') : undefined,
'-D' + q(`sonar.host.url=${host}`),
}}
/>
</p>
- <p className="big-spacer-top markdown">
- {translate('onboarding.analysis.auto_refresh_after_analysis')}
- </p>
+ <DoneNextSteps component={component} />
</div>
);
}
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../common/CodeSnippet';
import InstanceMessage from '../../../common/InstanceMessage';
+import DoneNextSteps from '../DoneNextSteps';
export interface JavaGradleProps {
+ component: T.Component;
host: string;
- projectKey: string;
token: string;
}
export default function JavaGradle(props: JavaGradleProps) {
- const { host, projectKey, token } = props;
+ const { host, component, token } = props;
const config = 'plugins {\n id "org.sonarqube" version "3.3"\n}';
const command = [
'./gradlew sonarqube',
- `-Dsonar.projectKey=${projectKey}`,
+ `-Dsonar.projectKey=${component.key}`,
`-Dsonar.host.url=${host}`,
`-Dsonar.login=${token}`
];
}}
/>
</p>
- <p className="big-spacer-top markdown">
- {translate('onboarding.analysis.auto_refresh_after_analysis')}
- </p>
+ <DoneNextSteps component={component} />
</div>
);
}
import { translate } from 'sonar-ui-common/helpers/l10n';
import CodeSnippet from '../../../common/CodeSnippet';
import InstanceMessage from '../../../common/InstanceMessage';
+import DoneNextSteps from '../DoneNextSteps';
export interface JavaMavenProps {
+ component: T.Component;
host: string;
- projectKey: string;
token: string;
}
export default function JavaMaven(props: JavaMavenProps) {
- const { host, projectKey, token } = props;
+ const { host, component, token } = props;
const command = [
'mvn sonar:sonar',
- `-Dsonar.projectKey=${projectKey}`,
+ `-Dsonar.projectKey=${component.key}`,
`-Dsonar.host.url=${host}`,
`-Dsonar.login=${token}`
];
}}
/>
</p>
- <p className="big-spacer-top markdown">
- {translate('onboarding.analysis.auto_refresh_after_analysis')}
- </p>
+ <DoneNextSteps component={component} />
</div>
);
}
import ExecScanner from './ExecScanner';
export interface OtherProps {
+ component: T.Component;
host: string;
os: OSs;
- projectKey: string;
token: string;
}
export default function Other(props: OtherProps) {
- const { host, os, projectKey, token } = props;
+ const { host, os, component, token } = props;
return (
<div>
<DownloadScanner os={os} />
- <ExecScanner host={host} os={os} projectKey={projectKey} token={token} />
+ <ExecScanner host={host} os={os} component={component} token={token} />
</div>
);
}
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
import { OSs } from '../../../types';
import ClangGCCCommand from '../ClangGCCCommand';
-it('Shoud renders correctly', () => {
+it('should render correctly', () => {
expect(
- shallow(<ClangGCCCommand os={OSs.Linux} host="host" projectKey="projectKey" token="token" />)
+ shallow(
+ <ClangGCCCommand
+ os={OSs.Linux}
+ host="host"
+ component={mockComponent({ key: 'projectKey' })}
+ token="token"
+ />
+ )
).toMatchSnapshot();
});
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
import DotNet from '../DotNet';
-it('Should renders correctly', () => {
- expect(shallow(<DotNet host="host" projectKey="projectKey" token="token" />)).toMatchSnapshot();
+it('should render correctly', () => {
+ expect(
+ shallow(<DotNet host="host" component={mockComponent({ key: 'projectKey' })} token="token" />)
+ ).toMatchSnapshot();
});
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
import DotNetExecute from '../DotNetExecute';
-it('Should renders correctly', () => {
- expect(shallow(<DotNetExecute commands={['command1', 'command2']} />)).toMatchSnapshot();
+it('should render correctly', () => {
+ expect(
+ shallow(<DotNetExecute commands={['command1', 'command2']} component={mockComponent()} />)
+ ).toMatchSnapshot();
});
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
import DotNetFramework from '../DotNetFramework';
-it('Should renders correctly', () => {
+it('should render correctly', () => {
expect(
- shallow(<DotNetFramework host="host" projectKey="projectKey" token="token" />)
+ shallow(
+ <DotNetFramework host="host" component={mockComponent({ key: 'projectKey' })} token="token" />
+ )
).toMatchSnapshot();
});
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
import DotNetCore from '../DotNetCore';
-it('Should renders correctly', () => {
+it('should render correctly', () => {
expect(
- shallow(<DotNetCore host="host" projectKey="projectKey" token="token" />)
+ shallow(
+ <DotNetCore host="host" component={mockComponent({ key: 'projectKey' })} token="token" />
+ )
).toMatchSnapshot();
});
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
import { OSs } from '../../../types';
import ExecScanner, { ExecScannerProps } from '../ExecScanner';
-it.each([OSs.Linux, OSs.Windows, OSs.MacOS])('Shoud renders for %p correctly', os => {
+it.each([OSs.Linux, OSs.Windows, OSs.MacOS])('should render correctly for %p', os => {
expect(shallowRender({ os })).toMatchSnapshot();
});
-it('Should render for cfamily', () => {
+it('should render correctly for cfamily', () => {
expect(shallowRender({ cfamily: true })).toMatchSnapshot();
});
function shallowRender(props: Partial<ExecScannerProps> = {}) {
return shallow<ExecScannerProps>(
- <ExecScanner host="host" os={OSs.Linux} projectKey="projectKey" token="token" {...props} />
+ <ExecScanner
+ host="host"
+ os={OSs.Linux}
+ component={mockComponent({ key: 'projectKey' })}
+ token="token"
+ {...props}
+ />
);
}
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
import JavaGradle from '../JavaGradle';
it('renders correctly', () => {
expect(
- shallow(<JavaGradle host="host" projectKey="projectKey" token="token" />)
+ shallow(
+ <JavaGradle host="host" component={mockComponent({ key: 'projectKey' })} token="token" />
+ )
).toMatchSnapshot();
});
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
import JavaMaven from '../JavaMaven';
it('renders correctly', () => {
expect(
- shallow(<JavaMaven host="host" projectKey="projectKey" token="token" />)
+ shallow(
+ <JavaMaven host="host" component={mockComponent({ key: 'projectKey' })} token="token" />
+ )
).toMatchSnapshot();
});
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
import { OSs } from '../../../types';
import Other, { OtherProps } from '../Other';
function shallowRender(props: Partial<OtherProps> = {}) {
return shallow<OtherProps>(
- <Other host="host" os={OSs.Linux} projectKey="projectKey" token="token" {...props} />
+ <Other
+ host="host"
+ os={OSs.Linux}
+ component={mockComponent({ key: 'projectKey' })}
+ token="token"
+ {...props}
+ />
);
}
exports[`renders correctly: .NET 1`] = `
<DotNet
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
host="HOST"
- projectKey="my-project"
token="myToken"
/>
`;
exports[`renders correctly: CFamily 1`] = `
<ClangGCCCustom
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
host="HOST"
os="linux"
- projectKey="my-project"
token="myToken"
/>
`;
exports[`renders correctly: gradle 1`] = `
<JavaGradle
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
host="HOST"
- projectKey="my-project"
token="myToken"
/>
`;
exports[`renders correctly: maven 1`] = `
<JavaMaven
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
host="HOST"
- projectKey="my-project"
token="myToken"
/>
`;
exports[`renders correctly: other 1`] = `
<Other
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
host="HOST"
os="win"
- projectKey="my-project"
token="myToken"
/>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Shoud renders correctly 1`] = `
+exports[`should render correctly 1`] = `
<div>
<DownloadBuildWrapper
os="linux"
/>
<ExecScanner
cfamily={true}
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "projectKey",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
host="host"
os="linux"
- projectKey="projectKey"
token="token"
/>
</div>
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Should renders correctly 1`] = `
+exports[`should render correctly 1`] = `
<Fragment>
<RenderOptions
checked="dotnet_core"
titleLabelKey="onboarding.build.dotnet.variant"
/>
<DotNetCore
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "projectKey",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
host="host"
- projectKey="projectKey"
token="token"
/>
</Fragment>
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Should renders correctly 1`] = `
+exports[`should render correctly 1`] = `
<Fragment>
<h4
className="huge-spacer-top spacer-bottom"
}
/>
</p>
+ <DoneNextSteps
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ />
</Fragment>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Should renders correctly 1`] = `
+exports[`should render correctly 1`] = `
<div>
<div>
<h4
"SonarScanner.MSBuild.exe end /d:sonar.login=\\"token\\"",
]
}
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "projectKey",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
/>
</div>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Should renders correctly 1`] = `
+exports[`should render correctly 1`] = `
<div>
<h4
className="huge-spacer-top spacer-bottom"
"dotnet sonarscanner end /d:sonar.login=\\"token\\"",
]
}
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "projectKey",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
/>
</div>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Shoud renders for "linux" correctly 1`] = `
+exports[`should render correctly for "linux" 1`] = `
<div>
<h4
className="huge-spacer-top spacer-bottom"
}
/>
</p>
- <p
- className="big-spacer-top markdown"
- >
- onboarding.analysis.auto_refresh_after_analysis
- </p>
+ <DoneNextSteps
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "projectKey",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ />
</div>
`;
-exports[`Shoud renders for "mac" correctly 1`] = `
+exports[`should render correctly for "mac" 1`] = `
<div>
<h4
className="huge-spacer-top spacer-bottom"
}
/>
</p>
- <p
- className="big-spacer-top markdown"
- >
- onboarding.analysis.auto_refresh_after_analysis
- </p>
+ <DoneNextSteps
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "projectKey",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ />
</div>
`;
-exports[`Shoud renders for "win" correctly 1`] = `
+exports[`should render correctly for "win" 1`] = `
<div>
<h4
className="huge-spacer-top spacer-bottom"
}
/>
</p>
- <p
- className="big-spacer-top markdown"
- >
- onboarding.analysis.auto_refresh_after_analysis
- </p>
+ <DoneNextSteps
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "projectKey",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ />
</div>
`;
-exports[`Should render for cfamily 1`] = `
+exports[`should render correctly for cfamily 1`] = `
<div>
<h4
className="huge-spacer-top spacer-bottom"
}
/>
</p>
- <p
- className="big-spacer-top markdown"
- >
- onboarding.analysis.auto_refresh_after_analysis
- </p>
+ <DoneNextSteps
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "projectKey",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ />
</div>
`;
}
/>
</p>
- <p
- className="big-spacer-top markdown"
- >
- onboarding.analysis.auto_refresh_after_analysis
- </p>
+ <DoneNextSteps
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "projectKey",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ />
</div>
`;
}
/>
</p>
- <p
- className="big-spacer-top markdown"
- >
- onboarding.analysis.auto_refresh_after_analysis
- </p>
+ <DoneNextSteps
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "projectKey",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ />
</div>
`;
os="linux"
/>
<ExecScanner
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "projectKey",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
host="host"
os="linux"
- projectKey="projectKey"
token="token"
/>
</div>
BitbucketPipelines = 'bitbucket-pipelines',
GitLabCI = 'gitlab-ci',
GitHubActions = 'github-actions',
- AzurePipelines = 'azure-pipelines'
+ AzurePipelines = 'azure-pipelines',
+ OtherCI = 'other-ci'
}
export enum BuildTools {
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { AlmKeys } from '../../types/alm-settings';
import { ComponentQualifier } from '../../types/component';
import { IssueType } from '../../types/issues';
import {
getComponentIssuesUrl,
getComponentOverviewUrl,
getComponentSecurityHotspotsUrl,
+ getGlobalSettingsUrl,
getIssuesUrl,
+ getProjectSettingsUrl,
getQualityGatesUrl,
getQualityGateUrl,
stripTrailingSlash
});
});
-describe('getComponentSecurityHotspotsUrl', () => {
+describe('#getComponentSecurityHotspotsUrl', () => {
it('should work with no extra parameters', () => {
expect(getComponentSecurityHotspotsUrl(SIMPLE_COMPONENT_KEY, {})).toEqual({
pathname: '/security_hotspots',
});
});
-describe('getComponentOverviewUrl', () => {
+describe('#getComponentOverviewUrl', () => {
it('should return a portfolio url for a portfolio', () => {
expect(getComponentOverviewUrl(SIMPLE_COMPONENT_KEY, ComponentQualifier.Portfolio)).toEqual({
pathname: '/portfolio',
});
});
-describe('getIssuesUrl', () => {
+describe('#getIssuesUrl', () => {
it('should work as expected', () => {
const type = IssueType.Bug;
expect(getIssuesUrl({ type })).toEqual({
});
});
});
+
+describe('#getGlobalSettingsUrl', () => {
+ it('should work as expected', () => {
+ expect(getGlobalSettingsUrl('foo')).toEqual({
+ pathname: '/admin/settings',
+ query: { category: 'foo' }
+ });
+ expect(getGlobalSettingsUrl('foo', { alm: AlmKeys.GitHub })).toEqual({
+ pathname: '/admin/settings',
+ query: { category: 'foo', alm: AlmKeys.GitHub }
+ });
+ });
+});
+
+describe('#getProjectSettingsUrl', () => {
+ it('should work as expected', () => {
+ expect(getProjectSettingsUrl('foo')).toEqual({
+ pathname: '/project/settings',
+ query: { id: 'foo' }
+ });
+ expect(getProjectSettingsUrl('foo', 'bar')).toEqual({
+ pathname: '/project/settings',
+ query: { id: 'foo', category: 'bar' }
+ });
+ });
+});
};
}
+export function getGlobalSettingsUrl(
+ category?: string,
+ query?: T.Dict<string | undefined | number>
+): Location {
+ return {
+ pathname: '/admin/settings',
+ query: { category, ...query }
+ };
+}
+
+export function getProjectSettingsUrl(id: string, category?: string): Location {
+ return {
+ pathname: '/project/settings',
+ query: { id, category }
+ };
+}
+
/**
* Generate URL for the rules page
*/
onboarding.tutorial.env_variables.token_generator.value=an existing token, or a newly generated one:
onboarding.analysis.header=Run analysis on your project
-onboarding.analysis.auto_refresh_after_analysis=Once the analysis is completed, this page will automatically refresh and you will be able to browse the analysis results.
+onboarding.analysis.auto_refresh_after_analysis.done=Is my analysis done?
+onboarding.analysis.auto_refresh_after_analysis.auto_refresh=If your analysis is successful, this page will automatically refresh in a few moments.
+onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.admin=You can set up Pull Request Decoration under the {link_project_settings}. To set up analysis with your favorite CI tool, {link_see_tutorials}.
+onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci=You can request from a project administrator to set up Pull Request Decoration. To set up analysis with your favorite CI tool, {link_see_tutorials}.
+onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.project_settings=project settings
+onboarding.analysis.auto_refresh_after_analysis.set_up_pr_deco_and_ci.see_tutorials=see the tutorials
+onboarding.analysis.auto_refresh_after_analysis.check_these_links=Check these useful links while you wait: {link_branches}, {link_pr_analysis}.
+onboarding.analysis.auto_refresh_after_analysis.check_these_links.pr_analysis=Pull Request Analysis
+onboarding.analysis.auto_refresh_after_analysis.check_these_links.branches=Branch Analysis
onboarding.build=What option best describes your build?
onboarding.build.maven=Maven
onboarding.analysis.build_wrapper.docs_link=official documentation
-onboarding.analysis.java.maven.header=Execute the Scanner for Maven from your computer
+onboarding.analysis.java.maven.header=Execute the Scanner for Maven
onboarding.analysis.java.maven.header.ci=Execute the Scanner for Maven from your CI
onboarding.analysis.java.maven.text=Running a {instance} analysis with Maven is straighforward. You just need to run the following command in your project's folder.
onboarding.analysis.java.maven.docs_link=official documentation of the Scanner for Maven
onboarding.analysis.java.maven.header.sonarcloud=Execute the Scanner for Maven from Travis
onboarding.analysis.java.maven.text.sonarcloud=Add the following lines to your <code>.travis.yml</code> file:
-onboarding.analysis.java.gradle.header=Execute the Scanner for Gradle from your computer
+onboarding.analysis.java.gradle.header=Execute the Scanner for Gradle
onboarding.analysis.java.gradle.header.ci=Execute the Scanner for Gradle from your CI
onboarding.analysis.java.gradle.text.1=Running an analysis with Gradle is straighforward. You just need to declare the {plugin_code} plugin in your {filename} file:
onboarding.analysis.java.gradle.text.2=and run the following command:
onboarding.analysis.msbuild.header=Download and unzip the Scanner for .NET
onboarding.analysis.msbuild.text=Visit the {link} to download the latest version, and add the executable's directory to the {code} environment variable
-onboarding.analysis.msbuild.execute=Execute the Scanner for .NET from your computer
+onboarding.analysis.msbuild.execute=Execute the Scanner for .NET
onboarding.analysis.msbuild.execute.text=Running a {instance} analysis is straighforward. You just need to execute the following commands at the root of your solution.
onboarding.analysis.msbuild.docs_link=official documentation of the Scanner for .NET
onboarding.analysis.sq_scanner.header.win=Download and unzip the Scanner for Windows
onboarding.analysis.sq_scanner.header.mac=Download and unzip the Scanner for macOS
onboarding.analysis.sq_scanner.text=Visit the {link} to download the latest version, and add the {dir} directory to the {env_var} environment variable
-onboarding.analysis.sq_scanner.execute=Execute the Scanner from your computer
+onboarding.analysis.sq_scanner.execute=Execute the Scanner
onboarding.analysis.sq_scanner.execute.text=Running a {instance} analysis is straighforward. You just need to execute the following commands in your project's folder.
onboarding.analysis.sq_scanner.execute.text.custom=Run the following commands in your project's folder.
onboarding.analysis.sq_scanner.docs=Please visit the {link} for more details.
onboarding.tutorial.other.project_key.sentence=Create a {file} file in your repository and paste the following code:
onboarding.tutorial.choose_method=How do you want to analyze your repository?
-onboarding.tutorial.choose_method.manual=Manually
+onboarding.tutorial.choose_method.manual=Locally
+onboarding.tutorial.choose_method.other-ci=Other CI
onboarding.tutorial.choose_method.jenkins=With Jenkins
-onboarding.tutorial.choose_method.github_action=With GitHub Actions
-onboarding.tutorial.choose_method.gitlab_ci=With GitLab CI
-onboarding.tutorial.choose_method.azure_pipelines=With Azure Pipelines
-onboarding.tutorial.choose_method.bitbucket_pipelines=With Bitbucket Pipelines
+onboarding.tutorial.choose_method.github-actions=With GitHub Actions
+onboarding.tutorial.choose_method.gitlab-ci=With GitLab CI
+onboarding.tutorial.choose_method.azure-pipelines=With Azure Pipelines
+onboarding.tutorial.choose_method.bitbucket-pipelines=With Bitbucket Pipelines
onboarding.tutorial.with.yaml.maven.pom=Update your {pom} file with the following properties: