Skip to main content
Skip table of contents

ISAC 3.6

These release notes include details of the New Features, Product Improvements that are added as part of the 3.6 release. In Zinier, we follow a push upgrade process for releases where the latest versions are all released simultaneously.

Web & Server Release Date:

Studio Z & Mobile Release Date

Dynamic Web Pages

  • Pages are designed and created during Development process and the whole definition of components, actions and behaviours are added to the page.

  • They cannot be changed during execution.

  • The common workaround in order to show different behaviours based on the context involves predefining pages where components are hide/show based on configuration

Solution

ISAC 3.6 provides the capability to define the components of a page dynamically as part of the loading process. By introducing this feature pages can change based on the context or functionality, providing flexibility and scalability to the product and solution implementations


Card Component

Provides a way to summarize and display a preview of the related data and trigger actions while clicking on them. It enable the user to configure an easy navigation experience by indexing pages. This component will we an important part for the upcoming version of the Task Builder (Results Side panel).

Sample Json:

JSON
{
    "value2": "@pageContext.value2",
    "value1": "@pageContext.value1",
    "cardStatusValue": "Status",
    "title": "Card Component",
    "type": "cardComponent",
    "progressValue": 90,
    "cardTitle": "title",
    "label1": "@pageContext.label1",
    "label2": "@pageContext.label2",
    "noOfExtraFields": 2,
    "actionOnClick": [
      "@actions.openModal1",
      "@actions.setPageContextAction"
    ],
    "cardBodyText": "Body Text",
    "cardStatusColor": "#EE82EE",
    "thumbnailUrl": "https://z2-nvirginia-edison.s3.amazonaws.com/1646905455238img3.jpg",
    "hoverText": {
      "title": "@lang.['xyz','Card Component']"
    }
  }

Map Component 2.0

ISAC 3.6 will introduce new capabilities for the map component:

  • Ability to draw routes between points, visualize the daily route of a technician, evaluate scheduler results.

  • Ability to draw segments on the map, visualize sites of the segment type based on a list of points to be visit by a technician.

  • Auto refresh, experience “real-time” updates on technicians location, define how often to refresh the map

  • Map filter, perform a specific search based on a particular date or technician, look for particular details on tasks and filter the ones you need.

More details here: Map Component


Server

Excel File Node

Capability to generate an excel file from a Workflow. It consist in a new Excel node that will carry the information to be added to the an excel file following a json template.

More Details:

Node Sample

JSON
{
    "name": "excel node",
    "description": "Node to generate excel template",
    "inputVarMap": {
      "async": "async", // optional - default - false
      "templateData": "data" // Mandatory
    },
    "outputVarMap": {
      "url": "data"
    },
    "nodeType": "EXCEL"
  }

Template Data Sample

JSON
{
    "metaData": {
        "filename": "RG-New-WorkOrder-main", // Mandatory - name for the file
        "template_filename": "RG-base.xlsx",
        "sheetName": "RG123.xlsx", // sheetName if available at service
        "sheetUrl": "http://example-bucket.s3-website.us-west-2.amazonaws.com/photo.jpg" // sheetUrl of template in bucket
        // sheetUrl or sheetName one of them should be present
        "sheetTitles": ["sheet1"] // existing sheet names from the excel template. // mandatory
    },
    // sheetData - mandatory
    "sheetData": [
        // each json represents data for a single sheet
        {
            "sheetTitle": "Day 2", // set sheet name
            "sheetIdentifier": "sheet1", // existing sheet to use for the data
            "images": {
                "D20": {
                        "url": "https://aws-filei-url",
                        "height": 200, // in pixels
                        "width": 200 //  in pixels
                      }
            },
            // data for the sheet - refer actual template cells
            "data": {
                "D1": "Black & Veacth",
                "D2": "MROWP032269",
                "D3": "14641460",
                "D4": "274527",
                "D6": 1,
                "D7": "03/05/22",
                "D8": "Yes",
                "D9": 2,
                "B12": "Alan Bayless",
                "F12": 234114,
                "B13": "Harlen Feltne",
                "F13": 234115,
                "B14": "Harlen",
                "F14": 244118,
            },
        }
    ],
	"global_validations": {
		"D8": {
			"type": "list",
			"formula": "Yes,No"
		},
		"D9": {
			"type": "list",
			"formula": "1,2,3,4,5,6,7,8,9,10"
		}
    }
}


