Customizing users edit screen

Hi Team ,

currently while overriding users screen to customize it as per our application requirements below is our current screen

User Entity


@Extends(User.class)
@Entity(name = "vtower_VTowerUser")
public class VTowerUser extends User {
    private static final long serialVersionUID = -5523663666385193410L;

    @NotNull
    @Column(name = "CAN_BE_ASSIGNED_TO_COUNTRY", nullable = false)
    protected Boolean canBeAssignedToCountry = false;

    @NotNull
    @Column(name = "IS_EMPLOYEE", nullable = false)
    protected Boolean isEmployee = false;

    @NotNull
    @Column(name = "IS_GLOBAL_USER", nullable = false)
    protected Boolean isGlobalUser = false;

    @Composition
    @OnDelete(DeletePolicy.CASCADE)
    @OneToMany(mappedBy = "user")
    protected List<OrganizationAssignableUser> assignableOrganizations;

    @Composition
    @OnDelete(DeletePolicy.CASCADE)
    @OneToMany(mappedBy = "user")
    protected List<LegalEntityUser> entities;

    @Composition
    @OnDelete(DeletePolicy.CASCADE)
    @OneToMany(mappedBy = "user")
    protected List<OrganizationUser> organizations;

    @Composition
    @OnDelete(DeletePolicy.CASCADE)
    @OneToMany(mappedBy = "user")
    protected List<CountryUser> countries;

    public List<CountryUser> getCountries() {
        return countries;
    }

    public void setCountries(List<CountryUser> countries) {
        this.countries = countries;
    }

    public List<OrganizationUser> getOrganizations() {
        return organizations;
    }

    public void setOrganizations(List<OrganizationUser> organizations) {
        this.organizations = organizations;
    }

    public List<LegalEntityUser> getEntities() {
        return entities;
    }

    public void setEntities(List<LegalEntityUser> entities) {
        this.entities = entities;
    }

    public List<OrganizationAssignableUser> getAssignableOrganizations() {
        return assignableOrganizations;
    }

    public void setAssignableOrganizations(List<OrganizationAssignableUser> assignableOrganizations) {
        this.assignableOrganizations = assignableOrganizations;
    }

    public Boolean getCanBeAssignedToCountry() {
        return canBeAssignedToCountry;
    }

    public void setCanBeAssignedToCountry(Boolean canBeAssignedToCountry) {
        this.canBeAssignedToCountry = canBeAssignedToCountry;
    }

    public Boolean getIsEmployee() {
        return isEmployee;
    }

    public void setIsEmployee(Boolean employee) {
        isEmployee = employee;
    }

    public Boolean getIsGlobalUser() {
        return isGlobalUser;
    }

    public void setIsGlobalUser(Boolean globalUser) {
        isGlobalUser = globalUser;
    }
}

