Merge branch 'master' into skeleton

This commit is contained in:
Sercan Yemen 2018-06-15 18:42:24 +03:00
parent c93cecdddd
commit 0e2dca00c0
238 changed files with 41 additions and 16744 deletions

View File

@ -5,7 +5,6 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterModule, Routes } from '@angular/router';
import { MatMomentDateModule } from '@angular/material-moment-adapter';
import { MatButtonModule, MatIconModule } from '@angular/material';
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { TranslateModule } from '@ngx-translate/core';
import 'hammerjs';
@ -15,35 +14,14 @@ import { FuseSidebarModule, FuseThemeOptionsModule } from '@fuse/components';
import { fuseConfig } from 'app/fuse-config';
import { FakeDbService } from 'app/fake-db/fake-db.service';
import { AppComponent } from 'app/app.component';
import { AppStoreModule } from 'app/store/store.module';
import { LayoutModule } from 'app/layout/layout.module';
import { SampleModule } from 'app/main/sample/sample.module';
const appRoutes: Routes = [
{
path : 'apps',
loadChildren: './main/apps/apps.module#AppsModule'
},
{
path : 'pages',
loadChildren: './main/pages/pages.module#PagesModule'
},
{
path : 'ui',
loadChildren: './main/ui/ui.module#UIModule'
},
{
path : 'documentation',
loadChildren: './main/documentation/documentation.module#DocumentationModule'
},
{
path : 'angular-material-elements',
loadChildren: './main/angular-material-elements/angular-material-elements.module#AngularMaterialElementsModule'
},
{
path : '**',
redirectTo: 'apps/dashboards/analytics'
redirectTo: 'sample'
}
];
@ -58,10 +36,6 @@ const appRoutes: Routes = [
RouterModule.forRoot(appRoutes),
TranslateModule.forRoot(),
InMemoryWebApiModule.forRoot(FakeDbService, {
delay : 0,
passThruUnknownUrl: true
}),
// Material moment date module
MatMomentDateModule,
@ -78,7 +52,7 @@ const appRoutes: Routes = [
// App modules
LayoutModule,
AppStoreModule
SampleModule
],
bootstrap : [
AppComponent

View File

@ -1,7 +1,4 @@
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector : 'quick-panel',
@ -9,24 +6,17 @@ import { takeUntil } from 'rxjs/operators';
styleUrls : ['./quick-panel.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class QuickPanelComponent implements OnInit, OnDestroy
export class QuickPanelComponent
{
date: Date;
events: any[];
notes: any[];
settings: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {HttpClient} _httpClient
*/
constructor(
private _httpClient: HttpClient
)
constructor()
{
// Set the defaults
this.date = new Date();
@ -35,42 +25,5 @@ export class QuickPanelComponent implements OnInit, OnDestroy
cloud : false,
retro : true
};
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to the events
this._httpClient.get('api/quick-panel-events')
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((response: any) => {
this.events = response;
});
// Subscribe to the notes
this._httpClient.get('api/quick-panel-notes')
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((response: any) => {
this.notes = response;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -1,60 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { COMPONENT_MAP } from 'app/main/angular-material-elements/example-components';
@Component({
selector : 'angular-material',
templateUrl: './angular-material-elements.component.html',
styleUrls : ['./angular-material-elements.component.scss']
})
export class AngularMaterialElementsComponent implements OnInit, OnDestroy
{
id: string;
title: string;
examples: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ActivatedRoute} _activatedRoute
*/
constructor(
private _activatedRoute: ActivatedRoute
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
/**
* On init
*/
ngOnInit(): void
{
this._activatedRoute.params
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(params => {
this.id = params['id'];
const _title = this.id.replace('-', ' ');
this.title = _title.charAt(0).toUpperCase() + _title.substring(1);
this.examples = COMPONENT_MAP[this.id];
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -1,45 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { FuseSharedModule } from '@fuse/shared.module';
import { FuseHighlightModule } from '@fuse/components/index';
import { FuseWidgetModule } from '@fuse/components/widget/widget.module';
import { MaterialModule } from 'app/main/angular-material-elements/material.module';
import { EXAMPLE_LIST } from 'app/main/angular-material-elements/example-components';
import { AngularMaterialElementsComponent } from 'app/main/angular-material-elements/angular-material-elements.component';
import { ExampleViewerComponent } from 'app/main/angular-material-elements/example-viewer/example-viewer';
const routes: Routes = [
{
path : '',
children: [
{
path : ':id',
component: AngularMaterialElementsComponent
}
]
}
];
@NgModule({
declarations : [
[...EXAMPLE_LIST],
AngularMaterialElementsComponent,
ExampleViewerComponent
],
imports : [
RouterModule.forChild(routes),
MaterialModule,
FuseSharedModule,
FuseHighlightModule,
FuseWidgetModule
],
entryComponents: EXAMPLE_LIST,
})
export class AngularMaterialElementsModule
{
}

View File

@ -1,152 +0,0 @@
import { AfterViewInit, Component, ComponentFactoryResolver, ComponentRef, Input, OnDestroy, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
import { MatSnackBar } from '@angular/material';
import 'prismjs/components/prism-scss';
import 'prismjs/components/prism-typescript';
import { fuseAnimations } from '@fuse/animations/index';
import { FuseCopierService } from '@fuse/services/copier.service';
import { EXAMPLE_COMPONENTS } from 'app/main/angular-material-elements/example-components';
export interface LiveExample
{
title: string;
component: any;
additionalFiles?: string[];
selectorName?: string;
}
@Component({
selector : 'example-viewer',
templateUrl : './example-viewer.html',
styleUrls : ['./example-viewer.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class ExampleViewerComponent implements AfterViewInit, OnDestroy
{
_example: string;
exampleData: LiveExample;
showSource: boolean;
previewRef: ComponentRef<any>;
selectedIndex: number;
@ViewChild('previewContainer', {read: ViewContainerRef})
private _previewContainer: ViewContainerRef;
/**
* Constructor
*
* @param {MatSnackBar} _matSnackBar
* @param {FuseCopierService} _fuseCopierService
* @param {ComponentFactoryResolver} _componentFactoryResolver
*/
constructor(
private _matSnackBar: MatSnackBar,
private _fuseCopierService: FuseCopierService,
private _componentFactoryResolver: ComponentFactoryResolver
)
{
// Set the defaults
this.selectedIndex = 0;
this.showSource = false;
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Container
*
* @param {ViewContainerRef} value
*/
set container(value: ViewContainerRef)
{
this._previewContainer = value;
}
get container(): ViewContainerRef
{
return this._previewContainer;
}
/**
* Example
*
* @param {string} example
*/
@Input()
set example(example: string)
{
if ( example && EXAMPLE_COMPONENTS[example] )
{
this._example = example;
this.exampleData = EXAMPLE_COMPONENTS[example];
}
else
{
console.log('MISSING EXAMPLE: ', example);
}
}
get example(): string
{
return this._example;
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* After view init
*/
ngAfterViewInit(): void
{
setTimeout(() => {
const cmpFactory = this._componentFactoryResolver.resolveComponentFactory(this.exampleData.component);
this.previewRef = this._previewContainer.createComponent(cmpFactory);
}, 0);
}
/**
* On destroy
*/
ngOnDestroy(): void
{
if ( this.previewRef )
{
this.previewRef.destroy();
}
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle source view
*/
toggleSourceView(): void
{
this.showSource = !this.showSource;
}
/**
* Copy the source
*
* @param {string} text
*/
copySource(text: string): void
{
if ( this._fuseCopierService.copyText(text) )
{
this._matSnackBar.open('Code copied', '', {duration: 2500});
}
else
{
this._matSnackBar.open('Copy failed. Please try again!', '', {duration: 2500});
}
}
}

View File

@ -1,97 +0,0 @@
<div id="academy-course" class="page-layout simple left-sidebar inner-scroll">
<!-- SIDEBAR -->
<fuse-sidebar class="sidebar" name="academy-course-left-sidebar-1" position="left" lockedOpen="gt-md">
<!-- SIDEBAR CONTENT -->
<div class="content" fusePerfectScrollbar>
<div class="steps">
<div class="step"
*ngFor="let step of course.steps; let i = index; let last = last; let first = first"
(click)="gotoStep(i)"
[ngClass]="{'current': currentStep === i, 'completed': currentStep > i, 'last': last, 'first': first}">
<div class="index">
<span>{{i + 1}}</span>
</div>
<div class="title">{{step.title}}</div>
</div>
</div>
</div>
<!-- / SIDEBAR CONTENT -->
</fuse-sidebar>
<!-- / SIDEBAR -->
<!-- CENTER -->
<div class="center">
<!-- HEADER -->
<div class="header mat-accent-bg p-24" fxLayout="row" fxLayoutAlign="start center">
<button mat-icon-button class="sidebar-toggle mr-16" fxHide.gt-md
(click)="toggleSidebar('academy-course-left-sidebar-1')">
<mat-icon>menu</mat-icon>
</button>
<button mat-icon-button class="mr-16" [routerLink]="'/apps/academy/courses'">
<mat-icon>arrow_back</mat-icon>
</button>
<div>
<h2>{{course.title}}</h2>
</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div id="course-content" class="content">
<ng-container *ngFor="let step of course.steps; let i = index;">
<div class="course-step" fusePerfectScrollbar
*ngIf="currentStep === i"
[@slideIn]="animationDirection">
<div id="course-step-content" class="course-step-content" [innerHTML]="step.content"></div>
</div>
</ng-container>
</div>
<!-- / CONTENT -->
<div class="step-navigation">
<button mat-fab class="previous mat-accent white-fg"
(click)="gotoPreviousStep()"
[disabled]="currentStep === 0"
[fxHide]="currentStep === 0">
<mat-icon>chevron_left</mat-icon>
</button>
<button mat-fab class="next mat-accent white-fg"
(click)="gotoNextStep()"
[disabled]="currentStep === course.totalSteps - 1"
[fxHide]="currentStep === course.totalSteps - 1">
<mat-icon>chevron_right</mat-icon>
</button>
<button mat-fab class="done mat-green-600-bg"
routerLink="/apps/academy/courses"
[disabled]="currentStep !== course.totalSteps - 1"
[fxShow]="currentStep === course.totalSteps - 1">
<mat-icon>check</mat-icon>
</button>
</div>
</div>
<!-- / CENTER -->
</div>

View File

@ -1,162 +0,0 @@
import { AfterViewInit, ChangeDetectorRef, Component, OnDestroy, OnInit, QueryList, ViewChildren, ViewEncapsulation } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FusePerfectScrollbarDirective } from '@fuse/directives/fuse-perfect-scrollbar/fuse-perfect-scrollbar.directive';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
import { AcademyCourseService } from 'app/main/apps/academy/course.service';
@Component({
selector : 'academy-course',
templateUrl : './course.component.html',
styleUrls : ['./course.component.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class AcademyCourseComponent implements OnInit, OnDestroy, AfterViewInit
{
animationDirection: 'left' | 'right' | 'none';
course: any;
courseStepContent: any;
currentStep: number;
@ViewChildren(FusePerfectScrollbarDirective)
fuseScrollbarDirectives: QueryList<FusePerfectScrollbarDirective>;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {AcademyCourseService} _academyCourseService
* @param {ChangeDetectorRef} _changeDetectorRef
* @param {FuseSidebarService} _fuseSidebarService
*/
constructor(
private _academyCourseService: AcademyCourseService,
private _changeDetectorRef: ChangeDetectorRef,
private _fuseSidebarService: FuseSidebarService
)
{
// Set the defaults
this.animationDirection = 'none';
this.currentStep = 0;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to courses
this._academyCourseService.onCourseChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(course => {
this.course = course;
});
}
/**
* After view init
*/
ngAfterViewInit(): void
{
this.courseStepContent = this.fuseScrollbarDirectives.find((fuseScrollbarDirective) => {
return fuseScrollbarDirective.elementRef.nativeElement.id === 'course-step-content';
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Go to step
*
* @param step
*/
gotoStep(step): void
{
// Decide the animation direction
this.animationDirection = this.currentStep < step ? 'left' : 'right';
// Run change detection so the change
// in the animation direction registered
this._changeDetectorRef.detectChanges();
// Set the current step
this.currentStep = step;
}
/**
* Go to next step
*/
gotoNextStep(): void
{
if ( this.currentStep === this.course.totalSteps - 1 )
{
return;
}
// Set the animation direction
this.animationDirection = 'left';
// Run change detection so the change
// in the animation direction registered
this._changeDetectorRef.detectChanges();
// Increase the current step
this.currentStep++;
}
/**
* Go to previous step
*/
gotoPreviousStep(): void
{
if ( this.currentStep === 0 )
{
return;
}
// Set the animation direction
this.animationDirection = 'right';
// Run change detection so the change
// in the animation direction registered
this._changeDetectorRef.detectChanges();
// Decrease the current step
this.currentStep--;
}
/**
* Toggle the sidebar
*
* @param name
*/
toggleSidebar(name): void
{
this._fuseSidebarService.getSidebar(name).toggleOpen();
}
}

View File

@ -1,126 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { AcademyCoursesService } from 'app/main/apps/academy/courses.service';
@Component({
selector : 'academy-courses',
templateUrl: './courses.component.html',
styleUrls : ['./courses.component.scss'],
animations : fuseAnimations
})
export class AcademyCoursesComponent implements OnInit, OnDestroy
{
categories: any[];
courses: any[];
coursesFilteredByCategory: any[];
filteredCourses: any[];
currentCategory: string;
searchTerm: string;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {AcademyCoursesService} _academyCoursesService
*/
constructor(
private _academyCoursesService: AcademyCoursesService
)
{
// Set the defaults
this.currentCategory = 'all';
this.searchTerm = '';
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to categories
this._academyCoursesService.onCategoriesChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(categories => {
this.categories = categories;
});
// Subscribe to courses
this._academyCoursesService.onCoursesChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(courses => {
this.filteredCourses = this.coursesFilteredByCategory = this.courses = courses;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Filter courses by category
*/
filterCoursesByCategory(): void
{
// Filter
if ( this.currentCategory === 'all' )
{
this.coursesFilteredByCategory = this.courses;
this.filteredCourses = this.courses;
}
else
{
this.coursesFilteredByCategory = this.courses.filter((course) => {
return course.category === this.currentCategory;
});
this.filteredCourses = [...this.coursesFilteredByCategory];
}
// Re-filter by search term
this.filterCoursesByTerm();
}
/**
* Filter courses by term
*/
filterCoursesByTerm(): void
{
const searchTerm = this.searchTerm.toLowerCase();
// Search
if ( searchTerm === '' )
{
this.filteredCourses = this.coursesFilteredByCategory;
}
else
{
this.filteredCourses = this.coursesFilteredByCategory.filter((course) => {
return course.title.toLowerCase().includes(searchTerm);
});
}
}
}

View File

@ -1,65 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FuseSharedModule } from '@fuse/shared.module';
const routes = [
{
path : 'dashboards/analytics',
loadChildren: './dashboards/analytics/analytics.module#AnalyticsDashboardModule'
},
{
path : 'dashboards/project',
loadChildren: './dashboards/project/project.module#ProjectDashboardModule'
},
{
path : 'mail',
loadChildren: './mail/mail.module#MailModule'
},
{
path : 'mail-ngrx',
loadChildren: './mail-ngrx/mail.module#MailNgrxModule'
},
{
path : 'chat',
loadChildren: './chat/chat.module#ChatModule'
},
{
path : 'calendar',
loadChildren: './calendar/calendar.module#CalendarModule'
},
{
path : 'e-commerce',
loadChildren: './e-commerce/e-commerce.module#EcommerceModule'
},
{
path : 'academy',
loadChildren: './academy/academy.module#AcademyModule'
},
{
path : 'todo',
loadChildren: './todo/todo.module#TodoModule'
},
{
path : 'file-manager',
loadChildren: './file-manager/file-manager.module#FileManagerModule'
},
{
path : 'contacts',
loadChildren: './contacts/contacts.module#ContactsModule'
},
{
path : 'scrumboard',
loadChildren: './scrumboard/scrumboard.module#ScrumboardModule'
}
];
@NgModule({
imports : [
RouterModule.forChild(routes),
FuseSharedModule
]
})
export class AppsModule
{
}

View File

@ -1,20 +0,0 @@
<div fxFlex fxLayout="column" fxLayoutAlign="center center">
<div class="big-circle mat-elevation-z1 app-logo" fxLayout="column" fxLayoutAlign="center center"
[@animate]="{value:'*',params:{delay:'50ms',scale:'0.2'}}">
<mat-icon class="s-64 s-mat-128 mat-accent">chat</mat-icon>
</div>
<span class="app-title my-24" [@animate]="{value:'*',params:{delay:'100ms',y:'25px'}}">Chat App</span>
<span fxHide fxShow.gt-md class="app-message" [@animate]="{value:'*',params:{delay:'200ms',y:'50px'}}">
Select contact to start the chat!..
</span>
<button mat-raised-button fxHide.gt-md fuseMatSidenavToggler="chat-left-sidenav">
Select contact to start the chat!..
</button>
</div>

View File

@ -1,164 +0,0 @@
import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild, ViewChildren } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FusePerfectScrollbarDirective } from '@fuse/directives/fuse-perfect-scrollbar/fuse-perfect-scrollbar.directive';
import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({
selector : 'chat-view',
templateUrl: './chat-view.component.html',
styleUrls : ['./chat-view.component.scss']
})
export class ChatViewComponent implements OnInit, OnDestroy, AfterViewInit
{
user: any;
chat: any;
dialog: any;
contact: any;
replyInput: any;
selectedChat: any;
@ViewChild(FusePerfectScrollbarDirective)
directiveScroll: FusePerfectScrollbarDirective;
@ViewChildren('replyInput')
replyInputField;
@ViewChild('replyForm')
replyForm: NgForm;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ChatService} _chatService
*/
constructor(
private _chatService: ChatService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.user = this._chatService.user;
this._chatService.onChatSelected
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(chatData => {
if ( chatData )
{
this.selectedChat = chatData;
this.contact = chatData.contact;
this.dialog = chatData.dialog;
this.readyToReply();
}
});
}
/**
* After view init
*/
ngAfterViewInit(): void
{
this.replyInput = this.replyInputField.first.nativeElement;
this.readyToReply();
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Select contact
*/
selectContact(): void
{
this._chatService.selectContact(this.contact);
}
/**
* Ready to reply
*/
readyToReply(): void
{
setTimeout(() => {
this.replyForm.reset();
this.focusReplyInput();
this.scrollToBottom();
});
}
/**
* Focus to the reply input
*/
focusReplyInput(): void
{
setTimeout(() => {
this.replyInput.focus();
});
}
/**
* Scroll to the bottom
*
* @param {number} speed
*/
scrollToBottom(speed?: number): void
{
speed = speed || 400;
if ( this.directiveScroll )
{
this.directiveScroll.update();
setTimeout(() => {
this.directiveScroll.scrollToBottom(0, speed);
});
}
}
/**
* Reply
*/
reply(): void
{
// Message
const message = {
who : this.user.id,
message: this.replyForm.form.value.message,
time : new Date().toISOString()
};
// Add the message to the chat
this.dialog.push(message);
// Update the server
this._chatService.updateDialog(this.selectedChat.chatId, this.dialog).then(response => {
this.readyToReply();
});
}
}

View File

@ -1,61 +0,0 @@
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({
selector : 'chat',
templateUrl : './chat.component.html',
styleUrls : ['./chat.component.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class ChatComponent implements OnInit, OnDestroy
{
selectedChat: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ChatService} _chatService
*/
constructor(
private _chatService: ChatService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._chatService.onChatSelected
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(chatData => {
this.selectedChat = chatData;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -1,62 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MatButtonModule, MatCardModule, MatFormFieldModule, MatIconModule, MatInputModule, MatListModule, MatMenuModule, MatRadioModule, MatSidenavModule, MatToolbarModule } from '@angular/material';
import { FuseSharedModule } from '@fuse/shared.module';
import { ChatService } from 'app/main/apps/chat/chat.service';
import { ChatComponent } from 'app/main/apps/chat/chat.component';
import { ChatStartComponent } from 'app/main/apps/chat/chat-start/chat-start.component';
import { ChatViewComponent } from 'app/main/apps/chat/chat-view/chat-view.component';
import { ChatChatsSidenavComponent } from 'app/main/apps/chat/sidenavs/left/chats/chats.component';
import { ChatUserSidenavComponent } from 'app/main/apps/chat/sidenavs/left/user/user.component';
import { ChatLeftSidenavComponent } from 'app/main/apps/chat/sidenavs/left/left.component';
import { ChatRightSidenavComponent } from 'app/main/apps/chat/sidenavs/right/right.component';
import { ChatContactSidenavComponent } from 'app/main/apps/chat/sidenavs/right/contact/contact.component';
const routes: Routes = [
{
path : '**',
component: ChatComponent,
children : [],
resolve : {
chat: ChatService
}
}
];
@NgModule({
declarations: [
ChatComponent,
ChatViewComponent,
ChatStartComponent,
ChatChatsSidenavComponent,
ChatUserSidenavComponent,
ChatLeftSidenavComponent,
ChatRightSidenavComponent,
ChatContactSidenavComponent
],
imports : [
RouterModule.forChild(routes),
MatButtonModule,
MatCardModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatRadioModule,
MatSidenavModule,
MatToolbarModule,
FuseSharedModule
],
providers : [
ChatService
]
})
export class ChatModule
{
}

View File

@ -1,133 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ObservableMedia } from '@angular/flex-layout';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseMatSidenavHelperService } from '@fuse/directives/fuse-mat-sidenav/fuse-mat-sidenav.service';
import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({
selector : 'chat-chats-sidenav',
templateUrl: './chats.component.html',
styleUrls : ['./chats.component.scss'],
animations : fuseAnimations
})
export class ChatChatsSidenavComponent implements OnInit, OnDestroy
{
chats: any[];
chatSearch: any;
contacts: any[];
searchText: string;
user: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ChatService} _chatService
* @param {FuseMatSidenavHelperService} _fuseMatSidenavHelperService
* @param {ObservableMedia} _observableMedia
*/
constructor(
private _chatService: ChatService,
private _fuseMatSidenavHelperService: FuseMatSidenavHelperService,
public _observableMedia: ObservableMedia
)
{
// Set the defaults
this.chatSearch = {
name: ''
};
this.searchText = '';
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.user = this._chatService.user;
this.chats = this._chatService.chats;
this.contacts = this._chatService.contacts;
this._chatService.onChatsUpdated
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(updatedChats => {
this.chats = updatedChats;
});
this._chatService.onUserUpdated
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(updatedUser => {
this.user = updatedUser;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Get chat
*
* @param contact
*/
getChat(contact): void
{
this._chatService.getChat(contact);
if ( !this._observableMedia.isActive('gt-md') )
{
this._fuseMatSidenavHelperService.getSidenav('chat-left-sidenav').toggle();
}
}
/**
* Set user status
*
* @param status
*/
setUserStatus(status): void
{
this._chatService.setUserStatus(status);
}
/**
* Change left sidenav view
*
* @param view
*/
changeLeftSidenavView(view): void
{
this._chatService.onLeftSidenavViewChanged.next(view);
}
/**
* Logout
*/
logout(): void
{
console.log('logout triggered');
}
}

View File

@ -1,12 +0,0 @@
<div [ngSwitch]="view" class="views">
<chat-chats-sidenav class="view"
*ngSwitchCase="'chats'"
[@slideInRight]>
</chat-chats-sidenav>
<chat-user-sidenav class="view"
*ngSwitchCase="'user'"
[@slideInLeft]
fusePerfectScrollbar>
</chat-user-sidenav>
</div>

View File

@ -1,63 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({
selector : 'chat-left-sidenav',
templateUrl: './left.component.html',
styleUrls : ['./left.component.scss'],
animations : fuseAnimations
})
export class ChatLeftSidenavComponent implements OnInit, OnDestroy
{
view: string;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ChatService} _chatService
*/
constructor(
private _chatService: ChatService
)
{
// Set the defaults
this.view = 'chats';
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._chatService.onLeftSidenavViewChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(view => {
this.view = view;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -1,87 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({
selector : 'chat-user-sidenav',
templateUrl: './user.component.html',
styleUrls : ['./user.component.scss']
})
export class ChatUserSidenavComponent implements OnInit, OnDestroy
{
user: any;
userForm: FormGroup;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ChatService} _chatService
*/
constructor(
private _chatService: ChatService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.user = this._chatService.user;
this.userForm = new FormGroup({
mood : new FormControl(this.user.mood),
status: new FormControl(this.user.status)
});
this.userForm.valueChanges
.pipe(
takeUntil(this._unsubscribeAll),
debounceTime(500),
distinctUntilChanged()
)
.subscribe(data => {
this.user.mood = data.mood;
this.user.status = data.status;
this._chatService.updateUserData(this.user);
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Change left sidenav view
*
* @param view
*/
changeLeftSidenavView(view): void
{
this._chatService.onLeftSidenavViewChanged.next(view);
}
}

View File

@ -1,57 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({
selector : 'chat-contact-sidenav',
templateUrl: './contact.component.html',
styleUrls : ['./contact.component.scss']
})
export class ChatContactSidenavComponent implements OnInit, OnDestroy
{
contact: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ChatService} _chatService
*/
constructor(
private _chatService: ChatService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._chatService.onContactSelected
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(contact => {
this.contact = contact;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -1,9 +0,0 @@
<div [ngSwitch]="view" class="views">
<chat-contact-sidenav class="view"
*ngSwitchCase="'contact'"
[@slideInRight]
fusePerfectScrollbar>
</chat-contact-sidenav>
</div>

View File

@ -1,59 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({
selector : 'chat-right-sidenav',
templateUrl: './right.component.html',
styleUrls : ['./right.component.scss'],
animations : fuseAnimations
})
export class ChatRightSidenavComponent implements OnInit, OnDestroy
{
view: string;
// Private
private _unsubscribeAll: Subject<any>;
constructor(
private _chatService: ChatService
)
{
// Set the defaults
this.view = 'contact';
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._chatService.onRightSidenavViewChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(view => {
this.view = view;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -1,242 +0,0 @@
import { Component, OnDestroy, OnInit, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { MatDialog, MatDialogRef } from '@angular/material';
import { DataSource } from '@angular/cdk/collections';
import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component';
import { ContactsService } from 'app/main/apps/contacts/contacts.service';
import { ContactsContactFormDialogComponent } from 'app/main/apps/contacts/contact-form/contact-form.component';
@Component({
selector : 'contacts-contact-list',
templateUrl : './contact-list.component.html',
styleUrls : ['./contact-list.component.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class ContactsContactListComponent implements OnInit, OnDestroy
{
@ViewChild('dialogContent')
dialogContent: TemplateRef<any>;
contacts: any;
user: any;
dataSource: FilesDataSource | null;
displayedColumns = ['checkbox', 'avatar', 'name', 'email', 'phone', 'jobTitle', 'buttons'];
selectedContacts: any[];
checkboxes: {};
dialogRef: any;
confirmDialogRef: MatDialogRef<FuseConfirmDialogComponent>;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ContactsService} _contactsService
* @param {MatDialog} _matDialog
*/
constructor(
private _contactsService: ContactsService,
public _matDialog: MatDialog
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.dataSource = new FilesDataSource(this._contactsService);
this._contactsService.onContactsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(contacts => {
this.contacts = contacts;
this.checkboxes = {};
contacts.map(contact => {
this.checkboxes[contact.id] = false;
});
});
this._contactsService.onSelectedContactsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(selectedContacts => {
for ( const id in this.checkboxes )
{
if ( !this.checkboxes.hasOwnProperty(id) )
{
continue;
}
this.checkboxes[id] = selectedContacts.includes(id);
}
this.selectedContacts = selectedContacts;
});
this._contactsService.onUserDataChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(user => {
this.user = user;
});
this._contactsService.onFilterChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
this._contactsService.deselectContacts();
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Edit contact
*
* @param contact
*/
editContact(contact): void
{
this.dialogRef = this._matDialog.open(ContactsContactFormDialogComponent, {
panelClass: 'contact-form-dialog',
data : {
contact: contact,
action : 'edit'
}
});
this.dialogRef.afterClosed()
.subscribe(response => {
if ( !response )
{
return;
}
const actionType: string = response[0];
const formData: FormGroup = response[1];
switch ( actionType )
{
/**
* Save
*/
case 'save':
this._contactsService.updateContact(formData.getRawValue());
break;
/**
* Delete
*/
case 'delete':
this.deleteContact(contact);
break;
}
});
}
/**
* Delete Contact
*/
deleteContact(contact): void
{
this.confirmDialogRef = this._matDialog.open(FuseConfirmDialogComponent, {
disableClose: false
});
this.confirmDialogRef.componentInstance.confirmMessage = 'Are you sure you want to delete?';
this.confirmDialogRef.afterClosed().subscribe(result => {
if ( result )
{
this._contactsService.deleteContact(contact);
}
this.confirmDialogRef = null;
});
}
/**
* On selected change
*
* @param contactId
*/
onSelectedChange(contactId): void
{
this._contactsService.toggleSelectedContact(contactId);
}
/**
* Toggle star
*
* @param contactId
*/
toggleStar(contactId): void
{
if ( this.user.starred.includes(contactId) )
{
this.user.starred.splice(this.user.starred.indexOf(contactId), 1);
}
else
{
this.user.starred.push(contactId);
}
this._contactsService.updateUserData(this.user);
}
}
export class FilesDataSource extends DataSource<any>
{
/**
* Constructor
*
* @param {ContactsService} _contactsService
*/
constructor(
private _contactsService: ContactsService
)
{
super();
}
/**
* Connect function called by the table to retrieve one stream containing the data to render.
* @returns {Observable<any[]>}
*/
connect(): Observable<any[]>
{
return this._contactsService.onContactsChanged;
}
/**
* Disconnect
*/
disconnect(): void
{
}
}

View File

@ -1,13 +0,0 @@
#contacts {
.content {
overflow: hidden;
.sidebar {
&:not(.locked-open) {
background: white;
}
}
}
}

View File

@ -1,121 +0,0 @@
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { MatDialog } from '@angular/material';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
import { ContactsService } from 'app/main/apps/contacts/contacts.service';
import { ContactsContactFormDialogComponent } from 'app/main/apps/contacts/contact-form/contact-form.component';
@Component({
selector : 'contacts',
templateUrl : './contacts.component.html',
styleUrls : ['./contacts.component.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class ContactsComponent implements OnInit, OnDestroy
{
dialogRef: any;
hasSelectedContacts: boolean;
searchInput: FormControl;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ContactsService} _contactsService
* @param {FuseSidebarService} _fuseSidebarService
* @param {MatDialog} _matDialog
*/
constructor(
private _contactsService: ContactsService,
private _fuseSidebarService: FuseSidebarService,
private _matDialog: MatDialog
)
{
// Set the defaults
this.searchInput = new FormControl('');
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._contactsService.onSelectedContactsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(selectedContacts => {
this.hasSelectedContacts = selectedContacts.length > 0;
});
this.searchInput.valueChanges
.pipe(
takeUntil(this._unsubscribeAll),
debounceTime(300),
distinctUntilChanged()
)
.subscribe(searchText => {
this._contactsService.onSearchTextChanged.next(searchText);
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* New contact
*/
newContact(): void
{
this.dialogRef = this._matDialog.open(ContactsContactFormDialogComponent, {
panelClass: 'contact-form-dialog',
data : {
action: 'new'
}
});
this.dialogRef.afterClosed()
.subscribe((response: FormGroup) => {
if ( !response )
{
return;
}
this._contactsService.updateContact(response.getRawValue());
});
}
/**
* Toggle the sidebar
*
* @param name
*/
toggleSidebar(name): void
{
this._fuseSidebarService.getSidebar(name).toggleOpen();
}
}

View File

@ -1,63 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CdkTableModule } from '@angular/cdk/table';
import { MatButtonModule, MatCheckboxModule, MatDatepickerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatMenuModule, MatRippleModule, MatTableModule, MatToolbarModule } from '@angular/material';
import { FuseSharedModule } from '@fuse/shared.module';
import { FuseConfirmDialogModule, FuseSidebarModule } from '@fuse/components';
import { ContactsComponent } from 'app/main/apps/contacts/contacts.component';
import { ContactsService } from 'app/main/apps/contacts/contacts.service';
import { ContactsContactListComponent } from 'app/main/apps/contacts/contact-list/contact-list.component';
import { ContactsSelectedBarComponent } from 'app/main/apps/contacts/selected-bar/selected-bar.component';
import { ContactsMainSidebarComponent } from 'app/main/apps/contacts/sidebars/main/main.component';
import { ContactsContactFormDialogComponent } from 'app/main/apps/contacts/contact-form/contact-form.component';
const routes: Routes = [
{
path : '**',
component: ContactsComponent,
resolve : {
contacts: ContactsService
}
}
];
@NgModule({
declarations : [
ContactsComponent,
ContactsContactListComponent,
ContactsSelectedBarComponent,
ContactsMainSidebarComponent,
ContactsContactFormDialogComponent
],
imports : [
RouterModule.forChild(routes),
CdkTableModule,
MatButtonModule,
MatCheckboxModule,
MatDatepickerModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatMenuModule,
MatRippleModule,
MatTableModule,
MatToolbarModule,
FuseSharedModule,
FuseConfirmDialogModule,
FuseSidebarModule
],
providers : [
ContactsService
],
entryComponents: [
ContactsContactFormDialogComponent
]
})
export class ContactsModule
{
}

View File

@ -1,110 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { MatDialog, MatDialogRef } from '@angular/material';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component';
import { ContactsService } from 'app/main/apps/contacts/contacts.service';
@Component({
selector : 'selected-bar',
templateUrl: './selected-bar.component.html',
styleUrls : ['./selected-bar.component.scss']
})
export class ContactsSelectedBarComponent implements OnInit, OnDestroy
{
confirmDialogRef: MatDialogRef<FuseConfirmDialogComponent>;
hasSelectedContacts: boolean;
isIndeterminate: boolean;
selectedContacts: string[];
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ContactsService} _contactsService
* @param {MatDialog} _matDialog
*/
constructor(
private _contactsService: ContactsService,
public _matDialog: MatDialog
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._contactsService.onSelectedContactsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(selectedContacts => {
this.selectedContacts = selectedContacts;
setTimeout(() => {
this.hasSelectedContacts = selectedContacts.length > 0;
this.isIndeterminate = (selectedContacts.length !== this._contactsService.contacts.length && selectedContacts.length > 0);
}, 0);
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Select all
*/
selectAll(): void
{
this._contactsService.selectContacts();
}
/**
* Deselect all
*/
deselectAll(): void
{
this._contactsService.deselectContacts();
}
/**
* Delete selected contacts
*/
deleteSelectedContacts(): void
{
this.confirmDialogRef = this._matDialog.open(FuseConfirmDialogComponent, {
disableClose: false
});
this.confirmDialogRef.componentInstance.confirmMessage = 'Are you sure you want to delete all selected contacts?';
this.confirmDialogRef.afterClosed()
.subscribe(result => {
if ( result )
{
this._contactsService.deleteSelectedContacts();
}
this.confirmDialogRef = null;
});
}
}

View File

@ -1,75 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { ContactsService } from 'app/main/apps/contacts/contacts.service';
@Component({
selector : 'contacts-main-sidebar',
templateUrl: './main.component.html',
styleUrls : ['./main.component.scss']
})
export class ContactsMainSidebarComponent implements OnInit, OnDestroy
{
user: any;
filterBy: string;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ContactsService} _contactsService
*/
constructor(
private _contactsService: ContactsService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.filterBy = this._contactsService.filterBy || 'all';
this._contactsService.onUserDataChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(user => {
this.user = user;
});
}
/**
* On destroy
*/
ngOnDestroy()
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Change the filter
*
* @param filter
*/
changeFilter(filter): void
{
this.filterBy = filter;
this._contactsService.onFilterChanged.next(this.filterBy);
}
}

View File

@ -1,903 +0,0 @@
<div id="dashboard-project" class="page-layout simple right-sidebar" fxLayout="row">
<!-- SIDEBAR -->
<fuse-sidebar class="sidebar" name="project-dashboard-right-sidebar-1" position="right" lockedOpen="gt-md">
<!-- SIDEBAR CONTENT -->
<div class="content">
<!-- WIDGET GROUP -->
<div class="widget-group" fxLayout="column" fxFlex="100" [@animateStagger]="{value:'50'}">
<!-- NOW WIDGET -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="p-0">
<!-- Front -->
<div class="fuse-widget-front">
<div class="pl-16 pr-8 py-16" fxLayout="row" fxLayoutAlign="space-between center">
<div class="h3">{{dateNow | date: 'EEEE, HH:mm:ss'}}</div>
<div>
<button mat-icon-button [matMenuTriggerFor]="moreMenu" aria-label="more">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #moreMenu="matMenu">
<button mat-menu-item aria-label="Flip widget">
Details
</button>
</mat-menu>
</div>
</div>
<div class="p-16 pb-24" fxLayout="column" fxLayoutAlign="center center">
<div class="h1 secondary-text">
<span>{{dateNow | date: 'MMMM'}}</span>
</div>
<div class="font-size-72 line-height-88 secondary-text font-weight-400">
{{dateNow | date: 'd'}}
</div>
<div class="h1 secondary-text">
<span>{{dateNow | date: 'y'}}</span>
</div>
</div>
<mat-divider></mat-divider>
</div>
<!-- / Front -->
</fuse-widget>
<!-- / NOW WIDGET -->
<!-- WEATHER WIDGET -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="p-0">
<!-- Front -->
<div class="fuse-widget-front">
<div class="pl-16 pr-8 py-16" fxLayout="row" fxLayoutAlign="space-between center">
<div class="h4" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text mr-8">place</mat-icon>
{{widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].name}}
</div>
<div>
<button mat-icon-button [matMenuTriggerFor]="moreMenu" aria-label="more">
<mat-icon class="secondary-text">more_vert</mat-icon>
</button>
<mat-menu #moreMenu="matMenu">
<button mat-menu-item aria-label="Flip widget">
Details
</button>
</mat-menu>
</div>
</div>
<div class="p-16 pb-32" fxLayout="column" fxLayoutAlign="center center">
<div fxLayout="row" fxLayoutAlign="center center">
<mat-icon fontSet="meteocons"
[fontIcon]="widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].icon"
class="icon s-40 secondary-text mr-16"></mat-icon>
<span class="mat-display-2 m-0 font-weight-300 secondary-text">
{{widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].temp[widgets.weatherWidget.tempUnit]}}
</span>
<span class="font-size-48 font-weight-300 hint-text text-super ml-8">°</span>
<span class="mat-display-2 mb-0 font-weight-300 hint-text ng-binding">C</span>
</div>
</div>
<div class="grey-300-bg p-16" fxLayout="row" fxLayoutAlign="space-between center">
<div fxLayout="row" fxLayoutAlign="start center">
<mat-icon fontSet="meteocons" fontIcon="icon-windy"
class="s-16 secondary-text mr-8"></mat-icon>
<span>
{{widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].windSpeed[widgets.weatherWidget.speedUnit]}}
</span>
<span class="secondary-text ml-5">{{widgets.weatherWidget.speedUnit}}</span>
</div>
<div fxLayout="row" fxLayoutAlign="start center">
<mat-icon fontSet="meteocons" fontIcon="icon-compass"
class="s-16 secondary-text mr-8"></mat-icon>
<span>
{{widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].windDirection}}
</span>
</div>
<div fxLayout="row" fxLayoutAlign="start center">
<mat-icon fontSet="meteocons" fontIcon="icon-rainy"
class="s-16 secondary-text mr-8"></mat-icon>
<span>
{{widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].rainProbability}}
</span>
</div>
</div>
<div class="py-16">
<div class="py-16 px-24" fxLayout="row" fxLayoutAlign="space-between center"
*ngFor="let day of widgets.weatherWidget.locations[widgets.weatherWidget.currentLocation].next3Days">
<span class="h4">{{day.name}}</span>
<div fxLayout="row" fxLayoutAlign="start center">
<mat-icon fontSet="meteocons" [fontIcon]="day.icon" class="secondary-text mr-16"></mat-icon>
<span class="h2">{{day.temp[widgets.weatherWidget.tempUnit]}}</span>
<span class="h2 font-weight-300 secondary-text text-super">&deg;</span>
<span class="h2 font-weight-300 secondary-text">
{{widgets.weatherWidget.tempUnit}}
</span>
</div>
</div>
</div>
<mat-divider></mat-divider>
</div>
<!-- / Front -->
</fuse-widget>
<!-- / WEATHER WIDGET -->
</div>
<!-- / WIDGET GROUP -->
</div>
<!-- / SIDEBAR CONTENT -->
</fuse-sidebar>
<!-- / SIDEBAR -->
<!-- CENTER -->
<div class="center" fusePerfectScrollbar>
<!-- HEADER -->
<div class="header mat-accent-bg p-24 pb-0" fxLayout="column" fxLayoutAlign="space-between">
<div fxLayout="row" fxLayoutAlign="space-between start">
<span class="mat-display-1 mb-0 welcome-message"
[@animate]="{value:'*',params:{x:'50px'}}">Welcome back, John!
</span>
<button mat-icon-button class="sidebar-toggle mr-8" fxHide.gt-md
(click)="toggleSidebar('project-dashboard-right-sidebar-1')">
<mat-icon>menu</mat-icon>
</button>
</div>
<div fxLayout="row">
<div class="selected-project">{{selectedProject.name}}</div>
<button mat-icon-button class="project-selector" [matMenuTriggerFor]="projectsMenu"
aria-label="Select project">
<mat-icon>more_horiz</mat-icon>
</button>
<mat-menu #projectsMenu="matMenu">
<button mat-menu-item *ngFor="let project of projects" (click)="selectedProject = project">
<span>{{project.name}}</span>
</button>
</mat-menu>
</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content">
<mat-tab-group dynamicHeight>
<mat-tab label="Home">
<div class="widget-group grey-100-bg p-12" fxLayout="row wrap" fxFlex="100" *fuseIfOnDom
[@animateStagger]="{value:'50'}">
<!-- WIDGET 1 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="pl-16 pr-8 py-16 h-52" fxLayout="row"
fxLayoutAlign="space-between center">
<mat-form-field>
<mat-select class="simplified font-size-16"
[(ngModel)]="widgets.widget1.currentRange"
aria-label="Change range">
<mat-option *ngFor="let range of widgets.widget1.ranges | keys"
[value]="range.key">
{{range.value}}
</mat-option>
</mat-select>
</mat-form-field>
<button mat-icon-button fuseWidgetToggle aria-label="more">
<mat-icon>more_vert</mat-icon>
</button>
</div>
<div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center">
<div class="light-blue-fg font-size-72 line-height-72">
{{widgets.widget1.data.count[widgets.widget1.currentRange]}}
</div>
<div class="h3 secondary-text font-weight-500">{{widgets.widget1.data.label}}
</div>
</div>
<div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center">
<span class="h4 secondary-text text-truncate">
{{widgets.widget1.data.extra.label}}:
</span>
<span class="h4 ml-8">
{{widgets.widget1.data.extra.count[widgets.widget1.currentRange]}}
</span>
</div>
</div>
<!-- / Front -->
<!-- Back -->
<div class="fuse-widget-back p-16 pt-32 mat-white-bg mat-elevation-z2">
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="Flip widget">
<mat-icon class="s-16">close</mat-icon>
</button>
<div>
{{widgets.widget1.detail}}
</div>
</div>
<!-- / Back -->
</fuse-widget>
<!-- / WIDGET 1 -->
<!-- WIDGET 2 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="pl-16 pr-8 py-16 h-52" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget2.title}}</div>
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="more">
<mat-icon>more_vert</mat-icon>
</button>
</div>
<div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center">
<div class="red-fg font-size-72 line-height-72">
{{widgets.widget2.data.count}}
</div>
<div class="h3 secondary-text font-weight-500">{{widgets.widget2.data.label}}
</div>
</div>
<div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center">
<span class="h4 secondary-text text-truncate">
{{widgets.widget2.data.extra.label}}:
</span>
<span class="h4 ml-8">{{widgets.widget2.data.extra.count}}</span>
</div>
</div>
<!-- / Front -->
<!-- Back -->
<div class="fuse-widget-back p-16 pt-32 mat-white-bg mat-elevation-z2">
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="Flip widget">
<mat-icon class="s-16">close</mat-icon>
</button>
<div>
{{widgets.widget2.detail}}
</div>
</div>
<!-- / Back -->
</fuse-widget>
<!-- / WIDGET 2 -->
<!-- WIDGET 3 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="pl-16 pr-8 py-16 h-52" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget3.title}}</div>
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="more">
<mat-icon>more_vert</mat-icon>
</button>
</div>
<div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center">
<div class="orange-fg font-size-72 line-height-72">
{{widgets.widget3.data.count}}
</div>
<div class="h3 secondary-text font-weight-500">{{widgets.widget3.data.label}}
</div>
</div>
<div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center">
<span class="h4 secondary-text text-truncate">
{{widgets.widget3.data.extra.label}}:
</span>
<span class="h4 ml-8">{{widgets.widget3.data.extra.count}}</span>
</div>
</div>
<!-- / Front -->
<!-- Back -->
<div class="fuse-widget-back p-16 pt-32 mat-white-bg mat-elevation-z2">
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="Flip widget">
<mat-icon class="s-16">close</mat-icon>
</button>
<div>
{{widgets.widget3.detail}}
</div>
</div>
<!-- / Back -->
</fuse-widget>
<!-- / WIDGET 3 -->
<!-- WIDGET 4 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="pl-16 pr-8 py-16 h-52" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget4.title}}</div>
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="more">
<mat-icon>more_vert</mat-icon>
</button>
</div>
<div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center">
<div class="blue-grey-fg font-size-72 line-height-72">
{{widgets.widget4.data.count}}
</div>
<div class="h3 secondary-text font-weight-500">{{widgets.widget4.data.label}}
</div>
</div>
<div class="p-16 grey-50-bg border-top" fxLayout="row" fxLayoutAlign="start center">
<span class="h4 secondary-text text-truncate">
{{widgets.widget4.data.extra.label}}:
</span>
<span class="h4 ml-8">{{widgets.widget4.data.extra.count}}</span>
</div>
</div>
<!-- / Front -->
<!-- Back -->
<div class="fuse-widget-back p-16 pt-32 mat-white-bg mat-elevation-z2">
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="Flip widget">
<mat-icon class="s-16">close</mat-icon>
</button>
<div>
{{widgets.widget4.detail}}
</div>
</div>
<!-- / Back -->
</fuse-widget>
<!-- / WIDGET 4 -->
<!-- WIDGET 5 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" fxLayout="row" fxFlex="100"
class="widget widget5">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="px-16 border-bottom" fxLayout="row wrap"
fxLayoutAlign="space-between center">
<div fxFlex class="py-16 h3">{{widgets.widget5.title}}</div>
<div fxFlex="0 1 auto" class="py-16" fxLayout="row">
<button mat-button class="px-16"
*ngFor="let range of widgets.widget5.ranges | keys"
(click)="widget5.currentRange = range.key"
[disabled]="widget5.currentRange == range.key">
{{range.value}}
</button>
</div>
</div>
<div fxLayout="row wrap" fxLayoutAlign="start start">
<div class="h-420 my-16" fxLayout="row" fxFlex="100" fxFlex.gt-sm="50">
<ngx-charts-bar-vertical-stacked
*fuseIfOnDom
[scheme]="widget5.scheme"
[results]="this.widgets.widget5.mainChart[this.widget5.currentRange]"
[gradient]="widget5.gradient"
[xAxis]="widget5.xAxis"
[yAxis]="widget5.yAxis"
[legend]="widget5.legend"
[showXAxisLabel]="widget5.showXAxisLabel"
[showYAxisLabel]="widget5.showYAxisLabel"
[xAxisLabel]="widget5.xAxisLabel"
[yAxisLabel]="widget5.yAxisLabel"
(select)="widget5.onSelect($event)">
</ngx-charts-bar-vertical-stacked>
</div>
<div class="my-16" fxFlex="100" fxLayout="row wrap" fxFlex.gt-sm="50">
<div fxLayout="column" fxFlex="100" fxFlex.gt-sm="50" fxLayoutAlign="center"
*ngFor="let widget of widgets.widget5.supporting | keys"
class="mb-24">
<div class="px-24">
<div class="h4 secondary-text">{{widget.value.label}}</div>
<div class="mat-display-1 m-0">
{{widget.value.count[widget5.currentRange]}}
</div>
</div>
<div class="h-64">
<ngx-charts-area-chart
*fuseIfOnDom
[results]="widget.value.chart[widget5.currentRange]"
[scheme]="widget5.supporting.scheme"
[gradient]="widget5.supporting.gradient"
[xAxis]="widget5.supporting.xAxis"
[yAxis]="widget5.supporting.yAxis"
[legend]="widget5.supporting.legend"
[showXAxisLabel]="widget5.supporting.showXAxisLabel"
[showYAxisLabel]="widget5.supporting.showYAxisLabel"
[xAxisLabel]="widget5.supporting.xAxisLabel"
[yAxisLabel]="widget5.supporting.yAxisLabel"
[curve]="widget5.supporting.curve">
</ngx-charts-area-chart>
</div>
</div>
</div>
</div>
</div>
<!-- / Front -->
</fuse-widget>
<!-- / WIDGET 5 -->
<!-- WIDGET 6 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-sm="50">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="px-16 py-8 border-bottom" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget6.title}}</div>
<mat-form-field>
<mat-select class="simplified" [(ngModel)]="widget6.currentRange"
aria-label="Change range">
<mat-option *ngFor="let range of widgets.widget6.ranges | keys"
[value]="range.key">
{{range.value}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="h-400">
<ngx-charts-pie-chart
*fuseIfOnDom
[scheme]="widget6.scheme"
[results]="widgets.widget6.mainChart[widget6.currentRange]"
[legend]="widget6.showLegend"
[explodeSlices]="widget6.explodeSlices"
[labels]="widget6.labels"
[doughnut]="widget6.doughnut"
[gradient]="widget6.gradient"
(select)="widget6.onSelect($event)">
</ngx-charts-pie-chart>
</div>
<div class="py-8 mh-16 border-top" fxLayout="row wrap" fxLayoutAlign="start center">
<div class="py-8 border-right" fxLayout="column" fxLayoutAlign="center center"
fxFlex="100" fxFlex.gt-sm="50">
<span class="mat-display-1 mb-0">
{{widgets.widget6.footerLeft.count[widget6.currentRange]}}
</span>
<span class="h4">{{widgets.widget6.footerLeft.title}}</span>
</div>
<div class="py-8" fxLayout="column" fxLayoutAlign="center center" fxFlex="100"
fxFlex.gt-sm="50">
<span class="mat-display-1 mb-0">
{{widgets.widget6.footerRight.count[widget6.currentRange]}}
</span>
<span class="h4">{{widgets.widget6.footerRight.title}}</span>
</div>
</div>
</div>
<!-- / Front -->
</fuse-widget>
<!-- / WIDGET 6 -->
<!-- WIDGET 7 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-sm="50">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="px-16 py-8 border-bottom" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget7.title}}</div>
<mat-form-field>
<mat-select class="simplified" [(ngModel)]="widget7.currentRange"
aria-label="Change range">
<mat-option *ngFor="let range of widgets.widget7.ranges | keys"
[value]="range.key">
{{range.value}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="p-16" fxLayout="row" fxLayoutAlign="space-between center"
*ngFor="let event of widgets.widget7.schedule[widget7.currentRange]">
<div>
<div class="h3">{{event.title}}</div>
<div>
<span class="secondary-text">{{event.time}}</span>
<span *ngIf="event.location">, {{event.location}}</span>
</div>
</div>
<button mat-icon-button aria-label="More information">
<mat-icon>more_vert</mat-icon>
</button>
</div>
</div>
<!-- / Front -->
</fuse-widget>
<!-- / WIDGET 7 -->
</div>
<!-- / WIDGET GROUP -->
</mat-tab>
<mat-tab label="Budget Summary">
<!-- WIDGET GROUP -->
<div class="widget-group grey-100-bg" fxLayout="row wrap" fxFlex="100" *fuseIfOnDom
[@animateStagger]="{value:'50'}">
<!-- WIDGET 8 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-sm="50">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="h3 px-16 py-24">
{{widgets.widget8.title}}
</div>
<mat-divider></mat-divider>
<div class="h-400">
<ngx-charts-pie-chart
*fuseIfOnDom
[scheme]="widget8.scheme"
[results]="widgets.widget8.mainChart"
[legend]="widget8.legend"
[explodeSlices]="widget8.explodeSlices"
[labels]="widget8.labels"
[doughnut]="widget8.doughnut"
[gradient]="widget8.gradient"
(select)="widget8.onSelect($event)">
</ngx-charts-pie-chart>
</div>
</div>
<!-- / Front -->
</fuse-widget>
<!-- / WIDGET 8 -->
<!-- WIDGET 9 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="column"
fxFlex="100" fxFlex.gt-sm="50">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="px-16 py-12 border-bottom" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h3">{{widgets.widget9.title}}</div>
<mat-form-field>
<mat-select [(ngModel)]="widget9.currentRange" aria-label="Change range">
<mat-option *ngFor="let range of widgets.widget9.ranges | keys"
[value]="range.key">
{{range.value}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="px-16 py-24" fxLayout="column" fxLayoutAlign="center"
fxLayout.gt-xs="row"
fxLayoutAlign.gt-xs="space-between end">
<div fxFlex="0 1 auto">
<div class="h4 secondary-text">{{widgets.widget9.weeklySpent.title}}</div>
<div class="pt-8 mat-display-1 m-0 font-weight-300 text-nowrap">
<span class="secondary-text">$</span>
<span>{{widgets.widget9.weeklySpent.count[widget9.currentRange]}}</span>
</div>
</div>
<div class="h-52" fxFlex>
<ngx-charts-area-chart
*fuseIfOnDom
[results]="widgets.widget9.weeklySpent.chart[widget9.currentRange]"
[scheme]="widget9.scheme"
[gradient]="widget9.gradient"
[xAxis]="widget9.xAxis"
[yAxis]="widget9.yAxis"
[legend]="widget9.legend"
[showXAxisLabel]="widget9.showXAxisLabel"
[showYAxisLabel]="widget9.showYAxisLabel"
[xAxisLabel]="widget9.xAxisLabel"
[yAxisLabel]="widget9.yAxisLabel"
[curve]="widget9.curve">
</ngx-charts-area-chart>
</div>
</div>
<div class="px-16 py-24" fxLayout="column" fxLayoutAlign="center"
fxLayout.gt-xs="row"
fxLayoutAlign.gt-xs="space-between end">
<div fxFlex="0 1 auto">
<div class="h4 secondary-text">{{widgets.widget9.totalSpent.title}}</div>
<div class="pt-8 mat-display-1 m-0 font-weight-300 text-nowrap">
<span class="secondary-text">$</span>
<span>{{widgets.widget9.totalSpent.count[widget9.currentRange]}}</span>
</div>
</div>
<div class="h-52" fxFlex>
<ngx-charts-area-chart
*fuseIfOnDom
[results]="widgets.widget9.totalSpent.chart[widget9.currentRange]"
[scheme]="widget9.scheme"
[gradient]="widget9.gradient"
[xAxis]="widget9.xAxis"
[yAxis]="widget9.yAxis"
[legend]="widget9.legend"
[showXAxisLabel]="widget9.showXAxisLabel"
[showYAxisLabel]="widget9.showYAxisLabel"
[xAxisLabel]="widget9.xAxisLabel"
[yAxisLabel]="widget9.yAxisLabel"
[curve]="widget9.curve">
</ngx-charts-area-chart>
</div>
</div>
<div class="px-16 py-24" fxLayout="column" fxLayoutAlign="center"
fxLayout.gt-xs="row"
fxLayoutAlign.gt-xs="space-between end">
<div fxFlex="0 1 auto">
<div class="h4 secondary-text">{{widgets.widget9.remaining.title}}</div>
<div class="pt-8 mat-display-1 m-0 font-weight-300 text-nowrap">
<span class="secondary-text">$</span>
<span>{{widgets.widget9.remaining.count[widget9.currentRange]}}</span>
</div>
</div>
<div class="h-52" fxFlex>
<ngx-charts-area-chart
*fuseIfOnDom
[results]="widgets.widget9.remaining.chart[widget9.currentRange]"
[scheme]="widget9.scheme"
[gradient]="widget9.gradient"
[xAxis]="widget9.xAxis"
[yAxis]="widget9.yAxis"
[legend]="widget9.legend"
[showXAxisLabel]="widget9.showXAxisLabel"
[showYAxisLabel]="widget9.showYAxisLabel"
[xAxisLabel]="widget9.xAxisLabel"
[yAxisLabel]="widget9.yAxisLabel"
[curve]="widget9.curve">
</ngx-charts-area-chart>
</div>
</div>
<div class="px-16 py-24 border-top">
<div class="h4 secondary-text">{{widgets.widget9.totalBudget.title}}</div>
<div class="pt-8 mat-display-1 m-0 font-weight-300">
<span class="secondary-text">$</span>
<span>{{widgets.widget9.totalBudget.count}}</span>
</div>
</div>
</div>
<!-- / Front -->
</fuse-widget>
<!-- / WIDGET 9 -->
<!-- WIDGET 10 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="row"
fxFlex="100">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="simple-table-container" ms-responsive-table>
<div class=" table-title">
{{widgets.widget10.title}}
</div>
<table class="simple">
<thead>
<tr>
<th *ngFor="let column of widgets.widget10.table.columns">
{{column.title}}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of widgets.widget10.table.rows">
<td *ngFor="let cell of row">
<span class="p-4" [ngClass]="cell.classes">
{{cell.value}}
</span>
<mat-icon *ngIf="cell.icon" class="s-16">{{cell.icon}}
</mat-icon>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- / Front -->
</fuse-widget>
<!-- / WIDGET 10 -->
</div>
<!-- / WIDGET GROUP -->
</mat-tab>
<mat-tab label="Team Members">
<!-- WIDGET GROUP -->
<div class="widget-group grey-100-bg" fxLayout="row wrap" fxFlex="100" *fuseIfOnDom
[@animateStagger]="{value:'50'}">
<!-- WIDGET 11 -->
<fuse-widget [@animate]="{value:'*',params:{y:'100%'}}" class="widget" fxLayout="row"
fxFlex="100">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="p-24 mb-8 border-bottom" fxLayout="row"
fxLayoutAlign="space-between center">
<div class="h2">{{widgets.widget11.title}}</div>
<div class="text-boxed red-bg white-fg m-0">
{{widgets.widget11.table.rows.length}}
members
</div>
</div>
<mat-table #table [dataSource]="widget11.dataSource">
<!-- Avatar Column -->
<ng-container cdkColumnDef="avatar">
<mat-header-cell fxFlex="96px" *cdkHeaderCellDef></mat-header-cell>
<mat-cell fxFlex="96px" *cdkCellDef="let contact">
<img class="avatar" *ngIf="contact.avatar" [alt]="contact.name"
[src]="contact.avatar"/>
</mat-cell>
</ng-container>
<!-- Name Column -->
<ng-container cdkColumnDef="name">
<mat-header-cell *cdkHeaderCellDef>Name</mat-header-cell>
<mat-cell *cdkCellDef="let contact">
<p class="text-truncate font-weight-600">{{contact.name}}
{{contact.lastName}}</p>
</mat-cell>
</ng-container>
<!-- Position Column -->
<ng-container cdkColumnDef="position">
<mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-sm>Position
</mat-header-cell>
<mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-sm>
<p class="position text-truncate">
{{contact.position}}
</p>
</mat-cell>
</ng-container>
<!-- Office Column -->
<ng-container cdkColumnDef="office">
<mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-md>Office
</mat-header-cell>
<mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-md>
<p class="office text-truncate">
{{contact.office}}
</p>
</mat-cell>
</ng-container>
<!-- Email Column -->
<ng-container cdkColumnDef="email">
<mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-sm>Email
</mat-header-cell>
<mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-sm>
<p class="email text-truncate">
{{contact.email}}
</p>
</mat-cell>
</ng-container>
<!-- Phone Column -->
<ng-container cdkColumnDef="phone">
<mat-header-cell *cdkHeaderCellDef fxHide fxShow.gt-md>Phone
</mat-header-cell>
<mat-cell *cdkCellDef="let contact" fxHide fxShow.gt-md>
<p class="phone text-truncate">
{{contact.phone}}
</p>
</mat-cell>
</ng-container>
<mat-header-row
*cdkHeaderRowDef="widgets.widget11.table.columns"></mat-header-row>
<mat-row *cdkRowDef="let contact; columns: widgets.widget11.table.columns;">
</mat-row>
</mat-table>
</div>
<!-- / Front -->
</fuse-widget>
<!-- / WIDGET 11 -->
</div>
<!-- / WIDGET GROUP -->
</mat-tab>
</mat-tab-group>
</div>
<!-- / CONTENT -->
</div>
<!-- / CENTER -->
</div>

View File

@ -1,62 +0,0 @@
#dashboard-project {
> .sidebar {
width: 280px;
min-width: 280px;
max-width: 280px;
}
> .center {
> .header {
height: 160px;
min-height: 160px;
max-height: 160px;
.selected-project {
background: rgba(0, 0, 0, 0.12);
color: #FFFFFF;
padding: 8px 16px;
height: 40px;
line-height: 24px;
font-size: 16px;
}
.project-selector {
margin-left: 1px;
border-radius: 0;
background: rgba(0, 0, 0, 0.12);
mat-icon {
color: #FFFFFF;
}
}
}
> .content {
flex: 1;
mat-tab-group {
height: 100%;
.mat-tab-body-wrapper {
flex-grow: 1;
}
}
.mat-tab-label-container {
padding: 0 24px;
}
}
}
.widget {
&.widget5 {
.gridline-path.gridline-path-horizontal {
display: none;
}
}
}
}

View File

@ -1,102 +0,0 @@
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Subject} from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { orderStatuses } from 'app/main/apps/e-commerce/order/order-statuses';
import { Order } from 'app/main/apps/e-commerce/order/order.model';
import { EcommerceOrderService } from 'app/main/apps/e-commerce/order/order.service';
@Component({
selector : 'e-commerce-order',
templateUrl : './order.component.html',
styleUrls : ['./order.component.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class EcommerceOrderComponent implements OnInit, OnDestroy
{
order: Order;
orderStatuses: any;
statusForm: FormGroup;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {EcommerceOrderService} _ecommerceOrderService
* @param {FormBuilder} _formBuilder
*/
constructor(
private _ecommerceOrderService: EcommerceOrderService,
private _formBuilder: FormBuilder
)
{
// Set the defaults
this.order = new Order();
this.orderStatuses = orderStatuses;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to update order on changes
this._ecommerceOrderService.onOrderChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(order => {
this.order = new Order(order);
});
this.statusForm = this._formBuilder.group({
newStatus: ['']
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Update status
*/
updateStatus(): void
{
const newStatusId = Number.parseInt(this.statusForm.get('newStatus').value);
if ( !newStatusId )
{
return;
}
const newStatus = this.orderStatuses.find((status) => {
return status.id === newStatusId;
});
newStatus['date'] = new Date().toString();
this.order.status.unshift(newStatus);
}
}

View File

@ -1,242 +0,0 @@
import { Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { MatPaginator, MatSort } from '@angular/material';
import { DataSource } from '@angular/cdk/collections';
import { merge, Observable, BehaviorSubject, fromEvent, Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseUtils } from '@fuse/utils';
import { EcommerceOrdersService } from 'app/main/apps/e-commerce/orders/orders.service';
import { takeUntil } from 'rxjs/internal/operators';
@Component({
selector : 'e-commerce-orders',
templateUrl: './orders.component.html',
styleUrls : ['./orders.component.scss'],
animations : fuseAnimations
})
export class EcommerceOrdersComponent implements OnInit, OnDestroy
{
dataSource: FilesDataSource | null;
displayedColumns = ['id', 'reference', 'customer', 'total', 'payment', 'status', 'date'];
@ViewChild(MatPaginator)
paginator: MatPaginator;
@ViewChild('filter')
filter: ElementRef;
@ViewChild(MatSort)
sort: MatSort;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {EcommerceOrdersService} _ecommerceOrdersService
*/
constructor(
private _ecommerceOrdersService: EcommerceOrdersService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.dataSource = new FilesDataSource(this._ecommerceOrdersService, this.paginator, this.sort);
fromEvent(this.filter.nativeElement, 'keyup')
.pipe(
takeUntil(this._unsubscribeAll),
debounceTime(150),
distinctUntilChanged()
)
.subscribe(() => {
if ( !this.dataSource )
{
return;
}
this.dataSource.filter = this.filter.nativeElement.value;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}
export class FilesDataSource extends DataSource<any>
{
// Private
private _filterChange = new BehaviorSubject('');
private _filteredDataChange = new BehaviorSubject('');
/**
* Constructor
*
* @param {EcommerceOrdersService} _ecommerceOrdersService
* @param {MatPaginator} _matPaginator
* @param {MatSort} _matSort
*/
constructor(
private _ecommerceOrdersService: EcommerceOrdersService,
private _matPaginator: MatPaginator,
private _matSort: MatSort
)
{
super();
this.filteredData = this._ecommerceOrdersService.orders;
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
// Filtered data
get filteredData(): any
{
return this._filteredDataChange.value;
}
set filteredData(value: any)
{
this._filteredDataChange.next(value);
}
// Filter
get filter(): string
{
return this._filterChange.value;
}
set filter(filter: string)
{
this._filterChange.next(filter);
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Connect function called by the table to retrieve one stream containing the data to render.
*
* @returns {Observable<any[]>}
*/
connect(): Observable<any[]>
{
const displayDataChanges = [
this._ecommerceOrdersService.onOrdersChanged,
this._matPaginator.page,
this._filterChange,
this._matSort.sortChange
];
return merge(...displayDataChanges).pipe(map(() => {
let data = this._ecommerceOrdersService.orders.slice();
data = this.filterData(data);
this.filteredData = [...data];
data = this.sortData(data);
// Grab the page's slice of data.
const startIndex = this._matPaginator.pageIndex * this._matPaginator.pageSize;
return data.splice(startIndex, this._matPaginator.pageSize);
})
);
}
/**
* Filter data
*
* @param data
* @returns {any}
*/
filterData(data): any
{
if ( !this.filter )
{
return data;
}
return FuseUtils.filterArrayByString(data, this.filter);
}
/**
* Sort data
*
* @param data
* @returns {any[]}
*/
sortData(data): any[]
{
if ( !this._matSort.active || this._matSort.direction === '' )
{
return data;
}
return data.sort((a, b) => {
let propertyA: number | string = '';
let propertyB: number | string = '';
switch ( this._matSort.active )
{
case 'id':
[propertyA, propertyB] = [a.id, b.id];
break;
case 'reference':
[propertyA, propertyB] = [a.reference, b.reference];
break;
case 'customer':
[propertyA, propertyB] = [a.customer.firstName, b.customer.firstName];
break;
case 'total':
[propertyA, propertyB] = [a.total, b.total];
break;
case 'payment':
[propertyA, propertyB] = [a.payment.method, b.payment.method];
break;
case 'status':
[propertyA, propertyB] = [a.status[0].name, b.status[0].name];
break;
case 'date':
[propertyA, propertyB] = [a.date, b.date];
break;
}
const valueA = isNaN(+propertyA) ? propertyA : +propertyA;
const valueB = isNaN(+propertyB) ? propertyB : +propertyB;
return (valueA < valueB ? -1 : 1) * (this._matSort.direction === 'asc' ? 1 : -1);
});
}
/**
* Disconnect
*/
disconnect(): void
{
}
}

View File

@ -1,171 +0,0 @@
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Location } from '@angular/common';
import { MatSnackBar } from '@angular/material';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseUtils } from '@fuse/utils';
import { Product } from 'app/main/apps/e-commerce/product/product.model';
import { EcommerceProductService } from 'app/main/apps/e-commerce/product/product.service';
@Component({
selector : 'e-commerce-product',
templateUrl : './product.component.html',
styleUrls : ['./product.component.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class EcommerceProductComponent implements OnInit, OnDestroy
{
product: Product;
pageType: string;
productForm: FormGroup;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {EcommerceProductService} _ecommerceProductService
* @param {FormBuilder} _formBuilder
* @param {Location} _location
* @param {MatSnackBar} _matSnackBar
*/
constructor(
private _ecommerceProductService: EcommerceProductService,
private _formBuilder: FormBuilder,
private _location: Location,
private _matSnackBar: MatSnackBar
)
{
// Set the default
this.product = new Product();
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to update product on changes
this._ecommerceProductService.onProductChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(product => {
if ( product )
{
this.product = new Product(product);
this.pageType = 'edit';
}
else
{
this.pageType = 'new';
this.product = new Product();
}
this.productForm = this.createProductForm();
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Create product form
*
* @returns {FormGroup}
*/
createProductForm(): FormGroup
{
return this._formBuilder.group({
id : [this.product.id],
name : [this.product.name],
handle : [this.product.handle],
description : [this.product.description],
categories : [this.product.categories],
tags : [this.product.tags],
images : [this.product.images],
priceTaxExcl : [this.product.priceTaxExcl],
priceTaxIncl : [this.product.priceTaxIncl],
taxRate : [this.product.taxRate],
comparedPrice : [this.product.comparedPrice],
quantity : [this.product.quantity],
sku : [this.product.sku],
width : [this.product.width],
height : [this.product.height],
depth : [this.product.depth],
weight : [this.product.weight],
extraShippingFee: [this.product.extraShippingFee],
active : [this.product.active]
});
}
/**
* Save product
*/
saveProduct(): void
{
const data = this.productForm.getRawValue();
data.handle = FuseUtils.handleize(data.name);
this._ecommerceProductService.saveProduct(data)
.then(() => {
// Trigger the subscription with new data
this._ecommerceProductService.onProductChanged.next(data);
// Show the success message
this._matSnackBar.open('Product saved', 'OK', {
verticalPosition: 'top',
duration : 2000
});
});
}
/**
* Add product
*/
addProduct(): void
{
const data = this.productForm.getRawValue();
data.handle = FuseUtils.handleize(data.name);
this._ecommerceProductService.addProduct(data)
.then(() => {
// Trigger the subscription with new data
this._ecommerceProductService.onProductChanged.next(data);
// Show the success message
this._matSnackBar.open('Product added', 'OK', {
verticalPosition: 'top',
duration : 2000
});
// Change the location with new one
this._location.go('apps/e-commerce/products/' + this.product.id + '/' + this.product.handle);
});
}
}

View File

@ -1,224 +0,0 @@
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { MatPaginator, MatSort } from '@angular/material';
import { DataSource } from '@angular/cdk/collections';
import { merge, Observable, BehaviorSubject, fromEvent, Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseUtils } from '@fuse/utils';
import { EcommerceProductsService } from 'app/main/apps/e-commerce/products/products.service';
import { takeUntil } from 'rxjs/internal/operators';
@Component({
selector : 'e-commerce-products',
templateUrl: './products.component.html',
styleUrls : ['./products.component.scss'],
animations : fuseAnimations
})
export class EcommerceProductsComponent implements OnInit
{
dataSource: FilesDataSource | null;
displayedColumns = ['id', 'image', 'name', 'category', 'price', 'quantity', 'active'];
@ViewChild(MatPaginator)
paginator: MatPaginator;
@ViewChild(MatSort)
sort: MatSort;
@ViewChild('filter')
filter: ElementRef;
// Private
private _unsubscribeAll: Subject<any>;
constructor(
private _ecommerceProductsService: EcommerceProductsService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.dataSource = new FilesDataSource(this._ecommerceProductsService, this.paginator, this.sort);
fromEvent(this.filter.nativeElement, 'keyup')
.pipe(
takeUntil(this._unsubscribeAll),
debounceTime(150),
distinctUntilChanged()
)
.subscribe(() => {
if ( !this.dataSource )
{
return;
}
this.dataSource.filter = this.filter.nativeElement.value;
});
}
}
export class FilesDataSource extends DataSource<any>
{
private _filterChange = new BehaviorSubject('');
private _filteredDataChange = new BehaviorSubject('');
/**
* Constructor
*
* @param {EcommerceProductsService} _ecommerceProductsService
* @param {MatPaginator} _matPaginator
* @param {MatSort} _matSort
*/
constructor(
private _ecommerceProductsService: EcommerceProductsService,
private _matPaginator: MatPaginator,
private _matSort: MatSort
)
{
super();
this.filteredData = this._ecommerceProductsService.products;
}
/**
* Connect function called by the table to retrieve one stream containing the data to render.
*
* @returns {Observable<any[]>}
*/
connect(): Observable<any[]>
{
const displayDataChanges = [
this._ecommerceProductsService.onProductsChanged,
this._matPaginator.page,
this._filterChange,
this._matSort.sortChange
];
return merge(...displayDataChanges)
.pipe(
map(() => {
let data = this._ecommerceProductsService.products.slice();
data = this.filterData(data);
this.filteredData = [...data];
data = this.sortData(data);
// Grab the page's slice of data.
const startIndex = this._matPaginator.pageIndex * this._matPaginator.pageSize;
return data.splice(startIndex, this._matPaginator.pageSize);
}
));
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
// Filtered data
get filteredData(): any
{
return this._filteredDataChange.value;
}
set filteredData(value: any)
{
this._filteredDataChange.next(value);
}
// Filter
get filter(): string
{
return this._filterChange.value;
}
set filter(filter: string)
{
this._filterChange.next(filter);
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Filter data
*
* @param data
* @returns {any}
*/
filterData(data): any
{
if ( !this.filter )
{
return data;
}
return FuseUtils.filterArrayByString(data, this.filter);
}
/**
* Sort data
*
* @param data
* @returns {any[]}
*/
sortData(data): any[]
{
if ( !this._matSort.active || this._matSort.direction === '' )
{
return data;
}
return data.sort((a, b) => {
let propertyA: number | string = '';
let propertyB: number | string = '';
switch ( this._matSort.active )
{
case 'id':
[propertyA, propertyB] = [a.id, b.id];
break;
case 'name':
[propertyA, propertyB] = [a.name, b.name];
break;
case 'categories':
[propertyA, propertyB] = [a.categories[0], b.categories[0]];
break;
case 'price':
[propertyA, propertyB] = [a.priceTaxIncl, b.priceTaxIncl];
break;
case 'quantity':
[propertyA, propertyB] = [a.quantity, b.quantity];
break;
case 'active':
[propertyA, propertyB] = [a.active, b.active];
break;
}
const valueA = isNaN(+propertyA) ? propertyA : +propertyA;
const valueB = isNaN(+propertyB) ? propertyB : +propertyB;
return (valueA < valueB ? -1 : 1) * (this._matSort.direction === 'asc' ? 1 : -1);
});
}
/**
* Disconnect
*/
disconnect(): void
{
}
}

View File

@ -1,131 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { DataSource } from '@angular/cdk/collections';
import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
import { FileManagerService } from 'app/main/apps/file-manager/file-manager.service';
@Component({
selector : 'file-list',
templateUrl: './file-list.component.html',
styleUrls : ['./file-list.component.scss'],
animations : fuseAnimations
})
export class FileManagerFileListComponent implements OnInit, OnDestroy
{
files: any;
dataSource: FilesDataSource | null;
displayedColumns = ['icon', 'name', 'type', 'owner', 'size', 'modified', 'detail-button'];
selected: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FileManagerService} _fileManagerService
* @param {FuseSidebarService} _fuseSidebarService
*/
constructor(
private _fileManagerService: FileManagerService,
private _fuseSidebarService: FuseSidebarService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.dataSource = new FilesDataSource(this._fileManagerService);
this._fileManagerService.onFilesChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(files => {
this.files = files;
});
this._fileManagerService.onFileSelected
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(selected => {
this.selected = selected;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* On select
*
* @param selected
*/
onSelect(selected): void
{
this._fileManagerService.onFileSelected.next(selected);
}
/**
* Toggle the sidebar
*
* @param name
*/
toggleSidebar(name): void
{
this._fuseSidebarService.getSidebar(name).toggleOpen();
}
}
export class FilesDataSource extends DataSource<any>
{
/**
* Constructor
*
* @param {FileManagerService} _fileManagerService
*/
constructor(
private _fileManagerService: FileManagerService
)
{
super();
}
/**
* Connect function called by the table to retrieve one stream containing the data to render.
*
* @returns {Observable<any[]>}
*/
connect(): Observable<any[]>
{
return this._fileManagerService.onFilesChanged;
}
/**
* Disconnect
*/
disconnect(): void
{
}
}

View File

@ -1,75 +0,0 @@
<div id="file-manager" class="page-layout simple right-sidebar inner-scroll">
<!-- SIDEBAR -->
<fuse-sidebar class="sidebar main-sidebar" name="file-manager-main-sidebar" position="left">
<file-manager-main-sidebar></file-manager-main-sidebar>
</fuse-sidebar>
<!-- / SIDEBAR -->
<!-- CENTER -->
<div class="center" fxFlex>
<!-- HEADER -->
<div class="header mat-accent-bg p-24" fxLayout="column" fxLayoutAlign="space-between start">
<!-- TOOLBAR -->
<div class="toolbar w-100-p" fxFlex fxLayout="row" fxLayoutAlign="space-between start">
<div class="left-side" fxLayout="row">
<button mat-icon-button class="sidebar-toggle"
(click)="toggleSidebar('file-manager-main-sidebar')">
<mat-icon>menu</mat-icon>
</button>
</div>
<div class="right-side" fxLayout="row">
<button mat-icon-button aria-label="Search" matTooltip="Search">
<mat-icon>search</mat-icon>
</button>
</div>
</div>
<!-- / TOOLBAR -->
<!-- BREADCRUMB -->
<div class="breadcrumb text-truncate h1 pl-72" fxLayout="row" fxLayoutAlign="start center"
[@animate]="{value:'*',params:{x:'50px'}}">
<div *ngFor="let path of pathArr; last as isLast" fxLayout="row" fxLayoutAlign="start center">
<span>{{path}}</span>
<mat-icon *ngIf="!isLast" class="separator">chevron_right</mat-icon>
</div>
</div>
<!-- / BREADCRUMB -->
<!-- ADD FILE BUTTON -->
<div class="file-uploader">
<input hidden type="file" #fileInput/>
<button mat-fab
class="add-file-button mat-warn"
(click)="fileInput.click()"
aria-label="Add file"
[@animate]="{value:'*', params:{delay:'300ms',scale:'0.2'}}">
<mat-icon>add</mat-icon>
</button>
</div>
<!-- / ADD FILE BUTTON -->
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content mat-white-bg" fusePerfectScrollbar>
<file-list></file-list>
</div>
<!-- / CONTENT -->
</div>
<!-- / CENTER -->
<!-- SIDEBAR -->
<fuse-sidebar class="sidebar details-sidebar" name="file-manager-details-sidebar" position="right"
lockedOpen="gt-md">
<file-manager-details-sidebar></file-manager-details-sidebar>
</fuse-sidebar>
<!-- / SIDEBAR -->
</div>

View File

@ -1,72 +0,0 @@
@import "src/@fuse/scss/fuse";
#file-manager {
.sidebar {
width: 320px !important;
min-width: 320px !important;
max-width: 320px !important;
&.main-sidebar {
}
&.details-sidebar {
@include media-breakpoint('gt-md') {
z-index: 0;
}
}
}
.center {
overflow: hidden;
.header {
position: relative;
height: 160px;
min-height: 160px;
max-height: 160px;
@include media-breakpoint-down('sm') {
height: 120px;
min-height: 120px;
max-height: 120px;
}
.add-file-button {
position: absolute;
bottom: -28px;
left: 16px;
z-index: 999;
}
}
.content {
flex: 1 1 auto;
overflow: auto;
}
}
.type-icon {
&.folder {
&:before {
content: 'folder';
color: #FFB300;
}
}
&.document {
&:before {
content: 'insert_drive_file';
color: #1565C0;
}
}
&.spreadsheet {
&:before {
content: 'insert_chart';
color: #4CAF50;
}
}
}
}

View File

@ -1,80 +0,0 @@
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
import { FileManagerService } from 'app/main/apps/file-manager/file-manager.service';
@Component({
selector : 'file-manager',
templateUrl : './file-manager.component.html',
styleUrls : ['./file-manager.component.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class FileManagerComponent implements OnInit, OnDestroy
{
selected: any;
pathArr: string[];
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FileManagerService} _fileManagerService
* @param {FuseSidebarService} _fuseSidebarService
*/
constructor(
private _fileManagerService: FileManagerService,
private _fuseSidebarService: FuseSidebarService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._fileManagerService.onFileSelected
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(selected => {
this.selected = selected;
this.pathArr = selected.location.split('>');
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle the sidebar
*
* @param name
*/
toggleSidebar(name): void
{
this._fuseSidebarService.getSidebar(name).toggleOpen();
}
}

View File

@ -1,52 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CdkTableModule } from '@angular/cdk/table';
import { MatButtonModule, MatIconModule, MatRippleModule, MatSlideToggleModule, MatTableModule } from '@angular/material';
import { FuseSharedModule } from '@fuse/shared.module';
import { FuseSidebarModule } from '@fuse/components';
import { FileManagerService } from 'app/main/apps/file-manager/file-manager.service';
import { FileManagerComponent } from 'app/main/apps/file-manager/file-manager.component';
import { FileManagerDetailsSidebarComponent } from 'app/main/apps/file-manager/sidebars/details/details.component';
import { FileManagerFileListComponent } from 'app/main/apps/file-manager/file-list/file-list.component';
import { FileManagerMainSidebarComponent } from 'app/main/apps/file-manager/sidebars/main/main.component';
const routes: Routes = [
{
path : '**',
component: FileManagerComponent,
children : [],
resolve : {
files: FileManagerService
}
}
];
@NgModule({
declarations: [
FileManagerComponent,
FileManagerFileListComponent,
FileManagerMainSidebarComponent,
FileManagerDetailsSidebarComponent
],
imports : [
RouterModule.forChild(routes),
CdkTableModule,
MatButtonModule,
MatIconModule,
MatRippleModule,
MatSlideToggleModule,
MatTableModule,
FuseSharedModule,
FuseSidebarModule
],
providers : [
FileManagerService
]
})
export class FileManagerModule
{
}

View File

@ -1,60 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FileManagerService } from 'app/main/apps/file-manager/file-manager.service';
@Component({
selector : 'file-manager-details-sidebar',
templateUrl: './details.component.html',
styleUrls : ['./details.component.scss'],
animations : fuseAnimations
})
export class FileManagerDetailsSidebarComponent implements OnInit, OnDestroy
{
selected: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FileManagerService} _fileManagerService
*/
constructor(
private _fileManagerService: FileManagerService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._fileManagerService.onFileSelected
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(selected => {
this.selected = selected;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -1,57 +0,0 @@
import { Component, Inject, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
@Component({
selector : 'mail-ngrx-compose',
templateUrl : './compose.component.html',
styleUrls : ['./compose.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class MailNgrxComposeDialogComponent
{
composeForm: FormGroup;
/**
* Constructor
*
* @param {MatDialogRef<MailNgrxComposeDialogComponent>} matDialogRef
* @param _data
* @param {FormBuilder} _formBuilder
*/
constructor(
public matDialogRef: MatDialogRef<MailNgrxComposeDialogComponent>,
@Inject(MAT_DIALOG_DATA) private _data: any,
private _formBuilder: FormBuilder
)
{
// Set the defaults
this.composeForm = this.createComposeForm();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Create compose form
*
* @returns {FormGroup}
*/
createComposeForm(): FormGroup
{
return this._formBuilder.group({
from : {
value : ['johndoe@creapond.com'],
disabled: [true]
},
to : [''],
cc : [''],
bcc : [''],
subject: [''],
message: ['']
});
}
}

View File

@ -1,111 +0,0 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { Mail } from 'app/main/apps/mail-ngrx/mail.model';
import * as fromStore from 'app/main/apps/mail-ngrx/store';
import { MailNgrxService } from 'app/main/apps/mail-ngrx/mail.service';
@Component({
selector : 'mail-ngrx-details',
templateUrl : './mail-details.component.html',
styleUrls : ['./mail-details.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MailNgrxDetailsComponent implements OnChanges
{
@Input('mail')
mailInput: Mail;
labels$: Observable<any>;
mail: Mail;
showDetails: boolean;
/**
* Constructor
*
* @param {MailNgrxService} _mailNgrxService
* @param {Store<MailAppState>} _store
*/
constructor(
private _mailNgrxService: MailNgrxService,
private _store: Store<fromStore.MailAppState>
)
{
// Set the defaults
this.labels$ = this._store.select(fromStore.getLabelsArr);
this.showDetails = false;
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On changes
*/
ngOnChanges(): void
{
this.updateModel(this.mailInput);
this.markAsRead();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Mark as read
*/
markAsRead(): void
{
if ( this.mail && !this.mail.read )
{
this.mail.markRead();
this.updateMail();
}
}
/**
* Toggle star
*
* @param event
*/
toggleStar(event): void
{
event.stopPropagation();
this.mail.toggleStar();
this.updateMail();
}
/**
* Toggle important
*
* @param event
*/
toggleImportant(event): void
{
event.stopPropagation();
this.mail.toggleImportant();
this.updateMail();
}
/**
* Update model
*
* @param data
*/
updateModel(data): void
{
this.mail = !data ? null : new Mail({...data});
}
/**
* Update the mail
*/
updateMail(): void
{
this._store.dispatch(new fromStore.UpdateMail(this.mail));
this.updateModel(this.mail);
}
}

View File

@ -1,64 +0,0 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Mail } from 'app/main/apps/mail-ngrx/mail.model';
import { MailNgrxService } from 'app/main/apps/mail-ngrx/mail.service';
@Component({
selector : 'mail-ngrx-list',
templateUrl : './mail-list.component.html',
styleUrls : ['./mail-list.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MailNgrxListComponent
{
@Input()
mails: Mail[];
@Input()
currentMail: Mail[];
/**
* Constructor
*
* @param {ActivatedRoute} _activatedRoute
* @param {MailNgrxService} _mailNgrxService
* @param {Router} _router
*/
constructor(
private _activatedRoute: ActivatedRoute,
private _mailNgrxService: MailNgrxService,
private _router: Router
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Read mail
*
* @param mailId
*/
readMail(mailId): void
{
const labelHandle = this._activatedRoute.snapshot.params.labelHandle,
filterHandle = this._activatedRoute.snapshot.params.filterHandle,
folderHandle = this._activatedRoute.snapshot.params.folderHandle;
if ( labelHandle )
{
this._router.navigate(['apps/mail-ngrx/label/' + labelHandle + '/' + mailId]);
}
else if ( filterHandle )
{
this._router.navigate(['apps/mail-ngrx/filter/' + filterHandle + '/' + mailId]);
}
else
{
this._router.navigate(['apps/mail-ngrx/' + folderHandle + '/' + mailId]);
}
}
}

View File

@ -1,109 +0,0 @@
<div id="mail" class="page-layout carded left-sidebar inner-scroll">
<!-- TOP BACKGROUND -->
<div class="top-bg mat-accent-bg"></div>
<!-- / TOP BACKGROUND -->
<!-- SIDEBAR -->
<fuse-sidebar class="sidebar" name="mail-ngrx-main-sidebar" position="left" lockedOpen="gt-md">
<mail-ngrx-main-sidebar></mail-ngrx-main-sidebar>
</fuse-sidebar>
<!-- / SIDEBAR -->
<!-- CENTER -->
<div class="center">
<!-- CONTENT HEADER -->
<div class="header" fxLayout="row" fxLayoutAlign="start center">
<div class="search-wrapper" fxFlex fxLayout="row" fxLayoutAlign="start center">
<button mat-icon-button class="sidebar-toggle" fxHide.gt-md
(click)="toggleSidebar('mail-ngrx-main-sidebar')">
<mat-icon>menu</mat-icon>
</button>
<div class="search mat-white-bg" flex fxLayout="row" fxLayoutAlign="start center">
<mat-icon>search</mat-icon>
<input [formControl]="searchInput" [placeholder]="'MAIL.SEARCH_PLACEHOLDER' | translate" fxFlex>
</div>
</div>
</div>
<!-- / CONTENT HEADER -->
<!-- CONTENT CARD -->
<div class="content-card mat-white-bg" [ngClass]="{'current-mail-selected':currentMail$ | async}">
<!-- CONTENT TOOLBAR -->
<div class="toolbar px-24 py-8">
<div class="mail-selection" fxFlex="row" fxLayoutAlign="start center">
<mat-checkbox (click)="toggleSelectAll($event)"
[checked]="hasSelectedMails"
[indeterminate]="isIndeterminate">
</mat-checkbox>
<button mat-icon-button [matMenuTriggerFor]="selectMenu">
<mat-icon>arrow_drop_down</mat-icon>
</button>
<mat-menu #selectMenu="matMenu">
<button mat-menu-item (click)="selectAllMails()">All</button>
<button mat-menu-item (click)="deselectAllMails()">None</button>
<button mat-menu-item (click)="selectMailsByParameter('read', true)">Read</button>
<button mat-menu-item (click)="selectMailsByParameter('read', false)">Unread</button>
<button mat-menu-item (click)="selectMailsByParameter('starred', true)">Starred</button>
<button mat-menu-item (click)="selectMailsByParameter('starred', false)">Unstarred</button>
<button mat-menu-item (click)="selectMailsByParameter('important', true)">Important</button>
<button mat-menu-item (click)="selectMailsByParameter('important', false)">Unimportant</button>
</mat-menu>
<div class="toolbar-separator" *ngIf="hasSelectedMails"></div>
<button mat-icon-button (click)="setFolderOnSelectedMails(4)" *ngIf="hasSelectedMails">
<mat-icon class="secondary-text">delete</mat-icon>
</button>
<button mat-icon-button [matMenuTriggerFor]="folderMenu" *ngIf="hasSelectedMails">
<mat-icon class="secondary-text">folder</mat-icon>
</button>
<mat-menu #folderMenu="matMenu">
<button mat-menu-item *ngFor="let folder of folders$ | async"
(click)="setFolderOnSelectedMails(folder.id)">{{folder.title}}
</button>
</mat-menu>
<button mat-icon-button [matMenuTriggerFor]="labelMenu" *ngIf="hasSelectedMails">
<mat-icon class="secondary-text">label</mat-icon>
</button>
<mat-menu #labelMenu="matMenu">
<button mat-menu-item *ngFor="let label of labels$ | async"
(click)="toggleLabelOnSelectedMails(label.id)">{{label.title}}
</button>
</mat-menu>
</div>
<div *ngIf="currentMail$ | async" fxHide.gt-xs>
<button mat-icon-button (click)="deselectCurrentMail()">
<mat-icon class="secondary-text">arrow_back</mat-icon>
</button>
</div>
</div>
<!-- / CONTENT TOOLBAR -->
<!-- CONTENT -->
<div class="content" fxLayout="row">
<mail-ngrx-list fusePerfectScrollbar fxFlex [mails]="mails$ | async" [currentMail]="currentMail$ | async"></mail-ngrx-list>
<mail-ngrx-details [mail]="currentMail$ | async" fusePerfectScrollbar fxFlex></mail-ngrx-details>
</div>
<!-- / CONTENT -->
</div>
<!-- / CONTENT CARD -->
</div>
<!-- / CENTER -->
</div>

View File

@ -1,206 +0,0 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
import { FuseTranslationLoaderService } from '@fuse/services/translation-loader.service';
import { Mail } from 'app/main/apps/mail-ngrx/mail.model';
import { MailNgrxService } from 'app/main/apps/mail-ngrx/mail.service';
import * as fromStore from 'app/main/apps/mail-ngrx/store';
import { locale as english } from 'app/main/apps/mail-ngrx/i18n/en';
import { locale as turkish } from 'app/main/apps/mail-ngrx/i18n/tr';
@Component({
selector : 'mail-ngrx',
templateUrl : './mail.component.html',
styleUrls : ['./mail.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MailNgrxComponent implements OnInit, OnDestroy
{
hasSelectedMails: boolean;
isIndeterminate: boolean;
searchInput: FormControl;
mails$: Observable<any>;
folders$: Observable<any>;
labels$: Observable<any>;
currentMail$: Observable<Mail>;
selectedMailIds$: Observable<string[]>;
searchText$: Observable<string>;
mails: Mail[];
selectedMailIds: string[];
/**
* Constructor
*
* @param {ChangeDetectorRef} _changeDetectorRef
* @param {FuseSidebarService} _fuseSidebarService
* @param {FuseTranslationLoaderService} _fuseTranslationLoaderService
* @param {MailNgrxService} _mailNgrxService
* @param {Store<MailAppState>} _store
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseSidebarService: FuseSidebarService,
private _fuseTranslationLoaderService: FuseTranslationLoaderService,
private _mailNgrxService: MailNgrxService,
private _store: Store<fromStore.MailAppState>
)
{
// Set the defaults
this.searchInput = new FormControl('');
this._fuseTranslationLoaderService.loadTranslations(english, turkish);
this.currentMail$ = this._store.select(fromStore.getCurrentMail);
this.mails$ = this._store.select(fromStore.getMailsArr);
this.folders$ = this._store.select(fromStore.getFoldersArr);
this.labels$ = this._store.select(fromStore.getLabelsArr);
this.selectedMailIds$ = this._store.select(fromStore.getSelectedMailIds);
this.searchText$ = this._store.select(fromStore.getSearchText);
this.mails = [];
this.selectedMailIds = [];
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.mails$.subscribe(mails => {
this.mails = mails;
});
this.selectedMailIds$
.subscribe(selectedMailIds => {
this.selectedMailIds = selectedMailIds;
this.hasSelectedMails = selectedMailIds.length > 0;
this.isIndeterminate = (selectedMailIds.length !== this.mails.length && selectedMailIds.length > 0);
this.refresh();
});
this.searchText$.subscribe(searchText => {
this.searchInput.setValue(searchText);
});
this.searchInput.valueChanges.pipe(
debounceTime(300),
distinctUntilChanged()
).subscribe(searchText => {
this._store.dispatch(new fromStore.SetSearchText(searchText));
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
this._changeDetectorRef.detach();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle select all
*
* @param ev
*/
toggleSelectAll(ev): void
{
ev.preventDefault();
if ( this.selectedMailIds.length && this.selectedMailIds.length > 0 )
{
this.deselectAllMails();
}
else
{
this.selectAllMails();
}
}
/**
* Select all mails
*/
selectAllMails(): void
{
this._store.dispatch(new fromStore.SelectAllMails());
}
/**
* Deselect all mails
*/
deselectAllMails(): void
{
this._store.dispatch(new fromStore.DeselectAllMails());
}
/**
* Select mails by parameter
*
* @param parameter
* @param value
*/
selectMailsByParameter(parameter, value): void
{
this._store.dispatch(new fromStore.SelectMailsByParameter({
parameter,
value
}));
}
/**
* Toggle label on selected mails
*
* @param labelId
*/
toggleLabelOnSelectedMails(labelId): void
{
this._store.dispatch(new fromStore.AddLabelOnSelectedMails(labelId));
}
/**
* Set folder on selected mails
*
* @param folderId
*/
setFolderOnSelectedMails(folderId): void
{
this._store.dispatch(new fromStore.SetFolderOnSelectedMails(folderId));
}
/**
* Deselect current mail
*/
deselectCurrentMail(): void
{
this._store.dispatch(new fromStore.SetCurrentMail(''));
}
/**
* Refresh
*/
refresh(): void
{
this._changeDetectorRef.markForCheck();
}
/**
* Toggle the sidebar
*
* @param name
*/
toggleSidebar(name): void
{
this._fuseSidebarService.getSidebar(name).toggleOpen();
}
}

View File

@ -1,94 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MatButtonModule, MatCheckboxModule, MatDialogModule, MatFormFieldModule, MatIconModule, MatInputModule, MatMenuModule, MatRippleModule, MatSelectModule, MatToolbarModule } from '@angular/material';
import { TranslateModule } from '@ngx-translate/core';
import { FuseSharedModule } from '@fuse/shared.module';
import { FuseSidebarModule } from '@fuse/components';
import * as fromGuards from 'app/main/apps/mail-ngrx/store/guards/index';
import { MailNgrxStoreModule } from 'app/main/apps/mail-ngrx/store/store.module';
import { MailNgrxComponent } from 'app/main/apps/mail-ngrx/mail.component';
import { MailNgrxListComponent } from 'app/main/apps/mail-ngrx/mail-list/mail-list.component';
import { MailNgrxListItemComponent } from 'app/main/apps/mail-ngrx/mail-list/mail-list-item/mail-list-item.component';
import { MailNgrxDetailsComponent } from 'app/main/apps/mail-ngrx/mail-details/mail-details.component';
import { MailNgrxMainSidebarComponent } from 'app/main/apps/mail-ngrx/sidebars/main/main-sidebar.component';
import { MailNgrxComposeDialogComponent } from 'app/main/apps/mail-ngrx/dialogs/compose/compose.component';
import { MailNgrxService } from 'app/main/apps/mail-ngrx/mail.service';
const routes: Routes = [
{
path : 'label/:labelHandle',
component : MailNgrxComponent,
canActivate: [fromGuards.ResolveGuard]
},
{
path : 'label/:labelHandle/:mailId',
component : MailNgrxComponent,
canActivate: [fromGuards.ResolveGuard]
},
{
path : 'filter/:filterHandle',
component : MailNgrxComponent,
canActivate: [fromGuards.ResolveGuard]
},
{
path : 'filter/:filterHandle/:mailId',
component : MailNgrxComponent,
canActivate: [fromGuards.ResolveGuard]
},
{
path : ':folderHandle',
component : MailNgrxComponent,
canActivate: [fromGuards.ResolveGuard]
},
{
path : ':folderHandle/:mailId',
component : MailNgrxComponent,
canActivate: [fromGuards.ResolveGuard]
},
{
path : '**',
redirectTo: 'inbox'
}
];
@NgModule({
declarations : [
MailNgrxComponent,
MailNgrxListComponent,
MailNgrxListItemComponent,
MailNgrxDetailsComponent,
MailNgrxMainSidebarComponent,
MailNgrxComposeDialogComponent
],
imports : [
RouterModule.forChild(routes),
MatButtonModule,
MatCheckboxModule,
MatDialogModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatMenuModule,
MatRippleModule,
MatSelectModule,
MatToolbarModule,
TranslateModule,
FuseSharedModule,
FuseSidebarModule,
MailNgrxStoreModule
],
providers : [
MailNgrxService,
fromGuards.ResolveGuard
],
entryComponents: [MailNgrxComposeDialogComponent]
})
export class MailNgrxModule
{
}

View File

@ -1,123 +0,0 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { Mail } from 'app/main/apps/mail-ngrx/mail.model';
import { MailAppState } from 'app/main/apps/mail-ngrx/store/reducers';
import { getFiltersArr, getFoldersArr, getLabelsArr, getMailsArr } from 'app/main/apps/mail-ngrx/store/selectors';
@Injectable()
export class MailNgrxService
{
foldersArr: any;
filtersArr: any;
labelsArr: any;
selectedMails: Mail[];
mails: Mail[];
/**
* Constructor
*
* @param {HttpClient} _httpClient
* @param {Store<MailAppState>} _store
*/
constructor(
private _httpClient: HttpClient,
private _store: Store<MailAppState>
)
{
this._store.select(getFoldersArr).subscribe(folders => {
this.foldersArr = folders;
});
this._store.select(getFiltersArr).subscribe(filters => {
this.filtersArr = filters;
});
this._store.select(getLabelsArr).subscribe(labels => {
this.labelsArr = labels;
});
this._store.select(getMailsArr).subscribe(mails => {
this.mails = mails;
});
this.selectedMails = [];
}
/**
* Get all mails
*
* @returns {Observable<Mail[]>}
*/
getAllMails(): Observable<Mail[]>
{
return this._httpClient.get<Mail[]>('api/mail-mails');
}
/**
* Get folders
*
* @returns {Observable<any>}
*/
getFolders(): Observable<any>
{
return this._httpClient.get('api/mail-folders');
}
/**
* Get filters
*
* @returns {Observable<any>}
*/
getFilters(): Observable<any>
{
return this._httpClient.get('api/mail-filters');
}
/**
* Get labels
*
* @returns {Observable<any>}
*/
getLabels(): Observable<any>
{
return this._httpClient.get('api/mail-labels');
}
/**
* Get mails
*
* @param handle
* @returns {Observable<Mail[]>}
*/
getMails(handle): Observable<Mail[]>
{
if ( handle.id === 'labelHandle' )
{
const labelId = this.labelsArr.find(label => label.handle === handle.value).id;
return this._httpClient.get<Mail[]>('api/mail-mails?labels=' + labelId);
}
else if ( handle.id === 'filterHandle' )
{
return this._httpClient.get<Mail[]>('api/mail-mails?' + handle.value + '=true');
}
else // folderHandle
{
const folderId = this.foldersArr.find(folder => folder.handle === handle.value).id;
return this._httpClient.get<any>('api/mail-mails?folder=' + folderId);
}
}
/**
* Update the mail
*
* @param mail
* @returns {Promise<any>}
*/
updateMail(mail): any
{
return this._httpClient.post('api/mail-mails/' + mail.id, {...mail});
}
}

View File

@ -1,90 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { MatDialog } from '@angular/material';
import { FormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { MailNgrxService } from 'app/main/apps/mail-ngrx/mail.service';
import * as fromStore from 'app/main/apps/mail-ngrx/store';
import { MailNgrxComposeDialogComponent } from 'app/main/apps/mail-ngrx/dialogs/compose/compose.component';
@Component({
selector : 'mail-ngrx-main-sidebar',
templateUrl : './main-sidebar.component.html',
styleUrls : ['./main-sidebar.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MailNgrxMainSidebarComponent
{
labels: any[];
accounts: object;
selectedAccount: string;
dialogRef: any;
folders$: Observable<any>;
filters$: Observable<any>;
labels$: Observable<any>;
/**
* Constructor
*
* @param {MailNgrxService} _mailNgrxService
* @param {MatDialog} _matDialog
* @param {Store<MailAppState>} _store
*/
constructor(
private _mailNgrxService: MailNgrxService,
private _matDialog: MatDialog,
private _store: Store<fromStore.MailAppState>
)
{
// Set the defaults
this.accounts = {
'creapond' : 'johndoe@creapond.com',
'withinpixels': 'johndoe@withinpixels.com'
};
this.selectedAccount = 'creapond';
this.folders$ = this._store.select(fromStore.getFoldersArr);
this.filters$ = this._store.select(fromStore.getFiltersArr);
this.labels$ = this._store.select(fromStore.getLabelsArr);
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Compose dialog
*/
composeDialog(): void
{
this.dialogRef = this._matDialog.open(MailNgrxComposeDialogComponent, {
panelClass: 'mail-ngrx-compose-dialog'
});
this.dialogRef.afterClosed()
.subscribe(response => {
if ( !response )
{
return;
}
const actionType: string = response[0];
const formData: FormGroup = response[1];
switch ( actionType )
{
/**
* Send
*/
case 'send':
console.log('new Mail', formData.getRawValue());
break;
/**
* Delete
*/
case 'delete':
console.log('delete Mail');
break;
}
});
}
}

View File

@ -1,106 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { Mail } from 'app/main/apps/mail/mail.model';
import { MailService } from 'app/main/apps/mail/mail.service';
@Component({
selector : 'mail-details',
templateUrl: './mail-details.component.html',
styleUrls : ['./mail-details.component.scss'],
animations : fuseAnimations
})
export class MailDetailsComponent implements OnInit, OnDestroy
{
mail: Mail;
labels: any[];
showDetails: boolean;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {MailService} _mailService
*/
constructor(
private _mailService: MailService
)
{
// Set the defaults
this.showDetails = false;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to update the current mail
this._mailService.onCurrentMailChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(currentMail => {
this.mail = currentMail;
});
// Subscribe to update on label change
this._mailService.onLabelsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(labels => {
this.labels = labels;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle star
*
* @param event
*/
toggleStar(event): void
{
event.stopPropagation();
this.mail.toggleStar();
this._mailService.updateMail(this.mail);
}
/**
* Toggle important
*
* @param event
*/
toggleImportant(event): void
{
event.stopPropagation();
this.mail.toggleImportant();
this._mailService.updateMail(this.mail);
}
}

View File

@ -1,125 +0,0 @@
import { Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Mail } from 'app/main/apps/mail/mail.model';
import { MailService } from 'app/main/apps/mail/mail.service';
@Component({
selector : 'mail-list-item',
templateUrl: './mail-list-item.component.html',
styleUrls : ['./mail-list-item.component.scss']
})
export class MailListItemComponent implements OnInit, OnDestroy
{
@Input() mail: Mail;
labels: any[];
@HostBinding('class.selected')
selected: boolean;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {MailService} _mailService
*/
constructor(
private _mailService: MailService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Set the initial values
this.mail = new Mail(this.mail);
// Subscribe to update on selected mail change
this._mailService.onSelectedMailsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(selectedMails => {
this.selected = false;
if ( selectedMails.length > 0 )
{
for ( const mail of selectedMails )
{
if ( mail.id === this.mail.id )
{
this.selected = true;
break;
}
}
}
});
// Subscribe to update on label change
this._mailService.onLabelsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(labels => {
this.labels = labels;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* On selected change
*/
onSelectedChange(): void
{
this._mailService.toggleSelectedMail(this.mail.id);
}
/**
* Toggle star
*
* @param event
*/
toggleStar(event): void
{
event.stopPropagation();
this.mail.toggleStar();
this._mailService.updateMail(this.mail);
}
/**
* Toggle Important
*
* @param event
*/
toggleImportant(event): void
{
event.stopPropagation();
this.mail.toggleImportant();
this._mailService.updateMail(this.mail);
}
}

View File

@ -1,10 +0,0 @@
<div *ngIf="mails.length === 0" fxLayout="column" fxLayoutAlign="center center" fxFlexFill>
<span class="no-messages-text hint-text">{{ 'MAIL.NO_MESSAGES' | translate }}</span>
</div>
<div class="mail-list" [@animateStagger]="{value:'50'}">
<mail-list-item matRipple *ngFor="let mail of mails" [mail]="mail" (click)="readMail(mail.id)"
[ngClass]="{'current-mail mat-accent-50-bg':mail?.id == currentMail?.id}"
[@animate]="{value:'*',params:{y:'100%'}}">
</mail-list-item>
</div>

View File

@ -1,134 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { ActivatedRoute } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { Mail } from 'app/main/apps/mail/mail.model';
import { MailService } from 'app/main/apps/mail/mail.service';
@Component({
selector : 'mail-list',
templateUrl: './mail-list.component.html',
styleUrls : ['./mail-list.component.scss'],
animations : fuseAnimations
})
export class MailListComponent implements OnInit, OnDestroy
{
mails: Mail[];
currentMail: Mail;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ActivatedRoute} _activatedRoute
* @param {MailService} _mailService
* @param {Location} _location
*/
constructor(
private _activatedRoute: ActivatedRoute,
private _mailService: MailService,
private _location: Location
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to update mails on changes
this._mailService.onMailsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(mails => {
this.mails = mails;
});
// Subscribe to update current mail on changes
this._mailService.onCurrentMailChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(currentMail => {
if ( !currentMail )
{
// Set the current mail id to null to deselect the current mail
this.currentMail = null;
// Handle the location changes
const labelHandle = this._activatedRoute.snapshot.params.labelHandle,
filterHandle = this._activatedRoute.snapshot.params.filterHandle,
folderHandle = this._activatedRoute.snapshot.params.folderHandle;
if ( labelHandle )
{
this._location.go('apps/mail/label/' + labelHandle);
}
else if ( filterHandle )
{
this._location.go('apps/mail/filter/' + filterHandle);
}
else
{
this._location.go('apps/mail/' + folderHandle);
}
}
else
{
this.currentMail = currentMail;
}
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Read mail
*
* @param mailId
*/
readMail(mailId): void
{
const labelHandle = this._activatedRoute.snapshot.params.labelHandle,
filterHandle = this._activatedRoute.snapshot.params.filterHandle,
folderHandle = this._activatedRoute.snapshot.params.folderHandle;
if ( labelHandle )
{
this._location.go('apps/mail/label/' + labelHandle + '/' + mailId);
}
else if ( filterHandle )
{
this._location.go('apps/mail/filter/' + filterHandle + '/' + mailId);
}
else
{
this._location.go('apps/mail/' + folderHandle + '/' + mailId);
}
// Set current mail
this._mailService.setCurrentMail(mailId);
}
}

View File

@ -1,107 +0,0 @@
<div id="mail" class="page-layout carded left-sidebar inner-scroll">
<!-- TOP BACKGROUND -->
<div class="top-bg mat-accent-bg"></div>
<!-- / TOP BACKGROUND -->
<!-- SIDEBAR -->
<fuse-sidebar class="sidebar" name="mail-main-sidebar" position="left" lockedOpen="gt-md">
<mail-main-sidebar></mail-main-sidebar>
</fuse-sidebar>
<!-- / SIDEBAR -->
<!-- CENTER -->
<div class="center">
<!-- CONTENT HEADER -->
<div class="header" fxLayout="row" fxLayoutAlign="start center">
<div class="search-wrapper" fxFlex fxLayout="row" fxLayoutAlign="start center">
<button mat-icon-button class="sidebar-toggle" fxHide.gt-md
(click)="toggleSidebar('mail-main-sidebar')">
<mat-icon>menu</mat-icon>
</button>
<div class="search mat-white-bg" flex fxLayout="row" fxLayoutAlign="start center">
<mat-icon>search</mat-icon>
<input [formControl]="searchInput" [placeholder]="'MAIL.SEARCH_PLACEHOLDER' | translate" fxFlex>
</div>
</div>
</div>
<!-- / CONTENT HEADER -->
<!-- CONTENT CARD -->
<div class="content-card mat-white-bg" [ngClass]="{'current-mail-selected':currentMail}">
<!-- CONTENT TOOLBAR -->
<div class="toolbar px-24 py-8">
<div class="mail-selection" fxFlex="row" fxLayoutAlign="start center">
<mat-checkbox (click)="toggleSelectAll()" [checked]="hasSelectedMails"
[indeterminate]="isIndeterminate"></mat-checkbox>
<button mat-icon-button [matMenuTriggerFor]="selectMenu">
<mat-icon>arrow_drop_down</mat-icon>
</button>
<mat-menu #selectMenu="matMenu">
<button mat-menu-item (click)="selectMails()">All</button>
<button mat-menu-item (click)="deselectMails()">None</button>
<button mat-menu-item (click)="selectMails('read', true)">Read</button>
<button mat-menu-item (click)="selectMails('read', false)">Unread</button>
<button mat-menu-item (click)="selectMails('starred', true)">Starred</button>
<button mat-menu-item (click)="selectMails('starred', false)">Unstarred</button>
<button mat-menu-item (click)="selectMails('important', true)">Important</button>
<button mat-menu-item (click)="selectMails('important', false)">Unimportant</button>
</mat-menu>
<div class="toolbar-separator" *ngIf="hasSelectedMails"></div>
<button mat-icon-button (click)="setFolderOnSelectedMails(4)" *ngIf="hasSelectedMails">
<mat-icon class="secondary-text">delete</mat-icon>
</button>
<button mat-icon-button [matMenuTriggerFor]="folderMenu" *ngIf="hasSelectedMails">
<mat-icon class="secondary-text">folder</mat-icon>
</button>
<mat-menu #folderMenu="matMenu">
<button mat-menu-item *ngFor="let folder of folders"
(click)="setFolderOnSelectedMails(folder.id)">{{folder.title}}
</button>
</mat-menu>
<button mat-icon-button [matMenuTriggerFor]="labelMenu" *ngIf="hasSelectedMails">
<mat-icon class="secondary-text">label</mat-icon>
</button>
<mat-menu #labelMenu="matMenu">
<button mat-menu-item *ngFor="let label of labels"
(click)="toggleLabelOnSelectedMails(label.id)">{{label.title}}
</button>
</mat-menu>
</div>
<div *ngIf="currentMail" fxHide.gt-xs>
<button mat-icon-button (click)="deselectCurrentMail()">
<mat-icon class="secondary-text">arrow_back</mat-icon>
</button>
</div>
</div>
<!-- / CONTENT TOOLBAR -->
<!-- CONTENT -->
<div class="content" fxLayout="row">
<mail-list fusePerfectScrollbar fxFlex></mail-list>
<mail-details fusePerfectScrollbar fxFlex></mail-details>
</div>
<!-- / CONTENT -->
</div>
<!-- / CONTENT CARD -->
</div>
<!-- / CENTER -->
</div>

View File

@ -1,193 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
import { FuseTranslationLoaderService } from '@fuse/services/translation-loader.service';
import { Mail } from 'app/main/apps/mail/mail.model';
import { MailService } from 'app/main/apps/mail/mail.service';
import { locale as english } from 'app/main/apps/mail//i18n/en';
import { locale as turkish } from 'app/main/apps/mail//i18n/tr';
@Component({
selector : 'mail',
templateUrl: './mail.component.html',
styleUrls : ['./mail.component.scss']
})
export class MailComponent implements OnInit, OnDestroy
{
hasSelectedMails: boolean;
isIndeterminate: boolean;
folders: any[];
filters: any[];
labels: any[];
searchInput: FormControl;
currentMail: Mail;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {MailService} _mailService
* @param {FuseSidebarService} _fuseSidebarService
* @param {FuseTranslationLoaderService} _fuseTranslationLoaderService
*/
constructor(
private _mailService: MailService,
private _fuseSidebarService: FuseSidebarService,
private _fuseTranslationLoaderService: FuseTranslationLoaderService
)
{
// Load the translations
this._fuseTranslationLoaderService.loadTranslations(english, turkish);
// Set the defaults
this.searchInput = new FormControl('');
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._mailService.onSelectedMailsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(selectedMails => {
setTimeout(() => {
this.hasSelectedMails = selectedMails.length > 0;
this.isIndeterminate = (selectedMails.length !== this._mailService.mails.length && selectedMails.length > 0);
}, 0);
});
this._mailService.onFoldersChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(folders => {
this.folders = this._mailService.folders;
});
this._mailService.onFiltersChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(folders => {
this.filters = this._mailService.filters;
});
this._mailService.onLabelsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(labels => {
this.labels = this._mailService.labels;
});
this._mailService.onCurrentMailChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(currentMail => {
if ( !currentMail )
{
this.currentMail = null;
}
else
{
this.currentMail = currentMail;
}
});
this.searchInput.valueChanges.pipe(
takeUntil(this._unsubscribeAll),
debounceTime(300),
distinctUntilChanged()
)
.subscribe(searchText => {
this._mailService.onSearchTextChanged.next(searchText);
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle select all
*/
toggleSelectAll(): void
{
this._mailService.toggleSelectAll();
}
/**
* Select mails
*
* @param filterParameter
* @param filterValue
*/
selectMails(filterParameter?, filterValue?): void
{
this._mailService.selectMails(filterParameter, filterValue);
}
/**
* Deselect mails
*/
deselectMails(): void
{
this._mailService.deselectMails();
}
/**
* Deselect current mail
*/
deselectCurrentMail(): void
{
this._mailService.onCurrentMailChanged.next(null);
}
/**
* Toggle label on selected mails
*
* @param labelId
*/
toggleLabelOnSelectedMails(labelId): void
{
this._mailService.toggleLabelOnSelectedMails(labelId);
}
/**
* Set folder on selected mails
*
* @param folderId
*/
setFolderOnSelectedMails(folderId): void
{
this._mailService.setFolderOnSelectedMails(folderId);
}
/**
* Toggle the sidebar
*
* @param name
*/
toggleSidebar(name): void
{
this._fuseSidebarService.getSidebar(name).toggleOpen();
}
}

View File

@ -1,127 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { MatDialog } from '@angular/material';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { MailService } from 'app/main/apps/mail/mail.service';
import { MailComposeDialogComponent } from 'app/main/apps/mail/dialogs/compose/compose.component';
@Component({
selector : 'mail-main-sidebar',
templateUrl: './main-sidebar.component.html',
styleUrls : ['./main-sidebar.component.scss'],
animations : fuseAnimations
})
export class MailMainSidebarComponent implements OnInit, OnDestroy
{
folders: any[];
filters: any[];
labels: any[];
accounts: object;
selectedAccount: string;
dialogRef: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {MailService} _mailService
* @param {MatDialog} _matDialog
*/
constructor(
private _mailService: MailService,
public _matDialog: MatDialog
)
{
// Set the defaults
this.accounts = {
'creapond' : 'johndoe@creapond.com',
'withinpixels': 'johndoe@withinpixels.com'
};
this.selectedAccount = 'creapond';
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._mailService.onFoldersChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(folders => {
this.folders = folders;
});
this._mailService.onFiltersChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(filters => {
this.filters = filters;
});
this._mailService.onLabelsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(labels => {
this.labels = labels;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Compose dialog
*/
composeDialog(): void
{
this.dialogRef = this._matDialog.open(MailComposeDialogComponent, {
panelClass: 'mail-compose-dialog'
});
this.dialogRef.afterClosed()
.subscribe(response => {
if ( !response )
{
return;
}
const actionType: string = response[0];
const formData: FormGroup = response[1];
switch ( actionType )
{
/**
* Send
*/
case 'send':
console.log('new Mail', formData.getRawValue());
break;
/**
* Delete
*/
case 'delete':
console.log('delete Mail');
break;
}
});
}
}

View File

@ -1,80 +0,0 @@
import { Component, EventEmitter, Output, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector : 'scrumboard-board-add-list',
templateUrl: './add-list.component.html',
styleUrls : ['./add-list.component.scss']
})
export class ScrumboardBoardAddListComponent
{
formActive: boolean;
form: FormGroup;
@Output()
onListAdd: EventEmitter<any>;
@ViewChild('nameInput')
nameInputField;
/**
* Constructor
*
* @param {FormBuilder} _formBuilder
*/
constructor(
private _formBuilder: FormBuilder
)
{
// Set the defaults
this.formActive = false;
this.onListAdd = new EventEmitter();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Open form
*/
openForm(): void
{
this.form = this._formBuilder.group({
name: ['']
});
this.formActive = true;
this.focusNameField();
}
/**
* Close form
*/
closeForm(): void
{
this.formActive = false;
}
/**
* Focus to the name field
*/
focusNameField(): void
{
setTimeout(() => {
this.nameInputField.nativeElement.focus();
});
}
/**
* On form submit
*/
onFormSubmit(): void
{
if ( this.form.valid )
{
this.onListAdd.next(this.form.getRawValue().name);
this.formActive = false;
}
}
}

View File

@ -1,100 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { ActivatedRoute } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { ScrumboardService } from 'app/main/apps/scrumboard/scrumboard.service';
import { List } from 'app/main/apps/scrumboard/list.model';
@Component({
selector : 'scrumboard-board',
templateUrl: './board.component.html',
styleUrls : ['./board.component.scss'],
animations : fuseAnimations
})
export class ScrumboardBoardComponent implements OnInit, OnDestroy
{
board: any;
// Private
private _unsubscribeAll: Subject<any>;
constructor(
private _activatedRoute: ActivatedRoute,
private _location: Location,
private _scrumboardService: ScrumboardService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._scrumboardService.onBoardChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(board => {
this.board = board;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* On list add
*
* @param newListName
*/
onListAdd(newListName): void
{
if ( newListName === '' )
{
return;
}
this._scrumboardService.addList(new List({name: newListName}));
}
/**
* On board name changed
*
* @param newName
*/
onBoardNameChanged(newName): void
{
this._scrumboardService.updateBoard();
this._location.go('/apps/scrumboard/boards/' + this.board.id + '/' + this.board.uri);
}
/**
* On drop
*
* @param ev
*/
onDrop(ev): void
{
this._scrumboardService.updateBoard();
}
}

View File

@ -1,114 +0,0 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseUtils } from '@fuse/utils';
import { ScrumboardService } from 'app/main/apps/scrumboard/scrumboard.service';
@Component({
selector : 'scrumboard-label-selector',
templateUrl : './label-selector.component.html',
styleUrls : ['./label-selector.component.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class ScrumboardLabelSelectorComponent implements OnInit, OnDestroy
{
@Input('card')
card: any;
@Output()
onCardLabelsChange: EventEmitter<any>;
board: any;
labelsMenuView: string;
selectedLabel: any;
newLabel: any;
toggleInArray: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ScrumboardService} _scrumboardService
*/
constructor(
private _scrumboardService: ScrumboardService
)
{
// Set the defaults
this.onCardLabelsChange = new EventEmitter();
this.labelsMenuView = 'labels';
this.newLabel = {
'id' : '',
'name' : '',
'color': 'mat-blue-400-bg'
};
this.toggleInArray = FuseUtils.toggleInArray;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._scrumboardService.onBoardChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(board => {
this.board = board;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Card labels changed
*/
cardLabelsChanged(): void
{
this.onCardLabelsChange.next();
}
/**
* On label change
*/
onLabelChange(): void
{
this._scrumboardService.updateBoard();
}
/**
* Add new label
*/
addNewLabel(): void
{
this.newLabel.id = FuseUtils.generateGUID();
this.board.labels.push(Object.assign({}, this.newLabel));
this.newLabel.name = '';
this.labelsMenuView = 'labels';
}
}

View File

@ -1,81 +0,0 @@
import { Component, EventEmitter, Output, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector : 'scrumboard-board-add-card',
templateUrl: './add-card.component.html',
styleUrls : ['./add-card.component.scss']
})
export class ScrumboardBoardAddCardComponent
{
formActive: boolean;
form: FormGroup;
@Output()
onCardAdd: EventEmitter<any>;
@ViewChild('nameInput')
nameInputField;
/**
* Constructor
*
* @param {FormBuilder} _formBuilder
*/
constructor(
private _formBuilder: FormBuilder
)
{
// Set the defaults
this.formActive = false;
this.onCardAdd = new EventEmitter();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Open the form
*/
openForm(): void
{
this.form = this._formBuilder.group({
name: ''
});
this.formActive = true;
this.focusNameField();
}
/**
* Close the form
*/
closeForm(): void
{
this.formActive = false;
}
/**
* Focus to the name field
*/
focusNameField(): void
{
setTimeout(() => {
this.nameInputField.nativeElement.focus();
});
}
/**
* On form submit
*/
onFormSubmit(): void
{
if ( this.form.valid )
{
const cardName = this.form.getRawValue().name;
this.onCardAdd.next(cardName);
this.formActive = false;
}
}
}

View File

@ -1,59 +0,0 @@
import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import * as moment from 'moment';
@Component({
selector : 'scrumboard-board-card',
templateUrl : './card.component.html',
styleUrls : ['./card.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ScrumboardBoardCardComponent implements OnInit
{
@Input()
cardId;
card: any;
board: any;
/**
* Constructor
*
* @param {ActivatedRoute} _activatedRoute
*/
constructor(
private _activatedRoute: ActivatedRoute
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.board = this._activatedRoute.snapshot.data.board;
this.card = this.board.cards.filter((card) => {
return this.cardId === card.id;
})[0];
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Is the card overdue?
*
* @param cardDate
* @returns {boolean}
*/
isOverdue(cardDate): boolean
{
return moment() > moment(new Date(cardDate));
}
}

View File

@ -1,83 +0,0 @@
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector : 'scrumboard-board-edit-list-name',
templateUrl: './edit-list-name.component.html',
styleUrls : ['./edit-list-name.component.scss']
})
export class ScrumboardBoardEditListNameComponent
{
formActive: boolean;
form: FormGroup;
@Input()
list;
@Output()
onNameChanged: EventEmitter<any>;
@ViewChild('nameInput')
nameInputField;
/**
* Constructor
*
* @param {FormBuilder} _formBuilder
*/
constructor(
private _formBuilder: FormBuilder
)
{
// Set the defaults
this.formActive = false;
this.onNameChanged = new EventEmitter();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Open the form
*/
openForm(): void
{
this.form = this._formBuilder.group({
name: [this.list.name]
});
this.formActive = true;
this.focusNameField();
}
/**
* Close the form
*/
closeForm(): void
{
this.formActive = false;
}
/**
* Focus to the name field
*/
focusNameField(): void
{
setTimeout(() => {
this.nameInputField.nativeElement.focus();
});
}
/**
* On form submit
*/
onFormSubmit(): void
{
if ( this.form.valid )
{
this.list.name = this.form.getRawValue().name;
this.onNameChanged.next(this.list.name);
this.formActive = false;
}
}
}

View File

@ -1,162 +0,0 @@
import { Component, Input, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { MatDialog, MatDialogRef } from '@angular/material';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component';
import { FusePerfectScrollbarDirective } from '@fuse/directives/fuse-perfect-scrollbar/fuse-perfect-scrollbar.directive';
import { ScrumboardService } from 'app/main/apps/scrumboard/scrumboard.service';
import { Card } from 'app/main/apps/scrumboard/card.model';
import { ScrumboardCardDialogComponent } from 'app/main/apps/scrumboard/board/dialogs/card/card.component';
@Component({
selector : 'scrumboard-board-list',
templateUrl : './list.component.html',
styleUrls : ['./list.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ScrumboardBoardListComponent implements OnInit, OnDestroy
{
board: any;
dialogRef: any;
@Input()
list;
@ViewChild(FusePerfectScrollbarDirective)
listScroll: FusePerfectScrollbarDirective;
confirmDialogRef: MatDialogRef<FuseConfirmDialogComponent>;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ActivatedRoute} _activatedRoute
* @param {ScrumboardService} _scrumboardService
* @param {MatDialog} _matDialog
*/
constructor(
private _activatedRoute: ActivatedRoute,
private _scrumboardService: ScrumboardService,
private _matDialog: MatDialog
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._scrumboardService.onBoardChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(board => {
this.board = board;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* On list name changed
*
* @param newListName
*/
onListNameChanged(newListName): void
{
this.list.name = newListName;
}
/**
* On card added
*
* @param newCardName
*/
onCardAdd(newCardName): void
{
if ( newCardName === '' )
{
return;
}
this._scrumboardService.addCard(this.list.id, new Card({name: newCardName}));
setTimeout(() => {
this.listScroll.scrollToBottom(0, 400);
});
}
/**
* Remove list
*
* @param listId
*/
removeList(listId): void
{
this.confirmDialogRef = this._matDialog.open(FuseConfirmDialogComponent, {
disableClose: false
});
this.confirmDialogRef.componentInstance.confirmMessage = 'Are you sure you want to delete the list and it\'s all cards?';
this.confirmDialogRef.afterClosed().subscribe(result => {
if ( result )
{
this._scrumboardService.removeList(listId);
}
});
}
/**
* Open card dialog
*
* @param cardId
*/
openCardDialog(cardId): void
{
this.dialogRef = this._matDialog.open(ScrumboardCardDialogComponent, {
panelClass: 'scrumboard-card-dialog',
data : {
cardId: cardId,
listId: this.list.id
}
});
this.dialogRef.afterClosed()
.subscribe(response => {
});
}
/**
* On drop
*
* @param ev
*/
onDrop(ev): void
{
this._scrumboardService.updateBoard();
}
}

View File

@ -1,78 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { MatColors } from '@fuse/mat-colors';
import { ScrumboardService } from 'app/main/apps/scrumboard/scrumboard.service';
@Component({
selector : 'scrumboard-board-color-selector',
templateUrl: './board-color-selector.component.html',
styleUrls : ['./board-color-selector.component.scss']
})
export class ScrumboardBoardColorSelectorComponent implements OnInit, OnDestroy
{
colors: any;
board: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ScrumboardService} _scrumboardService
*/
constructor(
private _scrumboardService: ScrumboardService
)
{
// Set the defaults
this.colors = MatColors.all;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._scrumboardService.onBoardChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(board => {
this.board = board;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Set the color
*
* @param color
*/
setColor(color): void
{
this.board.settings.color = color;
this._scrumboardService.updateBoard();
}
}

View File

@ -1,80 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { fuseAnimations } from '@fuse/animations';
import { ScrumboardService } from 'app/main/apps/scrumboard/scrumboard.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector : 'scrumboard-board-settings',
templateUrl: './settings.component.html',
styleUrls : ['./settings.component.scss'],
animations : fuseAnimations
})
export class ScrumboardBoardSettingsSidenavComponent implements OnInit, OnDestroy
{
board: any;
view: string;
// Private
private _unsubscribeAll: Subject<any>;
constructor(
private scrumboardService: ScrumboardService
)
{
// Set the defaults
this.view = 'main';
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.scrumboardService.onBoardChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(board => {
this.board = board;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle card cover
*/
toggleCardCover(): void
{
this.board.settings.cardCoverImages = !this.board.settings.cardCoverImages;
this.scrumboardService.updateBoard();
}
/**
* Toggle subscription
*/
toggleSubscription(): void
{
this.board.settings.subscribed = !this.board.settings.subscribed;
this.scrumboardService.updateBoard();
}
}

View File

@ -1,79 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { ScrumboardService } from 'app/main/apps/scrumboard/scrumboard.service';
import { Board } from 'app/main/apps/scrumboard/board.model';
@Component({
selector : 'scrumboard',
templateUrl: './scrumboard.component.html',
styleUrls : ['./scrumboard.component.scss'],
animations : fuseAnimations
})
export class ScrumboardComponent implements OnInit, OnDestroy
{
boards: any[];
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {Router} _router
* @param {ScrumboardService} _scrumboardService
*/
constructor(
private _router: Router,
private _scrumboardService: ScrumboardService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._scrumboardService.onBoardsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(boards => {
this.boards = boards;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* New board
*/
newBoard(): void
{
const newBoard = new Board({});
this._scrumboardService.createNewBoard(newBoard).then(() => {
this._router.navigate(['/apps/scrumboard/boards/' + newBoard.id + '/' + newBoard.uri]);
});
}
}

View File

@ -1,92 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MatButtonModule, MatCheckboxModule, MatChipsModule, MatDatepickerModule, MatDialogModule, MatFormFieldModule, MatIconModule, MatInputModule, MatListModule, MatMenuModule, MatProgressBarModule, MatRippleModule, MatSidenavModule, MatToolbarModule, MatTooltipModule } from '@angular/material';
import { NgxDnDModule } from '@swimlane/ngx-dnd';
import { FuseSharedModule } from '@fuse/shared.module';
import { FuseConfirmDialogModule, FuseMaterialColorPickerModule } from '@fuse/components';
import { BoardResolve, ScrumboardService } from 'app/main/apps/scrumboard/scrumboard.service';
import { ScrumboardComponent } from 'app/main/apps/scrumboard/scrumboard.component';
import { ScrumboardBoardComponent } from 'app/main/apps/scrumboard/board/board.component';
import { ScrumboardBoardListComponent } from 'app/main/apps/scrumboard/board/list/list.component';
import { ScrumboardBoardCardComponent } from 'app/main/apps/scrumboard/board/list/card/card.component';
import { ScrumboardBoardEditListNameComponent } from 'app/main/apps/scrumboard/board/list/edit-list-name/edit-list-name.component';
import { ScrumboardBoardAddCardComponent } from 'app/main/apps/scrumboard/board/list/add-card/add-card.component';
import { ScrumboardBoardAddListComponent } from 'app/main/apps/scrumboard/board/add-list/add-list.component';
import { ScrumboardCardDialogComponent } from 'app/main/apps/scrumboard/board/dialogs/card/card.component';
import { ScrumboardLabelSelectorComponent } from 'app/main/apps/scrumboard/board/dialogs/card/label-selector/label-selector.component';
import { ScrumboardEditBoardNameComponent } from 'app/main/apps/scrumboard/board/edit-board-name/edit-board-name.component';
import { ScrumboardBoardSettingsSidenavComponent } from 'app/main/apps/scrumboard/board/sidenavs/settings/settings.component';
import { ScrumboardBoardColorSelectorComponent } from 'app/main/apps/scrumboard/board/sidenavs/settings/board-color-selector/board-color-selector.component';
const routes: Routes = [
{
path : 'boards',
component: ScrumboardComponent,
resolve : {
scrumboard: ScrumboardService
}
},
{
path : 'boards/:boardId/:boardUri',
component: ScrumboardBoardComponent,
resolve : {
board: BoardResolve
}
},
{
path : '**',
redirectTo: 'boards'
}
];
@NgModule({
declarations : [
ScrumboardComponent,
ScrumboardBoardComponent,
ScrumboardBoardListComponent,
ScrumboardBoardCardComponent,
ScrumboardBoardEditListNameComponent,
ScrumboardBoardAddCardComponent,
ScrumboardBoardAddListComponent,
ScrumboardCardDialogComponent,
ScrumboardLabelSelectorComponent,
ScrumboardEditBoardNameComponent,
ScrumboardBoardSettingsSidenavComponent,
ScrumboardBoardColorSelectorComponent
],
imports : [
RouterModule.forChild(routes),
MatButtonModule,
MatCheckboxModule,
MatChipsModule,
MatDatepickerModule,
MatDialogModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatProgressBarModule,
MatRippleModule,
MatSidenavModule,
MatToolbarModule,
MatTooltipModule,
NgxDnDModule,
FuseSharedModule,
FuseConfirmDialogModule,
FuseMaterialColorPickerModule
],
providers : [
ScrumboardService,
BoardResolve
],
entryComponents: [ScrumboardCardDialogComponent]
})
export class ScrumboardModule
{
}

View File

@ -1,96 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { TodoService } from 'app/main/apps/todo/todo.service';
@Component({
selector : 'todo-main-sidebar',
templateUrl: './main-sidebar.component.html',
styleUrls : ['./main-sidebar.component.scss'],
animations : fuseAnimations
})
export class TodoMainSidebarComponent implements OnInit, OnDestroy
{
folders: any[];
filters: any[];
tags: any[];
accounts: object;
selectedAccount: string;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {TodoService} _todoService
* @param {Router} _router
*/
constructor(
private _todoService: TodoService,
private _router: Router
)
{
// Set the defaults
this.accounts = {
'creapond' : 'johndoe@creapond.com',
'withinpixels': 'johndoe@withinpixels.com'
};
this.selectedAccount = 'creapond';
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._todoService.onFiltersChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(filters => {
this.filters = filters;
});
this._todoService.onTagsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(tags => {
this.tags = tags;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* New todo
*/
newTodo(): void
{
this._router.navigate(['/apps/todo/all']).then(() => {
setTimeout(() => {
this._todoService.onNewTodoClicked.next('');
});
});
}
}

View File

@ -1,219 +0,0 @@
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { FuseUtils } from '@fuse/utils';
import { fuseAnimations } from '@fuse/animations';
import { Todo } from 'app/main/apps/todo/todo.model';
import { TodoService } from 'app/main/apps/todo/todo.service';
@Component({
selector : 'todo-details',
templateUrl: './todo-details.component.html',
styleUrls : ['./todo-details.component.scss'],
animations : fuseAnimations
})
export class TodoDetailsComponent implements OnInit, OnDestroy
{
todo: Todo;
tags: any[];
formType: string;
todoForm: FormGroup;
@ViewChild('titleInput')
titleInputField;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {TodoService} _todoService
* @param {FormBuilder} _formBuilder
*/
constructor(
private _todoService: TodoService,
private _formBuilder: FormBuilder
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to update the current todo
this._todoService.onCurrentTodoChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(([todo, formType]) => {
if ( todo && formType === 'edit' )
{
this.formType = 'edit';
this.todo = todo;
this.todoForm = this.createTodoForm();
this.todoForm.valueChanges
.pipe(
takeUntil(this._unsubscribeAll),
debounceTime(500),
distinctUntilChanged()
)
.subscribe(data => {
this._todoService.updateTodo(data);
});
}
});
// Subscribe to update on tag change
this._todoService.onTagsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(labels => {
this.tags = labels;
});
// Subscribe to update on tag change
this._todoService.onNewTodoClicked
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
this.todo = new Todo({});
this.todo.id = FuseUtils.generateGUID();
this.formType = 'new';
this.todoForm = this.createTodoForm();
this.focusTitleField();
this._todoService.onCurrentTodoChanged.next([this.todo, 'new']);
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Focus title field
*/
focusTitleField(): void
{
setTimeout(() => {
this.titleInputField.nativeElement.focus();
});
}
/**
* Create todo form
*
* @returns {FormGroup}
*/
createTodoForm(): FormGroup
{
return this._formBuilder.group({
'id' : [this.todo.id],
'title' : [this.todo.title],
'notes' : [this.todo.notes],
'startDate': [this.todo.startDate],
'dueDate' : [this.todo.dueDate],
'completed': [this.todo.completed],
'starred' : [this.todo.starred],
'important': [this.todo.important],
'deleted' : [this.todo.deleted],
'tags' : [this.todo.tags]
});
}
/**
* Toggle star
*
* @param event
*/
toggleStar(event): void
{
event.stopPropagation();
this.todo.toggleStar();
this._todoService.updateTodo(this.todo);
}
/**
* Toggle important
*
* @param event
*/
toggleImportant(event): void
{
event.stopPropagation();
this.todo.toggleImportant();
this._todoService.updateTodo(this.todo);
}
/**
* Toggle Completed
*
* @param event
*/
toggleCompleted(event): void
{
event.stopPropagation();
this.todo.toggleCompleted();
this._todoService.updateTodo(this.todo);
}
/**
* Toggle Deleted
*
* @param event
*/
toggleDeleted(event): void
{
event.stopPropagation();
this.todo.toggleDeleted();
this._todoService.updateTodo(this.todo);
}
/**
* Toggle tag on todo
*
* @param tagId
*/
toggleTagOnTodo(tagId): void
{
this._todoService.toggleTagOnTodo(tagId, this.todo);
}
/**
* Has tag?
*
* @param tagId
* @returns {any}
*/
hasTag(tagId): any
{
return this._todoService.hasTag(tagId, this.todo);
}
/**
* Add todo
*/
addTodo(): void
{
this._todoService.updateTodo(this.todoForm.getRawValue());
}
}

View File

@ -1,148 +0,0 @@
import { Component, HostBinding, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subject, Subscription } from 'rxjs';
import { Todo } from 'app/main/apps/todo/todo.model';
import { TodoService } from 'app/main/apps/todo/todo.service';
import { takeUntil } from 'rxjs/operators';
@Component({
selector : 'todo-list-item',
templateUrl : './todo-list-item.component.html',
styleUrls : ['./todo-list-item.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class TodoListItemComponent implements OnInit, OnDestroy
{
tags: any[];
@Input()
todo: Todo;
@HostBinding('class.selected')
selected: boolean;
@HostBinding('class.completed')
completed: boolean;
@HostBinding('class.move-disabled')
moveDisabled: boolean;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {TodoService} _todoService
* @param {ActivatedRoute} _activatedRoute
*/
constructor(
private _todoService: TodoService,
private _activatedRoute: ActivatedRoute
)
{
// Disable move if path is not /all
if ( _activatedRoute.snapshot.url[0].path !== 'all' )
{
this.moveDisabled = true;
}
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Set the initial values
this.todo = new Todo(this.todo);
this.completed = this.todo.completed;
// Subscribe to update on selected todo change
this._todoService.onSelectedTodosChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(selectedTodos => {
this.selected = false;
if ( selectedTodos.length > 0 )
{
for ( const todo of selectedTodos )
{
if ( todo.id === this.todo.id )
{
this.selected = true;
break;
}
}
}
});
// Subscribe to update on tag change
this._todoService.onTagsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(tags => {
this.tags = tags;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* On selected change
*/
onSelectedChange(): void
{
this._todoService.toggleSelectedTodo(this.todo.id);
}
/**
* Toggle star
*/
toggleStar(event): void
{
event.stopPropagation();
this.todo.toggleStar();
this._todoService.updateTodo(this.todo);
}
/**
* Toggle Important
*/
toggleImportant(event): void
{
event.stopPropagation();
this.todo.toggleImportant();
this._todoService.updateTodo(this.todo);
}
/**
* Toggle Completed
*/
toggleCompleted(event): void
{
event.stopPropagation();
this.todo.toggleCompleted();
this._todoService.updateTodo(this.todo);
}
}

View File

@ -1,14 +0,0 @@
<div *ngIf="todos.length === 0" fxLayout="column" fxLayoutAlign="center center" fxFlexFill>
<span class="no-todos-text hint-text">There are no todos!</span>
</div>
<div class="todo-list" ngxDroppable [model]="todos" (out)="onDrop($event)" [@animateStagger]="{value:'50'}">
<todo-list-item class="todo-list-item has-handle"
*ngFor="let todo of todos" [todo]="todo"
ngxDraggable
[model]="todo"
(click)="readTodo(todo.id)"
[ngClass]="{'current-todo mat-accent-50-bg':todo?.id == currentTodo?.id}"
matRipple
[@animate]="{value:'*',params:{y:'100%'}}">
</todo-list-item>
</div>

View File

@ -1,126 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { ActivatedRoute } from '@angular/router';
import { Subject } from 'rxjs';
import { fuseAnimations } from '@fuse/animations';
import { Todo } from 'app/main/apps/todo/todo.model';
import { TodoService } from 'app/main/apps/todo/todo.service';
import { takeUntil } from 'rxjs/operators';
@Component({
selector : 'todo-list',
templateUrl: './todo-list.component.html',
styleUrls : ['./todo-list.component.scss'],
animations : fuseAnimations
})
export class TodoListComponent implements OnInit, OnDestroy
{
todos: Todo[];
currentTodo: Todo;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ActivatedRoute} _activatedRoute
* @param {TodoService} _todoService
* @param {Location} _location
*/
constructor(
private _activatedRoute: ActivatedRoute,
private _todoService: TodoService,
private _location: Location
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to update todos on changes
this._todoService.onTodosChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(todos => {
this.todos = todos;
});
// Subscribe to update current todo on changes
this._todoService.onCurrentTodoChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(currentTodo => {
if ( !currentTodo )
{
// Set the current todo id to null to deselect the current todo
this.currentTodo = null;
// Handle the location changes
const tagHandle = this._activatedRoute.snapshot.params.tagHandle,
filterHandle = this._activatedRoute.snapshot.params.filterHandle;
if ( tagHandle )
{
this._location.go('apps/todo/tag/' + tagHandle);
}
else if ( filterHandle )
{
this._location.go('apps/todo/filter/' + filterHandle);
}
else
{
this._location.go('apps/todo/all');
}
}
else
{
this.currentTodo = currentTodo;
}
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Read todo
*
* @param todoId
*/
readTodo(todoId): void
{
// Set current todo
this._todoService.setCurrentTodo(todoId);
}
/**
* On drop
*
* @param ev
*/
onDrop(ev): void
{
}
}

View File

@ -1,93 +0,0 @@
<div id="todo" class="page-layout carded left-sidebar inner-scroll">
<!-- TOP BACKGROUND -->
<div class="top-bg mat-accent-bg"></div>
<!-- / TOP BACKGROUND -->
<!-- SIDEBAR -->
<fuse-sidebar class="sidebar" name="todo-main-sidebar" position="left" lockedOpen="gt-md">
<todo-main-sidebar></todo-main-sidebar>
</fuse-sidebar>
<!-- / SIDEBAR -->
<!-- CENTER -->
<div class="center">
<!-- CONTENT HEADER -->
<div class="header" fxLayout="row" fxLayoutAlign="start center">
<div class="search-wrapper mat-white-bg" fxFlex fxLayout="row" fxLayoutAlign="start center">
<button mat-icon-button class="sidebar-toggle" fxHide.gt-md
(click)="toggleSidebar('todo-main-sidebar')">
<mat-icon>menu</mat-icon>
</button>
<div class="search" flex fxLayout="row" fxLayoutAlign="start center">
<mat-icon>search</mat-icon>
<input [formControl]="searchInput" placeholder="Search for a task" fxFlex>
</div>
</div>
</div>
<!-- / CONTENT HEADER -->
<!-- CONTENT CARD -->
<div class="content-card mat-white-bg" [ngClass]="{'current-todo-selected':currentTodo}">
<!-- CONTENT TOOLBAR -->
<div class="toolbar px-24 py-8">
<div class="todo-selection" fxFlex="row" fxLayoutAlign="start center">
<mat-checkbox (click)="toggleSelectAll()" [checked]="hasSelectedTodos"
[indeterminate]="isIndeterminate"></mat-checkbox>
<button mat-icon-button [matMenuTriggerFor]="selectMenu">
<mat-icon>arrow_drop_down</mat-icon>
</button>
<mat-menu #selectMenu="matMenu">
<button mat-menu-item (click)="selectTodos()">All</button>
<button mat-menu-item (click)="deselectTodos()">None</button>
<button mat-menu-item (click)="selectTodos('read', true)">Read</button>
<button mat-menu-item (click)="selectTodos('read', false)">Unread</button>
<button mat-menu-item (click)="selectTodos('starred', true)">Starred</button>
<button mat-menu-item (click)="selectTodos('starred', false)">Unstarred</button>
<button mat-menu-item (click)="selectTodos('important', true)">Important</button>
<button mat-menu-item (click)="selectTodos('important', false)">Unimportant</button>
</mat-menu>
<div class="toolbar-separator" *ngIf="hasSelectedTodos"></div>
<button mat-icon-button [matMenuTriggerFor]="labelMenu" *ngIf="hasSelectedTodos">
<mat-icon class="secondary-text">label</mat-icon>
</button>
<mat-menu #labelMenu="matMenu">
<button mat-menu-item *ngFor="let tag of tags" (click)="toggleTagOnSelectedTodos(tag.id)">
{{tag.title}}
</button>
</mat-menu>
</div>
<div *ngIf="currentTodo" fxHide.gt-lg>
<button mat-icon-button (click)="deselectCurrentTodo()">
<mat-icon class="secondary-text">arrow_back</mat-icon>
</button>
</div>
</div>
<!-- / CONTENT TOOLBAR -->
<!-- CONTENT -->
<div class="content" fxFlexAlign="row">
<todo-list fusePerfectScrollbar fxFlex></todo-list>
<todo-details fusePerfectScrollbar fxFlex></todo-details>
</div>
<!-- / CONTENT -->
</div>
<!-- / CONTENT CARD -->
</div>
<!-- / CENTER -->
</div>

View File

@ -1,171 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
import { Todo } from 'app/main/apps/todo/todo.model';
import { TodoService } from 'app/main/apps/todo/todo.service';
@Component({
selector : 'todo',
templateUrl: './todo.component.html',
styleUrls : ['./todo.component.scss'],
animations : fuseAnimations
})
export class TodoComponent implements OnInit, OnDestroy
{
hasSelectedTodos: boolean;
isIndeterminate: boolean;
filters: any[];
tags: any[];
searchInput: FormControl;
currentTodo: Todo;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FuseSidebarService} _fuseSidebarService
* @param {TodoService} _todoService
*/
constructor(
private _fuseSidebarService: FuseSidebarService,
private _todoService: TodoService
)
{
// Set the defaults
this.searchInput = new FormControl('');
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._todoService.onSelectedTodosChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(selectedTodos => {
setTimeout(() => {
this.hasSelectedTodos = selectedTodos.length > 0;
this.isIndeterminate = (selectedTodos.length !== this._todoService.todos.length && selectedTodos.length > 0);
}, 0);
});
this._todoService.onFiltersChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(folders => {
this.filters = this._todoService.filters;
});
this._todoService.onTagsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(tags => {
this.tags = this._todoService.tags;
});
this.searchInput.valueChanges
.pipe(
takeUntil(this._unsubscribeAll),
debounceTime(300),
distinctUntilChanged()
)
.subscribe(searchText => {
this._todoService.onSearchTextChanged.next(searchText);
});
this._todoService.onCurrentTodoChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(([currentTodo, formType]) => {
if ( !currentTodo )
{
this.currentTodo = null;
}
else
{
this.currentTodo = currentTodo;
}
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Deselect current todo
*/
deselectCurrentTodo(): void
{
this._todoService.onCurrentTodoChanged.next([null, null]);
}
/**
* Toggle select all
*/
toggleSelectAll(): void
{
this._todoService.toggleSelectAll();
}
/**
* Select todos
*
* @param filterParameter
* @param filterValue
*/
selectTodos(filterParameter?, filterValue?): void
{
this._todoService.selectTodos(filterParameter, filterValue);
}
/**
* Deselect todos
*/
deselectTodos(): void
{
this._todoService.deselectTodos();
}
/**
* Toggle tag on selected todos
*
* @param tagId
*/
toggleTagOnSelectedTodos(tagId): void
{
this._todoService.toggleTagOnSelectedTodos(tagId);
}
/**
* Toggle the sidebar
*
* @param name
*/
toggleSidebar(name): void
{
this._fuseSidebarService.getSidebar(name).toggleOpen();
}
}

View File

@ -1,38 +0,0 @@
import { Component } from '@angular/core';
import { FuseConfigService } from '@fuse/services/config.service';
import { fuseAnimations } from '@fuse/animations';
@Component({
selector : 'mail-confirm',
templateUrl: './mail-confirm.component.html',
styleUrls : ['./mail-confirm.component.scss'],
animations : fuseAnimations
})
export class MailConfirmComponent
{
/**
* Constructor
*
* @param {FuseConfigService} _fuseConfigService
*/
constructor(
private _fuseConfigService: FuseConfigService
)
{
// Configure the layout
this._fuseConfigService.config = {
layout: {
navbar : {
hidden: true
},
toolbar: {
hidden: true
},
footer : {
hidden: true
}
}
};
}
}

View File

@ -1,38 +0,0 @@
import { Component } from '@angular/core';
import { FuseConfigService } from '@fuse/services/config.service';
import { fuseAnimations } from '@fuse/animations';
@Component({
selector : 'mail-confirm',
templateUrl: './mail-confirm.component.html',
styleUrls : ['./mail-confirm.component.scss'],
animations : fuseAnimations
})
export class MailConfirmComponent
{
/**
* Constructor
*
* @param {FuseConfigService} _fuseConfigService
*/
constructor(
private _fuseConfigService: FuseConfigService
)
{
// Configure the layout
this._fuseConfigService.config = {
layout: {
navbar : {
hidden: true
},
toolbar: {
hidden: true
},
footer : {
hidden: true
}
}
};
}
}

View File

@ -1,938 +0,0 @@
<div id="changelog" class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24" fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
</div>
<div class="h2 mt-16">Changelog</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<div class="changelog">
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v6.1.0 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v6.1.0</span>
<span class="date">(2018-06-xx)</span>
</div>
<div class="groups">
<div class="breaking-changes">
<span class="title">Breaking Changes</span>
<ul>
<li>New layout system and layouts</li>
<li>Replaced all mat-sidenav components with fuse-sidebar on apps and pages</li>
</ul>
</div>
<div class="new">
<span class="title">New</span>
<ul>
<li>Navigation service for easier modifications and for easier swapping</li>
<li>fusePerfectScrollbar now accepts a boolean to control the scrollbar's status</li>
<li>fusePerfectScrollbarOptions for Perfect Scrollbar options</li>
<li>Added an extra Angular Material color theme to the styles.scss file as an example</li>
</ul>
</div>
<div class="improved">
<span class="title">Improved</span>
<ul>
<li>Updated Angular and Angular Material</li>
<li>Updated various other packages</li>
<li>Improved the codebase and added a lot code comments</li>
<li>Improved the documentation and moved them into the Demo app</li>
<li>Changed the fuse-sidebar "align" input to "position"</li>
<li>Improved the page layouts</li>
<li>Navbar toggle button and fold button alignment on right navbar</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Set the selected language in toolbar from the translation service</li>
<li>Horizontal nav titles are collapsing on IE11</li>
<li>Angular Material card images not showing correctly</li>
<li>Other small fixes and improvements</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v6.0.1 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v6.0.1</span>
<span class="date">(2018-05-10)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated ngRx to 6.0.0-beta.1</li>
<li>Updated various other libraries to Angular 6 compatible versions</li>
<li>Updated demo code to make it compatible with RxJS 6.0.0</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Fixed: Scrumboard "Add a list" button is draggable and causing an error</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v6.0.0 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v6.0.0</span>
<span class="date">(2018-05-06)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular to 6.0.0</li>
<li>Updated Angular Material to 6.0.0</li>
<li>Updated Angular CLI to 6.0.0</li>
<li>Updated various other packages</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Fixed: Material icon button colors are being overwritten by Fuse</li>
<li>Fixed: Contacts app edit dialog issues</li>
<li>Fixed: Navigation sidebar doesn't scroll on mobile devices</li>
<li>Fixed: Horizontal navigation doesn't have 'hidden' and 'custom function' features like
the vertical
navigation
</li>
<li>Fixed: Search bar close icon alignment</li>
<li>Fixed: Profile page header background image doesn't cover the header</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v5.2.10 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v5.2.10</span>
<span class="date">(2018-03-10)</span>
</div>
<div class="groups">
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Fixed: Sidebar folded bugs</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v5.2.9 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v5.2.9</span>
<span class="date">(2018-03-10)</span>
</div>
<div class="groups">
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Fixed: Sidebar folded doesn't work correctly if activated programmatically</li>
<li>Fixed: Skeleton AoT building issues</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v5.2.8 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v5.2.8</span>
<span class="date">(2018-03-08)</span>
</div>
<div class="groups">
<div class="breaking-changes">
<span class="title">Breaking changes</span>
<ul>
<li>
<code>core</code> folder moved into the <code>@fuse</code> allowing project owners to
have their own core folder inside the app directory. Also allows for better separation
in between your app and core Fuse features.
</li>
<li>
Removed Angular Material module that includes all Material components at once and added
imports for all modules separately. From now on, you must include the Material
components that you have used in your components manually in that component's module
file. This was a required changed as it does increase the development performance as
well as decrease the building and the AoT building times.
</li>
<li>
Changed how navigation model works. Now it's just a simple const that being exported
from the <code>navigation.ts</code> file. It allows for easier swapping and editing of
the navigation.
</li>
<li>
New sidebar component. Allows us to move main navigation sidebar logic out of your way.
Check out the Demo app to see the full usage.
</li>
</ul>
</div>
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular to 5.2.8</li>
<li>Updated Angular Material to 5.2.4</li>
<li>Updated Angular CLI to 1.7.3</li>
<li>Matched the Fuse version number with the Angular</li>
<li>No more Fuse2, the package name update to Fuse since the version number matched to
Angular's.
</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Fixed various issues with Fuse Angular Material Color Picker component.</li>
<li>Fixed various other small layout and logic bugs.</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.3.6 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.3.6</span>
<span class="date">(2018-02-06)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular to 5.2.3</li>
<li>Updated Angular Material to 5.1.1</li>
<li>Updated Angular CLI to 1.6.7</li>
<li>New Analytics dashboard design</li>
<li>Added Chart.js examples through the new dashboard</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.3.5 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.3.5</span>
<span class="date">(2018-01-24)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated ngRx to 5.0.0</li>
<li>Updated Angular CLI to 1.6.5 to fix the wrong devkit version issue</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.3.4 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.3.4</span>
<span class="date">(2018-01-18)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular to 5.2.1</li>
<li>Updated Angular Material to 5.1.0</li>
<li>Updated various other packages to latest versions</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Quick Panel is too wide for smaller screens</li>
<li>Academy App course step doesn't scroll on mobile</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.3.3 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.3.3</span>
<span class="date">(2018-01-11)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular to 5.2.0</li>
<li>Updated Angular Material to 5.0.4</li>
<li>Updated various other packages to latest versions</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.3.2 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.3.2</span>
<span class="date">(2018-01-09)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular to 5.1.3</li>
<li>Updated Angular Material to 5.0.3</li>
<li>Updated various other packages to latest versions</li>
<li>Added new card designs</li>
<li>Added new fuse-highlight component</li>
<li>Added lazy load to various other demo modules to make the demo project faster</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>BREAKING CHANGE: Cards are moved to custom classes</li>
<li>BREAKING CHANGE: Removed fuse-hljs (Use fuse-highlight instead)</li>
<li>Various other small fixed and enhancements</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.3.1 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.3.1</span>
<span class="date">(2018-01-02)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular to 5.1.2</li>
<li>Updated Angular Material to 5.0.2</li>
<li>Updated various other packages to latest versions</li>
<li>New Academy app</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Mail compose dialog responsive issues</li>
<li>Fixed for various other bugs</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.3.0 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.3.0</span>
<span class="date">(2017-12-15)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular to 5.1.0</li>
<li>Updated Angular Material to 5.0.1</li>
<li>Updated various other packages to latest versions</li>
<li>New NgRx Sample app (Mail-NgRx app)</li>
<li>Form stepper examples</li>
<li>Added support for translations in navigation items</li>
<li>Moved the navigation.model.ts into its own folder</li>
<li>Added badge support for collapsable navigation items</li>
<li>Initialize the navigation from app.component rather then navigation.service</li>
<li>Trigger expand/collapse of the navigation on ngOnInit to update the active item</li>
<li>Replaced Calendar images</li>
<li>Added custom validator for password matching in Auth forms</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Custom scrollbars are showing in print</li>
<li>Various small issues in Auth pages</li>
<li>ngx-color-picker various style issues</li>
<li>Make sure the nav item has children before trying to get them</li>
<li>Renamed the KnowledgeBase demo module</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.2.3 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.2.3</span>
<span class="date">(2017-11-28)</span>
</div>
<div class="groups">
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Sidenav helper causes issues in mobile media steps</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.2.2 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.2.2</span>
<span class="date">(2017-11-27)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular to 5.0.3</li>
<li>Updated Angular Material to 5.0.0-rc.1</li>
<li>Updated Flex Layout</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Contacts app various issues</li>
<li>Duplicate content in Profile page tabs</li>
<li>Folded status of the Navbar shouldn't brake the layout if Horizontal Navbar is active
</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.2.1 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.2.1</span>
<span class="date">(2017-11-13)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular to 5.0.1</li>
<li>Updated Angular Material to 5.0.0-rc0</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Compatibility fixed for Angular Material 5.0.0-rc0</li>
<li>Scrumboard label selector not working properly</li>
<li>Todo detail style refinements</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.2.0 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.2.0</span>
<span class="date">(2017-11-06)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>BREAKING CHANGE: Updated Angular to 5.0.0 (clean installation recommended)</li>
<li>Updated Angular Flex Layout to 2.0.0-beta.10</li>
<li>E-Commerce App</li>
<li>File based translation service and its implementation example</li>
<li>Added Material Design cards</li>
<li>New 'Knowledge Base' page design</li>
<li>Added Tabbed versions of the Carded Sidenav layouts</li>
<li>Added an ability to control the folded status of the vertical navigation via
FuseConfig
</li>
<li>
Added 'exactMatch' property to the Navigation Model for more control over the active
item
highlighting
</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Angular 5 Compatibility fixed</li>
<li>Various iOS10 scrolling issues</li>
<li>FAQ page header shrinks on small heights</li>
<li>Stagger animation doesn't have 'optional' parameter</li>
<li>Toolbar navigation toggle button doesn't actually toggle the navigation bar</li>
<li>Nav items cannot be put on the root in Horizontal menu</li>
<li>Vertical navbar puts out wrong classes when its toggled</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.1.2 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.1.2</span>
<span class="date">(2017-10-16)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>BREAKING CHANGE: Updated Angular Material to 2.0.0-beta.12</li>
<li>Updated Angular to 4.4.5</li>
<li>New Reset and Forgot password page styles</li>
<li>Added 'agm-map', Google Maps component library.</li>
<li>New pricing page design</li>
<li>New mail confirmation page</li>
<li>New FAQ page design</li>
<li>Added new methods for accessing and updating specific nav items</li>
<li>Added the ability to add custom functions to the nav items</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Print styles and page breaks</li>
<li>Inconsistent font sizes across elements</li>
<li>Toolbar search bar button collapses on close</li>
<li>iOS scrolling issues</li>
<li>All 'mat-select' elements wrapped with 'mat-form-field' and fixed related issues</li>
<li>Auth page v2 styles iOS height issues</li>
<li>Chat view is not scrollable on mobile</li>
<li>Terms & Conditions checkbox styling issues on Auth forms</li>
<li>Some page layout header heights not correct on small devices</li>
<li>Lock page layout issues</li>
<li>Calendar & Scrumboard datepicker issues</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.1.1 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.1.1</span>
<span class="date">(2017-09-28)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular Material to 2.0.0-beta.11</li>
<li>Nested grouping in navigation</li>
<li>Added Angular Material elements showcase</li>
</ul>
</div>
<div class="improved">
<span class="title">Improved</span>
<ul>
<li>Replaced Http module with HttpClient</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.1.0 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.1.0</span>
<span class="date">(2017-09-22)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Updated Angular to 4.4.3</li>
<li>Added HMR config for starting the ng serve with HMR support</li>
<li>Added a way to swap navigation models on the fly</li>
<li>Enhanced animations for all apps and some pages</li>
<li>Custom perfect scrollbar directive</li>
<li>Navigation bar backdrop for closing the navigation easily on mobile</li>
</ul>
</div>
<div class="improved">
<span class="title">Improved</span>
<ul>
<li>BREAKING CHANGE: Completely re-structured the navigation model</li>
<li>Locked dev dependency versions to prevent majority of the npm update errors</li>
<li>Updated perfect scrollbar</li>
<li>Calendar, Mail, ToDo and Chat app visual and structural Improved</li>
<li>Disabled the perfect-scrollbar on mobile completely</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.0.5 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.0.5</span>
<span class="date">(2017-09-12)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Horizontal Navigation</li>
<li>Boxed Layout</li>
<li>New fade-in-out animation to Animations service</li>
</ul>
</div>
<div class="improved">
<span class="title">Improved</span>
<ul>
<li>Scrumboard & Chat style Improved</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Removed unused md2 library from skeleton</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.0.4 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.0.4</span>
<span class="date">(2017-08-31)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Scrumboard App</li>
</ul>
</div>
<div class="improved">
<span class="title">Improved</span>
<ul>
<li>Responsive Improved, many more will come</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Dashboard sidenav not correctly working on some mobile devices</li>
<li>Couple MS Edge issues</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.0.3 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.0.3</span>
<span class="date">(2017-08-30)</span>
</div>
<div class="groups">
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Reverted to Angular 4.3.5 since animations are not correctly working on 4.3.6</li>
<li>Firefox and Edge scroll issues</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.0.2 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.0.2</span>
<span class="date">(2017-08-30)</span>
</div>
<div class="groups">
<div class="improved">
<span class="title">Improved</span>
<ul>
<li>Angular Material v2.0.0-beta.10 Compatibility</li>
<li>Upgraded to Angular 4.3.6</li>
<li>Shortcuts component now stores the shortcuts in cookies</li>
<li>Added print styles</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.0.1 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.0.1</span>
<span class="date">(2017-08-24)</span>
</div>
<div class="groups">
<div class="improved">
<span class="title">Improved</span>
<ul>
<li>New router animations</li>
</ul>
</div>
<div class="fixed">
<span class="title">Fixed</span>
<ul>
<li>Fixed AoT compiler issues</li>
</ul>
</div>
</div>
</div>
<!-- --------------------------------------------------------------------------------------------- -->
<!-- @ v1.0.0 -->
<!-- --------------------------------------------------------------------------------------------- -->
<div class="entry">
<div class="title">
<span class="version">v1.0.0</span>
<span class="date">(2017-08-23)</span>
</div>
<div class="groups">
<div class="new">
<span class="title">New</span>
<ul>
<li>Initial Release</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- / CONTENT -->
</div>

View File

@ -1,6 +0,0 @@
@import "src/@fuse/scss/fuse";
:host {
}

View File

@ -1,13 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector : 'docs-changelog',
templateUrl: './changelog.component.html',
styleUrls : ['./changelog.component.scss']
})
export class DocsChangelogComponent
{
constructor()
{
}
}

View File

@ -1,63 +0,0 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector : 'docs-components-third-party-ngx-datatable',
templateUrl: './ngx-datatable.component.html',
styleUrls : ['./ngx-datatable.component.scss']
})
export class DocsComponentsThirdPartyNgxDatatableComponent implements OnInit, OnDestroy
{
rows: any[];
loadingIndicator: boolean;
reorderable: boolean;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {HttpClient} _httpClient
*/
constructor(
private _httpClient: HttpClient
)
{
// Set the defaults
this.loadingIndicator = true;
this.reorderable = true;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._httpClient.get('api/contacts-contacts')
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((contacts: any) => {
this.rows = contacts;
this.loadingIndicator = false;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -1,57 +0,0 @@
<div id="countdown" class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24 h-160" fxLayout="column" fxLayoutAlign="center center" fxLayout.gt-xs="row"
fxLayoutAlign.gt-xs="space-between center">
<div fxLayout="column" fxLayoutAlign="center center" fxLayout.gt-xs="column" fxLayoutAlign.gt-xs="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">3rd Party Components</span>
</div>
<div class="h2 mt-16">Google Maps</div>
</div>
<a mat-raised-button class="reference-button mat-white-bg mt-16 mt-sm-0"
href="https://angular-maps.com"
target="_blank">
<mat-icon class="mr-8">link</mat-icon>
<span>Reference</span>
</a>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>agm-map</code> is a angular component library for Google Maps.
</p>
<div class="sectiont-title">Sample</div>
<p fxLayout="row" fxLayoutAlign="start start">
<agm-map [latitude]="lat" [longitude]="lng">
<agm-marker [latitude]="lat" [longitude]="lng"></agm-marker>
</agm-map>
</p>
<div class="section-title">Usage</div>
<p class="mat-grey-200-bg py-8">
<fuse-highlight lang="html">
<textarea #source>
<agm-map [latitude]="lat" [longitude]="lng">
<agm-marker [latitude]="lat" [longitude]="lng"></agm-marker>
</agm-map>
</textarea>
</fuse-highlight>
</p>
<div class="sectiont-title">Inputs</div>
Checkout the component api docs for detail:
<a href="https://angular-maps.com/api-docs/agm-core/components/AgmMap.html" target="_blank">AgmMap Api</a>
</div>
</div>

View File

@ -1,22 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector : 'docs-components-third-party-google-maps',
templateUrl: './google-maps.component.html',
styleUrls : ['./google-maps.component.scss']
})
export class DocsComponentsThirdPartyGoogleMapsComponent
{
lat: number;
lng: number;
/**
* Constructor
*/
constructor()
{
// Set the defaults
this.lat = -34.397;
this.lng = 150.644;
}
}

View File

@ -1,224 +0,0 @@
import { Component } from '@angular/core';
import * as shape from 'd3-shape';
import { fuseAnimations } from '@fuse/animations/index';
@Component({
selector : 'docs-components-cards',
templateUrl: './cards.component.html',
styleUrls : ['./cards.component.scss'],
animations : fuseAnimations
})
export class DocsComponentsCardsComponent
{
view: string;
card9Expanded: boolean;
card10Expanded: boolean;
card19: any;
card24: any;
card25: any;
card26: any;
constructor()
{
// Set the defaults
this.view = 'preview';
this.card9Expanded = false;
this.card10Expanded = false;
this.card19 = {
scheme: {
domain: ['#5c84f1']
},
data : [
{
'name' : 'GOOG',
'series': [
{
'name' : 'Jan 1',
'value': 540.2
},
{
'name' : 'Jan 2',
'value': 539.4
},
{
'name' : 'Jan 3',
'value': 538.9
},
{
'name' : 'Jan 4',
'value': 539.6
},
{
'name' : 'Jan 5',
'value': 540
},
{
'name' : 'Jan 6',
'value': 540.2
},
{
'name' : 'Jan 7',
'value': 540.48
}
]
}
],
curve : shape.curveBasis
};
this.card24 = {
scheme : {
domain: ['#4867d2', '#5c84f1', '#89a9f4']
},
devices: [
{
'name' : 'Desktop',
'value' : 92.8,
'change': -0.6
},
{
'name' : 'Mobile',
'value' : 6.1,
'change': 0.7
},
{
'name' : 'Tablet',
'value' : 1.1,
'change': 0.1
}
]
};
this.card25 = {
scheme: {
domain: ['#5c84f1']
},
data : [
{
'name' : 'Monday',
'value': 221
},
{
'name' : 'Tuesday',
'value': 428
},
{
'name' : 'Wednesday',
'value': 492
},
{
'name' : 'Thursday',
'value': 471
},
{
'name' : 'Friday',
'value': 413
},
{
'name' : 'Saturday',
'value': 344
},
{
'name' : 'Sunday',
'value': 294
}
]
};
this.card26 = {
scheme: {
domain: ['#5c84f1']
},
data : [
{
'name' : 'Impressions',
'series': [
{
'name' : 'Jan 1',
'value': 670000
},
{
'name' : 'Jan 2',
'value': 540000
},
{
'name' : 'Jan 3',
'value': 820000
},
{
'name' : 'Jan 4',
'value': 570000
},
{
'name' : 'Jan 5',
'value': 720000
},
{
'name' : 'Jan 6',
'value': 570000
},
{
'name' : 'Jan 7',
'value': 870000
},
{
'name' : 'Jan 8',
'value': 720000
},
{
'name' : 'Jan 9',
'value': 890000
},
{
'name' : 'Jan 10',
'value': 987000
},
{
'name' : 'Jan 11',
'value': 1120000
},
{
'name' : 'Jan 12',
'value': 1360000
},
{
'name' : 'Jan 13',
'value': 1100000
},
{
'name' : 'Jan 14',
'value': 1490000
},
{
'name' : 'Jan 15',
'value': 980000
}
]
}
],
curve : shape.curveBasis
};
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle the view
*/
toggleView(): void
{
if ( this.view === 'preview' )
{
this.view = 'source';
}
else
{
this.view = 'preview';
}
}
}

View File

@ -1,95 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { MatButtonModule, MatButtonToggleModule, MatFormFieldModule, MatIconModule, MatListModule, MatMenuModule, MatSelectModule, MatSlideToggleModule, MatTabsModule } from '@angular/material';
import { NgxChartsModule } from '@swimlane/ngx-charts';
import { FuseSharedModule } from '@fuse/shared.module';
import { FuseCountdownModule, FuseHighlightModule, FuseMaterialColorPickerModule, FuseWidgetModule } from '@fuse/components';
import { DocsComponentsCardsComponent } from 'app/main/documentation/components/cards/cards.component';
import { DocsComponentsCountdownComponent } from 'app/main/documentation/components/countdown/countdown.component';
import { DocsComponentsHighlightComponent } from 'app/main/documentation/components/highlight/highlight.component';
import { DocsComponentsMaterialColorPickerComponent } from 'app/main/documentation/components/material-color-picker/material-color-picker.component';
import { DocsComponentsNavigationComponent } from 'app/main/documentation/components/navigation/navigation.component';
import { DocsComponentsSearchBarComponent } from 'app/main/documentation/components/search-bar/search-bar.component';
import { DocsComponentsSidebarComponent } from 'app/main/documentation/components/sidebar/sidebar.component';
import { DocsComponentsShortcutsComponent } from 'app/main/documentation/components/shortcuts/shortcuts.component';
import { DocsComponentsWidgetComponent } from 'app/main/documentation/components/widget/widget.component';
const routes = [
{
path : 'cards',
component: DocsComponentsCardsComponent
},
{
path : 'countdown',
component: DocsComponentsCountdownComponent
},
{
path : 'highlight',
component: DocsComponentsHighlightComponent
},
{
path : 'material-color-picker',
component: DocsComponentsMaterialColorPickerComponent
},
{
path : 'navigation',
component: DocsComponentsNavigationComponent
},
{
path : 'search-bar',
component: DocsComponentsSearchBarComponent
},
{
path : 'sidebar',
component: DocsComponentsSidebarComponent
},
{
path : 'shortcuts',
component: DocsComponentsShortcutsComponent
},
{
path : 'widget',
component: DocsComponentsWidgetComponent
}
];
@NgModule({
declarations: [
DocsComponentsCardsComponent,
DocsComponentsCountdownComponent,
DocsComponentsHighlightComponent,
DocsComponentsMaterialColorPickerComponent,
DocsComponentsNavigationComponent,
DocsComponentsSearchBarComponent,
DocsComponentsSidebarComponent,
DocsComponentsShortcutsComponent,
DocsComponentsWidgetComponent
],
imports : [
RouterModule.forChild(routes),
MatButtonModule,
MatButtonToggleModule,
MatFormFieldModule,
MatIconModule,
MatListModule,
MatMenuModule,
MatSelectModule,
MatSlideToggleModule,
MatTabsModule,
NgxChartsModule,
FuseSharedModule,
FuseCountdownModule,
FuseHighlightModule,
FuseMaterialColorPickerModule,
FuseWidgetModule
]
})
export class ComponentsModule
{
}

View File

@ -1,51 +0,0 @@
<div id="countdown" class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24 h-160" fxLayout="row" fxLayoutAlign="start center">
<div fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Components</span>
</div>
<div class="h2 mt-16">Countdown</div>
</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>fuse-countdown</code> is a custom built Fuse component allows you to create a countdowns.
</p>
<div class="section-title">Sample</div>
<p fxLayout="row" fxLayoutAlign="start start">
<fuse-countdown eventDate="2019-07-28"></fuse-countdown>
</p>
<div class="section-title">Usage</div>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<fuse-countdown eventDate="2019-07-28"></fuse-countdown>
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Inputs</div>
<p class="py-8" fxLayout="row" fxLayoutAlign="start center">
<code class="mr-16">eventDate</code>
<span>
The date of the event. Since fuse-countdown uses moment.js to parse the dates, any moment.js
compatible date string can be used.
</span>
</p>
</div>
</div>

View File

@ -1,68 +0,0 @@
<div id="highlight" class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24 h-160" fxLayout="row" fxLayoutAlign="start center">
<div fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Components</span>
</div>
<div class="h2 mt-16">Highlight</div>
</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>fuse-highlight</code> is a custom built Fuse component allows to show syntax highlighted codes.
</p>
<div class="section-title">Sample</div>
<p fxLayout="row" fxLayoutAlign="start start">
<fuse-highlight lang="html">
<textarea #source>
<div class="title">
<span>Example Title</span>
</div>
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Usage</div>
<p class="mat-grey-200-bg py-8">
<fuse-highlight lang="html">
<textarea #source>
&lt;fuse-highlight lang="html"&gt;
&lt;textarea #source&gt;
&lt;div class="title"&gt;
&lt;span&gt;Example Title&lt;/span&gt;
&lt;/div&gt;
&lt;/textarea&gt;
&lt;/fuse-highlight&gt;
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Inputs</div>
<p class="py-8" fxLayout="row" fxLayoutAlign="start center">
<code class="mr-16">lang</code>
<span>
Language of the code to be highlighted.
</span>
</p>
</div>
</div>

View File

@ -1,69 +0,0 @@
<div id="material-color-picker" class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24 h-160" fxLayout="row" fxLayoutAlign="start center">
<div fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Components</span>
</div>
<div class="h2 mt-16">Material Color Picker</div>
</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>fuse-material-color-picker</code> is a custom built Fuse component allows you to add a color picker
that allows to choose one of the many Material spec. colors.
</p>
<div class="section-title">Sample</div>
<p fxLayout="row" fxLayoutAlign="start start">
<fuse-material-color-picker></fuse-material-color-picker>
</p>
<div class="section-title">Usage</div>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<fuse-material-color-picker [(selectedClass)]="colorClass"
(onValueChange)="onSettingsChange()">
</fuse-material-color-picker>
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Two-way bindings</div>
<p class="py-8" fxLayout="row" fxLayoutAlign="start center">
<code class="mr-16">selectedClass</code>
<span>
The name of the Fuse color class to select, e.g. <code>mat-red-500-bg</code>
</span>
</p>
<p class="py-8 pt-4" fxLayout="row" fxLayoutAlign="start center">
<code class="mr-16">selectedBg</code>
<span>
The hex code of the color to be selected. It will be only selected if the hex code of the color
matches one of the material colors.
</span>
</p>
<div class="section-title">Outputs</div>
<p class="py-8" fxLayout="row" fxLayoutAlign="start center">
<code class="mr-16">onValueChange</code>
<span>
Event that triggered when a color selected. Returns an object that holds palette, hue, class name,
background and foreground colors.
</span>
</p>
</div>
</div>

View File

@ -1,381 +0,0 @@
<div id="navigation" class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24 h-160" fxLayout="row" fxLayoutAlign="start center">
<div fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Components</span>
</div>
<div class="h2 mt-16">Navigation</div>
</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>fuse-navigation</code> is a custom built Fuse component allows you to create a multi-level collapsable
navigation. It has built-in support for translations using <b>ngx-translate</b> module.
</p>
<div class="section-title">Usage</div>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<fuse-navigation [navigation]="navigation" [layout]="'vertical'"></fuse-navigation>
</textarea>
</fuse-highlight>
</p>
<div class="my-48">
<h2>[navigation]</h2>
<p class="py-8">
<code>&lt;fuse-navigation&gt;&lt;/fuse-navigation&gt;</code> uses a json file to populate
the entire navigation. It supports three different navigation items; <b>Group</b>,
<b>Collapsable</b> and <b>Item</b>. These items can be mixed and matched to create unique and complex
navigation layouts.
</p>
<p class="py-8">
Navigation data can be found in <code>src/app/navigation</code> folder along with its translation
files. Navigation data and its translation files are set in <b>app.component.ts</b> file. Check that
file for more detailed usage example.
</p>
</div>
<div class="my-48">
<h2>[layout]</h2>
<p class="py-8">
There are two different layout options for the component; <code>vertical</code> and
<code>horizontal</code>. You can set the layout using the <code>[layout]</code> input.
</p>
</div>
<div class="section-title">Alternative usage (preferred)</div>
<p class="py-8">
An alternative usage to the above one is to using the <b>Navigation Service</b>. Simply, you get your
navigation array, register that as a navigation using the service and then set it as the current
navigation. This allows for easier updating and swapping of the navigation:
</p>
<p class="py-8">
<fuse-highlight lang="ts">
<textarea #source>
// Get your navigation array from database or file
this.navigation = [...]
// Register the navigation to the service
this._fuseNavigationService.register('main', this.navigation);
// Set the main navigation as our current navigation
this._fuseNavigationService.setCurrentNavigation('main');
</textarea>
</fuse-highlight>
</p>
<p class="py-8">
Once you register your navigation like this, you no longer need to provide the <b>[navigation]</b> input
while using the <code>fuse-navigation</code>:
</p>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<fuse-navigation [layout]="'vertical'"></fuse-navigation>
</textarea>
</fuse-highlight>
</p>
<div class="main-title">Navigation item types</div>
<div class="section-title">Grouping</div>
<p class="py-8">
<fuse-highlight lang="json">
<textarea #source>
{
'id' : 'components',
'title' : 'COMPONENTS',
'translate': 'NAV.COMPONENTS',
'type' : 'group',
'children' : [
{
'id' : 'ngx-datatable',
'title': 'ngx-datatable',
'type' : 'item',
'url' : '/components/datatables/ngx-datatable'
}
]
}
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Collapsable</div>
<p class="py-8">
<fuse-highlight lang="json">
<textarea #source>
{
'id' : 'datatables',
'title' : 'Datatables',
'translate': 'NAV.DATATABLES',
'type' : 'collapsable',
'icon' : 'border_all',
'children' : [
{
'id' : 'ngx-datatable',
'title': 'ngx-datatable',
'type' : 'item',
'url' : '/components/datatables/ngx-datatable'
}
]
},
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Item</div>
<p class="py-8">
<fuse-highlight lang="json">
<textarea #source>
{
'id' : 'countdown',
'title' : 'Countdown',
'translate': 'NAV.COUNTDOWN',
'type' : 'item',
'icon' : 'settings_input_component',
'url' : '/components/countdown'
},
</textarea>
</fuse-highlight>
</p>
<div class="main-title">Vertical Navigation Default Folded Status</div>
<p>
It's possible to change the default folded status of the navigation.
</p>
<p>
Find the layout that you want to edit from <b>app/layout/vertical/</b> directory. Edit the layout's html
file and look for the <code>[folded]</code> attribute on <code>fuse-sidebar</code> components.
</p>
<p>
Assigning <code>true</code> to that attribute will make the vertical navigation folded by default.
</p>
<div class="main-title">Updating the navigation</div>
<p class="message-box warning">
In order to make the runtime modifications easier, it's strongly recommended that to give a unique id
to all of your navigation items.
</p>
<div class="section-title">Show / Hide certain navigation items</div>
<div class="my-24">
<button mat-button mat-raised-button color="accent" (click)="showHideCalendarMenuItem()">
Show / Hide calendar menu item
</button>
</div>
<p class="py-8 mb-48">
<fuse-highlight lang="typescript">
<textarea #source>
hidden = false;
showHideCalendarMenuItem(): void
{
// Get the calendar item from the navigation
const calendarNavItem = this._fuseNavigationService.getNavigationItem('calendar');
// Toggle the visibility
this.hidden = !this.hidden;
calendarNavItem.hidden = this.hidden;
}
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Update navigation item on-the-fly</div>
<div class="my-24">
<button mat-button mat-raised-button color="accent" (click)="updateMailBadge()">
Update Mail app badge
</button>
</div>
<p class="py-8 mb-48">
<fuse-highlight lang="typescript">
<textarea #source>
updateMailBadge()
{
// Get the mail nav item
const mailNavItem = this._fuseNavigationService.getNavigationItem('mail');
// Update the badge title
mailNavItem.badge.title = 35;
}
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Add a subitem to the Calendar nav item</div>
<div class="my-24">
<button mat-button mat-raised-button color="accent" (click)="addSubitemToCalendar()">
Add a subitem to the Calendar nav item
</button>
</div>
<p class="py-8 mb-48">
<fuse-highlight lang="typescript">
<textarea #source>
addSubitemToCalendar()
{
// Prepare the new nav item
const newNavItem = {
id : 'sub-item',
title: 'Sub Item',
type : 'item',
url : '/apps/calendar'
};
// Get the calendar item from the navigation
const calendarNavItem = this._fuseNavigationService.getNavigationItem('calendar');
// Make the calendar navigation item collapsable
calendarNavItem.type = 'collapse';
// Add the navigation item
this._fuseNavigationService.addNavigationItem(newNavItem, 'calendar');
}
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Add a nav item with custom function</div>
<div class="my-24">
<button mat-button mat-raised-button color="accent" (click)="addNavItemWithCustomFunction()">
Add a nav item with custom function
</button>
</div>
<p class="py-8 mb-48">
<fuse-highlight lang="typescript">
<textarea #source>
addNavItemWithCustomFunction()
{
// Prepare the new nav item
const newNavItem = {
id : 'custom-item',
title : 'Custom Item',
type : 'item',
function: () => {
alert('Custom function!');
}
};
// Add the new nav item at the beginning of the navigation
this._fuseNavigationService.addNavigationItem(newNavItem, 'start');
}
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Remove the Dashboards menu item</div>
<div class="my-24">
<button mat-button mat-raised-button color="accent" (click)="removeDashboards()">
Remove Dashboards menu item
</button>
</div>
<p class="py-8 mb-48">
<fuse-highlight lang="typescript">
<textarea #source>
removeDashboards(): void
{
this._fuseNavigationService.removeNavigationItem('dashboards');
}
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Register a new navigation and toggle to it</div>
<div class="my-24">
<button mat-button mat-raised-button color="accent" (click)="registerNewNavigationAndToggle()">
Register a new navigation and toggle to it
</button>
</div>
<p class="py-8">
<fuse-highlight lang="typescript">
<textarea #source>
registerNewNavigationAndToggle(): void
{
const adminNav = [
{
id : 'admin',
title : 'Admin',
type : 'group',
icon : 'apps',
children: [
{
id : 'users',
title: 'Users',
type : 'item',
icon : 'person',
url : '/apps/dashboards/analytics'
},
{
id : 'payments',
title: 'Payments',
type : 'item',
icon : 'attach_money',
url : '/apps/academy'
}
]
},
{
id : 'control-panel',
title : 'Control Panel',
type : 'group',
icon : 'apps',
children: [
{
id : 'cron-jobs',
title: 'Cron Jobs',
type : 'item',
icon : 'settings',
url : '/apps/file-manager'
},
{
id : 'maintenance-mode',
title: 'Maintenance Mode',
type : 'item',
icon : 'build',
url : '/apps/todo'
}
]
}
];
// Register the new navigation
this._fuseNavigationService.register('admin-nav', adminNav);
// Set the current navigation
this._fuseNavigationService.setCurrentNavigation('admin-nav');
}
</textarea>
</fuse-highlight>
</p>
</div>
</div>

View File

@ -1,163 +0,0 @@
import { Component } from '@angular/core';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
@Component({
selector : 'docs-components-navigation',
templateUrl: './navigation.component.html',
styleUrls : ['./navigation.component.scss']
})
export class DocsComponentsNavigationComponent
{
navigation: any;
hidden: boolean;
/**
* Constructor
*/
constructor(
private _fuseNavigationService: FuseNavigationService
)
{
// Set the defaults
this.hidden = false;
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Show/hide calendar menu item
*/
showHideCalendarMenuItem(): void
{
// Get the calendar item from the navigation
const calendarNavItem = this._fuseNavigationService.getNavigationItem('calendar');
// Toggle the visibility
this.hidden = !this.hidden;
calendarNavItem.hidden = this.hidden;
}
/**
* Update mail badge
*/
updateMailBadge(): void
{
// Get the mail nav item
const mailNavItem = this._fuseNavigationService.getNavigationItem('mail');
// Update the badge title
mailNavItem.badge.title = 35;
}
/**
* Add subitem to the calendar
*/
addSubitemToCalendar(): void
{
// Prepare the new nav item
const newNavItem = {
id : 'sub-item',
title: 'Sub Item',
type : 'item',
url : '/apps/calendar'
};
// Get the calendar item from the navigation
const calendarNavItem = this._fuseNavigationService.getNavigationItem('calendar');
// Make the calendar navigation item collapsable
calendarNavItem.type = 'collapsable';
// Add the navigation item
this._fuseNavigationService.addNavigationItem(newNavItem, 'calendar');
}
/**
* Add a nav item with custom function
*/
addNavItemWithCustomFunction(): void
{
// Prepare the new nav item
const newNavItem = {
id : 'custom-item',
title : 'Custom Item',
type : 'item',
function: () => {
alert('Custom function!');
}
};
// Add the new nav item at the beginning of the navigation
this._fuseNavigationService.addNavigationItem(newNavItem, 'start');
}
/**
* Remove the dashboard menu item
*/
removeDashboards(): void
{
this._fuseNavigationService.removeNavigationItem('dashboards');
}
/**
* Register a new navigation and toggle to it
*/
registerNewNavigationAndToggle(): void
{
const adminNav = [
{
id : 'admin',
title : 'Admin',
type : 'group',
icon : 'apps',
children: [
{
id : 'users',
title: 'Users',
type : 'item',
icon : 'person',
url : '/apps/dashboards/analytics'
},
{
id : 'payments',
title: 'Payments',
type : 'item',
icon : 'attach_money',
url : '/apps/academy'
}
]
},
{
id : 'control-panel',
title : 'Control Panel',
type : 'group',
icon : 'apps',
children: [
{
id : 'cron-jobs',
title: 'Cron Jobs',
type : 'item',
icon : 'settings',
url : '/apps/file-manager'
},
{
id : 'maintenance-mode',
title: 'Maintenance Mode',
type : 'item',
icon : 'build',
url : '/apps/todo'
}
]
}
];
// Register the new navigation
this._fuseNavigationService.register('admin-nav', adminNav);
// Set the current navigation
this._fuseNavigationService.setCurrentNavigation('admin-nav');
}
}

View File

@ -1,46 +0,0 @@
<div id="search-bar" class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24 h-160" fxLayout="row" fxLayoutAlign="start center">
<div fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Components</span>
</div>
<div class="h2 mt-16">Search Bar</div>
</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>fuse-search-bar</code> is a custom built Fuse component allows you to have a search bar that activates
on click.
</p>
<div class="section-title">Usage</div>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<fuse-search-bar (input)="search($event)"></fuse-search-bar>
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Outputs</div>
<p class="py-8" fxLayout="row" fxLayoutAlign="start center">
<code class="mr-8">input</code>
<span>Triggers every time an input occurs within the search bar. Can be used to trigger the actual
search mechanism. The $event is the value from the search input.
</span>
</p>
</div>
</div>

View File

@ -1,45 +0,0 @@
<div id="shortcuts" class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24 h-160" fxLayout="row" fxLayoutAlign="start center">
<div fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Components</span>
</div>
<div class="h2 mt-16">Shortcuts</div>
</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>fuse-shortcuts</code> is a custom built Fuse component allows you to create and save shortcuts from
the navigation model.
</p>
<div class="section-title">Usage</div>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<fuse-shortcuts></fuse-shortcuts>
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Model</div>
<p class="py-8">
<code>&lt;fuse-shortcuts&gt;&lt;/fuse-shortcuts&gt;</code> uses the same service with navigation
component to populate the shortcuts. It can search the navigation items as well as pin and unpin them as
shortcuts. It uses browser cookies to store the shortcuts.
</p>
</div>
</div>

View File

@ -1,108 +0,0 @@
<div id="widget" class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24 h-160" fxLayout="row" fxLayoutAlign="start center">
<div fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Components</span>
</div>
<div class="h2 mt-16">Widget</div>
</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>fuse-widget</code> is a custom built Fuse component allows to create flippable widget boxes.
</p>
<div class="section-title">Sample</div>
<div>
<fuse-widget class="" fxLayout="column" fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="pl-16 pr-8 py-16 h-52" fxLayout="row" fxLayoutAlign="space-between center">
<div>Widget title</div>
<button mat-icon-button fuseWidgetToggle aria-label="more">
<mat-icon>more_vert</mat-icon>
</button>
</div>
<div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center">
Widget Content
</div>
</div>
<!-- / Front -->
<!-- Back -->
<div class="fuse-widget-back p-16 pt-32 mat-white-bg mat-elevation-z2">
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="Flip widget">
<mat-icon class="s-16">close</mat-icon>
</button>
<div>
More widget info
</div>
</div>
<!-- / Back -->
</fuse-widget>
</div>
<div class="section-title">Usage</div>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<fuse-widget class="" fxLayout="column" fxFlex="100" fxFlex.gt-xs="50" fxFlex.gt-md="25">
<!-- Front -->
<div class="fuse-widget-front mat-white-bg mat-elevation-z2">
<div class="pl-16 pr-8 py-16 h-52" fxLayout="row" fxLayoutAlign="space-between center">
<div>Widget title</div>
<button mat-icon-button fuseWidgetToggle aria-label="more">
<mat-icon>more_vert</mat-icon>
</button>
</div>
<div class="pt-8 pb-32" fxLayout="column" fxLayoutAlign="center center">
Widget Content
</div>
</div>
<!-- / Front -->
<!-- Back -->
<div class="fuse-widget-back p-16 pt-32 mat-white-bg mat-elevation-z2">
<button mat-icon-button fuseWidgetToggle class="fuse-widget-flip-button"
aria-label="Flip widget">
<mat-icon class="s-16">close</mat-icon>
</button>
<div>
More widget info
</div>
</div>
<!-- / Back -->
</fuse-widget>
</textarea>
</fuse-highlight>
</p>
</div>
</div>

View File

@ -1,51 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { MatButtonModule, MatIconModule } from '@angular/material';
import { FuseSharedModule } from '@fuse/shared.module';
import { FuseHighlightModule } from '@fuse/components';
import { DocsDirectivesFuseIfOnDomComponent } from 'app/main/documentation/directives/fuseIfOnDom/fuse-if-on-dom.component';
import { DocsDirectivesFuseInnerScrollComponent } from 'app/main/documentation/directives/fuseInnerScroll/fuse-inner-scroll.component';
import { DocsDirectivesFuseMatSidenavComponent } from 'app/main/documentation/directives/fuseMatSidenav/fuse-mat-sidenav.component';
import { DocsDirectivesFusePerfectScrollbarComponent } from 'app/main/documentation/directives/fusePerfectScrollbar/fuse-perfect-scrollbar.component';
const routes = [
{
path : 'fuse-if-on-dom',
component: DocsDirectivesFuseIfOnDomComponent
},
{
path : 'fuse-inner-scroll',
component: DocsDirectivesFuseInnerScrollComponent
},
{
path : 'fuse-mat-sidenav',
component: DocsDirectivesFuseMatSidenavComponent
},
{
path : 'fuse-perfect-scrollbar',
component: DocsDirectivesFusePerfectScrollbarComponent
}
];
@NgModule({
declarations: [
DocsDirectivesFuseIfOnDomComponent,
DocsDirectivesFuseInnerScrollComponent,
DocsDirectivesFuseMatSidenavComponent,
DocsDirectivesFusePerfectScrollbarComponent
],
imports : [
RouterModule.forChild(routes),
MatButtonModule,
MatIconModule,
FuseSharedModule,
FuseHighlightModule
]
})
export class DirectivesModule
{
}

View File

@ -1,40 +0,0 @@
<div class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24" fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Directives</span>
</div>
<div class="h2 mt-16">fuseIfOnDom</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>*fuseIfOnDom</code> is a helper directive that detaches and re-attaches the given element if it's
currently in the DOM. This will help in various cases such as charts that don't resize properly or
animations that don't wait to route to be loaded completely.
</p>
<div class="section-title">Usage</div>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<div *fuseIfOnDom></div>
</textarea>
</fuse-highlight>
</p>
</div>
<!-- / CONTENT -->
</div>

View File

@ -1,13 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector : 'docs-directives-fuse-if-on-dom',
templateUrl: './fuse-if-on-dom.component.html',
styleUrls : ['./fuse-if-on-dom.component.scss']
})
export class DocsDirectivesFuseIfOnDomComponent
{
constructor()
{
}
}

View File

@ -1,43 +0,0 @@
<div class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24" fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Directives</span>
</div>
<div class="h2 mt-16">fuseInnerScroll</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>fuseInnerScroll</code> is a class directive that can be used in page layouts. It will lock the
container's scroll allowing for individual scroll such as sidebar and the content itself.
</p>
<p class="message-box warning">
This directive will only work with Fuse's pre-built page layouts and it's a class directive.
</p>
<div class="section-title">Usage</div>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<div class="page-layout carded left-sidebar inner-scroll">
</textarea>
</fuse-highlight>
</p>
</div>
<!-- / CONTENT -->
</div>

View File

@ -1,5 +0,0 @@
@import "src/@fuse/scss/fuse";
:host {
}

View File

@ -1,13 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector : 'docs-directives-fuse-inner-scroll',
templateUrl: './fuse-inner-scroll.component.html',
styleUrls : ['./fuse-inner-scroll.component.scss']
})
export class DocsDirectivesFuseInnerScrollComponent
{
constructor()
{
}
}

View File

@ -1,72 +0,0 @@
<div class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24" fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Directives</span>
</div>
<div class="h2 mt-16">fuseMatSidenav</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>fuseMatSidenav</code> is a helper directive that enhances the Angular Material's sidenav. It modifies
the sidenav so it will function like the Angular Material 1.x sidenav. It also has a service which you can
register a sidenav in order to access and control its status from anywhere.
</p>
<div class="section-title">Usage</div>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<mat-sidenav position="start" opened="true" mode="side"
fuseMatSidenavHelper="chat-left-sidenav" mat-is-locked-open="gt-md">
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Inputs</div>
<p class="py-8" fxLayout="row" fxLayoutAlign="start center">
<code class="mr-16">fuseMatSidenavHelper</code>
<span>
A unique name for the sidenav.
</span>
</p>
<p class="py-8" fxLayout="row" fxLayoutAlign="start center">
<code class="mr-16">mat-is-locked-open</code>
<span>
Adds a locked open functionality just like Angular Material 1.x sidenav. Works with the media step
aliases of the FlexLayout library.
</span>
</p>
<div class="section-title">Accessing to the sidebav methods from anywhere</div>
<p class="py-8">
<fuse-highlight lang="ts">
<textarea #source>
constructor(
private _fuseMatSidenavHelperService: FuseMatSidenavHelperService,
) {}
toggleSidenav()
{
this._fuseMatSidenavHelperService.getSidenav('chat-left-sidenav').toggle();
}
</textarea>
</fuse-highlight>
</p>
</div>
<!-- / CONTENT -->
</div>

View File

@ -1,8 +0,0 @@
@import "src/@fuse/scss/fuse";
:host {
code {
white-space: nowrap;
}
}

View File

@ -1,13 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector : 'docs-directives-fuse-mat-sidenav',
templateUrl: './fuse-mat-sidenav.component.html',
styleUrls : ['./fuse-mat-sidenav.component.scss']
})
export class DocsDirectivesFuseMatSidenavComponent
{
constructor()
{
}
}

View File

@ -1,65 +0,0 @@
<div class="page-layout simple fullwidth docs">
<!-- HEADER -->
<div class="header mat-accent-bg p-24" fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Directives</span>
</div>
<div class="h2 mt-16">fusePerfectScrollbar</div>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content p-24">
<p>
<code>fusePerfectScrollbar</code> is an Angular directive for the <a
href="https://github.com/utatti/perfect-scrollbar" target="_blank">Perfect Scrollbar</a> library.
</p>
<div class="section-title">Usage</div>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<div fusePerfectScrollbar>
</textarea>
</fuse-highlight>
</p>
<p class="py-8">
<fuse-highlight lang="html">
<textarea #source>
<div [fusePerfectScrollbar]="false" [fusePerfectScrollbarOptions]="{'updateOnRouteChange': true}">
</textarea>
</fuse-highlight>
</p>
<div class="section-title">Inputs</div>
<p class="py-8" fxLayout="row" fxLayoutAlign="start center">
<code class="mr-16">fusePerfectScrollbar</code>
<span>
Accepts an optional boolean which you can control the Perfect Scrollbar. If provided false, Perfect
Scrollbar will be destroyed or won't be initialized.
</span>
</p>
<p class="py-8" fxLayout="row" fxLayoutAlign="start center">
<code class="mr-16">fusePerfectScrollbarOptions</code>
<span>
Accepts the <a href="https://github.com/utatti/perfect-scrollbar#options" target="_blank">Perfect
Scrollbar options</a>. In addition to those options, there is also a custom <b>updateOnRouteChange</b>
option which updates the scrollbar on route changes. That's useful if your scrollbar wraps a
<b>router-outlet</b>.
</span>
</p>
</div>
<!-- / CONTENT -->
</div>

Some files were not shown because too many files have changed in this diff Show More