You are viewing a plain text version of this content. The canonical link for it is here.
Posted to infrastructure-dev@apache.org by Sam Ruby <ru...@intertwingly.net> on 2014/09/24 02:39:50 UTC
Whimsy board agenda tool overview and roll call 'attend' button implementation
Overview of the board agenda tool:
1) There is code which parses an agenda, combining it with some
information from other sources like LDAP, and returning a datastructure
consisting of hashes, arrays, and strings. This datastructure is
serialized as JSON and send to the client. The parsing code can be
found here:
https://svn.apache.org/repos/infra/infrastructure/trunk/projects/whimsy/lib/whimsy/asf/agenda.rb
https://svn.apache.org/repos/infra/infrastructure/trunk/projects/whimsy/lib/whimsy/asf/agenda
2) In addition to static HTML, stylesheets, and JavaScript, the client
makes use of Angular.JS which provides model, views, and controllers on
the client. A key feature of Angular.JS is two way data binding which
means that changes to the model are automatically reflected in views and
vice versa. Models in Angular.JS can be POJOs (plain old JavaScript
objects), and in the board agenda tool they represent items resulting
from the parsing of the JSON.
https://angularjs.org/
3) CSS from Bootstrap add style and animation.
http://getbootstrap.com/
4) Wunderbar and ruby2js makes it easy to create readable and correct
HTML and JavaScript from Ruby.
https://github.com/rubys/wunderbar#readme
https://github.com/rubys/ruby2js#readme
---
Updating the roll call demonstrates a number of these concepts. For
starters, the code for the button itself:
_ng_template.attend_button! do
_button.btn.btn_primary '{{ attend_label }}', ng_controller:
'Attend',
ng_click: 'click()', ng_disabled: 'disabled'
end
https://svn.apache.org/repos/infra/infrastructure/trunk/projects/whimsy/www/board/agenda/partials/section._html
This is a template as the button is conditionally shown.
'attend_button' is the identifier. 'btn' and 'btn_primary' correspond
to Bootstrap styles. The attend_label is computed. This button is
associted with the 'Attend' controller. Clicking the button calls the
click() function, and the 'disabled' value controls whether or not this
button is disabled.
With this in place, there are a number of todos: (1) decide when the
button is shown, (2) defind a controller that (a) sets the attend_button
and disabled values and (b) implements click.
Inside the Section controller (an agenda section corresponds to a page),
you will find the following code:
if item.title == 'Roll Call' and not @minutes['Roll Call']
Actions.add 'attend-button'
end
https://svn.apache.org/repos/infra/infrastructure/trunk/projects/whimsy/www/board/agenda/js/app._js
This adds the button if the page the user is viewing has a title of
'Roll Call' and there aren't minutes yet for the Roll Call.
Next up, the Attend controller. First the attend_label property:
controller :Attend do
def attend_label
if @item.people[@user] and @item.people[@user].attending
'regrets'
else
'attend'
end
end
...
end
Looking at the JSON for an agenda makes it easier to understand this code:
https://whimsy.apache.org/board/agenda/2014-10-15.json
The item with a title of "Roll Call" has a list of people. If the user
viewing this page is in that list, and is listed as attending, then the
button label will read 'regrets', otherwise it will read attend'.
Now for click handing:
controller :Attend do
...
def click()
if @attend_label == 'regrets'
data = {action: 'regrets', name: @item.people[@user].name}
else
data = {action: 'attend', userid: @user}
end
data.agenda = Data.get('agenda')
@disabled = true
$http.post('../json/attend', data).success { |response|
Agenda.put response
}.error { |data|
$log.error data.exception + "\n" + data.backtrace.join("\n")
alert data.exception
}.finally {
@disabled = false
}
end
end
Based on the attend label, different data will be sent on the request.
Additionally, the name of the agenda file will be passed. Before the
request is sent, @disabled is set to true, thereby disabling the button.
Upon receipt of a successful response, the entire agenda is replaced
with data from the server, causing everything in the browser window to
be re-evaluated. On a failure, the exception is logged and a pop-up
alert is shown. Finally, the button is re-enabled.
This leaves a final task of writing server logic that takes action based
on the data sent, and returns either an exception or an Agenda in JSON
format. This logic can be found here:
https://svn.apache.org/repos/infra/infrastructure/trunk/projects/whimsy/www/board/agenda/json/attend._json
Those interested may want to explore the generate JavaScript:
https://whimsy.apache.org/board/agenda/js/app.js
Search for AsfBoardAgenda.controller("Attend", function(...) {...});
Of particular note, 'attend_label' is a property as it was defined
without any parenthesis, and 'click' is a function as it was defined
with parenthesis. This is because properties and functions are handled
differently in JavaScript.