Document Action Logs, Including "Limitless" User Comments

Action Logs are something I'm sure we've all added to the bottom of a Domino web form. Here's an example of one I added to a recent Domino-based app I created and then wrapped with Bootstrap.


The log is shown to the user as a three column table(when, who, what) with the latest action first.

My approach to storing this data has always been to use a single multi-value text field. The value stored might look something like this:

24/09/2013 17:08:12^^24 Sep '13^^17:08^^Joe Bloggs/ROCKALL^^Document Created
24/09/2013 17:08:12^^24 Sep '13^^17:08^^System Admin/ROCKALL^^'New Document' email sent to related users
24/09/2013 17:21:57^^24 Sep '13^^17:21^^Jake Howlett/ROCKALL^^Status changed to Published
24/09/2013 17:21:57^^24 Sep '13^^17:21^^System Admin/ROCKALL^^'Document Published' email sent to related users

This field is built up by recurring calls to a LotusScript method called LogAction() in the WQS agent of the document.

The HTML table the user sees is generated in a Computed Value section that uses an @For() loop to create a <tr> for each entry in the log.

There are inherent limitations to this approach:

  • Limit of the amount of data the backend field can store.
  • Limit of HTML the Computed Value that displays the table on the web can store.

These limitations can be worked round, but for the majority of cases the above solution will suffice.

Adding Comments

The limitations became an issue recently when I was tasked with including user's comments in the Action Log. So that the log would look something like this:


Notice the comment on the 2nd row down!?

By adding comments, the chance of reaching the data limitations has greatly increased, becoming almost inevitable.

To avoid the limitation I chose to add each individual comment in a field of its own.

Each time an action is performed and logged with an accompanying comment a field called ActionComment_X is added, where X is the number stored in a field called ActionCommentCount incremented by 1.

The backend documents start to look like this:


Then, in the ActionLog field we add a reference to this comment field as an extra delimited field on each line. Notice in the values below that the 3rd line down ends in ^^ActionComment_1

24/09/2013 17:08:12^^24 Sep '13^^17:08^^Joe Bloggs/ROCKALL^^Document Created^^
24/09/2013 17:08:12^^24 Sep '13^^17:08^^System Admin/ROCKALL^^'New Document' email sent to related users^^
24/09/2013 17:21:57^^24 Sep '13^^17:21^^Jake Howlett/ROCKALL^^Status changed to Published^^ActionComment_1
24/09/2013 17:21:57^^24 Sep '13^^17:21^^System Admin/ROCKALL^^'Document Published' email sent to related users^^

When the HTML table is generated and each line in the ActionLog field is exploded on the delimiter ("^^") we can simply add the value stored in the comment field, like so:

