@provoly/dashboard 1.3.7 → 1.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/admin/components/admin-classes/admin-classes-view/admin-attributes-form/admin-attributes-form.component.d.ts +5 -2
  2. package/admin/components/admin-fields/admin-fields-form/admin-fields-form.component.d.ts +47 -18
  3. package/admin/components/admin-fields/admin-fields-select/admin-fields-select.component.d.ts +6 -2
  4. package/admin/components/admin-fields/admin-fields.component.d.ts +4 -1
  5. package/admin/components/admin-fields/store/admin-fields.model.d.ts +1 -1
  6. package/admin/components/admin-fields/store/fields.actions.d.ts +19 -12
  7. package/admin/components/admin-fields/store/fields.effects.d.ts +16 -3
  8. package/admin/i18n/en.translations.d.ts +33 -14
  9. package/admin/i18n/fr.translations.d.ts +33 -14
  10. package/components/checkbox/checkbox.component.d.ts +4 -2
  11. package/components/data-format/data-format.pipe.d.ts +11 -1
  12. package/components/paginator/index.d.ts +5 -0
  13. package/components/paginator/paginator.component.d.ts +19 -0
  14. package/components/paginator/paginator.module.d.ts +10 -0
  15. package/components/paginator/public-api.d.ts +3 -0
  16. package/components/paginator/style/_o-pry-paginator.scss +11 -0
  17. package/components/paginator/style/css.component.d.ts +5 -0
  18. package/dataset/components/dataset-detail/dataset-detail.component.d.ts +5 -8
  19. package/dataset/dataset.module.d.ts +1 -1
  20. package/dataset/i18n/en.translations.d.ts +0 -12
  21. package/dataset/i18n/fr.translations.d.ts +0 -12
  22. package/esm2022/admin/components/admin-abac-rules/components/attribute-condition/attribute-condition.component.mjs +4 -6
  23. package/esm2022/admin/components/admin-classes/admin-classes-customize/symbol/admin-classes-customize-symbol.component.mjs +1 -1
  24. package/esm2022/admin/components/admin-classes/admin-classes-customize/tooltip/admin-classes-customize-tooltip.component.mjs +1 -1
  25. package/esm2022/admin/components/admin-classes/admin-classes-view/admin-attributes-form/admin-attributes-form.component.mjs +10 -12
  26. package/esm2022/admin/components/admin-classes/admin-classes-view/admin-classes-view.component.mjs +6 -5
  27. package/esm2022/admin/components/admin-dataset/admin-select-dataset/admin-select-dataset.component.mjs +2 -2
  28. package/esm2022/admin/components/admin-fields/admin-fields-form/admin-fields-form.component.mjs +142 -63
  29. package/esm2022/admin/components/admin-fields/admin-fields-select/admin-fields-select.component.mjs +7 -8
  30. package/esm2022/admin/components/admin-fields/admin-fields.component.mjs +15 -11
  31. package/esm2022/admin/components/admin-fields/store/admin-fields.model.mjs +1 -1
  32. package/esm2022/admin/components/admin-fields/store/fields.actions.mjs +6 -5
  33. package/esm2022/admin/components/admin-fields/store/fields.effects.mjs +12 -6
  34. package/esm2022/admin/i18n/en.translations.mjs +34 -15
  35. package/esm2022/admin/i18n/fr.translations.mjs +34 -15
  36. package/esm2022/components/checkbox/checkbox.component.mjs +15 -7
  37. package/esm2022/components/data-format/data-format.pipe.mjs +88 -7
  38. package/esm2022/components/paginator/paginator.component.mjs +51 -0
  39. package/esm2022/components/paginator/paginator.module.mjs +20 -0
  40. package/esm2022/components/paginator/provoly-dashboard-components-paginator.mjs +5 -0
  41. package/esm2022/components/paginator/public-api.mjs +4 -0
  42. package/esm2022/components/paginator/style/css.component.mjs +11 -0
  43. package/esm2022/dataset/components/dataset-detail/dataset-detail.component.mjs +16 -26
  44. package/esm2022/dataset/dataset.module.mjs +2 -5
  45. package/esm2022/dataset/i18n/en.translations.mjs +1 -13
  46. package/esm2022/dataset/i18n/fr.translations.mjs +2 -14
  47. package/esm2022/import/components/form/import-form.component.mjs +174 -0
  48. package/esm2022/import/components/list/import-list.component.mjs +73 -0
  49. package/esm2022/import/components/version-modal/version-modal.component.mjs +26 -0
  50. package/esm2022/import/i18n/en.translations.mjs +16 -2
  51. package/esm2022/import/i18n/fr.translations.mjs +16 -2
  52. package/esm2022/import/import-routing.module.mjs +3 -3
  53. package/esm2022/import/import.module.mjs +25 -10
  54. package/esm2022/import/public-api.mjs +4 -2
  55. package/esm2022/import/style/css.component.mjs +2 -2
  56. package/esm2022/lib/core/components/select/select.component.mjs +3 -3
  57. package/esm2022/lib/core/components/share/legacy-share/share.component.mjs +8 -8
  58. package/esm2022/lib/core/components/status-modal/status-modal.component.mjs +48 -0
  59. package/esm2022/lib/core/components/{modal-status/modal-status.module.mjs → status-modal/status-modal.module.mjs} +9 -9
  60. package/esm2022/lib/core/core.module.mjs +5 -5
  61. package/esm2022/lib/core/i18n/en.translations.mjs +39 -6
  62. package/esm2022/lib/core/i18n/fr.translations.mjs +41 -6
  63. package/esm2022/lib/core/model/admin-api.model.mjs +5 -69
  64. package/esm2022/lib/core/model/widget-analytic-manifest.interface.mjs +1 -1
  65. package/esm2022/lib/core/model/widget-table-manifest.interface.mjs +1 -1
  66. package/esm2022/lib/core/public-api.mjs +3 -3
  67. package/esm2022/lib/core/store/class/class.interface.mjs +1 -1
  68. package/esm2022/lib/core/store/class/class.selectors.mjs +2 -2
  69. package/esm2022/lib/core/store/data-source/data-source.actions.mjs +3 -3
  70. package/esm2022/lib/core/store/data-source/data-source.effects.mjs +7 -4
  71. package/esm2022/lib/core/store/data-source/data-source.model.mjs +1 -1
  72. package/esm2022/lib/core/store/data-source/data-source.reducer.mjs +5 -3
  73. package/esm2022/lib/core/store/data-source/data-source.selectors.mjs +3 -11
  74. package/esm2022/lib/core/store/data-source/data-source.service.mjs +23 -5
  75. package/esm2022/lib/core/store/field/field.interface.mjs +1 -3
  76. package/esm2022/lib/core/store/field/field.service.mjs +7 -2
  77. package/esm2022/lib/dashboard/components/context-menu/object-edition/object-edition.component.mjs +3 -3
  78. package/esm2022/lib/dashboard/components/widgets/datasource-selector/datasource-card/datasource-card.component.mjs +3 -11
  79. package/esm2022/lib/dashboard/components/widgets/datasource-selector/datasource-list/datasource-list.component.mjs +2 -2
  80. package/esm2022/lib/dashboard/item-utils.mjs +5 -5
  81. package/esm2022/lib/dashboard/store/dashboard.actions.mjs +1 -4
  82. package/esm2022/lib/dashboard/store/dashboard.effects.mjs +1 -19
  83. package/esm2022/lib/dashboard/store/dashboard.reducers.mjs +1 -26
  84. package/esm2022/lib/dashboard/tooltip/components/default/default.tooltip.component.mjs +3 -3
  85. package/esm2022/lib/dashboard/tooltip/tooltip-factory.service.mjs +3 -2
  86. package/esm2022/search/search-mono-class/components/search-condition/search-condition.component.mjs +4 -4
  87. package/esm2022/search/search-mono-class/components/search-order/search-order.component.mjs +3 -3
  88. package/esm2022/search/search-mono-class/components/search-select-attribute/search-select-attribute.component.mjs +4 -5
  89. package/esm2022/search/search-mono-class/store/search-mono-class.effects.mjs +2 -2
  90. package/esm2022/search/search-mono-class/store/search-mono-class.service.mjs +5 -6
  91. package/esm2022/search/search-multi-class/store/search-multi-class.service.mjs +4 -4
  92. package/esm2022/toolbox/components/filter-settings/filter-settings.component.mjs +3 -3
  93. package/esm2022/toolbox/components/save-view/save-view.component.mjs +3 -3
  94. package/esm2022/tooltips/attribute/attribute-tooltip.component.mjs +17 -19
  95. package/esm2022/tooltips/attribute/attribute-tooltip.module.mjs +5 -4
  96. package/esm2022/widgets/widget-aggregated-chart/component/widget-aggregated-chart.component.mjs +54 -37
  97. package/esm2022/widgets/widget-analytic/component/widget-analytic.component.mjs +4 -16
  98. package/esm2022/widgets/widget-chart/component/widget-chart.component.mjs +9 -9
  99. package/esm2022/widgets/widget-detail/component/widget-detail.component.mjs +5 -5
  100. package/esm2022/widgets/widget-map/component/widget-map.component.mjs +30 -32
  101. package/esm2022/widgets/widget-map/pipe/widget-map-geometry-fields-for.pipe.mjs +2 -5
  102. package/esm2022/widgets/widget-map/utils/cql-utils.class.mjs +2 -2
  103. package/esm2022/widgets/widget-map/utils/widget-map.utils.mjs +6 -10
  104. package/esm2022/widgets/widget-table/component/widget-table.component.mjs +18 -14
  105. package/esm2022/widgets/widget-table/expand-value/expand-value.component.mjs +9 -5
  106. package/esm2022/widgets/widget-table/get-value/get-value.pipe.mjs +2 -2
  107. package/esm2022/widgets/widget-table/public-api.mjs +1 -2
  108. package/esm2022/widgets/widget-table/widget-table.module.mjs +12 -7
  109. package/esm2022/widgets/widget-tile/component/widget-tile.component.mjs +10 -15
  110. package/esm2022/widgets/widget-tile/widget-tile.module.mjs +8 -4
  111. package/esm2022/widgets/widget-vega/component/widget-vega.component.mjs +2 -2
  112. package/fesm2022/provoly-dashboard-admin.mjs +249 -126
  113. package/fesm2022/provoly-dashboard-admin.mjs.map +1 -1
  114. package/fesm2022/provoly-dashboard-components-checkbox.mjs +14 -6
  115. package/fesm2022/provoly-dashboard-components-checkbox.mjs.map +1 -1
  116. package/fesm2022/provoly-dashboard-components-data-format.mjs +88 -7
  117. package/fesm2022/provoly-dashboard-components-data-format.mjs.map +1 -1
  118. package/fesm2022/provoly-dashboard-components-paginator.mjs +82 -0
  119. package/fesm2022/provoly-dashboard-components-paginator.mjs.map +1 -0
  120. package/fesm2022/provoly-dashboard-dataset.mjs +21 -58
  121. package/fesm2022/provoly-dashboard-dataset.mjs.map +1 -1
  122. package/fesm2022/provoly-dashboard-import.mjs +249 -116
  123. package/fesm2022/provoly-dashboard-import.mjs.map +1 -1
  124. package/fesm2022/provoly-dashboard-search.mjs +15 -16
  125. package/fesm2022/provoly-dashboard-search.mjs.map +1 -1
  126. package/fesm2022/provoly-dashboard-toolbox.mjs +4 -4
  127. package/fesm2022/provoly-dashboard-toolbox.mjs.map +1 -1
  128. package/fesm2022/provoly-dashboard-tooltips-attribute.mjs +20 -21
  129. package/fesm2022/provoly-dashboard-tooltips-attribute.mjs.map +1 -1
  130. package/fesm2022/provoly-dashboard-widgets-widget-aggregated-chart.mjs +53 -36
  131. package/fesm2022/provoly-dashboard-widgets-widget-aggregated-chart.mjs.map +1 -1
  132. package/fesm2022/provoly-dashboard-widgets-widget-analytic.mjs +3 -15
  133. package/fesm2022/provoly-dashboard-widgets-widget-analytic.mjs.map +1 -1
  134. package/fesm2022/provoly-dashboard-widgets-widget-chart.mjs +9 -9
  135. package/fesm2022/provoly-dashboard-widgets-widget-chart.mjs.map +1 -1
  136. package/fesm2022/provoly-dashboard-widgets-widget-detail.mjs +4 -4
  137. package/fesm2022/provoly-dashboard-widgets-widget-detail.mjs.map +1 -1
  138. package/fesm2022/provoly-dashboard-widgets-widget-map.mjs +36 -45
  139. package/fesm2022/provoly-dashboard-widgets-widget-map.mjs.map +1 -1
  140. package/fesm2022/provoly-dashboard-widgets-widget-table.mjs +32 -38
  141. package/fesm2022/provoly-dashboard-widgets-widget-table.mjs.map +1 -1
  142. package/fesm2022/provoly-dashboard-widgets-widget-tile.mjs +16 -17
  143. package/fesm2022/provoly-dashboard-widgets-widget-tile.mjs.map +1 -1
  144. package/fesm2022/provoly-dashboard-widgets-widget-vega.mjs +1 -1
  145. package/fesm2022/provoly-dashboard-widgets-widget-vega.mjs.map +1 -1
  146. package/fesm2022/provoly-dashboard.mjs +286 -338
  147. package/fesm2022/provoly-dashboard.mjs.map +1 -1
  148. package/import/components/{import.component.d.ts → form/import-form.component.d.ts} +8 -4
  149. package/import/components/list/import-list.component.d.ts +34 -0
  150. package/import/components/version-modal/version-modal.component.d.ts +13 -0
  151. package/import/i18n/en.translations.d.ts +14 -0
  152. package/import/i18n/fr.translations.d.ts +14 -0
  153. package/import/import.module.d.ts +13 -10
  154. package/import/public-api.d.ts +3 -1
  155. package/import/style/_o-import.scss +50 -6
  156. package/lib/core/components/share/legacy-share/share.component.d.ts +1 -1
  157. package/lib/core/components/{modal-status/modal-status.component.d.ts → status-modal/status-modal.component.d.ts} +10 -6
  158. package/lib/core/components/{modal-status/modal-status.module.d.ts → status-modal/status-modal.module.d.ts} +5 -5
  159. package/lib/core/core.module.d.ts +2 -2
  160. package/lib/core/i18n/en.translations.d.ts +33 -0
  161. package/lib/core/i18n/fr.translations.d.ts +35 -0
  162. package/lib/core/model/admin-api.model.d.ts +6 -8
  163. package/lib/core/model/widget-analytic-manifest.interface.d.ts +0 -3
  164. package/lib/core/model/widget-table-manifest.interface.d.ts +2 -0
  165. package/lib/core/public-api.d.ts +2 -2
  166. package/lib/core/store/class/class.interface.d.ts +2 -1
  167. package/lib/core/store/class/class.selectors.d.ts +10 -10
  168. package/lib/core/store/data-source/data-source.actions.d.ts +21 -1
  169. package/lib/core/store/data-source/data-source.effects.d.ts +11 -1
  170. package/lib/core/store/data-source/data-source.model.d.ts +3 -2
  171. package/lib/core/store/data-source/data-source.reducer.d.ts +1 -0
  172. package/lib/core/store/data-source/data-source.selectors.d.ts +3 -3
  173. package/lib/core/store/data-source/data-source.service.d.ts +11 -2
  174. package/lib/core/store/field/field.interface.d.ts +8 -4
  175. package/lib/core/store/field/field.service.d.ts +1 -0
  176. package/lib/dashboard/components/context-menu/object-edition/object-edition.component.d.ts +1 -1
  177. package/lib/dashboard/components/widgets/datasource-selector/datasource-card/datasource-card.component.d.ts +3 -7
  178. package/lib/dashboard/item-utils.d.ts +1 -1
  179. package/lib/dashboard/store/dashboard.actions.d.ts +0 -11
  180. package/lib/dashboard/store/dashboard.effects.d.ts +0 -3
  181. package/lib/dashboard/tooltip/tooltip-factory.service.d.ts +2 -1
  182. package/package.json +18 -12
  183. package/styles/base/_utils.scss +9 -1
  184. package/styles/components/_a-btn.scss +7 -0
  185. package/styles/components/_a-table.scss +2 -16
  186. package/styles/layout/_o-workspace.scss +1 -0
  187. package/tooltips/attribute/attribute-tooltip.component.d.ts +6 -6
  188. package/tooltips/attribute/attribute-tooltip.module.d.ts +2 -1
  189. package/widgets/widget-aggregated-chart/component/widget-aggregated-chart.component.d.ts +16 -3
  190. package/widgets/widget-analytic/component/widget-analytic.component.d.ts +2 -3
  191. package/widgets/widget-detail/component/widget-detail.component.d.ts +1 -4
  192. package/widgets/widget-table/component/widget-table.component.d.ts +1 -0
  193. package/widgets/widget-table/expand-value/expand-value.component.d.ts +4 -2
  194. package/widgets/widget-table/public-api.d.ts +0 -1
  195. package/widgets/widget-table/widget-table.module.d.ts +9 -8
  196. package/widgets/widget-tile/component/widget-tile.component.d.ts +1 -0
  197. package/widgets/widget-tile/widget-tile.module.d.ts +2 -1
  198. package/esm2022/import/components/import.component.mjs +0 -167
  199. package/esm2022/lib/core/components/modal-status/modal-status.component.mjs +0 -45
  200. package/esm2022/widgets/widget-table/expand-value/format-number.pipe.mjs +0 -24
  201. package/widgets/widget-table/expand-value/format-number.pipe.d.ts +0 -10
