From 87e140b0878e858911e9763c4b677c49334e1e3d Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Mon, 12 Jul 2021 18:12:10 +0200 Subject: SONAR-15143 Enable users to download audit logs - UI --- .../js/apps/audit-logs/components/AuditApp.tsx | 95 ++++ .../audit-logs/components/AuditAppRenderer.tsx | 128 ++++++ .../apps/audit-logs/components/DownloadButton.tsx | 97 ++++ .../components/__tests__/AuditApp-test.tsx | 87 ++++ .../components/__tests__/AuditAppRenderer-test.tsx | 57 +++ .../components/__tests__/DownloadButton-test.tsx | 85 ++++ .../__tests__/__snapshots__/AuditApp-test.tsx.snap | 12 + .../__snapshots__/AuditAppRenderer-test.tsx.snap | 493 +++++++++++++++++++++ .../__snapshots__/DownloadButton-test.tsx.snap | 90 ++++ .../src/main/js/apps/audit-logs/routes.ts | 28 ++ .../src/main/js/apps/audit-logs/style.css | 19 + .../sonar-web/src/main/js/apps/audit-logs/utils.ts | 37 ++ 12 files changed, 1228 insertions(+) create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/components/AuditApp.tsx create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/components/AuditAppRenderer.tsx create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/components/DownloadButton.tsx create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditApp-test.tsx create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditAppRenderer-test.tsx create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/DownloadButton-test.tsx create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditApp-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditAppRenderer-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/DownloadButton-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/routes.ts create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/style.css create mode 100644 server/sonar-web/src/main/js/apps/audit-logs/utils.ts (limited to 'server/sonar-web/src/main/js/apps/audit-logs') diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/AuditApp.tsx b/server/sonar-web/src/main/js/apps/audit-logs/components/AuditApp.tsx new file mode 100644 index 00000000000..b33011d4050 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/components/AuditApp.tsx @@ -0,0 +1,95 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { connect } from 'react-redux'; +import { getAppState, getGlobalSettingValue, Store } from '../../../store/rootReducer'; +import { AdminPageExtension } from '../../../types/extension'; +import { fetchValues } from '../../settings/store/actions'; +import '../style.css'; +import { HousekeepingPolicy, RangeOption } from '../utils'; +import AuditAppRenderer from './AuditAppRenderer'; + +interface Props { + auditHousekeepingPolicy: HousekeepingPolicy; + fetchValues: typeof fetchValues; + hasGovernanceExtension?: boolean; +} + +interface State { + dateRange?: { from?: Date; to?: Date }; + downloadStarted: boolean; + selection: RangeOption; +} + +export class AuditApp extends React.PureComponent { + state: State = { + downloadStarted: false, + selection: RangeOption.Today + }; + + componentDidMount() { + const { hasGovernanceExtension } = this.props; + if (hasGovernanceExtension) { + this.props.fetchValues('sonar.dbcleaner.auditHousekeeping'); + } + } + + handleDateSelection = (dateRange: { from?: Date; to?: Date }) => + this.setState({ dateRange, downloadStarted: false, selection: RangeOption.Custom }); + + handleOptionSelection = (selection: RangeOption) => + this.setState({ dateRange: undefined, downloadStarted: false, selection }); + + handleStartDownload = () => { + setTimeout(() => { + this.setState({ downloadStarted: true }); + }, 0); + }; + + render() { + const { hasGovernanceExtension, auditHousekeepingPolicy } = this.props; + + return hasGovernanceExtension ? ( + + ) : null; + } +} + +const mapDispatchToProps = { fetchValues }; + +const mapStateToProps = (state: Store) => { + const settingValue = getGlobalSettingValue(state, 'sonar.dbcleaner.auditHousekeeping'); + const { adminPages } = getAppState(state); + const hasGovernanceExtension = Boolean( + adminPages?.find(e => e.key === AdminPageExtension.GovernanceConsole) + ); + return { + auditHousekeepingPolicy: settingValue?.value as HousekeepingPolicy, + hasGovernanceExtension + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(AuditApp); diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/AuditAppRenderer.tsx b/server/sonar-web/src/main/js/apps/audit-logs/components/AuditAppRenderer.tsx new file mode 100644 index 00000000000..7596356c453 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/components/AuditAppRenderer.tsx @@ -0,0 +1,128 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { subDays } from 'date-fns'; +import * as React from 'react'; +import { Helmet } from 'react-helmet-async'; +import { FormattedMessage } from 'react-intl'; +import { Link } from 'react-router'; +import Radio from 'sonar-ui-common/components/controls/Radio'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import Suggestions from '../../../app/components/embed-docs-modal/Suggestions'; +import DateRangeInput from '../../../components/controls/DateRangeInput'; +import '../style.css'; +import { HousekeepingPolicy, now, RangeOption } from '../utils'; +import DownloadButton from './DownloadButton'; + +export interface AuditAppRendererProps { + dateRange?: { from?: Date; to?: Date }; + downloadStarted: boolean; + handleOptionSelection: (option: RangeOption) => void; + handleDateSelection: (dateRange: { from?: Date; to?: Date }) => void; + handleStartDownload: () => void; + housekeepingPolicy: HousekeepingPolicy; + selection: RangeOption; +} + +const HOUSEKEEPING_MONTH_THRESHOLD = 30; +const HOUSEKEEPING_TRIMESTER_THRESHOLD = 90; + +const HOUSEKEEPING_POLICY_VALUES = { + [HousekeepingPolicy.Weekly]: 7, + [HousekeepingPolicy.Monthly]: 30, + [HousekeepingPolicy.Trimestrial]: 90, + [HousekeepingPolicy.Yearly]: 365 +}; + +const getRangeOptions = (housekeepingPolicy: HousekeepingPolicy) => { + const rangeOptions = [RangeOption.Today, RangeOption.Week]; + + if (HOUSEKEEPING_POLICY_VALUES[housekeepingPolicy] >= HOUSEKEEPING_MONTH_THRESHOLD) { + rangeOptions.push(RangeOption.Month); + } + + if (HOUSEKEEPING_POLICY_VALUES[housekeepingPolicy] >= HOUSEKEEPING_TRIMESTER_THRESHOLD) { + rangeOptions.push(RangeOption.Trimester); + } + + rangeOptions.push(RangeOption.Custom); + + return rangeOptions; +}; + +export default function AuditAppRenderer(props: AuditAppRendererProps) { + const { dateRange, downloadStarted, housekeepingPolicy, selection } = props; + + return ( +
+ + + +

{translate('audit_logs.page')}

+

+ {translate('audit_logs.page.description.1')} +
+ + {translate('audit_logs.page.description.link')} + + ) + }} + /> +

+ +
+

{translate('audit_logs.download')}

+ +
    + {getRangeOptions(housekeepingPolicy).map(option => ( +
  • + + {translate('audit_logs.range_option', option)} + +
  • + ))} +
+ + +
+ + +
+ ); +} diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/DownloadButton.tsx b/server/sonar-web/src/main/js/apps/audit-logs/components/DownloadButton.tsx new file mode 100644 index 00000000000..4fc60de4916 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/components/DownloadButton.tsx @@ -0,0 +1,97 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as classNames from 'classnames'; +import { endOfDay, startOfDay, subDays } from 'date-fns'; +import * as React from 'react'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import { getBaseUrl } from '../../../helpers/system'; +import '../style.css'; +import { now, RangeOption } from '../utils'; + +export interface DownloadButtonProps { + dateRange?: { from?: Date; to?: Date }; + downloadStarted: boolean; + onStartDownload: () => void; + selection: RangeOption; +} + +const RANGE_OPTION_START = { + [RangeOption.Today]: () => now(), + [RangeOption.Week]: () => subDays(now(), 7), + [RangeOption.Month]: () => subDays(now(), 30), + [RangeOption.Trimester]: () => subDays(now(), 90) +}; + +const toISODateString = (date: Date) => date.toISOString(); + +function getRangeParams(selection: RangeOption, dateRange?: { from?: Date; to?: Date }) { + if (selection === RangeOption.Custom) { + // dateRange should be complete if 'custom' is selected + if (!(dateRange?.to && dateRange?.from)) { + return ''; + } + + return new URLSearchParams({ + from: toISODateString(startOfDay(dateRange.from)), + to: toISODateString(endOfDay(dateRange.to)) + }).toString(); + } + + return new URLSearchParams({ + from: toISODateString(startOfDay(RANGE_OPTION_START[selection]())), + to: toISODateString(now()) + }).toString(); +} + +export default function DownloadButton(props: DownloadButtonProps) { + const { dateRange, downloadStarted, selection } = props; + + const downloadDisabled = + downloadStarted || + (selection === RangeOption.Custom && + (dateRange?.from === undefined || dateRange?.to === undefined)); + + const downloadUrl = downloadDisabled + ? '#' + : `${getBaseUrl()}/api/audit_logs/download?${getRangeParams(selection, dateRange)}`; + + return ( + <> + + {translate('download_verb')} + + + {downloadStarted && ( +
+

{translate('audit_logs.download_start.sentence.1')}

+

{translate('audit_logs.download_start.sentence.2')}

+
+

{translate('audit_logs.download_start.sentence.3')}

+
+ )} + + ); +} diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditApp-test.tsx b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditApp-test.tsx new file mode 100644 index 00000000000..0c8e55241cb --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditApp-test.tsx @@ -0,0 +1,87 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { subDays } from 'date-fns'; +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; +import { HousekeepingPolicy, RangeOption } from '../../utils'; +import { AuditApp } from '../AuditApp'; +import AuditAppRenderer from '../AuditAppRenderer'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +it('should do nothing if governance is not available', async () => { + const fetchValues = jest.fn(); + const wrapper = shallowRender({ fetchValues, hasGovernanceExtension: false }); + await waitAndUpdate(wrapper); + + expect(wrapper.type()).toBeNull(); + expect(fetchValues).not.toBeCalled(); +}); + +it('should fetch houskeeping policy on mount', async () => { + const fetchValues = jest.fn(); + const wrapper = shallowRender({ fetchValues }); + await waitAndUpdate(wrapper); + expect(fetchValues).toBeCalled(); +}); + +it('should handle date selection', () => { + const wrapper = shallowRender(); + const range = { from: subDays(new Date(), 2), to: new Date() }; + + expect(wrapper.state().selection).toBe(RangeOption.Today); + + wrapper + .find(AuditAppRenderer) + .props() + .handleDateSelection(range); + + expect(wrapper.state().selection).toBe(RangeOption.Custom); + expect(wrapper.state().dateRange).toBe(range); +}); + +it('should handle predefined selection', () => { + const wrapper = shallowRender(); + const dateRange = { from: subDays(new Date(), 2), to: new Date() }; + + wrapper.setState({ dateRange, selection: RangeOption.Custom }); + + wrapper + .find(AuditAppRenderer) + .props() + .handleOptionSelection(RangeOption.Week); + + expect(wrapper.state().selection).toBe(RangeOption.Week); + expect(wrapper.state().dateRange).toBeUndefined(); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditAppRenderer-test.tsx b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditAppRenderer-test.tsx new file mode 100644 index 00000000000..e8c53c0585b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/AuditAppRenderer-test.tsx @@ -0,0 +1,57 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { HousekeepingPolicy, RangeOption } from '../../utils'; +import AuditAppRenderer, { AuditAppRendererProps } from '../AuditAppRenderer'; + +jest.mock('../../utils', () => { + const { HousekeepingPolicy, RangeOption } = jest.requireActual('../../utils'); + const now = new Date('2020-07-21T12:00:00Z'); + + return { + HousekeepingPolicy, + now: jest.fn().mockReturnValue(now), + RangeOption + }; +}); + +it.each([ + [HousekeepingPolicy.Weekly], + [HousekeepingPolicy.Monthly], + [HousekeepingPolicy.Trimestrial], + [HousekeepingPolicy.Yearly] +])('should render correctly for %s housekeeping policy', housekeepingPolicy => { + expect(shallowRender({ housekeepingPolicy })).toMatchSnapshot(); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/DownloadButton-test.tsx b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/DownloadButton-test.tsx new file mode 100644 index 00000000000..1b7e4f795e6 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/DownloadButton-test.tsx @@ -0,0 +1,85 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { subDays } from 'date-fns'; +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { RangeOption } from '../../utils'; +import DownloadButton, { DownloadButtonProps } from '../DownloadButton'; + +jest.mock('date-fns', () => { + const { subDays } = jest.requireActual('date-fns'); + return { + endOfDay: jest.fn().mockImplementation(d => d), + startOfDay: jest.fn().mockImplementation(d => d), + subDays + }; +}); + +jest.mock('../../utils', () => { + const { HousekeepingPolicy, RangeOption } = jest.requireActual('../../utils'); + const now = new Date('2020-07-21T12:00:00Z'); + + return { + HousekeepingPolicy, + now: jest.fn().mockReturnValue(now), + RangeOption + }; +}); + +it.each([[RangeOption.Today], [RangeOption.Week], [RangeOption.Month], [RangeOption.Trimester]])( + 'should render correctly for %s', + selection => { + expect(shallowRender({ selection })).toMatchSnapshot('default'); + } +); + +it('should render correctly for custom range', () => { + const baseDate = new Date('2020-07-21T12:00:00Z'); + + expect(shallowRender({ selection: RangeOption.Custom })).toMatchSnapshot('no dates'); + expect( + shallowRender({ + dateRange: { from: subDays(baseDate, 2), to: baseDate }, + selection: RangeOption.Custom + }) + ).toMatchSnapshot('with dates'); +}); + +it('should handle download', () => { + const onStartDownload = jest.fn(); + const wrapper = shallowRender({ onStartDownload }); + + wrapper.find('a').simulate('click'); + wrapper.setProps({ downloadStarted: true }); + wrapper.find('a').simulate('click'); + + expect(onStartDownload).toBeCalledTimes(1); +}); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditApp-test.tsx.snap b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditApp-test.tsx.snap new file mode 100644 index 00000000000..6958c37fd2a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditApp-test.tsx.snap @@ -0,0 +1,12 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` + +`; diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditAppRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditAppRenderer-test.tsx.snap new file mode 100644 index 00000000000..015eb529785 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/AuditAppRenderer-test.tsx.snap @@ -0,0 +1,493 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly for monthly housekeeping policy 1`] = ` +
+ + +

+ audit_logs.page +

+

+ audit_logs.page.description.1 +
+ + audit_logs.page.description.link + , + } + } + /> +

+
+

+ audit_logs.download +

+
    +
  • + + audit_logs.range_option.today + +
  • +
  • + + audit_logs.range_option.7days + +
  • +
  • + + audit_logs.range_option.30days + +
  • +
  • + + audit_logs.range_option.custom + +
  • +
+ +
+ +
+`; + +exports[`should render correctly for trimestrial housekeeping policy 1`] = ` +
+ + +

+ audit_logs.page +

+

+ audit_logs.page.description.1 +
+ + audit_logs.page.description.link + , + } + } + /> +

