| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /** |
| * A directive which provides a filtering text input field which automatically |
| * produces a filtered subset of the given connection groups. |
| */ |
| angular.module('groupList').directive('guacGroupListFilter', [function guacGroupListFilter() { |
| |
| return { |
| restrict: 'E', |
| replace: true, |
| scope: { |
| |
| /** |
| * The property to which a subset of the provided map of connection |
| * groups will be assigned. The type of each item within the |
| * original map is preserved within the filtered map. |
| * |
| * @type Object.<String, ConnectionGroup|GroupListItem> |
| */ |
| filteredConnectionGroups : '=', |
| |
| /** |
| * The placeholder text to display within the filter input field |
| * when no filter has been provided. |
| * |
| * @type String |
| */ |
| placeholder : '&', |
| |
| /** |
| * The connection groups to filter, as a map of data source |
| * identifier to corresponding root group. A subset of this map |
| * will be exposed as filteredConnectionGroups. |
| * |
| * @type Object.<String, ConnectionGroup|GroupListItem> |
| */ |
| connectionGroups : '&', |
| |
| /** |
| * An array of expressions to filter against for each connection in |
| * the hierarchy of connections and groups in the provided map. |
| * These expressions must be Angular expressions which resolve to |
| * properties on the connections in the provided map. |
| * |
| * @type String[] |
| */ |
| connectionProperties : '&', |
| |
| /** |
| * An array of expressions to filter against for each connection group |
| * in the hierarchy of connections and groups in the provided map. |
| * These expressions must be Angular expressions which resolve to |
| * properties on the connection groups in the provided map. |
| * |
| * @type String[] |
| */ |
| connectionGroupProperties : '&' |
| |
| }, |
| |
| templateUrl: 'app/groupList/templates/guacGroupListFilter.html', |
| controller: ['$scope', '$injector', function guacGroupListFilterController($scope, $injector) { |
| |
| // Required types |
| var ConnectionGroup = $injector.get('ConnectionGroup'); |
| var FilterPattern = $injector.get('FilterPattern'); |
| var GroupListItem = $injector.get('GroupListItem'); |
| |
| /** |
| * The pattern object to use when filtering connections. |
| * |
| * @type FilterPattern |
| */ |
| var connectionFilterPattern = new FilterPattern($scope.connectionProperties()); |
| |
| /** |
| * The pattern object to use when filtering connection groups. |
| * |
| * @type FilterPattern |
| */ |
| var connectionGroupFilterPattern = new FilterPattern($scope.connectionGroupProperties()); |
| |
| /** |
| * The filter search string to use to restrict the displayed |
| * connection groups. |
| * |
| * @type String |
| */ |
| $scope.searchString = null; |
| |
| /** |
| * Flattens the connection group hierarchy of the given connection |
| * group such that all descendants are copied as immediate |
| * children. The hierarchy of nested connection groups is otherwise |
| * completely preserved. A connection or connection group nested |
| * two or more levels deep within the hierarchy will thus appear |
| * within the returned connection group in two places: in its |
| * original location AND as an immediate child. |
| * |
| * @param {ConnectionGroup} connectionGroup |
| * The connection group whose descendents should be copied as |
| * first-level children. |
| * |
| * @returns {ConnectionGroup} |
| * A new connection group completely identical to the provided |
| * connection group, except that absolutely all descendents |
| * have been copied into the first level of children. |
| */ |
| var flattenConnectionGroup = function flattenConnectionGroup(connectionGroup) { |
| |
| // Replace connection group with shallow copy |
| connectionGroup = new ConnectionGroup(connectionGroup); |
| |
| // Ensure child arrays are defined and independent copies |
| connectionGroup.childConnections = angular.copy(connectionGroup.childConnections) || []; |
| connectionGroup.childConnectionGroups = angular.copy(connectionGroup.childConnectionGroups) || []; |
| |
| // Flatten all children to the top-level group |
| angular.forEach(connectionGroup.childConnectionGroups, function flattenChild(child) { |
| |
| var flattenedChild = flattenConnectionGroup(child); |
| |
| // Merge all child connections |
| Array.prototype.push.apply( |
| connectionGroup.childConnections, |
| flattenedChild.childConnections |
| ); |
| |
| // Merge all child connection groups |
| Array.prototype.push.apply( |
| connectionGroup.childConnectionGroups, |
| flattenedChild.childConnectionGroups |
| ); |
| |
| }); |
| |
| return connectionGroup; |
| |
| }; |
| |
| /** |
| * Flattens the connection group hierarchy of the given |
| * GroupListItem such that all descendants are copied as immediate |
| * children. The hierarchy of nested items is otherwise completely |
| * preserved. A connection or connection group nested two or more |
| * levels deep within the hierarchy will thus appear within the |
| * returned item in two places: in its original location AND as an |
| * immediate child. |
| * |
| * @param {GroupListItem} item |
| * The GroupListItem whose descendents should be copied as |
| * first-level children. |
| * |
| * @returns {GroupListItem} |
| * A new GroupListItem completely identical to the provided |
| * item, except that absolutely all descendents have been |
| * copied into the first level of children. |
| */ |
| var flattenGroupListItem = function flattenGroupListItem(item) { |
| |
| // Replace item with shallow copy |
| item = new GroupListItem(item); |
| |
| // Ensure children are defined and independent copies |
| item.children = angular.copy(item.children) || []; |
| |
| // Flatten all children to the top-level group |
| angular.forEach(item.children, function flattenChild(child) { |
| if (child.type === GroupListItem.Type.CONNECTION_GROUP) { |
| |
| var flattenedChild = flattenConnectionGroup(child); |
| |
| // Merge all children |
| Array.prototype.push.apply( |
| item.children, |
| flattenedChild.children |
| ); |
| |
| } |
| }); |
| |
| return item; |
| |
| }; |
| |
| /** |
| * Replaces the set of children within the given GroupListItem such |
| * that only children which match the filter predicate for the |
| * current search string are present. |
| * |
| * @param {GroupListItem} item |
| * The GroupListItem whose children should be filtered. |
| */ |
| var filterGroupListItem = function filterGroupListItem(item) { |
| item.children = item.children.filter(function applyFilterPattern(child) { |
| |
| // Filter connections and connection groups by |
| // given pattern |
| switch (child.type) { |
| |
| case GroupListItem.Type.CONNECTION: |
| return connectionFilterPattern.predicate(child.wrappedItem); |
| |
| case GroupListItem.Type.CONNECTION_GROUP: |
| return connectionGroupFilterPattern.predicate(child.wrappedItem); |
| |
| } |
| |
| // Include all other children |
| return true; |
| |
| }); |
| }; |
| |
| /** |
| * Replaces the set of child connections and connection groups |
| * within the given connection group such that only children which |
| * match the filter predicate for the current search string are |
| * present. |
| * |
| * @param {ConnectionGroup} connectionGroup |
| * The connection group whose children should be filtered. |
| */ |
| var filterConnectionGroup = function filterConnectionGroup(connectionGroup) { |
| connectionGroup.childConnections = connectionGroup.childConnections.filter(connectionFilterPattern.predicate); |
| connectionGroup.childConnectionGroups = connectionGroup.childConnectionGroups.filter(connectionGroupFilterPattern.predicate); |
| }; |
| |
| /** |
| * Applies the current filter predicate, filtering all provided |
| * connection groups and storing the result in |
| * filteredConnectionGroups. |
| */ |
| var updateFilteredConnectionGroups = function updateFilteredConnectionGroups() { |
| |
| // Do not apply any filtering (and do not flatten) if no |
| // search string is provided |
| if (!$scope.searchString) { |
| $scope.filteredConnectionGroups = $scope.connectionGroups() || {}; |
| return; |
| } |
| |
| // Clear all current filtered groups |
| $scope.filteredConnectionGroups = {}; |
| |
| // Re-filter any provided groups |
| var connectionGroups = $scope.connectionGroups(); |
| if (connectionGroups) { |
| angular.forEach(connectionGroups, function updateFilteredConnectionGroup(connectionGroup, dataSource) { |
| |
| var filteredGroup; |
| |
| // Flatten and filter depending on type |
| if (connectionGroup instanceof GroupListItem) { |
| filteredGroup = flattenGroupListItem(connectionGroup); |
| filterGroupListItem(filteredGroup); |
| } |
| else { |
| filteredGroup = flattenConnectionGroup(connectionGroup); |
| filterConnectionGroup(filteredGroup); |
| } |
| |
| // Store now-filtered root |
| $scope.filteredConnectionGroups[dataSource] = filteredGroup; |
| |
| }); |
| } |
| |
| }; |
| |
| // Recompile and refilter when pattern is changed |
| $scope.$watch('searchString', function searchStringChanged(searchString) { |
| connectionFilterPattern.compile(searchString); |
| connectionGroupFilterPattern.compile(searchString); |
| updateFilteredConnectionGroups(); |
| }); |
| |
| // Refilter when items change |
| $scope.$watchCollection($scope.connectionGroups, function itemsChanged() { |
| updateFilteredConnectionGroups(); |
| }); |
| |
| }] |
| |
| }; |
| }]); |