GithubHelp home page GithubHelp logo

cuba-platform / dashboard-addon Goto Github PK

View Code? Open in Web Editor NEW
7.0 5.0 3.0 2.92 MB

This component is designed to create and embed dashboards. Dashboard consists of widgets - individual elements based on a frame.

License: Apache License 2.0

Java 84.50% XSLT 11.05% SCSS 4.45%
cuba-platform cuba-component apache2 dashboard

dashboard-addon's Introduction

license Build Status

Dashboards

1. Overview

This component enables creating and embedding dashboards into your application screens. Dashboards allow visualizing summarized information, data sets, charts and can be accessible only by authorized users.

A dashboard consists of widgets — individual elements based on a frame. An integrated set of layouts allows positioning widgets on a dashboard according to your needs. Use responsive layouts to adapt your dashboards to different displays.

You can add your own widgets or use Dashboard Chart Add-on that provides additional chart widgets for dashboard add-on.

See sample application using this add-on.

See webinar on the CUBA Platform channel.

2. Installation

The add-on can be added to your project in one of the ways described below. Installation from the Marketplace is the simplest way. The last version of the add-on compatible with the used version of the platform will be installed. Also, you can install the add-on by coordinates choosing the required version of the add-on from the table.

In case you want to install the add-on by manual editing or by building from sources see the complete add-ons installation guide in CUBA Platform documentation.

2.1. From the Marketplace

  1. Open your application in CUBA Studio. Check the latest version of CUBA Studio on the CUBA Platform site.
  2. Go to CUBA -> Marketplace in the main menu.

marketplace

  1. Find the Dashboards add-on there.

addons

  1. Click Install and apply the changes. The add-on corresponding to the used platform version will be installed.

2.2. By Coordinates

  1. Open your application in CUBA Studio. Check the latest version of CUBA Studio on the CUBA Platform site.
  2. Go to CUBA -> Marketplace in the main menu.
  3. Click the icon in the upper-right corner.

by-coordinates

  1. Paste the add-on coordinates in the corresponding field as follows:

com.haulmont.addon.dashboard:dashboard-global:<add-on version>

where <add-on version> is compatible with the used version of the CUBA platform.

Platform Version Add-on Version
7.2.X 3.2.3
7.1.X 3.1.3
7.0.X 3.0.4
6.10.X 2.0.1
  1. Click Install and apply the changes. The add-on will be installed to your project.

3.Configuration

Before starting working with dashboard editor in your application you should do some configuration setting: extend application theme and add widgets.

3.1. Extending Application Theme

For the correct rendering of the add-on UI controls, it is recommended to extend the hover theme in your application as described in CUBA Platform documentation.

3.2. Adding Widget Types

By default, the add-on does not have preset widgets. To add an additional widget type, you need to do the following:

  1. Create a fragment as described in CUBA Platform documentation.
  2. Add the annotation com.haulmont.addon.dashboard.web.annotation.DashboardWidget. Fill in the fields: name, editFrameId(optional, leave empty if there is no parameter in widget) in the annotation (see JavaDoc).
  3. widget, dashboard, dashboardFrame can be included in widget via @WindowParam annotation. Widget parameters in widget editor and widget frames should have @WidgetParam and @WindowParam annotations. For example:
@DashboardWidget(name = CAPTION, editFrameId = "dashboard$LookupWidget.edit")
public class LookupWidget extends AbstractFrame implements RefreshableWidget {
    public static final String CAPTION = "Lookup";

    @WindowParam
    protected Widget widget;

    @WindowParam
    protected Dashboard dashboard;

    @WindowParam
    protected DashboardFrame dashboardFrame;

    @WidgetParam
    @WindowParam
    protected String lookupWindowId;

    public String getLookupWindowId() {
        return lookupWindowId;
    }

    public void setLookupWindowId(String lookupWindowId) {
        this.lookupWindowId = lookupWindowId;
    }
}
  1. Add the frame for editing widget in the web module and register it in web-screens.xml. For example:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
        class="com.haulmont.addon.dashboard.web.widget.lookup.LookupWidgetEdit">
    <layout spacing="true">
        <hbox id="lookupIdBox"
              spacing="true">
            <label width="85px"
                   value="msg://lookupId"/>
            <lookupField id="lookupIdLookup"
                         nullOptionVisible="false"
                         required="true"/>
        </hbox>
    </layout>
</window>
public class LookupWidgetEdit extends AbstractFrame {
    @Inject
    protected LookupField lookupIdLookup;
    @Inject
    protected WindowConfig windowConfig;
    @Inject
    protected Metadata metadata;
    @Inject
    protected ScreenXmlLoader screenXmlLoader;

    protected Datasource<Widget> widgetDs;

    @WidgetParam
    @WindowParam
    protected String lookupWindowId;

    @Override
    public void init(Map<String, Object> params) {
        super.init(params);

        lookupIdLookup.setOptionsList(getAllLookupIds());
        lookupIdLookup.addValueChangeListener(e -> lookupIdSelected((String) e.getValue()));

        initWidgetDs(params);
        selectLookupId();
    }

    protected void initWidgetDs(Map<String, Object> params) {
        widgetDs = (Datasource<Widget>) params.get(WidgetEdit.ITEM_DS);
    }
}

If widget frame implements RefreshableWidget interface, then method refresh() will be invoked automatically on each dashboard update event.

4. Usage

After installation the add-on in your project the Dashboard menu will appear containing Dashboards and Widget Template screens.

