@sumaris-net/ngx-components 2.6.16 → 2.6.18

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 (30) hide show
  1. package/esm2020/src/app/admin/users/users.mjs +9 -3
  2. package/esm2020/src/app/core/form/buttons/form-buttons-bar.component.mjs +1 -1
  3. package/esm2020/src/app/core/form/entity/editor.class.mjs +3 -2
  4. package/esm2020/src/app/core/menu/menu.component.mjs +10 -6
  5. package/esm2020/src/app/core/menu/menu.service.mjs +7 -1
  6. package/esm2020/src/app/shared/services/memory-entity-service.class.mjs +3 -3
  7. package/esm2020/src/app/social/message/message.form.mjs +56 -4
  8. package/esm2020/src/app/social/message/message.modal.mjs +7 -3
  9. package/esm2020/src/app/social/message/message.model.mjs +4 -1
  10. package/esm2020/src/app/social/message/message.module.mjs +7 -20
  11. package/esm2020/src/app/social/message/message.service.mjs +3 -3
  12. package/esm2020/src/app/social/user-event/user-event.service.mjs +35 -22
  13. package/fesm2015/sumaris-net.ngx-components.mjs +181 -109
  14. package/fesm2015/sumaris-net.ngx-components.mjs.map +1 -1
  15. package/fesm2020/sumaris-net.ngx-components.mjs +180 -109
  16. package/fesm2020/sumaris-net.ngx-components.mjs.map +1 -1
  17. package/package.json +1 -1
  18. package/src/app/core/form/buttons/form-buttons-bar.component.d.ts +1 -1
  19. package/src/app/core/menu/menu.component.d.ts +6 -2
  20. package/src/app/core/menu/menu.service.d.ts +2 -0
  21. package/src/app/shared/services/memory-entity-service.class.d.ts +3 -1
  22. package/src/app/social/message/message.form.d.ts +8 -2
  23. package/src/app/social/message/message.modal.d.ts +5 -1
  24. package/src/app/social/message/message.model.d.ts +2 -0
  25. package/src/app/social/message/message.module.d.ts +2 -1
  26. package/src/app/social/user-event/user-event.service.d.ts +5 -0
  27. package/src/assets/i18n/en-US.json +1 -0
  28. package/src/assets/i18n/en.json +1 -0
  29. package/src/assets/i18n/fr.json +1 -0
  30. package/src/assets/manifest.json +1 -1
