}
export interface DonutChartProps {
+ cornerRadius?: number;
data: DataPoint[];
height: number;
+ minPercent?: number;
padAngle?: number;
padding?: [number, number, number, number];
thickness: number;
}
export function DonutChart(props: DonutChartProps) {
- const { height, padding = [0, 0, 0, 0], width } = props;
+ const { height, cornerRadius, minPercent = 0, padding = [0, 0, 0, 0], width } = props;
const availableWidth = width - padding[1] - padding[3];
const availableHeight = height - padding[0] - padding[2];
const size = Math.min(availableWidth, availableHeight);
const radius = Math.floor(size / 2);
+ const total = props.data.reduce((acc, d) => acc + d.value, 0);
+
const pie = d3Pie<any, DataPoint>()
.sort(null)
- .value((d) => d.value);
+ .value((d) => Math.max(d.value, (total / 100) * minPercent));
if (props.padAngle !== undefined) {
pie.padAngle(props.padAngle);
const sectors = pie(props.data).map((d, i) => {
return (
<Sector
+ cornerRadius={cornerRadius}
data={d}
fill={props.data[i].fill}
key={i}
}
interface SectorProps {
+ cornerRadius?: number;
data: PieArcDatum<DataPoint>;
fill: string;
radius: number;
const arc = d3Arc<any, PieArcDatum<DataPoint>>()
.outerRadius(props.radius)
.innerRadius(props.radius - props.thickness);
+
+ if (props.cornerRadius) {
+ arc.cornerRadius(props.cornerRadius);
+ }
const d = arc(props.data) as string;
return <path d={d} style={{ fill: props.fill }} />;
}
'rating.D': COLORS.red[200],
'rating.E': COLORS.red[200],
+ 'portfolio.rating.A.text': COLORS.green[900],
+ 'portfolio.rating.A.background': COLORS.green[100],
+ 'portfolio.rating.A.border': COLORS.green[400],
+ 'portfolio.rating.B.text': COLORS.yellowGreen[900],
+ 'portfolio.rating.B.background': COLORS.yellowGreen[100],
+ 'portfolio.rating.B.border': COLORS.yellowGreen[400],
+ 'portfolio.rating.C.text': COLORS.yellow[900],
+ 'portfolio.rating.C.background': COLORS.yellow[100],
+ 'portfolio.rating.C.border': COLORS.yellow[500],
+ 'portfolio.rating.D.text': COLORS.red[900],
+ 'portfolio.rating.D.background': COLORS.red[100],
+ 'portfolio.rating.D.border': COLORS.red[400],
+ 'portfolio.rating.E.text': COLORS.red[900],
+ 'portfolio.rating.E.background': COLORS.red[100],
+ 'portfolio.rating.E.border': COLORS.red[400],
+ 'portfolio.rating.NONE.text': COLORS.blueGrey[300],
+ 'portfolio.rating.NONE.background': COLORS.blueGrey[50],
+ 'portfolio.rating.NONE.border': COLORS.blueGrey[200],
+
+ 'portfolio.rating.legacy.A.text': COLORS.green[900],
+ 'portfolio.rating.legacy.A.background': COLORS.green[100],
+ 'portfolio.rating.legacy.A.border': COLORS.green[400],
+ 'portfolio.rating.legacy.B.text': COLORS.yellowGreen[900],
+ 'portfolio.rating.legacy.B.background': COLORS.yellowGreen[100],
+ 'portfolio.rating.legacy.B.border': COLORS.yellowGreen[400],
+ 'portfolio.rating.legacy.C.text': COLORS.yellow[900],
+ 'portfolio.rating.legacy.C.background': COLORS.yellow[100],
+ 'portfolio.rating.legacy.C.border': COLORS.yellow[500],
+ 'portfolio.rating.legacy.D.text': COLORS.orange[900],
+ 'portfolio.rating.legacy.D.background': COLORS.orange[100],
+ 'portfolio.rating.legacy.D.border': COLORS.orange[300],
+ 'portfolio.rating.legacy.E.text': COLORS.red[900],
+ 'portfolio.rating.legacy.E.background': COLORS.red[100],
+ 'portfolio.rating.legacy.E.border': COLORS.red[400],
+ 'portfolio.rating.legacy.NONE.text': COLORS.blueGrey[300],
+ 'portfolio.rating.legacy.NONE.background': COLORS.blueGrey[50],
+ 'portfolio.rating.legacy.NONE.border': COLORS.blueGrey[200],
+
// rating donut outside circle indicators
'ratingDonut.A': COLORS.green[400],
'ratingDonut.B': COLORS.yellowGreen[400],
export const SOFTWARE_QUALITY_RATING_METRICS_MAP: Record<string, MetricKey> = {
[MetricKey.releasability_rating]: MetricKey.software_quality_releasability_rating,
+ [MetricKey.releasability_rating_distribution]:
+ MetricKey.software_quality_releasability_rating_distribution,
[MetricKey.sqale_rating]: MetricKey.software_quality_maintainability_rating,
+ [MetricKey.maintainability_rating_distribution]:
+ MetricKey.software_quality_maintainability_rating_distribution,
[MetricKey.security_rating]: MetricKey.software_quality_security_rating,
+ [MetricKey.security_rating_distribution]: MetricKey.software_quality_security_rating_distribution,
[MetricKey.reliability_rating]: MetricKey.software_quality_reliability_rating,
+ [MetricKey.reliability_rating_distribution]:
+ MetricKey.software_quality_reliability_rating_distribution,
[MetricKey.security_review_rating]: MetricKey.software_quality_security_review_rating,
+ [MetricKey.security_review_rating_distribution]:
+ MetricKey.software_quality_security_review_rating_distribution,
[MetricKey.reliability_remediation_effort]:
MetricKey.software_quality_reliability_remediation_effort,
[MetricKey.security_remediation_effort]: MetricKey.software_quality_security_remediation_effort,
[MetricKey.effort_to_reach_maintainability_rating_a]:
MetricKey.effort_to_reach_software_quality_maintainability_rating_a,
[MetricKey.new_maintainability_rating]: MetricKey.new_software_quality_maintainability_rating,
+ [MetricKey.new_maintainability_rating_distribution]:
+ MetricKey.new_software_quality_maintainability_rating_distribution,
[MetricKey.new_security_rating]: MetricKey.new_software_quality_security_rating,
+ [MetricKey.new_security_rating_distribution]:
+ MetricKey.new_software_quality_security_rating_distribution,
[MetricKey.new_reliability_rating]: MetricKey.new_software_quality_reliability_rating,
+ [MetricKey.new_reliability_rating_distribution]:
+ MetricKey.new_software_quality_reliability_rating_distribution,
[MetricKey.new_security_review_rating]: MetricKey.new_software_quality_security_review_rating,
+ [MetricKey.new_security_review_rating_distribution]:
+ MetricKey.new_software_quality_security_review_rating_distribution,
[MetricKey.new_technical_debt]: MetricKey.new_software_quality_maintainability_remediation_effort,
[MetricKey.new_reliability_remediation_effort]:
MetricKey.new_software_quality_reliability_remediation_effort,
Issues = '/user-guide/issues/introduction/',
IssueStatuses = '/user-guide/issues/solution-overview/#life-cycle',
MainBranchAnalysis = '/project-administration/maintaining-the-branches-of-your-project/',
+ ManagingPortfolios = '/project-administration/managing-portfolios/',
MetricDefinitions = '/user-guide/code-metrics/metrics-definition/',
Monorepos = '/project-administration/monorepos/',
NewCodeDefinition = '/project-administration/clean-as-you-code-settings/defining-new-code/',
import { MetricKey } from '../sonar-aligned/types/metrics';
import { BranchLike } from '../types/branch-like';
import { Measure } from '../types/types';
-import { createInfiniteQueryHook, createQueryHook } from './common';
+import { createInfiniteQueryHook, createQueryHook, StaleTime } from './common';
export function useAllMeasuresHistoryQuery(
component: string | undefined,
});
},
);
+
+const PORTFOLIO_OVERVIEW_METRIC_KEYS = [
+ MetricKey.software_quality_releasability_rating,
+ MetricKey.software_quality_releasability_rating_distribution,
+ MetricKey.software_quality_security_rating_distribution,
+ MetricKey.software_quality_security_review_rating_distribution,
+ MetricKey.software_quality_maintainability_rating_distribution,
+ MetricKey.software_quality_reliability_rating_distribution,
+ MetricKey.new_software_quality_security_rating_distribution,
+ MetricKey.new_software_quality_security_review_rating_distribution,
+ MetricKey.new_software_quality_maintainability_rating_distribution,
+ MetricKey.new_software_quality_reliability_rating_distribution,
+];
+
+export const useMeasuresQuery = createQueryHook(
+ ({
+ componentKey,
+ metricKeys,
+ branchLike,
+ }: {
+ branchLike?: BranchLike;
+ componentKey: string;
+ metricKeys: string;
+ }) => {
+ const queryClient = useQueryClient();
+ const branchLikeQuery = getBranchLikeQuery(branchLike);
+
+ return queryOptions({
+ queryKey: ['measures', 'list', componentKey, 'branchLike', branchLikeQuery, metricKeys],
+ queryFn: async () => {
+ const measures = await getMeasures({
+ component: componentKey,
+ // TODO Remove once BE is ready
+ metricKeys: metricKeys
+ .split(',')
+ .filter((key) => !PORTFOLIO_OVERVIEW_METRIC_KEYS.includes(key as MetricKey))
+ .join(),
+ });
+
+ const measuresMapByMetricKey = groupBy(measures, 'metric');
+ metricKeys.split(',').forEach((metricKey) => {
+ const measure = measuresMapByMetricKey[metricKey]?.[0] ?? null;
+ queryClient.setQueryData<Measure>(
+ ['measures', 'details', componentKey, 'branchLike', branchLike, metricKey],
+ measure,
+ );
+ });
+ return measures;
+ },
+ staleTime: StaleTime.LONG,
+ });
+ },
+);