3.7.3. User Preferences
Steps to implement the feature
In order to implement this feature take the following steps:
Add the object with name UserPreferences to model.xml by copying the content of user-preferences-object.xml. into 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.
Add the highlighted code to the package metadata in 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>
Add the highlighted line to 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>
Generate the Runtime Model with the Runtime Model buildset.
Generate all
Have Liquibase create the UserPreferences table upon startup of the application:
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:
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" />
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:
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>
Add the project specific user preferences to model.xml:
User preferences can be added to attributes and references.
Attributes
For each attribute of an object that you would like to be initially set to a user preference, perform the following steps:
Add <user.preferences /> to the existing attribute.
Add a new attribute to the UserPreferences object with the name [object.name?uncap_first][attribute.name?cap_first], e.g. hourAmount.
Add metadata to the new attribute in the UserPreferences object:
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>
Add code to [project]-metafactory\src\snippets\[frontend]\owner\edit\edit-template-userpreferences.ftl to generate the rendering of the newly added user preference.
<@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.
Add a changeSet for the creation of the newly added project specific user preferences attribute at the end of liquibase-alters-changeLog.xml.
References
For each reference of an object that you would like to be initially set to a user preference, perform the following steps:
Add <user.preferences /> to the reference that you would like to be initially set to a user preference.
Add a reference to the UserPreferences object with the name [object.name?uncap_first][reference.name?cap_first], e.g. hourTask.
Add metadata to this reference:
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>
Add code to [project]-metafactory\src\snippets\[frontend]\owner\edit\edit-template-userpreferences.ftl to generate the rendering of the newly added user preference.
<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.
Add a changeSet for the creation of the newly added project specific user preferences reference at the end of liquibase-alters-changeLog.xml.
Generate the Runtime Model with the Runtime Model buildset.
Generate all
Translate User Preferences
[project]\[frontend]\src\main\webapp\i18n\en\userpreferences.json
[project]\[frontend]\src\main\webapp\i18n\nl\userpreferences.json
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.
Run the application
3.7.3.1. Files
In this section you can find the files you can use in implementing the feature.
<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.