فهرست منبع

HttpService caching for GET requests. Code cleanup

Joe Hawkins 8 سال پیش
والد
کامیت
ef48426370

+ 1 - 1
src/main/angular/src/i18n/translations_en.json

@@ -1,7 +1,7 @@
 {
 {
   "Title_PeopleSearch": "People Search",
   "Title_PeopleSearch": "People Search",
   "Title_Management": "Management",
   "Title_Management": "Management",
-  "Title_DirectReports": "Direct Reports",
+  "Title_DirectReports": "Direct Report(s)",
   "Title_Organization": "Organization",
   "Title_Organization": "Organization",
   "Title_OrgChart": "Organizational Chart",
   "Title_OrgChart": "Organizational Chart",
   "Title_Details": "Details",
   "Title_Details": "Details",

+ 11 - 7
src/main/angular/src/main.ts

@@ -2,8 +2,9 @@ import { bootstrap, module } from 'angular';
 import ConfigService from './services/config.service';
 import ConfigService from './services/config.service';
 import peopleSearchModule from './peoplesearch/peoplesearch.module';
 import peopleSearchModule from './peoplesearch/peoplesearch.module';
 import PeopleService from './services/people.service';
 import PeopleService from './services/people.service';
+import PwmService from './services/pwm.service';
 import routes from './routes';
 import routes from './routes';
-import translationsLoader from './services/translations-loader.factory';
+import TranslationsLoaderFactory from './services/translations-loader.factory';
 import uiRouter from 'angular-ui-router';
 import uiRouter from 'angular-ui-router';
 
 
 // fontgen-loader needs this :(
 // fontgen-loader needs this :(
@@ -16,14 +17,17 @@ module('app', [
 ])
 ])
 
 
     .config(routes)
     .config(routes)
-    .config(['$translateProvider', ($translateProvider: angular.translate.ITranslateProvider) => {
-        $translateProvider.useLoader('translationsLoader');
-        $translateProvider.useSanitizeValueStrategy('escapeParameters');
-        $translateProvider.preferredLanguage('en');
-    }])
+    .config([
+        '$translateProvider',
+        ($translateProvider: angular.translate.ITranslateProvider) => {
+            $translateProvider.useLoader('translationsLoader');
+            $translateProvider.useSanitizeValueStrategy('escapeParameters');
+            $translateProvider.preferredLanguage('en');
+        }])
     .service('PeopleService', PeopleService)
     .service('PeopleService', PeopleService)
+    .service('PwmService', PwmService)
     .service('ConfigService', ConfigService)
     .service('ConfigService', ConfigService)
-    .factory('translationsLoader', translationsLoader);
+    .factory('translationsLoader', TranslationsLoaderFactory);
 
 
 // Attach to the page document
 // Attach to the page document
 bootstrap(document, ['app']);
 bootstrap(document, ['app']);

+ 1 - 1
src/main/angular/src/models/person.model.ts

