Custom Dashboard

Compatibility

The content of this page can only be used if the following condition(s) are all met:

  • You must target the Vault Application Framework 2.0 or higher.

Version 2.1 of the Vault Application Framework introduces a new base class for your applications to inherit from. This new base class encapsulates a large chunk of boilerplate code that was previously required to be implemented manually, including the output of a simple dashboard containing the application name, version and description.

Implementing a custom dashboard involves overriding the GetDashboardContent method:

using System.Runtime.Serialization;
using MFiles.VAF.Configuration;
using MFiles.VAF.Configuration.AdminConfigurations;
using MFiles.VAF.Core;

namespace MFVaultApplication1
{
	public class VaultApplication
		: ConfigurableVaultApplicationBase<Configuration>
	{
		#region Overrides of ConfigurableVaultApplicationBase<Configuration>

		/// <inheritdoc />
		public override string GetDashboardContent(IConfigurationRequestContext context)
		{
			var loginAccount = context.Vault.UserOperations.GetLoginAccountOfUser( context.CurrentUserID );
			return $"<h3>Hello {loginAccount.FullName}</h3>";
		}

		#endregion
	}
	
	[DataContract]
	public class Configuration
	{
 
	}
}

The text returned by the GetDashboardContent method should be the same as the VAF 2.0 dashboard generator function.

Using commands within dashboards

Commands can also be used outside of dashboards. Please see the dedicated page on commands for more information.

Version 2.1 of the Vault Application Framework provides an easy way to create commands within dashboards that, when clicked, execute custom server-side code. This could include, for example, executing a vault extension method or creating objects in the vault. Creating a dashboard button and reacting to it being clicked involves three steps:

The code below registers one command named refreshDashboardCommand. When executed, this command instructs the dashboard to refresh. The dashboard simply contains the time that it was rendered, and displays a button that executes this command.

/// <summary>
/// The entry point for this Vault Application Framework application.
/// </summary>
/// <remarks>Examples and further information available on the developer portal: http://developer.m-files.com/. </remarks>
public partial class VaultApplication
	: ConfigurableVaultApplicationBase<Configuration>
{
	/// <summary>
	/// The command which will be executed.
	/// </summary>
	/// <remarks>The "Execute" method will be called when the command is clicked.</remarks>
	private readonly CustomDomainCommand refreshDashboardCommand = new CustomDomainCommand
	{
		ID = "cmdRefreshDashboard",
		ConfirmMessage = "Are you sure you would like to refresh the dashboard?",
		Execute = (c, o) =>
		{
			o.RefreshDashboard();
		}
	};

	#region Overrides of ConfigurableVaultApplicationBase<Configuration>

	/// <inheritdoc />
	public override IEnumerable<CustomDomainCommand> GetCommands(IConfigurationRequestContext context)
	{
		// Return any commands that the base implementation provides, plus our refresh command.
		return new List<CustomDomainCommand>(base.GetCommands(context))
			{
				this.refreshDashboardCommand
		};
	}

	/// <inheritdoc />
	public override string GetDashboardContent(IConfigurationRequestContext context)
	{
		// Create the surrounding dashboard.
		var dashboard = new StatusDashboard();

		// Create a panel showing when the dashboard was rendered.
		var refreshPanel = new DashboardPanel();
		refreshPanel.SetInnerContent( $"Dashboard generated at: {DateTime.Now.ToString( "T" )}" );

		// Add the refresh command to the panel, and the panel to the dashboard.
		refreshPanel.Commands.Add( DashboardHelper.CreateDomainCommand( "Refresh", this.refreshDashboardCommand.ID ) );
		dashboard.AddContent( refreshPanel );

		return dashboard.ToString();
	}

	#endregion

}

The dashboard generated by the above code, with a refresh button

Sometimes the execute method needs to access instance (i.e. non-static) content. In this case, assign the Execute method in the application startup:

/// <summary>
/// The entry point for this Vault Application Framework application.
/// </summary>
/// <remarks>Examples and further information available on the developer portal: http://developer.m-files.com/. </remarks>
public partial class VaultApplication
	: ConfigurableVaultApplicationBase<Configuration>
{
	/// <summary>
	/// The command which will be executed.
	/// </summary>
	/// <remarks>The "Execute" method will be called when the command is clicked.</remarks>
	private readonly CustomDomainCommand myCommand = new CustomDomainCommand
	{
		ID = "cmdMyCommand"
	};

	public VaultApplication()
	{
		// Set up the execute method for the command.
		this.myCommand.Execute = (c, o) =>
		{
			// Perform actions here with instance data.
		}
	}

	/* Rest of content ommitted for brevity */

}

Previous VAF implementations

VAF 2.0

Use this approach when using version 2.0 of the Vault Application Framework. When using version 2.1 or later, use the approach above.