menu-dashboards

4.1. Dashboards

Dashboard browser contains the list of dashboards and buttons for creating, editing and removing dashboards in a database.

persistent-dashboard

Dashboard editor screen appears after clicking the Create button on the Dashboards screen and allows editing a dashboard.

dashboard-editor-common

Dashboard Editor screen contains 6 areas:

  • the dashboard fields;
  • the dashboard parameters;
  • the palette with widgets and layouts;
  • the canvas where the position of dashboard elements (widgets and layouts) is specified;
  • the tree representation of the edited dashboard structure;
  • the buttons panel.

4.1.1 Dashboard Fields

To save the created dashboard it is necessary to fill in at least the required fields:

  • Title - a name of the dashboard.
  • Code - a unique identifier for a more convenient search in a database.

The following fields are available to set:

  • Refresh period (sec) - a time period in seconds for refresh a dashboard UI.
  • Assistant bean name - an optional reference to a Spring bean class that should be used for customizing the dashboard (assistance bean must have prototype bean scope).
  • Group - a dashboard group.
  • Available for all users - a flag which defines the user access to the dashboard. If set to false, then only the user who created the dashboard can view and edit it. Otherwise, all users can view and edit the dashboard.

4.1.2 Dashboard Parameters

The frame with dashboard parameters which allows adding, editing and removing dashboard parameters. These parameters are passed as input parameters for the widgets in this dashboard. For more information on adding and editing parameters, see Parameter Editor.

4.1.3 Palette

It is a container with 3 collapsible tabs. Each tab contains a container with components. When a component is dragged to the canvas, the corresponding element will be added to the canvas.

4.1.3.1 Widgets

By default, there are no widgets in this tab. You can add widgets as described in Adding Widget Types section. Drag an element from the palette for adding it on the canvas, and the widget editor will be opened in a dialog window. It is possible to make the widget a template (in this case, it is added to the tab Widget Templates).

palette-widgets

4.1.3.2 Layouts

Layouts help to place widgets in the specific way. Add the required layout before adding widgets on the canvas.

palette-layouts

The following layouts are available:

  • vertical - widgets are placed vertically one after another;
  • horizontal - widgets are placed horizontally one after another;
  • grid - widgets are placed inside a grid with a specified number of rows and columns;
  • css - enables full control over placement and styling of enclosed components using CSS;
  • responsive - widgets are placed vertically, but depending on the screen width, the number of columns with widgets changes. After adding this layout on the canvas the setting form will appear. The slider shows which part of the screen will be occupied by one widget when opening the dashboard on a particular device.

responsive-settings

4.1.3.3. Templates

Contains widget templates from a database. Templates can be created from the widgets added on the canvas using the corresponding button, or by using Widget Template Browser.

palette-widget-templates

4.1.4 Canvas

It is a container in which you can place widgets and layouts. Drag an element from the palette for adding it on the canvas.

canvas-drag-grid-layout

When dragging the Grid Layout to the canvas the dialog will open where you can set the number of rows and columns. When dragging a widget, the Widget Editor dialog will open. When dragging the Responsive Layout the dialog with settings will open.

Example of the dashboard with widgets:

canvas-with-widgets

Click on a layout or a widget to select it. The selected element contains the panel with the following buttons:

layout-buttons

trash - deletes a container from the canvas.

gear - opens the Widget Editor.

template - opens the Template Weidget Editor.

arrows - changes the weight (expand ratio) of a container in a parent container, or define colspan and rowspan attributes for the grid layout cells:

colspan-rowspan

brush - changes the style of a container: define the style name, modify the container's width and height:

style-editor

name - displays the element name specified by user.

For more information on using custom styles see CUBA Platform documentation.

4.1.5. Dashboard Layout Structure

Displays the current dashboard structure as a tree. The Root element is available by default and cannot be removed.

palette-tree

The following actions are available for the tree elements from the context menu:

  • Expand - defines a component within a container that should be expanded to use all available space in the direction of component placement. For a container with vertical placement, this attribute sets 100% height to a component; for the containers with horizontal placement - 100% width. Additionally, resizing a container will resize the expanded component.
  • Style - enables setting a style name and modifying the component's height and width.
  • Remove - removes a component from the tree.
  • Weight - changes the weight (expand ratio) of a container in a parent container.
  • Edit - opens the widget editor.
  • Template - opens the widget template editor.

tree-context-menu tree-context-menu

4.1.6. Buttons Panel

This panel contains the following buttons:

  • OK - saves the dashboard and close the editor.
  • Cancel - closes the editor without saving the dashboard.
  • Propagate - publishes event com.haulmont.addon.dashboard.web.events.DashboardUpdatedEvent.
  • Export Json - export the dashboard to a JSON file.
  • Import Json - import the dashboard from a JSON file and refresh the editor.

4.2 Dashboard Groups

The screen Dashboard Groups allows creating, editing, and removing dashboard groups. The screen Dashboard Group Editor allows adding or excluding dashboards in a dashboard group from a database.

To open the Dashboard Groups browser, click the Groups button in the Dashboard browser screen.

dashboard-group-browser

dashboard-group-editor

4.3. Widget Templates

This screen allows creating, editing and removing widget templates. Widget templates are preconfigured widgets which can be reused. Widget templates are stored in a database. This screen is available from the application menu.

menu-widget-templates

widget-template-browser

4.3.1 Widget Template Editor

