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.

ScopeFacet.tsx 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2020 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 { without } from 'lodash';
  21. import * as React from 'react';
  22. import QualifierIcon from 'sonar-ui-common/components/icons/QualifierIcon';
  23. import { translate } from 'sonar-ui-common/helpers/l10n';
  24. import FacetBox from '../../../components/facet/FacetBox';
  25. import FacetHeader from '../../../components/facet/FacetHeader';
  26. import FacetItem from '../../../components/facet/FacetItem';
  27. import FacetItemsList from '../../../components/facet/FacetItemsList';
  28. import MultipleSelectionHint from '../../../components/facet/MultipleSelectionHint';
  29. import { SOURCE_SCOPES } from '../../../helpers/constants';
  30. import { formatFacetStat, Query } from '../utils';
  31. export interface ScopeFacetProps {
  32. fetching: boolean;
  33. onChange: (changes: Partial<Query>) => void;
  34. onToggle: (property: string) => void;
  35. open: boolean;
  36. scopes: string[];
  37. stats: T.Dict<number> | undefined;
  38. }
  39. export default function ScopeFacet(props: ScopeFacetProps) {
  40. const { fetching, open, scopes = [], stats = {} } = props;
  41. const values = scopes.map(scope => translate('issue.scope', scope));
  42. return (
  43. <FacetBox property="scopes">
  44. <FacetHeader
  45. fetching={fetching}
  46. name={translate('issues.facet.scopes')}
  47. onClear={() => props.onChange({ scopes: [] })}
  48. onClick={() => props.onToggle('scopes')}
  49. open={open}
  50. values={values}
  51. />
  52. {open && (
  53. <>
  54. <FacetItemsList>
  55. {SOURCE_SCOPES.map(({ scope, qualifier }) => {
  56. const active = scopes.includes(scope);
  57. const stat = stats[scope];
  58. return (
  59. <FacetItem
  60. active={active}
  61. disabled={stat === 0 && !active}
  62. key={scope}
  63. name={
  64. <span className="display-flex-center">
  65. <QualifierIcon className="little-spacer-right" qualifier={qualifier} />{' '}
  66. {translate('issue.scope', scope)}
  67. </span>
  68. }
  69. onClick={(itemValue: string, multiple: boolean) => {
  70. if (multiple) {
  71. props.onChange({
  72. scopes: active ? without(scopes, itemValue) : [...scopes, itemValue]
  73. });
  74. } else {
  75. props.onChange({
  76. scopes: active && scopes.length === 1 ? [] : [itemValue]
  77. });
  78. }
  79. }}
  80. stat={formatFacetStat(stat)}
  81. value={scope}
  82. />
  83. );
  84. })}
  85. </FacetItemsList>
  86. <MultipleSelectionHint options={Object.keys(stats).length} values={scopes.length} />
  87. </>
  88. )}
  89. </FacetBox>
  90. );
  91. }