@netgrif/components-core 6.2.1 → 6.2.3

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 (38) hide show
  1. package/commons/schema.d.ts +1 -0
  2. package/esm2020/assets/i18n/de.json +11 -9
  3. package/esm2020/assets/i18n/en.json +4 -2
  4. package/esm2020/assets/i18n/sk.json +4 -2
  5. package/esm2020/commons/schema.mjs +1 -1
  6. package/esm2020/lib/authentication/components/abstract-authentication-overlay.mjs +4 -1
  7. package/esm2020/lib/authorization/permission/access.service.mjs +2 -2
  8. package/esm2020/lib/authorization/role/role-guard.service.mjs +36 -11
  9. package/esm2020/lib/data-fields/file-field/abstract-file-field.component.mjs +7 -3
  10. package/esm2020/lib/data-fields/file-list-field/abstract-file-list-field.component.mjs +5 -2
  11. package/esm2020/lib/data-fields/i18n-field/i18n-divider-field/abstract-i18n-divider-field.component.mjs +7 -1
  12. package/esm2020/lib/data-fields/i18n-field/models/i18n-field.mjs +5 -5
  13. package/esm2020/lib/data-fields/models/abstract-data-field.mjs +1 -1
  14. package/esm2020/lib/data-fields/multichoice-field/multichoice-autocomplete-field/abstract-multichoice-autocomplete-field-component.component.mjs +5 -2
  15. package/esm2020/lib/data-fields/number-field/currency-number-field/abstract-currency-number-field.component.mjs +3 -2
  16. package/esm2020/lib/navigation/navigation-double-drawer/abstract-navigation-double-drawer.mjs +7 -4
  17. package/esm2020/lib/resources/engine-endpoint/task-resource.service.mjs +3 -3
  18. package/esm2020/lib/search/models/category/case/case-dataset.mjs +7 -4
  19. package/esm2020/lib/search/search-operand-input-component/abstract-search-operand-input.component.mjs +3 -3
  20. package/esm2020/lib/side-menu/content-components/new-case/abstract-new-case.component.mjs +34 -12
  21. package/esm2020/lib/task-content/field-component-resolver/abstract-field-component-resolver.component.mjs +2 -3
  22. package/fesm2015/netgrif-components-core.mjs +132 -56
  23. package/fesm2015/netgrif-components-core.mjs.map +1 -1
  24. package/fesm2020/netgrif-components-core.mjs +131 -56
  25. package/fesm2020/netgrif-components-core.mjs.map +1 -1
  26. package/lib/authorization/role/role-guard.service.d.ts +2 -1
  27. package/lib/data-fields/i18n-field/i18n-divider-field/abstract-i18n-divider-field.component.d.ts +1 -0
  28. package/lib/data-fields/models/abstract-data-field.d.ts +1 -1
  29. package/lib/data-fields/multichoice-field/multichoice-autocomplete-field/abstract-multichoice-autocomplete-field-component.component.d.ts +1 -0
  30. package/lib/data-fields/number-field/currency-number-field/abstract-currency-number-field.component.d.ts +1 -0
  31. package/lib/navigation/navigation-double-drawer/abstract-navigation-double-drawer.d.ts +1 -1
  32. package/lib/resources/engine-endpoint/task-resource.service.d.ts +2 -1
  33. package/lib/search/search-operand-input-component/abstract-search-operand-input.component.d.ts +1 -1
  34. package/lib/side-menu/content-components/new-case/abstract-new-case.component.d.ts +2 -0
  35. package/package.json +1 -1
  36. package/src/assets/i18n/de.json +11 -9
  37. package/src/assets/i18n/en.json +5 -2
  38. package/src/assets/i18n/sk.json +4 -2
@@ -1081,7 +1081,8 @@ var admin$2 = {
1081
1081
  },
1082
1082
  "ldapGroup-list": {
1083
1083
  noLdapGroupsWereFound: "No LDAP group was found",
1084
- listTitle: "Ldap Groups"
1084
+ listTitle: "LDAP groups",
1085
+ count: "Number of groups"
1085
1086
  },