This screen allows editing a widget and consists of the following elements:

  • the Name field;
  • the Group drop-down;
  • the Widget Type lookup field;
  • the Customize button;
  • the checkbox to set the widget visibility.

widget-editor

When a user clicks the Customize button, the enhanced widget editor will be opened, consisting of the following elements:

  • the Caption field;
  • the Widget Id field;
  • the Description field;
  • the Show Widget Caption checkbox;
  • the Lookup id field, for the frames inherited from the com.haulmont.cuba.gui.components.AbstractLookup. Widgets of this type fire WidgetEntitiesSelectedEvent which contains the selected entities;
  • the frame with widget parameters which allows adding, editing and removing widget parameters. These parameters are passed as input parameters for the frame, based on which the widget was taken. For more information on adding and editing parameters, see Parameter Editor.

widget-editor-customize

4.3.2 Parameter Editor

This screen allows editing parameters. A parameter is a key-value pair, where the Name field is the key and the Value field is a value. The following types of values are available:

  • ENTITY
  • LIST_ENTITY
  • ENUM
  • DATE
  • DATETIME
  • TIME
  • UUID
  • INTEGER
  • STRING
  • DECIMAL
  • BOOLEAN
  • LONG

parameter-editor

4.4. Integration of the Dashboard-UI Component

To use the dashboard-ui component in your screen, you need to add the special scheme http://schemas.haulmont.com/cubadshb/ui-component.xsd in the XML descriptor of the screen.
Then add a namespace like dashboard for the schema. The schema contains information about the tag dashboard, which can contain the parameter elements.

Here is an example of adding dashboard to the screen:

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
         class="com.haulmont.example.web.SomeController"
         xmlns:dashboard="http://schemas.haulmont.com/cubadshb/ui-component.xsd">   
     ...
         <dashboard:dashboard id="dashboardId"
                              code="usersDashboard"
                              timerDelay="60">
              <dashboard:parameter name="role" value="Admin" type="string"/>           
         </dashboard:dashboard>
     ...

Dashboard tag contains the following attributes:

  • code - the attribute which will serve for a dashboard search in a database;
  • jsonPath - the classPath to the dashboard JSON file;
  • class - the controller class of the dashboard-ui component which has to be inherited from com.haulmont.addon.dashboard.web.dashboard.frames.uicomponent.WebDashboardFrame;
  • timerDelay - the time period in seconds for refresh a dashboard-ui.

Note: when embedding a dashboard, you must specify the code or jsonPath attribute. When specifying at the same time, the attribute code takes precedence over jsonPath.

Dashboard parameter tag has the following attributes:

  • name - the name of the parameter, required;
  • value - the value of the parameter, required;
  • type - the type of the value, can take one of the following values: boolean, date, dateTime, decimal, int, long, string, time, uuid.

Note: by default, the parameter type is set to string.

4.4.1. Loading a dashboard from JSON file

You can load a dashboard to the screen from JSON file. Use jsonPath attribute and set the relative path to the file in the XML descriptor. For example:

         <dashboard:dashboard id="dashboardId"
                              jsonPath="com/haulmont/sample/petclinic/web/screens/main/Users Dashboard.json"
                              timerDelay="60">
              <dashboard:parameter name="role" value="Admin" type="string"/>           
         </dashboard:dashboard>
     ...

A dashboard created in the Dashboard Editor screen can be exported into JSON file, just click the Export json button and specify the path to the file.

Also, you can import a dashboard from the file in the Dashboard Editor screen, just click the Import json button, enter the path to the file, specify the unique code and click OK to save a dashboard.

4.5. Predefined roles

Predefined security roles:

  • Dashboard admin - allows user to create and edit dashboards and widget templates.
  • Dashboard view - allows user to see embedded dashboards.
  • Dashboard browse - allows user to view a list of available dashboards.

dashboard-addon's People

Contributors

aleksey-stukalov avatar antmarr avatar jreznot avatar nikitashchienko avatar sergeev-ms avatar slogan163 avatar testuser346 avatar tinhol avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

dashboard-addon's Issues

Parameters editor doesn't remove old controls

Environment

  • Platform version: 7.0.6
  • Addon version: 3.0.3

Description of the bug or enhancement

When I open Parameter Editor (of the added Widget parameter) and change the Value type field two or more times, the editor keeps showing me one or more controls that left from the previous Value type selections.

Which is misleading.
Also, it leads to NPE sometimes.

Screenshot 1
Screenshot 2
Screenshot 3

[KNOWN ISSUE] Standard Parameter Editor doesn't load project's Entity classes

Environment

  • Platform version: 7.0.6
  • Addon version: 3.0.3
  • Operating system: macOS

Description of the bug or enhancement

Addon parameter's editor doesn't load any project-specific Enum classes into Enum Class field, when I define the Value type == ENUM
It loads only Enum classes that are defined in CUBA framework itself and not showing enums defined in my project, also it shows only one enum (SizeUnit) of the two that are defined in the addon.

Screenshot

Boolean value of widget param is always false

Environment

  • Platform version: 7.0.5
  • Addon version: 3.0.2

Description of the bug or enhancement

Boolean value of widget param always passed as false. Dashboard param passed normally.

Okey, looks like widget params do not passed at all.

Broken tree element

Environment

  • Platform version: 7.0.3
  • Addon version: 3.0-SNAPSHOT
  • com.haulmont.addon.dashboardchart:dashboardchart-global:1.1-SNAPSHOT

Description of the bug or enhancement

Broken style of tree-element.

