]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19912 Display indexation project count instead of percentage
authorDavid Cho-Lerat <david.cho-lerat@sonarsource.com>
Tue, 18 Jul 2023 14:47:42 +0000 (16:47 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 19 Jul 2023 20:03:05 +0000 (20:03 +0000)
13 files changed:
server/sonar-web/src/main/js/app/components/indexation/IndexationContextProvider.tsx
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__/IndexationContextProvider-test.tsx
server/sonar-web/src/main/js/app/components/indexation/__tests__/IndexationNotification-test.tsx
server/sonar-web/src/main/js/app/components/indexation/__tests__/IndexationNotificationHelper-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__/PageUnavailableDueToIndexation-test.tsx
server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationNotificationRenderer-test.tsx.snap
server/sonar-web/src/main/js/components/hoc/__tests__/withIndexationContext-test.tsx
server/sonar-web/src/main/js/components/hoc/__tests__/withIndexationGuard-test.tsx
server/sonar-web/src/main/js/types/indexation.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index c19b04f13e40ef3077e149a6517792e7598ee2dd..1a936598fb669ec9320422310d0f1f248857eacd 100644 (file)
@@ -17,7 +17,9 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 /* eslint-disable react/no-unused-state */
+
 import * as React from 'react';
 import { AppState } from '../../../types/appstate';
 import { IndexationContextInterface, IndexationStatus } from '../../../types/indexation';
@@ -41,7 +43,9 @@ export class IndexationContextProvider extends React.PureComponent<
     if (this.props.appState.needIssueSync) {
       IndexationNotificationHelper.startPolling(this.handleNewStatus);
     } else {
-      this.setState({ status: { isCompleted: true, percentCompleted: 100, hasFailures: false } });
+      this.setState({
+        status: { isCompleted: true, hasFailures: false },
+      });
     }
   }
 
