Blog: Posts from July, 2021

Labels
AJAX(112) Apple(1) Application Builder(242) Application Factory(207) ASP.NET(95) ASP.NET 3.5(45) ASP.NET Code Generator(72) ASP.NET Membership(28) Azure(18) Barcodes(3) BLOB(18) Business Rules(1) Business Rules/Logic(140) BYOD(13) Caching(2) Calendar(5) Charts(29) Cloud(14) Cloud On Time(2) Cloud On Time for Windows 7(2) Code Generator(54) Collaboration(11) command line(1) Conflict Detection(1) Content Management System(11) COT Tools for Excel(26) CRUD(1) Custom Actions(1) Data Aquarium Framework(122) Data Sheet(9) Data Sources(22) Database Lookups(50) Deployment(22) Designer(177) DotNetNuke(12) EASE(20) Email(6) Features(99) Firebird(1) Form Builder(14) Globalization and Localization(6) Hypermedia(2) Installation(4) JavaScript(20) Kiosk(1) Low Code(3) Mac(1) Many-To-Many(4) Maps(6) Master/Detail(36) Microservices(4) Mobile(63) Mode Builder(3) Model Builder(3) MySQL(10) Native Apps(5) News(15) OAuth(5) OAuth Scopes(1) OAuth2(6) Offline(14) Oracle(10) PKCE(1) PostgreSQL(2) QR codes(2) Rapid Application Development(5) Reading Pane(2) Release Notes(163) Reports(48) REST(26) RESTful(21) RESTful Workshop(13) RFID tags(1) SaaS(7) Security(75) SharePoint(12) SPA(5) SQL Anywhere(3) SQL Server(26) Stored Procedure(4) Teamwork(15) Tips and Tricks(81) Tools for Excel(2) Touch UI(93) Transactions(5) Tutorials(183) Universal Windows Platform(3) User Interface(331) Video Tutorial(37) Web 2.0(100) Web App Generator(101) Web Application Generator(607) Web Form Builder(39) Web.Config(9) Workflow(28)
Archive
Blog
Posts from July, 2021
Saturday, July 31, 2021PrintSubscribe
Clipboard, Drag & Drop, Auto-Refresh, Alt Master-Detail, and Property Grid

Code On Time release  8.9.21.0 introduces the clipboard and data drag & drop support in Touch UI. Dashboard data controllers can be enhanced to perform automatic refresh of the DataView fields according to the specified interval. DataView fields can also be connected into master-detail relationships even if there are no natural foreign key relationships. The Property Grid  is the new exciting feature of the framework - keep reading to learn more!
 

Clipboard & Drag & Drop

In a matter of minutes developers can configure the app to allow Cut/Copy/Paste and dragging of items from one data view to another. A simple programming model makes it easy to implement processing for the system commands CutPaste, CopyPaste, and DragDrop. The persistent clipboard allows moving data from a data view on one page of the app to another. 



Auto-Refresh in DataView Fields

DataView fields of a data controller can now be configured to refresh after a specified interval. Specify the Refresh Interval property in the Data View section of the data field in the “form” view. The interval is expressed in seconds.

This feature can be useful when implementing the monitoring dashboards. The framework will ensure that the app is not busy and the dataview is interactive and visible to the user when performing the synchronization of the view data with the server.

Alternative Master-Detail Linking in Forms

DataView fields can have a master-detail relationship with the other DataView fields in the form even if there is no natural foreign key relationship between them. The Clipboard and Drag & Drop tutorial demonstrates this in action by setting the link between the orders and the menu of products. The property Filter Source of the products is pointing to the orders and no filter fields are specified. If the order selection is changed then the products are refreshed. The server-side code can perform custom filtering based on the arbitrary condition.


Announcing Property Grid

We are pleased to announce that the new feature called Property Grid is now included in the framework. The screenshot shows the property grid displayed in response to the inspection of the display object on the page, that was constructed with the Content Hub Add-on and Display Flow

 
Soon you will see the Property Grid in the development mode of your own apps when configuring the ~/app/touch-setting.json or the project properties. The same component will be sliding out from the side of the screen when editing the content in the upcoming community site and when building the data-driven surveys at runtime.

