You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MeasuresCard.tsx 2.8KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2024 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. import styled from '@emotion/styled';
  21. import { LinkHighlight, LinkStandalone } from '@sonarsource/echoes-react';
  22. import { Badge, Card, themeBorder, themeColor } from 'design-system';
  23. import * as React from 'react';
  24. import { To } from 'react-router-dom';
  25. import { translate, translateWithParameters } from '../../../helpers/l10n';
  26. import { localizeMetric } from '../../../helpers/measures';
  27. import { MetricKey } from '../../../types/metrics';
  28. export interface MeasuresCardProps {
  29. url: To;
  30. value?: string;
  31. metric: MetricKey;
  32. label: string;
  33. failed?: boolean;
  34. icon?: React.ReactElement;
  35. }
  36. export default function MeasuresCard(
  37. props: React.PropsWithChildren<MeasuresCardProps & React.HTMLAttributes<HTMLDivElement>>,
  38. ) {
  39. const { failed, children, metric, icon, value, url, label, ...rest } = props;
  40. return (
  41. <StyledCard className="sw-p-6 sw-rounded-2 sw-text-base" {...rest}>
  42. <ColorBold className="sw-body-sm-highlight">{translate(label)}</ColorBold>
  43. {failed && (
  44. <Badge className="sw-mt-1/2 sw-px-1 sw-ml-2" variant="deleted">
  45. {translate('overview.measures.failed_badge')}
  46. </Badge>
  47. )}
  48. <div className="sw-flex sw-items-center sw-mt-1 sw-justify-between sw-font-semibold">
  49. <LinkStandalone
  50. highlight={LinkHighlight.Default}
  51. aria-label={
  52. value
  53. ? translateWithParameters(
  54. 'overview.see_more_details_on_x_of_y',
  55. value,
  56. localizeMetric(metric),
  57. )
  58. : translateWithParameters('no_measure_value_x', localizeMetric(metric))
  59. }
  60. className="it__overview-measures-value sw-text-lg"
  61. to={url}
  62. >
  63. {value ?? '-'}
  64. </LinkStandalone>
  65. {icon}
  66. </div>
  67. {children && <div className="sw-flex sw-flex-col">{children}</div>}
  68. </StyledCard>
  69. );
  70. }
  71. const StyledCard = styled(Card)`
  72. border: ${themeBorder('default')};
  73. `;
  74. const ColorBold = styled.span`
  75. color: ${themeColor('pageTitle')};
  76. `;