@@ -7,24 +7,25 @@ import { CommonModule, DatePipe } from '@angular/common';
7
7
  import * as i0 from '@angular/core';
8
8
  import { EventEmitter, Component, Output, Input, Injectable, ViewContainerRef, ViewChild, TemplateRef, ChangeDetectionStrategy, Optional, Inject, NgModule } from '@angular/core';
9
9
  import * as i3$1 from '@angular/forms';
10
- import { Validators, FormControl, UntypedFormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
10
+ import { Validators, FormGroup, FormControl, UntypedFormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
11
11
  import * as i1$2 from '@ngrx/effects';
12
12
  import { concatLatestFrom, createEffect, ofType, EffectsModule } from '@ngrx/effects';
13
13
  import * as i1 from '@ngrx/store';
14
14
  import { createAction, props, createReducer, on, createFeatureSelector, createSelector, StoreModule } from '@ngrx/store';
15
15
  import * as i4 from '@provoly/dashboard';
16
- import { ClassSelectors, FieldSelectors, FieldType, ClassActions, FieldActions, SubscriptionnerDirective, ConfigSelectors, ConfigActions, DEFAULT_ICON_URL, IconPosition, compareOperationFunctions, ItemUtils, CategoryActions, CategorySelectors, DataSourceActions, DataSourceSelectors, FIELD_OPTIONS, DEFAULT_CATEGORY_UUID, getShareLevel, PryDatasetType, ENV_OPTIONS, GeometricFieldTypes, DashboardSelectors, PryShareMode, PRY_ACCESS_TOKEN, META_OPTIONS, RelationTypesSelectors, RelationTypesActions, BaseMenuComponent, BaseLayoutComponent, PRY_ACCESS_GUARD, PryDialogConfirmComponent, PrySortModule, PryIconModule, PryModalModule, PryI18nModule, PryCoreModule, PrySelectModule, PryToggleModule, PryOverlayModule, PryShareModule } from '@provoly/dashboard';
16
+ import { ClassSelectors, FieldType, ClassActions, FieldActions, SubscriptionnerDirective, ConfigSelectors, FieldSelectors, ConfigActions, DEFAULT_ICON_URL, IconPosition, compareOperationFunctions, ItemUtils, CategoryActions, CategorySelectors, DataSourceActions, DataSourceSelectors, FIELD_I18N, DEFAULT_CATEGORY_UUID, getShareLevel, PryDatasetType, ENV_OPTIONS, GeometricFieldTypes, DashboardSelectors, PryShareMode, PRY_ACCESS_TOKEN, META_OPTIONS, RelationTypesSelectors, RelationTypesActions, BaseMenuComponent, BaseLayoutComponent, PRY_ACCESS_GUARD, PryDialogConfirmComponent, PrySortModule, PryIconModule, PryModalModule, PryI18nModule, PryCoreModule, PrySelectModule, PryToggleModule, PryOverlayModule, PryShareModule } from '@provoly/dashboard';
17
17
  import * as i5$1 from '@provoly/dashboard/components/checkbox';
18
18
  import { PryCheckboxModule } from '@provoly/dashboard/components/checkbox';
19
19
  import * as i6 from '@provoly/dashboard/components/metadata-editor';
20
20
  import { MetadataSelectors, MetadataActions, PryExpandPanelModule } from '@provoly/dashboard/components/metadata-editor';
21
21
  import * as i2 from '@angular/router';
22
22
  import { RouterModule } from '@angular/router';
23
- import { switchMap, mergeMap, combineLatest, of, map, filter, BehaviorSubject, combineLatestWith, Subscription, distinctUntilChanged as distinctUntilChanged$1, debounceTime, startWith, Subject, zip, withLatestFrom, takeUntil, catchError, tap } from 'rxjs';
23
+ import { switchMap, mergeMap, combineLatest, of, map, filter, BehaviorSubject, combineLatestWith, Subscription, distinctUntilChanged as distinctUntilChanged$1, debounceTime, startWith, Subject, withLatestFrom, takeUntil, catchError, tap } from 'rxjs';
24
24
  import { v4 } from 'uuid';
25
25
  import equal from 'fast-deep-equal/es6';
26
26
  import { distinctUntilChanged, map as map$1, filter as filter$1, mergeMap as mergeMap$1, catchError as catchError$1 } from 'rxjs/operators';
27
27
  import { TemplatePortal } from '@angular/cdk/portal';
28
+ import { dateFormatOptions } from '@provoly/dashboard/components/data-format';
28
29
  import { concatLatestFrom as concatLatestFrom$1 } from '@ngrx/operators';
29
30
  import * as i1$1 from '@angular/common/http';
30
31
  import { PryDatasetModule } from '@provoly/dashboard/dataset';
@@ -352,9 +353,7 @@ class AttributeConditionComponent {
352
353
  this.attribute$ = this.condition$.pipe(filter((cond) => cond !== null && cond !== undefined), mergeMap((cond) => combineLatest([of(cond), this.store.select(ClassSelectors.classByAttributeId(cond.attribute ?? ''))])), map(([cond, klass]) => {
353
354
  return klass?.attributes.find((a) => a.id === cond.attribute);
354
355
  }));
355
- this.field$ = this.attribute$.pipe(filter((attr) => attr !== undefined), switchMap((attr) => {
356
- return this.store.select(FieldSelectors.fieldById(attr.field));
357
- }));
356
+ this.field$ = this.attribute$.pipe(filter((attr) => attr !== undefined), map((attr) => attr.field));
358
357
  this.operatorOptions$ = this.field$.pipe(filter((field) => field !== undefined), map((field) => {
359
358
  const fieldType = field.type;
360
359
  if (fieldType === FieldType.STRING || fieldType === FieldType.KEYWORD) {
@@ -1076,7 +1075,7 @@ class AdminClassesCustomizeTooltipComponent extends SubscriptionnerDirective {
1076
1075
  return config;
1077
1076
  }
1078
1077
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminClassesCustomizeTooltipComponent, deps: [{ token: i4.TooltipFactoryService }, { token: i0.Injector }, { token: i4.PryI18nService }, { token: i1.Store }], target: i0.ɵɵFactoryTarget.Component }); }
1079
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: AdminClassesCustomizeTooltipComponent, selector: "pry-admin-classes-customize-tooltip", inputs: { currentClass: "currentClass" }, outputs: { backPressed: "backPressed" }, viewQueries: [{ propertyName: "example", first: true, predicate: ["example"], descendants: true, read: ViewContainerRef }], usesInheritance: true, ngImport: i0, template: "<div>\n <div class=\"m-form-label-field -width-xl\">\n <label class=\"a-label\" for=\"tooltip_type\">{{ '@pry.admin.customize.type' | i18n }}</label>\n <pry-select\n id=\"tooltip_type\"\n (ngModelChange)=\"tooltipTypeChanged($event)\"\n [ngModel]=\"currentClassConfig.type\"\n [items]=\"possibleTooltipTypes$ | async\"\n bindValue=\"value\"\n bindLabel=\"label\"\n ></pry-select>\n </div>\n\n <div>\n <pry-checkbox [(ngModel)]=\"advancedTooltip\">{{ '@pry.admin.customize.advanced' | i18n }}</pry-checkbox>\n </div>\n\n <div class=\"m-form-label-field -width-xl\" *ngIf=\"!advancedTooltip && currentClassConfig.type === 'attribute'\">\n <label class=\"a-label\" for=\"customize_simplified\">{{ '@pry.admin.customize.simplified' | i18n }}</label>\n <pry-select\n id=\"customize_simplified\"\n (ngModelChange)=\"changeAttributes($event)\"\n [ngModel]=\"currentClassConfig.options.attributes\"\n [items]=\"attributesOfClass$ | async\"\n [multiple]=\"true\"\n [closeOnSelect]=\"false\"\n bindLabel=\"name\"\n bindValue=\"id\"\n ></pry-select>\n </div>\n\n <ng-container *ngIf=\"advancedTooltip\">\n <textarea\n cols=\"100\"\n rows=\"15\"\n class=\"a-form-field\"\n [(ngModel)]=\"strOptions\"\n (focusout)=\"optionsChanged()\"\n ></textarea>\n </ng-container>\n</div>\n\n<div class=\"m-tooltip m-tooltip--example\" [class.-hidden]=\"noTooltip\">\n <div #example></div>\n</div>\n\n<div class=\"m-btn-group -width-md\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button class=\"a-btn a-btn--primary\" type=\"submit\" (click)=\"updateTemplate()\">\n {{ '@pry.admin.customize.update' | i18n }}\n </button>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5$1.PryCheckboxComponent, selector: "pry-checkbox", inputs: ["circle"] }, { kind: "component", type: i4.PrySelectComponent, selector: "pry-select", inputs: ["items", "clearable", "multiple", "closeOnSelect", "placeholder", "isForm", "required", "name", "readonly", "autocomplete", "alwaysShowAutosuggestedValues", "externalAutocompleteService", "bindValue", "bindLabel", "iconSize", "bindIcon", "template", "i18nPrefix", "bindClasses", "loading", "elementRef"], outputs: ["searched", "cleared", "clicked"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
1078
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: AdminClassesCustomizeTooltipComponent, selector: "pry-admin-classes-customize-tooltip", inputs: { currentClass: "currentClass" }, outputs: { backPressed: "backPressed" }, viewQueries: [{ propertyName: "example", first: true, predicate: ["example"], descendants: true, read: ViewContainerRef }], usesInheritance: true, ngImport: i0, template: "<div>\n <div class=\"m-form-label-field -width-xl\">\n <label class=\"a-label\" for=\"tooltip_type\">{{ '@pry.admin.customize.type' | i18n }}</label>\n <pry-select\n id=\"tooltip_type\"\n (ngModelChange)=\"tooltipTypeChanged($event)\"\n [ngModel]=\"currentClassConfig.type\"\n [items]=\"possibleTooltipTypes$ | async\"\n bindValue=\"value\"\n bindLabel=\"label\"\n ></pry-select>\n </div>\n\n <div>\n <pry-checkbox [(ngModel)]=\"advancedTooltip\">{{ '@pry.admin.customize.advanced' | i18n }}</pry-checkbox>\n </div>\n\n <div class=\"m-form-label-field -width-xl\" *ngIf=\"!advancedTooltip && currentClassConfig.type === 'attribute'\">\n <label class=\"a-label\" for=\"customize_simplified\">{{ '@pry.admin.customize.simplified' | i18n }}</label>\n <pry-select\n id=\"customize_simplified\"\n (ngModelChange)=\"changeAttributes($event)\"\n [ngModel]=\"currentClassConfig.options.attributes\"\n [items]=\"attributesOfClass$ | async\"\n [multiple]=\"true\"\n [closeOnSelect]=\"false\"\n bindLabel=\"name\"\n bindValue=\"id\"\n ></pry-select>\n </div>\n\n <ng-container *ngIf=\"advancedTooltip\">\n <textarea\n cols=\"100\"\n rows=\"15\"\n class=\"a-form-field\"\n [(ngModel)]=\"strOptions\"\n (focusout)=\"optionsChanged()\"\n ></textarea>\n </ng-container>\n</div>\n\n<div class=\"m-tooltip m-tooltip--example\" [class.-hidden]=\"noTooltip\">\n <div #example></div>\n</div>\n\n<div class=\"m-btn-group -width-md\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button class=\"a-btn a-btn--primary\" type=\"submit\" (click)=\"updateTemplate()\">\n {{ '@pry.admin.customize.update' | i18n }}\n </button>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5$1.PryCheckboxComponent, selector: "pry-checkbox", inputs: ["circle", "name", "inputId", "inhibit"] }, { kind: "component", type: i4.PrySelectComponent, selector: "pry-select", inputs: ["items", "clearable", "multiple", "closeOnSelect", "placeholder", "isForm", "required", "name", "readonly", "autocomplete", "alwaysShowAutosuggestedValues", "externalAutocompleteService", "bindValue", "bindLabel", "iconSize", "bindIcon", "template", "i18nPrefix", "bindClasses", "loading", "elementRef"], outputs: ["searched", "cleared", "clicked"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
1080
1079
  }
1081
1080
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminClassesCustomizeTooltipComponent, decorators: [{
1082
1081
  type: Component,
@@ -1215,7 +1214,7 @@ class AdminClassesCustomizeSymbolComponent extends SubscriptionnerDirective {
1215
1214
  this.store.dispatch(ConfigActions.updateIcons({ definitions: { [this.currentClass?.id ?? '']: this.definitions } }));
1216
1215
  }
1217
1216
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminClassesCustomizeSymbolComponent, deps: [{ token: i4.PryI18nService }, { token: i1.Store }], target: i0.ɵɵFactoryTarget.Component }); }
1218
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: AdminClassesCustomizeSymbolComponent, selector: "pry-admin-classes-customize-symbol", inputs: { currentClass: "currentClass" }, outputs: { backPressed: "backPressed" }, usesInheritance: true, ngImport: i0, template: "<ul class=\"m-rule-wrapper\">\n <li\n *ngFor=\"let definition of definitions; let i = index\"\n [class.m-rule--default]=\"definition.isDefault\"\n class=\"m-rule\"\n >\n <div class=\"m-rule__header\">\n <h3 class=\"a-h3\">\n {{ '@pry.admin.rule' | i18n : { id: i + 1 } }}\n <span>{{ definition.isDefault ? ('@pry.admin.defaultRule' | i18n) : '' }}</span>\n </h3>\n\n <div *ngIf=\"!definition.isDefault\" class=\"m-rule__actions\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--icon-only\"\n [class.-disabled]=\"i <= 1\"\n [disabled]=\"i <= 1\"\n (click)=\"move(i, i - 1)\"\n >\n <pry-icon [height]=\"25\" [width]=\"25\" iconSvg=\"fleche_haut\"></pry-icon>\n <span class=\"u-visually-hidden\">{{ '@pry.action.moveUp' | i18n }}</span>\n </button>\n <button\n type=\"button\"\n class=\"a-btn a-btn--icon-only\"\n [class.-disabled]=\"i >= definitions.length - 1\"\n [disabled]=\"i >= definitions.length - 1\"\n (click)=\"move(i, i + 1)\"\n >\n <pry-icon [height]=\"25\" [width]=\"25\" iconSvg=\"fleche_bas\"></pry-icon>\n <span class=\"u-visually-hidden\">{{ '@pry.action.moveDown' | i18n }}</span>\n </button>\n <button type=\"button\" class=\"a-btn a-btn--icon-only\" (click)=\"removeRule(i)\">\n <pry-icon [height]=\"20\" [width]=\"20\" iconSvg=\"delete\"></pry-icon>\n <span class=\"u-visually-hidden\">{{ '@pry.action.delete' | i18n }}</span>\n </button>\n </div>\n </div>\n\n <div>\n <pry-select-image [iconUrl]=\"definition.iconUrl\" (changed)=\"changeForImage($event, i)\"></pry-select-image>\n\n <ng-container *ngIf=\"definition.isDefault\">\n <div class=\"m-form-label-field m-rule__display-mode\">\n <label class=\"a-label\" for=\"size\">{{ '@pry.admin.size' | i18n }}</label>\n <pry-select\n (ngModelChange)=\"changeSize($event)\"\n [items]=\"sizes\"\n [ngModel]=\"definition.iconSize[0]\"\n bindLabel=\"label\"\n bindValue=\"value\"\n id=\"size\"\n ></pry-select>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"!definition.isDefault\">\n <div class=\"m-form-label-field m-rule__display-mode\">\n <label class=\"a-label\" for=\"display_mode\">{{ '@pry.admin.displayModeImage' | i18n }}</label>\n <pry-select\n (ngModelChange)=\"changePosition($event, i)\"\n [items]=\"positions\"\n [ngModel]=\"definition.position\"\n bindLabel=\"label\"\n bindValue=\"value\"\n id=\"display_mode\"\n ></pry-select>\n </div>\n <div class=\"m-form-label-field\">\n <pry-checkbox [ngModel]=\"!!definition.rule\" (click)=\"toggleRule(i)\">{{\n '@pry.admin.classes.condition' | i18n\n }}</pry-checkbox>\n </div>\n </ng-container>\n\n <div *ngIf=\"!!definition.rule && !definition.isDefault\">\n <div class=\"m-form-label-field\">\n <label class=\"a-label\" for=\"classes_attrname\">{{ '@pry.admin.classes.attrName' | i18n }}</label>\n <pry-select\n (ngModelChange)=\"changeAttrName($event, i)\"\n [items]=\"fieldsForClass\"\n [ngModel]=\"definition.rule.attributeName\"\n bindLabel=\"name\"\n bindValue=\"name\"\n id=\"classes_attrname\"\n ></pry-select>\n </div>\n\n <div class=\"m-form-label-field\">\n <label class=\"a-label\" for=\"classes_operation\">{{ '@pry.admin.classes.operation' | i18n }}</label>\n <pry-select\n (ngModelChange)=\"changeOperation($event, i)\"\n [items]=\"operations\"\n [ngModel]=\"definition.rule.operation\"\n bindLabel=\"label\"\n bindValue=\"name\"\n id=\"classes_operation\"\n ></pry-select>\n </div>\n\n <div class=\"m-form-label-field\">\n <label class=\"a-label\" for=\"classes_value\">{{ '@pry.admin.classes.value' | i18n }}</label>\n <input\n id=\"classes_value\"\n type=\"text\"\n class=\"a-form-field\"\n (ngModelChange)=\"changeValue($event, i)\"\n [ngModel]=\"definition.rule.value\"\n />\n </div>\n </div>\n </div>\n </li>\n</ul>\n\n<button type=\"button\" class=\"a-btn a-btn--secondary\" (click)=\"addRule()\">\n <pry-icon iconSvg=\"add\"></pry-icon>\n Ajouter une r\u00E8gle\n</button>\n\n<div class=\"m-btn-group -width-lg\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"restoreSymbols(); goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button\n class=\"a-btn a-btn--primary\"\n [innerHTML]=\"'@pry.admin.customize.updateIcons' | i18n\"\n (click)=\"valid()\"\n ></button>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.PrySelectImageComponent, selector: "pry-select-image", inputs: ["iconUrl", "size", "mode"], outputs: ["toggled", "changed"] }, { kind: "component", type: i4.PryIconComponent, selector: "pry-icon", inputs: ["color", "iconSvg", "animation", "iconImage", "alt", "width", "height", "classes"] }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5$1.PryCheckboxComponent, selector: "pry-checkbox", inputs: ["circle"] }, { kind: "component", type: i4.PrySelectComponent, selector: "pry-select", inputs: ["items", "clearable", "multiple", "closeOnSelect", "placeholder", "isForm", "required", "name", "readonly", "autocomplete", "alwaysShowAutosuggestedValues", "externalAutocompleteService", "bindValue", "bindLabel", "iconSize", "bindIcon", "template", "i18nPrefix", "bindClasses", "loading", "elementRef"], outputs: ["searched", "cleared", "clicked"] }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
1217
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: AdminClassesCustomizeSymbolComponent, selector: "pry-admin-classes-customize-symbol", inputs: { currentClass: "currentClass" }, outputs: { backPressed: "backPressed" }, usesInheritance: true, ngImport: i0, template: "<ul class=\"m-rule-wrapper\">\n <li\n *ngFor=\"let definition of definitions; let i = index\"\n [class.m-rule--default]=\"definition.isDefault\"\n class=\"m-rule\"\n >\n <div class=\"m-rule__header\">\n <h3 class=\"a-h3\">\n {{ '@pry.admin.rule' | i18n : { id: i + 1 } }}\n <span>{{ definition.isDefault ? ('@pry.admin.defaultRule' | i18n) : '' }}</span>\n </h3>\n\n <div *ngIf=\"!definition.isDefault\" class=\"m-rule__actions\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--icon-only\"\n [class.-disabled]=\"i <= 1\"\n [disabled]=\"i <= 1\"\n (click)=\"move(i, i - 1)\"\n >\n <pry-icon [height]=\"25\" [width]=\"25\" iconSvg=\"fleche_haut\"></pry-icon>\n <span class=\"u-visually-hidden\">{{ '@pry.action.moveUp' | i18n }}</span>\n </button>\n <button\n type=\"button\"\n class=\"a-btn a-btn--icon-only\"\n [class.-disabled]=\"i >= definitions.length - 1\"\n [disabled]=\"i >= definitions.length - 1\"\n (click)=\"move(i, i + 1)\"\n >\n <pry-icon [height]=\"25\" [width]=\"25\" iconSvg=\"fleche_bas\"></pry-icon>\n <span class=\"u-visually-hidden\">{{ '@pry.action.moveDown' | i18n }}</span>\n </button>\n <button type=\"button\" class=\"a-btn a-btn--icon-only\" (click)=\"removeRule(i)\">\n <pry-icon [height]=\"20\" [width]=\"20\" iconSvg=\"delete\"></pry-icon>\n <span class=\"u-visually-hidden\">{{ '@pry.action.delete' | i18n }}</span>\n </button>\n </div>\n </div>\n\n <div>\n <pry-select-image [iconUrl]=\"definition.iconUrl\" (changed)=\"changeForImage($event, i)\"></pry-select-image>\n\n <ng-container *ngIf=\"definition.isDefault\">\n <div class=\"m-form-label-field m-rule__display-mode\">\n <label class=\"a-label\" for=\"size\">{{ '@pry.admin.size' | i18n }}</label>\n <pry-select\n (ngModelChange)=\"changeSize($event)\"\n [items]=\"sizes\"\n [ngModel]=\"definition.iconSize[0]\"\n bindLabel=\"label\"\n bindValue=\"value\"\n id=\"size\"\n ></pry-select>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"!definition.isDefault\">\n <div class=\"m-form-label-field m-rule__display-mode\">\n <label class=\"a-label\" for=\"display_mode\">{{ '@pry.admin.displayModeImage' | i18n }}</label>\n <pry-select\n (ngModelChange)=\"changePosition($event, i)\"\n [items]=\"positions\"\n [ngModel]=\"definition.position\"\n bindLabel=\"label\"\n bindValue=\"value\"\n id=\"display_mode\"\n ></pry-select>\n </div>\n <div class=\"m-form-label-field\">\n <pry-checkbox [ngModel]=\"!!definition.rule\" (click)=\"toggleRule(i)\">{{\n '@pry.admin.classes.condition' | i18n\n }}</pry-checkbox>\n </div>\n </ng-container>\n\n <div *ngIf=\"!!definition.rule && !definition.isDefault\">\n <div class=\"m-form-label-field\">\n <label class=\"a-label\" for=\"classes_attrname\">{{ '@pry.admin.classes.attrName' | i18n }}</label>\n <pry-select\n (ngModelChange)=\"changeAttrName($event, i)\"\n [items]=\"fieldsForClass\"\n [ngModel]=\"definition.rule.attributeName\"\n bindLabel=\"name\"\n bindValue=\"name\"\n id=\"classes_attrname\"\n ></pry-select>\n </div>\n\n <div class=\"m-form-label-field\">\n <label class=\"a-label\" for=\"classes_operation\">{{ '@pry.admin.classes.operation' | i18n }}</label>\n <pry-select\n (ngModelChange)=\"changeOperation($event, i)\"\n [items]=\"operations\"\n [ngModel]=\"definition.rule.operation\"\n bindLabel=\"label\"\n bindValue=\"name\"\n id=\"classes_operation\"\n ></pry-select>\n </div>\n\n <div class=\"m-form-label-field\">\n <label class=\"a-label\" for=\"classes_value\">{{ '@pry.admin.classes.value' | i18n }}</label>\n <input\n id=\"classes_value\"\n type=\"text\"\n class=\"a-form-field\"\n (ngModelChange)=\"changeValue($event, i)\"\n [ngModel]=\"definition.rule.value\"\n />\n </div>\n </div>\n </div>\n </li>\n</ul>\n\n<button type=\"button\" class=\"a-btn a-btn--secondary\" (click)=\"addRule()\">\n <pry-icon iconSvg=\"add\"></pry-icon>\n Ajouter une r\u00E8gle\n</button>\n\n<div class=\"m-btn-group -width-lg\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"restoreSymbols(); goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button\n class=\"a-btn a-btn--primary\"\n [innerHTML]=\"'@pry.admin.customize.updateIcons' | i18n\"\n (click)=\"valid()\"\n ></button>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.PrySelectImageComponent, selector: "pry-select-image", inputs: ["iconUrl", "size", "mode"], outputs: ["toggled", "changed"] }, { kind: "component", type: i4.PryIconComponent, selector: "pry-icon", inputs: ["color", "iconSvg", "animation", "iconImage", "alt", "width", "height", "classes"] }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5$1.PryCheckboxComponent, selector: "pry-checkbox", inputs: ["circle", "name", "inputId", "inhibit"] }, { kind: "component", type: i4.PrySelectComponent, selector: "pry-select", inputs: ["items", "clearable", "multiple", "closeOnSelect", "placeholder", "isForm", "required", "name", "readonly", "autocomplete", "alwaysShowAutosuggestedValues", "externalAutocompleteService", "bindValue", "bindLabel", "iconSize", "bindIcon", "template", "i18nPrefix", "bindClasses", "loading", "elementRef"], outputs: ["searched", "cleared", "clicked"] }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
1219
1218
  }
1220
1219
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminClassesCustomizeSymbolComponent, decorators: [{
1221
1220
  type: Component,
@@ -1525,7 +1524,7 @@ class AdminAttributesFormComponent extends SubscriptionnerDirective {
1525
1524
  this.dialog = dialog;
1526
1525
  this.nameAlreadyExists = false;
1527
1526
  this.technicalNameAlreadyExists = false;
1528
- this.fieldTypeDescription = FIELD_OPTIONS;
1527
+ this.FIELD_I18N = FIELD_I18N;
1529
1528
  this.store.dispatch(FieldActions.load());
1530
1529
  this.fields$ = this.store.select(FieldSelectors.fields);
1531
1530
  this.store.dispatch(CategoryActions.load());
@@ -1582,12 +1581,10 @@ class AdminAttributesFormComponent extends SubscriptionnerDirective {
1582
1581
  this.technicalNameAlreadyExists = value;
1583
1582
  }));
1584
1583
  }
1585
- this.selectedFieldTypeDescription$ = this.attrForm.get('field')?.valueChanges.pipe(startWith(this.attrForm.get('field')?.value), distinctUntilChanged$1(), switchMap((selectedFieldId) => {
1586
- return this.fields$.pipe(map((fields) => {
1587
- const fieldDescription = this.fieldTypeDescription.find((fieldType) => fieldType.varType === fields.find((field) => field.id === selectedFieldId)?.type);
1588
- return fieldDescription ? this.i18nService.instant(fieldDescription.description) : '';
1589
- }));
1590
- }));
1584
+ this.selectedFieldTypeDescription$ = combineLatest([
1585
+ this.attrForm.get('field').valueChanges.pipe(startWith(this.attrForm.get('field')?.value)),
1586
+ this.fields$
1587
+ ]).pipe(map(([selectedFieldId, fields]) => FIELD_I18N.information + fields.find((field) => field.id === selectedFieldId)?.type));
1591
1588
  }
