RSS feed for blog Linkin Skype Mail Me Twitter

Stickfight

Blog Category: linkedin

Editable salesforce templates

Editing an email that is generated via an Saleforce email template BEFORE it is sent is something that I have had a few clients grumble over, the feature is baked into the Quote object which makes sense, but you try telling clients they cant have it for Order objects….

So this is a basic solution that gets round this problem and is the basic set-up for expanding it to solve all the issues, in this case I am solving the most common issue I have come access, in that you are generating a order recept or delivery note pdf using the ‘renderAs=”PDF”’ option in an email template and want to send the email with a custom message to one or more people that you decide at the time of sending.

To do that we are going to create a new visual force page that resembles a normal email and use it to fill in the details before we generate the email template


SFEditableEmail03.png

1) Create a new email custom object

This is just a basic object with the fields we need for the email, and a lookup field to the parent Order


New Custom Email Object

Note: For brevity I’m leaving out the creation of the layout for the custom object and the adding of the related list to the Order Layout

2) Add some extra Fields to your Order object

These are the temporary fields that we are using to actually send the template email, resist the urge to set the To/CC/BCC as email fields as that will stop you having multiple recipients.


Extra Fields

Obviously these fields have to be editable to all but not part of the order layouts so they don’t show up.

3) Create a new “Template Editor” Visualforce Page

This page is as simple or complex as you can want it, my one here takes email address separated by a comma but yours can be a really posh contact lookup


<apex:page controller="sendOrderPDFEmail">
    <apex:messages />
    <apex:pageBlock title="Email for Order: {!order.Name}">
    <p>Fill out the fields below and click "Send email"</p>
    <apex:form ><br/><br/>

        <apex:outputLabel value="Template To Attach" for="chooseTemplate"/>: <br/>
        <apex:selectList id="chooseTemplate" value="{!template}" size="1">
            <apex:selectOption itemValue="Template1" itemLabel="Template1"/>
            <apex:selectOption itemValue="Template2" itemLabel="Template2"/>
            <apex:selectOption itemValue="Template3" itemLabel="Template3"/>
        </apex:selectList>
        <br/><br/>  
    
        <apex:outputLabel value="To" for="To"/>: <br/>
        <apex:inputText value="{!to}" id="To" maxlength="255" style="width: 300px;"/>
        <br/><br/>  
        
        <apex:outputLabel value="CC" for="CC"/>: <br/>
        <apex:inputText value="{!cc}" id="CC" maxlength="255" style="width: 300px;"/>
        <br/><br/> 
        
        <apex:outputLabel value="BCC" for="BCC"/>: <br/>
        <apex:inputText value="{!bcc}" id="BCC" maxlength="255" style="width: 300px;"/>
        <br/><br/> 
    
    
        <apex:outputLabel value="Subject" for="Subject"/>: <br/>
        <apex:inputText value="{!subject}" id="Subject" maxlength="255" style="width: 500px;"/>
        <br/><br/>
        
        <apex:outputLabel value="Body" for="Body"/>: <br/>        
        <apex:inputTextarea value="{!body}" id="Body" richText="true" rows="20"/>
        <br/><br/>
        
        <apex:commandButton value="Send Email" action="{!send}"/>
    </apex:form>
    </apex:pageBlock>
</apex:page>


4) Create the “Send” code (don’t forget to create your test code).

I have just put comments on the code, as its not complex and follows the flow chart at the top of the blog.


public class sendOrderPDFEmail {


    public String template { get; set; }
    public String cc { get; set; }
    public String bcc { get; set; }
    public String to { get; set; }
    public String subject { get; set; }
    public String body { get; set; }
    
    
    public Account contactLookup { get; set; }
    private final Order order;

    public sendOrderPDFEmail() {
        //Get the Id of the order that we are working on
        template = '';
        String OrderId = ApexPages.currentPage().getParameters().get('id');
           
        order = [SELECT Name, ID
        FROM Order
        WHERE Id = :OrderId];
        
    }

    public Order getOrder() {
        return order;
    }


