Skip to content

Commit

Permalink
Merge pull request #1456 from thehyve/metadata-in-dialog
Browse files Browse the repository at this point in the history
Dialog for metadata details
  • Loading branch information
ewelinagr authored Dec 27, 2023
2 parents 6e65371 + 5cfda7d commit 01d7410
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 77 deletions.
53 changes: 35 additions & 18 deletions projects/mercury/src/metadata/common/LinkedDataLink.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,45 @@
import React, {useContext} from 'react';
import {Link as RouterLink} from "react-router-dom";
import * as PropTypes from "prop-types";
import {Link} from '@mui/material';
import {METADATA_PATH} from "../../constants";
import {Box, Modal, Tooltip} from '@mui/material';
import withStyles from '@mui/styles/withStyles';
import CloseIcon from '@mui/icons-material/Close';
import LinkedDataEntityPage from "./LinkedDataEntityPage";
import UserContext from '../../users/UserContext';

import styles from './LinkedDataLink.styles';
/**
* Renders a link to the metadata editor.
*
* @param props
* @constructor
* Renders a link to the metadata editor in a modal dialog when clicked.
*/
const LinkedDataLink = ({uri, children}) => {

const renderModal = (classes, open, handleClose, uri) => (
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box className={classes.modalDialog}>
<Tooltip title="Close - click or press 'Esc'">
<CloseIcon onClick={handleClose} className={classes.closeButton} />
</Tooltip>
<LinkedDataEntityPage title="Metadata" subject={uri} />
</Box>
</Modal>
);

const LinkedDataLink = ({classes, uri, children}) => {
const [open, setOpen] = React.useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);

const {currentUser} = useContext(UserContext);
if (currentUser && currentUser.canViewPublicMetadata) {
return (
<Link
component={RouterLink}
to={{pathname: METADATA_PATH, search: "?iri=" + encodeURIComponent(uri)}}
color="inherit"
underline="hover"
>
{children}
</Link>
<div>
<div onClick={handleOpen} className={classes.clickableDiv}>
{children}
</div>
{renderModal(classes, open, handleClose, uri)}
</div>
);
}
return children;
Expand All @@ -33,4 +50,4 @@ LinkedDataLink.propTypes = {
children: PropTypes.any.isRequired
};

export default LinkedDataLink;
export default withStyles(styles)(LinkedDataLink);
29 changes: 29 additions & 0 deletions projects/mercury/src/metadata/common/LinkedDataLink.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const styles = (theme) => ({
modalDialog: {
background: theme.palette.grey['200'],
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 800,
bgcolor: 'background.paper',
border: '0px solid #000',
boxShadow: 0,
outline: "none",
p: 4,
},
closeButton: {
float: 'right',
marginTop: 8,
marginRight: 8

},
clickableDiv: {
'cursor': 'pointer',
'&:hover': {
textDecoration: 'underline'
}
}
});

export default styles;
89 changes: 30 additions & 59 deletions projects/mercury/src/metadata/common/__tests__/LinkedDataLink.js
Original file line number Diff line number Diff line change
@@ -1,88 +1,59 @@
/* eslint-disable jsx-a11y/anchor-has-content */
import React from 'react';
import {configure, mount} from "enzyme";
import {configure} from "enzyme";
import Adapter from "@wojtekmaj/enzyme-adapter-react-17";

import {Router} from 'react-router-dom';
// eslint-disable-next-line import/no-extraneous-dependencies
import {createMemoryHistory} from 'history';
import LinkedDataLink from "../LinkedDataLink";
import {METADATA_PATH} from "../../../constants";
import {fireEvent, render} from "@testing-library/react";
import theme from "../../../App.theme";
import {ThemeProvider} from "@mui/material/styles";
import UserContext from '../../../users/UserContext';

// Enzyme is obsolete, the Adapter allows running our old tests.
// For new tests use React Testing Library. Consider migrating enzyme tests when refactoring.
configure({adapter: new Adapter()});
jest.mock('../LinkedDataEntityPage', () => () => <div>Mocked Metadata Page</div>);

describe('LinkedDataLink', () => {
it('should render internal link for any uri', () => {
const history: History = createMemoryHistory();
history.push = jest.fn();

const wrapper = mount(
it('renders LinkedDataLink without crashing', () => {
const { getByText } = render(
<UserContext.Provider value={{currentUser: {canViewPublicMetadata: true}}}>
<Router history={history}>
<LinkedDataLink uri="http://google.nl/some-path?search#hash">Go</LinkedDataLink>
</Router>
<ThemeProvider theme={theme}>
<LinkedDataLink uri="testUri">Test Content</LinkedDataLink>
</ThemeProvider>
</UserContext.Provider>
);

expect(wrapper.find('a').isEmpty()).toBeFalsy();
const anchor = wrapper.find('a').first();
const expectedLocation = `${METADATA_PATH}?iri=${encodeURIComponent("http://google.nl/some-path?search#hash")}`;
expect(anchor.prop('href')).toEqual(expectedLocation);
expect(anchor.text()).toEqual('Go');
expect(anchor.prop('onClick')).toBeTruthy();

anchor.prop('onClick')(new MouseEvent('click'));
expect(history.push).toBeCalledTimes(1);
expect(history.push).toBeCalledWith({
pathname: METADATA_PATH,
search: `?iri=${encodeURIComponent("http://google.nl/some-path?search#hash")}`
});
expect(getByText('Test Content')).toBeInTheDocument();
});

it('should display child elements for users without access to public metadata', () => {
const history: History = createMemoryHistory();
history.push = jest.fn();

const wrapper = mount(
<UserContext.Provider value={{currentUser: {canViewPublicMetadata: false}}}>
<Router history={history}>
<LinkedDataLink uri="http://google.nl/some-path?search#hash">Go</LinkedDataLink>
</Router>
it('shows the modal when clicked', () => {
const { getByText, queryByText } = render(
<UserContext.Provider value={{currentUser: {canViewPublicMetadata: true}}}>
<ThemeProvider theme={theme}>
<LinkedDataLink uri="testUri">Test Content</LinkedDataLink>
</ThemeProvider>
</UserContext.Provider>
);
expect(queryByText('Mocked Metadata Page')).not.toBeInTheDocument();

expect(wrapper.find('a').isEmpty()).toBeTruthy();
expect(wrapper.text()).toEqual('Go');
fireEvent.click(getByText('Test Content'));
expect(getByText('Mocked Metadata Page')).toBeInTheDocument();
});

it('should not break on an invalid url (return children only)', () => {
const uri = `some-invalid-url`;
const history: History = createMemoryHistory();
history.push = jest.fn();

const wrapper = mount(
it('closes the modal when close icon is clicked', () => {
const { getByText, getByTestId, queryByText } = render(
<UserContext.Provider value={{currentUser: {canViewPublicMetadata: true}}}>
<Router history={history}>
<LinkedDataLink uri={uri}>something</LinkedDataLink>
</Router>
<ThemeProvider theme={theme}>
<LinkedDataLink uri="testUri">Test Content</LinkedDataLink>
</ThemeProvider>
</UserContext.Provider>
);

expect(wrapper.find('a').isEmpty()).toBeFalsy();
const anchor = wrapper.find('a').first();
const expectedLocation = `${METADATA_PATH}?iri=${encodeURIComponent(uri)}`;
expect(anchor.prop('href')).toEqual(expectedLocation);
expect(anchor.text()).toEqual('something');
expect(anchor.prop('onClick')).toBeTruthy();
fireEvent.click(getByText('Test Content'));
expect(getByText('Mocked Metadata Page')).toBeInTheDocument();

anchor.prop('onClick')(new MouseEvent('click'));
expect(history.push).toBeCalledTimes(1);
expect(history.push).toBeCalledWith({
pathname: METADATA_PATH,
search: `?iri=${encodeURIComponent(uri)}`
});
const close = getByTestId('CloseIcon');
fireEvent.click(close);
expect(queryByText('Mocked Metadata Page')).not.toBeInTheDocument();
});
});

0 comments on commit 01d7410

Please sign in to comment.