Thanks for having me, DNUG !

I will be speaking at DNUG in June this year about a communications topic - how to use Watson AI to better prioritize your messaging and e-mail channels.
We will be showing a prototype that we have built for one of our canadian customers that will digest several input channels from GMail, Verse and Watson Workspace to assess the importance and relevance of the specific message in context of the users priorities and communication habits. It will then tell you the potentially most important messages in a web interface and via voice input/output using Amazon Alexa.

Please find the link to my session and everything around DNUG here:

https://dnug45.sched.com/event/Dj2L?iframe=no

See at Engage and at DNUG later on. Watch out for the Maple Lounge at Engage this year !

CU

Heiko.
Heiko Voigt   |   15 May 2018 10:37:07   |    DNUG  Watson  IBM  Verse    |   Comments [0]

Hi,

as I stumbled accross this issue a couple of weeks ago and found a workaround today. Some good'ole Notes Client stuff... .

What did I do ?


I created a Notes Document in LotusScript via an action button in a view. In the document, I changed some fields and used an action button to save the changes, close the uidocument, append some richtext via LotusScript to a richtext field an re-open the document using ws.editDocument(True,doc,,,False) in Edit mode again. We use this often if we have to append richtext programatically.

So far, so good. I continued editing in the UI and saved at some point - Notes wanted to create a save conflict due to multiple edits. The code I used for the above has not changed in years. The database has been using document locking for three years.

After some serious testing at the customer site, we learned that this behaviour started with Notes 9.0.1 FP8. Everyting earlier is fine, the problem also exists in FP9 and the 1st Beta of FP10, so something has changed since FP8 and after some more digging we came across document locking. It seems as if the sequence when the document gets unlocked by ui.close() and reopened (and re-locked) by ws.editDocument() must have changed - from FP8 onwards, the lockholders of the document re-openend for editing are empty for the UI Document but not for the backend document in the database ! So, indeed, there was an edit event happening in the backend after the re-open of the document in the UI.

The Workaround:


After fiddeling around with some events, I found a workaround by writing the current user as lockholder into the document in the querysave event of the underlying form:

Sub Querysave(Source As Notesuidocument, Continue As Variant)

       Dim doc As NotesDocument

       Dim s As New NotesSession

       Set doc = source.Document

       
       If(doc.IsNewNote=False) Then

               If doc.LockHolders(0)="" Then

                       Call doc.Lock(s.EffectiveUserName)

               End If

       End If

       
End Sub



So with that, if I am the current lockholder in the backend, I can successfully save my changes without generating a save conflict.

Hope this helps if someone runs into a similar issue.

Heiko.
Heiko Voigt   |   29 January 2018 15:45:27   |    Domino  Notes  FP8  FP9  FP6    |   Comments [0]

10 January 2018 Wednesday

2017 - mein Jahressückblick

Das Jahr 2017 – mein Rückblick

Das Jahr 2017 hat für mich turbulent begonnen. Unsere im November 2016 geborenen Zwillinge zwangen mir eine komplett neue Tages- und Nachtroutine auf. Füttern, wickeln, spielen, spazieren gehen, füttern, wickeln, schlafen, nachts um drei im Halbschlaf Schoppen machen und geben und das tagein tagaus. Ich lernte den Begriff “Jetstream” neu zu definieren – wenn meine kleine die Milchflasche in der Nacht in einem Zug weggeputzt hat, dann war dies der “Jetstream”.Und jede Nacht hoffte ich auf selbigen, entschied er doch, ob ich nach 15 Minuten wieder im Bett sein konnte oder ob es 45 bis 60 Minuten dauern würde.

Früh im Jahr verstarb mein Schwiegervater, ein Mann, zu dem ich ein sehr herzliches und liebevolles Verhältnis hatte und der mich immer wie einen seiner Söhne behandelt hat. Lieber Kurt, ich bin froh, dass Du Deine kleine Enkelchen noch kennenlernen konntest und wir noch ein gemeinsames Weihnachtsfest feiern durften. Du hinterlässt große Fusstapfen und ich habe viel von Dir gelernt.

Das Irre in dieser Zeit ist, dass man erst mit unglaublicher Verzögerung zum Nachdenken kommt. Bis Februar war ich noch vier Tage die Woche in einem tollen Projekt in Köln, zwei kleine Schlümpfe zuhause, Firmen in Kanada und Deutschland und zwei weitere direkt betreute Kunden in Süddeutschland. Und dann kam der harte Bruch – Elternzeit ab erstem März. Jetzt mussten die Firmen und Kunden mit “Minimalbetreuung” funktionieren – ich musste deligieren, umverteilen und Aufgaben abgeben an meine Mitarbeiter. Und es hat funktioniert ! An dieser Stelle möchte ich mich ganz herzlich bei den Mitarbeitern der SIT GmbH und der Harbour Light Software Development Ltd. bedanken, die mir in diesem Jahr mit großem Einsatz den Rücken frei gehalten haben. Ohne Euch hätte dieses Jahr ganz böse ausgehen können. Habt Dank dafür !

