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';
|
2020-10-29 18:20:42 +00:00
|
|
|
import { ISelection } from './interfaces/ISelection';
|
|
|
|
import { ISelectionItem } from './interfaces/ISelectionItem';
|
2020-09-02 15:00:03 +00:00
|
|
|
|
2020-10-29 18:20:42 +00:00
|
|
|
export interface SelectionProps<T> {
|
|
|
|
selection: ISelection<T>;
|
2020-09-07 05:21:53 +00:00
|
|
|
onItemSelected?: (item: T) => void;
|
|
|
|
allowUserSelect?: boolean;
|
2020-09-02 15:00:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface LayoutState<T> {
|
|
|
|
selected: string | number;
|
|
|
|
search: string;
|
|
|
|
}
|
|
|
|
|
2020-10-29 18:20:42 +00:00
|
|
|
class Selection<T> extends React.Component<SelectionProps<T>, LayoutState<T>> {
|
|
|
|
|
|
|
|
private _currentId = 0;
|
|
|
|
|
|
|
|
_generateId(){
|
|
|
|
const id = this._currentId;
|
|
|
|
this._currentId += 1;
|
|
|
|
return id;
|
|
|
|
}
|
2020-09-02 15:00:03 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
*/
|
2020-10-29 18:20:42 +00:00
|
|
|
protected _select(item: ISelectionItem<T>) {
|
|
|
|
console.log('select item',item)
|
2020-09-02 15:00:03 +00:00
|
|
|
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") {
|
2020-10-29 18:20:42 +00:00
|
|
|
this.props.onItemSelected(item.template);
|
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,
|
2020-10-29 18:20:42 +00:00
|
|
|
items: ISelectionItem<T>[]
|
2020-09-07 05:21:53 +00:00
|
|
|
}).items !== undefined) {
|
|
|
|
|
|
|
|
// Filter the Items, that match the Selection
|
|
|
|
(item as {
|
|
|
|
groupName: string,
|
2020-10-29 18:20:42 +00:00
|
|
|
items: ISelectionItem<T>[]
|
2020-09-07 05:21:53 +00:00
|
|
|
}).items = (item as {
|
|
|
|
groupName: string,
|
2020-10-29 18:20:42 +00:00
|
|
|
items: ISelectionItem<T>[]
|
|
|
|
}).items.map(item => {
|
|
|
|
item.id = _this._generateId();
|
|
|
|
return item;
|
|
|
|
}).filter(value =>
|
2020-09-07 05:21:53 +00:00
|
|
|
// Filter the Keywords
|
|
|
|
value.keywords.toLowerCase().includes(_this.state.search) ||
|
|
|
|
// Filter the Lable.
|
|
|
|
value.label.toLowerCase().includes(_this.state.search)
|
|
|
|
);
|
2020-10-29 18:20:42 +00:00
|
|
|
} else {
|
2020-10-30 18:30:59 +00:00
|
|
|
(item as any).id = _this._generateId();
|
2020-09-07 05:21:53 +00:00
|
|
|
}
|
|
|
|
|
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,
|
2020-10-29 18:20:42 +00:00
|
|
|
items: ISelectionItem<T>[]
|
2020-09-07 05:21:53 +00:00
|
|
|
}).items !== undefined) {
|
|
|
|
// Filter the Keywords
|
|
|
|
return (item as {
|
|
|
|
groupName: string,
|
2020-10-29 18:20:42 +00:00
|
|
|
items: ISelectionItem<T>[]
|
2020-09-07 05:21:53 +00:00
|
|
|
}).items.length > 0;
|
|
|
|
} else {
|
|
|
|
// Filter the Keywords
|
2020-10-29 18:20:42 +00:00
|
|
|
return (item as ISelectionItem<T>).keywords.toLowerCase().includes(_this.state.search) ||
|
2020-09-07 05:21:53 +00:00
|
|
|
// Filter the Lable.
|
2020-10-29 18:20:42 +00:00
|
|
|
(item as ISelectionItem<T>).label.toLowerCase().includes(_this.state.search)
|
2020-09-07 05:21:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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,
|
2020-10-29 18:20:42 +00:00
|
|
|
items: ISelectionItem<T>[]
|
2020-09-07 05:21:53 +00:00
|
|
|
}).items !== undefined) {
|
|
|
|
return (
|
|
|
|
<div key={idx}>
|
|
|
|
<hr />
|
2020-10-30 18:30:59 +00:00
|
|
|
{(item as {
|
2020-09-07 05:21:53 +00:00
|
|
|
groupName: string,
|
2020-10-29 18:20:42 +00:00
|
|
|
items: ISelectionItem<T>[]
|
2020-10-30 18:30:59 +00:00
|
|
|
}).groupName}
|
2020-09-07 05:21:53 +00:00
|
|
|
<hr />
|
|
|
|
<ListGroup>
|
|
|
|
{(item as {
|
|
|
|
groupName: string,
|
2020-10-29 18:20:42 +00:00
|
|
|
items: ISelectionItem<T>[]
|
2020-09-07 05:21:53 +00:00
|
|
|
}).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 ?
|
2020-10-29 18:20:42 +00:00
|
|
|
((item as ISelectionItem<T>).id === _this.state.selected ? "dark" : "light") :
|
|
|
|
(item as ISelectionItem<T>).color || 'light';
|
2020-09-07 05:21:53 +00:00
|
|
|
// Return the Template variant={variant}
|
|
|
|
return (
|
|
|
|
<ListGroup.Item key={idxOfItem} action variant={variant} onClick={e => {
|
2020-10-29 18:20:42 +00:00
|
|
|
_this._select(item as ISelectionItem<T>)
|
|
|
|
}}>{(item as ISelectionItem<T>).label}</ListGroup.Item>
|
2020-09-07 05:21:53 +00:00
|
|
|
)
|
|
|
|
}
|
2020-09-02 15:00:03 +00:00
|
|
|
}) :
|
|
|
|
<code>Nothing Found</code>
|
|
|
|
}
|
|
|
|
</>);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Selection;
|