Smart Office Paint

To facilitate users supporting each other when it comes to, e.g. specific applications, we created a simple paint application where you can draw, write text and take screenshots.

paint

One of the usage scenarios we see for using this application is when someone asks how to perform a specific action in an M3 application. In this case, you could start paint (paint://) and choose Screenshot. When the user performs this action, the screen will fade to light grey and the cursor will change to a crosshair as in the image below. This way of taking screenshots is used from other parts of Smart Office as well, such as in the Conversations window via the attach button and the Add Screenshot button in the share dialog of the Infor Ming.le™ integration.

customscreencapture

This faded screen allows the user to select a custom area of the screen that will be captured. It can be cancelled at any time using the Esc key on the keyboard.

customscreencapture2

After the area has been selected, the captured image is displayed in paint. The user can thereafter add text, highlight or draw in the captured image to clarify the description.

customscreencapture3

When the user is satisfied with his/her drawing, it can be shared via the share button in the upper right corner to e.g. Collaboration or Infor Ming.le™.

shareto

Custom data templates in M3 lists with JScript

Changing the appearance of M3 list cells with conditional styles is easy but in some cases you need to do things that require logic that cannot be expressed with conditional styles alone. This post will show you how to change the style of list cells in M3 lists using JScript, custom data templates and custom data template selectors.

Background

The MForms list uses data templates for displaying the text in all cells. Data templates are very common in WPF applications and they are used for customization of data presentation. If you are not familiar with data templates I would recommend that you read about them before you start to modify the examples in this post. There is an overview at MSDN here: Data Templating Overview

Data templates are very powerful but they also add complexity when you want to do something basic, like changing the color of the text in a list cell. To keep the examples simple I will only use one template that changes the foreground color for the text in list cells. The focus of this post is not about how to create complex data templates but rather how to use data templates from JScript in MForms. There are plenty of information about how to write WPF data templates in XAML on the web.

Custom data templates

When creating data templates in a regular WPF application or a Smart Office SDK feature you would write them in a XAML file. Using XAML files in JScript is not an option so we need another approach. The actual template markup will still be XAML but defined in a string in the JScript. The XAML string can then be parsed to a template instance using the WPF XamlReader class. To make the template XAML a bit more flexible and reusable we can add placeholders and the String.Format method to replace them with actual values.

The data template that will be used in the examples is defined like this:

var xamlTemplate = "<DataTemplate><TextBlock Text=\"{{Binding Path={0}, Mode=OneWay}}\" Foreground=\"{1}\" /></DataTemplate>";

The template contains a single TextBlock element that binds the value of the Text property and defines a new text color using Foreground property. To make this template usable we need to replace the placeholders.

var xaml = String.Format(xamlTemplate, "[0]", "#FFCC0000");

This example would set a red foreground color for the cells in the first list column when applied to the list. This is a basic example and you could create very complex templates with custom content other than text for example.

Custom data template script example

The first script example is called CustomCellTemplateExample and shows you how to set one template for an entire list column. The second example will show how to use different templates in one column.

In the bottom of the script example there are two utility functions that can be reused without change in your own scripts. The ParseTemplate function is used in both examples for parsing a XAML string to a data template instance. The SetColumnTemplate function changes the column template for a grid view column at a specified index.

The CreateForegroundCellTemplate function contains the XAML template string and the code that replaces the placeholder with the values for the binding path and the foreground color.

Finally we have the Init function that uses the Dispatcher to delay the call to the ChangeTemplate function that defines the column index and the color to use for the data template. Note that the list view items are refreshed to ensure that the template is applied.

The screenshot below shows the script running in CRS055. All cells in the first list column now have the red foreground color defined in the template.

M3CLCS01

import System;
import System.Windows;
import System.Windows.Controls;
import System.Windows.Data;
import System.Windows.Media;
import System.Windows.Markup;
import System.Windows.Threading;
import MForms;

package MForms.JScript {

   public class CustomCellTemplateExample {
      var controller;
      public function Init(element : Object, args : Object, controller : Object, debug : Object) {
         this.controller = controller;
         var action : Action = ChangeTemplate;
         Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input, action);
      }

      private function ChangeTemplate() {
         var columnIndex = 0;
         var bindingPath = "[" + columnIndex + "]";
         var brush = "#FFCC0000";
         var template = CreateForegroundCellTemplate(bindingPath, brush);
         var listView = controller.RenderEngine.ListControl.ListView;

         SetColumnTemplate(listView, columnIndex, template);
         listView.Items.Refresh();
      }

      private function CreateForegroundCellTemplate(bindingPath, brush) {
         var xamlTemplate = "<DataTemplate><TextBlock Text=\"{{Binding Path={0}, Mode=OneWay}}\" Foreground=\"{1}\" /></DataTemplate>";
         var xaml = String.Format(xamlTemplate, bindingPath, brush);
         return ParseTemplate(xaml);
      }

      private function SetColumnTemplate(listView, columnIndex, template) {
         var gridView = listView.View;
         var column = gridView.Columns[columnIndex];
         column.CellTemplateSelector = null;
         column.CellTemplate = null;
         column.CellTemplate = template;
      }

      private function ParseTemplate(xaml) {
         var context = new ParserContext();
         context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
         context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
         return XamlReader.Parse(xaml, context);
      }
   }
}