Wenn wir gerade bei der beruflichen Sicht sind – dieses Jahr wurden einige neue Technologien in unser Portfolio aufgenommen. Neben etlichen IBM Watson APIs haben Unity, die Microsoft Hololens und Amazon Alexa bei uns und in etlichen Kundenprojekten Einzug gehalten. Die letzte Ergänzung ist das Apple AR Kit.
Wir sind jetzt mit Mail und Collaboration in der Cloud. Tut. Reicht. Nicht alles geht, nicht immer sind wir online aber insgesamt überwiegen für uns als kleines Unternehmen die Kostenvorteile ganz klar. Schon die halbe gesparte Stromrechnung für unsere Connections Serverfarm im eigenen RZ bezahlt nun das Jahresabo für die IBM Connections Cloud und IBM Verse. Der freut sich der Schwabe in mir.

Meine Usergroup-Aktivitäten haben sich in diesem Jahr auf die Cross Canadian Collaboration Userg Group (C3UG) beschränkt – ein neues Video-Format wurde aufgesetzt und eine Multizeitzonen-Veranstaltung von der Ostküste in Halifax über Toronto und Calgary bis zur Westküste in Vancouver mit Vor-Ort-Veranstaltungen und Live-Video-Streams in die einzelnen Lokationen. Das alles hat tierisch Spaß gemacht und viele neue Kontakte und interessante Gespräche erbracht. Im Dezember konnte ich mein erstes Video für die C3UG produzieren mit Maureen Leleand zum Thema “Project Livegrid” - in Kürze auf dem C3UG YouTube Kanal.

Veranstaltungen. Ich war auf der DNUG in Berlin (in meinen Augen eine tolle Veranstaltung), auf besagter C3UG Veranstaltung und seit Jahren einmal nicht auf der Connect-O-Sphere. Und ich muss sagen, ich habe es nicht bedauert. Die Nachlese-Events hier sind sehr gut und bringen das Wesentliche auf den Punkt. Die Kontaktpflege wurde virtueller aber deswegen nicht weniger intensiv. Die DNUG Stammtische in Stuttgart habe ich nach einem letzten denkwürdigen Abend an den Nagel gehängt – zu viel Ärger mit den “Kollegen”.
In Kanada ticken die Uhren anders. Der permanente Mehltau über den IT-Entscheidungen in Deutschland weicht dort einem manchmal fast heiteren Ausprobieren. Klar, kostet Geld, wenn’s klappt ist gut, wenn nicht macht man was anderes. Man ist flexibel und undogmatisch bis auf zwei Dinge – iPhones und Microsoft Office 365. Alles andere kann munter mit hinzugemischt werden – in der Cloud, on premises oder hybrid – man setzt sich hin und analysiert die Fachanwendungen und entscheidet dann. Heterogenität wird als Chance betrachtet und nicht als IT-Leitungs-Versagen dargestellt. Einer unserer Kunden im Finanzsektor brachte es auf den Punkt - “wenn ihr uns ein Fachverfahren bauen könnt mit einer IT Lösung die wir noch nicht haben, die Lösung aber genau passt, dann nehmen wir sie. Wir sind in der IT Dienstleister des Fachbereichs, kein Klugscheißer.”. Man ist schneller bei einem Kunden drin, aber auch schneller wieder draußen, wenn die Leistung nicht passt. Die Zusammenarbeit ist in der Regel aber sehr gut – als einem unserer Kunden das Geld ausging und fünf Mitarbeiter aus dieser Firma heraus eine neue Firma gründeten, wurden wir von den weggehenden Leuten gewarnt, schnell unsere Forderungen geltend zu machen. So sind wir um einen großen Forderungsausfall herumgekommen und hatten einen neuen Kunden. Man muss auch mal Glück haben. Und so ist Harbour Light auch im 6. Jahr des Bestehens wieder profitabel und wächst. Unser größeres Büro in downtown Shelburne ist eröffnet und “operational” - es war ein gutes Jahr.

Für die SIT GmbH war es ebenfalls ein gutes Jahr. Wir konnten alle Bestandskunden halten und einige Neukunden gewinnen, bei denen sich langjährige Partnerschaften abzeichnen. Von einem Entwicklungspartner mussten wir uns mit einer Gerichtsverhandlung trennen aber auch dieses für mich persönlich sehr anstregende und unglaublich dämliche Verfahren konnte ebenfalls mittels eines Vergleichs noch in diesem Jahr abgeschlossen werden. Viel Zeit und Geld ging dabei verloren und manches Momentum ging vorüber. Trotz dieser aussergewöhnlichen Belastungen werden wir ein starkes wirtschaftliches Ergebnis haben, was einmal mehr für die Qualität meiner Mitarbeiter spricht.

Die knappe Zeit, die mir Job und Kinder gelassen haben, wurde von unserem dritten Nebenprojekt aufgefressen – wir bauen. Eine spezielle Erfahrung, die in Kürze mit eigenen Blogeinträgen gewürdigt werden wird. Einzug ist Ende Februar 2018 geplant – zum Ende meiner Elternzeit.