+
+

+ audit_logs.download +

+
    +
  • + + audit_logs.range_option.today + +
  • +
  • + + audit_logs.range_option.7days + +
  • +
  • + + audit_logs.range_option.30days + +
  • +
  • + + audit_logs.range_option.90days + +
  • +
  • + + audit_logs.range_option.custom + +
  • +
+ +
+ +
+`; + +exports[`should render correctly for weekly housekeeping policy 1`] = ` +
+ + +

+ audit_logs.page +

+

+ audit_logs.page.description.1 +
+ + audit_logs.page.description.link + , + } + } + /> +

+
+

+ audit_logs.download +

+
    +
  • + + audit_logs.range_option.today + +
  • +
  • + + audit_logs.range_option.7days + +
  • +
  • + + audit_logs.range_option.custom + +
  • +
+ +
+ +
+`; + +exports[`should render correctly for yearly housekeeping policy 1`] = ` +
+ + +

+ audit_logs.page +

+

+ audit_logs.page.description.1 +
+ + audit_logs.page.description.link + , + } + } + /> +

+
+

+ audit_logs.download +

+
    +
  • + + audit_logs.range_option.today + +
  • +
  • + + audit_logs.range_option.7days + +
  • +
  • + + audit_logs.range_option.30days + +
  • +
  • + + audit_logs.range_option.90days + +
  • +
  • + + audit_logs.range_option.custom + +
  • +