Property Grid is the Touch UI form driven by the metadata. The developer-friendly data input mode with the comprehensive keyboard support makes the grid suitable for various configuration tasks when building apps and content. It will be also possible to tag a form view as a property grid. The form view configuration will be converted into the Property Grid metadata by the framework at runtime and the end user will be presented with a sliding panel to edit the data.

Release Details

The following features, enhancements, and bug fixes are included in the release:
  • Data Clipboard with support for Cut/Copy/Paste and Drag & Drop
  • (Inline Editor) Focus frame is not visible when the grid with a large number of columns is scrolled and the focused field is out of view.
  • (Blob) Default blog image is triggered on the existing record. Previously this happened only if the existing blob was cleared.
  • (Touch UI) Removed the delay context scope reset when the panel action is executed on close. This eliminates the problem with the incorrect set of actions in the form views.
  • (Clipboard) If the data view is tagged as view-paste-Controller or view-drop-Controller then the current row or target row is ignored. Only the master values are supplied for the row representing the target of Paste or Drop.
  • (Cloud On Time) The app will not raise an exception when processing requests without the UserAgent header received from Cloud On Time during the custom app installation.
  • (Touch UI) Externalized the CSS rule that controls the visibility of the child dataview to improve performance.
  • (Touch UI) Child dataview field will behave as a dependent even the Filter Fields are not specified. The property Context Fields will be set to the value of the filter and is passed to the server for custom filtering with the access control rules.
  • (Touch UI) If the dependent data view of the master-detail relationship is not visible and there are no other visible elements in the simple or collapsible container then the container is also hidden until a data item the master data view is selected.
  • (Client Library) Method dataView.syncOnce() will synchronize the dataview when it stops being busy and is on the active page and ready for interaction. The first argument of the method specifies the name of the child DataView field. The corresponding dataview will be synced when the argument is specified. The second argument will force the immediate attempt to sync if set to true. 
  • (Touch UI) Property Refresh Interval of the DataView field on the form will cause the data to refresh after the period of time expressed in seconds.
  • (Classic UI) Method dataView.data() returns an object with correctly assigned "unmodified" properties. Previously the "null" value was assigned to the property that was not changed.
  • (Classic UI) Method dataView.data() returns an object with correctly assigned "unmodified" properties. Previously the value "null" was assigned to the property that was not changed.
  • (Client Library) Simplified the dataView.survey() method by removing the legacy processing of Classic UI.
  • (Client Library) Data objects returned by the method dataView.data() invoked on an instance of the data view will not have the "_modified" property with the properties of the original row instance. Invoke the method with the 'modified' parameter if you require the "changes" included.
  • (Clipboard) Method $app.clipboard.paste() will raise the client-side CopyPaste|CutPaste|DragDrop in the "Before" and "After" phases. The former may return a "promise" object to delay the command until resolved or false to prevent the command. The latter allows executed the custom in JavaScript upon completion.
  • (Framework) DataView fields with have access to the other DataView fields in the same master form if their names are listed in the Context Fields property. For example, MyOrderID=Orders will result in the primary key of the selected order in the Orders field to be available to be used in custom access control rules.
  • (Touch UI) Descriptions of items in the context menus have a unified 12px font size and are limited in width.
  • (Touch UI) Event keyboardpreview.app is triggered in the scrollable element of the virtual page.
  • (Touch UI) Event datainputfocus.app is triggered when the data input is styled to indicate the "focused" state.
  • (Touch UI) Notifications are displayed as centered when the docked virtual page is active.
  • (Touch UI) Event scrollablepageready.app is triggered on the scrollable wrapper of the virtual page. This event is triggered prior to the page transition and can be used to change the initial vertical scroll position in the form.
  • (Touch UI) Event pageautofocus.app is triggered on the active page.
  • (Touch UI) Event datainputmove.app is triggered on the current data input instead of the document.
  • (Touch UI) Event keyboardnavigation.app is triggered in the scrollable element of the page. Previously this event was triggered on the document.
  • (Inline Editor) The handler for keyboardnavigation.app event does not attempt to move the focus if there is no active focus frame of the inline editor.
  • (Touch UI) $app.touch.hasFocus() method removes focus from any other focused elements if the element specifed in the argument is focused.
  • (Touch UI) Event pageautofocus.app is triggered on the document. If the default is prevented then no attempt to set the focus is performed.
  • (Touch UI) Method $app.touch.scrollIntoView() will ensure the visibility of the element specified in the argument.
  • (Touch UI) REMOVED. Event beforefocus.app is not triggered anymore.
  • (Touch UI) Event datainputlabel.app is triggered on the data input label. If the default is prevented then no attempt to focus the corresponding input is performed. Property Grid of v9 designer uses this event to set the visual focus on the label.
  • (Touch UI) Enhanced the app-has-focus removal from the labels/values.
  • (Touch UI) Double click/tap on the label of the field in the form will trigger the vdblclick event on the label element.
  • (Touch UI) Method $app.touch.layout() will perform the layout of the form. Method must be called if the initially invisible regions of the form layout become visible.  Property Grid uses this method when collapsed complex properties and categories are expanded.
  • (Touch UI) Method $app.dblClick(elem) will return true if the elements was clicked or tapped twice in the past 500 milliseconds.
  • (Touch UI) Double click on the Drop Down List label will cycle the input value.
  • (Touch U) The drop down list button has a non-transparent background for improved presentation of input with the long lookup values.
  • (Touch UI) Delayed focus removal eliminates blinking of the focus indicators when the value of the input has changed after the focus loss and recovery.
  • (AppGen) Application generator creates a valid Visual Studio project when the word "Global" is included in the project name.
  • (Touch UI) Data view tagged as class-name-CSS_CLASS_NAME will assign the specified CSS class name to the "div" element of the virtual page.
  • (Client Library) Method $app.prettyText(text, capitalize) will capitalize the leading character if the second argument is set to true.
  • (Client Library) Method $app.prettyText now detects the national Unicode upper-case characters and treats as words the sequences of numbers. For example, the following calls will return the arguments with 3 spaces placed in front of the upper-case letter and the first digit:
            x1 = $app.prettyText('NextNewYear2021');
            x2 = $app.prettyText('PróximoAñoNuevo2021');
            x3 = $app.prettyText('ΕπόμενοΝέοΈτος2021'),
  • (Touch UI) Fixed issued with the incorrectly migrated labels when input-blob.js was extracted from touch.js.
  • (REST) Robust processing of REST API request to ~/_invoke/auth for authentication to obtain and renew the tokens.
  • (REST) Server-side framework implements the _invoke/auth API to allow obtaining and refreshing the access tokens.
  • (Framework) Refactored application services to support handlers with custom parsing of arguments to support the REST 2.0 and the upcoming Graph QL engine.
  • (AppGen) Fixed incorrect references to the ReportViewer DLLs v14 and v15.
  • (AppGen) Projects based on the class library will correctly copy the  runtime-loaded minified *.js files to the ~/app/js folder of the solution. That includes touch-draw, daf-search, daf-import, and daf-flow.
  • (Touch UI) Last input focus is restored on mouse-driven devices if the dragged away modal form restores its position in response to the user's click on the background.
  • (Touch UI) Windows focus will not cause an exception when the core framework is still being constructed.
  • (Classic UI) Fixed the problem with uploading of images in BLOB fields.
  • (Classic UI) Font preloading instruction is not included in the HTML pages.
  • (Framework) Nielsen Batista has contributed the pt-BR localization. Submit your own files with the support and we will have them included in the future releases of the product.
