From 05da65b2d01a75404059d7526b4cbb868f631dd7 Mon Sep 17 00:00:00 2001
From: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
Date: Fri, 13 Mar 2020 10:39:11 +0100
Subject: Fix odlux bugs

Fix help and about app not scrollable

Fix filter hiding and showing without user interaction and default sort  in all tables

Issue-ID: SDNC-1117
Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
Change-Id: I5c6ff86c73a3b222a8d9022125454788496f6399
---
 .../src/components/material-ui/treeView.tsx        | 120 ++++++++++++++++-----
 1 file changed, 95 insertions(+), 25 deletions(-)

(limited to 'sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx')

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 98ee291d1..1bb49367c 100644
--- a/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
@@ -37,6 +37,11 @@ const styles = (theme: Theme) => createStyles({
   }
 });
 
+export enum SearchMode {
+  OnKeyDown = 1,
+  OnEnter =2
+}
+
 export type TreeItem<TData = { }> = {
   disabled?: boolean;
   icon?: React.ComponentType<SvgIconProps>;
@@ -47,13 +52,19 @@ export type TreeItem<TData = { }> = {
   value?: TData;
 }
 
+export type ExternalTreeItem<TData = {}> = TreeItem<TData> & {
+  isMatch?: boolean;
+}
+
+
 type TreeViewComponentState<TData = { }> = {
   /** All indices of all expanded Items */
-  expandedItems: TreeItem<TData>[];
+  expandedItems: ExternalTreeItem<TData>[];
   /** The index of the active iten or undefined if no item is active. */
-  activeItem: undefined | TreeItem<TData>;
+  activeItem?: ExternalTreeItem<TData>;
   /** The search term or undefined if search is corrently not active. */
-  searchTerm: undefined | string;
+  searchTerm?: string;
+  searchTermValue?: string;
 }
 
 type TreeViewComponentBaseProps<TData = {}> = WithTheme & WithStyles<typeof styles> & {
@@ -65,6 +76,7 @@ type TreeViewComponentBaseProps<TData = {}> = WithTheme & WithStyles<typeof styl
   style?: React.CSSProperties;
   itemHeight?: number;
   depthOffset?: number;
+  searchMode?: SearchMode;
 }
 
 type TreeViewComponentWithInternalStateProps<TData = { }> = TreeViewComponentBaseProps<TData> & {
@@ -72,7 +84,17 @@ type TreeViewComponentWithInternalStateProps<TData = { }> = TreeViewComponentBas
   onFolderClick?: (item: TreeItem<TData>) => void;
 }
 
-type TreeViewComponentWithExternalStateProps<TData = { }> = TreeViewComponentBaseProps<TData> & TreeViewComponentState<TData> & {
+type TreeViewComponentWithExternalSearchProps<TData = {}> = TreeViewComponentBaseProps<TData> & {
+  items: ExternalTreeItem<TData>[];
+  searchTerm: string;
+  onSearch: (searchTerm: string) => void;
+  onItemClick?: (item: TreeItem<TData>) => void;
+  onFolderClick?: (item: TreeItem<TData>) => void;
+}
+
+type TreeViewComponentWithExternalStateProps<TData = {}> = TreeViewComponentBaseProps<TData> & TreeViewComponentState<TData> & {
+  items: ExternalTreeItem<TData>[];
+  searchTerm: string;
   onSearch: (searchTerm: string) => void;
   onItemClick: (item: TreeItem<TData>) => void;
   onFolderClick: (item: TreeItem<TData>) => void;
@@ -80,14 +102,25 @@ type TreeViewComponentWithExternalStateProps<TData = { }> = TreeViewComponentBas
 
 type TreeViewComponentProps<TData = { }> =
   | TreeViewComponentWithInternalStateProps<TData>
+  | TreeViewComponentWithExternalSearchProps<TData>
   | TreeViewComponentWithExternalStateProps<TData>;
 
+function isTreeViewComponentWithExternalSearchProps(props: TreeViewComponentProps): props is TreeViewComponentWithExternalSearchProps {
+  const propsWithExternalState = (props as TreeViewComponentWithExternalStateProps)
+  return (
+    propsWithExternalState.onSearch instanceof Function &&
+    propsWithExternalState.onFolderClick === undefined &&
+    propsWithExternalState.expandedItems === undefined &&
+    propsWithExternalState.searchTerm !== undefined
+  );
+}
+
 function isTreeViewComponentWithExternalStateProps(props: TreeViewComponentProps): props is TreeViewComponentWithExternalStateProps {
   const propsWithExternalState = (props as TreeViewComponentWithExternalStateProps)
   return (
-    propsWithExternalState.onSearch instanceof Function ||
-    propsWithExternalState.expandedItems !== undefined ||
-    propsWithExternalState.activeItem !== undefined ||
+    propsWithExternalState.onSearch instanceof Function &&
+    propsWithExternalState.onFolderClick instanceof Function &&
+    propsWithExternalState.expandedItems !== undefined &&
     propsWithExternalState.searchTerm !== undefined
   );
 }
@@ -103,19 +136,20 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
     this.state = {
       expandedItems: [],
       activeItem: undefined,
-      searchTerm: undefined
+      searchTerm: undefined,
+      searchTermValue: undefined
     };
   }
 
   render(): JSX.Element {
     this.itemIndex = 0;
-    const { searchTerm } = this.state;
+    const { searchTerm , searchTermValue} = this.state;
     const { children, items, enableSearchBar } = this.props;
 
     return (
       <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} className={ this.props.classes.search } value={searchTerm} onChange={this.onChangeSearchText} /> || null}
+        {enableSearchBar && <TextField label={"Search"} fullWidth={true} className={this.props.classes.search} value={searchTermValue} onKeyDown={this.onSearchKeyDown} onChange={this.onChangeSearchText} /> || null}
         <List>
           {this.renderItems(items, searchTerm && searchTerm.toLowerCase())}
         </List>
@@ -124,20 +158,21 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
   }
 
   private itemIndex: number = 0;
-  private renderItems = (items: TreeItem<TData>[], searchTerm: string | undefined, depth: number = 1) => {
+  private renderItems = (items: TreeItem<TData>[], searchTerm: string | undefined, depth: number = 1, forceRender: boolean = true) => {
+
     return items.reduce((acc, item) => {
 
       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 childrenJsx = children && this.renderItems(children, searchTerm, depth + 1, this.state.expandedItems.indexOf(item) > -1);
 
-      const expanded = searchTerm
+      const expanded = !isTreeViewComponentWithExternalStateProps(this.props) && searchTerm
         ? 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 || false);
+      const itemJsx = this.renderItem(item, searchTerm, depth, isFolder, expanded || false, forceRender);
       itemJsx && acc.push(itemJsx);
 
       if (isFolder && expanded && childrenJsx) {
@@ -147,7 +182,7 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
 
     }, [] as JSX.Element[]);
   }
-  private renderItem = (item: TreeItem<TData>, searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean): JSX.Element | null => {
+  private renderItem = (item: ExternalTreeItem<TData>, searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean, forceRender: boolean): JSX.Element | null => {
     const styles = {
       item: {
         paddingLeft: (((this.props.depthOffset || 0) + depth) * this.props.theme.spacing(3)),
@@ -175,7 +210,7 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
       }
     };
 
-    return ((searchTerm && (matchIndex > -1 || expanded) || !searchTerm)
+    return ((searchTerm && (matchIndex > -1 || expanded || (!isTreeViewComponentWithExternalStateProps(this.props) && item.isMatch || depth === 1)) || !searchTerm || forceRender)
       ? (
         <ListItem key={`tree-list-${this.itemIndex++}`} style={styles.item} onClick={handleClickCreator(false)} button >
 
@@ -186,7 +221,7 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
 
           { // highlight search result
             matchIndex > -1
-              ? (<span>
+              ? <ListItemText className={item.contentClass} primary={(<span>
                 {text.substring(0, matchIndex)}
                 <span
                   style={{
@@ -198,8 +233,15 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
                   {text.substring(matchIndex, matchIndex + searchTermLength)}
                 </span>
                 {text.substring(matchIndex + searchTermLength)}
-              </span>)
-              : (<ListItemText className={ item.contentClass } primary={text} />)
+              </span>)} />
+              : <ListItemText className={item.contentClass} primary={(
+                <span style={item.isMatch ? {
+                  display: 'inline-block',
+                  backgroundColor: 'rgba(255,235,59,0.5)',
+                  padding: '3px',
+                } : undefined}>
+                  {text} </span>
+              )} />
           }
 
           { // display the right icon, depending on the state
@@ -235,16 +277,39 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
     });
   };
 
+  private onSearchKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
+    const enterMode = this.props.searchMode === SearchMode.OnEnter;
+
+    if (enterMode && event.keyCode === 13) {
+      event.preventDefault();
+      event.stopPropagation();
+
+      enterMode && this.setState({
+        searchTerm: this.state.searchTermValue
+      });
+
+      if (isTreeViewComponentWithExternalSearchProps(this.props) || isTreeViewComponentWithExternalStateProps(this.props)) {
+        this.props.onSearch(this.state.searchTermValue || "");
+      }
+    }
+  }
+
   private onChangeSearchText = (event: React.ChangeEvent<HTMLInputElement>) => {
     event.preventDefault();
     event.stopPropagation();
 
-    if (isTreeViewComponentWithExternalStateProps(this.props)) {
-      this.props.onSearch(event.target.value)
-    } else {
-      this.setState({
-        searchTerm: event.target.value
-      });
+    const keyDownMode = (!this.props.searchMode || this.props.searchMode === SearchMode.OnKeyDown);
+
+    this.setState(keyDownMode
+      ? {
+        searchTerm: event.target.value,
+        searchTermValue: event.target.value,
+      } as any : {
+        searchTermValue: event.target.value,
+      }) as any;
+
+    if ((isTreeViewComponentWithExternalSearchProps(this.props) || isTreeViewComponentWithExternalStateProps(this.props)) && keyDownMode) {
+      this.props.onSearch(event.target.value);
     }
   };
 
@@ -256,6 +321,11 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
         activeItem: props.activeItem,
         searchTerm: props.searchTerm
       };
+    } else if (isTreeViewComponentWithExternalSearchProps(props)) {
+      return {
+        ...state,
+        searchTerm: props.searchTerm,
+      };
     }
     return state;
   }
-- 
cgit 1.2.3-korg

