Update git submodules
[docs.git] / docs / developer-guide / dluxapps.rst
1 =================
2 DLUX Applications
3 =================
4
5 Setup and Run
6 -------------
7
8 Required Technology Stack
9 ~~~~~~~~~~~~~~~~~~~~~~~~~
10
11 -  AngularJS (JavaScript client-side framework, http://www.angularjs.org
12    )
13
14 Run DLUX
15 ~~~~~~~~
16
17 To turn on the DLUX Applications, install feature via running following
18 command on the Karaf console -
19
20 ::
21
22     feature:install odl-dluxapps-applications
23
24 The above command will install odl-dlux-core along with all DLUX applications. Once this
25 feature is successfully installed, access the UI at
26 http://localhost:8181/index.html. The default credentials for login are
27 admin/admin.
28
29 DLUX Modules
30 ------------
31
32 DLUX modules are the individual features such as nodes and topology.
33 Each module has a defined structure and you can find all existing
34 modules at
35 https://github.com/opendaylight/dlux/tree/stable/boron/modules.
36
37 Module Structure
38 ~~~~~~~~~~~~~~~~
39
40 -  module\_folder
41
42    -  <module\_name>.module.js
43
44    -  <module\_name>.controller.js
45
46    -  <module\_name>.services.js
47
48    -  <module\_name>.directives.js
49
50    -  <module\_name>.filter.js
51
52    -  index.tpl.html
53
54    -  <a\_stylesheet>.css
55
56 Create New Module
57 ~~~~~~~~~~~~~~~~~
58
59 Define the module
60 ^^^^^^^^^^^^^^^^^
61
62 1. Create an empty maven project and create your module folder under
63    src/main/resources.
64
65 2. Create an empty file with pattern <module\_name>.module.js.
66
67 3. Next, you need to surround the angular module with a define function.
68    This allows RequireJs to see our module.js files. The first argument
69    is an array which contains all the module’s dependencies. The second
70    argument is a callback function, whose body contain the AngularJS
71    code base. The function parameters correspond with the order of
72    dependencies. Each dependency is injected into a parameter, if it is
73    provided.
74
75 4. Finally, you will return the angular module to be able to inject it
76    as a parameter in others modules.
77
78 For each new module, you must have at least these two dependencies :
79
80 -  angularAMD : It’s a wrapper around AngularJS to provide an AMD
81    (Asynchronous Module Definition) support, which is used by RequireJs.
82    For more information see the `AMD
83    documentation <https://github.com/amdjs/amdjs-api/blob/master/AMD.md>`__.
84
85 -  app/core/core.services : This one is mandatory, if you want to add
86    content in the navigation menu, the left bar or the top bar.
87
88 The following are not mandatory, but very often used.
89
90 -  angular-ui-router : A library to provide URL routing.
91
92 -  routingConfig : To set the level access to a page.
93
94 Your module.js file might look like this:
95
96 ::
97
98     define(['angularAMD','app/routingConfig', 'angular-ui-router','app/core/core.services'], function(ng) {
99        var module = angular.module('app.a_module', ['ui.router.state', 'app.core']);
100        // module configuration
101        module.config(function() {
102            [...]
103        });
104       return module;
105     });
106
107 Set the register function
108 ^^^^^^^^^^^^^^^^^^^^^^^^^
109
110 AngularJS allows lazy registration of a module’s components such as
111 controller, factory etc. Once you will install your application, DLUX
112 will load your module javascript, but not your angular component during
113 bootstrap phase. You have to register your angular components to make
114 sure they are available at the runtime.
115
116 Here is how to register your module’s component for lazy initialization
117 -
118
119 ::
120
121     module.config(function($compileProvider, $controllerProvider, $provide) {
122        module.register = {
123          controller : $controllerProvider.register,
124          directive : $compileProvider.directive,
125          factory : $provide.factory,
126          service : $provide.service
127        };
128     });
129
130 Set the route
131 ^^^^^^^^^^^^^
132
133 The next step is to set up the route for your module. This part is also
134 done in the configuration method of the module. We have to add
135 **$stateProvider** as a parameter.
136
137 ::
138
139     module.config(function($stateProvider) {
140        var access = routingConfig.accessLevels;
141        $stateProvider.state('main.module', {
142          url: 'module',
143          views : {
144            'content' : {
145              templateUrl: 'src/app/module/module.tpl.html',
146              controller: 'ModuleCtrl'
147            }
148          }
149        });
150     });
151
152 Adding element to the navigation menu
153 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
154
155 To be able to add item to the navigation menu, the module requires the
156 **NavHelperProvider** parameter in the configuration method.
157 **addToMenu** method in **NavMenuHelper** helper allows an item addition
158 to the menu.
159
160 ::
161
162     var module = angular.module('app.a_module', ['app.core']);
163     module.config(function(NavMenuHelper) {
164         NavMenuHelper.addToMenu('myFirstModule', {
165             "link" : "#/module/index",
166             "active" : "module",
167             "title" : "My First Module",
168             "icon" : "icon-sitemap",
169             "page" : {
170                 "title" : "My First Module",
171                 "description" : "My first module"
172             }
173         });
174     });
175
176 The first parameter is an ID that refers to the level of your menu and
177 the second is a object. For now, The ID parameter supports two levels of
178 depth. If your ID looks like *rootNode.childNode*, the helper will look
179 for a node named *rootNode* and it will append the *childNode* to it. If
180 the root node doesn’t exist, it will create it.
181
182 Link the AngularJS module’s controller file
183 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
184
185 To include the module’s controller file, you can use the
186 NavHelperProvider. It contains a method that will load the given file.
187
188 ::
189
190     [...]
191        NavHelperProvider.addControllerUrl('<path_to_module_folder>/<module_name>.controller');
192
193 This completes your module.js file.
194
195 Create the controller, factory, directive, etc
196 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
197
198 Creating the controller and other components is similar to the module.
199
200 -  First, add the define method.
201
202 -  Second, add the relative path to the module definition.
203
204 -  Last, create your methods as you usually do it with AngularJS.
205
206 For example -
207
208 ::
209
210     define(['<relative_path_to_module>/<module_name>.module'], function(module) {
211        module.register.controller('ModuleCtrl', function($rootScope, $scope) {
212        });
213     });
214
215 Add new application using DLUX modularity
216 -----------------------------------------
217
218 DLUX works as a Karaf based UI platform, where you can create a new
219 Karaf feature of your UI component and install that UI applications in
220 DLUX using blueprint. This page will help you to create and load a new
221 application for DLUX. You don’t have to add new module in DLUX
222 repository.
223
224 Add a new OSGi blueprint bundle
225 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
226
227 The OSGi Blueprint Container specification allows us to use dependency
228 injection in our OSGi environment. Each DLUX application module
229 registers itself via blueprint configuration. Each application will have
230 its own blueprint.xml to place its configuration.
231
232 1. Create a maven project to place blueprint configuration. For
233    reference, take a look at topology bundle, present at
234    https://github.com/opendaylight/dlux/tree/stable/boron/bundles/topology.
235    All the existing DLUX modules' configurations are available under
236    bundles directory of DLUX code.
237
238 2. In pom.xml, you have to add a maven plugin to unpack your module code
239    under generated-resources of this project. For reference, you can
240    check pom.xml of dlux/bundles/topology at
241    https://github.com/opendaylight/dlux/tree/stable/boron/bundles/topology.
242    Your bundle will eventually get deployed in Karaf as feature, so your
243    bundle should contain all your module code. If you want to combine
244    module and bundle project, that should not be an issue either.
245
246 3. Create a blueprint.xml configuration file under
247    src/main/resources/OSGI-INF/blueprint. Below is the content of the
248    blueprint.xml taken from topology bundles’s blueprint.xml. Any new
249    application should create a blueprint.xml in following format -
250
251 ::
252
253     <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
254         <reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/>
255         <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/>
256
257         <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule">
258           <property name="httpService" ref="httpService"/>
259           <property name="loader" ref="loader"/>
260           <property name="moduleName" value="topology "/>
261           <property name="url" value="/src/app/topology"/>
262           <property name="directory" value="/topology"/>
263           <property name="requireJs" value="app/topology/topology.module"/>
264           <property name="angularJs" value="app.topology"/>
265           <property name="cssDependencies">
266               <list>
267                   <value>http://yui.yahooapis.com/3.18.1/build/cssreset/cssreset-min.css</value>
268                   <value>src/app/topology/topology-custom.css</value>
269               </list>
270           </property>
271         </bean>
272     </blueprint>
273
274 In above configuration, there are two references with id httpService and
275 loader. These two beans will already be initialized by dlux-core, so any
276 new application can use them. Without these two bean references, a new
277 application will not be able to register.
278
279 Next is the initialization of your application bean, which will be an
280 instance of class org.opendaylight.dlux.loader.DluxModule. There are 5
281 properties that you should provide in this bean besides the references
282 of httpService and loader. Lets talk about those bean properties in
283 little more detail.
284
285 **moduleName** : Name of your module. This name should be unique in
286 DLUX.
287
288 **url**: This is the url via which RequireJS in DLUX will try to load
289 your module JS/HTML files. Also, this is the url that browser will use
290 to load the static HTML, JS or CSS files. RequireJS in DLUX has a base
291 path of **src**, so all the url should start with /src so RequireJS and
292 the browser can correctly find the files.
293
294 **directory**: In your bundle’s pom.xml, you unpack your module code.
295 This is the directory where your actual static files will reside. The
296 above mentioned url is registered with httpService, so when browser
297 makes a call to that url, it will be redirected to the directory
298 mentioned here. In the above example, all the topology files are present
299 under /topology directory and the browser/RequireJS can access those
300 files with uri /src/app/topology.
301
302 **requireJS**: This is the path to your RequireJS module. If you notice
303 closely, you will see the initial path of RequireJS app/topology in the
304 above example matches with the last part of url. This path will be be
305 used by RequireJS. As mentioned above, we have kept **src** as base path
306 in RequireJS, that is the exact reason that url start with /src.
307
308 **angularJS**: name of your AngularJS module.
309
310 **cssDependencies**: If the application has any external/internal css
311 dependencies, then those can be added here. If you create your own css
312 files, just point to those css files here. Use the url path that you
313 mentioned above, so the browser can find your css file.
314
315 OSGi understands blueprint.xml, once you will deploy your bundle in
316 karaf (or you can create a new feature for your application), karaf will
317 read your blueprint.xml and it will try to register your application
318 with dlux. Once successful, if you refresh your dlux UI, you will see
319 your application in left hand navigation bar of dlux.
320
321 Yang Utils
322 ----------
323
324 Yang Utils are used by UI to perform all CRUD operations. All of these
325 utilities are present in yangutils.services.js file. It has following
326 AngularJS factories -
327
328 -  **arrayUtils** – defines functions for working with arrays.
329
330 -  **pathUtils** – defines functions for working with xpath (paths to
331    APIs and subAPIs). It divides xpath string to array of elements, so
332    this array can be later used for search functions.
333
334 -  **syncFact** – provides synchronization between requests to and from
335    OpenDaylight when it’s needed.
336
337 -  **custFunct** – it is linked with
338    apiConnector.createCustomFunctionalityApis in yangui controller in
339    yangui.controller.js. That function makes it possible to create some
340    custom function called by the click on button in index.tpl.html. All
341    custom functions are stored in array and linked to specific subAPI.
342    When particular subAPI is expanded and clicked, its inputs (linked
343    root node with its child nodes) are displayed in the bottom part of
344    the page and its buttons with custom functionality are displayed
345    also.
346
347 -  **reqBuilder** – Builds object in JSON format from input fields of
348    the UI page. **Show Preview** button on Yang UI use this builder.
349    This request is sent to OpenDaylight when button PUT or POST is
350    clicked.
351
352 -  **yinParser** – factory for reading .xml files of yang models and
353    creating object hierarchy. Every statement from yang is represented
354    by a node.
355
356 -  **nodeWrapper** – adds functions to objects in tree hierarchy created
357    with yinParser. These functions provide functionality for every type
358    of node.
359
360 -  **apiConnector** – the main functionality is filling the main
361    structures and linking them. Structure of APIs and subAPIs which is
362    two level array - first level is filled by main APIs, second level is
363    filled by others sub APIs. Second main structure is array of root
364    nodes, which are objects including root node and its children nodes.
365    Linking these two structures is creating links between every subAPI
366    (second level of APIs array) and its root node, which must be
367    displayed like inputs when subAPI is expanded.
368
369 -  **yangUtils** – some top level functions which are used by yangui
370    controller for creating the main structures.
371