Labels: Release Notes
Friday, July 30, 2021PrintSubscribe
Drag, Cut, Copy, and Paste Your Data

Clipboard is an indispensable tool if you are composing an email, creating a document, or writing code. “Cut and paste” helps us to rearrange our thoughts. “Copy and paste” comes handy when we are out of ideas.

An input field in a custom business app provides instant access to the system clipboard when editing a value. A selected fragment of text can be dragged and dropped into a new position. App users work with the collections of data items. A data item represents a group of related fields. Wouldn't it be great to take advantage of the clipboard and drag & drop to copy or move the items between or within the data collections?

Clipboard and Drag & Drop With Structured Data

The clipboard commands and drag & drop can benefit a business app when applied to the structured data. Consider the Order Management Dashboard presented below. 

You can see the end user dragging the product from the menu and dropping it directly on the list of details of the selected order. The product Boston Crab Meat is semi-transparent in the menu of 77 products while it is being dragged. The “drop” frame outlines the Order Details as a target accepting the product. The mouse pointer is displayed as the “copy” arrow. The tooltip with the name of the dragged item is shown next to the pointer.

 

The result of the product “drop” is shown next. The product is no longer visible in the menu of 76 products presented on the right-hand side of the dashboard. The dropped product is now linked to the selected order. It is visible in the list of details. The “drop” frame has disappeared.

