This commit is contained in:
Sercan Yemen 2017-07-28 16:03:41 +03:00
commit be8195663e
10 changed files with 175 additions and 163 deletions

87
src/app/core/fuseUtils.ts Normal file
View File

@ -0,0 +1,87 @@
export class FuseUtils
{
public static filterArrayByString(mainArr, searchText)
{
if ( searchText === '' )
{
return mainArr;
}
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;
}
}

View File

@ -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));
} }
} }

View File

@ -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-->

View File

@ -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,

View File

@ -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>

View File

@ -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,21 @@ export class MailComponent implements OnInit, OnDestroy
folders: any[]; folders: any[];
filters: any[]; filters: any[];
labels: any[]; labels: any[];
searchInput: FormControl;
onSelectedMailsChanged: Subscription; onSelectedMailsChanged: Subscription;
onFoldersChanged: Subscription; onFoldersChanged: Subscription;
onFiltersChanged: Subscription; onFiltersChanged: Subscription;
onLabelsChanged: Subscription; onLabelsChanged: Subscription;
constructor( constructor(private mailService: MailService)
private mailService: MailService
)
{ {
this.searchInput = new FormControl('');
} }
ngOnInit() ngOnInit()
{ {
this.onSelectedMailsChanged = this.onSelectedMailsChanged =
this.mailService.onSelectedMailsChanged this.mailService.onSelectedMailsChanged
.subscribe(selectedMails => { .subscribe(selectedMails => {
@ -55,6 +58,14 @@ 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 => {
this.mailService.onSearchTextChanged.next(searchText);
});
} }
ngOnDestroy() ngOnDestroy()

View File

@ -4,6 +4,7 @@ import { Observable } from 'rxjs/Observable';
import { Http } from '@angular/http'; import { Http } from '@angular/http';
import { Mail } from './mail.model'; import { Mail } from './mail.model';
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { FuseUtils } from "app/core/fuseUtils";
@Injectable() @Injectable()
export class MailService implements Resolve<any> export class MailService implements Resolve<any>
@ -11,6 +12,7 @@ export class MailService implements Resolve<any>
mails: Mail[]; mails: Mail[];
selectedMails: Mail[]; selectedMails: Mail[];
currentMail: Mail; currentMail: Mail;
searchText = '';
folders: any[]; folders: any[];
filters: any[]; filters: any[];
@ -24,10 +26,9 @@ export class MailService implements Resolve<any>
onFoldersChanged: BehaviorSubject<any> = new BehaviorSubject([]); onFoldersChanged: BehaviorSubject<any> = new BehaviorSubject([]);
onFiltersChanged: BehaviorSubject<any> = new BehaviorSubject([]); onFiltersChanged: BehaviorSubject<any> = new BehaviorSubject([]);
onLabelsChanged: BehaviorSubject<any> = new BehaviorSubject([]); onLabelsChanged: BehaviorSubject<any> = new BehaviorSubject([]);
onSearchTextChanged: BehaviorSubject<any> = new BehaviorSubject('');
constructor( constructor(private http: Http)
private http: Http
)
{ {
this.selectedMails = []; this.selectedMails = [];
} }
@ -59,6 +60,19 @@ export class MailService implements Resolve<any>
this.setCurrentMail(null); this.setCurrentMail(null);
} }
this.onSearchTextChanged.subscribe(searchText => {
if ( searchText !== '' )
{
this.searchText = searchText;
this.getMails();
}
else
{
this.searchText = searchText;
this.getMails();
}
});
resolve(); resolve();
}, },
reject reject
@ -154,6 +168,8 @@ export class MailService implements Resolve<any>
return new Mail(mail); return new Mail(mail);
}); });
this.mails = FuseUtils.filterArrayByString(this.mails, this.searchText);
this.onMailsChanged.next(this.mails); this.onMailsChanged.next(this.mails);
resolve(this.mails); resolve(this.mails);
@ -179,6 +195,8 @@ export class MailService implements Resolve<any>
return new Mail(mail); return new Mail(mail);
}); });
this.mails = FuseUtils.filterArrayByString(this.mails, this.searchText);
this.onMailsChanged.next(this.mails); this.onMailsChanged.next(this.mails);
resolve(this.mails); resolve(this.mails);
@ -207,6 +225,8 @@ export class MailService implements Resolve<any>
return new Mail(mail); return new Mail(mail);
}); });
this.mails = FuseUtils.filterArrayByString(this.mails, this.searchText);
this.onMailsChanged.next(this.mails); this.onMailsChanged.next(this.mails);
resolve(this.mails); resolve(this.mails);