@If(@Word(log[n];6)=""; ""; @GetField(@Word(log[n];6))

All that remains is to markup the comment in a <blockquote> tag and add a sprinkle of CSS to make it look like a quote.

The only remaining issue is that, if people type in huge great long comments, the amount of HTML generated by the Computed Value quickly reaches its limit.

To get round this I added an ellipsis (copying off Gmail a little) to the end of a truncated comment like so:


Clicking on this ellipsis "button" uses Ajax to go fetch the rest of the comment.

It's a solution I'm happy with and I've been sitting on for a while, thinking of sharing. Just don't know what interest there is? If there is some I can build a demo/download.

Comment Icon There are 6 comments in 3 threads Read - Add

Bootstrap Advanced Date Picker Plugin

For some time now I've been creating date fields in Bootstrap-based websites that look like this:


Clicking either in the field or on the button next to it launches a date-picker, like this:


In the Notes Form the Date Field is configured in such a way that it accepts dates in the format 12-Dec-2009 (while storing them in normal Notes DateTime format of course).

The field properties are like so:



It all works well and users like them. Not least because there's no confusion over whether it's mm/dd or dd/mm! When the document is viewed in read-mode the dates are displayed in the same format automatically!

The only downside is that the field is marked up as "readonly" to prevent users trying to type in their own dates, which forces them to use the picker. Ok for most, but if you want to pick a date 10 years ago....

I'm assuming you're using Domino, but this is by no means restricted to use only with Domino.

Taking it Further

I was asked recently if a certain date field could be extended to add the ability for a user to choose from a list of predefined date ranges. Such as "A year from now" or "3 months from now".

Such is the beauty of bootstrap that I was soon able to extend my date field by creating a plugin that adds extra button, as below:


When clicked on, it looks like this:


Happy days!

How Did I Do It?

Creating the basic date picker is a simple case of marking it up like this:

<div class="input-append">
    <input name="DOB" id="DOB" rel="date" type="text" readonly="readonly">
    <button class="btn" onclick="$('#DOB').focus()"><i class="icon icon-calendar"></i></button>

Then at the bottom of the page (or better still, in an "form.init()" function called on "dom ready") do this:

$(function() {
 $("input[rel='date']").datepicker({dateFormat: "dd-M-yy"});

This code looks for all fields where rel="date" and binds the jQuery UI date picker to it.

Hey presto.

Advanced Version

To make the version with the additional dropdown, the HTML markup for the field changes to something like this:

<div class="input-append">
    <input name="DateExpected" value="" id="DateExpected" rel="date" type="text" class="span2" readonly="readonly">
    <div class="btn-group">
        <button class="btn dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>

        <ul class="dropdown-menu month-adder" role="menu">
            <li data-increment="1"><a>In One Month</a></li>
            <li data-increment="3"><a>In 3 Months</a></li>
            <li data-increment="6"><a>Within 6 Months</a></li>
            <li data-increment="12"><a>In a year</a></li>

        <button class="btn"><i class="icon icon-calendar"></i></button>

It should be obvious from that HTML how it all works. Maybe it's obvious to me as I'm au fais with Bootstrap?

Turning It In To A Plugin

While the HTML markup needed to wrap round a field to make it a datepicker isn't complicated you can imagine it's a bit of a pain to markup lots of date fields. What we really need is a plugin.

To create a plugin you'd simply add the following code in to your main "application.js" file:

(function( $ ) {
    $.fn.datePicker2 = function(options){
        var settings = $.extend({
            dateFormat: "dd/mm/yy"
        }, options );
        this.datepicker({dateFormat: settings.dateFormat}) //Initiate the datepicker
            .attr("readonly",true) //Make the field itself readonly!
            .wrap('<div class="input-append" />') //wrap it in all a div 
            .after($('<button class="btn"><i class="icon icon-calendar" /></button>') //add a button after the field
            .click(function(){$(this).closest('.input-append').children().first().focus()})); //Bind a click even to it
}( jQuery ));

Now, you don't need to wrap the date fields in any HTML. You just specify rel="date" and call change the previous "on load" event to this:

$(function() {
 $("input[rel='date']").datePicker2({dateFormat: "dd-M-yy"});

We're now using our own new jQuery plugin which does all the HTML markup for us.

Here's the code for the plugin which takes it further and adds the dropdown of "1 month", "1 year" etc.

(function( $ ) {
    $.fn.dateSelector = function(options){
        var settings = $.extend({
            dateFormat: "dd-M-yy"
        }, options );

            .wrap($('<div class="btn-group" />'))
            .before('<button class="btn dropdown-toggle" style="border-radius:0 !important;" data-toggle="dropdown"><span class="caret"></span></button>')
                    $('<ul class="dropdown-menu month-adder" role="menu"><li data-increment="1"><a>In One Month</a></li><li data-increment="3"><a>In 3 Months</a></li><li data-increment="6"><a>Within 6 Months</a></li><li data-increment="12"><a>In a year</a></li></ul>')
                    .on('click', 'li', function(){$(this).closest('.input-append').children().first().val(new Date((new Date().setMonth(new Date().getMonth()+$(this).data('increment')))).toUTCString().substring(5,16).replace(/ /g,"-"))})
}( jQuery ));


A Demo

You can see it in use in this "fiddle".

Taking it further Still

It's far from perfect. For a start the JavaScript is messy and could do with being re-factored. But also, it would be nice to have options like "in 2 days", "in 3 weeks" etc. And to be able to specify different or additional options on a per-field basis.

For now though, it'll do. Hope you like.

Comment Icon There are 5 comments in 4 threads Read - Add

Quick Tip: Login To Same Site as Two Different Users

Here's a tip I discovered kind of by accident in one of those "I wonder if" moments.

It came about after discovering a Fiddler tip that lets you trace localhost http traffic. The solution is simple: you simply add a trailing space, so that you surf to http://localhost./

At first I'd assumed that this was some odd quirk in the way browsers handled host names. Turns out it's actually working the way it should. Technically speaking all FQDNs should have a trailing space, in order to make them absolute. More here.

It's not just localhost. By way of an example the following two links both work




But, what's the tip?

My tip is that you can use the above "hack" to login to (most) websites using two different identities at the same time.

Oftentimes you want to test websites as two different users (even if one of them is "anonymous") and find yourself logging in and out as each user constantly.

Well, using the same browser, you can login as "User 1" at the site with no trailing dot and then as "User 2" in the site with the dot!!

Since discovering this a couple of hours ago it's already saved me an inordinate amount of time.

I know you can always do this by using different browsers (User 1 in Chrome, User 2 in IE) but it's normally the case that using the non-system-default browser ain't so straightforward.

Comment Icon There are 10 comments in 7 threads Read - Add

How To: Virgin Media + BT Infinity = Reliable Internet Connection?

The quest for an always-on internet connection is almost at an end!

As if to assure me it was worth it, within 24 hours of Virgin Media connecting my secondary (failover) broadband connection the "primary" BT line went down. Again. For the third time in as many months. This time, however, I was prepared and had a backup connection and could carry on working.

The BT engineer that came this time was very helpful. Bordering on apologetic for the fact I'd had so many visits of late. So much so he gave me his phone number in case it happens again and he'll try to personally fix it.

Apparently, the reason for my repeated issue is a dodgy chip on the card in the cabinet. He asked to be allowed to move my to another card but "they" said no. He logged the card as faulty, but said it would "be months" before anything is done.

For now though both are online and it was a massive relief to see both WANs go green on my router, as below:


With load-balancing enabled between the two WANs I'm getting the following speeds according to Broadbandspeedchecker.co.uk


Not that I'm overly-bothered about the actual speeds I get. In fact I don't care at all about the speed. All I care about is reliability of the connection. Which is what I feel I now have. Whether the Virgin connection is any more reliable than BT's remains to be seen. The reliability, I'm hoping, will stem from the fact it's unlikely (touch wood) that both will develop problems at the same time.

How It All Looks

For the curious, this is how it all looks:


What you can see above (front door on the left and cellar on the right):

1. The BT line which comes across the street, down the house, through the front door's frame and then down in to the cellar.

2. The Virgin Media cable comes out the ground, through this brown box, through the wall and across the cellar.

3. The BT line comes in to this master socket and then an RJ11 cable connects it straight to the router (6).

4. This is the coaxial cable from the Virgin Media (2) and connects to the back of Virgin's "Superhub" (5) which is their supplied router. It's connected to the WAN2 port on the router (6) using the green patch cable.

5. Virgin Media's router which is operating in "modem only" mode.

6. The Draytek Vigor 2850 router. Notice it's the non-wifi version. The red patch cable you can see goes off to the loft, where the WAP lives. I find the WAP provides much better whole-house coverage when it's above the rooms (no brick walls to go through).

That's all there is to the kit needed.

Notice the lack of a BT OpenReach modem. Not using BT's kit means I'm breaking their T&Cs and am unsupported. The BT modem is in a cupboard. Primarily because it's the property of BT, but also because if I have to call out a BT engineer I need to plug it back in before they get here and pretend it was always there. BT (apparently) charge ~£180 for a callout where it turns out to be a problem with your own kit. Before you log a call be sure to plug BT's modem back in and check that that too can't connect. Don't mention the non-use of a BT modem when you call your broadband provider!

As far as configuring the Draytek router goes this is something of a pain. Once you have it working make sure you use the router's Configuration Backup function to store the config somewhere safe. Then leave the router be.

Getting it working took me way longer than I'd hoped. I'm not going to talk about you do it in detail. All I will say is that if you can't get it to work following the online guides, then call Draytek's "internet connectivity helpline" which is how I finally managed to get it working.

Noteworthy Points:

Again, I can't emphasize this enough. If you find yourself struggling to get both WANs connected (like I did) then call Draytek's helpline. Don't waste time in the forums like I did. Where all the talk seems to be the order in which each piece of kit needs rebooting. Draytek's admin interfaces suck, but luckily, their helpline doesn't.

WAN Failure

As somebody pointed out the last time I discussed this the problem is knowing when one of the WANs has failed. If you only find this out when the other goes down then you have neither. To get round this you can use the router's email notification agent to tell you when either WAN fails. I've not been able to get this to work yet (the admin interface really does suck) but will continue to try and post back here when I do.

Worth The Cost?

The Draytek kit isn't the average bit of consumer equipment, costing ~£180 for the 2850. So, already this is an expensive exercise. On top of that Virgin Media has a setup fee of £49 (followed by a six month offer of £16 per month for for six months) and then £27 thereafter for their "up to" 60MB connection.

The existing BT-based connection I had is with Zen.co.uk who I pay £46 a month for an 80/20 "Fibre Pro" connection on a 20:1 contention ratio.

So, per month, I'm now paying about £75 a month. Although, technically, it's the company paying and so the VAT comes off those prices (20%) and I pay no income tax on it, which means the cost to me personally is about £40 a month.

For a home user this is probably all a bit OTT. However, for somebody who works at home and can't, in effect, work at all without an internet connection then this setup is a must-have. The actual cost is negligible when compared to the cost of being without the internet.

Some of you may think I'm crazy spending more than twice the amount I could get a single connection for. Personally I think it's money well spent.

Comment Icon There are 7 comments in 5 threads Read - Add

Modern Day Communication Reliability

Two weeks ago today I mentioned that I'd ordered a Virgin Media cable internet connection as a redundant 2nd connection in case my first goes down.

Today the engineer is due to come and connect me up. Yep, a two week wait to get connected. Luckily I'm already on the internet, otherwise there's not a chance I'd ever wait that long.

Anyway, I booked a date and the AM time slot for the visit and went about "waiting". Then, yesterday I got the message below:



Which sent my overly-paranoid and analytical mind in to overdrive.

These kind of text-based (non verbal) systems concern me. Note that I got no reply to my confirmation reply to say "Thanks for confirming". I now have no idea whether the engineer is coming or not. The time slot was 8am-1pm and it's now gone 10am...

Did I get my confirmation reply wrong maybe? Should the postcode have been all uppercase? With no space? Maybe the "+" sign is needed? Maybe "confirm" should also be in upper-case!?

I have no idea whether it's a) a person at the other end reading it or b) a PC with a badly written and intolerant string parsing function.

It reminded of something I said on Twitter a while back:


Dear Virgin Media, if you want to confirm that I still want the timeslot I've been waiting two weeks for, CALL ME.

If I had been waiting patiently for 2 weeks for a connection and then took a day off work to wait in, only to find that nobody came because, oooh, I dunno, your SMS didn't arrive, or my reply didn't, or I lost/damaged my phone, or changed my number, or I had my phone turned off, or my kids were messing with my phone and marked the SMS as read, or any other scenario that really could happen, I'm going to be pissed off.

It's the kind of conversation I get in to with my customers when "brain storming" ideas revolving around communication with their customers. Even the best ideas come with a myriad of "But, What Happens If..."

Comment Icon There are 7 comments in 4 threads Read - Add

‹ Previous | « Firsticon Page 2 of 344Last » | Next ›