Initial setup of mycontroller

This commit is contained in:
2019-11-28 09:16:11 -06:00
parent 62d71e30c1
commit 665eb783be
504 changed files with 212034 additions and 0 deletions

View File

@@ -0,0 +1,159 @@
/*
* Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
// don't forget to declare this service module as a dependency in your main app constructor!
//http://js2.coffee/#coffee2js
//https://coderwall.com/p/r_bvhg/angular-ui-bootstrap-alert-service-for-angular-js
'use strict';
angular.module('adf.widget.myc-a-sensor-graph', [])
.config(function(dashboardProvider){
dashboardProvider
.widget('mycSingleSensorGraph', {
title: 'A sensor graphical view',
description: 'Displays a sensor graphical view',
templateUrl: 'controllers/adf-widgets/adf-myc-asg/view.html?mcv=29',
controller: 'mycSingleSensorGraphController',
controllerAs: 'mycSingleSensorGraph',
config: {
variableId:null,
withMinMax:false,
chartFromTimestamp:'3600000',
refreshTime:30,
marginTop:5,
marginRight:20,
marginBottom:60,
marginLeft:65,
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-asg/edit.html?mcv=29',
controller: 'mycSingleSensorGraphEditController',
controllerAs: 'mycSingleSensorGraphEdit',
}
});
})
.controller('mycSingleSensorGraphController', function($scope, $interval, config, mchelper, $filter, MetricsFactory, TypesFactory, CommonServices){
var mycSingleSensorGraph = this;
mycSingleSensorGraph.showLoading = true;
mycSingleSensorGraph.showError = false;
mycSingleSensorGraph.isSyncing = false;
mycSingleSensorGraph.variables = {};
$scope.tooltipEnabled = false;
$scope.hideVariableName=true;
$scope.cs = CommonServices;
CommonServices.updateGraphMarginDefault(config);
mycSingleSensorGraph.chartOptions = {
chart: {
type: 'lineChart',
noErrorCheck: true,
height: 225,
margin : {
top: config.marginTop,
right: config.marginRight,
bottom: config.marginBottom,
left: config.marginLeft,
},
color: ["#2ca02c","#1f77b4", "#ff7f0e"],
noData:"No data available.",
x: function(d){return d[0];},
y: function(d){return d[1];},
useVoronoi: false,
clipEdge: false,
useInteractiveGuideline: true,
xAxis: {
showMaxMin: false,
tickFormat: function(d) {
return d3.time.format('hh:mm a')(new Date(d))
},
//axisLabel: 'Timestamp',
rotateLabels: -20
},
yAxis: {
tickFormat: function(d){
return d3.format(',.2f')(d);
},
axisLabelDistance: -10,
//axisLabel: ''
},
},
title: {
enable: false,
text: 'Title'
}
};
mycSingleSensorGraph.chartTimeFormat = mchelper.cfg.dateFormat;
mycSingleSensorGraph.chartOptions.chart.xAxis.tickFormat = function(d) {return $filter('date')(d, mycSingleSensorGraph.chartTimeFormat, mchelper.cfg.timezone)};
function updateChart(){
mycSingleSensorGraph.isSyncing = true;
MetricsFactory.getMetricsData({"variableId":config.variableId, "withMinMax":config.withMinMax, "start": new Date().getTime() - config.chartFromTimestamp}, function(resource){
if(resource.length > 0){
mycSingleSensorGraph.chartData = resource[0].chartData;
//Update display time format
mycSingleSensorGraph.chartTimeFormat = resource[0].timeFormat;
mycSingleSensorGraph.chartOptions.chart.type = resource[0].chartType;
mycSingleSensorGraph.chartOptions.chart.interpolate = resource[0].chartInterpolate;
if(resource[0].dataType === 'Double'){
mycSingleSensorGraph.chartOptions.chart.yAxis.tickFormat = function(d){return d3.format('.02f')(d) + ' ' + resource[0].unit};
}else if(resource[0].dataType === 'Binary' || resource[0].dataType === 'Counter'){
mycSingleSensorGraph.chartOptions.chart.yAxis.tickFormat = function(d){return d3.format('.0f')(d)};
}
mycSingleSensorGraph.chartOptions.title.text = resource[0].variableType;
mycSingleSensorGraph.resourceName = resource[0].resourceName;
mycSingleSensorGraph.internalId = resource[0].internalId;
}else{
if(config.variableId !== null){
mycSingleSensorGraph.showError = true;
}
}
mycSingleSensorGraph.isSyncing = false;
if(mycSingleSensorGraph.showLoading){
mycSingleSensorGraph.showLoading = false;
}
});
}
function updateVariables(){
if(mycSingleSensorGraph.isSyncing){
return;
}else if(config.variableId !== null){
updateChart();
}else{
mycSingleSensorGraph.showLoading = false;
}
}
//load graph initially
updateVariables();
// refresh every second
var promise = $interval(updateVariables, config.refreshTime*1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function(){
$interval.cancel(promise);
});
}).controller('mycSingleSensorGraphEditController', function($scope, $interval, config, mchelper, $filter, TypesFactory, CommonServices){
var mycSingleSensorGraphEdit = this;
mycSingleSensorGraphEdit.variables = TypesFactory.getSensorVariables({"metricType":["Double","Binary","Counter"]});
mycSingleSensorGraphEdit.cs = CommonServices;
});

View File

@@ -0,0 +1,88 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'REFRESH_TIME_SECONDS' | translate}}" ng-model="config.refreshTime" pf-validation="mycSingleSensorGraphEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<input ng-model="config.withMinMax" type="checkbox"/>
<label class="control-label">{{ 'ENABLE_MIN_MAX' | translate }}</label>
</div>
<div class="form-group">
<label>{{ 'MARGIN' | translate }}</label>
<table class="adf-table">
<tr>
<td>
<label>{{ 'LEFT' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="left" placeholder="{{'LEFT' | translate}}" ng-model="config.marginLeft" pf-validation="mycSingleSensorGraphEdit.cs.isNumber(input)" required>
</td>
<td>
<label class="mc-margin-right">{{ 'RIGHT' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="right" placeholder="{{'RIGHT' | translate}}" ng-model="config.marginRight" pf-validation="mycSingleSensorGraphEdit.cs.isNumber(input)" required>
</td>
</tr>
<tr>
<td>
<label>{{ 'TOP' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="top" placeholder="{{'TOP' | translate}}" ng-model="config.marginTop" pf-validation="mycSingleSensorGraphEdit.cs.isNumber(input)" required>
</td>
<td>
<label>{{ 'BOTTOM' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="bottom" placeholder="{{'BOTTOM' | translate}}" ng-model="config.marginBottom" pf-validation="mycSingleSensorGraphEdit.cs.isNumber(input)" required>
</td>
</tr>
</table>
</div>
<div class="form-group">
<label>{{ 'TIME_RANGE' | translate }}</label>
<select id="panelSize" class="form-control" pf-select ng-model="config.chartFromTimestamp">
<option value="" ng-hide="true"></option>
<option value="300000">{{ 'LAST_5_MINUTES' | translate }}</option>
<option value="3600000">{{ 'LAST_HOUR' | translate }}</option>
<option value="21600000">{{ 'LAST_6_HOURS' | translate }}</option>
<option value="43200000">{{ 'LAST_12_HOURS' | translate }}</option>
<option value="86400000">{{ 'LAST_DAY' | translate }}</option>
<option value="604800000">{{ 'LAST_WEEK' | translate }}</option>
<option value="2419200000">{{ 'LAST_MONTH' | translate }}</option>
<option value="31536000000">{{ 'LAST_YEAR' | translate }}</option>
</select>
</div>
<div class="form-group">
<label>{{ 'SENSOR_VARIABLE' | translate }}</label>
<select id="senVars" class="form-control" pf-select data-live-search="true" ng-model="config.variableId">
<option value="" ng-hide="true"></option>
<option ng-repeat="res in mycSingleSensorGraphEdit.variables" ng-bind-html="res.displayName | mcResourceRepresentation" value="{{res.id}}" ng-selected="config.variableId == res.id"></option>
</select>
</div>
</form>

View File

@@ -0,0 +1,32 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- Loading icon disaplay -->
<div ng-if="mycSingleSensorGraph.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-if="mycSingleSensorGraph.showError">
<div ng-include src="'partials/common-html/error-sm.html'"></div>
</div>
<div ng-if="!(mycSingleSensorGraph.showLoading || mycSingleSensorGraph.showError)">
<span class="mc-pointer" ng-bind-html="mycSingleSensorGraph.resourceName | mcResourceRepresentation" ui-sref="sensorsDetail({id:mycSingleSensorGraph.internalId})"></span>
<nvd3 id="asg-{{config.variableId}}" options='mycSingleSensorGraph.chartOptions' data="mycSingleSensorGraph.chartData"></nvd3>
<div ng-if="config.variableId === null" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>
</div>

View File

@@ -0,0 +1,106 @@
/*
* Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
// don't forget to declare this service module as a dependency in your main app constructor!
//http://js2.coffee/#coffee2js
//https://coderwall.com/p/r_bvhg/angular-ui-bootstrap-alert-service-for-angular-js
'use strict';
angular.module('adf.widget.myc-custom-buttons', [])
.config(function(dashboardProvider){
dashboardProvider
.widget('mycCustomBtns', {
title: 'Sensor custom buttons',
description: 'Create custom buttons',
templateUrl: 'controllers/adf-widgets/adf-myc-cb/view.html?mcv=29',
controller: 'mycCusBtnsController',
controllerAs: 'mycCBtns',
config: {
variableId:null,
refreshTime:30,
minBtnHeight:30,
minBtnWidth:90,
buttonsJson:"[\n]",
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-cb/edit.html?mcv=29',
controller: 'mycSenVarsEditController',
controllerAs: 'mycCBtnsEdit',
}
});
})
.controller('mycCusBtnsController', function($scope, $interval, config, mchelper, $filter, SensorsFactory, TypesFactory, CommonServices){
var mycCBtns = this;
mycCBtns.showLoading = true;
mycCBtns.isSyncing = true;
mycCBtns.variable = {};
$scope.tooltipEnabled = false;
$scope.hideVariableName=true;
$scope.cs = CommonServices;
mycCBtns.buttons = angular.fromJson(config.buttonsJson);
function loadVariable(){
mycCBtns.isSyncing = true;
SensorsFactory.getVariables({'ids':config.variableId}, function(response){
if(response.length > 0){
mycCBtns.variable = response[0];
}
mycCBtns.isSyncing = false;
if(mycCBtns.showLoading){
mycCBtns.showLoading = false;
}
});
};
function updateVariable(){
if(mycCBtns.isSyncing){
return;
}else if(config.variableId){
loadVariable();
}
}
//load variables initially
loadVariable();
//updateVariables();
//Update Variable / Send Payload
$scope.updateSVariable = function(button){
var variable = angular.copy(mycCBtns.variable);
variable.value = button.payload;
SensorsFactory.updateVariable(variable, function(){
//update Success
loadVariable();
},function(error){
displayRestError.display(error);
});
};
// refresh every second
var promise = $interval(updateVariable, config.refreshTime*1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function(){
$interval.cancel(promise);
});
}).controller('mycCusBtnsEditController', function($scope, $interval, config, mchelper, $filter, TypesFactory, CommonServices){
var mycCBtnsEdit = this;
mycCBtnsEdit.cs = CommonServices;
mycCBtnsEdit.variables = TypesFactory.getSensorVariables();
});

View File

@@ -0,0 +1,49 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'REFRESH_TIME_SECONDS' | translate}}" ng-model="config.refreshTime" pf-validation="mycCBtnsEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<label>{{ 'SENSOR_VARIABLE' | translate }}</label>
<select id="mycCBtns" class="form-control" pf-select data-live-search="true" ng-model="config.variableId" required>
<option value="" ng-hide="true"></option>
<option ng-repeat="res in mycCBtnsEdit.variables" ng-bind-html="res.displayName | mcResourceRepresentation" value="{{res.id}}" ng-selected="res.id.toString().indexOf(config.variableId) != -1"></option>
</select>
</div>
<legend><small>{{ 'BUTTON_SETTINGS' | translate }}</small></legend>
<div class="form-group">
<label class="mc-margin-right">{{ 'MINIMUM_HEIGHT' | translate }}</label>
<input type="text" id="height-min" class="mc-margin-right" placeholder="{{'MINIMUM_HEIGHT' | translate}}" ng-model="config.minBtnHeight" pf-validation="mycCBtnsEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
<label class="mc-margin-right">{{ 'MINIMUM_WIDTH' | translate }}</label>
<input type="text" id="width-min" placeholder="{{'MINIMUM_WIDTH' | translate}}" ng-model="config.minBtnWidth" pf-validation="mycCBtnsEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<label>{{ 'JSON' | translate }}</label>
<textarea class="form-control" rows="12" style="resize:none" ng-model="config.buttonsJson" required ></textarea>
</div>
</form>

View File

@@ -0,0 +1,36 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- Loading icon disaplay -->
<div ng-show="mycCBtns.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-hide="mycCBtns.showLoading">
<div ng-if="config.variableId" >
<span><span ng-bind-html="mycCBtns.variable.resourceName | mcResourceRepresentation"></span> <span class="badge">{{mycCBtns.variable.value}} {{mycCBtns.variable.unit}}</span></span>
<hr class="adf-myc-cb-margin">
<div id="custom-buttons-wrapper" class="row-fluid">
<button ng-repeat="button in mycCBtns.buttons track by $index" ng-click="updateSVariable(button)" class="btn"
ng-class="button.btnType ? 'btn-{{button.btnType}}' : 'btn-default'"
ng-style="{'min-width':'{{config.minBtnWidth}}px', 'min-height':'{{config.minBtnHeight}}px'}"
ng-bind-html="button.name"></button>
</div>
</div>
<!-- display no items configured -->
<div ng-if="!config.variableId" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>
</div>

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
'use strict';
angular.module('adf.widget.myc-custom-widget', [])
.config(function(dashboardProvider){
dashboardProvider
.widget('mycCustomWidget', {
title: 'Custom widget',
description: 'Make your own widget with script and template',
templateUrl: 'controllers/adf-widgets/adf-myc-cw/view.html?mcv=29',
controller: 'mycCustomWidgetController',
controllerAs: 'mycCustomWidget',
config: {
script: null,
template: null,
refreshTime:-1,
bindings: '{}',
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-cw/edit.html?mcv=29',
controller: 'mycCustomWidgetEditController',
controllerAs: 'mycCustomWidgetEdit',
}
});
})
.controller('mycCustomWidgetController', function($scope, $interval, config, TemplatesFactory, $sce, mchelper, CommonServices){
var mycCustomWidget = this;
mycCustomWidget.showLoading = true;
mycCustomWidget.isSyncing = false;
mycCustomWidget.htmlData = null;
mycCustomWidget.trustedHtml = "";
$scope.mchelper = mchelper;
$scope.cs = CommonServices;
function updateState(){
mycCustomWidget.dataAvailable = true;
mycCustomWidget.isSyncing = false;
if(mycCustomWidget.showLoading){
mycCustomWidget.showLoading = false;
}
};
function loadData(){
mycCustomWidget.isSyncing = true;
TemplatesFactory.getHtml({'template':config.template, 'script':config.script, 'scriptBindings':JSON.stringify(eval('('+config.bindings+')'))}, function(response){
mycCustomWidget.htmlData = response.message;
mycCustomWidget.trustedHtml = $sce.trustAsHtml(response.message);
updateState();
},function(error){
mycCustomWidget.htmlData = '<pre>'+error.data.errorMessage+'</pre>';
updateState();
});
};
function updateData(){
if(mycCustomWidget.isSyncing){
return;
}else if(config.template !== null){
loadData();
}
}
//load variables initially
if(config.dataKey !== null){
updateData();
}else{
mycCustomWidget.showLoading = false;
}
// refresh every second, if config.refreshTime has positive value
if(config.refreshTime > 0){
var promise = $interval(updateData, config.refreshTime*1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function(){
$interval.cancel(promise);
});
}
}).controller('mycCustomWidgetEditController', function($scope, $interval, config, TypesFactory, ScriptsFactory, TemplatesFactory, CommonServices){
var mycCustomWidgetEdit = this;
mycCustomWidgetEdit.cs = CommonServices;
// load variables at startup
mycCustomWidgetEdit.scripts = ScriptsFactory.getAllLessInfo({"type":"Operation"});
mycCustomWidgetEdit.templates = TemplatesFactory.getAllLessInfo();
});

View File

@@ -0,0 +1,46 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'REFRESH_TIME_SECONDS' | translate}}" ng-model="config.refreshTime" pf-validation="mycCustomWidgetEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<label>{{ 'TEMPLATE' | translate }}</label>
<select class="form-control" pf-select data-live-search="true" ng-options="template for template in mycCustomWidgetEdit.templates" ng-model="config.template" required>
<option value="" ng-hide="true"></option>
</select>
</div>
<div class="form-group">
<label>{{ 'SCRIPT' | translate }}</label>
<select class="form-control" pf-select data-live-search="true" ng-options="script for script in mycCustomWidgetEdit.scripts" ng-model="config.script" >
<option value="" ng-hide="false">{{ 'NOTHING_SELECTED' | translate }}</option>
</select>
</div>
<div class="form-group" ng-if="config.script">
<label>{{ 'SCRIPT_BINDINGS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'SCRIPT_BINDINGS' | translate}}" ng-model="config.bindings" pf-validation="mycCustomWidgetEdit.cs.isJsonString(input)" required>
<span class="help-block">{{ 'SYNTAX_ERROR' | translate }}</span>
</div>
</form>

View File

@@ -0,0 +1,30 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- Loading icon disaplay -->
<div ng-show="config.template !== null">
<div ng-show="mycCustomWidget.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-if="!mycCustomWidget.showLoading">
<mc-dynamic ng-bind-html="mycCustomWidget.trustedHtml"></mc-dynamic>
<div ng-if="!mycCustomWidget.htmlData"><span>{{'NO_DATA_AVAILABLE' | translate}}</span></div>
</div>
</div>
<div ng-if="config.template === null" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>

View File

@@ -0,0 +1,132 @@
/*
* Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
// don't forget to declare this service module as a dependency in your main app constructor!
//http://js2.coffee/#coffee2js
//https://coderwall.com/p/r_bvhg/angular-ui-bootstrap-alert-service-for-angular-js
'use strict';
angular.module('adf.widget.myc-dsi', [])
.config(function(dashboardProvider){
dashboardProvider
.widget('mycDisplayStaticImage', {
title: 'Display image file',
description: 'Displays image file from local disk or url',
templateUrl: 'controllers/adf-widgets/adf-myc-dsi/view.html?mcv=29',
controller: 'mycDisplayStaticImageController',
controllerAs: 'mycDisplayStaticImage',
config: {
locationType:"disk",
imageNameUrl:"",
refreshTime:30,
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-dsi/edit.html?mcv=29',
controller: 'mycDisplayStaticImageEditController',
controllerAs: 'mycDisplayStaticImageEdit',
}
});
})
.controller('mycDisplayStaticImageController', function($scope, $interval, config, mchelper, $filter, StatusFactory, displayRestError, CommonServices){
var mycDisplayStaticImage = this;
mycDisplayStaticImage.showLoading = true;
mycDisplayStaticImage.isSyncing = true;
mycDisplayStaticImage.fileData = {};
mycDisplayStaticImage.error = false;
mycDisplayStaticImage.errorMsg;
mycDisplayStaticImage.imageNameUrl = config.imageNameUrl;
$scope.cs = CommonServices;
function loadImage(){
mycDisplayStaticImage.isSyncing = true;
if(config.locationType === "disk"){
StatusFactory.getStaticImageFile({'fileName':config.imageNameUrl}, function(response){
mycDisplayStaticImage.fileData = response;
mycDisplayStaticImage.isSyncing = false;
if(mycDisplayStaticImage.showLoading){
mycDisplayStaticImage.showLoading = false;
}
mycDisplayStaticImage.error = false;
},function(error){
mycDisplayStaticImage.showLoading = false;
mycDisplayStaticImage.isSyncing = false;
mycDisplayStaticImage.error = true;
if(error.data && error.data.errorMessage){
mycDisplayStaticImage.errorMsg = error.data.errorMessage;
}else{
mycDisplayStaticImage.errorMsg = error.statusText;
displayRestError.display(error);
}
});
}else{
mycDisplayStaticImage.imageNameUrl = config.imageNameUrl+'?t='+Date.now(); // Image should updated on every refresh
mycDisplayStaticImage.isSyncing = false;
if(mycDisplayStaticImage.showLoading){
mycDisplayStaticImage.showLoading = false;
}
}
};
function updateImage(){
if(mycDisplayStaticImage.isSyncing){
return;
}else if(config.imageNameUrl && config.imageNameUrl.length > 0){
loadImage();
}
}
//load image initially
if(config.imageNameUrl && config.imageNameUrl.length > 0){
loadImage();
}else{
mycDisplayStaticImage.showLoading = false;
}
// refresh every second
var promise = $interval(updateImage, config.refreshTime*1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function(){
$interval.cancel(promise);
});
}).controller('mycDisplayStaticImageEditController', function($scope, config, StatusFactory, displayRestError, CommonServices){
var mycDisplayStaticImageEdit = this;
mycDisplayStaticImageEdit.cs = CommonServices;
mycDisplayStaticImageEdit.locationTypes = ["disk","url"];
mycDisplayStaticImageEdit.filesList = [];
mycDisplayStaticImageEdit.onLocationTypeChange = function(){
config.imageNameUrl = "";
if(config.locationType === "disk"){
StatusFactory.getStaticImageFilesList(function(response){
mycDisplayStaticImageEdit.filesList = response;
},function(error){
displayRestError.display(error);
});
}
};
if(config.locationType === "disk"){
var tmpImageUrl = config.imageNameUrl;
mycDisplayStaticImageEdit.onLocationTypeChange();
config.imageNameUrl = tmpImageUrl;
}
});

View File

@@ -0,0 +1,44 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'REFRESH_TIME_SECONDS' | translate}}" ng-model="config.refreshTime" pf-validation="mycDisplayStaticImageEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<label>{{ 'TYPE' | translate }}</label>
<select id="senVarsTypes" class="form-control" pf-select ng-model="config.locationType" ng-change="mycDisplayStaticImageEdit.onLocationTypeChange()" ng-options="type for type in mycDisplayStaticImageEdit.locationTypes">
<option value="" ng-hide="true"></option>
</select>
</div>
<div ng-if="config.locationType === 'disk'" class="form-group">
<label>{{ 'FILE' | translate }}</label>
<select id="senVars" class="form-control" pf-select data-live-search="true" ng-model="config.imageNameUrl" ng-options="fileName for fileName in mycDisplayStaticImageEdit.filesList" required>
<option value="" ng-hide="true"></option>
</select>
</div>
<div ng-if="config.locationType === 'url'" class="form-group">
<label>{{ 'URL' | translate }}</label>
<input type="text" class="form-control" id="fileUrl" placeholder="{{'URL' | translate}}" ng-model="config.imageNameUrl" required>
</div>
</form>

View File

@@ -0,0 +1,37 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- Loading icon disaplay -->
<div ng-show="mycDisplayStaticImage.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-if="!mycDisplayStaticImage.showLoading">
<div ng-if="mycDisplayStaticImage.error" class="alert alert-danger">
<span class="pficon pficon-error-circle-o"></span>
<span>{{mycDisplayStaticImage.errorMsg}}</span>
</div>
<div ng-if="!mycDisplayStaticImage.error">
<img ng-if="config.locationType === 'disk'" ng-src="data:image/{{mycDisplayStaticImage.fileData.extension}};base64,{{mycDisplayStaticImage.fileData.data}}" alt="{{mycDisplayStaticImage.fileData.name}}" class="adf-myc-dsi-image"/>
<img ng-if="config.locationType === 'url'" ng-src="{{mycDisplayStaticImage.imageNameUrl}}" alt="{{mycDisplayStaticImage.imageNameUrl}}" class="adf-myc-dsi-image"/>
<div ng-if="!config.imageNameUrl" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>
</div>
</div>

View File

@@ -0,0 +1,103 @@
/*
* Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
// don't forget to declare this service module as a dependency in your main app constructor!
//http://js2.coffee/#coffee2js
//https://coderwall.com/p/r_bvhg/angular-ui-bootstrap-alert-service-for-angular-js
'use strict';
angular.module('adf.widget.myc-groups', [])
.config(function(dashboardProvider){
dashboardProvider
.widget('mycGroups', {
title: 'Groups',
description: 'Change state(ON/OFF) of resources group(Scene control)',
templateUrl: 'controllers/adf-widgets/adf-myc-groups/view.html?mcv=29',
controller: 'mycGroupsController',
controllerAs: 'mycGroups',
config: {
itemIds:[],
itemsPerRow:"1",
refreshTime:30,
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-groups/edit.html?mcv=29',
controller: 'mycGroupsEditController',
controllerAs: 'mycGroupsEdit',
}
});
})
.controller('mycGroupsController', function($scope, $interval, config, mchelper, $filter, ResourcesGroupFactory, TypesFactory, CommonServices){
var mycGroups = this;
mycGroups.showLoading = true;
mycGroups.isSyncing = false;
mycGroups.items = {};
$scope.cs = CommonServices;
function loadItems(){
mycGroups.isSyncing = true;
ResourcesGroupFactory.getAll({'id':config.itemIds, 'page':1, 'pageLimit':30}, function(response){
mycGroups.items = response.data;
mycGroups.isSyncing = false;
if(mycGroups.showLoading){
mycGroups.showLoading = false;
}
});
};
function updateItems(){
if(mycGroups.isSyncing){
return;
}else if(config.itemIds.length > 0){
loadItems();
}
}
//load items initially
updateItems();
//On,Off switch control
$scope.changeMystate = function(item, state){
var itemArray = [item.id];
if(state){
ResourcesGroupFactory.turnOnIds(itemArray, function(response) {
//alertService.success($filter('translate')('RESOURCE_GROUP_TURNED_ON'));
},function(error){
displayRestError.display(error);
});
}else{
ResourcesGroupFactory.turnOffIds(itemArray, function(response) {
//alertService.success($filter('translate')('RESOURCE_GROUP_TURNED_OFF'));
},function(error){
displayRestError.display(error);
});
}
}
// refresh every second
var promise = $interval(updateItems, config.refreshTime*1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function(){
$interval.cancel(promise);
});
}).controller('mycGroupsEditController', function($scope, $interval, config, mchelper, $filter, TypesFactory, CommonServices){
var mycGroupsEdit = this;
mycGroupsEdit.cs = CommonServices;
mycGroupsEdit.items = TypesFactory.getResourcesGroups();
});

View File

@@ -0,0 +1,43 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'REFRESH_TIME_SECONDS' | translate}}" ng-model="config.refreshTime" pf-validation="mycGroupsEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<label>{{ 'ITEMS_PER_ROW' | translate }}</label>
<select id="panelSize" class="form-control" pf-select ng-model="config.itemsPerRow" required>
<option value="" ng-hide="true"></option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="6">6</option>
<option value="12">12</option>
</select>
</div>
<div class="form-group">
<label>{{ 'GROUPS' | translate }}</label>
<select id="senVars" class="form-control" multiple pf-select data-live-search="true" ng-model="config.itemIds">
<option value="" ng-hide="true"></option>
<option ng-repeat="res in mycGroupsEdit.items" ng-bind-html="res.displayName | mcResourceRepresentation" value="{{res.id}}" ng-selected="config.itemIds.indexOf(res.id.toString()) != -1"></option>
</select>
</div>
</form>

View File

@@ -0,0 +1,51 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<div ng-if="config.itemIds.length > 0">
<!-- Loading icon disaplay -->
<div ng-if="mycGroups.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-if="!mycGroups.showLoading">
<!-- items ng-repeat -->
<div ng-repeat="item in mycGroups.items">
<div class="col-md-{{12/config.itemsPerRow}}">
<div class="card-pf card-pf-aggregate-status card-pf-with-action card-pf-accented card-pf-aggregate-status-mini">
<h2 class="card-pf-title">
<span class="pficon pficon-replicator"></span>
<span class="card-pf-aggregate-status-count" tooltip-placement="top" uib-tooltip="{{item.name}}">{{item.name ? item.name : '-' | limitTo:18}}{{item.name.length > 18 ? '...' : ''}}</span>
<span tooltip-placement="top" uib-tooltip="{{item.description}}">{{item.description ? item.description : '-' | limitTo:36}}{{item.description.length > 36 ? '...' : ''}}</span>
</h2>
<div class="card-pf-body">
<p class="card-pf-aggregate-status-notifications">
<span class="card-pf-aggregate-status-notification">
<input bs-switch ng-change="changeMystate(item, state)" ng-init="state = item.state === 'On'? true:false" ng-model="state" type="checkbox"
switch-animate="true" switch-handle-width="35px" switch-label-width="7px"
switch-off-color="default" switch-on-color="primary" switch-size="small"
ng-true-value="true" ng-false-value="false" switch-on-text="{{ 'ON' | translate }}" switch-off-text="{{ 'OFF' | translate }}" >
</span>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div ng-if="config.itemIds.length == 0" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>

View File

@@ -0,0 +1,189 @@
/*
* Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
'use strict';
angular.module('adf.widget.myc-heat-map', [])
.config(function(dashboardProvider){
dashboardProvider
.widget('mycHeatMap', {
title: 'Heatmap chart',
description: 'Displays data as heatmap chart',
templateUrl: 'controllers/adf-widgets/adf-myc-hm/view.html?mcv=29',
controller: 'mycHeatMapController',
controllerAs: 'mycHeatMap',
config: {
dataType: null,
upperLimit: null,
thresholds: [],
colorPattern: [],
legendLabels: [],
dataKey:null,
refreshTime:30,
height:200,
maxBlockSize:50,
showLegends:true,
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-hm/edit.html?mcv=29',
controller: 'mycHeatMapEditController',
controllerAs: 'mycHeatMapEdit',
}
});
})
.controller('mycHeatMapController', function($scope, $interval, config, mchelper, $filter, MetricsFactory,$state){
var mycHeatMap = this;
mycHeatMap.showLoading = true;
mycHeatMap.isSyncing = false;
mycHeatMap.data = {};
mycHeatMap.dataAvailable = false;
function updateState(){
if(mycHeatMap.data.length === 0){
mycHeatMap.dataAvailable = false;
}else{
mycHeatMap.dataAvailable = true;
}
mycHeatMap.isSyncing = false;
if(mycHeatMap.showLoading){
mycHeatMap.showLoading = false;
}
};
function loadData(){
mycHeatMap.isSyncing = true;
if(config.dataType === 'NODE_STATUS'){
MetricsFactory.getHeatMapHeatMapNodeStatus({'nodeId':config.dataKey}, function(response){
mycHeatMap.data = response;
updateState();
});
}else if(config.dataType === 'BATTERY_LEVEL'){
MetricsFactory.getHeatMapBatteryLevel({'nodeId':config.dataKey}, function(response){
mycHeatMap.data = response;
updateState();
});
}else if(config.dataType === 'SENSOR_VARIABLES'){
MetricsFactory.getHeatMapHeatMapSensorVariable({'variableId':config.dataKey, 'upperLimit':config.upperLimit}, function(response){
mycHeatMap.data = response;
updateState();
});
}else if(config.dataType === 'SCRIPT'){
MetricsFactory.getHeatMapHeatMapScript({'scriptName':config.dataKey}, function(response){
mycHeatMap.data = response;
updateState();
});
}else{
mycHeatMap.isSyncing = false;
if(mycHeatMap.showLoading){
mycHeatMap.showLoading = false;
}
}
//remove this line
if(mycHeatMap.showLoading){
mycHeatMap.showLoading = false;
}
};
function updateData(){
if(mycHeatMap.isSyncing){
return;
}else if(config.dataKey !== null){
loadData();
}
}
//load variables initially
if(config.dataKey !== null){
updateData();
}else{
mycHeatMap.showLoading = false;
}
//Heat map click action
mycHeatMap.hmClickAction = function(block){
if(config.dataType === 'NODE_STATUS' || config.dataType === 'BATTERY_LEVEL'){
$state.go("nodesDetail", {'id':block.altId});
}else if(config.dataType === 'SENSOR_VARIABLES'){
$state.go("sensorsDetail", {'id':block.altId});
}else if(config.dataType === 'SCRIPT'){
//Not implemented yet
}
};
// refresh every second
var promise = $interval(updateData, config.refreshTime*1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function(){
$interval.cancel(promise);
});
}).controller('mycHeatMapEditController', function($scope, $interval, config, mchelper, $filter, TypesFactory, ScriptsFactory, CommonServices){
var mycHeatMapEdit = this;
mycHeatMapEdit.cs = CommonServices;
var generalColorPattern = ['#21781F', '#3F9C35', '#57A8D4', '#F9D67A', '#EC7A08', '#CC0000', '#F00'];
var generalThresholds = [0.1, 0.3, 0.5, 0.7, 0.8, 0.9];
var generalLabels = ['< 10%', '10-30%', '30-50%', '50-70%', '70-80%', '80-90%', '> 90%'];
var statusColorPattern = ['#C00', '#808080', '#3F9C35'];
var statusThresholds = [0.4, 0.6];
var statusLabels = ['Down', 'Unavailable', 'Up'];
//Change data type
mycHeatMapEdit.changeDataType = function(){
//Update pattern, colors, labels
if(config.dataType === 'NODE_STATUS'){
config.thresholds = angular.copy(statusThresholds);
config.colorPattern = angular.copy(statusColorPattern);
config.legendLabels = angular.copy(statusLabels);
}else if(config.dataType){
config.thresholds = angular.copy(generalThresholds);
config.colorPattern = angular.copy(generalColorPattern);
config.legendLabels = angular.copy(generalLabels);
}
//Change color to reverse order if selected object is battery level
if(config.dataType === 'BATTERY_LEVEL'){
mycHeatMapEdit.swapColors();
}
//Change object type
if(config.dataType === 'SCRIPT'){
config.dataKey = {};
}else{
config.dataKey = [];
}
//load variables
loadVariables();
};
var loadVariables = function(){
if(config.dataType === 'NODE_STATUS' || config.dataType === 'BATTERY_LEVEL'){
mycHeatMapEdit.variables = TypesFactory.getNodes();
}else if(config.dataType === 'SENSOR_VARIABLES'){
//Get only DOUBLE type devices
mycHeatMapEdit.variables = TypesFactory.getSensorVariables({"metricType":"Double"});
}else if(config.dataType === 'SCRIPT'){
mycHeatMapEdit.variables = ScriptsFactory.getAllLessInfo({"type":"Operation"});
}
}
// load variables at startup
loadVariables();
//Swap up down color
mycHeatMapEdit.swapColors = function(){
config.colorPattern.reverse();
}
});

View File

@@ -0,0 +1,84 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'REFRESH_TIME_SECONDS' | translate}}" ng-model="config.refreshTime" pf-validation="mycHeatMapEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group" ng-if="config.dataType">
<label class="mc-margin-right">{{ 'HEIGHT' | translate }}</label>
<input class="mc-margin-right" type="text" id="height" placeholder="{{'HEIGHT' | translate}}" ng-model="config.height" pf-validation="mycHeatMapEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
<label class="mc-margin-right">{{ 'MAXIMUM_BLOCK_SIZE' | translate }}</label>
<input type="text" id="height" placeholder="{{'MAXIMUM_BLOCK_SIZE' | translate}}" ng-model="config.maxBlockSize" pf-validation="mycHeatMapEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<input ng-model="config.showLegends" type="checkbox"/>
<label class="control-label">{{ 'SHOW_LEGENDS' | translate }}</label>
</div>
<div class="form-group">
<label>{{ 'DATA_TYPE' | translate }}</label>
<select id="panelSize" class="form-control" pf-select ng-change="mycHeatMapEdit.changeDataType()" ng-model="config.dataType">
<option value="" ng-hide="true"></option>
<option value="BATTERY_LEVEL">{{ 'BATTERY_LEVEL' | translate }}</option>
<option value="NODE_STATUS">{{ 'NODE_STATUS' | translate }}</option>
<option value="SENSOR_VARIABLES">{{ 'SENSOR_VARIABLES' | translate }}</option>
<option value="SCRIPT">{{ 'SCRIPT' | translate }}</option>
</select>
</div>
<div class="form-group" ng-if="config.dataType === 'SENSOR_VARIABLES'">
<label>{{ 'UPPER_LIMIT' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'UPPER_LIMIT' | translate}}" ng-model="config.upperLimit" pf-validation="mycHeatMapEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group" ng-if="config.dataType">
<label class="mc-margin-right">{{ 'COLOR' | translate }}</label>
<i uib-tooltip="{{ 'SWAP' | translate }}" tooltip-placement="top" ng-click="mycHeatMapEdit.swapColors()" class="fa fa-exchange mc-icon-md-3 mc-pointer text-primary"></i>
</div>
<div class="form-group" ng-if="config.dataType">
<span ng-repeat="item in config.colorPattern track by $index">
<span style="background-color:{{config.colorPattern[$index]}};width:72px;color:white;" class="btn btn-sm mc-margin-right" colorpicker="hex" colorpicker-position="top"
ng-model="config.colorPattern[$index]">{{config.legendLabels[$index] || "-"}}</span>
</span>
</div>
<div class="form-group">
<label ng-if="config.dataType === 'SENSOR_VARIABLES'">{{ 'SENSOR_VARIABLES' | translate }}</label>
<label ng-if="config.dataType === 'BATTERY_LEVEL'">{{ 'NODES' | translate }}</label>
<label ng-if="config.dataType === 'NODE_STATUS'">{{ 'NODES' | translate }}</label>
<label ng-if="config.dataType === 'SCRIPT'">{{ 'SCRIPT' | translate }}</label>
<select ng-if="config.dataType === 'SENSOR_VARIABLES' || config.dataType === 'BATTERY_LEVEL' || config.dataType === 'NODE_STATUS'"
id="dataKey" class="form-control" multiple pf-select data-live-search="true" ng-model="config.dataKey">
<option value="" ng-hide="true"></option>
<option ng-repeat="res in mycHeatMapEdit.variables" ng-bind-html="res.displayName | mcResourceRepresentation" value="{{res.id}}" ng-selected="config.dataKey.indexOf(res.id.toString()) != -1"></option>
</select>
<select ng-if="config.dataType === 'SCRIPT'" id="dataKey" class="form-control" pf-select data-live-search="true" ng-options="resource for resource in mycHeatMapEdit.variables" ng-model="config.dataKey">
<option value="" ng-hide="true"></option>
</select>
</div>
</form>

View File

@@ -0,0 +1,36 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- Loading icon disaplay -->
<div ng-show="mycHeatMap.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-if="!mycHeatMap.showLoading">
<div class="adf-myc-shm-margin" ng-if="mycHeatMap.data.length > 0" pf-heatmap
data="mycHeatMap.data" chart-data-available="mycHeatMap.dataAvailable"
show-legend="config.showLegends" legend-labels="config.legendLabels"
heatmap-color-pattern="config.colorPattern" thresholds="config.thresholds"
max-block-size="{{config.maxBlockSize}}" height="config.height"
click-action="mycHeatMap.hmClickAction">
</div>
<div ng-if="mycHeatMap.data.length == 0">
<span>{{'NO_DATA_AVAILABLE' | translate}}</span>
</div>
</div>
<div ng-if="config.dataKey === null" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2015-2019 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
// don't forget to declare this service module as a dependency in your main app constructor!
//http://js2.coffee/#coffee2js
//https://coderwall.com/p/r_bvhg/angular-ui-bootstrap-alert-service-for-angular-js
'use strict';
angular.module('adf.widget.myc-os-commands', [])
.config(function (dashboardProvider) {
dashboardProvider
.widget('mycOsCommands', {
title: 'OS Commands',
description: 'Create buttons to run Operating System Commands',
templateUrl: 'controllers/adf-widgets/adf-myc-os/view.html?mcv=${mc.gui.version}',
controller: 'mycOsCommandController',
controllerAs: 'mycOsBtns',
config: {
minBtnHeight: 30,
minBtnWidth: 90,
buttonsJson: "[\n]",
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-os/edit.html?mcv=${mc.gui.version}',
controller: 'mycOsCommandEditController',
controllerAs: 'mycOsBtnsEdit',
}
});
})
.controller('mycOsCommandController', function ($scope, $interval, config, mchelper, $uibModal, $filter, OSCommandFactory, CommonServices) {
var mycOsBtns = this;
mycOsBtns.showLoading = false;
$scope.tooltipEnabled = false;
$scope.cs = CommonServices;
mycOsBtns.buttons = angular.fromJson(config.buttonsJson);
// execute OS command directly
$scope.executeOsCommandDirect = function (button) {
var request = {};
request.os = button.os;
request.command = button.command;
OSCommandFactory.execute(request, function (response) {
if (response.error === undefined) {
alertService.success(response.result);
} else {
alertService.danger(angular.toJson(response));
}
}, function (error) {
displayRestError.display(error);
});
};
// execute OS command with confirmation check
$scope.executeOsCommand = function (button) {
if (button.confirmation === true) {
var addModalInstance = $uibModal.open({
templateUrl: 'controllers/adf-widgets/adf-myc-os/confirmation-modal.html?mcv=${mc.gui.version}',
controller: 'CommandConfirmationController',
resolve: {
button: button
}
});
addModalInstance.result.then(function () {
$scope.executeOsCommandDirect(button);
}),
function () {
//console.log('Modal dismissed at: ' + new Date());
}
} else {
$scope.executeOsCommandDirect(button);
}
};
}).controller('mycOsCommandEditController', function ($scope, $interval, config, mchelper, $filter, CommonServices) {
var mycOsBtnsEdit = this;
mycOsBtnsEdit.cs = CommonServices;
}).controller('CommandConfirmationController', function ($scope, $uibModalInstance, $filter, button) {
$scope.header = $filter('translate')('OS_COMMAND_EXECTION_CONFIRMATION_TITLE');
$scope.button = button;
$scope.reboot = function () {
$uibModalInstance.close();
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
}
});

View File

@@ -0,0 +1,40 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<div>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" ng-click="cancel()">
<span class="pficon pficon-close"></span>
</button>
<div class="modal-title"><b>{{header}}</b></div>
</div>
<div class="modal-body modal-body-text-only">
<div class="mc-model-text-margin">{{ 'OS_COMMAND_EXECTION_CONFIRMATION_MESSAGE' | translate }}
<div ng-if="button.os"> {{ 'OPERATING_SYSTEM' | translate }}: <b>{{button.os}}</b></div>
</div>
<div><pre> {{ 'COMMAND' | translate }}: <b>{{button.command}}</b></pre></div>
</div>
<div class="modal-footer">
<button class="btn btn-default" ng-click="cancel()"><i class="fa fa-close"></i> {{ 'CANCEL' | translate }}</button>
<button class="btn btn-primary" ng-click="reboot()"><i class="fa fa-check"></i> {{ 'CONTINUE' | translate }}</button>
</div>
</div>

View File

@@ -0,0 +1,35 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<legend><small>{{ 'BUTTON_SETTINGS' | translate }}</small></legend>
<div class="form-group">
<label class="mc-margin-right">{{ 'MINIMUM_HEIGHT' | translate }}</label>
<input type="text" id="height-min" class="mc-margin-right" placeholder="{{'MINIMUM_HEIGHT' | translate}}" ng-model="config.minBtnHeight" pf-validation="mycOsBtnsEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
<label class="mc-margin-right">{{ 'MINIMUM_WIDTH' | translate }}</label>
<input type="text" id="width-min" placeholder="{{'MINIMUM_WIDTH' | translate}}" ng-model="config.minBtnWidth" pf-validation="mycOsBtnsEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<label>{{ 'JSON' | translate }}</label>
<textarea class="form-control" rows="12" style="resize:none" ng-model="config.buttonsJson" required ></textarea>
</div>
</form>

View File

@@ -0,0 +1,34 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- Loading icon disaplay -->
<div ng-show="mycOsBtns.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-hide="mycOsBtns.showLoading">
<div ng-if="config.buttonsJson" >
<div id="custom-buttons-wrapper" class="row-fluid">
<button ng-repeat="button in mycOsBtns.buttons track by $index" ng-click="executeOsCommand(button)" class="btn"
ng-class="button.btnType ? 'btn-{{button.btnType}}' : 'btn-default'"
ng-style="{'min-width':'{{config.minBtnWidth}}px', 'min-height':'{{config.minBtnHeight}}px'}"
ng-bind-html="button.name"></button>
</div>
</div>
<!-- display no items configured -->
<div ng-if="config.buttonsJson.length < 5" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>
</div>

View File

@@ -0,0 +1,140 @@
/*
* Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
// don't forget to declare this service module as a dependency in your main app constructor!
//http://js2.coffee/#coffee2js
//https://coderwall.com/p/r_bvhg/angular-ui-bootstrap-alert-service-for-angular-js
'use strict';
angular.module('adf.widget.myc-sensors-bullet-graph', [])
.config(function(dashboardProvider){
dashboardProvider
.widget('mycSensorsBulletGraph', {
title: 'Sensors bullet graph',
description: 'Monitor sensors value with bullet graph',
templateUrl: 'controllers/adf-widgets/adf-myc-sbg/view.html?mcv=29',
controller: 'mycSensorsBulletGraphController',
controllerAs: 'mycSensorsBulletGraph',
config: {
colorUp:"#3f9c35",
colorDown:"#c00000",
chartFromTimestamp:'3600000',
variableIds:[],
refreshTime:30,
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-sbg/edit.html?mcv=29',
controller: 'mycSensorsBulletGraphEditController',
controllerAs: 'mycSensorsBulletGraphEdit',
}
});
})
.controller('mycSensorsBulletGraphController', function($scope, $interval, config, mchelper, $filter, MetricsFactory){
var mycSensorsBulletGraph = this;
mycSensorsBulletGraph.showLoading = true;
mycSensorsBulletGraph.isSyncing = true;
mycSensorsBulletGraph.variables = {};
$scope.tooltipEnabled = false;
$scope.hideVariableName=true;
mycSensorsBulletGraph.variables = {};
mycSensorsBulletGraph.chartOptions = {
chart: {
type: 'bulletChart',
transitionDuration: 500,
//color: config.color, //rgb(31, 119, 180)
noData: $filter('translate')('NO_DATA_AVAILABLE'),
margin: {
top: 8,
right: 10,
bottom: 21,
left: 5,
},
}
};
mycSensorsBulletGraph.getChartOptions = function(){
return angular.copy(mycSensorsBulletGraph.chartOptions);
}
function loadVariables(){
mycSensorsBulletGraph.isSyncing = true;
MetricsFactory.getBulletChart({'variableId':config.variableIds, "start": new Date().getTime() - config.chartFromTimestamp}, function(response){
mycSensorsBulletGraph.sensorVariables = response;
angular.forEach(mycSensorsBulletGraph.sensorVariables, function(item){
if(item.markers && item.markers[0]){
if(parseFloat(item.markers[0]) <= parseFloat(item.measures[0])){
item.color = config.colorUp;
}else{
item.color = config.colorDown;
}
}else{
item.color = "#1f77b4";//default color
}
});
mycSensorsBulletGraph.isSyncing = false;
if(mycSensorsBulletGraph.showLoading){
mycSensorsBulletGraph.showLoading = false;
}
});
};
function updateVariables(){
if(mycSensorsBulletGraph.isSyncing){
return;
}else if(config.variableIds.length > 0){
loadVariables();
}
}
//load variables initially
if(config.variableIds.length > 0){
loadVariables();
}else{
mycSensorsBulletGraph.showLoading = false;
}
//updateVariables();
//Update Variable / Send Payload
$scope.updateVariable = function(variable){
SensorsFactory.updateVariable(variable, function(){
//update Success
},function(error){
displayRestError.display(error);
});
};
// refresh every second
var promise = $interval(updateVariables, config.refreshTime*1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function(){
$interval.cancel(promise);
});
}).controller('mycSensorsBulletGraphEditController', function($scope, $interval, config, mchelper, $filter, TypesFactory, CommonServices){
var mycSensorsBulletGraphEdit = this;
mycSensorsBulletGraphEdit.cs = CommonServices;
//TODO: get only DOUBLE type devices
mycSensorsBulletGraphEdit.variables = TypesFactory.getSensorVariables({"metricType":"Double"});
//Swap up down color
mycSensorsBulletGraphEdit.swapColor = function(){
var colorUp = config.colorUp;
config.colorUp = config.colorDown;
config.colorDown = colorUp;
}
});

View File

@@ -0,0 +1,58 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'REFRESH_TIME_SECONDS' | translate}}" ng-model="config.refreshTime" pf-validation="mycSensorsBulletGraphEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<label class="mc-margin-right">{{ 'COLOR' | translate }}</label>
<i uib-tooltip="{{ 'UP' | translate }}" tooltip-placement="top" class="fa fa-arrow-up mc-icon-md-3"></i>
<span style="background-color:{{config.colorUp}};width:65px;color:white;" class="btn btn-sm mc-margin-right" colorpicker="hex" colorpicker-position="top" ng-model="config.colorUp">{{config.colorUp || "-"}}</span>
<i uib-tooltip="{{ 'DOWN' | translate }}" tooltip-placement="top" class="fa fa-arrow-down mc-icon-md-3"></i>
<span style="background-color:{{config.colorDown}};width:65px;color:white;" class="btn btn-sm mc-margin-right" colorpicker="hex" colorpicker-position="top" ng-model="config.colorDown">{{config.colorDown || "-"}}</span>
<i uib-tooltip="{{ 'SWAP' | translate }}" tooltip-placement="top" ng-click="mycSensorsBulletGraphEdit.swapColor()" class="fa fa-exchange mc-icon-md-3 mc-pointer text-primary"></i>
</div>
<div class="form-group">
<label>{{ 'TIME_RANGE' | translate }}</label>
<select id="panelSize" class="form-control" pf-select ng-model="config.chartFromTimestamp">
<option value="" ng-hide="true"></option>
<option value="300000">{{ 'LAST_5_MINUTES' | translate }}</option>
<option value="3600000">{{ 'LAST_HOUR' | translate }}</option>
<option value="21600000">{{ 'LAST_6_HOURS' | translate }}</option>
<option value="43200000">{{ 'LAST_12_HOURS' | translate }}</option>
<option value="86400000">{{ 'LAST_DAY' | translate }}</option>
<option value="604800000">{{ 'LAST_WEEK' | translate }}</option>
<option value="2419200000">{{ 'LAST_MONTH' | translate }}</option>
<option value="31536000000">{{ 'LAST_YEAR' | translate }}</option>
</select>
</div>
<div class="form-group">
<label>{{ 'SENSOR_VARIABLES' | translate }}</label>
<select id="senVars" class="form-control" multiple pf-select data-live-search="true" ng-model="config.variableIds">
<option value="" ng-hide="true"></option>
<option ng-repeat="res in mycSensorsBulletGraphEdit.variables" ng-bind-html="res.displayName | mcResourceRepresentation" value="{{res.id}}" ng-selected="config.variableIds.indexOf(res.id.toString()) != -1"></option>
</select>
</div>
</form>

View File

@@ -0,0 +1,35 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- Loading icon disaplay -->
<div ng-show="mycSensorsBulletGraph.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-if="!mycSensorsBulletGraph.showLoading">
<!-- variables ng-repeat -->
<div ng-repeat="sensorVariable in mycSensorsBulletGraph.sensorVariables track by $index">
<hr ng-if="$index != 0" class="adf-myc-sbg-margin">
<div class="adf-myc-sbg">
<span class="mc-pointer" tooltip-placement="top" ui-sref="sensorsDetail({id:sensorVariable.internalId})"
uib-tooltip-html="sensorVariable.resourceName | mcResourceRepresentation" ng-bind-html="'[S]:'+sensorVariable.displayName | mcResourceRepresentation"></span>
<nvd3 id="sbg-{{config.variableIds.join('-')}}" ng-init="chartOptions=mycSensorsBulletGraph.getChartOptions()" options="chartOptions" data="sensorVariable"></nvd3>
</div>
</div>
</div>
<div ng-if="config.variableIds.length == 0" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>

View File

@@ -0,0 +1,147 @@
/*
* Copyright 2015-2019 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
// don't forget to declare this service module as a dependency in your main app constructor!
//http://js2.coffee/#coffee2js
//https://coderwall.com/p/r_bvhg/angular-ui-bootstrap-alert-service-for-angular-js
'use strict';
angular.module('adf.widget.myc-sen-vars', [])
.config(function (dashboardProvider) {
dashboardProvider
.widget('mycSenVars', {
title: 'Sensors',
description: 'Monitor and change sensors state',
templateUrl: 'controllers/adf-widgets/adf-myc-sen-vars/view.html?mcv=29',
controller: 'mycSenVarsController',
controllerAs: 'mycSenVars',
config: {
variableIds: [],
showIcon: true,
confirmationEnabled: false,
itemsPerRow: "2",
refreshTime: 30,
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-sen-vars/edit.html?mcv=29',
controller: 'mycSenVarsEditController',
controllerAs: 'mycSenVarsEdit',
}
});
})
.controller('mycSenVarsController', function ($scope, $interval, config, mchelper, $filter, SensorsFactory, TypesFactory, CommonServices, $uibModal) {
var mycSenVars = this;
mycSenVars.showLoading = true;
mycSenVars.isSyncing = true;
mycSenVars.variables = {};
$scope.tooltipEnabled = false;
$scope.hideVariableName = !config.showIcon;
$scope.cs = CommonServices;
//HVAC heater options - HVAC flow state
$scope.hvacOptionsFlowState = TypesFactory.getHvacOptionsFlowState();
//HVAC heater options - HVAC flow mode
$scope.hvacOptionsFlowMode = TypesFactory.getHvacOptionsFlowMode();
//HVAC heater options - HVAC fan speed
$scope.hvacOptionsFanSpeed = TypesFactory.getHvacOptionsFanSpeed();
//Defined variable types list
$scope.definedVariableTypes = CommonServices.getSensorVariablesKnownList();
//update rgba color
$scope.updateRgba = function (variable) {
variable.value = CommonServices.rgba2hex(variable.rgba);
$scope.updateVariable(variable);
};
function loadVariables() {
mycSenVars.isSyncing = true;
SensorsFactory.getVariables({
'ids': config.variableIds
}, function (response) {
mycSenVars.variables = response;
mycSenVars.isSyncing = false;
if (mycSenVars.showLoading) {
mycSenVars.showLoading = false;
}
});
};
function updateVariables() {
if (mycSenVars.isSyncing) {
return;
} else if (config.variableIds.length > 0) {
loadVariables();
}
}
// load variables initially
loadVariables();
//updateVariables();
// update Variable / Send Payload
$scope.updateVariableFinal = function (variable) {
SensorsFactory.updateVariable(variable, function () {
//update Success
}, function (error) {
displayRestError.display(error);
});
};
// update Variable confirmation test
$scope.updateVariable = function (variable) {
if (config.confirmationEnabled) {
var addModalInstance = $uibModal.open({
templateUrl: 'controllers/adf-widgets/adf-myc-sen-vars/confirmation-modal.html?mcv=29',
controller: 'SensorVarsConfirmationController',
resolve: {
variable: variable
}
});
addModalInstance.result.then(function () {
$scope.updateVariableFinal(variable);
}),
function () {
//console.log('Modal dismissed at: ' + new Date());
}
} else {
$scope.updateVariableFinal(variable);
}
};
// refresh every second
var promise = $interval(updateVariables, config.refreshTime * 1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function () {
$interval.cancel(promise);
});
}).controller('mycSenVarsEditController', function ($scope, $interval, config, mchelper, $filter, TypesFactory, CommonServices) {
var mycSenVarsEdit = this;
mycSenVarsEdit.cs = CommonServices;
mycSenVarsEdit.variables = TypesFactory.getSensorVariables();
}).controller('SensorVarsConfirmationController', function ($scope, $uibModalInstance, $filter, variable) {
$scope.variable = variable;
$scope.accept = function () {
$uibModalInstance.close();
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
}
});

View File

@@ -0,0 +1,37 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<div>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" ng-click="cancel()">
<span class="pficon pficon-close"></span>
</button>
<div class="modal-title"><b>{{ 'SENSOR_VARIABLE_SUBMIT_CONFIRMATION_TITLE' | translate }}</b></div>
</div>
<div class="modal-body modal-body-text-only">
<div class="mc-model-text-margin">{{ 'SENSOR_VARIABLE_SUBMIT_CONFIRMATION_MESSAGE' | translate }}</div>
<pre><span ng-bind-html="variable.resourceName | mcResourceRepresentation"></span><span>, <b class="mc-color-steel-blue">{{ 'PAYLOAD' | translate }}: {{variable.value}}</span></b></pre>
</div>
<div class="modal-footer">
<button class="btn btn-default" ng-click="cancel()"><i class="fa fa-close"></i> {{ 'CANCEL' | translate }}</button>
<button class="btn btn-primary" ng-click="accept()"><i class="fa fa-check"></i> {{ 'CONTINUE' | translate }}</button>
</div>
</div>

View File

@@ -0,0 +1,54 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'REFRESH_TIME_SECONDS' | translate}}" ng-model="config.refreshTime" pf-validation="mycSenVarsEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<input ng-model="config.showIcon" type="checkbox"/>
<label class="control-label">{{ 'SHOW_ICON' | translate }}</label>
</div>
<div class="form-group">
<input ng-model="config.confirmationEnabled" type="checkbox"/>
<label class="control-label">{{ 'ENABLE_CONFIRMATION' | translate }}</label>
</div>
<div class="form-group">
<label>{{ 'ITEMS_PER_ROW' | translate }}</label>
<select id="panelSize" class="form-control" pf-select ng-model="config.itemsPerRow">
<option value="" ng-hide="true"></option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="6">6</option>
<option value="12">12</option>
</select>
</div>
<div class="form-group">
<label>{{ 'SENSOR_VARIABLES' | translate }}</label>
<select id="senVars" class="form-control" multiple pf-select data-live-search="true" ng-model="config.variableIds">
<option value="" ng-hide="true"></option>
<option ng-repeat="res in mycSenVarsEdit.variables" ng-bind-html="res.displayName | mcResourceRepresentation" value="{{res.id}}" ng-selected="config.variableIds.indexOf(res.id.toString()) != -1"></option>
</select>
</div>
</form>

View File

@@ -0,0 +1,41 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- Loading icon disaplay -->
<div ng-show="mycSenVars.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-hide="mycSenVars.showLoading">
<!-- variables ng-repeat -->
<div ng-repeat="variable in mycSenVars.variables">
<div class="col-md-{{12/config.itemsPerRow}}">
<div class="card-pf card-pf-aggregate-status card-pf-with-action card-pf-accented adf-myc-sen-var">
<h2 class="card-pf-title mc-pointer" tooltip-placement="top" uib-tooltip-html="variable.resourceName | mcResourceRepresentation" ui-sref="sensorsDetail({id:variable.sensorId})"><i class="fa fa-eye"></i>{{variable.sensorName}}</h2>
<div class="card-pf-body">
<!-- Sensor variables -->
<div ng-include src="'partials/common-html/sensor-actions-items.html'"></div>
</div>
</div>
</div>
</div>
<div ng-if="mycSenVars.variables.length == 0" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>
</div>
</div>

View File

@@ -0,0 +1,173 @@
/*
* Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
// don't forget to declare this service module as a dependency in your main app constructor!
//http://js2.coffee/#coffee2js
//https://coderwall.com/p/r_bvhg/angular-ui-bootstrap-alert-service-for-angular-js
'use strict';
angular.module('adf.widget.myc-sensors-grouped-graph', [])
.config(function(dashboardProvider){
dashboardProvider
.widget('mycSensorsGroupedGraph', {
title: 'Grouped sensors graph',
description: 'Similar type of sensors grouped graphical view',
templateUrl: 'controllers/adf-widgets/adf-myc-sgg/view.html?mcv=29',
controller: 'mycSensorsGroupedGraphController',
controllerAs: 'mycSensorsGroupedGraph',
config: {
useInteractiveGuideline:true,
enableUniqueName:false,
variableId:[],
variableType:null,
chartFromTimestamp:'3600000',
refreshTime:30,
marginTop:5,
marginRight:20,
marginBottom:60,
marginLeft:65,
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-sgg/edit.html?mcv=29',
controller: 'mycSensorsGroupedGraphEditController',
controllerAs: 'mycSensorsGroupedGraphEdit',
}
});
})
.controller('mycSensorsGroupedGraphController', function($scope, $interval, config, mchelper, $filter, MetricsFactory, CommonServices){
var mycSensorsGroupedGraph = this;
mycSensorsGroupedGraph.showLoading = true;
mycSensorsGroupedGraph.showError = false;
mycSensorsGroupedGraph.isSyncing = false;
mycSensorsGroupedGraph.cs = CommonServices;
CommonServices.updateGraphMarginDefault(config);
mycSensorsGroupedGraph.chartOptions = {
chart: {
type: 'lineChart',
noErrorCheck: true,
height: 225,
margin : {
top: config.marginTop,
right: config.marginRight,
bottom: config.marginBottom,
left: config.marginLeft,
},
color: d3.scale.category10().range(),
noData: $filter('translate')('NO_DATA_AVAILABLE'),
x: function(d){return d[0];},
y: function(d){return d[1];},
useVoronoi: !config.useInteractiveGuideline,
useInteractiveGuideline: config.useInteractiveGuideline,
clipEdge: false,
xAxis: {
showMaxMin: false,
tickFormat: function(d) {
return d3.time.format('hh:mm a')(new Date(d))
},
//axisLabel: 'Timestamp',
rotateLabels: -20
},
yAxis: {
tickFormat: function(d){
return d3.format(',.2f')(d);
},
axisLabelDistance: -10,
//axisLabel: ''
},
},
title: {
enable: false,
text: 'Title'
}
};
mycSensorsGroupedGraph.chartTimeFormat = mchelper.cfg.dateFormat;
function updateChart(){
mycSensorsGroupedGraph.isSyncing = true;
MetricsFactory.getMetricsData({"variableId":config.variableId, "chartType":"lineChart", "start": new Date().getTime() - config.chartFromTimestamp, "enableDetailedKey": config.enableUniqueName === undefined ? false : config.enableUniqueName}, function(resource){
if(resource.length > 0){
mycSensorsGroupedGraph.chartData = resource[0].chartData;
//Update display time format
mycSensorsGroupedGraph.chartTimeFormat = resource[0].timeFormat;
mycSensorsGroupedGraph.chartOptions.chart.xAxis.tickFormat = function(d) {return $filter('date')(d, mycSensorsGroupedGraph.chartTimeFormat, mchelper.cfg.timezone)};
mycSensorsGroupedGraph.chartOptions.chart.interpolate = resource[0].chartInterpolate;
if(resource[0].unit === ''){
mycSensorsGroupedGraph.chartOptions.chart.yAxis.tickFormat = function(d){return d3.format('.0f')(d);};
}else{
mycSensorsGroupedGraph.chartOptions.chart.yAxis.tickFormat = function(d){return d3.format('.02f')(d) + ' ' + resource[0].unit;};
}
}else{
if(config.variableId.length !== 0){
mycSensorsGroupedGraph.showError = true;
}
}
mycSensorsGroupedGraph.isSyncing = false;
if(mycSensorsGroupedGraph.showLoading){
mycSensorsGroupedGraph.showLoading = false;
}
});
}
function updateVariables(){
if(mycSensorsGroupedGraph.isSyncing){
return;
}else if(config.variableId.length !== 0){
updateChart();
}else{
mycSensorsGroupedGraph.showLoading = false;
}
}
//load graph initially
updateVariables();
// refresh every second
var promise = $interval(updateVariables, config.refreshTime*1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function(){
$interval.cancel(promise);
});
}).controller('mycSensorsGroupedGraphEditController', function($scope, $interval, config, mchelper, $filter, TypesFactory, CommonServices){
var mycSensorsGroupedGraphEdit = this;
mycSensorsGroupedGraphEdit.cs = CommonServices;
mycSensorsGroupedGraphEdit.onVariableTypeChange = function(){
config.variableId = [];
if(config.variableType){
mycSensorsGroupedGraphEdit.variables = TypesFactory.getSensorVariables({"variableType":config.variableType});
}else{
mycSensorsGroupedGraphEdit.variables = {};
}
};
//Load variable types
mycSensorsGroupedGraphEdit.variableTypes = TypesFactory.getSensorVariableTypes({"metricType":["Double","Binary", "Counter"]});
if(config.variableType){
var variableIdRef = config.variableId;
mycSensorsGroupedGraphEdit.onVariableTypeChange();
config.variableId = variableIdRef;
}
});

View File

@@ -0,0 +1,101 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'REFRESH_TIME_SECONDS' | translate}}" ng-model="config.refreshTime" pf-validation="mycSensorsGroupedGraphEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<input ng-model="config.useInteractiveGuideline" type="checkbox"/>
<label class="control-label">{{ 'USE_INTERACTIVE_GUIDE_LINE' | translate }}</label>
</div>
<div class="form-group">
<input ng-model="config.enableUniqueName" type="checkbox"/>
<label class="control-label">{{ 'ENABLE_UNIQUE_NAME' | translate }}</label>
</div>
<div class="form-group">
<label>{{ 'MARGIN' | translate }}</label>
<table class="adf-table">
<tr>
<td>
<label>{{ 'LEFT' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="left" placeholder="{{'LEFT' | translate}}" ng-model="config.marginLeft" pf-validation="mycSensorsGroupedGraphEdit.cs.isNumber(input)" required>
</td>
<td>
<label class="mc-margin-right">{{ 'RIGHT' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="right" placeholder="{{'RIGHT' | translate}}" ng-model="config.marginRight" pf-validation="mycSensorsGroupedGraphEdit.cs.isNumber(input)" required>
</td>
</tr>
<tr>
<td>
<label>{{ 'TOP' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="top" placeholder="{{'TOP' | translate}}" ng-model="config.marginTop" pf-validation="mycSensorsGroupedGraphEdit.cs.isNumber(input)" required>
</td>
<td>
<label>{{ 'BOTTOM' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="bottom" placeholder="{{'BOTTOM' | translate}}" ng-model="config.marginBottom" pf-validation="mycSensorsGroupedGraphEdit.cs.isNumber(input)" required>
</td>
</tr>
</table>
</div>
<div class="form-group">
<label>{{ 'TIME_RANGE' | translate }}</label>
<select id="panelSize" class="form-control" pf-select ng-model="config.chartFromTimestamp">
<option value="" ng-hide="true"></option>
<option value="300000">{{ 'LAST_5_MINUTES' | translate }}</option>
<option value="3600000">{{ 'LAST_HOUR' | translate }}</option>
<option value="21600000">{{ 'LAST_6_HOURS' | translate }}</option>
<option value="43200000">{{ 'LAST_12_HOURS' | translate }}</option>
<option value="86400000">{{ 'LAST_DAY' | translate }}</option>
<option value="604800000">{{ 'LAST_WEEK' | translate }}</option>
<option value="2419200000">{{ 'LAST_MONTH' | translate }}</option>
<option value="31536000000">{{ 'LAST_YEAR' | translate }}</option>
</select>
</div>
<div class="form-group">
<label>{{ 'SENSOR_VARIABLE_TYPE' | translate }}</label>
<select id="senVarsTypes" class="form-control" pf-select data-live-search="true" ng-model="config.variableType" ng-change="mycSensorsGroupedGraphEdit.onVariableTypeChange()">
<option value="" ng-hide="true"></option>
<option ng-repeat="vType in mycSensorsGroupedGraphEdit.variableTypes | orderBy: 'displayName'" value="{{vType.id}}" ng-selected="config.variableType === vType.id">{{vType.displayName}}</option>
</select>
</div>
<div class="form-group">
<label>{{ 'SENSOR_VARIABLE' | translate }}</label>
<select id="senVars" class="form-control" multiple pf-select data-live-search="true" ng-model="config.variableId">
<option value="" ng-hide="true"></option>
<option ng-repeat="res in mycSensorsGroupedGraphEdit.variables" ng-bind-html="res.displayName | mcResourceRepresentation" value="{{res.id}}"
ng-selected="config.variableId.indexOf(res.id.toString()) !== -1 "></option>
</select>
</div>
</form>

View File

@@ -0,0 +1,32 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- Loading icon disaplay -->
<div ng-if="mycSensorsGroupedGraph.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-if="mycSensorsGroupedGraph.showError">
<div ng-include src="'partials/common-html/error-sm.html'"></div>
</div>
<div ng-if="!(mycSensorsGroupedGraph.showLoading || mycSensorsGroupedGraph.showError)">
<!-- <label>{{ 'SENSOR_VARIABLE_TYPE' | translate }}: {{config.variableType}}</label> -->
<nvd3 id="sgg-{{config.variableId.join('-')}}" options='mycSensorsGroupedGraph.chartOptions' data="mycSensorsGroupedGraph.chartData"></nvd3>
<div ng-if="config.variableId.length === 0" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>
</div>

View File

@@ -0,0 +1,196 @@
/*
* Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
// don't forget to declare this service module as a dependency in your main app constructor!
//http://js2.coffee/#coffee2js
//https://coderwall.com/p/r_bvhg/angular-ui-bootstrap-alert-service-for-angular-js
'use strict';
angular.module('adf.widget.myc-sensors-mixed-graph', [])
.config(function(dashboardProvider){
dashboardProvider
.widget('mycSensorsMixedGraph', {
title: 'Mixed sensors graph',
description: 'Different type of sensors mixed graphical view [refer document]',
templateUrl: 'controllers/adf-widgets/adf-myc-smg/view.html?mcv=29',
controller: 'mycSensorsMixedGraphController',
controllerAs: 'mycSensorsMixedGraph',
config: {
useInteractiveGuideline:false,
enableUniqueName:false,
chartInterpolate:"linear",
variableId:[],
variableType:[],
chartFromTimestamp:'3600000',
refreshTime:30,
marginTop:5,
marginRight:20,
marginBottom:60,
marginLeft:65,
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-smg/edit.html?mcv=29',
controller: 'mycSensorsMixedGraphEditController',
controllerAs: 'mycSensorsMixedGraphEdit',
}
});
})
.controller('mycSensorsMixedGraphController', function($scope, $interval, config, mchelper, $filter, MetricsFactory, CommonServices){
var mycSensorsMixedGraph = this;
mycSensorsMixedGraph.showLoading = true;
mycSensorsMixedGraph.showError = false;
mycSensorsMixedGraph.isSyncing = false;
CommonServices.updateGraphMarginDefault(config);
mycSensorsMixedGraph.chartOptions = {
chart: {
type: 'multiChart',
noErrorCheck: true,
height: 225,
margin : {
top: config.marginTop,
right: config.marginRight,
bottom: config.marginBottom,
left: config.marginLeft,
},
color: d3.scale.category10().range(),
duration: 500,
noData: $filter('translate')('NO_DATA_AVAILABLE'),
//x: function(d,i){return d[0];},
//y: function(d,i){return d[1];},
clipEdge: false,
useVoronoi: !config.useInteractiveGuideline,
useInteractiveGuideline: config.useInteractiveGuideline,
xAxis: {
showMaxMin: false,
tickFormat: function(d) {
return d3.time.format('hh:mm a')(new Date(d))
},
//axisLabel: 'Timestamp',
rotateLabels: -20
},
yAxis1: {
axisLabelDistance: -10,
//axisLabel: ''
},
yAxis2: {
axisLabelDistance: -10,
//axisLabel: ''
},
},
title: {
enable: false,
text: 'Title'
}
};
mycSensorsMixedGraph.chartTimeFormat = mchelper.cfg.dateFormat;
function updateChart(){
mycSensorsMixedGraph.isSyncing = true;
MetricsFactory.getMetricsData({"variableId":config.variableId, "chartType":"multiChart", "start": new Date().getTime() - config.chartFromTimestamp, "enableDetailedKey": config.enableUniqueName === undefined ? false : config.enableUniqueName}, function(resource){
if(resource.length > 0){
mycSensorsMixedGraph.chartData = resource[0].chartData;
//Update display time format
mycSensorsMixedGraph.chartTimeFormat = resource[0].timeFormat;
mycSensorsMixedGraph.chartOptions.chart.xAxis.tickFormat = function(d) {return $filter('date')(d, mycSensorsMixedGraph.chartTimeFormat, mchelper.cfg.timezone)};
mycSensorsMixedGraph.chartOptions.chart.interpolate = config.chartInterpolate;
if(resource[0].unit === ''){
mycSensorsMixedGraph.chartOptions.chart.yAxis1.tickFormat = function(d){return d3.format('.0f')(d);};
}else{
//Not displaying properly axis unit, there is an issue
if(config.useInteractiveGuideline){
mycSensorsMixedGraph.chartOptions.chart.yAxis1.tickFormat = function(d){return d3.format('.02f')(d) + ' ' + resource[0].unit;};
}else{
mycSensorsMixedGraph.chartOptions.chart.yAxis1.tickFormat = function(d){return d3.format('.02f')(d)};
}
}
if(resource[0].unit2 === ''){
mycSensorsMixedGraph.chartOptions.chart.yAxis2.tickFormat = function(d){return d3.format('.0f')(d);};
}else{
mycSensorsMixedGraph.chartOptions.chart.yAxis2.tickFormat = function(d){return d3.format('.02f')(d) + ' ' + resource[0].unit2;};
}
}else{
if(config.variableId.length !== 0){
mycSensorsMixedGraph.showError = true;
}
}
mycSensorsMixedGraph.isSyncing = false;
if(mycSensorsMixedGraph.showLoading){
mycSensorsMixedGraph.showLoading = false;
}
});
}
function updateVariables(){
if(mycSensorsMixedGraph.isSyncing){
return;
}else if(config.variableId.length !== 0){
updateChart();
}
}
//load graph initially
updateVariables();
// refresh every second
var promise = $interval(updateChart, config.refreshTime*1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function(){
$interval.cancel(promise);
});
}).controller('mycSensorsMixedGraphEditController', function($scope, $interval, config, mchelper, $filter, TypesFactory, CommonServices){
var mycSensorsMixedGraphEdit = this;
mycSensorsMixedGraphEdit.onVariableTypeChange = function(){
if(config.variableType.length > 0){
TypesFactory.getSensorVariables({"variableType":config.variableType}, function(response){
mycSensorsMixedGraphEdit.variables = response;
var newVariableId = [];
response.forEach(function(item) {
if(config.variableId.indexOf(item.id.toString()) !== -1){
newVariableId.push(item.id.toString());
}
});
config.variableId = newVariableId;
});
}else{
mycSensorsMixedGraphEdit.variables = {};
config.variableId = [];
}
};
//Pre load
mycSensorsMixedGraphEdit.cs = CommonServices;
//Load variable types
mycSensorsMixedGraphEdit.variableTypes = TypesFactory.getSensorVariableTypes({"metricType":["Double","Binary","Counter"]});
if(config.variableType.length > 0){
var variableIdRef = config.variableId;
mycSensorsMixedGraphEdit.onVariableTypeChange();
config.variableId = variableIdRef;
}
});

View File

@@ -0,0 +1,120 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" placeholder="{{'REFRESH_TIME_SECONDS' | translate}}" ng-model="config.refreshTime" pf-validation="mycSensorsMixedGraphEdit.cs.isNumber(input)" required>
<span class="help-block">{{ 'VALIDATION_ERROR_NUMBER' | translate }}</span>
</div>
<div class="form-group">
<input ng-model="config.useInteractiveGuideline" type="checkbox"/>
<label class="control-label">{{ 'USE_INTERACTIVE_GUIDE_LINE' | translate }}</label>
</div>
<div class="form-group">
<input ng-model="config.enableUniqueName" type="checkbox"/>
<label class="control-label">{{ 'ENABLE_UNIQUE_NAME' | translate }}</label>
</div>
<div class="form-group">
<label>{{ 'MARGIN' | translate }}</label>
<table class="adf-table">
<tr>
<td>
<label>{{ 'LEFT' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="left" placeholder="{{'LEFT' | translate}}" ng-model="config.marginLeft" pf-validation="mycSensorsMixedGraphEdit.cs.isNumber(input)" required>
</td>
<td>
<label class="mc-margin-right">{{ 'RIGHT' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="right" placeholder="{{'RIGHT' | translate}}" ng-model="config.marginRight" pf-validation="mycSensorsMixedGraphEdit.cs.isNumber(input)" required>
</td>
</tr>
<tr>
<td>
<label>{{ 'TOP' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="top" placeholder="{{'TOP' | translate}}" ng-model="config.marginTop" pf-validation="mycSensorsMixedGraphEdit.cs.isNumber(input)" required>
</td>
<td>
<label>{{ 'BOTTOM' | translate }}</label>
</td>
<td>
<input class="form-control" type="number" id="bottom" placeholder="{{'BOTTOM' | translate}}" ng-model="config.marginBottom" pf-validation="mycSensorsMixedGraphEdit.cs.isNumber(input)" required>
</td>
</tr>
</table>
</div>
<div class="form-group">
<label>{{ 'INTERPOLATE_TYPE' | translate }}</label>
<select class="form-control" pf-select ng-model="config.chartInterpolate" required>
<option value="" ng-hide="true"></option>
<option value="linear">{{ 'LINEAR' | translate }}</option>
<option value="basis">{{ 'BASIS' | translate }}</option>
<option value="cardinal">{{ 'CARDINAL' | translate }}</option>
<option value="monotone">{{ 'MONOTONE' | translate }}</option>
<option value="bundle">{{ 'BUNDLE' | translate }}</option>
<option value="step-before">{{ 'STEP_BEFORE' | translate }}</option>
<option value="step-after">{{ 'STEP_AFTER' | translate }}</option>
<option value="basis-open">{{ 'BASIS_OPEN' | translate }}</option>
<option value="basis-closed">{{ 'BASIS_CLOSED' | translate }}</option>
<option value="cardinal-open">{{ 'CARDINAL_OPEN' | translate }}</option>
<option value="cardinal-closed">{{ 'CARDINAL_CLOSED' | translate }}</option>
</select>
</div>
<div class="form-group">
<label>{{ 'TIME_RANGE' | translate }}</label>
<select id="panelSize" class="form-control" pf-select ng-model="config.chartFromTimestamp" required>
<option value="" ng-hide="true"></option>
<option value="300000">{{ 'LAST_5_MINUTES' | translate }}</option>
<option value="3600000">{{ 'LAST_HOUR' | translate }}</option>
<option value="21600000">{{ 'LAST_6_HOURS' | translate }}</option>
<option value="43200000">{{ 'LAST_12_HOURS' | translate }}</option>
<option value="86400000">{{ 'LAST_DAY' | translate }}</option>
<option value="604800000">{{ 'LAST_WEEK' | translate }}</option>
<option value="2419200000">{{ 'LAST_MONTH' | translate }}</option>
<option value="31536000000">{{ 'LAST_YEAR' | translate }}</option>
</select>
</div>
<div class="form-group">
<label>{{ 'SENSOR_VARIABLE_TYPE' | translate }}</label>
<select id="senVarsTypes" class="form-control" multiple pf-select data-live-search="true" ng-model="config.variableType" ng-change="mycSensorsMixedGraphEdit.onVariableTypeChange()" required>
<option value="" ng-hide="true"></option>
<option ng-repeat="vType in mycSensorsMixedGraphEdit.variableTypes" value="{{vType.id}}" ng-selected="config.variableType.indexOf(vType.id) !== -1 ">{{vType.displayName}}</option>
</select>
</div>
<div class="form-group">
<label>{{ 'SENSOR_VARIABLE' | translate }}</label>
<select id="senVars" class="form-control" multiple pf-select data-live-search="true" ng-model="config.variableId" required>
<option value="" ng-hide="true"></option>
<option ng-repeat="res in mycSensorsMixedGraphEdit.variables" ng-bind-html="res.displayName | mcResourceRepresentation" value="{{res.id}}"
ng-selected="config.variableId.indexOf(res.id.toString()) !== -1 "></option>
</select>
</div>
</form>

View File

@@ -0,0 +1,38 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<div ng-if="config.variableId.length !== 0">
<!-- Loading icon disaplay -->
<div ng-if="mycSensorsMixedGraph.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-if="mycSensorsMixedGraph.showError">
<div ng-include src="'partials/common-html/error-sm.html'"></div>
</div>
<div ng-if="!(mycSensorsMixedGraph.showLoading || mycSensorsMixedGraph.showError)">
<!-- <span ng-bind-html="mycSensorsMixedGraph.resourceName | mcResourceRepresentation"></span> -->
<nvd3 id="msg-{{config.variableId.join('-')}}" options='mycSensorsMixedGraph.chartOptions' data="mycSensorsMixedGraph.chartData"></nvd3>
<div ng-if="config.variableId.length === 0" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>
</div>
</div>
<div ng-if="config.variableId.length == 0" ng-include src="'partials/common-html/no-items-filter-sm.html'"></div>

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
// don't forget to declare this service module as a dependency in your main app constructor!
//http://js2.coffee/#coffee2js
//https://coderwall.com/p/r_bvhg/angular-ui-bootstrap-alert-service-for-angular-js
'use strict';
angular.module('adf.widget.myc-sunrisetime', [])
.config(function(dashboardProvider){
dashboardProvider
.widget('mycSunriseTime', {
title: 'Sunrise and sunset time',
description: 'Displays sunrise and sunset time from MyController configuration',
templateUrl: 'controllers/adf-widgets/adf-myc-sunrisetime/view.html?mcv=29',
controller: 'mycSunriseController',
controllerAs: 'mycSunriseTime',
config: {
refreshTime:300,
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-sunrisetime/edit.html?mcv=29'
}
});
})
.controller('mycSunriseController', function($scope, $interval, config, mchelper, $filter, SettingsFactory){
var mycSunriseTime = this;
mycSunriseTime.isSyncing = false;
mycSunriseTime.showLoading = true;
function updateLocationSettings(){
if(mycSunriseTime.isSyncing){
return;
}
mycSunriseTime.isSyncing = true;
SettingsFactory.getLocation(function(response){
mycSunriseTime.sunriseTime = $filter('date')(response.sunriseTime, mchelper.cfg.timeFormatWithoutSeconds, mchelper.cfg.timezone);
mycSunriseTime.sunsetTime = $filter('date')(response.sunsetTime, mchelper.cfg.timeFormatWithoutSeconds, mchelper.cfg.timezone);
mycSunriseTime.latitude = response.latitude;
mycSunriseTime.longitude = response.longitude;
mycSunriseTime.name = response.name;
mycSunriseTime.isSyncing = false;
if(mycSunriseTime.showLoading){
mycSunriseTime.showLoading = false;
}
});
};
updateLocationSettings();
// refresh every five minutes
var promise = $interval(updateLocationSettings, config.refreshTime*1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function(){
$interval.cancel(promise);
});
});

View File

@@ -0,0 +1,23 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" ng-model="config.refreshTime">
</div>
</form>

View File

@@ -0,0 +1,28 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- Loading icon disaplay -->
<div ng-show="mycSunriseTime.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-hide="mycSunriseTime.showLoading">
<div class="adf-mycsr">
<div class="adf-mycsr-time"><i class="wi wi-sunrise"></i>{{mycSunriseTime.sunriseTime}}<i class="wi wi-sunset"></i>{{mycSunriseTime.sunsetTime}}</div>
<div class="adf-mycsr-location"><i class="fa fa-map-marker"></i>{{mycSunriseTime.name}}</div>
</div>
</div>

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com)
* and other contributors as indicated by the @author tags.
*
* 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.
*/
// don't forget to declare this service module as a dependency in your main app constructor!
//http://js2.coffee/#coffee2js
//https://coderwall.com/p/r_bvhg/angular-ui-bootstrap-alert-service-for-angular-js
'use strict';
angular.module('adf.widget.myc-time', [])
.config(function(dashboardProvider){
dashboardProvider
.widget('mycTime', {
title: 'MyController time',
description: 'Displays date and time of MyController',
templateUrl: 'controllers/adf-widgets/adf-myc-time/view.html?mcv=29',
controller: 'mycTimeController',
controllerAs: 'mycTime',
config: {
datePattern: 'MMM dd, yyyy',
refreshTime:120,
},
edit: {
templateUrl: 'controllers/adf-widgets/adf-myc-time/edit.html?mcv=29'
}
});
})
.controller('mycTimeController', function($scope, $interval, config, mchelper, $filter, StatusFactory){
var mycTime = this;
mycTime.isSyncing = false;
mycTime.showLoading = true;
mycTime.mycTimestamp = {};
function updateDateTime(){
mycTime.time = $filter('date')(mycTime.mycTimestamp.timestamp, mchelper.cfg.timeFormat, mchelper.cfg.timezone);
mycTime.date = $filter('date')(mycTime.mycTimestamp.timestamp, config.datePattern, mchelper.cfg.timezone);
mycTime.timezone = mchelper.cfg.timezone;
mycTime.timezoneString = mchelper.cfg.timezoneString;
};
function getTimestampFromServer(){
mycTime.isSyncing = true;
StatusFactory.getTimestamp(function(response){
mycTime.mycTimestamp = response;
updateDateTime();
mycTime.isSyncing = false;
if(mycTime.showLoading){
mycTime.showLoading = false;
}
});
};
function setDateAndTime(){
if(mycTime.isSyncing){
return;
}
if((mycTime.mycTimestamp.timestamp/1000 | 0) % config.refreshTime == 0){
if(!mycTime.isSyncing){
getTimestampFromServer();
}
}else{
mycTime.mycTimestamp.timestamp += 1000;
updateDateTime();
}
}
getTimestampFromServer();
setDateAndTime();
// refresh every second
var promise = $interval(setDateAndTime, 1000);
// cancel interval on scope destroy
$scope.$on('$destroy', function(){
$interval.cancel(promise);
});
});

