web: Components: Added loading options list in AdvancedSelector v2; Selector re-written to functional component

This commit is contained in:
Alexey Safronov 2019-11-02 21:36:34 +03:00
parent 3d6d78480e
commit 9639d89bd2

View File

@ -1,10 +1,18 @@
import React from "react";
import React, { useRef, useState } from "react";
import PropTypes from "prop-types";
import styled, {css} from "styled-components";
import styled, { css } from "styled-components";
import Checkbox from "../../checkbox";
//import ComboBox from "../../combobox";
import Loader from "../../loader";
import { Text } from "../../text";
import CustomScrollbarsVirtualList from "../../scrollbar/custom-scrollbars-virtual-list";
import ADSelectorColumn from "./column";
import ADSelectorFooter from "./footer";
import ADSelectorHeader from "./header";
import ADSelectorBody from "./body";
import { FixedSizeList as List } from "react-window";
import InfiniteLoader from "react-window-infinite-loader";
import AutoSizer from 'react-virtualized-auto-sizer';
/* eslint-disable no-unused-vars */
/* eslint-disable react/prop-types */
@ -41,11 +49,10 @@ const StyledContainer = styled(Container)`
.body2 {
grid-area: body2;
background-color: cyan;
}
}
`
: css`
: css`
height: 100%;
grid-template-columns: 1fr;
grid-template-rows: 1fr 69px;
@ -65,12 +72,12 @@ const StyledContainer = styled(Container)`
.header1 {
grid-area: header1;
background-color: white;
background-color: lightblue;
}
.body1 {
grid-area: body1;
background-color: lightblue;
background-color: white;
}
}
@ -79,46 +86,122 @@ const StyledContainer = styled(Container)`
}
`;
class ADSelector extends React.Component {
constructor(props) {
super(props);
}
const ADSelector = props => {
const { displayType, groups, selectButtonLabel, isDisabled, isMultiSelect, hasNextPage, options, isNextPageLoading, loadNextPage, selectedOptions } = props;
render() {
const { displayType, groups, selectButtonLabel, isDisabled, isMultiSelect } = this.props;
return (
<StyledContainer displayType={displayType}>
<ADSelectorColumn className="column1" displayType={displayType}>
<ADSelectorHeader className="header1">
<span>Header 1</span>
const listRef = useRef(null);
//const hasMountedRef = useRef(false);
const [selected, setSelected] = useState(selectedOptions || []);
// Every row is loaded except for our loading indicator row.
const isItemLoaded = (index) => {
return !hasNextPage || index < options.length
};
const onChange = (e) => {
const option = options[+e.target.value];
const newSelected = e.target.checked
? [option, ...selected]
: selected.filter(el => el.key !== option.key);
setSelected(newSelected);
};
// Render an item or a loading indicator.
// eslint-disable-next-line react/prop-types
const renderRow = ({ index, style }) => {
let content;
if (!isItemLoaded(index)) {
content = <div className="option" style={style} key="loader">
<Loader
type="oval"
size={16}
style={{
display: "inline",
marginRight: "10px"
}}
/>
<Text.Body as="span">Loading... Please wait...</Text.Body>
</div>;
} else {
const option = options[index];
const checked = selected.findIndex(el => el.key === option.key) > -1;
//console.log("Item render", item, checked, selected);
content = (
<Checkbox
id={option.key}
value={`${index}`}
label={option.label}
isChecked={checked}
className="option_checkbox"
onChange={onChange}
/>
);
}
return <div style={style}>{content}</div>;
};
// If there are more items to be loaded then add an extra row to hold a loading indicator.
const itemCount = hasNextPage ? options.length + 1 : options.length;
// Only load 1 page of items at a time.
// Pass an empty callback to InfiniteLoader in case it asks us to load more than once.
const loadMoreItems = isNextPageLoading ? () => { } : loadNextPage;
return (
<StyledContainer displayType={displayType}>
<ADSelectorColumn className="column1" displayType={displayType}>
<ADSelectorHeader className="header1">
<span>Header 1</span>
</ADSelectorHeader>
<ADSelectorBody className="body1">
<AutoSizer>
{({ height, width }) => (
<InfiniteLoader
ref={listRef}
isItemLoaded={isItemLoaded}
itemCount={itemCount}
loadMoreItems={loadMoreItems}
>
{({ onItemsRendered, ref }) => (
<List
className="options_list"
height={height}
itemCount={itemCount}
itemSize={32}
onItemsRendered={onItemsRendered}
ref={ref}
width={width}
outerElementType={CustomScrollbarsVirtualList}
>
{renderRow}
</List>
)}
</InfiniteLoader>
)}
</AutoSizer>
</ADSelectorBody>
</ADSelectorColumn>
{displayType === "dropdown" && groups && groups.length > 0 &&
<ADSelectorColumn className="column2" displayType={displayType}>
<ADSelectorHeader className="header2">
<span>Header 2</span>
</ADSelectorHeader>
<ADSelectorBody className="body1">
<span>Body 1</span>
<ADSelectorBody className="body2">
<span>Body 2</span>
</ADSelectorBody>
</ADSelectorColumn>
{displayType === "dropdown" && groups && groups.length > 0 &&
<ADSelectorColumn className="column2" displayType={displayType}>
<ADSelectorHeader className="header2">
<span>Header 2</span>
</ADSelectorHeader>
<ADSelectorBody className="body2">
<span>Body 2</span>
</ADSelectorBody>
</ADSelectorColumn>
}
<ADSelectorFooter
className="footer"
selectButtonLabel={selectButtonLabel}
isDisabled={isDisabled}
isMultiSelect={isMultiSelect}
isVisible={true}
/>
</StyledContainer>
);
}
}
<ADSelectorFooter
className="footer"
selectButtonLabel={selectButtonLabel}
isDisabled={isDisabled}
isVisible={isMultiSelect && selected.length > 0}
/>
</StyledContainer>
);
}
ADSelector.propTypes = {