diff options
author | Aijana Schumann <aijana.schumann@highstreet-technologies.com> | 2020-02-28 15:15:26 +0100 |
---|---|---|
committer | Aijana Schumann <aijana.schumann@highstreet-technologies.com> | 2020-02-28 15:15:26 +0100 |
commit | 889c7fbc0f78eadc302e8849ea7e6cad795e0d6e (patch) | |
tree | da4cb3a08d06520497f1ed584fbdf70afcc22edb /sdnr/wt/odlux/framework/src | |
parent | 4eed58ba1a434261510c996316d2d201a40eb760 (diff) |
update odlux stage 3
PerformanceApp: Add filter to chart view
add scrolling header to tables, add basic validation to editNetworkElementDialog
bugfixes
Issue-ID: SDNC-1087
Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
Change-Id: I585bd6cfeb11b867cd630e96e6479170d2f92fe8
Diffstat (limited to 'sdnr/wt/odlux/framework/src')
6 files changed, 77 insertions, 68 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
}
diff --git a/sdnr/wt/odlux/framework/src/views/test.tsx b/sdnr/wt/odlux/framework/src/views/test.tsx index 68b189340..763b79a1f 100644 --- a/sdnr/wt/odlux/framework/src/views/test.tsx +++ b/sdnr/wt/odlux/framework/src/views/test.tsx @@ -27,7 +27,7 @@ import Typography from '@material-ui/core/Typography'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { MaterialTable, MaterialTableCtorType, ColumnType } from '../components/material-table'; -import { TreeView, ITreeItem, TreeViewCtorType } from '../components/material-ui/treeView'; +import { TreeView, TreeItem, TreeViewCtorType } from '../components/material-ui/treeView'; import { SvgIconProps } from '@material-ui/core/SvgIcon'; const styles = (theme: Theme) => createStyles({ @@ -814,30 +814,25 @@ const components = { 'counter': 'demoApp.counter' }; -class TreeDemoItem implements ITreeItem { - title: string; - children?: TreeDemoItem[]; - disabled?: boolean; - icon?: React.ComponentType<SvgIconProps>; -} +type TreeDemoItem = TreeItem<string>; const treeData: TreeDemoItem[] = [ { - title: "Erste Ebene", children: [ + content: "Erste Ebene", children: [ { - title: "Zweite Ebene", children: [ - { title: "Dritte Ebene" }, + content: "Zweite Ebene", children: [ + { content: "Dritte Ebene" }, ] }, - { title: "Zweite Ebene 2" }, + { content: "Zweite Ebene 2" }, ] }, - { title: "Erste Ebene 3" }, + { content: "Erste Ebene 3" }, ]; const SampleDataMaterialTable = MaterialTable as MaterialTableCtorType<SampleData>; -const SampleTree = TreeView as any as TreeViewCtorType<TreeDemoItem>; +const SampleTree = TreeView as any as TreeViewCtorType<string>; const TestComponent = (props: WithComponents<typeof components> & WithStyles<typeof styles>) => { @@ -867,11 +862,11 @@ const TestComponent = (props: WithComponents<typeof components> & WithStyles<typ <Typography className={props.classes.heading}>Tree Demo</Typography> </ExpansionPanelSummary> <ExpansionPanelDetails> - <SampleTree items={treeData} contentProperty={"title"} childrenProperty={"children"} useFolderIcons enableSearchBar /> + <SampleTree items={treeData} useFolderIcons enableSearchBar /> </ExpansionPanelDetails> </ExpansionPanel> </div> - ) + ); }; export const Test = withComponents(components)(withStyles(styles)(TestComponent)); |