157 lines
3.8 KiB
JavaScript
Raw Normal View History

2019-10-30 17:27:58 +01:00
import React, { createRef, isValidElement, useEffect, useState } from 'react';
2019-10-23 15:49:03 +02:00
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { isEmpty } from 'lodash';
2019-12-03 16:04:41 +01:00
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
2019-10-23 15:49:03 +02:00
import matchSorter from 'match-sorter';
2019-10-16 16:56:44 +02:00
import Wrapper from './Wrapper';
2019-10-23 15:49:03 +02:00
import List from './List';
import Search from './Search';
2019-10-16 16:56:44 +02:00
2019-10-24 14:41:06 +02:00
import LeftMenuLink from '../LeftMenuLink';
2019-10-23 15:49:03 +02:00
import LeftMenuSubList from '../LeftMenuSubList';
2019-10-16 16:56:44 +02:00
2019-10-24 14:41:06 +02:00
function LeftMenuList({ customLink, links, title }) {
2019-10-23 15:49:03 +02:00
const [search, setSearch] = useState('');
const [showSearch, setShowSearch] = useState(false);
2019-10-30 17:27:58 +01:00
const ref = createRef();
2019-10-16 16:56:44 +02:00
2019-10-30 17:27:58 +01:00
useEffect(() => {
if (showSearch && ref.current) {
ref.current.focus();
}
}, [ref, showSearch]);
const { Component, componentProps } = customLink || {
Component: null,
componentProps: {},
};
2019-10-16 16:56:44 +02:00
2019-10-23 15:49:03 +02:00
const toggleSearch = () => setShowSearch(!showSearch);
2019-10-30 17:27:58 +01:00
const handleClose = () => {
clearSearch();
toggleSearch();
2019-10-23 15:49:03 +02:00
};
const clearSearch = () => {
setSearch('');
};
2019-10-30 17:27:58 +01:00
const handleChange = ({ target: { value } }) => {
setSearch(value);
2019-10-23 15:49:03 +02:00
};
2019-10-16 16:56:44 +02:00
2019-10-30 17:27:58 +01:00
const hasChildObject = () => links.some(link => !isEmpty(link.links));
const getCount = () => {
if (hasChildObject()) {
return links.reduce((acc, current) => {
return acc + current.links.length;
}, 0);
}
return links.length;
2019-10-23 15:49:03 +02:00
};
const getList = () => {
if (hasChildObject()) {
return links.map(link => {
return {
...link,
2019-12-06 16:40:50 +01:00
links: matchSorter(link.links, search, { keys: ['title'] }),
2019-10-23 15:49:03 +02:00
};
});
}
2019-12-06 16:40:50 +01:00
return matchSorter(links, search, { keys: ['title'] });
2019-10-23 15:49:03 +02:00
};
2019-10-24 14:41:06 +02:00
const getTitle = () =>
getCount() > 1 ? `${title.id}plural` : `${title.id}singular`;
2019-10-23 15:49:03 +02:00
const renderCompo = (link, i) => {
const { links, name, title, ...rest } = link;
2019-10-23 15:49:03 +02:00
if (links) {
2019-10-30 17:27:58 +01:00
const isSearching = !isEmpty(search);
2019-10-23 15:49:03 +02:00
return (
<LeftMenuSubList
key={name}
{...rest}
2019-10-23 15:49:03 +02:00
{...link}
2019-10-30 17:27:58 +01:00
isSearching={isSearching}
2019-10-23 15:49:03 +02:00
isFirstItem={i === 0}
/>
);
}
return (
<li key={name}>
2019-10-24 14:41:06 +02:00
<LeftMenuLink {...link}>{title}</LeftMenuLink>
2019-10-23 15:49:03 +02:00
</li>
);
};
2019-10-16 16:56:44 +02:00
return (
2019-10-23 15:49:03 +02:00
<Wrapper>
2019-10-16 16:56:44 +02:00
<div className="list-header">
2019-10-23 15:49:03 +02:00
{!showSearch ? (
<div className="title-wrapper">
<h3>
<FormattedMessage id={getTitle()} />
2019-12-11 10:31:19 +01:00
&nbsp;&nbsp;
<span className="count-info" datadescr={getCount()}>
{getCount()}
</span>
2019-10-23 15:49:03 +02:00
</h3>
<button onClick={toggleSearch}>
2019-12-03 16:04:41 +01:00
<FontAwesomeIcon icon="search" />
2019-10-23 15:49:03 +02:00
</button>
</div>
) : (
<div className="search-wrapper">
2019-12-03 16:04:41 +01:00
<FontAwesomeIcon icon="search" />
2019-10-23 15:49:03 +02:00
<button onClick={toggleSearch}></button>
<Search
2019-10-30 17:27:58 +01:00
ref={ref}
2019-10-23 15:49:03 +02:00
onChange={handleChange}
value={search}
placeholder="search…"
/>
<button onClick={handleClose}>
2019-12-03 16:04:41 +01:00
<FontAwesomeIcon icon="times" />
2019-10-23 15:49:03 +02:00
</button>
</div>
)}
</div>
<div>
<List>{getList().map((link, i) => renderCompo(link, i))}</List>
2019-10-30 17:27:58 +01:00
{Component && isValidElement(<Component />) && (
<Component {...componentProps} />
)}
2019-10-16 16:56:44 +02:00
</div>
</Wrapper>
);
}
2019-10-23 15:49:03 +02:00
LeftMenuList.defaultProps = {
2019-10-30 17:27:58 +01:00
customLink: null,
2019-10-23 15:49:03 +02:00
links: [],
2019-10-24 14:41:06 +02:00
title: 'models',
2019-10-23 15:49:03 +02:00
};
LeftMenuList.propTypes = {
customLink: PropTypes.shape({
Component: PropTypes.object,
componentProps: PropTypes.shape({
id: PropTypes.string,
onClick: PropTypes.func,
}),
}),
links: PropTypes.array,
2019-10-24 14:41:06 +02:00
title: PropTypes.string,
2019-10-23 15:49:03 +02:00
};
2019-10-16 16:56:44 +02:00
export default LeftMenuList;