Просмотр исходного кода

Merge remote-tracking branch 'uiteam/master' into angular

James Albright 8 лет назад
Родитель
Сommit
b2bc3ae9ff

+ 5 - 0
src/main/angular/src/peoplesearch/orgchart-search.component.scss

@@ -1,4 +1,9 @@
 org-chart-search {
+  display: flex;
+  flex-flow: column nowrap;
+  height: 100%;
+  overflow-x: auto;
+
   app-bar {
     > .app-bar-content {
       display: block;

+ 115 - 123
src/main/angular/src/peoplesearch/orgchart.component.scss

@@ -4,122 +4,14 @@ $org-chart-text-color: #808080;
 
 $manager-connector-height: 16px;
 
-// Default display
+// (XS) Default display
 org-chart {
   display: block;
   min-width: 300px;
   padding-top: 10px;
 
-  > .org-chart-section {
-    position: relative;
-    text-align: center;
-
-    &.direct-reports {
-      > .org-chart-connector {
-        height: 34px;
-      }
-    }
-
-    &.managers {
-      min-height: 98px;
-
-      &.overflow {
-        .manager {
-          &:last-child {
-            > person-card {
-              > .person-card-content {
-                > .avatar {
-                  background-image: url('../../images/m_circle-horz-menu.svg');
-                }
-
-                > .reports {
-                  display: none;
-                }
-              }
-            }
-          }
-        }
-      }
-
-      .manager {
-        margin-bottom: $manager-connector-height;
-        position: relative;
-        text-align: center;
-
-        &.empty-manager {
-          > person-card {
-            cursor: initial;
-
-            > .person-card-content {
-              > .avatar {
-                background: $org-chart-secondary-connector-color url('../../images/m_question_mark.svg');
-                border-color: $org-chart-secondary-connector-color;
-              }
-            }
-          }
-
-          > .org-chart-connector {
-            background-color: $org-chart-secondary-connector-color;
-          }
-        }
-
-        > person-card {
-          display: inline-block;
-        }
-      }
-
-      .org-chart-connector {
-        bottom: -$manager-connector-height;
-        height: $manager-connector-height;
-        top: initial;
-      }
-    }
-
-    > h3 {
-      color: $org-chart-text-color;
-      font-size: 14px;
-      line-height: 14px;
-      margin: 0;
-      padding: 15px 0 5px 0;
-      text-align: left;
-    }
-
-    > person-card {
-      &[size="large"] {
-        margin: 0 auto;
-      }
-    }
-
-    > .person-card-list {
-      border-top: 3px solid $org-chart-connector-color;
-      min-height: 90px;
-      padding-top: 5px;
-
-      > person-card {
-        display: inline-block;
-        width: 100%;
-
-        &:not(:last-child) {
-          margin-bottom: 5px;
-        }
-      }
-    }
-
-    .org-chart-connector {
-      background-color: $org-chart-connector-color;
-      left: 0;
-      margin: 0 auto;
-      position: absolute;
-      right: 0;
-      top: 0;
-      width: 5px;
-    }
-  }
-}
-
-// Too wide for full width person-card
-@media (min-width: 375px) {
-  org-chart {
+  // (S) Too wide for full width person-card in direct reports
+  &.small {
     > .org-chart-section {
       > .person-card-list {
         > person-card {
@@ -129,11 +21,9 @@ org-chart {
       }
     }
   }
-}
 
-// Wide enough to fit multiple person-cards next to each other inline
-@media (min-width: 420px) {
-  org-chart {
+  // (M) Wide enough to fit multiple person-cards next to each other inline
+  &.medium {
     > .org-chart-section {
       > .person-card-list {
         text-align: left;
@@ -146,11 +36,9 @@ org-chart {
       }
     }
   }
-}
 
-// Wide enough to show main person offset to the right. Manager should now be locked in place (instead of centered)
-@media (min-width: 464px) {
-  org-chart {
+  // (L) Wide enough to show main person offset to the right. Manager should now be locked in place (instead of centered)
+  &.large {
     > .org-chart-section {
       text-align: left;
 
@@ -178,11 +66,9 @@ org-chart {
       }
     }
   }
-}
 
-// Wide enough to display several managers horizontally
-@media (min-width: 490px) {
-  org-chart {
+  // (XL) Wide enough to display several managers horizontally
+  &.extra-large {
     > .org-chart-section {
       &.managers {
         margin-left: 0;
@@ -256,4 +142,110 @@ org-chart {
       }
     }
   }
+
+  > .org-chart-section {
+    position: relative;
+    text-align: center;
+
+    &.direct-reports {
+      > .org-chart-connector {
+        height: 34px;
+      }
+    }
+
+    &.managers {
+      min-height: 98px;
+
+      &.overflow {
+        .manager {
+          &:last-child {
+            > person-card {
+              > .person-card-content {
+                > .avatar {
+                  background-image: url('../../images/m_circle-horz-menu.svg');
+                }
+
+                > .reports {
+                  display: none;
+                }
+              }
+            }
+          }
+        }
+      }
+
+      .manager {
+        margin-bottom: $manager-connector-height;
+        position: relative;
+        text-align: center;
+
+        &.empty-manager {
+          > person-card {
+            cursor: initial;
+
+            > .person-card-content {
+              > .avatar {
+                background: $org-chart-secondary-connector-color url('../../images/m_question_mark.svg');
+                border-color: $org-chart-secondary-connector-color;
+              }
+            }
+          }
+
+          > .org-chart-connector {
+            background-color: $org-chart-secondary-connector-color;
+          }
+        }
+
+        > person-card {
+          display: inline-block;
+        }
+      }
+
+      .org-chart-connector {
+        bottom: -$manager-connector-height;
+        height: $manager-connector-height;
+        top: initial;
+      }
+    }
+
+    > h3 {
+      color: $org-chart-text-color;
+      font-size: 14px;
+      line-height: 14px;
+      margin: 0;
+      padding: 15px 0 5px 0;
+      text-align: left;
+    }
+
+    > person-card {
+      &[size="large"] {
+        margin: 0 auto;
+      }
+    }
+
+    > .person-card-list {
+      border-top: 3px solid $org-chart-connector-color;
+      min-height: 90px;
+      padding-top: 5px;
+
+      > person-card {
+        display: inline-block;
+        width: 100%;
+
+        &:not(:last-child) {
+          margin-bottom: 5px;
+        }
+      }
+    }
+
+    .org-chart-connector {
+      background-color: $org-chart-connector-color;
+      left: 0;
+      margin: 0 auto;
+      position: absolute;
+      right: 0;
+      top: 0;
+      width: 5px;
+    }
+  }
 }

+ 77 - 20
src/main/angular/src/peoplesearch/orgchart.component.ts

@@ -1,7 +1,15 @@
 import { Component } from '../component';
-import { element, IScope, IWindowService } from 'angular';
+import { element, IAugmentedJQuery, IFilterService, IScope, IWindowService } from 'angular';
 import Person from '../models/person.model';
 
+export enum OrgChartSize {
+    ExtraSmall = 0,
+    Small = 365,
+    Medium = 410,
+    Large = 454,
+    ExtraLarge = 480
+}
+
 @Component({
     bindings: {
         directReports: '<',
@@ -13,6 +21,7 @@ import Person from '../models/person.model';
 })
 export default class OrgChartComponent {
     directReports: Person[];
+    elementWidth: number;
     managementChain: Person[];
     person: Person;
 
@@ -24,45 +33,53 @@ export default class OrgChartComponent {
         userKey: null
     });
 
+    private elementSize: OrgChartSize = OrgChartSize.ExtraSmall;
     private maxVisibleManagers: number;
-    private windowWidth: number;
     private visibleManagers: Person[];
 
-    static $inject = ['$scope', '$state', '$window'];
+    static $inject = [ '$element', '$filter', '$scope', '$state', '$window' ];
     constructor(
+        private $element: IAugmentedJQuery,
+        private $filter: IFilterService,
         private $scope: IScope,
         private $state: angular.ui.IStateService,
         private $window: IWindowService) {
     }
 
+    $onDestroy(): void {
+        element(this.$window).off();
+    }
+
     $onInit(): void {
         var self = this;
 
         this.updateLayout();
 
-        // OrgChartComponent has different functionality at different window widths. On window resize, we
+        // OrgChartComponent has different functionality at different widths. On element resize, we
         // want to update the state of the component and trigger a $digest
-        // noinspection TypeScriptUnresolvedFunction
-        element(this.$window).bind('resize', () => {
-            self.updateLayout();
+        element(this.$window).on('resize', () => {
+            self.elementWidth = self.getElementWidth();
             self.$scope.$apply();
         });
+        this.$scope.$watch('$ctrl.elementWidth', () => {
+            self.updateLayout();
+        });
 
         // In large displays managers are displayed in a row. Any time this property changes, we want
         // to force our manager list to be recalculated in this.getManagementChain() so it returns the correct
-        // result at all window widths
+        // result at all element widths
         this.$scope.$watch('$ctrl.maxVisibleManagers', () => {
             this.resetManagerList();
         });
     }
 
     getManagerCardSize(): string {
-        return this.isWideLayout() ? 'small' : 'normal';
+        return this.isExtraLargeLayout() ? 'small' : 'normal';
     }
 
     getManagementChain(): Person[] {
         // Display managers in a row
-        if (this.isWideLayout()) {
+        if (this.isExtraLargeLayout()) {
             // All managers can fit on screen
             if (this.maxVisibleManagers >= this.managementChain.length) {
                 return this.managementChain;
@@ -111,27 +128,67 @@ export default class OrgChartComponent {
             this.visibleManagers.length < this.managementChain.length;
     }
 
-    private isWideLayout(): boolean {
-        return this.windowWidth >= 490;
+    private getElementWidth() {
+        return this.$element[0].clientWidth;
+    }
+
+    private isExtraLargeLayout(): boolean {
+        return this.elementSize === OrgChartSize.ExtraLarge;
     }
 
-    // Remove all displayed managers so the list is updated on window resize
+    // Remove all displayed managers so the list is updated on element resize
     private resetManagerList(): void {
         this.visibleManagers = null;
     }
 
-    private setMaxVisibleManagers(): void {
-        this.maxVisibleManagers = Math.floor(
-            (this.windowWidth - 115 /* left margin */) /
-            125 /* card width + right margin */);
+    private setElementClass(): void {
+        var className: string = [
+            OrgChartSize.Small,
+            OrgChartSize.ExtraSmall,
+            OrgChartSize.Medium,
+            OrgChartSize.Large,
+            OrgChartSize.ExtraLarge
+        ]
+            .filter((size: OrgChartSize): boolean => {
+                return size <= this.elementSize;
+            })
+            .map((size: OrgChartSize): string => {
+                return this.$filter<(input: string) => string>('dasherize')(OrgChartSize[size]);
+            })
+            .join(' ');
+
+        this.$element[0].className = '';
+        this.$element.addClass(className);
     }
 
-    private setWindowWidth(): void {
-        this.windowWidth = this.$window.innerWidth;
+    private setElementSize(): void {
+        var elementWidth: number = this.getElementWidth();
+
+        if (elementWidth < OrgChartSize.Small) {
+            this.elementSize = OrgChartSize.ExtraSmall;
+        }
+        else if (elementWidth < OrgChartSize.Medium) {
+            this.elementSize = OrgChartSize.Small;
+        }
+        else if (elementWidth < OrgChartSize.Large) {
+            this.elementSize = OrgChartSize.Medium;
+        }
+        else if (elementWidth < OrgChartSize.ExtraLarge) {
+            this.elementSize = OrgChartSize.Large;
+        }
+        else {
+            this.elementSize = OrgChartSize.ExtraLarge;
+        }
+    }
+
+    private setMaxVisibleManagers(): void {
+        this.maxVisibleManagers = Math.floor(
+            (this.getElementWidth() - 115 /* left margin */) / 125 /* card width + right margin */);
     }
 
     private updateLayout(): void {
-        this.setWindowWidth();
+        this.setElementSize();
+        this.setElementClass();
         this.setMaxVisibleManagers();
     }
 }

+ 0 - 5
src/main/angular/src/peoplesearch/peoplesearch-table.component.scss

@@ -1,12 +1,7 @@
 people-search-table {
-    display: flex;
-    flex-flow: column nowrap;
-    overflow-x: auto;
-
     > table {
         border: 1px solid #dae1e1;
         border-collapse: collapse;
-
         flex: 1 1;
         margin-top: 10px;
         width: 100%;

+ 8 - 0
src/main/angular/src/peoplesearch/peoplesearch.component.scss

@@ -1,5 +1,13 @@
 people-search {
+  display: flex;
+  flex-flow: column nowrap;
+  height: 100%;
+
   > .search-bar {
     margin-bottom: 10px;
   }
+
+  > ui-view {
+    overflow: auto;
+  }
 }

+ 2 - 0
src/main/angular/src/peoplesearch/peoplesearch.module.ts

@@ -1,4 +1,5 @@
 import { module } from 'angular';
+import { dasherize } from './string.filters';
 import OrgChartComponent from './orgchart.component';
 import OrgChartSearchComponent from './orgchart-search.component';
 import PeopleSearchService from './peoplesearch.service';
@@ -14,6 +15,7 @@ var moduleName = 'people-search';
 
 module(moduleName, [ uxModule ])
     .service('PeopleSearchService', PeopleSearchService)
+    .filter('dasherize', dasherize)
     .component('orgChart', OrgChartComponent)
     .component('orgChartSearch', OrgChartSearchComponent)
     .component('personCard', PersonCardComponent)

+ 5 - 0
src/main/angular/src/peoplesearch/peoplesearch.scss

@@ -1,7 +1,12 @@
+body, html {
+  height: 100%;
+}
+
 body {
   > ui-view {
     box-sizing: border-box;
     display: block;
+    height: 100%;
     overflow: hidden;
     padding: 5px;
     width: 100%;

+ 9 - 0
src/main/angular/src/peoplesearch/string.filters.ts

@@ -0,0 +1,9 @@
+export function dasherize(): (input: string) => string {
+    return (input: string): string => {
+        return input
+            .replace(/(?:^\w|[A-Z]|\b\w)/g, function (letter, index) {
+                return (index == 0 ? '' : '-') + letter.toLowerCase();
+            })
+            .replace(/\s+/g, '');
+    };
+}

+ 1 - 1
src/main/angular/src/routes.ts

@@ -2,7 +2,7 @@ export default [
     '$stateProvider',
     '$urlRouterProvider',
     ($stateProvider: angular.ui.IStateProvider, $urlRouterProvider: angular.ui.IUrlRouterProvider) => {
-        $urlRouterProvider.otherwise('/search/table');
+        $urlRouterProvider.otherwise('/search/cards');
 
         $stateProvider.state('search', { url: '/search?query', component: 'peopleSearch', reloadOnSearch: false });
         $stateProvider.state('search.table', { url: '/table', component: 'peopleSearchTable' });

+ 1 - 0
src/main/angular/tsconfig.json

@@ -13,6 +13,7 @@
       "angular",
       "angular-mocks",
       "jasmine",
+      "jquery",
       "node"
     ]
   },