View File

@ -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>

View File

@ -1,6 +1,8 @@
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';
@Component({ @Component({
selector : 'fuse-todo', selector : 'fuse-todo',
@ -13,6 +15,7 @@ export class TodoComponent implements OnInit, OnDestroy
isIndeterminate: boolean; isIndeterminate: boolean;
filters: any[]; filters: any[];
tags: any[]; tags: any[];
searchInput: FormControl;
onSelectedTodosChanged: Subscription; onSelectedTodosChanged: Subscription;
onFiltersChanged: Subscription; onFiltersChanged: Subscription;
@ -20,10 +23,12 @@ export class TodoComponent implements OnInit, OnDestroy
constructor(private todoService: TodoService) constructor(private todoService: TodoService)
{ {
this.searchInput = new FormControl('');
} }
ngOnInit() ngOnInit()
{ {
this.onSelectedTodosChanged = this.onSelectedTodosChanged =
this.todoService.onSelectedTodosChanged this.todoService.onSelectedTodosChanged
.subscribe(selectedTodos => { .subscribe(selectedTodos => {
@ -45,6 +50,13 @@ 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 => {
this.todoService.onSearchTextChanged.next(searchText);
});
} }
ngOnDestroy() ngOnDestroy()

View File

@ -4,6 +4,8 @@ import { Observable } from 'rxjs/Observable';
import { Http } from '@angular/http'; import { Http } from '@angular/http';
import { Todo } from './todo.model'; import { Todo } from './todo.model';
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subscription } from 'rxjs/Subscription';
import { FuseUtils } from '../../../core/fuseUtils';
@Injectable() @Injectable()
export class TodoService implements Resolve<any> export class TodoService implements Resolve<any>
@ -11,6 +13,7 @@ export class TodoService implements Resolve<any>
todos: Todo[]; todos: Todo[];
selectedTodos: Todo[]; selectedTodos: Todo[];
currentTodo: Todo; currentTodo: Todo;
searchText = '';
filters: any[]; filters: any[];
tags: any[]; tags: any[];
@ -22,6 +25,7 @@ export class TodoService implements Resolve<any>
onFiltersChanged: BehaviorSubject<any> = new BehaviorSubject([]); onFiltersChanged: BehaviorSubject<any> = new BehaviorSubject([]);
onTagsChanged: BehaviorSubject<any> = new BehaviorSubject([]); onTagsChanged: BehaviorSubject<any> = new BehaviorSubject([]);
onSearchTextChanged: BehaviorSubject<any> = new BehaviorSubject('');
constructor(private http: Http) constructor(private http: Http)
{ {
@ -55,6 +59,18 @@ export class TodoService implements Resolve<any>
this.setCurrentTodo(null); this.setCurrentTodo(null);
} }
this.onSearchTextChanged.subscribe(searchText => {
if ( searchText !== '' )
{
this.searchText = searchText;
this.getTodos();
}
else
{
this.searchText = searchText;
this.getTodos();
}
});
resolve(); resolve();
}, },
reject reject
@ -129,6 +145,8 @@ export class TodoService implements Resolve<any>
return new Todo(todo); return new Todo(todo);
}); });
this.todos = FuseUtils.filterArrayByString(this.todos, this.searchText);
this.onTodosChanged.next(this.todos); this.onTodosChanged.next(this.todos);
resolve(this.todos); resolve(this.todos);
@ -160,6 +178,8 @@ export class TodoService implements Resolve<any>
return new Todo(todo); return new Todo(todo);
}); });
this.todos = FuseUtils.filterArrayByString(this.todos, this.searchText);
this.onTodosChanged.next(this.todos); this.onTodosChanged.next(this.todos);
resolve(this.todos); resolve(this.todos);
@ -188,6 +208,8 @@ export class TodoService implements Resolve<any>
return new Todo(todo); return new Todo(todo);
}); });
this.todos = FuseUtils.filterArrayByString(this.todos, this.searchText);
this.onTodosChanged.next(this.todos); this.onTodosChanged.next(this.todos);
resolve(this.todos); resolve(this.todos);