Creating Inital Layout Element
This commit is contained in:
parent
a13f85c18f
commit
b90f39f00c
File diff suppressed because one or more lines are too long
@ -7,8 +7,9 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Col, Container, Row } from 'react-bootstrap';
|
||||
import LocalNavbar from '../navbar';
|
||||
import { ListGroup, Container, Row, Col, InputGroup, FormControl } from 'react-bootstrap';
|
||||
import Selection, { SelecitonProps } from './selection';
|
||||
|
||||
const mainStyle = {
|
||||
minHeight: '90vh',
|
||||
@ -23,29 +24,67 @@ const contentStyle = {
|
||||
padding: '10px',
|
||||
}
|
||||
|
||||
export default () => (
|
||||
<>
|
||||
export interface LayoutProps<T> extends SelecitonProps<T> {
|
||||
onResize?: () => void;
|
||||
onMount?: (_ref: React.RefObject<any>) => void;
|
||||
onUnmount?: () => void;
|
||||
}
|
||||
|
||||
export interface LayoutState<T> {
|
||||
}
|
||||
|
||||
class Layout<T> extends React.Component<LayoutProps<T>, LayoutState<T>> {
|
||||
|
||||
protected _ref: React.RefObject<any>;
|
||||
protected _handleResize: () => void;
|
||||
|
||||
componentDidMount() {
|
||||
const _this = this;
|
||||
|
||||
function handleResize() {
|
||||
if (typeof _this.props.onResize === 'function') {
|
||||
_this.props.onResize();
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof this.props.onMount === 'function') {
|
||||
this.props.onMount(this._ref);
|
||||
}
|
||||
|
||||
this._handleResize = handleResize;
|
||||
window.addEventListener('resize', this._handleResize);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('resize', this._handleResize);
|
||||
|
||||
// Call the unmount
|
||||
if (typeof this.props.onUnmount === 'function') {
|
||||
this.props.onUnmount();
|
||||
}
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this._ref = React.createRef();
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (<>
|
||||
<LocalNavbar></LocalNavbar>
|
||||
<Container fluid style={mainStyle}>
|
||||
<Row style={mainStyle}>
|
||||
<Col className="col-md-2 d-none d-md-block bg-light sidebar-sticky" style={sidebarStyle}>
|
||||
{/* A Search Field. */}
|
||||
<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" />
|
||||
</InputGroup>
|
||||
<ListGroup>
|
||||
<ListGroup.Item>Cras justo odio</ListGroup.Item>
|
||||
<ListGroup.Item>Dapibus ac facilisis in</ListGroup.Item>
|
||||
<ListGroup.Item>Morbi leo risus</ListGroup.Item>
|
||||
<ListGroup.Item>Porta ac consectetur ac</ListGroup.Item>
|
||||
<ListGroup.Item>Vestibulum at eros</ListGroup.Item>
|
||||
</ListGroup>
|
||||
<Selection selection={this.props.selection} ></Selection>
|
||||
</Col>
|
||||
<Col role="main" style={contentStyle}>
|
||||
{/* style={{height: '100%'}} */}
|
||||
<div ref={this._ref}></div>
|
||||
</Col>
|
||||
<Col role="main" style={contentStyle}>Content</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
</>);
|
||||
}
|
||||
}
|
||||
|
||||
export default Layout;
|
135
pages/ui/layout/selection.tsx
Normal file
135
pages/ui/layout/selection.tsx
Normal file
@ -0,0 +1,135 @@
|
||||
import React from 'react';
|
||||
import { FormControl, InputGroup, ListGroup } from 'react-bootstrap';
|
||||
import { deepClone } from '../../../lib/helpers/objectMethods';
|
||||
|
||||
export interface SelecitonProps<T> {
|
||||
selection: {
|
||||
groupName: string,
|
||||
items: SelectionItem<T>[]
|
||||
}[],
|
||||
onSelect?: (item: T) => void;
|
||||
}
|
||||
|
||||
export interface SelectionItem<T> {
|
||||
label: string,
|
||||
keywords: string,
|
||||
item: T,
|
||||
id: string | number,
|
||||
}
|
||||
|
||||
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,
|
||||
selected: item.id
|
||||
});
|
||||
|
||||
if (typeof this.props.onSelect === "function") {
|
||||
this.props.onSelect(item.item);
|
||||
}
|
||||
}
|
||||
|
||||
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 => {
|
||||
// Filter the Items, that match the Selection
|
||||
item.items = item.items.filter(value =>
|
||||
// Filter the Keywords
|
||||
value.keywords.toLowerCase().includes(_this.state.search) ||
|
||||
// Filter the Lable.
|
||||
value.label.toLowerCase().includes(_this.state.search)
|
||||
);
|
||||
// Return the Item
|
||||
return item;
|
||||
}).filter(
|
||||
item =>
|
||||
// Filter the Element by the lenght of the contained elements.
|
||||
item.items.length > 0
|
||||
);
|
||||
|
||||
let idx = 0;
|
||||
return (<>
|
||||
{/* A Search Field. */}
|
||||
<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>
|
||||
{
|
||||
items.length > 0 ?
|
||||
items.map(item => {
|
||||
idx++;
|
||||
return (
|
||||
<div key={idx}>
|
||||
<hr />
|
||||
<h4>{item.groupName}</h4>
|
||||
<hr />
|
||||
<ListGroup>
|
||||
{item.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 = template.id === _this.state.selected ? "dark" : "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>
|
||||
);
|
||||
}) :
|
||||
<code>Nothing Found</code>
|
||||
}
|
||||
</>);
|
||||
}
|
||||
}
|
||||
|
||||
export default Selection;
|
18
pages/ui/layout/toolbar.tsx
Normal file
18
pages/ui/layout/toolbar.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface ToolbarProps {
|
||||
|
||||
}
|
||||
|
||||
export interface ToolbarState {
|
||||
|
||||
}
|
||||
|
||||
class Toolbar extends React.Component<ToolbarProps, ToolbarState> {
|
||||
|
||||
render() {
|
||||
return ( );
|
||||
}
|
||||
}
|
||||
|
||||
export default Toolbar;
|
Loading…
Reference in New Issue
Block a user