This commit is contained in:
Sercan Yemen 2017-07-20 18:12:09 +03:00
parent b9569a5ba8
commit b0e4f87a8a
21 changed files with 557 additions and 297 deletions

View File

@ -3,10 +3,10 @@ import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'getById'})
export class GetByIdPipe implements PipeTransform
{
transform(value: any[], id: number, property: string ): any
transform(value: any[], id: number, property: string): any
{
const foundItem = value.find(item => {
if ( item.id )
if ( item.id !== undefined )
{
return item.id === id;
}

View File

@ -3,21 +3,18 @@ import { NgModule } from '@angular/core';
import { KeysPipe } from './keys.pipe';
import { GetByIdPipe } from './getById.pipe';
import { HtmlToPlaintextPipe } from './htmlToPlaintext.pipe';
import { SearchPipe } from './search.pipe';
@NgModule({
declarations: [
KeysPipe,
GetByIdPipe,
HtmlToPlaintextPipe,
SearchPipe
HtmlToPlaintextPipe
],
imports : [],
exports : [
KeysPipe,
GetByIdPipe,
HtmlToPlaintextPipe,
SearchPipe
HtmlToPlaintextPipe
]
})

View File

@ -1,49 +0,0 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'filter'
})
export class SearchPipe implements PipeTransform
{
transform(items: any, term: string): any
{
if ( term === undefined )
{
return items;
}
return this.filter(items, term);
}
filter(items: any, term: string)
{
return items.filter(item => {
for ( const property in item )
{
if ( !item.hasOwnProperty(property) || !item[property] )
{
console.log('continueing...');
continue;
}
if ( Array.isArray(item[property]) )
{
console.log('is Array');
return this.filter(item[property], term);
}
if ( item[property].toString().toLowerCase().includes(term.toLowerCase()) )
{
console.log('found!');
return true;
}
}
return false;
}
);
}
}

View File

@ -1,13 +1,14 @@
import {InMemoryDbService} from 'angular-in-memory-web-api';
import {MailFakeDb} from './mail';
import { InMemoryDbService } from 'angular-in-memory-web-api';
import { MailFakeDb } from './mail';
export class FuseFakeDbService implements InMemoryDbService
{
createDb()
{
return {
'mail-mails' : MailFakeDb.mails,
'mail-mails' : MailFakeDb.mails,
'mail-folders': MailFakeDb.folders,
'mail-filters': MailFakeDb.filters,
'mail-labels' : MailFakeDb.labels
};
}

View File

@ -47,11 +47,7 @@ export class MailFakeDb
'labels' : [
1
],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '154588a0864d2881124',
@ -74,11 +70,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '15453ba60d3baa5daaf',
@ -104,11 +96,7 @@ export class MailFakeDb
3,
2
],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '15453a06c08fb021776',
@ -134,11 +122,7 @@ export class MailFakeDb
3,
4
],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '154537435d5b32bf11a',
@ -161,11 +145,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '1544e43dcdae6ebf876',
@ -190,11 +170,7 @@ export class MailFakeDb
'labels' : [
2
],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '1543ee3a5b43e0f9f45',
@ -217,11 +193,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '1543cc4515df3146112',
@ -244,11 +216,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '154398a4770d7aaf9a2',
@ -271,11 +239,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '15438351f87dcd68567',
@ -298,11 +262,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '1542d75d929a603125',
@ -325,11 +285,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '1541ca7af66da284177',
@ -352,11 +308,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '154297167e781781745',
@ -379,11 +331,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
0,
1,
2
]
'folder' : 0
},
{
'id' : '15427f4c1b7f3953234',
@ -406,9 +354,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
3
]
'folder' : 3
},
{
'id' : '154204e45a59b168453',
@ -431,9 +377,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
3
]
'folder' : 3
},
{
'id' : '1541dd1e05dfc439216',
@ -456,9 +400,7 @@ export class MailFakeDb
'important' : false,
'hasAttachments': false,
'labels' : [],
'folders' : [
3
]
'folder' : 3
}
];
@ -492,15 +434,18 @@ export class MailFakeDb
'handle': 'trash',
'title' : 'Trash',
'icon' : 'delete'
},
}
];
public static filters = [
{
'id' : 5,
'id' : 0,
'handle': 'starred',
'title' : 'Starred',
'icon' : 'star'
},
{
'id' : 6,
'id' : 1,
'handle': 'important',
'title' : 'Important',
'icon' : 'label'

View File

@ -60,16 +60,9 @@
</div>
</div>
<a class="toggle-details"
*ngIf="!showDetails"
(click)="showDetails = !showDetails">
Show Details
</a>
<a class="toggle-details"
*ngIf="showDetails"
(click)="showDetails = !showDetails">
Hide Details
<a class="toggle-details" (click)="showDetails = !showDetails">
<span *ngIf="!showDetails">Show Details</span>
<span *ngIf="showDetails">Hide Details</span>
</a>
<div *ngIf="showDetails" class="details" fxLayout="row" fxLayoutAlign="start start">
@ -88,16 +81,13 @@
</div>
</div>
<button md-button
[mdMenuTriggerFor]="moreMenu"
aria-label="More" class="mat-icon-button"
<button md-button [mdMenuTriggerFor]="moreMenu" aria-label="More" class="mat-icon-button"
ng-click="$mdOpenMenu($event)">
<md-icon>more_vert</md-icon>
</button>
<md-menu #moreMenu="mdMenu">
<button md-menu-item aria-label="Reply"
ng-click="vm.replyDialog($event)">
<button md-menu-item aria-label="Reply">
<md-icon>reply</md-icon>
<span>Reply</span>
</button>
@ -125,7 +115,7 @@
({{mail.attachments.length}})
</div>
<div class="attachment-list" layout-wrap fxLayout="row">
<div class="attachment-list" fxLayout="row" fxLayoutWrap>
<div class="attachment" fxLayout="column"
*ngFor="let attachment of mail.attachments">
@ -133,8 +123,8 @@
<img class="preview" src="{{attachment.preview}}">
<div fxLayout="column">
<a href="#" class="md-accent-color link" onclick="event.preventDefault()">View</a>
<a href="#" class="md-accent-color link" onclick="event.preventDefault()">Download</a>
<a href="#" onclick="event.preventDefault()">View</a>
<a href="#" onclick="event.preventDefault()">Download</a>
<div class="size">({{attachment.size}})</div>
</div>

View File

@ -54,6 +54,8 @@
}
.toggle-details {
user-select: none;
text-decoration: underline;
padding-top: 16px;
cursor: pointer;
font-weight: 500;

View File

@ -1,28 +1,43 @@
import { Component, Input, OnInit } from '@angular/core';
import { Mail } from '../mail.model';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { MailService } from '../mail.service';
import { Mail } from '../mail.model';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector : 'fuse-mail-details',
templateUrl: './mail-details.component.html',
styleUrls : ['./mail-details.component.scss']
})
export class MailDetailsComponent implements OnInit
export class MailDetailsComponent implements OnInit, OnDestroy
{
@Input('selectedMail') public mail: Mail;
showDetails: boolean;
mail: Mail;
labels: any[];
showDetails = false;
onCurrentMailChanged: Subscription;
constructor(
private mailService: MailService
)
{
this.showDetails = false;
}
ngOnInit()
{
// Set initial values
this.labels = this.mailService.labels;
this.mail = this.mailService.currentMail;
// Subscribe to update the current mail
this.onCurrentMailChanged = this.mailService.onCurrentMailChanged
.subscribe(currentMail => {
this.mail = currentMail;
});
}
ngOnDestroy()
{
this.onCurrentMailChanged.unsubscribe();
}
toggleStar(event)
@ -31,7 +46,7 @@ export class MailDetailsComponent implements OnInit
this.mail.toggleStar();
this.mailService.update(this.mail);
this.mailService.updateMail(this.mail);
}
toggleImportant(event)
@ -40,7 +55,7 @@ export class MailDetailsComponent implements OnInit
this.mail.toggleImportant();
this.mailService.update(this.mail);
this.mailService.updateMail(this.mail);
}
}

