3.7.3. User Preferences

Steps to implement the feature

In order to implement this feature take the following steps:

  1. Add the object with name UserPreferences to model.xml by copying the content of user-preferences-object.xml. into model.xml.

    Listing 3.15 model.xml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    <model>
            <package>
                    <metadata>
                            ...
                    </metadata>
                    ...
                    <object name="UserPreferences">
                            ...
                    </object>
            </package>
    </model>
    

    Note

    If you are reading this documentation on paper you can find the file in the next section Files.

  2. Add the highlighted code to the package metadata in model.xml:

    Listing 3.16 model.xml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    <model>
            <package>
                    <metadata>
                    ...
                            <owner>
                                    <keyword>Owner</keyword>
                                    <role>USER</role>
                                    <url.prefix>owner</url.prefix>
                            </owner>
                    </metadata>
            </package>
            ...
    </model>
    
  3. Add the highlighted line to pattern.xml:

    Listing 3.17 pattern.xml
    1
    2
    3
    4
    5
    <pattern>
            ...
            <external.file id="libJH/jhipster620_angular800/frontend/webapp/app/account/preferences_route_ts.xml" skip="false" />
            ...
    </pattern>
    
  4. Generate the Runtime Model with the Runtime Model buildset.

  5. Generate all

  6. Have Liquibase create the UserPreferences table upon startup of the application:


Copy the two changeSets in the generated changeset-create-table-user_preferences.xml to the end of
[project]\[backend]\src\main\resources\config\liquibase\liquibase-alters-changeLog.xml
for the creation of the UserPreferences table.

Listing 3.18 liquibase-alters-changeLog.xml
1
2
3
4
5
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog>
        ...
        [insert changesets here]
</databaseChangeLog>

In liquibase-alters-changeLog.xml replace referencedTableName=”user” with referencedTableName=”jhi_user” in the highlighted line:

Listing 3.19 liquibase-alters-changeLog.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<addForeignKeyConstraint
        baseColumnNames="user_id"
        baseTableName="user_preferences"
        constraintName="fk_user_preferences_user_id_to_user"
        deferrable="false"
        initiallyDeferred="false"
        onDelete="NO ACTION"
        onUpdate="NO ACTION"
        referencedColumnNames="id"
        referencedTableName="user"
/>
  1. Adjust the custom file generated for the user preferences Angular component:

    • [project]-metafactory\src\snippets\[frontend]\owner\edit\edit-component-userpreferences.ftl

      Add the parameter this.id to the getMyUserPreferencesEditDto call:

      Listing 3.20 edit-component-userpreferences.ftl
      1
      2
      3
      4
      5
      6
      7
      8
      9
      <#assign onInitCode>
      ngOnInit() {
              // EDIT: retrieve the instance of this UserPreferences
              this.subs.sink = this.ownerUserPreferencesService.getMyUserPreferencesEditDto(this.id).subscribe((data: OwnerUserPreferencesEditDto) => {
                      this.ownerUserPreferencesEditDto = data;
                      this.buildFormGroup();
              });
      }
      </#assign>
      
  2. Add the project specific user preferences to model.xml:

    User preferences can be added to attributes and references.

    1. Attributes

      For each attribute of an object that you would like to be initially set to a user preference, perform the following steps:

      1. Add <user.preferences /> to the existing attribute.

      2. Add a new attribute to the UserPreferences object with the name [object.name?uncap_first][attribute.name?cap_first], e.g. hourAmount.

      3. Add metadata to the new attribute in the UserPreferences object:

        Listing 3.21 model.xml
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        <object name="UserPreferences">
                ...
                <attribute>
                        <metadata>
                                <edit.owner.row2>
                                        <col1>label</col1>
                                        <col1.colspan>3</col1.colspan>
                                        <col2>widget</col2>
                                        <col2>
                                                <colspan>3</colspan>
                                        </col2>
                                </edit.owner.row2>
                        </metadata>
                </attribute>
        </object>
        
      4. Add code to [project]-metafactory\src\snippets\[frontend]\owner\edit\edit-template-userpreferences.ftl to generate the rendering of the newly added user preference.

        Listing 3.22 edit-template-userpreferences.ftl for rendering an attribute
        <@generalMaterial.renderField false ''>
                <@generalMaterial.renderFieldLabel userPreferences.[attribute.name] metadataKey tsUserPreferences />
                <@generalMaterial.renderFieldBody wrapDivField=true wrapSecondDivField=true>
                        <@am.renderFormGroup userPreferences.[attribute.name]>
                                <@am.renderEdit userPreferences.[attribute.name] metadataKey tsUserPreferences />
                        </@am.renderFormGroup>
                </@generalMaterial.renderFieldBody>
        </@generalMaterial.renderField>
        

        Replace [attribute.name] with the attribute name as defined in the UserPreferences object, e.g. hourAmount.

      5. Add a changeSet for the creation of the newly added project specific user preferences attribute at the end of liquibase-alters-changeLog.xml.

    2. References

      For each reference of an object that you would like to be initially set to a user preference, perform the following steps:

      1. Add <user.preferences /> to the reference that you would like to be initially set to a user preference.

      2. Add a reference to the UserPreferences object with the name [object.name?uncap_first][reference.name?cap_first], e.g. hourTask.

      3. Add metadata to this reference:

        Listing 3.23 model.xml
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        <object name="UserPreferences">
                ...
                <reference>
                        <metadata>
                                <edit.owner.row2>
                                        <col1>label</col1>
                                        <col1.colspan>3</col1.colspan>
                                        <col2>widget</col2>
                                        <col2>
                                                <colspan>3</colspan>
                                        </col2>
                                </edit.owner.row2>
                        </metadata>
                </reference>
        </object>
        
      4. Add code to [project]-metafactory\src\snippets\[frontend]\owner\edit\edit-template-userpreferences.ftl to generate the rendering of the newly added user preference.

        Listing 3.24 edit-template-userpreferences.ftl for rendering a reference
        <ng-container *ngIf="parentContext===undefined || parentContext.parentReference!='[reference.name]'">
                <@generalMaterial.renderField>
                        <@generalMaterial.renderFieldLabel    userPreferences.[reference.name] metadataKey tsUserPreferences />
                        <@generalMaterial.renderFieldBody wrapDivField=true>
                                <@am.renderFormGroup userPreferences.[reference.name]>
                                        <@am.renderEdit userPreferences.[reference.name] metadataKey tsUserPreferences />
                                </@am.renderFormGroup>
                        </@generalMaterial.renderFieldBody>
                </@generalMaterial.renderField>
        </ng-container>
        

        Replace [reference.name] with the reference name as defined in the UserPreferences object, e.g. hourTask.

      5. Add a changeSet for the creation of the newly added project specific user preferences reference at the end of liquibase-alters-changeLog.xml.

    3. Generate the Runtime Model with the Runtime Model buildset.

    4. Generate all

  3. Translate User Preferences

    • [project]\[frontend]\src\main\webapp\i18n\en\userpreferences.json

    • [project]\[frontend]\src\main\webapp\i18n\nl\userpreferences.json

  4. Add menu item for User Preferences to the project’s top menu:

    Different projects have different top menu’s. So adding a menu item for User Preferences requires manual addition.

  5. Run the application

