Tuesday, 14 May 2019

Custom Notifications in Summer 19 Part 2 - Apex

Custom Notifications in Summer 19 Part 2 - Apex

Introduction

In Part 1 of this post I covered sending a custom notification from Process Builder when a record was created or edited with a specific attribute - a High Priority case to be exact. In this post I’ll cover sending a custom notification from Apex, although the notification is still actually sent from a Process Builder process, the logic around whether to send it lives in Apex.

To Code or Not to Code

The first question to ask yourself in these situations is do I actually need to go the Apex route. A process can send a notification when a record is created or edited to match a specific set of criteria, which coves a multitude of use cases. A couple of reasons why you might consider Apex are:

  • You want to send notifications for a large number of sObject typed and don’t want to create hundreds of processes. Not the greatest reason, but it would keep the process count down and thus remove some of the burden on your admins.
  • Separation of duties - if you are a developer and need a mechanism to send a notification without creating a new process, as you aren’t allowed to and the admins have a backlog of work. Again, not a great reason, as the governance is driving the solution, but this kind of thing does happen so we shouldn’t pretend it doesn’t.
  • When you want to send a notification only in specific circumstances, not every single time a record is created or edited. This is the most appropriate reason in my opinion - while you could create attributes to represent the circumstances in the record, you would be polluting your actual data with metadata to trigger functionality.

Platform Events

A process can be started in response to a number of things happening, but the one that can be used from Apex that isn’t changing a record is in response to a Platform Event. For the purposes of this post I’m reusing the Demo Event that I created for my Lightning Emp API in Winter 19 blog post.

Message sObject

In Part 1 of this post I mentioned in passing that the mechanism for generating notifications is better but not perfect, and this is a big reason why. As a process cannot use the payload of a platform event in decisions or actions, only as part of the entry criteria and choosing the record to use, I have to burn a custom object to hold details of the messages that I want to send. Not a huge deal, but it does add a certain clunkiness to the solution.

Custom Notification and Process Builder

As in Part 1, I need a custom notification type, Message in this case, to dovetail with the sObject name. I can then create a process builder that is started when a platform event is received and accesses a Message sObject whose ID is the platform event payload:

The notify action is trigged in all cases, as the logic is applied by Apex before the platform event is published, and sends a notification based on the contents of the associated Message record:

The Apex Code

Again from my my Lightning Emp API in Winter 19 post, I’m using the PlatformEventsDemo class to send the platform event after creating the Message record with details of the notification message and the user I want to send it to (there’s a link to the full solution at the end of this post):

Message__c message=new Message__c(Name='Demo Message',
                                  Message__c='Hello Bob!', 
                                  User__c='005B00000015moV');
insert message;
PlatformEventsDemo.PublishDemoEvent(message.Id);

Executing this code causes the red bell to display on the desktop and mobile, and the notification contains the message I sent:

Sharing is Caring

You can find the objects/events/code for this and the Part 1 post in my Summer 19 Samples repository.

Related Posts 

 

Sunday, 5 May 2019

Custom Notifications in Summer 19 Part 1 - Process Builder

Custom Notifications in Summer 19 Part 1 - Process Builder

Introduction

The Summer 19 Salesforce release is around a month away (check the trust site for the official dates) and my trusty pre-release org has been upgraded which allows me to play with some of the new functionality.

One of the items in the release notes that caught my eye was custom notifications, possibly because I’d been on the pilot and had been looking forward to using it in anger, possibly because I had some solutions that used the old method (see below) of sending notifications and it hurt my eyes every time I looked at it. Either way, I was keen to jump in.

The Old Way

To be clear (oh dear, I’m sounding like a UK politician) we’ve always been able to send notifications through custom code, but it’s been clunky, to put it nicely. You can read the full details in Salesforce1 Notifications from Apex, but the short version is that you have to programmatically create a chatter post using the ChatterConnect API and @mention the user you wanted to notify, and they received a notification that you had mentioned them and had to go to the chatter post to find out what you wanted, Not particularly elegant, I’m sure you’ll agree.

The New Way

Custom notifications are a much better solution - still not perfect but a big improvement on what we currently have. At the moment they are sent from Process Builder, so there’s still a little bit of hoop jumping required to send from Apex code.

Defining the Notification

Before you can send a custom notification, you need to define one via Setup -> Notification Builder -> Notification Types. Click New to create a new notification - for my first example I’m creating a custom notification for when a high priority case is received. Note that I can specify which channels a notification will be sent through. This is a nice feature as I’m more likely to want to notify Mobile users as a rule, as they are out of the office and may not be checking Salesforce that often. That said, as this is a high priority case notification, I’m sending it out everywhere that I can:

Once I have my notification, I can create a process that uses it -note that this is the only way that I can fire a notification directly.

Process Builder

My process is defined for the Case subject, when a record is created or edited:

The high priority case test looks for cases that are new or edited to change the priority field, and the priority field is ‘High’:

And the High Priority Case action sends me a notification that we are not in a good place.

After saving and activating the process, creating a new case with a priority of ‘High’ gives me red bell icon on desktop and my mobile, and a notification that is entirely appropriate to the case - clicking on the detail takes me through to the case itself. which is exactly what I want.

In Part 2 of this post I’ll show how notifications can be started from Apex. You still need a process builder to actually send the notification, but the logic around it can live elsewhere.

Related Posts

 

Sunday, 14 April 2019

Push Source Faster with the Salesforce CLI and VS Code

Push Source Faster with the Salesforce CLI and VS Code

Introduction

When working with SalesforceDX scratch orgs and VS Code, deploying source is as simple as opening the command palette and choosing the correct command. If there are errors, these are captured in the problems view and I can simply click on the problem to open the file:

Not too arduous right? Actually, it can be, especially when I’ve been on a train or plane and done a bunch of offline work that I’m then trying to deploy. After about a thousand push, fix, repeat cycles, opening the menu and choosing an option seems slow.

Configuring the Default Build Task

Note: this isn’t the way you want to do it when pushing source to a scratch org - it is for the metadata API and it’s also a useful thing to understand. I’m trying to build some suspense really.

As I’ve written before, I can configure any shell command as the default build task in VS Code.

To set up source push as the default, I :

  • open up the command palette and choose ‘Tasks: Configure Default Build Task’
  • choose ‘Create tasks.json file from template'
  • choose ‘Other’

I then replace the contents of the tasks.json file with :

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "command": "sfdx",
            "args": [
                "force:source:push"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

and I can now run the push as the default build task using the key sequence SHIFT+COMMAND+B (on a Mac):

There’s one downside to this and it’s quite a biggie - the problems view is empty so I have to look at the command output to figure the problem and manually locate the problem file and line. Luckily I can solve this relatively easily (it requires regular expressions so obviously there’s a number of attempts to get this right) by adding a problem matcher to parse the output and find any errors:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "command": "sfdx",
            "args": [
                "force:source:push"
            ],
            "problemMatcher": [
                {
                    "owner": "KAB-apex",
                    "fileLocation": [
                        "relative",
                        "${workspaceFolder}"
                    ],
                    "pattern": {
                        "regexp": "^(.*)  (.*) \\((\\d+):(\\d+)\\)$",
                        "file": 1,
                        "line": 3,
                        "column": 4,
                        "message": 2
                    }
                },
                {
                    "owner": "KAB-lc",
                    "fileLocation": [
                        "relative",
                        "${workspaceFolder}"
                    ],
                    "pattern": {
                            "regexp": "^(.*) \\s \\w*:(\\w*:)(\\d+),(\\d+):\\s(.*)$",
                            "file": 1,
                            "line": 3,
                            "column": 4
                    }
                }
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

Now the problems view is populated again, so I have the same functionality with shortcut to kick the deployment off:

The Easy Way

Replacing the default build task is something that I’ve been doing on most of my projects to wire in a node script that manages deployments via the Metadata API. In that scenario I didn’t have any other options, but in this case it felt like I was having to recreate a lot of things to replace standard functionality. It felt like I should be able to create a shortcut to the entry in the command palette, but every time I googled I only got results around binding keyboard shortcuts to tasks.

A long time after I’d given up, I was looking to create a regular keyboard shortcut and opened the menu Code -> Preferences -> Keyboard Shortcuts and absent-mindedly typed ‘SFDX’ into the resulting screen, probably because it reminded me of the command palette:

The set of SFDX commands appeared! Scrolling down I found the source push command, and hovering over this showed a ‘+’ button that allowed me to define a shortcut key sequence - I choose SHIFT+OPTION+P:

Having configured this, I can now push the source simply by pressing that key combination, and I haven't had to replace any of the standard functionality:

As mentioned earlier, I’ve looked for a way to do this a number of times and had no luck - why that is the case I don’t know, but at least I got there in the end! As long as I don’t think about how much time I could have saved, it’s fine.

Related Posts

 

Saturday, 6 April 2019

Lightning Web Component Animated Progress Bar

Lightning Web Component Animated Progress Bar

Introduction

Lightning Web Components went GA in Spring 19, to the delight of some and consternation of others. Rather than a critique, which would be pretty short at the moment given how little real life usage I’ve had out of them, I decided to take one of my Aura Components (remember, Lightning Components are renamed Aura Components to avoid confusion with Lightning Web Components) and convert that to a Lightning Web Component.

The component in question is from my Animated Lightning Progress Bar blog post, which as the name suggests animates a progress bar from the current value to the desired value. 

Tracking Values

Properties of the Lightning Web Component annotated with @track annotation are tracked (no kidding!) by the framework and the contents of the component are automatically re-rendered when a tracked value changes. In this example I have one tracked property:

  • value - the current value being displayed in the progress bar

As mentioned in the original blog post, animating a progress bar is simply a matter of making small changes to the current value via a timer function, until it matches the desired value, and redrawing the progress bar every time the current value changes. By binding the progress bar element to the value property, every time I change it in JavaScript the progress bar is redrawn. Nice.

The other great thing about this is that I don’t have to use any special functions to read or write the value of the tracked property - I just use it or set it as I need to and the framework takes care of the rest, simply because of the annotation. I don’t think I’ll miss the component.get/set(‘v.<name>’) type functions that are liberally sprinkled over my Aura Component controllers.

Re-Animator

One aspect immediately flagged up as different - I’m using the standard  lightning-input component with an onchange handler to fire when the user changes the value. The change handler is called every time the user types something, rather than when they tab out etc. Initially I was starting the animation as soon as the change event was received, but if the user then continued typing it wasn’t the greatest experience. To solve this, I delayed taking any action until 300ms after the user last pressed a key, via the standard JavaScript setTimeout function. When the change handler fires, it clears any existing timeout and detects if the value input by the user has changed. If it has, a  timeout is scheduled for 300ms time to start the animation. If the user continues typing then the timeout is continually cleared and rescheduled for another 300ms time. When the user finally stops typing (or stops for 300ms!) the timer fires and the animation is started.

The example animation increments or decrements the current value until it matches the amount input by the user, decrementing being used if a desired value is entered that is smaller than the current value. Another standard JavaScript function, setInterval, is used to execute a function every 100ms that updates the current value.  Once the final value matches the current value, the interval is cancelled.

 

 

What’s Different?

There are a few differences compared to the Aura component:

  • As mentioned above, property/attribute access is much cleaner. I also don’t have to pollute my markup with declarations of attributes.
  • In the Aura Component when the timer function fired it was outside the framework lifecycle, so needed to use the $A.getCallback function. In Lightning Web Components there’s no need to do this, I can just treat it as any other asynchronous Javascript function. This is very much the experience that I’ve been having with Lightning Web Components - everything feels a lot closer to standard JavaScript rather than programming against a library or framework.
  • My event handlers don’t have to have a “c.” prefix, again it looks like I’ve defined a regular JavaScript function and am using it.
  • Only one JavaScript file! No more JavaScript controllers that delegate to helpers, or business logic striped across these two and a renderer.
  • To make the component available to the Lightning App Builder, I add a targets stanza to the XML metadata for the Lightning Web Component, again avoiding polluting my markup with information for the framework.

The Code

There are three elements to this component, available at the following Gists:

One More Thing

In true Columbo style, there’s one more thing to mention that you’ll see in the component markup. The ESLint for Lightning Web Components will complain about setTimeout and setInterval. As I am using them for good reason, I don’t need to hear any more of it’s whining. I can stop this by adding a comment before the line of code that it dislikes:

// eslint-disable-next-line @lwc/lwc/no-async-operation
let timeoutRef = setInterval(function() {…});

Related Posts

 

  

Friday, 15 March 2019

O Trailhead! myTrailhead!

O Trailhead! myTrailhead!

Captain

Introduction

After a fairly lengthy wait (announced at DF 17 and 18) myTrailhead officially launched on March 6th 2019. Simply put, this allows you to provide much of the Trailhead features that you know and love (minus some, plus some others) within your organisation to create your own continuous learning system. Trails, modules, badges and points are all there.

The main addition is you can add items such as corporate presentations and documents to a trail, so you can re-use existing collateral without having to migrate it to Trailhead quiz format. You can also combine standard Salesforce Trailhead modules into your own trails, so there’s no need to reinvent the wheel.

The big minus is that (I think) the automated checking of code/configuration assignments isn’t (currently) available. While I’ve seen references to Trail Checker, as far as I can tell this is more of a manual check than the kind of automation we are familiar with from Superbadges. I can’t say I’m surprised by this - turning a verification system of this nature into a product is no small undertaking, but it would be a very powerful addition for those of us regularly on boarding admins and developers to maintain our existing Salesforce applications.

Familiarity Goes a Long Way

The familiar styling should help adoption. Trailhead is extremely widely used by Salesforce admins, devs, and users (and many of their children, for some reason) and a UI/UX that they are already intimately familiar with will immediately remove some barriers. I’m also pretty sure that the chance to earn more badges and points will be jumped on with alacrity.

Content is King

myTrailhead also includes content management - modules and trails are combined into releases that can be published (accessible to your users) or unpublished (the next iteration, currently being created or reviewed), giving fine grained control on when users can access content and ensuring that it is fit for purpose. As mentioned earlier, you can link to existing Trailhead content so you have a head start in terms of material that isn’t specific to your business.

This is the mechanism of managing content that is provided by myTrailhead. However, creating the content is a task that is all yours and should absolutely not be underestimated. Managing a library of engaging training content and ensuring this is kept up to date when underlying processes or applications change can be a huge task. I can’t imagine how long the Trailhead content team spend on this for a new Salesforce release, but one thing I can tell you is that they don’t ask the developers to do it in their spare time, so if you want a system that will be used, be prepared to invest in a content team of your own. By the same token, if you library consist of half a dozen badges from a couple of years ago, don’t be surprised if nobody is interested in earning them.

Licensing

Up until now I’ve been broadly positive about this, which might come as a surprise to regular readers of this blog, and here comes the negativity. I think Salesforce have made a bit of a mistake with the licensing.

myTrailhead is a $25/user/month add-on. While this isn’t cheap, that isn’t where my beef lies. Instead it’s the fact that it’s an add-on to an Enterprise Sales/Service/Platform license. So if I’m part of a large company (I’m not) and I want to use myTrailhead for staff that aren’t Salesforce users, I have to buy them a Salesforce license they will never use and then add myTrailhead on top of it. And of course I won’t do that, as it makes the cost prohibitive. Instead I’ll do it all on another platform or run two training systems, one for Salesforce users and one for everyone else, which will cause confusion. Or I’ll buy 10 licenses and continually cycle them around users when new training content becomes available.

A standalone license including myTrailhead and chatter, for example, would make much more sense from a purchasing perspective and allow me to train all my users through a single system. Hopefully this is being used to throttle uptake in the short term and we’ll see more licensing options in the future, otherwise I fear that it will only achieve a fraction of its potential.

Related Posts

 

  

Monday, 21 January 2019

Unsaved Changes in Spring 19

Unsaved Changes in Spring 19

Introduction

As I mentioned in my last post, it’s often the little things in a release that make all the difference. Another small change in the Spring 19 release is the lightning:unsavedChanges aura component (yes aura, remember that in Spring 19 Lightning Web Components are GA and Lightning Components are renamed Aura Components). The release notes are somewhat understated - "Notify the UI about unsaved changes in your component”, but what this means is that I can retire a bunch of code/components that I’ve written in the past to sop the user losing their hard earned changes to a record. Even better, I’m wiring in to the standard Lightning Experience behaviour so I don’t need to worry if Salesforce change this behaviour, I’ll just pick it up automatically.

Example

My example component is a simple form with a couple of inputs - first and last name:

<aura:component implements="flexipage:availableForAllPageTypes">
    <aura:attribute name="firstname" type="String" />
    <aura:attribute name="lastname" type="String" />
    <aura:handler name="change" value="{!v.firstname}" action="{!c.valueChanged}"/>
    <aura:handler name="change" value="{!v.lastname}" action="{!c.valueChanged}"/>

    <lightning:card variant="narrow" title="Unsaved Example">
        <div class="slds-p-around_medium">
            <lightning:input type="text" label="First Name" value="{!v.firstname}" />
            <lightning:input type="text" label="Last Name" value="{!v.lastname}" />
            <lightning:button variant="brand" label="Save" title="Save" onclick="{! c.save }" />
        </div>
    </lightning:card>

    <lightning:unsavedChanges aura:id="unsaved"
                onsave="{!c.save}"
                ondiscard="{!c.discard}" /> 
</aura:component>	

I have change handlers on the first name and last name attributes, so that I can notify the container that there are unsaved changes. I achieve this via the embedded lightning:unsavedChanges component, which exposes a method named setUnsavedChanges. In my change handler I invoke this method:

valueChanged : function(component, event, helper) {
    var unsaved = component.find("unsaved");
    unsaved.setUnsavedChanges(true, { label: 'Unsaved Example' });
}

So now if I add this component to a Lightning App page, enter some text and then try to click on another tab, I get a nice popup telling me that I may be making a big mistake. It also displays the label that I passed the setUnsavedChanges method, so that if there are multiple forms on the page then the user can easily identify which one I am referring to. 

Screenshot 2019 01 20 at 11 20 02

Of course, my Evil Co-Worker immediately spotted that they could pass the label of a different component and keep the user in a loop where they believe they have saved the changes but keep getting the popup. If I’m honest I expected something a bit more evil from them, like calling a method that clears the unsaved changes without saving the record when the user clicks the Save button,  clearly getting lazy as well as Evil in their old age.

What’s even nicer is that if I click the Discard Changes or Save buttons, my controller methods to discard or save the record are invoked, because I specified these on the component:

<lightning:unsavedChanges ..." onsave="{!c.save}" ondiscard="{!c.discard}" /> 

so I have full control over what happens.

This kind of interaction with the user is possible when I click on a link that is managed by the Lightning Experience, but not so much if I reload the page or navigate to a bookmark. In this scenario I’m at the mercy of the beforeunload event, which is browser specific and much more limited.

Screenshot 2019 01 20 at 11 36 40

This behaviour can’t be customised, the idea being that you can’t hold a user on your page against their will, regardless of whether you are doing it for their own good. 

On another note, when I created the original lightning app page for this I used a single column, but the inputs then spanned the whole page. Thanks to the Spring 19 feature of changing lightning page templates, I was able to switch to header, body and right sidebar in a few seconds, rather than having to create a whole new page. I sense that feature is the gift that keeps giving.

Related Posts

 

Saturday, 12 January 2019

Change Lightning Page Template in Spring 19

Change Lightning Page Template in Spring 19

Introduction

Sometimes it’s the little things that make all the difference, and in the Spring 19 release of Salesforce there’s a small change that will save me a bunch of time - support for changing the template of a Lightning Page. I seem to spend a huge amount of time recreating Lightning pages once I add a component that needs more room than is available. Often this is historic Bob's fault, because I’ve written a custom component that needs full width, but when I originally created the page I didn’t foresee this and chose a template that is now obviously unsuitable.

Changing Template

Here’s my demo page - as you can see the dashboard is a bit squashed as I’ve gone for main region and sidebar:

Screenshot 2019 01 12 at 16 13 44

Changing template is pretty simple - in the Lightning App builder (it can’t be long before this is renamed the Lightning Page builder can it?) edit the page and find the new option on the right hand side:

Screenshot 2019 01 12 at 16 15 13

Clicking this opens the change template dialog - initially, much like creating a page I get to choose from a list. I’ve gone for header and right sidebar so that my dashboard can take the full width header section:

Screenshot 2019 01 12 at 16 15 51

The next page is a departure from previous experience, in that I need to tell the dialog how to map the components from the old to the new template - I’ve left it as the defaults aside from the main region (which has my dashboard) which I add to the new header region:

Screenshot 2019 01 12 at 16 16 10

Once I’ve saved the page, I can view it and see the dashboard in it’s full width glory:

Screenshot 2019 01 12 at 16 16 41

Deploying Changes

While it’s great that we can do this through the UI, if I change the template of a Lightning Page in a sandbox I’d like to be able to deploy it via the metadata Api to production. When I tried this initially I had my API version set to 44.0 in my package.xml, which meant that I wasn’t hitting the Spring 19 metadata Api, but the Winter 19 version which doesn’t support template changes. Once I updated that, it all worked fine. If you are wondering how I can make such an obvious mistake, allow me to point you at this post, which explains everything.

Related Posts