Version: 20.05

Migration from v19.11 to v20.05

Workspaces used to be a fully integrated Frontend and Backend system. In Workspaces 20.05, by using Open UX CLI to deploy the Frontend as a Joruney Manager Form we were able to decouple Workspaces API from the client side application. This approach allows us to make the Frontend more customizable, but also preserved the best parts of Workspaces 19.11 - easy to get started, configurable, i18n, and much more.

Now that Workspaces Frontend can be deployed as a form, multiple versioned Workspaces Clients can be deployed and live along-side within the same Journey Manager Server.

Beyond that, Workspaces 20.05 introduces many new features: Space Configurations were moved into the code and converted to TypeScript, making it easy for developers to get instant feedback from their IDE, reuse and extend configs, use local fixtures, integrate into CI/CD pipelines and even run their own Workspaces Client without the need of a Journey Manager Server.

While our main focus will still be supporting Architects with feature requests development, from this point foward, we are also planning to work with them to create, manage and share reusable templates for different kind of solutions.

In terms of setting up the new development environment, we have created a new Guide section called Form Development.

Once the default template has been setup, to migrate from v19.11 to v20.05 there are a few minor changes needed, they can be done on the following order:

spaces

Space configurations are no longer part of Journey Manager properties, Instead they need to be moved into the codebase under src/configs and converted into TypeScript by running npm run prettier on the root folder.

Use the following steps to copy the old JSON properties.

  • Copy the src/configs/defaultfolder, and rename it to src/configs/custom.
  • Depending on how many space configs you need, update src/configs/custom/index.ts to import those only.
  • Update src/configs/custom/global.ts with Global.json properties. Note that the TypeScript version contains a function that returns an object. Global.json data can replace the returning object. By running npm run prettier on the root folder, all your JSON properties will get updated to TypeScript properties. Now, do the same with the rest of the spaces.
  • You should now have the same number of files as your JM space properties plus an index file, which groups all the space configs that Workspaces is going to use. There will be some TypeScript errors indicating which properties need to be updated.

Let's say you have Global and Process JSON properties in JM. If you want to move them within the new Workspaces 20.05, copy their content into two new files, src/configs/custom/global.ts and src/configs/custom/process.ts, and create another new file called src/configs/custom/index.ts, that exports them as default.

  • After copying Global JSON into the file, remove spaces and currentSpace from src/configs/custom/global.ts.

src/configs/custom/global.ts