A propos Elternzeit – ich rate jedem Elternteil, dieses Angebot UNBEDINGT zu nutzen. Die Erfahrungen, die ich in diesem Jahr mit meinen zwei Schlümpfen machen durfte sind unbezahlbar und unwiederbringlich. Ich habe die Zeit nicht immer ad-hoc genossen aber meist schon am Abend wieder über das Wunder des Lebens gestaunt und die unglaubliche Reise, die diese beiden kleinen Menschlein durchlaufen. Und heute, mit 13 Monaten, beginnen sie bereits zu sprechen und laufen auch schon. Ich habe einen eigenständigen Blog für diese Reise angefangen – mit dem für mich bezeichnenden Titel “Einling kann Jeder”. Zwillinge sind etwas besonderes und sind faszinierend in Ihrer Entwicklung. Gleichzeitig prasselt die gesamte westliche Shoppingkultur auf junge Eltern ein. Es ist unglaublich, was zwei kleine Kinder, die nicht laufen, essen und reden können bereits an Ausrüstung und Kleidung “brauchen” und wie groß die Industrie in diesem Komplex ist und wie viel Druck bereits aus Eltern speziell im Bereich Gesundheit und Sicherheit gemacht wird. Mir kommt es im Nachhinein wie ein Zufall vor, dass wir als Vorgeneration überhaupt die Kindheit überlebt haben.

Wir haben nun auch Trump schon eine Weile überstanden, die GROKO bei uns wird nicht vermisst, kommt aber wieder und beerdigt mal eben so das Klimaziel für 2020 am ersten Sondierungstag. Das Schlimme an solchen Hirnpüpsen ist, dass mit der Abkehr von solch zentralen Weichenstellungen für Wirtschaft und Gesellschaft irgendwann nichts mher sicher ist. Man sehe sich die Foriesten auf SPON zu diesem Thema an – die deutschen AKW-Betreiber schiessen aus allen Rohren, um auch diesen Ausstiegs-Beschluss wieder zu kippen. Aber so ist es, wenn man außer dem eigenen Machterhalt keine Werte und kein Rückgrat hat. Das betrifft zum einen die Union aber auch die SPD, die wie es Dieter Hildebrandt einmal treffend formuliert hat “… jede Hose vollmacht, die man ihr hinhält...”.

Somit wird 2018 turbulent werden – ich freue mich auf die “Maple Lounge” auf der Think!-Konferenz im März, auf spannende Themen im Bereich VR/AR und die intensive Zusammenarbeit mit meinen Kunden mit neuen und alten Themen.

Es grüßt ein neugieriger

Heiko Voigt.
Heiko Voigt   |   10 January 2018 09:56:36   |     |   Comments [1]

Hi again,

in this third part of my plugin series, I want to take a look at some visualization stuff. Mainly, I had to come up with some display options to show numbers in a certain context to the user. In this case, I had to display sentiment values for s specific text coming from IBM Watson Natural Language Services.This service gives you (besides other content) a sentiment value from -10 (very negative) to +10 (very positive). +


PLEASE NOTE: I AM FOCUSSING ON THE XPAGES PART HERE ! I WILL *NOT* DESCRIBE THE HANDLING OF THE WATSON SERVICE CALLS HERE ! If you are interested in those, sound of in the comments or give me a shout.


In the details analytics component for the text entered, I wanted to give the user the option to quickly see the result on a scale display like this:


Image:My XPages Plugin Series: Volume 3: ion Rangeslider and jQuery Knob

This is the first part, we are going to look into in this part of the series.


The 2nd part is sort of a dashboard feedback for multiple text elements to quickly grasp the feedback coming from IBM Watson. This is something like this:


Image:My XPages Plugin Series: Volume 3: ion Rangeslider and jQuery Knob


This control renders parts of the text and creates some value circles to display the return values from IBM Watson about that text.


The two plugins I use for that are:

ion Rangeslider:
http://ionden.com/a/plugins/ion.rangeSlider/en.html
and jQuery Knob:
http://anthonyterrien.com/demo/knob/

As usual, these get loaded as a HEAD-Tag in my XPages:



<
xp:headTag tagName="script">
   
<xp:this.attributes>
           
<xp:parameter name="type" value="text/javascript" />
           
<xp:parameter name="src"value="js/plugins/ionRangeSlider/ion.rangeSlider.min.js" />
           
</xp:this.attributes>
</
xp:headTag>
<
xp:headTag tagName="script">
   
<xp:this.attributes>
           
<xp:parameter name="type" value="text/javascript" />
           
<xp:parameter name="src"value="js/plugins/jsKnob/jquery.knob.js" />
           
</xp:this.attributes>
</
xp:headTag>

Within the XPage, I will display the value of the slider using a Session Scope variable. Other ways are possible as well, of course. The code to render the slider looks like this:


<
div class="col-md-12">
   
<p>
           
<span>
                   
<i class="fa fa-sliders"></i>
                   