index da2d32cea3ec5b2b6ef6aabfde4ca10ddcf71c32..eaee32ca95dcaf71eaa2a2dd1eec8943708092ec 100644 (file)
@@ -17,6 +17,7 @@
  * 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 withIndexationContext, {
   WithIndexationContextProps,
@@ -67,6 +68,7 @@ export class IndexationNotification extends React.PureComponent<Props, State> {
 
     if (!isCompleted) {
       IndexationNotificationHelper.markCompletedNotificationAsToDisplay();
+
       this.setState({
         notificationType: hasFailures
           ? IndexationNotificationType.InProgressWithFailure
@@ -78,6 +80,7 @@ export class IndexationNotification extends React.PureComponent<Props, State> {
       this.setState({
         notificationType: IndexationNotificationType.Completed,
       });
+
       IndexationNotificationHelper.markCompletedNotificationAsDisplayed();
 
       // Hide after some time
@@ -91,17 +94,18 @@ export class IndexationNotification extends React.PureComponent<Props, State> {
 
   render() {
     const { notificationType } = this.state;
+
     const {
       indexationContext: {
-        status: { percentCompleted },
+        status: { completedCount, total },
       },
     } = this.props;
 
     return !this.isSystemAdmin ? null : (
       <IndexationNotificationRenderer
+        completedCount={completedCount}
+        total={total}
         type={notificationType}
-        percentCompleted={percentCompleted}
-        isSystemAdmin={this.isSystemAdmin}
       />
     );
   }
index 924963867ae213398cc8f360b0fed60587548af6..bca3ce817897bf60043c240910d239aeae0ef746 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 /* eslint-disable react/no-unused-prop-types */
 
 import classNames from 'classnames';
@@ -30,9 +31,9 @@ import { IndexationNotificationType } from '../../../types/indexation';
 import { TaskStatuses, TaskTypes } from '../../../types/tasks';
 
 export interface IndexationNotificationRendererProps {
+  completedCount?: number;
+  total?: number;
   type?: IndexationNotificationType;
-  percentCompleted: number;
-  isSystemAdmin: boolean;
 }
 
 const NOTIFICATION_VARIANTS: { [key in IndexationNotificationType]: AlertProps['variant'] } = {
@@ -43,7 +44,7 @@ const NOTIFICATION_VARIANTS: { [key in IndexationNotificationType]: AlertProps['
 };
 
 export default function IndexationNotificationRenderer(props: IndexationNotificationRendererProps) {
-  const { type } = props;
+  const { completedCount, total, type } = props;
 
   return (
     <div className={classNames({ 'indexation-notification-wrapper': type })}>
@@ -55,12 +56,16 @@ export default function IndexationNotificationRenderer(props: IndexationNotifica
       >
         {type !== undefined && (
           <div className="display-flex-center">
-            {type === IndexationNotificationType.Completed && renderCompletedBanner(props)}
+            {type === IndexationNotificationType.Completed && renderCompletedBanner()}
+
             {type === IndexationNotificationType.CompletedWithFailure &&
-              renderCompletedWithFailureBanner(props)}
-            {type === IndexationNotificationType.InProgress && renderInProgressBanner(props)}
+              renderCompletedWithFailureBanner()}
+
+            {type === IndexationNotificationType.InProgress &&
+              renderInProgressBanner(completedCount as number, total as number)}
+
             {type === IndexationNotificationType.InProgressWithFailure &&
-              renderInProgressWithFailureBanner(props)}
+              renderInProgressWithFailureBanner(completedCount as number, total as number)}
           </div>
         )}
       </Alert>
@@ -68,78 +73,77 @@ export default function IndexationNotificationRenderer(props: IndexationNotifica
   );
 }
 
-function renderCompletedBanner(_props: IndexationNotificationRendererProps) {
+function renderCompletedBanner() {
   return <span className="spacer-right">{translate('indexation.completed')}</span>;
 }
 
-function renderCompletedWithFailureBanner(props: IndexationNotificationRendererProps) {
-  const { isSystemAdmin } = props;
-
+function renderCompletedWithFailureBanner() {
   return (
     <span className="spacer-right">
       <FormattedMessage
-        id="indexation.completed_with_error"
         defaultMessage={translate('indexation.completed_with_error')}
+        id="indexation.completed_with_error"
         values={{
-          link: isSystemAdmin
-            ? renderBackgroundTasksPageLink(true, translate('indexation.completed_with_error.link'))
-            : translate('indexation.completed_with_error.link'),
+          link: renderBackgroundTasksPageLink(
+            true,
+            translate('indexation.completed_with_error.link')
+          ),
         }}
       />
     </span>
   );
 }
 
-function renderInProgressBanner(props: IndexationNotificationRendererProps) {
-  const { percentCompleted, isSystemAdmin } = props;
-
+function renderInProgressBanner(completedCount: number, total: number) {
   return (
     <>
       <span className="spacer-right">{`${translate('indexation.in_progress')} ${translate(
         'indexation.projects_unavailable'
       )}`}</span>
       <i className="spinner spacer-right" />
+
       <span className="spacer-right">
-        {translateWithParameters('indexation.progression', percentCompleted)}
+        {translateWithParameters(
+          'indexation.progression',
+          completedCount.toString(),
+          total.toString()
+        )}
+      </span>
+
+      <span className="spacer-right">
+        <FormattedMessage
+          id="indexation.admin_link"
+          defaultMessage={translate('indexation.admin_link')}
+          values={{
+            link: renderBackgroundTasksPageLink(false, translate('background_tasks.page')),
+          }}
+        />
       </span>
-      {isSystemAdmin && (
-        <span className="spacer-right">
-          <FormattedMessage
-            id="indexation.admin_link"
-            defaultMessage={translate('indexation.admin_link')}
-            values={{
-              link: renderBackgroundTasksPageLink(false, translate('background_tasks.page')),
-            }}
-          />
-        </span>
-      )}
     </>
   );
 }
 
-function renderInProgressWithFailureBanner(props: IndexationNotificationRendererProps) {
-  const { percentCompleted, isSystemAdmin } = props;
-
+function renderInProgressWithFailureBanner(completedCount: number, total: number) {
   return (
     <>
       <span className="spacer-right">{`${translate('indexation.in_progress')} ${translate(
         'indexation.projects_unavailable'
       )}`}</span>
       <i className="spinner spacer-right" />
+
       <span className="spacer-right">
         <FormattedMessage
           id="indexation.progression_with_error"
           defaultMessage={translateWithParameters(
             'indexation.progression_with_error',
-            percentCompleted
+            completedCount.toString(),
+            total.toString()
           )}
           values={{
-            link: isSystemAdmin
-              ? renderBackgroundTasksPageLink(
-                  true,
-                  translate('indexation.progression_with_error.link')
-                )
-              : translate('indexation.progression_with_error.link'),
+            link: renderBackgroundTasksPageLink(
+              true,
+              translate('indexation.progression_with_error.link')
+            ),
           }}
         />
       </span>
index d8c052488ee31917fb1f6a3801492dbbdf75f1d1..d5f09e7d59b2c9ffeb7cfd54e6ea46e6c9014b47 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import { mount } from 'enzyme';
 import * as React from 'react';
 import { mockAppState } from '../../../../helpers/testMocks';
 import { IndexationStatus } from '../../../../types/indexation';
-import { IndexationContext } from '../IndexationContext';
 import {
   IndexationContextProvider,
   IndexationContextProviderProps,
@@ -46,22 +46,22 @@ it('should not start polling if no issue sync is needed', () => {
   expect(IndexationNotificationHelper.startPolling).not.toHaveBeenCalled();
 
   const expectedStatus: IndexationStatus = {
-    isCompleted: true,
-    percentCompleted: 100,
     hasFailures: false,
+    isCompleted: true,
   };
+
   expect(wrapper.state().status).toEqual(expectedStatus);
 });
 
 it('should update the state on new status', () => {
   const wrapper = mountRender();
 
-  const triggerNewStatus = (IndexationNotificationHelper.startPolling as jest.Mock).mock
+  const triggerNewStatus = jest.mocked(IndexationNotificationHelper.startPolling).mock
     .calls[0][0] as (status: IndexationStatus) => void;
+
   const newStatus: IndexationStatus = {
-    isCompleted: true,
-    percentCompleted: 100,
     hasFailures: false,
+    isCompleted: true,
   };
 
   triggerNewStatus(newStatus);
@@ -85,11 +85,6 @@ function mountRender(props?: IndexationContextProviderProps) {
   );
 }
 
-class TestComponent extends React.PureComponent {
-  context: IndexationStatus = { hasFailures: false, isCompleted: false, percentCompleted: 0 };
-  static contextType = IndexationContext;
-
-  render() {
-    return <h1>TestComponent</h1>;
-  }
+function TestComponent() {
+  return <h1>TestComponent</h1>;
 }
index f20ce6a385b81f32fe9248976de98285963a5c44..2ca99d7af36147159a8582c844fafec7437719d6 100644 (file)
@@ -17,6 +17,7 @@
  * 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 { mockCurrentUser } from '../../../../helpers/testMocks';
@@ -30,15 +31,15 @@ jest.mock('../IndexationNotificationHelper');
 
 describe('Completed banner', () => {
   it('should be displayed', () => {
-    (
-      IndexationNotificationHelper.shouldDisplayCompletedNotification as jest.Mock
-    ).mockReturnValueOnce(true);
+    jest
+      .mocked(IndexationNotificationHelper.shouldDisplayCompletedNotification)
+      .mockReturnValueOnce(true);
 
     const wrapper = shallowRender();
 
     wrapper.setProps({
       indexationContext: {
-        status: { isCompleted: true, percentCompleted: 100, hasFailures: false },
+        status: { hasFailures: false, isCompleted: true },
       },
     });
 
@@ -47,13 +48,13 @@ describe('Completed banner', () => {
   });
 
   it('should be displayed at startup', () => {
-    (
-      IndexationNotificationHelper.shouldDisplayCompletedNotification as jest.Mock
-    ).mockReturnValueOnce(true);
+    jest
+      .mocked(IndexationNotificationHelper.shouldDisplayCompletedNotification)
+      .mockReturnValueOnce(true);
 
     const wrapper = shallowRender({
       indexationContext: {
-        status: { isCompleted: true, percentCompleted: 100, hasFailures: false },
+        status: { hasFailures: false, isCompleted: true },
       },
     });
 
@@ -61,15 +62,16 @@ describe('Completed banner', () => {
     expect(wrapper.state().notificationType).toBe(IndexationNotificationType.Completed);
   });
 
-  it('should be hidden once displayed', () => {
+  it('should be hidden once completed without failure', () => {
     jest.useFakeTimers();
-    (
-      IndexationNotificationHelper.shouldDisplayCompletedNotification as jest.Mock
-    ).mockReturnValueOnce(true);
+
+    jest
+      .mocked(IndexationNotificationHelper.shouldDisplayCompletedNotification)
+      .mockReturnValueOnce(true);
 
     const wrapper = shallowRender({
       indexationContext: {
-        status: { isCompleted: true, percentCompleted: 100, hasFailures: false },
+        status: { hasFailures: false, isCompleted: true },
       },
     });
 
@@ -77,6 +79,7 @@ describe('Completed banner', () => {
     expect(IndexationNotificationHelper.markCompletedNotificationAsDisplayed).toHaveBeenCalled();
 
     jest.runAllTimers();
+
     expect(wrapper.state().notificationType).toBeUndefined();
 
     jest.useRealTimers();
@@ -85,7 +88,9 @@ describe('Completed banner', () => {
 
 it('should display the completed-with-failure banner', () => {
   const wrapper = shallowRender({
-    indexationContext: { status: { isCompleted: true, percentCompleted: 100, hasFailures: true } },
+    indexationContext: {
+      status: { hasFailures: true, isCompleted: true },
+    },
   });
 
   expect(wrapper.state().notificationType).toBe(IndexationNotificationType.CompletedWithFailure);
@@ -93,7 +98,9 @@ it('should display the completed-with-failure banner', () => {
 
 it('should display the progress banner', () => {
   const wrapper = shallowRender({
-    indexationContext: { status: { isCompleted: false, percentCompleted: 23, hasFailures: false } },
+    indexationContext: {
+      status: { completedCount: 23, hasFailures: false, isCompleted: false, total: 42 },
+    },
   });
 
   expect(IndexationNotificationHelper.markCompletedNotificationAsToDisplay).toHaveBeenCalled();
@@ -102,7 +109,9 @@ it('should display the progress banner', () => {
 
 it('should display the progress-with-failure banner', () => {
   const wrapper = shallowRender({
-    indexationContext: { status: { isCompleted: false, percentCompleted: 23, hasFailures: true } },
+    indexationContext: {
+      status: { completedCount: 23, hasFailures: true, isCompleted: false, total: 42 },
+    },
   });
 
   expect(IndexationNotificationHelper.markCompletedNotificationAsToDisplay).toHaveBeenCalled();
@@ -114,7 +123,7 @@ function shallowRender(props?: Partial<IndexationNotification['props']>) {
     <IndexationNotification
       currentUser={mockCurrentUser()}
       indexationContext={{
-        status: { isCompleted: false, percentCompleted: 23, hasFailures: false },
+        status: { completedCount: 23, hasFailures: false, isCompleted: false, total: 42 },
       }}
       {...props}
     />
index a40d976768299736802274ff456c8830a13809a5..6b37aea7c422bd8ff199e1a8da27c3e0ab22e3f6 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import { setImmediate } from 'timers';
 import { getIndexationStatus } from '../../../../api/ce';
 import { get, remove, save } from '../../../../helpers/storage';
@@ -45,12 +46,15 @@ jest.mock('../../../../helpers/storage', () => ({
 
 it('should properly start & stop polling for indexation status', async () => {
   const onNewStatus = jest.fn();
+
   const newStatus: IndexationStatus = {
-    isCompleted: false,
-    percentCompleted: 100,
+    completedCount: 23,
     hasFailures: false,
+    isCompleted: false,
+    total: 42,
   };
-  (getIndexationStatus as jest.Mock).mockResolvedValueOnce(newStatus);
+
+  jest.mocked(getIndexationStatus).mockResolvedValueOnce(newStatus);
 
   IndexationNotificationHelper.startPolling(onNewStatus);
   expect(getIndexationStatus).toHaveBeenCalled();
@@ -61,7 +65,7 @@ it('should properly start & stop polling for indexation status', async () => {
   jest.runOnlyPendingTimers();
   expect(getIndexationStatus).toHaveBeenCalledTimes(2);
 
-  (getIndexationStatus as jest.Mock).mockClear();
+  jest.mocked(getIndexationStatus).mockClear();
 
   IndexationNotificationHelper.stopPolling();
   jest.runAllTimers();
@@ -74,7 +78,7 @@ it('should properly handle the flag to show the completed banner', () => {
 
   expect(save).toHaveBeenCalledWith(expect.any(String), 'true');
 
-  (get as jest.Mock).mockReturnValueOnce('true');
+  jest.mocked(get).mockReturnValueOnce('true');
   let shouldDisplay = IndexationNotificationHelper.shouldDisplayCompletedNotification();
 
   expect(shouldDisplay).toBe(true);
index 4c17c0b83522e15ed1d72be2f210e19286c078cc..0a807e3014937e457f65e5fbdf9678ef567a1ed3 100644 (file)
@@ -17,6 +17,7 @@
  * 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 { IndexationNotificationType } from '../../../../types/indexation';
@@ -25,27 +26,20 @@ import IndexationNotificationRenderer, {
 } from '../IndexationNotificationRenderer';
 
 it.each([
-  [IndexationNotificationType.InProgress, false],
-  [IndexationNotificationType.InProgress, true],
-  [IndexationNotificationType.InProgressWithFailure, false],
-  [IndexationNotificationType.InProgressWithFailure, true],
-  [IndexationNotificationType.Completed, false],
-  [IndexationNotificationType.Completed, true],
-  [IndexationNotificationType.CompletedWithFailure, false],
-  [IndexationNotificationType.CompletedWithFailure, true],
-])(
-  'should render correctly for type=%p & isSystemAdmin=%p',
-  (type: IndexationNotificationType, isSystemAdmin: boolean) => {
-    expect(shallowRender({ type, isSystemAdmin })).toMatchSnapshot();
-  }
-);
+  [IndexationNotificationType.InProgress],
+  [IndexationNotificationType.InProgressWithFailure],
+  [IndexationNotificationType.Completed],
+  [IndexationNotificationType.CompletedWithFailure],
+])('should render correctly for type=%p', (type: IndexationNotificationType) => {
+  expect(shallowRender({ type })).toMatchSnapshot();
+});
 
 function shallowRender(props: Partial<IndexationNotificationRendererProps> = {}) {
   return shallow<IndexationNotificationRendererProps>(
     <IndexationNotificationRenderer
+      completedCount={23}
+      total={42}
       type={IndexationNotificationType.InProgress}
-      percentCompleted={25}
-      isSystemAdmin={false}
       {...props}
     />
   );
index 543fbdd4519c5b9e334b4bebc281a29309f144a9..7ea9bc3c3c84f151f4b770cb84459f82308acea0 100644 (file)
@@ -41,7 +41,9 @@ it('should not refresh the page once the indexation is complete if there were fa
   expect(reload).not.toHaveBeenCalled();
 
   wrapper.setProps({
-    indexationContext: { status: { isCompleted: true, percentCompleted: 100, hasFailures: true } },
+    indexationContext: {
+      status: { hasFailures: true, isCompleted: true },
+    },
   });
 
   wrapper.update();
@@ -62,7 +64,9 @@ it('should refresh the page once the indexation is complete if there were NO fai
   expect(reload).not.toHaveBeenCalled();
 
   wrapper.setProps({
-    indexationContext: { status: { isCompleted: true, percentCompleted: 100, hasFailures: false } },
+    indexationContext: {
+      status: { hasFailures: false, isCompleted: true },
+    },
   });
 
   wrapper.update();
@@ -74,7 +78,7 @@ function shallowRender() {
   return shallow<PageUnavailableDueToIndexation>(
     <PageUnavailableDueToIndexation
       indexationContext={{
-        status: { isCompleted: false, percentCompleted: 23, hasFailures: false },
+        status: { completedCount: 23, hasFailures: false, isCompleted: false, total: 42 },
       }}
     />
   );
index 6b8c3972439c047c84ef7eeb5d7614d06fed32b5..2217b780edd4bd8984da82241adf56ddf78644d0 100644 (file)
@@ -1,6 +1,6 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`should render correctly for type="Completed" & isSystemAdmin=false 1`] = `
+exports[`should render correctly for type="Completed" 1`] = `
 <div
   className="indexation-notification-wrapper"
 >
@@ -23,61 +23,7 @@ exports[`should render correctly for type="Completed" & isSystemAdmin=false 1`]
 </div>
 `;
 
-exports[`should render correctly for type="Completed" & isSystemAdmin=true 1`] = `
-<div
-  className="indexation-notification-wrapper"
->
-  <Alert
-    aria-live="assertive"
-    className="indexation-notification-banner"
-    display="banner"
-    variant="success"
-  >
-    <div
-      className="display-flex-center"
-    >
-      <span
-        className="spacer-right"
-      >
-        indexation.completed
-      </span>
-    </div>
-  </Alert>
-</div>
-`;
-
-exports[`should render correctly for type="CompletedWithFailure" & isSystemAdmin=false 1`] = `
-<div
-  className="indexation-notification-wrapper"
->
-  <Alert
-    aria-live="assertive"
-    className="indexation-notification-banner"
-    display="banner"
-    variant="error"
-  >
-    <div
-      className="display-flex-center"
-    >
-      <span
-        className="spacer-right"
-      >
-        <FormattedMessage
-          defaultMessage="indexation.completed_with_error"
-          id="indexation.completed_with_error"
-          values={
-            {
-              "link": "indexation.completed_with_error.link",
-            }
-          }
-        />
-      </span>
-    </div>
-  </Alert>
-</div>
-`;
-
-exports[`should render correctly for type="CompletedWithFailure" & isSystemAdmin=true 1`] = `
+exports[`should render correctly for type="CompletedWithFailure" 1`] = `
 <div
   className="indexation-notification-wrapper"
 >
@@ -117,38 +63,7 @@ exports[`should render correctly for type="CompletedWithFailure" & isSystemAdmin
 </div>
 `;
 
-exports[`should render correctly for type="InProgress" & isSystemAdmin=false 1`] = `
-<div
-  className="indexation-notification-wrapper"
->
-  <Alert
-    aria-live="assertive"
-    className="indexation-notification-banner"
-    display="banner"
-    variant="warning"
-  >
-    <div
-      className="display-flex-center"
-    >
-      <span
-        className="spacer-right"
-      >
-        indexation.in_progress indexation.projects_unavailable
-      </span>
-      <i
-        className="spinner spacer-right"
-      />
-      <span
-        className="spacer-right"
-      >
-        indexation.progression.25
-      </span>
-    </div>
-  </Alert>
-</div>
-`;
-
-exports[`should render correctly for type="InProgress" & isSystemAdmin=true 1`] = `
+exports[`should render correctly for type="InProgress" 1`] = `
 <div
   className="indexation-notification-wrapper"
 >
@@ -172,7 +87,7 @@ exports[`should render correctly for type="InProgress" & isSystemAdmin=true 1`]
       <span
         className="spacer-right"
       >
-        indexation.progression.25
+        indexation.progression.23.42
       </span>
       <span
         className="spacer-right"
@@ -201,46 +116,7 @@ exports[`should render correctly for type="InProgress" & isSystemAdmin=true 1`]
 </div>
 `;
 
-exports[`should render correctly for type="InProgressWithFailure" & isSystemAdmin=false 1`] = `
-<div
-  className="indexation-notification-wrapper"
->
-  <Alert
-    aria-live="assertive"
-    className="indexation-notification-banner"
-    display="banner"
-    variant="error"
-  >
-    <div
-      className="display-flex-center"
-    >
-      <span
-        className="spacer-right"
-      >
-        indexation.in_progress indexation.projects_unavailable
-      </span>
-      <i
-        className="spinner spacer-right"
-      />
-      <span
-        className="spacer-right"
-      >
-        <FormattedMessage
-          defaultMessage="indexation.progression_with_error.25"
-          id="indexation.progression_with_error"
-          values={
-            {
-              "link": "indexation.progression_with_error.link",
-            }
-          }
-        />
-      </span>
-    </div>
-  </Alert>
-</div>
-`;
-
-exports[`should render correctly for type="InProgressWithFailure" & isSystemAdmin=true 1`] = `
+exports[`should render correctly for type="InProgressWithFailure" 1`] = `
 <div
   className="indexation-notification-wrapper"
 >
@@ -265,7 +141,7 @@ exports[`should render correctly for type="InProgressWithFailure" & isSystemAdmi
         className="spacer-right"
       >
         <FormattedMessage
-          defaultMessage="indexation.progression_with_error.25"
+          defaultMessage="indexation.progression_with_error.23.42"
           id="indexation.progression_with_error"
           values={
             {
index 4a3af5804cbff7b716964d9c1b4fe32eb3b859ea..eac8a9679c90977cf7486e2815ef10022d1c5afd 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import { mount } from 'enzyme';
 import * as React from 'react';
 import { IndexationContext } from '../../../app/components/indexation/IndexationContext';
@@ -25,7 +26,7 @@ import withIndexationContext, { WithIndexationContextProps } from '../withIndexa
 
 it('should render correctly', () => {
   const indexationContext: IndexationContextInterface = {
-    status: { isCompleted: true, percentCompleted: 87, hasFailures: false },
+    status: { hasFailures: false, isCompleted: true },
   };
 
   const wrapper = mountRender(indexationContext);
@@ -37,7 +38,7 @@ function mountRender(indexationContext?: Partial<IndexationContextInterface>) {
   return mount(
     <IndexationContext.Provider
       value={{
-        status: { isCompleted: false, percentCompleted: 23, hasFailures: false },
+        status: { completedCount: 23, hasFailures: false, isCompleted: false, total: 42 },
         ...indexationContext,
       }}
     >
@@ -46,10 +47,8 @@ function mountRender(indexationContext?: Partial<IndexationContextInterface>) {
   );
 }
 
-class TestComponent extends React.PureComponent<WithIndexationContextProps> {
-  render() {
-    return <h1>TestComponent</h1>;
-  }
+function TestComponent(_props: WithIndexationContextProps) {
+  return <h1>TestComponent</h1>;
 }
 
 const TestComponentWithIndexationContext = withIndexationContext(TestComponent);
index 4884755b7ad7c6286c40ea3a5ca130138e34aa24..518176becb9eb09b22706eeab1f19a5ffc00a107 100644 (file)
@@ -46,7 +46,7 @@ function renderComponentWithIndexationGuard(showIndexationMessage: () => boolean
   return render(
     <IndexationContext.Provider
       value={{
-        status: { isCompleted: false, percentCompleted: 23, hasFailures: false },
+        status: { completedCount: 23, isCompleted: false, hasFailures: false, total: 42 },
       }}
     >
       <TestComponentWithGuard />
index 296d7ed701ff3b51381e12a821dad964cc87c5ae..601edc295ba91546c80b290b01cb2c73ed96a303 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-export interface IndexationStatus {
-  isCompleted: boolean;
-  percentCompleted: number;
-  hasFailures: boolean;
+
+interface IndexationStatusInProgress {
+  completedCount: number;
+  isCompleted: false;
+  total: number;
+}
+
+interface IndexationStatusCompleted {
+  completedCount?: number;
+  isCompleted: true;
+  total?: number;
 }
 
+export type IndexationStatus = {
+  hasFailures: boolean;
+} & (IndexationStatusInProgress | IndexationStatusCompleted);
+
 export interface IndexationContextInterface {
   status: IndexationStatus;
 }
index 2066a81cdd85aa6a8b23b8d1a2c4bb5c711a1f4f..b43d1ea5fc3e37c411734d7b77679ee60117325f 100644 (file)
@@ -4726,8 +4726,8 @@ indexation.in_progress=SonarQube is reindexing project data.
 indexation.details_unavailable=Details are unavailable until this process is complete.
 indexation.link_unavailable=The link to these results is unavailable until this process is complete.
 indexation.projects_unavailable=Some projects will be unavailable until this process is complete.
-indexation.progression={0}% complete.
-indexation.progression_with_error={0}% complete with some {link}.
+indexation.progression={0} out of {1} projects reindexed.
+indexation.progression_with_error={0} out of {1} projects reindexed with some {link}.
 indexation.progression_with_error.link=tasks failing
 indexation.completed=All project data has been reloaded.
 indexation.completed_with_error=SonarQube completed the reload of project data. Some {link} causing some projects to remain unavailable.