1592
1589
  goBack() {
1593
1590
  const redirectPath = this.selectedAttribute ? '../..' : '..';
@@ -1636,11 +1633,11 @@ class AdminAttributesFormComponent extends SubscriptionnerDirective {
1636
1633
  this.subscriptions.add(ref.component.closeModal.subscribe(() => ref.close()));
1637
1634
  }
1638
1635
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminAttributesFormComponent, deps: [{ token: i1.Store }, { token: i2.Router }, { token: i2.ActivatedRoute }, { token: i3$1.UntypedFormBuilder }, { token: i4.PryI18nService }, { token: i4.PryDialogService }], target: i0.ɵɵFactoryTarget.Component }); }
1639
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: AdminAttributesFormComponent, selector: "pry-admin-attributes-form", inputs: { selectedClass: "selectedClass", interClass: "interClass", selectedAttribute: "selectedAttribute" }, usesInheritance: true, ngImport: i0, template: "<form class=\"o-form\" [formGroup]=\"attrForm\" (ngSubmit)=\"addAttribute()\">\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"attr_technicalName\">{{ '@pry.admin.classes.attributes.technicalName' | i18n }}</label>\n <input id=\"attr_technicalName\" type=\"text\" class=\"a-form-field\" formControlName=\"technicalName\" required />\n <label class=\"a-label a-label--help -error\" *ngIf=\"technicalNameAlreadyExists$ | async\">{{\n '@pry.admin.exists' | i18n\n }}</label>\n <div *ngIf=\"attrForm.get('technicalName')?.invalid\">\n <div *ngIf=\"attrForm.get('technicalName')?.dirty && attrForm.get('technicalName')?.hasError('required')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{ '@pry.admin.required' | i18n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('technicalName')?.hasError('minlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.minLength' | i18n: { len: 2 }\n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('technicalName')?.hasError('maxlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.maxLength' | i18n: { len: 100 }\n }}</label>\n </div>\n <div\n *ngIf=\"\n attrForm.get('technicalName')?.hasError('whitespace') && !attrForm.get('technicalName')?.hasError('minlength')\n \"\n >\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.noWhitespace' | i18n\n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"attr_name\">{{ '@pry.admin.classes.attributes.name' | i18n }}</label>\n <input id=\"attr_name\" type=\"text\" class=\"a-form-field\" formControlName=\"name\" />\n <label class=\"a-label a-label--help -error\" *ngIf=\"nameAlreadyExists$ | async\">{{\n '@pry.admin.exists' | i18n\n }}</label>\n <div *ngIf=\"attrForm.get('name')?.invalid\">\n <div *ngIf=\"attrForm.get('name')?.hasError('maxlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_name\">{{\n '@pry.admin.maxLength' | i18n: { len: 50 }\n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('name')?.hasError('whitespace')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_name\">{{ '@pry.admin.noWhitespace' | i18n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"type\">{{ '@pry.admin.classes.attributes.field' | i18n }}</label>\n <div class=\"u-display-flex\">\n <pry-select\n id=\"type\"\n formControlName=\"field\"\n [items]=\"fields$ | async\"\n [autocomplete]=\"true\"\n bindLabel=\"name\"\n bindValue=\"id\"\n [isForm]=\"true\"\n required=\"true\"\n [template]=\"templateOption\"\n ></pry-select>\n <ng-template #templateOption let-item=\"item\">\n <div class=\"aligned-option\">\n <p>{{ item.name }}</p>\n <div class=\"a-chip\" *ngIf=\"item.crs\">{{ item.crs }}</div>\n </div>\n </ng-template>\n <div\n *ngIf=\"selectedFieldTypeDescription$ | async as description\"\n class=\"m-info-icon a-tooltip -tooltip-width-lg u-self-center -flex-shrink-0\"\n [attr.data-tooltip]=\"description\"\n data-tooltip-position=\"right\"\n >\n <span>i</span>\n </div>\n </div>\n <div *ngIf=\"attrForm.get('field')?.invalid\">\n <div *ngIf=\"attrForm.get('field')?.dirty && attrForm.get('field')?.hasError('required')\">\n <label class=\"a-label a-label--help -error\">{{ '@pry.admin.required' | i18n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"category\">{{ '@pry.admin.classes.attributes.category' | i18n }}</label>\n <pry-select\n id=\"category\"\n class=\"form-control\"\n formControlName=\"category\"\n [items]=\"categories$ | async\"\n (click)=\"openModal()\"\n bindValue=\"id\"\n bindLabel=\"name\"\n [isForm]=\"true\"\n [readonly]=\"true\"\n ></pry-select>\n </div>\n\n <div class=\"m-btn-group -width-sm\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button\n *pryAccess=\"{ module: 'admin', page: 'classes', action: 'add_attribute' }\"\n class=\"a-btn a-btn--primary\"\n type=\"submit\"\n [disabled]=\"attrForm.invalid || nameAlreadyExists || technicalNameAlreadyExists\"\n [innerHTML]=\"(selectedAttribute ? '@pry.admin.edit' : '@pry.admin.create') | i18n\"\n ></button>\n </div>\n</form>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.PryAccessDirective, selector: "[pryAccess]", inputs: ["pryAccess"] }, { kind: "directive", type: i3$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i4.PrySelectComponent, selector: "pry-select", inputs: ["items", "clearable", "multiple", "closeOnSelect", "placeholder", "isForm", "required", "name", "readonly", "autocomplete", "alwaysShowAutosuggestedValues", "externalAutocompleteService", "bindValue", "bindLabel", "iconSize", "bindIcon", "template", "i18nPrefix", "bindClasses", "loading", "elementRef"], outputs: ["searched", "cleared", "clicked"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
1636
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: AdminAttributesFormComponent, selector: "pry-admin-attributes-form", inputs: { selectedClass: "selectedClass", interClass: "interClass", selectedAttribute: "selectedAttribute" }, usesInheritance: true, ngImport: i0, template: "<form class=\"o-form\" [formGroup]=\"attrForm\" (ngSubmit)=\"addAttribute()\">\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"attr_technicalName\">{{ '@pry.admin.classes.attributes.technicalName' | i18n }}</label>\n <input id=\"attr_technicalName\" type=\"text\" class=\"a-form-field\" formControlName=\"technicalName\" required />\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\" *ngIf=\"technicalNameAlreadyExists$ | async\">{{\n '@pry.admin.exists' | i18n\n }}</label>\n <div *ngIf=\"attrForm.get('technicalName')?.invalid\">\n <div *ngIf=\"attrForm.get('technicalName')?.dirty && attrForm.get('technicalName')?.hasError('required')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{ '@pry.admin.required' | i18n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('technicalName')?.hasError('minlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.minLength' | i18n: { len: 2 }\n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('technicalName')?.hasError('maxlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.maxLength' | i18n: { len: 100 }\n }}</label>\n </div>\n <div\n *ngIf=\"\n attrForm.get('technicalName')?.hasError('whitespace') && !attrForm.get('technicalName')?.hasError('minlength')\n \"\n >\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.noWhitespace' | i18n\n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"attr_name\">{{ '@pry.admin.classes.attributes.name' | i18n }}</label>\n <input id=\"attr_name\" type=\"text\" class=\"a-form-field\" formControlName=\"name\" />\n <label class=\"a-label a-label--help -error\" for=\"attr_name\" *ngIf=\"nameAlreadyExists$ | async\">{{\n '@pry.admin.exists' | i18n\n }}</label>\n <div *ngIf=\"attrForm.get('name')?.invalid\">\n <div *ngIf=\"attrForm.get('name')?.hasError('maxlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_name\">{{\n '@pry.admin.maxLength' | i18n: { len: 50 }\n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('name')?.hasError('whitespace')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_name\">{{ '@pry.admin.noWhitespace' | i18n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"type\">{{ '@pry.admin.classes.attributes.field' | i18n }}</label>\n <div class=\"u-display-flex\">\n <pry-select\n id=\"type\"\n formControlName=\"field\"\n [items]=\"fields$ | async\"\n [autocomplete]=\"true\"\n bindLabel=\"name\"\n bindValue=\"id\"\n [isForm]=\"true\"\n required=\"true\"\n [template]=\"templateOption\"\n ></pry-select>\n <ng-template #templateOption let-item=\"item\">\n <div class=\"aligned-option\">\n <p>{{ item.name }}</p>\n <div class=\"a-chip\" *ngIf=\"item.crs\">{{ item.crs }}</div>\n </div>\n </ng-template>\n <div\n class=\"m-info-icon a-tooltip -tooltip-width-lg u-self-center u-flex-shrink-0\"\n [attr.data-tooltip]=\"(selectedFieldTypeDescription$ | async) ?? '' | i18n\"\n data-tooltip-position=\"right\"\n >\n <span>i</span>\n </div>\n </div>\n <div *ngIf=\"attrForm.get('field')?.invalid\">\n <div *ngIf=\"attrForm.get('field')?.dirty && attrForm.get('field')?.hasError('required')\">\n <label class=\"a-label a-label--help -error\" for=\"type\">{{ '@pry.admin.required' | i18n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"category\">{{ '@pry.admin.classes.attributes.category' | i18n }}</label>\n <pry-select\n id=\"category\"\n class=\"form-control\"\n formControlName=\"category\"\n [items]=\"categories$ | async\"\n (click)=\"openModal()\"\n bindValue=\"id\"\n bindLabel=\"name\"\n [isForm]=\"true\"\n [readonly]=\"true\"\n ></pry-select>\n </div>\n\n <div class=\"m-btn-group -width-sm\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button\n *pryAccess=\"{ module: 'admin', page: 'classes', action: 'add_attribute' }\"\n class=\"a-btn a-btn--primary\"\n type=\"submit\"\n [disabled]=\"attrForm.invalid || nameAlreadyExists || technicalNameAlreadyExists\"\n [innerHTML]=\"(selectedAttribute ? '@pry.admin.edit' : '@pry.admin.create') | i18n\"\n ></button>\n </div>\n</form>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.PryAccessDirective, selector: "[pryAccess]", inputs: ["pryAccess"] }, { kind: "directive", type: i3$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i4.PrySelectComponent, selector: "pry-select", inputs: ["items", "clearable", "multiple", "closeOnSelect", "placeholder", "isForm", "required", "name", "readonly", "autocomplete", "alwaysShowAutosuggestedValues", "externalAutocompleteService", "bindValue", "bindLabel", "iconSize", "bindIcon", "template", "i18nPrefix", "bindClasses", "loading", "elementRef"], outputs: ["searched", "cleared", "clicked"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
1640
1637
  }