Custom data template selectors

In many cases a single data template for a list column is too limiting. You might want to apply several different templates depending on the value in the list cells. This can be solved by extending the WPF DataTemplateSelector class. Your custom date template selector will override the SelectTemplate method where you can choose which template to return depending on the data for the current list row.

Custom data template selector example

The second script example is called CustomCellTemplateSelectorExample and shows you how to use a data template selector that can return two different templates. This example shares some of the functions in the previous example so I’ll just cover the ones that are unique to this example.

At the end of the example you will find the CustomTemplateSelector class that extends the DataTemplateSelector class. Make sure to place additional classes such as this one after the main script class. The CustomTemplateSelector class has properties for the column index it applies to and for the two different templates it can return. The implementation of the SelectTemplate method gets the text for the cell by using the indexer on the item parameter. For an M3 list the item parameter will be an instance of the ListRow class that you might be familiar with. In a normal list the object returned from the list row indexer is a string. In editable list the object returned will be an EditableCell instance instead. If the cell text contains an “A” character a template with a green foreground color is returned, in all other cases a template with a red foreground color is returned.

The implementation of the SelectTemplate function can be a lot more complex than this simple example. You could compare values in different list cells on the same list row for example. The selector instance could also be initialized with more values that controls what the SelectTemplate function returns.

The remaining code is similar to the previous example but the SetColumnTemplateSelector function is used instead of the SetColumnTemplate function to set the template selector on the grid view column.

The screenshot below shows the script running in CRS055. The list cells in the first column that contains an “A” are green and the other are red.

M3CLCS02

import System;
import System.Windows;
import System.Windows.Controls;
import System.Windows.Data;
import System.Windows.Media;
import System.Windows.Markup;
import System.Windows.Threading;
import MForms;

package MForms.JScript {

   public class CustomCellTemplateSelectorExample {
      var controller;
      var debug;
      public function Init(element : Object, args : Object, controller : Object, debug : Object) {
         this.controller = controller;
         this.debug = debug;
         var action : Action = ChangeTemplate;
         Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input, action);
      }

      private function ChangeTemplate() {
         var columnIndex = 0;
         var bindingPath = "[" + columnIndex + "]";
         var brush;
         var listView = controller.RenderEngine.ListControl.ListView;

         var selector = new CustomTemplateSelector();
         selector.columnIndex = 0;
         selector.templateRed = CreateForegroundCellTemplate(bindingPath, "#FFCC0000");
         selector.templateGreen = CreateForegroundCellTemplate(bindingPath, "#FF00CC00");

         SetColumnTemplateSelector(listView, columnIndex, selector);
         listView.Items.Refresh();
      }

      private function CreateForegroundCellTemplate(bindingPath, brush) {
         var xamlTemplate = "<DataTemplate><TextBlock Text=\"{{Binding Path={0}, Mode=OneWay}}\" Foreground=\"{1}\" /></DataTemplate>";
         var xaml = String.Format(xamlTemplate, bindingPath, brush);
         return ParseTemplate(xaml);
      }

      private function SetColumnTemplateSelector(listView, columnIndex, selector) {
         var gridView = listView.View;
         var column = gridView.Columns[columnIndex];
         column.CellTemplateSelector = selector;
      }

      private function ParseTemplate(xaml) {
         var context = new ParserContext();
         context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
         context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
         return XamlReader.Parse(xaml, context);
      }
   }

   public class CustomTemplateSelector extends DataTemplateSelector{
      public var columnIndex;
      public var templateRed;
      public var templateGreen;

      public override function SelectTemplate(item : Object, container : DependencyObject) : DataTemplate{
         var text = item[columnIndex];
         if (text.Contains("A")) {
            return templateGreen;
         } else {
            return templateRed;
         }
      }
   }
}

Final notes

When creating your own templates I would suggest that you test them in a WPF test application or perhaps in the Mashup Designer before using them in a script. You want to be sure that your XAML code is correct before adding the additional complexity of using it from a script. Incorrect templates can cause quite severe errors in WPF in some cases.

If you use a lot of templates or complex templates you might consider caching the parsed template instances. This could be done using either the SessionCache or the InstanceCache to avoid frequent parsing of the data templates.

Category Files Administration tool

In this post I’m going to give you a bit of information regarding the Category Files Administration tool that has been around since 10.0.5.2. It is a generic tool that handles files in the database but it can be configured to view files of a specific category so this tool is also the Mashup File Administration and the Startpad File Administration. The Startpad in 10.0.5 and 10.1 is a separate install which some customers do not install so in 10.0.5 you might just have the Mashup File Administration but it is in fact the same tool as below it is just that you are not allowed to change category.

Here is a picture of the tool and its different areas:
CategoryFilesOverview

1. Category Selection. There are currently five possible categories. Default canvas files, Mashup, Shared files, System files and Startpad (optional). When you select a category all files in that category will be listed in the file list.

2. The File List – A list of all files and when they were last modified. The changed by column show the last user who changed the file. It does not mean that the file was changed from within the tool, it can be that a user added a shared link in the S3.xml or edited a propery in the profile. The Connect Roles and Users column is just to give you a quick overview if the file is only available to a set of users. If the file can be connected to roles/users depends on the category. Only the Mashup and Startpad category supports connecting roles and/or users.

3. Actions. Once you have selected a file all the buttons will be enabled. The file list does not support multi select so you can only select one file at the time. All buttons except the new button requires a file to be selected. If some buttons are not visible they are not supported for the category. This might be controlled by a setting. One example is in the Mashup category where ‘Enable Mashup Deploy’ has to be set to true. The update button is great if you for example has manually updated the links file or the profile file. The file you browse to do not have to have the same name as the file you would like to update in the list. You select the file you would like to update and then press update and select a file to be uploaded. Note that for some versions of Smart Office you need to do a dummy change in the Profile Editor for the profile cache to be up to date.

File detail area

The File detail area will be disabled for all categories except for Mashup and Startpad. The Mashup and Startpad are the only category files that you can control per role and/or user. It is possible to have a specific default canvas file but that is controlled by adding a rule to the Canvas property in the Mango.UI section in the Settings Editor.

The reason we added categories even for files that does not support the role/user mapping is simply becuase it reduced development time. Instead of adding a lot of different tools we reused the existing tool add as we moved a lot of files from the file system to the database. We are taking these steps becuase we would like to support scale out in the future and then we can’t have any files on disk. I think we have a lot of admin tools already and I hope to see a consolidation in the future, but we are resistant to removing tools since it might be confusing to existing customers.

4. File access level. This section is only applicable for files in category. Access none means that the file is uploaded but in draft and will not be downloaded by any clients. Public means that it is accessible for all and role means that only roles or users visible in section 7 will download the file. This only applies to Mashups and Startpad files.

5. User ID entry. There you can connect and allow specific users to access the file by typing their user ID and pressing Add user. If your Session Provider supports name lookup you will get a username in the list but you still need to know the User ID and enter it manually.

6. Available roles from the Session Provider. This section shows a list of available Session Providers. Only the Windows Session Provider, LDAP Session Provider and SAML Session Provider support roles. The DSSO session provider does NOT support roles. Lots of customers use DSSO and I’ve been trying to push for this functionality for the DSSO session provider. If you would like this functionality I suggest you enter a request to support listing roles (for the DSSO Session Provider).

7. Roles and users with access. This list shows you the users and/or roles that have access and will download the selected file. Please note that those connected entities will only have affect if the Access type is role (and for category Mashup and Startpad). If you change the access level to Public you can expect the connected entities list to be cleared so you will lose any connections added.

Data Categories

Default canvas files

Default canvas files storage. To connect the file to a role/user you cannot use the section with the roles. You connect a specific template to a role by adding a Rule with the name of the file in the Settings Editor in the Mango.UI section. The name of the setting is ‘Canvas” see picture below. Think of this category as a storage for the file but the confiugration is done in the Settings Editor. If you would like to have another default canvas than the one delivered, replace (update) the LawsonCanvas.jade file with a saved canvas file with other content.

Mashup

All Mashups deployed from Life Cycle Manager or the Grid Management Pages (10.2 only). Mashups can be connected to specific roles and or users if the Session Provider supports it. Note that this category is only available if the Mashup scheme is enabled/allowed.

Startpad

Startpad files that contain public deployed startpads. Note that this category is only available if the Startpad feature is installed and enabled in the profile when you run this tool.

Shared Files

