Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file.

### Added

- Added search links for subject headings ([#765](https://github.com/project-lux/lux-frontend/issues/765)).

### Changed

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion client/src/features/set/About.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ const About: React.FC<IObject> = ({ data }) => {
<AboutSubsection
content={about}
label="About"
id="sets-about-link-container"
id="about-subject-headings"
/>
)}
{represents.length > 0 && (
Expand Down
2 changes: 1 addition & 1 deletion client/src/features/works/About.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ const About: React.FC<IObject> = ({ entity }) => {
<AboutSubsection
content={about}
label="About"
id="works-about-link-container"
id="about-subject-headings"
/>
)}
{represents.length > 0 && (
Expand Down
69 changes: 38 additions & 31 deletions client/src/features/works/AboutSubsection.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import React, { useState } from 'react'
import { useLocation } from 'react-router-dom'
import { Col, Row } from 'react-bootstrap'

import StyledDataRow from '../../styles/shared/DataRow'
import StyledHr from '../../styles/shared/Hr'
import ExpandableList from '../common/ExpandableList'
import TextValue from '../common/TextValue'
import TextLabel from '../common/TextLabel'
import { isObjectOrWork } from '../../lib/util/uri'
import theme from '../../styles/theme'
import useResizeableWindow from '../../lib/hooks/useResizeableWindow'
import RecordLink from '../common/RecordLink'

import SubjectHeadingsList from './SubjectHeadingsList'

interface ILinkData {
content: Array<Array<string> | string>
id: string
label?: string
expandColumns?: boolean
id?: string
}

// Show an expandable list of links with a label in the left column
const AboutSubsection: React.FC<ILinkData> = ({
content,
id,
label,
expandColumns = false,
id = 'link-container',
}) => {
const [isMobile, setIsMobile] = useState<boolean>(
window.innerWidth < theme.breakpoints.md,
Expand All @@ -32,40 +33,46 @@ const AboutSubsection: React.FC<ILinkData> = ({

useResizeableWindow(setIsMobile)

const values = content.map((c: Array<string> | string) => {
return (
<React.Fragment>
{Array.isArray(c) ? (
c.map((link, ind: number) => (
<React.Fragment key={link}>
<RecordLink url={link} /> {ind !== c.length - 1 ? ' -- ' : ''}
</React.Fragment>
))
) : (
<RecordLink url={c} />
)}
</React.Fragment>
)
})
const values = content.map((c: Array<string> | string) => (
<SubjectHeadingsList subjectHeadings={c} />
))

if (content && content.length > 0) {
return (
<StyledDataRow className="row" id={id} data-testid={id}>
{label !== undefined && (
<TextLabel label={label} className="col-md-3 col-sm-12" />
)}
<ExpandableList
className="col-md-9 col-sm-12"
length={20}
itemSpacing="double"
>
<TextValue values={values} className="col-12" itemSpacing="double" />
</ExpandableList>
<Row id={id} data-testid={`${id}-row`}>
<Col xl={3} lg={3} md={12} sm={12}>
{label !== undefined && <TextLabel label={label} />}
</Col>
<Col xl={9} lg={9} md={12} sm={12}>
<Row>
{!isMobile && (
<React.Fragment>
<Col xs={7}>
<dt>Subjects</dt>
</Col>
<Col xs={5}>
<dt>Matching Works</dt>
</Col>
</React.Fragment>
)}
<ExpandableList
className="col-sm-12"
length={20}
itemSpacing="double"
>
<TextValue
values={values}
className="col-12"
itemSpacing="double"
/>
</ExpandableList>
</Row>
</Col>
<StyledHr
className="linkContainerHr"
hidden={expandColumns || (isObjectOrWork(pathname) && isMobile)}
/>
</StyledDataRow>
</Row>
)
}

Expand Down
70 changes: 70 additions & 0 deletions client/src/features/works/SubjectHeadingsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { useState } from 'react'
import { Col, Row } from 'react-bootstrap'

import RecordLink from '../common/RecordLink'
import { getSubjectHeadingObject } from '../../lib/parse/data/helper'
import config from '../../config/config'
import { useGetSearchRelationshipQuery } from '../../redux/api/ml_api'
import SearchResultsLink from '../relatedLists/SearchResultsLink'
import theme from '../../styles/theme'
import useResizeableWindow from '../../lib/hooks/useResizeableWindow'

interface ILinkData {
subjectHeadings: Array<string> | string
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const formatSubjectHeadingHalLink = (params: Record<string, any>): string => {
const urlParams = new URLSearchParams()
urlParams.set('q', JSON.stringify(params))
return `${config.env.dataApiBaseUrl}api/search/work?${urlParams.toString()}`
}

// Show an expandable list of links with a label in the left column
const SubjectHeadingsList: React.FC<ILinkData> = ({ subjectHeadings }) => {
const [isMobile, setIsMobile] = useState<boolean>(
window.innerWidth < theme.breakpoints.md,
)
useResizeableWindow(setIsMobile)

const subjectHeadingsSearchCriteriaObjects = Array.isArray(subjectHeadings)
? subjectHeadings.map((link) => getSubjectHeadingObject(link))
: [getSubjectHeadingObject(subjectHeadings)]
const subjectHeadingsSearchCriteria = {
AND: subjectHeadingsSearchCriteriaObjects,
}
const halLink = formatSubjectHeadingHalLink(subjectHeadingsSearchCriteria)
const { isSuccess, data } = useGetSearchRelationshipQuery({
uri: halLink,
})

return (
<Row className="data-row">
<Col xl={7} lg={7} md={7} sm={12} xs={12}>
{Array.isArray(subjectHeadings) ? (
subjectHeadings.map((link, ind: number) => (
<React.Fragment key={link}>
<RecordLink url={link} />{' '}
{ind !== subjectHeadings.length - 1 ? ' -- ' : ''}
</React.Fragment>
))
) : (
<RecordLink url={subjectHeadings} />
)}
</Col>
<Col xl={5} lg={5} md={5} sm={12} xs={12}>
{isSuccess && data && (
<SearchResultsLink
data={data}
eventTitle="Subject Headings Search Link"
url={halLink}
scope="works"
additionalLinkText={isMobile ? 'work' : ''}
/>
)}
</Col>
</Row>
)
}

export default SubjectHeadingsList
6 changes: 3 additions & 3 deletions client/src/lib/parse/data/EntityParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -763,13 +763,13 @@ export default class EntityParser {

const aboutData = about
.map((obj) => {
const ids: Array<string> = []
const ids: Array<string | undefined> = []
if (obj.hasOwnProperty('created_by')) {
obj.created_by.influenced_by.map((influencedBy: IEntity) => {
ids.push(influencedBy.id!)
ids.push(influencedBy.id)
})
}
return ids
return ids.filter((id) => id !== undefined)
})
.filter((arr) => arr.length !== 0)

Expand Down
36 changes: 36 additions & 0 deletions client/src/lib/parse/data/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,42 @@ export const getLabelBasedOnEntityType = (path: string): string => {
return 'Name'
}

/**
* Returns the tab of the record based on its uri
* @param {string} uri the uri used to determine the tab
* @returns {string}
*/
export const getSubjectHeadingObject = (uri: string): Record<string, any> => {
let searchTerm = ''
if (uri.includes('object') || uri.includes('digital')) {
searchTerm = 'aboutItem'
}
if (uri.includes('text') || uri.includes('visual')) {
searchTerm = 'aboutWork'
}
if (uri.includes('person') || uri.includes('group')) {
searchTerm = 'aboutAgent'
}
if (uri.includes('place')) {
searchTerm = 'aboutPlace'
}
if (uri.includes('concept')) {
searchTerm = 'aboutConcept'
}
if (uri.includes('activity') || uri.includes('period')) {
searchTerm = 'aboutEvent'
}

return {
[searchTerm]: {
id: uri.replace(
`${config.env.dataApiBaseUrl}`,
'https://lux.collections.yale.edu/',
),
},
}
}

/**
* Returns name to be displayed as the primary name
* This requires parsing all nested objects in /identified_by where the /type='Name'
Expand Down