Broker System for Supercredit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

227 lines
6.8KB

  1. import {Component, forwardRef, Input, OnInit, ViewChild} from '@angular/core';
  2. import {AuthService} from '../service/auth.service';
  3. import { debounce } from 'ts-debounce';
  4. import {PeopleModel} from '../models/people.model';
  5. import {ControlValueAccessor, FormControl, FormGroup, NG_VALUE_ACCESSOR} from '@angular/forms';
  6. import {MultiColumnComboBoxComponent} from '@progress/kendo-angular-dropdowns';
  7. import {Observable} from 'rxjs';
  8. import {PeopleService} from '../service/people.service';
  9. @Component({
  10. selector: 'app-people-select',
  11. templateUrl: './people-select.component.html',
  12. styleUrls: ['./people-select.component.scss'],
  13. providers: [
  14. {
  15. provide: NG_VALUE_ACCESSOR,
  16. useExisting: forwardRef(() => PeopleSelectComponent),
  17. multi: true
  18. }
  19. ]
  20. })
  21. export class PeopleSelectComponent implements OnInit, ControlValueAccessor {
  22. @Input() disabled = false;
  23. @Input() translateId: true; // always tralsnate user Id, because name is not unique
  24. @Input() width: number;
  25. @Input() initSearch: PeopleModel[];
  26. @Input() formControl: FormControl = new FormControl(); // this is a dummy place holder
  27. @ViewChild('list', {static: true}) public text: MultiColumnComboBoxComponent;
  28. public searchResult: PeopleModel[] = [];
  29. public value = ''; // selecting the default and only empty contact element // TODO: remove ngModel
  30. public total = 0;
  31. private debounceFilter: any ;
  32. // Function to call when the rating changes.
  33. private onChange = ( nameOrId: string) => {};
  34. // Function to call when the input is touched (when a star is clicked).
  35. private onTouched = () => {};
  36. constructor(private auth: AuthService, private ps: PeopleService) { }
  37. ngOnInit(): void {
  38. this.prepareSearchPeople();
  39. this.initSearchResult();
  40. }
  41. private initSearchResult(): void {
  42. this.initSearch.forEach( v => {
  43. this.searchResult.push(v);
  44. });
  45. this.total = this.initSearch.length;
  46. }
  47. private prepareSearchPeople(): void{
  48. this.debounceFilter = debounce( (filter: string): void => {
  49. this.ps.getPeopleList(filter).subscribe(
  50. resp => {
  51. this.text.loading = false;
  52. this.searchResult = resp.List;
  53. this.total = resp.Count;
  54. },
  55. error => { this.text.loading = false; },
  56. () => { this.text.loading = false; }
  57. );
  58. }, 500) ;
  59. }
  60. getEffectiveField(): string {
  61. return this.translateId ? 'Id' : 'Display';
  62. }
  63. filterChange(filter: string): void {
  64. if ( filter.length > 0 ) {
  65. this.text.loading = true;
  66. this.debounceFilter(filter); // conduct search even if filter is empty
  67. }
  68. }
  69. public getContactImageUrl(contactId: string): string {
  70. return this.auth.getUrl('avatar/' + contactId);
  71. }
  72. // ComboBox emit event on value change
  73. public valueChange(str: string): void {
  74. return;
  75. console.log('value change', str);
  76. this.onChange(this.value);
  77. }
  78. // public selectionChange(value: PeopleModel): void {
  79. // this.onTouched();
  80. // console.log('selectionChange', value);
  81. // this.value = this.translateId ? value.Id : value.FullName;
  82. // this.onChange(this.value);
  83. // }
  84. // public open(): void {
  85. // this.onTouched();
  86. // // console.log('open', this.text);
  87. // }
  88. //
  89. // public close(): void {
  90. // this.onTouched();
  91. // // console.log('close', this.text);
  92. // }
  93. //
  94. // public focus(): void {
  95. // this.onTouched();
  96. // // console.log('focus', this.text);
  97. // }
  98. //
  99. // public blur(): void {
  100. // // console.log('blur', this.text);
  101. // }
  102. // Allows Angular to update the model (name or ID).
  103. // Update the model and changes needed for the view here.
  104. writeValue(nameOrId: string): void {
  105. if ( nameOrId === undefined ){
  106. console.log('who called me for write', this);
  107. return;
  108. }
  109. const changed = nameOrId !== this.value;
  110. if (this.needSearch(nameOrId) ){
  111. this.text.loading = true;
  112. console.log('searching ... ', nameOrId, this.translateId ? 'by id' : 'by name');
  113. this.searchUser(nameOrId, this.translateId).subscribe(
  114. ppl => {
  115. const person = new PeopleModel(ppl);
  116. console.log('got search result ', person);
  117. this.searchResult.push(person); // make sure it's available for selection, thus proper display
  118. this.value = this.translateId ? person.Id : person.FullName;
  119. console.log('before update', this.text.value);
  120. this.text.value = this.value;
  121. console.log('after update', this.text.value);
  122. }, error => { console.error(error); this.text.loading = false; },
  123. () => {this.text.loading = false; }
  124. );
  125. if ( changed ) {
  126. this.onChange(nameOrId);
  127. }
  128. }
  129. }
  130. needSearch(incoming: string ): boolean {
  131. if ( incoming === undefined || incoming === '' || incoming === this.value ) {
  132. return false;
  133. }
  134. const idx = this.searchResult.findIndex( person => {
  135. if ( this.translateId) {
  136. return person.Id === incoming;
  137. }else{
  138. return person.FullName.includes(incoming);
  139. }
  140. });
  141. return idx === -1; // not found need search
  142. }
  143. // Search a user either based on partial name or a complete ID
  144. searchUser(nameOrId: string, translateId: boolean): Observable<PeopleModel>{
  145. if ( translateId ) {
  146. return this.ps.getPeopleById(nameOrId);
  147. // return this.searchPersonById( nameOrId) ;
  148. }else{
  149. // return this.ps.searchById(nameOrId);
  150. // return this.searchPersonByName(nameOrId) ;
  151. }
  152. }
  153. // searchPersonByName(name: string): Observable<PeopleModel>{
  154. // return new Observable ( observer => {
  155. // const dummy: PeopleModel = new PeopleModel(
  156. // 'dummy-id',
  157. // 'FSearch',
  158. // 'LResult',
  159. // '',
  160. // 'Mr.',
  161. // 'Display Name',
  162. // 'Nick Name'
  163. // );
  164. // setTimeout(() => {
  165. // observer.next(dummy);
  166. // observer.complete();
  167. // }, 1000);
  168. // });
  169. // }
  170. //
  171. // searchPersonById( id: string): Observable<PeopleModel> {
  172. // return new Observable ( observer => {
  173. // const dummy: PeopleModel = new PeopleModel(
  174. // id,
  175. // 'FSearch',
  176. // 'LResult',
  177. // '',
  178. // 'Mr.',
  179. // 'P:' + id,
  180. // 'Nick Name'
  181. // );
  182. // setTimeout(() => {
  183. // observer.next(dummy);
  184. // observer.complete();
  185. // }, 1000);
  186. // });
  187. // }
  188. // Allows Angular to register a function to call when the model (rating) changes.
  189. // Save the function as a property to call later here.
  190. registerOnChange(fn: (nameOrId: string) => void): void {
  191. this.onChange = fn;
  192. }
  193. // Allows Angular to register a function to call when the input has been touched.
  194. // Save the function as a property to call later here.
  195. registerOnTouched(fn: () => void): void {
  196. this.onTouched = fn;
  197. }
  198. // Allows Angular to disable the input.
  199. setDisabledState(isDisabled: boolean): void {
  200. this.disabled = isDisabled;
  201. }
  202. }