image

Style broken even at Reports -> Edit report -> Report structure.

Ability to refresh dashboard with external parameters

Environment

  • Platform version: 7.0.x>
  • Addon version: 3.1.x

Description of enhancement

add new method refresh(Map<String,Object> params) to DashboardFrame which will allow to override default dashboard parameters

Can't pass a parameter to dashboard from XML screen layout

Environment

  • Platform version: 7.0.10, 7.1.0
  • Addon version: 3.0.4

Description of the bug or enhancement

Can't pass a parameter to widget from XML screen descriptor.

Assume we have a dashboard with code main-dashboard and when creates it at some screen, we also want to pass some parameter to the dashboard using declarative style:

<dashboard:dashboard id="mainDashboard"
                     code="main-dashboard"
                     timerDelay="60"
                     width="100%">
    <dashboard:parameter name="font-size" value="huge"/>
</dashboard:dashboard>

In this case I get an NPE exception. In my case it happen right after logon, since the dashboard was at main screen, btw my main screen was a legacy window (extended AbstractMainWindow).
On the other hand, when I create the parameter with exactly same name and value in the main-screen editor (dashboards editor screen). Everything works just fine.

The stacktrace:

17:21:29.933 INFO  c.h.cuba.gui.config.WindowConfig        - WindowConfig initialized in 77 ms
17:21:32.785 INFO  c.h.c.s.a.AuthenticationManagerBean     - Logged in: 1e35a7d6-c83d-62f5-b065-38f7011b4077 [admin]
17:21:33.068 WARN  c.h.c.w.a.loginwindow.AppLoginWindow    - Unable to login
java.lang.NullPointerException: null
	at com.haulmont.addon.dashboard.gui.components.loaders.DashboardFrameLoader.createParameterValue(DashboardFrameLoader.java:251) ~[dashboard-gui-3.0.4.jar:na]
	at com.haulmont.addon.dashboard.gui.components.loaders.DashboardFrameLoader.createParameter(DashboardFrameLoader.java:246) ~[dashboard-gui-3.0.4.jar:na]
	at com.haulmont.addon.dashboard.gui.components.loaders.DashboardFrameLoader.lambda$loadParams$1(DashboardFrameLoader.java:232) ~[dashboard-gui-3.0.4.jar:na]
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_161]
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[na:1.8.0_161]
	at java.util.Iterator.forEachRemaining(Iterator.java:116) ~[na:1.8.0_161]
	at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) ~[na:1.8.0_161]
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[na:1.8.0_161]
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_161]
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) ~[na:1.8.0_161]
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_161]
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) ~[na:1.8.0_161]
	at com.haulmont.addon.dashboard.gui.components.loaders.DashboardFrameLoader.loadParams(DashboardFrameLoader.java:233) ~[dashboard-gui-3.0.4.jar:na]
	at com.haulmont.addon.dashboard.gui.components.loaders.DashboardFrameLoader.loadComponent(DashboardFrameLoader.java:161) ~[dashboard-gui-3.0.4.jar:na]
	at com.haulmont.cuba.gui.xml.layout.loaders.ContainerLoader.loadSubComponents(ContainerLoader.java:37) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.ContainerLoader.loadSubComponentsAndExpand(ContainerLoader.java:88) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.AbstractBoxLoader.loadComponent(AbstractBoxLoader.java:47) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.ContainerLoader.loadSubComponents(ContainerLoader.java:37) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.ContainerLoader.loadSubComponentsAndExpand(ContainerLoader.java:88) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.AbstractBoxLoader.loadComponent(AbstractBoxLoader.java:47) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.AppWorkAreaLoader.loadComponent(AppWorkAreaLoader.java:57) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.ContainerLoader.loadSubComponents(ContainerLoader.java:37) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.ContainerLoader.loadSubComponentsAndExpand(ContainerLoader.java:88) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.AbstractBoxLoader.loadComponent(AbstractBoxLoader.java:47) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.ContainerLoader.loadSubComponents(ContainerLoader.java:37) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.ContainerLoader.loadSubComponentsAndExpand(ContainerLoader.java:88) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.xml.layout.loaders.WindowLoader.loadComponent(WindowLoader.java:99) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.sys.WebScreens.loadWindowFromXml(WebScreens.java:358) ~[cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.sys.WebScreens.createScreen(WebScreens.java:231) ~[cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.sys.WebScreens.create(WebScreens.java:175) ~[cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.gui.Screens.create(Screens.java:70) ~[cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.App.createTopLevelWindow(App.java:296) ~[cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.DefaultApp.initializeUi(DefaultApp.java:173) ~[cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.DefaultApp.connectionStateChanged(DefaultApp.java:87) ~[cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.bali.events.EventHub.publish(EventHub.java:170) ~[cuba-global-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.security.ConnectionImpl.fireStateChangeListeners(ConnectionImpl.java:228) ~[cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.security.ConnectionImpl.login(ConnectionImpl.java:106) ~[cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.app.loginwindow.AppLoginWindow.doLogin(AppLoginWindow.java:349) [cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.app.loginwindow.AppLoginWindow.doLogin(AppLoginWindow.java:318) [cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.app.loginwindow.AppLoginWindow.login(AppLoginWindow.java:264) [cuba-web-7.0.10.jar:7.0.10]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
	at com.haulmont.cuba.gui.xml.DeclarativeAction.actionPerform(DeclarativeAction.java:96) [cuba-gui-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.gui.components.WebButton.buttonClicked(WebButton.java:64) [cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.widgets.CubaButton.fireClick(CubaButton.java:76) ~[cuba-web-widgets-7.0.10.jar:na]
	at com.vaadin.ui.Button$1.click(Button.java:57) ~[vaadin-server-8.6.4-17-cuba.jar:8.6.4-17-cuba]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:153) ~[vaadin-server-8.6.4-17-cuba.jar:8.6.4-17-cuba]
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:115) ~[vaadin-server-8.6.4-17-cuba.jar:8.6.4-17-cuba]
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:431) ~[vaadin-server-8.6.4-17-cuba.jar:8.6.4-17-cuba]
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:396) ~[vaadin-server-8.6.4-17-cuba.jar:8.6.4-17-cuba]
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:260) ~[vaadin-server-8.6.4-17-cuba.jar:8.6.4-17-cuba]
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:82) ~[vaadin-server-8.6.4-17-cuba.jar:8.6.4-17-cuba]
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[vaadin-server-8.6.4-17-cuba.jar:8.6.4-17-cuba]
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1577) ~[vaadin-server-8.6.4-17-cuba.jar:8.6.4-17-cuba]
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:425) ~[vaadin-server-8.6.4-17-cuba.jar:8.6.4-17-cuba]
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:329) ~[cuba-web-7.0.10.jar:7.0.10]
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:215) ~[cuba-web-7.0.10.jar:7.0.10]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[servlet-api.jar:na]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[catalina.jar:9.0.14]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.14]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-websocket.jar:9.0.14]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.14]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.14]
	at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:107) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:73) ~[spring-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
	at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:108) ~[cuba-web-7.0.10.jar:7.0.10]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.14]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.14]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[catalina.jar:9.0.14]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[catalina.jar:9.0.14]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) ~[catalina.jar:9.0.14]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[catalina.jar:9.0.14]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[catalina.jar:9.0.14]
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668) ~[catalina.jar:9.0.14]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[catalina.jar:9.0.14]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[catalina.jar:9.0.14]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) ~[tomcat-coyote.jar:9.0.14]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-coyote.jar:9.0.14]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834) ~[tomcat-coyote.jar:9.0.14]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417) ~[tomcat-coyote.jar:9.0.14]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-coyote.jar:9.0.14]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_161]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_161]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-util.jar:9.0.14]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_161]