&#160;What's the sentiment of this message ?
           
</span>
           
<div class="ibox-content">
                   
<div class="m-b-sm m-t">
                             
<small ><strong>Sentiment value:</strong> from -10 (negative) via 0 (neutral)&#160;to +10 (positive) </small>
             
</div>
                     
<div id="ionrange_3"></div>
                                                                   
           
</div>
           
<xp:inputText id="inputSentiment" styleClass="inputSentiment"
value
="#{sessionScope.Sentiment}" style="display:none">
           <
/xp:inputText>
   
</p>
</
div>

The value is located in a hidden field (display.none), the DIV ionrange_3 contains the slider. To complete the slider component, we will have to initialize it in the document.ready() function, this will initialize the knob controls as well:


<!-- Script Blocks for jQuery -->

<
xp:scriptBlock id="scriptBlock1">
   
<xp:this.value><![CDATA[$(document).ready(function(){
         $("#ionrange_3").ionRangeSlider({

       min: -10,

       max: 10,

       from: sval,

       prettify: false,

       hasGrid: true

   });

   $(".dial").knob();

});
]]></xp:this.value>
</
xp:scriptBlock>

As you can see, ionRangeSlider offers various parameters to play around with, just take a peek on the website above.

Now, let's take a look at the knob part, the following code snippet defines the knob control. I create the complete control as a computed text and the item gets rendered at runtime in the browser.



<
div class="m-r-md inline">
     
<xp:text escape="false"        disableTheme="true">
     
<xp:this.value><![CDATA[#{javascript:var         value=myDemoBean.getSentiment();
     var back ="<input type=\"text\" value="+value+" readonly class=\"dial m-r\" data-fgColor=\"#5367CE\" data-width=\"85\" data-height=\"85\" data-step=\"1\" data-min=\"-10\" data-max=\"10\" data-displayPrevious=true>";

     return back;}
]]></xp:this.value>
</
xp:text>
     <
div class="m-b-sm m-t">
             
<small ><strong>Sentiment: (-10 to +10) ?</strong></small>
   
</div>
</
div>


The base element to identify the input type as a dial knob is the class element "dial m-r". I don't want to change the values displayed so the input tag is readonly. My next job is to move this control in a custom control and add  parameters like the Min/Max values, Step size, etc..
The value to display is coming from a java bean.

As described, both plugins give you a huge set of parameters to play around with. One of the next parts of this series will be about using these controls for data input and how to persist the values in a bean or a domino document.

So far for today, happy coding !


Heiko.
Heiko Voigt   |   14 November 2017 10:08:24   |    Domino  XPages  jQuery  Bootstrap    |   Comments [0]

13 November 2017 Monday

Es könnte so schön sein....


Ein paar traurige Erfahrungen von der Projekt-Front.

Heute war ich wieder mal bei meinem Lieblingskunden und hatte nach einiger Zeit wieder einmal mit den dortigen Administratoren zu tun. Ich kenne die Kollegen dort schon einige Jahre, aber einen so deprimierten Eindruck haben die Kollegen noch nie auf mich gemacht. Was war geschehen ? Seit einem oder zwei Jahren haben sie einen neuen Abteilungsleiter, der als Führungskraft gerne Durftmarken im IT-Bereich setzen möchte. Dies hat er getan - nicht immer mit allzu großem Erfolg. Einige dieser nicht so erfolgreichen Aktionen sind ihm auch direkt selbst anzulasten. Was tut nun ein gestandener Manager ohne persönliche finanzielle Verantwortung in solch einer prekären Situation ? Er tritt zum Angriff an.
Das bedeutet, dass zunächst die Kontrolldichte der eigenen Abteilung erhöht wird, in dem Eigenverantwortung der Mitarbeiter durch Bürokratie ersetzt wird und Vertrauen durch konsequentes Misstrauen und "Fertig-machen" der eigenen Leute ersetzt wird. Parallel werden Nebenkriegsschauplätze eröffnet, indem im Management-Zirkel bislang unauffällige Randbereiche in den Fokus genommen werden um z.B. bestehende, hoch effizient arbeitende und top administrierte Anwendungssysteme kaputt zu reden. Dies wird mit einiger Perfidität im Management vorangetrieben. Wie das geht ? Der berühmte deutsche Innovationsansatz im ideenlosen Mittel-(Maß-)-IT-Management: kaputt sparen.

Man nehme eine funktionierende Infrastruktur mit kosteneffizienten Anwendungen, guten Antwortzeiten und motivierten Mitarbeitern für Entwicklung und Betrieb. Man stoppe möglichst viele Wartungs- und Optimierungsvorhaben auf der Plattform (O-Ton: "... es läuft doch auch so ..."), überziehe die Mitarbeiter mit bürokratischen Prozessen zur Aufwandserhöhung bei gleichzeitiger Verkleinerung der Mannschaft. Man stoppt außerdem die Neuentwicklung von Anwendungen auf der Plattform und schafft Doppelstrukturen nach eigenem Gusto. Damit kann für jedes Projekt endlos diskutiert werden, wo es denn implementiert werden soll/darf/kann.
Durch mangelnde Wartung der Anwendungen und der Infrastruktur schließt sich dann nach einiger Zeit der Kreis - es kommt zu den ersten Ausfällen einer Kernanwendung für 2 Stunden nach 10 Jahren (!!!) Uptime. Das ist natürlich sofort ein Grund, die gesamte Plattform lieber heute als morgen rauszunehmen. Man hat es ja schon immer gewusst.

