|
|
# Table of Content
|
|
|
|
|
|
Shell / Main Window:
|
|
|
* [How to customize toolbar and menu](#how-to-customize-toolbar-and-menu)
|
|
|
|
|
|
Navigation Shortcuts:
|
|
|
* [`cmpInitConfig` vs `customParams`](#cmpinitconfig-vs-customparams)
|
|
|
* [How to configure a filter for grid rows](#how-to-configure-a-filter-for-grid-rows)
|
|
|
|
|
|
Entity Grid Panel:
|
|
|
* [How to customize grid columns](#how-to-customize-grid-columns)
|
|
|
* [How to customize a form, showed for a grid item](#how-to-customize-a-form-showed-for-a-grid-item)
|
|
|
* [How to perform deep customization of grid](#how-to-perform-deep-customization-of-grid)
|
|
|
* [How to control availability of actions in grid](#how-to-control-availability-of-actions-in-grid)
|
|
|
* [How to open grid item in tab instead of popup](#how-to-open-grid-item-in-tab-instead-of-popup)
|
|
|
|
|
|
Base Panel:
|
|
|
* [How to add custom buttons into toolbar](#how-to-add-custom-buttons-into-toolbar)
|
|
|
* [How to hide some actions from the form's toolbar](#how-to-hide-some-actions-from-the-forms-toolbar)
|
|
|
* [How to close the UB form](#how-to-close-the-ub-form)
|
|
|
* [How to hook up before save on an entity form](#how-to-hook-up-before-save-on-an-entity-form)
|
|
|
* [How to remove document field button from toolbar](#how-to-remove-document-field-button-from-toolbar)
|
|
|
* [How to control actions availability](#how-to-control-actions-availability)
|
|
|
* [How to dymanically add UBDetailGrid to a form](#how-to-dymanically-add-ubdetailgrid-to-a-form)
|
|
|
|
|
|
Custom Forms and Controls:
|
|
|
* [My custom form does not work](#my-custom-form-does-not-work)
|
|
|
* [How to create a UB enum control](#how-to-create-a-ub-enum-control)
|
|
|
|
|
|
|
|
|
# Shell / Main Window
|
|
|
|
|
|
## How to customize toolbar and menu
|
|
|
|
|
|
It is possible to customize main window toolbar.
|
|
|
The best place to do that is `initModel.js` script inside a project model. If the project includes only external models, create one for the project and include script there.
|
|
|
|
|
|
Global `$App` object has `buildMainMenu` event.
|
|
|
|
|
|
The is, for example, how the default menu is built:
|
|
|
```javascript
|
|
|
// Create default toolbar menu
|
|
|
$App.on('buildMainMenu', function(items) {
|
|
|
items.push(
|
|
|
Ext.create('UB.view.ToolbarMenuButton'),
|
|
|
{
|
|
|
xtype: "button",
|
|
|
iconCls: "iconLogo",
|
|
|
tooltip: UB.i18n('informatsiyaOPrilozhenii')
|
|
|
},
|
|
|
"-",
|
|
|
Ext.create('UB.view.ToolbarMenu'),
|
|
|
"->",
|
|
|
Ext.create('UB.view.ToolbarUser')
|
|
|
);
|
|
|
});
|
|
|
```
|
|
|
|
|
|
It's better to add only elements inherited from `UB.view.ToolbarWidget`.
|
|
|
UnityBase come with several widgets:
|
|
|
* `UB.view.ToolbarMenuButton` - left-side menu controller. This is leftmost item by default.
|
|
|
* `UB.view.ToolbarUser` - user related menu. This is rightmost menu by default.
|
|
|
* `UB.view.ToolbarMenu` - left-side menu representation in the main toolbar.
|
|
|
|
|
|
To create your own widget - extend `UB.view.ToolbarWidget`.
|
|
|
Example: widget with image
|
|
|
```javascript
|
|
|
Ext.define('MyWidget', {
|
|
|
extend: 'UB.view.ToolbarWidget',
|
|
|
items: {
|
|
|
type: 'image',
|
|
|
src: 'images/loginPictute.png',
|
|
|
height: 38,
|
|
|
width: 120
|
|
|
}
|
|
|
});
|
|
|
```
|
|
|
|
|
|
Example: insert your widget after 2-nd element in the main toolbar:
|
|
|
```javascript
|
|
|
$App.on('buildMainMenu', function(items){
|
|
|
items.splice(2, 0, Ext.create('MyWidget'));
|
|
|
});
|
|
|
```
|
|
|
|
|
|
Example: remove toolbar menu and add picture in the center of toolbar:
|
|
|
```javascript
|
|
|
$App.on('buildMainMenu', function(items) {
|
|
|
items.splice(2, 1, ['->', Ext.create('MyWidget') '->']); // Remove 2nd menu item and add our widget
|
|
|
});
|
|
|
```
|
|
|
|
|
|
> The overall height of main toolbar space, accessible for widget is 38.
|
|
|
|
|
|
Also, there is an event `desktopChanged`, which allows some more advanced customization of desktop:
|
|
|
```javascript
|
|
|
$App.on({
|
|
|
desktopChanged: function(items) {
|
|
|
$App.viewport.topPanel.height = 200; // Change top toolbar height to 200
|
|
|
$App.viewport.updateLayout();
|
|
|
},
|
|
|
single: true
|
|
|
});
|
|
|
```
|
|
|
|
|
|
But such actions shall be done with care - make sure it won't break the desktop.
|
|
|
|
|
|
|
|
|
|
|
|
# Shortcuts
|
|
|
|
|
|
## `cmpInitConfig` vs `customParams`
|
|
|
|
|
|
Always prefer `cmpInitConfig` over `customParams`, because:
|
|
|
* It is possible to set a default value
|
|
|
* It is possible to describe the config option via jsdocs
|
|
|
* It is possible to use `cmpInitConfig` and specify `customParams` option, which would basically do the same as `customParams`.
|
|
|
|
|
|
It looks like `customParams` is an obsolete mechanism of passing properties into forms from commands and
|
|
|
shortcuts.
|
|
|
|
|
|
## How to configure a filter for grid rows
|
|
|
|
|
|
Use `whereList` parameter of entity query.
|
|
|
|
|
|
Example:
|
|
|
```json
|
|
|
{
|
|
|
"cmdType": "showList",
|
|
|
"cmdData": {
|
|
|
"params": [
|
|
|
{
|
|
|
"entity": "uba_user",
|
|
|
"method": "select",
|
|
|
"fieldList": [
|
|
|
"disabled",
|
|
|
"isPending",
|
|
|
"name",
|
|
|
"firstName",
|
|
|
"lastName"
|
|
|
],
|
|
|
"whereList": {
|
|
|
"byDisabled": {
|
|
|
"expression": "[disabled]",
|
|
|
"condition": "equal",
|
|
|
"values": {"v0": 0}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
|
|
|
# Entity Grid Panel
|
|
|
|
|
|
## How to customize grid columns
|
|
|
|
|
|
For UB `showList` forms, which just show `UB.view.EntityGridPanel`, it is possible to set in `fieldList`
|
|
|
an object instead of string.
|
|
|
The object supports the following parameters:
|
|
|
* name
|
|
|
* visibility
|
|
|
* description
|
|
|
* format
|
|
|
|
|
|
Example - defining property `entityConfig` for a grid - add hidden columns:
|
|
|
```
|
|
|
entityConfig: {
|
|
|
method: 'select',
|
|
|
fieldList: [
|
|
|
'subjectID.name',
|
|
|
{name: 'objectID', visibility: false},
|
|
|
{name: 'subjectID', visibility: false},
|
|
|
{name: 'subjectID.sType', visibility: false},
|
|
|
'role'
|
|
|
]
|
|
|
},
|
|
|
```
|
|
|
|
|
|
`format` function for a field is a custom rendered. Here is an example of it:
|
|
|
```
|
|
|
/**
|
|
|
* Format column "subject name" - add icon depending on subject type.
|
|
|
* @param {string} text Value of column
|
|
|
* @param {object} columnInstance
|
|
|
* @return {string}
|
|
|
* @private
|
|
|
*/
|
|
|
formatSubjectName: function (text, columnInstance) {
|
|
|
var t = columnInstance.record.data['subjectID.sType'];
|
|
|
var iconCls = UB.bpm.ux.ParticipantsGrid.subjectTypeIcons[t] || '';
|
|
|
return '<span class="fa fa-fw ' + iconCls + '"></span><span style="padding-left: 5px;">' +
|
|
|
_.escape(text) + '</span>';
|
|
|
}
|
|
|
```
|
|
|
Do not forget to encode rendered text to prevent XSS attacks.
|
|
|
|
|
|
## How to customize a form, showed for a grid item
|
|
|
|
|
|
The `showList` command allows to customize an action to be taken on opening item's form.
|
|
|
In order to do that, specify `formCode` attribute for the command. The attribute shall be a function
|
|
|
(yes, command is NOT a JSON!).
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"cmdType": "showList",
|
|
|
"cmdData": {
|
|
|
"params": [
|
|
|
{
|
|
|
"entity": "bpm_Process",
|
|
|
"method": "select",
|
|
|
"fieldList": ["processDefinitionID","status","startDate","endDate","startUserID","businessKey"]
|
|
|
}
|
|
|
],
|
|
|
"formCode": function (entity, instanceID, onFormCodeRun, ubCommand) {
|
|
|
// TODO:
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
Note that you are responsible how for calling a window.
|
|
|
The `formCode` function has 4 arguments:
|
|
|
* `entity` - name of entity
|
|
|
* `instanceID` - ID of object to show a form to
|
|
|
* `onFormCodeRun` - just ignore it, it supposed to be a callback showing a form, but it just does not work
|
|
|
* `ubCommand` - the command object
|
|
|
|
|
|
In order to show a form, use the following code snippet as an example:
|
|
|
```javascript
|
|
|
$App.doCommand({
|
|
|
cmdType: UB.core.UBCommand.commandType.showForm,
|
|
|
formCode: 'bpm_ProcessDefinition-diagram',
|
|
|
entity: 'bpm_ProcessDefinition',
|
|
|
instanceID: this.record.get('processID.processDefinitionID')
|
|
|
});
|
|
|
```
|
|
|
|
|
|
## How to perform deep customization of grid
|
|
|
|
|
|
The best way to do it is to create a new ExtJS component, nested from one of the following:
|
|
|
* `UB.view.EntityGridPanel` - if you are looking for customization of entity grid
|
|
|
* `UB.ux.UBDetailGrid` - in case you need to customize a detail grid
|
|
|
|
|
|
This would allow to customize behavior in much deeper degree than it is available via config properties or event handlers.
|
|
|
|
|
|
```
|
|
|
/**
|
|
|
* The participants detail grid. Suitable to be used in forms for entities, which use "Participants" mixin.
|
|
|
*/
|
|
|
Ext.define('UB.bpm.ux.ParticipantsGrid', {
|
|
|
extend: 'UB.ux.UBDetailGrid',
|
|
|
alias: 'widget.ub-participants-grid',
|
|
|
|
|
|
...
|
|
|
});
|
|
|
```
|
|
|
|
|
|
## How to control availability of actions in grid
|
|
|
|
|
|
`EntityGridPanel` does not provide standard mechanism to control actions availability in event driven or callback driven way. But it is possible to inherit own component from `EntityGridPanel` and override the method `setupActions` and after the call of parent method perform there any additional logic related to actions availability:
|
|
|
|
|
|
```
|
|
|
setupActions: function () {
|
|
|
this.callParent(arguments);
|
|
|
this.actions[UB.view.EntityGridPanel.actionId.addNew].setHidden(
|
|
|
!this.masterEntity.haveAccessToMethod(UB.bpm.ux.ParticipantsGrid.methodNames.ADD_PARTICIPANT)
|
|
|
);
|
|
|
this.actions[UB.view.EntityGridPanel.actionId.addNew].setDisabled(
|
|
|
!this.masterEntity.haveAccessToMethod(UB.bpm.ux.ParticipantsGrid.methodNames.ADD_PARTICIPANT)
|
|
|
);
|
|
|
this.actions[UB.view.EntityGridPanel.actionId.del].setHidden(
|
|
|
!this.masterEntity.haveAccessToMethod(UB.bpm.ux.ParticipantsGrid.methodNames.REMOVE_PARTICIPANT)
|
|
|
);
|
|
|
},
|
|
|
```
|
|
|
Note that the same in form is done in method `updateActions`.
|
|
|
|
|
|
Also, there are the following methods are available in `EntityGridPanel`, which expose control over actions availability and visibility:
|
|
|
* `hideAction`
|
|
|
* `showAction`
|
|
|
* `enableAction`
|
|
|
* `disableAction`
|
|
|
|
|
|
In order to control availability of actions depending on currently selected row, subscribe to `selectionchange` event:
|
|
|
```
|
|
|
grid.on('selectionchange', this._onSelectionChange, this);
|
|
|
```
|
|
|
|
|
|
In the handler, control the actions:
|
|
|
```
|
|
|
_onSelectionChange: function (selectionModel, selected, eOpts) {
|
|
|
if (selected.length >= 1) {
|
|
|
var data = selected[0].data,
|
|
|
isStandalone = data['processID'] == null;
|
|
|
|
|
|
var grid = this.queryById('grid');
|
|
|
if (isStandalone) {
|
|
|
grid.enableAction(UB.view.EntityGridPanel.actionId.del);
|
|
|
} else {
|
|
|
grid.disableAction(UB.view.EntityGridPanel.actionId.del);
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
```
|
|
|
|
|
|
One advanced subcase of that is control of action availability, basing on ELS. If a user may not to do a server call (no permissions) - it is best to hide an action on client, so that user won't get error messages.
|
|
|
|
|
|
In order to do that, use `entity.haveAccessToMethod` function to deterine, if user actually has access to an entity method:
|
|
|
```
|
|
|
this.actions[UB.view.EntityGridPanel.actionId.addNew].setHidden(
|
|
|
!this.entity.haveAccessToMethod('myCustomAddMethod')
|
|
|
);
|
|
|
```
|
|
|
|
|
|
## How to open grid item in tab instead of popup
|
|
|
|
|
|
For grids, which are places on a form (and not grids opened from navigation shortcut), items are by default opened in a popup, as a model window. That is right solution for cases, when it is allowed to add new items or to edit items.
|
|
|
But sometimes, you might need to open a view form for large entity. And this is more suitable to do in a separate tab.
|
|
|
|
|
|
In order to do that, you need to override method `openForm`, like the following:
|
|
|
```javascript
|
|
|
openForm: function (eOpts) {
|
|
|
$App.doCommand({
|
|
|
cmdType: 'showForm',
|
|
|
entity: 'bpm_Process',
|
|
|
formCode: 'bpm_Process',
|
|
|
instanceID: eOpts.instanceID,
|
|
|
target: $App.viewport.centralPanel,
|
|
|
tabId: 'bpm_Process' + eOpts.instanceID,
|
|
|
sender: me
|
|
|
});
|
|
|
},
|
|
|
```
|
|
|
|
|
|
It could be done in an inherited compoment, or it could be juse a configuration property of `ubdetailgrid` component.
|
|
|
|
|
|
|
|
|
# Base Panel
|
|
|
|
|
|
## How to add custom buttons into toolbar
|
|
|
|
|
|
Toolbar component could be found using the following query: `tbar = this.query('[ubID=mainToolbar]')[0]`.
|
|
|
It could be manipulated during form initialization, for example, inside `initUBComponent` method add the following code:
|
|
|
```
|
|
|
var me = this,
|
|
|
tbar = this.query('[ubID=mainToolbar]')[0],
|
|
|
allActions = tbar.query('[menuId=AllActions]')[0];
|
|
|
|
|
|
// ...
|
|
|
tbar.insert(tbar.items.length - 2, '-');
|
|
|
tbar.insert(tbar.items.length - 2, {
|
|
|
xtype: 'button',
|
|
|
text: UB.i18n('bpm_action_reopen'),
|
|
|
handler: me.reopen.bind(me)
|
|
|
});
|
|
|
```
|
|
|
|
|
|
|
|
|
## How to hide some actions from the form's toolbar
|
|
|
|
|
|
For auto forms, specify an array of actions to hide in `hideActions` config property:
|
|
|
```
|
|
|
hideActions: [
|
|
|
UB.view.BasePanel.actionId.fDelete
|
|
|
],
|
|
|
```
|
|
|
The `UB.view.BasePanel.actionId` object contains list of available actions.
|
|
|
|
|
|
|
|
|
## How to close the UB form
|
|
|
|
|
|
For auto forms, just use `this.closeWindow();`, but for custom forms, inherited for some Ext component
|
|
|
(not UB component like `BasePanel`), opened as popup window, close the parent component:
|
|
|
```javascript
|
|
|
this.ownerCt.close();
|
|
|
```
|
|
|
|
|
|
## How to hook up before save on an entity form
|
|
|
|
|
|
On auto forms, you may want to perform additional operations.
|
|
|
One example is do a call of `setDocument`, another is to create a record in other entity and set
|
|
|
foreign key value to it.
|
|
|
|
|
|
In order to do that, set up an event handler for `beforeSaveForm' event:
|
|
|
```
|
|
|
this.on('beforeSaveForm', this.onBeforeSaveForm, this);
|
|
|
```
|
|
|
|
|
|
The handler shall take a `functionList` parameter, which is an array of arrays.
|
|
|
Each inner array shall consist of two elements:
|
|
|
- a number - order of function called, in it does not matter, leave it `0`
|
|
|
- a function, which must return a promise.
|
|
|
|
|
|
Entity will be saved, after all the promises in that array resolve:
|
|
|
```
|
|
|
onBeforeSaveForm: function (functionList) {
|
|
|
functionList.push([0, function () {
|
|
|
return me._saveToTempStore(xml, instanceID, function () {
|
|
|
me.record.set('version', me.record.get('version') + 1);
|
|
|
me._refreshByStatus('draft');
|
|
|
});
|
|
|
}]);
|
|
|
})
|
|
|
```
|
|
|
|
|
|
## How to remove document field button from toolbar
|
|
|
|
|
|
First of all, need to find a toolbar, this is done using query by `ubID=mainToolbar`. Unfortunatelly, there is no good query for the button, so we have to rely on the fact tha the button is always have index 2. The following code snipped removes the button:
|
|
|
|
|
|
```
|
|
|
var tbar = this.query('[ubID=mainToolbar]')[0],
|
|
|
tbar.insert(tbar.items.length - 1, info);
|
|
|
tbar.remove(tbar.items.getAt(2));
|
|
|
tbar.remove(tbar.items.getAt(2));
|
|
|
```
|
|
|
|
|
|
## How to control actions availability
|
|
|
|
|
|
`BasePanel` does not provide standard mechanism to control actions availability in event driven or callback driven way. But it is possible to override the method `updateActions` and after the call of parent method perform there any additional logic related to actions availability:
|
|
|
|
|
|
```
|
|
|
updateActions: function () {
|
|
|
this.callParent(arguments);
|
|
|
if (!this.isStandaloneTask) {
|
|
|
this.setActionDisabled(UB.view.BasePanel.actionId.fDelete, true);
|
|
|
}
|
|
|
},
|
|
|
```
|
|
|
The same in grid is done in method `setupActions`.
|
|
|
|
|
|
## How to dymanically add UBDetailGrid to a form
|
|
|
|
|
|
When a detail grid is added to a form dynamically, i.e. after form created an initialized, the detail component will display grid, but it will not be attached to a master record.
|
|
|
In order to "connect" it to the master record, use the following code snippet:
|
|
|
```javascript
|
|
|
me.details = me.getDetails();
|
|
|
me.setDetails(me.record);
|
|
|
```
|
|
|
|
|
|
Beware that `getDetails` and `setDetails` are not getter and setter methods, they are just methods (named not in the best way) with the following meaning:
|
|
|
* `getDetails` scans the form recursively and searches for all the details. The `details` attribute stores the list - so, need to assign result returned by `getDetails` to it.
|
|
|
* `setDetails` is actually the method, which 'establishes' the link between master and detail.
|
|
|
|
|
|
|
|
|
# Custom Forms and controls
|
|
|
|
|
|
## My custom form does not work
|
|
|
|
|
|
Check the following:
|
|
|
* Form type is set "custom", not "auto"
|
|
|
* The form extends a control. For example:
|
|
|
|
|
|
```javascript
|
|
|
extend: 'Ext.form.Panel',
|
|
|
```
|
|
|
* It is a common mistake miss a base class or to misspell "extend" ("extends" won't work and won't indicate it is a misspell!)
|
|
|
|
|
|
## How to create a UB enum control
|
|
|
|
|
|
For auto forms, `BasePanel` automatically creates control for entity attributes, and if attribute type is enum, appropriate combobox control will be created automatically. However, sometimes, it is needed to create an enum combobox in custom form or in a custom ExtJS control.
|
|
|
|
|
|
In such a case, the following snipped should help to make the trick:
|
|
|
```
|
|
|
{
|
|
|
xtype: 'ubcombobox',
|
|
|
name: 'engineType',
|
|
|
fieldLabel: UB.i18n('bpm_ProcessDefinition.engineType'),
|
|
|
allowBlank: false,
|
|
|
valueField: 'code',
|
|
|
displayField: 'name',
|
|
|
ubRequest: UB.core.UBEnumManager.getUBStore('BPM_ENGINE_TYPE').ubRequest
|
|
|
}
|
|
|
```
|
|
|
|
|
|
`UB.core.UBEnumManager.getUBStore` function creates a request to get list of available enumeration options.
|
|
|
|
|
|
Notice the `UB.i18n('bpm_ProcessDefinition.engineType')` syntax. That is a shorthand syntax instead of `$App.domainInfo.entities['bpm_ProcessDefinition'].attributes['engineType'].caption` . |
|
|
\ No newline at end of file |