Can't create a RefreshableWidget with CUBA 7.1

Environment

  • Platform version: 7.1.0.BETA3
  • Addon version: 3.0.4

Description

When adding a refreshable widget (those that implements RefreshableWidget interface). It doesn't update (on view dashboard screen). And throws

IllegalStateException: Can't find component class for 'timer'

Steps to reproduce:

  • Create a widget that implements RefreshableWidget
  • override refresh method
  • Add this widget to a dashboard, set refresh timer of the dashboard to some non-zero value
  • Save and go to dashboard -> view
  • You'll see the exception

Note: the same application works just fine when downgrade CUBA to 7.0.x version.

Exception stacktrace:

java.lang.IllegalStateException: Can't find component class for 'timer'
	at com.haulmont.cuba.web.gui.WebUiComponents.create(WebUiComponents.java:163)
	at com.haulmont.cuba.web.gui.WebUiComponents.create(WebUiComponents.java:199)
	at com.haulmont.addon.dashboard.web.dashboard.frames.uicomponent.WebDashboardFrame.initTimer(WebDashboardFrame.java:217)
	at com.haulmont.addon.dashboard.web.dashboard.frames.uicomponent.WebDashboardFrame.init(WebDashboardFrame.java:133)
	at com.haulmont.cuba.gui.components.AbstractFrame.init(AbstractFrame.java:103)
	at com.haulmont.bali.events.EventHub.publish(EventHub.java:170)
	at com.haulmont.cuba.gui.screen.ScreenFragment.fireEvent(ScreenFragment.java:85)
	at com.haulmont.cuba.gui.screen.UiControllerUtils.fireEvent(UiControllerUtils.java:62)
	at com.haulmont.cuba.gui.sys.FragmentHelper$FragmentLoaderInitTask.execute(FragmentHelper.java:220)
	at com.haulmont.cuba.gui.xml.layout.loaders.ComponentLoaderContext.executeInitTasks(ComponentLoaderContext.java:178)
	at com.haulmont.cuba.web.sys.WebFragments.init(WebFragments.java:214)
	at com.haulmont.cuba.gui.screen.ScreenFragment.init(ScreenFragment.java:177)
	at com.haulmont.addon.dashboard.web.dashboard.frames.view.DashboardView.init(DashboardView.java:44)
	at com.haulmont.cuba.gui.components.AbstractWindow.init(AbstractWindow.java:99)
	at com.haulmont.bali.events.EventHub.publish(EventHub.java:170)
	at com.haulmont.cuba.gui.screen.Screen.fireEvent(Screen.java:128)
	at com.haulmont.cuba.gui.screen.UiControllerUtils.fireEvent(UiControllerUtils.java:60)
	at com.haulmont.cuba.web.sys.WebScreens.createScreen(WebScreens.java:253)
	at com.haulmont.cuba.web.sys.WebScreens.create(WebScreens.java:163)
	at com.haulmont.addon.dashboard.web.dashboard.frames.browse.PersistentDashboardBrowse.viewDashboard(PersistentDashboardBrowse.java:44)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.haulmont.cuba.gui.xml.DeclarativeAction.actionPerform(DeclarativeAction.java:101)
	at com.haulmont.cuba.web.gui.components.WebButton.buttonClicked(WebButton.java:64)
	at com.haulmont.cuba.web.widgets.CubaButton.fireClick(CubaButton.java:76)
	at com.vaadin.ui.Button$1.click(Button.java:57)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:153)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:115)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:431)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:396)
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:260)
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:82)
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1577)
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:425)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:329)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:215)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:107)
	at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:73)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:93)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

