2020-09-02 15:00:03 +00:00
|
|
|
import React from 'react';
|
|
|
|
import { FormControl, InputGroup, ListGroup } from 'react-bootstrap';
|
|
|
|
import { deepClone } from '../../../lib/helpers/objectMethods';
|
|
|
|
|
|
|
|
export interface SelecitonProps<T> {
|
2020-09-07 05:21:53 +00:00
|
|
|
selection: Array<{
|
2020-09-02 15:00:03 +00:00
|
|
|
groupName: string,
|
|
|
|
items: SelectionItem<T>[]
|
2020-09-07 05:21:53 +00:00
|
|
|
} | SelectionItem<T>>,
|
|
|
|
onItemSelected?: (item: T) => void;
|
|
|
|
allowUserSelect?: boolean;
|
2020-09-02 15:00:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface SelectionItem<T> {
|
|
|
|
label: string,
|
|
|
|
keywords: string,
|
|
|
|
item: T,
|
|
|
|
id: string | number,
|
2020-09-07 05:21:53 +00:00
|
|
|
color?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'light'
|
2020-09-02 15:00:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface LayoutState<T> {
|
|
|
|
selected: string | number;
|
|
|
|
search: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
class Selection<T> extends React.Component<SelecitonProps<T>, LayoutState<T>> {
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
search: '',
|
|
|
|
selected: null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function to Filter the Selection.
|
|
|
|
* @param search The Search Term.
|
|
|
|
*/
|
|
|
|
protected _filter(search: string) {
|
|
|
|
this.setState({
|
|
|
|
search: search.toLocaleLowerCase(),
|
|
|
|
selected: this.state.selected
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function used to Select an item
|
|
|
|
* @param item which will be selected
|
|
|
|
*/
|
|
|
|
protected _select(item: SelectionItem<T>) {
|
|
|
|
this.setState({
|
|
|
|
search: this.state.search,
|
2020-09-07 05:21:53 +00:00
|
|
|
selected: this.props.allowUserSelect ? item.id : -1
|
2020-09-02 15:00:03 +00:00
|
|
|
});
|
|
|
|
|
2020-09-07 05:21:53 +00:00
|
|
|
if (this.props.allowUserSelect && typeof this.props.onItemSelected === "function") {
|
|
|
|
this.props.onItemSelected(item.item);
|
2020-09-02 15:00:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public render() {
|
|
|
|
const _this = this;
|
|
|
|
|
|
|
|
// Filter only Valid items.
|
|
|
|
// Therefore iterate over the Groups and
|
|
|
|
// Filter the Items with the Search String
|
|
|
|
// and there Labels / Keywords.
|
|
|
|
// Afterwards filter the groups and remove
|
|
|
|
// Empty Groups
|
|
|
|
const items = deepClone(this.props).selection.map(item => {
|
2020-09-07 05:21:53 +00:00
|
|
|
|
|
|
|
if ((item as {
|
|
|
|
groupName: string,
|
|
|
|
items: SelectionItem<T>[]
|
|
|
|
}).items !== undefined) {
|
|
|
|
|
|
|
|
// Filter the Items, that match the Selection
|
|
|
|
(item as {
|
|
|
|
groupName: string,
|
|
|
|
items: SelectionItem<T>[]
|
|
|
|
}).items = (item as {
|
|
|
|
groupName: string,
|
|
|
|
items: SelectionItem<T>[]
|
|
|
|
}).items.filter(value =>
|
|
|
|
// Filter the Keywords
|
|
|
|
value.keywords.toLowerCase().includes(_this.state.search) ||
|
|
|
|
// Filter the Lable.
|
|
|
|
value.label.toLowerCase().includes(_this.state.search)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-09-02 15:00:03 +00:00
|
|
|
// Return the Item
|
|
|
|
return item;
|
|
|
|
}).filter(
|
2020-09-07 05:21:53 +00:00
|
|
|
item => {
|
2020-09-02 15:00:03 +00:00
|
|
|
// Filter the Element by the lenght of the contained elements.
|
2020-09-07 05:21:53 +00:00
|
|
|
if ((item as {
|
|
|
|
groupName: string,
|
|
|
|
items: SelectionItem<T>[]
|
|
|
|
}).items !== undefined) {
|
|
|
|
// Filter the Keywords
|
|
|
|
return (item as {
|
|
|
|
groupName: string,
|
|
|
|
items: SelectionItem<T>[]
|
|
|
|
}).items.length > 0;
|
|
|
|
} else {
|
|
|
|
// Filter the Keywords
|
|
|
|
return (item as SelectionItem<T>).keywords.toLowerCase().includes(_this.state.search) ||
|
|
|
|
// Filter the Lable.
|
|
|
|
(item as SelectionItem<T>).label.toLowerCase().includes(_this.state.search)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-02 15:00:03 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
let idx = 0;
|
|
|
|
return (<>
|
|
|
|
{/* A Search Field. */}
|
2020-09-07 05:21:53 +00:00
|
|
|
{this.props.allowUserSelect ?
|
|
|
|
<InputGroup size="sm" className="mb-3">
|
|
|
|
<InputGroup.Prepend>
|
|
|
|
<InputGroup.Text id="inputGroup-sizing-sm" >Search</InputGroup.Text>
|
|
|
|
</InputGroup.Prepend>
|
|
|
|
<FormControl aria-label="Small" aria-describedby="inputGroup-sizing-sm" onChange={(event) => {
|
|
|
|
_this._filter(event.currentTarget.value);
|
|
|
|
}} />
|
|
|
|
</InputGroup> : ''
|
|
|
|
}
|
2020-09-02 15:00:03 +00:00
|
|
|
{
|
|
|
|
items.length > 0 ?
|
|
|
|
items.map(item => {
|
|
|
|
idx++;
|
2020-09-07 05:21:53 +00:00
|
|
|
|
|
|
|
if ((item as {
|
|
|
|
groupName: string,
|
|
|
|
items: SelectionItem<T>[]
|
|
|
|
}).items !== undefined) {
|
|
|
|
return (
|
|
|
|
<div key={idx}>
|
|
|
|
<hr />
|
|
|
|
<h4>{(item as {
|
|
|
|
groupName: string,
|
|
|
|
items: SelectionItem<T>[]
|
|
|
|
}).groupName}</h4>
|
|
|
|
<hr />
|
|
|
|
<ListGroup>
|
|
|
|
{(item as {
|
|
|
|
groupName: string,
|
|
|
|
items: SelectionItem<T>[]
|
|
|
|
}).items.map(template => {
|
|
|
|
// Raise the ID
|
|
|
|
idx++;
|
|
|
|
// Store the Item Index
|
|
|
|
const idxOfItem = idx;
|
|
|
|
|
|
|
|
// Based on the selected Item assign the Color
|
|
|
|
// dark = selected
|
|
|
|
// light = unselected
|
|
|
|
const variant = _this.props.allowUserSelect ?
|
|
|
|
(template.id === _this.state.selected ? "dark" : "light") :
|
|
|
|
template.color || 'light';
|
|
|
|
|
|
|
|
// Return the Template variant={variant}
|
|
|
|
return (
|
|
|
|
<ListGroup.Item key={idxOfItem} action variant={variant} onClick={e => {
|
|
|
|
_this._select(template)
|
|
|
|
}}>{template.label}</ListGroup.Item>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</ListGroup>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
// Store the Item Index
|
|
|
|
const idxOfItem = idx;
|
|
|
|
|
|
|
|
// Based on the selected Item assign the Color
|
|
|
|
// dark = selected
|
|
|
|
// light = unselected
|
|
|
|
const variant = _this.props.allowUserSelect ?
|
|
|
|
((item as SelectionItem<T>).id === _this.state.selected ? "dark" : "light") :
|
|
|
|
(item as SelectionItem<T>).color || 'light';
|
|
|
|
// Return the Template variant={variant}
|
|
|
|
return (
|
|
|
|
<ListGroup.Item key={idxOfItem} action variant={variant} onClick={e => {
|
|
|
|
_this._select(item as SelectionItem<T>)
|
|
|
|
}}>{(item as SelectionItem<T>).label}</ListGroup.Item>
|
|
|
|
)
|
|
|
|
}
|
2020-09-02 15:00:03 +00:00
|
|
|
}) :
|
|
|
|
<code>Nothing Found</code>
|
|
|
|
}
|
|
|
|
</>);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Selection;
|