mirror of
https://github.com/richard-loafle/fuse-angular.git
synced 2025-01-10 04:25:08 +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…
Reference in New Issue
Block a user