Init timers and dashboard assistant on manual dashboard refresh.

Environment

  • Platform version: 7.0
  • Addon version: 3.0
  • Client type:
  • Browser:
  • Database:
  • Operating system:

Description of the bug or enhancement

Steps to replicate the issue:

  1. Place an empty DashboardFrame in MainWindow.
  2. This dashboard frame 's init method will execute after login, at this moment, the dashboard’s code is empty, so the assistant and timer will not be setup.
  3. Then I call the dashboard frame 's setCode and refresh method to set a new dashboard for the dashboard frame. The new dashboard has a timer and assistant config. In this case, But the timer and assistant will don’t work due to the init method not called.

Dashboard is not refreshed in the View screen

Environment

  • Platform version: 7.0.x
  • Addon version: 3.0-SNAPSHOT
  • Database: HSQLDB

Description

  1. Create a dashboard
  2. Set the required parameters, Refresh period, select Assistant bean name
  3. Move one of the given layouts on the canvas
  4. Move Clock widget on the layout
  5. Save the dashboard
  6. Click the View button
  • Expected behavior: the dashboard is refreshed after the set refresh period time
  • Actual behavior: the dashboard is not refreshed

ScreenFragment is not recognised as a Widget

Environment

  • Platform version: 7.0.8
  • Addon version: 3.0.3

Description of the bug or enhancement

Despite documentation says that in CUBA 7 we can extend ScreenFragment to make a widget. If we do that the widget won't be detected by the addon unless in xml file we specify a link to the controller class (it's legacy behaviour that CUBA 7).

So unless you added class attribute that points to the controller class manually, your dashboard widget will not be accessible in the dashboard editor screen

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<fragment xmlns="http://schemas.haulmont.com/cuba/screen/fragment.xsd"
          class="com.haulmont.sample.petclinic.web.dashboards.ClientsDashboard">
    <layout>
        <label value="LOL!"/>
    </layout>
</fragment>

Update docs for how to load a dashboard from JSON file

Environment

  • Platform version: 7.0.8
  • Addon version: 3.0.3

Description of the bug or enhancement

We need to update addon's documentation for how to load dashboards described by json file that could be exported from dashboard editor.

Error while viewing a dashboard with Responsive layout

Environment

  • Platform version: 7.0.4
  • Addon version: 3.0-SNAPSHOT
  • Database: HSQLDB

Description

  1. Create a dashboard
  2. Set the required parameters, Refresh period, select Assistant bean name
  3. Move Responsive layout on the canvas
  4. Move one or more widgets on the layer
  5. Save the dashboard
  6. Click the View button
  • Expected behavior: the dashboard refreshes after the time set in the Refresh period
  • Actual behavior: error appears after the refresh period time
java.lang.ClassCastException: org.strangeway.responsive.web.components.impl.WebResponsiveRow cannot be cast to com.haulmont.addon.dashboard.web.dashboard.layouts.CanvasLayout
	at com.haulmont.addon.dashboard.web.dashboard.frames.uicomponent.WebDashboardFrame.searchWidgetFrame(WebDashboardFrame.java:319)
	at com.haulmont.addon.dashboard.web.dashboard.frames.uicomponent.WebDashboardFrame.searchWidgetFrame(WebDashboardFrame.java:319)
	at com.haulmont.addon.dashboard.web.dashboard.frames.uicomponent.WebDashboardFrame.getWidget(WebDashboardFrame.java:306)
	at com.haulmont.demo.dashboard.web.assistant.ClockAssistant.dashboardEventListener(ClockAssistant.java:25)
	at sun.reflect.GeneratedMethodAccessor165.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.haulmont.addon.dashboard.web.dashboard.frames.uicomponent.WebDashboardFrame.dashboardEventListener(WebDashboardFrame.java:204)
	at sun.reflect.GeneratedMethodAccessor164.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.haulmont.cuba.gui.events.sys.UiEventListenerMethodAdapter.doInvoke(UiEventListenerMethodAdapter.java:224)
	at com.haulmont.cuba.gui.events.sys.UiEventListenerMethodAdapter.processEvent(UiEventListenerMethodAdapter.java:150)
	at com.haulmont.cuba.gui.events.sys.UiEventListenerMethodAdapter.onApplicationEvent(UiEventListenerMethodAdapter.java:109)
	at com.haulmont.cuba.gui.events.sys.UiEventsMulticasterImpl.invokeListener(UiEventsMulticasterImpl.java:73)
	at com.haulmont.cuba.gui.events.sys.UiEventsMulticasterImpl.multicastEvent(UiEventsMulticasterImpl.java:66)
	at com.haulmont.cuba.web.sys.WebEvents.publish(WebEvents.java:31)
	at com.haulmont.addon.dashboard.web.dashboard.frames.uicomponent.WebDashboardFrame.lambda$initTimer$1(WebDashboardFrame.java:179)
	at com.haulmont.cuba.web.gui.WebTimer$CubaTimerActionListenerWrapper.timerAction(WebTimer.java:138)
	at com.haulmont.cuba.web.widgets.CubaTimer.onTimer(CubaTimer.java:105)
	at sun.reflect.GeneratedMethodAccessor163.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:153)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:115)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:431)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:396)
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:260)
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:82)
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1577)
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:425)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:329)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:215)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:107)
	at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:73)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:108)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

