svn commit: r1662855 [11/12] - in /portals/jetspeed-2/applications/j2-admin/trunk: ./ src/main/java/org/apache/jetspeed/jetapp/ src/main/java/org/apache/jetspeed/jetapp/dto/ src/main/webapp/WEB-INF/ src/main/webapp/jetapp/ src/main/webapp/jetapp/bower_...

[email protected]
Newsgroups gmane.comp.jakarta.jetspeed.devel
Message-ID <[email protected]>
Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/BOILERPLATE_LICENSE.md
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/BOILERPLATE_LICENSE.md?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/BOILERPLATE_LICENSE.md (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/BOILERPLATE_LICENSE.md Fri Feb 27 23:33:58 2015
@@ -0,0 +1,19 @@
+Copyright (c) HTML5 Boilerplate
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/BOOTSTRAP_LICENSE
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/BOOTSTRAP_LICENSE?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/BOOTSTRAP_LICENSE (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/BOOTSTRAP_LICENSE Fri Feb 27 23:33:58 2015
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2011-2015 Twitter, Inc
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/JQUERY_MIT_LICENSE.txt
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/JQUERY_MIT_LICENSE.txt?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/JQUERY_MIT_LICENSE.txt (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/JQUERY_MIT_LICENSE.txt Fri Feb 27 23:33:58 2015
@@ -0,0 +1,21 @@
+Copyright 2014 jQuery Foundation and other contributors
+http://jquery.com/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/LODASH_LICENSE
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/LODASH_LICENSE?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/LODASH_LICENSE (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/LODASH_LICENSE Fri Feb 27 23:33:58 2015
@@ -0,0 +1,22 @@
+Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
+Based on Underscore.js 1.7.0, copyright 2009-2015 Jeremy Ashkenas,
+DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/MIT_LICENSE
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/MIT_LICENSE?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/MIT_LICENSE (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/MIT_LICENSE Fri Feb 27 23:33:58 2015
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2010-2015 Google, Inc. http://angularjs.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/MOMENT_LICENSE
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/MOMENT_LICENSE?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/MOMENT_LICENSE (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/MOMENT_LICENSE Fri Feb 27 23:33:58 2015
@@ -0,0 +1,22 @@
+Copyright (c) 2011-2014 Tim Wood, Iskren Chernev, Moment.js contributors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/NG_GRID_LICENSE.md
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/NG_GRID_LICENSE.md?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/NG_GRID_LICENSE.md (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/bower_licenses/NG_GRID_LICENSE.md Fri Feb 27 23:33:58 2015
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2012 the AngularUI Team, http://angular-ui.github.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/j2-admin-skin.css
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/j2-admin-skin.css?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/j2-admin-skin.css (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/j2-admin-skin.css Fri Feb 27 23:33:58 2015
@@ -0,0 +1,3 @@
+@import url(styles/ng-grid.min.css);
+@import url(styles/app.css);
+@import url(styles/default.css);
\ No newline at end of file

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/PortletService.js
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/PortletService.js?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/PortletService.js (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/PortletService.js Fri Feb 27 23:33:58 2015
@@ -0,0 +1,34 @@
+var PortletService = function ($http, $q, ServerService) {
+
+    var service = {
+
+        config: {
+            withCredentials: true
+        },
+
+        lookupPreferences: function (url) {
+            var self = this, deferred = $q.defer();
+            $http.get(url, service.config)
+                .success(function success(data, status, headers, config) {
+                    deferred.resolve(data, status);
+                })
+                .error(function error(data, status) {
+                    deferred.reject(data, status);
+                });
+            return deferred.promise;
+        },
+        storePreferences: function (url, prefs) {
+            var self = this, deferred = $q.defer();
+            $http.post(url, prefs, service.config)
+                .success(function success(data, status, headers, config) {
+                    deferred.resolve(data, status);
+                })
+                .error(function error(data, status) {
+                    deferred.reject(data, status);
+                });
+            return deferred.promise;
+        }
+
+    }
+    return service;
+}

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/RestApiService.js
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/RestApiService.js?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/RestApiService.js (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/RestApiService.js Fri Feb 27 23:33:58 2015
@@ -0,0 +1,160 @@
+'use strict';
+
+/* Services */
+
+var RestService = function ($http, $q, ServerService) {
+
+    var service = {
+
+        profiles: [],
+
+        /**
+         * List Profiles via query. The query is specified as an object with the
+         * following fields;
+         *
+         * 'id' : matches profile id
+         * 'title' : contains within title
+         * 'concreteClass' : contains within class name
+         *
+         * Profiles are returned in ascending id order. All matches are
+         * case insensitive.
+         *
+         * @param queryObject optional query object, defaults to {}
+         * @param first optional first data item index, defaults to 0
+         * @param count optional count to return, defaults to user preference
+         * @returns promise rejected or resolved with a wrapped list of Profile objects.
+         */
+        listProfiles: function(queryObject, first, count) {
+            var deferred = $q.defer();
+            var self = this;
+            var url = ServerService.api('/profiler/list');
+            var config = ServerService.apiConfig();
+            config.params = {
+                "type" : "json"
+            };
+            $http.get(url, config)
+                .success(function success(data, status, headers, config) {
+                    deferred.resolve(data, status);
+                })
+                .error(function error(data, status) {
+                    if (status == 404) {
+                        deferred.resolve(data, status);
+                    }
+                    else {
+                        deferred.reject(data, status);
+                    }
+                });
+            return deferred.promise;
+        },
+
+        /**
+         * Lookup a HostIdentity by id or host names. Matches are case insensitive.
+         *
+         * @param id primary key profile id to look up by
+         * @returns promise rejected or resolved with a Profile object.
+         */
+        getProfile: function(id) {
+            var deferred = $q.defer();
+            var url = ServerService.api('/profiler/edit', encodeURIComponent(id));
+            $http.get(url, ServerService.apiConfig())
+                .success(function success(data, status) {
+                    deferred.resolve(data, status);
+                })
+                .error(function error(message, status) {
+                    deferred.reject(message, status);
+                }
+            );
+            return deferred.promise;
+        },
+
+        /**
+         * Delete Profiles
+         *
+         * @param profileIds array of profile ids to delete
+         * @returns promise rejected or resolved
+         */
+        deleteProfiles: function(profileIds) {
+            var deferred = $q.defer();
+            var httpConfig = {
+                method: 'DELETE',
+                url: ServerService.api('/profiler'),
+                headers: {'Content-Type': 'application/json'},
+                data: profileIds
+            };
+            _.merge(httpConfig, ServerService.apiConfig());
+            $http(httpConfig)
+                .success(function success(data, status) {
+                    if (!!data && (data.status === 200)) {
+                        deferred.resolve(undefined, status);
+                    } else {
+                        deferred.reject("Profiles not deleted.", status);
+                    }
+                })
+                .error(function error(message, status) {
+                    deferred.reject(message, status);
+                }
+            );
+            return deferred.promise;
+        },
+
+
+        /**
+         * Create or update Profile. Operation is considered a create if the
+         * profile id is unique and the id is undefined.
+         *
+         * @param profile the Profile record to create or update
+         * @returns promise rejected or resolved with entity string
+         */
+        createOrUpdateProfile: function(profile) {
+            var deferred = $q.defer();
+            var url = ServerService.api('/profiler/update');
+            var config = ServerService.apiConfig();
+            config.params = {
+                "type" : "json"
+            };
+            $http.post(url, profile, ServerService.apiConfig())
+                .success(function success(data, status) {
+                    resolveWithEntityOrRejectWithMessage(deferred, data, status);
+                })
+                .error(function error(message, status) {
+                    deferred.reject(message, status);
+                }
+            );
+            return deferred.promise;
+        }
+    };
+
+    /**
+     * Format Date into SQL string.
+     *
+     * @param date Date instance
+     * @returns formatted SQL string
+     */
+    function formatTimestamp(date) {
+        return date.getFullYear()+'-'+('0'+(date.getMonth()+1)).slice(-2)+'-'+('0'+date.getDate()).slice(-2)+' '+('0'+date.getHours()).slice(-2)+':'+('0'+date.getMinutes()).slice(-2)+':'+('0'+date.getSeconds()).slice(-2);
+    }
+
+    /**
+     * Resolve with entity or reject with message.
+     *
+     * @param deferred deferred prommise
+     * @param data results data
+     * @param status status
+     */
+    function resolveWithEntityOrRejectWithMessage(deferred, data, status) {
+        if (!!data && ((data.successful === 1) || (data.status == 200))) {
+            var entity = ((!!data && !!data.results && data.results.length) ? data.results[0].entity : undefined);
+            deferred.resolve(entity, status);
+        } else {
+            var message = ((!!data && !!data.results && data.results.length) ? data.results[0].message : undefined);
+            deferred.reject(message, status);
+        }
+    }
+
+    return service;
+};
+
+// Demonstrate how to register services
+// In this case it is a simple value service.
+angular.module('myApp.services', []).
+    value('version', '0.1');

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/ServerService.js
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/ServerService.js?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/ServerService.js (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/ServerService.js Fri Feb 27 23:33:58 2015
@@ -0,0 +1,96 @@
+/* jshint indent:false, unused:false */
+/* jshint -W087 */
+/* global appConfig:true, _:true */
+'use strict';
+
+var ServerService = function ($cookies) {
+
+    var apiHttpConfig = {
+        // override this setting with request URL parsing
+        rootPath : "http://localhost:8080/jetspeed/services",
+        withCredentials: false,
+        withToken: false,
+        headers: {
+            'JETAPP-API-TOKEN': '6CB95F7FFA7B4B0ABF92216D822E4ECD',
+            'JETAPP-APP-NAME' : 'j2-admin'
+        }
+    }
+
+    var PATH_SEPARATOR = "/";
+    var PORT_SEPARATOR = ":";
+
+    function endsWith(str, suffix) {
+        return str.indexOf(suffix, str.length - suffix.length) !== -1;
+    }
+
+    function startsWith(str, prefix) {
+        return str.indexOf(prefix) === 0;
+    }
+
+    function getContextPath() {
+        return window.location.pathname.substring(0, window.location.pathname.indexOf("/",2));
+    }
+
+    function concatenatePaths(base, path) {
+        var result = "";
+        if (base === null) base = "";
+        if (path === null) path = "";
+        result = result + base;
+        if (endsWith(base, PATH_SEPARATOR)) {
+            if (startsWith(path, PATH_SEPARATOR)) {
+                result = result + path.substring(1);
+            }
+            else
+                result = result + path;
+        }
+        else {
+            if (startsWith(path, PATH_SEPARATOR) || startsWith(path, PORT_SEPARATOR))
+                result = result + path;
+            else {
+                result = result  + PATH_SEPARATOR;
+                result = result + path;
+            }
+        }
+        return result;
+    }
+
+
+    return {
+        api: function (endPoint, pathParam, pathParam2, pathParam3, pathParam4) {
+            var url = window.location.origin + getContextPath() + '/services' + endPoint;
+            if (apiHttpConfig.withToken) {
+                var token = $cookies.JetAppToken;
+                if (!_.isUndefined(token)) {
+                    apiHttpConfig.headers['JETAPP-API-TOKEN'] = token;
+                }
+                var root = angular.fromJson($cookies.JetAppRestService);
+                var url = "";
+                if (!_.isUndefined(root)) {
+                    apiHttpConfig.headers.rootPath = root;
+                    url = concatenatePaths(root, endPoint);
+                }
+                else {
+                    url = window.location.origin + '/jetspeed/services' + endPoint;
+                }
+            }
+            if (pathParam !== undefined) {
+                url += '/' + pathParam;
+            }
+            if (pathParam2 !== undefined) {
+                url += '/' + pathParam2;
+            }
+            if (pathParam3 !== undefined) {
+                url += '/' + pathParam3;
+            }
+            if (pathParam4 !== undefined) {
+                url += '/' + pathParam4;
+            }
+            return url;
+        },
+
+        apiConfig: function () {
+            return _.clone(apiHttpConfig);
+        }
+    }
+};
+

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/TextMessages.js
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/TextMessages.js?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/TextMessages.js (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/TextMessages.js Fri Feb 27 23:33:58 2015
@@ -0,0 +1,35 @@
+var TextMessages = function () {
+
+    var service = {
+
+        messages_en: {
+            notFound: 'Message not found',
+            serverFailure:
+                'We\'re sorry, but we had trouble contacting our Monitor server. Please contact support for further assistance. Message: %s status: %s',
+            serverSuccess: 'Server is up and running',
+            serverFailed: 'Bad status. Status: %s',
+            prefsUpdated: 'Your preferences have been updated.'
+        },
+
+        get: function (key, etc) {
+            // TODO: localize
+            var message = service.messages_en[key];
+            if (message === undefined)
+                return service.messages_en['notFound'];
+            if (arguments.length <= 1)
+                return message;
+            var args = Array.prototype.slice.call(arguments, 1);
+            args.unshift(message);
+            return service.sprintf.apply(service, args);
+        },
+
+        sprintf: function(format, etc) {
+            var arg = arguments;
+            var i = 1;
+            return format.replace(/%((%)|s)/g, function (m) { return m[2] || arg[i++] })
+        }
+
+    }
+
+    return service;
+}

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/controllers.js
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/controllers.js?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/controllers.js (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/controllers.js Fri Feb 27 23:33:58 2015
@@ -0,0 +1,439 @@
+'use strict';
+
+/* Controllers: */
+angular.module('j2admin.controllers', [])
+    .controller('ProfilerController', function ($scope, $q, $interval, $log, $modal, DataService, TextMessages, PortletService) {
+        $scope.columnDefs = [
+            {
+                field: 'id', displayName: 'ID', width: '20%',
+                cellTemplate: '<div ng-click="editProfile(row.rowIndex)"><div class="ngCellText">{{row.getProperty(col.field)}}</div></div>'
+            },
+            {
+                field: 'title', displayName: 'Profile Name', width: '50%',
+                cellTemplate: '<div ng-click="editProfile(row.rowIndex)"><div class="ngCellText">{{row.getProperty(col.field)}}</div></div>'
+            },
+            {
+                field: 'concreteClass', displayName: 'Class', width: '30%',
+                cellTemplate: '<div ng-click="editProfile(row.rowIndex)"><div class="ngCellText">{{row.getProperty(col.field)}}</div></div>'
+            }
+        ];
+
+        $scope.filters = {
+            term: ''
+        };
+
+        var searchTimeout = null;
+        $scope.perPage = 10;
+        $scope.page = 0;
+        $scope.maxPage = 0;
+        $scope.currentIndex = -1;
+
+        $scope.options = {
+            showSelectionCheckbox: true,
+            selectWithCheckboxOnly: true,
+            selectedItems: [],
+            data: 'profiles',
+            columnDefs: 'columnDefs',
+            plugins: [new ngGridFlexibleHeightPlugin()]
+        };
+        $scope.initialized = false;
+
+        $scope.alerts = [];
+
+        $scope.closeAlert = function (index) {
+            $scope.alerts = [];
+        };
+
+        $scope.addFailureAlert = function (errorMessage, status) {
+            $scope.alerts.length = 0;
+            var statusMsg = (status === undefined) ? "none" : status;
+            $scope.alerts.push({type: 'danger', msg: TextMessages.get('serverFailure', errorMessage, statusMsg)});
+        };
+
+        // ---- init function
+        $scope.init = function (readResourceURL) {
+
+            $scope.readResourceURL = readResourceURL;
+            PortletService.lookupPreferences(readResourceURL).then(
+                function success(prefs, status) {
+                    $scope.prefs = prefs;
+                    $scope.perPage = prefs.rowsPerPage;
+                    // $scope.columnDefs[1].displayName = (!!~prefs.service.indexOf('cpu')) ? "CPU %" : "Memory %";
+                    $scope.getData();
+
+                    if ($scope.initialized == false) {
+                        //$interval(refresh, $scope.prefs.refreshSeconds * 1000);
+                    }
+
+                    $scope.initialized = true;
+                },
+                function error(msg, status) {
+                    console.log(msg);
+                    $scope.addFailureAlert(msg, status);
+                }
+            );
+        }; // end init
+
+        // -- retrieve a page of profiles
+        $scope.getData = function () {
+            var filters = {};
+
+            if ($scope.filters.term.length) {
+                filters.id = $scope.filters.term;
+                filters.title = $scope.filters.term;
+                filters.concreteClass = $scope.filters.term;
+            }
+
+            DataService.listProfiles(filters, $scope.page * $scope.perPage, $scope.perPage).then(
+                function success(profiles, status) {
+                    $scope.profilesAll = profiles.records;
+                    $scope.maxPage = Math.floor($scope.profilesAll.length / $scope.perPage);
+                    $scope.getPage();
+                },
+                function error(msg, status) {
+                    console.log(msg);
+                    $scope.addFailureAlert(msg, status);
+                }
+            )
+        }; // end getPage
+
+        $scope.getPage = function () {
+            var intermediary = _.filter($scope.profilesAll, function(profile) {
+                return ((profile.id.indexOf($scope.filters.term) !== -1) ||
+                (profile.title.indexOf($scope.filters.term) !== -1) ||
+                (profile.concreteClass.indexOf($scope.filters.term) !== -1))
+            });
+
+            $scope.profiles = intermediary.slice($scope.page * $scope.perPage, ($scope.page + 1) * $scope.perPage);
+
+            if (!$scope.$$phase) {
+                $scope.$apply();
+            }
+        };
+
+        // -- get previous page
+        $scope.getNextPage = function () {
+            $scope.page++;
+
+            $scope.getPage();
+        };
+
+        // -- get next page
+        $scope.getPrevPage = function () {
+            $scope.page--;
+
+            if($scope.page < 0) {
+                $scope.page = 0;
+            }
+
+            $scope.getPage();
+        };
+
+        // -- perform search
+        $scope.search = function() {
+            if(searchTimeout) {
+                clearTimeout(searchTimeout);
+            }
+
+            searchTimeout = setTimeout(function() {
+                    $scope.page = 0;
+                    $scope.getPage();
+                },
+                500);
+        };
+
+        var activeDialog = null;
+
+        // -- add or edit profile
+        $scope.editProfile = function(index) {
+            $scope.currentIndex = index;
+
+            if(activeDialog) {
+                return;
+            }
+
+            var modalInstance = $modal.open({
+                // TODO: get context
+                templateUrl: '/j2-admin/jetapp/views/modals/profile-detail.html',
+                controller: ProfileDetailsInstanceController,
+                backdrop: false,
+                resolve: {
+                    DataService: function() { return DataService; },
+                    profile: function() { return (typeof index === 'undefined') ? null : $scope.profiles[index]; },
+                    parentScope: function() { return $scope; },
+                    existing: function() { return (typeof index !== 'undefined'); },
+                    existingIds: function() { return _.pluck($scope.profilesAll, "id"); }
+                }
+            });
+
+            activeDialog = modalInstance;
+
+            modalInstance.result.then(function () {
+                activeDialog = null;
+                $scope.getData();
+            }, function () {
+                activeDialog = null;
+                $log.info('Modal dismissed at: ' + new Date());
+            });
+        };
+
+        $scope.deleteHosts = function() {
+            var modalInstance = $modal.open({
+                // TODO: get context
+                templateUrl: '/j2-admin/jetapp/views/modals/profiles-delete.html',
+                controller: DeleteProfilesInstanceController,
+                resolve: {
+                    DataService: function() { return DataService; },
+                    selectedItems: function() { return $scope.options.selectedItems; }
+                }
+            });
+
+            modalInstance.result.then(function () {
+                $scope.options.selectedItems = [];
+                $scope.getData();
+            }, function () {
+                $log.info('Modal dismissed at: ' + new Date());
+            });
+        };
+    }
+)
+    .controller('ProfilerEditController', function ($scope, DataService, PortletService) {
+        $scope.master = {};
+
+        $scope.init = function (readResourceURL, writeResourceURL, renderURL) {
+            $scope.readResourceURL = readResourceURL;
+            $scope.writeResourceURL = writeResourceURL;
+            $scope.renderURL = renderURL;
+            PortletService.lookupPreferences(readResourceURL).then(
+                function success(prefs, status) {
+                    $scope.prefs = prefs;
+                    $scope.master = angular.copy(prefs);
+                    //$scope.profileEditForm.$setPristine();
+                },
+                function error(msg, status) {
+                    console.log(msg);
+                    $scope.addFailureAlert(msg, status);
+                }
+            )
+        };
+
+        $scope.update = function (prefs) {
+            PortletService.storePreferences($scope.writeResourceURL, prefs).then(
+                function success(result, status) {
+                    //window.location = $scope.renderURL;
+                },
+                function error(msg, status) {
+                    console.log(msg);
+                    $scope.addFailureAlert(msg, status);
+                }
+            )
+        };
+
+        $scope.reset = function () {
+            $scope.prefs = angular.copy($scope.master);
+        };
+
+        $scope.clear = function () {
+            $scope.master = {};
+            $scope.prefs = {};
+            $scope.profileEditForm.$setPristine();
+        };
+
+        $scope.isUnchanged = function (prefs) {
+            return angular.equals(prefs, $scope.master);
+        };
+
+        $scope.alerts = [
+        ];
+
+        $scope.closeAlert = function (index) {
+            $scope.alerts = [];
+        };
+
+        $scope.addFailureAlert = function (errorMessage, status) {
+            $scope.alerts.length = 0;
+            var statusMsg = (status === undefined) ? "none" : status;
+            $scope.alerts.push({type: 'danger', msg: TextMessages.get('serverFailure', errorMessage, statusMsg) });
+        };
+
+        $scope.addSuccessAlert = function () {
+            $scope.alerts.length = 0;
+            $scope.alerts.push({type: 'success', msg: TextMessages.get('PrefsUpdated') });
+        };
+
+        $scope.reset();
+    });
+
+var CriteriaDetailsInstanceController = function ($scope, $modalInstance, criteria) {
+
+    $scope.criteria = criteria || {
+        name: '',
+        value: '',
+        resolverType: '',
+        fallback: -1,
+        order: 0
+    };
+
+    $scope.add = function() {
+        $modalInstance.close($scope.criteria);
+    };
+
+    $scope.close = function() {
+        $modalInstance.dismiss();
+    };
+};
+CriteriaDetailsInstanceController.$inject = ['$scope', '$modalInstance', 'criteria'];
+
+/**
+ * Profile Instance Controller for modal dialog of editing of profile form
+ *
+ * @param $scope
+ * @param $modalInstance
+ * @param DataService
+ * @param profile
+ * @param parentScope
+ * @constructor
+ */
+var ProfileDetailsInstanceController = function ($scope, $modal, $modalInstance, $log, DataService, profile, parentScope, existing, existingIds) {
+
+    $scope.profile = profile || {
+        id: '',
+        title: '',
+        concreteClass: '',
+        criteria: []
+    };
+
+    $scope.existing = existing;
+    $scope.existingIds = existingIds;
+
+    if (profile != null) {
+        DataService.getProfile(profile.id).then(
+            function success(result) {
+                $scope.profile = result;
+            },
+            function error(message) {
+                console.log(message);
+                $scope.addFailureAlert(message);
+            });
+    }
+
+    parentScope.$watch('currentIndex', function(newIndex) {
+        if(typeof(newIndex) != 'undefined') {
+            $scope.profile = parentScope.profiles[newIndex];
+        }
+    });
+
+    $scope.isUniqueId = function() {
+        return ($scope.existingIds.indexOf($scope.profile.id) === -1);
+    };
+
+    $scope.isValidTitle = function() {
+        var hostNameRegEx = /^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$/;
+        return true;
+        //return ipaddr.isValid($scope.hostIdentity.hostName) || hostNameRegEx.test($scope.hostIdentity.hostName);
+    };
+
+    $scope.alerts = [];
+
+    $scope.hasAlias = function(alias) {
+        return ($scope.hostIdentity.hostNames.indexOf(alias) !== -1);
+    };
+
+    //$scope.addAlias = function(alias) {
+    //    $scope.hostIdentity.hostNames.push('');
+    //};
+    //
+    //$scope.removeAlias = function(index) {
+    //    $scope.hostIdentity.hostNames.splice(index, 1);
+    //};
+
+    $scope.add = function() {
+        //var names = $scope.hostIdentity.hostNames;
+        //
+        //for(var i = 0; i < names.length; i++) {
+        //    if(!names[i].length) {
+        //        names.splice(i, 1);
+        //        i--;
+        //    }
+        //}
+
+        DataService.createOrUpdateProfile($scope.profile).then(
+            function success(entity) {
+                $modalInstance.close();
+            },
+            function error(message) {
+                if(message.indexOf('ConstraintViolationException') != -1) {
+                    message = 'This profile is likely to exist already - please choose another name.';
+                }
+
+                console.log(message);
+                $scope.addFailureAlert(message);
+            });
+    };
+
+    $scope.addCriteria = function(index) {
+        var modalInstance = $modal.open({
+            // TODO: get context
+            templateUrl: '/j2-admin/jetapp/views/modals/criteria-detail.html',
+            controller: CriteriaDetailsInstanceController,
+            backdrop: false,
+            resolve: {
+                criteria: function() { return $scope.profile.criteria[index] || {}; }
+            }
+        });
+
+        modalInstance.result.then(function (retCriteria) {
+            if(typeof index !== 'undefined') {
+                $scope.profile.criteria[index] = retCriteria;
+            }
+            else {
+                $scope.profile.criteria.push(retCriteria);
+            }
+        }, function () {
+            $log.info('Modal dismissed at: ' + new Date());
+        });
+    };
+
+    $scope.removeCriteria = function(index) {
+        $scope.profile.criteria.splice(index, 1);
+    };
+
+    $scope.close = function() {
+        $modalInstance.dismiss();
+    };
+
+    $scope.addFailureAlert = function(message) {
+        $scope.alerts.length = 0;
+        $scope.alerts.push({type: 'danger', msg: message});
+    };
+
+    $scope.closeAlert = function(index) {
+        $scope.alerts.splice(index, 1);
+    };
+};
+ProfileDetailsInstanceController.$inject = ['$scope', '$modal', '$modalInstance', '$log', 'DataService', 'profile', 'parentScope', 'existing', 'existingIds'];
+
+var DeleteProfilesInstanceController = function ($scope, $modalInstance, DataService, selectedItems) {
+
+    $scope.deleteItems = function() {
+        var ids = [];
+
+        for(var i = 0, iLimit = selectedItems.length; i < iLimit; i++) {
+            ids.push(selectedItems[i].id);
+        }
+
+        DataService.deleteProfiles(ids).then(
+            function success(data) {
+                $modalInstance.close();
+            },
+            function failures(message, status) {
+                $scope.addFailureAlert(message);
+            });
+    };
+
+    $scope.close = function() {
+        $modalInstance.dismiss();
+    };
+};
+DeleteProfilesInstanceController.$inject = ['$scope', '$modalInstance', 'DataService', 'selectedItems'];
+

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/directives.js
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/directives.js?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/directives.js (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/directives.js Fri Feb 27 23:33:58 2015
@@ -0,0 +1,272 @@
+'use strict';
+
+/* Directives: */
+angular.module('j2admin.directives', [])
+    .directive('gwpStatusIcon', ['$timeout', function ($timeout) {
+        return {
+            restrict: 'A',
+            link : function(scope, element, attrs){
+                var self = $(element);
+
+                $timeout(function() {
+                    if(self.hasClass('status-yellow')) {
+                        self.append('<div class="glyphicon glyphicon-warning-sign"></div>');
+                    }
+                });
+            }
+        }
+    }])
+    .directive('gwpStatusHover', ['DataService', function (DataService) {
+        return {
+            restrict: 'A',
+            link : function(scope, element, attrs) {
+                var self = $(element),
+                    item = scope.item,
+                    body = $(document.body);
+
+                self.hover(function() {
+                        $('#infohover').remove();
+
+                        var position = self.offset();
+
+                        DataService.getEventsByHost(item.hostName)
+                            .then(function(data) {
+                                var events = data,
+                                    highAlerts = [1, 2, 3], avgAlerts = [1, 2, 3], lowAlerts = [1, 2, 3];
+
+                                for(var i = 0, iLimit = events.length; i < iLimit; i++) {
+                                    var event = events[i];
+
+                                    switch(event.monitorStatus) {
+                                        case 'SCHEDULED CRITICAL':
+                                        case 'SCHEDULED DOWN':
+                                        case 'UNREACHABLE':
+                                        case 'UNSCHEDULED DOWN':
+                                        case 'UNSCHEDULED CRITICAL':
+                                        case 'ACKNOWLEDGEMENT (CRITICAL)':
+                                        case 'ACKNOWLEDGEMENT (DOWN)':
+                                        case 'ACKNOWLEDGEMENT (UNREACHABLE)':
+                                        case 'CRITICAL':
+                                        case 'DOWN':
+                                            highAlerts.push(event);
+                                            break;
+
+                                        case 'WARNING':
+                                        case 'ACKNOWLEDGEMENT (WARNING)':
+                                        case 'ACKNOWLEDGEMENT (MAINTENANCE)':
+                                        case 'MAINTENANCE':
+                                            avgAlerts.push(event);
+                                            break;
+
+                                        case 'UP':
+                                        case 'OK':
+                                        case 'ACKNOWLEDGEMENT (UP)':
+                                        case 'ACKNOWLEDGEMENT (OK)':
+                                        case 'UNKNOWN':
+                                        case 'PENDING':
+                                        case 'ACKNOWLEDGEMENT (UNKNOWN)':
+                                        case 'ACKNOWLEDGEMENT (PENDING)':
+                                        case 'SUSPENDED':
+                                        default:
+                                            lowAlerts.push(event);
+                                            break;
+                                    }
+                                }
+
+                                var alertHtml = '';
+
+                                if(highAlerts.length || avgAlerts.length || lowAlerts.length) {
+                                    alertHtml = '<hr />';
+
+                                    if(highAlerts.length) {
+                                        alertHtml += '<h4><img class="icon icon-alert" src="/portal-groundwork-base/app/images/status/host-red.gif" />Critical alerts (' + highAlerts.length + ')</h4>';
+                                        /*
+                                         for(i = 0, iLimit = highAlerts.length; i < iLimit; i++) {
+                                         alertHtml += '<p>' + highAlerts[i].textMessage + '</p>';
+                                         }
+                                         */
+                                        if(avgAlerts.length || lowAlerts.length) {
+                                            alertHtml += '<hr />';
+                                        }
+                                    }
+
+                                    if(avgAlerts.length) {
+                                        alertHtml += '<h4><img class="icon" src="/portal-groundwork-base/app/images/status/host-yellow.gif" />Warning alerts (' + avgAlerts.length + ')</h4>';
+                                        /*
+                                         for(i = 0, iLimit = avgAlerts.length; i < iLimit; i++) {
+                                         alertHtml += '<p>' + avgAlerts[i].textMessage + '</p>';
+                                         }
+                                         */
+                                        if(lowAlerts.length) {
+                                            alertHtml += '<hr />';
+                                        }
+                                    }
+
+                                    if(lowAlerts.length) {
+                                        alertHtml += '<h4><img class="icon" src="/portal-groundwork-base/app/images/status/host-green.gif" />Info alerts (' + lowAlerts.length + ')</h4>';
+                                        /*
+                                         for(i = 0, iLimit = lowAlerts.length; i < iLimit; i++) {
+                                         alertHtml += '<p>' + lowAlerts[i].textMessage + '</p>';
+                                         }
+                                         */
+                                    }
+                                }
+
+                                $('#infohover').remove();
+
+                                var bodyWidth = body.width();
+                                var infoHover = $('<div id="infohover"><h3>' + item.hostName + '</h3><p class="timestamp">' + moment(item.lastCheckTime).format('dddd, MMMM Do YYYY, h:mm:ss a') + '</p>' + alertHtml + '</div>');
+                                body.append(infoHover);
+
+                                var left = position.left + self.outerWidth()  / 1.5;
+
+                                if((left + infoHover.width()) > bodyWidth) {
+                                    left = position.left + self.outerWidth() / 3 - infoHover.width();
+                                }
+
+                                infoHover.css({
+                                    top:  position.top  + self.outerHeight() / 1.5,
+                                    left: left
+                                });
+                            },
+                            function() {
+                            });
+                    },
+                    function() {
+                        $('#infohover').remove();
+                    });
+                    
+                    self.closest('tab-content').hover(function() {}, function() {
+                        $('#infohover').remove();
+                    });
+            }
+        }
+    }])
+    .directive('gwpEventHover', ['DataService', function (DataService) {
+        return {
+            restrict: 'A',
+            link : function(scope, element, attrs){
+                var self = $(element),
+                    event = scope.event,
+                    body = $(document.body);
+
+                self.hover(function() {
+                        $('#eventhover').remove();
+
+                        var position = self.offset();
+
+                        var eventHover = $('<div id="eventhover"><p>Updated ' + event.lastDate.format('dddd, MMMM Do YYYY, h:mm:ss a') + ', click to view this alert.</p><p>' + event.event.textMessage + '</p></div>');
+
+                        body.append(eventHover);
+
+                        eventHover.css({
+                            top:  position.top  + self.outerHeight(),
+                            left: position.left + 100
+                        });
+                    },
+                    function() {
+                        $('#eventhover').remove();
+                    });
+            }
+        }
+    }])
+    .directive('gwpDatepicker', function () {
+        return {
+            restrict: 'A',
+            link : function(scope, element, attrs){
+                var self = $(element), path = attrs.gwpDatepicker.split('.');
+
+                self.Zebra_DatePicker({format: 'Y-m-d', onSelect: function(e) {
+                    var variable = scope;
+
+                    for(var i = 0, iLimit = path.length; i < iLimit; i++) {
+                        variable = variable[path[i]];
+                    }
+
+                    variable = e;
+                    scope.getPage();
+                }});
+            }
+        }
+    })
+    .directive('gwpSlidingDialog', function () {
+        return {
+            restrict: 'A',
+            link : function(scope, element, attrs){
+                var self = $(element), dialog = self.closest('.modal');
+                dialog.addClass('slide-from-right');
+
+                var baseGrid = $('#grid.base-grid');
+                if(baseGrid.length) {
+                    var top = baseGrid.offset().top;
+
+                    dialog.css('margin-top', top + 'px');
+                }
+            }
+        }
+    })
+    .directive('gwpAutofocus', function () {
+        return {
+            restrict: 'A',
+            link : function(scope, element, attrs){
+                var self = $(element), dialog = self.closest('.modal');
+
+                dialog.on('shown.bs.modal', function () {
+                    setTimeout(function() {
+                        element.focus();
+                    },
+                    100);
+                });
+
+                setTimeout(function() {
+                    element.focus();
+                },
+                100);
+            }
+        }
+    })
+    .directive('gwpNoSpaces', function () {
+        return {
+            restrict: 'A',
+            link : function(scope, element, attrs){
+                var self = $(element);
+
+                self.on('keypress', function(e) {
+                    if(e.which === 32) {
+                        if(e.preventDefault) {
+                            e.preventDefault();
+                        }
+
+                        return false;
+                    }
+                });
+
+                self.on('paste', function () {
+                    setTimeout(function () {
+                        var text = self.val().replace(/\s/g, "");
+
+                        self.val(text);
+                    },
+                    100);
+                });
+            }
+        }
+    })
+    .directive('gwpFitGrid', ['$timeout', function ($timeout) {
+        return {
+            restrict: 'A',
+            link : function(scope, element, attrs){
+                var container = $(element);
+
+                $timeout(function() {
+                    var nav = container.find('.audit-nav-container'),
+                        grid = container.find('.panel-grid'),
+                        viewport = grid.find('.ngViewport');
+
+                    grid.css({height: (container.height() - nav.height()) + 'px'});
+                    viewport.css({height: (container.height() - nav.height() - grid.find('.ngHeaderContainer').height()) + 'px'});
+                });
+            }
+        }
+    }]);
+

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/filters.js
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/filters.js?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/filters.js (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/scripts/filters.js Fri Feb 27 23:33:58 2015
@@ -0,0 +1,10 @@
+'use strict';
+
+/* Filters */
+
+angular.module('j2admin.filters', []).
+  filter('interpolate', ['version', function(version) {
+    return function(text) {
+      return String(text).replace(/\%VERSION\%/mg, version);
+    };
+  }]);

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/app.css
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/app.css?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/app.css (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/app.css Fri Feb 27 23:33:58 2015
@@ -0,0 +1,293 @@
+/* custom inclusion of right, left and below tabs */
+a.ItemIcon.DefaultPageIcon {
+    color: black !important;
+    font-family: Helvetica, Arial, sans-serif;
+    font-size: 11px;
+}
+
+.UINavigationPortlet .UITab a.TabIcon {
+    color: black ;
+    text-decoration: none ;
+}
+
+.UINavigationPortlet .NormalNavigationTab a.TabIcon {
+    color: #fff;
+}
+
+.TabIcon {
+    font-size: 11px !important;
+    font-family: sans-serif !important;
+}
+.FL {
+    font-size: 11px !important;
+    font-family: sans-serif !important;
+}
+.Selected {
+    font-size: 11px !important;
+    font-family: sans-serif !important;
+}
+
+.tabs-below > .nav-tabs,
+.tabs-right > .nav-tabs,
+.tabs-left > .nav-tabs {
+    border-bottom: 0;
+}
+
+.tab-content > .tab-pane,
+.pill-content > .pill-pane {
+    display: none;
+}
+
+.tab-content > .active,
+.pill-content > .active {
+    display: block;
+}
+
+.tabs-below > .nav-tabs {
+    border-top: 1px solid #ddd;
+}
+
+.tabs-below > .nav-tabs > li {
+    margin-top: -1px;
+    margin-bottom: 0;
+}
+
+.tabs-below > .nav-tabs > li > a {
+    -webkit-border-radius: 0 0 4px 4px;
+    -moz-border-radius: 0 0 4px 4px;
+    border-radius: 0 0 4px 4px;
+}
+
+.tabs-below > .nav-tabs > li > a:hover,
+.tabs-below > .nav-tabs > li > a:focus {
+    border-top-color: #ddd;
+    border-bottom-color: transparent;
+}
+
+.tabs-below > .nav-tabs > .active > a,
+.tabs-below > .nav-tabs > .active > a:hover,
+.tabs-below > .nav-tabs > .active > a:focus {
+    border-color: transparent #ddd #ddd #ddd;
+}
+
+.tab-icon {
+    max-height: 2em;
+    margin-right: 1.5em;
+}
+
+.tab-name {
+    margin-top: 1em;
+}
+
+.tab-pane {
+    border-left: 1px solid #ddd;
+    border-right: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+    padding: 1em;
+    height: 500px;
+    max-height: 500px;
+    overflow-x: hidden;
+    overflow-y: auto
+text-align: center;
+}
+
+.icon-list {
+    list-style-type: none;
+    margin: 0;
+    padding: 0;
+}
+
+.icon-list:after {
+    clear: both;
+}
+
+.icon-list .icon-list-item {
+    float: left;
+    position: relative;
+    margin: 0 0 4px 0;
+    width: 72px;
+    height: 72px;
+    text-align: center;
+    padding: 8px;
+}
+
+.icon-list .icon-list-item .status {
+    position: absolute;
+    top: 0px;
+    right: 3px;
+}
+
+.icon-list .icon-list-item .status-red {
+    color: red;
+}
+
+.icon-list .icon-list-item .status-yellow {
+    color: #7F6A00;
+}
+
+.icon-list .icon-list-item div.img-container {
+    padding: 10px;
+    max-width: 100px;
+    border: 1px solid lightgrey;
+}
+
+.icon-list .icon-list-item div.img-container img {
+    max-width: 100%;
+}
+
+.icon-list .icon-list-item p.name {
+    margin-top: 1px;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    font-size: 7pt;
+}
+
+.no-margin {
+    margin: 0;
+}
+
+.no-padding {
+    padding: 0 !important;
+}
+
+.audit-nav-container form {
+    padding: 0;
+}
+
+.panel.no-border {
+    border: 0;
+}
+
+.Zebra_DatePicker_Icon_Wrapper {
+    float: none !important;
+}
+
+#audit-next[disabled] {
+    color: #999;
+}
+
+#infohover {
+    position: absolute;
+    top: 0;
+    left: 0;
+    padding: .5em;
+    background: white;
+    border: 1px solid lightgrey;
+    width: 300px;
+    min-height: 100px;
+    max-height: 500px;
+    overflow-x: hidden;
+    overflow-y: auto;
+    text-align: left;
+    z-index: 1;
+}
+
+#infohover h3 {
+    padding-top: 0;
+    margin-top: 0;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    overflow: hidden;
+    width: 270px;
+    font-size: 1.6em;
+    display: block;
+    text-decoration: none !important;
+}
+
+#infohover .timestamp {
+    font-size: 1.2em;
+}
+
+#infohover h4 {
+    font-size: 1em;
+}
+
+#infohover h4 .icon {
+    position: relative;
+    top: -1px;
+    margin-right: .7em;
+}
+
+#infohover h4 .icon.icon-alert {
+    top: -3px;
+}
+
+#infohover hr {
+    padding: 0;
+    margin: 1em;
+    color: grey;
+    border-top: 1px solid grey;
+}
+
+.alert {
+    color: red;
+    padding-bottom: 0;
+    margin-bottom: 0;
+    text-shadow: 0 0 0;
+    box-shadow: none;
+}
+
+table.filter-table, table.filter-table-2 {
+    margin: .5em .25em 1em .25em;
+}
+
+table.filter-table td {
+    padding: .5em 1em;
+}
+
+table.filter-table td label, table.filter-table-2 td label {
+    margin-bottom: 3px;
+}
+
+table.filter-table td input, table.filter-table-2 td input {
+    width: 100%;
+    padding: 5px;
+    height: 25px;
+}
+
+table.filter-table td .btn, table.filter-table-2 td .btn {
+    padding: 2px 5px;
+    font-size: 1.2em;
+}
+
+.audit-nav-container {
+    position: relative;
+}
+
+.audit-nav-top {
+    position: absolute;
+    bottom: 20px;
+    right: 10px;
+}
+
+input#host-identities-search {
+    padding: 7px;
+    height: 26px;
+}
+
+input.error {
+    color: red;
+    background-color: #FFE9E8;
+    border-color: red;
+}
+
+.margin-bottom10 {
+    margin-bottom: 10px;
+}
+
+.modal.fade.slide-from-right {
+    margin: 0;
+}
+
+.modal.fade.slide-from-right:not(.in) .modal-dialog {
+    -webkit-transform: translate3d(25%, 0, 0);
+    transform: translate3d(25%, 0, 0);
+}
+
+.modal.fade.slide-from-right.in .modal-dialog {
+    margin: 0px 10% 0px auto;
+}
+.ngViewport {
+    min-height: 50px;
+}
\ No newline at end of file

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/default.css
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/default.css?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/default.css (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/default.css Fri Feb 27 23:33:58 2015
@@ -0,0 +1,102 @@
+/*
+
+    Zebra_DatePicker: a lightweight jQuery date picker plugin
+
+    Default theme
+
+    copyright (c) 2011 - 2014 Stefan Gabos
+    http://stefangabos.ro/jquery/zebra-datepicker/
+
+*/
+
+.Zebra_DatePicker *,
+.Zebra_DatePicker *:after,
+.Zebra_DatePicker *:before  { -moz-box-sizing: content-box !important; -webkit-box-sizing: content-box !important; box-sizing: content-box !important }
+
+.Zebra_DatePicker           { position: absolute; background: #666; border: 3px solid #666; z-index: 100; font-family: Tahoma, Arial, Helvetica, sans-serif; font-size: 13px; }
+
+.Zebra_DatePicker *         { margin: 0; padding: 0; color: #000; background: transparent; border: none }
+
+/* = GLOBALS
+----------------------------------------------------------------------------------------------------------------------*/
+.Zebra_DatePicker table                      { border-collapse: collapse; border-spacing: 0; width: auto; table-layout: auto; }
+
+.Zebra_DatePicker td,
+.Zebra_DatePicker th                         { text-align: center; padding: 5px 0 }
+
+.Zebra_DatePicker td                         { cursor: pointer }
+
+.Zebra_DatePicker .dp_daypicker,
+.Zebra_DatePicker .dp_monthpicker,
+.Zebra_DatePicker .dp_yearpicker             { margin-top: 3px }
+
+.Zebra_DatePicker .dp_daypicker td,
+.Zebra_DatePicker .dp_daypicker th,
+.Zebra_DatePicker .dp_monthpicker td,
+.Zebra_DatePicker .dp_yearpicker td         { background: #E8E8E8; width: 30px; border: 1px solid #7BACD2 }
+
+.Zebra_DatePicker,
+.Zebra_DatePicker .dp_header .dp_hover,
+.Zebra_DatePicker .dp_footer .dp_hover { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px }
+
+/* = VISIBLE/HIDDEN STATES (USE TRANSITIONS FOR EFFECTS)
+----------------------------------------------------------------------------------------------------------------------*/
+.Zebra_DatePicker.dp_visible               { display: block; visibility: visible; filter: alpha(opacity=100); -khtml-opacity: 1; -moz-opacity: 1; opacity: 1; transition: opacity 0.2s ease-in-out }
+.Zebra_DatePicker.dp_hidden                { display: none; visibility: hidden; filter: alpha(opacity=0); -khtml-opacity: 0; -moz-opacity: 0; opacity: 0 }
+
+/* = HEADER
+----------------------------------------------------------------------------------------------------------------------*/
+.Zebra_DatePicker .dp_header td             { color: #FFF }
+
+.Zebra_DatePicker .dp_header .dp_previous,
+.Zebra_DatePicker .dp_header .dp_next       { width: 30px }
+
+.Zebra_DatePicker .dp_header .dp_caption    { font-weight: bold }
+.Zebra_DatePicker .dp_header .dp_hover      { background: #222; color: #FFF }
+
+/* = DATEPICKER
+----------------------------------------------------------------------------------------------------------------------*/
+.Zebra_DatePicker .dp_daypicker th              { background: #FFCC33 }
+.Zebra_DatePicker td.dp_not_in_month            { background: #F3F3F3; color: #CDCDCD; cursor: default }
+.Zebra_DatePicker td.dp_not_in_month_selectable { background: #F3F3F3; color: #CDCDCD; cursor: pointer }
+.Zebra_DatePicker td.dp_weekend                 { background: #D8D8D8 }
+.Zebra_DatePicker td.dp_weekend_disabled        { color: #CCC; cursor: default }
+.Zebra_DatePicker td.dp_selected                { background: #5A4B4B; color: #FFF !important }
+.Zebra_DatePicker td.dp_week_number             { background: #FFCC33; color: #555; cursor: text; font-style: italic }
+
+/* = MONTHPICKER
+----------------------------------------------------------------------------------------------------------------------*/
+.Zebra_DatePicker .dp_monthpicker td    { width: 33% }
+
+/* = YEARPICKER
+----------------------------------------------------------------------------------------------------------------------*/
+.Zebra_DatePicker .dp_yearpicker td     { width: 33% }
+
+/* = FOOTER
+----------------------------------------------------------------------------------------------------------------------*/
+.Zebra_DatePicker .dp_footer            { margin-top: 3px }
+.Zebra_DatePicker .dp_footer .dp_hover  { background: #222; color: #FFF }
+
+/* = SELECT CURRENT DAY
+----------------------------------------------------------------------------------------------------------------------*/
+.Zebra_DatePicker .dp_today { color: #FFF; padding: 3px }
+
+/* = CLEAR DATE
+----------------------------------------------------------------------------------------------------------------------*/
+.Zebra_DatePicker .dp_clear { color: #FFF; padding: 3px }
+
+/* = SOME MORE GLOBALS (MUST BE LAST IN ORDER TO OVERWRITE PREVIOUS PROPERTIES)
+----------------------------------------------------------------------------------------------------------------------*/
+.Zebra_DatePicker td.dp_current             { color: #C40000 }
+.Zebra_DatePicker td.dp_disabled_current    { color: #E38585 }
+.Zebra_DatePicker td.dp_disabled            { background: #F3F3F3; color: #CDCDCD; cursor: default }
+.Zebra_DatePicker td.dp_hover               { background: #482424; color: #FFF }
+
+/* = ICON
+----------------------------------------------------------------------------------------------------------------------*/
+button.Zebra_DatePicker_Icon                { display: block; position: absolute; width: 16px; height: 16px; background: url('calendar.png') no-repeat left top; text-indent: -9000px; border: none; cursor: pointer; padding: 0; line-height: 0; vertical-align: top }
+button.Zebra_DatePicker_Icon_Disabled       { background-image: url('calendar-disabled.png') }
+
+/* don't set vertical margins! */
+button.Zebra_DatePicker_Icon                { margin: 0 0 0 3px }
+button.Zebra_DatePicker_Icon_Inside         { margin: 0 3px 0 0 }
\ No newline at end of file

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/ng-grid.min.css
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/ng-grid.min.css?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/ng-grid.min.css (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/styles/ng-grid.min.css Fri Feb 27 23:33:58 2015
@@ -0,0 +1 @@
+.ngGrid{background-color:#fdfdfd}.ngGrid input[type="checkbox"]{margin:0;padding:0}.ngGrid input{vertical-align:top}.ngGrid.unselectable{-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.ngViewport{overflow:auto;min-height:20px}.ngViewport:focus{outline:0}.ngCanvas{position:relative}.ngVerticalBar{position:absolute;right:0;width:0}.ngVerticalBarVisible{width:1px;background-color:#d4d4d4}#testDataLength{position:absolute;top:0;right:0;z-index:-100000}.ngHeaderContainer{position:relative;overflow:hidden;font-weight:bold;background-color:inherit}.ngHeaderCell{position:absolute;top:0;bottom:0;background-color:inherit}.ngHeaderCell.pinned{z-index:1}.ngHeaderSortColumn{position:absolute;overflow:hidden}.ngTopPanel{position:relative;z-in
 dex:1;background-color:#eaeaea;border-bottom:1px solid #d4d4d4}.ngSortButtonDown{position:absolute;top:3px;left:0;right:0;margin-left:auto;margin-right:auto;border-color:gray transparent;border-styl
 e:solid;border-width:0 5px 5px 5px;height:0;width:0}.ngNoSort{cursor:default}.ngHeaderButton{position:absolute;right:2px;top:8px;-moz-border-radius:50%;-webkit-border-radius:50%;border-radius:50%;width:14px;height:14px;z-index:1;background-color:#9fbbb4;cursor:pointer}.ngSortButtonUp{position:absolute;top:3px;left:0;right:0;margin-left:auto;margin-right:auto;border-color:gray transparent;border-style:solid;border-width:5px 5px 0 5px;height:0;width:0}.ngHeaderScroller{position:absolute;background-color:inherit}.ngSortPriority{position:absolute;top:-5px;left:1px;font-size:6pt;font-weight:bold}.ngHeaderGrip{cursor:col-resize;width:10px;right:-5px;top:0;height:100%;position:absolute;background-color:transparent}.ngHeaderText{padding:5px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box
 ;box-sizing:border-box;white-space:nowrap;-ms-text-overflow:ellipsis;-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden}.ngHeaderButtonArrow{position:absolute;top:4px;left:3px;width:0;
 height:0;border-style:solid;border-width:6.5px 4.5px 0 4.5px;border-color:#4d4d4d transparent transparent transparent}.ngPinnedIcon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABp0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuMTAw9HKhAAAAmElEQVQoU33PQapBURjA8UtkwJuaWYGSgfQWYBMvczPmTCzAAGVuaA228BZhRCkDGSmE31FucuRfvzq3vr5zT/JSjSU7DsypEPXDkDVn2hSIytJhw4kWGaLCxgHh2gt/RBuLzNhz5caWPjnSqqw4EraFfwznf8qklWjwy4IRTerkiQoPGtPl40OehcEJvcfXl8LglLfBJLkDcMgbgHlHhK8AAAAASUVORK5CYII=);background-repeat:no-repeat;position:absolute;right:5px;top:5px;height:10px;width:10px}.ngUnPinnedIcon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAA
 ABp0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuMTAw9HKhAAAAlElEQVQoU33PPQrCQBRF4fFnI2KfZVi5ARvdgo1l6mwmkCJVOgluwd5OwUoDtnoOxAei8cLXTN7cvEl/skCNDCMPfsUPO5zQwOHIDEvYtMURHe6wOVLgigvOePRyeDkyR4ln7wZ//7XfFBu8B2
 3+aDJjrHGAwza7hjtHJvDmHg7b7Bru7AMjK7Rw2ObBVHDY5oGk9AKQNB2zy8MBTgAAAABJRU5ErkJggg==);background-repeat:no-repeat;position:absolute;height:10px;width:10px;right:5px;top:5px}.ngColMenu{right:2px;padding:5px;top:25px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-color:#bdd0cb;position:absolute;border:2px solid #d4d4d4;z-index:1}.ngColListCheckbox{position:relative;right:3px;top:4px}.ngColList{list-style-type:none;margin-top:2px;margin-left:8px}.ngColListItem{white-space:nowrap}.ngMenuText{position:relative;top:2px;left:2px}.ngGroupPanel{background-color:#eaeaea;overflow:hidden;border-bottom:1px solid #d4d4d4}.ngGroupPanelDescription{margin-top:5px;margin-left:5px}.ngGroupList{list-style-type:none;margin:0;padding:0}.ngAggHeader{position:absolute;border:0}.ngGro
 upElement{float:left;height:100%;width:100%}.ngGroupIcon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAYAAACZ3F9/AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADs
 MAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAEFJREFUKFNjoAhISkr+h2J5JDZODNXGwGBsbPwfhIGAA8bGh6HaGBiAGhxAGJmND4M1gQCSM0adCsVQbcPcqQwMALWDGyDvWPefAAAAAElFTkSuQmCC);background-repeat:no-repeat;height:15px;width:15px;position:absolute;right:-2px;top:2px}.ngGroupedByIcon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAYAAACZ3F9/AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAElJREFUKFNjoAhISkr+R8LyaHwMDNXGwGBsbPwfhoGAA5mPDUO1oWpE52PDYE0gALTFAYbR+dgwWBMIoPlh1I9ADNU2NPzIwAAAFQYI9E4OLvEAAAAASUVORK5CYII=);background-repeat:no-repeat;height:15px;width:15px;position:absolute;right:-2px;top:2px}.ngGroupName{background-color:#fdfdfd;border:1px solid #d4d4d4;padding:3px 10px;float
 :left;margin-left:0;margin-top:2px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;font-weight:bold}.ngGroupArrow{width:0;height:0;border-top:6px solid transparent;border-bottom:6
 px solid transparent;border-left:6px solid black;margin-top:10px;margin-left:5px;margin-right:5px;float:right}.ngGroupingNumber{position:absolute;right:-10px;top:-2px}.ngAggArrowCollapsed{position:absolute;left:8px;bottom:10px;width:0;height:0;border-style:solid;border-width:5px 0 5px 8.7px;border-color:transparent transparent transparent #000}.ngGroupItem{float:left}.ngGroupItem:first-child{margin-left:2px}.ngRemoveGroup{width:5px;-moz-opacity:.4;opacity:.4;margin-top:-1px;margin-left:5px}.ngRemoveGroup:hover{color:black;text-decoration:none;cursor:pointer;-moz-opacity:.7;opacity:.7}.ngAggArrowExpanded{position:absolute;left:8px;bottom:10px;width:0;height:0;border-style:solid;border-width:0 0 9px 9px;border-color:transparent transparent #000 transparent}.ngAggregate{position:absolute;bac
 kground-color:#c9dde1;border-bottom:1px solid beige;overflow:hidden;top:0;bottom:0;right:-1px;left:0}.ngAggregateText{position:absolute;left:27px;top:5px;line-height:20px;white-space:nowrap}.ngRow{p
 osition:absolute;border-bottom:1px solid #d4d4d4}.ngRow.odd{background-color:#fdfdfd}.ngRow.even{background-color:#f3f3f3}.ngRow.selected{background-color:#c9dde1}.ngCell{overflow:hidden;position:absolute;top:0;bottom:0;background-color:inherit}.ngCell.pinned{z-index:1}.ngCellText{padding:5px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;white-space:nowrap;-ms-text-overflow:ellipsis;-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden}.ngSelectionCell{margin-top:9px;margin-left:6px}.ngSelectionHeader{position:absolute;top:11px;left:6px}.ngCellElement:focus{outline:0;background-color:#b3c4c7}.ngRow.canSelect{cursor:pointer}.ngSelectionCheckbox{margin-top:9px;margin-left:6px}.ngFooterPanel{background-color:#eaeaea;padding:0;border-top:1px solid #
 d4d4d4;position:relative}.nglabel{display:block;float:left;font-weight:bold;padding-right:5px}.ngTotalSelectContainer{float:left;margin:5px;margin-top:7px}.ngFooterSelectedItems{padding:2px}.ngFoote
 rTotalItems.ngnoMultiSelect{padding:0!important}.ngGridMaxPagesNumber{vertical-align:middle}.ngPagerFirstBar{width:10px;border-left:2px solid #4d4d4d;margin-top:-6px;height:12px;margin-left:-3px}.ngPagerButton{height:25px;min-width:26px}.ngPagerFirstTriangle{width:0;height:0;border-style:solid;border-width:5px 8.7px 5px 0;border-color:transparent #4d4d4d transparent transparent;margin-left:2px}.ngPagerNextTriangle{margin-left:1px}.ngPagerPrevTriangle{margin-left:0}.ngPagerLastTriangle{width:0;height:0;border-style:solid;border-width:5px 0 5px 8.7px;border-color:transparent transparent transparent #4d4d4d;margin-left:-1px}.ngPagerLastBar{width:10px;border-left:2px solid #4d4d4d;margin-top:-6px;height:12px;margin-left:1px}.ngFooterTotalItems{padding:2px}
\ No newline at end of file

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/criteria-detail.html
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/criteria-detail.html?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/criteria-detail.html (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/criteria-detail.html Fri Feb 27 23:33:58 2015
@@ -0,0 +1,80 @@
+<div class="modal-header" gwp-sliding-dialog>
+    <button type="button" class="close" aria-hidden="true" ng-click="close()">&times;</button>
+    <h4 class="modal-title" ng-show="!criteria.name">New Criteria<span ng-show="criteria.name.length">: {{criteria.name}}</span></h4>
+    <h4 class="modal-title" ng-show="criteria.name">Criteria Detail: <span>{{criteria.name}}</span></h4>
+</div>
+<form role="form" novalidate class="form-horizontal css-form">
+    <div class="modal-body">
+        <div class="form-group">
+            <label for="criteria-name" class="col-sm-2 control-label">Name</label>
+            <div class="col-md-10 col-sm-10">
+                <input type="text" id="criteria-name" class="form-control" ng-model="criteria.name" gwp-autofocus gwp-no-spaces />
+                <span id="helpBlockID" class="help-block">Enter a unique name for this criteria</span>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label for="criteria-value" class="col-sm-2 control-label">Value</label>
+            <div class="col-md-10 col-sm-10">
+                <input type="text" id="criteria-value" class="form-control" ng-model="criteria.value" />
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label for="criteria-resolver" class="col-sm-2 control-label">Resolver Type</label>
+            <div class="col-md-10 col-sm-10">
+                <select id="criteria-resolver" class="form-control" ng-model="criteria.resolverType">
+                    <option value="request">request</option>
+                    <option value="session">session</option>
+                    <option value="request.session">request.session</option>
+                    <option value="hard.coded">hard.coded</option>
+                    <option value="group.role.user">group.role.user</option>
+                    <option value="user">user</option>
+                    <option value="group">group</option>
+                    <option value="role">role</option>
+                    <option value="mediatype">mediatype</option>
+                    <option value="country">country</option>
+                    <option value="language">language</option>
+                    <option value="roles">roles</option>
+                    <option value="path">path</option>
+                    <option value="page">page</option>
+                    <option value="path.session">path.session</option>
+                    <option value="user.attribute">user.attribute</option>
+                    <option value="navigation">navigation</option>
+                    <option value="ip">ip</option>
+                    <option value="hostname">hostname</option>
+                </select>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label for="criteria-fallback" class="col-sm-2 control-label">Fallback Type</label>
+            <div class="col-md-10 col-sm-10">
+                <select id="criteria-fallback" class="form-control" ng-model="criteria.fallback">
+                    <option value="1">Continue</option>
+                    <option value="0">Stop</option>
+                    <option value="2">Loop</option>
+                </select>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label for="criteria-order" class="col-sm-2 control-label">Order</label>
+            <div class="col-md-10 col-sm-10">
+                <input type="number" id="criteria-order" class="form-control" ng-model="criteria.order" />
+            </div>
+        </div>
+
+        <div class="form-group">
+            <div class="col-md-10 col-sm-10 padding-left0">
+                <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)"><strong>{{alert.msg}}</strong></alert>
+            </div>
+            <br />
+        </div>
+    </div>
+    <div class="modal-footer">
+        <button class="btn btn-default" ng-click="close()">Cancel</button>
+        <input type="submit" class="btn btn-primary" ng-click="add()" ng-disabled="!criteria.name.length || !criteria.resolverType.length || (criteria.fallback === -1)" ng-show="!criteria.name" value="Add"/>
+        <input type="submit" class="btn btn-primary" ng-click="add()" ng-disabled="!criteria.name.length || !criteria.resolverType.length || (criteria.fallback === -1)" ng-show="criteria.name" value="Update"/>
+    </div>
+</form>

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/profile-detail.html
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/profile-detail.html?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/profile-detail.html (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/profile-detail.html Fri Feb 27 23:33:58 2015
@@ -0,0 +1,72 @@
+<div class="modal-header" gwp-sliding-dialog>
+    <button type="button" class="close" aria-hidden="true" ng-click="close()">&times;</button>
+    <h4 class="modal-title" ng-show="!profile.id">New Profile<span ng-show="profile.id.length">: {{profile.id}}</span></h4>
+    <h4 class="modal-title" ng-show="profile.id">Profile Detail: <span>{{profile.id}}</span></h4>
+</div>
+<form role="form" novalidate class="form-horizontal css-form">
+    <div class="modal-body">
+        <div class="form-group">
+            <label for="profile-id" class="col-sm-2 control-label">Profile ID</label>
+            <div class="col-md-10 col-sm-10">
+                <input type="text" id="profile-id" class="form-control" placeholder="new-profile-id" ng-model="profile.id" ng-class="{error: !isValidTitle()}" ng-disabled="existing" gwp-autofocus gwp-no-spaces />
+                <span id="helpBlockID" class="help-block" ng-show="!existing">Enter a unique ID for this Profile</span>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label for="profile-title" class="col-sm-2 control-label">Description</label>
+            <div class="col-md-10 col-sm-10">
+                <input type="text" id="profile-title" class="form-control" placeholder="new-profile-title" ng-model="profile.title" ng-class="{error: !isValidTitle()}" />
+                <span id="helpBlockTitle" class="help-block">Enter a description of this Profile</span>
+            </div>
+        </div>
+        <div class="form-group">
+            <label for="profile-class" class="col-sm-2 control-label">Java Class</label>
+            <div class="col-md-10 col-sm-10">
+                <select id="profile-class" class="form-control" placeholder="new-profile-class" ng-required ng-model="profile.concreteClass">
+                    <option value="org.apache.jetspeed.profiler.rules.impl.StandardProfilingRule">Standard</option>
+                    <option value="org.apache.jetspeed.profiler.rules.impl.RoleFallbackProfilingRule">Fallback</option>
+                </select>
+            </div>
+        </div>
+        <div class="form-group">
+            <label for="profile-class" class="col-sm-2 control-label">Criteria<br /><button type="button" class="btn btn-success btn-xs" ng-click="addCriteria()">add</button></label>
+            <div class="col-md-10 col-sm-10">
+                <span ng-show="!profile.criteria.length"><br />None</span>
+                <table ng-show="profile.criteria.length" class="table">
+                    <thead>
+                    <tr>
+                        <th>Name</th>
+                        <th>Value</th>
+                        <th>Resolver Type</th>
+                        <th>Fallback Type</th>
+                        <th>Order</th>
+                        <th></th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <tr ng-repeat="criteria in profile.criteria" ng-click="addCriteria($index)">
+                        <td ng-bind="criteria.name"></td>
+                        <td ng-bind="criteria.value"></td>
+                        <td ng-bind="criteria.resolverType"></td>
+                        <td ng-bind="criteria.fallback"></td>
+                        <td ng-bind="criteria.order"></td>
+                        <td><button type="button" class="btn btn-danger btn-sm" ng-click="removeCriteria($index)">-</button></td>
+                    </tr>
+                    </tbody>
+                </table>
+            </div>
+        </div>
+        <div class="form-group">
+            <div class="col-md-10 col-sm-10 padding-left0">
+                <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)"><strong>{{alert.msg}}</strong></alert>
+            </div>
+            <br />
+        </div>
+    </div>
+    <div class="modal-footer">
+        <button class="btn btn-default" ng-click="close()">Cancel</button>
+        <input type="submit" class="btn btn-primary" ng-click="add()" ng-disabled="!profile.id.length || !profile.concreteClass.length || !isValidTitle() || !isUniqueId()" ng-show="!existing" value="Add"/>
+        <input type="submit" class="btn btn-primary" ng-click="add()" ng-disabled="!profile.id.length || !profile.concreteClass.length || !isValidTitle()" ng-show="existing" value="Update"/>
+    </div>
+</form>

Added: portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/profiles-delete.html
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/profiles-delete.html?rev=1662855&view=auto
==============================================================================
--- portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/profiles-delete.html (added)
+++ portals/jetspeed-2/applications/j2-admin/trunk/src/main/webapp/jetapp/views/modals/profiles-delete.html Fri Feb 27 23:33:58 2015
@@ -0,0 +1,20 @@
+<div class="modal-header">
+    <button type="button" class="close" aria-hidden="true" ng-click="close()">&times;</button>
+    <h4 class="modal-title">Delete Profiles</h4>
+</div>
+<form role="form" novalidate class="css-form">
+    <div class="modal-body">
+        <p class="text-danger">Are you sure you want to delete all the selected profiles?</p>
+        <p class="text-danger">This cannot be undone.</p>
+        <div class="form-group">
+            <div>
+                <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)"><strong>{{alert.msg}}</strong></alert>
+            </div>
+            <br />
+        </div>
+    </div>
+    <div class="modal-footer">
+        <button class="btn btn-default" ng-click="close()">Cancel</button>
+        <button type="submit" class="btn btn-primary" ng-click="deleteItems()">Delete</button>
+    </div>
+</form>
\ No newline at end of file
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.