nope/resources/ui/layout/selection.tsx

204 lines
7.8 KiB
TypeScript
Raw Normal View History

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 {
item.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 />
<h4>{(item as {
groupName: string,
2020-10-29 18:20:42 +00:00
items: ISelectionItem<T>[]
2020-09-07 05:21:53 +00:00
}).groupName}</h4>
<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;