Importing Z Rules

Introducing a new capability to import ZRules into a process node. Allowing to have reusable javascript code among the Z Rules and enabling them to be used as libraries. Creating Utility libraries for date and time formatting, among other common calculations in workflow execution

CODE
{
    "connectors": [
      {
        "exitPortType": "NextStep",
        "nodeId": "end"
      }
    ],
    "contextChangePermitted": true,
    "name": "processnTayP",
    "description": "Use this for processing data in workflow",
    "processRule": "@testingrule",
    "id": "processnTayP",
    "position": {
      "x": 214.75,
      "y": -13.0234375
    },
    "nodeType": "PROCESS",
    "importableRuleIds": [
      "replaceAbc"
    ]
  }

Studio Z

All studio Z Features are available to all org when the release is live, no configuration is needed.


Mobile

New App Modules Launch Menu

In order to access app modules the mobile app provides a '+' button, with the condition that if there is a single element on the list of modules the button will redirect you automatically to the first and only module. Unfortunately, for a new user there is no explicit way to know that in order to find the access to the first module (Inventory) this is the only way.

Solution

Provide visibility to the user on the available mobile modules by introducing a launch menu from a new bottom navigation bar. This will include a Task tab and an Apps tab that the user could use to navigate between both UIs.

Multi-image Upload

Often, field technicians face situations were they need to upload large amounts of pictures taken in the field. Previously, we only offered an option to do it one by one, so it became a tedious process for the users to complete their work.

Solution

Implement a new component that would enable users to upload multiple images with one action.

Multi-Files Download

In some situations field technicians require to download several files in order to complete their work, these files could be documents that they need to update or go through, guides, manual, etc. For situations where the amount of files is quite big, we did not had a nice User Experience.

Solution

Implement a new component that would enable users to download multiple files with one action.

Live Datagrid

Previously, our tables or datagrids used to be populated with records that were fetched during the execution of the Mobile Workflow. This result on a limitation once new functionalities were being build on the Solution side (Inventory), where the was a need to keep the records on the datagrid in sync with the server.

In order to cover this product gap the datagrid components were enhanced to allow the, configure a call to an API to fetches the latest version of objects to be displayed on the component.

Now, the datagrid is able to support queries and workflows executed by the server and keep the data in sync.

Fetching records through event API Call

Fetching records through an external API

JSON
{
	"allowDelete": 0,
	"endColumn": 11,
	"indexName": "",
	"columns": [
		{
			"col": 1,
			"name": "{%status}",
			"row": 1,
			"key": "Status"
		}
	],
	"editable": 1,
	"index": 3,
	"infiniteScroll": true/false,
	"type": "datagrid",
	"title": "Status Grid",
	"isAutoSave": false,
	"required": 0,
	"editRowPageId": "",
	"startColumn": 0,
	"addRowPageId": "",
	"disableAdd": true,
	"id": "status",
	"value": "@pageContext.statusData",
	"source": "api/default",
	"url": "/event/start",
	"apiObject":{
		"data": [
			{
				"eventId": "multiActionSyncTo-IR-TO-RO-Event",
				"contextVar": {
					"inventoryRequestData": "@pageContext.inventoryRequestData",
					"irDataVersion": "@pageContext.irDataVersion",
					"transferOrderData": "@pageContext.transferOrderData",
					"toDataVersion": "@pageContext.toDataVersion",
					"returnOrderData": "@pageContext.returnOrderData",
					"roDataVersion": "@pageContext.roDataVersion",
					"truckAssignedToUser": "@pageContext.truckAssignedToUser",
					"currentUserId": "@pageContext.__sys__loggedIn_UserId"
				},
				"batchSize": 50, //Should come from Mobile
        "batchNumber": 1 //Should come from Mobile
			}
		]
	},
	"totalCount": "@responseData.count",
	"responseVariable": "@responseData.data"
}