Eigentlich bin ich ein Freund von Veränderungen. Neue Besen kehren gut - da ist eigentlich was dran. Aber - wenn ein Besen immer nur "neu" ist, sprich als Wanderpokal von Firma zu Firma zieht und verschwindet, wenn ihn seine Fehler wieder einholen - da ist aus meiner Sicht Vorsicht geboten. Aber das zählt ja nicht bei der Einstellung von solchen Leuten. Das Ergebnis bei diesem Kunden, die nun eine "IT-Heuschrecke" im Haus haben ist mehr als ernüchternd - die Motivation, die Begeisterung und die Leistungsbereitschaft eines der technisch und menschlich besten Teams die ich über die Jahre bei meinen Kunden kennengelernt habe geht den Bach 'runter. Die Leute werden konsequent verunsichert und entweder zum Dienst nach Vorschrift oder in die innere und äußere Emigration getrieben.

Und so verlottert eine der besten, schnellsten und technisch und kostenseitig besten Infrastrukturen und IT-Systemen die ich kenne aufgrund - ja, warum eigentlich ? Wegen den persönlichen Eitelkeiten einer IT-Heuschrecke ? Das wäre zu wünschen - die zieht bald weiter und es bestünde Grund zur Hoffnung. Wenn die Heuschrecke aber auf höheren Befehl handelt und nur die Rampensau für noch höhere Granden spielt - dann geht wohl wieder ein großes Stück IT-Kompetenz in Deutschland verloren.

Es könnte so schön sein - es kann der frömmste, schnellste und kostengünstigste nicht in Frieden arbeiten, wenn es der bösen Führungskraft nicht gefällt.

Etwas traurig grüßt,

Heiko.
Heiko Voigt   |   13 November 2017 19:51:08   |    Kunden  Management  Zufriedenheit    |   Comments [0]

2 November 2017 Thursday

My XPAGES Plugin Series Part 2: Footable

XPages JQuery/Boostrap Plugin Series – Volume 2: Footable

Hello,

in the first volume of this series, I took a look at dualselect to build a nice select/deselect interface for a listbox.
In this part, I will take a look on formatting table data in a convenient way to add pagination, search, sort and action into a table.

Like in the first example, my table will be fed from a backend Java Bean. The bean contains a list of objects coming from Notes Documents and will be presented as rows inside of the table. Some columns of the table will be sortable and I want a filter component as well. Also, I want an action submenu for each row of the table to interact with the content of the specific row. Overall, I want something like this:

Image:My XPAGES Plugin Series Part 2: Footable

For this purpose, I will use the plugin „Footable“:
https://fooplugins.com/plugins/footable-jquery/

First, we will load the plugin via a head tag in the xpage:


<
xp:headTag tagName="script">
     
<xp:this.attributes>
             
<xp:parameter name="type" value="text/javascript" />
                     
<xp:parameter name="src"
                     
value="js/plugins/footable/footable.all.min.js" />
     
</xp:this.attributes>
<
/xp:headTag>



BTW, I organize my plugins using package explorer and the WebContent Folder of the Notes Application:

Image:My XPAGES Plugin Series Part 2: Footable

Before we can use the table, we have to enable the plugin using a call in an output script block inside of the $(document.)ready() event:



$('.footable').footable();


We will use the css class footable insinde of our table definition to do this (see below):

After having loaded all the moving parts of the plugin, let’s code the table. I will define the table, header and footer inside of the xpages code. The rows will be rendered by a repeat control.

If you go through the code below, you will run into a line of code that starts with „swal(...)“ – this will be covered in the next part of this series on how to prettify alert boxes using the the SWAL plugin.

The table will be enclosed in a DIV from the bootstrap theme I use in the overall application. Right before the code of the table, we will define a html field for the text filter of the table:


<
input type="text" class="form-control input-sm m-b-xs" id="filter" placeholder="Search in table"></input>

The filter element gets  defined via ist ID in the page definitions. The code for the table itself looks like this:


<
table class="footable table table-stripped" data-page-size="8" data-filter="#filter">
<
thead>
     
<tr>
             
<th>Account type</th>
             
<th>E-Mail Address</th>
             
<th>Actions</th>
     
</tr>
</
thead>
<
tbody>

Inside of the repeat control, I retrieve the row data as a JSON Object and refer to it using the variable jRowData. My Java Bean has a method the returns the account objects as a JSON list.


<
xp:repeat id="repeatAccounts" rows="30" var="jRowData"
     