@@ -1,7 +1,7 @@
 export default class Person {
 export default class Person {
     // Common properties
     // Common properties
     userKey: string;
     userKey: string;
-    numOfDirectReports: number;
+    numDirectReports: number;
 
 
     // Autocomplete properties (via Search)
     // Autocomplete properties (via Search)
     _displayName: string;
     _displayName: string;

+ 3 - 2
src/main/angular/src/peoplesearch/orgchart.component.html

@@ -8,7 +8,7 @@
             <div class="org-chart-connector"></div>
             <div class="org-chart-connector"></div>
             <person-card person="manager"
             <person-card person="manager"
                          size="{{ $ctrl.getManagerCardSize() }}"
                          size="{{ $ctrl.getManagerCardSize() }}"
-                         show-direct-report-count="true"
+                         show-direct-report-count="false"
                          ng-click="$ctrl.selectPerson(manager.userKey)">
                          ng-click="$ctrl.selectPerson(manager.userKey)">
             </person-card>
             </person-card>
         </div>
         </div>
@@ -30,7 +30,8 @@
     <div class="org-chart-connector"></div>
     <div class="org-chart-connector"></div>
 
 
     <div class="person-card-list">
     <div class="person-card-list">
-        <person-card person="directReport" show-direct-report-count="true"
+        <person-card person="directReport"
+                     show-direct-report-count="false"
                      ng-repeat="directReport in $ctrl.directReports"
                      ng-repeat="directReport in $ctrl.directReports"
                      ng-click="$ctrl.selectPerson(directReport.userKey)">
                      ng-click="$ctrl.selectPerson(directReport.userKey)">
         </person-card>
         </person-card>

+ 0 - 3
src/main/angular/src/peoplesearch/orgchart.component.test.ts

@@ -1,6 +1,3 @@
-// import 'jasmine';
-// import { OrgChartComponent } from './orgchart.component';
-
 describe('testing OrgChartComponent', () => {
 describe('testing OrgChartComponent', () => {
     beforeEach(() => {
     beforeEach(() => {
     });
     });

+ 1 - 1
src/main/angular/src/peoplesearch/peoplesearch-table.component.ts

@@ -21,7 +21,7 @@ export default class PeopleSearchTableComponent extends PeopleSearchBaseComponen
     }
     }
 
 
     $onInit(): void {
     $onInit(): void {
-        this.initialize(this.peopleService.cardSearch);
+        this.initialize(this.peopleService.search);
 
 
         let self = this;
         let self = this;
 
 

+ 3 - 2
src/main/angular/src/peoplesearch/person-card.component.html

@@ -1,8 +1,9 @@
 <div class="person-card-content" ng-switch="$ctrl.size">
 <div class="person-card-content" ng-switch="$ctrl.size">
     <div class="avatar" ng-style="$ctrl.getAvatarStyle()" aria-label="User avatar"></div>
     <div class="avatar" ng-style="$ctrl.getAvatarStyle()" aria-label="User avatar"></div>
     <div class="reports"
     <div class="reports"
-         ng-if="$ctrl.showDirectReportCount && $ctrl.person.numOfDirectReports"
-         ng-bind="$ctrl.person.numOfDirectReports"></div>
+         ng-if="$ctrl.showDirectReportCount && $ctrl.person.numDirectReports"
+         ng-bind="$ctrl.person.numDirectReports"
+         ng-attr-title="{{$ctrl.person.numDirectReports}} {{ 'Title_DirectReports' | translate }}"></div>
 
 
     <div class="details" ng-switch-when="small">
     <div class="details" ng-switch-when="small">
         <div ng-bind="$ctrl.person.displayNames[0]"></div>
         <div ng-bind="$ctrl.person.displayNames[0]"></div>

+ 7 - 9
src/main/angular/src/peoplesearch/person-card.component.ts

@@ -7,7 +7,7 @@ import { IPeopleService } from '../services/people.service';
         directReports: '<',
         directReports: '<',
         person: '<',
         person: '<',
         size: '@',
         size: '@',
-        showDirectReportCount: '@'
+        showDirectReportCount: '='
     },
     },
     stylesheetUrl: require('peoplesearch/person-card.component.scss'),
     stylesheetUrl: require('peoplesearch/person-card.component.scss'),
     templateUrl: require('peoplesearch/person-card.component.html')
     templateUrl: require('peoplesearch/person-card.component.html')
@@ -22,19 +22,17 @@ export default class PersonCardComponent {
     static $inject = ['PeopleService'];
     static $inject = ['PeopleService'];
     constructor(private peopleService: IPeopleService) {
     constructor(private peopleService: IPeopleService) {
         this.details = [];
         this.details = [];
+        this.size = 'medium';
     }
     }
 
 
-    $onInit() {
-    }
-
-    $onChanges() {
+    $onChanges(): void {
         if (this.person) {
         if (this.person) {
             this.setDisplayData();
             this.setDisplayData();
 
 
             if (this.showDirectReportCount) {
             if (this.showDirectReportCount) {
                 this.peopleService.getNumberOfDirectReports(this.person.userKey)
                 this.peopleService.getNumberOfDirectReports(this.person.userKey)
-                    .then((numOfDirectReports) => {
-                        this.person.numOfDirectReports = numOfDirectReports;
+                    .then((numDirectReports) => {
+                        this.person.numDirectReports = numDirectReports;
                     }).catch((result) => {
                     }).catch((result) => {
                     console.log(result);
                     console.log(result);
                 });
                 });
@@ -50,7 +48,7 @@ export default class PersonCardComponent {
         return {};
         return {};
     }
     }
 
 
-    private setDisplayData() {
+    private setDisplayData(): void {
         if (this.person.detail) {
         if (this.person.detail) {
             this.details = Object
             this.details = Object
                 .keys(this.person.detail)
                 .keys(this.person.detail)
@@ -60,7 +58,7 @@ export default class PersonCardComponent {
         }
         }
 
 
         if (this.directReports) {
         if (this.directReports) {
-            this.person.numOfDirectReports = this.directReports.length;
+            this.person.numDirectReports = this.directReports.length;
         }
         }
     }
     }
 }
 }

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

@@ -8,7 +8,10 @@ export default [
         $locationProvider: angular.ILocationProvider
         $locationProvider: angular.ILocationProvider
     ) => {
     ) => {
         $urlRouterProvider.otherwise('/search/cards');
         $urlRouterProvider.otherwise('/search/cards');
-        $locationProvider.html5Mode(true);
+        $locationProvider.html5Mode({
+            enabled: true,
+            requireBase: false
+        });
 
 
         $stateProvider.state('search', {
         $stateProvider.state('search', {
             url: '/search?query',
             url: '/search?query',

+ 3 - 6
src/main/angular/src/services/config.service.dev.ts

@@ -1,12 +1,9 @@
 import { IConfigService } from './config.service';
 import { IConfigService } from './config.service';
 import { IPromise, IQService } from 'angular';
 import { IPromise, IQService } from 'angular';
-import PwmService from './pwm.service';
 
 
-export default class ConfigService extends PwmService implements IConfigService {
-    static $inject = ['$q'];
-    constructor(private $q: IQService) {
-        super();
-    }
+export default class ConfigService implements IConfigService {
+    static $inject = [ '$q' ];
+    constructor(private $q: IQService) {}
 
 
     getColumnConfiguration(): IPromise<any> {
     getColumnConfiguration(): IPromise<any> {
         return this.$q.resolve({
         return this.$q.resolve({

+ 6 - 5
src/main/angular/src/services/config.service.ts

@@ -5,15 +5,16 @@ export interface IConfigService {
     getColumnConfiguration(): IPromise<any>;
     getColumnConfiguration(): IPromise<any>;
 }
 }
 
 
-export default class ConfigService extends PwmService implements IConfigService {
-    static $inject = ['$http', '$q'];
-    constructor(private $http: IHttpService, private $q: IQService) {
-        super();
+export default class ConfigService implements IConfigService {
+    static $inject = ['$http', '$q', PwmService ];
+    constructor(private $http: IHttpService,
+                private $q: IQService,
+                private pwmService: PwmService) {
     }
     }
 
 
     getColumnConfiguration(): IPromise<any> {
     getColumnConfiguration(): IPromise<any> {
         return this.$http
         return this.$http
-            .get(this.getServerUrl('clientData'))
+            .get(this.pwmService.getServerUrl('clientData'), { cache: true })
             .then((response) => {
             .then((response) => {
                 return this.$q.resolve(response.data['data']['peoplesearch_search_columns']);
                 return this.$q.resolve(response.data['data']['peoplesearch_search_columns']);
             });
             });

+ 12 - 13
src/main/angular/src/services/people.service.ts

@@ -16,14 +16,12 @@ export interface IPeopleService {
     search(query: string): IPromise<SearchResult>;
     search(query: string): IPromise<SearchResult>;
 }
 }
 
 
-export default class PeopleService extends PwmService implements IPeopleService {
-    static $inject = ['$http', '$q'];
-    constructor(private $http: IHttpService, private $q: IQService) {
-        super();
-    }
+export default class PeopleService implements IPeopleService {
+    static $inject = ['$http', '$q', 'PwmService' ];
+    constructor(private $http: IHttpService, private $q: IQService, private pwmService: PwmService) {}
 
 
     autoComplete(query: string): IPromise<Person[]> {
     autoComplete(query: string): IPromise<Person[]> {
-        return this.search(query)
+        return this.search(query, { 'includeDisplayName': true })
             .then((searchResult: SearchResult) => {
             .then((searchResult: SearchResult) => {
                 let people = searchResult.people;
                 let people = searchResult.people;
                 if (people && people.length > 10) {
                 if (people && people.length > 10) {
@@ -92,7 +90,7 @@ export default class PeopleService extends PwmService implements IPeopleService
 
 
     getOrgChartData(personId: string): angular.IPromise<OrgChartData> {
     getOrgChartData(personId: string): angular.IPromise<OrgChartData> {
         return this.$http
         return this.$http
-            .get(this.getServerUrl('orgChartData'), { params: { userKey: personId } })
+            .get(this.pwmService.getServerUrl('orgChartData'), { cache: true, params: { userKey: personId } })
             .then((response) => {
             .then((response) => {
                 let responseData = response.data['data'];
                 let responseData = response.data['data'];
 
 
@@ -101,15 +99,13 @@ export default class PeopleService extends PwmService implements IPeopleService
                 const children = responseData['children'].map((child: any) => new Person(child));
                 const children = responseData['children'].map((child: any) => new Person(child));
                 const self = new Person(responseData['self']);
                 const self = new Person(responseData['self']);
 
 
-                const orgChartData = new OrgChartData(manager, children, self);
-
-                return this.$q.resolve(orgChartData);
+                return this.$q.resolve(new OrgChartData(manager, children, self));
             });
             });
     }
     }
 
 
     getPerson(id: string): IPromise<Person> {
     getPerson(id: string): IPromise<Person> {
         return this.$http
         return this.$http
-            .get(this.getServerUrl('detail'), { params: { userKey: id } })
+            .get(this.pwmService.getServerUrl('detail'), { cache: true, params: { userKey: id } })
             .then((response) => {
             .then((response) => {
                 let person: Person = new Person(response.data['data']);
                 let person: Person = new Person(response.data['data']);
                 return this.$q.resolve(person);
                 return this.$q.resolve(person);
@@ -121,9 +117,12 @@ export default class PeopleService extends PwmService implements IPeopleService
         return this.$q.resolve(true);
         return this.$q.resolve(true);
     }
     }
 
 
-    search(query: string): IPromise<SearchResult> {
+    search(query: string, params?: any): IPromise<SearchResult> {
         return this.$http
         return this.$http
-            .get(this.getServerUrl('search', { 'includeDisplayName': true }), { params: { username: query } })
+            .get(
+                this.pwmService.getServerUrl('search', { 'includeDisplayName': true }),
+                { cache: true, params: { username: query } }
+            )
             .then((response) => {
             .then((response) => {
                 let receivedData: any = response.data['data'];
                 let receivedData: any = response.data['data'];
                 let searchResult: SearchResult = new SearchResult(receivedData);
                 let searchResult: SearchResult = new SearchResult(receivedData);

+ 62 - 9
src/main/angular/src/services/pwm.service.ts

@@ -1,21 +1,74 @@
-// These come from legacy PWM:
-declare var PWM_GLOBAL: any;
-declare var PWM_MAIN: any;
+import { ILogService, IWindowService } from 'angular';
 
 
 export default class PwmService {
 export default class PwmService {
-    protected getServerUrl(processAction: string, additionalParameters?: any): string {
-        let url: string = PWM_GLOBAL['url-context'] + '/private/peoplesearch?processAction=' + processAction;
-        url = PwmService.addParameters(url, additionalParameters);
-        url = PWM_MAIN.addPwmFormIDtoURL(url);
+    PWM_GLOBAL: any;
+    PWM_MAIN: any;
+
+    urlContext: string;
+
+    static $inject = [ '$log', '$window' ];
+    constructor(private $log: ILogService, $window: IWindowService) {
+        this.urlContext = '';
+
+        // Search window references to PWM_GLOBAL and PWM_MAIN add by legacy PWM code
+        if ($window['PWM_GLOBAL']) {
+            this.PWM_GLOBAL = $window['PWM_GLOBAL'];
+            this.urlContext = this.PWM_GLOBAL['url-context'];
+        }
+        else {
+            this.$log.warn('PWM_GLOBAL is not defined on window');
+        }
+
+        if ($window['PWM_MAIN']) {
+            this.PWM_MAIN = $window['PWM_MAIN'];
+        }
+        else {
+            this.$log.warn('PWM_MAIN is not defined on window');
+        }
+    }
+
+    getServerUrl(processAction: string, additionalParameters?: any): string {
+        let url: string = this.urlContext + '/private/peoplesearch?processAction=' + processAction;
+        url = this.addParameters(url, additionalParameters);
+        url = this.addPwmFormIdToUrl(url);
 
 
         return url;
         return url;
     }
     }
 
 
-    private static addParameters(url: string, params: any): string {
+    get localeStrings(): any {
+        if (this.PWM_GLOBAL) {
+            return this.PWM_GLOBAL['localeStrings'];
+        }
+
+        return {};
+    }
+
+    get startupFunctions(): any[] {
+        if (this.PWM_GLOBAL) {
+            return this.PWM_GLOBAL['startupFunctions'];
+        }
+
+        return [];
+    }
+
+    private addPwmFormIdToUrl(url: string): string {
+        if (!this.PWM_MAIN) {
+            return url;
+        }
+
+        return this.PWM_MAIN.addPwmFormIDtoURL(url);
+    }
+
+
+    private addParameters(url: string, params: any): string {
+        if (!this.PWM_MAIN) {
+            return url;
+        }
+
         if (params) {
         if (params) {
             for (var name in params) {
             for (var name in params) {
                 if (params.hasOwnProperty(name)) {
                 if (params.hasOwnProperty(name)) {
-                    url = PWM_MAIN.addParamToUrl(url, name, params[name]);
+                    url = this.PWM_MAIN.addParamToUrl(url, name, params[name]);
                 }
                 }
             }
             }
         }
         }

+ 15 - 14
src/main/angular/src/services/translations-loader.factory.ts

@@ -1,18 +1,19 @@
-import { IQService } from 'angular';
 import 'angular-translate';
 import 'angular-translate';
+import { IQService } from 'angular';
+import PwmService from './pwm.service';
 
 
-declare var PWM_GLOBAL: any;
-
-export default ['$q', ($q: IQService) => {
-    // return loaderFn
-    return function (options) {
-        var deferred = $q.defer();
+export default [
+    '$q',
+    'PwmService',
+    ($q: IQService, pwmService: PwmService) => {
+        return function () {
+            var deferred = $q.defer();
 
 
-        PWM_GLOBAL['startupFunctions'].push(() => {
-            deferred.resolve(PWM_GLOBAL['localeStrings']['Display']);
-        });
+            pwmService.startupFunctions.push(() => {
+                deferred.resolve(pwmService.localeStrings['Display']);
+            });
 
 
-        // resolve with translation data
-        return deferred.promise;
-    };
-}];
+            // resolve with translation data
+            return deferred.promise;
+        };
+    }];

+ 1 - 6
src/main/angular/webpack.common.js

@@ -1,5 +1,4 @@
 var HtmlWebpackPlugin = require('html-webpack-plugin');
 var HtmlWebpackPlugin = require('html-webpack-plugin');
-var WriteFileWebpackPlugin = require('write-file-webpack-plugin');
 var autoPrefixer = require('autoprefixer');
 var autoPrefixer = require('autoprefixer');
 var path = require('path');
 var path = require('path');
 var webpack = require('webpack');
 var webpack = require('webpack');
@@ -68,11 +67,7 @@ module.exports = {
         new HtmlWebpackPlugin({
         new HtmlWebpackPlugin({
             template: 'index.html',
             template: 'index.html',
             inject: 'body'
             inject: 'body'
-        }),
-
-        // Because we copy the output to another directory, we need file system watch support.
-        // Webpack-dev-server does not do this without the plugin.
-        new WriteFileWebpackPlugin()
+        })
     ],
     ],
     postcss: function() {
     postcss: function() {
         return [
         return [

+ 1 - 1
src/main/resources/password/pwm/config/PwmSetting.xml

@@ -1485,7 +1485,7 @@
     <setting hidden="false" key="security.cspHeader" level="2">
     <setting hidden="false" key="security.cspHeader" level="2">
         <default>
         <default>
             <!--<value><![CDATA[]]></value>-->
             <!--<value><![CDATA[]]></value>-->
-            <value><![CDATA[default-src 'self'; object-src 'none'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ 'self' 'unsafe-eval' 'unsafe-inline' 'nonce-%NONCE%' ; frame-src https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/; report-uri /sspr/public/command/csp-report]]></value>
+            <value><![CDATA[default-src 'self'; connect-src 'self' blob:; object-src 'none'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ 'self' 'unsafe-eval' 'unsafe-inline' 'nonce-%NONCE%' ; frame-src https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/; report-uri /sspr/public/command/csp-report]]></value>
             <!-- 'unsafe-inline' on script-src is included for backward compatibility of CSP Level1 browsers.  CSP2 and future ignore it when the nonce is specified -->
             <!-- 'unsafe-inline' on script-src is included for backward compatibility of CSP Level1 browsers.  CSP2 and future ignore it when the nonce is specified -->
         </default>
         </default>
     </setting>
     </setting>