export const globalConfig = ({ date, currentUser }: any): Config => ({
...
<Global.json>
...
});
  • The label, icon and permissions for each 'spaces' property needs to be moved into the corresponding space now. Note that title and `value can be removed from the current spaces definition.

src/configs/custom/process.ts

export const processConfig = ({ date, currentUser }: any): Config => ({
...
<Process.json>
...
label: 'Process',
icon: 'BallotOutlined',
permissions: {
type: 'role',
value: ['Processing Staff', 'Work Spaces Staff'],
},
...
});

src/configs/custom/Index.ts

import global from './global';
import process from './process';
const spaces = [process];
export default {
global,
spaces,
};

Don't forget to change the config path from ./config/development to ./config/custom on src/index.jsx.

src/index.jsx

import 'dayjs/locale/en';
import App from '@transact-open-ux/workspaces/dist/App';
import configs from './configs/custom';
import messages from './locales/en';
const root = document.getElementById('root');
export default async function init() {
if (process.env.NODE_ENV === 'development') {
const { default: fixtures } = await import('./fixtures/development');
const { default: makeServer } = await import('@transact-open-ux/workspaces/dist/Server');
// start server
makeServer({
fixtures,
});
}
// start only the cleint if production
App(root, configs, messages, 'en');
}
init();

Once the content was copied, you will see a few errors in your IDE, that's typescript reporting wrong code formatting for the configs. In order to fix that, all you need to do is to run the following command on the root dir.

npm run prettier

Now you can continue to fix the pending errors reported by TypeScript.

locales

  • locales and currentLocale configs are no longer needed, and should be removed from global.ts. The new Workspaces 20.05 locales have been moved into the codebase. Only one locale at a time is supported, which can still be configured in index.ts. importing the required dayjs language pack and adding the corresponding messages file into the root App.
import 'dayjs/locale/en';
import App from '@transact-open-ux/workspaces/dist/App';
import configs from './configs/development';
import messages from './locales/en';
const root = document.getElementById('root');
export default async function init() {
if (process.env.NODE_ENV === 'development') {
const { default: fixtures } = await import('./fixtures/development');
const { default: makeServer } = await import('@transact-open-ux/workspaces/dist/Server');
// start server
makeServer({
fixtures,
});
}
// start only the cleint if production
App(root, configs, messages, 'en');
}
init();

filters

  • Filter of type picker was removed and split into datepicker and daterangepicker to allow single date selection. If you don't need single date selection, you can replace picker occurences with daterangepicker.

On the example below $appAge renders DateRangePicker component.

{
...
"mappings": {
...
"$appAge": {
"label": "App age",
"icon": "EventOutlined",
"dataIndex": "job.timeCreated",
"type": "date",
"format": "duration",
"sorter": true,
"filter": {
"type": "picker",
"options": {
"minDate": "{{ date('1 month ago') }}",
"maxDate": "{{ date('now') }}"
}
}
},
...
},
...
}

By changing filter type to datepicker, the component rendered will be a single DatePicker.

{
...
mappings: {
...
$appAge: {
label: 'App age',
icon: 'EventOutlined',
dataIndex: 'job.timeCreated',
type: 'date',
format: 'duration',
sorter: true,
filter: {
type: 'datepicker',
options: {
minDate: date('1 month ago'),
maxDate: date('now'),
},
},
},
},
...
}

expressions

  • With the introduction of TypeScript, {{ currentUser }} and {{ date('today') }} expressions were converted to function parameters, so there is no need to wrap them into strings with brackets.

Using the following example

{
...
"viees": [
...
{
"label": "Assigned to me",
"properties": [
"$appId",
"$primaryName",
"$product",
"$appAge",
"$dateOfBirth",
"$currentQueue",
"$currentTask",
"$taskCreated",
"$assigned",
"$formLastModified"
],
"filterBy": {
"$assigned": ["{{ currentUser }}"]
},
"sortOrder": "desc",
"sortBy": "$appAge"
},
...
],
"globalFilters": {
"GroupName": {
"label": "Queues",
"options": ["Error Review", "Fraud Review", "Manual Review"],
"value": "All",
},
"DateCreated": {
"label": "Created Date",
"value": ["{{ date('4 weeks ago') }}", "{{ date('now') }}"],
}
},
...
}

Refactored version should look as below

export const processConfig = ({ date, currentUser }: any): Config => ({
...
viees: [
...
{
label: 'Assigned to me',
properties: [
'$appId',
'$primaryName',
'$product',
'$appAge',
'$dateOfBirth',
'$currentQueue',
'$currentTask',
'$taskCreated',
'$assigned',
'$formLastModified',
],
filterBy: {
$assigned: [currentUser],
},
sortOrder: 'desc',
sortBy: '$appAge',
},
...
],
globalFilters: {
GroupName: {
label: 'Queues',
options: ['Error Review', 'Fraud Review', 'Manual Review'],
value: 'All',
},
DateCreated: {
label: 'Created Date',
value: [date('4 weeks ago'), date('now')],
},
},
...
});

actions

  • action have been split into jobActions and txnActions respectively. You can check the example below or refer to the actions section under Current Space configuration.

Say you had the following configuration for your space.

{
...
"actions": {
"Claim": {
"label": "Claim"
},
"Release": {
"label": "Release"
},
"Decision": {
"label": "Decision"
},
"Receipt": {
"label": "Receipt",
"permissions": {
"type": "group",
"value": ["Manual Review"]
}
},
},
...
}

After refactoring and converting to TypeScript, it looks like this:

{
...
txnActions: {
Claim: {
label: 'Claim',
},
Release: {
label: 'Release',
},
Decision: {
label: 'Decision',
},
},
jobActions: {
Receipt: {
label: 'Receipt',
permissions: {
type: 'group',
value: ['Manual Review'],
},
},
},
...
}