/*- * ============LICENSE_START======================================================= * SDC * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed 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. * ============LICENSE_END========================================================= */ import * as _ from "lodash"; import { Component, IAppMenu, LeftPanelModel, NodesFactory, LeftPaletteComponent, CompositionCiNodeBase, ComponentInstance, Point } from "app/models"; import { CompositionGraphGeneralUtils } from "../composition-graph/utils/composition-graph-general-utils"; import { EventListenerService } from "app/services"; import { ResourceType, GRAPH_EVENTS, EVENTS, ComponentInstanceFactory, ModalsHandler } from "app/utils"; import 'sdc-angular-dragdrop'; import { LeftPaletteLoaderService } from "../../../services/components/utils/composition-left-palette-service"; import { Resource } from "app/models/components/resource"; import { ComponentType } from "app/utils/constants"; import { LeftPaletteMetadataTypes } from "../../../models/components/displayComponent"; import { IDirectiveLinkFn, IScope } from "angular"; interface IPaletteScope extends IScope { components: Array; currentComponent: Component; model: any; displaySortedCategories: any; expandedSection: string; dragElement: JQuery; dragbleNode: { event: JQueryEventObject, components: LeftPaletteComponent, ui: any } addInstanceClick: () => void; // added code onPopupMouseOver: () => void // added code onPopupMouseOut: () => void // added code sectionClick: (section: string) => void; searchComponents: (searchText: string) => void; onMouseOver: (displayComponent: LeftPaletteComponent, elem: HTMLElement) => void; onMouseOut: (displayComponent: LeftPaletteComponent) => void; dragStartCallback: (event: JQueryEventObject, ui, displayComponent: LeftPaletteComponent) => void; dragStopCallback: () => void; onDragCallback: (event: JQueryEventObject) => void; setElementTemplate: (e: JQueryEventObject) => void; isOnDrag: boolean; isDragable: boolean; isLoading: boolean; isViewOnly: boolean; } export class Palette implements ng.IDirective { constructor(private $log: ng.ILogService, private LeftPaletteLoaderService: LeftPaletteLoaderService, private sdcConfig, private ComponentFactory, private ComponentInstanceFactory: ComponentInstanceFactory, private NodesFactory: NodesFactory, private CompositionGraphGeneralUtils: CompositionGraphGeneralUtils, private EventListenerService: EventListenerService, private sdcMenu: IAppMenu, private ModalsHandler: ModalsHandler ) { } private fetchingComponentFromServer: boolean = false; private nodeHtmlSubstitute: JQuery; scope = { currentComponent: '=', isViewOnly: '=', isLoading: '=' }; restrict = 'E'; template = require('./palette.html'); link: IDirectiveLinkFn = (scope: IPaletteScope, el: JQuery) => { this.LeftPaletteLoaderService.loadLeftPanel(scope.currentComponent); this.nodeHtmlSubstitute = $('
'); el.append(this.nodeHtmlSubstitute); this.registerEventListenerForLeftPalette(scope); this.initComponents(scope); this.initEvents(scope); this.initDragEvents(scope); this._initExpandedSection(scope, ''); el.on('$destroy', () => { //remove listener of download event this.unRegisterEventListenerForLeftPalette(scope); }); }; private registerEventListenerForLeftPalette = (scope: IPaletteScope): void => { this.EventListenerService.registerObserverCallback(EVENTS.LEFT_PALETTE_UPDATE_EVENT, () => { this.updateLeftPanelDisplay(scope); }); }; private unRegisterEventListenerForLeftPalette = (scope: IPaletteScope): void => { this.EventListenerService.unRegisterObserver(EVENTS.LEFT_PALETTE_UPDATE_EVENT); }; private leftPanelResourceFilter(resourcesNotAbstract: Array, resourceFilterTypes: Array): Array { let filterResources = _.filter(resourcesNotAbstract, (component) => { return resourceFilterTypes.indexOf(component.getComponentSubType()) > -1; }); return filterResources; } private initLeftPanel(leftPanelComponents: Array, resourceFilterTypes: Array): LeftPanelModel { let leftPanelModel = new LeftPanelModel(); if (resourceFilterTypes && resourceFilterTypes.length) { leftPanelComponents = this.leftPanelResourceFilter(leftPanelComponents, resourceFilterTypes); } leftPanelModel.numberOfElements = leftPanelComponents && leftPanelComponents.length || 0; if (leftPanelComponents && leftPanelComponents.length) { let categories: any = _.groupBy(leftPanelComponents, 'mainCategory'); for (let category in categories) categories[category] = _.groupBy(categories[category], 'subCategory'); leftPanelModel.sortedCategories = categories; } return leftPanelModel; } private initEvents(scope: IPaletteScope) { scope.sectionClick = (section: string) => { if (section === scope.expandedSection) { scope.expandedSection = ''; return; } scope.expandedSection = section; }; scope.onMouseOver = (displayComponent: LeftPaletteComponent, sectionElem: HTMLElement) => { if (this.isGroupOrPolicy(displayComponent)) { this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_SHOW_POPUP_PANEL, scope.currentComponent, displayComponent, sectionElem); } else { if (scope.isOnDrag) { return; } scope.isOnDrag = true; this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, displayComponent); this.$log.debug('palette::onMouseOver:: fired'); } }; scope.onMouseOut = (displayComponent: LeftPaletteComponent) => { if (this.isGroupOrPolicy(displayComponent)) { this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HIDE_POPUP_PANEL); } else { scope.isOnDrag = false; this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_OUT); } }; } private isGroupOrPolicy(component: LeftPaletteComponent): boolean { if (component && (component.categoryType === LeftPaletteMetadataTypes.Group || component.categoryType === LeftPaletteMetadataTypes.Policy)) { return true; } return false; } private initComponents(scope: IPaletteScope) { scope.searchComponents = (searchText: any): void => { scope.displaySortedCategories = this._searchComponents(searchText, scope.model.sortedCategories); this._initExpandedSection(scope, searchText); }; scope.isDragable = scope.currentComponent.isComplex(); this.updateLeftPanelDisplay(scope); } private updateLeftPanelDisplay(scope: IPaletteScope) { let entityType: string = scope.currentComponent.componentType.toLowerCase(); let resourceFilterTypes: Array = this.sdcConfig.resourceTypesFilter[entityType]; scope.components = this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent); //remove the container component from the list let componentTempToDisplay = angular.copy(scope.components); componentTempToDisplay = _.remove(componentTempToDisplay, function (leftPalettecomponent) { return leftPalettecomponent.invariantUUID !== scope.currentComponent.invariantUUID; }); scope.model = this.initLeftPanel(componentTempToDisplay, resourceFilterTypes); scope.displaySortedCategories = angular.copy(scope.model.sortedCategories); }; private _initExpandedSection(scope: IPaletteScope, searchText: string): void { if (searchText == '') { let isContainingCategory: boolean = false; let categoryToExpand: string; if (scope.currentComponent && scope.currentComponent.categories && scope.currentComponent.categories[0]) { categoryToExpand = this.sdcMenu.categoriesDictionary[scope.currentComponent.categories[0].name]; for (let category in scope.model.sortedCategories) { if (categoryToExpand == category) { isContainingCategory = true; break; } } } isContainingCategory ? scope.expandedSection = categoryToExpand : scope.expandedSection = 'Generic'; } else { scope.expandedSection = Object.keys(scope.displaySortedCategories).sort()[0]; } }; private initDragEvents(scope: IPaletteScope) { scope.dragStartCallback = (event: IDragDropEvent, ui, displayComponent: LeftPaletteComponent): void => { if (scope.isLoading || !scope.isDragable || scope.isViewOnly || this.isGroupOrPolicy(displayComponent)) { return; } let component = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent), (componentFullData: LeftPaletteComponent) => { return displayComponent.uniqueId === componentFullData.uniqueId; }); this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_START, scope.dragElement, component); scope.isOnDrag = true; // this.graphUtils.showMatchingNodes(component, myDiagram, scope.sdcConfig.imagesPath); // document.addEventListener('mousemove', moveOnDocument); event.dataTransfer.component = component; }; scope.dragStopCallback = () => { scope.isOnDrag = false; }; scope.onDragCallback = (event: IDragDropEvent): void => { this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_ACTION, event); }; scope.setElementTemplate = (e) => { let dragComponent: LeftPaletteComponent = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent), (fullComponent: LeftPaletteComponent) => { return (angular.element(e.currentTarget).scope()).component.uniqueId === fullComponent.uniqueId; }); let componentInstance: ComponentInstance = this.ComponentInstanceFactory.createComponentInstanceFromComponent(dragComponent); let node: CompositionCiNodeBase = this.NodesFactory.createNode(componentInstance); // myDiagram.dragFromPalette = node; this.nodeHtmlSubstitute.find("img").attr('src', node.img); scope.dragElement = this.nodeHtmlSubstitute.clone().show(); return scope.dragElement; }; } private _searchComponents = (searchText: string, categories: any): void => { let displaySortedCategories = angular.copy(categories); if (searchText != '') { angular.forEach(categories, function (category: any, categoryKey) { angular.forEach(category, function (subcategory: Array, subcategoryKey) { let filteredResources = []; angular.forEach(subcategory, function (component: LeftPaletteComponent) { let resourceFilterTerm: string = component.searchFilterTerms.toLowerCase(); if (resourceFilterTerm.indexOf(searchText.toLowerCase()) >= 0) { filteredResources.push(component); } }); if (filteredResources.length > 0) { displaySortedCategories[categoryKey][subcategoryKey] = filteredResources; } else { delete displaySortedCategories[categoryKey][subcategoryKey]; } }); if (!(Object.keys(displaySortedCategories[categoryKey]).length > 0)) { delete displaySortedCategories[categoryKey]; } }); } return displaySortedCategories; }; public static factory = ($log, LeftPaletteLoaderService, sdcConfig, ComponentFactory, ComponentInstanceFactory, NodesFactory, CompositionGraphGeneralUtils, EventListenerService, sdcMenu, ModalsHandler ) => { return new Palette($log, LeftPaletteLoaderService, sdcConfig, ComponentFactory, ComponentInstanceFactory, NodesFactory, CompositionGraphGeneralUtils, EventListenerService, sdcMenu, ModalsHandler ); }; } Palette.factory.$inject = [ '$log', 'LeftPaletteLoaderService', 'sdcConfig', 'ComponentFactory', 'ComponentInstanceFactory', 'NodesFactory', 'CompositionGraphGeneralUtils', 'EventListenerService', 'sdcMenu', 'ModalsHandler' ];