thingsboard-aplcache
Changes
ui/src/app/api/rule-chain.service.js 26(+15 -11)
ui/src/app/common/types.constant.js 23(+23 -0)
ui/src/app/locale/locale.constant.js 7(+7 -0)
ui/src/app/rulechain/link.directive.js 100(+94 -6)
ui/src/app/rulechain/link.scss 30(+30 -0)
ui/src/app/rulechain/link-fieldset.tpl.html 43(+41 -2)
ui/src/app/rulechain/rulechain.controller.js 86(+62 -24)
ui/src/app/rulechain/rulechain.scss 4(+4 -0)
ui/src/scss/main.scss 7(+7 -0)
ui/src/scss/mixins.scss 27(+26 -1)
Details
ui/src/app/api/rule-chain.service.js 26(+15 -11)
diff --git a/ui/src/app/api/rule-chain.service.js b/ui/src/app/api/rule-chain.service.js
index e7436de..186e31c 100644
--- a/ui/src/app/api/rule-chain.service.js
+++ b/ui/src/app/api/rule-chain.service.js
@@ -32,6 +32,7 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co
getRuleNodeComponents: getRuleNodeComponents,
getRuleNodeComponentByClazz: getRuleNodeComponentByClazz,
getRuleNodeSupportedLinks: getRuleNodeSupportedLinks,
+ ruleNodeAllowCustomLinks: ruleNodeAllowCustomLinks,
resolveTargetRuleChains: resolveTargetRuleChains,
testScript: testScript,
getLatestRuleNodeDebugInput: getLatestRuleNodeDebugInput
@@ -127,21 +128,21 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co
function getRuleNodeSupportedLinks(component) {
var relationTypes = component.configurationDescriptor.nodeDefinition.relationTypes;
- var customRelations = component.configurationDescriptor.nodeDefinition.customRelations;
- var linkLabels = [];
+ var linkLabels = {};
for (var i=0;i<relationTypes.length;i++) {
- linkLabels.push({
- name: relationTypes[i], custom: false
- });
- }
- if (customRelations) {
- linkLabels.push(
- { name: 'Custom', custom: true }
- );
+ var label = relationTypes[i];
+ linkLabels[label] = {
+ name: label,
+ value: label
+ };
}
return linkLabels;
}
+ function ruleNodeAllowCustomLinks(component) {
+ return component.configurationDescriptor.nodeDefinition.customRelations;
+ }
+
function getRuleNodeComponents() {
var deferred = $q.defer();
if (ruleNodeComponents) {
@@ -226,7 +227,10 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co
if (res && res.length) {
return res[0];
}
- return null;
+ var unknownComponent = angular.copy(types.unknownNodeComponent);
+ unknownComponent.clazz = clazz;
+ unknownComponent.configurationDescriptor.nodeDefinition.details = "Unknown Rule Node class: " + clazz;
+ return unknownComponent;
}
function resolveTargetRuleChains(ruleChainConnections) {
ui/src/app/common/types.constant.js 23(+23 -0)
diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js
index cf1023e..1aa7539 100644
--- a/ui/src/app/common/types.constant.js
+++ b/ui/src/app/common/types.constant.js
@@ -510,6 +510,22 @@ export default angular.module('thingsboard.types', [])
}
}
},
+ unknownNodeComponent: {
+ type: 'UNKNOWN',
+ name: 'unknown',
+ clazz: 'tb.internal.Unknown',
+ configurationDescriptor: {
+ nodeDefinition: {
+ description: "",
+ details: "",
+ inEnabled: true,
+ outEnabled: true,
+ relationTypes: [],
+ customRelations: false,
+ defaultConfiguration: {}
+ }
+ }
+ },
inputNodeComponent: {
type: 'INPUT',
name: 'Input',
@@ -565,6 +581,13 @@ export default angular.module('thingsboard.types', [])
nodeClass: "tb-input-type",
icon: "input",
special: true
+ },
+ UNKNOWN: {
+ value: "UNKNOWN",
+ name: "rulenode.type-unknown",
+ details: "rulenode.type-unknown-details",
+ nodeClass: "tb-unknown-type",
+ icon: "help_outline"
}
},
valueType: {
diff --git a/ui/src/app/device/device-card.tpl.html b/ui/src/app/device/device-card.tpl.html
index de8b7ee..fbda549 100644
--- a/ui/src/app/device/device-card.tpl.html
+++ b/ui/src/app/device/device-card.tpl.html
@@ -16,8 +16,8 @@
-->
<div flex layout="column" style="margin-top: -10px;">
- <div flex>{{vm.item.additionalInfo.description}}</div>
- <div flex style="text-transform: uppercase; padding-bottom: 10px;">{{vm.item.type}}</div>
- <div class="tb-small" ng-show="vm.isAssignedToCustomer()">{{'device.assignedToCustomer' | translate}} '{{vm.item.assignedCustomer.title}}'</div>
- <div class="tb-small" ng-show="vm.isPublic()">{{'device.public' | translate}}</div>
+ <div style="text-transform: uppercase; padding-bottom: 5px;">{{vm.item.type}}</div>
+ <div class="tb-card-description">{{vm.item.additionalInfo.description}}</div>
+ <div style="padding-top: 5px;" class="tb-small" ng-show="vm.isAssignedToCustomer()">{{'device.assignedToCustomer' | translate}} '{{vm.item.assignedCustomer.title}}'</div>
+ <div style="padding-top: 5px;" class="tb-small" ng-show="vm.isPublic()">{{'device.public' | translate}}</div>
</div>
ui/src/app/locale/locale.constant.js 7(+7 -0)
diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js
index 29f6f8e..4cf34f8 100644
--- a/ui/src/app/locale/locale.constant.js
+++ b/ui/src/app/locale/locale.constant.js
@@ -1157,6 +1157,11 @@ export default angular.module('thingsboard.locale', [])
"link-label-required": "Link label is required.",
"custom-link-label": "Custom link label",
"custom-link-label-required": "Custom link label is required.",
+ "link-labels": "Link labels",
+ "link-labels-required": "Link labels is required.",
+ "no-link-labels-found": "No link labels found",
+ "no-link-label-matching": "'{{label}}' not found.",
+ "create-new-link-label": "Create a new one!",
"type-filter": "Filter",
"type-filter-details": "Filter incoming messages with configured conditions",
"type-enrichment": "Enrichment",
@@ -1171,6 +1176,8 @@ export default angular.module('thingsboard.locale', [])
"type-rule-chain-details": "Forwards incoming messages to specified Rule Chain",
"type-input": "Input",
"type-input-details": "Logical input of Rule Chain, forwards incoming messages to next related Rule Node",
+ "type-unknown": "Unknown",
+ "type-unknown-details": "Unresolved Rule Node",
"directive-is-not-loaded": "Defined configuration directive '{{directiveName}}' is not available.",
"ui-resources-load-error": "Failed to load configuration ui resources.",
"invalid-target-rulechain": "Unable to resolve target rule chain!",
diff --git a/ui/src/app/rulechain/add-link.tpl.html b/ui/src/app/rulechain/add-link.tpl.html
index 0a21104..c5855b7 100644
--- a/ui/src/app/rulechain/add-link.tpl.html
+++ b/ui/src/app/rulechain/add-link.tpl.html
@@ -31,7 +31,7 @@
<span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span>
<md-dialog-content>
<div class="md-dialog-content">
- <tb-rule-node-link link="vm.link" labels="vm.labels" is-edit="true" the-form="theForm"></tb-rule-node-link>
+ <tb-rule-node-link ng-model="vm.link" allowed-labels="vm.labels" is-edit="true" allow-custom="vm.allowCustomLabels"></tb-rule-node-link>
</div>
</md-dialog-content>
<md-dialog-actions layout="row">
ui/src/app/rulechain/link.directive.js 100(+94 -6)
diff --git a/ui/src/app/rulechain/link.directive.js b/ui/src/app/rulechain/link.directive.js
index b3565a3..dd43821 100644
--- a/ui/src/app/rulechain/link.directive.js
+++ b/ui/src/app/rulechain/link.directive.js
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+import './link.scss';
+
/* eslint-disable import/no-unresolved, import/default */
import linkFieldsetTemplate from './link-fieldset.tpl.html';
@@ -22,13 +24,18 @@ import linkFieldsetTemplate from './link-fieldset.tpl.html';
/*@ngInject*/
export default function LinkDirective($compile, $templateCache, $filter) {
- var linker = function (scope, element) {
+ var linker = function (scope, element, attrs, ngModelCtrl) {
var template = $templateCache.get(linkFieldsetTemplate);
element.html(template);
scope.selectedLabel = null;
+ scope.labelSearchText = null;
+
+ scope.ngModelCtrl = ngModelCtrl;
+
+ var labelsList = [];
- scope.$watch('link', function() {
+ /*scope.$watch('link', function() {
scope.selectedLabel = null;
if (scope.link && scope.labels) {
if (scope.link.label) {
@@ -53,19 +60,100 @@ export default function LinkDirective($compile, $templateCache, $filter) {
scope.link.label = "";
}
}
+ };*/
+
+ scope.transformLinkLabelChip = function (chip) {
+ var res = $filter('filter')(labelsList, {name: chip}, true);
+ var result;
+ if (res && res.length) {
+ result = angular.copy(res[0]);
+ } else {
+ result = {
+ name: chip,
+ value: chip
+ };
+ }
+ return result;
+ };
+
+ scope.labelsSearch = function (searchText) {
+ var labels = searchText ? $filter('filter')(labelsList, {name: searchText}) : labelsList;
+ return labels.map((label) => label.name);
+ };
+
+ scope.createLinkLabel = function (event, chipsId) {
+ var chipsChild = angular.element(chipsId, element)[0].firstElementChild;
+ var el = angular.element(chipsChild);
+ var chipBuffer = el.scope().$mdChipsCtrl.getChipBuffer();
+ event.preventDefault();
+ event.stopPropagation();
+ el.scope().$mdChipsCtrl.appendChip(chipBuffer.trim());
+ el.scope().$mdChipsCtrl.resetChipBuffer();
};
+
+ ngModelCtrl.$render = function () {
+ labelsList.length = 0;
+ for (var label in scope.allowedLabels) {
+ var linkLabel = {
+ name: scope.allowedLabels[label].name,
+ value: scope.allowedLabels[label].value
+ };
+ labelsList.push(linkLabel);
+ }
+
+ var link = ngModelCtrl.$viewValue;
+ var labels = [];
+ if (link && link.labels) {
+ for (var i = 0; i < link.labels.length; i++) {
+ label = link.labels[i];
+ if (scope.allowedLabels[label]) {
+ labels.push(angular.copy(scope.allowedLabels[label]));
+ } else {
+ labels.push({
+ name: label,
+ value: label
+ });
+ }
+ }
+ }
+ scope.labels = labels;
+ scope.$watch('labels', function (newVal, prevVal) {
+ if (!angular.equals(newVal, prevVal)) {
+ updateLabels();
+ }
+ }, true);
+ };
+
+ function updateLabels() {
+ if (ngModelCtrl.$viewValue) {
+ var labels = [];
+ for (var i = 0; i < scope.labels.length; i++) {
+ labels.push(scope.labels[i].value);
+ }
+ ngModelCtrl.$viewValue.labels = labels;
+ ngModelCtrl.$viewValue.label = labels.join(' / ');
+ updateValidity();
+ }
+ }
+
+ function updateValidity() {
+ var valid = ngModelCtrl.$viewValue.labels &&
+ ngModelCtrl.$viewValue.labels.length ? true : false;
+ ngModelCtrl.$setValidity('linkLabels', valid);
+ }
+
$compile(element.contents())(scope);
}
return {
restrict: "E",
+ require: "^ngModel",
link: linker,
scope: {
- link: '=',
- labels: '=',
+ allowedLabels: '=',
+ allowCustom: '=',
isEdit: '=',
- isReadOnly: '=',
- theForm: '='
+ isReadOnly: '='
}
};
}
ui/src/app/rulechain/link.scss 30(+30 -0)
diff --git a/ui/src/app/rulechain/link.scss b/ui/src/app/rulechain/link.scss
new file mode 100644
index 0000000..3e86619
--- /dev/null
+++ b/ui/src/app/rulechain/link.scss
@@ -0,0 +1,30 @@
+/**
+ * Copyright © 2016-2018 The Thingsboard Authors
+ *
+ * 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.
+ */
+
+.tb-link-label-autocomplete {
+ .tb-not-found {
+ display: block;
+ line-height: 1.5;
+ height: 48px;
+ .tb-no-entries {
+ line-height: 48px;
+ }
+ }
+ li {
+ height: auto !important;
+ white-space: normal !important;
+ }
+}
ui/src/app/rulechain/link-fieldset.tpl.html 43(+41 -2)
diff --git a/ui/src/app/rulechain/link-fieldset.tpl.html b/ui/src/app/rulechain/link-fieldset.tpl.html
index 13ec6c3..3dbe33f 100644
--- a/ui/src/app/rulechain/link-fieldset.tpl.html
+++ b/ui/src/app/rulechain/link-fieldset.tpl.html
@@ -17,7 +17,46 @@
-->
<md-content class="md-padding tb-link" layout="column">
<fieldset ng-disabled="$root.loading || !isEdit || isReadOnly">
- <md-input-container class="md-block">
+ <label translate class="tb-title no-padding" ng-class="{'tb-required': required}">rulenode.link-labels</label>
+ <md-chips id="link_label_chips"
+ ng-required="true"
+ readonly="$root.loading || !isEdit || isReadOnly"
+ ng-model="labels" md-autocomplete-snap
+ md-transform-chip="transformLinkLabelChip($chip)"
+ md-require-match="!allowCustom">
+ <md-autocomplete
+ id="link_label"
+ md-no-cache="true"
+ md-selected-item="selectedLabel"
+ md-search-text="labelSearchText"
+ md-items="item in labelsSearch(labelSearchText)"
+ md-item-text="item.name"
+ md-min-length="0"
+ placeholder="{{'rulenode.link-label' | translate }}"
+ md-menu-class="tb-link-label-autocomplete">
+ <span md-highlight-text="labelSearchText" md-highlight-flags="^i">{{item}}</span>
+ <md-not-found>
+ <div class="tb-not-found">
+ <div class="tb-no-entries" ng-if="!labelSearchText || !labelSearchText.length">
+ <span translate>rulenode.no-link-labels-found</span>
+ </div>
+ <div ng-if="labelSearchText && labelSearchText.length">
+ <span translate translate-values='{ label: "{{labelSearchText | truncate:true:6:'...'}}" }'>rulenode.no-link-label-matching</span>
+ <span ng-if="allowCustom">
+ <a translate ng-click="createLinkLabel($event, '#link_label_chips')">rulenode.create-new-link-label</a>
+ </span>
+ </div>
+ </div>
+ </md-not-found>
+ </md-autocomplete>
+ <md-chip-template>
+ <span>{{$chip.name}}</span>
+ </md-chip-template>
+ </md-chips>
+ <div class="tb-error-messages" ng-messages="ngModelCtrl.$error" role="alert">
+ <div translate ng-message="linkLabels" class="tb-error-message">rulenode.link-labels-required</div>
+ </div>
+ <!--md-input-container class="md-block">
<label translate>rulenode.link-label</label>
<md-select ng-model="selectedLabel" ng-change="selectedLabelChanged()">
<md-option ng-repeat="label in labels" ng-value="label">
@@ -34,6 +73,6 @@
<div ng-messages="theForm.customLinkLabel.$error">
<div translate ng-message="required">rulenode.custom-link-label-required</div>
</div>
- </md-input-container>
+ </md-input-container-->
</fieldset>
</md-content>
ui/src/app/rulechain/rulechain.controller.js 86(+62 -24)
diff --git a/ui/src/app/rulechain/rulechain.controller.js b/ui/src/app/rulechain/rulechain.controller.js
index dfd1a97..a38f8a8 100644
--- a/ui/src/app/rulechain/rulechain.controller.js
+++ b/ui/src/app/rulechain/rulechain.controller.js
@@ -669,11 +669,15 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
}
} else {
if (edge.label) {
+ if (!edge.labels) {
+ edge.labels = edge.label.split(' / ');
+ }
deferred.resolve(edge);
} else {
var labels = ruleChainService.getRuleNodeSupportedLinks(sourceNode.component);
+ var allowCustomLabels = ruleChainService.ruleNodeAllowCustomLinks(sourceNode.component);
vm.enableHotKeys = false;
- addRuleNodeLink(event, edge, labels).then(
+ addRuleNodeLink(event, edge, labels, allowCustomLabels).then(
(link) => {
deferred.resolve(link);
vm.enableHotKeys = true;
@@ -713,6 +717,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
vm.isEditingRuleNode = false;
vm.editingRuleNode = null;
vm.editingRuleNodeLinkLabels = ruleChainService.getRuleNodeSupportedLinks(sourceNode.component);
+ vm.editingRuleNodeAllowCustomLabels = ruleChainService.ruleNodeAllowCustomLinks(sourceNode.component);
vm.isEditingRuleNodeLink = true;
vm.editingRuleNodeLinkIndex = vm.ruleChainModel.edges.indexOf(edge);
vm.editingRuleNodeLink = angular.copy(edge);
@@ -744,7 +749,8 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
isInputSource: isInputSource,
fromIndex: fromIndex,
toIndex: toIndex,
- label: edge.label
+ label: edge.label,
+ labels: edge.labels
};
connections.push(connection);
}
@@ -816,7 +822,8 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
var edge = {
source: source,
destination: destination,
- label: connection.label
+ label: connection.label,
+ labels: connection.labels
};
vm.ruleChainModel.edges.push(edge);
vm.modelservice.edges.select(edge);
@@ -1024,6 +1031,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
}
if (vm.ruleChainMetaData.connections) {
+ var edgeMap = {};
for (i = 0; i < vm.ruleChainMetaData.connections.length; i++) {
var connection = vm.ruleChainMetaData.connections[i];
var sourceNode = nodes[connection.fromIndex];
@@ -1032,12 +1040,23 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
var sourceConnectors = vm.modelservice.nodes.getConnectorsByType(sourceNode, flowchartConstants.rightConnectorType);
var destConnectors = vm.modelservice.nodes.getConnectorsByType(destNode, flowchartConstants.leftConnectorType);
if (sourceConnectors && sourceConnectors.length && destConnectors && destConnectors.length) {
- edge = {
- source: sourceConnectors[0].id,
- destination: destConnectors[0].id,
- label: connection.type
- };
- vm.ruleChainModel.edges.push(edge);
+ var sourceId = sourceConnectors[0].id;
+ var destId = destConnectors[0].id;
+ var edgeKey = sourceId + '_' + destId;
+ edge = edgeMap[edgeKey];
+ if (!edge) {
+ edge = {
+ source: sourceId,
+ destination: destId,
+ label: connection.type,
+ labels: [connection.type]
+ };
+ edgeMap[edgeKey] = edge;
+ vm.ruleChainModel.edges.push(edge);
+ } else {
+ edge.label += ' / ' +connection.type;
+ edge.labels.push(connection.type);
+ }
}
}
}
@@ -1045,6 +1064,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
if (vm.ruleChainMetaData.ruleChainConnections) {
var ruleChainNodesMap = {};
+ var ruleChainEdgeMap = {};
for (i = 0; i < vm.ruleChainMetaData.ruleChainConnections.length; i++) {
var ruleChainConnection = vm.ruleChainMetaData.ruleChainConnections[i];
var ruleChain = ruleChainsMap[ruleChainConnection.targetRuleChainId.id];
@@ -1081,12 +1101,23 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
if (sourceNode) {
connectors = vm.modelservice.nodes.getConnectorsByType(sourceNode, flowchartConstants.rightConnectorType);
if (connectors && connectors.length) {
- var ruleChainEdge = {
- source: connectors[0].id,
- destination: ruleChainNode.connectors[0].id,
- label: ruleChainConnection.type
- };
- vm.ruleChainModel.edges.push(ruleChainEdge);
+ sourceId = connectors[0].id;
+ destId = ruleChainNode.connectors[0].id;
+ edgeKey = sourceId + '_' + destId;
+ var ruleChainEdge = ruleChainEdgeMap[edgeKey];
+ if (!ruleChainEdge) {
+ ruleChainEdge = {
+ source: sourceId,
+ destination: destId,
+ label: ruleChainConnection.type,
+ labels: [ruleChainConnection.type]
+ };
+ ruleChainEdgeMap[edgeKey] = ruleChainEdge;
+ vm.ruleChainModel.edges.push(ruleChainEdge);
+ } else {
+ ruleChainEdge.label += ' / ' +ruleChainConnection.type;
+ ruleChainEdge.labels.push(ruleChainConnection.type);
+ }
}
}
}
@@ -1199,8 +1230,7 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
var ruleChainConnection = {
fromIndex: fromIndex,
targetRuleChainId: {entityType: vm.types.entityType.rulechain, id: destNode.targetRuleChainId},
- additionalInfo: destNode.additionalInfo,
- type: edge.label
+ additionalInfo: destNode.additionalInfo
};
if (!ruleChainConnection.additionalInfo) {
ruleChainConnection.additionalInfo = {};
@@ -1208,15 +1238,22 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
ruleChainConnection.additionalInfo.layoutX = Math.round(destNode.x);
ruleChainConnection.additionalInfo.layoutY = Math.round(destNode.y);
ruleChainConnection.additionalInfo.ruleChainNodeId = destNode.id;
- ruleChainMetaData.ruleChainConnections.push(ruleChainConnection);
+ for (var rcIndex=0;rcIndex<edge.labels.length;rcIndex++) {
+ var newRuleChainConnection = angular.copy(ruleChainConnection);
+ newRuleChainConnection.type = edge.labels[rcIndex];
+ ruleChainMetaData.ruleChainConnections.push(newRuleChainConnection);
+ }
} else {
var toIndex = nodes.indexOf(destNode);
var nodeConnection = {
fromIndex: fromIndex,
- toIndex: toIndex,
- type: edge.label
+ toIndex: toIndex
};
- ruleChainMetaData.connections.push(nodeConnection);
+ for (var cIndex=0;cIndex<edge.labels.length;cIndex++) {
+ var newNodeConnection = angular.copy(nodeConnection);
+ newNodeConnection.type = edge.labels[cIndex];
+ ruleChainMetaData.connections.push(newNodeConnection);
+ }
}
}
}
@@ -1285,13 +1322,13 @@ export function RuleChainController($state, $scope, $compile, $q, $mdUtil, $time
});
}
- function addRuleNodeLink($event, link, labels) {
+ function addRuleNodeLink($event, link, labels, allowCustomLabels) {
return $mdDialog.show({
controller: 'AddRuleNodeLinkController',
controllerAs: 'vm',
templateUrl: addRuleNodeLinkTemplate,
parent: angular.element($document[0].body),
- locals: {link: link, labels: labels},
+ locals: {link: link, labels: labels, allowCustomLabels: allowCustomLabels},
fullscreen: true,
targetEvent: $event
});
@@ -1335,13 +1372,14 @@ export function AddRuleNodeController($scope, $mdDialog, ruleNode, ruleChainId,
}
/*@ngInject*/
-export function AddRuleNodeLinkController($scope, $mdDialog, link, labels, helpLinks) {
+export function AddRuleNodeLinkController($scope, $mdDialog, link, labels, allowCustomLabels, helpLinks) {
var vm = this;
vm.helpLinks = helpLinks;
vm.link = link;
vm.labels = labels;
+ vm.allowCustomLabels = allowCustomLabels;
vm.add = add;
vm.cancel = cancel;
ui/src/app/rulechain/rulechain.scss 4(+4 -0)
diff --git a/ui/src/app/rulechain/rulechain.scss b/ui/src/app/rulechain/rulechain.scss
index c51a955..5999b7e 100644
--- a/ui/src/app/rulechain/rulechain.scss
+++ b/ui/src/app/rulechain/rulechain.scss
@@ -170,6 +170,9 @@
&.tb-rule-chain-type {
background-color: #d6c4f1;
}
+ &.tb-unknown-type {
+ background-color: #f16c29;
+ }
}
.tb-rule-node {
@@ -202,6 +205,7 @@
background-color: #a3eaa9;
user-select: none;
}
+
md-icon {
font-size: 20px;
width: 20px;
diff --git a/ui/src/app/rulechain/rulechain.tpl.html b/ui/src/app/rulechain/rulechain.tpl.html
index a84df90..9c77ae4 100644
--- a/ui/src/app/rulechain/rulechain.tpl.html
+++ b/ui/src/app/rulechain/rulechain.tpl.html
@@ -207,11 +207,11 @@
</details-buttons>
<form name="vm.ruleNodeLinkForm" ng-if="vm.isEditingRuleNodeLink">
<tb-rule-node-link
- link="vm.editingRuleNodeLink"
- labels="vm.editingRuleNodeLinkLabels"
+ ng-model="vm.editingRuleNodeLink"
+ allowed-labels="vm.editingRuleNodeLinkLabels"
+ allow-custom="vm.editingRuleNodeAllowCustomLabels"
is-edit="true"
- is-read-only="false"
- the-form="vm.ruleNodeLinkForm">
+ is-read-only="false">
</tb-rule-node-link>
</form>
</tb-details-sidenav>
ui/src/scss/main.scss 7(+7 -0)
diff --git a/ui/src/scss/main.scss b/ui/src/scss/main.scss
index 8fed892..2852a7b 100644
--- a/ui/src/scss/main.scss
+++ b/ui/src/scss/main.scss
@@ -16,6 +16,7 @@
@import "~compass-sass-mixins/lib/compass";
@import "constants";
@import "animations";
+@import "mixins";
@import "fonts";
/***************
@@ -437,6 +438,12 @@ pre.tb-highlight {
}
}
+.tb-card-description {
+ color: rgba(0,0,0,0.54);
+ font-size: 13px;
+ @include line-clamp(2, 1.1);
+}
+
/***********************
* Flow
***********************/
ui/src/scss/mixins.scss 27(+26 -1)
diff --git a/ui/src/scss/mixins.scss b/ui/src/scss/mixins.scss
index 9e8b7df..cb66171 100644
--- a/ui/src/scss/mixins.scss
+++ b/ui/src/scss/mixins.scss
@@ -31,4 +31,29 @@
&:-ms-input-placeholder {
@content;
}
-}
\ No newline at end of file
+}
+
+@mixin line-clamp($numLines: 1, $lineHeight: 1.412) {
+ overflow: hidden;
+ position: relative;
+ line-height: $lineHeight;
+ text-align: justify;
+ margin-right: -1em;
+ padding-right: 2em;
+ max-height: ($numLines*$lineHeight)+em;
+ &:before {
+ content: '...';
+ position: absolute;
+ right: 1em;
+ bottom: 0;
+ }
+ &:after {
+ content: '';
+ position: absolute;
+ right: 1em;
+ width: 1em;
+ height: 1em;
+ margin-top: 0.2em;
+ background: white;
+ }
+}