The following screenshot shows the state of the dashboard just moments after the user has started dragging the product. The list of details is still empty. The mouse pointer is a no-drop icon indicating that the drop is not accepted in the current position. The “drop” frame will appear when the pointer is over the list of details.

 

 
The end user can select the Copy command from the context menu of a product. The “drag indicator” doubles as the “more” menu when tapped or clicked. The command is also visible on the toolbar of the Products grid.

 
Here is the result of the Paste command executed three times on the Order Details. The product Aniseed Syrup has disappeared from the menu of products, which is now reduced to 75 items. The product is visible in the list of order details with the quantity set to 3. The Paste command on the toolbar of the details shows the tooltip with the description of the copied item and its source.

 
This application also enables the drag & drop capabilities for the Shippers. It may be useful when implementing the rearranging of items. 

The “drag indicator” icon is shown in each row next to the values in the first column of the grid. It replaces the standard “more” icon. The mouse pointer switches to the “grab” style when hovering over the icon. It prompts the end user that the corresponding item can be dragged.


Dragging of the item will switch the pointer to “no-drop” when dragging over the targets that do not accept the drop. The dragged item is semi-transparent and the tooltip next to the system pointer explains what is being dragged.


The list of shippers is configured to accept the drop of its own items. The mouse pointer style is “move” when hovering over the items in the same list. 


Dragging to the other user interface elements of the Shippers grid will cause the entire list to become the “drop” target.

 

Cut/Copy/Paste and Drag & Drop in Touch UI

Touch UI provides the built-in data clipboard with the persistent state. System actions Cut/Copy/Paste and item dragging is enabled in the app with the simple tagging of the corresponding data views. Commands CutPaste, CopyPaste, and DragDrop are automatically executed by the framework in response to the user actions. Developers can create custom JavaScript, SQL, and Code business rules responding to the commands. The command argument indicates the name of the source data controller. Developers have access to the target row of the command and the row that was cut, copied, or dragged. The source row fields are prefixed with the name of the source data controller. There is no built-in processing for the commands and their interpretation and security is left up to the application developers. If multiple items were copied, cut, or dropped, then the corresponding command is executed for each item in the context of the transaction. The successful execution of the command for all items will result in the automatic commit. An error will rollback the effect of CutPaste, CopyPaste, and DragDrop for all items. Clipboard objects created with Cut and Copy commands are available to all pages of the application. This makes it possible to offer a comprehensive clipboard experience with the structured data. The clipboard contents remain persisted until the next Cut/Copy is executed by the user. This enables pasting the same data multiple times. Developers may opt to clear the clipboard after each CutPaste or CopyPaste command when needed. The unique unified data processing of Touch UI allows creating a consistent clipboard and drag & drop experience for the structured data. Let’s learn how to build this Order Management Dashboard.
 

Dashboard Configuration

