From 540d320d4fafa686f8d61aed734bafb1c4e82f20 Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Mon, 1 Jul 2024 10:09:58 +0100 Subject: [PATCH] feat: Group versions by date (#4246) --- frontend/web/components/DateList.tsx | 98 +++++++++++++++++++ .../components/pages/FeatureHistoryPage.tsx | 50 +++++----- frontend/web/styles/project/_project-nav.scss | 4 +- 3 files changed, 124 insertions(+), 28 deletions(-) create mode 100644 frontend/web/components/DateList.tsx diff --git a/frontend/web/components/DateList.tsx b/frontend/web/components/DateList.tsx new file mode 100644 index 000000000000..03b27ae4f792 --- /dev/null +++ b/frontend/web/components/DateList.tsx @@ -0,0 +1,98 @@ +import React, { FC, useMemo } from 'react' +import moment from 'moment' +import { PagedResponse } from 'common/types/responses' +import _ from 'lodash' +import Icon from './Icon' +import Paging from './Paging' +import classNames from 'classnames' + +type DateListType = { + items: PagedResponse | undefined + dateProperty?: keyof T + renderRow: (item: T, i: number) => JSX.Element + dateFormat?: string + isLoading: boolean + nextPage: () => void + prevPage: () => void + goToPage: (page: number) => void +} + +function formatDate(date: string) { + const today = moment().startOf('day') + const yesterday = moment().subtract(1, 'days').startOf('day') + + if (moment(date).isSame(today, 'd')) { + return 'Today' + } else if (moment(date).isSame(yesterday, 'd')) { + return 'Yesterday' + } else { + return moment(date).format('MMM Do, YYYY') + } +} + +const DateList = ({ + dateFormat = 'YYYY-MM-DD', + dateProperty = 'created_at' as keyof T, + goToPage, + isLoading, + items, + nextPage, + prevPage, + renderRow, +}: DateListType) => { + const groupedData = useMemo(() => { + return _.groupBy(items?.results || [], (item) => + moment(item[dateProperty] as unknown as string).format(dateFormat), + ) + }, [items, dateFormat, dateProperty]) + + const groupedItems = Object.entries(groupedData) + let itemIndex = 0 + return ( + <> + {groupedItems.map(([date, dateItems], index) => ( +
+
0, + })} + > +
+ {(!!items?.previous || index > 0) && ( +
+ )} + +
+
+
{formatDate(date)}
+
+ +
+ {dateItems.map((item, i) => { + const isLastItem = i + 1 === dateItems.length + const inner = renderRow(item, itemIndex) + itemIndex++ + return ( +
+ {inner} + {!isLastItem &&
} +
+ ) + })} +
+
+ ))} + {!!items && ( + + )} + + ) +} + +export default DateList diff --git a/frontend/web/components/pages/FeatureHistoryPage.tsx b/frontend/web/components/pages/FeatureHistoryPage.tsx index dc7fffcc525f..751667bc37d3 100644 --- a/frontend/web/components/pages/FeatureHistoryPage.tsx +++ b/frontend/web/components/pages/FeatureHistoryPage.tsx @@ -19,6 +19,7 @@ import InlineModal from 'components/InlineModal' import TableFilterItem from 'components/tables/TableFilterItem' import moment from 'moment' import { Link } from 'react-router-dom' +import DateList from 'components/DateList' const widths = [250, 150] type FeatureHistoryPageType = { @@ -46,7 +47,7 @@ const FeatureHistoryPage: FC = ({ match, router }) => { organisationId: AccountStore.getOrganisation().id, }) const [page, setPage] = useState(1) - const { data } = useGetFeatureVersionsQuery( + const { data, isLoading } = useGetFeatureVersionsQuery( { environmentId, featureId: feature, @@ -87,25 +88,13 @@ const FeatureHistoryPage: FC = ({ match, router }) => {
-
- + + items={data} + isLoading={isLoading} + nextPage={() => setPage(page + 1)} + prevPage={() => setPage(page + 1)} goToPage={setPage} - header={ - -
- Date -
-
User
-
- View -
-
- Compare -
-
- } renderRow={(v: TFeatureVersion, i: number) => { const user = users?.find((user) => v.published_by === user.id) @@ -113,14 +102,21 @@ const FeatureHistoryPage: FC = ({ match, router }) => {
-
- {moment(v.live_from).format('Do MMM HH:mma')} - {!i && Live} -
-
- {user - ? `${user.first_name || ''} ${user.last_name || ''} ` - : 'System '} +
+
+ {moment(v.live_from).format('HH:mma')} +
+ {user + ? `${user.first_name || ''} ${ + user.last_name || '' + } ` + : 'System '} +
+ {!i && Live} +