+ +
+ +
+`; diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/DownloadButton-test.tsx.snap b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/DownloadButton-test.tsx.snap new file mode 100644 index 00000000000..2bd20adf4e5 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/components/__tests__/__snapshots__/DownloadButton-test.tsx.snap @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly for 7days: default 1`] = ` + + + download_verb + + +`; + +exports[`should render correctly for 30days: default 1`] = ` + + + download_verb + + +`; + +exports[`should render correctly for 90days: default 1`] = ` + + + download_verb + + +`; + +exports[`should render correctly for custom range: no dates 1`] = ` + + + download_verb + + +`; + +exports[`should render correctly for custom range: with dates 1`] = ` + + + download_verb + + +`; + +exports[`should render correctly for today: default 1`] = ` + + + download_verb + + +`; diff --git a/server/sonar-web/src/main/js/apps/audit-logs/routes.ts b/server/sonar-web/src/main/js/apps/audit-logs/routes.ts new file mode 100644 index 00000000000..ac15e95075b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/routes.ts @@ -0,0 +1,28 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { lazyLoadComponent } from 'sonar-ui-common/components/lazyLoadComponent'; + +const routes = [ + { + indexRoute: { component: lazyLoadComponent(() => import('./components/AuditApp')) } + } +]; + +export default routes; diff --git a/server/sonar-web/src/main/js/apps/audit-logs/style.css b/server/sonar-web/src/main/js/apps/audit-logs/style.css new file mode 100644 index 00000000000..deac52aa61c --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/style.css @@ -0,0 +1,19 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ diff --git a/server/sonar-web/src/main/js/apps/audit-logs/utils.ts b/server/sonar-web/src/main/js/apps/audit-logs/utils.ts new file mode 100644 index 00000000000..f77590b1a69 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/audit-logs/utils.ts @@ -0,0 +1,37 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +export enum HousekeepingPolicy { + Weekly = 'weekly', + Monthly = 'monthly', + Trimestrial = 'trimestrial', + Yearly = 'yearly' +} + +export enum RangeOption { + Today = 'today', + Week = '7days', + Month = '30days', + Trimester = '90days', + Custom = 'custom' +} + +export function now() { + return new Date(); +} -- cgit v1.2.3