    public PageReference send() {
    
    if( !String.isBlank(cc)) {
        cc = cc.trim();
    }
    
    if( !String.isBlank(bcc)) {
        bcc = bcc.trim();
    }
    
    if( !String.isBlank(to)) {
        to = to.trim();
    }
    
    
    //Mail email Order object
    orderemail__c con = new orderemail__c(
        Address_CC__c=cc,
        Address_BCC__c=bcc,
        Address_to__c=to,
        Body__c=body,
        parent_order__c=order.id,
        Subject__c=subject,
        Template__c=template
        );
    insert con;

    //Store the temp values in the Order
    order.le_Address_BCC__c=bcc;
    order.le_Address_CC__c=cc;
    order.le_Address_to__c=to;
    order.le_Body__c=body;
    order.le_Subject__c=subject;
    order.le_Template__c=template;
    
    
    update order;

    if ( String.isBlank(to) ) {
         to = 'test@test.com';
     }
    
     // Construct the list of emails we want to send
     List<Messaging.SingleEmailMessage> lstMsgs = new List<Messaging.SingleEmailMessage>();
    
     Messaging.SingleEmailMessage msg = new Messaging.SingleEmailMessage();
     
     
     //set the email tempalte from the name chossen on the email form
     EmailTemplate[] emailTemplate = [select id from EmailTemplate where Name=:template];
     if (emailTemplate.size() > 0) {
          msg.setTemplateId( emailTemplate[0].id );
          
     } else {
         msg.setPlainTextBody('No Template Provided');
     }

     // Trim and convert the comma delimted string to a suitable recipiant list for the email.
     String[] trimmedtoarray;
     if (!String.isBlank(to)) {
        String[] toarray = to.split(',');
        trimmedtoarray = new String[toarray.size()];
        Integer k = 0;
        for (String singlEmail: toarray) {
           trimmedtoarray[k++] = singlEmail.trim();
        }
        msg.setToAddresses(trimmedtoarray);
     }
     
     if (!String.isBlank(cc)) {
         String[] ccarray = cc.split(',');
         String[] trimmedccarray = new String[ccarray.size()];
         Integer i = 0;
         for (String singlEmail: ccarray) {
             trimmedccarray[i++] = singlEmail.trim();
         }
         msg.setCcAddresses(trimmedccarray);
     }
     
    
     if (!String.isBlank(bcc)) {
         String[] bccarray = bcc.split(',');
         String[] trimmedbccarray = new String[bccarray.size()];
         Integer j = 0;
         for (String singlEmail: bccarray) {
            trimmedbccarray[j++] = singlEmail.trim();
         }
         msg.setBccAddresses(trimmedbccarray);
     }
     
     
     // Templates do need an object (Contact that he pdf will be used to generate against) for things like first name etc
     // So we are going to pick the first contact on the to list.
     Contact c = [select id, Email from Contact where email = :trimmedtoarray[0] limit 1];
     
     msg.setWhatId( order.id );
     msg.setTargetObjectId(c.id);
     
    
    
    
     lstMsgs.add(msg);

     //Send the email
     Messaging.sendEmail(lstMsgs);


    // clear out the temp fields we used to generate the email.
    order.le_Address_CC__c='';
    order.le_Address_BCC__c='';
    order.le_Address_to__c='';
    order.le_Body__c='';
    order.le_Subject__c='';
    order.le_Template__c='';
    
    
    update order;
        
        //Send the user back to the Order
        PageReference backToQuotePage = new PageReference('/' + order.id);
        backToQuotePage.setRedirect(true);
        return backToQuotePage;
    }
    
    
}


5) Create a button in the Order object to launch your “Email” screen


End Email Button

6) Update your Email template

Now update your email templates to use the “le_Body__c” and “le_Subject__c” fields for their email contents,

<messaging:emailTemplate recipientType="Contact"
    relatedToType="Order"
    subject="{!RelatedTo.le_Subject__c}"
    replyTo="orders@XXXX.com">
    <messaging:htmlEmailBody >

        <html>
        <c:EmailStyle />
        <body>
            <apex:outputText value="{!RelatedTo.le_Body__c}" escape="false"/>
        </body>
        </html>
    </messaging:htmlEmailBody>

    <messaging:plainTextEmailBody >
    <apex:outputText value="{!RelatedTo.le_Body__c}" escape="false"/>
    </messaging:plainTextEmailBody>

<messaging:attachment renderAs="PDF" filename="GeneratedEmail.pdf">
      <style>
      @page {
      size: A4 landscape;
      margin-top: 1.0cm;
      margin-left: 1.0cm;
      margin-right: 1.0cm;
      margin-bottom: 7cm;
        @bottom-center {
          content: element(footer);
        }

      }
      </style>

        <html>
        <c:EmailStyle />
        <body>
        
        //POSH PDF STUFF HERE

        </body>
        </html>
</messaging:attachment>

</messaging:emailTemplate>


Note:

So PDF’s generated by Email templates in Salesforce are not saved and you cant get hold of them, so we are not saving them in the custom email object, if you do need that, then you will need to convert your email templates to visual force pages then render as PDFs and save them in the custom objects.

New Platform Type New Client Type

I have been doing a lot of cloud dev in recent months, not Internet facing work (been doing that for over a decade), but proper work on various cloud platforms (4+ of them) and they have turned out to require a shifting of mental gears, not from a technical aspect nor from a platform or paradigm shift (saas) but from dealing with a different type of client point of view.

Now that seems odd, sure your cloud clients are nearly all the business rather than IT, but lots of my work is direct with the business and it is often a relief to do so as you can deliver a product that best matches the exact needs of the people that use it.

So why?

After a lot of head scratching and reviewing of the projects I have come up with the following reasons

  1. Sales before IT: With cloud based projects the sales team have very often just finished with the customer, so the customer arrives with the expectation that the platform is a PERFECT fit for everything they might want and it might just needs a tiny update to match their needs and that the update will only take a hour or 2…. but as is always true the devil it in the details, so when we look at their requirements and say that it’s going to take a week of hard work and then they will have to spend time testing, you have suddenly upset both their time frames and budgets. 1

  2. Client reflexes: A lot of the cloud clients are sales/marketing people or from another branch where haggling and negotiations are built-in, these people live in a fast moving world and have never liked the iterative and somewhat slow moving nature of traditional IT projects “I just want it to work how I want”. for such people paying “not a penny more” and getting more than you paid for are Good Things. A side-effect of this is that such clients are quick to anger when they require a change that will take more money or time. Small changes are non-stop with cloud projects where the client can see the work as it is done: I have heard phrases like “Just one more thing”, “It will only take 5 minutes”, “I had assumed” and — my absolute favourite — “It’s just common sense, it should do XXX,” more over the last six months than I have in the previous six years combined.

  3. They have already paid: Decent cloud services are not cheap and the clients have often already paid a fair lump before they get to customising their environment, so every penny you want is money they feel is an extra, very much like someone at a hotel, we all enjoy the extra stuff but are really unhappy to see it on our bill. 2

  4. Re-tooling: All of the new cloud platforms are feature rich and do a lot of things very quickly but that is often within the boundaries of a given tool or feature, I can see why this is so 3, you are aiming for the old 80/20 rule , so when a customer says “I just need it to do xxxxx” and you simply can’t make the tool do that, have then used a different tool and spent a load of time reconfiguring the new tool to look like the old one so you can add the one missing feature. it does not matter how clever that is or how hard you have worked, from a clients point of view you have turned a simple 5 min job into a 5 day job you and are from their point of view are not providing value for money 4.

  5. Client rapport: Most cloud customisations are quick things, as a developer you have had very little time to get to know the client, what they mean vs what they say, what pressures they are under, if they have budget for these changes etc etc, and they often just view you as someone just getting in the way of their shiny new cloud platform.

These relatively new changes in the client developer relationship mean you have to change your way of dealing with clients

So how do we fix this??

This is the hard bit, I have laid awake at night for a number of nights, wondering hard how to fix this, my time honoured method of working my guts off having failed me.

So far I have come up with:

  1. Make it human: Try and make the relationship one between humans, site visit if possible, Skype video if not, so clients feel that they are working with people and more importantly people who’s professional opinion they can trust.

  2. Speed up interactions: Not speed up coding as that has actually not got much faster with the new platforms, but speed-up the feedback you give clients, a quick Agile Scum with a client each morning can head a lot of bad things off and make them feel far more in the loop 5, use this to also keep them informed on how much the client has used / left in their bank / project pool, even it they have pushed for a fixed price, addionally the clients can cut their losses if a small change is going to take a long time.

  3. Be firm: I’m rubbish at this part but with cloud clients there is an underlying expectation that you get loads for free, and that includes any changes they might want to make after a spec has been agreed, there is a middle groud between “nickle and diming” and being used as a doormat, try and get a rapport with your client so that you both know where that is.

Any one else got any good ideas?


  1. Both Matt and Julian have been REALLY serious about avoiding this kind of thing on LDCVia and have made the phase “it will be easy, it will only take and hour or so” a capital offence. 

  2. One thing that I have found after multiple quotes, is that honesty works even less with cloud based quotes than it does with traditional IT quotes, I have had at least 3 occasions where I was genuinely puzzled that a quote I had done had not got picked for a spec, and a much cheaper quote was accepted, on all occasions I questioned the ability to deliver on a quote that low (even using offshore staff) and have been told each time that the competition just use the quote to get in the door then nickle and dime the project to death…. I hate that, I really hate it >:( 

  3. Hell I’m one of the co-developers of a cloud platform and when we are coding new stuff it always with an eye to “how can we spend our time on stuff that will get the most use”. 

  4. BTW the phrase “I’m trying to do what you asked” does not help here. 

  5. But be firm that the meeting is only of keeping everyone on track, it is not a place to add a few new requirements in to the spec every day (ohhh boy don’t they love to try that), and that each person does only get 2-5 mins, if they want a longer meeting, book it later in the day. 

Engage 2016

Where to start….

I should have done a proper blog after IBM Connect 2016, but its been so busy I did not make time, however a number of the points here that were just supposition at Connect have now been turned into facts.

Engage the Event

Theo Heselmans who for all intents and purposes IS Engage, managed to do the impossible and top last years conference, firmly establishing Engage as the best event after Connect, with a huge array of varied content and no subject taboo, all that is required is that the content is GOOD!!, there were a number of times when I really would have liked to be in two places at the same time and that has not happened at a conference in ages.

The venue was the crazy Evoluon in Eindhoven which seemed custom built for such event (if they could get a grip on the wifi)

In a cheeky moment Theo did a backpack give away (because Connect did not this year for the first time)

Back Pack

LDC Via

We went live with LDC Via one year ago at the last Engage so it holds a special place for us, in that year a lot has happened and we have delivered tons more, but we got a lot more attention this year and found that we even have some competition, in this last year we have become established in peoples minds and people realise we offer a great product, all 4 of us were there and did not seem to have a quiet second, as always the speed sponsoring was exhausting and Julian did a great job on the 30 second new speed sponsoring to the whole conference, Matt White was bogged down with cold but still fought his way through the conference and drove us both there and back while at the same time giving his flipping cold to the rest of us.

This years give away “Colin” did sterling work and won the unofficial “best conference give-away” from a number of sources.

Colin


We tried a different tack with the sponsor session, showing how many ways you could integrate LDC Via into different frameworks (slide deck below)


LDC Via building a new app from Mark Myers


IBM and Champions

Well bugger me… Inhi Cho Suh really impressed us all, from the little we saw of her at Connect (she was only introduced to the community right at the end of the conference) we guessed that she might not only be sane but sane and HUMAN and it turned out that she was!!, far more than we had all dared to hope, no “two tassel talk”1, she had fresh new ideas and had already started acting on them (such as moving Connect to San Francisco in 2017), we had a proper round table event where she dealt well with the hysterical gibbering we blasted her with and left us feeling that it might actually be possible to finally turn things around and start IBM ICS again (somebody pinch me)

On that note being a champion meant something at Engage and made me really think that I must buck my ideas up and start delivering far more.

The Community

Sadly I was doing another round of late night work while I was there so missed out on the parties and such (hence no photos), but judging from the state of my fellow LDC Via colleagues, the events and evenings were great fun and even members who were no longer in the IBM world turned up to revive past glories.

I got happy gifts from friends, Carl Tyler played mule for the amazing vegan mayonnaise that I cant get in Europe, and Rene Winkelmeyer got me the most amazing energy drink

Engage Food

Gabriella Davis got me this totally apt t-shirt (which has since been pinched by my wife)

Tshirt

Me

The session I luckily got accepted for was with Paul Mooney and was on Salesforce, a relatively new skill set for me and we were standing room only (mainly due to Paul), but people liked it and we were asked lots of good questions.

Saleforce For Domino Dogs from Mark Myers



Other than that, it was mayhem, I had terrible client overflow and was running around all over the place stressing every second, but frankly I would not change it for the world. roll on next year.


  1. “two tassel talk” : This is the long stream of corporate platitudes (sort of the corporate version of what politicians say) that you get off senior managers that are just marking time in their current role before they hope to be promoted away. 

LDCVia Webinar

As we ramp up for Connect 2016, we decided to do a quick introduction to LDC Via. this means that if you see something you want to ask questions about or a feature that is a must have we can sit down over a drink at Connect and see if we can solve them.

So come join us and listen to Matts dulcet tones (as well as Julian)


ldcvia-webinar.png

Current Android Software 2015

This is more an aide memoire than anything else (in case of a phone rebuild), but it is the list of essential software I have on my phone at the end of 2015


Audio/Media

DI Radio

Audible

Google Play Music (so much better than Spotify for play lists and radio)

Dog Catcher (for podcasts)

MX Player

Music Folder Player Full (the only decent player for displaying audio as it is laid out in the filesystem)

BBC Iplayer Radio


Productivity

Clockwork Tomato (The Best timer for the Pomodoro Technique)

Power Nap

Freshbooks

Wunderlist

Timely


Communication

Slack (a truly amazing team chat)

Skype

Twitter (The stock version is actually the best)

Facebook (Unfortunately)

Go To Meeting

IBM Verse


System

Dropsync

File Explorer

1 Password

Disk Usage

Swiftkey


Games (I tend to not play games on my phone as I have a Nvidia Shield Tablet)

mahjong

Chess

Sorcery 1 (or any choose your own adventure game)

Gemini rue


Misc

National Rail Enquiries

Speedtest.net

Sworkit pro

Moovit (best for London bus times)

Priority Pass

Plus mobile banking and mobile ISP provider’s app.

Salesforce read mode hide-when hack

It seems the need for hacks has not gone away with the move to cloud, but you do have to be more careful, as I have already found out Salesforce can break your custom code at will.

So that being true one of the things that SalesForce does not seem to have that every other framework does is a simple an powerful “hide when”, IMHO this feature should be present in every line button and object on every page and most platforms do,

It is the most requested feature for customisation that I have come across, and this is the hack that I use for read mode documents or forms (which strangely is where the request is most often made) (and yes it is a hack)

We are going to just stuff some JavaScript into a apex page, you can see an example of it below

<apex:page standardController="Case" showHeader="false" sidebar="false">

<script>

myVar = checkforbutton();

function checkforbutton()
{
    if (typeof(parent.document.getElementsByName("searchArticles")[0]) != "undefined" )
    {
               if ( parent.document.title.indexOf("Customer Community") != -1) {        
                   parent.document.getElementsByName("searchArticles")[0].style.display = "none"; 
               }
    }
    else
    {
            window.setTimeout("checkforbutton();",100);
    }
} 


</script>

   
</apex:page>


Lets break it down

  1. We have to use “parent.document” to get JavaScript objects as when we use this page SalesForce will embed it inside a Iframe

  2. We have to do a wait loop that keeps looking for the object till it finds it (then stops), because SalesForce adds button objects in after the page loads so they wont be there when it first opens

    if (typeof(parent.document.getElementsByName("searchArticles")[0]) != "undefined" )
    {
            //do stuff
    }
    else
    {
            window.setTimeout("checkforbutton();",100);
    }


  1. When the button is confirmed to be there then we are going to check the page for a condition(s) and if it’s true/false we are going to hide the button/element on the basis of it, in the above example, if we are on the “Customer Community” version of a page, we don’t want to allow the users to search for articles, so we hide the “searchArticles” button, it’s not a security issue, we just don’t want to confuse the user experience by allowing this feature.

So we put this code into a Page

SF Page

This insert that page into the layout Object layout we want it to effect.

SF Page

that would normally give a big white space where the inserted form lives, so we make the page a 1% by 1px block


SFHIDEWHENHACK03.png

And that’s it, just save the layout, the button/”what ever” will hide when the page loads, a hack but a simple reliable hack

Now as always “hide when” is not security, remember to make sure that you don’t leave functions exposed and think this kind of thing covers you.

Classic Domino and multi country dates with Bootstrap

I was doing some fixes on a classic domino web app that uses bootstrap datepicker when an issue was raised. turns out its a bugger to get the jquery datapicker and domino date format to agree with each other for different countires ie mm/dd/yyyy or dd/mm/yyyy or dd.mm.yyyy

you would think that a little bit of JavaScript would solve the problem but there was multiple instances with a variety of browsers where it ended up that what ever domino was doing to calculate the date format was not matching the result of the JavaScript.

So we cheated, we replaced the “format:” parameter in the date picker below:

$('#MYDATE').datepicker({
    format: "mm/dd/yyyy",
    clearBtn: true,
    orientation: "top auto",
    todayHighlight: true,
    autoclose: true,
    weekStart: 1
 });


with some computed text with the following formula:

dat := @Text(@ToTime("01/28/1900");"D0S0") ;
sep := @Middle(dat ;2;1) ;
@If( @Left(dat; 2) = "28" ; "dd" + sep + "mm" + sep + "yyyy" ; "mm" + sep + "dd" + sep + "yyyy")


I find the best way is to put this in the default setting meaning you only have to do it once

$.datepicker.setDefaults({
     dateFormat: '<Computed Value>'
});


Simple, worked fine with a wide variety of date formats and kept everything in sync with what ever format Domino ended up picking.

C3 charts on Saleforce Winter16

As @devinthecloud points out in his Blog post Salesforce Winter 16 wrecked C3 charts on the pages he and I had developed. he found the removal of <apex:form> fixed the issue on his pages, but on my page the charts were still broken, so instead of this:


Salesforce-C3-Charts-01.png

You get this


Salesforce-C3-Charts-02.png

I stripped the page down to a bare minimum that you can use to recreate the issue, see below,

<apex:page docType="html-5.0" 
           applyBodyTag="false"
           showHeader="true"
           readOnly="true"
           sidebar="false">
<html lang="en">
  <head>
      <!-- Static Resources for CSS -->
        <link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css" rel="stylesheet"/>
    </head>
    

    <body>
      <div id="chart"></div>

      <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js" />
      <script>
        var chart = c3.generate({
          data: {
            columns: [
  //            ["setosa", 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5, 0.2, 0.2, 0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2, 0.2, 0.2, 0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3, 0.2, 0.2, 0.2, 0.2],
              ["versicolor", 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6, 1.0, 1.3, 1.4, 1.0, 1.5, 1.0, 1.4, 1.3, 1.4, 1.5, 1.0, 1.5, 1.1, 1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7, 1.5, 1.0, 1.1, 1.0, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 1.2, 1.4, 1.2, 1.0, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3],
              ["virginica", 2.5, 1.9, 2.1, 1.8, 2.2, 2.1, 1.7, 1.8, 1.8, 2.5, 2.0, 1.9, 2.1, 2.0, 2.4, 2.3, 1.8, 2.2, 2.3, 1.5, 2.3, 2.0, 2.0, 1.8, 2.1, 1.8, 1.8, 1.8, 2.1, 1.6, 1.9, 2.0, 2.2, 1.5, 1.4, 2.3, 2.4, 1.8, 1.8, 2.1, 2.4, 2.3, 1.9, 2.3, 2.5, 2.3, 1.9, 2.0, 2.3, 1.8],
              ["setosa", 30],
  //            ["versicolor", 40],
  //            ["virginica", 50],
            ],
            type : 'pie',
            onmouseover: function (d, i) { console.log("onmouseover", d, i, this); },
            onmouseout: function (d, i) { console.log("onmouseout", d, i, this); },
            onclick: function (d, i) { console.log("onclick", d, i, this); },
          },
          axis: {
            x: {
              label: 'Sepal.Width'
            },
            y: {
              label: 'Petal.Width'
            }
          }
        });

        setTimeout(function () {
          chart.load({
            columns: [
              ["setosa", 130],
            ]
          });
        }, 1000);

        setTimeout(function () {
          chart.unload({
            ids: 'virginica'
          });
        }, 2000);

      </script>
    </body>
</html>
</apex:page>


This let me narrow it down to the Salesforce header.

when you set showHeader=”true” it breaks

if you set showHeader=”false” it starts working

As this is obviously and provably down to a change in winter 16 I can raise it with Salesforce and get a fix.

…….. Wrong!

I quote

“At times, Client Side JS conflict with SFDC header JS will collide with already defined functions with the same name.”

“the behaviour of JavaScript is inconsistent with Salesforce components.”

and

“as we don’t support JavaScript”

Ah it’s nice to see that young Internet companies have the same grasp of customer service as the traditional IT companies and thus it falls back on consultants to fix, in this case with an Iframe, I’m not a fan of Iframes normally but as Salesforce use them themselves there is precedent

And so we now split our single page into 2 pages, an inner content and an outer Iframe wrapper

First we take out the existing page (it was called “chart_test”), rename it to “chart_test_inner” and set showHeader=”false”

Then we put in a Iframe wrapper with the old name and a bit of CSS to make it size properly then point it to the inner content

<apex:page docType="html-5.0" 
           applyBodyTag="false"
           showHeader="true"
           readOnly="true"
           sidebar="false">
<html lang="en">
  <head>
  
  <style>
  .fluidMedia {
    position: relative;
    padding-bottom: 56.25%; /* proportion value to aspect ratio 16:9 (9 / 16 = 0.5625 or 56.25%) */
    padding-top: 30px;
    height: 0;
    overflow: hidden;
  }

    .fluidMedia iframe {
        position: absolute;
        top: 0; 
        left: 0;
        width: 100%;
        height: 100%;
    }
      </style>
  
  </head>
    
    <body>
    
    <div class="fluidMedia">
        <iframe src="../apex/chart_test_inner" frameborder="0" > </iframe>
    </div>
       
    </body>
</html>
</apex:page>


And now instead of a broken


We have a working


Hooray!!!

Updating Statamic on AWS

For this blog I use Statamic, a very nice website CMS bassed on Markdown and using flat files which makes it perfect for the way I work in that I can link a Drop box account to the cheap AWS server I use for hosting and then edit blogs via mobile on a wide variety of machines with just a test editor.

Anyway the site has been rock solid for ages (5500+ hours) when I suddenly realised I wanted to upgraded the Statamic version to take advantage of some new features, that’s an easy job, you just replace a couple of directories in the httpd WWW directory, but I got a couple of errors and realised that I had an old version of PHP53 on the server and I had not patched it for a while (wince). also it had been so long since I had even logged on to the box that I could not remember what to do, so this is just an aide-memoire for those in the same situation

as I’m on Linux you need to make sure your AWS pem is secure sooo

sudo chmod 644 serverkey.pem


Then connect to the box with SSH

ssh -i serverkey.pem ec2-user@XXX.XXX.XXX.XXX


Now first things first, lets do a full update

sudo yum update


Once that is done, we have to remove http and php to update them all (yes you will get an outage)

sudo yum remove php httpd php-cli php-xml php-common httpd-tools


This will uninstall the server its self (but not your website), lets install the new version

sudo yum install php55 php55-pdo php55-gd 


If you notice I added “php55-gd” to the install as you will need this for some of the new Statamic features such as the file and gallery features. Quick start the server before anyone notices

sudo service httpd start
 


You will find that the site seems to work fine, but as soon as you attempt to go to a individual blog you will find it gives you a 404, this is because the htaccess files in Statamic are being ignored so you will have to go back and tell httpd to not ignore them. so you need to edit the httpd.conf file

So first lets go to the httpd config directory

[ec2-user@ip-XX-XXX-XX-XXX /]$ cd etc/httpd/conf
 


And edit the httpd.conf file ( a good cheat sheet to vi is Here )

sudo vi httpd.conf


change the instances of “AllowOverride None” to “AllowOverride All”

once that is saved you just restart httpd

sudo service httpd restart


And you should be all done.

Icon UK 2015

A very hectic Icon UK has just passed in a blur, leaving a hangover and a sense of satisfaction.

Tim Clark put on great display aided by a number of brave souls, with great content and facilities (ignoring the on site WIFI) and amazing after event social times.

As always the IBM community put on its best and came out with a wide variety of vendors and attendees (most of them long time friends that I get to see far too infrequently) all very positive and with fresh new ideas.

But for me the highlight of the conference was the arrival of IBM Marketing’s Penny Hill and the IBM champion manager Amanda Bauman , marketings absence has been a long bug bear and to finally meet someone and be able to offer help to and get help in return was wonderful ( so Penny or Amanda if you are reading this, I was serious about just yelling if there was anything I could do to help and I suspect that applies for a lot of the community.) I also must not forget the none marketing branches of IBM who also came out, took criticism and came back with excellent answers, well done all round.

LDC Via was taken far more seriously by attendees then in previous conferences (well it seemed so to me), with us having the highest turn out of all the vendor sessions, so much so that we ran out of Gin and Pimms (and no we did not tell people before the session that we would be serving drinks) and a good stream of people with serious questions and excellent use case scenarios, leaving use with a ton of leads to follow up and a bunch of new features to go Gold with.

No technical presentations for me this time though I did help with Tim and Femke’s presentation as well as present the Changing technologies with Gab Davis


Chris Harris was taking the good pictures this time around and did a great one of the LDCVia team. The proper serious one will appear on the official LDC Via blog for the event but in the mean time here is one of the silly ones.


UKIcon2015-1.jpg

Latest Blogs