Rule Chain UI: Context menu support.

This commit is contained in:
Igor Kulikov 2018-04-06 22:03:15 +03:00
parent c2b353f47e
commit 4eb08a6490
4 changed files with 155 additions and 28 deletions

View File

@ -1209,6 +1209,7 @@ export default angular.module('thingsboard.locale', [])
"rulenode-details": "Rule node details", "rulenode-details": "Rule node details",
"debug-mode": "Debug mode", "debug-mode": "Debug mode",
"configuration": "Configuration", "configuration": "Configuration",
"link": "Link",
"link-details": "Rule node link details", "link-details": "Rule node link details",
"add-link": "Add link", "add-link": "Add link",
"link-label": "Link label", "link-label": "Link label",

View File

@ -104,8 +104,89 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
vm.triggerResize = triggerResize; vm.triggerResize = triggerResize;
vm.openRuleChainContextMenu = openRuleChainContextMenu;
initHotKeys(); initHotKeys();
function openRuleChainContextMenu($event, $mdOpenMousepointMenu) {
if (vm.canvasControl.modelservice && !$event.ctrlKey && !$event.metaKey) {
var x = $event.clientX;
var y = $event.clientY;
var item = vm.canvasControl.modelservice.getItemInfoAtPoint(x, y);
vm.contextInfo = prepareContextMenu(item);
if (vm.contextInfo.items && vm.contextInfo.items.length > 0) {
vm.contextMenuEvent = $event;
$mdOpenMousepointMenu($event);
return false;
}
}
}
function prepareContextMenu(item) {
if (objectsSelected() || (!item.node && !item.edge)) {
return prepareRuleChainContextMenu();
} else if (item.node) {
return prepareRuleNodeContextMenu(item.node);
} else if (item.edge) {
return prepareEdgeContextMenu(item.edge);
}
}
function prepareRuleChainContextMenu() {
var contextInfo = {
title: vm.ruleChain.name,
subtitle: $translate.instant('rulechain.rulechain')
};
contextInfo.items = [];
return contextInfo;
}
function prepareRuleNodeContextMenu(node) {
var contextInfo = {
headerClass: node.nodeClass,
icon: node.icon,
title: node.name,
subtitle: node.component.name
};
contextInfo.items = [];
if (!node.readonly) {
contextInfo.items.push(
{
action: function () {
vm.canvasControl.modelservice.nodes.delete(node);
},
enabled: true,
value: "action.delete",
icon: "clear",
shortcut: "M-X"
}
);
}
return contextInfo;
}
function prepareEdgeContextMenu(edge) {
var contextInfo = {
headerClass: 'tb-link',
icon: 'trending_flat',
title: edge.label,
subtitle: $translate.instant('rulenode.link')
};
contextInfo.items = [];
contextInfo.items.push(
{
action: function () {
vm.canvasControl.modelservice.edges.delete(edge);
},
enabled: true,
value: "action.delete",
icon: "clear",
shortcut: "M-X"
}
);
return contextInfo;
}
function initHotKeys() { function initHotKeys() {
hotkeys.bindTo($scope) hotkeys.bindTo($scope)
.add({ .add({
@ -652,7 +733,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
} }
if (vm.canvasControl.adjustCanvasSize) { if (vm.canvasControl.adjustCanvasSize) {
vm.canvasControl.adjustCanvasSize(); vm.canvasControl.adjustCanvasSize(true);
} }
vm.isDirty = false; vm.isDirty = false;

View File

@ -105,12 +105,53 @@
} }
} }
#tb-rule-chain-context-menu {
padding-top: 0px;
border-radius: 8px;
.tb-context-menu-header {
padding: 8px 5px 5px;
font-size: 14px;
display: flex;
flex-direction: row;
&.tb-link {
background-color: #aac7e4;
}
md-icon {
padding-left: 2px;
padding-right: 10px;
}
.tb-context-menu-title {
font-weight: 500;
}
.tb-context-menu-subtitle {
}
}
}
.fc-canvas { .fc-canvas {
min-width: 100%; min-width: 100%;
min-height: 100%; min-height: 100%;
outline: none; outline: none;
} }
.tb-rule-node, #tb-rule-chain-context-menu .tb-context-menu-header {
&.tb-filter-type {
background-color: #f1e861;
}
&.tb-enrichment-type {
background-color: #cdf14e;
}
&.tb-transformation-type {
background-color: #79cef1;
}
&.tb-action-type {
background-color: #f1928f;
}
&.tb-rule-chain-type {
background-color: #d6c4f1;
}
}
.tb-rule-node { .tb-rule-node {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -139,21 +180,6 @@
background-color: #a3eaa9; background-color: #a3eaa9;
user-select: none; user-select: none;
} }
&.tb-filter-type {
background-color: #f1e861;
}
&.tb-enrichment-type {
background-color: #cdf14e;
}
&.tb-transformation-type {
background-color: #79cef1;
}
&.tb-action-type {
background-color: #f1928f;
}
&.tb-rule-chain-type {
background-color: #d6c4f1;
}
md-icon { md-icon {
font-size: 20px; font-size: 20px;
width: 20px; width: 20px;

View File

@ -99,18 +99,37 @@
</md-expansion-panel> </md-expansion-panel>
</md-expansion-panel-group> </md-expansion-panel-group>
</md-sidenav> </md-sidenav>
<div flex class="tb-rulechain-graph"> <md-menu flex style="position: relative;" md-position-mode="target target" tb-mousepoint-menu>
<fc-canvas id="tb-rulchain-canvas" <div class="tb-absolute-fill tb-rulechain-graph" ng-click="" tb-contextmenu="vm.openRuleChainContextMenu($event, $mdOpenMousepointMenu)">
model="vm.ruleChainModel" <fc-canvas id="tb-rulchain-canvas"
selected-objects="vm.selectedObjects" model="vm.ruleChainModel"
edge-style="curved" selected-objects="vm.selectedObjects"
node-width="170" edge-style="curved"
node-height="50" node-width="170"
automatic-resize="true" node-height="50"
control="vm.canvasControl" automatic-resize="true"
callbacks="vm.editCallbacks"> control="vm.canvasControl"
</fc-canvas> callbacks="vm.editCallbacks">
</div> </fc-canvas>
</div>
<md-menu-content id="tb-rule-chain-context-menu" width="4" ng-mouseleave="$mdCloseMousepointMenu()">
<div class="tb-context-menu-header {{vm.contextInfo.headerClass}}">
<md-icon aria-label="node-type-icon"
class="material-icons">{{vm.contextInfo.icon}}</md-icon>
<div flex>
<div class="tb-context-menu-title">{{vm.contextInfo.title}}</div>
<div class="tb-context-menu-subtitle">{{vm.contextInfo.subtitle}}</div>
</div>
</div>
<md-menu-item ng-repeat="item in vm.contextInfo.items">
<md-button ng-disabled="!item.enabled" ng-click="item.action(vm.contextMenuEvent)">
<md-icon ng-if="item.icon" md-menu-align-target aria-label="{{ item.value | translate }}" class="material-icons">{{item.icon}}</md-icon>
<span translate>{{item.value}}</span>
<span ng-if="item.shortcut" class="tb-alt-text"> {{ item.shortcut | keyboardShortcut }}</span>
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
</div> </div>
<tb-details-sidenav class="tb-rulenode-details-sidenav" <tb-details-sidenav class="tb-rulenode-details-sidenav"
header-title="{{vm.editingRuleNode.name}}" header-title="{{vm.editingRuleNode.name}}"