You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2018/11/08 16:44:22 UTC

[2/3] brooklyn-ui git commit: Merge branch 'master' into jcCompactList

Merge branch 'master' into jcCompactList

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/55ae032e
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/55ae032e
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/55ae032e

Branch: refs/heads/master
Commit: 55ae032efe88a02120deae27dddb14485b6bbbf3
Parents: cb074a5 43c154c
Author: Juan Cabrerizo <ju...@cabrerizo.es>
Authored: Thu Nov 8 16:37:16 2018 +0000
Committer: GitHub <no...@github.com>
Committed: Thu Nov 8 16:37:16 2018 +0000

----------------------------------------------------------------------
 .../blueprint-data-manager.directive.js         |  28 +-
 .../breacrumbs/breadcrumbs.directive.js         |  44 +-
 .../catalog-saver/catalog-saver.directive.js    |  22 +-
 .../catalog-selector.directive.js               | 580 +++++++++++--------
 .../catalog-selector/catalog-selector.less      |  41 ++
 .../catalog-selector.template.html              |  59 +-
 .../suggestion-dropdown.html                    |   2 +-
 .../custom-config-widget/suggestion-dropdown.js |  13 +-
 .../components/designer/designer.directive.js   |  27 +-
 .../app/components/dsl-editor/dsl-editor.js     |  12 +-
 .../app/components/dsl-viewer/dsl-viewer.js     |  12 +-
 .../factories/object-cache.factory.js           |   9 +
 .../factories/recursion-helper.factory.js       |  61 --
 .../app/components/filters/entity.filter.js     |  17 +-
 .../app/components/filters/locations.filter.js  |   9 +
 .../providers/action-service.provider.js        |  11 +-
 .../providers/blueprint-service.provider.js     |   8 +
 .../providers/dsl-service.provider.js           |   7 +
 .../providers/palette-dragndrop.provider.js     |   7 +
 .../providers/recently-used-service.provider.js |   8 +
 .../spec-editor/spec-editor.directive.js        |   8 +-
 .../spec-editor/spec-editor.template.html       |  50 +-
 ui-modules/blueprint-composer/app/index.js      |  55 +-
 .../app/views/main/graphical/edit/add/add.html  |   2 +-
 .../app/views/main/graphical/edit/add/add.js    |  11 +
 .../views/main/graphical/graphical.state.html   |   4 +-
 .../app/views/main/graphical/graphical.state.js |  28 +-
 27 files changed, 697 insertions(+), 438 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/55ae032e/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.directive.js
----------------------------------------------------------------------
diff --cc ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.directive.js
index 298ba80,2cad3ef..3d90b92
--- a/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.directive.js
+++ b/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.directive.js
@@@ -32,11 -37,11 +37,12 @@@ const PALETTE_VIEW_ORDERS = 
      };
  
  const PALETTE_VIEW_MODES = {
-         compact: { name: "Compact", classes: "col-xs-2 item-compact", itemsPerRow: 6, rowHeightPx: 75, hideName: true },
-         normal: { name: "Normal", classes: "col-xs-3", itemsPerRow: 4 },
-         large: { name: "Large", classes: "col-xs-4", itemsPerRow: 3 },
+         tiny: { name: "Tiny", classes: "col-xs-2 item-compact", itemsPerRow: 6, rowHeightPx: 75, hideName: true },
+         compact: { name: "Compact", classes: "col-xs-3", itemsPerRow: 4 },
+         normal: { name: "Normal", classes: "col-xs-4", itemsPerRow: 3 },
+         large: { name: "Large", classes: "col-xs-6", itemsPerRow: 2 },
          list: { name: "List", classes: "col-xs-12 item-full-width", itemsPerRow: 1 },
 +        compactList: { name: "Compact list", classes: "col-xs-12 item-compact-list", itemsPerRow: 1, rowHeightPx: 30 },
      };
  
  // fields in either bundle or type record:
@@@ -56,33 -74,288 +75,287 @@@ export function catalogSelectorDirectiv
          controller: ['$scope', '$element', '$timeout', '$q', '$uibModal', '$log', '$templateCache', 'paletteApi', 'paletteDragAndDropService', 'iconGenerator', 'composerOverrides', 'recentlyUsedService', controller],
          link: link,
      };
- }
  