External parameters are not available in widgets

Environment

  • Platform version: 7.0.x
  • Addon version: 3.0-SNAPSHOT

Description of the bug or enhancement

Dashboard external parameters which were set via setXmlParameters method are not availabe in widgets after manual refresh.

Upgrade add-on to CUBA 7.1 platform version.

Upgrade add-on to CUBA 7.1 platform version.
Snapshot add-on version should be updated to 3.2.
Current releases/cuba_7.0 branch should be merged from the master. Create this branch if it does not exist.

No widget types listed on a widget template editor screen

Environment

  • Platform version: 7.2.7
  • Addon version: 3.2.3
  • Client type: Web
  • Browser: Chrome
  • Database: PostgreSQL
  • Operating system: Windows
    Additional widget parameters
  • Helium addon installed (v. 0.3.0)

Description of the bug or enhancement

  • Setup: Sample empty project with installed dashboard and helium addons
  • Expected: can create widget template
  • Actual behavior: see the following screenshot
    Screenshot_3

Exception when selecting an entity with non-UUID PK as widget parameter value

  • Open dashboard editor
  • Open Widget editor
  • Add parameter
  • Select the entity with non-uuid primary key (e.g. Long) as a parameter value

image

  • Close the parameter editor
  • Close the widget editor

AR: exception