View File

@ -1,6 +1,6 @@
<div fxLayout="row" fxLayoutAlign="start center">
<md-checkbox></md-checkbox>
<md-checkbox [(ngModel)]="selected" (ngModelChange)="onSelectedChange()" (click)="$event.stopPropagation();"></md-checkbox>
<div class="info" fxFlex FlexLayout="column">

View File

@ -41,7 +41,7 @@
}
}
&.selected-mail {
&.current-mail {
background: #E3F2FD;
.info {

View File

@ -1,20 +1,22 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { Mail } from '../../mail.model';
import { MailService } from '../../mail.service';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector : 'fuse-mail-list-item',
templateUrl: './mail-list-item.component.html',
styleUrls : ['./mail-list-item.component.scss']
})
export class MailListItemComponent implements OnInit
export class MailListItemComponent implements OnInit, OnDestroy
{
@Input() mail: Mail;
labels: any[];
selected: boolean;
onSelectedMailsChanged: Subscription;
constructor(
private route: ActivatedRoute,
private mailService: MailService
)
{
@ -23,25 +25,75 @@ export class MailListItemComponent implements OnInit
ngOnInit()
{
// Set the initial values
this.mail = new Mail(this.mail);
this.labels = this.mailService.labels;
if ( this.mailService.selectedMails.length > 0 )
{
for ( const mail of this.mailService.selectedMails )
{
if ( mail.id === this.mail.id )
{
this.selected = true;
break;
}
}
}
// Subscribe to update on selected mail change
this.onSelectedMailsChanged =
this.mailService.onSelectedMailsChanged
.subscribe(selectedMails => {
this.selected = false;
if ( selectedMails.length > 0 )
{
for ( const mail of selectedMails )
{
if ( mail.id === this.mail.id )
{
this.selected = true;
break;
}
}
}
});
}
ngOnDestroy()
{
this.onSelectedMailsChanged.unsubscribe();
}
onSelectedChange()
{
this.mailService.toggleSelectedMail(this.mail.id);
}
/**
* Toggle star
* @param event
*/
toggleStar(event)
{
event.stopPropagation();
this.mail.toggleStar();
this.mailService.update(this.mail);
this.mailService.updateMail(this.mail);
}
/**
* Toggle Important
* @param event
*/
toggleImportant(event)
{
event.stopPropagation();
this.mail.toggleImportant();
this.mailService.update(this.mail);
this.mailService.updateMail(this.mail);
}
}

View File

@ -2,15 +2,6 @@
<span class="hint-text">There are no messages!</span>
</div>
<input type="text" [(ngModel)]="search">
{{search}}
<br>
<br>
<br>
<br>
<fuse-mail-list-item *ngFor="let mail of mails | filter:search" [mail]="mail" md-ripple (click)="selectMail(mail.id)"
[ngClass]="{'selected-mail':mail?.id === selectedMail?.id}">
<fuse-mail-list-item md-ripple *ngFor="let mail of mails" [mail]="mail" (click)="readMail(mail.id)"
[ngClass]="{'current-mail':mail?.id == currentMail?.id}">
</fuse-mail-list-item>

View File

@ -1,21 +1,22 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Mail } from '../mail.model';
import { ActivatedRoute } from '@angular/router';
import { MailService } from '../mail.service';
import { Location } from '@angular/common';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector : 'fuse-mail-list',
templateUrl: './mail-list.component.html',
styleUrls : ['./mail-list.component.scss']
})
export class MailListComponent implements OnInit
export class MailListComponent implements OnInit, OnDestroy
{
mails: Mail[];
currentMail: Mail;
@Input('selectedMail') public selectedMail: Mail;
search: string;
onMailsChanged: Subscription;
onCurrentMailChanged: Subscription;
constructor(
private route: ActivatedRoute,
@ -30,32 +31,56 @@ export class MailListComponent implements OnInit
// Get mails for the first time
this.mails = this.mailService.mails;
// Get current mail for the first time if available
this.currentMail = this.mailService.currentMail || null;
// Subscribe to update mails on changes
this.mailService.onMailsUpdated
.subscribe(mails => {
this.mails = mails;
});
this.onMailsChanged =
this.mailService.onMailsChanged
.subscribe(mails => {
this.mails = mails;
});
this.mailService.onSelectedMailUpdated
.subscribe(selectedMail => {
if ( !selectedMail )
{
const labelHandle = this.route.snapshot.params.labelHandle,
folderHandle = this.route.snapshot.params.folderHandle;
if ( labelHandle )
// Subscribe to update current mail on changes
this.onCurrentMailChanged =
this.mailService.onCurrentMailChanged
.subscribe(currentMail => {
if ( !currentMail )
{
this.location.go('apps/mail/label/' + labelHandle);
// Set the current mail id to null to deselect the current mail
this.currentMail = null;
// Handle the location changes
const labelHandle = this.route.snapshot.params.labelHandle,
folderHandle = this.route.snapshot.params.folderHandle;
if ( labelHandle )
{
this.location.go('apps/mail/label/' + labelHandle);
}
else
{
this.location.go('apps/mail/' + folderHandle);
}
}
else
{
this.location.go('apps/mail/' + folderHandle);
this.currentMail = currentMail;
}
}
});
});
}
selectMail(mailId)
ngOnDestroy()
{
this.onMailsChanged.unsubscribe();
this.onCurrentMailChanged.unsubscribe();
}
/**
* Read mail
* @param mailId
*/
readMail(mailId)
{
const labelHandle = this.route.snapshot.params.labelHandle,
folderHandle = this.route.snapshot.params.folderHandle;
@ -69,8 +94,8 @@ export class MailListComponent implements OnInit
this.location.go('apps/mail/' + folderHandle + '/' + mailId);
}
// Set selected mail
this.mailService.setSelectedMail(mailId);
// Set current mail
this.mailService.setCurrentMail(mailId);
}
}