1086
1087
  "process-list": {
1087
1088
  newestVersion: "Newest version",
@@ -1187,7 +1188,8 @@ var en = {
1187
1188
  errThird: "Color is required.",
1188
1189
  noNets: "No allowed Nets",
1189
1190
  createCase: "Successful create new case",
1190
- defaultCaseName: "with default case name"
1191
+ defaultCaseName: "with default case name",
1192
+ createCaseError: "A new case was created, but an error occurred while executing actions"
1191
1193
  },
1192
1194
  user: {
1193
1195
  assign: "User Assign",
@@ -1559,7 +1561,8 @@ var admin$1 = {
1559
1561
  },
1560
1562
  "ldapGroup-list": {
1561
1563
  noLdapGroupsWereFound: "Žiadna LDAP skupina nebola najdená",
1562
- listTitle: "Ldap Skupiny"
1564
+ listTitle: "LDAP Skupiny",
1565
+ count: "Počet skupín"
1563
1566
  },
1564
1567
  "process-list": {
1565
1568
  newestVersion: "Najnovšia verzia",
@@ -1665,7 +1668,8 @@ var sk = {
1665
1668
  errThird: "Farba je povinné pole.",
1666
1669
  noNets: "Žiadne povolené siete",
1667
1670
  createCase: "Úspešne vytvorený nový prípad",
1668
- defaultCaseName: "s prednastaveným názvom prípadu"
1671
+ defaultCaseName: "s prednastaveným názvom prípadu",
1672
+ createCaseError: "Nový prípad vytvorený, nastala však chyba pri vykonávaní akcií"
1669
1673
  },
1670
1674
  user: {
1671
1675
  assign: "Priradiť používateľa",
@@ -1943,8 +1947,8 @@ var forms = {
1943
1947
  enterEmail: "Ihre E-Mail Adresse eingeben"
1944
1948
  },
1945
1949
  login: {
1946
- length: "Das Benützername muss mindestens 4 Zeichen enthalten",
1947
- login: "Benützername",
1950
+ length: "Das Benutzername muss mindestens 4 Zeichen enthalten",
1951
+ login: "Benutzername",
1948
1952
  wrongCredentials: "Falsche Anmeldeinformationen!",
1949
1953
  loginButton: "Anmelden",
1950
1954
  reset: "Kennwort wiederherstellen",
@@ -2037,7 +2041,8 @@ var admin = {
2037
2041
  },
2038
2042
  "ldapGroup-list": {
2039
2043
  noLdapGroupsWereFound: "Keine LDAP Gruppe wurde gefunden",
2040
- listTitle: "LDAP Gruppen"
2044
+ listTitle: "LDAP Gruppen",
2045
+ count: "Anzahl der Gruppen"
2041
2046
  },
2042
2047
  "process-list": {
2043
2048
  newestVersion: "Neuste Version",
@@ -2143,14 +2148,15 @@ var de = {
2143
2148
  errThird: "Sie müssen eine Farbe auswählen.",
2144
2149
  noNets: "Es gibt keine erlaubte Netze",
2145
2150
  createCase: "Neuen Fall würde erfolgreich erzeugt",
2146
- defaultCaseName: "mit einem Standardfallnamen"
2151
+ defaultCaseName: "mit einem Standardfallnamen",
2152
+ createCaseError: "Neuer Fall wurde erstellt, aber beim Ausführen von Aktionen ist ein Fehler aufgetreten"
2147
2153
  },
2148
2154
  user: {
2149
- assign: "Benützer zuweisen",
2150
- choose: "Benützer auswählen",
2151
- noUser: "Es gibt keine Benützer",
2152
- err: "Beim laden der Benützer ist eine Fehler aufgetreten",
2153
- showcase: "Benützeransichtmodus ist nicht ausgewählt!"
2155
+ assign: "Benutzer zuweisen",
2156
+ choose: "Benutzer auswählen",
2157
+ noUser: "Es gibt keine Benutzer",
2158
+ err: "Beim laden der Benutzer ist eine Fehler aufgetreten",
2159
+ showcase: "Die Benutzeransicht ist nicht gesetzt!"
2154
2160
  },
2155
2161
  ldapGroup: {
2156
2162
  choose: "LDAP-Gruppe suchen",
@@ -5590,8 +5596,8 @@ class I18nField extends DataField {
5590
5596
  && ((!a.translations && !!b.translations) || (!b.translations && !!a.translations)));
5591
5597
  }
5592
5598
  static translationsEquality(a, b) {
5593
- const aKeys = Object.keys(a.translations).sort();
5594
- const bKeys = Object.keys(b.translations).sort();
5599
+ const aKeys = !!a.translations ? Object.keys(a.translations).sort() : [];
5600
+ const bKeys = !!b.translations ? Object.keys(b.translations).sort() : [];
5595
5601
  if (aKeys.length !== bKeys.length
5596
5602
  || !aKeys.every((element, index) => {
5597
5603
  return element === bKeys[index];
@@ -5707,13 +5713,13 @@ class I18nField extends DataField {
5707
5713
  validTranslationRequired(countries) {
5708
5714
  return (fc) => {
5709
5715
  return countries.every(languageCode => languageCode in fc.value.translations)
5710
- ? (null) : ({ translationRequired: true });
5716
+ ? null : ({ translationRequired: true });
5711
5717
  };
5712
5718
  }
5713
5719
  validTranslationOnly(countries) {
5714
5720
  return (fc) => {
5715
5721
  return Object.keys(fc.value.translations).every(translation => countries.includes(translation))
5716
- ? (null) : ({ translationOnly: true });
5722
+ ? null : ({ translationOnly: true });
5717
5723
  };
5718
5724
  }
5719
5725
  validRequiredI18n(fc) {
@@ -6284,9 +6290,9 @@ class TaskResourceService extends AbstractResourceService {
6284
6290
  * Delete file from the task
6285
6291
  * DELETE
6286
6292
  */
6287
- deleteFile(taskId, fieldId, name) {
6293
+ deleteFile(taskId, fieldId, name, param) {
6288
6294
  const url = !!name ? 'task/' + taskId + '/file/' + fieldId + '/' + name : 'task/' + taskId + '/file/' + fieldId;
6289
- return this._resourceProvider.delete$(url, this.SERVER_URL).pipe(map(r => this.changeType(r, undefined)));
6295
+ return this._resourceProvider.delete$(url, this.SERVER_URL, param).pipe(map(r => this.changeType(r, undefined)));
6290
6296
  }
6291
6297
  /**
6292
6298
  * Download task file preview for field value
@@ -6440,6 +6446,7 @@ class AbstractFileFieldComponent extends AbstractDataFieldComponent {
6440
6446
  }
6441
6447
  }
6442
6448
  this.updatedFieldSubscription = this.dataField.updated.subscribe(() => {
6449
+ this.previewSource = undefined;
6443
6450
  if (!!this.filePreview
6444
6451
  && !!this.dataField.value
6445
6452
  && !!this.dataField.value.name) {
@@ -6613,7 +6620,9 @@ class AbstractFileFieldComponent extends AbstractDataFieldComponent {
6613
6620
  this._log.error('File cannot be deleted. No task is set to the field.');
6614
6621
  return;
6615
6622
  }
6616
- this._taskResourceService.deleteFile(this.taskId, this.dataField.stringId).pipe(take(1)).subscribe(response => {
6623
+ let param = new HttpParams();
6624
+ param = param.set("parentTaskId", this.resolveParentTaskId());
6625
+ this._taskResourceService.deleteFile(this.taskId, this.dataField.stringId, undefined, param).pipe(take(1)).subscribe(response => {
6617
6626
  if (response.success) {
6618
6627
  const filename = this.dataField.value.name;
6619
6628
  this.dataField.value = {};
@@ -6697,7 +6706,7 @@ class AbstractFileFieldComponent extends AbstractDataFieldComponent {
6697
6706
  if (!this.checkFileBeforeDownload()) {
6698
6707
  return;
6699
6708
  }
6700
- this._taskResourceService.downloadFile(this.taskId, this.dataField.stringId).subscribe(response => {
6709
+ this._taskResourceService.downloadFile(this.resolveParentTaskId(), this.dataField.stringId).subscribe(response => {
6701
6710
  if (!response.type || response.type !== ProgressType.DOWNLOAD) {
6702
6711
  this._log.debug(`File [${this.dataField.stringId}] ${this.dataField.value.name} was successfully downloaded`);
6703
6712
  this.initDownloadFile(response);
@@ -7004,7 +7013,9 @@ class AbstractFileListFieldComponent extends AbstractDataFieldComponent {
7004
7013
  this._log.error('File cannot be deleted. No task is set to the field.');
7005
7014
  return;
7006
7015
  }
7007
- this._taskResourceService.deleteFile(this.taskId, this.dataField.stringId, fileName).pipe(take(1)).subscribe((response) => {
7016
+ let param = new HttpParams();
7017
+ param = param.set("parentTaskId", this.resolveParentTaskId());
7018
+ this._taskResourceService.deleteFile(this.taskId, this.dataField.stringId, fileName, param).pipe(take(1)).subscribe((response) => {
7008
7019
  if (response.success) {
7009
7020
  const changedFieldsMap = this._eventService.parseChangedFieldsFromOutcomeTree(response.outcome);
7010
7021
  this.dataField.emitChangedFields(changedFieldsMap);
@@ -7127,7 +7138,7 @@ class AbstractMultichoiceAutocompleteFieldComponentComponent {
7127
7138
  this.filteredOptions = undefined;
7128
7139
  }
7129
7140
  add(event) {
7130
- const value = (event.value || '').trim();
7141
+ const value = (event['key'] || '').trim();
7131
7142
  if (value) {
7132
7143
  const choiceArray = [...this.multichoiceField.value];
7133
7144
  choiceArray.push(value);
@@ -7162,6 +7173,9 @@ class AbstractMultichoiceAutocompleteFieldComponentComponent {
7162
7173
  return this.multichoiceField.choices.filter(option => option.value.toLowerCase().normalize('NFD')
7163
7174
  .replace(/[\u0300-\u036f]/g, '').indexOf(filterValue) === 0);
7164
7175
  }
7176
+ getValueFromKey(key) {
7177
+ return this.multichoiceField.choices.find(choice => choice.key === key)?.value;
7178
+ }
7165
7179
  }
7166
7180
  AbstractMultichoiceAutocompleteFieldComponentComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: AbstractMultichoiceAutocompleteFieldComponentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7167
7181
  AbstractMultichoiceAutocompleteFieldComponentComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: AbstractMultichoiceAutocompleteFieldComponentComponent, selector: "ncc-abstract-multichoice-autocomplete-field", inputs: { multichoiceField: "multichoiceField", formControlRef: "formControlRef", showLargeLayout: "showLargeLayout" }, viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true }], ngImport: i0, template: '', isInline: true });
@@ -7300,6 +7314,7 @@ class AbstractCurrencyNumberFieldComponent extends AbstractNumberErrorsComponent
7300
7314
  this._currencyPipe = _currencyPipe;
7301
7315
  this.NUMBER_TYPE = 'number';
7302
7316
  this.TEXT_TYPE = 'text';
7317
+ this.WHITESPACE = ' ';
7303
7318
  }
7304
7319
  ngAfterViewInit() {
7305
7320
  this.fieldType = this.TEXT_TYPE;
@@ -7307,7 +7322,7 @@ class AbstractCurrencyNumberFieldComponent extends AbstractNumberErrorsComponent
7307
7322
  this.numberField.valueChanges().subscribe(value => {
7308
7323
  if (value !== undefined) {
7309
7324
  if (this.fieldType === this.TEXT_TYPE) {
7310
- this.transformedValue = this.transformCurrency(value.toString());
7325
+ this.transformedValue = this.transformCurrency(value.toString()) + this.WHITESPACE;
7311
7326
  }
7312
7327
  }
7313
7328
  else {
@@ -11084,14 +11099,17 @@ class CaseDataset extends Category {
11084
11099
  return resolver.getIndex(datafield.fieldId, SearchIndex.BOOLEAN);
11085
11100
  case 'file':
11086
11101
  case 'fileList':
11087
- return resolver.getIndex(datafield.fieldId, SearchIndex.FILE_NAME, this.isSelectedOperator(Equals) || this.isSelectedOperator(NotEquals) || this.isSelectedOperator(Substring));
11102
+ return resolver.getIndex(datafield.fieldId, SearchIndex.FILE_NAME, this.isSelectedOperator(Equals) || this.isSelectedOperator(NotEquals) || this.isSelectedOperator(Substring)
11103
+ || this.isSelectedOperator(IsNull));
11088
11104
  case 'user':
11089
11105
  case 'userList':
11090
11106
  return resolver.getIndex(datafield.fieldId, SearchIndex.USER_ID);
11091
11107
  case 'i18n':
11092
- return resolver.getIndex(datafield.fieldId, SearchIndex.TEXT, this.isSelectedOperator(Equals) || this.isSelectedOperator(NotEquals) || this.isSelectedOperator(Substring));
11108
+ return resolver.getIndex(datafield.fieldId, SearchIndex.TEXT, this.isSelectedOperator(Equals) || this.isSelectedOperator(NotEquals) || this.isSelectedOperator(Substring)
11109
+ || this.isSelectedOperator(IsNull));
11093
11110
  default:
11094
- return resolver.getIndex(datafield.fieldId, SearchIndex.FULLTEXT, this.isSelectedOperator(Equals) || this.isSelectedOperator(NotEquals) || this.isSelectedOperator(Substring));
11111
+ return resolver.getIndex(datafield.fieldId, SearchIndex.FULLTEXT, this.isSelectedOperator(Equals) || this.isSelectedOperator(NotEquals) || this.isSelectedOperator(Substring)
11112
+ || this.isSelectedOperator(IsNull));
11095
11113
  }
11096
11114
  }
11097
11115
  get inputPlaceholder() {
@@ -13372,6 +13390,12 @@ class AbstractI18nDividerFieldComponent {
13372
13390
  return this.dividerI18nField.component.properties.dividerColor;
13373
13391
  }
13374
13392
  }
13393
+ isDividerLGBTQ() {
13394
+ if (this.dividerPropertyEnabled('dividerLGBTQ')) {
13395
+ return this.dividerI18nField.component.properties.dividerLGBTQ === 'true';
13396
+ }
13397
+ return false;
13398
+ }
13375
13399
  getDividerFontSize() {
13376
13400
  if (this.dividerPropertyEnabled('fontSize')) {
13377
13401
  return this.dividerI18nField.component.properties.fontSize + 'px';
@@ -13942,6 +13966,9 @@ class AbstractAuthenticationOverlayComponent {
13942
13966
  if (!!user && !!user.id && user.id.length > 0) {
13943
13967
  this.redirect(!active);
13944
13968
  }
13969
+ else if (!active) {
13970
+ this._spinnerOverlay.spin$.next(false);
13971
+ }
13945
13972
  });
13946
13973
  });
13947
13974
  }
@@ -19984,6 +20011,7 @@ class AbstractNewCaseComponent {
19984
20011
  this._hasMultipleNets$ = new ReplaySubject(1);
19985
20012
  this._notInitialized$ = new BehaviorSubject(true);
19986
20013
  this._options$ = new ReplaySubject(1);
20014
+ this.loadingSubmit = new LoadingEmitter(false);
19987
20015
  this._allowedNetsSubscription = this._injectedData.allowedNets$.pipe(map(nets => nets.map(petriNet => ({
19988
20016
  value: petriNet.stringId,
19989
20017
  viewValue: petriNet.title,
@@ -20020,6 +20048,7 @@ class AbstractNewCaseComponent {
20020
20048
  }
20021
20049
  ngOnDestroy() {
20022
20050
  this._hasMultipleNets$.complete();
20051
+ this.loadingSubmit.complete();
20023
20052
  this._allowedNetsSubscription.unsubscribe();
20024
20053
  }
20025
20054
  get hasMultipleNets$() {
@@ -20039,25 +20068,44 @@ class AbstractNewCaseComponent {
20039
20068
  return process && process.viewValue ? process.viewValue : '';
20040
20069
  }
20041
20070
  createNewCase() {
20071
+ if (this.loadingSubmit.value) {
20072
+ return;
20073
+ }
20042
20074
  if (this.titleFormControl.valid || !this.isCaseTitleRequired()) {
20043
20075
  const newCase = {
20044
20076
  title: this.titleFormControl.value === '' ? null : this.titleFormControl.value,
20045
20077
  color: 'panel-primary-icon',
20046
20078
  netId: this.options.length === 1 ? this.options[0].value : this.processFormControl.value.value
20047
20079
  };
20080
+ this.loadingSubmit.on();
20048
20081
  this._caseResourceService.createCase(newCase)
20049
20082
  .subscribe((response) => {
20050
- this._snackBarService.openSuccessSnackBar(response.outcome.message === undefined
20051
- ? this._translate.instant('side-menu.new-case.createCase') + ' ' + newCase.title
20052
- : response.outcome.message);
20053
- this._sideMenuControl.close({
20054
- opened: false,
20055
- message: response.outcome.message === undefined
20056
- ? 'Confirm new case setup'
20057
- : response.outcome.message,
20058
- data: response.outcome.aCase
20059
- });
20060
- }, error => this._snackBarService.openErrorSnackBar(error.message ? error.message : error));
20083
+ this.loadingSubmit.off();
20084
+ if (!!response.outcome) {
20085
+ this._snackBarService.openSuccessSnackBar(response.outcome.message === undefined
20086
+ ? this._translate.instant('side-menu.new-case.createCase') + ' ' + newCase.title
20087
+ : response.outcome.message);
20088
+ this._sideMenuControl.close({
20089
+ opened: false,
20090
+ message: response.outcome.message === undefined
20091
+ ? 'Confirm new case setup'
20092
+ : response.outcome.message,
20093
+ data: response.outcome.aCase
20094
+ });
20095
+ }
20096
+ else if (!!response.error) {
20097
+ this._snackBarService.openWarningSnackBar(this._translate.instant('side-menu.new-case.createCaseError') + ' ' + newCase.title);
20098
+ this._sideMenuControl.close({
20099
+ opened: false,
20100
+ message: response.error === undefined
20101
+ ? 'Confirm new case setup'
20102
+ : response.error
20103
+ });
20104
+ }
20105
+ }, error => {
20106
+ this.loadingSubmit.off();
20107
+ this._snackBarService.openErrorSnackBar(error.message ? error.message : error);
20108
+ });
20061
20109
  }
20062
20110
  }
20063
20111
  /**
@@ -23410,16 +23458,35 @@ class RoleGuardService {
23410
23458
  return this.canAccessView(view, state.url.toString());
23411
23459
  }
23412
23460
  canAccessView(view, url) {
23413
- if (typeof view.access !== 'string' && view.access.hasOwnProperty('role')) {
23414
- const allowedRoles = this.parseRoleConstraints(view.access.role, url);
23415
- return allowedRoles.some(constraint => {
23416
- if (constraint.roleIdentifier) {
23417
- return this._userService.hasRoleByIdentifier(constraint.roleIdentifier, constraint.processIdentifier);
23461
+ if (typeof view.access !== 'string' && (view.access.hasOwnProperty('role') || view.access.hasOwnProperty('bannedRole'))) {
23462
+ if (view.access.hasOwnProperty('role') && view.access.hasOwnProperty('bannedRole')) {
23463
+ const bannedRoles = this.parseRoleConstraints(view.access.bannedRole, url);
23464
+ const allowedRoles = this.parseRoleConstraints(view.access.role, url);
23465
+ if (bannedRoles.some(role => this.decideAccessByRole(role))) {
23466
+ return false;
23418
23467
  }
23419
- else {
23420
- return this._userService.hasRoleByName(constraint.roleName, constraint.processIdentifier);
23468
+ if (allowedRoles.length === 0) {
23469
+ this._log.warn(`View at '${url}' defines role access constraint with an empty array!`
23470
+ + ` No users will be allowed to enter this view!`);
23421
23471
  }
23422
- });
23472
+ return allowedRoles.some(role => this.decideAccessByRole(role)); // user was not denied access by a banned role, they need at least one allowed role
23473
+ }
23474
+ if (view.access.hasOwnProperty('bannedRole')) {
23475
+ const bannedRoles = this.parseRoleConstraints(view.access.bannedRole, url);
23476
+ return !bannedRoles.some(constraint => {
23477
+ return this.decideAccessByRole(constraint);
23478
+ });
23479
+ }
23480
+ if (view.access.hasOwnProperty('role')) {
23481
+ const allowedRoles = this.parseRoleConstraints(view.access.role, url);
23482
+ if (allowedRoles.length === 0) {
23483
+ this._log.warn(`View at '${url}' defines role access constraint with an empty array!`
23484
+ + ` No users will be allowed to enter this view!`);
23485
+ }
23486
+ return allowedRoles.some(constraint => {
23487
+ return this.decideAccessByRole(constraint);
23488
+ });
23489
+ }
23423
23490
  }
23424
23491
  throw new Error('Role guard is declared for a view with no role guard configuration!'
23425
23492
  + ` Add role guard configuration for view at ${url}, or remove the guard.`);
@@ -23430,8 +23497,6 @@ class RoleGuardService {
23430
23497
  }
23431
23498
  if (Array.isArray(roleConstrains)) {
23432
23499
  if (roleConstrains.length === 0) {
23433
- this._log.warn(`View at '${viewUrl}' defines role access constraint with an empty array!`
23434
- + ` No users will be allowed to enter this view!`);
23435
23500
  return [];
23436
23501
  }
23437
23502
  if (typeof roleConstrains[0] === 'string') {
@@ -23469,6 +23534,14 @@ class RoleGuardService {
23469
23534
  return { processIdentifier: constraint.processId, roleIdentifier: constraint.roleId };
23470
23535
  });
23471
23536
  }
23537
+ decideAccessByRole(constraint) {
23538
+ if (constraint.roleIdentifier) {
23539
+ return this._userService.hasRoleByIdentifier(constraint.roleIdentifier, constraint.processIdentifier);
23540
+ }
23541
+ else {
23542
+ return this._userService.hasRoleByName(constraint.roleName, constraint.processIdentifier);
23543
+ }
23544
+ }
23472
23545
  }
23473
23546
  RoleGuardService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RoleGuardService, deps: [{ token: RedirectService }, { token: UserService }, { token: ConfigurationService }, { token: LoggerService }], target: i0.ɵɵFactoryTarget.Injectable });
23474
23547
  RoleGuardService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RoleGuardService, providedIn: AuthenticationModule });
@@ -23676,7 +23749,7 @@ class AccessService {
23676
23749
  * @returns whether the user passes the role guard condition for accessing the specified view
23677
23750
  */
23678
23751
  passesRoleGuard(view, url) {
23679
- return !view.access.hasOwnProperty('role') || this._roleGuard.canAccessView(view, url);
23752
+ return (!view.access.hasOwnProperty('role') && !view.access.hasOwnProperty('bannedRole')) || this._roleGuard.canAccessView(view, url);
23680
23753
  }
23681
23754
  /**
23682
23755
  * @param view the view whose access permissions we want to check
@@ -25146,15 +25219,18 @@ class AbstractNavigationDoubleDrawerComponent {
25146
25219
  id: filter.stringId,
25147
25220
  resource: filter
25148
25221
  };
25149
- const resolvedRoles = this.resolveAccessRoles(filter);
25222
+ const resolvedRoles = this.resolveAccessRoles(filter, 'allowed_roles');
25223
+ const resolvedBannedRoles = this.resolveAccessRoles(filter, 'banned_roles');
25150
25224
  if (!!resolvedRoles)
25151
25225
  item.access['role'] = resolvedRoles;
25226
+ if (!!resolvedBannedRoles)
25227
+ item.access['bannedRole'] = resolvedBannedRoles;
25152
25228
  if (!this._accessService.canAccessView(item, item.routingPath))
25153
25229
  return;
25154
25230
  return item;
25155
25231
  }
25156
- resolveAccessRoles(filter) {
25157
- const allowedRoles = filter.immediateData.find(f => f.stringId === 'allowed_roles')?.options;
25232
+ resolveAccessRoles(filter, roleType) {
25233
+ const allowedRoles = filter.immediateData.find(f => f.stringId === roleType)?.options;
25158
25234
  if (!allowedRoles || Object.keys(allowedRoles).length === 0)
25159
25235
  return undefined;
25160
25236
  const roles = [];
@@ -28426,7 +28502,7 @@ class AbstractSearchOperandInputComponent {
28426
28502
  }
28427
28503
  return this._filteredOptions$;
28428
28504
  }
28429
- get isInputFilled() {
28505
+ isInputFilled() {
28430
28506
  if (!this._inputConfirmed) {
28431
28507
  return false;
28432
28508
  }
@@ -28439,7 +28515,7 @@ class AbstractSearchOperandInputComponent {
28439
28515
  return;
28440
28516
  }
28441
28517
  this._initialExpansion = false;
28442
- if (!this.isInputFilled) {
28518
+ if (!this.isInputFilled()) {
28443
28519
  setTimeout(() => {
28444
28520
  input.nativeElement.focus();
28445
28521
  });
@@ -31559,8 +31635,7 @@ class AbstractFieldComponentResolverComponent {
31559
31635
  return this.gridElement.item;
31560
31636
  }
31561
31637
  getTaskId() {
31562
- const referencedTaskId = this.taskContentService.getReferencedFieldTask(this.getDataField().stringId);
31563
- return referencedTaskId ?? this.taskContentService.task.stringId;
31638
+ return this.taskContentService.task.stringId;
31564
31639
  }
31565
31640
  isField() {
31566
31641
  return this.gridElement.type !== TaskElementType.BLANK && this.gridElement.type !== TaskElementType.DATA_GROUP_TITLE;