mirror of
				https://github.com/richard-loafle/fuse-angular.git
				synced 2025-10-31 01:53:34 +00:00 
			
		
		
		
	Filter Pipe updated,
FuseUtils added, Filtering applied for mail, todo, chat app.
This commit is contained in:
		
							parent
							
								
									0b3a7ef919
								
							
						
					
					
						commit
						2d459864f1
					
				
							
								
								
									
										82
									
								
								src/app/core/fuseUtils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/app/core/fuseUtils.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | |||||||
|  | export class FuseUtils | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |     public static filterArrayByString(mainArr, searchText) | ||||||
|  |     { | ||||||
|  |         searchText = searchText.toLowerCase(); | ||||||
|  | 
 | ||||||
|  |         return mainArr.filter(itemObj => { | ||||||
|  |             return this.searchInObj(itemObj, searchText); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static searchInObj(itemObj, searchText) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         for ( const prop in itemObj ) | ||||||
|  |         { | ||||||
|  |             if ( !itemObj.hasOwnProperty(prop) ) | ||||||
|  |             { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             const value = itemObj[prop]; | ||||||
|  | 
 | ||||||
|  |             if ( typeof value === 'string' ) | ||||||
|  |             { | ||||||
|  |                 if ( this.searchInSting(value, searchText) ) | ||||||
|  |                 { | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             else if ( Array.isArray(value) ) | ||||||
|  |             { | ||||||
|  |                 if ( this.searchInArray(value, searchText) ) | ||||||
|  |                 { | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if ( typeof value === 'object' ) | ||||||
|  |             { | ||||||
|  |                 if ( this.searchInObj(value, searchText) ) | ||||||
|  |                 { | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static searchInArray(arr, searchText) | ||||||
|  |     { | ||||||
|  |         for ( const value of arr ) | ||||||
|  |         { | ||||||
|  |             if ( typeof value === 'string' ) | ||||||
|  |             { | ||||||
|  |                 if ( this.searchInSting(value, searchText) ) | ||||||
|  |                 { | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if ( typeof value === 'object' ) | ||||||
|  |             { | ||||||
|  |                 if ( this.searchInObj(value, searchText) ) | ||||||
|  |                 { | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static searchInSting(value, searchText) | ||||||
|  |     { | ||||||
|  |         if ( value.toLowerCase().includes(searchText) ) | ||||||
|  |         { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,152 +1,11 @@ | |||||||
| /** | import { Pipe, PipeTransform } from '@angular/core'; | ||||||
|  * Created by vadimdez on 28/06/16. | import { FuseUtils } from '../fuseUtils'; | ||||||
|  */ |  | ||||||
| import { Pipe, Injectable } from '@angular/core'; |  | ||||||
| 
 | 
 | ||||||
| @Pipe({ | @Pipe({name: 'filter'}) | ||||||
|     name: 'filterBy', | export class FilterPipe implements PipeTransform | ||||||
|     pure: false | { | ||||||
| }) |     transform(mainArr: any[], searchText: string, property: string): any | ||||||
| 
 |     { | ||||||
| @Injectable() |         return FuseUtils.filterArrayByString(mainArr, searchText); | ||||||
| export class FilterPipe { |  | ||||||
| 
 |  | ||||||
|     private filterByString(filter) { |  | ||||||
|         if (filter) { |  | ||||||
|             filter = filter.toLowerCase(); |  | ||||||
|         } |  | ||||||
|         return value => { |  | ||||||
|             return !filter || (value ? ('' + value).toLowerCase().indexOf(filter) !== -1 : false); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private filterByBoolean(filter) { |  | ||||||
|         return value => { |  | ||||||
|             return Boolean(value) === filter; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private filterByObject(filter) { |  | ||||||
|         return value => { |  | ||||||
|             for (let key in filter) { |  | ||||||
| 
 |  | ||||||
|                 if (key === '$or') { |  | ||||||
|                     if (!this.filterByOr(filter.$or)(this.getValue(value))) { |  | ||||||
|                         return false; |  | ||||||
|                     } |  | ||||||
|                     continue; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 if (!value.hasOwnProperty(key) && !Object.getOwnPropertyDescriptor(Object.getPrototypeOf(value), key)) { |  | ||||||
|                     return false; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 let val = this.getValue(value[key]); |  | ||||||
|                 const filterType = typeof filter[key]; |  | ||||||
|                 let isMatching; |  | ||||||
| 
 |  | ||||||
|                 if (filterType === 'boolean') { |  | ||||||
|                     isMatching = this.filterByBoolean(filter[key])(val); |  | ||||||
|                 } else if (filterType === 'string') { |  | ||||||
|                     isMatching = this.filterByString(filter[key])(val); |  | ||||||
|                 } else if (filterType === 'object') { |  | ||||||
|                     isMatching = this.filterByObject(filter[key])(val); |  | ||||||
|                 } else { |  | ||||||
|                     isMatching = this.filterDefault(filter[key])(val); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 if (!isMatching) { |  | ||||||
|                     return false; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return true; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Filter value by $or |  | ||||||
|      * |  | ||||||
|      * @param filter |  | ||||||
|      * @returns {(value:any)=>boolean} |  | ||||||
|      */ |  | ||||||
|     private filterByOr(filter: any[]) { |  | ||||||
|         return (value: any) => { |  | ||||||
|             let hasMatch = false; |  | ||||||
|             const length = filter.length; |  | ||||||
|             const isArray = value instanceof Array; |  | ||||||
| 
 |  | ||||||
|             const arrayComparison = (i) => { |  | ||||||
|                 return value.indexOf(filter[i]) !== -1; |  | ||||||
|             }; |  | ||||||
|             const otherComparison = (i) => { |  | ||||||
|                 return value === filter[i]; |  | ||||||
|             }; |  | ||||||
|             const comparison = isArray ? arrayComparison : otherComparison; |  | ||||||
| 
 |  | ||||||
|             for (let i = 0; i < length; i++) { |  | ||||||
|                 if (comparison(i)) { |  | ||||||
|                     hasMatch = true; |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return hasMatch; |  | ||||||
|         }; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Checks function's value if type is function otherwise same value |  | ||||||
|      * @param value |  | ||||||
|      * @returns {any} |  | ||||||
|      */ |  | ||||||
|     private getValue(value: any) { |  | ||||||
|         return typeof value === 'function' ? value() : value; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Defatul filterDefault function |  | ||||||
|      * |  | ||||||
|      * @param filter |  | ||||||
|      * @returns {(value:any)=>boolean} |  | ||||||
|      */ |  | ||||||
|     private filterDefault(filter) { |  | ||||||
|         return value => { |  | ||||||
|             return filter === undefined || filter == value; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private isNumber(value) { |  | ||||||
|         return !isNaN(parseInt(value, 10)) && isFinite(value); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     transform(array: any[], filter: any): any { |  | ||||||
|         const type = typeof filter; |  | ||||||
| 
 |  | ||||||
|         if (!array) { |  | ||||||
|             return array; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (type === 'boolean') { |  | ||||||
|             return array.filter(this.filterByBoolean(filter)); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (type === 'string') { |  | ||||||
|             if (this.isNumber(filter)) { |  | ||||||
|                 return array.filter(this.filterDefault(filter)); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return array.filter(this.filterByString(filter)); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (type === 'object') { |  | ||||||
|             return array.filter(this.filterByObject(filter)); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (type === 'function') { |  | ||||||
|             return array.filter(filter); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return array.filter(this.filterDefault(filter)); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -82,7 +82,7 @@ | |||||||
| 
 | 
 | ||||||
|                     <md-icon>search</md-icon> |                     <md-icon>search</md-icon> | ||||||
| 
 | 
 | ||||||
|                     <input [(ngModel)]="chatSearch.name" type="text" placeholder="Search or start new chat" fxFlex> |                     <input [(ngModel)]="searchText" type="text" placeholder="Search or start new chat" fxFlex> | ||||||
| 
 | 
 | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
| @ -106,12 +106,12 @@ | |||||||
|         <!-- CHATS LIST--> |         <!-- CHATS LIST--> | ||||||
|         <div class="chat-list" fxLayout="column"> |         <div class="chat-list" fxLayout="column"> | ||||||
| 
 | 
 | ||||||
|             <div md-subheader *ngIf="(user.chatList | filterBy: chatSearch).length > 0"> |             <div md-subheader *ngIf="(user.chatList | filter: searchText).length > 0"> | ||||||
|                 Chats |                 Chats | ||||||
|             </div> |             </div> | ||||||
| 
 | 
 | ||||||
|             <button md-button class="contact" |             <button md-button class="contact" | ||||||
|                     *ngFor="let chat of user.chatList | filterBy: chatSearch" |                     *ngFor="let chat of user.chatList | filter: searchText" | ||||||
|                     (click)="getChat(chat.contactId)" ngClass="{'unread':contact.unread}"> |                     (click)="getChat(chat.contactId)" ngClass="{'unread':contact.unread}"> | ||||||
| 
 | 
 | ||||||
|                 <div fxLayout="row" fxLayoutAlign="start center"> |                 <div fxLayout="row" fxLayoutAlign="start center"> | ||||||
| @ -146,13 +146,13 @@ | |||||||
|         <!-- CONTACTS LIST--> |         <!-- CONTACTS LIST--> | ||||||
|         <div class="contact-list" fxLayout="column"> |         <div class="contact-list" fxLayout="column"> | ||||||
| 
 | 
 | ||||||
|             <div md-subheader *ngIf="(contacts| filterBy: chatSearch).length > 0"> |             <div md-subheader *ngIf="(contacts| filter: searchText).length > 0"> | ||||||
|                 Contacts |                 Contacts | ||||||
|             </div> |             </div> | ||||||
| 
 | 
 | ||||||
|             <button md-button class="contact" |             <button md-button class="contact" | ||||||
|                     ng-show="chatSearch" |                     ng-show="chatSearch" | ||||||
|                     *ngFor="let contact of contacts| filterBy: chatSearch" |                     *ngFor="let contact of contacts| filter: searchText" | ||||||
|                     (click)="getChat(contact.id)"> |                     (click)="getChat(contact.id)"> | ||||||
| 
 | 
 | ||||||
|                 <div fxLayout="row" fxLayoutAlign="start center"> |                 <div fxLayout="row" fxLayoutAlign="start center"> | ||||||
| @ -171,7 +171,7 @@ | |||||||
|         <!-- / CONTACTS LIST--> |         <!-- / CONTACTS LIST--> | ||||||
| 
 | 
 | ||||||
|         <!-- NO RESULTS MESSAGE --> |         <!-- NO RESULTS MESSAGE --> | ||||||
|         <div *ngIf="(contacts| filterBy: chatSearch).length === 0" class="no-results-message"> |         <div *ngIf="(contacts| filter: searchText).length === 0" class="no-results-message"> | ||||||
|             No results.. |             No results.. | ||||||
|         </div> |         </div> | ||||||
|         <!-- NO RESULTS MESSAGE--> |         <!-- NO RESULTS MESSAGE--> | ||||||
|  | |||||||
| @ -14,6 +14,7 @@ export class ChatsSidenavComponent implements OnInit | |||||||
|     chats: any[]; |     chats: any[]; | ||||||
|     contacts: any[]; |     contacts: any[]; | ||||||
|     chatSearch: any; |     chatSearch: any; | ||||||
|  |     searchText = ''; | ||||||
| 
 | 
 | ||||||
|     constructor(private chatService: ChatService, |     constructor(private chatService: ChatService, | ||||||
|                 private fuseMdSidenavService: FuseMdSidenavHelperService, |                 private fuseMdSidenavService: FuseMdSidenavHelperService, | ||||||
|  | |||||||
| @ -29,7 +29,7 @@ | |||||||
| 
 | 
 | ||||||
|                     <div class="search" flex fxLayout="row" fxLayoutAlign="start center"> |                     <div class="search" flex fxLayout="row" fxLayoutAlign="start center"> | ||||||
|                         <md-icon>search</md-icon> |                         <md-icon>search</md-icon> | ||||||
|                         <input fxFlex type="text" placeholder="Search for an e-mail or contact"> |                         <input [formControl]="searchInput" placeholder="Search for an e-mail or contact" fxFlex> | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,8 @@ | |||||||
| import { Component, OnDestroy, OnInit } from '@angular/core'; | import { Component, OnDestroy, OnInit } from '@angular/core'; | ||||||
| import { MailService } from './mail.service'; | import { MailService } from './mail.service'; | ||||||
| import { Subscription } from 'rxjs/Subscription'; | import { Subscription } from 'rxjs/Subscription'; | ||||||
|  | import { FormControl } from '@angular/forms'; | ||||||
|  | import { FuseUtils } from '../../../core/fuseUtils'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|     selector   : 'fuse-mail', |     selector   : 'fuse-mail', | ||||||
| @ -14,20 +16,30 @@ export class MailComponent implements OnInit, OnDestroy | |||||||
|     folders: any[]; |     folders: any[]; | ||||||
|     filters: any[]; |     filters: any[]; | ||||||
|     labels: any[]; |     labels: any[]; | ||||||
|  |     mails: any[]; | ||||||
|  |     searchInput: FormControl; | ||||||
| 
 | 
 | ||||||
|     onSelectedMailsChanged: Subscription; |     onSelectedMailsChanged: Subscription; | ||||||
|     onFoldersChanged: Subscription; |     onFoldersChanged: Subscription; | ||||||
|     onFiltersChanged: Subscription; |     onFiltersChanged: Subscription; | ||||||
|     onLabelsChanged: Subscription; |     onLabelsChanged: Subscription; | ||||||
|  |     onMailsChanged: Subscription; | ||||||
| 
 | 
 | ||||||
|     constructor( | 
 | ||||||
|         private mailService: MailService |     constructor(private mailService: MailService) | ||||||
|     ) |  | ||||||
|     { |     { | ||||||
|  |         this.searchInput = new FormControl(''); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ngOnInit() |     ngOnInit() | ||||||
|     { |     { | ||||||
|  |         // Subscribe to update mails on changes
 | ||||||
|  |         this.onMailsChanged = | ||||||
|  |             this.mailService.onMailsChanged | ||||||
|  |                 .subscribe(mails => { | ||||||
|  |                     this.mails = mails; | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|         this.onSelectedMailsChanged = |         this.onSelectedMailsChanged = | ||||||
|             this.mailService.onSelectedMailsChanged |             this.mailService.onSelectedMailsChanged | ||||||
|                 .subscribe(selectedMails => { |                 .subscribe(selectedMails => { | ||||||
| @ -55,6 +67,22 @@ export class MailComponent implements OnInit, OnDestroy | |||||||
|                 .subscribe(labels => { |                 .subscribe(labels => { | ||||||
|                     this.labels = this.mailService.labels; |                     this.labels = this.mailService.labels; | ||||||
|                 }); |                 }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         this.searchInput.valueChanges | ||||||
|  |             .debounceTime(300) | ||||||
|  |             .distinctUntilChanged() | ||||||
|  |             .subscribe(searchText => { | ||||||
|  |                 if ( searchText !== '' ) | ||||||
|  |                 { | ||||||
|  |                     const newArr = FuseUtils.filterArrayByString(this.mails, searchText); | ||||||
|  |                     this.mailService.onMailsChanged.next(newArr); | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     this.mailService.getMails(); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ngOnDestroy() |     ngOnDestroy() | ||||||
|  | |||||||
| @ -29,7 +29,7 @@ | |||||||
| 
 | 
 | ||||||
|                     <div class="search" flex fxLayout="row" fxLayoutAlign="start center"> |                     <div class="search" flex fxLayout="row" fxLayoutAlign="start center"> | ||||||
|                         <md-icon>search</md-icon> |                         <md-icon>search</md-icon> | ||||||
|                         <input fxFlex type="text" placeholder="Search for an todo"> |                         <input [formControl]="searchInput" placeholder="Search for an todo" fxFlex> | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,9 @@ | |||||||
| import { Component, OnDestroy, OnInit } from '@angular/core'; | import { Component, OnDestroy, OnInit } from '@angular/core'; | ||||||
| import { Subscription } from 'rxjs/Subscription'; | import { Subscription } from 'rxjs/Subscription'; | ||||||
| import { TodoService } from './todo.service'; | import { TodoService } from './todo.service'; | ||||||
|  | import { FormControl } from '@angular/forms'; | ||||||
|  | import { Todo } from './todo.model'; | ||||||
|  | import { FuseUtils } from '../../../core/fuseUtils'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|     selector   : 'fuse-todo', |     selector   : 'fuse-todo', | ||||||
| @ -11,19 +14,30 @@ export class TodoComponent implements OnInit, OnDestroy | |||||||
| { | { | ||||||
|     hasSelectedTodos: boolean; |     hasSelectedTodos: boolean; | ||||||
|     isIndeterminate: boolean; |     isIndeterminate: boolean; | ||||||
|  |     todos: Todo[]; | ||||||
|     filters: any[]; |     filters: any[]; | ||||||
|     tags: any[]; |     tags: any[]; | ||||||
|  |     searchInput: FormControl; | ||||||
| 
 | 
 | ||||||
|  |     onTodosChanged: Subscription; | ||||||
|     onSelectedTodosChanged: Subscription; |     onSelectedTodosChanged: Subscription; | ||||||
|     onFiltersChanged: Subscription; |     onFiltersChanged: Subscription; | ||||||
|     onTagsChanged: Subscription; |     onTagsChanged: Subscription; | ||||||
| 
 | 
 | ||||||
|     constructor(private todoService: TodoService) |     constructor(private todoService: TodoService) | ||||||
|     { |     { | ||||||
|  |         this.searchInput = new FormControl(''); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ngOnInit() |     ngOnInit() | ||||||
|     { |     { | ||||||
|  |         // Subscribe to update todos on changes
 | ||||||
|  |         this.onTodosChanged = | ||||||
|  |             this.todoService.onTodosChanged | ||||||
|  |                 .subscribe(todos => { | ||||||
|  |                     this.todos = todos; | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|         this.onSelectedTodosChanged = |         this.onSelectedTodosChanged = | ||||||
|             this.todoService.onSelectedTodosChanged |             this.todoService.onSelectedTodosChanged | ||||||
|                 .subscribe(selectedTodos => { |                 .subscribe(selectedTodos => { | ||||||
| @ -45,6 +59,21 @@ export class TodoComponent implements OnInit, OnDestroy | |||||||
|                 .subscribe(tags => { |                 .subscribe(tags => { | ||||||
|                     this.tags = this.todoService.tags; |                     this.tags = this.todoService.tags; | ||||||
|                 }); |                 }); | ||||||
|  | 
 | ||||||
|  |         this.searchInput.valueChanges | ||||||
|  |             .debounceTime(300) | ||||||
|  |             .distinctUntilChanged() | ||||||
|  |             .subscribe(searchText => { | ||||||
|  |                 if ( searchText !== '' ) | ||||||
|  |                 { | ||||||
|  |                     const newArr = FuseUtils.filterArrayByString(this.todos, searchText); | ||||||
|  |                     this.todoService.onTodosChanged.next(newArr); | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     this.todoService.getTodos(); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ngOnDestroy() |     ngOnDestroy() | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user