View File

@ -42,7 +42,41 @@
<!-- CONTENT TOOLBAR -->
<div class="toolbar">
<span>Content toolbar</span>
<md-checkbox (click)="toggleSelectAll()" [checked]="hasSelectedMails"
[indeterminate]="isIndeterminate"></md-checkbox>
<button md-icon-button [mdMenuTriggerFor]="selectMenu">
<md-icon>arrow_drop_down</md-icon>
</button>
<md-menu #selectMenu="mdMenu">
<button md-menu-item (click)="selectMails()">All</button>
<button md-menu-item (click)="deselectMails()">None</button>
<button md-menu-item (click)="selectMails('read', true)">Read</button>
<button md-menu-item (click)="selectMails('read', false)">Unread</button>
<button md-menu-item (click)="selectMails('starred', true)">Starred</button>
<button md-menu-item (click)="selectMails('starred', false)">Unstarred</button>
<button md-menu-item (click)="selectMails('important', true)">Important</button>
<button md-menu-item (click)="selectMails('important', false)">Unimportant</button>
</md-menu>
<button md-icon-button (click)="setFolderOnSelectedMails(4)" *ngIf="hasSelectedMails">
<md-icon>delete</md-icon>
</button>
<button md-icon-button [mdMenuTriggerFor]="folderMenu" *ngIf="hasSelectedMails">
<md-icon>folder</md-icon>
</button>
<md-menu #folderMenu="mdMenu">
<button md-menu-item *ngFor="let folder of folders" (click)="setFolderOnSelectedMails(folder.id)">{{folder.title}}</button>
</md-menu>
<button md-icon-button [mdMenuTriggerFor]="labelMenu" *ngIf="hasSelectedMails">
<md-icon>label</md-icon>
</button>
<md-menu #labelMenu="mdMenu">
<button md-menu-item *ngFor="let label of labels" (click)="toggleLabelOnSelectedMails(label.id)">{{label.title}}</button>
</md-menu>
</div>
<!-- / CONTENT TOOLBAR -->
@ -51,9 +85,9 @@
<div fxLayout="row" fxFill>
<fuse-mail-list fxFlex [selectedMail]="selectedMail" perfect-scrollbar></fuse-mail-list>
<fuse-mail-list fxFlex perfect-scrollbar></fuse-mail-list>
<fuse-mail-details fxFlex [selectedMail]="selectedMail" perfect-scrollbar></fuse-mail-details>
<fuse-mail-details fxFlex perfect-scrollbar></fuse-mail-details>
</div>

