diff --git a/src/app/src/components/FacilityDetailSidebarContributors.jsx b/src/app/src/components/FacilityDetailSidebarContributors.jsx index 67fb35408..486813738 100644 --- a/src/app/src/components/FacilityDetailSidebarContributors.jsx +++ b/src/app/src/components/FacilityDetailSidebarContributors.jsx @@ -1,9 +1,11 @@ import React from 'react'; import { withStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; -import Divider from '@material-ui/core/Divider'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemText from '@material-ui/core/ListItemText'; -import FacilityDetailSidebarDetail from './FacilityDetailSidebarDetail'; +import ShowOnly from './ShowOnly'; +import BadgeVerified from './BadgeVerified'; import { makeProfileRouteLink } from '../util/util'; @@ -18,6 +20,9 @@ const detailsSidebarStyles = theme => textTransform: 'uppercase', fontWeight: theme.typography.fontWeightMedium, }, + primaryText: { + wordWrap: 'break-word', + }, secondaryText: { color: 'rgba(0, 0, 0, 0.54)', display: 'flex', @@ -25,8 +30,14 @@ const detailsSidebarStyles = theme => fontSize: '12px', justify: 'flex-end', }, - divider: { - backgroundColor: 'rgba(0, 0, 0, 0.06)', + icon: { + color: 'rgb(106, 106, 106)', + fontSize: '24px', + fontWeight: 300, + textAlign: 'center', + }, + contributor: { + boxShadow: '0px -1px 0px 0px rgb(240, 240, 240)', }, }); @@ -38,18 +49,30 @@ const FacilityDetailSidebarContributors = ({ classes, contributors, push }) => { return (
Contributors - - {contributors.map(contributor => ( - push(makeProfileRouteLink(contributor.id))} - key={contributor.id} - verified={contributor.is_verified} - /> + {visibleContributors.map(contributor => ( + { + if (!contributor.id) return; + push(makeProfileRouteLink(contributor.id)); + }} + key={`${contributor.id} ${contributor.list_name}`} + className={classes.contributor} + > + + + + + + + + ))}
); diff --git a/src/app/src/components/FacilityDetailSidebarDetail.jsx b/src/app/src/components/FacilityDetailSidebarDetail.jsx index b630e952b..5eb1ed027 100644 --- a/src/app/src/components/FacilityDetailSidebarDetail.jsx +++ b/src/app/src/components/FacilityDetailSidebarDetail.jsx @@ -2,8 +2,6 @@ import React from 'react'; import { withStyles } from '@material-ui/core/styles'; import ListItem from '@material-ui/core/ListItem'; import ListItemText from '@material-ui/core/ListItemText'; -import Divider from '@material-ui/core/Divider'; -import ArrowForwardIcon from '@material-ui/icons/ChevronRight'; import ShowOnly from './ShowOnly'; import BadgeVerified from './BadgeVerified'; @@ -13,56 +11,27 @@ const detailsSidebarStyles = () => primaryText: { wordWrap: 'break-word', }, - secondaryText: { - color: 'rgba(0, 0, 0, 0.54)', - display: 'flex', - alignItems: 'center', - fontSize: '12px', - justify: 'flex-end', - }, - divider: { - backgroundColor: 'rgba(0, 0, 0, 0.06)', + item: { + boxShadow: '0px -1px 0px 0px rgb(240, 240, 240)', }, }); const FacilityDetailSidebarDetail = ({ - hasAdditionalContent, - additionalContentCount, primary, secondary, - onClick, - hideTopDivider, verified, classes, }) => ( - <> - - + + + - { - if (!hasAdditionalContent) return; - onClick(); - }} - > - - - - - -
- - -
-
-
- - + +
); export default withStyles(detailsSidebarStyles)(FacilityDetailSidebarDetail); diff --git a/src/app/src/components/FacilityDetailSidebarExtended.jsx b/src/app/src/components/FacilityDetailSidebarExtended.jsx index dcfe5e647..4275d2057 100644 --- a/src/app/src/components/FacilityDetailSidebarExtended.jsx +++ b/src/app/src/components/FacilityDetailSidebarExtended.jsx @@ -1,9 +1,10 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useMemo } from 'react'; import { Redirect } from 'react-router'; import { connect } from 'react-redux'; import { withStyles } from '@material-ui/core/styles'; import get from 'lodash/get'; import includes from 'lodash/includes'; +import filter from 'lodash/filter'; import moment from 'moment'; import CircularProgress from '@material-ui/core/CircularProgress'; import List from '@material-ui/core/List'; @@ -22,7 +23,10 @@ import { resetSingleFacility, } from '../actions/facilities'; -import { facilitySidebarActions } from '../util/constants'; +import { + facilitySidebarActions, + EXTENDED_FIELD_TYPES, +} from '../util/constants'; import { makeReportADataIssueEmailLink, @@ -80,6 +84,31 @@ const detailsSidebarStyles = theme => const formatAttribution = (createdAt, contributor) => `${moment(createdAt).format('LL')} by ${contributor}`; +/* eslint-disable camelcase */ +const formatExtendedField = ({ + value, + updated_at, + contributor_name, + verified, + id, + formatValue = v => v, +}) => ({ + primary: formatValue(value), + secondary: formatAttribution(updated_at, contributor_name), + verified, + key: id, +}); + +const formatOtherValues = (data, fieldName, extendedFieldName) => [ + ...get(data, `properties.${fieldName}`, []).map(item => ({ + primary: item, + key: item, + })), + ...get(data, `properties.extended_fields.${extendedFieldName}`, []).map( + formatExtendedField, + ), +]; + const FacilityDetailSidebar = ({ classes, data, @@ -105,6 +134,16 @@ const FacilityDetailSidebar = ({ // Clears the selected facility when unmounted useEffect(() => () => clearFacility(), []); + const otherNames = useMemo( + () => formatOtherValues(data, 'other_names', 'name'), + [data], + ); + + const otherAddresses = useMemo( + () => formatOtherValues(data, 'other_addresses', 'address'), + [data], + ); + if (fetching) { return (
@@ -153,6 +192,30 @@ const FacilityDetailSidebar = ({ const isClaimed = !!data?.properties?.claim_info; const claimFacility = () => push(makeClaimFacilityLink(oarId)); + const renderExtendedField = ({ label, fieldName, formatValue }) => { + const values = get(data, `properties.extended_fields.${fieldName}`, []); + if (!values.length || !values[0]) return null; + + const formatField = item => + formatExtendedField({ ...item, formatValue }); + + const topValue = formatField(values[0]); + + return ( + + ); + }; + + const contributorFields = filter( + get(data, 'properties.contributor_fields', null), + field => field.value !== null, + ); + return (
@@ -171,29 +234,46 @@ const FacilityDetailSidebar = ({ oarId={data.properties.oar_id} onClaimFacility={claimFacility} /> - +
+ {EXTENDED_FIELD_TYPES.map(renderExtendedField)} + + + {contributorFields.map(field => ( + + ))} +
, style: { - background: 'rgb(9, 18, 50)', + background: 'rgb(61, 50, 138)', color: 'rgb(255, 255, 255)', }, }; diff --git a/src/app/src/components/FacilityDetailSidebarItem.jsx b/src/app/src/components/FacilityDetailSidebarItem.jsx index 05f0d5bfa..c81283be3 100644 --- a/src/app/src/components/FacilityDetailSidebarItem.jsx +++ b/src/app/src/components/FacilityDetailSidebarItem.jsx @@ -1,8 +1,10 @@ -import React from 'react'; +import React, { useState } from 'react'; import { withStyles } from '@material-ui/core/styles'; -import Typography from '@material-ui/core/Typography'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemText from '@material-ui/core/ListItemText'; import FacilityDetailSidebarDetail from './FacilityDetailSidebarDetail'; +import ShowOnly from './ShowOnly'; const detailsSidebarStyles = () => Object.freeze({ @@ -10,11 +12,29 @@ const detailsSidebarStyles = () => paddingTop: '16px', }, label: { - padding: '12px 24px 4px 24px', fontSize: '0.75rem', textTransform: 'uppercase', fontWeight: 'bold', }, + primaryText: { + wordWrap: 'break-word', + }, + secondaryText: { + color: 'rgba(0, 0, 0, 0.54)', + display: 'flex', + alignItems: 'center', + fontSize: '12px', + justify: 'flex-end', + }, + divider: { + backgroundColor: 'rgba(0, 0, 0, 0.06)', + }, + icon: { + color: 'rgb(106, 106, 106)', + fontSize: '24px', + fontWeight: 300, + textAlign: 'center', + }, }); const FacilityDetailSidebarItem = ({ @@ -24,23 +44,45 @@ const FacilityDetailSidebarItem = ({ secondary, classes, embed, - href, - link, + verified, }) => { - const hasAdditionalContent = !!additionalContent?.length; + const [isOpen, setIsOpen] = useState(false); + const hasAdditionalContent = !embed && !!additionalContent?.length; + const additionalContentCount = additionalContent?.length; return (
- {label} + { + if (!hasAdditionalContent) return; + setIsOpen(!isOpen); + }} + > + + +
+ + +
+
+
{}} - link={link} - href={href} + verified={verified} /> + {isOpen && + additionalContent.map(item => ( + + ))}
); }; diff --git a/src/app/src/components/FacilityDetailSidebarLocation.jsx b/src/app/src/components/FacilityDetailSidebarLocation.jsx index cb6df6c57..ba07cbbfd 100644 --- a/src/app/src/components/FacilityDetailSidebarLocation.jsx +++ b/src/app/src/components/FacilityDetailSidebarLocation.jsx @@ -33,7 +33,12 @@ const FacilityDetailSidebarLocation = ({ data, embed }) => { label="GPS" primary={`${facilityLng}, ${facilityLat}`} secondary={attribution} - additionalContent={otherLocationsData} + embed={embed} + additionalContent={otherLocationsData.map((item, i) => ({ + primary: `${item.lng}, ${item.lat}`, + secondary: item.contributor_name, + key: `${item.lng}, ${item.lat} - ${i}`, + }))} /> ); diff --git a/src/app/src/util/constants.js b/src/app/src/util/constants.js index 4e4f3ba8e..8116c4086 100644 --- a/src/app/src/util/constants.js +++ b/src/app/src/util/constants.js @@ -715,3 +715,37 @@ export const facilitySidebarActions = { CLAIM_FACILITY: 'Claim this facility', VIEW_ON_OAR: 'View on the Open Apparel Registry', }; + +export const EXTENDED_FIELD_TYPES = [ + { + label: 'Parent Company', + fieldName: 'parent_company', + formatValue: v => v, + }, + { + label: 'Facility Type', + fieldName: 'facility_type', + formatValue: v => v, + }, + { + label: 'Product Type', + fieldName: 'product_type', + formatValue: v => v, + }, + { + label: 'Processing Type', + fieldName: 'processing_type', + formatValue: v => v, + }, + { + label: 'Number of Workers', + fieldName: 'number_of_workers', + formatValue: ({ min, max }) => + max === min ? `${max} workers` : `${min}-${max} workers`, + }, + { + label: 'Native Language Name', + fieldName: 'native_language_name', + formatValue: v => v, + }, +];