indexVar="jRow" disableOutputTag="true">
<
xp:this.value><![CDATA[#{javascript:var list=UserBean.getAccountsAsJSON();
return eval("("+list+")");}
]]></xp:this.value>
     
<tr class="gradeA">
             
<td>
     
<xp:label value="#{javascript:jRowData.type}" id="labeltype"></xp:label>
             
</td>
             
<td>
             
<xp:label value="#{javascript:jRowData.emailaddress}" id="label1">
             </
xp:label>
             
</td>
             
<td class="center">
             
<div class="btn-group">
                     
<button data-toggle="dropdown" class="btn btn-primary dropdown-toggle">Actions&#160; <span class="caret"></span></button>
                     
<ul class="dropdown-menu">
<
li><xp:link escape="true" text="Edit" id="link2" value="#modal-form">
     
<xp:this.attrs>
     
<xp:attr name="data-toggle" value="modal"></xp:attr>
     
</xp:this.attrs>
     
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="popupform">
<
xp:this.action><![CDATA[#{javascript:UserBean.setSelectedAccount(jRowData.emailaddress);
sessionScope.put("SelectedAccount",jRowData.emailaddress)}
]]></xp:this.action>
</
xp:eventHandler>
     
</xp:link></li>
<
li>
<
xp:link escape="true" text="Delete" id="link3" value="#">
             
<xp:eventHandler event="onclick" submit="false"
action
="#{javascript:UserBean.disableAccount(jRowData.emailaddress);}">
<
xp:this.script><![CDATA[swal({  
         title: "Are you sure ?",  
         text: "Do you really want to delete this account ?",  
         type: "warning",  
         showCancelButton: true,  
         confirmButtonColor: "#DD6B55",  
         confirmButtonText: "Yes, please delete !",  
         closeOnConfirm: false,
         closeOnCancel:false

     }, function(isConfirm){

             if(isConfirm) {

                     var myhiddenButton = '#{
javascript:getClientId("saveAll")}';
                     document.getElementById(myhiddenButton).click();

                     return true;

             } else {

                     swal("Not deleted !", "The account has not been deleted.", "success");
                     return false;

             }

});

]]></
xp:this.script>
</
xp:eventHandler>
</
xp:link></li>
</
ul>
</
div>

Inside the action code, (Action delete) I display an alert box before deleting the account. As I will have to let data travel back to the server depending on a client side event in an alert box, I took a shortcut and created a hidden button with the server side code that gets triggered in the alertbox if the user decides to really delete the account. I will go into further details of this section in the next episode about the SWAL plugin.


<
xp:button value="Hidden Button for Save !" id="saveAll“ style="display:none">
<
xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<
xp:this.action>
<
xp:actionGroup>
<
xp:executeScript
script
="#{javascript:UserBean.disableAccount(jRowData.emailaddress);}">
</
xp:executeScript>
</
xp:actionGroup>
</
xp:this.action>
</
xp:eventHandler>
</
xp:button>
</
td>
</
tr>
</
xp:repeat>
</
tbody>

Inside of the table footer, the pagination will show up.


<
tfoot>
     
<tr>
     
<td colspan="5">
                     
<ul class="pagination pull-right"></ul>
             
</td>
     <
/tr>
</
tfoot>
</
table>

The edit action as well as the add function will trigger a model dialog that allows me to enter/alter the account data. For the sake of the code size of this post, I decided to leave that part out of this post for the moment. The modal form resides in a DIV called „popupform“.

For your convenience, I will pull a demo template together with all the code inside and put that out on github within the next week or so – so stay tuned for more to come....

Heiko.
Heiko Voigt   |   2 November 2017 07:00:00   |    Domino  Xpages  jQuery  Bootstrap  Footable    |   Comments [0]

25 October 2017 Wednesday

Domino 2025 ...

So,

tonight there have been some big announcements coming from IBM about a strategic partnership between HCL and IBM to have HCL as the development partner to do the future development of a huge part of the ICS portfolio, including IBM Notes and Domino. I have not gathered all the details about this partnership yet and we will have to weigh what this means for customer, partners and the future of the product line, but at least this is progress.


This partnership includes the following products:



Domino
Notes (on premises and SmartCloud)
Traveler
Verse
Sametime
IBM Client Access
IMSMO (mail support for Microsoft Outlook)




Ed Brill provided a video about the future development process and the ideas for  participation:


https://www.youtube.com/embed/dRsizuGIGy4



So stay tuned, there's a ot more to come about this.
Heiko Voigt   |   25 October 2017 21:33:28   |    HCL  Domino  IBM    |   Comments [1]

Hi,

Within the last couple of weeks I have been busy implementing a first Watson AI powered product implementation at a customer site using a Domino/Xpages based frontend. The Watson part of this application will be something to talk about later on but I wanted to take the chance to blog about a couple of frontend components and plugins for the Xpages part, that I found truly handy along the way. This will be a series of blog posts in the next couple of weeks but each post will be independent from each other.