1641
1638
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminAttributesFormComponent, decorators: [{
1642
1639
  type: Component,
1643
- args: [{ selector: 'pry-admin-attributes-form', template: "<form class=\"o-form\" [formGroup]=\"attrForm\" (ngSubmit)=\"addAttribute()\">\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"attr_technicalName\">{{ '@pry.admin.classes.attributes.technicalName' | i18n }}</label>\n <input id=\"attr_technicalName\" type=\"text\" class=\"a-form-field\" formControlName=\"technicalName\" required />\n <label class=\"a-label a-label--help -error\" *ngIf=\"technicalNameAlreadyExists$ | async\">{{\n '@pry.admin.exists' | i18n\n }}</label>\n <div *ngIf=\"attrForm.get('technicalName')?.invalid\">\n <div *ngIf=\"attrForm.get('technicalName')?.dirty && attrForm.get('technicalName')?.hasError('required')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{ '@pry.admin.required' | i18n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('technicalName')?.hasError('minlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.minLength' | i18n: { len: 2 }\n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('technicalName')?.hasError('maxlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.maxLength' | i18n: { len: 100 }\n }}</label>\n </div>\n <div\n *ngIf=\"\n attrForm.get('technicalName')?.hasError('whitespace') && !attrForm.get('technicalName')?.hasError('minlength')\n \"\n >\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.noWhitespace' | i18n\n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"attr_name\">{{ '@pry.admin.classes.attributes.name' | i18n }}</label>\n <input id=\"attr_name\" type=\"text\" class=\"a-form-field\" formControlName=\"name\" />\n <label class=\"a-label a-label--help -error\" *ngIf=\"nameAlreadyExists$ | async\">{{\n '@pry.admin.exists' | i18n\n }}</label>\n <div *ngIf=\"attrForm.get('name')?.invalid\">\n <div *ngIf=\"attrForm.get('name')?.hasError('maxlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_name\">{{\n '@pry.admin.maxLength' | i18n: { len: 50 }\n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('name')?.hasError('whitespace')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_name\">{{ '@pry.admin.noWhitespace' | i18n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"type\">{{ '@pry.admin.classes.attributes.field' | i18n }}</label>\n <div class=\"u-display-flex\">\n <pry-select\n id=\"type\"\n formControlName=\"field\"\n [items]=\"fields$ | async\"\n [autocomplete]=\"true\"\n bindLabel=\"name\"\n bindValue=\"id\"\n [isForm]=\"true\"\n required=\"true\"\n [template]=\"templateOption\"\n ></pry-select>\n <ng-template #templateOption let-item=\"item\">\n <div class=\"aligned-option\">\n <p>{{ item.name }}</p>\n <div class=\"a-chip\" *ngIf=\"item.crs\">{{ item.crs }}</div>\n </div>\n </ng-template>\n <div\n *ngIf=\"selectedFieldTypeDescription$ | async as description\"\n class=\"m-info-icon a-tooltip -tooltip-width-lg u-self-center -flex-shrink-0\"\n [attr.data-tooltip]=\"description\"\n data-tooltip-position=\"right\"\n >\n <span>i</span>\n </div>\n </div>\n <div *ngIf=\"attrForm.get('field')?.invalid\">\n <div *ngIf=\"attrForm.get('field')?.dirty && attrForm.get('field')?.hasError('required')\">\n <label class=\"a-label a-label--help -error\">{{ '@pry.admin.required' | i18n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"category\">{{ '@pry.admin.classes.attributes.category' | i18n }}</label>\n <pry-select\n id=\"category\"\n class=\"form-control\"\n formControlName=\"category\"\n [items]=\"categories$ | async\"\n (click)=\"openModal()\"\n bindValue=\"id\"\n bindLabel=\"name\"\n [isForm]=\"true\"\n [readonly]=\"true\"\n ></pry-select>\n </div>\n\n <div class=\"m-btn-group -width-sm\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button\n *pryAccess=\"{ module: 'admin', page: 'classes', action: 'add_attribute' }\"\n class=\"a-btn a-btn--primary\"\n type=\"submit\"\n [disabled]=\"attrForm.invalid || nameAlreadyExists || technicalNameAlreadyExists\"\n [innerHTML]=\"(selectedAttribute ? '@pry.admin.edit' : '@pry.admin.create') | i18n\"\n ></button>\n </div>\n</form>\n" }]
1640
+ args: [{ selector: 'pry-admin-attributes-form', template: "<form class=\"o-form\" [formGroup]=\"attrForm\" (ngSubmit)=\"addAttribute()\">\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"attr_technicalName\">{{ '@pry.admin.classes.attributes.technicalName' | i18n }}</label>\n <input id=\"attr_technicalName\" type=\"text\" class=\"a-form-field\" formControlName=\"technicalName\" required />\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\" *ngIf=\"technicalNameAlreadyExists$ | async\">{{\n '@pry.admin.exists' | i18n\n }}</label>\n <div *ngIf=\"attrForm.get('technicalName')?.invalid\">\n <div *ngIf=\"attrForm.get('technicalName')?.dirty && attrForm.get('technicalName')?.hasError('required')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{ '@pry.admin.required' | i18n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('technicalName')?.hasError('minlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.minLength' | i18n: { len: 2 }\n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('technicalName')?.hasError('maxlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.maxLength' | i18n: { len: 100 }\n }}</label>\n </div>\n <div\n *ngIf=\"\n attrForm.get('technicalName')?.hasError('whitespace') && !attrForm.get('technicalName')?.hasError('minlength')\n \"\n >\n <label class=\"a-label a-label--help -error\" for=\"attr_technicalName\">{{\n '@pry.admin.noWhitespace' | i18n\n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"attr_name\">{{ '@pry.admin.classes.attributes.name' | i18n }}</label>\n <input id=\"attr_name\" type=\"text\" class=\"a-form-field\" formControlName=\"name\" />\n <label class=\"a-label a-label--help -error\" for=\"attr_name\" *ngIf=\"nameAlreadyExists$ | async\">{{\n '@pry.admin.exists' | i18n\n }}</label>\n <div *ngIf=\"attrForm.get('name')?.invalid\">\n <div *ngIf=\"attrForm.get('name')?.hasError('maxlength')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_name\">{{\n '@pry.admin.maxLength' | i18n: { len: 50 }\n }}</label>\n </div>\n <div *ngIf=\"attrForm.get('name')?.hasError('whitespace')\">\n <label class=\"a-label a-label--help -error\" for=\"attr_name\">{{ '@pry.admin.noWhitespace' | i18n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"type\">{{ '@pry.admin.classes.attributes.field' | i18n }}</label>\n <div class=\"u-display-flex\">\n <pry-select\n id=\"type\"\n formControlName=\"field\"\n [items]=\"fields$ | async\"\n [autocomplete]=\"true\"\n bindLabel=\"name\"\n bindValue=\"id\"\n [isForm]=\"true\"\n required=\"true\"\n [template]=\"templateOption\"\n ></pry-select>\n <ng-template #templateOption let-item=\"item\">\n <div class=\"aligned-option\">\n <p>{{ item.name }}</p>\n <div class=\"a-chip\" *ngIf=\"item.crs\">{{ item.crs }}</div>\n </div>\n </ng-template>\n <div\n class=\"m-info-icon a-tooltip -tooltip-width-lg u-self-center u-flex-shrink-0\"\n [attr.data-tooltip]=\"(selectedFieldTypeDescription$ | async) ?? '' | i18n\"\n data-tooltip-position=\"right\"\n >\n <span>i</span>\n </div>\n </div>\n <div *ngIf=\"attrForm.get('field')?.invalid\">\n <div *ngIf=\"attrForm.get('field')?.dirty && attrForm.get('field')?.hasError('required')\">\n <label class=\"a-label a-label--help -error\" for=\"type\">{{ '@pry.admin.required' | i18n }}</label>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"category\">{{ '@pry.admin.classes.attributes.category' | i18n }}</label>\n <pry-select\n id=\"category\"\n class=\"form-control\"\n formControlName=\"category\"\n [items]=\"categories$ | async\"\n (click)=\"openModal()\"\n bindValue=\"id\"\n bindLabel=\"name\"\n [isForm]=\"true\"\n [readonly]=\"true\"\n ></pry-select>\n </div>\n\n <div class=\"m-btn-group -width-sm\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button\n *pryAccess=\"{ module: 'admin', page: 'classes', action: 'add_attribute' }\"\n class=\"a-btn a-btn--primary\"\n type=\"submit\"\n [disabled]=\"attrForm.invalid || nameAlreadyExists || technicalNameAlreadyExists\"\n [innerHTML]=\"(selectedAttribute ? '@pry.admin.edit' : '@pry.admin.create') | i18n\"\n ></button>\n </div>\n</form>\n" }]
1644
1641
  }], ctorParameters: () => [{ type: i1.Store }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: i3$1.UntypedFormBuilder }, { type: i4.PryI18nService }, { type: i4.PryDialogService }], propDecorators: { selectedClass: [{
1645
1642
  type: Input
1646
1643
  }], interClass: [{
@@ -1748,12 +1745,13 @@ class AdminClassesViewComponent {
1748
1745
  this.sub.unsubscribe();
1749
1746
  }
1750
1747
  getAttrExtended() {
1751
- return combineLatest([this.attributes$, this.fields$, this.categories$]).pipe(filter(([attributes, fields, categories]) => fields.length > 0 && categories.length > 0), map(([attributes, fields, categories]) => {
1748
+ return combineLatest([this.attributes$, this.categories$]).pipe(filter(([attributes, categories]) => categories.length > 0), map(([attributes, categories]) => {
1752
1749
  return attributes.map((attr) => ({
1753
1750
  ...attr,
1754
- fieldName: fields.find((field) => field.id === attr.field)?.name || this.i18n.instant('@pry.admin.attributes.unknownField'),
1755
- categoryName: attr.category ?
1756
- categories.find((category) => category.id === attr.category)?.name ?? this.i18n.instant('@pry.admin.attributes.unknownCategory')
1751
+ fieldName: attr.field.name,
1752
+ categoryName: attr.category
1753
+ ? categories.find((category) => category.id === attr.category)?.name ??
1754
+ this.i18n.instant('@pry.admin.attributes.unknownCategory')
1757
1755
  : this.i18n.instant('@pry.admin.attributes.noCategory')
1758
1756
  }));
1759
1757
  }));
@@ -2420,114 +2418,193 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImpor
2420
2418
 
2421
2419
  const FieldsActions = {
2422
2420
  updateToolbox: createAction('[Admin/Fields] Update Toolbox Class'),
2421
+ failure: createAction('[Admin/Fields] failure action', props()),
2423
2422
  saveField: createAction('[Admin/Fields] Save Field', props()),
2424
2423
  saveFieldSuccess: createAction('[Admin/Fields Api] Save Field Success', props()),
2425
- saveFieldFailure: createAction('[Admin/Fields Api] Save Field Failure', props()),
2426
- selectField: createAction('[Admin/Fields] Select Field', props()),
2427
- unselectField: createAction('[Admin/Fields] unselect Field'),
2424
+ updateField: createAction('[Admin/Fields] Update Field', props()),
2425
+ updateFieldSuccess: createAction('[Admin/Fields Api] Update Field Success', props()),
2428
2426
  confirmFieldDeletion: createAction('[Admin/Fields] Open Modal for Deleting Field', props()),
2429
2427
  deleteField: createAction('[Admin/Fields] Delete Field', props()),
2430
2428
  deleteFieldSuccess: createAction('[Admin/Fields] Delete Field Success'),
2431
- deleteFieldFailure: createAction('[Admin/Fields] Delete Field Failure', props())
2429
+ selectField: createAction('[Admin/Fields] Select Field', props()),
2430
+ unselectField: createAction('[Admin/Fields] unselect Field')
2432
2431
  };
2433
2432
 
2434
2433
  const CRS_OPTIONS = [
2435
2434
  { label: 'WGS84 (EPSG:4326)', code: 'EPSG:4326' },
2436
2435
  { label: 'Lambert93 (EPSG: 2154)', code: 'EPSG:2154' }
2437
2436
  ];
2438
- class AdminFieldsFormComponent {
2439
- constructor(store, router, route, formBuilder, i18nService) {
2437
+ class AdminFieldsFormComponent extends SubscriptionnerDirective {
2438
+ constructor(store, router, route, i18n) {
2439
+ super();
2440
2440
  this.store = store;
2441
2441
  this.router = router;
2442
2442
  this.route = route;
2443
- this.formBuilder = formBuilder;
2444
- this.i18nService = i18nService;
2445
- this.sub = new Subscription();
2446
- this.isSubmitted = false;
2447
- this.fieldTypeTranslations = [];
2443
+ this.i18n = i18n;
2444
+ this.dateFormats = Object.keys(dateFormatOptions.value);
2448
2445
  this.CRS_OPTIONS = CRS_OPTIONS;
2449
- this.fieldTypeTranslations = FIELD_OPTIONS.map((translate) => ({
2450
- varType: translate.varType,
2451
- translation: this.i18nService.instant(translate.translation),
2452
- description: this.i18nService.instant(translate.description)
2453
- }));
2454
- this.fieldTypeTranslations.sort((a, b) => a['translation'].localeCompare(b['translation']));
2446
+ this.FieldType = FieldType;
2447
+ this.FIELD_I18N = FIELD_I18N;
2455
2448
  this.store.dispatch(FieldActions.load());
2456
- this.goBackPath = this.router.createUrlTree(['..'], { relativeTo: this.route }).toString();
2457
- this.goBackPathEdit = this.router.createUrlTree(['../..'], { relativeTo: this.route }).toString();
2458
- this.fieldForm = this.formBuilder.group({
2459
- id: [v4()],
2460
- name: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(100), noWhitespaceValidator]],
2461
- type: [this.fieldTypeTranslations[0]['varType']]
2462
- });
2463
- }
2464
- ngOnInit() {
2465
2449
  this.fieldNames$ = this.store
2466
2450
  .select(FieldSelectors.fields)
2467
2451
  .pipe(map((fields) => fields.map((field) => field.name.toLowerCase())));
2468
- this.nameAlreadyExists$ = combineLatest([
2469
- this.fieldForm.get('name')?.valueChanges,
2470
- this.fieldNames$
2471
- ]).pipe(map(([value, fieldNames]) => fieldNames.includes(value.toLowerCase()) && value != this.currentField?.name));
2472
- this.sub.add(this.nameAlreadyExists$.subscribe((value) => {
2452
+ this.fieldTypes = Object.values(FieldType)
2453
+ .filter((type) => type !== FieldType.GEOMETRYCOLLECTION)
2454
+ .sort((a, b) => {
2455
+ const [labelA, labelB] = [this.i18n.instant(FIELD_I18N.label + a), this.i18n.instant(FIELD_I18N.label + b)];
2456
+ return labelA.localeCompare(labelB);
2457
+ });
2458
+ this.form = new FormGroup({
2459
+ name: new FormControl('', {
2460
+ validators: [Validators.required, Validators.minLength(3), Validators.maxLength(100), noWhitespaceValidator],
2461
+ nonNullable: true
2462
+ }),
2463
+ type: new FormControl(this.fieldTypes[0], { nonNullable: true }),
2464
+ formatOptions: new FormGroup({})
2465
+ });
2466
+ this.subscriptions.add(this.type?.valueChanges.subscribe((type) => this.setFormatOptionControls(type)));
2467
+ this.form.patchValue({ type: this.fieldTypes[0] });
2468
+ this.nameAlreadyExists$ = combineLatest([this.name.valueChanges, this.fieldNames$]).pipe(map(([value, fieldNames]) => fieldNames.includes(value.toLowerCase()) && value != this.currentField?.name));
2469
+ this.subscriptions.add(this.nameAlreadyExists$.subscribe((value) => {
2473
2470
  if (value) {
2474
- this.fieldForm.controls['name'].setErrors({ 'same-name': true });
2471
+ this.name?.setErrors({ 'same-name': true });
2475
2472
  }
2476
2473
  return value;
2477
2474
  }));
2475
+ this.goBackPath = this.router.createUrlTree(['..'], { relativeTo: this.route }).toString();
2476
+ this.goBackPathEdit = this.router.createUrlTree(['../..'], { relativeTo: this.route }).toString();
2477
+ }
2478
+ ngOnInit() {
2478
2479
  if (this.currentField) {
2479
- this.fieldForm.patchValue({
2480
- id: this.currentField.id,
2480
+ this.form.patchValue({
2481
2481
  name: this.currentField.name,
2482
2482
  type: this.currentField.type
2483
2483
  });
2484
- this.fieldForm.controls['type'].disable();
2484
+ this.type.disable();
2485
2485
  if (this.isGeographicType) {
2486
- this.fieldForm.addControl('crs', new FormControl(this.currentField.crs, [Validators.required]));
2487
- this.fieldForm.controls['crs'].disable();
2486
+ this.form.addControl('crs', new FormControl(this.currentField.crs, { validators: [Validators.required], nonNullable: true }));
2487
+ this.crs?.disable();
2488
2488
  }
2489
+ this.setFormatOptionValues();
2489
2490
  }
2490
- this.selectedFieldTypeDescription$ = this.fieldForm.get('type')?.valueChanges.pipe(startWith(this.currentField?.type ?? this.fieldTypeTranslations[0]['varType']), distinctUntilChanged(), map((selectedType) => this.fieldTypeTranslations.find((translation) => translation['varType'] === selectedType)?.['description'] ??
2491
- ''));
2492
- this.fieldForm.get('type').valueChanges.subscribe((type) => {
2491
+ this.subscriptions.add(this.type.valueChanges.subscribe((type) => {
2493
2492
  if (this.isGeographicType) {
2494
- this.fieldForm.addControl('crs', new FormControl(CRS_OPTIONS[0].code, [Validators.required]));
2493
+ this.form.addControl('crs', new FormControl(CRS_OPTIONS[0].code, { validators: [Validators.required], nonNullable: true }));
2495
2494
  }
2496
2495
  else {
2497
- this.fieldForm.removeControl('crs');
2496
+ this.form.removeControl('crs');
2498
2497
  }
2499
- });
2498
+ }));
2500
2499
  }
2501
- get isGeographicType() {
2502
- return GeometricFieldTypes.includes(this.fieldForm.get('type')?.value);
2500
+ get name() {
2501
+ return this.form.get('name');
2503
2502
  }
2504
- ngOnDestroy() {
2505
- this.sub.unsubscribe();
2503
+ get type() {
2504
+ return this.form.get('type');
2505
+ }
2506
+ get crs() {
2507
+ return this.form.get('crs');
2508
+ }
2509
+ get formatOptions() {
2510
+ return this.form.get('formatOptions');
2511
+ }
2512
+ get isGeographicType() {
2513
+ return GeometricFieldTypes.includes(this.type?.value);
2506
2514
  }
2507
2515
  goBack() {
2508
2516
  this.store.dispatch(AdminActions.routeTo({ path: this.getPath(), params: undefined }));
2509
2517
  }
2510
- addField() {
2511
- this.fieldForm.patchValue({
2512
- name: this.fieldForm.value.name.trim()
2518
+ getFormValue() {
2519
+ return {
2520
+ name: this.name.value,
2521
+ type: this.type.value,
2522
+ crs: this.crs?.value,
2523
+ unit: this.formatOptions?.value.unit ?? undefined,
2524
+ decimalPrecision: this.formatOptions?.value.decimalPrecision ?? undefined,
2525
+ isLocaleFormat: this.formatOptions?.value.isLocaleFormat ?? undefined,
2526
+ format: this.formatOptions?.value.dateFormat ?? undefined
2527
+ };
2528
+ }
2529
+ submit() {
2530
+ this.form.patchValue({
2531
+ name: this.name?.value?.trim()
2513
2532
  });
2514
- this.isSubmitted = true;
2515
- if (this.fieldForm.valid) {
2516
- this.isSubmitted = false;
2517
- let fieldToSave = this.fieldForm.getRawValue();
2518
- this.store.dispatch(FieldsActions.saveField({ field: fieldToSave, route: this.getPath() }));
2533
+ if (this.form.valid) {
2534
+ this.currentField ? this.updateField() : this.saveField();
2535
+ }
2536
+ }
2537
+ saveField() {
2538
+ this.store.dispatch(FieldsActions.saveField({
2539
+ field: { id: v4(), ...this.getFormValue() },
2540
+ route: this.getPath()
2541
+ }));
2542
+ }
2543
+ updateField() {
2544
+ this.store.dispatch(FieldsActions.updateField({
2545
+ field: { id: this.currentField.id, ...this.getFormValue() },
2546
+ route: this.getPath()
2547
+ }));
2548
+ }
2549
+ setFormatOptionControls(type) {
2550
+ switch (type) {
2551
+ case FieldType.INTEGER:
2552
+ case FieldType.LONG:
2553
+ this.formatOptions?.addControl('isLocaleFormat', new FormControl(true));
2554
+ this.formatOptions?.setControl('unit', new FormControl(null));
2555
+ this.formatOptions?.removeControl('decimalPrecision');
2556
+ this.formatOptions?.removeControl('dateFormat');
2557
+ break;
2558
+ case FieldType.DECIMAL:
2559
+ this.formatOptions?.addControl('isLocaleFormat', new FormControl(true));
2560
+ this.formatOptions?.setControl('unit', new FormControl(null));
2561
+ this.formatOptions?.setControl('decimalPrecision', new FormControl(2));
2562
+ this.formatOptions?.removeControl('dateFormat');
2563
+ break;
2564
+ case FieldType.INSTANT:
2565
+ this.formatOptions?.removeControl('isLocaleFormat');
2566
+ this.formatOptions?.removeControl('unit');
2567
+ this.formatOptions?.removeControl('decimalPrecision');
2568
+ this.formatOptions?.setControl('dateFormat', new FormControl(null));
2569
+ break;
2570
+ default:
2571
+ this.form.removeControl('formatOptions');
2572
+ break;
2573
+ }
2574
+ }
2575
+ setFormatOptionValues() {
2576
+ switch (this.currentField?.type) {
2577
+ case FieldType.INTEGER:
2578
+ case FieldType.LONG:
2579
+ this.formatOptions?.patchValue({
2580
+ isLocaleFormat: this.currentField?.isLocaleFormat,
2581
+ unit: this.currentField?.unit
2582
+ });
2583
+ break;
2584
+ case FieldType.DECIMAL:
2585
+ this.formatOptions?.patchValue({
2586
+ isLocaleFormat: this.currentField?.isLocaleFormat,
2587
+ unit: this.currentField?.unit,
2588
+ decimalPrecision: this.currentField?.decimalPrecision
2589
+ });
2590
+ break;
2591
+ case FieldType.INSTANT:
2592
+ this.formatOptions?.patchValue({ dateFormat: this.currentField?.format });
2593
+ break;
2594
+ default:
2595
+ break;
2519
2596
  }
2520
2597
  }
2521
2598
  getPath() {
2522
2599
  return this.currentField ? this.goBackPathEdit : this.goBackPath;
2523
2600
  }
2524
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminFieldsFormComponent, deps: [{ token: i1.Store }, { token: i2.Router }, { token: i2.ActivatedRoute }, { token: i3$1.UntypedFormBuilder }, { token: i4.PryI18nService }], target: i0.ɵɵFactoryTarget.Component }); }
2525
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: AdminFieldsFormComponent, selector: "pry-admin-fields-form", inputs: { currentField: "currentField" }, ngImport: i0, template: "<div>\n <form class=\"o-form\" [formGroup]=\"fieldForm\" (ngSubmit)=\"addField()\">\n <div class=\"m-form-label-field -width-sm\">\n <label id=\"name-label\" for=\"field_name\" class=\"a-label\">\n {{ '@pry.admin.fields.name' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <input\n id=\"field_name\"\n type=\"text\"\n class=\"a-form-field\"\n formControlName=\"name\"\n [attr.aria-labelledby]=\"isSubmitted && fieldForm.get('name')?.invalid ? 'name-label name-error' : 'name-label'\"\n [attr.aria-invalid]=\"isSubmitted && fieldForm.get('name')?.invalid\"\n required\n />\n <label\n *ngIf=\"isSubmitted && fieldForm.get('name')?.invalid\"\n id=\"name-error\"\n for=\"field_name\"\n class=\"a-label a-label--help -error\"\n >\n <span *ngIf=\"fieldForm.get('name')?.hasError('same-name')\">{{ '@pry.admin.exists' | i18n }}</span>\n <span *ngIf=\"fieldForm.get('name')?.hasError('required')\">{{ '@pry.admin.required' | i18n }}</span>\n <span *ngIf=\"fieldForm.get('name')?.hasError('minlength')\">{{\n '@pry.admin.minLength' | i18n : { len: 3 }\n }}</span>\n <span *ngIf=\"fieldForm.get('name')?.hasError('maxlength')\">{{\n '@pry.admin.maxLength' | i18n : { len: 100 }\n }}</span>\n <span *ngIf=\"fieldForm.get('name')?.hasError('whitespace') && !fieldForm.get('name')?.hasError('minlength')\">{{\n '@pry.admin.noWhitespace' | i18n\n }}</span>\n </label>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\">\n {{ '@pry.admin.fields.type' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <div class=\"u-display-flex\">\n <pry-select\n class=\"-width-sm\"\n formControlName=\"type\"\n [items]=\"fieldTypeTranslations\"\n bindValue=\"varType\"\n bindLabel=\"translation\"\n [isForm]=\"true\"\n ></pry-select>\n <div\n *ngIf=\"selectedFieldTypeDescription$ | async as description\"\n class=\"m-info-icon a-tooltip -tooltip-width-lg u-self-center -flex-shrink-0\"\n [attr.data-tooltip]=\"description\"\n data-tooltip-position=\"right\"\n >\n <span>i</span>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\" *ngIf=\"isGeographicType\">\n <label class=\"a-label\">\n {{ '@pry.admin.fields.crs' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <div class=\"u-display-flex\">\n <pry-select\n class=\"-width-sm\"\n formControlName=\"crs\"\n [items]=\"CRS_OPTIONS\"\n bindValue=\"code\"\n bindLabel=\"label\"\n [isForm]=\"true\"\n id=\"crs\"\n ></pry-select>\n </div>\n <label\n *ngIf=\"isSubmitted && fieldForm.get('crs') && fieldForm.get('crs')?.invalid\"\n id=\"crs-error\"\n for=\"crs\"\n class=\"a-label a-label--help -error\"\n >\n <span *ngIf=\"fieldForm.get('name')?.hasError('required')\">{{ '@pry.admin.required' | i18n }}</span>\n </label>\n </div>\n\n <div class=\"m-btn-group -width-sm\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button\n class=\"a-btn a-btn--primary\"\n type=\"submit\"\n [innerHTML]=\"(currentField ? '@pry.admin.edit' : '@pry.admin.create') | i18n\"\n ></button>\n </div>\n </form>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i4.PrySelectComponent, selector: "pry-select", inputs: ["items", "clearable", "multiple", "closeOnSelect", "placeholder", "isForm", "required", "name", "readonly", "autocomplete", "alwaysShowAutosuggestedValues", "externalAutocompleteService", "bindValue", "bindLabel", "iconSize", "bindIcon", "template", "i18nPrefix", "bindClasses", "loading", "elementRef"], outputs: ["searched", "cleared", "clicked"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
2601
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminFieldsFormComponent, deps: [{ token: i1.Store }, { token: i2.Router }, { token: i2.ActivatedRoute }, { token: i4.PryI18nService }], target: i0.ɵɵFactoryTarget.Component }); }
2602
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.1.3", type: AdminFieldsFormComponent, selector: "pry-admin-fields-form", inputs: { currentField: "currentField" }, usesInheritance: true, ngImport: i0, template: "<div>\n <form class=\"o-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n <div class=\"m-form-label-field -width-sm\">\n <label id=\"name-label\" for=\"field_name\" class=\"a-label\">\n {{ '@pry.admin.fields.name' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <input\n id=\"field_name\"\n type=\"text\"\n class=\"a-form-field\"\n formControlName=\"name\"\n [attr.aria-labelledby]=\"name?.dirty && name?.invalid ? 'name-label name-error' : 'name-label'\"\n [attr.aria-invalid]=\"name?.dirty && name?.invalid\"\n />\n @if (name?.dirty && name?.invalid) {\n <label id=\"name-error\" for=\"field_name\" class=\"a-label a-label--help -error\">\n @if (name?.hasError('same-name')) {\n <span>{{ '@pry.admin.exists' | i18n }}</span>\n }\n @if (name?.hasError('required')) {\n <span>{{ '@pry.admin.required' | i18n }}</span>\n }\n @if (name?.hasError('minlength')) {\n <span>{{ '@pry.admin.minLength' | i18n: { len: 3 } }}</span>\n }\n @if (name?.hasError('maxlength')) {\n <span>{{ '@pry.admin.maxLength' | i18n: { len: 100 } }}</span>\n }\n @if (name?.hasError('whitespace') && !name?.hasError('minlength')) {\n <span>{{ '@pry.admin.noWhitespace' | i18n }}</span>\n }\n </label>\n }\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"field_type\">\n {{ '@pry.admin.fields.type' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <div class=\"u-display-flex\">\n <pry-select\n id=\"field_type\"\n class=\"u-flex-grow-1\"\n formControlName=\"type\"\n [items]=\"fieldTypes\"\n [i18nPrefix]=\"FIELD_I18N.label\"\n [isForm]=\"true\"\n ></pry-select>\n <div\n class=\"m-info-icon a-tooltip -tooltip-width-lg u-self-center u-flex-shrink-0\"\n [attr.data-tooltip]=\"FIELD_I18N.information + this.type?.value | i18n\"\n data-tooltip-position=\"right\"\n >\n <span>i</span>\n </div>\n </div>\n </div>\n\n @if (isGeographicType) {\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"crs\">\n {{ '@pry.admin.fields.crs' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <div class=\"u-display-flex\">\n <pry-select\n class=\"-width-sm\"\n formControlName=\"crs\"\n [items]=\"CRS_OPTIONS\"\n bindValue=\"code\"\n bindLabel=\"label\"\n [isForm]=\"true\"\n id=\"crs\"\n ></pry-select>\n </div>\n @if (crs?.dirty && crs?.invalid) {\n <label id=\"crs-error\" for=\"crs\" class=\"a-label a-label--help -error\">\n @if (crs?.hasError('required')) {\n <span>{{ '@pry.admin.required' | i18n }}</span>\n }\n </label>\n }\n </div>\n }\n\n @if (formatOptions) {\n <div formGroupName=\"formatOptions\">\n <h3 class=\"a-h3\">{{ '@pry.admin.fields.formatOptions.title' | i18n }}</h3>\n @if (type?.value === FieldType.INTEGER || type?.value === FieldType.LONG || type?.value === FieldType.DECIMAL) {\n <ng-container *ngTemplateOutlet=\"numberFormatOptions\"></ng-container>\n } @else if (type?.value === FieldType.INSTANT) {\n <ng-container *ngTemplateOutlet=\"dateFormatOptions\"></ng-container>\n }\n\n <ng-template #numberFormatOptions>\n @if (type?.value === FieldType.DECIMAL) {\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"field_format_comma\">{{\n '@pry.admin.fields.formatOptions.decimalPrecision' | i18n\n }}</label>\n <input formControlName=\"decimalPrecision\" id=\"field_format_comma\" type=\"number\" class=\"a-form-field\" />\n </div>\n }\n <div class=\"m-form-label-field -width-sm\">\n <pry-checkbox\n formControlName=\"isLocaleFormat\"\n inputId=\"field_format_locale_number_format\"\n [inhibit]=\"false\"\n >\n {{ '@pry.admin.fields.formatOptions.isLocaleFormat' | i18n }}\n </pry-checkbox>\n </div>\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"field_format_unit\">{{ '@pry.admin.fields.formatOptions.unit' | i18n }}</label>\n <input formControlName=\"unit\" id=\"field_format_unit\" type=\"text\" class=\"a-form-field\" />\n </div>\n </ng-template>\n\n <ng-template #dateFormatOptions>\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"field_format_date\">{{\n '@pry.admin.fields.formatOptions.dateFormat' | i18n\n }}</label>\n <pry-select\n formControlName=\"dateFormat\"\n id=\"field_format_date\"\n [items]=\"dateFormats\"\n [isForm]=\"true\"\n i18nPrefix=\"@pry.admin.fields.formatOptions.dateFormatOptions.\"\n [clearable]=\"true\"\n ></pry-select>\n </div>\n </ng-template>\n </div>\n }\n\n <div class=\"m-btn-group -width-sm\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button\n class=\"a-btn a-btn--primary\"\n type=\"submit\"\n [innerHTML]=\"(currentField ? '@pry.admin.edit' : '@pry.admin.create') | i18n\"\n ></button>\n </div>\n </form>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i3$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: i5$1.PryCheckboxComponent, selector: "pry-checkbox", inputs: ["circle", "name", "inputId", "inhibit"] }, { kind: "component", type: i4.PrySelectComponent, selector: "pry-select", inputs: ["items", "clearable", "multiple", "closeOnSelect", "placeholder", "isForm", "required", "name", "readonly", "autocomplete", "alwaysShowAutosuggestedValues", "externalAutocompleteService", "bindValue", "bindLabel", "iconSize", "bindIcon", "template", "i18nPrefix", "bindClasses", "loading", "elementRef"], outputs: ["searched", "cleared", "clicked"] }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
2526
2603
  }
2527
2604
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminFieldsFormComponent, decorators: [{
2528
2605
  type: Component,
2529
- args: [{ selector: 'pry-admin-fields-form', template: "<div>\n <form class=\"o-form\" [formGroup]=\"fieldForm\" (ngSubmit)=\"addField()\">\n <div class=\"m-form-label-field -width-sm\">\n <label id=\"name-label\" for=\"field_name\" class=\"a-label\">\n {{ '@pry.admin.fields.name' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <input\n id=\"field_name\"\n type=\"text\"\n class=\"a-form-field\"\n formControlName=\"name\"\n [attr.aria-labelledby]=\"isSubmitted && fieldForm.get('name')?.invalid ? 'name-label name-error' : 'name-label'\"\n [attr.aria-invalid]=\"isSubmitted && fieldForm.get('name')?.invalid\"\n required\n />\n <label\n *ngIf=\"isSubmitted && fieldForm.get('name')?.invalid\"\n id=\"name-error\"\n for=\"field_name\"\n class=\"a-label a-label--help -error\"\n >\n <span *ngIf=\"fieldForm.get('name')?.hasError('same-name')\">{{ '@pry.admin.exists' | i18n }}</span>\n <span *ngIf=\"fieldForm.get('name')?.hasError('required')\">{{ '@pry.admin.required' | i18n }}</span>\n <span *ngIf=\"fieldForm.get('name')?.hasError('minlength')\">{{\n '@pry.admin.minLength' | i18n : { len: 3 }\n }}</span>\n <span *ngIf=\"fieldForm.get('name')?.hasError('maxlength')\">{{\n '@pry.admin.maxLength' | i18n : { len: 100 }\n }}</span>\n <span *ngIf=\"fieldForm.get('name')?.hasError('whitespace') && !fieldForm.get('name')?.hasError('minlength')\">{{\n '@pry.admin.noWhitespace' | i18n\n }}</span>\n </label>\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\">\n {{ '@pry.admin.fields.type' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <div class=\"u-display-flex\">\n <pry-select\n class=\"-width-sm\"\n formControlName=\"type\"\n [items]=\"fieldTypeTranslations\"\n bindValue=\"varType\"\n bindLabel=\"translation\"\n [isForm]=\"true\"\n ></pry-select>\n <div\n *ngIf=\"selectedFieldTypeDescription$ | async as description\"\n class=\"m-info-icon a-tooltip -tooltip-width-lg u-self-center -flex-shrink-0\"\n [attr.data-tooltip]=\"description\"\n data-tooltip-position=\"right\"\n >\n <span>i</span>\n </div>\n </div>\n </div>\n\n <div class=\"m-form-label-field -width-sm\" *ngIf=\"isGeographicType\">\n <label class=\"a-label\">\n {{ '@pry.admin.fields.crs' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <div class=\"u-display-flex\">\n <pry-select\n class=\"-width-sm\"\n formControlName=\"crs\"\n [items]=\"CRS_OPTIONS\"\n bindValue=\"code\"\n bindLabel=\"label\"\n [isForm]=\"true\"\n id=\"crs\"\n ></pry-select>\n </div>\n <label\n *ngIf=\"isSubmitted && fieldForm.get('crs') && fieldForm.get('crs')?.invalid\"\n id=\"crs-error\"\n for=\"crs\"\n class=\"a-label a-label--help -error\"\n >\n <span *ngIf=\"fieldForm.get('name')?.hasError('required')\">{{ '@pry.admin.required' | i18n }}</span>\n </label>\n </div>\n\n <div class=\"m-btn-group -width-sm\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button\n class=\"a-btn a-btn--primary\"\n type=\"submit\"\n [innerHTML]=\"(currentField ? '@pry.admin.edit' : '@pry.admin.create') | i18n\"\n ></button>\n </div>\n </form>\n</div>\n" }]
2530
- }], ctorParameters: () => [{ type: i1.Store }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: i3$1.UntypedFormBuilder }, { type: i4.PryI18nService }], propDecorators: { currentField: [{
2606
+ args: [{ selector: 'pry-admin-fields-form', template: "<div>\n <form class=\"o-form\" [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n <div class=\"m-form-label-field -width-sm\">\n <label id=\"name-label\" for=\"field_name\" class=\"a-label\">\n {{ '@pry.admin.fields.name' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <input\n id=\"field_name\"\n type=\"text\"\n class=\"a-form-field\"\n formControlName=\"name\"\n [attr.aria-labelledby]=\"name?.dirty && name?.invalid ? 'name-label name-error' : 'name-label'\"\n [attr.aria-invalid]=\"name?.dirty && name?.invalid\"\n />\n @if (name?.dirty && name?.invalid) {\n <label id=\"name-error\" for=\"field_name\" class=\"a-label a-label--help -error\">\n @if (name?.hasError('same-name')) {\n <span>{{ '@pry.admin.exists' | i18n }}</span>\n }\n @if (name?.hasError('required')) {\n <span>{{ '@pry.admin.required' | i18n }}</span>\n }\n @if (name?.hasError('minlength')) {\n <span>{{ '@pry.admin.minLength' | i18n: { len: 3 } }}</span>\n }\n @if (name?.hasError('maxlength')) {\n <span>{{ '@pry.admin.maxLength' | i18n: { len: 100 } }}</span>\n }\n @if (name?.hasError('whitespace') && !name?.hasError('minlength')) {\n <span>{{ '@pry.admin.noWhitespace' | i18n }}</span>\n }\n </label>\n }\n </div>\n\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"field_type\">\n {{ '@pry.admin.fields.type' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <div class=\"u-display-flex\">\n <pry-select\n id=\"field_type\"\n class=\"u-flex-grow-1\"\n formControlName=\"type\"\n [items]=\"fieldTypes\"\n [i18nPrefix]=\"FIELD_I18N.label\"\n [isForm]=\"true\"\n ></pry-select>\n <div\n class=\"m-info-icon a-tooltip -tooltip-width-lg u-self-center u-flex-shrink-0\"\n [attr.data-tooltip]=\"FIELD_I18N.information + this.type?.value | i18n\"\n data-tooltip-position=\"right\"\n >\n <span>i</span>\n </div>\n </div>\n </div>\n\n @if (isGeographicType) {\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"crs\">\n {{ '@pry.admin.fields.crs' | i18n }} *\n <span class=\"u-visually-hidden\">({{ '@pry.admin.required' | i18n }})</span>\n </label>\n <div class=\"u-display-flex\">\n <pry-select\n class=\"-width-sm\"\n formControlName=\"crs\"\n [items]=\"CRS_OPTIONS\"\n bindValue=\"code\"\n bindLabel=\"label\"\n [isForm]=\"true\"\n id=\"crs\"\n ></pry-select>\n </div>\n @if (crs?.dirty && crs?.invalid) {\n <label id=\"crs-error\" for=\"crs\" class=\"a-label a-label--help -error\">\n @if (crs?.hasError('required')) {\n <span>{{ '@pry.admin.required' | i18n }}</span>\n }\n </label>\n }\n </div>\n }\n\n @if (formatOptions) {\n <div formGroupName=\"formatOptions\">\n <h3 class=\"a-h3\">{{ '@pry.admin.fields.formatOptions.title' | i18n }}</h3>\n @if (type?.value === FieldType.INTEGER || type?.value === FieldType.LONG || type?.value === FieldType.DECIMAL) {\n <ng-container *ngTemplateOutlet=\"numberFormatOptions\"></ng-container>\n } @else if (type?.value === FieldType.INSTANT) {\n <ng-container *ngTemplateOutlet=\"dateFormatOptions\"></ng-container>\n }\n\n <ng-template #numberFormatOptions>\n @if (type?.value === FieldType.DECIMAL) {\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"field_format_comma\">{{\n '@pry.admin.fields.formatOptions.decimalPrecision' | i18n\n }}</label>\n <input formControlName=\"decimalPrecision\" id=\"field_format_comma\" type=\"number\" class=\"a-form-field\" />\n </div>\n }\n <div class=\"m-form-label-field -width-sm\">\n <pry-checkbox\n formControlName=\"isLocaleFormat\"\n inputId=\"field_format_locale_number_format\"\n [inhibit]=\"false\"\n >\n {{ '@pry.admin.fields.formatOptions.isLocaleFormat' | i18n }}\n </pry-checkbox>\n </div>\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"field_format_unit\">{{ '@pry.admin.fields.formatOptions.unit' | i18n }}</label>\n <input formControlName=\"unit\" id=\"field_format_unit\" type=\"text\" class=\"a-form-field\" />\n </div>\n </ng-template>\n\n <ng-template #dateFormatOptions>\n <div class=\"m-form-label-field -width-sm\">\n <label class=\"a-label\" for=\"field_format_date\">{{\n '@pry.admin.fields.formatOptions.dateFormat' | i18n\n }}</label>\n <pry-select\n formControlName=\"dateFormat\"\n id=\"field_format_date\"\n [items]=\"dateFormats\"\n [isForm]=\"true\"\n i18nPrefix=\"@pry.admin.fields.formatOptions.dateFormatOptions.\"\n [clearable]=\"true\"\n ></pry-select>\n </div>\n </ng-template>\n </div>\n }\n\n <div class=\"m-btn-group -width-sm\">\n <button\n type=\"button\"\n class=\"a-btn a-btn--secondary\"\n (click)=\"goBack()\"\n [innerHTML]=\"'@pry.admin.cancel' | i18n\"\n ></button>\n <button\n class=\"a-btn a-btn--primary\"\n type=\"submit\"\n [innerHTML]=\"(currentField ? '@pry.admin.edit' : '@pry.admin.create') | i18n\"\n ></button>\n </div>\n </form>\n</div>\n" }]
2607
+ }], ctorParameters: () => [{ type: i1.Store }, { type: i2.Router }, { type: i2.ActivatedRoute }, { type: i4.PryI18nService }], propDecorators: { currentField: [{
2531
2608
  type: Input
2532
2609
  }] } });
2533
2610
 
@@ -2587,11 +2664,18 @@ class AdminFieldsComponent {
2587
2664
  this.route = route;
2588
2665
  this.sortActive = 'name';
2589
2666
  this.sortDirection = 'asc';
2667
+ this.FIELD_I18N = FIELD_I18N;
2590
2668
  this.store.dispatch(ClassActions.load());
2591
2669
  this.store.dispatch(FieldActions.load());
2592
2670
  this.store.dispatch(FieldsActions.unselectField());
2593
2671
  this.currentFieldId$ = this.store.select(FieldsSelectors.selectedFieldId);
2594
- this.fields$ = this.store.select(FieldSelectors.fields).pipe(switchMap((fields) => zip(fields.map((field) => zip(of(field), this.store.select(ClassSelectors.attributesByFieldId(field.id)))))), map((superFields) => superFields.map(([field, attributes]) => ({ ...field, attributes: attributes?.length ?? 0 }))));
2672
+ this.fields$ = combineLatest([
2673
+ this.store.select(FieldSelectors.fields),
2674
+ this.store.select(ClassSelectors.classes)
2675
+ ]).pipe(map(([fields, classes]) => fields.map((f) => ({
2676
+ ...f,
2677
+ attributeCount: classes.reduce((p, c) => p + c.attributes.filter((a) => a.field.id === f.id).length, 0)
2678
+ }))));
2595
2679
  const path = this.router.createUrlTree(['.', 'new'], { relativeTo: this.route });
2596
2680
  this.store.dispatch(AdminActions.mainActions({
2597
2681
  actions: [
@@ -2611,15 +2695,12 @@ class AdminFieldsComponent {
2611
2695
  this.store.dispatch(AdminActions.selectComponentType({ componentType: 'AdminFieldsSelectComponent' }));
2612
2696
  this.store.dispatch(AdminActions.fetchFieldAssociations({ id: field.id }));
2613
2697
  }
2614
- getTranslationType(type) {
2615
- return FIELD_OPTIONS.find((el) => el.varType === type)?.translation || 'undefined';
2616
- }
2617
2698
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminFieldsComponent, deps: [{ token: i1.Store }, { token: i2.Router }, { token: i2.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component }); }
2618
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: AdminFieldsComponent, selector: "pry-admin-fields", ngImport: i0, template: "<div class=\"o-base-container\">\n <h1 class=\"a-h1\">{{ '@pry.admin.fields.list' | i18n }}</h1>\n <table\n class=\"a-table\"\n prySortTable\n prySortActive=\"name\"\n prySortDirection=\"asc\"\n (prySortChange)=\"sortActive = $event.active; sortDirection = $event.direction\"\n >\n <caption>\n {{\n '@pry.admin.fields.list' | i18n\n }},\n {{\n '@pry.action.sortableColumnHeader' | i18n\n }}\n </caption>\n <thead>\n <tr>\n <th></th>\n <th prySortHeader=\"name\">{{ '@pry.admin.fields.name' | i18n }}</th>\n <th prySortHeader=\"type\">{{ '@pry.admin.fields.type' | i18n }}</th>\n <th prySortHeader=\"attributes\">{{ '@pry.admin.fields.attributes' | i18n }}</th>\n </tr>\n </thead>\n <tbody>\n <tr\n *ngFor=\"let field of fields$ | async | prySortData: sortActive : sortDirection\"\n (click)=\"selectField(field)\"\n [class.is-selected]=\"(currentFieldId$ | async) === field.id\"\n >\n <td class=\"view-details\">\n <button\n [id]=\"'button-field-' + field.id\"\n type=\"button\"\n class=\"a-btn a-btn--icon-only\"\n title=\"{{ '@pry.action.viewDetails' | i18n }}\"\n [attr.aria-expanded]=\"(currentFieldId$ | async) === field.id\"\n aria-haspopup\n [attr.aria-controls]=\"'panel-field-' + field.id\"\n >\n <span class=\"u-visually-hidden\">{{ field.name }}, {{ '@pry.action.viewDetails' | i18n }}</span>\n <pry-icon iconSvg=\"eye\" [width]=\"15\" [height]=\"15\"></pry-icon>\n </button>\n </td>\n <td>{{ field.name }}</td>\n <td>{{ getTranslationType(field.type) | i18n }}</td>\n <td>{{ field.attributes }}</td>\n </tr>\n </tbody>\n </table>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i4.PryIconComponent, selector: "pry-icon", inputs: ["color", "iconSvg", "animation", "iconImage", "alt", "width", "height", "classes"] }, { kind: "component", type: i4.PrySortHeaderComponent, selector: "th[prySortHeader]", inputs: ["prySortHeader"], outputs: ["sortChange"] }, { kind: "directive", type: i4.PrySortHeaderDirective, selector: "[prySortHeader]" }, { kind: "directive", type: i4.PrySortTableDirective, selector: "[prySortTable]", inputs: ["prySortActive", "prySortDirection"], outputs: ["prySortChange"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.PrySortDataPipe, name: "prySortData" }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
2699
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.1.3", type: AdminFieldsComponent, selector: "pry-admin-fields", ngImport: i0, template: "<div class=\"o-base-container\">\n <h1 class=\"a-h1\">{{ '@pry.admin.fields.list' | i18n }}</h1>\n @if (fields$ | async; as fields) {\n <table\n class=\"a-table\"\n prySortTable\n prySortActive=\"name\"\n prySortDirection=\"asc\"\n (prySortChange)=\"sortActive = $event.active; sortDirection = $event.direction\"\n >\n <caption>\n {{\n '@pry.admin.fields.list' | i18n\n }},\n {{\n '@pry.action.sortableColumnHeader' | i18n\n }}\n </caption>\n <thead>\n <tr>\n <th></th>\n <th prySortHeader=\"name\">{{ '@pry.admin.fields.name' | i18n }}</th>\n <th prySortHeader=\"type\">{{ '@pry.admin.fields.type' | i18n }}</th>\n <th prySortHeader=\"attributes\">{{ '@pry.admin.fields.attributes' | i18n }}</th>\n </tr>\n </thead>\n <tbody>\n @for (field of fields | prySortData: sortActive : sortDirection; track field.id) {\n <tr (click)=\"selectField(field)\" [class.is-selected]=\"(currentFieldId$ | async) === field.id\">\n <td class=\"view-details\">\n <button\n [id]=\"'button-field-' + field.id\"\n type=\"button\"\n class=\"a-btn a-btn--icon-only\"\n title=\"{{ '@pry.action.viewDetails' | i18n }}\"\n [attr.aria-expanded]=\"(currentFieldId$ | async) === field.id\"\n aria-haspopup\n [attr.aria-controls]=\"'panel-field-' + field.id\"\n >\n <span class=\"u-visually-hidden\">{{ field.name }}, {{ '@pry.action.viewDetails' | i18n }}</span>\n <pry-icon iconSvg=\"eye\" [width]=\"15\" [height]=\"15\"></pry-icon>\n </button>\n </td>\n <td>{{ field.name }}</td>\n <td>{{ FIELD_I18N.label + field.type | i18n }}</td>\n <td>{{ field.attributeCount }}</td>\n </tr>\n }\n </tbody>\n </table>\n }\n</div>\n", dependencies: [{ kind: "component", type: i4.PryIconComponent, selector: "pry-icon", inputs: ["color", "iconSvg", "animation", "iconImage", "alt", "width", "height", "classes"] }, { kind: "component", type: i4.PrySortHeaderComponent, selector: "th[prySortHeader]", inputs: ["prySortHeader"], outputs: ["sortChange"] }, { kind: "directive", type: i4.PrySortHeaderDirective, selector: "[prySortHeader]" }, { kind: "directive", type: i4.PrySortTableDirective, selector: "[prySortTable]", inputs: ["prySortActive", "prySortDirection"], outputs: ["prySortChange"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.PrySortDataPipe, name: "prySortData" }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
2619
2700
  }
2620
2701
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminFieldsComponent, decorators: [{
2621
2702
  type: Component,
2622
- args: [{ selector: 'pry-admin-fields', template: "<div class=\"o-base-container\">\n <h1 class=\"a-h1\">{{ '@pry.admin.fields.list' | i18n }}</h1>\n <table\n class=\"a-table\"\n prySortTable\n prySortActive=\"name\"\n prySortDirection=\"asc\"\n (prySortChange)=\"sortActive = $event.active; sortDirection = $event.direction\"\n >\n <caption>\n {{\n '@pry.admin.fields.list' | i18n\n }},\n {{\n '@pry.action.sortableColumnHeader' | i18n\n }}\n </caption>\n <thead>\n <tr>\n <th></th>\n <th prySortHeader=\"name\">{{ '@pry.admin.fields.name' | i18n }}</th>\n <th prySortHeader=\"type\">{{ '@pry.admin.fields.type' | i18n }}</th>\n <th prySortHeader=\"attributes\">{{ '@pry.admin.fields.attributes' | i18n }}</th>\n </tr>\n </thead>\n <tbody>\n <tr\n *ngFor=\"let field of fields$ | async | prySortData: sortActive : sortDirection\"\n (click)=\"selectField(field)\"\n [class.is-selected]=\"(currentFieldId$ | async) === field.id\"\n >\n <td class=\"view-details\">\n <button\n [id]=\"'button-field-' + field.id\"\n type=\"button\"\n class=\"a-btn a-btn--icon-only\"\n title=\"{{ '@pry.action.viewDetails' | i18n }}\"\n [attr.aria-expanded]=\"(currentFieldId$ | async) === field.id\"\n aria-haspopup\n [attr.aria-controls]=\"'panel-field-' + field.id\"\n >\n <span class=\"u-visually-hidden\">{{ field.name }}, {{ '@pry.action.viewDetails' | i18n }}</span>\n <pry-icon iconSvg=\"eye\" [width]=\"15\" [height]=\"15\"></pry-icon>\n </button>\n </td>\n <td>{{ field.name }}</td>\n <td>{{ getTranslationType(field.type) | i18n }}</td>\n <td>{{ field.attributes }}</td>\n </tr>\n </tbody>\n </table>\n</div>\n" }]
2703
+ args: [{ selector: 'pry-admin-fields', template: "<div class=\"o-base-container\">\n <h1 class=\"a-h1\">{{ '@pry.admin.fields.list' | i18n }}</h1>\n @if (fields$ | async; as fields) {\n <table\n class=\"a-table\"\n prySortTable\n prySortActive=\"name\"\n prySortDirection=\"asc\"\n (prySortChange)=\"sortActive = $event.active; sortDirection = $event.direction\"\n >\n <caption>\n {{\n '@pry.admin.fields.list' | i18n\n }},\n {{\n '@pry.action.sortableColumnHeader' | i18n\n }}\n </caption>\n <thead>\n <tr>\n <th></th>\n <th prySortHeader=\"name\">{{ '@pry.admin.fields.name' | i18n }}</th>\n <th prySortHeader=\"type\">{{ '@pry.admin.fields.type' | i18n }}</th>\n <th prySortHeader=\"attributes\">{{ '@pry.admin.fields.attributes' | i18n }}</th>\n </tr>\n </thead>\n <tbody>\n @for (field of fields | prySortData: sortActive : sortDirection; track field.id) {\n <tr (click)=\"selectField(field)\" [class.is-selected]=\"(currentFieldId$ | async) === field.id\">\n <td class=\"view-details\">\n <button\n [id]=\"'button-field-' + field.id\"\n type=\"button\"\n class=\"a-btn a-btn--icon-only\"\n title=\"{{ '@pry.action.viewDetails' | i18n }}\"\n [attr.aria-expanded]=\"(currentFieldId$ | async) === field.id\"\n aria-haspopup\n [attr.aria-controls]=\"'panel-field-' + field.id\"\n >\n <span class=\"u-visually-hidden\">{{ field.name }}, {{ '@pry.action.viewDetails' | i18n }}</span>\n <pry-icon iconSvg=\"eye\" [width]=\"15\" [height]=\"15\"></pry-icon>\n </button>\n </td>\n <td>{{ field.name }}</td>\n <td>{{ FIELD_I18N.label + field.type | i18n }}</td>\n <td>{{ field.attributeCount }}</td>\n </tr>\n }\n </tbody>\n </table>\n }\n</div>\n" }]
2623
2704
  }], ctorParameters: () => [{ type: i1.Store }, { type: i2.Router }, { type: i2.ActivatedRoute }] });
2624
2705
 
2625
2706
  const adminFeatureKey = '@pry/admin';
@@ -2944,7 +3025,7 @@ class AdminSelectDatasetComponent extends SubscriptionnerDirective {
2944
3025
  moduleAccess: 'admin',
2945
3026
  pageAccess: 'dataset',
2946
3027
  actionAccess: 'write',
2947
- disabled: versions.filter((v) => v.dataset === dataset.id).length > 0
3028
+ disabled: versions.filter((v) => v.dataset.id === dataset.id).length > 0
2948
3029
  }
2949
3030
  ]
2950
3031
  }));
@@ -3112,12 +3193,14 @@ class AdminFieldsSelectComponent {
3112
3193
  this.router = router;
3113
3194
  this.route = route;
3114
3195
  this.sub = new Subscription();
3196
+ this.FIELD_I18N = FIELD_I18N;
3197
+ this.FieldType = FieldType;
3115
3198
  this.currentField$ = this.store.select(FieldsSelectors.selectedField);
3116
3199
  this.associations$ = this.store.select(AdminSelectors.selectedAssociation);
3117
3200
  this.attributes$ = combineLatest([this.currentField$, store.select(ClassSelectors.classes)]).pipe(map(([field, classes]) => {
3118
3201
  return classes
3119
3202
  .map((clazz) => clazz.attributes
3120
- .filter((attribute) => attribute.field === field?.id)
3203
+ .filter((attribute) => attribute.field.id === field?.id)
3121
3204
  .map((attribute) => ({ technicalName: attribute.technicalName, classId: clazz.id })))
3122
3205
  .flat();
3123
3206
  }));
@@ -3153,9 +3236,6 @@ class AdminFieldsSelectComponent {
3153
3236
  }
3154
3237
  }));
3155
3238
  }
3156
- getTranslationType(type) {
3157
- return FIELD_OPTIONS.find((el) => el.varType === type)?.translation || 'undefined';
3158
- }
3159
3239
  closePanel() {
3160
3240
  this.store.dispatch(FieldsActions.unselectField());
3161
3241
  this.store.dispatch(AdminActions.togglePanel({ panelOpen: false }));
@@ -3177,11 +3257,11 @@ class AdminFieldsSelectComponent {
3177
3257
  this.sub.unsubscribe();
3178
3258
  }
3179
3259
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminFieldsSelectComponent, deps: [{ token: i1.Store }, { token: i2.Router }, { token: i2.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component }); }
3180
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: AdminFieldsSelectComponent, selector: "pry-admin-fields-select", ngImport: i0, template: "<div\n *ngIf=\"currentField$ | async as field\"\n [id]=\"'panel-field-' + field.id\"\n [attr.aria-labelledby]=\"'button-field-' + field.id\"\n class=\"o-panel\"\n>\n <div class=\"o-panel__header\">\n <button type=\"button\" class=\"a-btn a-btn--icon-only\" (click)=\"closePanel()\">\n <span class=\"u-visually-hidden\">{{ '@pry.action.closePanel' | i18n }}</span>\n <pry-icon iconSvg=\"close\"></pry-icon>\n </button>\n\n <h3 class=\"a-h3\">\n {{ '@pry.admin.fields.info' | i18n }}\n </h3>\n </div>\n\n <pry-tab-group translationStringBase=\"@pry.admin.\">\n <pry-tab [templateRef]=\"fieldDetails\" name=\"details\"></pry-tab>\n <pry-tab [templateRef]=\"fieldAssociations\" name=\"classes.associations\"></pry-tab>\n </pry-tab-group>\n\n <ng-template #fieldDetails>\n <h4 class=\"a-h4\">{{ '@pry.admin.properties' | i18n }}</h4>\n <p class=\"a-p\">\n {{ '@pry.admin.fields.name' | i18n }} :\n <strong>{{ field.name }}</strong>\n </p>\n <p class=\"a-p\">{{ '@pry.admin.fields.description' | i18n }} :</p>\n <p class=\"a-p\">\n {{ '@pry.admin.fields.type' | i18n }} :\n <strong>{{ getTranslationType(field.type) | i18n }}</strong>\n </p>\n </ng-template>\n\n <ng-template #fieldAssociations>\n <h4 class=\"a-h4\">{{ '@pry.admin.classes.associations' | i18n }}</h4>\n <pry-association [associations]=\"associations$ | async\"></pry-association>\n </ng-template>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.TabGroupComponent, selector: "pry-tab-group", inputs: ["translationStringBase"], outputs: ["clickedTabIdx"] }, { kind: "component", type: i4.TabComponent, selector: "pry-tab", inputs: ["name", "templateRef", "index"] }, { kind: "component", type: i4.PryIconComponent, selector: "pry-icon", inputs: ["color", "iconSvg", "animation", "iconImage", "alt", "width", "height", "classes"] }, { kind: "component", type: PryAssociationComponent, selector: "pry-association", inputs: ["associations"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
3260
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.1.3", type: AdminFieldsSelectComponent, selector: "pry-admin-fields-select", ngImport: i0, template: "<div\n *ngIf=\"currentField$ | async as field\"\n [id]=\"'panel-field-' + field.id\"\n [attr.aria-labelledby]=\"'button-field-' + field.id\"\n class=\"o-panel\"\n>\n <div class=\"o-panel__header\">\n <button type=\"button\" class=\"a-btn a-btn--icon-only\" (click)=\"closePanel()\">\n <span class=\"u-visually-hidden\">{{ '@pry.action.closePanel' | i18n }}</span>\n <pry-icon iconSvg=\"close\"></pry-icon>\n </button>\n\n <h3 class=\"a-h3\">\n {{ '@pry.admin.fields.info' | i18n }}\n </h3>\n </div>\n\n <pry-tab-group translationStringBase=\"@pry.admin.\">\n <pry-tab [templateRef]=\"fieldDetails\" name=\"details\"></pry-tab>\n <pry-tab [templateRef]=\"fieldAssociations\" name=\"classes.associations\"></pry-tab>\n </pry-tab-group>\n\n <ng-template #fieldDetails>\n <div class=\"u-display-flex -column -gap-20\">\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.name' | i18n }}</h4>\n <span>{{ field.name }}</span>\n </div>\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.type' | i18n }}</h4>\n <span>{{ FIELD_I18N.label + field.type | i18n }}</span>\n </div>\n @if ([FieldType.INTEGER, FieldType.LONG, FieldType.DECIMAL, FieldType.INSTANT].includes(field.type)) {\n <div>\n <h3 class=\"a-h3 -no-padding\">{{ '@pry.admin.fields.formatOptions.title' | i18n }}</h3>\n <div class=\"u-display-flex -column -gap-20\">\n @switch (field.type) {\n @case (FieldType.INTEGER) {\n <ng-container *ngTemplateOutlet=\"numberFormatOptions\"></ng-container>\n }\n @case (FieldType.LONG) {\n <ng-container *ngTemplateOutlet=\"numberFormatOptions\"></ng-container>\n }\n @case (FieldType.DECIMAL) {\n <ng-container *ngTemplateOutlet=\"numberFormatOptions\"></ng-container>\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.formatOptions.decimalPrecision' | i18n }}</h4>\n @if (field.decimalPrecision) {\n <span>{{ field.decimalPrecision }}</span>\n } @else {\n <span class=\"-italic\">{{ '@pry.admin.fields.formatOptions.noDecimalPrecision' | i18n }}</span>\n }\n </div>\n }\n @case (FieldType.INSTANT) {\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.formatOptions.dateFormat' | i18n }}</h4>\n @if (field.format) {\n <span>{{ '@pry.admin.fields.formatOptions.dateFormatOptions' + field.format | i18n }}</span>\n } @else {\n <span class=\"-italic\">{{ '@pry.admin.fields.formatOptions.noDateFormat' | i18n }}</span>\n }\n </div>\n }\n }\n </div>\n </div>\n }\n @if (field.crs) {\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.crs' | i18n }}</h4>\n <span>{{ field.crs }}</span>\n </div>\n }\n </div>\n\n <ng-template #numberFormatOptions>\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.formatOptions.unit' | i18n }}</h4>\n @if (field.unit) {\n <span>{{ field.unit }}</span>\n } @else {\n <span class=\"-italic\">{{ '@pry.admin.fields.formatOptions.noUnit' | i18n }}</span>\n }\n </div>\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.formatOptions.isLocaleFormat' | i18n }}</h4>\n <span>{{ (field.isLocaleFormat ? '@pry.action.yes' : '@pry.action.no') | i18n }}</span>\n </div>\n </ng-template>\n </ng-template>\n\n <ng-template #fieldAssociations>\n <h4 class=\"a-h4\">{{ '@pry.admin.classes.associations' | i18n }}</h4>\n <pry-association [associations]=\"associations$ | async\"></pry-association>\n </ng-template>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.TabGroupComponent, selector: "pry-tab-group", inputs: ["translationStringBase"], outputs: ["clickedTabIdx"] }, { kind: "component", type: i4.TabComponent, selector: "pry-tab", inputs: ["name", "templateRef", "index"] }, { kind: "component", type: i4.PryIconComponent, selector: "pry-icon", inputs: ["color", "iconSvg", "animation", "iconImage", "alt", "width", "height", "classes"] }, { kind: "component", type: PryAssociationComponent, selector: "pry-association", inputs: ["associations"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.I18nPipe, name: "i18n" }] }); }
3181
3261
  }
3182
3262
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AdminFieldsSelectComponent, decorators: [{
3183
3263
  type: Component,
3184
- args: [{ selector: 'pry-admin-fields-select', template: "<div\n *ngIf=\"currentField$ | async as field\"\n [id]=\"'panel-field-' + field.id\"\n [attr.aria-labelledby]=\"'button-field-' + field.id\"\n class=\"o-panel\"\n>\n <div class=\"o-panel__header\">\n <button type=\"button\" class=\"a-btn a-btn--icon-only\" (click)=\"closePanel()\">\n <span class=\"u-visually-hidden\">{{ '@pry.action.closePanel' | i18n }}</span>\n <pry-icon iconSvg=\"close\"></pry-icon>\n </button>\n\n <h3 class=\"a-h3\">\n {{ '@pry.admin.fields.info' | i18n }}\n </h3>\n </div>\n\n <pry-tab-group translationStringBase=\"@pry.admin.\">\n <pry-tab [templateRef]=\"fieldDetails\" name=\"details\"></pry-tab>\n <pry-tab [templateRef]=\"fieldAssociations\" name=\"classes.associations\"></pry-tab>\n </pry-tab-group>\n\n <ng-template #fieldDetails>\n <h4 class=\"a-h4\">{{ '@pry.admin.properties' | i18n }}</h4>\n <p class=\"a-p\">\n {{ '@pry.admin.fields.name' | i18n }} :\n <strong>{{ field.name }}</strong>\n </p>\n <p class=\"a-p\">{{ '@pry.admin.fields.description' | i18n }} :</p>\n <p class=\"a-p\">\n {{ '@pry.admin.fields.type' | i18n }} :\n <strong>{{ getTranslationType(field.type) | i18n }}</strong>\n </p>\n </ng-template>\n\n <ng-template #fieldAssociations>\n <h4 class=\"a-h4\">{{ '@pry.admin.classes.associations' | i18n }}</h4>\n <pry-association [associations]=\"associations$ | async\"></pry-association>\n </ng-template>\n</div>\n" }]
3264
+ args: [{ selector: 'pry-admin-fields-select', template: "<div\n *ngIf=\"currentField$ | async as field\"\n [id]=\"'panel-field-' + field.id\"\n [attr.aria-labelledby]=\"'button-field-' + field.id\"\n class=\"o-panel\"\n>\n <div class=\"o-panel__header\">\n <button type=\"button\" class=\"a-btn a-btn--icon-only\" (click)=\"closePanel()\">\n <span class=\"u-visually-hidden\">{{ '@pry.action.closePanel' | i18n }}</span>\n <pry-icon iconSvg=\"close\"></pry-icon>\n </button>\n\n <h3 class=\"a-h3\">\n {{ '@pry.admin.fields.info' | i18n }}\n </h3>\n </div>\n\n <pry-tab-group translationStringBase=\"@pry.admin.\">\n <pry-tab [templateRef]=\"fieldDetails\" name=\"details\"></pry-tab>\n <pry-tab [templateRef]=\"fieldAssociations\" name=\"classes.associations\"></pry-tab>\n </pry-tab-group>\n\n <ng-template #fieldDetails>\n <div class=\"u-display-flex -column -gap-20\">\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.name' | i18n }}</h4>\n <span>{{ field.name }}</span>\n </div>\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.type' | i18n }}</h4>\n <span>{{ FIELD_I18N.label + field.type | i18n }}</span>\n </div>\n @if ([FieldType.INTEGER, FieldType.LONG, FieldType.DECIMAL, FieldType.INSTANT].includes(field.type)) {\n <div>\n <h3 class=\"a-h3 -no-padding\">{{ '@pry.admin.fields.formatOptions.title' | i18n }}</h3>\n <div class=\"u-display-flex -column -gap-20\">\n @switch (field.type) {\n @case (FieldType.INTEGER) {\n <ng-container *ngTemplateOutlet=\"numberFormatOptions\"></ng-container>\n }\n @case (FieldType.LONG) {\n <ng-container *ngTemplateOutlet=\"numberFormatOptions\"></ng-container>\n }\n @case (FieldType.DECIMAL) {\n <ng-container *ngTemplateOutlet=\"numberFormatOptions\"></ng-container>\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.formatOptions.decimalPrecision' | i18n }}</h4>\n @if (field.decimalPrecision) {\n <span>{{ field.decimalPrecision }}</span>\n } @else {\n <span class=\"-italic\">{{ '@pry.admin.fields.formatOptions.noDecimalPrecision' | i18n }}</span>\n }\n </div>\n }\n @case (FieldType.INSTANT) {\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.formatOptions.dateFormat' | i18n }}</h4>\n @if (field.format) {\n <span>{{ '@pry.admin.fields.formatOptions.dateFormatOptions' + field.format | i18n }}</span>\n } @else {\n <span class=\"-italic\">{{ '@pry.admin.fields.formatOptions.noDateFormat' | i18n }}</span>\n }\n </div>\n }\n }\n </div>\n </div>\n }\n @if (field.crs) {\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.crs' | i18n }}</h4>\n <span>{{ field.crs }}</span>\n </div>\n }\n </div>\n\n <ng-template #numberFormatOptions>\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.formatOptions.unit' | i18n }}</h4>\n @if (field.unit) {\n <span>{{ field.unit }}</span>\n } @else {\n <span class=\"-italic\">{{ '@pry.admin.fields.formatOptions.noUnit' | i18n }}</span>\n }\n </div>\n <div>\n <h4 class=\"a-h4\">{{ '@pry.admin.fields.formatOptions.isLocaleFormat' | i18n }}</h4>\n <span>{{ (field.isLocaleFormat ? '@pry.action.yes' : '@pry.action.no') | i18n }}</span>\n </div>\n </ng-template>\n </ng-template>\n\n <ng-template #fieldAssociations>\n <h4 class=\"a-h4\">{{ '@pry.admin.classes.associations' | i18n }}</h4>\n <pry-association [associations]=\"associations$ | async\"></pry-association>\n </ng-template>\n</div>\n" }]
3185
3265
  }], ctorParameters: () => [{ type: i1.Store }, { type: i2.Router }, { type: i2.ActivatedRoute }] });
3186
3266
 
3187
3267
  var MetadataRulesActionTypes;
@@ -5801,17 +5881,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImpor
5801
5881
  }], ctorParameters: () => [{ type: i1$2.Actions }, { type: AdminService }, { type: i2.Router }] });