View File

@@ -0,0 +1,31 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<form role="form">
<div class="form-group">
<label>{{ 'REFRESH_TIME_SECONDS' | translate }}</label>
<input type="text" class="form-control" id="refreshTime" ng-model="config.refreshTime">
</div>
<div class="form-group">
<label for="date">{{ 'DATE_PATTERN' | translate }}</label>
<input type="text" class="form-control" id="date" ng-model="config.datePattern">
</div>
<p class="text-info">
For the list of possible patterns, please have a look at
<a target="_blank" href="https://docs.angularjs.org/api/ng/filter/date">angular date documentation</a>
</p>
</form>

View File

@@ -0,0 +1,28 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- Loading icon disaplay -->
<div ng-show="mycTime.showLoading">
<div ng-include src="'partials/common-html/loading-sm.html'"></div>
</div>
<div ng-hide="mycTime.showLoading">
<div class="adf-myct">
<div class="adf-myct-time">{{mycTime.time}}</div>
<div class="adf-myct-date">{{mycTime.date}},<span class="adf-myct-timezone"> {{mycTime.timezoneString}} ({{mycTime.timezone}})</span></div>
</div>
</div>

View File

@@ -0,0 +1,18 @@
<!--
Copyright (C) 2015-2016 Jeeva Kandasamy (jkandasa@gmail.com)
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.
-->
<!-- to avoid 'apply' issue, while changing title of widgets -->