3.7.3.1. Files

In this section you can find the files you can use in implementing the feature.

Listing 3.25 user-preferences-object.xml
<object name="UserPreferences">
	<metadata>
		<application.angular>true</application.angular>
		<class.jpa.type>entity</class.jpa.type>
		<createAngularFactories>true</createAngularFactories>
		<createAngularRoute>true</createAngularRoute>
		<createFixture>true</createFixture>
		<createPojo>true</createPojo>
		<createRepository>true</createRepository>
		<createSearchDto>true</createSearchDto>
		<createService>true</createService>
		<createTranslationTemplate>true</createTranslationTemplate>
		<crud>
			<batch.delete>false</batch.delete>
			<save.and.create>false</save.and.create>
		</crud>
		<display>
			<field>user</field>
			<format>%1$s</format>
		</display>
		<dto>owner</dto>
		<dto.owner>
			<keyword>Owner</keyword>
			<prefix>my</prefix>
			<role>USER</role>
			<url.prefix>owner</url.prefix>
		</dto.owner>
		<edit>owner</edit>
		<edit.owner>
			<columnCount>6</columnCount>
			<createCustomComponent>true</createCustomComponent>
			<createCustomLayout>true</createCustomLayout>
			<defaultFocus>row1.col2</defaultFocus>
			<displayMode>page</displayMode>
			<ngmodel>userPreferences</ngmodel>
			<propertyprefix>edit.owner</propertyprefix>
			<renderSmall>true</renderSmall>
			<rowCount>4</rowCount>
			<serial.version>1L</serial.version>
		</edit.owner>
		<enum>false</enum>
		<filters.include.null>false</filters.include.null>
		<find>
			<as.selectable.dto>false</as.selectable.dto>
			<by>
				<autocomplete>false</autocomplete>
				<autocomplete.dto>false</autocomplete.dto>
			</by>
		</find>
		<isCouplingEntity>false</isCouplingEntity>
		<jpa.annotation.class>javax.persistence.Entity</jpa.annotation.class>
		<list.owner.excel.createExport>false</list.owner.excel.createExport>
		<name.plural>UserPreferences</name.plural>
		<overview.uses.paging>true</overview.uses.paging>
		<search>false</search>
		<search.tab>false</search.tab>
		<serialVersionUID>0</serialVersionUID>
		<show>
			<detail.crudButtons>false</detail.crudButtons>
			<overview.crudButtons>false</overview.crudButtons>
		</show>
	</metadata>
	<reference name="user" type="User" multiplicity="1..1" notnull="true">
		<metadata>
			<create.finder.method.single>true</create.finder.method.single>
			<crud.create.from.edit>false</crud.create.from.edit>
			<dto.owner.edit.render.custom.display.field>false</dto.owner.edit.render.custom.display.field>
			<edit.owner>
				<render.with.grouping>false</render.with.grouping>
				<row1>
					<col1>label</col1>
					<col1.colspan>3</col1.colspan>
					<col2>widget</col2>
					<col2.colspan>3</col2.colspan>
				</row1>
			</edit.owner>
			<jpa>
				<fetchType>lazy</fetchType>
				<mapsid>false</mapsid>
				<onetoone.owner>true</onetoone.owner>
				<relation>OneToOne</relation>
			</jpa>
			<search.for.null.value>false</search.for.null.value>
		</metadata>
	</reference>
</object>

3.7.3.2. Developer notes

Important

For projects that do not have a UserPreferences object in model.xml yet, the aim is to generate no user preferences related code.

For projects like AMI that do have a UserPreferences object in model.xml, the aim is to let AMI’s custom patterns/snippets generate all user preferences related code, so no significant outgoing changes should occur.