From: Wouter Admiraal Date: Tue, 11 Oct 2022 07:26:51 +0000 (+0200) Subject: SONAR-17011 [894182] Detailed alternative description is missing X-Git-Tag: 9.7.0.61563~24 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=10630ace5b2f8a966ddb1fef08a333f4f8402026;p=sonarqube.git SONAR-17011 [894182] Detailed alternative description is missing --- diff --git a/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx b/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx index b737b1bbd07..c894d53d819 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/ActivityPanel.tsx @@ -98,6 +98,7 @@ export function ActivityPanel(props: ActivityPanelProps) { 'overview.activity.graph_shows_data_for_x', displayedMetrics.map(metricKey => localizeMetric(metricKey)).join(', ') )} + canShowDataAsTable={false} graph={graph} graphs={graphs} leakPeriodDate={shownLeakPeriodDate} diff --git a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/ActivityPanel-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/ActivityPanel-test.tsx.snap index ca28c6eba5e..1a33e48545e 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/ActivityPanel-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/overview/branches/__tests__/__snapshots__/ActivityPanel-test.tsx.snap @@ -39,6 +39,7 @@ exports[`should render correctly 1`] = ` void; +} + +type DataTableEntry = { date: Date } & { [x: string]: string | undefined }; + +const MAX_DATA_TABLE_ROWS = 100; + +export default function DataTableModal(props: DataTableModalProps) { + const { analyses, series, graphEndDate, graphStartDate } = props; + + if (series.length === 0) { + return renderModal( + props, + + {translate('project_activity.graphs.data_table.no_data_warning')} + + ); + } + + const tableData = series.reduce((acc, serie) => { + const data = filter( + serie.data, + // Make sure we respect the date filtering. On the graph, this is done by dynamically + // "zooming" on the series. Here, we actually have to "cut off" part of the serie's + // data points. + ({ x }) => { + if (graphEndDate && x > graphEndDate) { + return false; + } + if (graphStartDate && x < graphStartDate) { + return false; + } + return true; + } + ); + + data.forEach(({ x, y }) => { + const key = x.getTime(); + if (acc[key] === undefined) { + acc[key] = { date: x } as DataTableEntry; + } + + if (y !== undefined && !(typeof y === 'number' && isNaN(y))) { + acc[key][serie.name] = formatMeasure(y, serie.type); + } + }); + + return acc; + }, {} as { [x: number]: DataTableEntry }); + + const metrics = series.map(({ name }) => name); + const rows = slice( + sortBy(Object.values(tableData), ({ date }) => -date), + 0, + MAX_DATA_TABLE_ROWS + ).map(({ date, ...values }) => ( + + + +
+ +
+ + {metrics.map(metric => ( + + {values[metric] || '-'} + + ))} + +
    + {getAnalysisEventsForDate(analyses, date).map(event => ( +
  • + +
  • + ))} +
+ + + )); + + const rowCount = rows.length; + + if (rowCount === 0) { + const start = graphStartDate && ; + const end = graphEndDate && ; + let suffix = ''; + if (start && end) { + suffix = '_x_y'; + } else if (start) { + suffix = '_x'; + } else if (end) { + suffix = '_y'; + } + return renderModal( + props, + + + + ); + } + + return renderModal( + props, + <> + {rowCount === MAX_DATA_TABLE_ROWS && ( + + {translateWithParameters( + 'project_activity.graphs.data_table.max_lines_warning', + MAX_DATA_TABLE_ROWS + )} + + )} + + + + + {series.map(serie => ( + + ))} + + + + {rows} +
{translate('date')} + {serie.translatedName} + {translate('events')}
+ + ); +} + +function renderModal(props: DataTableModalProps, children: React.ReactNode) { + const heading = translate('project_activity.graphs.data_table.title'); + return ( + +
+

{heading}

+
+
{children}
+
+ +
+
+ ); +} diff --git a/server/sonar-web/src/main/js/components/activity-graph/GraphHistory.tsx b/server/sonar-web/src/main/js/components/activity-graph/GraphHistory.tsx index 33117b15773..f19056711d3 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/GraphHistory.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/GraphHistory.tsx @@ -20,15 +20,21 @@ import * as React from 'react'; import { AutoSizer } from 'react-virtualized/dist/commonjs/AutoSizer'; import AdvancedTimeline from '../../components/charts/AdvancedTimeline'; +import { translate } from '../../helpers/l10n'; import { formatMeasure, getShortType } from '../../helpers/measures'; import { MeasureHistory, Serie } from '../../types/project-activity'; -import { AnalysisEvent } from '../../types/types'; +import { ParsedAnalysis } from '../../types/types'; +import { Button } from '../controls/buttons'; +import ModalButton from '../controls/ModalButton'; +import DataTableModal from './DataTableModal'; import GraphsLegendCustom from './GraphsLegendCustom'; import GraphsLegendStatic from './GraphsLegendStatic'; import GraphsTooltips from './GraphsTooltips'; +import { getAnalysisEventsForDate } from './utils'; interface Props { - events: AnalysisEvent[]; + analyses: ParsedAnalysis[]; + canShowDataAsTable?: boolean; graph: string; graphEndDate?: Date; graphStartDate?: Date; @@ -69,7 +75,8 @@ export default class GraphHistory extends React.PureComponent { render() { const { - events, + analyses, + canShowDataAsTable = true, graph, graphEndDate, graphStartDate, @@ -83,6 +90,7 @@ export default class GraphHistory extends React.PureComponent { graphDescription } = this.props; const { tooltipIdx, tooltipXPos } = this.state; + const events = getAnalysisEventsForDate(analyses, selectedDate); return (
@@ -132,6 +140,24 @@ export default class GraphHistory extends React.PureComponent { )}
+ {canShowDataAsTable && ( + ( + + )}> + {({ onClick }) => ( + + )} + + )} ); } diff --git a/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx b/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx index f0d4a97f820..288bd4773b3 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx @@ -31,6 +31,7 @@ import { getSeriesMetricType, hasHistoryData, isCustomGraph } from './utils'; interface Props { analyses: ParsedAnalysis[]; ariaLabel?: string; + canShowDataAsTable?: boolean; graph: GraphType; graphs: Serie[][]; graphEndDate?: Date; @@ -63,31 +64,19 @@ export default class GraphsHistory extends React.PureComponent { } } - getSelectedDateEvents = () => { - const { selectedDate } = this.state; - const { analyses } = this.props; - if (analyses && selectedDate) { - const analysis = analyses.find(a => a.date.valueOf() === selectedDate.valueOf()); - if (analysis) { - return analysis.events; - } - } - return []; - }; - updateTooltip = (selectedDate?: Date) => { this.setState({ selectedDate }); }; render() { - const { graph, loading, series, ariaLabel } = this.props; + const { analyses, graph, loading, series, ariaLabel, canShowDataAsTable } = this.props; const isCustom = isCustomGraph(graph); if (loading) { return (
- +
); @@ -114,14 +103,14 @@ export default class GraphsHistory extends React.PureComponent { ); } - const events = this.getSelectedDateEvents(); const showAreas = [GraphType.coverage, GraphType.duplications].includes(graph); return (
{this.props.graphs.map((graphSeries, idx) => { return ( void; } -export default function GraphsZoom(props: Props) { +export default function GraphsZoom(props: GraphsZoomProps) { if (props.loading || !hasHistoryData(props.series)) { return null; } return ( -
+ // We hide this for screen readers; they should use date inputs instead. +
{({ width }) => (
+
+
+ + + +
+
`; @@ -76,5 +89,18 @@ exports[`should correctly render a graph: custom 1`] = `
+
+
+ + + +
+
`; diff --git a/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsHistory-test.tsx.snap b/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsHistory-test.tsx.snap index b7d7f3fadc7..1bb06610746 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsHistory-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsHistory-test.tsx.snap @@ -5,8 +5,43 @@ exports[`should correctly render a graph 1`] = ` className="display-flex-justify-center display-flex-column display-flex-stretch flex-grow" > a.date.valueOf() === date.valueOf()); + if (analysis) { + return analysis.events; + } + } + return []; +} + function findMetric(key: string, metrics: Metric[] | Dict) { if (Array.isArray(metrics)) { return metrics.find(metric => metric.key === key); diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 76dc91099ce..c79c05f3719 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -112,6 +112,7 @@ list_of_issues=List of issues list_of_projects=List of projects load_more=Load more load_verb=Load +loading=Loading login=Login major=Major manual=Manual @@ -1551,6 +1552,13 @@ project_activity.graphs.custom.no_history=There isn't enough data to generate an project_activity.graphs.custom.metric_no_history=This metric has no historical data to display. project_activity.graphs.custom.search=Search for a metric by name project_activity.graphs.custom.type_x_message=Only "{0}" metrics are available with your current selection. +project_activity.graphs.open_in_table=Show the graph data in a table +project_activity.graphs.data_table.title=Graph data in table format +project_activity.graphs.data_table.max_lines_warning=Only the {0} most recent data entries are shown. If you want to see different data, change the date filters on the main page. +project_activity.graphs.data_table.no_data_warning=There is no data for the selected series. +project_activity.graphs.data_table.no_data_warning_check_dates_x=There is no data for the selected date range (everything after {start}). Try modifying the date filters on the main page. +project_activity.graphs.data_table.no_data_warning_check_dates_y=There is no data for the selected date range (everything before {end}). Try modifying the date filters on the main page. +project_activity.graphs.data_table.no_data_warning_check_dates_x_y=There is no data for the selected date range ({start} to {end}). Try modifying the date filters on the main page. project_activity.custom_metric.covered_lines=Covered Lines