function link()

in ui-modules/blueprint-composer/app/components/designer/designer.directive.js [50:286]


    function link($scope, $element) {
        let container = $element[0];
        let blueprintGraph = new D3Blueprint(container, {shouldShowNode: composerOverrides.shouldShowNode}).center();

        // allow downstream to configure this directive and/or scope
        (composerOverrides.configureDesignerDirective || function () {})($scope, $element, blueprintGraph);

        $scope.blueprint = blueprintService.get();

        blueprintService.refreshBlueprintMetadata().then(() => {
            redrawGraph();

            // Start watching blueprint changes after metadata is refreshed. Metadata is changed many times while being
            // refreshed, no need to re-draw on every change.
            $scope.$watch('blueprint', () => {
                redrawGraph();
            }, true);

            // Broadcast 'd3.metadata-refreshed' event, allow downstream to react on this event.
            $scope.$broadcast('d3.metadata-refreshed');
        });

        $scope.selectedEntity = null;

        $scope.$on('d3.redraw', (event, initial) => {
            $log.debug(TAG + 'Re-draw blueprint, triggered by ' + event.name, initial, $scope.blueprint);

            blueprintService.refreshBlueprintMetadata().then(() => {
                redrawGraph();
                if (initial) {
                    blueprintGraph.center();
                }
            });
        });

        $scope.$on('d3.remove', (event, entity) => {
            $log.debug(TAG + `Delete ${entity.family.displayName} ${entity._id}`, entity);

            let relationships = blueprintService.getRelationships().filter((relation) => (relation.target === entity));

            switch (entity.family) {
                case EntityFamily.ENTITY:
                    if (entity.hasParent()) {
                        $state.go(graphicalEditEntityState, { entityId: entity.parent._id })
                    }
                    entity.delete();
                    break;
                case EntityFamily.POLICY:
                    entity.parent.removePolicy(entity._id);
                    break;
                case EntityFamily.ENRICHER:
                    entity.parent.removeEnricher(entity._id);
                    break;
                case EntityFamily.SPEC:
                    let memberSpecMap = entity.parent.getClusterMemberspecEntities();
                    Object.keys(memberSpecMap).forEach((key) => {
                        if (memberSpecMap[key] === entity) {
                            entity.parent.removeConfig(key);
                        }
                    });
                    break;
            }

            $q.all(relationships.map((relation) => (blueprintService.refreshRelationships(relation.source)))).then(() => {
                $scope.$applyAsync(() => {
                    redrawGraph();
                    $state.go('main.graphical');
                });
            });

            // Broadcast 'd3.removed' event, allow downstream to react on this event.
            $scope.$broadcast('d3.removed');
        });

        $scope.$on('$stateChangeSuccess', (event, toState, toParams, fromState, fromParams, options) => {
            let id;
            switch (toState) {
                case graphicalEditEntityState:
                    id = toParams.entityId;
                    break;
                case graphicalEditSpecState:
                    id = toParams.specId;
                    break;
                case graphicalEditPolicyState:
                    id = toParams.policyId;
                    break;
                case graphicalEditEnricherState:
                    id = toParams.enricherId;
                    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');
            });
        });

        $element.bind('click-entity', (event) => {
            $scope.$apply(() => {
                const clickedEntity = event.detail.entity;
                $log.debug(TAG + 'edit node ' + clickedEntity._id, clickedEntity);
                switch (clickedEntity.family) {
                    case EntityFamily.ENTITY:
                        const blueprint = blueprintService.get();
                        if (blueprint.isInDslEdit) {
                            $rootScope.$broadcast('d3.entity-selected', clickedEntity);
                            blueprintGraph.hideShadow();
                            blueprintGraph.dropShadow(clickedEntity._id);
                        } else {
                            $state.go(graphicalEditEntityState, {entityId: clickedEntity._id});
                        }
                        break;
                    case EntityFamily.SPEC:
                        $state.go(graphicalEditSpecState, {entityId: clickedEntity.parent._id, specId: clickedEntity._id});
                        break;
                    case EntityFamily.POLICY:
                        $state.go(graphicalEditPolicyState, {entityId: clickedEntity.parent._id, policyId: clickedEntity._id});
                        break;
                    case EntityFamily.ENRICHER:
                        $state.go(graphicalEditEnricherState, {entityId: clickedEntity.parent._id, enricherId: clickedEntity._id});
                        break;
                }
            });
        });

        $element.bind('click-add-child', (event) => {
            $log.debug(TAG + 'Add child to node ' + event.detail.entity._id);
            $scope.$apply(() => {
                $state.go('main.graphical.edit.add', {entityId: event.detail.entity._id, family: 'entity'});
            });
        });

        $element.bind('move-entity', function (event) {
            if (!event.detail.isNewParent) { // Do not remove, this event is intercepted in customized versions.
                return;
            }
            let currentNode = blueprintService.find(event.detail.nodeId);
            let parentNode = blueprintService.find(event.detail.parentId);
            if (parentNode.hasAncestor(currentNode)) {
                brSnackbar.create('Cannot move an entity node below itself or its own descendants');
            } else {
                $log.debug(TAG + 'move-entity ' + event.detail.nodeId, currentNode);
                let targetIndex = event.detail.targetIndex;
                if (currentNode.parent === parentNode && targetIndex > parentNode.children.indexOf(currentNode)) {
                    targetIndex--;
                }
                currentNode.parent.removeChild(currentNode._id);
                if (targetIndex >= 0) {
                    parentNode.insertChild(currentNode, targetIndex);
                }
                else {
                    parentNode.addChild(currentNode);
                }
            }
            blueprintService.refreshAllRelationships().then(()=> {
                redrawGraph();
            });
        });

        $element.bind('delete-entity', function (event) {
            $log.debug('delete-entity');
            $scope.$broadcast('d3.remove', event.detail.entity);
        });

        $element.bind('graph-redrawn', () => $scope.$root.$broadcast('layers.filter'));

        $element.bind('drop-external-node', event => {
            let draggedItem = paletteDragAndDropService.draggedItem();
            let targetEntity = blueprintService.find(event.detail.parentId);

            if (draggedItem.supertypes.includes(EntityFamily.ENTITY.superType)) {
                let targetIndex = event.detail.targetIndex;
                let newEntity = blueprintService.populateEntityFromApi(new Entity(), draggedItem);
                if (targetIndex >= 0) {
                    targetEntity.insertChild(newEntity, targetIndex);
                } else {
                    targetEntity.addChild(newEntity);
                }
                blueprintService.refreshEntityMetadata(newEntity, EntityFamily.ENTITY).then(() => {
                    container.dispatchEvent(new CustomEvent('new-entity-created', {
                        detail: {
                            nodeId: newEntity._id,
                            parentId: targetEntity._id
                        }
                    }));
                    $state.go(graphicalEditEntityState, {entityId: newEntity._id});
                });
            }
            else if (draggedItem.supertypes.includes(EntityFamily.POLICY.superType)) {
                let newPolicy = blueprintService.populateEntityFromApi(new Entity(), draggedItem);
                targetEntity.addPolicy(newPolicy);
                blueprintService.refreshEntityMetadata(newPolicy, EntityFamily.POLICY).then(() => {
                    $state.go(graphicalEditPolicyState, {entityId: targetEntity._id, policyId: newPolicy._id});
                });
            }
            else if (draggedItem.supertypes.includes(EntityFamily.ENRICHER.superType)) {
                let newEnricher = blueprintService.populateEntityFromApi(new Entity(), draggedItem);
                targetEntity.addEnricher(newEnricher);
                blueprintService.refreshEntityMetadata(newEnricher, EntityFamily.ENRICHER).then(() => {
                    $state.go(graphicalEditEnricherState, {entityId: targetEntity._id, enricherId: newEnricher._id});
                });
            }
            else if (draggedItem.supertypes.includes(EntityFamily.LOCATION.superType)) {
                blueprintService.populateLocationFromApi(targetEntity, draggedItem);
                $state.go(graphicalEditEntityState, {entityId: targetEntity._id});
            }

            // Refresh relationships & redraw.
            blueprintService.refreshAllRelationships().then(()=> {
                redrawGraph();
            });
        });

        function redrawGraph() {
            let crossLinks = blueprintService.getRelationships();

            blueprintGraph.update($scope.blueprint, crossLinks).draw();
            if ($scope.selectedEntity) {
                blueprintGraph.select($scope.selectedEntity._id);
            } else {
                blueprintGraph.unselect();
            }
            if (!$scope.blueprint.isInDslEdit) {
                blueprintGraph.hideShadow();
            }
        }
    }