XML

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
        xmlns:ext="http://schemas.haulmont.com/cuba/window-ext.xsd"
        class="com.vtss.vtower.web.screens.user.VTowerUserEditor"
        extends="com/haulmont/cuba/gui/app/security/user/edit/user-edit.xml"
        messagesPack="com.vtss.vtower.web.screens.user">
    <dsContext>
        <datasource id="userDs" class="com.vtss.vtower.entity.user.VTowerUser" view="vtower-user-base-edit">
            <collectionDatasource id="assignableOrganizationsDs" property="assignableOrganizations"/>
        </datasource>
        <collectionDatasource id="applicationRoleTemplatesDs" class="com.vtss.vtower.entity.approle.ApplicationRoleTemplate"
                              datasourceClass="com.vtss.vtower.web.screens.user.datasource.ApplicationRoleTemplateCollectionDatasource"
                              view="application-role-template-base-view"/>
    </dsContext>
    <actions>
        <action id="applyRolesTemplate" invoke="onApplyRolesTemplate"/>
        <action id="revokeRolesTemplate" invoke="onRevokeRolesTemplate"/>
    </actions>
    <dialogMode height="600" width="800"/>
    <layout expand="scrollBox">

        <groupBox id="propertiesBox" spacing="true">
            <grid id="propertiesGrid">
                <rows>
                    <row id="propertiesRow">
                        <fieldGroup id="fieldGroupLeft">
                            <column>
                                <field id="login" editable="false"/>
                                <field id="passw" visible="false"/>
                                <field id="confirmPassw" visible="false"/>
                                <field id="firstName" visible="false"/>
                                <field id="middleName" visible="false"/>
                                <field id="lastName" visible="false"/>
                                <field ext:index="7" id="timeZone" custom="true"/>
                                <field ext:index="8" id="active" property="active"/>
                                <field ext:index="9" id="ipMask" property="ipMask"/>
                                <field id="email" visible="false"/>
                            </column>
                        </fieldGroup>
                        <fieldGroup id="fieldGroupRight">
                            <column>
                                <field id="group" visible="false"/>
                                <field id="position" visible="false"/>
                                <field id="language" visible="false"/>
                                <field id="timeZone" visible="false"/>
                                <field id="ipMask" visible="false"/>
                                <field id="active" visible="false"/>
                                <field id="canBeAssignedToCountry" property="canBeAssignedToCountry"/>
                                <field id="isGlobalUser" property="isGlobalUser"/>
                                <field id="isEmployee" property="isEmployee"/>
                            </column>
                        </fieldGroup>
                    </row>
                </rows>
            </grid>
            <lookupField id="rolesTemplateId" caption="Roles Template" optionsDatasource="applicationRoleTemplatesDs"
                         width="350px"/>
            <buttonsPanel id="roleTemplateActionsPnl" enable="false">
                <button id="applyTemplateBtn" action="applyRolesTemplate" caption="msg://action.apply.role" enable="false" stylename="primary"/>
                <button id="revokeTemplateBtn" action="revokeRolesTemplate" caption="msg://action.revoke.role" enable="false" stylename="friendly"/>
            </buttonsPanel>
        </groupBox>
        <scrollBox id="scrollBox" height="300px" ext:index="1">
            <hbox height="400px" spacing="true" width="100%" >
                <groupBox caption="msg://roles" spacing="true">
                    <table id="extendedRolesTable" width="100%" stylename="borderless">
                        <actions>
                            <action id="create" openType="DIALOG"/>
                            <action id="remove"/>
                        </actions>
                        <columns/>
                        <rows datasource="rolesDs"/>
                        <rowsCount/>
                        <buttonsPanel id="buttonsPanel" alwaysVisible="true">
                            <button id="createBtn" action="extendedRolesTable.create" stylename="primary"/>
                            <button id="removeBtn" action="extendedRolesTable.remove" stylename="danger"/>
                        </buttonsPanel>
                    </table>
                </groupBox>
                <groupBox id="assignableOrganizationsGroupbox" caption="msg://assignable-organizations">
                    <table id="extendedAssignableOrganizationsTable" width="100%" stylename="borderless">
                        <actions>
                            <action id="create" openType="DIALOG"/>
                            <action id="remove"/>
                        </actions>
                        <columns>
                            <column id="organization"/>
                        </columns>
                        <rows datasource="assignableOrganizationsDs"/>
                        <rowsCount/>
                        <buttonsPanel alwaysVisible="true">
                            <button id="createBtn1" action="extendedAssignableOrganizationsTable.create" stylename="primary"/>
                            <button id="removeBtn1" action="extendedAssignableOrganizationsTable.remove" stylename="danger"/>
                        </buttonsPanel>
                    </table>
                </groupBox>
            </hbox>
        </scrollBox>
        <split id="split" visible="false"/>
    </layout>
</window>

Controller


public class VTowerUserEditor extends UserEditor {

    @Inject
    private Table<UserRole> extendedRolesTable;

    @Inject
    private GroupBoxLayout assignableOrganizationsGroupbox;

    @Inject
    private ApplicationRoleTemplateCollectionDatasource applicationRoleTemplatesDs;

    @Inject
    private LookupField<ApplicationRoleTemplate> rolesTemplateId;

    @Inject
    private ButtonsPanel roleTemplateActionsPnl;

    @Inject
    private UserService userService;

    @Named("fieldGroupLeft.login")
    private TextField<String> login;