5802
5882
 
5803
5883
  class FieldsEffects {
5804
- constructor(actions$, fieldService, pryDialog) {
5884
+ constructor(actions$, fieldService, pryDialog, store) {
5805
5885
  this.actions$ = actions$;
5806
5886
  this.fieldService = fieldService;
5807
5887
  this.pryDialog = pryDialog;
5888
+ this.store = store;
5808
5889
  this.updateToolbox$ = createEffect(() => this.actions$.pipe(ofType(FieldsActions.updateToolbox), mergeMap$1((action) => {
5809
5890
  return [FieldActions.load(), AdminActions.selectComponentType({ componentType: null })];
5810
5891
  })));
5811
- this.saveField$ = createEffect(() => this.actions$.pipe(ofType(FieldsActions.saveField), mergeMap$1((action) => this.fieldService.saveField(action.field).pipe(map$1(() => FieldsActions.saveFieldSuccess({ route: action.route })), catchError$1((error) => [FieldsActions.saveFieldFailure({ error: error })])))));
5892
+ this.saveField$ = createEffect(() => this.actions$.pipe(ofType(FieldsActions.saveField), mergeMap$1((action) => this.fieldService.saveField(action.field).pipe(map$1(() => FieldsActions.saveFieldSuccess({ route: action.route })), catchError$1((error) => [FieldsActions.failure({ error: error })])))));
5812
5893
  this.saveFieldSuccess$ = createEffect(() => this.actions$.pipe(ofType(FieldsActions.saveFieldSuccess), map$1((action) => {
5813
5894
  return AdminActions.routeTo({ path: action.route });
5814
5895
  })));
5896
+ this.updateField$ = createEffect(() => this.actions$.pipe(ofType(FieldsActions.updateField), mergeMap$1((action) => this.fieldService.updateField(action.field).pipe(map$1(() => FieldsActions.updateFieldSuccess({ route: action.route })), catchError$1((error) => [FieldsActions.failure({ error: error })])))));
5897
+ this.updateFieldSuccess$ = createEffect(() => this.actions$.pipe(ofType(FieldsActions.updateFieldSuccess), map$1((action) => {
5898
+ return AdminActions.routeTo({ path: action.route });
5899
+ })));
5815
5900
  this.confirmFieldDeletion$ = createEffect(() => this.actions$.pipe(ofType(FieldsActions.confirmFieldDeletion), tap((action) => {
5816
5901
  const data = {
5817
5902
  title: '@pry.admin.fields.confirmFieldDeletion',
@@ -5830,7 +5915,7 @@ class FieldsEffects {
5830
5915
  };
5831
5916
  this.pryDialog.open(PryDialogConfirmComponent, { data });
5832
5917
  })), { dispatch: false });
5833
- this.deleteField$ = createEffect(() => this.actions$.pipe(ofType(FieldsActions.deleteField), mergeMap$1((action) => this.fieldService.deleteField(action.id).pipe(map$1(() => FieldsActions.deleteFieldSuccess()), catchError$1((error) => [FieldsActions.deleteFieldFailure({ error: error })])))));
5918
+ this.deleteField$ = createEffect(() => this.actions$.pipe(ofType(FieldsActions.deleteField), mergeMap$1((action) => this.fieldService.deleteField(action.id).pipe(map$1(() => FieldsActions.deleteFieldSuccess()), catchError$1((error) => [FieldsActions.failure({ error: error })])))));
5834
5919
  this.deleteFieldSuccess$ = createEffect(() => this.actions$.pipe(ofType(FieldsActions.deleteFieldSuccess), map$1((action) => {
5835
5920
  return FieldActions.load();
5836
5921
  })));
@@ -5838,12 +5923,12 @@ class FieldsEffects {
5838
5923
  return AdminActions.togglePanel({ panelOpen: false });
5839
5924
  })));
5840
5925
  }
