mitchellstutler
Tera Contributor

The Service Portal has an extremely useful feature called Record Watch. Record Watch allows you to configure a listener function that notifies your widget when certain database actions take place. When you have a Record Watch function configured, your widget can automatically adjust itself accordingly.

In this example, I am going to explain how I added a Record Watch listener function that automatically increases the size of a bar in a bar chart when a matching record is added. This will build on a previous post of mine which can be found here, so this post will strictly focus on the Record Watch portion.

Record Watch Function

First, you'll want to inject spUtil into your client script function parameters. I'll post my full client script at the end in case you aren't sure where to put this.

Here is my Record Watch function which I will walk through:

spUtil.recordWatch($scope, "incident", "active=true", function(name, d) {                                        

                      if (d.action == 'entry') {

                                              for (i=0; i < $scope.activeData.length; i++) {

                                                                      if (d.record.category.display_value == $scope.activeData[i].category) {

                                                                                              $scope.activeData[i].value++;

                                                                                              break;

                                                                      }

                                              }

                                              $scope.updateBars($scope.activeData);

                      }

});

In the first line, we call the Record Watch function from spUtil. The second parameter we pass is the table that we want to listen to and the third parameter is the filter so we only get notifications for the specific types of records we want. Lastly, we create an anonymous function that will allow us to make sense of the notification we receive from our Record Watch function.

We are passing the parameters of name and d to our anonymous function. The name will provide information about the update. The d parameter contains information about the action type as well as the information from the record that was updated. I encourage you to log these 2 objects to your console so you can explore them to get a better feel for what we get back from Record Watch.

 

You can see that inside of my anonymous function I am only looking for inserted records by using if (d.action == 'entry'). When I get a matching notification, I check the newly created incident's category and increment the bar that has a matching category.

This is just one example out of infinite possibilities of how you can use the Record Watch functionality. My specific thought behind this example is that you could create a dashboard that doesn't need to be refreshed because the widgets automatically adjust according to the Record Watch notifications.

Listening Bar Chart.png

Client Script

function(spUtil, $scope) {

                      /* widget controller */

                      var c = this;

               

                      // Grab our category counts from our Server Script

                      $scope.activeData = c.data.active;

                      $scope.inactiveData = c.data.inactive;

                      $scope.allData = c.data.all;

               

                      // Set the width of the chart along with the height of each bar

                      var width = c.options.width,

                      barHeight = c.options.bar_height,

                      leftMargin = c.options.left_margin;

               

                      $scope.updateBars = function(data) {              

                                              // Set the dimensions of our chart

                                              var chart = d3.select(".chart").attr("width", width)

                                              .attr("height", barHeight * data.length + 50);

                                              // Remove existing axis and tooltip

                                              d3.select(".x.axis").remove();

                                              chart.select(".counter").remove();

                                       

                                              // Add a placeholder text element for our tooltip

                                              var counter = chart.append("text").attr("class", "counter")

                                                                      .attr("y", 10)

                                                                      .attr("x", width-20);

                                       

                                              // Set the domain and range of the chart

                                              var x = d3.scaleLinear()

                                                                      .range([leftMargin, width])

                                                                      .domain([0, d3.max(data, function(d) { return d.value * 1; }) + 10]);

                                              // Bind our new data to our g elements

                                              var bar = chart.selectAll("g").data(data, function(d) { return d.category;});

                                       

                                              // Remove existing bars that aren't in the new data

                                              bar.exit().remove();

                                       

                                              // Create new g elements for new categories in our new data

                                              var barEnter = bar.enter().append("g")

                                                                      .attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });

                                       

                                              // Enter new rect elements

                                              barEnter.append("rect")

                                                                      .on("mouseover", highlightBar)

                                                                      .on("mouseout", unhighlightBar)

                                                                      .attr("class", "chart-bar")

                                                                      .attr("height", barHeight - 1)

                                                                      .attr("x", leftMargin)

                                                                      .transition().duration(750)

                                                                      .attr("width", function(d) { return x(d.value) - leftMargin; });

                                                               

                                              // Enter new text labels

                                              barEnter.append("text")

                                                                      .attr("x", leftMargin - 5)

                                                                      .attr("y", barHeight / 2)

                                                                      .attr("width", leftMargin)

                                                                      .attr("dy", ".35em")

                                                                      .style("fill", "black")

                                                                      .style("text-anchor", "end")

                                                                      .transition()

                                                                      .delay(750)

                                                                      .text(function(d) { return d.category; });

                                       

                                              // Update existing bars

                                              bar.transition().duration(750)

                                                                      .attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });

                                                                                       

                                              bar.selectAll('rect')

                                                                      .on("mouseover", highlightBar)

                                                                      .on("mouseout", unhighlightBar)

                                                                      .data(data, function(d) { return d.category;})

                                                                      .transition().duration(750)

                                                                      .attr("width", function(d) { return x(d.value) - leftMargin; });

                                       

                                              // Create the x-axis and append it to the bottom of the chart          

                                              var xAxis = d3.axisBottom().scale(x);

               

                                              chart.append("g")

                                                                      .attr("class", "x axis")

                                                                      .attr("transform", "translate(0," + (barHeight * data.length) + ")")

                                                                      .attr("x", leftMargin)

                                                                      .call(xAxis);

                                       

                                              // Define functions for our hover functionality

                                              function highlightBar(d,i) {

                                                                      d3.select(this).style("fill", "#b0c4de");                                    

                                                                      counter.text(d.category + ' ' + d.value);          

                                              }

                                       

                                              function unhighlightBar(d,i) {

                                                                      d3.select(this).style("fill", "#4682b4");

                                                                      counter.text("");

                                              }

                                       

                      }

               

                      spUtil.recordWatch($scope, "incident", "active=true", function(name, d) {                                        

                                              if (d.action == 'entry') {

                                                                      for (i=0; i < $scope.activeData.length; i++) {

                                                                                              if (d.record.category.display_value == $scope.activeData[i].category) {

                                                                                                                      $scope.activeData[i].value++;

                                                                                                                      break;

                                                                                              }

                                                                      }

                                                                      $scope.updateBars($scope.activeData);

                                              }

  });

               

                      $scope.updateBars($scope.activeData);

               

}

Mitch Stutler

VividCharts Founder

vividcharts.com

linkedin.com/in/mitchellstutler

twitter.com/mitchstutler

Sources

- Record Watch

- d3js.org

1 Comment