-
Notifications
You must be signed in to change notification settings - Fork 144
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ui): freight history in stage details (#2730)
Signed-off-by: Mayursinh Sarvaiya <[email protected]>
- Loading branch information
Showing
7 changed files
with
270 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import { useQuery } from '@connectrpc/connect-query'; | ||
import { faHistory } from '@fortawesome/free-solid-svg-icons'; | ||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | ||
import { Empty } from 'antd'; | ||
import classNames from 'classnames'; | ||
import { useMemo } from 'react'; | ||
import { generatePath, Link, useNavigate } from 'react-router-dom'; | ||
|
||
import { paths } from '@ui/config/paths'; | ||
import freightTimelineStyles from '@ui/features/freight-timeline/freight-timeline.module.less'; | ||
import { queryFreight } from '@ui/gen/service/v1alpha1/service-KargoService_connectquery'; | ||
import { | ||
Freight, | ||
FreightReference, | ||
FreightRequest, | ||
StageStatus | ||
} from '@ui/gen/v1alpha1/generated_pb'; | ||
|
||
import { LoadingState } from '../common'; | ||
import { FreightContents } from '../freight-timeline/freight-contents'; | ||
import { FreightItemLabel } from '../freight-timeline/freight-item-label'; | ||
import { FreightTimelineWrapper } from '../freight-timeline/freight-timeline-wrapper'; | ||
|
||
import requestedFreightStyles from './requested-freight.module.less'; | ||
|
||
export const FreightHistory = ({ | ||
projectName, | ||
freightHistory, | ||
requestedFreights, | ||
className | ||
}: { | ||
className?: string; | ||
requestedFreights: FreightRequest[]; | ||
projectName: string; | ||
// show the freight history thats 1:1 with requested freight | ||
freightHistory?: StageStatus['freightHistory']; | ||
// freight hash name which is active at the moment | ||
// you can get this from lastPromotion in stage status | ||
// usually last one is active but we have to consider multi-pipeline case | ||
currentActiveFreight?: string; | ||
}) => { | ||
const navigate = useNavigate(); | ||
|
||
const freightQuery = useQuery(queryFreight, { project: projectName }); | ||
|
||
const freightMap = useMemo(() => { | ||
const freightData = freightQuery.data; | ||
// generate metadata.name -> full freight data (because history doesn't have it all) to show in freight history | ||
const freightMap: Record<string, Freight> = {}; | ||
|
||
for (const freight of freightData?.groups?.['']?.freight || []) { | ||
const freightId = freight?.metadata?.name; | ||
if (freightId) { | ||
freightMap[freightId] = freight; | ||
} | ||
} | ||
|
||
return freightMap; | ||
}, [freightQuery.data]); | ||
|
||
const freightHistoryPerWarehouse = useMemo(() => { | ||
// to show the history | ||
const freightHistoryPerWarehouse: Record< | ||
string /* warehouse eg. Warehouse/w-1 or Warehouse/w-2 */, | ||
FreightReference[] | ||
> = {}; | ||
|
||
for (const freightCollection of freightHistory || []) { | ||
// key - value | ||
// warehouse identifier - freight reference | ||
const items = freightCollection?.items || {}; | ||
|
||
for (const [warehouseIdentifier, freightReference] of Object.entries(items)) { | ||
if (!freightHistoryPerWarehouse[warehouseIdentifier]) { | ||
freightHistoryPerWarehouse[warehouseIdentifier] = []; | ||
} | ||
|
||
freightHistoryPerWarehouse[warehouseIdentifier].push(freightReference); | ||
} | ||
} | ||
|
||
return freightHistoryPerWarehouse; | ||
}, [freightHistory]); | ||
|
||
if (freightQuery.isFetching) { | ||
return <LoadingState />; | ||
} | ||
|
||
return ( | ||
<div className={className}> | ||
<h3> | ||
<FontAwesomeIcon icon={faHistory} className='mr-2' /> | ||
Freight History | ||
</h3> | ||
|
||
{requestedFreights?.map((freight, i) => { | ||
const freightUniqueIdentifier = `${freight.origin?.kind}/${freight.origin?.name}`; | ||
|
||
const freightReferences = freightHistoryPerWarehouse[freightUniqueIdentifier] || []; | ||
|
||
return ( | ||
<> | ||
<Link | ||
className='block' | ||
style={{ marginBottom: '16px', marginTop: '32px' }} | ||
to={generatePath(paths.warehouse, { | ||
name: projectName, | ||
warehouseName: freight?.origin?.name | ||
})} | ||
> | ||
{freightUniqueIdentifier} | ||
</Link> | ||
<div key={i} className='py-5 bg-gray-50'> | ||
<div className='flex gap-8'> | ||
{freightReferences.length === 0 && ( | ||
<Empty | ||
description={`No freight history of ${freightUniqueIdentifier}`} | ||
className='mx-auto' | ||
/> | ||
)} | ||
{freightReferences.length > 0 && ( | ||
<FreightTimelineWrapper containerClassName='py-0'> | ||
<div className='flex gap-2 w-full h-full'> | ||
{freightReferences.map((freightReference, idx) => ( | ||
<div | ||
key={freightReference.name} | ||
className={classNames( | ||
freightTimelineStyles.freightItem, | ||
'cursor-pointer', | ||
idx === 0 && requestedFreightStyles['active-freight-item'] | ||
)} | ||
onClick={() => | ||
navigate( | ||
generatePath(paths.freight, { | ||
name: projectName, | ||
freightName: freightReference.name | ||
}) | ||
) | ||
} | ||
> | ||
<FreightContents highlighted={false} freight={freightReference} /> | ||
<div className='text-xs mt-auto'> | ||
<FreightItemLabel | ||
freight={ | ||
{ | ||
...freightReference, | ||
metadata: { | ||
name: freightReference?.name | ||
}, | ||
alias: | ||
freightMap[freightReference?.name || '']?.alias || | ||
freightReference.name | ||
} as Freight | ||
} | ||
/> | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
</FreightTimelineWrapper> | ||
)} | ||
</div> | ||
</div> | ||
</> | ||
); | ||
})} | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.active-freight-item { | ||
border: 2px solid #66b2ff; | ||
box-shadow: 0 4px 12px rgba(0, 123, 255, 0.2), 0 2px 4px rgba(0, 0, 0, 0.1); | ||
|
||
&:hover { | ||
border: 2px solid #66b2ff !important; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.