Components

Widget concept

Before beginning

This guide assumes that you are already familiar with concepts inherent in JSF programming and in Ivy development.

Introduction

This document provides a high-level explanation of how to develop a Portal widget. The ability to use Portal services and styles can be particularly useful to developers who wish to do one or more of the following:

  • Create their own widgets for Portal which have a consistent look and feel with the existing widgets.

  • Reuse existing portal services to create their own widgets which can manipulate Portal data, such as: cases, tasks, process starts, users,...

How it is

This section introduces the Html Dialog Component and Portal services, predefined styles used in building a widget, and goes on to describe the process of designing and implementing.

Portal widgets should be implemented using the Html Dialog Component technology from Axon.ivy and follow the famous model-view-controller pattern.

Furthermore, to have a clean architecture and avoid a lot of headaches going forward, we suggest that you should separate your widget into layers like below:

  • Entities

    Entities are the business objects of the widget. They encapsulate the most general and high-level rules. They are the least likely to change when something external changes. (e.g.: by a change to page navigation, or security).

  • Use Cases

    Use case are widget specific business rules. This layer encapsulates and implements all of the use case of the widget. Changes in this layer should not affect the entities. This layer should not be affected by changes to externalities such as the Portal services, the UI, or any of the common frameworks.

  • Interfaces Adapters

    Interfaces Adapters are set of adapters that convert data from the format most convenient for the use cases and entities, to the format most convenient for some external agency such as the database or the web. Similarly, data is converted, in this layer, from the form most convenient for entities and use case, into the form most convenient for whatever persistence framework is being used. (The presenters, views, and controllers all belong in here. The models are likely just data structures that are passed from the controllers to the use case, and then back from the use cases to the presenters and views.)

  • Frameworks and Drivers

    This layer is generally composed of frameworks and tools such as the database, the web framework, Portal services, etc. This layer is where all the details go. The Web is a detail. The Portal services are detail. We keep these thing on the outside where they can do little harm.

Tip

There's no rule that says you must always have just the four layers above. However, you should always apply that the source code dependencies point from mechanisms to policies:

Frameworks and Drivers > Interfaces Adapters > User Cases > Entities

By doing so, you will create a widget that is intrinsically testable, independent of frameworks, independent of UI, independent of database, and independent of any external agency. When any of the external parts of the system become obsolete, like the database, or the web framework, you can replace those obsolete elements with a minimum of fuss.

Main technology and concept

You should have an understanding of the following technology and concept as you build your widget:

  • Managed Beans: in Html Dialog Component it is possible to communicate with normal Java Objects by using Managed Beans.

  • User Dialog Concept: an Html Dialog Component follows the model-view-controller pattern of the User Dialog Concept.

    • Model is a data class whose data fields can be bound to widget properties of the view via the special object data.

    • Controller is implemented by a series of UI processes that can be mapped to events on the view such as mouse clicks. Axon.ivy provides the keyword logic to call an event process or a method process in the logic.

    • View of an Html Dialog is defined with the means of an XHTML document.

Services

There are separate services for working with each type of data:

  • Application Services: set of services for getting information about applications.

  • Absence Services: set of services for manipulating the user's absence.

  • Case Services: set of services for working with cases and related data, such as: additional properties, notes,...

  • Task Services: set of services for working with tasks.

  • Process Start Services: set of services for querying process starts from the Portal system.

  • Security Services: set of services for querying users and roles.

  • User Setting Services: set of services for manipulating the user settings and related data, such as: email settings, language settings.

  • Portal Configuration Services: set of services for controlling the Portal configuration.

Built-in widgets