Some basics – all I am talking about is using Bootstrap and jQuery as the base for the frontend component. I also use a bootstrap theme for the application so I will not cover overly much of the CSS parts of the application besides the CSS parts of the specific plugin.


Also, the application de-couples frontend and backend data by using beans in the Xpages world and to use JSON micro services to get to the requested data in the backend.


Let’s start out with a common problem in a form – multi selection fields with a nice bootstrap interface, especially if you have to select from a large amount of options. I was looking for a plugin that allows search, multi selection and is so easy that it binds to a single HTML field.


I wanted to achieve something like this:

Image:My XPages Plugin Series - Part1: Dual Listbox



After looking around for some time I eventually came across the plugin named “Boostrap Dual Listbox” (source:
https://www.virtuosoft.eu/code/bootstrap-duallistbox/). It gives us something that looks similar to this:
Image:My XPages Plugin Series - Part1: Dual Listbox

So where do the selection options come from ? They are persisted in the back end Domino database as documents. A bean reads them (session scope bean) and returns a javascript list element that displays them. What does the code in the xpage look like ?


First, we have to load our plugin:



<xp:headTag tagName="script">

<xp:this.attributes>

<xp:parameter name="type" value="text/javascript" />

<xp:parameter name="src" value="
js/plugins/dualListbox/jquery.bootstrap-duallistbox.js" />
</xp:this.attributes>

</xp:headTag>



Note that we load this as a head tag to work around AMD loading issues with good’ole DOJO.
Also, we have to add the CSS:



<xp:styleSheet href="css/plugins/dualListbox/bootstrap-duallistbox.min.css"></xp:styleSheet>



Then, we need our field that will be using the plugin and save the data:


<xp:listBox id="listBox1" multiple="true"

styleClass="form-control dual_select" defaultValue=""

value="#{sessionScope.countries}">

<xp:eventHandler event="onchange"

submit="true" refreshMode="partial" refreshId="listBox1">

</xp:eventHandler>

<xp:selectItems>

<xp:this.value><![CDATA[#{
javascript:var liste = UserBean.getKeyWordList();
return liste;}]]></xp:this.value>

</xp:selectItems>

</xp:listBox>



The key value connection is the style information “dual_select”. The “form-control” style defines an input field inside the Bootstrap theme.


Also, we need a Output Script to enable the plugin:



<xp:scriptBlock id="scriptBlock1">

<xp:this.value><![CDATA[$(document).ready(function(){

$('.dual_select').bootstrapDualListbox({

selectorMinimalHeight: 160,

preserveSelectionOnMove: 'moved',

moveOnSelect: false

});


});

]]></xp:this.value>

</xp:scriptBlock>



And that’s basically it. There is a small caveat – I do not bind the result to a bean property as I have to convert the data structures here, that’s why I bind the selection to a session scope variable. This get’s set in the afterPageLoad() Event in the xpage from the bean and in the form submit button, the session Scope variable gets read out and sent to the bean:


try {

var result = $U.toArray(sessionScope.get("countries"));

var v:java.util.Vector = new java.util.Vector();


var arrayLength = result.length;

for (var i = 0; i < arrayLength; i++) {


//Do something

v.add(result[i]);

}


UserBean.setKeyWords(v);

UserBean.save();

} catch (e) {

print(e);

}

sessionScope.put("Mode","0");

context.reloadPage();


W
hy did I do this ? Well, the Xpages Listbox is a real beast when it comes to return values. If you do not select anything, it will return a null value as expected. If you select one item, it will return a String, if you select multiple options, it will return an array. So we have to normalize this for our bean to pick up the data correctly. There might be a better way to do this and probably someone came up with a more sophisticated solution. Anywho – it works for now.

So overall no big deal to get this up and running – the bean delivers an array of select items.


Have fun with this one – I really like the filter options and the in and out switches to quickly find and select items from a potentially long list.


That’s it !


Cheers,


Heiko.
Heiko Voigt   |   18 October 2017 23:42:25   |    domino  xpages  bootstrap    |    [0]

Hi,

Within the last couple of weeks I have been busy implementing a first Watson AI powered product implementation at a customer site using a Domino/Xpages based frontend. The Watson part of this application will be something to talk about later on but I wanted to take the chance to blog about a couple of frontend components and plugins for the Xpages part, that I found truly handy along the way. This will be a series of blog posts in the next couple of weeks but each post will be independent from each other.

Some basics – all I am talking about is using Bootstrap and jQuery as the base for the frontend component. I also use a bootstrap theme for the application so I will not cover overly much of the CSS parts of the application besides the CSS parts of the specific plugin.


Also, the application de-couples frontend and backend data by using beans in the Xpages world and to use JSON micro services to get to the requested data in the backend.


Let’s start out with a common problem in a form – multi selection fields with a nice bootstrap interface, especially if you have to select from a large amount of options. I was looking for a plugin that allows search, multi selection and is so easy that it binds to a single HTML field.


I wanted to achieve something like this:


Image:My XPages Plugin Series - Part1: Dual Listbox