JSON
{"pageContext"{
	"datagridId":{
		"prevObj":{"externalBatchSize" : , "externalBatchNumber": },
		"batchNumber": "",
		"batchSize": "",
		"searchText": ""
	}
}}

"source": "externalAPI",
"header": "@pageContext.headerObj",
"callType": "GET/POST/DELETE/PUT",
"addToPrevObj":{
	"var1": {
		return (data[0].resp1)
	}
},
"preProcessRuleForBatch": {
		"externalBatchSize": "function(pageContext):{return pageContext.batchSize}", // The previous values should also be avilable
		"externalBatchNumber": "function(pageContext):{return pageContext.batchNumber - 1}" // The previous values should also be avilable prevObj {"externalBatchSize" : , "externalBatchNumber": }
	},
"apiObject":{
	"data": [
		{
			"eventId": "multiActionSyncTo-IR-TO-RO-Event",
			"contextVar": {
				"inventoryRequestData": "@pageContext.inventoryRequestData",
				"irDataVersion": "@pageContext.irDataVersion",
				"transferOrderData": "@pageContext.transferOrderData",
				"toDataVersion": "@pageContext.toDataVersion",
				"returnOrderData": "@pageContext.returnOrderData",
				"roDataVersion": "@pageContext.roDataVersion",
				"truckAssignedToUser": "@pageContext.truckAssignedToUser",
				"currentUserId": "@pageContext.__sys__loggedIn_UserId"
			},
			"externalBatchSize": "@preProcessRuleForBatch.externalBatchSize", //Should come from Mobile
			"externalBatchSize": "@preProcessRuleForBatch.externalBatchNumber", //Should come from Mobile
		}
	]
}

Dynamic Page Content

Mobile Workflows and pages have to be built on a Static manner, these could not changed depending on the context were the user was working.

In order to achieve different UIs based on the users context, we needed prebuilt the pages and show and hide components and workflow actions and this was directly limiting flexibility.

With the dynamic page content support, we want to allow to configure components and workflow actions on the page in order to give more flexibility to the business user.

Other Issues

  1. Unnecessary code on a page

  2. More difficult to upgrade/change pages in mobile workflows

  3. Features cannot be decoupled, we're aiming to have modularised workflows, the current architecture needs to be enhanced in order to achieve this

Solution
Introduce the support for content or page definition to be changed and loaded dynamically.

Provide a new component capable of rendering a list of sub components as part of its definition

JSON
{
  "instance_nav": false,
  "footer": {},
  "children": [],
  "jslib": "@subContext.jslib",
  "header": {
    "leftButton": {
      "id": "aHeadLeft",
      "title": "@subContext.title",
      "enabled": true
    },
    "rightButton": {
      "image": "@icon.kebabMenuWhite",
      "action": "openDropdown",
      "id": "aHeadRight",
      "list": "@subContext.wfActions",
      "title": "Next",
      "enabled": false
    }
  },
  "id": "subPagesTbWF",
  "title": "@subContext.title",
  "cols": [
    {
      "name": "c1",
      "body": [
        {
          "endColumn": 11,
          "hidden": false,
          "startColumn": 0,
          "index": 1,
          "id": "dynamicInput",
          "type": "dynamic",
          "value": "@subContext.components"
        },
        {
          "endColumn": 11,
          "buttonType": "primary",
          "startColumn": 0,
          "index": 2,
          "actionOnClick": {
            "beforeUpdate": [
              {
                "updateKeys": [
                  "subContext.progresPercentValue"
                ],
                "jslib": "function(pageContext) { let filledValueCount = 0, totalFeildCount = 0; if (typeof pageContext.subContext !== 'undefined' && pageContext.subContext !== '') { if (typeof pageContext.subContext.progresPercentRequired !== 'undefined' && pageContext.subContext.progresPercentRequired !== '' && pageContext.subContext.progresPercentRequired == true) { if (typeof pageContext.subContext.components !== 'undefined' && pageContext.subContext.components !== '') { totalFeildCount = pageContext.subContext.components.length; pageContext.subContext.components.forEach(function(comp) { var key = comp.id; if (pageContext.taskBuilderMap.hasOwnProperty(key) && typeof pageContext.taskBuilderMap[key] !== 'undefined' && pageContext.taskBuilderMap[key] !== '') { if (typeof pageContext.taskBuilderMap[key] === 'object' && Object.getPrototypeOf(pageContext.taskBuilderMap[key]).isPrototypeOf(Object)) { if (typeof pageContext.taskBuilderMap[key]['media'] !== 'undefined' && pageContext.taskBuilderMap[key]['media'] !== '') { filledValueCount++; } } else if (Array.isArray(pageContext.taskBuilderMap[key]) && pageContext.taskBuilderMap[key].length > 0) { if ((typeof pageContext.taskBuilderMap[key]['0']['photoDetails'] !== 'undefined' && typeof pageContext.taskBuilderMap[key]['0']['photoDetails']['media'] !== 'undefined' && pageContext.taskBuilderMap[key]['0']['photoDetails']['media'] !== '') || (typeof pageContext.taskBuilderMap[key]['0']['videoDetails'] !== 'undefined' && typeof pageContext.taskBuilderMap[key]['0']['videoDetails']['media'] !== 'undefined' && pageContext.taskBuilderMap[key]['0']['videoDetails']['media'] !== '')) { filledValueCount++; } } else { filledValueCount++; } } }); } } else { return ''; } } if (Number(totalFeildCount) > 0) { return (filledValueCount / totalFeildCount); } else { return ''; } }"
              }
            ]
          },
          "id": "saveProgress",
          "title": "{%save}",
          "type": "button",
          "enabled": true,
          "required": false
        }
      ],
      "span": 1
    }
  ]
}

