///
module Sdc.Directives {
import Dictionary = Sdc.Utils.Dictionary;
import GRAPH_EVENTS = Sdc.Utils.Constants.GRAPH_EVENTS;
import ImageCreatorService = Sdc.Utils.ImageCreatorService;
interface IPaletteScope {
components: any;
currentComponent: any;
model: any;
displaySortedCategories: any;
expandedSection: string;
p2pVL: Models.Components.Component;
mp2mpVL: Models.Components.Component;
vlType: string;
dragElement: JQuery;
dragbleNode: {
event: JQueryEventObject,
components: Models.DisplayComponent,
ui: any
}
sectionClick: (section: string)=>void;
searchComponents: (searchText: string)=>void;
onMouseOver: (displayComponent: Models.DisplayComponent)=>void;
onMouseOut: (displayComponent: Models.DisplayComponent)=>void;
dragStartCallback: (event: JQueryEventObject, ui, displayComponent: Models.DisplayComponent)=>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,
private sdcConfig,
private ComponentFactory,
private ComponentInstanceFactory: Utils.ComponentInstanceFactory,
private NodesFactory: Utils.NodesFactory,
private CompositionGraphGeneralUtils: Graph.Utils.CompositionGraphGeneralUtils,
private EventListenerService: Services.EventListenerService,
private sdcMenu: Models.IAppMenu) {
}
private fetchingComponentFromServer: boolean = false;
private nodeHtmlSubstitute: JQuery;
scope = {
components: '=',
currentComponent: '=',
isViewOnly: '=',
isLoading: '='
};
restrict = 'E';
templateUrl = '/app/scripts/directives/graphs-v2/palette/palette.html';
link = (scope: IPaletteScope, el: JQuery) => {
this.nodeHtmlSubstitute = $('
');
el.append(this.nodeHtmlSubstitute);
this.initComponents(scope);
this.initScopeVls(scope);
this.initEvents(scope);
this.initDragEvents(scope);
this._initExpandedSection(scope, '');
};
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): Models.LeftPanelModel {
let leftPanelModel = new Models.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 initScopeVls(scope: IPaletteScope): void {
let vls = this.LeftPaletteLoaderService.getFullDataComponentList(Utils.Constants.ResourceType.VL);
scope.vlType = null;
vls.forEach((item) => {
let key = _.find(Object.keys(item.capabilities), (key) => {
return _.includes(key.toLowerCase(), 'linkable');
});
let linkable = item.capabilities[key];
if (linkable) {
if (linkable[0].maxOccurrences == '2') {
scope.p2pVL = _.find(vls, (component: Models.Components.Component) => {
return component.uniqueId === item.uniqueId;
});
} else {//assuming unbounded occurrences
scope.mp2mpVL = _.find(vls, (component: Models.Components.Component) => {
return component.uniqueId === item.uniqueId;
});
}
}
});
};
private initEvents(scope: IPaletteScope) {
/**
*
* @param section
*/
scope.sectionClick = (section: string) => {
if (section === scope.expandedSection) {
scope.expandedSection = '';
return;
}
scope.expandedSection = section;
};
scope.onMouseOver = (displayComponent: Models.DisplayComponent) => {
if (scope.isOnDrag) {
return;
}
scope.isOnDrag = true;
this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, displayComponent);
this.$log.debug('palette::onMouseOver:: fired');
if (this.CompositionGraphGeneralUtils.componentRequirementsAndCapabilitiesCaching.containsKey(displayComponent.uniqueId)) {
this.$log.debug(`palette::onMouseOver:: component id ${displayComponent.uniqueId} found in cache`);
let cacheComponent: Models.Components.Component = this.CompositionGraphGeneralUtils.componentRequirementsAndCapabilitiesCaching.getValue(displayComponent.uniqueId);
//TODO: Danny: fire event to highlight matching nodes
//showMatchingNodes(cacheComponent);
return;
}
this.$log.debug(`palette::onMouseOver:: component id ${displayComponent.uniqueId} not found in cache, initiating server get`);
// This will bring the component from the server including requirements and capabilities
// Check that we do not fetch many times, because only in the success we add the component to componentRequirementsAndCapabilitiesCaching
if (this.fetchingComponentFromServer) {
return;
}
this.fetchingComponentFromServer = true;
this.ComponentFactory.getComponentFromServer(displayComponent.componentSubType, displayComponent.uniqueId)
.then((component: Models.Components.Component) => {
this.$log.debug(`palette::onMouseOver:: component id ${displayComponent.uniqueId} fetch success`);
this.LeftPaletteLoaderService.updateSpecificComponentLeftPalette(component, scope.currentComponent.componentType);
this.CompositionGraphGeneralUtils.componentRequirementsAndCapabilitiesCaching.setValue(component.uniqueId, component);
this.fetchingComponentFromServer = false;
//TODO: Danny: fire event to highlight matching nodes
//showMatchingNodes(component);
})
.catch(() => {
this.$log.debug('palette::onMouseOver:: component id fetch error');
this.fetchingComponentFromServer = false;
});
};
scope.onMouseOut = () => {
scope.isOnDrag = false;
this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_OUT);
}
}
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();
let entityType: string = scope.currentComponent.componentType.toLowerCase();
let resourceFilterTypes: Array = this.sdcConfig.resourceTypesFilter[entityType];
scope.components = this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent.componentType);
scope.model = this.initLeftPanel(scope.components, 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: Models.DisplayComponent): void => {
if (scope.isLoading || !scope.isDragable || scope.isViewOnly) {
return;
}
let component = _.find(this.LeftPaletteLoaderService.getFullDataComponentListWithVls(scope.currentComponent.componentType), (componentFullData: Models.DisplayComponent) => {
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: Models.Components.Component = _.find(this.LeftPaletteLoaderService.getFullDataComponentListWithVls(scope.currentComponent.componentType),
(fullComponent: Models.Components.Component) => {
return (angular.element(e.currentTarget).scope()).component.uniqueId === fullComponent.uniqueId;
});
let componentInstance: Models.ComponentsInstances.ComponentInstance = this.ComponentInstanceFactory.createComponentInstanceFromComponent(dragComponent);
let node: Models.Graph.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: Models.DisplayComponent) {
let resourceFilterTerm: string = component.searchFilterTerms;
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) => {
return new Palette($log,
LeftPaletteLoaderService,
sdcConfig,
ComponentFactory,
ComponentInstanceFactory,
NodesFactory,
CompositionGraphGeneralUtils,
EventListenerService,
sdcMenu);
};
}
Palette.factory.$inject = [
'$log',
'LeftPaletteLoaderService',
'sdcConfig',
'ComponentFactory',
'ComponentInstanceFactory',
'NodesFactory',
'CompositionGraphGeneralUtils',
'EventListenerService',
'sdcMenu'
];
}