The platform provides the ability to create your own types of content and applications.
Table of Contents
Why create custom applications and content?
If you are writing a new application or have content (internal or external) that you want to interact with Verint Community's core services, creating a custom content and application type within the community can be beneficial. Content Types within the community can interact with core services. Likes, Ratings, Comments, Moderation, Mentions and Hashtags are some of the services your content will have access to once registered with the community.
There is a deeper discussion of how content and applications fit in the community platform in The Content Model article.
Content and Content Types
There are two interfaces that are provided in the platform to identify types of content and individual content entities. The IContentType interface is used to identify types of content and the IContent interface is used to represent the individual content entities. Both of these interfaces are found in the Telligent.Evolution.Core.dll.
Applications and Application Types
Similar to content, the platform provides the IApplicationType to identify a type of application and IApplication to represent an individual application entity. These interfaces are also found in the Telligent.Evolution.Core.dll.
Creating an Application and Content
For our example application, we will create a Links Application. The Links Application will be a collection of links to websites.
First, let's outline our entities.
LinksApplication Entity
Our LinksApplication Entity will implement the IApplication interface and represent an instance of a Links Application.
ApplicationTypeId is a unique id that represents a type of application in the community, you define this value. In the example, we have a static class where we define our Id, so it can be referenced from multiple locations. ApplicationId is the unique Id for an individual application in the community. We will provide this to the community as well.
public Guid ApplicationId { get; set; } public Guid ApplicationTypeId { get { return ContentTypes.LinksApplicationId; } }
The Name and Description fields are not required by the IApplication interface, but allow us to store a raw version of the there values. The HtmlName and HtmlDescription methods are then used to provide the output depending on the target. These allow the output to be tailored to those targets, for instance if your target was an email you may not want to display images inline in your content. Our example data just uses text for Name and Descriptions, there is no need to tailor our output to different targets, instead we will just return the text for all targets.
public string Name { get; set; } public string Description { get; set; } public string HtmlName(string target) { return Name; } public string HtmlDescription(string target) { return Description; }
For this example we won't allow disabling the application, so the IsEnabled property will always return true. We wont store our applications in different groups, instead they will all be located in the Site Root group so we will always return the Site group for the Application's Container. Our application won't have a url to view it or an avatar associated with it, both AvatarUrl and the Url will just return null.
public bool IsEnabled { get { return true; } } public IContainer Container { get { return Apis.Get<IGroups>().Root; } } string IApplication.AvatarUrl { get { return null; } } string IApplication.Url { get { return null; } }
Here is the completed LinksApplication entity source:
https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/LinksApplication_2E00_cs
LinksItem Entity
Our LinkItem Entity will implement the IContent interface and represent a single link item in the Links Application.
ContentTypeId is a unique id that represents a type of content in the community, you define this value when creating your content type. The example uses the same static class that defines the ApplicationTypeId to define this Id. ContentId is the unique Id for an individual content item in the community. We will provide this to the community as well.
public Guid ContentId { get; set; } public Guid ContentTypeId { get { return ContentTypes.LinksItemId; } }
Each piece of Content is related to an application in the community, we have defined a property to store the ApplicationId for our content's application. We use this value to return an instance of our application when we implement the Application property on the IContent interface.
public Guid ApplicationId { get; set; } public IApplication Application { get { return LinksData.GetApplication(ApplicationId); } }
The Name and Description fields are not required by the IContent interface, but allow use to store a raw version of the there values. The HtmlName and HtmlDescription methods are then used to provide the output depending on the target. These allow the output to be tailored to those targets, for instance if your target was an email you may not want to display images inline in your content.
public string Name { get; set; } public string Description { get; set; } public string HtmlName(string target) { return Name; } public string HtmlDescription(string target) { return Description; }
Each link item has a Url and the IContent interface requires a Url, so we will use that property to store the Url and satisfy the interface.
public string Url { get; set; }
The CreatedDate, IsEnabled, AvatarUrl and CreatedByUserId properties are required by the interface but will be static or are not needed in this example, so we will implement those, but they don't provide any additional value. If this were a fully functional example that implemented core services or other features of the platform these values would become important to populate correctly.
public DateTime CreatedDate { get; set; } public bool IsEnabled { get { return true; } } string IContent.AvatarUrl { get { return null; } } int? IContent.CreatedByUserId { get { return null; } }
Here is the completed LinkItem entity source:
https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/LinkItem_2E00_cs
Next we will define our Application and Content Types that make use of our entities to register those with the platform.
LinksApplication Application Type
The IPlugin and ITranslatablePlugin interfaces are discussed in other articles, we will skip the explanation of those implementations and focus on the IApplicationType implementation.
ApplicationTypeId is the same id that was used when defining our IApplication entity. ApplicationName is the name of the application that will be displayed in the community. The example uses a translation so the application name can be translated for each language the community supports.
Guid IApplicationType.ApplicationTypeId { get { return ContentTypes.LinksApplicationId; ; } } string IApplicationType.ApplicationTypeName { get { return _translations.GetLanguageResourceValue("ApplicationTypeName"); } }
The AttachChangeEvents method provides access to an IApplicationStateChanges object. This object is used by your application type to inform the platform of changes to your application. For instance, when you application is deleted, informing the platform of the deletion allows the platform to remove data associated with that application.
void IApplicationType.AttachChangeEvents(IApplicationStateChanges stateChanges) { _applicationState = stateChanges; }
The ContainerTypes property should return all the types of containers that can hold this application. In this case the only container is groups, so that Id is returned.
Guid[] IApplicationType.ContainerTypes { get { return new Guid[] { Apis.Get<IGroups>().ContentTypeId }; } }
Lastly, the Get method should return an instance of the Application entity.
IApplication IApplicationType.Get(Guid applicationId) { return LinksData.GetApplication(applicationId); }
Here is the completed LinksApplicationType source:
https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/LinksApplicationType_2E00_cs
LinkItem Content Type
Again, the IPlugin and ITranslatablePlugin interfaces are discussed in other articles, we will skip the explanation of those implementations and focus on the IContentType implementation.
ContentTypeId is the same id that was used when defining our IContent entity. ContentName is the name of the content that will be displayed in the community. The example uses a translation so the content name can be translated for each language the community supports.
Guid IContentType.ContentTypeId { get { return ContentTypes.LinksItemId; } } string IContentType.ContentTypeName { get { return _translations.GetLanguageResourceValue("ContentTypeName"); } }
The AttachChangeEvents method provides access to an IContentStateChanges object. This object is used by your content type to inform the platform of changes to your content. For instance, when you content is deleted, informing the platform of the deletion allows the platform to remove data associated with that content.
void IContentType.AttachChangeEvents(IContentStateChanges stateChanges) { _contentState = stateChanges; }
The ApplicationTypes property should return all the types of applications that can hold this content. In this case the only application is our LinksApplication, so that Id is returned.
Guid[] IContentType.ApplicationTypes { get { return new Guid[] { ContentTypes.LinksApplicationId }; } }
Finally the Get method should return an instance of the Content entity.
IContent IContentType.Get(Guid contentId) { return LinksData.GetLink(contentId); }
Here is the completed LinkItemContentType entity source:
https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/1856_2E00_LinkItemContentType_2E00_cs
The custom content and application plugins are now completed, but we can add some additional functionality to make this easier to use in a community site.
Widget Extensions
As of now, we won't be able to interact with our new application or content from a velocity widget, a couple custom IScriptedContentFragmentExtensions can expose our data methods so they can be called from velocity. We will add an extension that works with the LinksApplication called telligent_v1_links and an extension for the LinkItem methods called telligent_v1_linkitem.
Our extension will expose the LinksApplicationMethods class. $telligent_v1_links.List() will return a list of all the links applications, while telligent_v1_links.Get(Guid applicationId) will return a single links application.
The source code for the telligent_v1_links extension:
https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/LinksApplicationWidgetExtension_2E00_cs
Similarly, we will use a LinkItemMethods class to expose methods to List all LinkItems in a Link Application and another to Get a single LinkItem. $telligent_v1_linkitem.List(Guid applicationId) will return the list, while $telligent_v1_linkitem.Get(Guid contentId) will return a single instance of a LinkItem.
The source code for the telligent_v1_linkitem extension:
https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/LinkItemWidgetExtension_2E00_cs
Plugin Group
We could deploy this as is, but you would need to search around the admin panel to enable each of the 4 different plugins, not to mention these plugins have dependencies on each other and should not be used independently of one another. We can use a IPluginGroup to create a single point to enable or disable all related plugins at the same time to care of both of these issues.
Here is the completed source for our Plugin Group:
https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/LinksPluginGroup_2E00_cs
Example Widget
We can now deploy the dll containing our Links Application to the community and enable the Links Application Plugin group. We can use a widget to test that our application is working and our content can use a core service, in this case the Like service.
The widget will list all the Links Applications. For each application it will list all the Link Items and those items will each display a Like button.
The velocity code for that widget would look like:
#set($linkapps = $telligent_v1_links.List()) #foreach ($linkapp in $linkapps) #beforeall <ul class="content-list simple"> #each <li class="content-item simple"> <h4 style="margin-bottom: 5px;">$linkapp.Name</h4> <div class="description" style="margin: 5px 0;">$linkapp.Description</div> #set($links = $telligent_v1_linkitem.List($linkapp.ApplicationId)) #foreach ($link in $links) #beforeall <ul class="links"> #each <li class="link-item" style="margin-bottom: 5px;"> #if ($core_v2_user.IsRegistered($core_v2_user.Accessing.Id)) #set ($likeFormat = '{toggle} <span class="count"><span class="icon"></span>{count}</span>') #else #set ($likeFormat = '<span class="count"><span class="icon"></span>{count}</span>') #end <a href="$link.Url">$link.Name</a> - $core_v2_ui.Like($link.ContentId, $link.ContentTypeId, "%{ Format = $likeFormat, IncludeTip = 'true' }") <div class="description">$link.Description</div> </li> #afterall </ul> #end </li> #afterall </ul> #end
Once the widget is added to a page you should see the following:
Downloadable Source
Now that we have a base level application and content type, we can begin to add support for core services to our application. Additional articles discussing Adding Core Service Support to Content are available.