@@ -23123,7 +23123,7 @@ class InMemoryEntitiesService extends StartableObservableService {
23123
23123
  const res = { data, total };
23124
23124
  const nextOffset = size > 0 ? (offset || 0) + size : total;
23125
23125
  if (nextOffset < total) {
23126
- res.fetchMore = () => this.loadAll(nextOffset, size, sortBy, sortDirection, filter, opts)
23126
+ res.fetchMore = () => this.loadAll(nextOffset, size, sortBy, sortDirection, filter, { ...opts, updateHiddenData: false })
23127
23127
  .then(res => {
23128
23128
  // Update hidden data (remove new fetched item)
23129
23129
  if (res.data?.length) {
@@ -23136,7 +23136,7 @@ class InMemoryEntitiesService extends StartableObservableService {
23136
23136
  }
23137
23137
  finally {
23138
23138
  // Remember hidden data
23139
- if (offset === 0) {
23139
+ if (opts?.updateHiddenData !== false) {
23140
23140
  this._hiddenData = !excludedDataByPagination ? excludedDataByFilter : excludedDataByFilter.concat(...excludedDataByPagination);
23141
23141
  }
23142
23142
  }
@@ -24510,6 +24510,12 @@ class MenuService extends StartableObservableService {
24510
24510
  _markAsClosed() {
24511
24511
  this._$opened.next(false);
24512
24512
  }
24513
+ async close() {
24514
+ this._$opened.next(false);
24515
+ }
24516
+ async open() {
24517
+ this._$opened.next(true);
24518
+ }
24513
24519
  async ngOnStart() {
24514
24520
  console.info(`${this._logPrefix}Starting...`);
24515
24521
  // Restore sub items from settings
@@ -24906,7 +24912,7 @@ class MenuComponent {
24906
24912
  this._subscription.add(this.menuService.opened
24907
24913
  // Avoid duplicated events
24908
24914
  .pipe(distinctUntilChanged())
24909
- .subscribe((value) => (value ? this.open() : this.close())));
24915
+ .subscribe((value) => (value ? this.open({ emitEvent: false }) : this.close({ emitEvent: false }))));
24910
24916
  // TODO : Find a more reliable way to do this :
24911
24917
  // Must be donne after menuService subscription :
24912
24918
  // - In MenuService.ngOnStart accountChanges change will be emitted before the service is ready
@@ -24956,25 +24962,29 @@ class MenuComponent {
24956
24962
  await this.close();
24957
24963
  }
24958
24964
  }
24959
- async open() {
24965
+ async open(opts) {
24960
24966
  console.debug('[menu] Checking open event...');
24961
24967
  const opened = await this.menu.isOpen(this.menuId);
24962
24968
  if (!opened) {
24963
24969
  console.debug('[menu] Opening menu');
24964
24970
  await this.menu.open(this.menuId);
24965
24971
  // Propagate to service
24966
- this.menuService._markAsOpened();
24972
+ if (!opts || opts.emitEvent !== false) {
24973
+ this.menuService._markAsOpened();
24974
+ }
24967
24975
  }
24968
24976
  return true;
24969
24977
  }
24970
- async close() {
24978
+ async close(opts) {
24971
24979
  console.debug('[menu] Checking close event...');
24972
24980
  const opened = await this.menu.isOpen(this.menuId);
24973
24981
  if (opened) {
24974
24982
  console.debug('[menu] Closing menu');
24975
24983
  await this.menu.close(this.menuId);
24976
24984
  // Propagate to service
24977
- this.menuService._markAsClosed();
24985
+ if (!opts || opts.emitEvent !== false) {
24986
+ this.menuService._markAsClosed();
24987
+ }
24978
24988
  }
24979
24989
  return true;
24980
24990
  }
@@ -30790,7 +30800,8 @@ class AppEditor {
30790
30800
  }
30791
30801
  }
30792
30802
  setError(value, opts) {
30793
- if (this.errorSubject.value !== value) {
30803
+ // Compare using '!=' to detect null and undefined as same value
30804
+ if (this.errorSubject.value != value) {
30794
30805
  this.errorSubject.next(value);
30795
30806
  if (!opts || opts.emitEvent !== false)
30796
30807
  this.markForCheck();
@@ -34897,6 +34908,7 @@ class AbstractUserEventService extends BaseGraphqlService {
34897
34908
  this.queries = options.queries;
34898
34909
  this.mutations = options.mutations || {};
34899
34910
  this.subscriptions = options.subscriptions || {};
34911
+ this.watchQueriesUpdatePolicy = options.watchQueriesUpdatePolicy || 'update-cache';
34900
34912
  this._logPrefix = '[user-event-service] ';
34901
34913
  }
34902
34914
  get countSubject() {
@@ -35038,10 +35050,21 @@ class AbstractUserEventService extends BaseGraphqlService {
35038
35050
  return; // Rejected
35039
35051
  const withContent = !!entity.content;
35040
35052
  // Add user event locally
35041
- this.insertIntoMutableCachedQueries(this.graphql.cache, {
35042
- query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
35043
- data: entity
35044
- });
35053
+ if (this.watchQueriesUpdatePolicy === 'update-cache') {
35054
+ if (withContent) {
35055
+ this.insertIntoMutableCachedQueries(this.graphql.cache, {
35056
+ query: this.queries.loadAllWithContent,
35057
+ data: entity
35058
+ });
35059
+ }
35060
+ this.insertIntoMutableCachedQueries(this.graphql.cache, {
35061
+ query: this.queries.loadAll,
35062
+ data: {
35063
+ ...entity,
35064
+ content: null
35065
+ }
35066
+ });
35067
+ }
35045
35068
  // Update count
35046
35069
  this._countSubject.next(this._countSubject.value + 1);
35047
35070
  // Add id
@@ -35155,16 +35178,14 @@ class AbstractUserEventService extends BaseGraphqlService {
35155
35178
  variables: {
35156
35179
  ids
35157
35180
  },
35158
- update: (proxy) => {
35159
- // Remove from caches
35160
- this.removeFromMutableCachedQueriesByIds(proxy, {
35161
- query: this.queries.loadAll,
35162
- ids
35163
- });
35164
- this.removeFromMutableCachedQueriesByIds(proxy, {
35165
- query: this.queries.loadAllWithContent,
35166
- ids
35167
- });
35181
+ update: (cache) => {
35182
+ // Remove from cache
35183
+ if (this.watchQueriesUpdatePolicy === 'update-cache') {
35184
+ this.removeFromMutableCachedQueriesByIds(cache, {
35185
+ queries: this.getLoadQueries(),
35186
+ ids
35187
+ });
35188
+ }
35168
35189
  if (this._debug)
35169
35190
  console.debug(`${this._logPrefix}Events deleted in ${Date.now() - now}ms`);
35170
35191
  }
@@ -35192,13 +35213,13 @@ class AbstractUserEventService extends BaseGraphqlService {
35192
35213
  console.debug(`${this._logPrefix}User event saved in ${Date.now() - now}ms`, entity);
35193
35214
  this.copyIdAndUpdateDate(savedEntity, entity);
35194
35215
  // Add to cache
35195
- if (withContent) {
35196
- this.insertIntoMutableCachedQueries(proxy, {
35197
- query: this.queries.loadAllWithContent,
35198
- data: savedEntity
35199
- });
35200
- }
35201
- else {
35216
+ if (this.watchQueriesUpdatePolicy === 'update-cache') {
35217
+ if (withContent) {
35218
+ this.insertIntoMutableCachedQueries(proxy, {
35219
+ query: this.queries.loadAllWithContent,
35220
+ data: savedEntity
35221
+ });
35222
+ }
35202
35223
  this.insertIntoMutableCachedQueries(proxy, {
35203
35224
  query: this.queries.loadAll,
35204
35225
  data: {
@@ -35349,6 +35370,9 @@ class AbstractUserEventService extends BaseGraphqlService {
35349
35370
  copyIdAndUpdateDate(source, target) {
35350
35371
  EntityUtils.copyIdAndUpdateDate(source, target);
35351
35372
  }
35373
+ getLoadQueries() {
35374
+ return [this.queries.loadAll, this.queries.loadAllWithContent].filter(isNotNil);
35375
+ }
35352
35376
  }
35353
35377
  AbstractUserEventService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: AbstractUserEventService, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive });
35354
35378
  AbstractUserEventService.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", type: AbstractUserEventService, usesInheritance: true, ngImport: i0 });
@@ -35714,6 +35738,59 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
35714
35738
  }]
35715
35739
  }] });
35716
35740
 
35741
+ var PersonFilter_1;
35742
+ // @dynamic
35743
+ let PersonFilter = PersonFilter_1 = class PersonFilter extends EntityFilter {
35744
+ constructor() {
35745
+ super(PersonFilter_1.TYPENAME);
35746
+ }
35747
+ static searchFilter(source) {
35748
+ return source && PersonFilter_1.fromObject(source).asFilterFn();
35749
+ }
35750
+ fromObject(source, opts) {
35751
+ super.fromObject(source, opts);
35752
+ this.email = source.email;
35753
+ this.pubkey = source.pubkey;
35754
+ this.searchText = source.searchText;
35755
+ this.statusIds = source.statusIds || (isNotNil(source.statusId) ? [source.statusId] : undefined);
35756
+ this.userProfiles = source.userProfiles;
35757
+ this.excludedIds = source.excludedIds;
35758
+ this.searchAttribute = source.searchAttribute;
35759
+ this.searchAttributes = source.searchAttributes;
35760
+ }
35761
+ asObject(opts) {
35762
+ const target = super.asObject(opts);
35763
+ target.email = this.email;
35764
+ target.pubkey = this.pubkey;
35765
+ target.searchText = this.searchText;
35766
+ target.statusIds = this.statusIds;
35767
+ target.userProfiles = this.userProfiles;
35768
+ target.excludedIds = this.excludedIds;
35769
+ target.searchAttribute = this.searchAttribute;
35770
+ target.searchAttributes = this.searchAttributes;
35771
+ return target;
35772
+ }
35773
+ buildFilter() {
35774
+ const filterFns = super.buildFilter();
35775
+ // Filter by status
35776
+ if (isNotEmptyArray(this.statusIds)) {
35777
+ filterFns.push(e => this.statusIds.includes(e.statusId));
35778
+ }
35779
+ // Filter excluded ids
35780
+ if (isNotEmptyArray(this.excludedIds)) {
35781
+ filterFns.push(e => isNil(e.id) || !this.excludedIds.includes(e.id));
35782
+ }
35783
+ // Search text
35784
+ const searchTextFilter = EntityUtils.searchTextFilter(this.searchAttribute || this.searchAttributes || ['lastName', 'firstName', 'department.name'], this.searchText);
35785
+ if (searchTextFilter)
35786
+ filterFns.push(searchTextFilter);
35787
+ return filterFns;
35788
+ }
35789
+ };
35790
+ PersonFilter = PersonFilter_1 = __decorate([
35791
+ EntityClass({ typename: 'PersonFilterVO' })
35792
+ ], PersonFilter);
35793
+
35717
35794
  const MessageTypes = {
35718
35795
  INBOX_MESSAGE: 'INBOX_MESSAGE',
35719
35796
  EMAIL: 'EMAIL',
@@ -35746,12 +35823,14 @@ let Message = class Message extends Entity {
35746
35823
  this.type = source.type;
35747
35824
  this.issuer = source.issuer && Person.fromObject(source.issuer);
35748
35825
  this.recipients = source.recipients && source.recipients.map(Person.fromObject);
35826
+ this.recipientFilter = source.recipientFilter && PersonFilter.fromObject(source.recipientFilter) || undefined;
35749
35827
  this.subject = source.subject;
35750
35828
  this.body = source.body;
35751
35829
  }
35752
35830
  asObject(opts) {
35753
35831
  const target = super.asObject(opts);
35754
35832
  target.recipients = this.recipients && this.recipients.map(p => p.asObject(opts));
35833
+ target.recipientFilter = this.recipientFilter && this.recipientFilter.asObject(opts) || undefined;
35755
35834
  return target;
35756
35835
  }
35757
35836
  };
@@ -35781,6 +35860,8 @@ class MessageForm extends AppForm {
35781
35860
  this.bodyMaxLength = 2000;
35782
35861
  this.bodyAutoHeight = true;
35783
35862
  this.canSelectType = false;
35863
+ this.canRecipientFilter = false;
35864
+ this.recipientFilterCount = 0;
35784
35865
  this.types = MessageTypeList;
35785
35866
  this.mobile = this.settings.mobile;
35786
35867
  }
@@ -35788,6 +35869,7 @@ class MessageForm extends AppForm {
35788
35869
  this.setForm(this.formBuilder.group({
35789
35870
  type: [MessageTypes.INBOX_MESSAGE, Validators.required],
35790
35871
  recipients: [null, Validators.required],
35872
+ recipientFilter: [null],
35791
35873
  subject: [
35792
35874
  null,
35793
35875
  this.subjectMaxLength
@@ -35796,6 +35878,11 @@ class MessageForm extends AppForm {
35796
35878
  ],
35797
35879
  body: [null, this.bodyMaxLength ? Validators.compose([Validators.maxLength(this.bodyMaxLength)]) : Validators.required],
35798
35880
  }));
35881
+ this.registerSubscription(this._form
35882
+ .get('type')
35883
+ .valueChanges.pipe(filter(isNotNil))
35884
+ .subscribe((type) => this.updateFormGroup(this._form, { type })));
35885
+ // Person combo
35799
35886
  const personAttributes = this.settings.getFieldDisplayAttributes('person', ['lastName', 'firstName', 'department.name']);
35800
35887
  this.registerAutocompleteField('recipients', {
35801
35888
  showAllOnFocus: false,
@@ -35813,15 +35900,53 @@ class MessageForm extends AppForm {
35813
35900
  isSamePerson(o1, o2) {
35814
35901
  return EntityUtils.equals(o1, o2, 'id');
35815
35902
  }
35903
+ updateFormGroup(formGroup, opts) {
35904
+ console.debug('[message-form] Updating form group...', opts);
35905
+ // Recipient validator
35906
+ const recipientsRequired = toBoolean(opts?.recipientRequired, opts?.type !== MessageTypes.FEED);
35907
+ {
35908
+ const control = formGroup.get('recipients');
35909
+ if (recipientsRequired) {
35910
+ if (!control.hasValidator(Validators.required)) {
35911
+ control.addValidators(Validators.required);
35912
+ }
35913
+ control.enable();
35914
+ }
35915
+ else {
35916
+ if (control.hasValidator(Validators.required)) {
35917
+ control.removeValidators(Validators.required);
35918
+ }
35919
+ control.disable();
35920
+ }
35921
+ }
35922
+ // Recipient filter validator
35923
+ const recipientFilterRequired = this.canRecipientFilter && !recipientsRequired;
35924
+ {
35925
+ const control = formGroup.get('recipientFilter');
35926
+ if (recipientFilterRequired) {
35927
+ if (!control.hasValidator(Validators.required)) {
35928
+ control.addValidators(Validators.required);
35929
+ }
35930
+ control.enable();
35931
+ }
35932
+ else {
35933
+ if (control.hasValidator(Validators.required)) {
35934
+ control.removeValidators(Validators.required);
35935
+ }
35936
+ control.disable();
35937
+ }
35938
+ }
35939
+ formGroup.updateValueAndValidity();
35940
+ }
35816
35941
  markForCheck() {
35817
35942
  this.cd.markForCheck();
35818
35943
  }
35819
35944
  }
35820
35945
  MessageForm.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MessageForm, deps: [{ token: i0.Injector }, { token: i1$2.UntypedFormBuilder }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
35821
- MessageForm.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: MessageForm, selector: "app-message-form", inputs: { suggestFn: "suggestFn", subjectMinLength: "subjectMinLength", subjectMaxLength: "subjectMaxLength", bodyMaxLength: "bodyMaxLength", bodyAutoHeight: "bodyAutoHeight", canSelectType: "canSelectType" }, usesInheritance: true, ngImport: i0, template: "\n\n<form [formGroup]=\"form\" class=\"form-container\">\n\n <!-- type -->\n <mat-form-field *ngIf=\"canSelectType\">\n <mat-select formControlName=\"type\" [placeholder]=\"'SOCIAL.MESSAGE.TYPE'|translate\">\n <mat-option *ngFor=\"let item of types\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label |translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n\n <!-- Recipients -->\n <mat-chips-field *ngIf=\"(form.controls.type.valueChanges|async) !== 'FEED'\"\n formControlName=\"recipients\"\n chipColor=\"accent\"\n [placeholder]=\"'SOCIAL.MESSAGE.RECIPIENTS'|translate\"\n [config]=\"autocompleteFields.recipients\"\n [equals]=\"isSamePerson\">\n </mat-chips-field>\n\n <!-- Subject -->\n <mat-form-field>\n <input matInput type=\"text\"\n [placeholder]=\"'SOCIAL.MESSAGE.SUBJECT'|translate\"\n formControlName=\"subject\"\n autocomplete=\"off\"\n required>\n <mat-error *ngIf=\"form.controls.subject.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.subject.hasError('minlength')\">\n {{ 'ERROR.FIELD_MIN_LENGTH_COMPACT'|translate }}\n </mat-error>\n <mat-error *ngIf=\"form.controls.subject.hasError('maxlength')\">\n {{ 'ERROR.FIELD_MAX_LENGTH_COMPACT'|translate }}\n </mat-error>\n <mat-hint *ngIf=\"subjectMaxLength\" align=\"end\">\n {{ 'INFO.TEXT_PROGRESS' | translate: { current: form.controls.subject.value?.length || 0, max: subjectMaxLength } }}\n </mat-hint>\n </mat-form-field>\n\n <!-- Body -->\n <mat-form-field floatLabel=\"never\">\n <textarea matInput type=\"text\"\n [placeholder]=\"'SOCIAL.MESSAGE.BODY_HELP'|translate\"\n formControlName=\"body\"\n [class.fixed-height]=\"!bodyAutoHeight\"\n [cdkTextareaAutosize]=\"bodyAutoHeight\"\n (keydown.control.enter)=\"doSubmit($event)\"\n >\n </textarea>\n <mat-error *ngIf=\"form.controls.body.hasError('maxlength')\">\n {{ 'ERROR.FIELD_MAX_LENGTH' | translate: form.controls.body.errors.maxlength }}\n </mat-error>\n <mat-hint *ngIf=\"bodyMaxLength\" align=\"end\">\n {{ 'INFO.TEXT_PROGRESS' | translate: { current: form.controls.body.value?.length || 0, max: bodyMaxLength } }}\n </mat-hint>\n </mat-form-field>\n\n</form>\n", styles: ["textarea.fixed-height{height:11.5em}textarea{min-height:11.5em}\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: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6$1.MatError, selector: "mat-error", inputs: ["id"] }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i12.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: MatChipsField, selector: "mat-chips-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "appearance", "placeholder", "suggestFn", "required", "mobile", "readonly", "clearable", "debounceTime", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "autofocus", "config", "i18nPrefix", "noResultMessage", "class", "panelWidth", "matAutocompletePosition", "itemSize", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "chipColor", "debug", "filter", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keyup.enter"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
35946
+ MessageForm.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: MessageForm, selector: "app-message-form", inputs: { suggestFn: "suggestFn", subjectMinLength: "subjectMinLength", subjectMaxLength: "subjectMaxLength", bodyMaxLength: "bodyMaxLength", bodyAutoHeight: "bodyAutoHeight", canSelectType: "canSelectType", canRecipientFilter: "canRecipientFilter", recipientFilterCount: "recipientFilterCount" }, usesInheritance: true, ngImport: i0, template: "\n\n<form [formGroup]=\"form\" class=\"form-container\">\n\n <!-- type -->\n <mat-form-field *ngIf=\"canSelectType\">\n <mat-select formControlName=\"type\" [placeholder]=\"'SOCIAL.MESSAGE.TYPE'|translate\">\n <ng-container *ngFor=\"let item of types\">\n <mat-option [value]=\"item.id\" *ngIf=\"item.id !== 'FEED' || canRecipientFilter\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label |translate }}\n </mat-option>\n </ng-container>\n </mat-select>\n </mat-form-field>\n\n <!-- Recipients -->\n <mat-chips-field *ngIf=\"(form.controls.type.valueChanges|async) !== 'FEED'; else recipientFilter\"\n formControlName=\"recipients\"\n chipColor=\"accent\"\n [placeholder]=\"'SOCIAL.MESSAGE.RECIPIENTS'|translate\"\n [config]=\"autocompleteFields.recipients\"\n [equals]=\"isSamePerson\">\n </mat-chips-field>\n <ng-template #recipientFilter>\n <mat-form-field>\n <mat-chip-list>\n <mat-chip>{{'SOCIAL.MESSAGE.RECIPIENT_FILTER_COUNT'|translate: {count: recipientFilterCount} }}</mat-chip>\n </mat-chip-list>\n <input matInput hidden type=\"number\">\n </mat-form-field>\n </ng-template>\n\n <!-- Subject -->\n <mat-form-field>\n <input matInput type=\"text\"\n [placeholder]=\"'SOCIAL.MESSAGE.SUBJECT'|translate\"\n formControlName=\"subject\"\n autocomplete=\"off\"\n required>\n <mat-error *ngIf=\"form.controls.subject.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.subject.hasError('minlength')\">\n {{ 'ERROR.FIELD_MIN_LENGTH_COMPACT'|translate }}\n </mat-error>\n <mat-error *ngIf=\"form.controls.subject.hasError('maxlength')\">\n {{ 'ERROR.FIELD_MAX_LENGTH_COMPACT'|translate }}\n </mat-error>\n <mat-hint *ngIf=\"subjectMaxLength\" align=\"end\">\n {{ 'INFO.TEXT_PROGRESS' | translate: { current: form.controls.subject.value?.length || 0, max: subjectMaxLength } }}\n </mat-hint>\n </mat-form-field>\n\n <!-- Body -->\n <mat-form-field floatLabel=\"never\">\n <textarea matInput type=\"text\"\n [placeholder]=\"'SOCIAL.MESSAGE.BODY_HELP'|translate\"\n formControlName=\"body\"\n [class.fixed-height]=\"!bodyAutoHeight\"\n [cdkTextareaAutosize]=\"bodyAutoHeight\"\n (keydown.control.enter)=\"doSubmit($event)\"\n >\n </textarea>\n <mat-error *ngIf=\"form.controls.body.hasError('maxlength')\">\n {{ 'ERROR.FIELD_MAX_LENGTH' | translate: form.controls.body.errors.maxlength }}\n </mat-error>\n <mat-hint *ngIf=\"bodyMaxLength\" align=\"end\">\n {{ 'INFO.TEXT_PROGRESS' | translate: { current: form.controls.body.value?.length || 0, max: bodyMaxLength } }}\n </mat-hint>\n </mat-form-field>\n\n</form>\n", styles: ["textarea.fixed-height{height:11.5em}textarea{min-height:11.5em}\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: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6$1.MatError, selector: "mat-error", inputs: ["id"] }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i12.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: MatChipsField, selector: "mat-chips-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "appearance", "placeholder", "suggestFn", "required", "mobile", "readonly", "clearable", "debounceTime", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "autofocus", "config", "i18nPrefix", "noResultMessage", "class", "panelWidth", "matAutocompletePosition", "itemSize", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "chipColor", "debug", "filter", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keyup.enter"] }, { kind: "component", type: i11$1.MatChipList, selector: "mat-chip-list", inputs: ["role", "aria-describedby", "errorStateMatcher", "multiple", "compareWith", "value", "required", "placeholder", "disabled", "aria-orientation", "selectable", "tabIndex"], outputs: ["change", "valueChange"], exportAs: ["matChipList"] }, { kind: "directive", type: i11$1.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disableRipple", "tabIndex", "role", "selected", "value", "selectable", "disabled", "removable"], outputs: ["selectionChange", "destroyed", "removed"], exportAs: ["matChip"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
35822
35947
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MessageForm, decorators: [{
35823
35948
  type: Component,
35824
- args: [{ selector: 'app-message-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "\n\n<form [formGroup]=\"form\" class=\"form-container\">\n\n <!-- type -->\n <mat-form-field *ngIf=\"canSelectType\">\n <mat-select formControlName=\"type\" [placeholder]=\"'SOCIAL.MESSAGE.TYPE'|translate\">\n <mat-option *ngFor=\"let item of types\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label |translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n\n <!-- Recipients -->\n <mat-chips-field *ngIf=\"(form.controls.type.valueChanges|async) !== 'FEED'\"\n formControlName=\"recipients\"\n chipColor=\"accent\"\n [placeholder]=\"'SOCIAL.MESSAGE.RECIPIENTS'|translate\"\n [config]=\"autocompleteFields.recipients\"\n [equals]=\"isSamePerson\">\n </mat-chips-field>\n\n <!-- Subject -->\n <mat-form-field>\n <input matInput type=\"text\"\n [placeholder]=\"'SOCIAL.MESSAGE.SUBJECT'|translate\"\n formControlName=\"subject\"\n autocomplete=\"off\"\n required>\n <mat-error *ngIf=\"form.controls.subject.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.subject.hasError('minlength')\">\n {{ 'ERROR.FIELD_MIN_LENGTH_COMPACT'|translate }}\n </mat-error>\n <mat-error *ngIf=\"form.controls.subject.hasError('maxlength')\">\n {{ 'ERROR.FIELD_MAX_LENGTH_COMPACT'|translate }}\n </mat-error>\n <mat-hint *ngIf=\"subjectMaxLength\" align=\"end\">\n {{ 'INFO.TEXT_PROGRESS' | translate: { current: form.controls.subject.value?.length || 0, max: subjectMaxLength } }}\n </mat-hint>\n </mat-form-field>\n\n <!-- Body -->\n <mat-form-field floatLabel=\"never\">\n <textarea matInput type=\"text\"\n [placeholder]=\"'SOCIAL.MESSAGE.BODY_HELP'|translate\"\n formControlName=\"body\"\n [class.fixed-height]=\"!bodyAutoHeight\"\n [cdkTextareaAutosize]=\"bodyAutoHeight\"\n (keydown.control.enter)=\"doSubmit($event)\"\n >\n </textarea>\n <mat-error *ngIf=\"form.controls.body.hasError('maxlength')\">\n {{ 'ERROR.FIELD_MAX_LENGTH' | translate: form.controls.body.errors.maxlength }}\n </mat-error>\n <mat-hint *ngIf=\"bodyMaxLength\" align=\"end\">\n {{ 'INFO.TEXT_PROGRESS' | translate: { current: form.controls.body.value?.length || 0, max: bodyMaxLength } }}\n </mat-hint>\n </mat-form-field>\n\n</form>\n", styles: ["textarea.fixed-height{height:11.5em}textarea{min-height:11.5em}\n"] }]
35949
+ args: [{ selector: 'app-message-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "\n\n<form [formGroup]=\"form\" class=\"form-container\">\n\n <!-- type -->\n <mat-form-field *ngIf=\"canSelectType\">\n <mat-select formControlName=\"type\" [placeholder]=\"'SOCIAL.MESSAGE.TYPE'|translate\">\n <ng-container *ngFor=\"let item of types\">\n <mat-option [value]=\"item.id\" *ngIf=\"item.id !== 'FEED' || canRecipientFilter\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label |translate }}\n </mat-option>\n </ng-container>\n </mat-select>\n </mat-form-field>\n\n <!-- Recipients -->\n <mat-chips-field *ngIf=\"(form.controls.type.valueChanges|async) !== 'FEED'; else recipientFilter\"\n formControlName=\"recipients\"\n chipColor=\"accent\"\n [placeholder]=\"'SOCIAL.MESSAGE.RECIPIENTS'|translate\"\n [config]=\"autocompleteFields.recipients\"\n [equals]=\"isSamePerson\">\n </mat-chips-field>\n <ng-template #recipientFilter>\n <mat-form-field>\n <mat-chip-list>\n <mat-chip>{{'SOCIAL.MESSAGE.RECIPIENT_FILTER_COUNT'|translate: {count: recipientFilterCount} }}</mat-chip>\n </mat-chip-list>\n <input matInput hidden type=\"number\">\n </mat-form-field>\n </ng-template>\n\n <!-- Subject -->\n <mat-form-field>\n <input matInput type=\"text\"\n [placeholder]=\"'SOCIAL.MESSAGE.SUBJECT'|translate\"\n formControlName=\"subject\"\n autocomplete=\"off\"\n required>\n <mat-error *ngIf=\"form.controls.subject.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.subject.hasError('minlength')\">\n {{ 'ERROR.FIELD_MIN_LENGTH_COMPACT'|translate }}\n </mat-error>\n <mat-error *ngIf=\"form.controls.subject.hasError('maxlength')\">\n {{ 'ERROR.FIELD_MAX_LENGTH_COMPACT'|translate }}\n </mat-error>\n <mat-hint *ngIf=\"subjectMaxLength\" align=\"end\">\n {{ 'INFO.TEXT_PROGRESS' | translate: { current: form.controls.subject.value?.length || 0, max: subjectMaxLength } }}\n </mat-hint>\n </mat-form-field>\n\n <!-- Body -->\n <mat-form-field floatLabel=\"never\">\n <textarea matInput type=\"text\"\n [placeholder]=\"'SOCIAL.MESSAGE.BODY_HELP'|translate\"\n formControlName=\"body\"\n [class.fixed-height]=\"!bodyAutoHeight\"\n [cdkTextareaAutosize]=\"bodyAutoHeight\"\n (keydown.control.enter)=\"doSubmit($event)\"\n >\n </textarea>\n <mat-error *ngIf=\"form.controls.body.hasError('maxlength')\">\n {{ 'ERROR.FIELD_MAX_LENGTH' | translate: form.controls.body.errors.maxlength }}\n </mat-error>\n <mat-hint *ngIf=\"bodyMaxLength\" align=\"end\">\n {{ 'INFO.TEXT_PROGRESS' | translate: { current: form.controls.body.value?.length || 0, max: bodyMaxLength } }}\n </mat-hint>\n </mat-form-field>\n\n</form>\n", styles: ["textarea.fixed-height{height:11.5em}textarea{min-height:11.5em}\n"] }]
35825
35950
  }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i1$2.UntypedFormBuilder }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { suggestFn: [{
35826
35951
  type: Input
35827
35952
  }], subjectMinLength: [{
@@ -35834,6 +35959,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
35834
35959
  type: Input
35835
35960
  }], canSelectType: [{
35836
35961
  type: Input
35962
+ }], canRecipientFilter: [{
35963
+ type: Input
35964
+ }], recipientFilterCount: [{
35965
+ type: Input
35837
35966
  }] } });
35838
35967
 
35839
35968
  class MessageModal {
@@ -35904,16 +36033,20 @@ class MessageModal {
35904
36033
  }
35905
36034
  }
35906
36035
  MessageModal.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MessageModal, deps: [{ token: LocalSettingsService }, { token: i2$1.ModalController }, { token: AccountService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
35907
- MessageModal.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: MessageModal, selector: "app-message-modal", inputs: { suggestFn: "suggestFn", data: "data", canSelectType: "canSelectType" }, viewQueries: [{ propertyName: "form", first: true, predicate: ["form"], descendants: true, static: true }], ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"secondary\">\n <ion-buttons slot=\"start\">\n <ion-button class=\"back-button\" (click)=\"cancel($event)\" visible-xs visible-sm visible-mobile>\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n </ion-buttons>\n\n <ion-title>\n {{'SOCIAL.MESSAGE.NEW.TITLE' | translate}}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n\n <ion-button class=\"back-button\" (click)=\"doSubmit($event)\"\n [disabled]=\"!form.valid\"\n visible-xs visible-sm visible-mobile>\n <ion-icon slot=\"icon-only\" name=\"checkmark\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n\n<ion-content class=\"ion-padding\" >\n\n <ion-item *ngIf=\"form.error\" visible-xs visible-sm visible-mobile lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"form.error|translate\"></ion-label>\n </ion-item>\n\n <app-message-form #form (onSubmit)=\"doSubmit($event)\"\n (onCancel)=\"cancel($event)\"\n [canSelectType]=\"canSelectType\"\n [suggestFn]=\"suggestFn\">\n </app-message-form>\n\n</ion-content>\n\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n\n <ion-toolbar>\n\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <!-- buttons -->\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"cancel($event)\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n\n <ion-button [fill]=\"form.invalid ? 'clear' : 'solid'\"\n [disabled]=\"form.loading || form.invalid\"\n (keyup.enter)=\"doSubmit($event)\"\n (click)=\"doSubmit($event)\" color=\"tertiary\">\n <ion-label translate>COMMON.BTN_SEND</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n\n\n </ion-toolbar>\n</ion-footer>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: MessageForm, selector: "app-message-form", inputs: ["suggestFn", "subjectMinLength", "subjectMaxLength", "bodyMaxLength", "bodyAutoHeight", "canSelectType"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
36036
+ MessageModal.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: MessageModal, selector: "app-message-modal", inputs: { suggestFn: "suggestFn", data: "data", canSelectType: "canSelectType", canRecipientFilter: "canRecipientFilter", recipientFilterCount: "recipientFilterCount" }, viewQueries: [{ propertyName: "form", first: true, predicate: ["form"], descendants: true, static: true }], ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"secondary\">\n <ion-buttons slot=\"start\">\n <ion-button class=\"back-button\" (click)=\"cancel($event)\" visible-xs visible-sm visible-mobile>\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n </ion-buttons>\n\n <ion-title>\n {{'SOCIAL.MESSAGE.NEW.TITLE' | translate}}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n\n <ion-button class=\"back-button\" (click)=\"doSubmit($event)\"\n [disabled]=\"!form.valid\"\n visible-xs visible-sm visible-mobile>\n <ion-icon slot=\"icon-only\" name=\"checkmark\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n\n<ion-content class=\"ion-padding\" >\n\n <ion-item *ngIf=\"form.error\" visible-xs visible-sm visible-mobile lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"form.error|translate\"></ion-label>\n </ion-item>\n\n <app-message-form #form (onSubmit)=\"doSubmit($event)\"\n (onCancel)=\"cancel($event)\"\n [canSelectType]=\"canSelectType\"\n [canRecipientFilter]=\"canRecipientFilter\"\n [recipientFilterCount]=\"recipientFilterCount\"\n [suggestFn]=\"suggestFn\">\n </app-message-form>\n\n</ion-content>\n\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n\n <ion-toolbar>\n\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <!-- buttons -->\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"cancel($event)\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n\n <ion-button [fill]=\"form.invalid ? 'clear' : 'solid'\"\n [disabled]=\"form.loading || form.invalid\"\n (keyup.enter)=\"doSubmit($event)\"\n (click)=\"doSubmit($event)\" color=\"tertiary\">\n <ion-label translate>COMMON.BTN_SEND</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n\n\n </ion-toolbar>\n</ion-footer>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: MessageForm, selector: "app-message-form", inputs: ["suggestFn", "subjectMinLength", "subjectMaxLength", "bodyMaxLength", "bodyAutoHeight", "canSelectType", "canRecipientFilter", "recipientFilterCount"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
35908
36037
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MessageModal, decorators: [{
35909
36038
  type: Component,
35910
- args: [{ selector: 'app-message-modal', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar color=\"secondary\">\n <ion-buttons slot=\"start\">\n <ion-button class=\"back-button\" (click)=\"cancel($event)\" visible-xs visible-sm visible-mobile>\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n </ion-buttons>\n\n <ion-title>\n {{'SOCIAL.MESSAGE.NEW.TITLE' | translate}}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n\n <ion-button class=\"back-button\" (click)=\"doSubmit($event)\"\n [disabled]=\"!form.valid\"\n visible-xs visible-sm visible-mobile>\n <ion-icon slot=\"icon-only\" name=\"checkmark\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n\n<ion-content class=\"ion-padding\" >\n\n <ion-item *ngIf=\"form.error\" visible-xs visible-sm visible-mobile lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"form.error|translate\"></ion-label>\n </ion-item>\n\n <app-message-form #form (onSubmit)=\"doSubmit($event)\"\n (onCancel)=\"cancel($event)\"\n [canSelectType]=\"canSelectType\"\n [suggestFn]=\"suggestFn\">\n </app-message-form>\n\n</ion-content>\n\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n\n <ion-toolbar>\n\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <!-- buttons -->\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"cancel($event)\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n\n <ion-button [fill]=\"form.invalid ? 'clear' : 'solid'\"\n [disabled]=\"form.loading || form.invalid\"\n (keyup.enter)=\"doSubmit($event)\"\n (click)=\"doSubmit($event)\" color=\"tertiary\">\n <ion-label translate>COMMON.BTN_SEND</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n\n\n </ion-toolbar>\n</ion-footer>\n" }]
36039
+ args: [{ selector: 'app-message-modal', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar color=\"secondary\">\n <ion-buttons slot=\"start\">\n <ion-button class=\"back-button\" (click)=\"cancel($event)\" visible-xs visible-sm visible-mobile>\n <ion-icon slot=\"icon-only\" name=\"arrow-back\"></ion-icon>\n </ion-button>\n </ion-buttons>\n\n <ion-title>\n {{'SOCIAL.MESSAGE.NEW.TITLE' | translate}}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n\n <ion-button class=\"back-button\" (click)=\"doSubmit($event)\"\n [disabled]=\"!form.valid\"\n visible-xs visible-sm visible-mobile>\n <ion-icon slot=\"icon-only\" name=\"checkmark\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n\n<ion-content class=\"ion-padding\" >\n\n <ion-item *ngIf=\"form.error\" visible-xs visible-sm visible-mobile lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"form.error|translate\"></ion-label>\n </ion-item>\n\n <app-message-form #form (onSubmit)=\"doSubmit($event)\"\n (onCancel)=\"cancel($event)\"\n [canSelectType]=\"canSelectType\"\n [canRecipientFilter]=\"canRecipientFilter\"\n [recipientFilterCount]=\"recipientFilterCount\"\n [suggestFn]=\"suggestFn\">\n </app-message-form>\n\n</ion-content>\n\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n\n <ion-toolbar>\n\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <!-- buttons -->\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"cancel($event)\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n\n <ion-button [fill]=\"form.invalid ? 'clear' : 'solid'\"\n [disabled]=\"form.loading || form.invalid\"\n (keyup.enter)=\"doSubmit($event)\"\n (click)=\"doSubmit($event)\" color=\"tertiary\">\n <ion-label translate>COMMON.BTN_SEND</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n\n\n </ion-toolbar>\n</ion-footer>\n" }]
35911
36040
  }], ctorParameters: function () { return [{ type: LocalSettingsService }, { type: i2$1.ModalController }, { type: AccountService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { suggestFn: [{
35912
36041
  type: Input
35913
36042
  }], data: [{
35914
36043
  type: Input
35915
36044
  }], canSelectType: [{
35916
36045
  type: Input
36046
+ }], canRecipientFilter: [{
36047
+ type: Input
36048
+ }], recipientFilterCount: [{
36049
+ type: Input
35917
36050
  }], form: [{
35918
36051
  type: ViewChild,
35919
36052
  args: ['form', { static: true }]
@@ -35922,28 +36055,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
35922
36055
  class MessageModule {
35923
36056
  }
35924
36057
  MessageModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MessageModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
35925
- MessageModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: MessageModule, declarations: [MessageModal,
35926
- MessageForm], imports: [CommonModule,
35927
- CoreModule,
35928
- SharedModule], exports: [MessageModal] });
35929
- MessageModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MessageModule, imports: [CommonModule,
35930
- CoreModule,
35931
- SharedModule] });
36058
+ MessageModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: MessageModule, declarations: [MessageModal, MessageForm], imports: [CommonModule, CoreModule, SharedModule, MatChipsModule], exports: [MessageModal] });
36059
+ MessageModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MessageModule, imports: [CommonModule, CoreModule, SharedModule, MatChipsModule] });
35932
36060
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MessageModule, decorators: [{
35933
36061
  type: NgModule,
35934
36062
  args: [{
35935
- imports: [
35936
- CommonModule,
35937
- CoreModule,
35938
- SharedModule
35939
- ],
35940
- declarations: [
35941
- MessageModal,
35942
- MessageForm
35943
- ],
35944
- exports: [
35945
- MessageModal
35946
- ]
36063
+ imports: [CommonModule, CoreModule, SharedModule, MatChipsModule],
36064
+ declarations: [MessageModal, MessageForm],
36065
+ exports: [MessageModal],
35947
36066
  }]
35948
36067
  }] });
35949
36068
 
@@ -36417,9 +36536,9 @@ class MessageService extends BaseGraphqlService {
36417
36536
  // On dismiss
36418
36537
  const { data } = await modal.onDidDismiss();
36419
36538
  if (!data || !(data instanceof Message))
36420
- return; // CANCELLED
36539
+ return true; // CANCELLED
36421
36540
  // Send message
36422
- await this.send(data, { showToast: options?.showToast });
36541
+ return await this.send(data, { showToast: options?.showToast });
36423
36542
  }
36424
36543
  /* -- protected methods -- */
36425
36544
  async showToast(opts) {
@@ -36442,59 +36561,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
36442
36561
  args: [ENVIRONMENT]
36443
36562
  }] }]; } });
36444
36563
 
36445
- var PersonFilter_1;
36446
- // @dynamic
36447
- let PersonFilter = PersonFilter_1 = class PersonFilter extends EntityFilter {
36448
- constructor() {
36449
- super(PersonFilter_1.TYPENAME);
36450
- }
36451
- static searchFilter(source) {
36452
- return source && PersonFilter_1.fromObject(source).asFilterFn();
36453
- }
36454
- fromObject(source, opts) {
36455
- super.fromObject(source, opts);
36456
- this.email = source.email;
36457
- this.pubkey = source.pubkey;
36458
- this.searchText = source.searchText;
36459
- this.statusIds = source.statusIds || (isNotNil(source.statusId) ? [source.statusId] : undefined);
36460
- this.userProfiles = source.userProfiles;
36461
- this.excludedIds = source.excludedIds;
36462
- this.searchAttribute = source.searchAttribute;
36463
- this.searchAttributes = source.searchAttributes;
36464
- }
36465
- asObject(opts) {
36466
- const target = super.asObject(opts);
36467
- target.email = this.email;
36468
- target.pubkey = this.pubkey;
36469
- target.searchText = this.searchText;
36470
- target.statusIds = this.statusIds;
36471
- target.userProfiles = this.userProfiles;
36472
- target.excludedIds = this.excludedIds;
36473
- target.searchAttribute = this.searchAttribute;
36474
- target.searchAttributes = this.searchAttributes;
36475
- return target;
36476
- }
36477
- buildFilter() {
36478
- const filterFns = super.buildFilter();
36479
- // Filter by status
36480
- if (isNotEmptyArray(this.statusIds)) {
36481
- filterFns.push(e => this.statusIds.includes(e.statusId));
36482
- }
36483
- // Filter excluded ids
36484
- if (isNotEmptyArray(this.excludedIds)) {
36485
- filterFns.push(e => isNil(e.id) || !this.excludedIds.includes(e.id));
36486
- }
36487
- // Search text
36488
- const searchTextFilter = EntityUtils.searchTextFilter(this.searchAttribute || this.searchAttributes || ['lastName', 'firstName', 'department.name'], this.searchText);
36489
- if (searchTextFilter)
36490
- filterFns.push(searchTextFilter);
36491
- return filterFns;
36492
- }
36493
- };
36494
- PersonFilter = PersonFilter_1 = __decorate([
36495
- EntityClass({ typename: 'PersonFilterVO' })
36496
- ], PersonFilter);
36497
-
36498
36564
  const PersonFragments = {
36499
36565
  person: gql `
36500
36566
  fragment PersonFragment on PersonVO {
@@ -36820,11 +36886,16 @@ class UsersPage extends AppTable {
36820
36886
  target.department = p.department?.asObject();
36821
36887
  return target;
36822
36888
  });
36889
+ const recipientFilter = PersonFilter.fromObject(this.filter);
36890
+ const canRecipientFilter = !recipientFilter.isEmpty() && (this.accountService.isAdmin() || this.accountService.isSupervisor());
36823
36891
  return this.messageService.openComposeModal({
36824
36892
  suggestFn: (value, filter, sortBy, sortDirection) => this.dataService.suggest(value, filter, sortBy, sortDirection),
36825
- data: {
36893
+ canRecipientFilter,
36894
+ recipientFilterCount: this.totalRowCount,
36895
+ data: Message.fromObject({
36826
36896
  recipients,
36827
- },
36897
+ recipientFilter,
36898
+ }),
36828
36899
  });
36829
36900
  }
36830
36901
  /* -- protected methods -- */