Cuisine
- Author: Charalampos Georgiadis (Software Engineer @ axregio3)
- Git: https://github.com/Event-Riddle/Cuisine
Cuisine is mainly concerned with the construction of the Ui.
The UI was build with AngularJs wich is a structural framework for dynamic web apps. To add AngularJs to your project you just have to download the library from the official website and add it to your javascript folder.
JQuery is a fast, small, and feature-rich JavaScript library. We use the CDN library from JQuery to build the Voting-diagrams.
Bootstrap makes front-end web development faster and easier. We use Bootstrap for the styling of the UI. To add Bootstrap to your project you just have to download the library and add it to your css folder.
To show the incoming events we use CanvasJS. With CanvasJs and the connection via websockets to luculus and services, we make responsive charts which run across devices.
At the same time, we have kept to the colors and shapes of IBM Bluemix. In addition to our own css, we have also used Bootstrap and other libraries to generate a fast development. Since Bluemix used material design we have rebuild styling parts but we also use stylings from other developers to guarantee a unique user experience. Gadgets have also been implemented, e.g. Drag and drop or connection pulping elements with svg. In order To show the user that his activities trigger something and keep in active in the happening.
All librarys, controller, models and router are bound in the index.html. By using the AngularJs widget "ui-view" the individual html pages are loaded dynamically to the index.html.
<div ui-view>
<!--Content here -->
</div>
To get structure to our project external libraries are separated from our own doveloped module-libraries.
(function () {
angular.module('riddle',[
'riddle.core',
'riddle.structure',
'riddle.content',
'riddle.detail'
]);
})();
In the core module third party libraries are added. We use different kind of vendor libs to provide more funktionality in the Ui. You can just inject angular libs to the root scope by reference the third party libraries in the core model.
(function () {
angular.module('riddle.core',[
'ui.router',
'ui.router.stateHelper',
'gm.dragDrop',
'ngSanitize',
'ngResource',
'third-party'
]);
})();
The core router is responsible for the routing between the individual html pages and the other routers. In case of non-existent destination addresses, /struct is always called.
(function(){
angular
.module('riddle.core')
.config(function($urlRouterProvider, $stateProvider){
$urlRouterProvider
.otherwise('/struct');
});
})();
We use the AngularJs pattern for mvc to divide our application into three interconnected parts in order to separate internal representations of information from the ways that information is presented to and accepted from the user.
- Each
Cuisine/public/components/
has its own logic for its modules, controllers, routers and hmtls. - Components can also include their own widget which in turn bring their own mvc with them. We've used widget to separate bootstrap modals and their logic.
Cuisine / public / components / detail / widgetEditFilter / widgetEditFilter.ctrl.js
In the context of client-side JavaScript frameworks, you will find these patterns mentioned frequently.
The MVC pattern separates the application concerns into three distinct parts—Model,View, and Controller. Simply put, the Model represents the application data, a View represents the application’s user interface, and a Controller acts like a middleman between the other two parts and also manages the overall application flow.
In the context of JavaScript applications, a Model is usually a JavaScript object or a collection of objects. A View consists of HTML markup from the document object model (DOM) tree. A Controller acts as a layer that connects the Model and the View. The Controller might do tasks such as handling events, validating data, performing some business-specific processing, and changing the model data.
The “Whatever” used by the pattern can be a View Model or a Controller or whatever suits the application requirements. JavaScript frameworks such as AngularJS are based on the MVW pattern.
'Source' (Beginning SOLID Principles and Design Patterns for ASP.NET Developers).
In order to offer faster data processing and static variables, a service interface was implemented. That offers a browser internal database.
Cuisine/public/components/detail/service.cDB.js
The interface provides three public methods to separate view logic and database logic from each other.
return {
getData: _getData,
getItem: _getItem,
addData: _addData
}
Cuisine/public/components/detail/service.api.js
To get a loose coupling for the http get and post calls, our interface offers two public methods. The api call is triggered by moving the elements in the chain of event handlers and by configuring the individual elements. For example if you add or change the configuration of the filter, correlator and so on
- The configType is set variable and contains the names of the elements present in the chain.
- The methods getConfig and postConfig can be used independently for which handler the data is required.
See also:
Link: http://riddle-api.mybluemix.net/
return {
api: getConfig(),
apiPost: postConfig()
}
function getConfig() {
return $resource(
'http://riddle-api.mybluemix.net/api/v1/config/:configType',{
configType:'@configType'
},{
'getConfig': {method: 'GET', isArray: true, cache: false}
}
);
}
function postConfig() {
return $resource(
'http://riddle-api.mybluemix.net/api/v1/config/:configType',{
configType:'@configType'
},{
'postConfig': {
method: 'POST', isArray: true, cache:false,
headers: {
'content-type':'application/x-www-form-urlencoded'
}
}
}
);
}
In this controller the http requests for activating and deactivating the chain are dealt with.
//API calls
var urlLuculus = 'http://lucullus.mybluemix.net/api/v1/start';
var urlDeactivate = 'http://lucullus.mybluemix.net/api/v1/stop';
Furthermore, the handler chain is set when the user interface is loaded.
Cuisine/public/components/content/ctrl.js
var urlUser = 'http://riddle-api.mybluemix.net/api/v1/config/user';
This output shows how the event handlers are set in the toolbar and in the handler chain.
{"chain":[{"name":"filter","order":1},{"name":"correlator","order":3}],"toolbar":[{"name":"unique filter","order":4},{"name":"dedub","order":2}]}
We use canvasJsTo display all incoming and outgoing events and to actively participate the user.
cont.dps = [
{ label: "GateWay", y: 1 },
{ label: "OpenWhisk", y: 1 },
];
//canvasJS
var chart = new CanvasJS.Chart("chartContainer", {
theme: 'theme2',
animationEnabled: false, // change to true
data: [
{
// Change type to "bar", "area", "spline", "pie",etc.
type: "column",
dataPoints: cont.dps
}
]
});
chart.render();
The WebSocket specification specifies an API that creates socket connections between a Web browser and a server. In short, there is a persistent connection between the client and the server and both parties can start sending data at any time. We have used websockets to show all the events that are coming from the iot gateway and which are triggered in openwhisk.
var ws = 'ws://lucullus.mybluemix.net/count';
ws = new WebSocket(ws);
ws.onopen = function (e) {
console.log("onopen:", arguments);
};
ws.onclose = function (e) {
console.log("onclose:", arguments);
};
ws.onmessage = function (e) {
var data = JSON.parse(e.data);
$rootScope.$apply(function() {
cont.gateWay = data['count_in'];
cont.opw = data['count_out'];
cont.dps[0] = { label: "GateWay", y: cont.gateWay };
cont.dps[1] = { label: "OpenWhisk", y: cont.opw };
//update Chart
chart.render();
});
};
ws.onerror = function (e) {
console.log(e);
console.log("onerror:", arguments);
};
See also:
Link: http://riddle-api.mybluemix.net/
Check the UI: