Skip to content

Commit

Permalink
Org pins can be manipulated by admin/super users | initial concepts c…
Browse files Browse the repository at this point in the history
…omparison view
  • Loading branch information
snyaggarwal committed Dec 18, 2020
1 parent e32b624 commit 4492993
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 8 deletions.
6 changes: 6 additions & 0 deletions src/components/app/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import './App.scss';
import SearchInput from '../search/SearchInput';
import Search from '../search/Search';
import ConceptHome from '../concepts/ConceptHome';
import ConceptsComparison from '../concepts/ConceptsComparison';
import MappingHome from '../mappings/MappingHome';
import SourceHome from '../sources/SourceHome';
import CollectionHome from '../collections/CollectionHome';
Expand Down Expand Up @@ -130,6 +131,11 @@ class App extends Component {
path="/orgs/:org([a-zA-Z0-9\-\.\_]+)/sources/:source([a-zA-Z0-9\-\.\_]+)/:version([a-zA-Z0-9\-\.\_]+)/concepts/:concept([a-zA-Z0-9\-\.\_]+)"
component={ConceptHome}
/>
<Route
exact
path="/concepts/compare"
component={ConceptsComparison}
/>

{ /* Mapping Home */ }
<Route
Expand Down
14 changes: 14 additions & 0 deletions src/components/app/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ td.pagination-center {
-webkit-box-orient: vertical;
overflow: hidden;
}
.gray-italics {
color: gray;
font-style: italic;
margin-right: 5px;
}
.gray-italics-small {
color: gray;
font-style: italic;
Expand Down Expand Up @@ -432,3 +437,12 @@ div.login-paper {
overflow: hidden;
}
}
.diff-red {
background-color: rgba(232, 217, 218, 0.5);
}
.diff-green {
background-color: rgb(231, 255, 238);
}
.border-primary {
border: 1px solid rgb(51, 115, 170);
}
172 changes: 172 additions & 0 deletions src/components/concepts/ConceptsComparison.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import React from 'react';
import {
TableContainer, Table, TableHead, TableBody, TableCell, TableRow,
Tooltip
} from '@material-ui/core';
import { Flag as FlagIcon } from '@material-ui/icons';
import { get, startCase, map, isEmpty, includes, isEqual } from 'lodash';
import APIService from '../../services/APIService';
import { formatDate } from '../../common/utils';

const ATTRIBUTES = {
text1: ['datatype', 'display_locale', 'external_id'],
list: ['names', 'descriptions'],
text2: ['created_by', 'updated_by'],
date: ['created_on', 'updated_on'],
}

const getLocaleLabel = locale => {
const nameAttr = get(locale, 'name') ? 'name' : 'description';
return (
<React.Fragment key={locale.uuid}>
<div className='flex-vertical-center'>
<span className='gray-italics'>
{get(locale, 'name_type') || get(locale, 'description_type')}
</span>
<span style={{marginLeft: '5px'}}>
{get(locale, 'name') || get(locale, 'description')}
</span>
<span className='gray-italics-small' style={{marginLeft: '5px'}}>
{`[${locale.locale}]`}
</span>
{
locale.locale_preferred &&
<span style={{marginLeft: '5px'}}>
<Tooltip title={`Preferred ${nameAttr} for this locale`} placement='top-start'>
<FlagIcon color='secondary' fontSize='small' style={{width: '18px', marginTop: '4px'}}/>
</Tooltip>
</span>
}
</div>
</React.Fragment>
)
}

class ConceptsComparison extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoadingLHS: true,
isLoadingRHS: true,
lhs: {},
rhs: {},
}
}

componentDidMount() {
this.setObjectsForComparison()
}

componentDidUpdate(prevProps) {
if(prevProps.location.search !== this.props.location.search)
this.setObjectsForComparison()
}

setObjectsForComparison() {
const queryParams = new URLSearchParams(this.props.location.search)
this.fetchConcept(queryParams.get('lhs'), 'lhs', 'isLoadingLHS')
this.fetchConcept(queryParams.get('rhs'), 'rhs', 'isLoadingRHS')
}

fetchConcept(uri, attr, loadingAttr) {
if(uri && attr && loadingAttr) {
APIService.new().overrideURL(uri).get().then(response => {
if(get(response, 'status') === 200)
this.setState({[attr]: response.data, [loadingAttr]: false})
})
}
}

getConceptHeader(concept) {
return (
<React.Fragment>
<div style={{margin: '5px 2px'}}>
<span>
<span className='gray-italics'>Source:</span>
<span>{concept.source}</span>
</span>
<span style={{marginLeft: '10px'}}>
<span className='gray-italics'>Type:</span>
<span>{concept.concept_class}</span>
</span>
<span style={{marginLeft: '10px'}}>
<span className='gray-italics'>UID:</span>
<span>{concept.id}</span>
</span>
</div>
</React.Fragment>
)
}

getValue(concept, attr, type) {
if(type === 'list') {
if(includes(['names', 'descriptions'], attr)) {
const locales = get(concept, attr)
return isEmpty(locales) ? '-' : map(locales, getLocaleLabel)
}
} else if(type === 'date') {
const date = get(concept, attr);
return date ? formatDate(date) : '-';
} else {
return get(concept, attr, '-')
}
}

render() {
const { lhs, rhs } = this.state;
return (
<div className='col-md-12' style={{paddingTop: '10px', paddingBottom: '10px'}}>
<TableContainer style={{borderRadius: '4px'}}>
<Table size='small'>
<TableHead>
<TableRow colSpan="12">
<TableCell colSpan="2" style={{width: '20%'}}></TableCell>
<TableCell colSpan="5" style={{width: '40%'}}>
<div style={{fontSize: '12px'}}>
{this.getConceptHeader(lhs)}
</div>
<div style={{fontSize: '18px'}}>
{get(lhs, 'display_name')}
</div>
</TableCell>
<TableCell colSpan="5" style={{width: '40%'}}>
<div style={{fontSize: '12px'}}>
{this.getConceptHeader(rhs)}
</div>
<div style={{fontSize: '18px'}}>
{get(rhs, 'display_name')}
</div>
</TableCell>
</TableRow>
</TableHead>
<TableBody style={{border: '1px solid lightgray'}}>
{
map(ATTRIBUTES, (attrs, type) => {
return map(attrs, attr => {
const isDiff = !isEqual(get(lhs, attr), get(rhs, attr));
const className = isDiff ? 'diff-red' : '';
return (
<TableRow key={attr} colSpan='12' className={className}>
<TableCell colSpan='2' style={{width: '20%', fontWeight: 'bold'}}>
{startCase(attr)}
</TableCell>
<TableCell colSpan='5' style={{width: '40%'}}>
{this.getValue(lhs, attr, type)}
</TableCell>
<TableCell colSpan='5' style={{width: '40%'}}>
{this.getValue(rhs, attr, type)}
</TableCell>
</TableRow>
)
})
})
}
</TableBody>
</Table>
</TableContainer>
</div>
)
}
}

export default ConceptsComparison;
4 changes: 2 additions & 2 deletions src/components/orgs/OrgHome.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { CircularProgress } from '@material-ui/core';
import { reject, get, isEmpty } from 'lodash';
import APIService from '../../services/APIService';
import { isCurrentUserMemberOf } from '../../common/utils';
import { isCurrentUserMemberOf, isAdminUser } from '../../common/utils';
import Pins from '../common/Pins';
import OrgHomeHeader from './OrgHomeHeader';
import OrgHomeTabs from './OrgHomeTabs';
Expand Down Expand Up @@ -129,7 +129,7 @@ class OrgHome extends React.Component {
render() {
const { org, isLoading, tab, pins } = this.state;
const url = this.getURLFromPath()
const isCurrentUserMemberOfOrg = isCurrentUserMemberOf(this.getOrgId());
const isCurrentUserMemberOfOrg = isCurrentUserMemberOf(this.getOrgId()) || isAdminUser();
const showAboutTab = this.shouldShowAboutTab()
return (
<div style={isLoading ? {textAlign: 'center', marginTop: '40px'} : {}}>
Expand Down
43 changes: 37 additions & 6 deletions src/components/search/ResultsTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { Link } from 'react-router-dom';
import {
TableContainer, Table, TableHead, TableBody, TableCell, TableRow,
Collapse, IconButton, Box, Paper, Tabs, Tab, Checkbox, TableSortLabel, Tooltip,
Collapse, IconButton, Box, Paper, Tabs, Tab, Checkbox, TableSortLabel, Tooltip, Button,
} from '@material-ui/core';
import {
KeyboardArrowDown as KeyboardArrowDownIcon,
Expand All @@ -17,17 +17,18 @@ import {
Person as PersonIcon,
Home as HomeIcon,
Loyalty as LoyaltyIcon,
CompareArrows as CompareArrowsIcon
} from '@material-ui/icons'
import { Pagination } from '@material-ui/lab'
import {
map, startCase, get, without, uniq, includes, find, keys, values, isEmpty,
map, startCase, get, without, uniq, includes, find, keys, values, isEmpty, filter,
} from 'lodash';
import {
BLUE, WHITE, DARKGRAY, COLOR_ROW_SELECTED, ORANGE, GREEN, EMPTY_VALUE
} from '../../common/constants';
import {
formatDate, formatDateTime, headFirst, isLoggedIn, defaultCreatePin, defaultDeletePin,
getCurrentUserUsername, isCurrentUserMemberOf,
getCurrentUserUsername, isCurrentUserMemberOf, isAdminUser,
} from '../../common/utils';
import ReferenceChip from '../common/ReferenceChip';
import OwnerChip from '../common/OwnerChip';
Expand Down Expand Up @@ -314,7 +315,7 @@ const ExpandibleRow = props => {
const username = get(props, 'match.params.user') || getCurrentUserUsername();
const orgId = get(props, 'match.params.org');
let service = null;
if(orgId && isCurrentUserMemberOf(orgId))
if(orgId && (isCurrentUserMemberOf(orgId) || isAdminUser()))
service = APIService.orgs(orgId)
else if(username && isLoggedIn())
service = APIService.users(username)
Expand Down Expand Up @@ -615,6 +616,22 @@ const ResultsTable = (
onSortChange(sortQuery)
}

const getSelectedItems = () => {
return filter(results.items, item => includes(selectedList, item.id))
}

const shouldShowCompareOption = resource === 'concepts' && selectedList.length === 2;
const selectionRowColumnsCount = shouldShowCompareOption ? columnsCount - 2 : columnsCount;
const onCompareClick = event => {
event.stopPropagation()
event.preventDefault()
const urls = map(getSelectedItems(), 'url')
if(urls.length == 2) {
const url = `#/concepts/compare?lhs=${urls[0]}&rhs=${urls[1]}`
window.open(url, '_blank')
}
}

return (
<div className='col-sm-12 no-side-padding'>
{
Expand All @@ -625,10 +642,24 @@ const ResultsTable = (
<TableHead style={theadStyles}>
{
selectedList.length > 0 &&
<TableRow colSpan={columnsCount} style={{backgroundColor: DARKGRAY, border: `1px solid ${DARKGRAY}`}}>
<TableCell colSpan={columnsCount} align='left' style={{color: WHITE}}>
<TableRow colSpan={selectionRowColumnsCount} style={{backgroundColor: DARKGRAY, border: `1px solid ${DARKGRAY}`}}>
<TableCell colSpan={selectionRowColumnsCount} align='left' style={{color: WHITE}}>
{selectedList.length} Selected
</TableCell>
{
shouldShowCompareOption &&
<TableCell colSpan="2" align='center' style={{color: WHITE}}>
<Button
startIcon={<CompareArrowsIcon fontSize='small' />}
variant='contained'
size='small'
color='secondary'
onClick={onCompareClick}
>
Compare
</Button>
</TableCell>
}
</TableRow>
}
<TableRow>
Expand Down

0 comments on commit 4492993

Please sign in to comment.