Begin by creating a new project with Code On Time. Connect to the instance of the Northwind database. Create the following models with the default settings: Orders, Customers, Employees, Shippers, OrderDetails, Categories, Products, and Suppliers. Optionally configure the orders to sort by dates with the most recent ones at the top. Activate the project designer and create the new custom data controller with the name Dashboard1. This controller is not based on any data model. Select Orders, OrderDetails, and Products controllers with Ctrl+click and choose Copy in the context menu of either one of them. Right-click the Dashboard1 controller and choose Paste. This will create the corresponding DataView fields. Set the Filter Source of OrderDetails field to Orders and Filter Field #1 to Order ID. This will enable the master-detail relationship between the Orders and the Details in the dashboard. If the order is selected, then the details will be filtered to show the linked items. Set the Filter Source property of the Products field to Orders but do not select any filter fields. The product menu will behave as any other detail in the master-detail relationship. It will hide if there is no order selected in the dashboard. It will show up and refresh when the order selection has changed. The server-side code will also have access to the primary key of the order. Create the view form1, set its type to Form, the label to Order Manager, and tag it as material-icon-category. Create two categories in the form1. Set the flow of both categories to New Column. Rename the categories by selecting the corresponding command in the context menu to orders and products. Drag the Orders and OrderDetails fields to the first category. Set the Page Size of the Orders data field to 3. Also set its Auto Highlight First Row to Yes. This will ensure that only the three most recent orders are visible with the first one selected when the dashboard is loaded. Next set the Page Size of the OrderDetails data field to 25. Drag the Products field to the second category and set the Page Size of the created data field to 7. The Dashboard1 data controller will look like this in the Project Designer on the Controllers tab.
 


Now it is time to configure the Cut/Copy/Paste and Drag & Drop. Tag the Dashboard1 / views / form1 / orders / OrderDetails data field as shown below to enable the pasting and dropping of Products into Order Details

item-paste-Products item-drop-Products
Tag the Dashboard1 / views / form1 / products / Products data field with the following tags to enable Cut, Copy, and dragging of Products:

item-cut item-copy item-drag myapp-product-menu
The custom tag myapp-product-menu will be used later when filtering the product menu. Create the page called Dashboard and drag it after the Home page. Copy and paste the data controller Dashboard1 onto the page. Set its property Show Action Buttons to None. Enter Wide in the Icon / Custom Style property to remove the sidebar on the page. The visual configuration of the dashboard is now complete!
 

Implementing Paste and Drop

Commands CopyPaste, CutPaste, and DragDrop are executed on the OrderDetails data controller when the user pastes the previously cut or copied product or drags and drops one from the product menu onto the view. We will create a single SQL business rule to handle all of these situations. Our objective is to insert or update a record in the Order Details table.


 
Create a new SQL business rule in the OrderDetails data controller. Set its phase to Execute and its Command Name to CutPaste|CopyPaste|DragDrop regular expression. Enter the following script:
 


The business rule is triggered when the command with the name matching the regular expression is detected by the app framework on the server. 

The SQL script will attempt to increment the Quantity column of the existing [Order Details] row with the product ID matching the parameter @Products_ProductID. This parameter is supplied by Touch UI and its value is set to the dragged, cut, or copied ProductID. Note that it is possible to access any other property of the product by specifying the name of the data controller as a prefix separated with the underscore character from the field name.

Touch UI also supplies the value of the parameter @OrderID. It is set to the value of the OrderDetails.OrderID field in the “drop” or “paste” target item. If the target is the entire Order Details view then the field values are set to NULL with the exception of the fields specified in the Filter Fields property. The values of these fields are borrowed from the selected master row. The business rule has the value of the selected OrderID regardless of the drop or paste target.

If no rows have changed after UPDATE then the SQL business rule will INSERT an order detail with the same product and order identifiers with the quantity of 1.

Filtering Items in the Product Menu 

Let’s make it so that the product menu in the dashboard is empty unless an order is selected. 

Choose the Products data controller in the Project Designer and set its Handler property to ProductsBusinessRules. Browse the app to generate the placeholder file ~/app/App_Code/custom/Rules/Products/ProductBusinessRules.cs. Right-click the controller and choose Edit Handler in Visual Studio.

Enter the following code:
 

 
Method EnumerateDynamicAccessControlRules will impose the access control restrictions when the app is retrieving the data for grid1 view of the Products tagged as myapp-product-menu. This is exactly how the product menu is configured in the dashboard. The name Orders specified in the Filter Source property of the data view field Products is ensuring that the order ID selected in the dashboard is available under the “Orders” alias to the business rules.

If the order ID is not available, then our list of products will be limited to those with the primary key set to -1. Such products do not exist and therefore the user will see the empty list of products.

Otherwise we will deny access to the products that are already linked to the details of the selected order. Such products will not be visible in the product menu.

