Deploying angular-seed to Heroku

heroku-LogoAngular-seed is an application skeleton for AngularJS apps. It helps you to quickly bootstrap new applications. I’m currently using it for an app I’m writing and wanted to deploy that to Heroku for testing. Since that wasn’t a very straightforward process, I thought I’d share my experiences here.

If you’re reading this, you’ve probably already cloned the repo from https://github.com/angular/angular-seed and wrote the app. Of course you can also just deploy the sample app that comes with angular-seed, but you’ll need to make a couple of changes to prepare it for Heroku.

bower-logoBower

Angular-seed uses bower (check package.json: it’s already listed there as a devDependency), but in order for Heroku to use it, we’ll need to add it to the dependencies section too:

npm install bower --save

We also need to update the path to bower in package.json:

"postinstall" : "./node_modules/bower/bin/bower install",

Express as a web server

Angular-seed uses http-server as the web server to test your changes, but I didn’t find a way to use that on Heroku. Instead, I just add a simple Express based static files server.

First we’ll add Express as a node module:

npm install express --save

Next create a new file in the root of your project named app.js to serve static files from angular-seed’s app folder:

var express = require('express');
var app = express();
app.use(express.static(__dirname + '/app'));
app.listen(process.env.PORT || 3000);

Define a Procfile

We need to tell Heroku what it needs to do to start your app: create a file named Procfile in the root of your project and add:

web: node app.js

This tells Heroku to launch node using the app.js file.

Heroku

We’re ready to push our app to Heroku. Log in to Heroku and create an app. Install the Heroku toolbelt on your computer so we can call heroku commands from the command line.

To send your project to Heroku, we’ll need to add Heroku as a git remote

heroku git:remote -a <your_app_name>

Next, commit all the changes we’ve made in the local project and send your project to Heroku:

git add .
git commit
git push -u heroku master

In the terminal you’ll see your app being deployed, compiled and started on Heroku. You can now view it using the shortcut command ‘heroku open‘.

Screen Shot 2014-10-07 at 15.55.53

There are probably different ways to do this, but this method worked for me. Please let me know if this worked for you too or if you would do it different!

Escaping the yellow bubble at ICON UK

IMAG1819
Last Friday I was in Londen for what was yet again an excellent ICON UK. Tim Clark really did a great job in organising it and I hope he can now relax again. Kudos also to Tony Holder for organising the speaker dinner at Wilton’s. Didn’t know you can eat that well in the UK!

The venue (IBM Client Centre) added a nice touch to the conference and was conveniently located at the center of Londen. That allowed me to try out a Boris Bike and see what cycling on the left side of the road is like. Straight sections didn’t cause me any problems, but sweat ran down my back at every crossing. I’m glad I’m still alive to write this. But hey: no guts, no glory!

I was once again allowed to host a session and decided this time to NOT do it about XPages or any other IBM technology, but share my experiences with an alternative web development stack called MEAN (that’s MongoDb, Express, AngularJS and Node). Thanks to anyone who was in the room for attending. For all of you who weren’t, here’s the deck:

XPages gotcha: mode=”concat” in your themes

Suppose you have an XPage with a repeat control on it to show a list of documents. In the repeat you generate an <xp:button> for every document. Based on the status of the document you decide to give the button a different color, so you make the styleClass property of the button computed:

<xp:repeat
  id="repeat1"
  rows="30"
  var="entry">

  <xp:this.value><![CDATA[#{javascript:
    print("computing repeat value");
    return ["style1", "style2"];
  }]]></xp:this.value>

    <xp:button
      value="Label"
      id="button">
        <xp:this.styleClass><![CDATA[#{javascript:
          print("computing styleClass:");
          print( typeof entry);
          return entry
        }]]></xp:this.styleClass>
    </xp:button>

</xp:repeat>

That’s (roughly) the code you’d have to write. And guess what: it all works. Everyone’s happy!

Screen Shot 2014-08-28 at 15.35.03So you decide to enhance the looks of your application and include Bootstrap. Bootstrap requires the btn class on all buttons for styling. Being an expert XPage developer you create a theme for your application, add the Bootstrap CSS file and add a control definition to give all buttons that btn class:

<control>
  <name>Button.Command</name>
  <property mode="concat">
     <name>styleClass</name>
    <value>btn</value>
  </property>
