Examples of how to optimize the user interface of your Thinkwise application
- 28 Topics
- 47 Replies
From version 2022.1, the Thinkwise Thinkstore has been integrated into the Software Factory development environment. The demos and code samples shown here are still available for older versions for now but are not actively maintained. We recommend upgrading to the latest version of the Thinkwise platform to benefit from the latest features and the integrated Thinkstore.Do you have any new ideas? For example, which solutions would you like to see in the Thinkstore or which function will enrich our Thinkstore, then we would like to see them in the Ideas module. This way, other members of the community can also see your idea and vote on it.
Topic type: conversationTitle: <Explain the purpose of your topic>Description: Start with the header 'Goal’<Explain the purpose of your functionality or screenThen continue with the header 'Solution’<Share the solution here.>Example PS: Don’t forget to subscribe for the ThinkStore!
GoalWe are often asked by companies whether we offer functionality for Workflow and/or Case Management. At the moment, there is no standard functionality for this in the Thinkwise Platform. In this topic you will find a Workflow Engine which can be used in (existing) Thinkwise applications.SolutionIn the video you will find all the steps needed to start using this module. The steps are Import the workflow in the Software Factory Upgrading an application to add workflow The architecture of the workflow Defining workflows Executing workflow tasks Monitoring workflows Configure notifications Technical side notes This workflow module automatically generates process flows which might be used in the workflow execution tasks. Such a process flow might end with starting a certain task in your application. When in your application this task is defined as the start of an other process flow, this flow would not be started, because the Thinkwise Platform does not support linked proces
ProblemThe ones using Indicium probably encountered this problem. Indicium marks all date(time) as UTC. Which can cause a problem when a third party GUI interprets this date with its timezone marking. Although SQL server has domains for date/time that can hold timezone information, a lot of times it lacks this info.Solution The best solution is to use a date/time domain like datetimeoffset that also holds timezone information, however if that is not available, or not really necessary if you work in just one timezone. In all cases you could create a function that takes a datetime and converts it to UTC in this case. create function get_datetime_in_UTC ( @date_time date_time ) returns date_time as begin-- Datum/tijd in UTC teruggeven omdat indicium elke tijd aanmerkt als UTC declare @TimeZone varchar(50) exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE' ,'SYSTEM\CurrentControlSet\Control\TimeZoneInformation'
GoalWhen you have system versioned tables in your database, SQL Server logs all changes made to the data in those tables. This solution makes this logging data available for the user. This can look like this: SolutionThe solution in this topic creates views on all system-versioned tables. These views give the user access to the logging data. Also, all of these views get conditional layouts in the Software Factory. These conditional layouts give fields with changed values a color, which makes it easier to analyze the data.Dynamic model meta_view_historyThis code create a view definition for every system versioned table, along with conditional layouts to point out changed data.When you add this code to the dynamic model, you have to change a few values first:@screen_type_id Your desired screen type: You can keep this null, or change the value.@original_date_column Name of an existing date column with settings that can be copied.@valid_from Name of columns that
GoalThe goal of this solution is to automatically add trace fields to all tables so the user can see who added the record or who made the last change. This solution adds these fields to a separate tab page on a form. This looks like this in the GUI: You can choose at what moment you want the fields to be filled: During editing or after saving the record.SolutionThe solution consists of code for Dynamic Model (for adding the fields) and two Control Procedures (for filling the fields). Depending on the moment you want the fields to be filled (during editing or after saving), you can choose either for a control procedure for defaults or for a control procedure for triggers.Dynamic model add_trace_columnsThis code adds trace columns to every table.The trace fields are: update_user update_date_time insert_user insert_date_time If you add the tag 'no_trace' to a table, no trace columns will be added to that table. The trace column are automatically translated in ENG and NL.Important:
In applications built with the Thinkwise Platform, the GUI supports multi language translations of objects like menu’s, entities, columns, tasks, and so on. However, the data is not multi language (yet). For example, when you have a table Products, the name of the product can be “Car”. This is fine when you’re English speaking, but when you’re French, it would be nice if you would see ‘Voiture’.The data to be translated resides in your application, not in the Thinkwise Platform. Therefore it is hard (and not desirable) to solve this challenge in the Thinkwise Platform itself.GoalIn this solution you will find functionality to translate one or more values per record. This functionality automatically generates:Tables in which you can translate one or more values of records. Lookup queries which retrieve lookup values in the language of the user.SolutionThe solution for multi-language data consists of one Dynamic Model script. This script generates translation tables for every table which
GoalWhen you are using icons for tasks, reports, prefilters and cube views, it is not always clear what the icons represent. Is it a task or is it a prefilter?You can use the ribbon or the context menu to know what it is, but you can also add this information to the tooltip (e.g. Task: …., Prefilter: ….). Now you only have to hover the mouse over the icon. SolutionYou can do this with a simple dynamic model procedure. Based on the type of object the tooltip is default filled when the object is translated and the tooltip is empty. update t set tooltip_text = case when type_of_object = 11 then case when appl_lang_id = 'NL' then 'Taak: ' when appl_lang_id = 'ENG' then 'Task: ' end when type_of_object = 10 then case when appl_lang_id = 'NL' then 'Rapport: ' when appl_lang_id = 'ENG' then 'Report: ' end
GoalWhen working with the Software Factory, it is possible to make tables System versioned, or another name is temporal tables. The SF will create a history table when the the setting System versioning is set to true. However, to make use of this history data we recommend using a function to obtain records from the history table. SolutionHere is a Dynamic model control procedure that automatically creates a 'get_[table]_at_point_in_time’ function. And below this code, find more code - this is the Control procedure that is needed to create the function.(This script works for the 2021.2 version of the Software Factory. Compatibility may change over time.)Dynamic model (meta_function_point_in_time):select @project_id as project_id, @project_vrs_id as project_vrs_id, 'get_' + tab_id + '_at_point_in_time' as subroutine_id, 'Function' as subroutine_type_id, 2
GoalApplications often use a checkbox to determine whether a record is active or inactive. In most tables you would like to display the records which are marked as active and hide the records marked as inactive. This means you will have to set up a prefilter to hide the inactive records. Image how great it would be if you could generate those prefilters automatically. This topic will teach you how to configure the automatic generation of prefilters.SolutionThis topic will provide you with a dynamic model procedure which generated prefilters on tables that contain a column named inactive. It also provides this prefilter with an image and sets the prefilter to enabled and visible on the main, detail and popup screens. The icon and the column which triggers this script, can be ajusted to match your own application.Create a dynamic procedure and submit the following control procedure code:--------------------------------------------------------------- create prefilter active where not exis
GoalCreating a drag and drop task for the first time can be challenging. This example will tell how to create a simple drag-drop task that will enable you to drag products into a shopping cart.SolutionThere are three components, namely the Source tab, the Target tab and of course the Drag-drop task. Assuming the tabs are already present, we will focus on making the task and setting it correctly.Create a task that has the Primary Key of the source tab and the target tab. Connect it to the Target tab on the Primary key columns. In Subjects, navigate to the Source tab and create an entry in Links → Drag-drop. Enter for the Drag-drop parameters (at least) the Primary key columns of the Source tab. These are the parameters that get filled with values from the SOurce tab. Set up the drag-drop interaction and you are good to go. Enable def. drag-drop enabled if needed at the Settings tab in Subjects.Result looks like this: Code used for this example:--Product not in shopping cart yetif not ex
GoalSome lists have an order number that functions as a standard sorting, or as a sequence of actions, or for other reasons. The Drag and drop functionality the GUI offers is a great tool to use for this but it needs some coding.SolutionThe following code is a good start for sequential lists (1,2,3,4,etc.) and work with multi-selection.Requirements: Task with PK parameters, a from_order_no and a to_order_no parameter. Connect to table with only to_order_no = table.order_no Create drag-drop at desired subject and connect PK parameters and from_order_no = table.order_noUse following code in Functionality > Template.--Continue if differentif @from_order_no <> @to_order_nobegin --Copy all records into #temp select * into #temp from [table] t --Make space for reorder update t set t.order_no = order_no * 10 from #temp t --Alter order no of dragged row (+1/-1 depending higher/lower dragging) update t set t.order_no = @to_order_no * 10 + ii
GoalAfter opening a screen the dataset is loaded within this screen. When you open a different screen and afterwards reactivate the screen, which you had opened previously, the dataset is still the same. You have to manually click on refresh to activate a refresh action within this screen. You could also set an automatic refresh based on a specified schedule, but this is often not the most suitable option.Image being able to automatically refresh data after reactivating a screen, that is exactly what this topic allows you to configure.SolutionThis topic will guide you through setting up a dynamic Software Factory model template. It will create the following objects:Processflow Per table/variant, determined by which table/variant is accessible through a menu type or table/variant tag Processactions Start Stop Activate document Refresh table Processteps in this order Start process Activate document Refresh table Implementing it requires you to set a control procedure in the “Dynam
GoalWorking with a new application can get quite overwhelming for end users. Not only is there a whole new UI for them to figure out, but they could also get overwhelmed with information, options, and functionality that is not yet relevant for their day-to-day tasks. This makes them take longer to get used to the whole UI. Someone who just started at sales and uses the application for the first time, might not immediately need historical data or Business Intelligence to target their first prospects. It is important that these ‘beginner’ employees smooth into using the application with a simplified version of the UI. In a later stadium, these users can then be scaled up to an ‘advanced’ or ‘expert’ level, revealing new objects (e.g., menu items, details, tasks, etc.). SolutionTo achieve this at this moment we need to define user groups in the Intelligent Application Manager, for each difficulty level (e.g., ‘sales_beginner’, ‘sales_advanced & ‘sales_expert’). For each difficulty le
GoalShow a 5 star rating in form and list.This function creates a star rating up to 5 stars based on the used parameterExample of stars in formExample of stars in listSolutionCreate a subroutine that gets a numeric(2,1) as input and retuns a varbinary(max). This would look somelike this:/* Drop function get_stars_rating first. */if exists (select 1 from sysobjects where name = 'get_stars_rating' and (type = 'FN' or type = 'TF' or type = 'IF')) drop function get_stars_ratinggocreate function get_stars_rating( @amount_of_stars numeric(2,1) )returns varbinary(max)asbegin --control_proc_id: function_get_stars_rating --template_id: function_get_stars_rating --prog_object_item_id: function_get_stars_rating --template_description: Returns an icon with max 5 stars based on the amount of stars inputted return cast('<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewB
Goal This validation checks whether at least one group label exists on each form tab in a table (variant). Solution-- Table form field group labels.;with min_form_no as (select MIN(c.form_order_no) as min_form_order_no ,MAX(c.form_order_no) as max_form_order_no ,c.tab_id from col c where c.project_id = @project_id and c.project_vrs_id = @project_vrs_id group by c.tab_id)select c.project_id ,c.project_vrs_id ,c.tab_id ,c.col_id ,c.field_on_next_tab ,c.next_tab_label ,ISNULL(c.next_tab_label,c.tab_id) as form_label ,c.abs_order_no ,c.form_order_no as current_form_order_no ,LEAD(c.form_order_no,1,m.max_form_order_no + 1) over (partition by c.tab_id order by c.tab_id, c.form_order_no, c.col_id) as next_form_order_no into #col from col c join min_form_no m on m.tab_id = c.tab_id where c.project_id = @pr
GoalThis dynamic control procedure places the fields from a list (of both tables and variants) in the same order in the filter and search screens.Fields that are not visible in the list but are in the form are placed under 'Extended'.Fields that are not visible on the list or form are not displayed in the filter and search screen.An exception can be made by means of the table tag 'custom_filter'. Solution/* This dynamic control procedure places the fields from a list (of both tables and variants) in the same order in the filter and search screens. Fields that are not visible in the list but are in the form are placed under 'Extended'. Fields that are not visible on the list or form are not displayed in the filter and search screen. An exception can be made by means of the table tag 'custom_filter'.*/declare @custom_filter_tag tag_id = 'custom_filter' ,@sql varchar(max) = ''/* visible_for_filter / visible_for_search 0 - Always 1 - Extended 2 - Never*/
Goal: A simple and easy to user CRM system For a prospect we created a CRM system in Universal. To give you a good idea of what is already possible with this new GUI, we would like to share this with you. Account overview The general account screen. Within this screen all accounts can be found with only information that is initially needed. If detailed information is needed, this can be found in the next tab 'form'. In addition, all tabs with information such as addresses, account owners, alternative names and classifications can be found based on the selected account. Detailed tiles can be found on the right side of the screen. Here you can consult information such as contacts, emails, meetings, leads and opportunities attached to the selected account. Account hierarchy Within the account screen there is also the possibility to consult all accounts over a hierarchy. This gives you an overview of the parent and subsidiaries. This simple solution ensures that you can see
GoalSometimes it is necessary to know what data has changed between two databases. This can occur when using multiple branches in a big project. Upon merging to the trunk, from time to time there is reason to add/alter/delete data. For instance, you could have a base data setup where the trunk supplies data to all users. This could be currencies, countries, postal codes, color names/codes, storage locations, etcetera. When adding/altering/deleting data it is possible to forget what a previous state was of that data. If there's no logging, it's quite tedious to find out what has been added/altered/deleted. To compare the trunk and the branch data of given tables, you can use the following to find out what data has been added, altered or deleted. SolutionIt has been made for SQL 2017+, because of the string_agg() function. The code only returns changed rows. If nothing is changed, no results will appear.Few things need to be changed, namely the database names and the given tables. You c
Goal Especially when you create business systems that support multiple regions or even the world, a geographic tabel is a necessity to use especially for reporting purposes. Solution A good source for this can be found through the following link. It also has regions and sub-regions. https://github.com/lukes/ISO-3166-Countries-with-Regional-Codes/blob/master/all/all.csv
Goal Tasks are a frequently used solution to perform business functions. And often these functions are restricted, and can only be executed under certain conditions. I would like to advocate that it's more user friendly to stay ahead of these checks. It's common that these checks are done at execution time of the task. However, and especially when there are more conditions to be met, it can be frustrating to go from notification to notification. Using the full extent of tasks can get you a long way in giving users insight in meeting the pre-conditions of a business task. Solution Using task parameters, image combos, conditional formatting and the power of defaults and layouts you can visually show to what extend the pre-conditions are met. You could even generate custom messages upfront so a complete overview can be given on potential errors and warnings. In belows example materials are accompanied by certificates and stock needs match fully or partially. We used a little algori
Have you been wondering how to pass a product ID or customer name to tsf_send_message? Confession: I did. Keep in mind that the second parameter of tsf_send_msg has to be a (set of) prepared XML-string(s). Those two things do not work: Not using XML: exec tsf_send_message 'option is incorrect', @option_id, 0 Expecting SQL-parameters do be usable: exec tsf_send_message 'option is incorrect', '<text>@option_id</text>', 0 The correct way to go about this, is defining your XML-string(s) beforehand and assigning them to an SQL-variable that is then used in calling tsf_send_message: declare @msg_parameter varchar (50)set @msg_parameter = (select concat ('<texst>' , option_id, ' - ', option_name,'</texst>' from options where option_id = the_incorrect_one))exec tsf_send_message 'option is incorrect', @msg_parameter, 0 In this case there is a single message parameter, the translation record of the message ‘option_is_incorrect’ in de SF would resemble: “Dear
Goal When you are building a table for sales order, deliveries, invoices, and so on, you will need some kind of identifying number. Such a number can be constructed in several ways, but in many case there are these few parts: prefix date order number This could lead to something like this: INV-2020052001 In this example you can see how you can create such a number. Solution This example shows a select query which constructs an id with the format INV-YYYYMMDDOO. You could use this example to create functionality in a default or trigger, which stores the number in a column. ------------------------------------------------------------ This example show a select query which constructs an id-- with the format INV-YYYYMMDDOO----------------------------------------------------------select 'INV-' + cast(year(si.invoice_date) as varchar(4)) + right('00' + cast(month(si.invoice_date) as varchar(4)), 2) + right('00' + cast( row_number() over (par
Goal In the Software Factory task en report parameters have their own translations. As a developer, you have to fill them in, after creating a task or report. Though this is a flexible solution, most of the time the translations are the same as the translation of columns with the same name. This solution makes sure those translations are always the same. Solution This solution consists of code for Dynamic Model. The code copies the translation from columns to task and report parameters with the same name. This means that those parameters are translated automatically while generating your application.
Goal Sometimes you have a prefilter which you also would like to have on other tables in your application. For example, a user only has access to customers from a specific region. Now when he opens the outgoing invoices table, he should only see the outgoing invoices of the customers of that specific region. In fact, in every screen with some kind of customer data, you want to restrict the access to that data, based on that region. This solution automatically generates prefilters throughout the application. Solution This solution consists of code for Dynamic Model which generates prefilters based on a prefilter which is locked. With the tag AUTHORIZATION_PREFILTERS_NOT_INHERITED you can exclude prefilters, target tables or references from this mechanism. Example: Let's say you have the following code as prefilter on customer: exists (select 1 from region r where r.region_id = t1.region_id and r.region_name = 'Northern Europe') This solution will generat
Login to the Thinkwise Software Community
Enter your username or e-mail address. We'll send you an e-mail with instructions to reset your password.