Portal comes with some useful widgets:

  1. Task widget

    Below is the sample how the task widget being use in the default template:

    <ui:define name="taskWidget">

    <ic:ch.ivy.addon.portalkit.component.TaskWidget id="task-widget" tasks="#{logic.getTasksOfSessionUser()}" ... />

    </ui:define>

  2. Process widget

    Below is the sample how the process widget being use in the default template:

    <ui:define name="processWidget">

    <ic:ch.ivy.addon.portalkit.component.ProcessWidget id="process-widget" compactMode="true" ... .>

    </ui:define>

  3. Statistic widget

    Below is the sample how the statistic widget being use in the default template:

    <ui:define name="statisticWidget">

    <ic:ch.ivy.addon.portalkit.component.StatisticWidget id="statistics-widget" compactMode="true" ... >

    ...

    </ic:ch.ivy.addon.portalkit.component.StatisticWidget>

    </ui:define>

Portal setup these widget with the default settings for you, but you can always re-define them in order to match with your needs. Moreover, if you want to turn off a built-in widget, you can simply leave its ui:define container empty like this:

<ui:define name="taskWidget">

<!-- leave it empty -->

</ui:define>

Predefined styles

There are separate common styles are predefined to ensure every Portal widget has a consistent structure and appearance:

<div class="widget">

<div class="widget-header">

<ul class="widget-header-menu">

<li class="widget-header-menu-item">...</li>

<li class="widget-header-menu-item">...</li>

<li class="widget-header-menu-item">...</li>

...

</ul>

...

</div>

<div class="widget-content">

<div class="widget-content-list">

<div class="widget-content-list-item">...</div>

<div class="widget-content-list-item">...</div>

<div class="widget-content-list-item">...</div>

...

</div>

</div>

<div class="widdget-footer">

...

</div>

</div>

Flow

The general flow for developing a widget for portal is as follows:

  1. Design your widget, deciding which parts to implement in Ivy component, and which parts to implement as pure JSF.

  2. Create an Html Dialog Component.

    The following code fragment defines an example Html Dialog component:

    <cc:interface componentType="IvyComponent">

    <cc:attribute name="caption" />

    </cc:interface>

    <cc:implementation>

    ...

    </cc:implementation>

    A component could be inserted with the ic tag.

    <ic:my.namespace.ComponentName ... />

    For more information, see the Html Dialog Component section in Axon.ivy Designer - Help: Designer Guide > User Interface > User Dialogs > Html Dialogs

  3. If you are writing a widget, which manipulates task, case,... consider using Portal built-in services.
  4. Optionally, your widgets can have their own configuration. There are separate methods for manipulating widget configuration:
    • You can initiate or update your widget configuration by passing an JSON object to saveSettings().

    • You can load your widget configuration by calling loadSettings().

Integration

The general flow for integrating a widget into Portal homepage is as follows:

  1. Create a new home page which uses the DefaultHomePageTemplate.xhtml template. By doing this, your new home page will inherit the widget from the previous home page and has a place holder for your own widgets. Your custom home page should look like below:

    <ui:composition template="/layouts/DefaultHomePageTemplate.xhtml" xmlns="http://www.w3.org/1999/xhtml"

    xmlns:f="http://xmlns.jcp.org/jsf/core" xmlns:h="http://xmlns.jcp.org/jsf/html"

    xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:ic="http://ivyteam.ch/jsf/component">

    <ui:define name="customWidget">

    ...

    </ui:define>

    </ui:composition>

  2. Create a new process start for the new home page. Now you will use this process start as the entry point of your portal instead of the default one. To let portal know about your new portal home, you have to go to the portal settings and set the portal home url to the new one.

  3. In your new home page, place your widget inside the customWidget section.

    <ui:define name="customWidget">

    <ic:my.namespace.ComponentName ... />

    ...

    </ui:define>

For more details, visit Portal home.

Exception handling

Portal separates exception into 2 types: ajax and non-ajax exception.

Portal handle non-ajax exception for you. You do not need to do anything for this type of exception.

Portal also handle ajax exception for you as default, but you can implement your own exception handler by using the Primefaces built-in exception handler: p:ajaxExceptionHandler.

Layout templates

Templates for development

Your Portal Project is dependent on PortalTemplate project, in which there are 7 templates that can be used directly.

  1. Basic template

  2. Two column template

  3. Task template

  4. Case template

  5. Task list template

  6. Case list template

  7. Default homepage template

These templates have the same header, which is a menu of applications that you configure in Administration page. Since version 6.4, Portal officially supports responsiveness for 3 resolutions: iMac (1920*1050), iPad (1366*1024) iPad Portrait: (1024*1366), every templates has its default responsiveness, you can refer to Responsiveness to override it. Besides, there are user settings like: Absences, Email, Language Settings and Administration (for admin only). Details about user settings can be found in Settings.

Basic template

Basic template provides basic layout where user can put their custom content. It lacks Portal menu and Case details. We recommend to use task template for your process.

How to use Basic template

  1. Create a new HTML User Dialog and then use ui:composition to define the template inside and reuse the default responsiveness behavior. To override it, please use pageContent instead of simplePageContent and Responsiveness.

    <ui:composition template="/layouts/BasicTemplate.xhtml">

    <ui:define name="pageTitle">Sample Page</ui:define>

    <ui:define name="simplePageContent">

    This is sample content.

    </ui:define>

    </ui:composition>

  2. See the result after using Basic template for example:

Two column template

Two column template inherits Basic Template. It has 2 columns which user can customize their contents. Normally, the first column is for navigation, the second for displaying corresponding content.

How to use Two column template

  1. Create a HTML User Dialog, define template in ui:composition and insert content of second column and third column using ui:define.

    <ui:composition template="/layouts/TwoColumnTemplate.xhtml">

    <ui:define name="pageTitle">Sample Page</ui:define>

    <ui:define name="navigationRegion">

    Navigation Region

    </ui:define>

    <ui:define name="contentRegion">

    Content Region

    </ui:define>

    </ui:composition>

  2. See the result after using Two column template for example:

Task template

Task template is used for displaying task functionality and related information to support completing the task. There are a lot of regions to be filled with your custom content:

  • Request name

  • Process chain

  • Errors

  • Information

  • Dynamic tabs

  • Request form

  • Case information tab

  • Buttons at footer

How to use template TaskTemplate.xhtml

  1. Create a new HTML User Dialog and then use ui:composition to define template which you use inside.

    <ui:composition template="/layouts/TaskTemplate.xhtml">

  2. Set caseId value so that the Case information tab is available to users where they can see info of case, documents, related tasks and history. It is mandatory.

    <ui:param name="caseId" value="#{ivy.case.id}" />

  3. Set data to actualStepIndex and steps variables which are used for ProcessChain component in template. It is mandatory.

    <ui:param name="actualStepIndex" value="#{data.actualStepIndex}" />

    <ui:param name="steps" value="#{data.steps}" />

  4. Inserts contents for taskName, errorsZone, infoZone. It is optional.

    <ui:define name="taskName">...</ui:define>

    <ui:define name="errorsZone">...</ui:define>

    <ui:define name="infoZone">...</ui:define>

  5. Inserts some new tabs, refers some segment of code as below. If your application has multiple tabs, use it and turn off request form by set showTaskFormTab to false.

    <ui:param name="showTaskFormTab" value="false" />

    <ui:define name="dynamicTabs">

    <p:tab title="My first tab">

    <p:inputText id="first-name" value="#{data.firstname}"/>

    </p:tab>

    <p:tab title="My second tab">

    <p:inputText id="last-name" value="#{data.lastname}"/>

    </p:tab>

    </ui:define>

  6. Overwrite contents of default tab. Use it when your application need only 1 tab.

    <ui:define name="taskForm">

    <h:form>

    <p:outputLabel name="myCustomLabel" />

    ...

    </h:form>

    </ui:define>

  7. Set visible/invisible for default tab case information. Set following variables as true if you want to visible and vice versa.

    <ui:param name="showCaseStatusInfoTab" value="true" />

  8. Inserts left buttons and right buttons which stay at the bottom of the page. It is optional. You can use it to define your action button. Consider using partialSubmit to submit your data im tabs.

    <ui:define name="leftButtons">

    <p:commandButton value="Save" actionListener="#{logic.save}" partialSubmit="true" process="first-name last-name" update="first-name last-name" />

    </ui:define>

    <ui:define name="rightButtons">

    <p:commandButton value="Cancel" actionListener="#{logic.cancel}" immediate="true" />

    </ui:define>

Case template

Case template is similar to Task Template in both UI and usage. The difference is it is used for displaying case details functionality.

How to use case template

Create a new HTML User Dialog and then use ui:composition to define template which you use inside.

<ui:composition template="/layouts/CaseTemplate.xhtml">

Default homepage template

Default homepage template is used to create pages that have the look as default homepage of Portal. Besides, users can customize it by disabling default widgets, add new widgets, change position of widgets. For more details including basic and advanced customization, refer to Portal home

How to use default homepage template

Create a new HTML User Dialog and then use ui:composition to define template.

<ui:composition template="/layouts/DefaultHomePageTemplate.xhtml">

Task list template

Task list template is used to display task list where user can see tasks and their details.

How to use task list template

  1. Create a new HTML User Dialog and then use ui:composition to define template.

    <ui:composition template="/layouts/PortalTasksTemplate.xhtml">

    </ui:composition>

  2. Data class of this dialog should have an attribute named taskView with type ch.ivy.addon.portal.generic.view.TaskView. By changing this attribute, user can modify title of the task list widget, collected tasks (through dataModel) and more. The following is a sample to build a taskView.

    import ch.ivy.addon.portalkit.datamodel.TaskLazyDataModel;

    import ch.ivy.addon.portalkit.bo.MainMenuNode;

    import ch.ivy.addon.portal.generic.view.TaskView;

    TaskLazyDataModel dataModel = new TaskLazyDataModel();

    dataModel.setIgnoreInvolvedUser(true);

    dataModel.setSortType(ch.ivy.addon.portalkit.enums.SortType.BY_PRIORITY);

    MainMenuNode category = new MainMenuNode();

    category.value = "My Task List";

    out.taskView = TaskView.create().dataModel(dataModel).pageTitle("My Task List").hideTaskFilter(true).category(category).showHeaderToolbar(false).createNewTaskView();

Case list template

Case list template is used to display case list where user can see cases and their details.

How to use case list template

  1. Create a new HTML User Dialog and then use ui:composition to define template.

    <ui:composition template="/layouts/PortalCasesTemplate.xhtml">

    </ui:composition>

  2. Data class of this dialog should have an attribute named caseView with type ch.ivy.addon.portal.generic.view.CaseView. By changing this attribute, user can modify title of the case list widget, collected cases (through dataModel) and more. The following is an example to build a caseView.

    import ch.ivy.addon.portalkit.datamodel.CaseLazyDataModel;

    import ch.ivy.addon.portal.generic.view.CaseView;

    CaseLazyDataModel dataModel = new CaseLazyDataModel();

    out.caseView = CaseView.create().dataModel(dataModel).withTitle("My Cases").buildNewView();

Handle required Login in templates

All templates require login to access by default. But templates also provide functionality to access page without login by adding the isNotRequiredLogin parameter.

How to handle required login in template

  1. Create a new HTML User Dialog and then use ui:param to define the template inside

    <ui:composition template="/layouts/BasicTemplate.xhtml">

    <ui:param name="isNotRequiredLogin" value="#{data.isNotRequiredLogin}" />

    <ui:define name="pageContent">

    This is sample content.

    </ui:define>

    </ui:composition>

  2. Result after using template for example (All user settings and application menus will not visible).

Responsiveness

Since version 6.4, Portal officially supports responsiveness for 3 screen widths: iMac(width 1920), iPad landscape(width 1366) and iPad portrait(width 1024).

To apply your styles for the above resolutions, you can add your own media query css:

/* Small screen */ @media screen and (max-width: 1365px) {/*.....*/}

/* Medium screen */ @media screen and (min-width: 1366px) and (max-width: 1919px) {/*.....*/},

/* Large screen */ @media screen and (min-width: 1920px) {/*......*/}

In Portal's new design, the main container's width should be changed according to menu state (expand/colapse).

To adapt the change, you need to initialize the ResponsiveToolkit Javascript object and introduce 3 objects to handle 3 screen resolutions and each object has to implement the updateMainContainer method.

Portal templates define their own responsiveness, you can redefine the footer section to override:

E.g. Initialize ResponsiveToolkit for TaskList page.

<ui:define name="footer">

<script type="text/javascript">

$(function(){

var taskListLargeScreen = new TaskListLargeScreenHandler();

var taskListMediumScreen = new TaskListMediumScreenHandler();

var taskListSmallScreen = new TaskListSmallScreenHandler();

var responsiveToolkit = ResponsiveToolkit(taskListLargeScreen, taskListMediumScreen, taskListSmallScreen);

Portal.init(responsiveToolkit);

});

</script>

</ui:define>

Enable Portal chat

Chat feature

Information

Chat feature was implemented on Portal.

There are couple of reason, it's intentionally disabled by default:

  • Customers have their own Chat, they do not need another.

  • For using Chat, system administrator has to configure it on their server (needs additional Libraries).

  • With added libraries for using Chat, it slows AxonIvyEngine down.

  • It has log-in issue as if AxonIvyEngine is configured with IIS (version 7.5 or older) to manage SSO.

  • Not fully support UNICODE characters on Ivy 6.3 and upwards.

For users who want to use chat feature

Follow the steps below:

  1. First, IvyEngine/Designer needs some configuration to use Chat. Copy two libraries and then paste into webapps/ivy/WEB-INF/lib folder located on AxonIvyEngine, AxonIvyDesigner.

    Note

    You can find these libraries inside PortalKit module, located on PortalKit/lib_chat or download from this site.

  2. Second, Enables Chat on UI by setting enablesChat param

    <ui:param name="enablesChat" value="true" />

    Added this line to your pages that are using BasicTemplates of Portal (adds to DefaultPortalHomeTemplate.xhtml, TaskTempate.xhtml, etc.)

    E.g.:

    <ui:composition template="/layouts/BasicTemplate.xhtml">

    <ui:param name="enablesChat" value="true" />

    <...>

    </ui:composition>

    Or simply change param's value on BasicTemplate.xhtml

    <ui:param name="enablesChat" value="#{enablesChat}" /> to <ui:param name="enablesChat" value="true" />

  3. Restarts AxonIvy Desinger/Engine. Then enjoy Chat.

Error handling

In this section, we introduce 2 kinds of errors, when and how to handle them in Portal.

  • Ajax error : this kind of errors occur during a JSF ajax requests, for example when the user clicks on the show full mode button to tell the task widget switches to full mode, without handling the end user would not get any form of feedback if the action was successfully performed or not.

  • Non-ajax error : this kind of errors occur when user access to Portal from a url which could not be handled successfully by server side, or being navigated by a corrupted url. For example, when the user clicks on a link to start a task which does not exist.

Ajax error handling

Introduction

By default, Portal handles all exceptions from ajax requests.

When an exception occurs, Portal will show an error notification with the exception type and message to end user. The exception details is available when user click on show details button.

Stacktrace on error messages can be showed/hid depend on ivy system property Errors.ShowDetailsToEndUser.

Note

This feature is only available if using the portal default template: BasicTemplate or its extension.

Result

Non-ajax error handling

Introduction

By default, when the server has any error such as : HTTP 404, HTTP 500, or exception while page's loading, AxonIvyEngine will show an default error page. E.g.:

You can find content of this page is the file located on ${AxonIvyEngineFolder}/webapp/ivy/ivy-error-page.xhtml, but the error page is not user friendly, too much technical information that normal user may not understand. Thus, Axon Ivy Portal provides an alternative solution to make this page nicer.

How to configure

Download the zip file below to configure on your own engine (or designer).

Important

Read README.txt

PortalErrorPageConfiguration.zip

Result

HTTP 404 Page Not Found

Example testing URL: 404

HTTP 500 Error

Example testing URL: 500

Additional Components

Process history

Introduction

This component is a lazy loading list which displays all business cases of a business entity in your application. You can include this component everywhere:

In a page

In a dialog

How to use

