Custom Dashboards

A dashboard is a collection of widgets that gives you an overview of the reports and metrics you care about most.

A widget is a mini-report that can display your data in a number of presentation styles, including simple numeric metrics, tables and charts. You can define widgets within the Dashboard yourself.

With the Dynamicweb dashboard API, you can create custom dashboards and custom widgets. You can extend the functionality of dashboards to render content from external sources, or present DW data within a unique format.

As such, custom widgets help you to build a consolidated overview of the information which is important to your information system, e.g.:

  1. A list of the most valued folders
  2. A chart of the number of shipped product orders per city
  3. Application memory usage with colored threshold states

Key dashboards features:

  • Use premade or custom widgets
  • Dashboard layouts are personal for a persistent experience across sessions
  • Use the API to retrieve data for your dashboards
  • Drag & Drop interface for re-arranging your widgets

You can read more about using standard Dashboards here

The Dynamicweb dashboard API is simple and very useful – as illustrated by this class diagram of the domain model (Figure 2.1):

Figure 2.1 A class diagram of the dashboards API

As you can see, we have a predefined widgets hierarchy – a developer must use one of the predefined types to create a custom widget or dashboard.

Before you can create custom widgets and dashboards, you must add the appropriate references and packages to a new project:

  1. Create new Visual Studio class library project 
Figure 3.1 Create a new VS Class Library project
  1. Add reference to System.ComponentModel.Composition assembly
  2. Open nuget package manager and install Dynamicweb.Dashboard package to project
Figure 3.2 Add references

As you can see in class diagram we have several types of widgets:

  • Counters – CountWidget, ThresholdCountWidget
  • List – ListWidget
  • Grid – GridWidget
  • Graphs – ChartWidget

All widgets are configurable add-ins, so you can add input controls to the interface for configuring the widget etc. You can read more about Configurable Addins in the API documentation and in the T3: Platform Developer course.

As an example, let’s create a simple counter widget which shows a number defined in the widget settings. First, add new class MyTestCounter to the project with this code:

C#
using Dynamicweb.Dashboards.Widgets; using Dynamicweb.Extensibility.AddIns; using Dynamicweb.Extensibility.Editors; using Dynamicweb.Dashboards; namespace Dynamicweb.Dashboards.Examples { [AddInName("My Test Counter")] [AddInDescription("My Test Counter description")] [AddInIcon(Dynamicweb.Core.UI.Icons.KnownIcon.HeartO)] public class MyTestCounter : CountWidget { public MyTestCounter() { Title = "My Test Counter"; Subtitle = "products"; } [AddInLabel("Products"), AddInParameter("ProductsAmount"), AddInParameterEditor(typeof(IntegerNumberParameterEditor), "")] public string Products { get; set; } = "10"; protected override string GetCounterNumber(IDashboard dashboard, string path) { return Products; } } }

Build the project and copy the assembly to the solution bin folder. Login to the solution, edit the home dashboard, and add the "My Test Counter" widget to the dashboard. The result:

Figure 5.2 My Test Counter

As you can see, each count widget has got two default properties (title, color) available in the widget edit settings. If you want to hide one of them - you can override the appropriate property in code without any addins attributes.

The code below hides the title and color editors and sets up predefined values:

C#
public override string DefaultBackgroundColor { get { return "#cc1111"; } } public override string Title { get { return "My products counter"; } }

The class ThresholdCountWidget provides a base counter dashboard widget with threshold states. Let’s create a simple threshold counter which renders minutes in a ‘human’ format. The color of the widget will be changed if number of minutes is greater than 60.

Add new class MyTestThresholdCounter to the project with this code:

C#
using Dynamicweb.Dashboards.Widgets; using Dynamicweb.Extensibility.AddIns; using Dynamicweb.Extensibility.Editors; using Dynamicweb.Dashboards; using System; namespace MyCompanyDwDashboardTest1 { [AddInName("My Test Threshold Counter")] [AddInDescription("My Test Threshold Counter description")] [AddInIcon(Dynamicweb.Core.UI.Icons.KnownIcon.HeartO)] public class MyTestThresholdCounter : ThresholdCountWidget { public MyTestThresholdCounter() { Title = "My Test Threshold minutes counter"; } [AddInLabel("Minutes"), AddInParameter("Minutes"), AddInParameterGroup(" "), AddInParameterEditor(typeof(IntegerNumberParameterEditor), "")] public int Minutes { get; set; } = 130; protected override double GetCounterValue(IDashboard dashboard, string path, out string formattedValue) { var time = TimeSpan.FromMinutes(Minutes); formattedValue = ToHumanTimeString(time); return Minutes; } private string ToHumanTimeString(TimeSpan span) { var format = "G3"; return span.TotalMilliseconds < 1000 ? span.TotalMilliseconds.ToString(format) + " milliseconds" : (span.TotalSeconds < 60 ? span.TotalSeconds.ToString(format) + " seconds" : (span.TotalMinutes < 60 ? span.TotalMinutes.ToString(format) + " minutes" : (span.TotalHours < 24 ? span.TotalHours.ToString(format) + " hours" : span.TotalDays.ToString(format) + " days"))); } } }