After looking around for some time I eventually came across the plugin named “Boostrap Dual Listbox” (source:
https://www.virtuosoft.eu/code/bootstrap-duallistbox/). It gives us something that looks similar to this:

Image:My XPages Plugin Series - Part1: Dual Listbox

So where do the selection options come from ? They are persisted in the back end Domino database as documents. A bean reads them (session scope bean) and returns a javascript list element that displays them. What does the code in the xpage look like ?


First, we have to load our plugin:



<xp:headTag tagName="script">

<xp:this.attributes>

<xp:parameter name="type" value="text/javascript" />

<xp:parameter name="src" value="
js/plugins/dualListbox/jquery.bootstrap-duallistbox.js" />
</xp:this.attributes>

</xp:headTag>



Note that we load this as a head tag to work around AMD loading issues with good’ole DOJO.
Also, we have to add the CSS:



<xp:styleSheet href="css/plugins/dualListbox/bootstrap-duallistbox.min.css"></xp:styleSheet>



Then, we need our field that will be using the plugin and save the data:


<xp:listBox id="listBox1" multiple="true"

styleClass="form-control dual_select" defaultValue=""

value="#{sessionScope.countries}">

<xp:eventHandler event="onchange"

submit="true" refreshMode="partial" refreshId="listBox1">

</xp:eventHandler>

<xp:selectItems>

<xp:this.value><![CDATA[#{
javascript:var liste = UserBean.getKeyWordList();
return liste;}]]></xp:this.value>

</xp:selectItems>

</xp:listBox>



The key value connection is the style information “dual_select”. The “form-control” style defines an input field inside the Bootstrap theme.


Also, we need a Output Script to enable the plugin:



<xp:scriptBlock id="scriptBlock1">

 <xp:this.value><![CDATA[$(document).ready(function(){

$('.dual_select').bootstrapDualListbox({

 selectorMinimalHeight: 160,

 preserveSelectionOnMove: 'moved',

 moveOnSelect: false

});


});

]]></xp:this.value>

</xp:scriptBlock>



And that’s basically it. There is a small caveat – I do not bind the result to a bean property as I have to convert the data structures here, that’s why I bind the selection to a session scope variable. This get’s set in the afterPageLoad() Event in the xpage from the bean and in the form submit button, the session Scope variable gets read out and sent to the bean:


try {

var result = $U.toArray(sessionScope.get("countries"));

var v:java.util.Vector = new java.util.Vector();


var arrayLength = result.length;

for (var i = 0; i < arrayLength; i++) {

 
 //Do something

 v.add(result[i]);

}


UserBean.setKeyWords(v);

UserBean.save();

} catch (e) {

print(e);

}

sessionScope.put("Mode","0");

context.reloadPage();


W
hy did I do this ? Well, the Xpages Listbox is a real beast when it comes to return values. If you do not select anything, it will return a null value as expected. If you select one item, it will return a String, if you select multiple options, it will return an array. So we have to normalize this for our bean to pick up the data correctly. There might be a better way to do this and probably someone came up with a more sophisticated solution. Anywho – it works for now.

So overall no big deal to get this up and running – the bean delivers an array of select items.


Have fun with this one – I really like the filter options and the in and out switches to quickly find and select items from a potentially long list.


That’s it !


Cheers,


Heiko.
Heiko Voigt   |   18 October 2017 23:42:25   |    domino  xpages  bootstrap    |    [0]

27 June 2017 Tuesday

What a workhorse.... (Update)

A customer calls...

this week we got a call from one of our customers using our web content management system SIT Portal DXP as the base for their web portal based on Domino. They were asking for a new sizing for their primary web server that was "... getting a little bit slow..." over the past months. To get some insight on what's happening at the server, we took a look at the web stats and I think they are quiet remarkable. The customer had consistently expanded the website to now 60 portals and a couple of thousand landing pages and it is still running on one Domino server !

Image:What a workhorse.... (Update)

Oh, and did I mention that this poor little server also is the web mail gateway for 500 internal users ?

Now, to be clear - that's not an environment that we recommend for a site of that size
but it clearly shows how capable a Domino web server is in a real world scenario. The server is a virtual linux box, 2 virtual processors, 16 4 GB RAM, managed by one part time admin who also does content management in the overall portal environment. The portal is bootstrap based fully responsive, etc... .

* Update - I stand corrected: the server had only 4 GB of RAM until Monday of last week. Then, my colleagues decided that it was about time to ease the pain a bit immediately.

Compare that to other web application servers - can you grow your infrastructure to that size using one machine ? I doubt it in a lot of cases and from an availability and load balancing aspect you would not do that. And of course we will be considering all of these aspects in the new sizing - the customer started small seven years ago and never had the desire to upgrade until this year and I guess by looking at the numbers here, that totally makes sense. We will also put a reverse / cache proxy up to reduce the load even more and taking the SSL burden away from Domino as well.

Can't wait to see this baby run with all the enhancements mentioned above :-).

impressed,

Heiko.
Heiko Voigt   |   27 June 2017 11:09:05   |    Domino  XPages  Web    |   Comments [6]