Skip to content

Commit

Permalink
feat: Group versions by date (#4246)
Browse files Browse the repository at this point in the history
  • Loading branch information
kyle-ssg authored Jul 1, 2024
1 parent c6089c7 commit 540d320
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 28 deletions.
98 changes: 98 additions & 0 deletions frontend/web/components/DateList.tsx
Original file line number Diff line number Diff line change
@@ -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<T> = {
items: PagedResponse<T> | 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 = <T extends { [key: string]: any }>({
dateFormat = 'YYYY-MM-DD',
dateProperty = 'created_at' as keyof T,
goToPage,
isLoading,
items,
nextPage,
prevPage,
renderRow,
}: DateListType<T>) => {
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) => (
<div key={date}>
<div
className={classNames('d-flex gap-2', {
'align-items-center': !!items?.previous || index > 0,
})}
>
<div className='ps-8 d-flex flex-column gap-1 align-items-center'>
{(!!items?.previous || index > 0) && (
<div style={{ height: 15, width: 1 }} className='border-1' />
)}
<Icon name='clock' fill='#9DA4AE' />
<div style={{ height: 15, width: 1 }} className='border-1' />
</div>
<div className='text-muted py-1 fs-caption'>{formatDate(date)}</div>
</div>

<div className='border-1 rounded'>
{dateItems.map((item, i) => {
const isLastItem = i + 1 === dateItems.length
const inner = renderRow(item, itemIndex)
itemIndex++
return (
<div key={itemIndex}>
{inner}
{!isLastItem && <hr className='my-0' />}
</div>
)
})}
</div>
</div>
))}
{!!items && (
<Paging
paging={items}
isLoading={isLoading}
nextPage={nextPage}
prevPage={prevPage}
goToPage={goToPage}
/>
)}
</>
)
}

export default DateList
50 changes: 23 additions & 27 deletions frontend/web/components/pages/FeatureHistoryPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -46,7 +47,7 @@ const FeatureHistoryPage: FC<FeatureHistoryPageType> = ({ match, router }) => {
organisationId: AccountStore.getOrganisation().id,
})
const [page, setPage] = useState(1)
const { data } = useGetFeatureVersionsQuery(
const { data, isLoading } = useGetFeatureVersionsQuery(
{
environmentId,
featureId: feature,
Expand Down Expand Up @@ -87,40 +88,35 @@ const FeatureHistoryPage: FC<FeatureHistoryPageType> = ({ match, router }) => {
</div>
</div>
</div>
<div>
<PanelSearch
className='no-pad overflow-visible'
items={data?.results}
<div className='mt-4'>
<DateList<TFeatureVersion>
items={data}
isLoading={isLoading}
nextPage={() => setPage(page + 1)}
prevPage={() => setPage(page + 1)}
goToPage={setPage}
header={
<Row className='table-header'>
<div className='table-column' style={{ width: widths[0] }}>
Date
</div>
<div className='table-column text-left flex-fill'>User</div>
<div className='table-column' style={{ width: widths[1] }}>
View
</div>
<div className='table-column' style={{ width: widths[1] }}>
Compare
</div>
</Row>
}
renderRow={(v: TFeatureVersion, i: number) => {
const user = users?.find((user) => v.published_by === user.id)

return (
<Row className='list-item py-2 mh-auto'>
<div className='flex-fill'>
<div className='flex-row flex-fill'>
<div className='table-column' style={{ width: widths[0] }}>
{moment(v.live_from).format('Do MMM HH:mma')}
{!i && <span className='chip ms-2'>Live</span>}
</div>
<div className='table-column text-left flex-fill'>
{user
? `${user.first_name || ''} ${user.last_name || ''} `
: 'System '}
<div
className='table-column flex-fill'
style={{ width: widths[0] }}
>
<div className='font-weight-medium d-flex gap-2 align-items-center mb-1'>
{moment(v.live_from).format('HH:mma')}
<div className='text-muted fw-normal text-small'>
{user
? `${user.first_name || ''} ${
user.last_name || ''
} `
: 'System '}
</div>
{!i && <span className='chip chip--xs px-2'>Live</span>}
</div>
</div>
<div className='table-column' style={{ width: widths[1] }}>
<Link
Expand Down
4 changes: 3 additions & 1 deletion frontend/web/styles/project/_project-nav.scss
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ nav a {
}
}
}

.border-1 {
border: 1px solid $hr-border-color;
}
.border-right {
border-right: 1px solid $hr-border-color;
}
Expand Down

0 comments on commit 540d320

Please sign in to comment.