]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19604 Migrating activity header to MIUI
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>
Tue, 20 Jun 2023 14:50:40 +0000 (16:50 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 26 Jun 2023 20:03:54 +0000 (20:03 +0000)
server/sonar-web/design-system/src/components/InputSelect.tsx
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAppRenderer.tsx
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityDateInput.tsx
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageFilters.tsx
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-it.tsx

index f000f7321367bbe44a1583ba8eb4eeab1200036c..4edc8e5844227d51d66c49e0b9f4ffe01bae6673 100644 (file)
@@ -192,7 +192,7 @@ export function selectStyle<
     }),
     placeholder: (base) => ({
       ...base,
-      color: themeContrast('primaryLight')({ theme }),
+      color: themeContrast('inputPlaceholder')({ theme }),
     }),
   };
 }
index ed619464a56c72bf0cc26126ae20451492c1fa36..913c0863f6ece7a25416c14451bfe836dcad9bc7 100644 (file)
@@ -27,10 +27,10 @@ import { ComponentQualifier } from '../../../types/component';
 import { MeasureHistory, ParsedAnalysis } from '../../../types/project-activity';
 import { Component, Metric } from '../../../types/types';
 import { Query } from '../utils';
-import './projectActivity.css';
 import ProjectActivityAnalysesList from './ProjectActivityAnalysesList';
 import ProjectActivityGraphs from './ProjectActivityGraphs';
 import ProjectActivityPageFilters from './ProjectActivityPageFilters';
