|
| 1 | +//// |
| 2 | +Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH |
| 3 | + |
| 4 | +See the AUTHORS file(s) distributed with this work for additional information regarding authorship. |
| 5 | + |
| 6 | +This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. |
| 7 | +If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/ |
| 8 | +SPDX-License-Identifier: MPL-2.0 |
| 9 | +//// |
| 10 | + |
| 11 | += Card component generation |
| 12 | + |
| 13 | +== _Detailed schema overview_ |
| 14 | + |
| 15 | +NOTE: Before generating a card component refer to the xref:internationalization.adoc[internationalization] file. |
| 16 | + |
| 17 | +In the example, a brand-new application was generated using the command: |
| 18 | + |
| 19 | +[source] |
| 20 | +ng new app demo-schematics |
| 21 | + |
| 22 | +A schematics will be generated using the following command: |
| 23 | + |
| 24 | +[source] |
| 25 | +ng generate [collection-name]:[schematics-name] |
| 26 | + |
| 27 | + |
| 28 | +For demonstration purposes, the https://github.com/eclipse-esmf/esmf-aspect-model-editor/blob/main/core/apps/ame/src/assets/aspect-models/org.esmf.examples.movement/1.0.0/Movement.ttl[Movement.ttl] Aspect Model will be used. |
| 29 | +Below is a detailed representation of the command-line interface steps which generates a card component using the Movement.ttl Aspect Model file by running the command. |
| 30 | + |
| 31 | +NOTE: Before running any schematics commands make sure you are in the Angular project folder where you want to generate the new component. |
| 32 | + |
| 33 | +Component generation is achieved by running either of the following commands: |
| 34 | + |
| 35 | +[source] |
| 36 | +ng generate @esmf/semantic-ui-schematics:card |
| 37 | + |
| 38 | +[source] |
| 39 | +ng g @esmf/semantic-ui-schematics:card |
| 40 | + |
| 41 | +NOTE: The Angular folder where the component generation takes place should contain another folder with the .ttl files. |
| 42 | + |
| 43 | +=== _Load pre-existing configuration file_ |
| 44 | +After going through the wizard at least once, a config file will be |
| 45 | +auto-generated. The first prompt allows you to load a config file or start from scratch by loading one or multiple Aspect Model files. |
| 46 | + |
| 47 | +image::config-file-loading.png[width=100%] |
| 48 | + |
| 49 | +When you decide to create a new configuration file, you will be prompted to specify a name for your config file. This provided name will be integrated into the default naming structure for the config file. |
| 50 | + |
| 51 | +The naming structure is <config-file-name>-wizard.config.json. Here, <config-file-name> is the name that you provide when prompted. |
| 52 | + |
| 53 | +For example, if you enter myConfig when prompted for the config file name, your new config file will be named myConfig-wizard.config.json. |
| 54 | + |
| 55 | +image::schema.enter-name-for-config-file.png[width=100%] |
| 56 | + |
| 57 | +When you decide to load a pre-existing config file, the system will display the result as follows: |
| 58 | + |
| 59 | +image::schema.load-config-file.yes.png[width=100%] |
| 60 | + |
| 61 | +This will give access to the folder structure and by using a FUZZY search mechanism can provide the possibility to input the pre-existing config file. The config file will now be named based on your input _<config-file-name>_-wizard.config.json, and can be found in the root folder of the project. |
| 62 | + |
| 63 | +=== _Aspect Model selection_ |
| 64 | +If no pre-existing config file is loaded, then there is an option to choose for one or multiple Aspect Model files from the folder structure, using the same FUZZY search mechanism. |
| 65 | + |
| 66 | +image::schema.aspect-model-selection.png[width=100%] |
| 67 | + |
| 68 | +image::schema.another-aspect-model-selection.png[width=100%] |
| 69 | + |
| 70 | +=== _Entity or specific aspect selection_ |
| 71 | + |
| 72 | +An Aspect or an Entity must be chosen in order for the card to be created. This can be done in this step by choosing from a list. |
| 73 | + |
| 74 | +image::schema.aspect-or-entity-selection-card.png[width=100%] |
| 75 | + |
| 76 | +=== _Property exclusion_ |
| 77 | + |
| 78 | +Some properties may be omitted. This can be done in the following step. |
| 79 | + |
| 80 | +image::schema.exclude-properties.png[width=100%] |
| 81 | + |
| 82 | +=== _Default property sorting_ |
| 83 | + |
| 84 | +The card can sort based on a property. In this step the default one can be chosen. |
| 85 | + |
| 86 | +image::schema.default-sorting-property.png[width=100%] |
| 87 | + |
| 88 | +=== _Command bar_ |
| 89 | + |
| 90 | +The command bar is displayed above the cards, and it holds the controls for searching and filtering the data inside the card. This is shown only if the 'yes' option is chosen in the provided input. |
| 91 | + |
| 92 | +image::command-bar-prompt.png[width=100%] |
| 93 | + |
| 94 | +If you select to have a command bar, another prompt question will appear for selecting the additional functionality attached to it. |
| 95 | + |
| 96 | +image::command-bar-additional-functionalities.png[width=100%] |
| 97 | + |
| 98 | +In the example provided, only the search functionality will be available. |
| 99 | + |
| 100 | +image::search-bar.png[width=100%] |
| 101 | + |
| 102 | +The search input is present allowing you to filter the existing data in the card if the data is handled on the client side or request new data. This can be decided in the next steps. The filtered data will be displayed after pressing the `search` button next to the search field. |
| 103 | + |
| 104 | +NOTE: _The search input will filter the data `*ONLY*` by the existing `*STRING*` properties in the chosen Aspect Model._ |
| 105 | + |
| 106 | +Once the search functionality has been enabled, the next step is to choose the default language for remote access. This language selection determines the language used in the statement when accessing the system remotely. |
| 107 | + |
| 108 | +image::choose-language.png[width=100%] |
| 109 | + |
| 110 | +=== _Data handling_ |
| 111 | + |
| 112 | +After generating a component, you can pass the data from the parent to the child components and also the other way around. There is a prompt present which determines if the data should be handled on the client side or remote via an API call. |
| 113 | + |
| 114 | +image::remote-data-handling-prompt.png[width=100%] |
| 115 | + |
| 116 | +This means that any time you request data, an API endpoint will be called and the result coming from that endpoint will populate the card with a fresh set of data. |
| 117 | + |
| 118 | +=== _Component path_ |
| 119 | + |
| 120 | +Once all the prompts are answered, a card will be generated based on the selected options. The default path of the newly generated component is `*_src/app/shared/components/<component-name>_*`. |
| 121 | + |
| 122 | +[source] |
| 123 | +---- |
| 124 | +shared |
| 125 | +└─── components |
| 126 | + └─── <component-name> |
| 127 | + │ │ <component-name>.component.html |
| 128 | + │ │ <component-name>.component.scss |
| 129 | + │ │ <component-name>.component.ts |
| 130 | + │ │ <component-name>-command-bar.component.ts |
| 131 | + │ │ <component-name>-command-bar.component.html |
| 132 | + │ │ <component-name>-chip-list.component.ts |
| 133 | + │ │ <component-name>-chip-list.component.scss |
| 134 | + │ │ <component-name>-chip-list.component.html |
| 135 | + │ │ <component-name>.module.ts |
| 136 | + │ │ <component-name>.service.ts |
| 137 | + │ │ <component-name>-filter.service.ts |
| 138 | +---- |
| 139 | + |
| 140 | +=== _Persistent custom service_ |
| 141 | + |
| 142 | +By default, as seen above, a _<component-name>.service.ts_ file is auto-generated. This file is `*OVERRIDDEN*` each time a component is re-generated. |
| 143 | + |
| 144 | +Which is why we introduced another prompt question for a custom service generation which is `_persistent_` if the component is re-generated. |
| 145 | + |
| 146 | +image::custom-service.png[width=100%] |
| 147 | + |
| 148 | +If this option is selected, another file will show up in the folder structure. |
| 149 | + |
| 150 | +[source] |
| 151 | +---- |
| 152 | +shared |
| 153 | +└───components |
| 154 | + └─── <component-name> |
| 155 | + │ │ custom-<component-name>.service.ts |
| 156 | + │ │ <component-name>.component.html |
| 157 | + │ │ <component-name>.component.scss |
| 158 | + │ │ <component-name>.component.ts |
| 159 | + │ │ <component-name>-command-bar.component.ts |
| 160 | + │ │ <component-name>-command-bar.component.html |
| 161 | + │ │ <component-name>-chip-list.component.ts |
| 162 | + │ │ <component-name>-chip-list.component.scss |
| 163 | + │ │ <component-name>-chip-list.component.html |
| 164 | + │ │ <component-name>.module.ts |
| 165 | + │ │ <component-name>.service.ts |
| 166 | + │ │ <component-name>-filter.service.ts |
| 167 | +---- |
| 168 | + |
| 169 | +This file will be overridden `_ONLY_` if you choose to do so by providing the `--overwrite` option when starting the generation process. |
| 170 | + |
| 171 | +=== _Multiple version support_ |
| 172 | + |
| 173 | +An Aspect Model can have multiple versions. If this is the case, and you want to generate multiple components having different version, this can be done when this prompt question shows up: |
| 174 | + |
| 175 | +image::multi-version-support.png[width=100%] |
| 176 | + |
| 177 | +The folder structure will then change accordingly. |
| 178 | + |
| 179 | +[source] |
| 180 | +---- |
| 181 | +shared |
| 182 | +└───components |
| 183 | + └─── <component-version-0> |
| 184 | + │ └─── <component-name> |
| 185 | + │ │ │ custom-<component-name>.service.ts |
| 186 | + │ │ │ <component-name>.component.html |
| 187 | + │ │ │ <component-name>.component.scss |
| 188 | + │ │ │ <component-name>.component.ts |
| 189 | + │ │ │ <component-name>-command-bar.component.ts |
| 190 | + │ │ │ <component-name>-command-bar.component.html |
| 191 | + │ │ │ <component-name>-chip-list.component.ts |
| 192 | + │ │ │ <component-name>-chip-list.component.scss |
| 193 | + │ │ │ <component-name>-chip-list.component.html |
| 194 | + │ │ │ <component-name>.module.ts |
| 195 | + │ │ │ <component-name>.service.ts |
| 196 | + │ │ │ <component-name>-filter.service.ts |
| 197 | + └─── <component-version-1> |
| 198 | + │ └─── <component-name> |
| 199 | + │ │ │ custom-<component-name>.service.ts |
| 200 | + │ │ │ <component-name>.component.html |
| 201 | + │ │ │ <component-name>.component.scss |
| 202 | + │ │ │ <component-name>.component.ts |
| 203 | + │ │ │ <component-name>-command-bar.component.ts |
| 204 | + │ │ │ <component-name>-command-bar.component.html |
| 205 | + │ │ │ <component-name>-chip-list.component.ts |
| 206 | + │ │ │ <component-name>-chip-list.component.scss |
| 207 | + │ │ │ <component-name>-chip-list.component.html |
| 208 | + │ │ │ <component-name>.module.ts |
| 209 | + │ │ │ <component-name>.service.ts |
| 210 | + │ │ │ <component-name>-filter.service.ts |
| 211 | +---- |
| 212 | + |
| 213 | +=== _Material theme(Indigo pink)_ |
| 214 | + |
| 215 | +User can add to angular.json Indigo pink material theme. These action will appear in the actions column of the card. In the following prompt you can choose to add the Indigo pink material theme. |
| 216 | + |
| 217 | +image::material-theme-prompt.png[width=100%] |
| 218 | + |
| 219 | +In the generated angular.json card if user selected yes we can observe the change in styles array. |
| 220 | + |
| 221 | +image::angular-json-example.png[width=100%] |
| 222 | + |
| 223 | +=== _Set view encapsulation strategy for the generated card component_ |
| 224 | + |
| 225 | +User can set the View Encapsulation strategy by default the ViewEncapsulation will be set to None on the generated card component. In the following prompt you can choose to add another View Encapsulation value. |
| 226 | + |
| 227 | +image::view-encapsulation-prompt.png[width=100%] |
| 228 | + |
| 229 | +=== _Flags for generating the card_ |
| 230 | + |
| 231 | +By using |
| 232 | + |
| 233 | +[source] |
| 234 | +ng generate @esmf/semantic-ui-schematics:card --help |
| 235 | + |
| 236 | +or |
| 237 | + |
| 238 | +[source] |
| 239 | +ng g @esmf/semantic-ui-schematics:card --help |
| 240 | + |
| 241 | +you can get access to all the options encapsulated in the schema.json file. Each field has a description for a better understanding of it and how to use it. |
| 242 | + |
| 243 | +|=== |
| 244 | +|Flag |Description |Default |Type |
| 245 | +|_--add-command-bar_ |
| 246 | +|Flag to add the command bar |
| 247 | +|false |
| 248 | +|boolean |
| 249 | +|_--aspect-model-urn-to-load_ |
| 250 | +|Specify the Aspect Model for card generation |
| 251 | +|'' |
| 252 | +|string |
| 253 | +|_--change-detection_ |
| 254 | +|Change detection strategy for the generated angular component |
| 255 | +|'default' |
| 256 | +|enum |
| 257 | +|_--custom-remote-service_ |
| 258 | +|Generate _custom-<component-name>.service.ts_ file |
| 259 | +which is persistent and not overwritable in case the |
| 260 | +component is regenerated. |
| 261 | + |
| 262 | +This can be changed using the `_--overwrite_` flag |
| 263 | +Conditions: this flag appears only if the data is |
| 264 | +handled remotely. This is specified using the flag |
| 265 | +`_--enable-remote-data-handling_` |
| 266 | +|false |
| 267 | +|boolean |
| 268 | +|_--enable-remote-data-handling_ |
| 269 | +|Flag used to choose how to handle the data, pagination, sorting or filtering. |
| 270 | + |
| 271 | +(client-side or remote) |
| 272 | +|false |
| 273 | +|boolean |
| 274 | +|_--enable-version-support_ |
| 275 | +|Multiple versions support for different version of an |
| 276 | + |
| 277 | +Aspect Model |
| 278 | +|false |
| 279 | +|boolean |
| 280 | +|_--json-access-path_ |
| 281 | +|Enter the access path in the JSON payload e.g. position |
| 282 | +|'' |
| 283 | +|string |
| 284 | +|_--overwrite_ |
| 285 | +|Overwrite existing files |
| 286 | +|true |
| 287 | +|boolean |
| 288 | +|_--selected-model-element-urn_ |
| 289 | +|Choose a specific Entity or Aspect to show as card |
| 290 | +|'' |
| 291 | +|string |
| 292 | +|_--ttl_ |
| 293 | +|Path for the Aspect Model files |
| 294 | +|[] |
| 295 | +|string[] |
| 296 | +|=== |
| 297 | + |
| 298 | +## Customize the date format |
| 299 | + |
| 300 | +Various date formats can be configured e.g. for the date filter and the corresponding chip label. |
| 301 | + |
| 302 | +Set the desired default format for dates in the app.component.ts: |
| 303 | + |
| 304 | + constructor(@Inject(MAT_DATE_FORMATS) private dateFormats: MatDateFormats) { |
| 305 | + this.dateFormats.display.dateInput = 'DD.MMM.YYYY'; |
| 306 | + this.dateFormats.display.monthYearLabel = 'MMM YYYY'; |
| 307 | + this.dateFormats.display.dateA11yLabel = 'LL'; |
| 308 | + this.dateFormats.display.monthYearA11yLabel = 'MMMM YYYY'; |
| 309 | + } |
| 310 | + |
| 311 | +Make sure moment.js and dateAdaptor are correctly installed |
| 312 | + |
| 313 | +## Set default language |
| 314 | + |
| 315 | +In app.component.ts, it is required to set the default language: |
| 316 | + |
| 317 | + constructor(lang: TranslateService) { |
| 318 | + lang.use(lang.defaultLang); |
| 319 | + } |
| 320 | + |
| 321 | +--- |
| 322 | + |
| 323 | +## Add custom content template |
| 324 | + |
| 325 | +In the app.component.ts you can determine the content of the cards yourself: |
| 326 | + |
| 327 | + <esmf-ui-cards [data]="data"> |
| 328 | + <ng-template #cardTemplate let-data let-element="cardValues" let-getElementValue="getElementValue" let-translateService="translateService"> |
| 329 | + <div class="data-card-element" *ngFor="let elem of element"> |
| 330 | + <b>{{ translateService.instant(elem + '.preferredName') }}</b>: {{ getElementValue(data, elem) }} |
| 331 | + </div> |
| 332 | + </ng-template> |
| 333 | + </esmf-ui-cards> |
| 334 | + |
| 335 | +The ng-tempalte values can be used from the child componente or can be determined by the user. |
| 336 | + |
| 337 | +--- |
| 338 | + |
| 339 | + |
0 commit comments