frontend/src/js/components/ResourceBreadcrumbs/ResourceTrail.tsx (78 lines of code) (raw):

import React from 'react'; import PropTypes from 'prop-types'; import {Link} from 'react-router-dom'; import zip from 'lodash/zip'; import { BasicResource, basicResourcePropType } from '../../types/Resource'; type ResourceComponentProps = { resource: BasicResource, className: string, lastSegmentOnly: boolean } export const ResourceTrail = (props: ResourceComponentProps) => { switch(props.resource.type) { case('file'): case('directory'): case('ingestion'): case('collection'): case('blob'): case('email'): return <PathBasedResource className={props.className} resource={props.resource} lastSegmentOnly={props.lastSegmentOnly} />; default: return <div>Unknown Resource Type</div>; } }; // I've retained the proptypes to ensure checking with usages that have not been converted to Typescript yet ResourceTrail.propTypes = { resource: basicResourcePropType, className: PropTypes.string, lastSegmentOnly: PropTypes.bool }; type PathBasedResourceProps = { className: string, resource: BasicResource, lastSegmentOnly: boolean }; type PathSegment = { uri: string, display: string }; export function buildSegments(resource: BasicResource): PathSegment[] { const uriParts = resource.uri.split("/"); const displayParts = resource.display ? resource.display.split("/") : []; // Ingestions do not have a full display name for backwards compatibility reasons const parts = uriParts.length === displayParts.length ? zip(uriParts, displayParts) : zip(uriParts, uriParts.map(decodeURIComponent)); let acc = ""; const ret = []; for(const [uri, display] of parts) { acc += (acc.length === 0 ? uri : `/${uri}`); ret.push({ uri: acc, display: display || uri! }) } return ret; } function shrinkDisplay(display: string): string { if(display.length > 15) { return display.substring(0, 15) + '...'; } return display; } function PathBasedResource({ className, resource, lastSegmentOnly }: PathBasedResourceProps) { const allSegments = buildSegments(resource); const segments = lastSegmentOnly ? [allSegments[allSegments.length - 1]] : allSegments; return ( <div className={className}> <div className='resource-browser__path'> { segments.map(({ uri, display }, i) => { const isLastSegment = i === (segments.length - 1); return (<Link key={uri} className='resource-browser__resource' to={`/resources/${encodeURI(uri)}`}> { isLastSegment ? display : shrinkDisplay(display) } </Link>); }) } </div> </div> ); }