- function link($scope, $element, attrs, controller) {
-     let main = angular.element($element[0].querySelector(".catalog-palette-main"));
 -
+     function link($scope, $element, attrs, controller) {
+         let main = angular.element($element[0].querySelector(".catalog-palette-main"));
  
-     // repaginate when load completes (and items are shown), or it is resized
-     $scope.$watchGroup(
-         [ () => $scope.isLoading, () => main[0].offsetHeight, () => $scope.state.viewMode.name ],
-         (values) => controller.$timeout( () => repaginate($scope, $element) ) );
-     // also repaginate on window resize    
-     angular.element(window).bind('resize', () => repaginate($scope, $element));
- }
+         // repaginate when load completes (and items are shown), or it is resized
+         $scope.$watchGroup(
 -            [() => $scope.isLoading, () => main[0].offsetHeight, () => $scope.state.viewMode.itemsPerRow],
++            [() => $scope.isLoading, () => main[0].offsetHeight, () => $scope.state.viewMode.name],
+             (values) => controller.$timeout(() => repaginate($scope, $element)));
+         // also repaginate on window resize
+         angular.element(window).bind('resize', () => repaginate($scope, $element));
  
- function repaginate($scope, $element) {
-     let rowsPerPage = $scope.rowsPerPage;
-     if (!rowsPerPage) {
-         let main = angular.element($element[0].querySelector(".catalog-palette-main"));
-         if (!main || main[0].offsetHeight==0) {
-             // no main, or hidden, or items per page fixed
-             return;
+         $scope.templateUrls = {
+             subhead: TEMPLATE_SUBHEAD_URL,
+             footer: TEMPLATE_FOOTER_URL
          }
-         let header = angular.element(main[0].querySelector(".catalog-palette-header"));
-         let footer = angular.element(main[0].querySelector(".catalog-palette-footer"));
-         rowsPerPage = Math.max(MIN_ROWS_PER_PAGE, Math.floor( (main[0].offsetHeight - header[0].offsetHeight - footer[0].offsetHeight - 16) / ($scope.state.viewMode.rowHeightPx || 96)) );
      }
-     $scope.$apply( () => $scope.pagination.itemsPerPage = rowsPerPage * $scope.state.viewMode.itemsPerRow );
+ 
+     function controller($scope, $element, $timeout, $q, $uibModal, $log, $templateCache, paletteApi, paletteDragAndDropService, iconGenerator, composerOverrides, recentlyUsedService) {
+         this.$timeout = $timeout;
+ 
+         $scope.viewModes = PALETTE_VIEW_MODES;
+         $scope.viewOrders = PALETTE_VIEW_ORDERS;
+ 
+         if (!$scope.state) $scope.state = {};
+         if (!$scope.state.viewMode) $scope.state.viewMode = PALETTE_VIEW_MODES.normal;
+ 
+         $scope.pagination = {
+             page: 1,
+             itemsPerPage: $scope.state.viewMode.itemsPerRow * ($scope.rowsPerPage || 1)  // will fill out after load
+         };
+ 
+         $scope.getEntityNameForPalette = function(item, entityName) {
+             return (composerOverrides.getEntityNameForPalette ||
+                 // above can be overridden with function of signature below to customize display name in palette
+                 function(item, entityName, scope) { return entityName; }
+             )(item, entityName, $scope);
+         };
+ 
+         $scope.getPlaceHolder = function () {
+             return 'Search';
+         };
+ 
+         $scope.isLoading = true;
+ 
+         $scope.$watch('search', () => {
+             $scope.freeFormTile = {
+                 symbolicName: $scope.search,
+                 name: $scope.search,
+                 displayName: $scope.search,
+                 supertypes: ($scope.family ? [ $scope.family.superType ] : []),
+             };
+         });
+ 
+         $scope.getItems = function (search) {
+             let defer = $q.resolve([]);
+ 
+             switch ($scope.family) {
+                 case EntityFamily.ENTITY:
+                 case EntityFamily.SPEC:
+                     defer = paletteApi.getTypes({params: {supertype: 'entity', fragment: search}});
+                     break;
+                 case EntityFamily.POLICY:
+                     defer = paletteApi.getTypes({params: {supertype: 'policy', fragment: search}});
+                     break;
+                 case EntityFamily.ENRICHER:
+                     defer = paletteApi.getTypes({params: {supertype: 'enricher', fragment: search}});
+                     break;
+                 case EntityFamily.LOCATION:
+                     defer = paletteApi.getLocations();
+                     break;
+             }
+ 
+             return defer.then(data => {
+                 data = $scope.filterPaletteItemsForMode(data, $scope);
+                 data.forEach( recentlyUsedService.embellish );
+                 return data;
+ 
+             }).catch(error => {
+                 return [];
+             }).finally(() => {
+                 $scope.isLoading = false;
+             });
+         };
+         function tryMarkUsed(item) {
+             try {
+                 recentlyUsedService.markUsed(item);
+             } catch (e) {
+                 // session storage can get full; usually the culprit is icons not this,
+                 // but we may wish to clear out old items to ensure we don't bleed here
+                 $log.warn("Could not mark item as used: "+item, e);
+             }
+         }
+         $scope.mouseInfoPopover = (item, enter) => {
+             if ($scope.popoverModal && $scope.popoverVisible && $scope.popover==item) {
+                 // ignore if modal
+                 return;
+             }
+             $scope.popoverModal = false;
+             if (enter) {
+                 $scope.popover = item;
+                 $scope.popoverVisible = true;
+             } else {
+                 $scope.popoverVisible = false;
+             }
+         };
+         $scope.onClickItem = (item, isInfoIcon, $event) => {
+             if (!isInfoIcon && $scope.iconSelects) {
+                 $scope.onSelectItem(item);
+             } else if ($scope.popoverModal && $scope.popoverVisible && $scope.popover == item) {
+                 $scope.closePopover();
+             } else {
+                 $scope.popover = item;
+                 $scope.popoverVisible = true;
+                 $scope.popoverModal = true;
+             }
+             $event.stopPropagation();
+         };
+         $scope.closePopover = () => {
+             $scope.popoverVisible = false;
+             $scope.popoverModal = false;
+         };
+         $scope.getOnSelectText = function (item) {
+             if (!($scope.onSelectText)) return "Select";
+             return $scope.onSelectText({item: item});
+         };
+         $scope.onSelectItem = function (item) {
+             $scope.closePopover();
+             if (angular.isFunction($scope.onSelect)) {
+                 tryMarkUsed(item);
+                 $scope.onSelect({item: item});
+             }
+             $scope.search = '';
+         };
+         $scope.onDragItem = function (item, event) {
+             let frame = document.createElement('div');
+             frame.classList.add('drag-frame');
+             event.target.appendChild(frame);
+             setTimeout(function() {
+                 // can remove at end of this cycle, browser will have grabbed its drag image
+                 frame.parentNode.removeChild(frame);
+             }, 0);
+             /* have tried many other ways to get a nice drag image;
+                this seems to work best, adding an empty div which forces the size to be larger,
+                so when grabbing the image it grabs the drop-shadow.
+                things that _didn't_ work include:
+                - styling event.target now then unstyling (normally this would work, in posts on the web, but it doesn't here; angular?)
+                - make a restyled cloned copy offscreen (this comes so close but remote img srcs aren't loaded
+              */
+ 
+             paletteDragAndDropService.dragStart(item);
+         };
+         $scope.onDragEnd = function (item, event) {
+             paletteDragAndDropService.dragEnd();
+             tryMarkUsed(item);
+         };
+ 
+         $scope.getOpenCatalogLink = (item) => {
+             return "/brooklyn-ui-catalog/#!/bundles/"+item.containingBundle.replace(":","/")+"/types/"+item.symbolicName+"/"+item.version;
+         };
+         $scope.sortBy = function (order) {
+             let newFirst = {};
+             if (order) {
+                 newFirst[order.id] = order;
+             }
+             $scope.state.currentOrder = Object.assign(newFirst, $scope.state.currentOrder, newFirst);
+             $scope.state.currentOrderFields = [];
+             $scope.state.currentOrderValues = [];
+             Object.values($scope.state.currentOrder).forEach( it => {
+                 $scope.state.currentOrderValues.push(it);
+                 $scope.state.currentOrderFields.push(it.field);
+             });
+         };
+         if (!$scope.state.currentOrder) $scope.state.currentOrder = Object.assign({}, PALETTE_VIEW_ORDERS);
+         $scope.sortBy();
+ 
+         $scope.allowFreeForm = function () {
+             return [
+                 EntityFamily.LOCATION
+             ].indexOf($scope.family) > -1;
+         };
+         $scope.isReserved = function () {
+             if (!$scope.reservedKeys || !angular.isArray($scope.reservedKeys)) {
+                 return false;
+             }
+             return $scope.reservedKeys.indexOf($scope.search) > -1;
+         };
+         $scope.onImageError = (scope, el, attrs) => {
+             $log.warn("Icon for "+attrs.itemId+" at "+angular.element(el).attr("src")+" could not be loaded; generating icon");
+             angular.element(el).attr("src", iconGenerator(attrs.itemId));
+         };
+ 
+         // Init
+         $scope.items = [];
+         function getDisplayTags(tags) {
+             if (!tags || !tags.length || !tags.reduce) return tags;
+             return tags.reduce((result, tag) => {
+                 if (!(/[=:\[\]()]/.exec(tag))) {
+                     result.push(tag);
+                 }
+                 return result;
+             }, []);
+         }
+         $scope.getItems().then((items)=> {
+             // add displayTags, as any tag that doesn't contain = : or ( ) [ ]
+             // any tag that is an object will be eliminated as it is toStringed to make [ object object ]
+             items.forEach(item => {
+                 if (item.tags) {
+                     item.displayTags = getDisplayTags(item.tags);
+                 }
+             });
+             $scope.items = items;
+         });
+         $scope.lastUsedText = (item) => {
+             if (item==null) return "";
+             let l = (Number)(item.lastUsed);
+             if (!l || isNaN(l) || l<=0) return "";
+             if (l < 100000) return 'Preselected for inclusion in "Recent" filter.';
+             return 'Last used: ' + distanceInWordsToNow(l, { includeSeconds: true, addSuffix: true });
+         };
+ 
+         $scope.showPaletteControls = false;
+         $scope.onFiltersShown = () => {
+             $timeout( () => {
+                 // check do we need to show the multiline
+                 let filters = angular.element($element[0].querySelector(".filters"));
+                 $scope.$apply( () => $scope.filterSettings.filtersMultilineAvailable = filters[0].scrollHeight > filters[0].offsetHeight + 6 );
+ 
+                 repaginate($scope, $element);
+             } );
+         };
+         $scope.togglePaletteControls = () => {
+             $scope.showPaletteControls = !$scope.showPaletteControls;
+             $timeout( () => repaginate($scope, $element) );
+         };
+         $scope.toggleShowAllFilters = () => {
+             $scope.filterSettings.showAllFilters = !$scope.filterSettings.showAllFilters;
+             $timeout( () => repaginate($scope, $element) );
+         };
+         $scope.filterSettings = {};
+ 
+         $scope.filters = [
+             { label: 'Recent', icon: 'clock-o', title: "Recently used and standard favorites", limitToOnePage: true,
+                 filterInit: items => {
+                     $scope.recentItems = items.filter( i => i.lastUsed && i.lastUsed>0 );
+                     $scope.recentItems.sort( (a,b) => b.lastUsed - a.lastUsed );
+                     return $scope.recentItems;
+                 }, enabled: false },
+         ];
+         $scope.disableFilters = (showFilters) => {
+             $scope.filters.forEach( f => f.enabled = false );
+             if (showFilters !== false) {
+                 $scope.showPaletteControls = true;
+             }
+         };
+ 
+         // can be overridden to disable "open in catalog" button
+         $scope.allowOpenInCatalog = true;
+ 
+         // this can be overridden for palette sections/modes which show a subset of the types returned by the server;
+         // this is applied when the data is received from the server.
+         // it is used by catalogSelectorFiltersFilter;
+         $scope.filterPaletteItemsForMode = (items) => items;
+ 
+         // allow downstream to configure this controller and/or scope
+         (composerOverrides.configurePaletteController || function() {})(this, $scope, $element);
+     }
+ 
+     function repaginate($scope, $element) {
+         let rowsPerPage = $scope.rowsPerPage;
+         if (!rowsPerPage) {
+             let main = angular.element($element[0].querySelector(".catalog-palette-main"));
+             if (!main || main[0].offsetHeight == 0) {
+                 // no main, or hidden, or items per page fixed
+                 return;
+             }
+             let header = angular.element(main[0].querySelector(".catalog-palette-header"));
+             let footer = angular.element(main[0].querySelector(".catalog-palette-footer"));
+             rowsPerPage = Math.max(MIN_ROWS_PER_PAGE, Math.floor((main[0].offsetHeight - header[0].offsetHeight - footer[0].offsetHeight - 16) / ($scope.state.viewMode.rowHeightPx || 96)));
+         }
+         $scope.$apply(() => $scope.pagination.itemsPerPage = rowsPerPage * $scope.state.viewMode.itemsPerRow);
+     }
  }
  
  export function catalogSelectorSearchFilter() {

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/55ae032e/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.less
----------------------------------------------------------------------