Each configuration node can define a method which builds a dashboard which is shown to the user when they select the “Dashboard” tab for the application within the M-Files Admin software. In the sample below, the DashboardGenerator method has been set as the generator for the configuration node. This method must return a valid HTML string which will then be displayed.

using System.Runtime.Serialization;
using MFiles.VAF;
using MFiles.VAF.AdminConfigurations;
using MFiles.VAF.Common;
using MFilesAPI;

namespace MFVaultApplication1
{
	[DataContract]
	public class Configuration
	{
		[DataMember]
		public string ConnectionString { get; set; }

	}

	public class VaultApplication
		: VaultApplicationBase, IUsesAdminConfigurations
	{

		private ConfigurationNode<Configuration> config { get; set; }

		public void InitializeAdminConfigurations(IAdminConfigurations adminConfigurations)
		{
			// Add it to the configuration screen.
			this.config = adminConfigurations.AddSimpleConfigurationNode<Configuration>(
				"My Vault Application",
				this.DashboardGenerator);
		}
		private string DashboardGenerator()
		{
			return "<p>hello world</p>";
		}
	}
}

Only simple HTML is allowed; elements such as <script> will be ignored.

An example of a basic dashboard

Using helper functions

Generating the HTML for standard dashboard components can be done through the use of the StatusDashboard class. Once the dashboard is populated, the HTML required to render it can be retrieved by calling its ToString method:

using System.Runtime.Serialization;
using MFiles.VAF;
using MFiles.VAF.AdminConfigurations;
using MFiles.VAF.Common;
using MFilesAPI;

namespace MFVaultApplication1
{
	[DataContract]
	public class Configuration
	{
		[DataMember]
		public string ConnectionString { get; set; }

	}

	public class VaultApplication
		: VaultApplicationBase, IUsesAdminConfigurations
	{

		private ConfigurationNode<Configuration> config { get; set; }

		public void InitializeAdminConfigurations(IAdminConfigurations adminConfigurations)
		{
			// Add it to the configuration screen.
			this.config = adminConfigurations.AddSimpleConfigurationNode<Configuration>(
				"My Vault Application",
				this.DashboardGenerator);
		}
		private string DashboardGenerator()
		{
			var statusDashboard = new StatusDashboard();
			return statusDashboard.ToString();
		}
	}
}

Dashboard contents

The StatusDashboard has a property named Contents which is a collection of items that are shown within it. Whilst the built-in implementations are shown below, any class which implements the IDashboardContent interface can be added to the collection.

Panels

// Create the panel.
var panel = new DashboardPanel()
{
	Title = "Dashboard panel 1"
};

// Panels can also contain other dashboard content like lists or text
// (not shown, for clarity).
// panel.InnerContent.Add( ... )

// Set up the dashboard.
var statusDashboard = new StatusDashboard();
statusDashboard.Contents.Add(panel);

// Return the HTML.
return statusDashboard.ToString();

Lists

// Create the list.
var list = new DashboardList()
{
	Title = "My list"
};

// Add a list item.
list.Items.Add(new DashboardListItem()
{
	Title = "First List item",
	StatusSummary = new DomainStatusSummary()
	{
		Status = DomainStatus.Enabled
	}
});

// Set up the dashboard.
var statusDashboard = new StatusDashboard();
statusDashboard.Contents.Add(list);

// Return the HTML.
return statusDashboard.ToString();

Text

// Create the text.
// Any newlines (\n) in the text will be respected in the HTML rendered.
var dashboardText = new DashboardText("line 1\nline 1");

// Set up the dashboard.
var statusDashboard = new StatusDashboard();
statusDashboard.Contents.Add(dashboardText);

// Return the HTML.
return statusDashboard.ToString();

Custom content

// Create the custom content.
var customContent = new DashboardCustomContent("<table><tr><td>Item 1</td><td>Item 2</td></tr></table>");

// Set up the dashboard.
var statusDashboard = new StatusDashboard();
statusDashboard.Contents.Add(customContent);

// Return the HTML.
return statusDashboard.ToString();

Allowed HTML tags and attributes

The following HTML tags are allowed within dashboards:

The following attributes are allowed:

Tips and tricks

Displaying an image in a dashboard

The content rendered within a dashboard is limited, and HTML <img /> tags are not directly supported. It is, however, possible to render an image within a dashboard:

// Read the image and convert it to a Base64 encoding format.
var image = DashboardHelper.ImageFileToDataUri("image.png");

// Create a dashboard panel for the content to sit into.
var panel = new DashboardPanel();
panel.InnerContent = new DashboardContentCollection()
{
	// Add the image as a CSS background to a div.
	new DashboardCustomContent($"<div style='background-image: url({image}); background-repeat: no-repeat; height: 92px; width: 92px'></div>"),
};

// Set up the dashboard.
var dashboard = new StatusDashboard();
dashboard.Contents.Add(panel);

// Return the HTML.
return dashboard.ToString();