Multi-page support

Zinier mobile application has been enhanced in order to provide a way for solution developers to define page nodes on a Mobile Workflow including Multi-page support. As a result these are the benefits from this new improvement:

  • Dynamically define the sequence of pages to be presented to a field technician. These pages can be defined during the execution of the workflow or preconfigured as part of a solution.

  • Reusing a particular workflow by providing different user experience and reduce the amount of maintenance and updates to other versions.

  • Simplifying the structure of a workflow by decoupling the UI from the processing nodes.

  • Introducing changes on UI or UX without the need of deploying a new solution

This new capability is key to the next to be released version of the No Code Task Builder

Mobile page structure

JSON
{
  "multiPageDef": "@pageContext.dynamicPages"
}
JSON
{
    "1": {
        "instance_nav": false,
        "footer": {
            "leftButton": {
                "id": "aFootLeft",
                "title": "Back",
                "enabled": true
            },
            "rightButton": {
                "id": "aFootRight",
                "title": "Next",
                "enabled": true
            }
        },
        "header": {
            "leftButton": {
                "id": "aHeadLeft",
                "title": "X",
                "enabled": true
            },
            "rightButton": {
                "image": "@icon.kebabMenuWhite",
                "action": "openDropdown",
                "id": "aHeadRight",
                "list": [],
                "title": "Next",
                "enabled": false
            }
        },
        "id": "page1",
        "title": "Page 1",
        "cols": [
            {
                "name": "c1",
                "body": [
                    {
                        "endColumn": 11,
                        "hidden": false,
                        "lng": "77.69",
                        "heading": "Label",
                        "index": 0,
                        "type": "mapaddress",
                        "title": "Placeholder",
                        "enabled": true,
                        "required": false,
                        "startColumn": 0,
                        "id": "mapaddress29",
                        "capturedTime": "",
                        "locationCoordinates": "",
                        "radius": 50,
                        "value": "@pageContext.taskBuilderMap.mapaddress29",
                        "lat": "12.93"
                    },
                    {
                        "endColumn": 11,
                        "hidden": false,
                        "index": 1,
                        "type": "barcode",
                        "title": "Label",
                        "enabled": true,
                        "required": false,
                        "startColumn": 0,
                        "disabled": true,
                        "id": "barcode302",
                        "capturedTime": "",
                        "locationCoordinates": "",
                        "value": "@pageContext.taskBuilderMap.barcode302",
                        "placeHolder": "Placeholder"
                    }
                ],
                "span": 1
            }
        ]
    }
}
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.