diff --git a/.changeset/silver-wolves-breathe.md b/.changeset/silver-wolves-breathe.md new file mode 100644 index 0000000000..8c1529e142 --- /dev/null +++ b/.changeset/silver-wolves-breathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-sentry': minor +--- + +Add option to filter issues based on the time it was triggered diff --git a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx index 647208f141..5bf6b1e92b 100644 --- a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx +++ b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx @@ -19,6 +19,7 @@ import SentryIssuesTable from './SentryIssuesTable'; import { SentryIssue } from '../../api'; import mockIssue from '../../api/mock/sentry-issue-mock.json'; import { renderInTestApp } from '@backstage/test-utils'; +import { DateTime } from 'luxon'; describe('SentryIssuesTable', () => { it('should render headers in a table', async () => { @@ -62,6 +63,7 @@ describe('SentryIssuesTable', () => { }, count: '101', userCount: 202, + lastSeen: DateTime.now().toISO(), }, ]; const table = await renderInTestApp( @@ -105,6 +107,6 @@ describe('SentryIssuesTable', () => { }} />, ); - expect(await table.findByText('Last 24h')).toBeInTheDocument(); + expect(await table.findByText('Stats for 24h')).toBeInTheDocument(); }); }); diff --git a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx index abe29efd7f..60ee6b7dbf 100644 --- a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx +++ b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx @@ -14,13 +14,19 @@ * limitations under the License. */ -import React from 'react'; +import React, { useCallback, useState } from 'react'; import { SentryIssue } from '../../api'; -import { DateTime } from 'luxon'; +import { DateTime, Duration } from 'luxon'; import { ErrorCell } from '../ErrorCell/ErrorCell'; import { ErrorGraph } from '../ErrorGraph/ErrorGraph'; import { Table, TableColumn } from '@backstage/core-components'; +import Select from '@material-ui/core/Select'; import { Options } from '@material-table/core'; +import { FormControl, Grid, MenuItem } from '@material-ui/core'; + +const ONE_DAY_IN_MILLIS = 86400000; +const SEVEN_DAYS_IN_MILLIS = ONE_DAY_IN_MILLIS * 7; +const FOURTEEN_DAYS_IN_MILLIS = ONE_DAY_IN_MILLIS * 14; const columns: TableColumn[] = [ { @@ -66,14 +72,55 @@ type SentryIssuesTableProps = { const SentryIssuesTable = (props: SentryIssuesTableProps) => { const { sentryIssues, statsFor, tableOptions } = props; + const [selected, setSelected] = useState(ONE_DAY_IN_MILLIS); + + const filterByDate = useCallback((issue, selectedFilter) => { + return ( + DateTime.fromISO(issue.lastSeen) > + DateTime.now().minus(Duration.fromMillis(selectedFilter)) + ); + }, []); + const [filteredIssues, setFilteredIssues] = useState( + sentryIssues.filter(i => filterByDate(i, selected)), + ); + + const handleFilterChange = ( + event: React.ChangeEvent<{ name?: string; value: unknown }>, + ) => { + const item = event.target.value; + if (typeof item === 'number') { + setSelected(item); + if (item === Number.NEGATIVE_INFINITY) { + setFilteredIssues(sentryIssues); + return; + } + setFilteredIssues(sentryIssues.filter(i => filterByDate(i, item))); + } + }; return ( - + <> +
+ Sentry Issues + + + + + + + } + subtitle={statsFor ? `Stats for ${statsFor}` : undefined} + data={filteredIssues} + /> + ); };