There are global files shared with all users. Different features can store files in this category. M3 and Lawson use this category for storing shared links. Please note that these link files must have the name with slash in them. You can update those files by selecting them in the list and clicking update but if you manually need to add a new file with a slash in the name you need to first click new – import and then right click to get the context menu and select rename.

Example files:
Links/M3.xml
Links/S3.xml
Links/S3List.xml

System files

These files are related to the Infor Smart Office framework. Features are not allowed to store files in this category.

Example files:

  • channels.xml – contains information about manually created channels used in version x-10.1. (Not 10.2 and later)
  • profile.xml – The profile.xml is the list of profiles that you can edit via the profile editor.
  • template.xml – contains the template for what to create when a new profile is created. You can export and manually remove old blocks in the template. Smart Office does not remove block when features are uninstalled so after a few years there might be unused blocks for features that you might not have installed anymore.
  • users.xml – the list of users who have used the built in collaboration service. This file is not used in version 10.2 and later. In that version they are stored in the collaboration tables in the database.

There are no roles and I get an error message

There is an error message the first time you start the tool if your Session Provider (installed in the grid where Smart Office is running) does not return any roles. The error message is “Unable to load the list of available roles. Please check the client log for more information.” In the case of DSSO the session provider actually implements an interface so that Smart Office expect roles but the LSF backend (Landmark identity provider has never supported listed roles) does not support listing roles or in some versions of the backend there is an exception when looping over an empty list.

When roles are not listed in section 6 you can only connect individual users by using the input section 5. The DSSO session provider does not support listing roles becuase the LSF identity provider and the Landmark identity provider does nor have that functionality. If you would like this functionality I recommend you to enter a request to support (it should be directed to DSSO session provider or LSF (Security) or Landmark (Security) and not Smart Office. You also have the option of using the Windows session provider or the LDAP Session provider but it will have other implications as well. Internally at Infor we use both the LDAP Session Provider and the DSSO Session Provider (in different installations of course) for running Lawson Applications in Smart Office.

Enable Mashup Deploy

If you would like to use the Category File Administration tool or the Mashup File Administration tool (it’s the same tool) to upload and manage your Mashups you must set the Enable Mashup Deploy to true in the Settings Editor for Mango.Core. If the action buttons are not visisble it is because you have disabled it in the Settings Editor.

Enable Mashup Deploy

You should also be aware that the file format for the Mashup is a .mashup file. This is in fact the Mashup project file so it can contain several mashups. It is not allowed to upload a .lawsonapplication file here but if you change a .lawsonapplication to a .zip application you can unzip and get the containing Mashup. You can also build a .mashup file from the Mashup Designer if you are developing the Mashup. But for all categories it is important to upload the correct file type.

In Smart Office 10.2 there is also a Grid Management Page that can be used for installing Mashups.

This means that there are other options to using Life Cycle Manager (LCM). Please note that Mashups installed with LCM and the MangoServer Grid Management Pages will still be visible in the Smart Office tool but not the other way around.

Add a new default canvas file

Something that every customer should do is to replace the default canvas with their own default canvas. If you still would like to keep the old default you need to do the following.

In Smart Office you can save your current canvas and use that as a templates. The default canvas only applies to users who have never run Smart Office. There is however one exception to the rule and that is if Disable changes to user Canvas is checked in the Mango.UI settings. That setting has a really bad name because changes are allowed but they will not be saved so if you restart you will have the default canvas file again.

  • 1. Save the canvas by selecting Show -> Switch canvas -> Save canvas. Save the file and give it a filename, for example DeveloperCanvas.jade
  • 2. In the Category Files Administration tool select category Default canvas files
  • 3. Press the new button and browse to the file.
  • 4. Open the Settings Editor and select Mango.UI. Change the name of the Canvas setting by changing the value or add a rule by clicking the button next to the input field. In my example below I have created a rule and you can see there is a Rule because the button has an asterisk.

CanvasSettings

Managing the profile.xml

The profile.xml is one of the files where you might want to take a backup or manually remove unused entries. Depending on your Smart Office version this can also be done in the Profile Editor’s advanced tab. In Smart Office Mashups and features can add entries to the settings and those settings are not cleared when the feature is uninstalled.

Function expressions in variable replacements

This post is an introduction to the enhancements made to the variable replacement functionality in Smart Office 10.2. The variable replacement syntax now supports function expressions that adds the possibility to modify values during a variable replacement.

Function expressions are currently supported in many places that uses variable replacements. Some examples are M3 toolbox shortcuts, Mashup parameters and links, Mashup controls such as WebBrowser and FileBrowser and data service parameters. Smart Links do not support function expressions in the current 10.2 release but this has been addressed and support for function expressions in Smart Links will ship in the next fix pack for Smart Office 10.2. Continue reading