Procházet zdrojové kódy

SONAR-11616 Save selected activity graph per project

tags/7.6
Grégoire Aubert před 5 roky
rodič
revize
7a2be62002

+ 52
- 65
server/sonar-web/src/main/js/apps/overview/components/OverviewApp.tsx Zobrazit soubor

@@ -33,13 +33,11 @@ import { getAllTimeMachineData } from '../../../api/time-machine';
import { parseDate } from '../../../helpers/dates';
import { enhanceMeasuresWithMetrics } from '../../../helpers/measures';
import { getLeakPeriod } from '../../../helpers/periods';
import { get } from '../../../helpers/storage';
import { METRICS, HISTORY_METRICS_LIST } from '../utils';
import {
DEFAULT_GRAPH,
getDisplayedHistoryMetrics,
PROJECT_ACTIVITY_GRAPH,
PROJECT_ACTIVITY_GRAPH_CUSTOM
getProjectActivityGraph
} from '../../projectActivity/utils';
import {
isSameBranchLike,
@@ -51,22 +49,14 @@ import { getMetrics, Store } from '../../../store/rootReducer';
import { translate } from '../../../helpers/l10n';
import '../styles.css';

interface OwnProps {
interface Props {
branchLike?: T.BranchLike;
component: T.Component;
fetchMetrics: () => void;
onComponentChange: (changes: {}) => void;
}

interface StateToProps {
metrics: { [key: string]: T.Metric };
}

interface DispatchToProps {
fetchMetrics: () => void;
}

type Props = StateToProps & DispatchToProps & OwnProps;

interface State {
history?: {
[metric: string]: Array<{ date: Date; value?: string }>;
@@ -100,40 +90,24 @@ export class OverviewApp extends React.PureComponent<Props, State> {
this.mounted = false;
}

loadMeasures() {
const { branchLike, component } = this.props;
this.setState({ loading: true });
getApplicationLeakPeriod = () => {
return this.state.measures.find(measure => measure.metric.key === 'new_bugs')
? ({ index: 1 } as T.Period)
: undefined;
};

return getMeasuresAndMeta(component.key, METRICS, {
additionalFields: 'metrics,periods',
...getBranchLikeQuery(branchLike)
}).then(
({ component, metrics, periods }) => {
if (this.mounted && metrics && component.measures) {
this.setState({
loading: false,
measures: enhanceMeasuresWithMetrics(component.measures, metrics),
periods
});
}
},
error => {
throwGlobalError(error);
if (this.mounted) {
this.setState({ loading: false });
}
}
isEmpty = () => {
return (
this.state.measures === undefined ||
this.state.measures.find(measure => measure.metric.key === 'ncloc') === undefined
);
}
};

loadHistory = () => {
const { branchLike, component } = this.props;

const customGraphs = get(PROJECT_ACTIVITY_GRAPH_CUSTOM);
let graphMetrics = getDisplayedHistoryMetrics(
get(PROJECT_ACTIVITY_GRAPH) || 'issues',
customGraphs ? customGraphs.split(',') : []
);
const { graph, customGraphs } = getProjectActivityGraph(component.key);
let graphMetrics = getDisplayedHistoryMetrics(graph, customGraphs);
if (!graphMetrics || graphMetrics.length <= 0) {
graphMetrics = getDisplayedHistoryMetrics(DEFAULT_GRAPH, []);
}
@@ -159,24 +133,33 @@ export class OverviewApp extends React.PureComponent<Props, State> {
});
};

getApplicationLeakPeriod = () =>
this.state.measures.find(measure => measure.metric.key === 'new_bugs')
? ({ index: 1 } as T.Period)
: undefined;

isEmpty = () =>
this.state.measures === undefined ||
this.state.measures.find(measure => measure.metric.key === 'ncloc') === undefined;
loadMeasures = () => {
const { branchLike, component } = this.props;
this.setState({ loading: true });

renderLoading() {
return (
<div className="text-center">
<i className="spinner spinner-margin" />
</div>
return getMeasuresAndMeta(component.key, METRICS, {
additionalFields: 'metrics,periods',
...getBranchLikeQuery(branchLike)
}).then(
({ component, metrics, periods }) => {
if (this.mounted && metrics && component.measures) {
this.setState({
loading: false,
measures: enhanceMeasuresWithMetrics(component.measures, metrics),
periods
});
}
},
error => {
throwGlobalError(error);
if (this.mounted) {
this.setState({ loading: false });
}
}
);
}
};

renderEmpty() {
renderEmpty = () => {
const { component } = this.props;
const isApp = component.qualifier === 'APP';
return (
@@ -191,9 +174,17 @@ export class OverviewApp extends React.PureComponent<Props, State> {
</h3>
</div>
);
}
};

renderMain() {
renderLoading = () => {
return (
<div className="text-center">
<i className="spinner spinner-margin" />
</div>
);
};

renderMain = () => {
const { branchLike, component } = this.props;
const { periods, measures, history, historyStartDate } = this.state;
const leakPeriod =
@@ -230,7 +221,7 @@ export class OverviewApp extends React.PureComponent<Props, State> {
</div>
</div>
);
}
};

render() {
const { branchLike, component } = this.props;
@@ -261,13 +252,9 @@ export class OverviewApp extends React.PureComponent<Props, State> {
}
}

const mapDispatchToProps: DispatchToProps = {
fetchMetrics
};
const mapDispatchToProps = { fetchMetrics };

const mapStateToProps = (state: Store): StateToProps => ({
metrics: getMetrics(state)
});
const mapStateToProps = (state: Store) => ({ metrics: getMetrics(state) });

export default connect(
mapStateToProps,

+ 3
- 8
server/sonar-web/src/main/js/apps/portfolio/components/Activity.tsx Zobrazit soubor

@@ -21,14 +21,12 @@ import * as React from 'react';
import {
getDisplayedHistoryMetrics,
DEFAULT_GRAPH,
PROJECT_ACTIVITY_GRAPH,
PROJECT_ACTIVITY_GRAPH_CUSTOM
getProjectActivityGraph
} from '../../projectActivity/utils';
import PreviewGraph from '../../../components/preview-graph/PreviewGraph';
import { getAllTimeMachineData } from '../../../api/time-machine';
import { parseDate } from '../../../helpers/dates';
import { translate } from '../../../helpers/l10n';
import { get } from '../../../helpers/storage';

interface Props {
component: string;
@@ -64,11 +62,8 @@ export default class Activity extends React.PureComponent<Props> {
fetchHistory = () => {
const { component } = this.props;

const customGraphs = get(PROJECT_ACTIVITY_GRAPH_CUSTOM);
let graphMetrics = getDisplayedHistoryMetrics(
get(PROJECT_ACTIVITY_GRAPH) || 'issues',
customGraphs ? customGraphs.split(',') : []
);
const { graph, customGraphs } = getProjectActivityGraph(component);
let graphMetrics = getDisplayedHistoryMetrics(graph, customGraphs);
if (!graphMetrics || graphMetrics.length <= 0) {
graphMetrics = getDisplayedHistoryMetrics(DEFAULT_GRAPH, []);
}

+ 26
- 24
server/sonar-web/src/main/js/apps/portfolio/components/__tests__/Activity-test.tsx Zobrazit soubor

@@ -17,36 +17,37 @@
* 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 import/first, import/order */
jest.mock('../../../../helpers/storage', () => ({
get: (key: string) => (key === 'sonarqube.project_activity.graph.custom' ? 'coverage' : 'custom')
}));

jest.mock('../../../../api/time-machine', () => ({
getAllTimeMachineData: jest.fn(() =>
Promise.resolve({
measures: [
{
metric: 'coverage',
history: [
{ date: '2017-01-01T00:00:00.000Z', value: '73' },
{ date: '2017-01-02T00:00:00.000Z', value: '82' }
]
}
]
})
)
}));

import * as React from 'react';
import { mount, shallow } from 'enzyme';
import Activity from '../Activity';
import { getAllTimeMachineData } from '../../../../api/time-machine';
import { getProjectActivityGraph } from '../../../projectActivity/utils';

jest.mock('../../../projectActivity/utils', () => {
const utils = require.requireActual('../../../projectActivity/utils');
utils.getProjectActivityGraph = jest
.fn()
.mockReturnValue({ graph: 'custom', customGraphs: ['coverage'] });
return utils;
});

const getAllTimeMachineData = require('../../../../api/time-machine')
.getAllTimeMachineData as jest.Mock<any>;
jest.mock('../../../../api/time-machine', () => ({
getAllTimeMachineData: jest.fn().mockResolvedValue({
measures: [
{
metric: 'coverage',
history: [
{ date: '2017-01-01T00:00:00.000Z', value: '73' },
{ date: '2017-01-02T00:00:00.000Z', value: '82' }
]
}
]
})
}));

beforeEach(() => {
getAllTimeMachineData.mockClear();
(getAllTimeMachineData as jest.Mock).mockClear();
(getProjectActivityGraph as jest.Mock).mockClear();
});

it('renders', () => {
@@ -62,6 +63,7 @@ it('renders', () => {
metrics: [{ key: 'coverage' }]
});
expect(wrapper).toMatchSnapshot();
expect(getProjectActivityGraph).toBeCalledWith('foo');
});

it('fetches history', () => {

+ 2
- 1
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.tsx Zobrazit soubor

@@ -38,7 +38,7 @@ interface Props {
deleteEvent: (analysis: string, event: string) => Promise<void>;
graphLoading: boolean;
initializing: boolean;
project: Pick<T.Component, 'configuration' | 'leakPeriodDate' | 'qualifier'>;
project: Pick<T.Component, 'configuration' | 'key' | 'leakPeriodDate' | 'qualifier'>;
metrics: T.Metric[];
measuresHistory: MeasureHistory[];
query: Query;
@@ -93,6 +93,7 @@ export default function ProjectActivityApp(props: Props) {
loading={props.graphLoading}
measuresHistory={measuresHistory}
metrics={props.metrics}
project={props.project.key}
query={query}
updateQuery={props.updateQuery}
/>

+ 36
- 29
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAppContainer.tsx Zobrazit soubor

@@ -27,20 +27,18 @@ import * as api from '../../../api/projectActivity';
import * as actions from '../actions';
import { getBranchLikeQuery } from '../../../helpers/branches';
import { parseDate } from '../../../helpers/dates';
import { get } from '../../../helpers/storage';
import {
customMetricsChanged,
DEFAULT_GRAPH,
getHistoryMetrics,
getProjectActivityGraph,
isCustomGraph,
parseQuery,
PROJECT_ACTIVITY_GRAPH,
PROJECT_ACTIVITY_GRAPH_CUSTOM,
serializeQuery,
serializeUrlQuery,
MeasureHistory,
parseQuery,
ParsedAnalysis,
Query,
ParsedAnalysis
serializeQuery,
serializeUrlQuery
} from '../utils';
import { RawQuery } from '../../../helpers/query';

@@ -81,10 +79,10 @@ export default class ProjectActivityAppContainer extends React.PureComponent<Pro
componentDidMount() {
this.mounted = true;
if (this.shouldRedirect()) {
const newQuery = { ...this.state.query, graph: get(PROJECT_ACTIVITY_GRAPH) || 'issues' };
const { graph, customGraphs } = getProjectActivityGraph(this.props.component.key);
const newQuery = { ...this.state.query, graph };
if (isCustomGraph(newQuery.graph)) {
const customGraphs = get(PROJECT_ACTIVITY_GRAPH_CUSTOM);
newQuery.customMetrics = customGraphs ? customGraphs.split(',') : [];
newQuery.customMetrics = customGraphs;
}
this.props.router.replace({
pathname: this.props.location.pathname,
@@ -98,14 +96,14 @@ export default class ProjectActivityAppContainer extends React.PureComponent<Pro
}
}

componentWillReceiveProps(nextProps: Props) {
if (nextProps.location.query !== this.props.location.query) {
const query = parseQuery(nextProps.location.query);
componentDidUpdate(prevProps: Props) {
if (prevProps.location.query !== this.props.location.query) {
const query = parseQuery(this.props.location.query);
if (query.graph !== this.state.query.graph || customMetricsChanged(this.state.query, query)) {
if (this.state.initialized) {
this.updateGraphData(query.graph, query.customMetrics);
} else {
this.firstLoadData(query, nextProps.component);
this.firstLoadData(query, this.props.component);
}
}
this.setState({ query });
@@ -185,6 +183,26 @@ export default class ProjectActivityAppContainer extends React.PureComponent<Pro
);
};

fetchAllActivities = (topLevelComponent: string) => {
this.setState({ analysesLoading: true });
this.loadAllActivities(topLevelComponent).then(
({ analyses, paging }) => {
if (this.mounted) {
this.setState({
analyses,
analysesLoading: false,
paging
});
}
},
() => {
if (this.mounted) {
this.setState({ analysesLoading: false });
}
}
);
};

loadAllActivities = (
project: string,
prevResult?: { analyses: ParsedAnalysis[]; paging: T.Paging }
@@ -230,7 +248,6 @@ export default class ProjectActivityAppContainer extends React.PureComponent<Pro
if (this.mounted) {
this.setState({
analyses: response[0].analyses,
analysesLoading: true,
graphLoading: false,
initialized: true,
measuresHistory: response[2],
@@ -238,20 +255,12 @@ export default class ProjectActivityAppContainer extends React.PureComponent<Pro
paging: response[0].paging
});

this.loadAllActivities(topLevelComponent).then(({ analyses, paging }) => {
if (this.mounted) {
this.setState({
analyses,
analysesLoading: false,
paging
});
}
});
this.fetchAllActivities(topLevelComponent);
}
},
() => {
if (this.mounted) {
this.setState({ initialized: true, analysesLoading: false, graphLoading: false });
this.setState({ initialized: true, graphLoading: false });
}
}
);
@@ -298,10 +307,8 @@ export default class ProjectActivityAppContainer extends React.PureComponent<Pro
key => key !== 'id' && locationQuery[key] !== ''
);

const customGraphs = get(PROJECT_ACTIVITY_GRAPH_CUSTOM);
const graph = get(PROJECT_ACTIVITY_GRAPH) || 'issues';
const emptyCustomGraph =
isCustomGraph(graph) && customGraphs && customGraphs.split(',').length <= 0;
const { graph, customGraphs } = getProjectActivityGraph(this.props.component.key);
const emptyCustomGraph = isCustomGraph(graph) && customGraphs.length <= 0;

// if there is no filter, but there are saved preferences in the localStorage
// also don't redirect to custom if there is no metrics selected for it

+ 28
- 27
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphs.tsx Zobrazit soubor

@@ -22,7 +22,7 @@ import { debounce, findLast, maxBy, minBy, sortBy } from 'lodash';
import ProjectActivityGraphsHeader from './ProjectActivityGraphsHeader';
import GraphsZoom from './GraphsZoom';
import GraphsHistory from './GraphsHistory';
import { get, save } from '../../../helpers/storage';
import { save } from '../../../helpers/storage';
import {
datesQueryChanged,
generateSeries,
@@ -30,14 +30,15 @@ import {
getSeriesMetricType,
historyQueryChanged,
isCustomGraph,
MeasureHistory,
ParsedAnalysis,
Point,
PROJECT_ACTIVITY_GRAPH,
PROJECT_ACTIVITY_GRAPH_CUSTOM,
splitSeriesInGraphs,
MeasureHistory,
Query,
Serie,
Point,
ParsedAnalysis
splitSeriesInGraphs,
getProjectActivityGraph
} from '../utils';

interface Props {
@@ -46,6 +47,7 @@ interface Props {
loading: boolean;
measuresHistory: MeasureHistory[];
metrics: T.Metric[];
project: string;
query: Query;
updateQuery: (changes: Partial<Query>) => void;
}
@@ -77,23 +79,23 @@ export default class ProjectActivityGraphs extends React.PureComponent<Props, St
this.updateQueryDateRange = debounce(this.updateQueryDateRange, 500);
}

componentWillReceiveProps(nextProps: Props) {
componentDidUpdate(prevProps: Props) {
let newSeries;
let newGraphs;
if (
nextProps.measuresHistory !== this.props.measuresHistory ||
historyQueryChanged(this.props.query, nextProps.query)
prevProps.measuresHistory !== this.props.measuresHistory ||
historyQueryChanged(prevProps.query, this.props.query)
) {
newSeries = generateSeries(
nextProps.measuresHistory,
nextProps.query.graph,
nextProps.metrics,
getDisplayedHistoryMetrics(nextProps.query.graph, nextProps.query.customMetrics)
this.props.measuresHistory,
this.props.query.graph,
this.props.metrics,
getDisplayedHistoryMetrics(this.props.query.graph, this.props.query.customMetrics)
);
newGraphs = splitSeriesInGraphs(newSeries, MAX_GRAPH_NB, MAX_SERIES_PER_GRAPH);
}

const newDates = this.getStateZoomDates(this.props, nextProps, newSeries);
const newDates = this.getStateZoomDates(prevProps, this.props, newSeries);

if (newSeries || newDates) {
let newState = {} as State;
@@ -110,28 +112,27 @@ export default class ProjectActivityGraphs extends React.PureComponent<Props, St
}
}

getStateZoomDates = (props: Props | undefined, nextProps: Props, newSeries?: Serie[]) => {
getStateZoomDates = (prevProps: Props | undefined, props: Props, newSeries?: Serie[]) => {
const newDates = {
from: nextProps.query.from || undefined,
to: nextProps.query.to || undefined
from: props.query.from || undefined,
to: props.query.to || undefined
};
if (!props || datesQueryChanged(props.query, nextProps.query)) {
if (!prevProps || datesQueryChanged(prevProps.query, props.query)) {
return { graphEndDate: newDates.to, graphStartDate: newDates.from };
}

if (newDates.to === undefined && newDates.from === undefined && newSeries !== undefined) {
const series = newSeries ? newSeries : this.state.series;
const firstValid = minBy(
series.map(serie => serie.data.find(p => Boolean(p.y || p.y === 0))),
newSeries.map(serie => serie.data.find(p => Boolean(p.y || p.y === 0))),
'x'
);
const lastValid = maxBy<Point>(
series.map(serie => findLast(serie.data, p => Boolean(p.y || p.y === 0))!),
newSeries.map(serie => findLast(serie.data, p => Boolean(p.y || p.y === 0))!),
'x'
);
return {
graphEndDate: lastValid ? lastValid.x : newDates.to,
graphStartDate: firstValid ? firstValid.x : newDates.from
graphEndDate: lastValid && lastValid.x,
graphStartDate: firstValid && firstValid.x
};
}
return null;
@@ -148,21 +149,21 @@ export default class ProjectActivityGraphs extends React.PureComponent<Props, St

addCustomMetric = (metric: string) => {
const customMetrics = [...this.props.query.customMetrics, metric];
save(PROJECT_ACTIVITY_GRAPH_CUSTOM, customMetrics.join(','));
save(PROJECT_ACTIVITY_GRAPH_CUSTOM, customMetrics.join(','), this.props.project);
this.props.updateQuery({ customMetrics });
};

removeCustomMetric = (removedMetric: string) => {
const customMetrics = this.props.query.customMetrics.filter(metric => metric !== removedMetric);
save(PROJECT_ACTIVITY_GRAPH_CUSTOM, customMetrics.join(','));
save(PROJECT_ACTIVITY_GRAPH_CUSTOM, customMetrics.join(','), this.props.project);
this.props.updateQuery({ customMetrics });
};

updateGraph = (graph: string) => {
save(PROJECT_ACTIVITY_GRAPH, graph);
save(PROJECT_ACTIVITY_GRAPH, graph, this.props.project);
if (isCustomGraph(graph) && this.props.query.customMetrics.length <= 0) {
const customGraphs = get(PROJECT_ACTIVITY_GRAPH_CUSTOM);
this.props.updateQuery({ graph, customMetrics: customGraphs ? customGraphs.split(',') : [] });
const { customGraphs } = getProjectActivityGraph(this.props.project);
this.props.updateQuery({ graph, customMetrics: customGraphs });
} else {
this.props.updateQuery({ graph, customMetrics: [] });
}

+ 1
- 0
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.tsx Zobrazit soubor

@@ -70,6 +70,7 @@ const DEFAULT_PROPS = {
graphLoading: false,
initializing: false,
project: {
key: 'foo',
leakPeriodDate: '2017-05-16T13:50:02+0200',
qualifier: 'TRK'
},

+ 1
- 0
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityGraphs-test.tsx Zobrazit soubor

@@ -61,6 +61,7 @@ const DEFAULT_PROPS: ProjectActivityGraphs['props'] = {
}
],
metrics: METRICS,
project: 'foo',
query: {
category: '',
customMetrics: [],

+ 3
- 0
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.tsx.snap Zobrazit soubor

@@ -17,6 +17,7 @@ exports[`should render correctly 1`] = `
category=""
project={
Object {
"key": "foo",
"leakPeriodDate": "2017-05-16T13:50:02+0200",
"qualifier": "TRK",
}
@@ -78,6 +79,7 @@ exports[`should render correctly 1`] = `
initializing={false}
project={
Object {
"key": "foo",
"leakPeriodDate": "2017-05-16T13:50:02+0200",
"qualifier": "TRK",
}
@@ -162,6 +164,7 @@ exports[`should render correctly 1`] = `
},
]
}
project="foo"
query={
Object {
"category": "",

+ 15
- 6
server/sonar-web/src/main/js/apps/projectActivity/utils.ts Zobrazit soubor

@@ -30,6 +30,7 @@ import {
} from '../../helpers/query';
import { parseDate, startOfDay } from '../../helpers/dates';
import { getLocalizedMetricName, translate } from '../../helpers/l10n';
import { get } from '../../helpers/storage';

export type ParsedAnalysis = T.Omit<T.Analysis, 'date'> & { date: Date };

@@ -84,12 +85,8 @@ export const GRAPHS_METRICS: { [x: string]: string[] } = {
duplications: GRAPHS_METRICS_DISPLAYED['duplications'].concat(['duplicated_lines_density'])
};

export const PROJECT_ACTIVITY_GRAPH = 'sonarqube.project_activity.graph';
export const PROJECT_ACTIVITY_GRAPH_CUSTOM = 'sonarqube.project_activity.graph.custom';

export function datesQueryChanged(prevQuery: Query, nextQuery: Query) {
return !isEqual(prevQuery.from, nextQuery.from) || !isEqual(prevQuery.to, nextQuery.to);
}
export const PROJECT_ACTIVITY_GRAPH = 'sonar_project_activity.graph';
export const PROJECT_ACTIVITY_GRAPH_CUSTOM = 'sonar_project_activity.graph.custom';

export function activityQueryChanged(prevQuery: Query, nextQuery: Query) {
return prevQuery.category !== nextQuery.category || datesQueryChanged(prevQuery, nextQuery);
@@ -99,6 +96,10 @@ export function customMetricsChanged(prevQuery: Query, nextQuery: Query) {
return !isEqual(prevQuery.customMetrics, nextQuery.customMetrics);
}

export function datesQueryChanged(prevQuery: Query, nextQuery: Query) {
return !isEqual(prevQuery.from, nextQuery.from) || !isEqual(prevQuery.to, nextQuery.to);
}

export function hasDataValues(serie: Serie) {
return serie.data.some(point => Boolean(point.y || point.y === 0));
}
@@ -246,6 +247,14 @@ export function getHistoryMetrics(graph: string, customMetrics: string[]) {
return isCustomGraph(graph) ? customMetrics : GRAPHS_METRICS[graph];
}

export function getProjectActivityGraph(project: string) {
const customGraphs = get(PROJECT_ACTIVITY_GRAPH_CUSTOM, project);
return {
graph: get(PROJECT_ACTIVITY_GRAPH, project) || 'issues',
customGraphs: customGraphs ? customGraphs.split(',') : []
};
}

function parseGraph(value?: string) {
const graph = parseAsString(value);
return GRAPH_TYPES.includes(graph) ? graph : DEFAULT_GRAPH;

+ 9
- 15
server/sonar-web/src/main/js/components/preview-graph/PreviewGraph.tsx Zobrazit soubor

@@ -24,16 +24,14 @@ import PreviewGraphTooltips from './PreviewGraphTooltips';
import AdvancedTimeline from '../charts/AdvancedTimeline';
import {
DEFAULT_GRAPH,
getDisplayedHistoryMetrics,
generateSeries,
getDisplayedHistoryMetrics,
getProjectActivityGraph,
getSeriesMetricType,
hasHistoryDataValue,
PROJECT_ACTIVITY_GRAPH,
PROJECT_ACTIVITY_GRAPH_CUSTOM,
splitSeriesInGraphs,
Serie
Serie,
splitSeriesInGraphs
} from '../../apps/projectActivity/utils';
import { get } from '../../helpers/storage';
import { formatMeasure, getShortType } from '../../helpers/measures';
import { getBranchLikeQuery } from '../../helpers/branches';
import { withRouter, Router } from '../hoc/withRouter';
@@ -67,9 +65,7 @@ const MAX_SERIES_PER_GRAPH = 3;
class PreviewGraph extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
const customGraphs = get(PROJECT_ACTIVITY_GRAPH_CUSTOM);
const graph = get(PROJECT_ACTIVITY_GRAPH) || 'issues';
const customMetrics = customGraphs ? customGraphs.split(',') : [];
const { graph, customGraphs: customMetrics } = getProjectActivityGraph(props.project);
const series = splitSeriesInGraphs(
this.getSeries(props.history, graph, customMetrics, props.metrics),
MAX_GRAPH_NB,
@@ -82,13 +78,11 @@ class PreviewGraph extends React.PureComponent<Props, State> {
};
}

componentWillReceiveProps(nextProps: Props) {
if (nextProps.history !== this.props.history || nextProps.metrics !== this.props.metrics) {
const customGraphs = get(PROJECT_ACTIVITY_GRAPH_CUSTOM);
const graph = get(PROJECT_ACTIVITY_GRAPH) || 'issues';
const customMetrics = customGraphs ? customGraphs.split(',') : [];
componentDidUpdate(prevProps: Props) {
if (prevProps.history !== this.props.history || prevProps.metrics !== this.props.metrics) {
const { graph, customGraphs: customMetrics } = getProjectActivityGraph(this.props.project);
const series = splitSeriesInGraphs(
this.getSeries(nextProps.history, graph, customMetrics, nextProps.metrics),
this.getSeries(this.props.history, graph, customMetrics, this.props.metrics),
MAX_GRAPH_NB,
MAX_SERIES_PER_GRAPH
);

Načítá se…
Zrušit
Uložit