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.

AuditAppRenderer.tsx 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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 { Link, RadioButtonGroup } from '@sonarsource/echoes-react';
  21. import { subDays } from 'date-fns';
  22. import {
  23. DateRangePicker,
  24. LargeCenteredLayout,
  25. PageContentFontWrapper,
  26. PopupZLevel,
  27. Title,
  28. } from 'design-system';
  29. import * as React from 'react';
  30. import { Helmet } from 'react-helmet-async';
  31. import { FormattedMessage } from 'react-intl';
  32. import { queryToSearchString } from '~sonar-aligned/helpers/urls';
  33. import Suggestions from '../../../components/embed-docs-modal/Suggestions';
  34. import { now } from '../../../helpers/dates';
  35. import { translate } from '../../../helpers/l10n';
  36. import '../style.css';
  37. import { HousekeepingPolicy, RangeOption } from '../utils';
  38. import DownloadButton from './DownloadButton';
  39. export interface AuditAppRendererProps {
  40. dateRange?: { from?: Date; to?: Date };
  41. downloadStarted: boolean;
  42. handleOptionSelection: (option: RangeOption) => void;
  43. handleDateSelection: (dateRange: { from?: Date; to?: Date }) => void;
  44. handleStartDownload: () => void;
  45. housekeepingPolicy: HousekeepingPolicy;
  46. selection: RangeOption;
  47. }
  48. const HOUSEKEEPING_MONTH_THRESHOLD = 30;
  49. const HOUSEKEEPING_TRIMESTER_THRESHOLD = 90;
  50. const HOUSEKEEPING_POLICY_VALUES = {
  51. [HousekeepingPolicy.Weekly]: 7,
  52. [HousekeepingPolicy.Monthly]: 30,
  53. [HousekeepingPolicy.Trimestrial]: 90,
  54. [HousekeepingPolicy.Yearly]: 365,
  55. };
  56. const getRangeOptions = (housekeepingPolicy: HousekeepingPolicy) => {
  57. const rangeOptions = [RangeOption.Today, RangeOption.Week];
  58. if (HOUSEKEEPING_POLICY_VALUES[housekeepingPolicy] >= HOUSEKEEPING_MONTH_THRESHOLD) {
  59. rangeOptions.push(RangeOption.Month);
  60. }
  61. if (HOUSEKEEPING_POLICY_VALUES[housekeepingPolicy] >= HOUSEKEEPING_TRIMESTER_THRESHOLD) {
  62. rangeOptions.push(RangeOption.Trimester);
  63. }
  64. rangeOptions.push(RangeOption.Custom);
  65. return rangeOptions;
  66. };
  67. export default function AuditAppRenderer(props: Readonly<AuditAppRendererProps>) {
  68. const { dateRange, downloadStarted, housekeepingPolicy, selection } = props;
  69. return (
  70. <LargeCenteredLayout as="main" id="audit-logs-page">
  71. <PageContentFontWrapper className="sw-body-sm sw-my-8">
  72. <Suggestions suggestions="audit-logs" />
  73. <Helmet title={translate('audit_logs.page')} />
  74. <Title>{translate('audit_logs.page')}</Title>
  75. <p className="sw-mb-4">
  76. {translate('audit_logs.page.description.1')}
  77. <br />
  78. <FormattedMessage
  79. id="audit_logs.page.description.2"
  80. defaultMessage={translate('audit_logs.page.description.2')}
  81. values={{
  82. housekeeping: translate('audit_logs.housekeeping_policy', housekeepingPolicy),
  83. link: (
  84. <Link
  85. to={{
  86. pathname: '/admin/settings',
  87. search: queryToSearchString({ category: 'housekeeping' }),
  88. hash: '#auditLogs',
  89. }}
  90. >
  91. {translate('audit_logs.page.description.link')}
  92. </Link>
  93. ),
  94. }}
  95. />
  96. </p>
  97. <div className="sw-mb-6">
  98. <h3 className="sw-mb-4">{translate('audit_logs.download')}</h3>
  99. <RadioButtonGroup
  100. id="audit-logs-housekeeping-radio"
  101. options={getRangeOptions(housekeepingPolicy).map((option) => ({
  102. label: translate('audit_logs.range_option', option),
  103. value: option,
  104. }))}
  105. value={selection}
  106. onChange={props.handleOptionSelection}
  107. />
  108. <DateRangePicker
  109. className="sw-w-abs-350 sw-mt-4"
  110. clearButtonLabel={translate('clear')}
  111. fromLabel={translate('start_date')}
  112. onChange={props.handleDateSelection}
  113. separatorText={translate('to_')}
  114. toLabel={translate('end_date')}
  115. value={dateRange}
  116. minDate={subDays(now(), HOUSEKEEPING_POLICY_VALUES[housekeepingPolicy])}
  117. maxDate={now()}
  118. zLevel={PopupZLevel.Content}
  119. />
  120. </div>
  121. <DownloadButton
  122. dateRange={dateRange}
  123. downloadStarted={downloadStarted}
  124. onStartDownload={props.handleStartDownload}
  125. selection={selection}
  126. />
  127. </PageContentFontWrapper>
  128. </LargeCenteredLayout>
  129. );
  130. }