Caused by: java.lang.IllegalArgumentException: Invalid UUID string: 2
	at java.util.UUID.fromString(UUID.java:194) ~[na:1.8.0_265]
	at com.haulmont.addon.dashboard.web.parametertransformer.ParameterTransformerImpl.loadEntity(ParameterTransformerImpl.java:76) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at com.haulmont.addon.dashboard.web.parametertransformer.ParameterTransformerImpl.transform(ParameterTransformerImpl.java:60) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at com.haulmont.addon.dashboard.web.repository.WidgetRepositoryImpl.getWidgetParams(WidgetRepositoryImpl.java:149) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at com.haulmont.addon.dashboard.web.dashboard.tools.componentfactory.CanvasUiComponentsFactory.createCanvasWidgetLayout(CanvasUiComponentsFactory.java:120) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at com.haulmont.addon.dashboard.web.dashboard.tools.componentfactory.CanvasDropComponentsFactory.createCanvasWidgetLayout(CanvasDropComponentsFactory.java:131) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at com.haulmont.addon.dashboard.web.dashboard.tools.DashboardModelConverter.modelToContainer(DashboardModelConverter.java:64) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at com.haulmont.addon.dashboard.web.dashboard.tools.DashboardModelConverter.initChilds(DashboardModelConverter.java:113) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at com.haulmont.addon.dashboard.web.dashboard.tools.DashboardModelConverter.modelToContainer(DashboardModelConverter.java:52) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at com.haulmont.addon.dashboard.web.dashboard.frames.editor.canvas.CanvasFrame.updateLayout(CanvasFrame.java:84) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at com.haulmont.addon.dashboard.web.dashboard.frames.editor.canvas.CanvasEditorFrame.updateLayout(CanvasEditorFrame.java:60) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at com.haulmont.addon.dashboard.web.dashboard.frames.editor.canvas.CanvasEditorFrame.onLayoutRefreshedEvent(CanvasEditorFrame.java:95) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_265]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_265]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_265]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_265]
	at com.haulmont.cuba.gui.events.sys.UiEventListenerMethodAdapter.doInvoke(UiEventListenerMethodAdapter.java:226) ~[cuba-gui-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.gui.events.sys.UiEventListenerMethodAdapter.processEvent(UiEventListenerMethodAdapter.java:151) ~[cuba-gui-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.gui.events.sys.UiEventListenerMethodAdapter.onApplicationEvent(UiEventListenerMethodAdapter.java:110) ~[cuba-gui-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.gui.events.sys.UiEventsMulticasterImpl.invokeListener(UiEventsMulticasterImpl.java:74) ~[cuba-gui-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.gui.events.sys.UiEventsMulticasterImpl.multicastEvent(UiEventsMulticasterImpl.java:67) ~[cuba-gui-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.web.sys.WebEvents.publish(WebEvents.java:31) ~[cuba-web-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.addon.dashboard.web.dashboard.frames.editor.DashboardEdit.lambda$onOpenWidgetEditor$9(DashboardEdit.java:415) ~[dashboard-web-3.2.0.BETA1.jar:na]
	at com.haulmont.bali.events.EventHub.publish(EventHub.java:170) ~[cuba-global-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.gui.screen.Screen.fireEvent(Screen.java:128) ~[cuba-gui-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.gui.screen.Screen.close(Screen.java:343) ~[cuba-gui-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.gui.components.AbstractEditor.closeWithCommit(AbstractEditor.java:432) ~[cuba-gui-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.gui.components.AbstractEditor.commitAndClose(AbstractEditor.java:446) ~[cuba-gui-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.gui.components.AbstractEditor.lambda$initCommitActions$1(AbstractEditor.java:104) ~[cuba-gui-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.bali.events.EventHub.publish(EventHub.java:170) ~[cuba-global-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.gui.components.actions.BaseAction.actionPerform(BaseAction.java:224) ~[cuba-gui-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.web.gui.components.WebButton.buttonClicked(WebButton.java:67) ~[cuba-web-7.2.0.BETA1.jar:7.2.0.BETA1]
	at com.haulmont.cuba.web.widgets.CubaButton.fireClick(CubaButton.java:76) ~[cuba-web-widgets-7.2.0.BETA1.jar:na]
	at com.vaadin.ui.Button$1.click(Button.java:57) ~[vaadin-server-8.9.2-0-cuba.jar:8.9.2-0-cuba]
	... 43 common frames omitted

ER: entities with any PK type should be supported

Forum topic: https://www.cuba-platform.ru/discuss/t/dashboard-i-entity-s-id-tipa-long/5078

Document message pack usage for @Dashboard annotation

Environment

  • Platform version: 7.0.x
  • Addon version: 3.0.3

Description of the bug or enhancement

Usage of message packs for @DasghboardWidget is not documented. It's not clear can they be used or not, and how.

In fact, dashboard addon able to use only global message packs and requires dashboard-widget prefix for these messages.

can not run

7.04 run error
11:59:18.034 ERROR c.h.c.c.s.AbstractWebAppContextLoader - Error initializing application
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘dashboard_uiComponentsFactory’: Lookup method resolution failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [com.haulmont.addon.dashboard.web.dashboard.tools.componentfactory.CanvasUiComponentsFactory] from ClassLoader [ParallelWebappClassLoader
context: lims
delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@7fc4780b
]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:265) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1269) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1184) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$21/316935832.getObject(Unknown Source) ~[na:na]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:849) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:144) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:95) ~[spring-context-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at com.haulmont.cuba.core.sys.CubaClassPathXmlApplicationContext.(CubaClassPathXmlApplicationContext.java:27) ~[cuba-global-7.0.4.jar:7.0.4]
at com.haulmont.cuba.core.sys.AbstractAppContextLoader.createApplicationContext(AbstractAppContextLoader.java:90) ~[cuba-global-7.0.4.jar:7.0.4]
at com.haulmont.cuba.core.sys.AbstractAppContextLoader.initAppContext(AbstractAppContextLoader.java:62) ~[cuba-global-7.0.4.jar:7.0.4]
at com.haulmont.cuba.core.sys.AbstractWebAppContextLoader.contextInitialized(AbstractWebAppContextLoader.java:78) ~[cuba-global-7.0.4.jar:7.0.4]
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4663) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5131) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14]
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:713) [catalina.jar:9.0.14]
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695) [catalina.jar:9.0.14]
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1133) [catalina.jar:9.0.14]
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1868) [catalina.jar:9.0.14]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_45]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_45]
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-util.jar:9.0.14]
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112) [na:1.8.0_45]
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:1045) [catalina.jar:9.0.14]
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:429) [catalina.jar:9.0.14]
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1577) [catalina.jar:9.0.14]
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:309) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:424) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:367) [catalina.jar:9.0.14]
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:934) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1382) [catalina.jar:9.0.14]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1372) [catalina.jar:9.0.14]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_45]
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-util.jar:9.0.14]
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) [na:1.8.0_45]
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:907) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:423) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:933) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14]
at org.apache.catalina.startup.Catalina.start(Catalina.java:637) [catalina.jar:9.0.14]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350) [bootstrap.jar:9.0.14]
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492) [bootstrap.jar:9.0.14]
Caused by: java.lang.IllegalStateException: Failed to introspect Class [com.haulmont.addon.dashboard.web.dashboard.tools.componentfactory.CanvasUiComponentsFactory] from ClassLoader [ParallelWebappClassLoader
context: lims
delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@7fc4780b
]
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:507) ~[spring-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:404) ~[spring-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:389) ~[spring-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:248) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
… 59 common frames omitted
Caused by: java.lang.NoClassDefFoundError: com/haulmont/cuba/gui/components/Component$Container
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_45]
at java.lang.ClassLoader.defineClass(ClassLoader.java:760) ~[na:1.8.0_45]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_45]
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2388) ~[catalina.jar:9.0.14]
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:850) ~[catalina.jar:9.0.14]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1312) ~[catalina.jar:9.0.14]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1173) ~[catalina.jar:9.0.14]
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_45]
at java.lang.ClassLoader.defineClass(ClassLoader.java:760) ~[na:1.8.0_45]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_45]
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2388) ~[catalina.jar:9.0.14]
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:850) ~[catalina.jar:9.0.14]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1312) ~[catalina.jar:9.0.14]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1173) ~[catalina.jar:9.0.14]
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_45]
at java.lang.ClassLoader.defineClass(ClassLoader.java:760) ~[na:1.8.0_45]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_45]
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2388) ~[catalina.jar:9.0.14]
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:850) ~[catalina.jar:9.0.14]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1312) ~[catalina.jar:9.0.14]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1173) ~[catalina.jar:9.0.14]
at java.lang.Class.getDeclaredMethods0(Native Method) ~[na:1.8.0_45]
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[na:1.8.0_45]
at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[na:1.8.0_45]
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:489) ~[spring-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
… 62 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.haulmont.cuba.gui.components.Component$Container
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1343) ~[catalina.jar:9.0.14]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1173) ~[catalina.jar:9.0.14]
… 87 common frames omitted

Add predefined roles

Environment

  • Platform version: 7.2.x
  • Addon version: 3.2.x

Description

Create predefined system roles

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.