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
----------------------------------------------------------------------