Since Tridion 2011 has been released with its shiny new GUI framework everyone and their sister have either been creating or thinking about creating extensions. I myself have been heavily involved in creating some.
Traditionally, extensions for the most part are islands of functionality; code is typically hardly ever reused. This is something I’d like to improve. With the advancement of the Tridion framework and by following OO practices, it’s possible to create reusable code, frameworks and more, the sky it the limit really.
A few weeks ago I thought about customizing GUI extensions. As extensions mature it will make sense to allow Tridion users, whether administrators or business, the ability to make changes to extensions’ behavior, to turn functionalities on and off and more, without having to change the underlying code. This led to… *drumroll* … The Extensions Manager.
The Extensions Manager (extension) has two sides:
- A programmatic interface (API) for extensions developers to leverage in order for them to both register their extensions so they appear in the Manager GUI as well as to retrieve the values set by the users.
- A graphical user interface (shown above) to allow users to set values for the fields registered by the extension’s creator.
Meet the Extensions Manager
So let me give you the tour: …Through here you have the living room, over there is the breakfast nook and to the left is the conservatory which is just gorgeous during the summer… hmm… sorry! Wrong tour.
Let’s try this again. The Extensions Manager is packed with features, in this post ill focus on the functional side and in a separate article I’ll detail on the technical one.
The concept behind the Manager is simple; you’re building a great extension and you recognize that different users will need different options or perhaps an Administrator should be able to turn on the extension for specific groups of users while not for others, maybe your extension needs different parameters depending on the environment its running on.
Well, you have a few options then. You can leave the configuration stuff in your code, which will be easiest for you as an extension creator but not very user friendly. Since you are Mr (or Miss) user friendly, as we all are, you would like to build a way for users to customize your extension(s), right? But that will require another big development effort and introduce new complexities such as how should you display these options? How to persist them between sessions? And so on.
The good news is that there’s a third option. You may have guessed it by now, it’s the Extensions Manager! With a few lines of code you can register your extension, define the fields to show your users and Voila! You’re done.
Extension Configuration Fields
Field Types
The Extensions Manager comes with 5 types of fields: Text, Number, Options, Groups and Color.
The first 3 types can be seen in the following screenshot:
Nothing special here really, Text and Number are self-explanatory and Option means that you can pre-define the values that will be displayed using check-boxes or radio buttons.
Field type “Groups”:
The Manager will make sure to load all available Tridion groups so they can be listed for fields of this type.
Field type “Color”:
A nice utility field I decided to add to make it possible to visually customize extensions’ elements. I got the jQuery plugin for the color picker from: http://www.eyecon.ro/colorpicker/
Multiple Values
Most types only support a single value, however, the Option and Groups fields can also be marked as multi-valued fields.
Single valued Option field:
Multi valued Option field:
The “All” option is added automatically by the Manager to make it easy for users to select all options.
Admin Only
It is possible to specify that a field is for Administrative use only and so can only be modified by Tridion administrators. The admin fields will be shown in the “Admin” tab of the Manager:
Default Value and Help Text
Defaults are pretty obvious; it is possible to define default values for fields registered with the Manager.
It is also possible to add help text for each field in order for the Manager to display it as a tooltip like so:
Validators
The Manager comes with one (global) validator for the Number field type simply making sure that the value entered to this type of fields is a valid number.
Developers can register their own validators for all field types per extension or globally for all extensions.
The Manager will immediately alert the user of an invalid value by changing the color of the field and adding an indicator near the extension title:
Interaction
Accessing the Extensions Manager is done through a button in the toolbar:
If all of the extensions registered to the Manager have only “Admin” fields, the button will be disabled for regular users and only be enabled for Administrators.
Save & Close Buttons
The Close button of the Manager is always shown to allow users to hide the Manager window at all times.
The Save button becomes available when a field value has been changed by the user. It will be disabled during a save operation.
Users can hide the Manager display even during a save or reload operation, these operations will continue in the background.
Reload Settings Button
Clicking the Reload button will retrieve the values stored for the currently showing extension from the server and re-apply them to the fields on the screen.
Tabs
There are only two tabs. “Settings” will show all of the fields that all users can access. “Admin” will only be shown to Tridion administrators and will contain fields which were set by the Extension creator to only be modified by administrators.
A very important difference between the two sets of fields is that the values shown in the “Settings” tab are stored separately for each user while the “Admin” values are stored in just one place on the server and a change done by one administrator will be reflected for all users. Therefore, the “Settings” values are Private and the “Admin” values are Global.
Extensions List
The list will always display all extensions registered to the Manager. The order in which they are displayed is the order in which the extensions are registered and therefore depends mostly on the order in which extensions were configured in the Editor configuration file and partly on the way the registering code is executed within the Extension’s implementation.
The list only expands one item at a time which includes the title and the description (if one provided). If no title was provided when the extension was registered, the ID property of the extension will be used.
Items in the list have 3 modes. “Normal”, “Pending” and “Invalid”. Normal is the state shown for the items in the above image and is the case when there are no pending changes.
Pending notifies the user that there are one or more fields that have been changed but not saved yet:
Invalid notifies the user that there are one or more fields that have been changed but failed the validation and so must be corrected before its possible to save:
Example
I chose a simple example to show the Manager’s capabilities. For my Item Xml Display I have registered a color field which will allow users to determine the background color of the display:
In just very few lines of code, users of the extension can determine for themselves what the background color of the overlay will be:
Manager:
Extension:
Manager:
Extension:
Even though this is a trivial example I think it shows the capabilities and the possibilities of the Extensions Manager quite nicely.
Installation & Configuration
First download the Manager here.
You may want to follow my 8 steps to configure a GUI extension first as the first steps are pretty much the same.
- Place the editor folder on the server somewhere. I named my editor 2011Extensions but you may want to rename it.
- Set up the editor in the same way explained in my previous article (mentioned above).
- In IIS, create a new application pool named something like: “ExtensionsConfigurationManager”. Make sure its using .NET 4, in Integrated Mode and that the identity is an impersonation user, typically that will be the Network Service. You can compare that to the identity of the CME app pool.
- Still in IIS, you will need to configure a new application for the extension. Navigate to the new editor directory in IIS and then reach the /server/ExtensionsConfigurationManager directory. Right-click and select “Convert to Application”. You should achieve something like this:
- In IIS, navigate to your new application and click on the “Authentication” icon, Make sure then that both Anonymous and Windows are enabled:
- In file explorer: navigate to your editor folder on disk and then to the \server\ExtensionsConfigurationManager. Open the web.config file for editing and update the following:
- Find: “ManagerConfigurationSection\Application\DataRoot” and change the value to a location which will be writable by the extension. This is the place where the Extensions Manager will create folders and the xml files containing the extensions’ definitions and values.
- Find: “log4net\appender\file” and change the value to a location which will be writable by the extension. This is the file the logger of the server side will write to. In the “logger\level” element you can change the logging level. Most of the logging is done at Debug level besides errors of course. Only change to ‘DEBUG’ if there are issues with getting the Manager to work otherwise it will needlessly fill the log file up pretty quickly.
- Go into the BIN folder in “\server\ExtensionsConfigurationManager” and copy “Yoav.Extensions.dll” into “<Tridion_home>\Web\WebUI\WebRoot\bin”.
- If you chose a different name for your Editor you will need to do a quick change to the JS code. This is the only one: open for editing the following file under your Editor folder: “client\generic\utils.js”. in line 14 set the value of the ‘EDITOR_NAME’ variable to the name you have chosen:
this.EDITOR_NAME = “2011Extensions“;
Testing
To make sure that configuring the extension was successful I recommend performing the following checks:
- In your browser open the following url: http://<CME_host_name>/WebUI/editors/<Editor_name>/server/ExtensionsConfigurationManager/test.html. You should be able to see the message on that page.
- Next, open this url: http://<CME_host_name>/WebUI/editors/<Editor_name>/server/ExtensionsConfigurationManager/services/ExtensionsManagerService.svc
You should see this screen:
- Finally, test whether the service is working with this URL: http://<CME_host_name>/WebUI/editors/<Editor_name>/server/ExtensionsConfigurationManager/services/ExtensionsManagerService.svc/json/GetExtension?name=Test
This should result in a JSON response with these contents:
If these steps don’t work for you, follow the errors on the screen and in the log file to try and figure out whats going wrong. Please let me know if you’re having trouble with it as well.
I have tested the Manager on the big 3 browsers and it looks to be working on all. I saw some weird behavior with an older version of IE 8 but on a machine with the latest updates it seems to be alright. On Chrome 9 and 10 and Firefox 3.6 and 4.0 it seems to be working with no apparent issues.
Download
New! – version 0.3 can be downloaded here. This version includes a couple of bug fixes and some enhancements. See the included text file for more details.
The beta version (0.2) can be downloaded here.
Interested in learning how to program with the Extensions Manager? Follow this link.
As always I really appreciate any feedback you may have!
Yoav, this is awesome stuff!!
Very nice Yoav!!! Or should I say the “Yoav the white” 🙂 I’ll introduce this stuff in my extensions as soon as I have time…
Nice post. I’m eagar to work on Tridion 2011 🙂
Wow! well done this is absolutely amazing. I’m wondering if i can dodge client work for an hour to to get this installed and have a play with it 🙂
Hey Yoav, I have the ext manager installed and the tests are correct, but i don’t get an icon in the ribbon (logged in as admin). Any idea which step i’m missing?
Thanks
Hi John,
thats quite strange. dont see a reason why it wouldnt show. Make sure that have set up the editor information in the system.config correctly and that the toolbar extension is added in the editor’s /config/extension.config file.
Then look into the browser’s console. There should be information logged by the extension to five you a notion of whats going on.
Let me know how it goes.
Thanks,
Yoav.
Thanks Yoav, Checked the config under system.config. Restarted iss, com etc. I have a new error now. The gui hangs before loading the top ribbon. If i remove the node from system.config everything is great.
Any ideas?
Sorry to hassle you for support, i just need to get through the initial teething problems of getting an extension up and running.
Hi, sorry to hear you’re having problems getting it to work…
So what’s the error you’re getting? If u look at the browser console, what kind of information do you see being logged there before the error occurs?
Hey Yoav,
I get the following errors:
1)
addJqueryUI() is not a function
Dashboard_v6.0.0.39607.0_.aspx?mode=js()Dashbo…mode=js (line 485)
2)
Value should be a function.
[Break On This Error] Type.registerNamespace(“Tridion.Utils….(a)};var $assert=Tridion.Utils.Assert
[Break On This Error] (function(a,C){var g=”null”,e=”string”…sertBefore(c[0]);a(c).remove()}})($j)
Thanks
John
very strange… I just tried setting up the extension on a 2011 image and it just works for me, no problem… Have you changed the name of the Editor by any chance? Any other modification? What browser are you trying this with?
You can turn off the minification of the js code sent by the GUI to the browser in the system.config file, you need to set the “enabled” property of the resource\filter to “false”. you do this on the filter that has for=”Script”. That will perhaps make it easier to find where the problem is happening.
Hi Yoav,
Setting the config value to false broke the gui, but setting to “never” (a guess from the opposite of “always”) and the whole thing works
Set back to always and it breaks.
Hi John,
I managed to get the extension to work with the JS code minimized. For some reason when minimized the GUI didnt like the addJqueryXXXX methods I added so I changed it a bit and now it all works. Minimized or not.
I will hopefully today or tomorrow post a new version of the Extensions Manager with a few more bug fixes and enhancements.
Thanks for your persistence! 🙂
Great stuff! Congrats on this, it works brilliantly. Feel free to delete the steam of comments between us, perhaps you wouldn’t mind me having your email address for any future pestering!
Hi Yoav,
I was trying to implement your extension manager on my DEV tridion.
Firstly it was giving error to load 6.0 tridion dlls, I replaced all of them from 6.1 dlls (Tridion.Web.UI.Core.dll etc.) and also i was looking for configuration folder for system.config file, I copied from Tridion\web\WebUI\WebRoot and my test page works fine now, however /WebUI/Editors/2011Extensions/server/ExtensionsConfigurationManager/services/ExtensionsManagerService.svc does not returns any value also don’t give any error too.
And now if I try to load my DEV tridion I can see Extension Manager icon over there however now when I click on it I get below error
Unknown server tag ‘ui:ActiveMessageCenter’.
System.Web.HttpParseException (0x80004005): Unknown server tag ‘ui:ActiveMessageCenter’. —> System.Web.HttpParseException (0x80004005): Unknown server tag ‘ui:ActiveMessageCenter’. —> System.Web.HttpException (0x80004005): Unknown server tag ‘ui:ActiveMessageCenter’. at System.Web.UI.TagPrefixTagNameToTypeMapper.System.Web.UI.ITagNameToTypeMapper.GetControlType(String tagName, IDictionary attribs) at System.Web.UI.MainTagNameToTypeMapper.GetControlType2(String tagName, IDictionary attribs, Boolean fAllowHtmlTags) at System.Web.UI.MainTagNameToTypeMapper.GetControlType(String tagName, IDictionary attribs, Boolean fAllowHtmlTags) at System.Web.UI.RootBuilder.GetChildControlType(String tagName, IDictionary attribs) at System.Web.UI.ControlBuilder.CreateChildBuilder(String filter, String tagName, IDictionary attribs, TemplateParser parser, ControlBuilder parentBuilder, String id, Int32 line, VirtualPath virtualPath, Type& childType, Boolean defaultProperty) at System.Web.UI.TemplateParser.ProcessBeginTag(Match match, String inputText) at System.Web.UI.TemplateParser.ParseStringInternal(String text, Encoding fileEncoding) at System.Web.UI.TemplateParser.ProcessException(Exception ex) at System.Web.UI.TemplateParser.ParseStringInternal(String text, Encoding fileEncoding) at System.Web.UI.TemplateParser.ParseString(String text, VirtualPath virtualPath, Encoding fileEncoding) at System.Web.UI.TemplateParser.ParseString(String text, VirtualPath virtualPath, Encoding fileEncoding) at System.Web.UI.TemplateParser.ParseFile(String physicalPath, VirtualPath virtualPath) at System.Web.UI.TemplateParser.ParseInternal() at System.Web.UI.TemplateParser.Parse() at System.Web.Compilation.BaseTemplateBuildProvider.get_CodeCompilerType() at System.Web.Compilation.BuildProvider.GetCompilerTypeFromBuildProvider(BuildProvider buildProvider) at System.Web.Compilation.BuildProvidersCompiler.ProcessBuildProviders() at System.Web.Compilation.BuildProvidersCompiler.PerformBuild() at System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath) at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound) at System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp) at System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath) at System.Web.UI.PageHandlerFactory.GetHandler(HttpContext context, String requestType, String virtualPath, String path) at System.Web.HttpApplication.MaterializeHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&
Hi Manoj,
sorry youre having difficulties with the extension.
Im actually no longer working at Tridion or with Tridion for the last year and a half so its been a while since i touched these extensions.
I dont have a Tridion system available to check it either of course.
Id recommend posting this question on Stackoverflow, http://stackoverflow.com/questions/tagged/tridion
Im sure someone will be able to help you with it there.
Good luck!
Yoav