5841
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: FieldsEffects, deps: [{ token: i1$2.Actions }, { token: i4.FieldService }, { token: i4.PryDialogService }], target: i0.ɵɵFactoryTarget.Injectable }); }
5926
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: FieldsEffects, deps: [{ token: i1$2.Actions }, { token: i4.FieldService }, { token: i4.PryDialogService }, { token: i1.Store }], target: i0.ɵɵFactoryTarget.Injectable }); }
5842
5927
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: FieldsEffects }); }
5843
5928
  }
5844
5929
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: FieldsEffects, decorators: [{
5845
5930
  type: Injectable
5846
- }], ctorParameters: () => [{ type: i1$2.Actions }, { type: i4.FieldService }, { type: i4.PryDialogService }] });
5931
+ }], ctorParameters: () => [{ type: i1$2.Actions }, { type: i4.FieldService }, { type: i4.PryDialogService }, { type: i1.Store }] });
5847
5932
 
5848
5933
  class LinksEffects {
5849
5934
  constructor(actions$, service, router) {
@@ -6251,38 +6336,57 @@ const enTranslations = {
6251
6336
  className: 'Class',
6252
6337
  confirmFieldDeletion: 'Confirm deleting the selected field',
6253
6338
  fieldType: {
6254
- int: 'Integer',
6339
+ integer: 'Integer',
6255
6340
  long: 'Long number',
6256
6341
  decimal: 'Double number',
6257
6342
  string: 'Text',
6258
6343
  keyword: 'Keyword',
6259
6344
  instant: 'date',
6260
6345
  raw: 'Raw',
6261
- point: 'Point',
6262
- multipoint: 'Multi-points',
6263
- line: 'Line',
6264
- multiline: 'Multi-lines',
6265
- polygon: 'Polygon',
6266
- multipolygon: 'Multi-polygons',
6346
+ Point: 'Point',
6347
+ MultiPoint: 'Multi-points',
6348
+ LineString: 'Line',
6349
+ MultiLineString: 'Multi-lines',
6350
+ Polygon: 'Polygon',
6351
+ MultiPolygon: 'Multi-polygons',
6267
6352
  information: {
6268
- int: 'Allows you to store integer numeric data less than 2^32',
6353
+ integer: 'Allows you to store integer numeric data less than 2^32',
6269
6354
  long: 'Allows you to store integer numeric data that can exceed 2^32',
6270
6355
  decimal: 'Allows you to store numeric data with decimal places',
6271
6356
  string: 'Allows you to store data in alphanumeric format. This data is not indexed: it is possible to search on it but no aggregation',
6272
6357
  keyword: 'Allows you to store data in alphanumeric format. This data is indexed: it is possible to search on it as well as aggregations.',
6273
6358
  instant: 'Allows you to store a date',
6274
6359
  raw: 'allows you to store image or file type data',
6275
- point: 'Allows you to store geographic coordinates of an object represented by a point (geo-json format)',
6276
- multipoint: 'Allows you to store geographic coordinates of an object composed of several unconnected points (geo-json format)',
6277
- line: 'Allows you to store geographic coordinates of an object represented as a line (geo-json format)',
6278
- multiline: 'Allows you to store geographic coordinates of an object represented with several unconnected lines (longitude and latitude geo-json format)',
6279
- polygon: 'Allows you to store geographic coordinates of an object represented by a polygon (geo-json format)',
6280
- multipolygon: 'Allows you to store geographic coordinates of an object represented by several polygons nested or not (geo-json format)'
6360
+ Point: 'Allows you to store geographic coordinates of an object represented by a point (geo-json format)',
6361
+ MultiPoint: 'Allows you to store geographic coordinates of an object composed of several unconnected points (geo-json format)',
6362
+ LineString: 'Allows you to store geographic coordinates of an object represented as a line (geo-json format)',
6363
+ MultiLineString: 'Allows you to store geographic coordinates of an object represented with several unconnected lines (longitude and latitude geo-json format)',
6364
+ Polygon: 'Allows you to store geographic coordinates of an object represented by a polygon (geo-json format)',
6365
+ MultiPolygon: 'Allows you to store geographic coordinates of an object represented by several polygons nested or not (geo-json format)'
6281
6366
  }
6282
6367
  },
6283
6368
  rawMethods: {
6284
6369
  http: 'From external url',
6285
6370
  upload: 'Upload from my computer'
6371
+ },
6372
+ formatOptions: {
6373
+ title: 'Formatting options',
6374
+ decimalPrecision: 'Decimal precision',
6375
+ noDecimalPrecision: 'No decimal precision provided',
6376
+ isLocaleFormat: 'Localized format',
6377
+ unit: 'Unit',
6378
+ noUnit: 'No unit provided',
6379
+ dateFormat: 'Date format',
6380
+ noDateFormat: 'No date format provided',
6381
+ dateFormatOptions: {
6382
+ DATETIME: 'Date and time',
6383
+ DATE: 'Date',
6384
+ MONTH_YEAR: 'Month and year',
6385
+ DAY_MONTH: 'Day and month',
6386
+ YEAR: 'Year',
6387
+ MONTH: 'Month',
6388
+ DAY: 'Day'
6389
+ }
6286
6390
  }
6287
6391
  },
6288
6392
  userInfo: {
@@ -6648,38 +6752,57 @@ const frTranslations = {
6648
6752
  className: 'Classe',
6649
6753
  confirmFieldDeletion: 'Confirmez-vous la suppression de ce type métier ?',
6650
6754
  fieldType: {
6651
- int: 'Nombre entier',
6755
+ integer: 'Nombre entier',
6652
6756
  long: 'Nombre entier long',
6653
6757
  decimal: 'Nombre décimal',
6654
6758
  string: 'Texte brut',
6655
6759
  keyword: 'Texte indexé',
6656
6760
  instant: 'Date',
6657
6761
  raw: 'Donnée non structurée',
6658
- point: 'Point',
6659
- multipoint: 'Multi-points',
6660
- line: 'Ligne',
6661
- multiline: 'Multi-lignes',
6662
- polygon: 'Polygone',
6663
- multipolygon: 'Multi-polygones',
6762
+ Point: 'Point',
6763
+ MultiPoint: 'Multi-points',
6764
+ LineString: 'Ligne',
6765
+ MultiLineString: 'Multi-lignes',
6766
+ Polygon: 'Polygone',
6767
+ MultiPolygon: 'Multi-polygones',
6664
6768
  information: {
6665
- int: 'Permet de stocker des données numériques entières inférieures à 2^32',
6769
+ integer: 'Permet de stocker des données numériques entières inférieures à 2^32',
6666
6770
  long: 'Permet de stocker des données numériques entières pouvant dépasser 2^32',
6667
6771
  decimal: 'Permet de stocker des données numériques avec des décimales',
6668
6772
  string: "Permet de stocker des données au format alphanumérique. Ces données ne sont pas indexées : il est possible de faire une recherche dessus mais pas d'agrégation",
6669
6773
  keyword: 'Permet de stocker des données au format alphanumérique. Ces données sont indexées : il est possible de faire une recherche dessus ainsi que des agrégations.',
6670
6774
  instant: 'Permet de stocker une date',
6671
6775
  raw: 'permet de stocker des données de type image ou fichier',
6672
- point: "Permet de stocker des coordonnées géographiques d'un objet représenté par un point (format géojson)",
6673
- multipoint: "Permet de stocker des coordonnées géographiques d'un objet composé de plusieurs points non reliés (format géojson)",
6674
- line: "Permet de stocker des coordonnées géographiques d'un objet représenté comme une ligne (format géojson)",
6675
- multiline: "Permet de stocker des coordonnées géographiques d'un objet représenté avec plusieurs lignes non reliées entre elles (longitude et latitude format géojson)",
6676
- polygon: "Permet de stocker des coordonnées géographiques d'un objet représenté par un polygone (format géojson)",
6677
- multipolygon: "Permet de stocker des coordonnées géographiques d'un objet représenté par plusieurs polygones imbriqués ou non (format géojson)"
6776
+ Point: "Permet de stocker des coordonnées géographiques d'un objet représenté par un point (format géojson)",
6777
+ MultiPoint: "Permet de stocker des coordonnées géographiques d'un objet composé de plusieurs points non reliés (format géojson)",
6778
+ LineString: "Permet de stocker des coordonnées géographiques d'un objet représenté comme une ligne (format géojson)",
6779
+ MultiLineString: "Permet de stocker des coordonnées géographiques d'un objet représenté avec plusieurs lignes non reliées entre elles (longitude et latitude format géojson)",
6780
+ Polygon: "Permet de stocker des coordonnées géographiques d'un objet représenté par un polygone (format géojson)",
6781
+ MultiPolygon: "Permet de stocker des coordonnées géographiques d'un objet représenté par plusieurs polygones imbriqués ou non (format géojson)"
6678
6782
  }
6679
6783
  },
6680
6784
  rawMethods: {
6681
6785
  http: 'Depuis une url',
6682
6786
  upload: 'Téléverser depuis mon ordinateur'
6787
+ },
6788
+ formatOptions: {
6789
+ title: 'Options de formatage',
6790
+ decimalPrecision: 'Nombre de décimales souhaité',
6791
+ noDecimalPrecision: 'Pas de précision spécifiée',
6792
+ isLocaleFormat: 'Formatage comme nombre',
6793
+ unit: 'Unité',
6794
+ noUnit: "Pas d'unité spécifiée",
6795
+ dateFormat: 'Format de date',
6796
+ noDateFormat: 'Pas de format de date specifié',
6797
+ dateFormatOptions: {
6798
+ DATETIME: 'Date et heure',
6799
+ DATE: 'Date',
6800
+ MONTH_YEAR: 'Mois et année',
6801
+ DAY_MONTH: 'Jour et mois',
6802
+ YEAR: 'Année',
6803
+ MONTH: 'Mois',
6804
+ DAY: 'Jour'
6805
+ }
6683
6806
  }
6684
6807
  },
6685
6808
  userInfo: {