View File

@ -1,15 +1,20 @@
import { Component, OnInit } from '@angular/core';
import { Mail } from './mail.model';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { MailService } from './mail.service';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector : 'fuse-mail',
templateUrl: './mail.component.html',
styleUrls : ['./mail.component.scss']
})
export class MailComponent implements OnInit
export class MailComponent implements OnInit, OnDestroy
{
selectedMail: Mail;
hasSelectedMails: boolean;
isIndeterminate: boolean;
folders: any[];
labels: any[];
onSelectedMailsChanged: Subscription;
constructor(
private mailService: MailService
@ -20,11 +25,48 @@ export class MailComponent implements OnInit
ngOnInit()
{
this.selectedMail = this.mailService.selectedMail;
// Get the values for the first time
this.labels = this.mailService.labels;
this.folders = this.mailService.folders;
this.mailService.onSelectedMailUpdated
.subscribe(selectedMail => {
this.selectedMail = selectedMail;
});
this.onSelectedMailsChanged =
this.mailService.onSelectedMailsChanged
.subscribe(selectedMails => {
setTimeout(() => {
this.hasSelectedMails = selectedMails.length > 0;
this.isIndeterminate = (selectedMails.length !== this.mailService.mails.length && selectedMails.length > 0);
}, 0);
});
}
ngOnDestroy()
{
this.onSelectedMailsChanged.unsubscribe();
}
toggleSelectAll()
{
this.mailService.toggleSelectAll();
}
selectMails(filterParameter?, filterValue?)
{
this.mailService.selectMails(filterParameter, filterValue);
}
deselectMails()
{
this.mailService.deselectMails();
}
toggleLabelOnSelectedMails(labelId)
{
this.mailService.toggleLabelOnSelectedMails(labelId);
}
setFolderOnSelectedMails(folderId)
{
this.mailService.setFolderOnSelectedMails(folderId);
}
}

View File

@ -25,7 +25,7 @@ export class Mail
size: string
}[];
labels: string[];
folders: string[];
folder: string;
constructor(mail)
{
@ -41,7 +41,7 @@ export class Mail
this.hasAttachments = mail.hasAttachments;
this.attachments = mail.attachments;
this.labels = mail.labels;
this.folders = mail.folders;
this.folder = mail.folder;
}
toggleStar()

