Skip to content

Commit

Permalink
allow selection text and behaviour to be customized in palette
Browse files Browse the repository at this point in the history
when adding, clicking the icon adds it directly; but on palette clicking opens popup;
and popup button gets correct configurable message
  • Loading branch information
ahgittin committed Nov 1, 2018
1 parent feac3fc commit e20a8d1
Showing 9 changed files with 74 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -41,19 +41,20 @@ const PALETTE_VIEW_MODES = {
};

// fields in either bundle or type record:
const FIELDS_TO_SEARCH = ['displayName', 'name', 'symbolicName', 'version', 'type', 'supertypes', 'containingBundle', 'description', 'displayTags', 'tags'];
const FIELDS_TO_SEARCH = ['displayName', 'name', 'symbolicName', 'type', 'version', 'containingBundle', 'description', 'displayTags', 'tags', 'supertypes'];

export function catalogSelectorDirective() {
return {
restrict: 'E',
scope: {
family: '<',
onSelect: '&',
onSelectText: "@?",
rowsPerPage: '<?', // if unset then fill
onSelect: '&', // action to do when item is selected
onSelectText: "&?", // function returning text to show in the "on select" button for an item
iconSelects: '<?', // boolean whether clicking the icon triggers selection directly or shows popup (false, default)
rowsPerPage: '<?', // optionally show fixed number of rows; unset (default and normal) computes based on available height
reservedKeys: '<?',
state: '<?',
mode: '@?', // for use by downstream projects to pass in special modes
state: '<?', // for shared state usage
mode: '@?', // for use by downstream projects to pass in special modes to do add'l processing / rendering
},
template: template,
controller: ['$scope', '$element', '$timeout', '$q', '$uibModal', '$log', '$templateCache', 'paletteApi', 'paletteDragAndDropService', 'iconGenerator', 'composerOverrides', 'recentlyUsedService', controller],
@@ -251,8 +252,10 @@ function controller($scope, $element, $timeout, $q, $uibModal, $log, $templateCa
$scope.popover = null;
}
}
$scope.onClickItem = (item, $event) => {
if ($scope.popoverModal && $scope.popover == item) {
$scope.onClickItem = (item, isInfoIcon, $event) => {
if (!isInfoIcon && $scope.iconSelects) {
$scope.onSelectItem(item);
} else if ($scope.popoverModal && $scope.popover == item) {
$scope.closePopover();
} else {
$scope.popover = item;
@@ -264,7 +267,12 @@ function controller($scope, $element, $timeout, $q, $uibModal, $log, $templateCa
$scope.popover = null;
$scope.popoverModal = false;
}
$scope.onSelectItemToAdd = function (item) {
$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});
@@ -394,6 +402,9 @@ function controller($scope, $element, $timeout, $q, $uibModal, $log, $templateCa
}
}

// 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;
Original file line number Diff line number Diff line change
@@ -291,6 +291,9 @@ catalog-selector {
margin-top: -3px;
margin-bottom: 12px;
padding: 0px 16px 6px 16px;
.closer {
margin-top: 6px;
}
}
.closer {
width: 10px;
@@ -311,6 +314,11 @@ catalog-selector {
line-height: 1;
margin-left: 12px;
}
.select-item-button {
flex: 0 1 auto;
text-overflow: ellipsis;
overflow: hidden;
}
}
}

Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@
this could be configurable ("compressed"=xs-2 w no labels, "normal"=xs-3, "big"=xs-4) -->
<div class="catalog-palette-item" ng-class="state.viewMode.classes"
ng-repeat="item in searchedItems = (items | catalogSelectorSearch:search | catalogSelectorFilters:this) | orderBy:state.currentOrderFields | limitTo:pagination.itemsPerPage:(pagination.page-1)*pagination.itemsPerPage track by (item.containingBundle + ':' + item.symbolicName + ':' + item.version)"
ng-click="onClickItem(item, $event)">
ng-click="onClickItem(item, false, $event)">
<div class="item" draggable="true" ng-dragstart="onDragItem(item, $event)" ng-dragend="onDragEnd(item, $event)">
<div class="item-logo">
<img ng-src="{{item | iconGeneratorPipe:'symbolicName'}}" alt="{{item.displayName}} logo" on-error="onImageError" item-id="{{item.symbolicName}}"/>
@@ -111,6 +111,7 @@ <h3>{{ getEntityNameForPalette(item, item | entityName) }}</h3>
</div>
<i class="fa fa-info-circle"
uib-popover-template="'QuickInfoTemplate.html'"
ng-click="onClickItem(item, true, $event)"
popover-is-open="popover == item"
popover-placement="right" popover-trigger="'none'"
popover-class="catalog-selector-popover" popover-append-to-body="true"
@@ -174,8 +175,8 @@ <h3>{{freeFormTile | entityName}}</h3>
</div>
<div class="quick-info-buttons">
<div class="spacer"></div>
<button class="btn btn-primary btn-outline" ng-click="onSelectItemToAdd(popover)">{{ onSelectText || "Select" }}</button>
<a ng-if="popover.containingBundle" href="{{ getOpenCatalogLink(popover) }}" target="_blank"><button class="btn btn-info btn-outline">Open in catalog</button></a>
<button class="btn btn-primary btn-outline select-item-button" ng-click="onSelectItem(popover, false, $event)">{{ getOnSelectText(popover) }}</button>
<a ng-if="popover.containingBundle && allowOpenInCatalog" href="{{ getOpenCatalogLink(popover) }}" target="_blank"><button class="btn btn-info btn-outline">Open in catalog</button></a>
</div>
</div>
</script>
Original file line number Diff line number Diff line change
@@ -29,6 +29,9 @@ const TAG = 'DIRECTIVE :: DESIGNER :: ';
export function designerDirective($log, $state, $q, iconGenerator, catalogApi, blueprintService, brSnackbar, paletteDragAndDropService) {
let directive = {
restrict: 'E',
scope: {
onSelectionChange: '<?'
},
template: '',
link: link
};
@@ -109,13 +112,16 @@ export function designerDirective($log, $state, $q, iconGenerator, catalogApi, b
break;
}
if (angular.isDefined(id)) {
$log.debug(TAG + 'Select canvas, selected node: ' + id);
$scope.selectedEntity = blueprintService.findAny(id);
if ($scope.onSelectionChange) $scope.onSelectionChange($scope.selectedEntity);
}
});

$element.bind('click-svg', (event)=> {
$log.debug(TAG + 'Select canvas, un-select node (if one selected before)');
$scope.selectedEntity = null;
if ($scope.onSelectionChange) $scope.onSelectionChange($scope.selectedEntity);
$scope.$apply(()=> {
redrawGraph();
$state.go('main.graphical');
Original file line number Diff line number Diff line change
@@ -16,11 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
const DEFAULT = '';

export function entityNameFilter() {
return function (input) {
var result = input ? (input.displayName || input.name || input.symbolicName || input.type || DEFAULT) : DEFAULT;
var result = input ? (input.displayName || input.name || input.symbolicName || input.type || null) : null;
if (!result) {
if (input && !input.parent) result = 'Application';
else result = 'Unnamed entity';
}
if (result.match(/^[^\w]*deprecated[^\w]*/i)) {
result = result.replace(/^[^\w]*deprecated[^\w]*/i, '');
}
Original file line number Diff line number Diff line change
@@ -45,7 +45,7 @@ <h3>
<br-svg type="close" class="pull-right" ng-click="vm.selectedSection = undefined"></br-svg>
</h3>
</div>
<catalog-selector state="paletteState" family="section.type" mode="{{ section.mode }}" on-select="vm.onTypeSelected(item)" class="palette-full-height-wrapper"></catalog-selector>
<catalog-selector state="paletteState" family="section.type" mode="{{ section.mode }}" on-select="vm.onTypeSelected(item)" on-select-text="vm.getOnSelectText(item)" icon-selects="true" class="palette-full-height-wrapper"></catalog-selector>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -88,6 +88,17 @@ export function GraphicalEditAddController($scope, $filter, $state, $stateParams

return label;
};

this.getOnSelectText = () => {
switch ($scope.family) {
case EntityFamily.ENTITY: return "Add as child";
case EntityFamily.SPEC: return "Set as spec";
case EntityFamily.POLICY: return "Add this policy";
case EntityFamily.ENRICHER: return "Add this enricher";
case EntityFamily.LOCATION: return "Add this location";
}
return "Select";
};

this.onTypeSelected = (type)=> {
switch ($scope.family) {
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@
</div>
</div>

<designer></designer>
<designer on-selection-change="vm.onCanvasSelection"></designer>
</div>

<div class="pane pane-palette" ng-if="vm.selectedSection">
@@ -44,7 +44,7 @@ <h3>
<br-svg type="close" class="pull-right" ng-click="vm.selectedSection = undefined"></br-svg>
</h3>
</div>
<catalog-selector state="paletteState" family="section.type" mode="{{ section.mode }}" on-select="vm.onTypeSelected(item)" class="palette-full-height-wrapper"></catalog-selector>
<catalog-selector state="paletteState" family="section.type" mode="{{ section.mode }}" on-select="vm.addSelectedTypeToTargetEntity(item)" on-select-text="vm.getOnSelectText()" class="palette-full-height-wrapper"></catalog-selector>
</div>
</div>

Original file line number Diff line number Diff line change
@@ -28,47 +28,53 @@ export const graphicalState = {
templateProvider: function(composerOverrides) {
return composerOverrides.paletteGraphicalStateTemplate || template;
},
controller: ['$scope', '$state', 'blueprintService', 'paletteService', graphicalController],
controller: ['$scope', '$state', '$filter', 'blueprintService', 'paletteService', graphicalController],
controllerAs: 'vm',
data: {
label: 'Graphical Designer'
}
};

function graphicalController($scope, $state, blueprintService, paletteService) {
function graphicalController($scope, $state, $filter, blueprintService, paletteService) {
this.EntityFamily = EntityFamily;

this.sections = paletteService.getSections();
this.selectedSection = Object.values(this.sections).find(section => section.type === EntityFamily.ENTITY);
$scope.paletteState = {}; // share state among all sections

this.onTypeSelected = (selectedType)=> {
let rootEntity = blueprintService.get();
this.onCanvasSelection = (item) => {
$scope.canvasSelectedItem = item;
}
this.getOnSelectText = (selectableType) => $scope.canvasSelectedItem ? "Add to " + $filter('entityName')($scope.canvasSelectedItem) : "Add to application";

this.addSelectedTypeToTargetEntity = (selectedType, targetEntity) => {
if (!targetEntity) targetEntity = $scope.canvasSelectedItem;
if (!targetEntity) targetEntity = blueprintService.get();

if (selectedType.supertypes.includes(EntityFamily.ENTITY.superType)) {
let newEntity = blueprintService.populateEntityFromApi(new Entity(), selectedType);
rootEntity.addChild(newEntity);
targetEntity.addChild(newEntity);
blueprintService.refreshEntityMetadata(newEntity, EntityFamily.ENTITY).then(() => {
$state.go(graphicalEditEntityState, {entityId: newEntity._id});
})
}
else if (selectedType.supertypes.includes(EntityFamily.POLICY.superType)) {
let newPolicy = blueprintService.populateEntityFromApi(new Entity(), selectedType);
rootEntity.addPolicy(newPolicy);
targetEntity.addPolicy(newPolicy);
blueprintService.refreshEntityMetadata(newPolicy, EntityFamily.POLICY).then(() => {
$state.go(graphicalEditPolicyState, {entityId: rootEntity._id, policyId: newPolicy._id});
$state.go(graphicalEditPolicyState, {entityId: targetEntity._id, policyId: newPolicy._id});
});
}
else if (selectedType.supertypes.includes(EntityFamily.ENRICHER.superType)) {
let newEnricher = blueprintService.populateEntityFromApi(new Entity(), selectedType);
rootEntity.addEnricher(newEnricher);
targetEntity.addEnricher(newEnricher);
blueprintService.refreshEntityMetadata(newEnricher, EntityFamily.ENRICHER).then(() => {
$state.go(graphicalEditEnricherState, {entityId: rootEntity._id, enricherId: newEnricher._id});
$state.go(graphicalEditEnricherState, {entityId: targetEntity._id, enricherId: newEnricher._id});
});
}
else if (selectedType.supertypes.includes(EntityFamily.LOCATION.superType)) {
blueprintService.populateLocationFromApi(rootEntity, selectedType);
$state.go(graphicalEditEntityState, {entityId: rootEntity._id});
blueprintService.populateLocationFromApi(targetEntity, selectedType);
$state.go(graphicalEditEntityState, {entityId: targetEntity._id});
}
};
}

0 comments on commit e20a8d1

Please sign in to comment.