aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/directives/graphs-v2/palette
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/src/app/directives/graphs-v2/palette')
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/palette/interfaces/i-dragdrop-event.d.ts7
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts349
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/palette/palette.html57
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/palette/palette.less92
4 files changed, 505 insertions, 0 deletions
diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/interfaces/i-dragdrop-event.d.ts b/catalog-ui/src/app/directives/graphs-v2/palette/interfaces/i-dragdrop-event.d.ts
new file mode 100644
index 0000000000..26c042611c
--- /dev/null
+++ b/catalog-ui/src/app/directives/graphs-v2/palette/interfaces/i-dragdrop-event.d.ts
@@ -0,0 +1,7 @@
+interface IDragDropEvent extends JQueryEventObject {
+ dataTransfer: any;
+ toElement: {
+ naturalWidth: number;
+ naturalHeight: number;
+ }
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts b/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts
new file mode 100644
index 0000000000..4bfbe5270e
--- /dev/null
+++ b/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts
@@ -0,0 +1,349 @@
+import {
+ Component,
+ IAppMenu,
+ LeftPanelModel,
+ NodesFactory,
+ LeftPaletteComponent,
+ CompositionCiNodeBase,
+ ComponentInstance
+} 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 'angular-dragdrop';
+import {LeftPaletteLoaderService} from "../../../services/components/utils/composition-left-palette-service";
+
+interface IPaletteScope {
+ components:Array<LeftPaletteComponent>;
+ currentComponent:Component;
+ model:any;
+ displaySortedCategories:any;
+ expandedSection:string;
+ dragElement:JQuery;
+ dragbleNode:{
+ event:JQueryEventObject,
+ components:LeftPaletteComponent,
+ ui:any
+ }
+
+ sectionClick:(section:string)=>void;
+ searchComponents:(searchText:string)=>void;
+ onMouseOver:(displayComponent:LeftPaletteComponent)=>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 = (scope:IPaletteScope, el:JQuery) => {
+ this.nodeHtmlSubstitute = $('<div class="node-substitute"><span></span><img /></div>');
+ el.append(this.nodeHtmlSubstitute);
+ this.registerEventListenerForLeftPalette(scope);
+ // this.LeftPaletteLoaderService.loadLeftPanel(scope.currentComponent.componentType);
+
+ 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 => {
+ if (scope.currentComponent.isResource()) {
+ this.EventListenerService.registerObserverCallback(EVENTS.RESOURCE_LEFT_PALETTE_UPDATE_EVENT, () => {
+ this.updateLeftPanelDisplay(scope);
+ });
+ }
+ if (scope.currentComponent.isService()) {
+ this.EventListenerService.registerObserverCallback(EVENTS.SERVICE_LEFT_PALETTE_UPDATE_EVENT, () => {
+ this.updateLeftPanelDisplay(scope);
+ });
+ }
+ if (scope.currentComponent.isProduct()) {
+ this.EventListenerService.registerObserverCallback(EVENTS.PRODUCT_LEFT_PALETTE_UPDATE_EVENT, () => {
+ this.updateLeftPanelDisplay(scope);
+ });
+ }
+ };
+
+ private unRegisterEventListenerForLeftPalette = (scope:IPaletteScope):void => {
+ if (scope.currentComponent.isResource()) {
+ this.EventListenerService.unRegisterObserver(EVENTS.RESOURCE_LEFT_PALETTE_UPDATE_EVENT);
+ }
+ if (scope.currentComponent.isService()) {
+ this.EventListenerService.unRegisterObserver(EVENTS.SERVICE_LEFT_PALETTE_UPDATE_EVENT);
+ }
+ if (scope.currentComponent.isProduct()) {
+ this.EventListenerService.unRegisterObserver(EVENTS.PRODUCT_LEFT_PALETTE_UPDATE_EVENT);
+ }
+ };
+
+ private leftPanelResourceFilter(resourcesNotAbstract:Array<LeftPaletteComponent>, resourceFilterTypes:Array<string>):Array<LeftPaletteComponent> {
+ let filterResources = _.filter(resourcesNotAbstract, (component) => {
+ return resourceFilterTypes.indexOf(component.getComponentSubType()) > -1;
+ });
+ return filterResources;
+ }
+
+ private initLeftPanel(leftPanelComponents:Array<LeftPaletteComponent>, resourceFilterTypes:Array<string>):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) {
+ /**
+ *
+ * @param section
+ */
+ scope.sectionClick = (section:string) => {
+ if (section === scope.expandedSection) {
+ scope.expandedSection = '';
+ return;
+ }
+ scope.expandedSection = section;
+ };
+
+ scope.onMouseOver = (displayComponent:LeftPaletteComponent) => {
+ 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: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: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();
+ this.updateLeftPanelDisplay(scope);
+ }
+
+ private updateLeftPanelDisplay(scope:IPaletteScope) {
+ let entityType:string = scope.currentComponent.componentType.toLowerCase();
+ let resourceFilterTypes:Array<string> = 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:LeftPaletteComponent):void => {
+ if (scope.isLoading || !scope.isDragable || scope.isViewOnly) {
+ return;
+ }
+
+ let component = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent.componentType), (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.componentType),
+ (fullComponent:LeftPaletteComponent) => {
+ return (<any>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<LeftPaletteComponent>, subcategoryKey) {
+ let filteredResources = [];
+ angular.forEach(subcategory, function (component:LeftPaletteComponent) {
+
+ 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,
+ 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'
+];
diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/palette.html b/catalog-ui/src/app/directives/graphs-v2/palette/palette.html
new file mode 100644
index 0000000000..4b123e5777
--- /dev/null
+++ b/catalog-ui/src/app/directives/graphs-v2/palette/palette.html
@@ -0,0 +1,57 @@
+<div class="w-sdc-designer-leftbar">
+ <div class="w-sdc-designer-leftbar-title">Elements <span class="w-sdc-designer-leftbar-title-count">{{model.numberOfElements}}</span>
+ </div>
+
+ <div class="w-sdc-designer-leftbar-search">
+ <input type="text" class="w-sdc-designer-leftbar-search-input" placeholder="Search..."
+ data-ng-model="searchText" data-ng-change="searchComponents(searchText)"
+ ng-model-options="{ debounce: 500 }" data-tests-id="searchAsset"/>
+ <span class="w-sdc-search-icon leftbar" data-ng-class="{'cancel':searchText, 'magnification':!searchText}"
+ data-ng-click="searchText=''; searchComponents('',categories)"></span>
+ </div>
+ <div class="i-sdc-designer-leftbar-section"
+ data-ng-repeat="(entityCategory, objCategory) in displaySortedCategories track by $index"
+ data-ng-class="{'expanded': expandedSection.indexOf(entityCategory) !== -1}">
+ <div class="i-sdc-designer-leftbar-section-title pointer" data-ng-click="sectionClick(entityCategory)"
+ data-tests-id="leftbar-section-title-{{entityCategory}}">
+ {{entityCategory}}
+ <div class="i-sdc-designer-leftbar-section-title-icon"></div>
+ </div>
+ <div class="i-sdc-designer-leftbar-section-content"
+ data-ng-repeat="(subCategory, components) in objCategory track by $index">
+ <div class="i-sdc-designer-leftbar-section-content-subcat i-sdc-designer-leftbar-section-content-item">
+ {{subCategory}}
+ </div>
+ <div class="i-sdc-designer-leftbar-section-content-item"
+ data-ng-class="{'default-pointer': isViewOnly}"
+ data-ng-mouseover="!isViewOnly && onMouseOver(component)"
+ data-ng-mouseleave="!isViewOnly && onMouseOut()"
+ data-drag="{{!isViewOnly}}"
+ data-jqyoui-options="{revert: 'invalid', helper:setElementTemplate, appendTo:'body', cursorAt: {left:38, top: 38}, cursor:'move'}"
+ jqyoui-draggable="{index:{{$index}},animate:true,onStart:'dragStartCallback(component)',onStop:'dragStopCallback()', onDrag:'onDragCallback()'}"
+ data-ng-repeat="component in components | orderBy: 'displayName' track by $index"
+ data-tests-id={{component.displayName}}>
+ <div class="i-sdc-designer-leftbar-section-content-item-icon-ph">
+ <div class="medium {{component.iconClass}}"
+ data-tests-id="leftbar-section-content-item-{{component.displayName}}">
+ <div class="{{component.certifiedIconClass}}" uib-tooltip="Not certified"
+ tooltip-class="uib-custom-tooltip" tooltip-placement="bottom" tooltip-popup-delay="700">
+ </div>
+ </div>
+ </div>
+ <div class="i-sdc-designer-leftbar-section-content-item-info">
+ <span class="i-sdc-designer-leftbar-section-content-item-info-title"
+ uib-tooltip="{{component.displayName}}" tooltip-class="uib-custom-tooltip"
+ tooltip-placement="bottom" tooltip-popup-delay="700">
+ {{component.displayName}}</span>
+ <div class="i-sdc-designer-leftbar-section-content-item-info-text">
+ V.{{component.version}}
+ </div>
+ <div class="i-sdc-designer-leftbar-section-content-item-info-text"> Type:
+ {{component.componentSubType}}
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/palette.less b/catalog-ui/src/app/directives/graphs-v2/palette/palette.less
new file mode 100644
index 0000000000..85657a43a5
--- /dev/null
+++ b/catalog-ui/src/app/directives/graphs-v2/palette/palette.less
@@ -0,0 +1,92 @@
+.drag-icon-border{
+ border: 7px solid red;
+ border-radius: 500px;
+ -webkit-border-radius: 500px;
+ -moz-border-radius: 500px;
+ width: 53px;
+ height: 53px;
+}
+
+.drag-icon-circle{
+ width: 60px;
+ height: 60px;
+ -webkit-border-radius: 50%;
+ -moz-border-radius: 50%;
+ border-radius: 50%;
+ position: relative;
+
+}
+
+
+@green-shadow: rgba(29, 154, 149, 0.3);
+@red-shadow: rgba(218, 31, 61, 0.3);
+.drag-icon-circle .sprite-resource-icons {
+ position: absolute;
+ top: 10px;
+ left: 10px;
+}
+
+.drag-icon-circle.red {
+ background: @red-shadow;
+}
+
+.drag-icon-circle.green {
+ background: @green-shadow;
+}
+
+
+.node-substitute {
+ display: none;
+ position: absolute;
+ z-index: 9999;
+ height: 80px;
+ width: 80px;
+ border-radius: 50%;
+ text-align: center;
+
+ span {
+ display: inline-block;
+ vertical-align: middle;
+ height: 100%;
+ }
+
+ img {
+ height: 40px;
+ width: 40px;
+ box-shadow: 0 0 0 10px @green-shadow;
+ border-radius: 50%;
+
+ -webkit-user-drag: none;
+ -moz-user-drag: none;
+ user-drag: none;
+ }
+ &.red img {
+ box-shadow: 0 0 0 10px @red-shadow;
+ }
+ &.bounce img {
+ -moz-animation:bounceOut 0.3s linear;
+ -webkit-animation:bounceOut 0.3s linear;
+ animation:bounceOut 0.3s linear;
+ }
+}
+
+@keyframes bounceOut {
+ 0%{ box-shadow: 0 0 0 10px @green-shadow; width: 40px; height: 40px; }
+ 60%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
+ 85%{ box-shadow: 0 0 0 0px @green-shadow; width: 75px; height: 75px; }
+ 100%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
+}
+
+@-moz-keyframes bounceOut {
+ 0%{ box-shadow: 0 0 0 10px @green-shadow; width: 40px; height: 40px; }
+ 60%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
+ 85%{ box-shadow: 0 0 0 0px @green-shadow; width: 75px; height: 75px; }
+ 100%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
+}
+
+@-webkit-keyframes bounceOut {
+ 0%{ box-shadow: 0 0 0 10px @green-shadow; width: 40px; height: 40px; }
+ 60%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
+ 85%{ box-shadow: 0 0 0 0px @green-shadow; width: 75px; height: 75px; }
+ 100%{ box-shadow: 0 0 0 0px @green-shadow; width: 60px; height: 60px; }
+}