You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FirstAnalysisNextStepsNotif.tsx 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2024 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. import { Link } from 'design-system';
  21. import * as React from 'react';
  22. import { FormattedMessage } from 'react-intl';
  23. import { queryToSearchString } from '~sonar-aligned/helpers/urls';
  24. import { ComponentQualifier } from '~sonar-aligned/types/component';
  25. import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
  26. import DismissableAlert from '../../../components/ui/DismissableAlert';
  27. import { translate } from '../../../helpers/l10n';
  28. import { useProjectBindingQuery } from '../../../queries/devops-integration';
  29. import { Component } from '../../../types/types';
  30. import { CurrentUser, isLoggedIn } from '../../../types/users';
  31. import { PULL_REQUEST_DECORATION_BINDING_CATEGORY } from '../../settings/constants';
  32. export interface FirstAnalysisNextStepsNotifProps {
  33. branchesEnabled?: boolean;
  34. component: Component;
  35. currentUser: CurrentUser;
  36. detectedCIOnLastAnalysis?: boolean;
  37. }
  38. export function FirstAnalysisNextStepsNotif(props: FirstAnalysisNextStepsNotifProps) {
  39. const { component, currentUser, branchesEnabled, detectedCIOnLastAnalysis } = props;
  40. const { data: projectBinding, isLoading } = useProjectBindingQuery(component.key);
  41. if (!isLoggedIn(currentUser) || component.qualifier !== ComponentQualifier.Project || isLoading) {
  42. return null;
  43. }
  44. const showConfigurePullRequestDecoNotif = branchesEnabled && projectBinding == null;
  45. const showConfigureCINotif =
  46. detectedCIOnLastAnalysis !== undefined ? !detectedCIOnLastAnalysis : false;
  47. if (!showConfigureCINotif && !showConfigurePullRequestDecoNotif) {
  48. return null;
  49. }
  50. const showOnlyConfigureCI = showConfigureCINotif && !showConfigurePullRequestDecoNotif;
  51. const showOnlyConfigurePR = showConfigurePullRequestDecoNotif && !showConfigureCINotif;
  52. const showBoth = showConfigureCINotif && showConfigurePullRequestDecoNotif;
  53. const isProjectAdmin = component.configuration?.showSettings;
  54. const tutorialsLink = (
  55. <Link
  56. to={{
  57. pathname: '/tutorials',
  58. search: queryToSearchString({ id: component.key }),
  59. }}
  60. >
  61. {translate('overview.project.next_steps.links.set_up_ci')}
  62. </Link>
  63. );
  64. const projectSettingsLink = (
  65. <Link
  66. to={{
  67. pathname: '/project/settings',
  68. search: queryToSearchString({
  69. id: component.key,
  70. category: PULL_REQUEST_DECORATION_BINDING_CATEGORY,
  71. }),
  72. }}
  73. >
  74. {translate('overview.project.next_steps.links.project_settings')}
  75. </Link>
  76. );
  77. return (
  78. <DismissableAlert alertKey={`config_ci_pr_deco.${component.key}`} variant="info">
  79. <div>
  80. {showOnlyConfigureCI && (
  81. <FormattedMessage
  82. defaultMessage={translate('overview.project.next_steps.set_up_ci')}
  83. id="overview.project.next_steps.set_up_ci"
  84. values={{
  85. link: tutorialsLink,
  86. }}
  87. />
  88. )}
  89. {showOnlyConfigurePR &&
  90. (isProjectAdmin ? (
  91. <FormattedMessage
  92. defaultMessage={translate('overview.project.next_steps.set_up_pr_deco.admin')}
  93. id="overview.project.next_steps.set_up_pr_deco.admin"
  94. values={{
  95. link_project_settings: projectSettingsLink,
  96. }}
  97. />
  98. ) : (
  99. translate('overview.project.next_steps.set_up_pr_deco')
  100. ))}
  101. {showBoth &&
  102. (isProjectAdmin ? (
  103. <FormattedMessage
  104. defaultMessage={translate('overview.project.next_steps.set_up_pr_deco_and_ci.admin')}
  105. id="overview.project.next_steps.set_up_pr_deco_and_ci.admin"
  106. values={{
  107. link_ci: tutorialsLink,
  108. link_project_settings: projectSettingsLink,
  109. }}
  110. />
  111. ) : (
  112. <FormattedMessage
  113. defaultMessage={translate('overview.project.next_steps.set_up_pr_deco_and_ci')}
  114. id="overview.project.next_steps.set_up_pr_deco_and_ci"
  115. values={{ link_ci: tutorialsLink }}
  116. />
  117. ))}
  118. </div>
  119. </DismissableAlert>
  120. );
  121. }
  122. export default withCurrentUserContext(FirstAnalysisNextStepsNotif);