First you need to link the cases to the business entity. Call the subprocess SetBusinessEntityId in the process which need to be linked and input an identifier unique to your business entity. The subprocess will set the id to the additional property "CASE_BUSINESS_ENTITY_PROPERTY" of the business case.

Include the process history component into your page:

<ic:ch.ivy.addon.portal.component.ProcessHistory businessEntityId="resourceA247" >

The value of the attribute businessEntityId must match the id input into the subprocess in the first step.

By default the component will load 20 cases at a time. You can change this by setting the attribute chunkSize to the number you want . You should use this attribute alongside with the attribute scrollHeight to configure the scroll bar of the list.

Note

If you use this component in a dialog, you must run this script processHistory.setup(); when the dialog is shown. For example:

<p:dialog widgetVar="process-history-dialog" id="process-history-dialog" width="800" height="500" header="Process history of Resource A247" onShow="processHistory.setup();">

<ic:ch.ivy.addon.portal.component.ProcessHistory businessEntityId="resourceA247" chunkSize="6" scrollHeight="400" />

</p:dialog>

Important

If your process has a Trigger component or sends a signal to start another process with the option "Attach to Business Case that triggered this process" selected, the current case of the process will become a technical case and will not be loaded into the process history list. In this case You need to call the SetBusinessEntityId subprocess after the first Trigger or signal sending step.

Task Analysis

Introduction

Task Analysis component of Portal provides features for users to analyze not only tasks but also cases. These features are:

  1. Set of filters for both tasks and cases which allow user to filter and to find tasks, cases more better. More, user can create and manage their own filter set for future usage.

  2. Dynamic result table with lots of information for both task and case.

  3. Support export result as Excel files (currently we only support .xlsx extension).

How to use

Task Analysis component is integrated into Statistic widget. You can use this component directly when open Statistic widget. If you want to use this component, you only have to redirect to Task Analysis component with following code:

import javax.faces.context.FacesContext;

String taskAnalysisUrl = ivy.html.startref("Start Processes/TaskAnalysis/start.ivp");

FacesContext.getCurrentInstance().getExternalContext().redirect(taskAnalysisUrl);

Process Chain

Introduction

Process Chain component of Portal provides features for users to know status of all steps in a process: the step's working, these steps are done, these steps is not done. These features are:

  1. Support to display all working steps or display only helpful steps as begin, last, current, previous current, next current steps.

  2. Support to change the sharp of process chain: circle or line.

  3. Support to change direction of process chain: horizontal or vertical.

How to use

Process Chain component can be integrated in any widget by including this component into a page. In order to use this component in a page, include this component to this page with following code:

<ic:ch.ivy.addon.portalkit.singleapp.process.ProcessChain id="process-chain-circle-horizontal"

componentId="component-circle-horizontal" shape="CIRCLE" direction="HORIZONTAL"

isShowAllSteps="FALSE" actualStepIndex="#{data.actualCurrentIndex}" steps="#{data.steps}" />

  1. Must to set value for actualStepIndex parameter. This is current step index.

  2. Must to set value for steps parameter. This is list of working steps.

  3. Can change shape parameter to CIRCLE or LINE based on the requirement. Default value of this is CIRCLE.

  4. Can change direction parameter to HORIZONTAL or VERTICAL based on the requirement. Default value of this is HORIZONTAL.

  5. Can change isShowAllSteps parameter to TRUE or FALSE based on the requirement. Default value of this is FALSE.

Change Last Drilldown Level Of Task By Expiry Chart

Task by expiry chart

For users who want to change last drilldown level of Task by expiry chart

By default, the last drilldown level of a expiry chart is HOUR. It means that, to open a related tasks list of this chart, users must navigate from YEAR -> MONTH -> WEEK -> DAY -> HOUR, clicking on a column of HOUR chart to open the tasks.

To change this last drilldown level, users can set the value of EXPIRY_CHART_LAST_DRILLDOWN_LEVEL in Global settings.

For example, to navigate to task list immediately when clicking on a week column, set EXPIRY_CHART_LAST_DRILLDOWN_LEVEL = WEEK: