We love contributions. This page is intended to help you get started hacking on the code, it contains various information on technology and tools together with code walk-throughs.
Welcome and enjoy! Its hawt, but stay cool! :)
Check out How To Build The Code if you want to start hacking on the source.
hawtio is a single page application which is highly modular and capable of dynamically loading plugins based on the capability of the server.
You may want to check out:
The following are recommended if you want to contribute to the code
- hawtio Typescript API documentation Typedoc output for all of the typescript code on hawtio's master branch
- IntelliJ IDEA EAP 12 or later as this has TypeScript support and is the daddy of IDEs!
- There are other TypeScript plugins if you prefer Sublime, Emacs or VIM. (Unfortunately we're not aware of an eclipse plugin yet).
- AngularJS plugin for IDEA if you use IDEA then this plugin really helps work with Angular JS
- AngularJS plugin for Chrome which is handy for visualising scopes and performance testing etc.
- JSONView plugin for Chrome makes it easy to visualise JSON returned by the REST API of Jolokia
- Apache Maven 3.0.3 or later
- gruntjs a build tool for JavaScript. See nearly the beginning of this document for details of how to install and use.
- Dash.app is a handy tool for browsing API documentation for JavaScript, HTML, CSS, jquery, AngularJS etc.
For those interested in contributing or just learning how to build single page applications, here is a list of the various open source libraries used to build hawtio:
- AngularJS is the web framework for performing real time two-way binding of HTML to the model of the UI using simple declarative attributes in the HTML.
- jolokia is the server side / JVM plugin for exposing JMX as JSON over HTTP. It's awesome and is currently the only server side component of hawtio.
- TypeScript is the language used to implement the console; it compiles to JavaScript and adds classes, modules, type inference & type checking. We recommend IntelliJ IDEA EAP 12 or later for editing TypeScript--especially if you don't use Windows or Visual Studio (though there is a Sublime Text plugin too).
- angular ui is a library of AngularJS additions and directives
- d3 is the visualization library used to do the force layout graphs (for example the diagram view for ActiveMQ)
- cubism implements the real-time horizon charts
- dagre for graphviz style layouts of d3 diagrams (e.g. the Camel diagram view).
- ng-grid an AngualrJS based table/grid component for sorting/filtering/resizing tables
- marked for rendering Github-flavoured Markdown as HTML
- DataTables for sorted/filtered tables (though we are migrating to ng-grid as its a bit more natural for AngularJS)
- DynaTree for tree widget
- jQuery small bits of general DOM stuff, usually when working with third-party libraries which don't use AngularJS
- Twitter Bootstrap for CSS
- Toastr for notifications
We're not yet using it but these look handy too:
- jquery-mobile-angular-adapter for easy interop of jQuery Mobile and AngularJS
- breezejs for easy LINQ / ActiveRecord style database access and synchronization
If you are interested in working on the code the following references and articles have been really useful so far:
- available AngularJS Directives
- angularjs API
- bootstrap API
- cubism API
- d3 API
- ng-grid API
- datatables API
- javascript API
- sugarjs API
- icons from Font Awesome
- Fun with AngularJS is great overview on AngularJS!
- egghead.io various short angularjs videos
- great angularjs talk
- AngularJS plugins
- AngularJS tips and tricks
- more AngularJS magic to supercharge your webapp
- AngularJS questions on stackoverflow
- Modeling Data and State in Your AngularJS Application
- 6 Common Pitfalls Using Scopes
If you fancy contributing--and we love contributions!--the following should give you an overview of how the code hangs together:
- hawtio is a single page web application, from this single page of HTML
- We use AngularJS routing to display different partial pages depending on which tab/view you choose. You'll notice that the partials are simple HTML fragments which use AngularJS attributes (starting with ng-) along with some {{expressions}} in the markup.
- Other than the JavaScript libraries listed above which live in webapp/lib and are included in the index.html, we then implement AngularJS controllers using TypeScript. All the typescript source is in the in files in webapp/app/pluginName/js/ directory which is then compiled into the webapp/app/app.js file
- To be able to compile with TypeScript's static type checking we use the various TypeScript definition files to define the optional statically typed APIs for the various APIs we use
- The controllers use the Jolokia JavaScript API to interact with the server side JMX MBeans
Tabs can dynamically become visible or disappear based on the following:
- the contents of the JVM
- the plugins,
- and the current UI selection(s).
Plugins can register new top-level tabs by adding to the topLevelTabs on the workspace which can be dependency injected into your plugin via AngularJS Dependency Injection.
The isValid() function is then used to specify when this top-level tab should be visible.
You can register subLevelTabs which are then visible when the right kind of MBean is selected.
For more detail check out the plugin documentation.
We recommend you enable Source Maps in your browser (e.g. in Chrome) for easier debugging by clicking on the bottom-right Settings icon in the JavaScript Console and enabling Source Maps support such as in this video.
To help IDEA navigate to functions in your source and to avoid noise, you may want to ignore some JavaScript files in IDEA so that they are not included in the navigation. Go to Settings/Preferences -> File Types -> Ignore Files
then add these patterns to the end:
*.min.js;*-min.js
Ignoring these files will let IDEA ignore the minified versions of the JavaScript libraries.
Then select the generated webapp/app/app.js file in the Project Explorer, right-click and select Mark as Plain Text so that it is ignored as being JavaScript source. This hint came from this forum thread, hopefully there will be a nicer way to do all this one day!
Open the JavaScript Console and select the Console tab so you can type expressions into the shell. Select part of the DOM of the scope you want to investigate Right click and select Inspect Element In the console type the following
s = angular.element($0).scope()
You have now defined a variable called s which contains all the values in the active AngularJS scope so you can navigate into the scope and inspect values or invoke functions in the REPL, etc.
Open the JavaScript Console and select the Console tab so you can type expressions into the shell. Select a DOM element (e.g., button) for which you want to check what jquery event handlers are attached. In the console type:
jQuery._data($0, "events")
You'll get array of events. When you expand the events and go to "handler" member (e.g., click->0->handler
), you can:
- in Firebug right click
function()
and select Inspect in Script Panel - in Chrome dev tools right click
function()
and select Show Function Definition
to see the body of handler method.
When binding models to HTML templates; its always a good idea to use a level of indirection between the $scope and the property. So rather than binding to $scope.name, bind to $scope.entity.name then have code like
$scope.entity = { "name": "James" };
This means to that to reset the form you can just do
$scope.entity = {};
And you can then refer to the entire entity via $scope.entity. Another reason for doing this is that when you have lots of nested scopes; for example when using nested directives, or using includes or layouts, you don't get inheritence issues; since you can acess $scope.entity from child scopes fine.
Its often useful to use $routeParams to get the URI template parameters. However due to the rules on who gets the $routeParams injected when using layouts and so forth, the $routeParams can be empty.
So put all code that uses $routeParams inside the $routeChangeSuccess callback:
$scope.$on('$routeChangeSuccess', function(event, routeData){
// process $routeParams now...
});
hawtio uses local storage to store preferences and preferred views for different kinds of MBean type and so forth.
You can view the current Local Storage in the Chrome developer tools console in the Resources / Local Storage tab.
If you ever want to clear it out in Chrome on OS X you'll find this located at ~/Library/Application Support/Google/Chrome/Default/Local Storage
.