</control>

You reload the page, thinking you’re done and guess what: errors!

That’s roughly what I’ve been looking at today and at some point thinking I lost my sanity.

The print() statements in the code above were added by me to show the order of execution. Without the <control> definition in the theme I saw this on the server console:

> computing repeat value
> computing styleClass:
> string
> computing styleClass:
> string

Exactly what I expected! But… after adding the <control> definition I saw this:

> computing styleClass:
> undefined
> computing styleClass:
> undefined
> computing repeat value

Notice the subtle, yet very important, difference in the order of computing: with the <control> definition the styleClass is computed before (!) the repeat value, making it impossible to let the button style depend on the repeat value. This behaviour is caused by the mode=”concat” part, that should combine the value of the styleClass with the one set in the theme.

The Bootstrap4XPages plugin has that same <control> definition in it, so if you’re using that you will likely run into this some day.

The solution I came up with for now is to add a new <control> definition to the theme, setting it to override any inherited settings and setting the mode to the default (‘override’). Set the themeId to the new <control> name and it all works again:

<control>
  <name>Button.NoConcat</name>
  <property>
  <name>styleClass</name>
    <value>btn</value>
  </property>
</control>

and:

<xp:button value="Label" themeId="Button.NoConcat"></xp:button>

I have no idea why it behaves this way and would have never guessed that a <control> breaks anything but the UI in my app. If anyone can share some light on this: please do!

Getting HTML from any RichText item

HTML_logoLast week I blogged about sending the contents of a RichText field (including images and attachments) as an HTML mail. Today’s task was related: get the contents of a RichText item as HTML, knowing that the contents can be stored in the item as either MIME or standard RichText.

With the wrapDocument() function I showed you last week you can easily get MIME contents as HTML. It turns out that with some small changes you can use the same method to let Domino convert ‘standard’ RichText into HTML. You probably saw this in action already: create a document with RichText in the Notes client and edit it on the web. What’s new is that this method allows you to do it programmatically.

The trick is in the DominoRichTextItem class: it has two constructors to create it: using either a MIMEEntity or by giving it a RichTextItem. That’s all the info I needed to update my previous function:

/*
 * Wraps a lotus.domino.Document as a com.ibx.xsp.model.domino.wrapped.DominoDocument, including a RichText item
 *
 * @param doc document to be wrapped
 *
 * @param richTextItemName name of the rich text item containing standard RichText or MIME  contents that need to be wrapped
 */
private static DominoDocument wrapDocument(final Document doc, final String richTextItemName) throws NotesException {</code>

  DominoDocument wrappedDoc = null;

  Database db = doc.getParentDatabase();

  //disable MIME to RichText conversion
  db.getParent().setConvertMIME(false);

  //wrap the lotus.domino.Document as a lotus.domino.DominoDocument
  //see http://public.dhe.ibm.com/software/dw/lotus/Domino-Designer/JavaDocs/DesignerAPIs/com/ibm/xsp/model/domino/wrapped/DominoDocument.html
  wrappedDoc = DominoDocument.wrap(doc.getParentDatabase().getFilePath(), doc, null, null, false, null, null);

  //see http://public.dhe.ibm.com/software/dw/lotus/Domino-Designer/JavaDocs/DesignerAPIs/com/ibm/xsp/model/domino/wrapped/DominoRichTextItem.html
  DominoRichTextItem drti = null;

  Item itemRT = doc.getFirstItem(richTextItemName);

  if (null != itemRT) {

    if (itemRT.getType() == Item.RICHTEXT) {

      //create a DominoRichTextItem from the RichTextItem
      RichTextItem rt = (RichTextItem) itemRT;
      drti = new DominoRichTextItem(wrappedDoc, rt);

    } else if (itemRT.getType() == Item.MIME_PART) {

      //create a DominoRichTextItem from the Rich Text item that contains MIME
      MIMEEntity rtAsMime = doc.getMIMEEntity(richTextItemName);
      drti = new DominoRichTextItem(wrappedDoc, rtAsMime, richTextItemName);

    }
  }

  wrappedDoc.setRichTextItem(richTextItemName, drti);

  return wrappedDoc;

}

Using this function you can wrap any document and get the HTML from a RichText item:

View view = db.getView("someview");
Document doc = view.getFirstDocument();

DominoDocument ddoc = wrapDocument(doc, "Body");
DominoRichTextItem drti = ddoc.getRichTextItem("Body");

String html = drti.getHTML();
System.out.println(html);

Create HTML emails from RichText fields with embedded images and attachments

If you want to send formatted (HTML) emails from Domino you have a couple of options.

Starting with version 9, there’s a simple action that allows you to send HTML mail by just configuring some options. You can also use Tony McGuckin’s emailBean snippet to send an HTML mail from an XPage directly, including embedded images and/or attachments. And there’s also the SSJS snippet I wrote to send an email from any backend SSJS script.

Unfortunately, none of these could do what I wanted: send an HTML mail with the contents based on a RichText field (stored as MIME), including any embedded images. With the standard photo upload option available in the XPage embedded CKEditor it’s real easy to add embedded images. Tony’s emailBean snippet came close, but it requires a DominoDocument object as a parameter and thus only works when used directly on the XPage where you create the content. In my case, I either wanted to pick a set of documents to be send or use a scheduled agent to do that.

So I investigated how I could create a DominoDocument from a standard document object.

First stop: this snippet that uses the .wrap() function of the DominoDocument object to wrap a standard document. That worked, but didn’t add the RichText fields to the wrapped document. So I dived deeper and found the JavaDocs for the DominoDocument here. Turns out that there is a getRichTextItem() function that returns a DominoRichTextItem. That object, the DominoRichTextItem, is also used in the emailBean code. The JavaDocs for the DominoRichTextItem describe that you can use a MIMEEntity to create one. The newly created DominoRichTextItem can then be attached to the wrapped DominoDocument.

Here’s the XSnippet I just added to wrap a document, including MIME.

For this to work you need to enable the “Store contents as HTML and MIME” option of the RichText field that you’re storing the HTMl in. When you’ve done that you can use the emailBean to create and send the email:

function sendEmailFromRichText() {
  DominoDocument wrappedDoc = wrapDocument(docMail, "body");

  //now we can pass the wrapped document, including the MIME contents to the EmailBean
  EmailBean emailBean = new  EmailBean();

  emailBean.setSendTo("someone@somewhere.com");
  emailBean.setSubject("Here's a mail");

  emailBean.setDocument(wrappedDoc);
  emailBean.setFieldName("body");

  emailBean.setBannerHTML("<p>Hi, "  + sendTo + "</p>");
  emailBean.setFooterHTML("<p>Kind regards, "  + senderName + "</p>");

  emailBean.setSenderEmail("i@dontexist.com");
  emailBean.setSenderName("Name of the sender");

  emailBean.send();
}

/*
 * Wraps a lotus.domino.Document as a com.ibx.xsp.model.domino.wrapped.DominoDocument, including the RichText item
 * 
 * @param doc document to be wrapped
 * @param richTextItemName name of the rich text item containing the MIME contents that need to be wrapped too
 */
private static DominoDocument wrapDocument( final Document doc, final String richTextItemName ) throws NotesException {
     
  DominoDocument wrappedDoc = null;
       
  Database db = doc.getParentDatabase();
     
  //disable MIME to RichText conversion
  db.getParent().setConvertMIME(false) ;
 
  //wrap the lotus.domino.Document as a lotus.domino.DominoDocument
  //see http://public.dhe.ibm.com/software/dw/lotus/Domino-Designer/JavaDocs/DesignerAPIs/com/ibm/xsp/model/domino/wrapped/DominoDocument.html
  wrappedDoc = DominoDocument.wrap(doc.getParentDatabase().getFilePath(), doc, null, null, false, null, null);
     
  //get the RichText field containing the MIME contents as MIME
  MIMEEntity rtAsMime = doc.getMIMEEntity("mailingBody");
     
  //add the RichText field to the wrapped document
  //see http://public.dhe.ibm.com/software/dw/lotus/Domino-Designer/JavaDocs/DesignerAPIs/com/ibm/xsp/model/domino/wrapped/DominoRichTextItem.html
  DominoRichTextItem drti = new DominoRichTextItem(wrappedDoc, rtAsMime, richTextItemName);
     
  wrappedDoc.setRichTextItem(richTextItemName, drti);
     
  return wrappedDoc;
     
}