    @Override
    public void init(Map<String, Object> params) {
        refreshRolesTemplateLKP(params);
        rolesTemplateId.addValueChangeListener(tempId -> {
            if (Objects.nonNull(tempId.getValue())) {
                roleTemplateActionsPnl.setEnabled(true);
            } else {
                roleTemplateActionsPnl.setEnabled(false);
            }
        });
        rolesDs.addItemChangeListener(e -> {
            if(rolesDs.getItem() != null) {
                if (rolesDs.getItem().getRole().getDefaultRole() != null && rolesDs.getItem().getRole().getDefaultRole()) {
                    extendedRolesTable.getAction("remove").setEnabled(false);
                } else {
                    extendedRolesTable.getAction("remove").setEnabled(true);
                }
            }
        });
        CreateAction roleCreate = ((CreateAction) extendedRolesTable.getAction("create"));
        roleCreate.setWindowId("sec$UsersRole.edit");
        roleCreate.setWindowParams(ParamsMap.of(Constants.APPLICATION_ROLE_TYPE_PARAM, params.get(Constants.APPLICATION_ROLE_TYPE_PARAM)));
        passwField.setVisible(false);
        confirmPasswField.setVisible(false);
        passwField.setRequired(false);
        confirmPasswField.setRequired(false);
        fieldGroupLeft.getField("name").setRequired(true);
        fieldGroupRight.getField("isEmployee").setEditable(false);
        if (PersistenceHelper.isNew(params.get("ITEM"))) {
            User user = ((User)params.get("ITEM"));
            login.setEditable(true);
            login.addValueChangeListener(e -> {
                if (!Pattern.compile(Constants.EMAIL).matcher(login.getRawValue()).matches()) {
                    login.setValue(null);
                    frame.showNotification("Invalid Email");
                } else {
                    user.setEmail(e.getValue());
                }

            });
            fieldGroupLeft.getField("active").setEditable(false);
            user.setGroup(userService.getStandardGroup());
        }
        FieldGroup.FieldConfig canBeAssignedToCounty = fieldGroupRight.getField("canBeAssignedToCountry");
        FieldGroup.FieldConfig isGlobalUser = fieldGroupRight.getField("isGlobalUser");
        FieldGroup.FieldConfig isEmployee = fieldGroupRight.getField("isEmployee");
        if (params.containsKey("OPENED_FROM")) {
            fieldGroupLeft.getField("ipMask").setVisible(false);
            canBeAssignedToCounty.setVisible(false);
            isGlobalUser.setVisible(false);
            isEmployee.setVisible(false);
            assignableOrganizationsGroupbox.setVisible(false);

            if (PersistenceHelper.isNew(params.get("ITEM"))) {
                switch ((String) params.get("OPENED_FROM")) {
                    case "COUNTRY":
                        ((HasValue) canBeAssignedToCounty.getComponent()).setValue(true);
                    case "GLOBAL":
                        ((HasValue) isGlobalUser.getComponent()).setValue(true);
                }
            }
        } else {
            VTowerUser user = (VTowerUser) AppBeans.get(UserSessionSource.class).getUserSession().getUser();
            Boolean isSuperAdmin = user.getUserRoles().stream().anyMatch(userRole -> userRole.getRole().getType() == RoleType.SUPER);
            if(!isSuperAdmin){
                if(!user.getCanBeAssignedToCountry()){
                    canBeAssignedToCounty.setEditable(false);
                }
                if(!user.getIsGlobalUser()){
                    isGlobalUser.setEditable(false);
                }
            }
        }
    }


    private void refreshRolesTemplateLKP(Map<String, Object> params) {
        if (params.containsKey(Constants.ENTITY_PARAM)) {
            applicationRoleTemplatesDs.refresh(ParamsMap.of(Constants.APPLICATION_ROLE_TYPE_PARAM, params.get(Constants.APPLICATION_ROLE_TYPE_PARAM), Constants.ENTITY_PARAM, params.get(Constants.ENTITY_PARAM)));
        } else if (params.containsKey(Constants.APPLICATION_ROLE_TYPE_PARAM)) {
            applicationRoleTemplatesDs.refresh(ParamsMap.of(Constants.APPLICATION_ROLE_TYPE_PARAM, params.get(Constants.APPLICATION_ROLE_TYPE_PARAM), Constants.ORGANIZATION_PARAM, params.get(Constants.ORGANIZATION_PARAM)));
        } else {
            applicationRoleTemplatesDs.refresh(ParamsMap.of(Constants.APPLICATION_ROLE_TYPE_PARAM, params.get(Constants.APPLICATION_ROLE_TYPE_PARAM)));
        }
    }

    @Override
    protected void createTimeZoneField() {
        FieldGroup.FieldConfig timeZoneFc = fieldGroupLeft.getFieldNN("timeZone");

        HBoxLayout hbox = uiComponents.create(HBoxLayout.class);
        hbox.setSpacing(true);

        timeZoneLookup = uiComponents.create(LookupField.TYPE_STRING);

        timeZoneLookup.setDatasource(timeZoneFc.getTargetDatasource(), timeZoneFc.getProperty());
        timeZoneLookup.setRequired(false);

        MetaClass userMetaClass = userDs.getMetaClass();
        timeZoneLookup.setEditable(fieldGroupRight.isEditable()
                && security.isEntityAttrUpdatePermitted(userMetaClass, timeZoneFc.getProperty()));

        Map<String, String> options = new TreeMap<>();
        for (String id : TimeZone.getAvailableIDs()) {
            TimeZone timeZone = TimeZone.getTimeZone(id);
            options.put(timeZones.getDisplayNameLong(timeZone), id);
        }
        timeZoneLookup.setOptionsMap(options);

        hbox.add(timeZoneLookup);

        CheckBox autoDetectField = uiComponents.create(CheckBox.class);
        autoDetectField.setDatasource(timeZoneFc.getTargetDatasource(), "timeZoneAuto");
        autoDetectField.setCaption(messages.getMainMessage("timeZone.auto"));
        autoDetectField.setDescription(messages.getMainMessage("timeZone.auto.descr"));
        autoDetectField.setAlignment(Alignment.MIDDLE_RIGHT);

        autoDetectField.setEditable(fieldGroupRight.isEditable()
                && security.isEntityAttrUpdatePermitted(userMetaClass, "timeZoneAuto"));

        hbox.add(autoDetectField);
        hbox.expand(timeZoneLookup);

        timeZoneFc.setComponent(hbox);
    }

    @Override
    protected void createGroupField() {
        super.createGroupField();
        fieldGroupRight.getFieldNN("group").setVisible(false);
    }

    @Override
    protected void createLanguageLookup() {
        super.createLanguageLookup();
        fieldGroupRight.getFieldNN("language").setVisible(false);
    }


    public void onApplyRolesTemplate(Component source) {
        User user = getItem();
        rolesTemplateId.getValue().getTemplateLines().forEach(applicationRoleTemplateLine -> {
            if(!rolesDs.getItems().stream().anyMatch(userRole -> userRole.getRole().equals(applicationRoleTemplateLine.getRole()))) {
                UserRole role = metadata.create(UserRole.class);
                role.setUser(user);
                role.setRole(applicationRoleTemplateLine.getRole());
                rolesDs.addItem(role);
            }
        });
    }

    public void onRevokeRolesTemplate(Component source) {
        User user = getItem();
        rolesTemplateId.getValue().getTemplateLines().forEach(applicationRoleTemplateLine -> {
            UserRole role = rolesDs.getItems().stream().filter(userRole -> userRole.getRole().equals(applicationRoleTemplateLine.getRole())).findFirst().orElse(null);
            if(role != null){
                rolesDs.removeItem(role);
            }
        });
    }
}

currently i’m getting null pointer exception exactly on passwField while trying to create new user , our application current version is 7.2.1 although on old version of the application when we have version 6.10 every thing was working fine

Thanks

Hi,

If you investigate source code of the UserEditor class in CUBA 7.2, you’ll find that passwField is initialized in the UserEditor#createPasswordFields method which is called from the UserEditor#init method.

As I can see, in the VTowerUserEditor you have completely overridden init() method - therefore createPasswordFields() is not called, and passwField attribute is not initialized.

1 Like