Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Add extended field handling to facility details #1593

Merged
merged 1 commit into from
Jan 19, 2022
Merged
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Added

- Add extended field handling to facility details [#1593](https://github.com/open-apparel-registry/open-apparel-registry/pull/1593)

### Changed

- Identify exact matches pre-dedupe [#1568](https://github.com/open-apparel-registry/open-apparel-registry/pull/1568)
Expand Down
55 changes: 39 additions & 16 deletions src/app/src/components/FacilityDetailSidebarContributors.jsx
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -18,15 +20,24 @@ const detailsSidebarStyles = theme =>
textTransform: 'uppercase',
fontWeight: theme.typography.fontWeightMedium,
},
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',
},
contributor: {
boxShadow: '0px -1px 0px 0px rgb(240, 240, 240)',
},
});

Expand All @@ -38,18 +49,30 @@ const FacilityDetailSidebarContributors = ({ classes, contributors, push }) => {
return (
<div className={classes.item}>
<Typography className={classes.label}>Contributors</Typography>
<Divider className={classes.divider} />
{contributors.map(contributor => (
<FacilityDetailSidebarDetail
primary={contributor.contributor_name}
secondary={contributor.list_name}
hasAdditionalContent={!!contributor.id}
hideTopDivider
additionalContentCount=""
onClick={() => push(makeProfileRouteLink(contributor.id))}
key={contributor.id}
verified={contributor.is_verified}
/>
{visibleContributors.map(contributor => (
<ListItem
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched from using the FacilityDetailSidebarDetail here because the structure is different enough now to make it overly complex

button={!!contributor.id}
onClick={() => {
if (!contributor.id) return;
push(makeProfileRouteLink(contributor.id));
}}
key={`${contributor.id} ${contributor.list_name}`}
className={classes.contributor}
>
<ShowOnly when={contributor.is_verified}>
<BadgeVerified />
</ShowOnly>
<ListItemText
primary={contributor.contributor_name}
secondary={contributor.list_name}
classes={{ primary: classes.primaryText }}
/>
<ShowOnly when={!!contributor.id}>
<i
className={`${classes.icon} far fa-fw fa-angle-right`}
/>
</ShowOnly>
</ListItem>
))}
</div>
);
Expand Down
53 changes: 11 additions & 42 deletions src/app/src/components/FacilityDetailSidebarDetail.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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,
}) => (
<>
<ShowOnly when={!hideTopDivider}>
<Divider className={classes.divider} />
<ListItem className={classes.item}>
<ShowOnly when={verified}>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm showing the verified badge when an extended field is verified (presumably includes when the contributor is verified, based on upcoming changes). Do we want this, or should there be no badge for verified items?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense that we visually indicate the status of these items. I like shoing the badge.

<BadgeVerified />
</ShowOnly>
<ListItem
button={hasAdditionalContent}
onClick={() => {
if (!hasAdditionalContent) return;
onClick();
}}
>
<ShowOnly when={verified}>
<BadgeVerified />
</ShowOnly>
<ListItemText
primary={primary}
secondary={secondary}
classes={{ primary: classes.primaryText }}
/>
<ShowOnly when={hasAdditionalContent}>
<div className={classes.secondaryText}>
<ListItemText secondary={additionalContentCount} />
<ArrowForwardIcon />
</div>
</ShowOnly>
</ListItem>
<Divider className={classes.divider} />
</>
<ListItemText
primary={primary}
secondary={secondary}
classes={{ primary: classes.primaryText }}
/>
</ListItem>
);

export default withStyles(detailsSidebarStyles)(FacilityDetailSidebarDetail);
90 changes: 85 additions & 5 deletions src/app/src/components/FacilityDetailSidebarExtended.jsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -22,7 +23,10 @@ import {
resetSingleFacility,
} from '../actions/facilities';

import { facilitySidebarActions } from '../util/constants';
import {
facilitySidebarActions,
EXTENDED_FIELD_TYPES,
} from '../util/constants';

import {
makeReportADataIssueEmailLink,
Expand Down Expand Up @@ -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,
Expand All @@ -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 (
<div className={classes.root}>
Expand Down Expand Up @@ -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 (
<FacilityDetailSidebarItem
{...topValue}
label={label}
additionalContent={values.slice(1).map(formatField)}
embed={embed}
/>
);
};

const contributorFields = filter(
get(data, 'properties.contributor_fields', null),
field => field.value !== null,
);

return (
<div className={classes.root}>
<List className={classes.list}>
Expand All @@ -171,29 +234,46 @@ const FacilityDetailSidebar = ({
oarId={data.properties.oar_id}
onClaimFacility={claimFacility}
/>
<FacilityDetailSidebarItem label="OAR ID" primary={oarId} />
<FacilityDetailSidebarItem
label="OAR ID"
primary={oarId}
embed={embed}
/>
<FacilityDetailSidebarItem
label="Name"
primary={data.properties.name}
secondary={createdFrom}
additionalContent={data.properties.other_names}
additionalContent={otherNames}
embed={embed}
/>
<FacilityDetailSidebarItem
label="Address"
primary={`${data.properties.address} - ${data.properties.country_name}`}
secondary={createdFrom}
additionalContent={data.properties.other_addresses}
additionalContent={otherAddresses}
embed={embed}
/>
<div style={{ padding: '0 16px' }}>
<FacilityDetailsStaticMap data={data} />
</div>
<FacilityDetailSidebarLocation data={data} embed={embed} />
<ShowOnly when={!embed}>
{EXTENDED_FIELD_TYPES.map(renderExtendedField)}

<FacilityDetailSidebarContributors
contributors={data.properties.contributors}
push={push}
/>
</ShowOnly>
<ShowOnly when={embed}>
{contributorFields.map(field => (
<FacilityDetailSidebarItem
label={field.label}
primary={field.value}
key={field.label}
/>
))}
</ShowOnly>
<div className={classes.actions}>
<ShowOnly when={!embed}>
<FacilityDetailSidebarAction
Expand Down
2 changes: 1 addition & 1 deletion src/app/src/components/FacilityDetailSidebarHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const getContent = ({
secondary: 'Claim this facility',
icon: <BadgeUnclaimed />,
style: {
background: 'rgb(9, 18, 50)',
background: 'rgb(61, 50, 138)',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating to new unclaimed header color per new wireframes

color: 'rgb(255, 255, 255)',
},
};
Expand Down
Loading