+import './projectActivity.css';
 
 interface Props {
   onAddCustomEvent: (analysis: string, name: string, category?: string) => Promise<void>;
index eee70352b85d058337069089d4ea2fc55bbc0210..2cf1064ed445344427c0187dcd89552d30d70095 100644 (file)
@@ -17,9 +17,8 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { ButtonSecondary, DateRangePicker } from 'design-system';
 import * as React from 'react';
-import { Button } from '../../../components/controls/buttons';
-import DateRangeInput from '../../../components/controls/DateRangeInput';
 import { translate } from '../../../helpers/l10n';
 import { Query } from '../utils';
 
@@ -40,18 +39,24 @@ export default class ProjectActivityDateInput extends React.PureComponent<Props>
 
   render() {
     return (
-      <div className="display-flex-end">
-        <DateRangeInput
+      <div className="sw-flex">
+        <DateRangePicker
+          ariaNextMonthLabel={translate('next_')}
+          ariaPreviousMonthLabel={translate('previous_')}
+          clearButtonLabel={translate('clear')}
+          fromLabel={translate('start_date')}
           onChange={this.handleChange}
+          separatorText={translate('to_')}
+          toLabel={translate('end_date')}
           value={{ from: this.props.from, to: this.props.to }}
         />
-        <Button
-          className="spacer-left"
+        <ButtonSecondary
+          className="sw-ml-2"
           disabled={this.props.from === undefined && this.props.to === undefined}
           onClick={this.handleResetClick}
         >
           {translate('project_activity.reset_dates')}
-        </Button>
+        </ButtonSecondary>
       </div>
     );
   }
index d54edc3ddee9de12658ae38aa786b70386a6b7e3..b2bf750cb686e7826d3e4f4402f413167dbf75f8 100644 (file)
@@ -17,8 +17,8 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { InputSelect, LabelValueSelectOption } from 'design-system';
 import * as React from 'react';
-import Select from '../../../components/controls/Select';
 import { translate } from '../../../helpers/l10n';
 import { ComponentQualifier, isPortfolioLike } from '../../../types/component';
 import {
@@ -38,13 +38,13 @@ interface ProjectActivityPageFiltersProps {
 }
 
 export default function ProjectActivityPageFilters(props: ProjectActivityPageFiltersProps) {
-  const { project, category, from, to, updateQuery } = props;
+  const { category, project, from, to, updateQuery } = props;
 
   const isApp = project.qualifier === ComponentQualifier.Application;
   const eventTypes = isApp
     ? Object.values(ApplicationAnalysisEventCategory)
     : Object.values(ProjectAnalysisEventCategory);
-  const options = eventTypes.map((category) => ({
+  const options: LabelValueSelectOption<string>[] = eventTypes.map((category) => ({
     label: translate('event.category', category),
     value: category,
   }));
@@ -57,25 +57,17 @@ export default function ProjectActivityPageFilters(props: ProjectActivityPageFil
   );
 
   return (
-    <div className="page-header display-flex-start">
+    <div className="sw-flex sw-mb-5 sw-items-center">
       {!isPortfolioLike(project.qualifier) && (
-        <div className="display-flex-column big-spacer-right">
-          <label className="text-bold little-spacer-bottom" htmlFor="filter-events">
-            {translate('project_activity.filter_events')}
-          </label>
-          <Select
-            // For some reason, not setting this aria-label makes some tests fail. They cannot seem to link
-            // the label above with this input.
-            aria-label={translate('project_activity.filter_events')}
-            className={isApp ? 'input-large' : 'input-medium'}
-            id="filter-events"
-            isClearable
-            isSearchable={false}
-            onChange={handleCategoryChange}
-            options={options}
-            value={options.filter((o) => o.value === category)}
-          />
-        </div>
+        <InputSelect
+          aria-label={translate('project_activity.filter_events')}
+          className="sw-mr-8 sw-body-sm"
+          onChange={(data: LabelValueSelectOption<string>) => handleCategoryChange(data)}
+          options={options}
+          placeholder={translate('project_activity.filter_events')}
+          size="small"
+          value={options.find((o) => o.value === category)}
+        />
       )}
       <ProjectActivityDateInput from={from} onChange={props.updateQuery} to={to} />
     </div>
index 2fd8e4b83c1c65ddb4622c7797c77bb480f96442..bcad96af0d8201650b802abbe2776e2bffcdcc2b 100644 (file)
@@ -18,7 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-import { screen, waitFor } from '@testing-library/react';
+import { screen, waitFor, within } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
 import { keyBy, times } from 'lodash';
 import React from 'react';
@@ -37,11 +37,8 @@ import {
 } from '../../../../helpers/mocks/project-activity';
 import { get } from '../../../../helpers/storage';
 import { mockMetric } from '../../../../helpers/testMocks';
-import {
-  dateInputEvent,
-  renderAppWithComponentContext,
-} from '../../../../helpers/testReactTestingUtils';
-import { byLabelText, byRole, byText } from '../../../../helpers/testSelector';
+import { renderAppWithComponentContext } from '../../../../helpers/testReactTestingUtils';
+import { byLabelText, byRole, byTestId, byText } from '../../../../helpers/testSelector';
 import { ComponentQualifier } from '../../../../types/component';
 import { MetricKey, MetricType } from '../../../../types/metrics';
 import {
@@ -422,10 +419,10 @@ function getPageObject() {
     metricCheckbox: (name: MetricKey) => byRole('checkbox', { name }),
 
     // Filtering.
-    categorySelect: byRole('combobox', { name: 'project_activity.filter_events' }),
+    categorySelect: byLabelText('project_activity.filter_events'),
     resetDatesBtn: byRole('button', { name: 'project_activity.reset_dates' }),
-    fromDateInput: byRole('textbox', { name: 'start_date' }),
-    toDateInput: byRole('textbox', { name: 'end_date' }),
+    fromDateInput: byLabelText('start_date'),
+    toDateInput: byLabelText('end_date'),
 
     // Analysis interactions.
     activityItem: byLabelText(/project_activity.show_analysis_X_on_graph/),
@@ -448,6 +445,8 @@ function getPageObject() {
     loading: byLabelText('loading'),
     baseline: byText('project_activity.new_code_period_start'),
     bugsPopupCell: byRole('cell', { name: MetricKey.bugs }),
+    monthSelector: byTestId('month-select'),
+    yearSelector: byTestId('year-select'),
   };
 
   return {
@@ -521,20 +520,59 @@ function getPageObject() {
       async filterByCategory(
         category: ProjectAnalysisEventCategory | ApplicationAnalysisEventCategory
       ) {
-        await selectEvent.select(ui.categorySelect.get(), [`event.category.${category}`]);
+        await user.click(ui.categorySelect.get());
+        const optionForType = await screen.findByText(`event.category.${category}`);
+        await user.click(optionForType);
       },
 
       async setDateRange(from?: string, to?: string) {
-        const dateInput = dateInputEvent(user);
         if (from) {
-          await dateInput.pickDate(ui.fromDateInput.get(), parseDate(from));
+          await this.selectDate(from, ui.fromDateInput.get());
         }
 
         if (to) {
-          await dateInput.pickDate(ui.toDateInput.get(), parseDate(to));
+          await this.selectDate(to, ui.toDateInput.get());
         }
       },
 
+      async selectDate(date: string, datePickerSelector: HTMLElement) {
+        const monthMap = [
+          'Jan',
+          'Feb',
+          'Mar',
+          'Apr',
+          'May',
+          'Jun',
+          'Jul',
+          'Aug',
+          'Sep',
+          'Oct',
+          'Nov',
+          'Dec',
+        ];
+        const parsedDate = parseDate(date);
+        await user.click(datePickerSelector);
+        const monthSelector = within(ui.monthSelector.get()).getByRole('combobox');
+
+        await user.click(monthSelector);
+        const selectedMonthElements = within(ui.monthSelector.get()).getAllByText(
+          monthMap[parseDate(parsedDate).getMonth()]
+        );
+        await user.click(selectedMonthElements[selectedMonthElements.length - 1]);
+
+        const yearSelector = within(ui.yearSelector.get()).getByRole('combobox');
+
+        await user.click(yearSelector);
+        const selectedYearElements = within(ui.yearSelector.get()).getAllByText(
+          parseDate(parsedDate).getFullYear()
+        );
+        await user.click(selectedYearElements[selectedYearElements.length - 1]);
+
+        await user.click(
+          screen.getByText(parseDate(parsedDate).getDate().toString(), { selector: 'button' })
+        );
+      },
+
       async resetDateFilters() {
         await user.click(ui.resetDatesBtn.get());
       },