View File

@ -23,6 +23,20 @@ const routes: Routes = [
mail: MailService
}
},
{
path : 'filter/:filterHandle',
component: MailComponent,
resolve : {
mail: MailService
}
},
{
path : 'filter/:filterHandle/:mailId',
component: MailComponent,
resolve : {
mail: MailService
}
},
{
path : ':folderHandle',
component: MailComponent,

View File

@ -9,24 +9,35 @@ import { Subject } from 'rxjs/Subject';
export class MailService implements Resolve<any>
{
mails: Mail[];
selectedMail: Mail;
labels: any[];
folders: any[];
selectedMails: Mail[];
currentMail: Mail;
folders: any[];
filters: any[];
labels: any[];
routeParams: any;
onMailsUpdated = new Subject<Mail[]>();
onSelectedMailUpdated = new Subject<Mail>();
onLabelsUpdated = new Subject<any[]>();
onFoldersUpdated = new Subject<any[]>();
onMailsChanged = new Subject<Mail[]>();
onSelectedMailsChanged = new Subject<Mail[]>();
onCurrentMailChanged = new Subject<Mail>();
onFoldersChanged = new Subject<any[]>();
onFiltersChanged = new Subject<any[]>();
onLabelsChanged = new Subject<any[]>();
constructor(
private http: Http
)
{
this.selectedMails = [];
}
/**
* Resolve
* @param {ActivatedRouteSnapshot} route
* @param {RouterStateSnapshot} state
* @returns {Observable<any> | Promise<any> | any}
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any
{
this.routeParams = route.params;
@ -34,17 +45,18 @@ export class MailService implements Resolve<any>
return new Promise((resolve, reject) => {
Promise.all([
this.getFolders(),
this.getFilters(),
this.getLabels(),
this.getMails()
]).then(
() => {
if ( this.routeParams.mailId )
{
this.setSelectedMail(this.routeParams.mailId);
this.setCurrentMail(this.routeParams.mailId);
}
else
{
this.setSelectedMail(null);
this.setCurrentMail(null);
}
resolve();
@ -54,30 +66,58 @@ export class MailService implements Resolve<any>
});
}
/**
* Get all folders
* @returns {Promise<any>}
*/
getFolders(): Promise<any>
{
return new Promise((resolve, reject) => {
this.http.get('api/mail-folders')
.subscribe(response => {
this.folders = response.json().data;
this.onFoldersUpdated.next(this.folders);
this.onFoldersChanged.next(this.folders);
resolve(this.folders);
}, reject);
});
}
/**
* Get all filters
* @returns {Promise<any>}
*/
getFilters(): Promise<any>
{
return new Promise((resolve, reject) => {
this.http.get('api/mail-filters')
.subscribe(response => {
this.filters = response.json().data;
this.onFiltersChanged.next(this.filters);
resolve(this.filters);
}, reject);
});
}
/**
* Get all labels
* @returns {Promise<any>}
*/
getLabels(): Promise<any>
{
return new Promise((resolve, reject) => {
this.http.get('api/mail-labels')
.subscribe(response => {
this.labels = response.json().data;
this.onLabelsUpdated.next(this.labels);
this.onLabelsChanged.next(this.labels);
resolve(this.labels);
}, reject);
});
}
/**
* Get all mails
* @returns {Promise<Mail[]>}
*/
getMails(): Promise<Mail[]>
{
if ( this.routeParams.labelHandle )
@ -85,52 +125,73 @@ export class MailService implements Resolve<any>
return this.getMailsByLabel(this.routeParams.labelHandle);
}
if ( this.routeParams.filterHandle )
{
return this.getMailsByFilter(this.routeParams.filterHandle);
}
return this.getMailsByFolder(this.routeParams.folderHandle);
}
/**
* Get mails by folder
* @param handle
* @returns {Promise<Mail[]>}
*/
getMailsByFolder(handle): Promise<Mail[]>
{
return new Promise((resolve, reject) => {
if ( handle === 'starred' || handle === 'important' )
{
this.http.get('api/mail-mails?' + handle + '=true')
.subscribe(mails => {
this.http.get('api/mail-folders?handle=' + handle)
.subscribe(folders => {
this.mails = mails.json().data.map(mail => {
return new Mail(mail);
});
const folderId = folders.json().data[0].id;
this.onMailsUpdated.next(this.mails);
this.http.get('api/mail-mails?folder=' + folderId)
.subscribe(mails => {
resolve(this.mails);
this.mails = mails.json().data.map(mail => {
return new Mail(mail);
});
}, reject);
}
else
{
this.http.get('api/mail-folders?handle=' + handle)
.subscribe(folders => {
this.onMailsChanged.next(this.mails);
const folderId = folders.json().data[0].id;
resolve(this.mails);
this.http.get('api/mail-mails?folders=' + folderId)
.subscribe(mails => {
this.mails = mails.json().data.map(mail => {
return new Mail(mail);
});
this.onMailsUpdated.next(this.mails);
resolve(this.mails);
}, reject);
});
}
}, reject);
});
});
}
/**
* Get mails by filter
* @param handle
* @returns {Promise<Mail[]>}
*/
getMailsByFilter(handle): Promise<Mail[]>
{
return new Promise((resolve, reject) => {
this.http.get('api/mail-mails?' + handle + '=true')
.subscribe(mails => {
this.mails = mails.json().data.map(mail => {
return new Mail(mail);
});
this.onMailsChanged.next(this.mails);
resolve(this.mails);
}, reject);
});
}
/**
* Get mails by label
* @param handle
* @returns {Promise<Mail[]>}
*/
getMailsByLabel(handle): Promise<Mail[]>
{
return new Promise((resolve, reject) => {
@ -146,7 +207,7 @@ export class MailService implements Resolve<any>
return new Mail(mail);
});
this.onMailsUpdated.next(this.mails);
this.onMailsChanged.next(this.mails);
resolve(this.mails);
@ -155,42 +216,167 @@ export class MailService implements Resolve<any>
});
}
getMailById(id): Promise<Mail>
/**
* Toggle selected mail by id
* @param id
*/
toggleSelectedMail(id)
{
return new Promise((resolve, reject) => {
this.http.get('api/mail-mails/' + id)
.subscribe(mail => {
resolve(mail.json().data);
}, reject);
});
// First, check if we already have that mail as selected...
if ( this.selectedMails.length > 0 )
{
for ( const mail of this.selectedMails )
{
// ...delete the selected mail
if ( mail.id === id )
{
const index = this.selectedMails.indexOf(mail);
if ( index !== -1 )
{
this.selectedMails.splice(index, 1);
// Trigger the next event
this.onSelectedMailsChanged.next(this.selectedMails);
// Return
return;
}
}
}
}
// If we don't have it, push as selected
this.selectedMails.push(
this.mails.find(mail => {
return mail.id === id;
})
);
// Trigger the next event
this.onSelectedMailsChanged.next(this.selectedMails);
}
setSelectedMail(id)
/**
* Toggle select all
*/
toggleSelectAll()
{
this.selectedMail = this.mails.find(mail => {
if ( this.selectedMails.length > 0 )
{
this.deselectMails();
}
else
{
this.selectMails();
}
}
selectMails(filterParameter?, filterValue?)
{
this.selectedMails = [];
// If there is no filter, select all mails
if ( filterParameter === undefined || filterValue === undefined )
{
this.selectedMails = this.mails;
}
else
{
this.selectedMails.push(...
this.mails.filter(mail => {
return mail[filterParameter] === filterValue;
})
);
}
// Trigger the next event
this.onSelectedMailsChanged.next(this.selectedMails);
}
deselectMails()
{
this.selectedMails = [];
// Trigger the next event
this.onSelectedMailsChanged.next(this.selectedMails);
}
/**
* Set current mail by id
* @param id
*/
setCurrentMail(id)
{
this.currentMail = this.mails.find(mail => {
return mail.id === id;
});
this.onSelectedMailUpdated.next(this.selectedMail);
this.onCurrentMailChanged.next(this.currentMail);
}
update(mail)
/**
* Toggle label on selected mails
* @param labelId
*/
toggleLabelOnSelectedMails(labelId)
{
this.selectedMails.map(mail => {
const index = mail.labels.indexOf(labelId);
if ( index !== -1 )
{
mail.labels.splice(index, 1);
}
else
{
mail.labels.push(labelId);
}
this.updateMail(mail);
});
}
/**
* Set folder on selected mails
* @param folderId
*/
setFolderOnSelectedMails(folderId)
{
this.selectedMails.map(mail => {
mail.folder = folderId;
this.updateMail(mail);
});
this.deselectMails();
}
/**
* Update the mail
* @param mail
* @returns {Promise<any>}
*/
updateMail(mail)
{
return new Promise((resolve, reject) => {
this.http.post('api/mail-mails/' + mail.id, {...mail}).subscribe(response => {
this.http.post('api/mail-mails/' + mail.id, {...mail})
.subscribe(response => {
this.getMails().then(mails => {
this.getMails().then(mails => {
if ( mails && this.selectedMail )
{
this.setSelectedMail(this.selectedMail.id);
}
if ( mails && this.currentMail )
{
this.setCurrentMail(this.currentMail.id);
}
resolve(mails);
resolve(mails);
}, reject);
});
}, reject);
});
});
}

View File

@ -26,19 +26,28 @@
<div class="nav-subheader">FOLDERS</div>
<div class="nav-item" *ngFor="let item of folders">
<a class="nav-link" md-ripple [routerLink]="'/apps/mail/' + item.handle" routerLinkActive="active">
<md-icon class="nav-link-icon" *ngIf="item.icon">{{item.icon}}</md-icon>
<span>{{item.title}}</span>
<div class="nav-item" *ngFor="let folder of folders">
<a class="nav-link" md-ripple [routerLink]="'/apps/mail/' + folder.handle" routerLinkActive="active">
<md-icon class="nav-link-icon" *ngIf="folder.icon">{{folder.icon}}</md-icon>
<span>{{folder.title}}</span>
</a>
</div>
<div class="nav-subheader">FILTERS</div>
<div class="nav-item" *ngFor="let filter of filters">
<a class="nav-link" md-ripple [routerLink]="'/apps/mail/filter/' + filter.handle" routerLinkActive="active">
<md-icon class="nav-link-icon" *ngIf="filter.icon">{{filter.icon}}</md-icon>
<span>{{filter.title}}</span>
</a>
</div>
<div class="nav-subheader">LABELS</div>
<div class="nav-item" *ngFor="let item of labels">
<a class="nav-link" md-ripple [routerLink]="'/apps/mail/label/' + item.handle" routerLinkActive="active">
<md-icon class="nav-link-icon" [ngStyle]="{'color':item.color}">label</md-icon>
<span>{{item.title}}</span>
<div class="nav-item" *ngFor="let label of labels">
<a class="nav-link" md-ripple [routerLink]="'/apps/mail/label/' + label.handle" routerLinkActive="active">
<md-icon class="nav-link-icon" [ngStyle]="{'color':label.color}">label</md-icon>
<span>{{label.title}}</span>
</a>
</div>

View File

@ -8,8 +8,9 @@ import { MailService } from '../../mail.service';
})
export class MainSidenavComponent implements OnInit
{
labels: any[];
folders: any[];
filters: any[];
labels: any[];
accounts: object;
selectedAccount: string;
@ -28,15 +29,20 @@ export class MainSidenavComponent implements OnInit
ngOnInit()
{
this.labels = this.mailService.labels;
this.folders = this.mailService.folders;
this.filters = this.mailService.filters;
this.labels = this.mailService.labels;
this.mailService.onLabelsUpdated.subscribe(labels => {
this.labels = this.mailService.labels;
this.mailService.onFoldersChanged.subscribe(folders => {
this.folders = this.mailService.folders;
});
this.mailService.onFoldersUpdated.subscribe(folders => {
this.folders = this.mailService.folders;
this.mailService.onFiltersChanged.subscribe(folders => {
this.filters = this.mailService.filters;
});
this.mailService.onLabelsChanged.subscribe(labels => {
this.labels = this.mailService.labels;
});
}
}

View File

@ -26,7 +26,7 @@
"label-position": true,
"max-line-length": [
true,
120
180
],
"member-access": false,
"member-ordering": [