]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10036 Autoscroll branch dropdown to selected item
authorPascal Mugnier <pascal.mugnier@sonarsource.com>
Fri, 4 May 2018 08:23:18 +0000 (10:23 +0200)
committerSonarTech <sonartech@sonarsource.com>
Mon, 7 May 2018 18:20:45 +0000 (20:20 +0200)
server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBranchesMenu.tsx
server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBranchesMenuItem.tsx
server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavBranchesMenu-test.tsx.snap

index 10f4b1ba8851fc2e830487970a47f3812ba2a64f..5772988c123c5ace579759a84ddac8d9b55cfdb4 100644 (file)
@@ -31,6 +31,7 @@ import {
   isPullRequest,
   isBranch
 } from '../../../../helpers/branches';
+import { scrollToElement } from '../../../../helpers/scrolling';
 import { translate } from '../../../../helpers/l10n';
 import { getBranchLikeUrl } from '../../../../helpers/urls';
 import SearchBox from '../../../../components/controls/SearchBox';
@@ -51,6 +52,8 @@ interface State {
 
 export default class ComponentNavBranchesMenu extends React.PureComponent<Props, State> {
   private node?: HTMLElement | null;
+  private listNode?: HTMLUListElement | null;
+  private selectedBranchNode?: HTMLLIElement | null;
 
   static contextTypes = {
     router: PropTypes.object
@@ -63,12 +66,26 @@ export default class ComponentNavBranchesMenu extends React.PureComponent<Props,
 
   componentDidMount() {
     window.addEventListener('click', this.handleClickOutside);
+    this.scrollToSelectedBranch(false);
+  }
+
+  componentDidUpdate() {
+    this.scrollToSelectedBranch(true);
   }
 
   componentWillUnmount() {
     window.removeEventListener('click', this.handleClickOutside);
   }
 
+  scrollToSelectedBranch(smooth: boolean) {
+    if (this.listNode && this.selectedBranchNode) {
+      scrollToElement(this.selectedBranchNode, {
+        parent: this.listNode,
+        smooth
+      });
+    }
+  }
+
   getFilteredBranchLikes = () => {
     const query = this.state.query.toLowerCase();
     return sortBranchesAsTree(this.props.branchLikes).filter(branchLike => {
@@ -190,7 +207,7 @@ export default class ComponentNavBranchesMenu extends React.PureComponent<Props,
         !showOrphanHeader && isPullRequest(branchLike) && !isPullRequest(previous);
       const showShortLivingBranchHeader =
         !showOrphanHeader && isShortLivingBranch(branchLike) && !isShortLivingBranch(previous);
-
+      const isSelected = isSameBranchLike(branchLike, selected);
       return (
         <React.Fragment key={getBranchLikeKey(branchLike)}>
           {showDivider && <li className="divider" />}
@@ -218,15 +235,22 @@ export default class ComponentNavBranchesMenu extends React.PureComponent<Props,
           <ComponentNavBranchesMenuItem
             branchLike={branchLike}
             component={this.props.component}
+            innerRef={node =>
+              (this.selectedBranchNode = isSelected ? node : this.selectedBranchNode)
+            }
             key={getBranchLikeKey(branchLike)}
             onSelect={this.handleSelect}
-            selected={isSameBranchLike(branchLike, selected)}
+            selected={isSelected}
           />
         </React.Fragment>
       );
     });
 
-    return <ul className="menu menu-vertically-limited">{items}</ul>;
+    return (
+      <ul className="menu menu-vertically-limited" ref={node => (this.listNode = node)}>
+        {items}
+      </ul>
+    );
   };
 
   render() {
index 316ee5f06b1a126db078d1a378b8b5c3a20fb18b..8788fe657c12f39affea5607d2c9171070c6cdc6 100644 (file)
@@ -39,6 +39,7 @@ export interface Props {
   component: Component;
   onSelect: (branchLike: BranchLike) => void;
   selected: boolean;
+  innerRef?: (node: HTMLLIElement) => void;
 }
 
 export default function ComponentNavBranchesMenuItem({ branchLike, ...props }: Props) {
@@ -51,7 +52,7 @@ export default function ComponentNavBranchesMenuItem({ branchLike, ...props }: P
     (isShortLivingBranch(branchLike) && !branchLike.isOrphan) || isPullRequest(branchLike);
 
   return (
-    <li key={getBranchLikeKey(branchLike)} onMouseEnter={handleMouseEnter}>
+    <li key={getBranchLikeKey(branchLike)} onMouseEnter={handleMouseEnter} ref={props.innerRef}>
       <Link
         className={classNames('navbar-context-meta-branch-menu-item', {
           active: props.selected
index c104c23e7d39b2d682178067f26431447f6254c6..cac918b498529475bfee1b0b06a3f21da916e5f3 100644 (file)
@@ -33,6 +33,7 @@ exports[`renders list 1`] = `
             "key": "component",
           }
         }
+        innerRef={[Function]}
         key="branch-master"
         onSelect={[Function]}
         selected={true}
@@ -66,6 +67,7 @@ exports[`renders list 1`] = `
             "key": "component",
           }
         }
+        innerRef={[Function]}
         key="pull-request-1234"
         onSelect={[Function]}
         selected={false}
@@ -111,6 +113,7 @@ exports[`renders list 1`] = `
             "key": "component",
           }
         }
+        innerRef={[Function]}
         key="branch-baz"
         onSelect={[Function]}
         selected={false}
@@ -140,6 +143,7 @@ exports[`renders list 1`] = `
             "key": "component",
           }
         }
+        innerRef={[Function]}
         key="branch-foo"
         onSelect={[Function]}
         selected={false}
@@ -164,6 +168,7 @@ exports[`renders list 1`] = `
             "key": "component",
           }
         }
+        innerRef={[Function]}
         key="branch-bar"
         onSelect={[Function]}
         selected={false}
@@ -209,6 +214,7 @@ exports[`renders list 1`] = `
             "key": "component",
           }
         }
+        innerRef={[Function]}
         key="branch-baz"
         onSelect={[Function]}
         selected={false}
@@ -265,6 +271,7 @@ exports[`searches 1`] = `
             "key": "component",
           }
         }
+        innerRef={[Function]}
         key="branch-foobar"
         onSelect={[Function]}
         selected={true}
@@ -289,6 +296,7 @@ exports[`searches 1`] = `
             "key": "component",
           }
         }
+        innerRef={[Function]}
         key="branch-bar"
         onSelect={[Function]}
         selected={false}