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