Build the project and copy the assembly to the solution bin folder. . Login to the solution, edit the home dashboard, and add the widget to the dashboard and play with the settings:

Figure 6.2 A count widget with thresholds

The list widget is a simple list which renders list of strings with icons. Let’s create a simple list which should show best-selling products.

Add new class MyTestList to the project with this code:

C#
using Dynamicweb.Dashboards.Widgets; using Dynamicweb.Extensibility.AddIns; using Dynamicweb.Dashboards; using Dynamicweb.UI.Elements.Displays; using System.Collections.Generic; namespace Dynamicweb.Dashboards.Examples { [AddInName("My Test List")] [AddInDescription("My Test List description")] [AddInIcon(Dynamicweb.Core.UI.Icons.KnownIcon.HeartO)] public class MyTestList : ListWidget { public MyTestList() { Title = "The best-selling products"; } public override IEnumerable<ListViewItem> GetItems(IDashboard dashboard, string path) { return new [] { new ListViewItem() { Title = "Descente Short Sleeve Jersey", Hint = "Streamlined and stylish, this jersey will go wherever the prevailing wind leads you", RightText = "950", Icon = Core.UI.Icons.KnownIcon.Users }, new ListViewItem() { Title = "GT Marathon 2.0 Mountain Bike", Hint = "This bike will have you turning those 'short afternoon rides' into 'epic trail runs'", RightText = "678", Icon = Core.UI.Icons.KnownIcon.Road }, new ListViewItem() { Title = "Mongoose Tyax Comp Disc", Hint = "So fast. So agile. So stable. So comfortable. So simple.", RightText = "638", StatusColor = StatusColor.Green, Icon = Core.UI.Icons.KnownIcon.Rocket }, new ListViewItem() { Title = "Mongoose Teocali Elite Mountain Bike", Hint = "This is Mongoose.", RightText = "129", Icon = Core.UI.Icons.KnownIcon.Rocket }, }; } } }

This is the result:

Figure 7.2 A List widget

The grid widget is a spreadsheet/table component. To create a custom grid widget you only have to set a list of columns to override the GetColumns method, and return a list of rows to override GetItems method. Let’s create simple grid showing the best customers.

Add new class MyTestGrid to the project with this code:

C#
using System.Collections.Generic; using Dynamicweb.Core.UI; using Dynamicweb.Dashboards.Widgets; using Dynamicweb.Extensibility.AddIns; using Dynamicweb.UI.Elements.Displays; using Dynamicweb.Dashboards; namespace Dynamicweb.Dashboards.Examples { [AddInName("My Test grid")] [AddInDescription("My Test grid description")] [AddInIcon(Core.UI.Icons.KnownIcon.Table)] public sealed class MyTestGrid : GridWidget { public MyTestGrid() { Title = "Our best buyers"; } public override IEnumerable<GridColumn> GetColumns() { return new[] { new GridColumn() { Id = "UserName", Title = "Buyer", TruncateText = true, EnableTooltip = true, Width = "60%", }, new GridColumn() { Id = "Orders", Title = "Orders", Align = GridColumnAlign.Center, Width = "10%" }, new GridColumn() { Id = "Products", Title = "Products", Align = GridColumnAlign.Center, Width = "10%" }, new GridColumn() { Id = "TotalAmount", Title = "Amount", Align = GridColumnAlign.Left, Width = "20%", } }; } public override GridViewResponse GetItems(IDashboard dashboard, string path) { var data = new GridViewResponse() { Rows = new[] { new { UserName = "Samanta Lee", Products = "22", Orders = 11, TotalAmount = "16760 $" }, new { UserName = "Alex Chen", Products = "31", Orders = 2, TotalAmount = "9560 $" }, new { UserName = "John snow", Products = "70", Orders = 15, TotalAmount = "7543 $" } } }; return data; } } }

The result:

The chart widget displays quantitative attributes as a graphical representation of data. It allows end users to observe possible patterns and trends out of raw data. Chart widget provides three types of data presentations: Line, Bar, Pie. For the Line and Bar presentation you can define the color of the line using the color property, but the color property doesn't affect to the Pie mode.

It's easy to get started with chart widget. You simply have to override GetData method and return chart data. In this example we create a chart with Pie presentation by default to show the population of various cities. Add a new class MyTestChart to the project with this code:

C#
using Dynamicweb.Dashboards; using Dynamicweb.Dashboards.Widgets; using Dynamicweb.UI.Elements.Displays.Charts; using Dynamicweb.Extensibility.AddIns; namespace Dynamicweb.Dashboards.Examples { [AddInName("My Test chart")] [AddInDescription("Show test chart")] [AddInIcon(Core.UI.Icons.KnownIcon.PieChart)] public sealed class MyTestChart : ChartWidget { public MyTestChart() { Title = "Total cities population"; ChartType = ChartType.Pie; InstantFetch = true; } public override ChartData GetData(IDashboard dashboard, string path) { var data = new ChartData { Labels = new[] { "London", "New York", "Moscow", "Copenhagen" }, Series = new[] { 500d, 200d, 150d, 300d } }; return data; } } }

The result:

The widgets presented above allow you to cover most of the user's needs with minimal development efforts, but there are times when you need to do something really custom to fully control the rendering. To do this, you must create a class and inherit it from DashboardWidget and overload the Fetch and Render methods there. The Fetch method populates the widget with data. The Render method is responsible for the widget presentation.

Let's create a simple HTML widget that will show the local time running.

Add new class SimpleHtmlWidget to the project with this code:

C#
using Dynamicweb.Dashboards.Widgets; using Dynamicweb.Extensibility.AddIns; using System; namespace Dynamicweb.Dashboards.Examples { [AddInName("Date time widget")] [AddInDescription("Show current date and time")] [AddInIcon(Core.UI.Icons.KnownIcon.LocalHotel)] public sealed class SimpleHtmlWidget : DashboardWidget { private string currentDate = string.Empty; private string currentTime = string.Empty; public SimpleHtmlWidget() { Columns = 2; } public override void Fetch(IDashboard dashboard, string path) { var dt = DateTime.Now; currentTime = dt.ToShortTimeString(); currentDate = dt.ToShortDateString(); } public override string Render() { var str = $"<div style=\"text-align: center; position:relative;min-height:161px;\"><div style=\"position: absolute;top: 50%;transform: translate(0, -50%);width: 100%;font-size: 170%;\"><span id=\"smpl-time-{Id}-time\">{currentTime}</span><br /><small id=\"smpl-time-{Id}-date\">{currentDate}</small></div></div>"; str += $"<script>(function(el) {{setInterval(function() {{var d = new Date();el.innerHTML = d.toLocaleTimeString()}}, 1000);}})(document.getElementById(\"smpl-time-{Id}-time\"));</script>"; return str; } } }

As you can see, the dashboard is a responsive grid system, so we allow developers to control widget size by setting the Columns property in the widget constructor to either 2, 4, or 6.

The result is an animated timer:

Dynamicweb also contains several predefined dashboards – their system names are:

  • Home
  • Ecommerce
  • PIM
  • Marketing

Developers can also create their own dashboard, and use it anywhere in admin by URL. This dashboard gets a unique system name which characterizes it. The dashboard system name is string and must contain only English letters and digits, the minus sign (“- “) is also possible.

The dashboard URL structure: <site>/Admin/Dashboard/<DashboardSystemName>/View/<path>

As shown above, the dashboard is a workspace for widgets, and developers can control how widgets will be stored or loaded, and what type of the widgets will be available for the dashboard.

Let’s create a simple dashboard:

  • Create class with the following code:
C#
using Dynamicweb.Dashboards; using System.ComponentModel.Composition; namespace Dynamicweb.Dashboards.Examples { [Export(SystemName, typeof(IDashboard))] public class HelloWorldDashboard : DashboardBase { public const string SystemName = "MyTestDashboard"; } }
  • Build Project and copy assembly to your site bin folder
  • Login to dw Admin, and open url <yoursite>/Admin/Dashboard/MyTestDashboard/View and see your first custom dashboard!

This is a very simple dashboard. It does nothing interesting, it shows an empty dashboard page by default, and allows user to configure dashboard with any widgets which exist in system.

Often developer wishes to show default widgets and also to restrict type of widgets which can be added to the dashboard. For example, we want to show by default only two TestCounter widgets with the values 20 and 35, and we also want to limit users so they can only add the widget types that we’ve created above (MyTestCounter, MyThresholdCounter, MyTestChart, MyThresholdCounter, MyTestList).

So modify the code below to support it:

C#
using Dynamicweb.Dashboards; using Dynamicweb.Dashboards.Widgets; using System; using System.Collections.Generic; using System.ComponentModel.Composition; namespace Dynamicweb.Dashboards.Examples { [Export(SystemName, typeof(IDashboard))] public class HelloWorldDashboard : DashboardBase { public const string SystemName = "MyTestDashboard"; private static readonly IEnumerable<Type> mySpecificWidgetsTypes = new Type[] { typeof(MyTestCounter), typeof(MyTestThresholdCounter), typeof(MyTestList), typeof(MyTestGrid), typeof(MyTestChart) }; protected override DashboardConfiguration GetDefault(string path) { return new DashboardConfiguration() { Widgets = new[] { new MyTestThresholdCounter() { Minutes = 20, DefaultBackgroundColor = "red" }, new MyTestThresholdCounter() { Minutes = 35, DefaultBackgroundColor = "green" } } }; } public override IEnumerable<Type> GetAllAvailableWidgets(string path, IEnumerable<Type> allWidgets) { return mySpecificWidgetsTypes; } } }

The result: 

Figure 11.3 A custom dashboard