summaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/framework/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'sdnr/wt/odlux/framework/src/components')
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/index.tsx3
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx6
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/index.ts2
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx102
-rw-r--r--sdnr/wt/odlux/framework/src/components/navigationMenu.tsx7
5 files changed, 67 insertions, 53 deletions
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/index.tsx b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
index b85319b40..a80a5a58d 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
@@ -105,6 +105,7 @@ export type MaterialTableComponentState<TData = {}> = {
export type TableApi = { forceRefresh?: () => Promise<void> };
type MaterialTableComponentBaseProps<TData> = WithStyles<typeof styles> & {
+ className?: string;
columns: ColumnModel<TData>[];
idProperty: keyof TData | ((data: TData) => React.Key);
tableId?: string;
@@ -187,7 +188,7 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
const getId = typeof this.props.idProperty !== "function" ? (data: TData) => ((data as { [key: string]: any })[this.props.idProperty as any as string] as string | number) : this.props.idProperty;
const toggleFilter = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.onToggleFilter : () => { !this.props.disableFilter && this.setState({ showFilter: !showFilter }, this.update) }
return (
- <Paper className={classes.root}>
+ <Paper className={this.props.className ? `${classes.root} ${this.props.className}` : classes.root}>
<TableContainer className={classes.container}>
<TableToolbar tableId={this.props.tableId} numSelected={selected && selected.length} title={this.props.title} customActionButtons={this.props.customActionButtons} onExportToCsv={this.exportToCsv}
onToggleFilter={toggleFilter} />
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
index 8ea0a93f4..464350a62 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
@@ -61,7 +61,7 @@ class EnhancedTableFilterComponent extends React.Component<IEnhancedTableFilterC
</TableCell>
: null
}
- {columns.map(col => {
+ {columns.map((col, ind) => {
const style = col.width ? { width: col.width } : {};
return (
<TableCell
@@ -73,14 +73,14 @@ class EnhancedTableFilterComponent extends React.Component<IEnhancedTableFilterC
{col.disableFilter || (col.type === ColumnType.custom)
? null
: (col.type === ColumnType.boolean)
- ? <Select className={classes.input} aria-label={(col.title as string).toLowerCase() + ' filter'} value={filter[col.property] !== undefined ? filter[col.property] : ''} onChange={this.createFilterHandler(col.property)} inputProps={{ name: `${col.property}-bool`, id: `${col.property}-bool` }} >
+ ? <Select className={classes.input} aria-label={col.title ? (col.title as string).toLowerCase() + ' filter' : `${ind + 1}-filter`} value={filter[col.property] !== undefined ? filter[col.property] : ''} onChange={this.createFilterHandler(col.property)} inputProps={{ name: `${col.property}-bool`, id: `${col.property}-bool` }} >
<MenuItem value={undefined} >
<em>None</em>
</MenuItem>
<MenuItem value={true as any as string}>{col.labels ? col.labels["true"] : "true"}</MenuItem>
<MenuItem value={false as any as string}>{col.labels ? col.labels["false"] : "false"}</MenuItem>
</Select>
- : <Input className={classes.input} inputProps={{ 'aria-label': (col.title as string).toLowerCase() + ' filter' }} value={filter[col.property] || ''} onChange={this.createFilterHandler(col.property)} />}
+ : <Input className={classes.input} inputProps={{ 'aria-label': col.title ? (col.title as string).toLowerCase() + ' filter' : `${ind + 1}-filter` }} value={filter[col.property] || ''} onChange={this.createFilterHandler(col.property)} />}
</TableCell>
);
}, this)}
diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/index.ts b/sdnr/wt/odlux/framework/src/components/material-ui/index.ts
index e0e3fc943..096e4439d 100644
--- a/sdnr/wt/odlux/framework/src/components/material-ui/index.ts
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/index.ts
@@ -18,5 +18,5 @@
export { ListItemLink } from './listItemLink';
export { Panel } from './panel';
export { ToggleButton, ToggleButtonClassKey } from './toggleButton';
-export { TreeView, ITreeItem, TreeViewCtorType} from './treeView';
+export { TreeView, TreeItem, TreeViewCtorType} from './treeView';
export { Loader } from './loader';
diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
index e4eb3a794..98ee291d1 100644
--- a/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
@@ -16,33 +16,49 @@
* ============LICENSE_END==========================================================================
*/
import * as React from 'react';
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
-import { SvgIconProps } from '@material-ui/core/SvgIcon';
import { List, ListItem, TextField, ListItemText, ListItemIcon, WithTheme, withTheme, Omit } from '@material-ui/core';
+import { SvgIconProps } from '@material-ui/core/SvgIcon';
import FileIcon from '@material-ui/icons/InsertDriveFile';
import CloseIcon from '@material-ui/icons/ExpandLess';
import OpenIcon from '@material-ui/icons/ExpandMore';
import FolderIcon from '@material-ui/icons/Folder';
-export interface ITreeItem {
+const styles = (theme: Theme) => createStyles({
+ root: {
+ padding: 0,
+ paddingBottom: 8,
+ paddingTop: 8,
+ },
+ search: {
+ padding: `0px ${theme.spacing(1)}px`
+ }
+});
+
+export type TreeItem<TData = { }> = {
disabled?: boolean;
icon?: React.ComponentType<SvgIconProps>;
+ iconClass?: string;
+ content: string;
+ contentClass?: string;
+ children?: TreeItem<TData>[];
+ value?: TData;
}
-type TreeViewComponentState<TData extends ITreeItem = ITreeItem> = {
+type TreeViewComponentState<TData = { }> = {
/** All indices of all expanded Items */
- expandedItems: TData[];
+ expandedItems: TreeItem<TData>[];
/** The index of the active iten or undefined if no item is active. */
- activeItem: undefined | TData;
+ activeItem: undefined | TreeItem<TData>;
/** The search term or undefined if search is corrently not active. */
searchTerm: undefined | string;
}
-type TreeViewComponentBaseProps<TData extends ITreeItem = ITreeItem> = WithTheme & {
- items: TData[];
- contentProperty: keyof Omit<TData, keyof ITreeItem>;
- childrenProperty: keyof Omit<TData, keyof ITreeItem>;
+type TreeViewComponentBaseProps<TData = {}> = WithTheme & WithStyles<typeof styles> & {
+ className?: string;
+ items: TreeItem<TData>[];
useFolderIcons?: boolean;
enableSearchBar?: boolean;
autoExpandFolder?: boolean;
@@ -51,23 +67,23 @@ type TreeViewComponentBaseProps<TData extends ITreeItem = ITreeItem> = WithTheme
depthOffset?: number;
}
-type TreeViewComponentWithInternalStateProps<TData extends ITreeItem = ITreeItem> = TreeViewComponentBaseProps<TData> & {
- onItemClick?: (item: TData) => void;
- onFolderClick?: (item: TData) => void;
+type TreeViewComponentWithInternalStateProps<TData = { }> = TreeViewComponentBaseProps<TData> & {
+ onItemClick?: (item: TreeItem<TData>) => void;
+ onFolderClick?: (item: TreeItem<TData>) => void;
}
-type TreeViewComponentWithExternalStateProps<TData extends ITreeItem = ITreeItem> = TreeViewComponentBaseProps<TData> & TreeViewComponentState<TData> & {
+type TreeViewComponentWithExternalStateProps<TData = { }> = TreeViewComponentBaseProps<TData> & TreeViewComponentState<TData> & {
onSearch: (searchTerm: string) => void;
- onItemClick: (item: TData) => void;
- onFolderClick: (item: TData) => void;
+ onItemClick: (item: TreeItem<TData>) => void;
+ onFolderClick: (item: TreeItem<TData>) => void;
}
-type TreeViewComponentProps<TData extends ITreeItem = ITreeItem> =
- TreeViewComponentWithInternalStateProps<TData> |
- TreeViewComponentWithExternalStateProps<TData>;
+type TreeViewComponentProps<TData = { }> =
+ | TreeViewComponentWithInternalStateProps<TData>
+ | TreeViewComponentWithExternalStateProps<TData>;
-function isTreeViewComponentWithExternalStateProps<TData extends ITreeItem = ITreeItem>(props: TreeViewComponentProps<TData>): props is TreeViewComponentWithExternalStateProps<TData> {
- const propsWithExternalState = (props as TreeViewComponentWithExternalStateProps<TData>)
+function isTreeViewComponentWithExternalStateProps(props: TreeViewComponentProps): props is TreeViewComponentWithExternalStateProps {
+ const propsWithExternalState = (props as TreeViewComponentWithExternalStateProps)
return (
propsWithExternalState.onSearch instanceof Function ||
propsWithExternalState.expandedItems !== undefined ||
@@ -76,7 +92,7 @@ function isTreeViewComponentWithExternalStateProps<TData extends ITreeItem = ITr
);
}
-class TreeViewComponent<TData extends ITreeItem> extends React.Component<TreeViewComponentProps<TData>, TreeViewComponentState> {
+class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentProps<TData>, TreeViewComponentState<TData>> {
/**
* Initializes a new instance.
@@ -95,21 +111,11 @@ class TreeViewComponent<TData extends ITreeItem> extends React.Component<TreeVie
this.itemIndex = 0;
const { searchTerm } = this.state;
const { children, items, enableSearchBar } = this.props;
- const styles = {
- root: {
- padding: 0,
- paddingBottom: 8,
- paddingTop: children ? 0 : 8,
- ...this.props.style
- },
- search: {
- padding: `0px ${this.props.theme.spacing(1)}px`
- }
- };
+
return (
- <div style={styles.root}>
+ <div className={this.props.className ? `${this.props.classes.root} ${this.props.className}` : this.props.classes.root} style={this.props.style}>
{children}
- {enableSearchBar && <TextField label={"Search"} fullWidth={true} style={styles.search} value={searchTerm} onChange={this.onChangeSearchText} /> || null}
+ {enableSearchBar && <TextField label={"Search"} fullWidth={true} className={ this.props.classes.search } value={searchTerm} onChange={this.onChangeSearchText} /> || null}
<List>
{this.renderItems(items, searchTerm && searchTerm.toLowerCase())}
</List>
@@ -118,30 +124,30 @@ class TreeViewComponent<TData extends ITreeItem> extends React.Component<TreeVie
}
private itemIndex: number = 0;
- private renderItems = (items: TData[], searchTerm: string | undefined, depth: number = 1) => {
+ private renderItems = (items: TreeItem<TData>[], searchTerm: string | undefined, depth: number = 1) => {
return items.reduce((acc, item) => {
- const children = this.props.childrenProperty && ((item as any)[this.props.childrenProperty] as TData[]);
+ const children = item.children; // this.props.childrenProperty && ((item as any)[this.props.childrenProperty] as TData[]);
const childrenJsx = children && this.renderItems(children, searchTerm, depth + 1);
const expanded = searchTerm
- ? children && childrenJsx.length > 0
+ ? childrenJsx && childrenJsx.length > 0
: !children
? false
: this.state.expandedItems.indexOf(item) > -1;
const isFolder = children !== undefined;
- const itemJsx = this.renderItem(item, searchTerm, depth, isFolder, expanded);
+ const itemJsx = this.renderItem(item, searchTerm, depth, isFolder, expanded || false);
itemJsx && acc.push(itemJsx);
- if (isFolder && expanded) {
+ if (isFolder && expanded && childrenJsx) {
acc.push(...childrenJsx);
}
return acc;
}, [] as JSX.Element[]);
}
- private renderItem = (item: TData, searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean): JSX.Element | null => {
+ private renderItem = (item: TreeItem<TData>, searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean): JSX.Element | null => {
const styles = {
item: {
paddingLeft: (((this.props.depthOffset || 0) + depth) * this.props.theme.spacing(3)),
@@ -154,7 +160,7 @@ class TreeViewComponent<TData extends ITreeItem> extends React.Component<TreeVie
}
};
- const text = (item as any)[this.props.contentProperty] as string || ''; // need to keep track of search
+ const text = item.content || ''; // need to keep track of search
const matchIndex = searchTerm ? text.toLowerCase().indexOf(searchTerm) : -1;
const searchTermLength = searchTerm && searchTerm.length || 0;
@@ -175,7 +181,7 @@ class TreeViewComponent<TData extends ITreeItem> extends React.Component<TreeVie
{ // display the left icon
(this.props.useFolderIcons && <ListItemIcon>{isFolder ? <FolderIcon /> : <FileIcon />}</ListItemIcon>) ||
- (item.icon && (<ListItemIcon><item.icon /></ListItemIcon>))}
+ (item.icon && (<ListItemIcon className={ item.iconClass }><item.icon /></ListItemIcon>))}
{ // highlight search result
@@ -193,10 +199,10 @@ class TreeViewComponent<TData extends ITreeItem> extends React.Component<TreeVie
</span>
{text.substring(matchIndex + searchTermLength)}
</span>)
- : (<ListItemText primary={text} />)
+ : (<ListItemText className={ item.contentClass } primary={text} />)
}
- { // display the right icon, depending on the state
+ { // display the right icon, depending on the state
!isFolder ? null : expanded ? (<OpenIcon onClick={handleClickCreator(true)} />) : (<CloseIcon onClick={handleClickCreator(true)} />)}
</ListItem>
)
@@ -204,7 +210,7 @@ class TreeViewComponent<TData extends ITreeItem> extends React.Component<TreeVie
);
}
- private onFolderClick = (item: TData) => {
+ private onFolderClick = (item: TreeItem<TData>) => {
// toggle items with children
if (this.state.searchTerm) return;
const indexOfItemToToggle = this.state.expandedItems.indexOf(item);
@@ -222,7 +228,7 @@ class TreeViewComponent<TData extends ITreeItem> extends React.Component<TreeVie
}
};
- private onItemClick = (item: TData) => {
+ private onItemClick = (item: TreeItem<TData>) => {
// activate items without children
this.setState({
activeItem: item,
@@ -262,7 +268,7 @@ class TreeViewComponent<TData extends ITreeItem> extends React.Component<TreeVie
}
}
-export type TreeViewCtorType<TData extends ITreeItem = ITreeItem> = new () => React.Component<Omit<TreeViewComponentProps<TData>, 'theme'>>;
+export type TreeViewCtorType<TData = { }> = new () => React.Component<Omit<TreeViewComponentProps<TData>, 'theme'|'classes'>>;
-export const TreeView = withTheme(TreeViewComponent);
+export const TreeView = withTheme(withStyles(styles)(TreeViewComponent));
export default TreeView; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
index fee51621e..233c2fd61 100644
--- a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
+++ b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
@@ -133,6 +133,13 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di
}
<Divider />
<ListItemLink to="/about" primary="About" icon={<FontAwesomeIcon icon={faAddressBook} />} />
+ {(false && process.env.NODE_ENV === "development")
+ ? <>
+ <Divider />
+ <ListItemLink to="/test" primary="Test" icon={<FontAwesomeIcon icon={faHome} />} />
+ </>
+ : null
+ }
</List>
</> || null
}