]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-13398 System admin are provided with a link to the global background task page
authorPhilippe Perrin <philippe.perrin@sonarsource.com>
Mon, 15 Jun 2020 15:51:10 +0000 (17:51 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 26 Jun 2020 20:04:58 +0000 (20:04 +0000)
server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap
server/sonar-web/src/main/js/app/components/indexation/IndexationNotification.tsx
server/sonar-web/src/main/js/app/components/indexation/IndexationNotificationRenderer.tsx
server/sonar-web/src/main/js/app/components/indexation/__tests__/IndexationNotification-test.tsx
server/sonar-web/src/main/js/app/components/indexation/__tests__/IndexationNotificationRenderer-test.tsx
server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationNotificationRenderer-test.tsx.snap
server/sonar-web/src/main/js/apps/background-tasks/constants.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index adf8cc40e4721a800b3fc50c5c020d6cc2c4f7af..cf87ae0d4f2c55392a6f7ea9205043d84d37a811 100644 (file)
@@ -31,7 +31,7 @@ exports[`should render correctly 1`] = `
                   }
                 />
                 <Connect(GlobalMessages) />
-                <withIndexationContext(IndexationNotification) />
+                <Connect(withCurrentUser(withIndexationContext(IndexationNotification))) />
                 <ChildComponent />
               </Connect(withAppState(IndexationContextProvider))>
             </Workspace>
index 50c98188e1ea8f99629a6a2ff025d18e29fb11e2..e53b6e65257f398d911546230e3f833979a847bf 100644 (file)
  */
 
 import * as React from 'react';
+import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
 import withIndexationContext, {
   WithIndexationContextProps
 } from '../../../components/hoc/withIndexationContext';
+import { hasGlobalPermission, isLoggedIn } from '../../../helpers/users';
 import './IndexationNotification.css';
 import IndexationNotificationHelper from './IndexationNotificationHelper';
 import IndexationNotificationRenderer from './IndexationNotificationRenderer';
 
+interface Props extends WithIndexationContextProps {
+  currentUser: T.CurrentUser;
+}
+
 interface State {
   progression?: IndexationProgression;
 }
@@ -35,10 +41,17 @@ export enum IndexationProgression {
   Completed
 }
 
-export class IndexationNotification extends React.PureComponent<WithIndexationContextProps, State> {
-  state: State = {
-    progression: undefined
-  };
+export class IndexationNotification extends React.PureComponent<Props, State> {
+  state: State;
+  isSystemAdmin = false;
+
+  constructor(props: Props) {
+    super(props);
+
+    this.state = { progression: undefined };
+    this.isSystemAdmin =
+      isLoggedIn(this.props.currentUser) && hasGlobalPermission(this.props.currentUser, 'admin');
+  }
 
   componentDidMount() {
     this.refreshNotification();
@@ -79,9 +92,10 @@ export class IndexationNotification extends React.PureComponent<WithIndexationCo
         progression={progression}
         percentCompleted={percentCompleted ?? 0}
         onDismissCompletedNotification={this.handleDismissCompletedNotification}
+        displayBackgroundTaskLink={this.isSystemAdmin}
       />
     );
   }
 }
 
-export default withIndexationContext(IndexationNotification);
+export default withCurrentUser(withIndexationContext(IndexationNotification));
index 9cb464cd6de19f75aaee02cadca95afcb0f5f5e9..794786e793e1ff85d9860db4b1ce1269b09d2686 100644 (file)
  */
 
 import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
 import { ButtonLink } from 'sonar-ui-common/components/controls/buttons';
 import { Alert } from 'sonar-ui-common/components/ui/Alert';
 import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
+import { BackgroundTaskTypes } from '../../../apps/background-tasks/constants';
 import { IndexationProgression } from './IndexationNotification';
 
 export interface IndexationNotificationRendererProps {
   progression: IndexationProgression;
   percentCompleted: number;
   onDismissCompletedNotification: VoidFunction;
+  displayBackgroundTaskLink?: boolean;
 }
 
 export default function IndexationNotificationRenderer(props: IndexationNotificationRendererProps) {
-  const { progression, percentCompleted } = props;
+  const { progression, percentCompleted, displayBackgroundTaskLink } = props;
 
   const inProgress = progression === IndexationProgression.InProgress;
 
@@ -49,6 +53,25 @@ export default function IndexationNotificationRenderer(props: IndexationNotifica
               <span className="spacer-left">
                 {translateWithParameters('indexation.in_progress.details', percentCompleted)}
               </span>
+              {displayBackgroundTaskLink && (
+                <span className="spacer-left">
+                  <FormattedMessage
+                    id="indexation.in_progress.admin_details"
+                    defaultMessage={translate('indexation.in_progress.admin_details')}
+                    values={{
+                      link: (
+                        <Link
+                          to={{
+                            pathname: '/admin/background_tasks',
+                            query: { taskType: BackgroundTaskTypes.IssueSync }
+                          }}>
+                          {translate('background_tasks.page')}
+                        </Link>
+                      )
+                    }}
+                  />
+                </span>
+              )}
             </>
           ) : (
             <>
index 207db1ee7134b44655c8b13bec8ee860d2779f18..f09fc87d60a7c95abd8c92ee4d7ee33ef6638170 100644 (file)
@@ -20,6 +20,7 @@
 
 import { shallow } from 'enzyme';
 import * as React from 'react';
+import { mockCurrentUser } from '../../../../helpers/testMocks';
 import { IndexationNotification, IndexationProgression } from '../IndexationNotification';
 import IndexationNotificationHelper from '../IndexationNotificationHelper';
 import IndexationNotificationRenderer from '../IndexationNotificationRenderer';
@@ -82,6 +83,10 @@ it('should hide the success banner on dismiss action', () => {
 
 function shallowRender(props?: Partial<IndexationNotification['props']>) {
   return shallow<IndexationNotification>(
-    <IndexationNotification indexationContext={{ status: { isCompleted: false } }} {...props} />
+    <IndexationNotification
+      currentUser={mockCurrentUser()}
+      indexationContext={{ status: { isCompleted: false } }}
+      {...props}
+    />
   );
 }
index 3bafb5ebba82a5554d534a73df0d368bbb6fb668..ace5c8ee506f9f5b255fc957009ea16f50415037 100644 (file)
@@ -29,6 +29,7 @@ import IndexationNotificationRenderer, {
 
 it('should render correctly', () => {
   expect(shallowRender()).toMatchSnapshot('in-progress');
+  expect(shallowRender({ displayBackgroundTaskLink: true })).toMatchSnapshot('in-progress-admin');
   expect(shallowRender({ progression: IndexationProgression.Completed })).toMatchSnapshot(
     'completed'
   );
index c0cb064d7dff30d15715a37fe355bb42499320a1..2674a8f4a124347c7c26a6b1cc8940c540ce26bf 100644 (file)
@@ -55,3 +55,57 @@ exports[`should render correctly: in-progress 1`] = `
   </Alert>
 </div>
 `;
+
+exports[`should render correctly: in-progress-admin 1`] = `
+<div
+  className="indexation-notification-wrapper"
+>
+  <Alert
+    className="indexation-notification-banner"
+    display="banner"
+    variant="warning"
+  >
+    <div
+      className="display-flex-center"
+    >
+      <span>
+        indexation.in_progress
+      </span>
+      <i
+        className="spinner spacer-left"
+      />
+      <span
+        className="spacer-left"
+      >
+        indexation.in_progress.details.25
+      </span>
+      <span
+        className="spacer-left"
+      >
+        <FormattedMessage
+          defaultMessage="indexation.in_progress.admin_details"
+          id="indexation.in_progress.admin_details"
+          values={
+            Object {
+              "link": <Link
+                onlyActiveOnIndex={false}
+                style={Object {}}
+                to={
+                  Object {
+                    "pathname": "/admin/background_tasks",
+                    "query": Object {
+                      "taskType": "ISSUE_SYNC",
+                    },
+                  }
+                }
+              >
+                background_tasks.page
+              </Link>,
+            }
+          }
+        />
+      </span>
+    </div>
+  </Alert>
+</div>
+`;
index 34d1d7f642e35c90d54905c221e4900ffc9a7ded..ec685551027a28c6df90a5fc709d151694c803e6 100644 (file)
@@ -29,6 +29,11 @@ export const STATUSES = {
   CANCELED: 'CANCELED'
 };
 
+export enum BackgroundTaskTypes {
+  Report = 'REPORT',
+  IssueSync = 'ISSUE_SYNC'
+}
+
 export const ALL_TYPES = 'ALL_TYPES';
 
 export const CURRENTS = {
index 4cf2149df4d9119247a3906ec79772374dcb9e80..bd2f2512a13a3a45273d86b96ca05f4d7c3ed4c6 100644 (file)
@@ -3563,7 +3563,8 @@ maintenance.sonarqube_is_offline.text=The connection to SonarQube is lost. Pleas
 #
 #------------------------------------------------------------------------------
 indexation.in_progress=SonarQube is reloading project data. Some projects will be unavailable until this process is complete. 
-indexation.in_progress.details={0}% completed
+indexation.in_progress.details={0}% completed.
+indexation.in_progress.admin_details=See {link}.
 indexation.completed=All project data has been reloaded.
 
 #------------------------------------------------------------------------------