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
35 changes: 25 additions & 10 deletions app/frontend/src/components/Relation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { formatStructuredName } from '../utilities'
import { updateRel } from '../store/relations/actions'
import { SnameTooltip } from './SnameTooltip'

export const Relation = ({ relation }) => {
const dispatch = useDispatch()
const [formattedName1, formattedName2] = useSelector(state => {
return [
formatStructuredName(state.map[relation.name1], state),
formatStructuredName(state.map[relation.name2], state),
]
})
const [formattedName1, formattedName2, sname1, sname2] = useSelector(
state => {
return [
formatStructuredName(state.map[relation.name1], state),
formatStructuredName(state.map[relation.name2], state),
state.map[relation.name1],
state.map[relation.name1],
]
}
)

const swap = () => {
dispatch(
Expand All @@ -33,8 +38,13 @@ export const Relation = ({ relation }) => {

return (
<div className='w3-row v-center'>
<div className='w3-col s5 w3-center hide-overflow'>
<p>{formattedName1}</p>
<div className='w3-col s5'>
<div className='tooltip'>
<SnameTooltip sname={sname1} />
<div className='w3-center hide-overflow'>
<p>{formattedName1}</p>
</div>
</div>
</div>
<div className='w3-col s1 w3-center'>
<button className='w3-button' onClick={swap}>
Expand All @@ -49,8 +59,13 @@ export const Relation = ({ relation }) => {
checked={relation.belongs_to}
/>
</div>
<div className='w3-col s5 w3-center hide-overflow'>
<p>{formattedName2}</p>
<div className='w3-col s5'>
<div className='tooltip'>
<SnameTooltip sname={sname2} />
<div className='w3-center hide-overflow'>
<p>{formattedName2}</p>
</div>
</div>
</div>
</div>
)
Expand Down
62 changes: 36 additions & 26 deletions app/frontend/src/components/RelationSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { makeId, formatStructuredName } from '../utilities'
import { addRel, deleteRel } from '../store/relations/actions'
import { BelongsToSelector } from './BelongsToSelector'
import { Relation } from './Relation'
import { SnameTooltip } from './SnameTooltip'

export const RelationSelector = () => {
const dispatch = useDispatch()
Expand All @@ -12,6 +13,7 @@ export const RelationSelector = () => {
.map(v => {
return {
id: v,
structuredName: state.map[v],
formattedName: formatStructuredName(state.map[v], state),
}
})
Expand Down Expand Up @@ -71,14 +73,16 @@ export const RelationSelector = () => {
data-testid='relselector-left-test-id'
>
{structuredNames.map(v => (
<div
key={v.id}
className={`w3-button w3-bar hide-overflow ${
v.id === primaryName ? 'w3-grey' : ''
}`}
onClick={() => setPrimaryName(v.id)}
>
{v.formattedName}
<div key={v.id} className='tooltip'>
<SnameTooltip sname={v.structuredName} />
<div
className={`w3-button w3-bar hide-overflow ${
v.id === primaryName ? 'w3-grey' : ''
}`}
onClick={() => setPrimaryName(v.id)}
>
{v.formattedName}
</div>
</div>
))}
</div>
Expand All @@ -89,24 +93,30 @@ export const RelationSelector = () => {
{structuredNames
.filter(v => v.id !== primaryName)
.map(v => (
<div className='w3-bar hide-overflow' key={v.id}>
<BelongsToSelector
idA={primaryName}
idB={v.id}
relation={relationExists(primaryName, v.id)}
/>
<div
className={`w3-button w3-bar hide-overflow ${
relationExists(primaryName, v.id)
? 'w3-grey'
: ''
}`}
style={{ width: '70%' }}
onClick={() =>
toggleRelation(primaryName, v.id)
}
>
{v.formattedName}
<div key={v.id} className='tooltip'>
<SnameTooltip sname={v.structuredName} />
<div className='w3-bar hide-overflow'>
<BelongsToSelector
idA={primaryName}
idB={v.id}
relation={relationExists(
primaryName,
v.id
)}
/>
<div
className={`w3-button w3-bar hide-overflow ${
relationExists(primaryName, v.id)
? 'w3-grey'
: ''
}`}
style={{ width: '70%' }}
onClick={() =>
toggleRelation(primaryName, v.id)
}
>
{v.formattedName}
</div>
</div>
</div>
))}
Expand Down
5 changes: 4 additions & 1 deletion app/frontend/src/components/SelectedStructuredNames.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from '../store/selected_structured_names/actions'
import { loadServerData } from '../services/server'
import { formatStructuredName, parseId } from '../utilities'
import {SnameTooltip} from './SnameTooltip'

export const SelectedStructuredNames = () => {
const [selection, dbNames] = useSelector(state => {
Expand All @@ -23,6 +24,7 @@ export const SelectedStructuredNames = () => {
.map(v => {
return {
id: v,
structuredName: state.map[v],
formattedName: formatName(state.map[v]),
}
}),
Expand Down Expand Up @@ -74,7 +76,8 @@ export const SelectedStructuredNames = () => {
))}
</datalist>
{selection.map(v => (
<div key={v.id}>
<div key={v.id} className='tooltip'>
<SnameTooltip sname={v.structuredName} />
<p>
{v.formattedName}
<button
Expand Down
24 changes: 14 additions & 10 deletions app/frontend/src/components/Sname.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { deleteName } from '../store/names/actions'
import { deselectStructuredName } from '../store/selected_structured_names/actions'
import { formatStructuredName, parseId } from '../utilities'
import { SnameTooltip } from './SnameTooltip'

const CAN_DELETE_ERROR_MSG =
'Added relation is dependent on this structured name. Please remove the relation associated with this structured name first.'
Expand Down Expand Up @@ -88,16 +89,19 @@ export const Sname = ({

return (
<div className='w3-container'>
<p>
{formatStructuredName(sname, { map })}
<button
className='w3-button w3-grey w3-circle w3-margin-left'
type='button'
onClick={deleteSnameHandler}
>
<i title='Delete' className='fa fa-trash'></i>
</button>
</p>
<div className='tooltip'>
<SnameTooltip sname={sname} />
<p>
{formatStructuredName(sname, { map })}
<button
className='w3-button w3-grey w3-circle w3-margin-left'
type='button'
onClick={deleteSnameHandler}
>
<i title='Delete' className='fa fa-trash'></i>
</button>
</p>
</div>
</div>
)
}
53 changes: 53 additions & 0 deletions app/frontend/src/components/SnameTooltip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react'
import { useSelector } from 'react-redux'

export const SnameTooltip = ({ sname }) => {
console.log(sname)
const qualifierName = {
1: 'Chronostratigraphy',
2: 'Lithostratigraphy',
3: 'Regional Standard',
4: 'Chemostratigraphy',
5: 'Biostratigraphy',
6: 'Sequence-stratigraphy',
}

const data = useSelector(state => {
return {
...sname,
reference: state.map[sname.reference_id],
name: state.map[sname.name_id],
qualifier: state.map[sname.qualifier_id],
qualifierName:
state.map[state.map[sname.qualifier_id].qualifier_name_id],
location: state.map[sname.location_id],
}
})

const remarks = data.remarks ? <p>Remarks: {data.remarks}</p> : <></>
const reference = data.reference ? (
<p>{`${data.reference.title} (${data.reference.year})`}</p>
) : (
<></>
)

if (!data.name || !data.location || !data.qualifierName)
return <></>

return (
<div className='tooltip-wrapper'>
<div className='w3-card w3-white w3-container w3-padding-16 tooltip-content'>
<p>{data.name.name}</p>
<p>{data.location.name}</p>
<p>{data.qualifierName.name}</p>
<p>
{`${
qualifierName[data.qualifier.stratigraphic_qualifier_id]
} level ${1}`}
</p>
{remarks}
{reference}
</div>
</div>
)
}
2 changes: 0 additions & 2 deletions app/frontend/src/components/Submit.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ export const Submit = () => {
),
}

console.log(submit_data)

const csrfmiddlewaretoken = document.querySelector(
'[name=csrfmiddlewaretoken]'
).value
Expand Down
12 changes: 8 additions & 4 deletions app/frontend/src/components/__tests__/RelationSelector.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ describe('When some structured names have been selected, but no relations formed

expect(relationSelectorOnTheLeft.childNodes).toHaveLength(3)
relationSelectorOnTheLeft.childNodes.forEach(childNode => {
expect(options).toContain(childNode.innerHTML)
expect(options).toContain(childNode.childNodes[1].innerHTML)
})
})

Expand All @@ -198,7 +198,9 @@ describe('When some structured names have been selected, but no relations formed
const options = [dbSname1Formatted, dbSname2Formatted]
expect(relationSelectorOnTheRight.childNodes).toHaveLength(2)
relationSelectorOnTheRight.childNodes.forEach(childNode => {
expect(options).toContain(childNode.childNodes[3].innerHTML)
expect(options).toContain(
childNode.childNodes[1].childNodes[3].innerHTML
)
})
})

Expand Down Expand Up @@ -313,7 +315,8 @@ describe('When some structured names have been selected, but no relations formed
const relationSelectorOnTheRight = screen.getByTestId(
relationSelectorSidesTestIds.right
)
const firstOption = relationSelectorOnTheRight.childNodes[0].lastChild
const firstOption =
relationSelectorOnTheRight.childNodes[0].childNodes[1].childNodes[3]
const firstOptionsFormattedName = firstOption.innerHTML
userEvent.click(firstOption)
const relationsList = screen.getByTestId('active-relations-list')
Expand All @@ -324,7 +327,8 @@ describe('When some structured names have been selected, but no relations formed
const relationSelectorOnTheRight = screen.getByTestId(
relationSelectorSidesTestIds.right
)
const firstOption = relationSelectorOnTheRight.childNodes[0].lastChild
const firstOption =
relationSelectorOnTheRight.childNodes[0].childNodes[1].childNodes[3]
userEvent.click(firstOption)
const checkbox = await screen.findByRole('checkbox')
expect(checkbox).not.toBeChecked()
Expand Down
8 changes: 2 additions & 6 deletions app/frontend/src/components/__tests__/Sname.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,8 @@ describe('Sname', () => {
})

test('shows structured name information', () => {
const name = screen.getByText(/1a/)
const qualifier = screen.getByText(/Bio_Ammonite/)
const location = screen.getByText(/Alabama/)
expect(name).toBeInTheDocument()
expect(qualifier).toBeInTheDocument()
expect(location).toBeInTheDocument()
const sname = screen.getByText('1a / Bio_Ammonite / Alabama')
expect(sname).toBeInTheDocument()
})

test('shows "delete" button', () => {
Expand Down
27 changes: 26 additions & 1 deletion app/frontend/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,29 @@

.check-notop {
top: 0 !important;
}
}

.tooltip-wrapper {
position: relative;
opacity: 0;
}

.tooltip-content {
display: none;
position: absolute;
max-width: 400px;
max-height: 200px;
overflow-y: auto;
transform: translateY(-100%);
}

.tooltip:hover > .tooltip-wrapper > .tooltip-content {
display: inline-block;
}

.tooltip:hover > .tooltip-wrapper {
width: auto;
height: auto;
opacity: 1;
transition: opacity 0.1s linear 1.6s;
}