Trying It Out

Run the app and try populating order details with Cut/Copy/Paste and Drag & Drop. You will notice that the product menu gets shorter as more details are created in the selected order. The framework automatically syncs the details and the product menu with the server after each successful CutPaste, CopyPaste, or DragDrop command.

If you insert a new detail with the help of the New command or delete a few details from the order then the product menu will become out of sync. The selected order is not changed if you perform these operations. The menu will have to be refreshed manually. 

Copy and Cut commands move data to the app clipboard. The data remains there even when you refresh the page or restart the browser and sign in with the user identity. You may want to clear the clipboard after each Paste. 

Paste and Drop do not display a confirmation message and execute instantly. There may be circumstances when the user assent is required.

JavaScript Business Rules

Let’s perfect the syncing of the product menu and provide some pre and post processing when products are pasted or dropped onto the order details.

Create the file ~/app/js/dragdrop.js with the following code. It declares the syncProductMenu() function and the custom client-side business rules for OrderDetails.


The function syncProductMenu()  will locate the product menu on the dashboard and request it to sync once. The default ID of the Dashboard1 data controller instance is view1. The name of the dataview field Products is specified as the argument of syncOnce method. This method will wait for the user interface to stop being busy and sync the data. Subsequent calls to syncOnce will cancel the previous requests to avoid redundant calls. Use this method whenever a dataview on the page requires a data refresh.

The business rule responding to the CopyPaste command will interrupt the execution and display a confirmation. The method $app.confirm returns a promise to the framework. Touch UI will proceed to execute the command if the promise is resolved, which happens when the user agrees to proceed by pressing the OK button in the confirmation prompt. 

The post-processing will sync the product menu after the details are inserted or deleted.

If the copy CopyPaste command has completed successfully, then a custom confirmation with the text describing the clipboard contents is displayed.

The command CutPaste is followed by the clearing of the clipboard.

Advanced Techniques

The default scope of the app clipboard is “global”. Data placed in the clipboard is available on all pages of the app to Paste. You can limit the scope of the clipboard to the current page by setting the option clipboard.scope to “local” in ~/app/touch-settings.json file.

Tags item-paste-Controller and item-drop-Controller make it possible for the user to target individual items in the data view. End users can also paste and drop data by targeting the entire view. There will be situations where the items shall not become the target. Tag view-paste-Controller will make it possible to paste only through the context menu of the dataview. Tag view-drop-Controller will cause the drop target to extend to the entire view when its item is target. 

Cut/Copy/Paste and Drag & Drop are relying on the clipboard to accumulate and perform execution of the CutPaste, CopyPaste, and DragDrop commands. There is no default interpretation for these commands. If your app is relying on the Offline Data Processor to allow transaction input of master-detail records, then the server-side execution of these commands makes little sense. The master-detail data is accumulated and staged by the ODP directly in the WebView. Only the saving of the master record will cause the transaction to be executed on the client. If you want to support the data clipboard and drag & drop with ODP then you will need to write a custom interpretation of the commands in JavaScript.

The live app https://demo.codeontime.com allows cutting and pasting products between supplier and category masters. ODP is enabled on the Categories and Products pages, since their Offline property is set to yes.  ODP is enabled in the "offline" pages loaded in the web browser and also in the disconnected mode when the app is hosted in Cloud On Time. following script implements a custom CutPaste and CopyPaste, which will replace the category or the supplier of the pasted product.


Conclusion

The dashboard can be further enhanced to allow dragging and dropping the order details onto the product menu to provide an alternative method to delete the details.

If the order detail is dropped onto another order, then the detail product can be moved between orders.

The dedicated Products page can provide the Copy and Cut commands. The pasting of the products into Order Details will automatically work on the dashboard page since the clipboard contents are persisted.

If the items in the dataview have a sequential order, then tagging the dataview as item-drag item-drop-Controller will enable the drag & drop movement of items. Use the physical name of the data controller instead of “Controller” in the tag. Implement the business rule to change the item indexes in the response to the DragDrop command.

The consistent user interface of Touch UI makes it possible to create amazing apps with spectacular results that are impossible to achieve with any other tool.