jmix-projects / jmix-old

DEPRECATED. Use https://github.com/jmix-framework/jmix
16 stars 3 forks source link

Feature/user settings #375

Closed Flaurite closed 4 years ago

Flaurite commented 4 years ago

Description

Description in the ticket: jmix-framework/jmix#226

Coordinates

Add-on added to the starter-standard: io.jmix.starter.standard:jmix-starter-standard

Add-on coordinates: io.jmix.starter.ui.persistence:jmix-starter-ui-persistence

Screen descriptor API

The base API for screen components settings is placed into ScreenSettingsFacet. In the screen descriptor, we should add the following schema:

xmlns:settings="http://jmix.io/schema/ui/ui-data.xsd"

And now we able to add screen settings facet:

<facets>
    <settings:screenSettings id="settingsFacet" auto="true"/>
</facets>

By default when we just add given facet it applies and saves settings for all available components on the screen. We can configure facet to save only specific components using attribute auto=false:

<settings:screenSettings id="settingsFacet" auto="false">
    <settings:component id="usersTable"/>
</settings:screenSettings>

Note, that settingsEnabled attrbitue does not work for controller (screen) that extends Screen class. This property works only for Legacy screens.

Screen controller API

ScreenSettingsFacet provides hooks for the screen settings lifecycle:

Example of install delegate for appling settings ``` @Inject private ScreenSettingsFacet settingsFacet; @Install(to = "settingsFacet", subject = "applySettingsDelegate") private void applySettings(ScreenSettingsFacet.SettingsContext settings) { settings.getBoolean("myPanel", "visible") .ifPresent(myPanel::setVisible); // apply for others settingsFacet.applySettings(settings); } ```
Example if window contains lazy tab ``` @Inject private ScreenSettingsFacet settingsFacet; @Install(to = "settingsFacet", subject = "applySettingsDelegate") private void onApplySettings(ScreenSettingsFacet.SettingsContext context) { if (getWindow().equals(context.getSource())) { // if source is window settingsFacet.applySettings(context.getScreenSettings()); } else { // if source is lazy tab (accordion or tabSheet) settingsFacet.applySettings(context.getComponents(), context.getScreenSettings()); } } ```

ScreenSettings class

ScreenSettings - a base interface for putting and getting component settings. The default implementation is ScreenSettingsJson which uses JSON for storing settings. ScreenSettingsJson is a prototype bean so it can be easily replaced by another implementation.

ScreenSettings has methods for putting and getting base primitive types: String, Integer, Long, Double, Boolean

It also supports the whole POJO of settings for a specific component:

ScreenSettings put(ComponentSettings settings);

<T extends ComponentSettings> Optional<T> getSettings(String componentId, Class<T> settingsClass);

ComponentSettings as settings class for a component

There are components that have settings that can be applied for the component and stored. To make settings more clear it is possible to create some settings class (POJO). This class provides properties that can be applied for the component and easy to store. Just implement ComponentSettings interface:

GroupBoxSettings example ``` public class GroupBoxSettings implements ComponentSettings { protected String id; protected Boolean expanded; @Override public String getId() { return id; } @Override public void setId(String id) { this.id = id; } public Boolean getExpanded() { return expanded; } public void setExpanded(Boolean expanded) { this.expanded = expanded; } } ```

ComponentSettingsBinder as settings worker

Since we have ComponentSettings implementation we should bind it to the corresponding component. To achieve this we should create bean implementation of ComponentSettingsBinder. It will provide:

GroupBoxSettingsWorker example ``` @org.springframework.stereotype.Component(GroupBoxSettingsWorker.NAME) public class GroupBoxSettingsWorker implements ComponentSettingsWorker { public static final String NAME = "jmix_GroupBoxSettingsWorker"; @Override public Class getComponentClass() { return WebGroupBox.class; } @Override public Class getSettingsClass() { return GroupBoxSettings.class; } @Override public void applySettings(Component component, SettingsWrapper wrapper) { ... } @Override public boolean saveSettings(Component component, SettingsWrapper wrapper) { ... return true // or false it should depends from changes } @Override public ComponentSettings getSettings(Component component) { ... return settings; } } ```