Improving the codebase (wip)

This commit is contained in:
Sercan Yemen 2018-05-20 10:12:31 +03:00
parent ced0853af8
commit 0039f44936
170 changed files with 4715 additions and 2064 deletions

View File

@ -25,7 +25,7 @@
"assets": [ "assets": [
"src/favicon.ico", "src/favicon.ico",
"src/assets", "src/assets",
"src/app/main/content/components/angular-material" "src/app/main/components/angular-material"
], ],
"styles": [ "styles": [
"src/styles.scss" "src/styles.scss"

View File

@ -10,7 +10,14 @@ export class FuseConfirmDialogComponent
{ {
public confirmMessage: string; public confirmMessage: string;
constructor(public dialogRef: MatDialogRef<FuseConfirmDialogComponent>) /**
* Constructor
*
* @param {MatDialogRef<FuseConfirmDialogComponent>} dialogRef
*/
constructor(
public dialogRef: MatDialogRef<FuseConfirmDialogComponent>
)
{ {
} }

View File

@ -1,8 +1,6 @@
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { interval, Subject } from 'rxjs';
import { interval } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators';
import { map } from 'rxjs/operators';
import * as moment from 'moment'; import * as moment from 'moment';
@Component({ @Component({
@ -10,46 +8,82 @@ import * as moment from 'moment';
templateUrl: './countdown.component.html', templateUrl: './countdown.component.html',
styleUrls : ['./countdown.component.scss'] styleUrls : ['./countdown.component.scss']
}) })
export class FuseCountdownComponent implements OnInit export class FuseCountdownComponent implements OnInit, OnDestroy
{ {
@Input('eventDate') eventDate; // Event date
@Input('eventDate')
eventDate;
countdown: any; countdown: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*/
constructor() constructor()
{ {
// Set the defaults
this.countdown = { this.countdown = {
days : '', days : '',
hours : '', hours : '',
minutes: '', minutes: '',
seconds: '' seconds: ''
}; };
// Set the private defaults
this._unsubscribeAll = new Subject();
} }
ngOnInit() // -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{ {
const currDate = moment(); const currDate = moment();
const eventDate = moment(this.eventDate); const eventDate = moment(this.eventDate);
// Get the difference in between the current date and event date
let diff = eventDate.diff(currDate, 'seconds'); let diff = eventDate.diff(currDate, 'seconds');
const countDown = interval(1000).pipe( // Create a subscribable interval
map(value => { const countDown = interval(1000)
return diff = diff - 1; .pipe(
}), map(value => {
map(value => { return diff = diff - 1;
const timeLeft = moment.duration(value, 'seconds'); }),
map(value => {
const timeLeft = moment.duration(value, 'seconds');
return { return {
days : timeLeft.asDays().toFixed(0), days : timeLeft.asDays().toFixed(0),
hours : timeLeft.hours(), hours : timeLeft.hours(),
minutes: timeLeft.minutes(), minutes: timeLeft.minutes(),
seconds: timeLeft.seconds() seconds: timeLeft.seconds()
}; };
}) })
); );
countDown.subscribe(value => { // Subscribe to the countdown interval
this.countdown = value; countDown
}); .pipe(takeUntil(this._unsubscribeAll))
.subscribe(value => {
this.countdown = value;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
} }
} }

View File

@ -7,6 +7,9 @@ import { Component } from '@angular/core';
}) })
export class FuseDemoContentComponent export class FuseDemoContentComponent
{ {
/**
* Constructor
*/
constructor() constructor()
{ {
} }

View File

@ -7,6 +7,9 @@ import { Component } from '@angular/core';
}) })
export class FuseDemoSidenavComponent export class FuseDemoSidenavComponent
{ {
/**
* Constructor
*/
constructor() constructor()
{ {
} }

View File

@ -1,28 +1,55 @@
import { Component, ContentChild, ElementRef, Input, OnInit } from '@angular/core'; import { Component, ContentChild, ElementRef, Input, OnDestroy, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import * as Prism from 'prismjs/prism'; import * as Prism from 'prismjs/prism';
import './prism-languages'; import '@fuse/components/highlight/prism-languages';
@Component({ @Component({
selector : 'fuse-highlight', selector : 'fuse-highlight',
template : ' ', template : '',
styleUrls: ['./highlight.component.scss'] styleUrls: ['./highlight.component.scss']
}) })
export class FuseHighlightComponent implements OnInit export class FuseHighlightComponent implements OnInit, OnDestroy
{ {
@ContentChild('source') source: ElementRef; // Source
@Input('lang') lang: string; @ContentChild('source')
@Input('path') path: string; source: ElementRef;
// Lang
@Input('lang')
lang: string;
// Path
@Input('path')
path: string;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ElementRef} _elementRef
* @param {HttpClient} _httpClient
*/
constructor( constructor(
private elementRef: ElementRef, private _elementRef: ElementRef,
private http: HttpClient private _httpClient: HttpClient
) )
{ {
// Set the private defaults
this._unsubscribeAll = new Subject();
} }
ngOnInit() // -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{ {
// If there is no language defined, return... // If there is no language defined, return...
if ( !this.lang ) if ( !this.lang )
@ -34,11 +61,13 @@ export class FuseHighlightComponent implements OnInit
if ( this.path ) if ( this.path )
{ {
// Get the source // Get the source
this.http.get(this.path, {responseType: 'text'}).subscribe((response) => { this._httpClient.get(this.path, {responseType: 'text'})
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((response) => {
// Highlight it // Highlight it
this.highlight(response); this.highlight(response);
}); });
} }
// If the path is not defined and the source element exists... // If the path is not defined and the source element exists...
@ -49,7 +78,26 @@ export class FuseHighlightComponent implements OnInit
} }
} }
highlight(sourceCode) /**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Highlight the given source code
*
* @param sourceCode
*/
highlight(sourceCode): void
{ {
// Split the source into lines // Split the source into lines
const sourceLines = sourceCode.split('\n'); const sourceLines = sourceCode.split('\n');
@ -94,9 +142,8 @@ export class FuseHighlightComponent implements OnInit
const highlightedCode = Prism.highlight(source, Prism.languages[this.lang]); const highlightedCode = Prism.highlight(source, Prism.languages[this.lang]);
// Replace the innerHTML of the component with the highlighted code // Replace the innerHTML of the component with the highlighted code
this.elementRef.nativeElement.innerHTML = this._elementRef.nativeElement.innerHTML =
'<pre><code class="highlight language-' + this.lang + '">' + highlightedCode + '</code></pre>'; '<pre><code class="highlight language-' + this.lang + '">' + highlightedCode + '</code></pre>';
} }
} }

View File

@ -2,7 +2,6 @@ export * from './confirm-dialog/confirm-dialog.module';
export * from './countdown/countdown.module'; export * from './countdown/countdown.module';
export * from './demo/demo.module'; export * from './demo/demo.module';
export * from './highlight/highlight.module'; export * from './highlight/highlight.module';
export * from './layouts/layouts.module';
export * from './material-color-picker/material-color-picker.module'; export * from './material-color-picker/material-color-picker.module';
export * from './navigation/navigation.module'; export * from './navigation/navigation.module';
export * from './search-bar/search-bar.module'; export * from './search-bar/search-bar.module';

View File

@ -1,19 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FuseVerticalNavBasicLayoutComponent } from '@fuse/components/layouts/vertical-nav/basic/basic.component';
@NgModule({
declarations: [
FuseVerticalNavBasicLayoutComponent
],
imports : [
CommonModule
],
exports : [
FuseVerticalNavBasicLayoutComponent
]
})
export class FuseLayoutsModule
{
}

View File

@ -1,77 +0,0 @@
<mat-sidenav-container>
<div id="fuse-main-content">
<!-- TOOLBAR: Above -->
<ng-container *ngIf="fuseSettings.layout.toolbar === 'above'">
<fuse-toolbar class="above" [ngClass]="fuseSettings.colorClasses.toolbar"></fuse-toolbar>
</ng-container>
<!-- / TOOLBAR: Above -->
<!-- NAVBAR: Top -->
<fuse-navbar layout="horizontal"
class="top-navbar" fxHide fxShow.gt-md
[ngClass]="fuseSettings.colorClasses.navbar"
*ngIf="fuseSettings.layout.navigation === 'top'">
</fuse-navbar>
<!-- / NAVBAR: Top -->
<div id="wrapper">
<!-- NAVBAR: Left -->
<fuse-sidebar [name]="'navbar'"
[folded]="fuseSettings.layout.navigationFolded"
[lockedOpen]="'gt-md'"
class="left-navbar" [ngClass]="fuseSettings.colorClasses.navbar"
*ngIf="fuseSettings.layout.navigation === 'left' || fuseSettings.layout.navigation === 'top'">
<fuse-navbar layout="vertical"></fuse-navbar>
</fuse-sidebar>
<!-- / NAVBAR: Left -->
<div class="content-wrapper">
<!-- TOOLBAR: Below -->
<ng-container *ngIf="fuseSettings.layout.toolbar === 'below'">
<fuse-toolbar class="below" [ngClass]="fuseSettings.colorClasses.toolbar"></fuse-toolbar>
</ng-container>
<!-- / TOOLBAR: Below -->
<fuse-content></fuse-content>
<!-- FOOTER: Below -->
<ng-container *ngIf="fuseSettings.layout.footer === 'below'">
<fuse-footer class="below" [ngClass]="fuseSettings.colorClasses.footer"></fuse-footer>
</ng-container>
<!-- / FOOTER: Below -->
</div>
<!-- NAVBAR: Right -->
<fuse-sidebar [name]="'navbar'" [align]="'right'"
[folded]="fuseSettings.layout.navigationFolded"
[lockedOpen]="'gt-md'"
class="right-navbar" [ngClass]="fuseSettings.colorClasses.navbar"
*ngIf="fuseSettings.layout.navigation === 'right'">
<fuse-navbar layout="vertical"></fuse-navbar>
</fuse-sidebar>
<!-- / NAVBAR: Right -->
</div>
<!-- FOOTER: Above -->
<ng-container *ngIf="fuseSettings.layout.footer === 'above'">
<fuse-footer class="above" [ngClass]="fuseSettings.colorClasses.footer"></fuse-footer>
</ng-container>
<!-- FOOTER: Above -->
</div>
<!-- QUICK PANEL -->
<mat-sidenav fuseMatSidenavHelper="quick-panel" position="end">
<fuse-quick-panel></fuse-quick-panel>
</mat-sidenav>
<!-- / QUICK PANEL -->
</mat-sidenav-container>
<fuse-theme-options [navigation]="navigation"></fuse-theme-options>

View File

@ -1,14 +0,0 @@
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector : 'fuse-vertical-nav-basic-layout',
templateUrl : './basic.component.html',
styleUrls : ['./basic.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FuseVerticalNavBasicLayoutComponent
{
constructor()
{
}
}

View File

@ -1,8 +1,9 @@
import { Component, HostBinding, HostListener, Input, OnDestroy } from '@angular/core'; import { Component, HostBinding, HostListener, Input, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '../../../../animations/index'; import { fuseAnimations } from '@fuse/animations';
import { FuseConfigService } from '../../../../services/config.service'; import { FuseConfigService } from '@fuse/services/config.service';
@Component({ @Component({
selector : 'fuse-nav-horizontal-collapse', selector : 'fuse-nav-horizontal-collapse',
@ -10,42 +11,76 @@ import { FuseConfigService } from '../../../../services/config.service';
styleUrls : ['./nav-horizontal-collapse.component.scss'], styleUrls : ['./nav-horizontal-collapse.component.scss'],
animations : fuseAnimations animations : fuseAnimations
}) })
export class FuseNavHorizontalCollapseComponent implements OnDestroy export class FuseNavHorizontalCollapseComponent implements OnInit, OnDestroy
{ {
onConfigChanged: Subscription; fuseConfig: any;
fuseSettings: any;
isOpen = false; isOpen = false;
@HostBinding('class') classes = 'nav-item nav-collapse'; @HostBinding('class')
@Input() item: any; classes = 'nav-item nav-collapse';
@Input()
item: any;
// Private
private _unsubscribeAll: Subject<any>;
constructor(
private _fuseConfigService: FuseConfigService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(
(config) => {
this.fuseConfig = config;
}
);
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Open
*/
@HostListener('mouseenter') @HostListener('mouseenter')
open() open(): void
{ {
this.isOpen = true; this.isOpen = true;
} }
/**
* Close
*/
@HostListener('mouseleave') @HostListener('mouseleave')
close() close(): void
{ {
this.isOpen = false; this.isOpen = false;
} }
constructor(
private fuseConfig: FuseConfigService
)
{
this.onConfigChanged =
this.fuseConfig.onConfigChanged
.subscribe(
(newSettings) => {
this.fuseSettings = newSettings;
}
);
}
ngOnDestroy()
{
this.onConfigChanged.unsubscribe();
}
} }

View File

@ -7,6 +7,17 @@ import { Component, HostBinding, Input } from '@angular/core';
}) })
export class FuseNavHorizontalItemComponent export class FuseNavHorizontalItemComponent
{ {
@HostBinding('class') classes = 'nav-item'; @HostBinding('class')
@Input() item: any; classes = 'nav-item';
@Input()
item: any;
/**
* Constructor
*/
constructor()
{
}
} }

View File

@ -8,9 +8,15 @@ import { Component, Input, ViewEncapsulation } from '@angular/core';
}) })
export class FuseNavigationComponent export class FuseNavigationComponent
{ {
@Input() layout = 'vertical'; @Input()
@Input() navigation: any; layout = 'vertical';
@Input()
navigation: any;
/**
* Constructor
*/
constructor() constructor()
{ {

View File

@ -9,16 +9,24 @@ export class FuseNavigationService
onItemCollapsed: Subject<any> = new Subject; onItemCollapsed: Subject<any> = new Subject;
onItemCollapseToggled: Subject<any> = new Subject; onItemCollapseToggled: Subject<any> = new Subject;
/**
* Constructor
*/
constructor() constructor()
{ {
} }
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/** /**
* Get flattened navigation array * Get flattened navigation array
*
* @param navigation * @param navigation
* @returns {any[]} * @returns {any[]}
*/ */
getFlatNavigation(navigation) getFlatNavigation(navigation): any
{ {
for ( const navItem of navigation ) for ( const navItem of navigation )
{ {

View File

@ -1,7 +1,10 @@
import { Component, HostBinding, Input, OnInit } from '@angular/core'; import { Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
import { FuseNavigationService } from '../../navigation.service';
import { NavigationEnd, Router } from '@angular/router'; import { NavigationEnd, Router } from '@angular/router';
import { fuseAnimations } from '../../../../animations/index'; import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
import { FuseNavigationService } from '../../navigation.service';
import { fuseAnimations } from '@fuse/animations';
@Component({ @Component({
selector : 'fuse-nav-vertical-collapse', selector : 'fuse-nav-vertical-collapse',
@ -9,38 +12,67 @@ import { fuseAnimations } from '../../../../animations/index';
styleUrls : ['./nav-vertical-collapse.component.scss'], styleUrls : ['./nav-vertical-collapse.component.scss'],
animations : fuseAnimations animations : fuseAnimations
}) })
export class FuseNavVerticalCollapseComponent implements OnInit export class FuseNavVerticalCollapseComponent implements OnInit, OnDestroy
{ {
@Input() item: any; @Input()
@HostBinding('class') classes = 'nav-collapse nav-item'; item: any;
@HostBinding('class.open') public isOpen = false;
@HostBinding('class')
classes = 'nav-collapse nav-item';
@HostBinding('class.open')
public isOpen = false;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FuseNavigationService} _fuseNavigationService
* @param {Router} _router
*/
constructor( constructor(
private navigationService: FuseNavigationService, private _fuseNavigationService: FuseNavigationService,
private router: Router private _router: Router
) )
{ {
// Listen for route changes // Set the private defaults
router.events.subscribe( this._unsubscribeAll = new Subject();
(event) => { }
if ( event instanceof NavigationEnd )
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Listen for router events
this._router.events
.pipe(
filter(event => event instanceof NavigationEnd),
takeUntil(this._unsubscribeAll)
)
.subscribe((event: NavigationEnd) => {
// Check if the url can be found in
// one of the children of this item
if ( this.isUrlInChildren(this.item, event.urlAfterRedirects) )
{ {
// Check if the url can be found in this.expand();
// one of the children of this item
if ( this.isUrlInChildren(this.item, event.urlAfterRedirects) )
{
this.expand();
}
else
{
this.collapse();
}
} }
} else
); {
this.collapse();
}
});
// Listen for collapsing of any navigation item // Listen for collapsing of any navigation item
this.navigationService.onItemCollapsed this._fuseNavigationService.onItemCollapsed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe( .subscribe(
(clickedItem) => { (clickedItem) => {
if ( clickedItem && clickedItem.children ) if ( clickedItem && clickedItem.children )
@ -54,7 +86,7 @@ export class FuseNavVerticalCollapseComponent implements OnInit
// Check if the url can be found in // Check if the url can be found in
// one of the children of this item // one of the children of this item
if ( this.isUrlInChildren(this.item, this.router.url) ) if ( this.isUrlInChildren(this.item, this._router.url) )
{ {
return; return;
} }
@ -67,13 +99,10 @@ export class FuseNavVerticalCollapseComponent implements OnInit
} }
} }
); );
}
ngOnInit()
{
// Check if the url can be found in // Check if the url can be found in
// one of the children of this item // one of the children of this item
if ( this.isUrlInChildren(this.item, this.router.url) ) if ( this.isUrlInChildren(this.item, this._router.url) )
{ {
this.expand(); this.expand();
} }
@ -83,26 +112,40 @@ export class FuseNavVerticalCollapseComponent implements OnInit
} }
} }
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/** /**
* Toggle collapse * Toggle collapse
* *
* @param ev * @param ev
*/ */
toggleOpen(ev) toggleOpen(ev): void
{ {
ev.preventDefault(); ev.preventDefault();
this.isOpen = !this.isOpen; this.isOpen = !this.isOpen;
// Navigation collapse toggled... // Navigation collapse toggled...
this.navigationService.onItemCollapsed.next(this.item); this._fuseNavigationService.onItemCollapsed.next(this.item);
this.navigationService.onItemCollapseToggled.next(); this._fuseNavigationService.onItemCollapseToggled.next();
} }
/** /**
* Expand the collapsable navigation * Expand the collapsable navigation
*/ */
expand() expand(): void
{ {
if ( this.isOpen ) if ( this.isOpen )
{ {
@ -110,13 +153,13 @@ export class FuseNavVerticalCollapseComponent implements OnInit
} }
this.isOpen = true; this.isOpen = true;
this.navigationService.onItemCollapseToggled.next(); this._fuseNavigationService.onItemCollapseToggled.next();
} }
/** /**
* Collapse the collapsable navigation * Collapse the collapsable navigation
*/ */
collapse() collapse(): void
{ {
if ( !this.isOpen ) if ( !this.isOpen )
{ {
@ -124,7 +167,7 @@ export class FuseNavVerticalCollapseComponent implements OnInit
} }
this.isOpen = false; this.isOpen = false;
this.navigationService.onItemCollapseToggled.next(); this._fuseNavigationService.onItemCollapseToggled.next();
} }
/** /**
@ -133,9 +176,9 @@ export class FuseNavVerticalCollapseComponent implements OnInit
* *
* @param parent * @param parent
* @param item * @param item
* @return {any} * @returns {boolean}
*/ */
isChildrenOf(parent, item) isChildrenOf(parent, item): boolean
{ {
if ( !parent.children ) if ( !parent.children )
{ {
@ -162,9 +205,9 @@ export class FuseNavVerticalCollapseComponent implements OnInit
* *
* @param parent * @param parent
* @param url * @param url
* @returns {any} * @returns {boolean}
*/ */
isUrlInChildren(parent, url) isUrlInChildren(parent, url): boolean
{ {
if ( !parent.children ) if ( !parent.children )
{ {

View File

@ -7,9 +7,15 @@ import { Component, HostBinding, Input } from '@angular/core';
}) })
export class FuseNavVerticalGroupComponent export class FuseNavVerticalGroupComponent
{ {
@HostBinding('class') classes = 'nav-group nav-item'; @HostBinding('class')
@Input() item: any; classes = 'nav-group nav-item';
@Input()
item: any;
/**
* Constructor
*/
constructor() constructor()
{ {
} }

View File

@ -7,9 +7,15 @@ import { Component, HostBinding, Input } from '@angular/core';
}) })
export class FuseNavVerticalItemComponent export class FuseNavVerticalItemComponent
{ {
@HostBinding('class') classes = 'nav-item'; @HostBinding('class')
@Input() item: any; classes = 'nav-item';
@Input()
item: any;
/**
* Constructor
*/
constructor() constructor()
{ {
} }

View File

@ -1,5 +1,6 @@
import { Component, EventEmitter, Output } from '@angular/core'; import { Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core';
import { Subscription } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseConfigService } from '@fuse/services/config.service'; import { FuseConfigService } from '@fuse/services/config.service';
@ -8,38 +9,89 @@ import { FuseConfigService } from '@fuse/services/config.service';
templateUrl: './search-bar.component.html', templateUrl: './search-bar.component.html',
styleUrls : ['./search-bar.component.scss'] styleUrls : ['./search-bar.component.scss']
}) })
export class FuseSearchBarComponent export class FuseSearchBarComponent implements OnInit, OnDestroy
{ {
collapsed: boolean; collapsed: boolean;
fuseConfig: any;
toolbarColor: string; toolbarColor: string;
@Output() onInput: EventEmitter<any> = new EventEmitter();
onConfigChanged: Subscription;
@Output()
onInput: EventEmitter<any> = new EventEmitter();
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FuseConfigService} _fuseConfigService
*/
constructor( constructor(
private fuseConfig: FuseConfigService private _fuseConfigService: FuseConfigService
) )
{ {
// Set the defaults
this.collapsed = true; this.collapsed = true;
this.onConfigChanged =
this.fuseConfig.onConfigChanged // Set the private defaults
.subscribe( this._unsubscribeAll = new Subject();
(newSettings) => {
this.toolbarColor = newSettings.colorClasses.toolbar;
}
);
} }
collapse() // -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(
(config) => {
this.toolbarColor = config.colorClasses.toolbar;
}
);
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Collapse
*/
collapse(): void
{ {
this.collapsed = true; this.collapsed = true;
} }
expand() /**
* Expand
*/
expand(): void
{ {
this.collapsed = false; this.collapsed = false;
} }
search(event) /**
* Search
*
* @param event
*/
search(event): void
{ {
const value = event.target.value; const value = event.target.value;

View File

@ -1,7 +1,7 @@
import { Component, ElementRef, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core'; import { Component, ElementRef, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';
import { ObservableMedia } from '@angular/flex-layout'; import { ObservableMedia } from '@angular/flex-layout';
import { Subject, Subscription } from 'rxjs';
import { Subscription } from 'rxjs'; import { takeUntil } from 'rxjs/operators';
import { CookieService } from 'ngx-cookie-service'; import { CookieService } from 'ngx-cookie-service';
import { FuseMatchMediaService } from '@fuse/services/match-media.service'; import { FuseMatchMediaService } from '@fuse/services/match-media.service';
@ -21,42 +21,67 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
searching = false; searching = false;
mobileShortcutsPanelActive = false; mobileShortcutsPanelActive = false;
toolbarColor: string; toolbarColor: string;
matchMediaSubscription: Subscription;
onConfigChanged: Subscription;
@Input() navigation: any; @Input()
navigation: any;
@ViewChild('searchInput') searchInputField; @ViewChild('searchInput')
@ViewChild('shortcuts') shortcutsEl: ElementRef; searchInputField;
@ViewChild('shortcuts')
shortcutsEl: ElementRef;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {Renderer2} _renderer
* @param {CookieService} _cookieService
* @param {FuseMatchMediaService} _fuseMatchMediaService
* @param {FuseNavigationService} _fuseNavigationService
* @param {FuseConfigService} _fuseConfigService
* @param {ObservableMedia} _observableMedia
*/
constructor( constructor(
private renderer: Renderer2, private _renderer: Renderer2,
private observableMedia: ObservableMedia, private _cookieService: CookieService,
private fuseMatchMedia: FuseMatchMediaService, private _fuseMatchMediaService: FuseMatchMediaService,
private fuseNavigationService: FuseNavigationService, private _fuseNavigationService: FuseNavigationService,
private fuseConfig: FuseConfigService, private _fuseConfigService: FuseConfigService,
private cookieService: CookieService private _observableMedia: ObservableMedia
) )
{ {
this.onConfigChanged = // Set the private defaults
this.fuseConfig.onConfigChanged this._unsubscribeAll = new Subject();
.subscribe(
(newSettings) => {
this.toolbarColor = newSettings.colorClasses.toolbar;
}
);
} }
ngOnInit() // -----------------------------------------------------------------------------------------------------
{ // @ Lifecycle hooks
// Get the navigation items and flatten them // -----------------------------------------------------------------------------------------------------
this.filteredNavigationItems = this.navigationItems = this.fuseNavigationService.getFlatNavigation(this.navigation);
const cookieExists = this.cookieService.check('FUSE2.shortcuts'); /**
* On init
*/
ngOnInit(): void
{
// Subscribe to config changes
this._fuseConfigService.config
.subscribe(
(config) => {
this.toolbarColor = config.colorClasses.toolbar;
}
);
// Get the navigation items and flatten them
this.filteredNavigationItems = this.navigationItems = this._fuseNavigationService.getFlatNavigation(this.navigation);
const cookieExists = this._cookieService.check('FUSE2.shortcuts');
if ( cookieExists ) if ( cookieExists )
{ {
this.shortcutItems = JSON.parse(this.cookieService.get('FUSE2.shortcuts')); this.shortcutItems = JSON.parse(this._cookieService.get('FUSE2.shortcuts'));
} }
else else
{ {
@ -89,21 +114,36 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
]; ];
} }
this.matchMediaSubscription = this._fuseMatchMediaService.onMediaChange
this.fuseMatchMedia.onMediaChange.subscribe(() => { .pipe(takeUntil(this._unsubscribeAll))
if ( this.observableMedia.isActive('gt-sm') ) .subscribe(() => {
if ( this._observableMedia.isActive('gt-sm') )
{ {
this.hideMobileShortcutsPanel(); this.hideMobileShortcutsPanel();
} }
}); });
} }
ngOnDestroy() /**
* On destroy
*/
ngOnDestroy(): void
{ {
this.matchMediaSubscription.unsubscribe(); // Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
} }
search(event) // -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Search
*
* @param event
*/
search(event): void
{ {
const value = event.target.value.toLowerCase(); const value = event.target.value.toLowerCase();
@ -122,7 +162,13 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
}); });
} }
toggleShortcut(event, itemToToggle) /**
* Toggle shortcut
*
* @param event
* @param itemToToggle
*/
toggleShortcut(event, itemToToggle): void
{ {
event.stopPropagation(); event.stopPropagation();
@ -133,7 +179,7 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
this.shortcutItems.splice(i, 1); this.shortcutItems.splice(i, 1);
// Save to the cookies // Save to the cookies
this.cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems)); this._cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems));
return; return;
} }
@ -142,32 +188,47 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
this.shortcutItems.push(itemToToggle); this.shortcutItems.push(itemToToggle);
// Save to the cookies // Save to the cookies
this.cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems)); this._cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems));
} }
isInShortcuts(navigationItem) /**
* Is in shortcuts?
*
* @param navigationItem
* @returns {any}
*/
isInShortcuts(navigationItem): any
{ {
return this.shortcutItems.find(item => { return this.shortcutItems.find(item => {
return item.url === navigationItem.url; return item.url === navigationItem.url;
}); });
} }
onMenuOpen() /**
* On menu open
*/
onMenuOpen(): void
{ {
setTimeout(() => { setTimeout(() => {
this.searchInputField.nativeElement.focus(); this.searchInputField.nativeElement.focus();
}); });
} }
showMobileShortcutsPanel() /**
* Show mobile shortcuts
*/
showMobileShortcutsPanel(): void
{ {
this.mobileShortcutsPanelActive = true; this.mobileShortcutsPanelActive = true;
this.renderer.addClass(this.shortcutsEl.nativeElement, 'show-mobile-panel'); this._renderer.addClass(this.shortcutsEl.nativeElement, 'show-mobile-panel');
} }
hideMobileShortcutsPanel() /**
* Hide mobile shortcuts
*/
hideMobileShortcutsPanel(): void
{ {
this.mobileShortcutsPanelActive = false; this.mobileShortcutsPanelActive = false;
this.renderer.removeClass(this.shortcutsEl.nativeElement, 'show-mobile-panel'); this._renderer.removeClass(this.shortcutsEl.nativeElement, 'show-mobile-panel');
} }
} }

View File

@ -1,11 +1,12 @@
import { Component, ElementRef, HostBinding, HostListener, Input, OnDestroy, OnInit, Renderer2, ViewEncapsulation } from '@angular/core'; import { Component, ElementRef, HostBinding, HostListener, Input, OnDestroy, OnInit, Renderer2, ViewEncapsulation } from '@angular/core';
import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations'; import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
import { ObservableMedia } from '@angular/flex-layout'; import { ObservableMedia } from '@angular/flex-layout';
import { Subscription } from 'rxjs'; import { Subject, Subscription } from 'rxjs';
import { FuseSidebarService } from './sidebar.service'; import { FuseSidebarService } from './sidebar.service';
import { FuseMatchMediaService } from '@fuse/services/match-media.service'; import { FuseMatchMediaService } from '@fuse/services/match-media.service';
import { FuseConfigService } from '@fuse/services/config.service'; import { FuseConfigService } from '@fuse/services/config.service';
import { takeUntil } from 'rxjs/internal/operators';
@Component({ @Component({
selector : 'fuse-sidebar', selector : 'fuse-sidebar',
@ -35,6 +36,52 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
@HostBinding('class.locked-open') @HostBinding('class.locked-open')
isLockedOpen: boolean; isLockedOpen: boolean;
// Folded unfolded
@HostBinding('class.unfolded')
unfolded: boolean;
// Private
private _folded: boolean;
private _fuseConfig: any;
private _wasActive: boolean;
private _backdrop: HTMLElement | null = null;
private _player: AnimationPlayer;
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {AnimationBuilder} _animationBuilder
* @param {ElementRef} _elementRef
* @param {FuseConfigService} _fuseConfigService
* @param {FuseMatchMediaService} _fuseMatchMediaService
* @param {FuseSidebarService} _fuseSidebarService
* @param {ObservableMedia} _observableMedia
* @param {Renderer2} _renderer
*/
constructor(
private _animationBuilder: AnimationBuilder,
private _elementRef: ElementRef,
private _fuseConfigService: FuseConfigService,
private _fuseMatchMediaService: FuseMatchMediaService,
private _fuseSidebarService: FuseSidebarService,
private _observableMedia: ObservableMedia,
private _renderer: Renderer2
)
{
// Set the defaults
this.opened = false;
this.folded = false;
this.align = 'left';
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
// Folded // Folded
@HostBinding('class.folded') @HostBinding('class.folded')
@Input() @Input()
@ -59,12 +106,12 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
// Get the sibling and set the style rule // Get the sibling and set the style rule
if ( this.align === 'left' ) if ( this.align === 'left' )
{ {
sibling = this.elementRef.nativeElement.nextElementSibling; sibling = this._elementRef.nativeElement.nextElementSibling;
styleRule = 'marginLeft'; styleRule = 'marginLeft';
} }
else else
{ {
sibling = this.elementRef.nativeElement.previousElementSibling; sibling = this._elementRef.nativeElement.previousElementSibling;
styleRule = 'marginRight'; styleRule = 'marginRight';
} }
@ -78,13 +125,13 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
if ( value ) if ( value )
{ {
// Set the style // Set the style
this.renderer.setStyle(sibling, styleRule, styleValue); this._renderer.setStyle(sibling, styleRule, styleValue);
} }
// If unfolded... // If unfolded...
else else
{ {
// Remove the style // Remove the style
this.renderer.removeStyle(sibling, styleRule); this._renderer.removeStyle(sibling, styleRule);
} }
} }
@ -93,51 +140,24 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
return this._folded; return this._folded;
} }
// Folded unfolded // -----------------------------------------------------------------------------------------------------
@HostBinding('class.unfolded') // @ Lifecycle hooks
unfolded: boolean; // -----------------------------------------------------------------------------------------------------
// Private
private _folded: boolean;
private _wasActive: boolean;
private _backdrop: HTMLElement | null = null;
private _player: AnimationPlayer;
private _onMediaChangeSubscription: Subscription;
/**
* Constructor
*
* @param {Renderer2} renderer
* @param {ElementRef} elementRef
* @param {AnimationBuilder} animationBuilder
* @param {ObservableMedia} observableMedia
* @param {FuseConfigService} fuseConfigService
* @param {FuseSidebarService} fuseSidebarService
* @param {FuseMatchMediaService} fuseMatchMediaService
*/
constructor(
private renderer: Renderer2,
private elementRef: ElementRef,
private animationBuilder: AnimationBuilder,
private observableMedia: ObservableMedia,
private fuseConfigService: FuseConfigService,
private fuseSidebarService: FuseSidebarService,
private fuseMatchMediaService: FuseMatchMediaService
)
{
// Set the defaults
this.opened = false;
this.folded = false;
this.align = 'left';
}
/** /**
* On init * On init
*/ */
ngOnInit(): void ngOnInit(): void
{ {
// Subscribe to config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._fuseConfig = config;
});
// Register the sidebar // Register the sidebar
this.fuseSidebarService.register(this.name, this); this._fuseSidebarService.register(this.name, this);
// Setup alignment // Setup alignment
this._setupAlignment(); this._setupAlignment();
@ -158,12 +178,17 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
} }
// Unregister the sidebar // Unregister the sidebar
this.fuseSidebarService.unregister(this.name); this._fuseSidebarService.unregister(this.name);
// Unsubscribe from the media watcher subscription // Unsubscribe from all subscriptions
this._onMediaChangeSubscription.unsubscribe(); this._unsubscribeAll.next();
this._unsubscribeAll.complete();
} }
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/** /**
* Set the sidebar alignment * Set the sidebar alignment
* *
@ -175,11 +200,11 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
// element depending on the align attribute // element depending on the align attribute
if ( this.align === 'right' ) if ( this.align === 'right' )
{ {
this.renderer.addClass(this.elementRef.nativeElement, 'right-aligned'); this._renderer.addClass(this._elementRef.nativeElement, 'right-aligned');
} }
else else
{ {
this.renderer.addClass(this.elementRef.nativeElement, 'left-aligned'); this._renderer.addClass(this._elementRef.nativeElement, 'left-aligned');
} }
} }
@ -200,12 +225,12 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
this._wasActive = false; this._wasActive = false;
// Act on every media change // Act on every media change
this._onMediaChangeSubscription = this._fuseMatchMediaService.onMediaChange
.pipe(takeUntil(this._unsubscribeAll))
this.fuseMatchMediaService.onMediaChange.subscribe(() => { .subscribe(() => {
// Get the active status // Get the active status
const isActive = this.observableMedia.isActive(this.lockedOpen); const isActive = this._observableMedia.isActive(this.lockedOpen);
// If the both status are the same, don't act // If the both status are the same, don't act
if ( this._wasActive === isActive ) if ( this._wasActive === isActive )
@ -224,7 +249,7 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
// Read the folded setting from the config // Read the folded setting from the config
// and fold the sidebar if it's true // and fold the sidebar if it's true
if ( this.fuseConfigService.config.layout.navigationFolded ) if ( this._fuseConfig.layout.navigation.folded )
{ {
this.fold(); this.fold();
} }
@ -250,6 +275,10 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
}); });
} }
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/** /**
* Open the sidebar * Open the sidebar
*/ */
@ -382,17 +411,17 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
showBackdrop(): void showBackdrop(): void
{ {
// Create the backdrop element // Create the backdrop element
this._backdrop = this.renderer.createElement('div'); this._backdrop = this._renderer.createElement('div');
// Add a class to the backdrop element // Add a class to the backdrop element
this._backdrop.classList.add('fuse-sidebar-overlay'); this._backdrop.classList.add('fuse-sidebar-overlay');
// Append the backdrop to the parent of the sidebar // Append the backdrop to the parent of the sidebar
this.renderer.appendChild(this.elementRef.nativeElement.parentElement, this._backdrop); this._renderer.appendChild(this._elementRef.nativeElement.parentElement, this._backdrop);
// Create the enter animation and attach it to the player // Create the enter animation and attach it to the player
this._player = this._player =
this.animationBuilder this._animationBuilder
.build([ .build([
animate('300ms ease', style({opacity: 1})) animate('300ms ease', style({opacity: 1}))
]).create(this._backdrop); ]).create(this._backdrop);
@ -419,7 +448,7 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
// Create the leave animation and attach it to the player // Create the leave animation and attach it to the player
this._player = this._player =
this.animationBuilder this._animationBuilder
.build([ .build([
animate('300ms ease', style({opacity: 0})) animate('300ms ease', style({opacity: 0}))
]).create(this._backdrop); ]).create(this._backdrop);

View File

@ -13,7 +13,7 @@
<div class="theme-options-panel-inner" fxLayout="column" fxLayoutAlign="start start"> <div class="theme-options-panel-inner" fxLayout="column" fxLayoutAlign="start start">
<h3>Layout:</h3> <h3>Layout:</h3>
<mat-radio-group [(ngModel)]="config.layout.style" (ngModelChange)="onSettingsChange()" <mat-radio-group [(ngModel)]="fuseConfig.layout.style" (ngModelChange)="onConfigChange()"
fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start"> fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start">
<mat-radio-button class="mr-8 mb-8" value="vertical">Vertical</mat-radio-button> <mat-radio-button class="mr-8 mb-8" value="vertical">Vertical</mat-radio-button>
<mat-radio-button class="mr-8 mb-8" value="horizontal">Horizontal</mat-radio-button> <mat-radio-button class="mr-8 mb-8" value="horizontal">Horizontal</mat-radio-button>
@ -21,7 +21,7 @@
</mat-radio-group> </mat-radio-group>
<h3>Navigation:</h3> <h3>Navigation:</h3>
<mat-radio-group [(ngModel)]="config.layout.navigation" (ngModelChange)="onSettingsChange()" <mat-radio-group [(ngModel)]="fuseConfig.layout.navigation" (ngModelChange)="onConfigChange()"
fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start"> fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start">
<mat-radio-button class="mr-8 mb-8" value="top">Top</mat-radio-button> <mat-radio-button class="mr-8 mb-8" value="top">Top</mat-radio-button>
<mat-radio-button class="mr-8 mb-8" value="left">Left</mat-radio-button> <mat-radio-button class="mr-8 mb-8" value="left">Left</mat-radio-button>
@ -30,13 +30,13 @@
</mat-radio-group> </mat-radio-group>
<h3>Navigation Fold (for vertical navigation):</h3> <h3>Navigation Fold (for vertical navigation):</h3>
<mat-slide-toggle [(ngModel)]="config.layout.navigationFolded" <mat-slide-toggle [(ngModel)]="fuseConfig.layout.navigationFolded"
(change)="onSettingsChange()"> (change)="onConfigChange()">
Folded Folded
</mat-slide-toggle> </mat-slide-toggle>
<h3 class="mt-24">Toolbar:</h3> <h3 class="mt-24">Toolbar:</h3>
<mat-radio-group [(ngModel)]="config.layout.toolbar" (ngModelChange)="onSettingsChange()" <mat-radio-group [(ngModel)]="fuseConfig.layout.toolbar" (ngModelChange)="onConfigChange()"
fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start"> fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start">
<mat-radio-button class="mr-8 mb-8" value="below">Below</mat-radio-button> <mat-radio-button class="mr-8 mb-8" value="below">Below</mat-radio-button>
<mat-radio-button class="mr-8 mb-8" value="above">Above</mat-radio-button> <mat-radio-button class="mr-8 mb-8" value="above">Above</mat-radio-button>
@ -44,7 +44,7 @@
</mat-radio-group> </mat-radio-group>
<h3 class="mt-24">Footer:</h3> <h3 class="mt-24">Footer:</h3>
<mat-radio-group [(ngModel)]="config.layout.footer" (ngModelChange)="onSettingsChange()" <mat-radio-group [(ngModel)]="fuseConfig.layout.footer" (ngModelChange)="onConfigChange()"
fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start"> fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start">
<mat-radio-button class="mr-8 mb-8" value="below">Below</mat-radio-button> <mat-radio-button class="mr-8 mb-8" value="below">Below</mat-radio-button>
<mat-radio-button class="mr-8 mb-8" value="above">Above</mat-radio-button> <mat-radio-button class="mr-8 mb-8" value="above">Above</mat-radio-button>
@ -52,7 +52,7 @@
</mat-radio-group> </mat-radio-group>
<h3 class="mt-24">Layout Mode:</h3> <h3 class="mt-24">Layout Mode:</h3>
<mat-radio-group [(ngModel)]="config.layout.mode" (ngModelChange)="onSettingsChange()" <mat-radio-group [(ngModel)]="fuseConfig.layout.mode" (ngModelChange)="onConfigChange()"
fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start"> fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign="start start">
<mat-radio-button class="mr-8 mb-8" value="boxed">Boxed</mat-radio-button> <mat-radio-button class="mr-8 mb-8" value="boxed">Boxed</mat-radio-button>
<mat-radio-button class="mr-8 mb-8" value="fullwidth">Fullwidth</mat-radio-button> <mat-radio-button class="mr-8 mb-8" value="fullwidth">Fullwidth</mat-radio-button>
@ -65,20 +65,20 @@
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center"> <div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
<h4 class="mr-8">Toolbar Color</h4> <h4 class="mr-8">Toolbar Color</h4>
<fuse-material-color-picker [(selectedClass)]="config.colorClasses.toolbar" <fuse-material-color-picker [(selectedClass)]="fuseConfig.colorClasses.toolbar"
(onValueChange)="onSettingsChange()"></fuse-material-color-picker> (onValueChange)="onConfigChange()"></fuse-material-color-picker>
</div> </div>
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center"> <div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
<h4 class="mr-8">Navigation Bar Color</h4> <h4 class="mr-8">Navigation Bar Color</h4>
<fuse-material-color-picker [(selectedClass)]="config.colorClasses.navbar" <fuse-material-color-picker [(selectedClass)]="fuseConfig.colorClasses.navbar"
(onValueChange)="onSettingsChange()"></fuse-material-color-picker> (onValueChange)="onConfigChange()"></fuse-material-color-picker>
</div> </div>
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center"> <div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
<h4 class="mr-8">Footer Color</h4> <h4 class="mr-8">Footer Color</h4>
<fuse-material-color-picker [(selectedClass)]="config.colorClasses.footer" <fuse-material-color-picker [(selectedClass)]="fuseConfig.colorClasses.footer"
(onValueChange)="onSettingsChange()"></fuse-material-color-picker> (onValueChange)="onConfigChange()"></fuse-material-color-picker>
</div> </div>
</div> </div>
@ -87,7 +87,7 @@
<h3>Router Animation:</h3> <h3>Router Animation:</h3>
<mat-form-field class="w-100-p"> <mat-form-field class="w-100-p">
<mat-select class="p-0" [(ngModel)]="config.routerAnimation"> <mat-select class="p-0" [(ngModel)]="fuseConfig.routerAnimation">
<mat-option value="none"> <mat-option value="none">
None None
</mat-option> </mat-option>

View File

@ -1,6 +1,7 @@
import { Component, ElementRef, HostBinding, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core'; import { Component, ElementRef, HostBinding, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';
import { style, animate, AnimationBuilder, AnimationPlayer } from '@angular/animations'; import { style, animate, AnimationBuilder, AnimationPlayer } from '@angular/animations';
import { Subscription } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations'; import { fuseAnimations } from '@fuse/animations';
import { FuseConfigService } from '@fuse/services/config.service'; import { FuseConfigService } from '@fuse/services/config.service';
@ -14,39 +15,59 @@ import { FuseNavigationService } from '@fuse/components/navigation/navigation.se
}) })
export class FuseThemeOptionsComponent implements OnInit, OnDestroy export class FuseThemeOptionsComponent implements OnInit, OnDestroy
{ {
@Input() navigation; @Input()
@ViewChild('openButton') openButton; navigation;
@ViewChild('panel') panel;
@ViewChild('overlay') overlay: ElementRef;
public player: AnimationPlayer; @ViewChild('openButton')
config: any; openButton;
onConfigChanged: Subscription; @ViewChild('panel')
panel;
@ViewChild('overlay')
overlay: ElementRef;
player: AnimationPlayer;
fuseConfig: any;
@HostBinding('class.bar-closed') barClosed: boolean; @HostBinding('class.bar-closed') barClosed: boolean;
// Private
private _unsubscribeAll: Subject<any>;
constructor( constructor(
private animationBuilder: AnimationBuilder, private _animationBuilder: AnimationBuilder,
private fuseConfig: FuseConfigService, private _fuseConfigService: FuseConfigService,
private navigationService: FuseNavigationService, private _fuseNavigationService: FuseNavigationService,
private renderer: Renderer2 private _renderer: Renderer2
) )
{ {
// Set the defaults
this.barClosed = true; this.barClosed = true;
this.onConfigChanged = // Set the private defaults
this.fuseConfig.onConfigChanged this._unsubscribeAll = new Subject();
.subscribe(
(newConfig) => {
this.config = newConfig;
}
);
} }
ngOnInit() // -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{ {
this.renderer.listen(this.overlay.nativeElement, 'click', () => { // Subscribe to the config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this.fuseConfig = config;
}
);
// Listen for the overlay's click event
this._renderer.listen(this.overlay.nativeElement, 'click', () => {
this.closeBar(); this.closeBar();
}); });
@ -72,20 +93,52 @@ export class FuseThemeOptionsComponent implements OnInit, OnDestroy
}); });
} }
ngOnDestroy() /**
* On destroy
*/
ngOnDestroy(): void
{ {
this.onConfigChanged.unsubscribe(); // Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
} }
onSettingsChange() // -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* On config change
*/
onConfigChange(): void
{ {
this.fuseConfig.setConfig(this.config); this._fuseConfigService.config = this.fuseConfig;
} }
closeBar() /**
* Open the bar
*/
openBar(): void
{
this.barClosed = false;
this.player =
this._animationBuilder
.build([
style({transform: 'translate3d(100%,0,0)'}),
animate('400ms ease', style({transform: 'translate3d(0,0,0)'}))
]).create(this.panel.nativeElement);
this.player.play();
}
/**
* Close the bar
*/
closeBar(): void
{ {
this.player = this.player =
this.animationBuilder this._animationBuilder
.build([ .build([
style({transform: 'translate3d(0,0,0)'}), style({transform: 'translate3d(0,0,0)'}),
animate('400ms ease', style({transform: 'translate3d(100%,0,0)'})) animate('400ms ease', style({transform: 'translate3d(100%,0,0)'}))
@ -97,18 +150,4 @@ export class FuseThemeOptionsComponent implements OnInit, OnDestroy
this.barClosed = true; this.barClosed = true;
}); });
} }
openBar()
{
this.barClosed = false;
this.player =
this.animationBuilder
.build([
style({transform: 'translate3d(100%,0,0)'}),
animate('400ms ease', style({transform: 'translate3d(0,0,0)'}))
]).create(this.panel.nativeElement);
this.player.play();
}
} }

View File

@ -5,7 +5,14 @@ import { Directive, ElementRef } from '@angular/core';
}) })
export class FuseWidgetToggleDirective export class FuseWidgetToggleDirective
{ {
constructor(public el: ElementRef) /**
* Constructor
*
* @param {ElementRef} elementRef
*/
constructor(
public elementRef: ElementRef
)
{ {
} }
} }

View File

@ -10,19 +10,38 @@ import { FuseWidgetToggleDirective } from './widget-toggle.directive';
export class FuseWidgetComponent implements AfterContentInit export class FuseWidgetComponent implements AfterContentInit
{ {
@HostBinding('class.flipped') flipped = false; @HostBinding('class.flipped')
@ContentChildren(FuseWidgetToggleDirective, {descendants: true}) toggleButtons: QueryList<FuseWidgetToggleDirective>; flipped = false;
constructor(private el: ElementRef, private renderer: Renderer2) @ContentChildren(FuseWidgetToggleDirective, {descendants: true})
toggleButtons: QueryList<FuseWidgetToggleDirective>;
/**
* Constructor
*
* @param {ElementRef} _elementRef
* @param {Renderer2} _renderer
*/
constructor(
private _elementRef: ElementRef,
private _renderer: Renderer2
)
{ {
} }
ngAfterContentInit() // -----------------------------------------------------------------------------------------------------
{ // @ Lifecycle hooks
setTimeout(() => { // -----------------------------------------------------------------------------------------------------
/**
* After content init
*/
ngAfterContentInit(): void
{
// Listen for the flip button click
setTimeout(() => {
this.toggleButtons.forEach(flipButton => { this.toggleButtons.forEach(flipButton => {
this.renderer.listen(flipButton.el.nativeElement, 'click', (event) => { this._renderer.listen(flipButton.elementRef.nativeElement, 'click', (event) => {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
this.toggle(); this.toggle();
@ -31,7 +50,14 @@ export class FuseWidgetComponent implements AfterContentInit
}); });
} }
toggle() // -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle the flipped status
*/
toggle(): void
{ {
this.flipped = !this.flipped; this.flipped = !this.flipped;
} }

View File

@ -7,26 +7,40 @@ export class FuseIfOnDomDirective implements AfterContentChecked
{ {
isCreated = false; isCreated = false;
/**
* Constructor
*
* @param {ElementRef} _elementRef
* @param {TemplateRef<any>} _templateRef
* @param {ViewContainerRef} _viewContainerRef
*/
constructor( constructor(
private templateRef: TemplateRef<any>, private _elementRef: ElementRef,
private viewContainer: ViewContainerRef, private _templateRef: TemplateRef<any>,
private element: ElementRef private _viewContainerRef: ViewContainerRef
) )
{ {
} }
ngAfterContentChecked() // -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* After content checked
*/
ngAfterContentChecked(): void
{ {
if ( document.body.contains(this.element.nativeElement) && !this.isCreated ) if ( document.body.contains(this._elementRef.nativeElement) && !this.isCreated )
{ {
setTimeout(() => { setTimeout(() => {
this.viewContainer.createEmbeddedView(this.templateRef); this._viewContainerRef.createEmbeddedView(this._templateRef);
}, 300); }, 300);
this.isCreated = true; this.isCreated = true;
} }
else if ( this.isCreated && !document.body.contains(this.element.nativeElement) ) else if ( this.isCreated && !document.body.contains(this._elementRef.nativeElement) )
{ {
this.viewContainer.clear(); this._viewContainerRef.clear();
this.isCreated = false; this.isCreated = false;
} }
} }

View File

@ -1,7 +1,8 @@
import { Directive, Input, OnInit, HostListener, OnDestroy, HostBinding } from '@angular/core'; import { Directive, Input, OnInit, HostListener, OnDestroy, HostBinding } from '@angular/core';
import { MatSidenav } from '@angular/material'; import { MatSidenav } from '@angular/material';
import { ObservableMedia } from '@angular/flex-layout'; import { ObservableMedia } from '@angular/flex-layout';
import { Subscription } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseMatchMediaService } from '@fuse/services/match-media.service'; import { FuseMatchMediaService } from '@fuse/services/match-media.service';
import { FuseMatSidenavHelperService } from '@fuse/directives/fuse-mat-sidenav/fuse-mat-sidenav.service'; import { FuseMatSidenavHelperService } from '@fuse/directives/fuse-mat-sidenav/fuse-mat-sidenav.service';
@ -11,56 +12,88 @@ import { FuseMatSidenavHelperService } from '@fuse/directives/fuse-mat-sidenav/f
}) })
export class FuseMatSidenavHelperDirective implements OnInit, OnDestroy export class FuseMatSidenavHelperDirective implements OnInit, OnDestroy
{ {
matchMediaSubscription: Subscription; @HostBinding('class.mat-is-locked-open')
@HostBinding('class.mat-is-locked-open') isLockedOpen = true; isLockedOpen = true;
@Input('fuseMatSidenavHelper') id: string;
@Input('mat-is-locked-open') matIsLockedOpenBreakpoint: string;
@Input('fuseMatSidenavHelper')
id: string;
@Input('mat-is-locked-open')
matIsLockedOpenBreakpoint: string;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FuseMatchMediaService} _fuseMatchMediaService
* @param {FuseMatSidenavHelperService} _fuseMatSidenavHelperService
* @param {MatSidenav} _matSidenav
* @param {ObservableMedia} _observableMedia
*/
constructor( constructor(
private fuseMatSidenavService: FuseMatSidenavHelperService, private _fuseMatchMediaService: FuseMatchMediaService,
private fuseMatchMedia: FuseMatchMediaService, private _fuseMatSidenavHelperService: FuseMatSidenavHelperService,
private observableMedia: ObservableMedia, private _matSidenav: MatSidenav,
private matSidenav: MatSidenav private _observableMedia: ObservableMedia
) )
{ {
// Set the private defaults
this._unsubscribeAll = new Subject();
} }
ngOnInit() // -----------------------------------------------------------------------------------------------------
{ // @ Lifecycle hooks
this.fuseMatSidenavService.setSidenav(this.id, this.matSidenav); // -----------------------------------------------------------------------------------------------------
if ( this.observableMedia.isActive(this.matIsLockedOpenBreakpoint) ) /**
* On init
*/
ngOnInit(): void
{
// Register the sidenav to the service
this._fuseMatSidenavHelperService.setSidenav(this.id, this._matSidenav);
if ( this._observableMedia.isActive(this.matIsLockedOpenBreakpoint) )
{ {
this.isLockedOpen = true; this.isLockedOpen = true;
this.matSidenav.mode = 'side'; this._matSidenav.mode = 'side';
this.matSidenav.toggle(true); this._matSidenav.toggle(true);
} }
else else
{ {
this.isLockedOpen = false; this.isLockedOpen = false;
this.matSidenav.mode = 'over'; this._matSidenav.mode = 'over';
this.matSidenav.toggle(false); this._matSidenav.toggle(false);
} }
this.matchMediaSubscription = this.fuseMatchMedia.onMediaChange.subscribe(() => { this._fuseMatchMediaService.onMediaChange
if ( this.observableMedia.isActive(this.matIsLockedOpenBreakpoint) ) .pipe(takeUntil(this._unsubscribeAll))
{ .subscribe(() => {
this.isLockedOpen = true; if ( this._observableMedia.isActive(this.matIsLockedOpenBreakpoint) )
this.matSidenav.mode = 'side'; {
this.matSidenav.toggle(true); this.isLockedOpen = true;
} this._matSidenav.mode = 'side';
else this._matSidenav.toggle(true);
{ }
this.isLockedOpen = false; else
this.matSidenav.mode = 'over'; {
this.matSidenav.toggle(false); this.isLockedOpen = false;
} this._matSidenav.mode = 'over';
}); this._matSidenav.toggle(false);
}
});
} }
ngOnDestroy() /**
* On destroy
*/
ngOnDestroy(): void
{ {
this.matchMediaSubscription.unsubscribe(); // Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
} }
} }
@ -69,15 +102,29 @@ export class FuseMatSidenavHelperDirective implements OnInit, OnDestroy
}) })
export class FuseMatSidenavTogglerDirective export class FuseMatSidenavTogglerDirective
{ {
@Input('fuseMatSidenavToggler') id; @Input('fuseMatSidenavToggler')
id;
constructor(private fuseMatSidenavService: FuseMatSidenavHelperService) /**
* Constructor
*
* @param {FuseMatSidenavHelperService} _fuseMatSidenavHelperService
*/
constructor(
private _fuseMatSidenavHelperService: FuseMatSidenavHelperService)
{ {
} }
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* On click
*/
@HostListener('click') @HostListener('click')
onClick() onClick()
{ {
this.fuseMatSidenavService.getSidenav(this.id).toggle(); this._fuseMatSidenavHelperService.getSidenav(this.id).toggle();
} }
} }

View File

@ -6,17 +6,36 @@ export class FuseMatSidenavHelperService
{ {
sidenavInstances: MatSidenav[]; sidenavInstances: MatSidenav[];
/**
* Constructor
*/
constructor() constructor()
{ {
this.sidenavInstances = []; this.sidenavInstances = [];
} }
setSidenav(id, instance) // -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Set sidenav
*
* @param id
* @param instance
*/
setSidenav(id, instance): void
{ {
this.sidenavInstances[id] = instance; this.sidenavInstances[id] = instance;
} }
getSidenav(id) /**
* Get sidenav
*
* @param id
* @returns {any}
*/
getSidenav(id): any
{ {
return this.sidenavInstances[id]; return this.sidenavInstances[id];
} }

View File

@ -1,6 +1,7 @@
import { AfterViewInit, Directive, ElementRef, HostListener, OnDestroy, OnInit } from '@angular/core'; import { AfterViewInit, Directive, ElementRef, HostListener, OnDestroy, OnInit } from '@angular/core';
import { Platform } from '@angular/cdk/platform'; import { Platform } from '@angular/cdk/platform';
import { Subscription } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import PerfectScrollbar from 'perfect-scrollbar'; import PerfectScrollbar from 'perfect-scrollbar';
@ -11,36 +12,58 @@ import { FuseConfigService } from '@fuse/services/config.service';
}) })
export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnDestroy export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnDestroy
{ {
onConfigChanged: Subscription;
isDisableCustomScrollbars = false; isDisableCustomScrollbars = false;
isMobile = false; isMobile = false;
isInitialized = true; isInitialized = true;
ps: PerfectScrollbar; ps: PerfectScrollbar;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ElementRef} elementRef
* @param {FuseConfigService} _fuseConfigService
* @param {Platform} _platform
*/
constructor( constructor(
public element: ElementRef, public elementRef: ElementRef,
private fuseConfig: FuseConfigService, private _fuseConfigService: FuseConfigService,
private platform: Platform private _platform: Platform
) )
{ {
// Set the private defaults
this._unsubscribeAll = new Subject();
} }
ngOnInit() // -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{ {
this.onConfigChanged = this._fuseConfigService.config
this.fuseConfig.onConfigChanged.subscribe( .pipe(takeUntil(this._unsubscribeAll))
.subscribe(
(settings) => { (settings) => {
this.isDisableCustomScrollbars = !settings.customScrollbars; this.isDisableCustomScrollbars = !settings.customScrollbars;
} }
); );
if ( this.platform.ANDROID || this.platform.IOS ) if ( this._platform.ANDROID || this._platform.IOS )
{ {
this.isMobile = true; this.isMobile = true;
} }
} }
ngAfterViewInit() /**
* After view init
*/
ngAfterViewInit(): void
{ {
if ( this.isMobile || this.isDisableCustomScrollbars ) if ( this.isMobile || this.isDisableCustomScrollbars )
{ {
@ -49,24 +72,38 @@ export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnD
} }
// Initialize the perfect-scrollbar // Initialize the perfect-scrollbar
this.ps = new PerfectScrollbar(this.element.nativeElement, { this.ps = new PerfectScrollbar(this.elementRef.nativeElement, {
wheelPropagation: true wheelPropagation: true
}); });
} }
ngOnDestroy() /**
* On destroy
*/
ngOnDestroy(): void
{ {
if ( !this.isInitialized || !this.ps ) if ( !this.isInitialized || !this.ps )
{ {
return; return;
} }
this.onConfigChanged.unsubscribe(); // Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
// Destroy the perfect-scrollbar // Destroy the perfect-scrollbar
this.ps.destroy(); this.ps.destroy();
} }
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Document click
*
* @param {Event} event
*/
@HostListener('document:click', ['$event']) @HostListener('document:click', ['$event'])
documentClick(event: Event): void documentClick(event: Event): void
{ {
@ -82,7 +119,10 @@ export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnD
this.ps.update(); this.ps.update();
} }
update() /**
* Update the scrollbar
*/
update(): void
{ {
if ( !this.isInitialized ) if ( !this.isInitialized )
{ {
@ -93,62 +133,108 @@ export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnD
this.ps.update(); this.ps.update();
} }
destroy() /**
* Destroy the scrollbar
*/
destroy(): void
{ {
this.ngOnDestroy(); this.ngOnDestroy();
} }
scrollToX(x: number, speed?: number) /**
* Scroll to X
*
* @param {number} x
* @param {number} speed
*/
scrollToX(x: number, speed?: number): void
{ {
this.animateScrolling('scrollLeft', x, speed); this.animateScrolling('scrollLeft', x, speed);
} }
scrollToY(y: number, speed?: number) /**
* Scroll to Y
*
* @param {number} y
* @param {number} speed
*/
scrollToY(y: number, speed?: number): void
{ {
this.animateScrolling('scrollTop', y, speed); this.animateScrolling('scrollTop', y, speed);
} }
scrollToTop(offset?: number, speed?: number) /**
* Scroll to top
*
* @param {number} offset
* @param {number} speed
*/
scrollToTop(offset?: number, speed?: number): void
{ {
this.animateScrolling('scrollTop', (offset || 0), speed); this.animateScrolling('scrollTop', (offset || 0), speed);
} }
scrollToLeft(offset?: number, speed?: number) /**
* Scroll to left
*
* @param {number} offset
* @param {number} speed
*/
scrollToLeft(offset?: number, speed?: number): void
{ {
this.animateScrolling('scrollLeft', (offset || 0), speed); this.animateScrolling('scrollLeft', (offset || 0), speed);
} }
scrollToRight(offset?: number, speed?: number) /**
* Scroll to right
*
* @param {number} offset
* @param {number} speed
*/
scrollToRight(offset?: number, speed?: number): void
{ {
const width = this.element.nativeElement.scrollWidth; const width = this.elementRef.nativeElement.scrollWidth;
this.animateScrolling('scrollLeft', width - (offset || 0), speed); this.animateScrolling('scrollLeft', width - (offset || 0), speed);
} }
scrollToBottom(offset?: number, speed?: number) /**
* Scroll to bottom
*
* @param {number} offset
* @param {number} speed
*/
scrollToBottom(offset?: number, speed?: number): void
{ {
const height = this.element.nativeElement.scrollHeight; const height = this.elementRef.nativeElement.scrollHeight;
this.animateScrolling('scrollTop', height - (offset || 0), speed); this.animateScrolling('scrollTop', height - (offset || 0), speed);
} }
animateScrolling(target: string, value: number, speed?: number) /**
* Animate scrolling
*
* @param {string} target
* @param {number} value
* @param {number} speed
*/
animateScrolling(target: string, value: number, speed?: number): void
{ {
if ( !speed ) if ( !speed )
{ {
this.element.nativeElement[target] = value; this.elementRef.nativeElement[target] = value;
// PS has weird event sending order, this is a workaround for that // PS has weird event sending order, this is a workaround for that
this.update(); this.update();
this.update(); this.update();
} }
else if ( value !== this.element.nativeElement[target] ) else if ( value !== this.elementRef.nativeElement[target] )
{ {
let newValue = 0; let newValue = 0;
let scrollCount = 0; let scrollCount = 0;
let oldTimestamp = performance.now(); let oldTimestamp = performance.now();
let oldValue = this.element.nativeElement[target]; let oldValue = this.elementRef.nativeElement[target];
const cosParameter = (oldValue - value) / 2; const cosParameter = (oldValue - value) / 2;
@ -158,11 +244,11 @@ export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnD
newValue = Math.round(value + cosParameter + cosParameter * Math.cos(scrollCount)); newValue = Math.round(value + cosParameter + cosParameter * Math.cos(scrollCount));
// Only continue animation if scroll position has not changed // Only continue animation if scroll position has not changed
if ( this.element.nativeElement[target] === oldValue ) if ( this.elementRef.nativeElement[target] === oldValue )
{ {
if ( scrollCount >= Math.PI ) if ( scrollCount >= Math.PI )
{ {
this.element.nativeElement[target] = value; this.elementRef.nativeElement[target] = value;
// PS has weird event sending order, this is a workaround for that // PS has weird event sending order, this is a workaround for that
this.update(); this.update();
@ -171,7 +257,7 @@ export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnD
} }
else else
{ {
this.element.nativeElement[target] = oldValue = newValue; this.elementRef.nativeElement[target] = oldValue = newValue;
oldTimestamp = newTimestamp; oldTimestamp = newTimestamp;

View File

@ -3,7 +3,14 @@ import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'camelCaseToDash'}) @Pipe({name: 'camelCaseToDash'})
export class CamelCaseToDashPipe implements PipeTransform export class CamelCaseToDashPipe implements PipeTransform
{ {
transform(value: string, args: any[] = []) /**
* Transform
*
* @param {string} value
* @param {any[]} args
* @returns {string}
*/
transform(value: string, args: any[] = []): string
{ {
return value ? String(value).replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`) : ''; return value ? String(value).replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`) : '';
} }

View File

@ -4,6 +4,14 @@ import { FuseUtils } from '@fuse/utils';
@Pipe({name: 'filter'}) @Pipe({name: 'filter'})
export class FilterPipe implements PipeTransform export class FilterPipe implements PipeTransform
{ {
/**
* Transform
*
* @param {any[]} mainArr
* @param {string} searchText
* @param {string} property
* @returns {any}
*/
transform(mainArr: any[], searchText: string, property: string): any transform(mainArr: any[], searchText: string, property: string): any
{ {
return FuseUtils.filterArrayByString(mainArr, searchText); return FuseUtils.filterArrayByString(mainArr, searchText);

View File

@ -6,6 +6,14 @@ import { Pipe, PipeTransform } from '@angular/core';
}) })
export class GetByIdPipe implements PipeTransform export class GetByIdPipe implements PipeTransform
{ {
/**
* Transform
*
* @param {any[]} value
* @param {number} id
* @param {string} property
* @returns {any}
*/
transform(value: any[], id: number, property: string): any transform(value: any[], id: number, property: string): any
{ {
const foundItem = value.find(item => { const foundItem = value.find(item => {

View File

@ -3,7 +3,14 @@ import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'htmlToPlaintext'}) @Pipe({name: 'htmlToPlaintext'})
export class HtmlToPlaintextPipe implements PipeTransform export class HtmlToPlaintextPipe implements PipeTransform
{ {
transform(value: string, args: any[] = []) /**
* Transform
*
* @param {string} value
* @param {any[]} args
* @returns {string}
*/
transform(value: string, args: any[] = []): string
{ {
return value ? String(value).replace(/<[^>]+>/gm, '') : ''; return value ? String(value).replace(/<[^>]+>/gm, '') : '';
} }

View File

@ -3,6 +3,13 @@ import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'keys'}) @Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform export class KeysPipe implements PipeTransform
{ {
/**
* Transform
*
* @param value
* @param {string[]} args
* @returns {any}
*/
transform(value: any, args: string[]): any transform(value: any, args: string[]): any
{ {
const keys: any[] = []; const keys: any[] = [];

View File

@ -1,93 +1,96 @@
import { Inject, Injectable, InjectionToken } from '@angular/core'; import { Inject, Injectable, InjectionToken } from '@angular/core';
import { NavigationEnd, NavigationStart, Router } from '@angular/router'; import { NavigationStart, Router } from '@angular/router';
import { Platform } from '@angular/cdk/platform'; import { Platform } from '@angular/cdk/platform';
import { BehaviorSubject } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
import { filter } from 'rxjs/operators';
import * as _ from 'lodash'; import * as _ from 'lodash';
// Create the injection token for the custom config // Create the injection token for the custom settings
export const FUSE_CONFIG = new InjectionToken('fuseCustomConfig'); export const FUSE_CONFIG = new InjectionToken('fuseCustomConfig');
@Injectable() @Injectable()
export class FuseConfigService export class FuseConfigService
{ {
config: any; // Private
defaultConfig: any; private _configSubject: BehaviorSubject<any>;
isSetConfigRan = false; private readonly _defaultConfig: any;
onConfigChanged: BehaviorSubject<any>;
/** /**
* Constructor * Constructor
* *
* @param router * @param {Platform} _platform
* @param platform * @param {Router} _router
* @param config * @param _config
*/ */
constructor( constructor(
private router: Router, private _platform: Platform,
public platform: Platform, private _router: Router,
@Inject(FUSE_CONFIG) config @Inject(FUSE_CONFIG) private _config
) )
{ {
// Set the default config from the user provided one (forRoot) // Set the default config from the user provided config (from forRoot)
this.defaultConfig = config; this._defaultConfig = _config;
/** // Initialize the service
* Disable Custom Scrollbars if Browser is Mobile this._init();
*/
if ( this.platform.ANDROID || this.platform.IOS )
{
this.defaultConfig.customScrollbars = false;
}
// Set the config from the default config
this.config = _.cloneDeep(this.defaultConfig);
// Reload the default settings for the
// layout on every navigation start
router.events.subscribe(
(event) => {
if ( event instanceof NavigationStart )
{
this.isSetConfigRan = false;
}
if ( event instanceof NavigationEnd )
{
if ( this.isSetConfigRan )
{
return;
}
this.setConfig({
layout: this.defaultConfig.layout
}
);
}
}
);
// Create the behavior subject
this.onConfigChanged = new BehaviorSubject(this.config);
} }
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/** /**
* Set the new config from given object * Set and get the config
*
* @param config
*/ */
setConfig(config): void set config(value)
{ {
// Set the SetConfigRan true // Get the value from the behavior subject
this.isSetConfigRan = true; let config = this._configSubject.getValue();
// Merge the config // Merge the new config
this.config = _.merge({}, this.config, config); config = _.merge({}, config, value);
// Trigger the event // Notify the observers
this.onConfigChanged.next(this.config); this._configSubject.next(config);
}
get config(): any | Observable<any>
{
return this._configSubject.asObservable();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Initialize
*
* @private
*/
private _init(): void
{
/**
* Disable custom scrollbars if browser is mobile
*/
if ( this._platform.ANDROID || this._platform.IOS )
{
this._defaultConfig.customScrollbars = false;
}
// Set the settings from the default settings
this._configSubject = new BehaviorSubject(_.cloneDeep(this._defaultConfig));
// Reload the default settings on every navigation start if
// the current settings are different from defaults
this._router.events
.pipe(filter(event => event instanceof NavigationStart))
.subscribe(() => {
if ( !_.isEqual(this._configSubject.getValue(), this._defaultConfig) )
{
this._configSubject.next(_.cloneDeep(this._defaultConfig));
}
});
} }
} }

View File

@ -11,16 +11,20 @@ import { Injectable } from '@angular/core';
@Injectable() @Injectable()
export class FuseCopierService export class FuseCopierService
{ {
private textarea: HTMLTextAreaElement; private textarea: HTMLTextAreaElement;
/** Copy the text value to the clipboard. */ /**
* Copy the text value to the clipboard
*
* @param {string} text
* @returns {boolean}
*/
copyText(text: string): boolean copyText(text: string): boolean
{ {
this.createTextareaAndSelect(text); this.createTextareaAndSelect(text);
const copySuccessful = document.execCommand('copy'); const copySuccessful = document.execCommand('copy');
this.removeFake(); this._removeFake();
return copySuccessful; return copySuccessful;
} }
@ -28,8 +32,10 @@ export class FuseCopierService
/** /**
* Creates a hidden textarea element, sets its value from `text` property, * Creates a hidden textarea element, sets its value from `text` property,
* and makes a selection on it. * and makes a selection on it.
*
* @param {string} text
*/ */
private createTextareaAndSelect(text: string) private createTextareaAndSelect(text: string): void
{ {
// Create a fake element to hold the contents to copy // Create a fake element to hold the contents to copy
this.textarea = document.createElement('textarea'); this.textarea = document.createElement('textarea');
@ -53,8 +59,12 @@ export class FuseCopierService
this.textarea.setSelectionRange(0, this.textarea.value.length); this.textarea.setSelectionRange(0, this.textarea.value.length);
} }
/** Remove the text area from the DOM. */ /**
private removeFake() * Remove the text area from the DOM
*
* @private
*/
private _removeFake(): void
{ {
if ( this.textarea ) if ( this.textarea )
{ {

View File

@ -8,16 +8,41 @@ export class FuseMatchMediaService
activeMediaQuery: string; activeMediaQuery: string;
onMediaChange: BehaviorSubject<string> = new BehaviorSubject<string>(''); onMediaChange: BehaviorSubject<string> = new BehaviorSubject<string>('');
constructor(private observableMedia: ObservableMedia) /**
* Constructor
*
* @param {ObservableMedia} _observableMedia
*/
constructor(
private _observableMedia: ObservableMedia
)
{ {
// Set the defaults
this.activeMediaQuery = ''; this.activeMediaQuery = '';
this.observableMedia.subscribe((change: MediaChange) => { // Initialize
if ( this.activeMediaQuery !== change.mqAlias ) this._init();
{
this.activeMediaQuery = change.mqAlias; }
this.onMediaChange.next(change.mqAlias);
} // -----------------------------------------------------------------------------------------------------
}); // @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Initialize
*
* @private
*/
private _init(): void
{
this._observableMedia
.subscribe((change: MediaChange) => {
if ( this.activeMediaQuery !== change.mqAlias )
{
this.activeMediaQuery = change.mqAlias;
this.onMediaChange.next(change.mqAlias);
}
});
} }
} }

View File

@ -6,23 +6,45 @@ import { NavigationEnd, Router } from '@angular/router';
@Injectable() @Injectable()
export class FuseSplashScreenService export class FuseSplashScreenService
{ {
splashScreenEl; splashScreenEl: any;
public player: AnimationPlayer; player: AnimationPlayer;
/**
* Constructor
*
* @param {AnimationBuilder} _animationBuilder
* @param _document
* @param {Router} _router
*/
constructor( constructor(
private animationBuilder: AnimationBuilder, private _animationBuilder: AnimationBuilder,
@Inject(DOCUMENT) private document: any, @Inject(DOCUMENT) private _document: any,
private router: Router private _router: Router
) )
{
// Initialize
this._init();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Initialize
*
* @private
*/
private _init(): void
{ {
// Get the splash screen element // Get the splash screen element
this.splashScreenEl = this.document.body.querySelector('#fuse-splash-screen'); this.splashScreenEl = this._document.body.querySelector('#fuse-splash-screen');
// If the splash screen element exists... // If the splash screen element exists...
if ( this.splashScreenEl ) if ( this.splashScreenEl )
{ {
// Hide it on the first NavigationEnd event // Hide it on the first NavigationEnd event
const hideOnLoad = this.router.events.subscribe((event) => { const hideOnLoad = this._router.events.subscribe((event) => {
if ( event instanceof NavigationEnd ) if ( event instanceof NavigationEnd )
{ {
setTimeout(() => { setTimeout(() => {
@ -38,10 +60,17 @@ export class FuseSplashScreenService
} }
} }
show() // -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Show the splash screen
*/
show(): void
{ {
this.player = this.player =
this.animationBuilder this._animationBuilder
.build([ .build([
style({ style({
opacity: '0', opacity: '0',
@ -55,10 +84,13 @@ export class FuseSplashScreenService
}, 0); }, 0);
} }
hide() /**
* Hide the splash screen
*/
hide(): void
{ {
this.player = this.player =
this.animationBuilder this._animationBuilder
.build([ .build([
style({opacity: '1'}), style({opacity: '1'}),
animate('400ms ease', style({ animate('400ms ease', style({

View File

@ -10,18 +10,34 @@ export interface Locale
@Injectable() @Injectable()
export class FuseTranslationLoaderService export class FuseTranslationLoaderService
{ {
constructor(private translate: TranslateService) /**
* Constructor
*
* @param {TranslateService} _translateService
*/
constructor(
private _translateService: TranslateService
)
{ {
} }
public loadTranslations(...args: Locale[]): void // -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Load translations
*
* @param {Locale} args
*/
loadTranslations(...args: Locale[]): void
{ {
const locales = [...args]; const locales = [...args];
locales.forEach((locale) => { locales.forEach((locale) => {
// use setTranslation() with the third argument set to true // use setTranslation() with the third argument set to true
// to append translations instead of replacing them // to append translations instead of replacing them
this.translate.setTranslation(locale.lang, locale.data, true); this._translateService.setTranslation(locale.lang, locale.data, true);
}); });
} }
} }

View File

@ -1,6 +1,13 @@
export class FuseUtils export class FuseUtils
{ {
public static filterArrayByString(mainArr, searchText) /**
* Filter array by string
*
* @param mainArr
* @param searchText
* @returns {any}
*/
public static filterArrayByString(mainArr, searchText): any
{ {
if ( searchText === '' ) if ( searchText === '' )
{ {
@ -14,7 +21,14 @@ export class FuseUtils
}); });
} }
public static searchInObj(itemObj, searchText) /**
* Search in object
*
* @param itemObj
* @param searchText
* @returns {boolean}
*/
public static searchInObj(itemObj, searchText): boolean
{ {
for ( const prop in itemObj ) for ( const prop in itemObj )
{ {
@ -51,7 +65,14 @@ export class FuseUtils
} }
} }
public static searchInArray(arr, searchText) /**
* Search in array
*
* @param arr
* @param searchText
* @returns {boolean}
*/
public static searchInArray(arr, searchText): boolean
{ {
for ( const value of arr ) for ( const value of arr )
{ {
@ -73,14 +94,26 @@ export class FuseUtils
} }
} }
public static searchInString(value, searchText) /**
* Search in string
*
* @param value
* @param searchText
* @returns {any}
*/
public static searchInString(value, searchText): any
{ {
return value.toLowerCase().includes(searchText); return value.toLowerCase().includes(searchText);
} }
public static generateGUID() /**
* Generate a unique GUID
*
* @returns {string}
*/
public static generateGUID(): string
{ {
function S4() function S4(): string
{ {
return Math.floor((1 + Math.random()) * 0x10000) return Math.floor((1 + Math.random()) * 0x10000)
.toString(16) .toString(16)
@ -90,7 +123,13 @@ export class FuseUtils
return S4() + S4(); return S4() + S4();
} }
public static toggleInArray(item, array) /**
* Toggle in array
*
* @param item
* @param array
*/
public static toggleInArray(item, array): void
{ {
if ( array.indexOf(item) === -1 ) if ( array.indexOf(item) === -1 )
{ {
@ -102,7 +141,13 @@ export class FuseUtils
} }
} }
public static handleize(text) /**
* Handleize
*
* @param text
* @returns {string}
*/
public static handleize(text): string
{ {
return text.toString().toLowerCase() return text.toString().toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with - .replace(/\s+/g, '-') // Replace spaces with -

View File

@ -1,8 +1 @@
<!--<fuse-main></fuse-main>--> <vertical-nav-basic-layout></vertical-nav-basic-layout>
<fuse-vertical-nav-basic-layout>
<fuse-navbar></fuse-navbar>
<fuse-toolbar></fuse-toolbar>
<fuse-content></fuse-content>
<fuse-footer></fuse-footer>
</fuse-vertical-nav-basic-layout>

View File

@ -5,8 +5,9 @@ import { FuseSplashScreenService } from '@fuse/services/splash-screen.service';
import { FuseTranslationLoaderService } from '@fuse/services/translation-loader.service'; import { FuseTranslationLoaderService } from '@fuse/services/translation-loader.service';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service'; import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { locale as navigationEnglish } from './navigation/i18n/en'; import { navigation } from 'app/navigation/navigation';
import { locale as navigationTurkish } from './navigation/i18n/tr'; import { locale as navigationEnglish } from 'app/navigation/i18n/en';
import { locale as navigationTurkish } from 'app/navigation/i18n/tr';
@Component({ @Component({
selector : 'fuse-root', selector : 'fuse-root',
@ -15,23 +16,36 @@ import { locale as navigationTurkish } from './navigation/i18n/tr';
}) })
export class AppComponent export class AppComponent
{ {
navigation: any;
/**
* Constructor
*
* @param {FuseNavigationService} _fuseNavigationService
* @param {FuseSplashScreenService} _fuseSplashScreenService
* @param {FuseTranslationLoaderService} _fuseTranslationLoaderService
* @param {TranslateService} _translateService
*/
constructor( constructor(
private translate: TranslateService, private _fuseNavigationService: FuseNavigationService,
private fuseNavigationService: FuseNavigationService, private _fuseSplashScreenService: FuseSplashScreenService,
private fuseSplashScreen: FuseSplashScreenService, private _fuseTranslationLoaderService: FuseTranslationLoaderService,
private fuseTranslationLoader: FuseTranslationLoaderService private _translateService: TranslateService
) )
{ {
// Navigation
this.navigation = navigation;
// Add languages // Add languages
this.translate.addLangs(['en', 'tr']); this._translateService.addLangs(['en', 'tr']);
// Set the default language // Set the default language
this.translate.setDefaultLang('en'); this._translateService.setDefaultLang('en');
// Set the navigation translations // Set the navigation translations
this.fuseTranslationLoader.loadTranslations(navigationEnglish, navigationTurkish); this._fuseTranslationLoaderService.loadTranslations(navigationEnglish, navigationTurkish);
// Use a language // Use a language
this.translate.use('en'); this._translateService.use('en');
} }
} }

View File

@ -8,23 +8,23 @@ import { TranslateModule } from '@ngx-translate/core';
import 'hammerjs'; import 'hammerjs';
import { FuseModule } from '@fuse/fuse.module'; import { FuseModule } from '@fuse/fuse.module';
import { FuseLayoutsModule } from '@fuse/components';
import { FuseSharedModule } from '@fuse/shared.module'; import { FuseSharedModule } from '@fuse/shared.module';
import { fuseConfig } from './fuse-config'; import { fuseConfig } from 'app/fuse-config';
import { AppComponent } from './app.component'; import { FuseFakeDbService } from 'app/fuse-fake-db/fuse-fake-db.service';
import { FuseFakeDbService } from './fuse-fake-db/fuse-fake-db.service'; import { AppComponent } from 'app/app.component';
import { AppStoreModule } from './store/store.module'; import { AppStoreModule } from 'app/store/store.module';
import { LayoutModule } from 'app/layout/layout.module';
const appRoutes: Routes = [ const appRoutes: Routes = [
{ {
path : 'apps', path : 'apps',
loadChildren: './main/apps/apps.module#FuseAppsModule' loadChildren: './main/apps/apps.module#AppsModule'
}, },
{ {
path : 'pages', path : 'pages',
loadChildren: './main/pages/pages.module#FusePagesModule' loadChildren: './main/pages/pages.module#PagesModule'
}, },
{ {
path : 'ui', path : 'ui',
@ -32,15 +32,15 @@ const appRoutes: Routes = [
}, },
{ {
path : 'services', path : 'services',
loadChildren: './main/services/services.module#FuseServicesModule' loadChildren: './main/services/services.module#ServicesModule'
}, },
{ {
path : 'components', path : 'components',
loadChildren: './main/components/components.module#FuseComponentsModule' loadChildren: './main/components/components.module#ComponentsModule'
}, },
{ {
path : 'components-third-party', path : 'components-third-party',
loadChildren: './main/components-third-party/components-third-party.module#FuseComponentsThirdPartyModule' loadChildren: './main/components-third-party/components-third-party.module#ComponentsThirdPartyModule'
}, },
{ {
path : '**', path : '**',
@ -64,11 +64,12 @@ const appRoutes: Routes = [
passThruUnknownUrl: true passThruUnknownUrl: true
}), }),
// Fuse Main and Shared modules // Fuse modules
FuseModule.forRoot(fuseConfig), FuseModule.forRoot(fuseConfig),
FuseLayoutsModule,
FuseSharedModule, FuseSharedModule,
// App modules
LayoutModule,
AppStoreModule AppStoreModule
], ],
bootstrap : [ bootstrap : [

View File

@ -2,12 +2,12 @@
* Default Fuse Configuration * Default Fuse Configuration
* *
* You can edit these options to change the default options. All these options also can be changed per component * You can edit these options to change the default options. All these options also can be changed per component
* basis. See `app/main/content/pages/authentication/login/login.component.ts` constructor method to learn more * basis. See `app/main/pages/authentication/login/login.component.ts` constructor method to learn more
* about changing these options per component basis. * about changing these options per component basis.
*/ */
export const fuseConfig = { export const fuseConfig = {
layout : { layout : {
style : 'vertical', style : 'vertical-basic',
navigation: { navigation: {
position: 'left', position: 'left',
folded : false folded : false

View File

@ -0,0 +1,110 @@
import { Component, HostBinding, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { Subject } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseConfigService } from '@fuse/services/config.service';
@Component({
selector : 'content',
templateUrl: './content.component.html',
styleUrls : ['./content.component.scss'],
animations : fuseAnimations
})
export class ContentComponent implements OnInit, OnDestroy
{
fuseConfig: any;
@HostBinding('@routerTransitionUp')
routeAnimationUp = false;
@HostBinding('@routerTransitionDown')
routeAnimationDown = false;
@HostBinding('@routerTransitionRight')
routeAnimationRight = false;
@HostBinding('@routerTransitionLeft')
routeAnimationLeft = false;
@HostBinding('@routerTransitionFade')
routeAnimationFade = false;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ActivatedRoute} _activatedRoute
* @param {FuseConfigService} _fuseConfigService
* @param {Router} _router
*/
constructor(
private _activatedRoute: ActivatedRoute,
private _fuseConfigService: FuseConfigService,
private _router: Router
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to the router events for router animations
this._router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this._activatedRoute)
)
.subscribe(() => {
switch ( this.fuseConfig.routerAnimation )
{
case 'fadeIn':
this.routeAnimationFade = !this.routeAnimationFade;
break;
case 'slideUp':
this.routeAnimationUp = !this.routeAnimationUp;
break;
case 'slideDown':
this.routeAnimationDown = !this.routeAnimationDown;
break;
case 'slideRight':
this.routeAnimationRight = !this.routeAnimationRight;
break;
case 'slideLeft':
this.routeAnimationLeft = !this.routeAnimationLeft;
break;
}
});
// Subscribe to config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(
(config) => {
this.fuseConfig = config;
}
);
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -3,21 +3,20 @@ import { RouterModule } from '@angular/router';
import { FuseSharedModule } from '@fuse/shared.module'; import { FuseSharedModule } from '@fuse/shared.module';
import { FuseContentComponent } from 'app/layout/content/content.component'; import { ContentComponent } from 'app/layout/blocks/content/content.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
FuseContentComponent ContentComponent
], ],
imports : [ imports : [
RouterModule, RouterModule,
FuseSharedModule, FuseSharedModule,
], ],
exports: [ exports: [
FuseContentComponent ContentComponent
] ]
}) })
export class FuseContentModule export class ContentModule
{ {
} }

View File

@ -1,13 +1,15 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
@Component({ @Component({
selector : 'fuse-footer', selector : 'footer',
templateUrl: './footer.component.html', templateUrl: './footer.component.html',
styleUrls : ['./footer.component.scss'] styleUrls : ['./footer.component.scss']
}) })
export class FuseFooterComponent export class FooterComponent
{ {
/**
* Constructor
*/
constructor() constructor()
{ {
} }

View File

@ -1,18 +1,15 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { MatButtonModule, MatIconModule, MatToolbarModule } from '@angular/material'; import { MatButtonModule, MatIconModule, MatToolbarModule } from '@angular/material';
import { FuseSharedModule } from '@fuse/shared.module'; import { FuseSharedModule } from '@fuse/shared.module';
import { FuseFooterComponent } from 'app/layout/footer/footer.component'; import { FooterComponent } from 'app/layout/blocks/footer/footer.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
FuseFooterComponent FooterComponent
], ],
imports : [ imports : [
RouterModule,
MatButtonModule, MatButtonModule,
MatIconModule, MatIconModule,
MatToolbarModule, MatToolbarModule,
@ -20,9 +17,9 @@ import { FuseFooterComponent } from 'app/layout/footer/footer.component';
FuseSharedModule FuseSharedModule
], ],
exports : [ exports : [
FuseFooterComponent FooterComponent
] ]
}) })
export class FuseFooterModule export class FooterModule
{ {
} }

View File

@ -1,4 +1,4 @@
@import "../../../@fuse/scss/fuse"; @import "src/@fuse/scss/fuse";
body { body {
@ -44,7 +44,7 @@ fuse-sidebar {
} }
} }
fuse-navbar { navbar {
&:not(.top-navbar) { &:not(.top-navbar) {
height: 100%; height: 100%;

View File

@ -0,0 +1,133 @@
import { Component, Input, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
import { FusePerfectScrollbarDirective } from '@fuse/directives/fuse-perfect-scrollbar/fuse-perfect-scrollbar.directive';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
import { navigation } from 'app/navigation/navigation';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
@Component({
selector : 'navbar',
templateUrl : './navbar.component.html',
styleUrls : ['./navbar.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class NavbarComponent implements OnInit, OnDestroy
{
// Layout
@Input()
layout;
fusePerfectScrollbarUpdateTimeout: any;
navigation: any;
// Private
private _fusePerfectScrollbar: FusePerfectScrollbarDirective;
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FuseNavigationService} _fuseNavigationService
* @param {FuseSidebarService} _fuseSidebarService
* @param {Router} _router
*/
constructor(
private _fuseNavigationService: FuseNavigationService,
private _fuseSidebarService: FuseSidebarService,
private _router: Router
)
{
// Set the defaults
this.layout = 'vertical';
this.navigation = navigation;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
// Directive
@ViewChild(FusePerfectScrollbarDirective)
set directive(theDirective: FusePerfectScrollbarDirective)
{
if ( !theDirective )
{
return;
}
this._fusePerfectScrollbar = theDirective;
this._fuseNavigationService.onItemCollapseToggled
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
this.fusePerfectScrollbarUpdateTimeout = setTimeout(() => {
this._fusePerfectScrollbar.update();
}, 310);
});
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this._router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
takeUntil(this._unsubscribeAll)
)
.subscribe(() => {
if ( this._fuseSidebarService.getSidebar('navbar') )
{
this._fuseSidebarService.getSidebar('navbar').close();
}
}
);
}
/**
* On destroy
*/
ngOnDestroy(): void
{
if ( this.fusePerfectScrollbarUpdateTimeout )
{
clearTimeout(this.fusePerfectScrollbarUpdateTimeout);
}
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle sidebar opened status
*/
toggleSidebarOpened(): void
{
this._fuseSidebarService.getSidebar('navbar').toggleOpen();
}
/**
* Toggle sidebar folded status
*/
toggleSidebarFolded(): void
{
this._fuseSidebarService.getSidebar('navbar').toggleFold();
}
}

View File

@ -1,20 +1,16 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { MatButtonModule, MatIconModule } from '@angular/material'; import { MatButtonModule, MatIconModule } from '@angular/material';
import { FuseNavigationModule } from '@fuse/components';
import { FuseSharedModule } from '@fuse/shared.module'; import { FuseSharedModule } from '@fuse/shared.module';
import { FuseNavbarComponent } from 'app/layout/navbar/navbar.component'; import { NavbarComponent } from 'app/layout/blocks/navbar/navbar.component';
import { FuseNavigationModule } from '@fuse/components';
@NgModule({ @NgModule({
declarations: [ declarations: [
FuseNavbarComponent NavbarComponent
], ],
imports : [ imports : [
RouterModule,
MatButtonModule, MatButtonModule,
MatIconModule, MatIconModule,
@ -22,9 +18,9 @@ import { FuseNavigationModule } from '@fuse/components';
FuseNavigationModule FuseNavigationModule
], ],
exports : [ exports : [
FuseNavbarComponent NavbarComponent
] ]
}) })
export class FuseNavbarModule export class NavbarModule
{ {
} }

View File

@ -1,4 +1,4 @@
fuse-quick-panel { quick-panel {
display: flex; display: flex;
width: 280px; width: 280px;
min-width: 280px; min-width: 280px;

View File

@ -0,0 +1,76 @@
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector : 'quick-panel',
templateUrl : './quick-panel.component.html',
styleUrls : ['./quick-panel.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class QuickPanelComponent implements OnInit, OnDestroy
{
date: Date;
events: any[];
notes: any[];
settings: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {HttpClient} _httpClient
*/
constructor(
private _httpClient: HttpClient
)
{
// Set the defaults
this.date = new Date();
this.settings = {
notify: true,
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,18 +1,15 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { MatDividerModule, MatListModule, MatSlideToggleModule } from '@angular/material'; import { MatDividerModule, MatListModule, MatSlideToggleModule } from '@angular/material';
import { FuseSharedModule } from '@fuse/shared.module'; import { FuseSharedModule } from '@fuse/shared.module';
import { FuseQuickPanelComponent } from 'app/layout/quick-panel/quick-panel.component'; import { QuickPanelComponent } from 'app/layout/blocks/quick-panel/quick-panel.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
FuseQuickPanelComponent QuickPanelComponent
], ],
imports : [ imports : [
RouterModule,
MatDividerModule, MatDividerModule,
MatListModule, MatListModule,
MatSlideToggleModule, MatSlideToggleModule,
@ -20,9 +17,9 @@ import { FuseQuickPanelComponent } from 'app/layout/quick-panel/quick-panel.comp
FuseSharedModule, FuseSharedModule,
], ],
exports: [ exports: [
FuseQuickPanelComponent QuickPanelComponent
] ]
}) })
export class FuseQuickPanelModule export class QuickPanelModule
{ {
} }

View File

@ -98,5 +98,7 @@
</button> </button>
</div> </div>
</div> </div>
</mat-toolbar> </mat-toolbar>

View File

@ -1,4 +1,4 @@
@import '../../../@fuse/scss/fuse'; @import "src/@fuse/scss/fuse";
:host { :host {
position: relative; position: relative;

View File

@ -0,0 +1,182 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { NavigationEnd, NavigationStart, Router } from '@angular/router';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
import * as _ from 'lodash';
import { FuseConfigService } from '@fuse/services/config.service';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
import { navigation } from 'app/navigation/navigation';
@Component({
selector : 'toolbar',
templateUrl: './toolbar.component.html',
styleUrls : ['./toolbar.component.scss']
})
export class ToolbarComponent implements OnInit, OnDestroy
{
horizontalNav: boolean;
languages: any;
noNav: boolean;
navigation: any;
selectedLanguage: any;
showLoadingBar: boolean;
userStatusOptions: any[];
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FuseConfigService} _fuseConfigService
* @param {FuseSidebarService} _fuseSidebarService
* @param {Router} _router
* @param {TranslateService} _translateService
*/
constructor(
private _fuseConfigService: FuseConfigService,
private _fuseSidebarService: FuseSidebarService,
private _router: Router,
private _translateService: TranslateService
)
{
// Set the defaults
this.userStatusOptions = [
{
'title': 'Online',
'icon' : 'icon-checkbox-marked-circle',
'color': '#4CAF50'
},
{
'title': 'Away',
'icon' : 'icon-clock',
'color': '#FFC107'
},
{
'title': 'Do not Disturb',
'icon' : 'icon-minus-circle',
'color': '#F44336'
},
{
'title': 'Invisible',
'icon' : 'icon-checkbox-blank-circle-outline',
'color': '#BDBDBD'
},
{
'title': 'Offline',
'icon' : 'icon-checkbox-blank-circle-outline',
'color': '#616161'
}
];
this.languages = [
{
id : 'en',
title: 'English',
flag : 'us'
},
{
id : 'tr',
title: 'Turkish',
flag : 'tr'
}
];
this.navigation = navigation;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to the router events to show/hide the loading bar
this._router.events
.pipe(
filter((event) => event instanceof NavigationStart),
takeUntil(this._unsubscribeAll)
)
.subscribe((event) => {
this.showLoadingBar = true;
});
this._router.events
.pipe(
filter((event) => event instanceof NavigationEnd)
)
.subscribe((event) => {
this.showLoadingBar = false;
});
// Subscribe to the config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((settings) => {
this.horizontalNav = settings.layout.navigation.position === 'top';
this.noNav = settings.layout.navigation.position === 'none';
});
// Set the selected language from default languages
this.selectedLanguage = _.find(this.languages, {'id': this._translateService.currentLang});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle sidebar opened
*
* @param key
*/
toggleSidebarOpened(key): void
{
this._fuseSidebarService.getSidebar(key).toggleOpen();
}
/**
* Search
*
* @param value
*/
search(value): void
{
// Do your search here...
console.log(value);
}
/**
* Set the language
*
* @param langId
*/
setLanguage(langId): void
{
// Set the selected language for toolbar
this.selectedLanguage = _.find(this.languages, {'id': langId});
// Use the selected language for translations
this._translateService.use(langId);
}
}

View File

@ -2,18 +2,17 @@ import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { MatButtonModule, MatIconModule, MatMenuModule, MatProgressBarModule, MatToolbarModule } from '@angular/material'; import { MatButtonModule, MatIconModule, MatMenuModule, MatProgressBarModule, MatToolbarModule } from '@angular/material';
import { FuseSearchBarModule, FuseShortcutsModule } from '@fuse/components';
import { FuseSharedModule } from '@fuse/shared.module'; import { FuseSharedModule } from '@fuse/shared.module';
import { FuseToolbarComponent } from 'app/layout/toolbar/toolbar.component'; import { ToolbarComponent } from 'app/layout/blocks/toolbar/toolbar.component';
import { FuseSearchBarModule, FuseShortcutsModule } from '@fuse/components';
@NgModule({ @NgModule({
declarations: [ declarations: [
FuseToolbarComponent ToolbarComponent
], ],
imports : [ imports : [
RouterModule, RouterModule,
MatButtonModule, MatButtonModule,
MatIconModule, MatIconModule,
MatMenuModule, MatMenuModule,
@ -25,9 +24,9 @@ import { FuseSearchBarModule, FuseShortcutsModule } from '@fuse/components';
FuseShortcutsModule FuseShortcutsModule
], ],
exports : [ exports : [
FuseToolbarComponent ToolbarComponent
] ]
}) })
export class FuseToolbarModule export class ToolbarModule
{ {
} }

View File

@ -1,70 +0,0 @@
import { Component, HostBinding, OnDestroy } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations/index';
import { FuseConfigService } from '@fuse/services/config.service';
@Component({
selector : 'fuse-content',
templateUrl: './content.component.html',
styleUrls : ['./content.component.scss'],
animations : fuseAnimations
})
export class FuseContentComponent implements OnDestroy
{
onConfigChanged: Subscription;
fuseSettings: any;
@HostBinding('@routerTransitionUp') routeAnimationUp = false;
@HostBinding('@routerTransitionDown') routeAnimationDown = false;
@HostBinding('@routerTransitionRight') routeAnimationRight = false;
@HostBinding('@routerTransitionLeft') routeAnimationLeft = false;
@HostBinding('@routerTransitionFade') routeAnimationFade = false;
constructor(
private router: Router,
private activatedRoute: ActivatedRoute,
private fuseConfig: FuseConfigService
)
{
this.router.events.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this.activatedRoute)
).subscribe((event) => {
switch ( this.fuseSettings.routerAnimation )
{
case 'fadeIn':
this.routeAnimationFade = !this.routeAnimationFade;
break;
case 'slideUp':
this.routeAnimationUp = !this.routeAnimationUp;
break;
case 'slideDown':
this.routeAnimationDown = !this.routeAnimationDown;
break;
case 'slideRight':
this.routeAnimationRight = !this.routeAnimationRight;
break;
case 'slideLeft':
this.routeAnimationLeft = !this.routeAnimationLeft;
break;
}
});
this.onConfigChanged =
this.fuseConfig.onConfigChanged
.subscribe(
(newSettings) => {
this.fuseSettings = newSettings;
}
);
}
ngOnDestroy()
{
this.onConfigChanged.unsubscribe();
}
}

View File

@ -0,0 +1,15 @@
import { NgModule } from '@angular/core';
import { VerticalNavBasicLayoutModule } from 'app/layout/vertical/basic/basic.module';
@NgModule({
imports: [
VerticalNavBasicLayoutModule
],
exports: [
VerticalNavBasicLayoutModule
]
})
export class LayoutModule
{
}

View File

@ -1,95 +0,0 @@
import { Component, Input, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { FusePerfectScrollbarDirective } from '@fuse/directives/fuse-perfect-scrollbar/fuse-perfect-scrollbar.directive';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
import { navigation } from 'app/navigation/navigation';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseSidebarComponent } from '@fuse/components/sidebar/sidebar.component';
@Component({
selector : 'fuse-navbar',
templateUrl : './navbar.component.html',
styleUrls : ['./navbar.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FuseNavbarComponent implements OnInit, OnDestroy
{
private fusePerfectScrollbar: FusePerfectScrollbarDirective;
@ViewChild(FusePerfectScrollbarDirective) set directive(theDirective: FusePerfectScrollbarDirective)
{
if ( !theDirective )
{
return;
}
this.fusePerfectScrollbar = theDirective;
this.navigationServiceWatcher =
this.navigationService.onItemCollapseToggled.subscribe(() => {
this.fusePerfectScrollbarUpdateTimeout = setTimeout(() => {
this.fusePerfectScrollbar.update();
}, 310);
});
}
@Input() layout;
navigation: any;
navigationServiceWatcher: Subscription;
fusePerfectScrollbarUpdateTimeout;
constructor(
private sidebarService: FuseSidebarService,
private navigationService: FuseNavigationService,
private router: Router
)
{
// Navigation data
this.navigation = navigation;
// Default layout
this.layout = 'vertical';
}
ngOnInit()
{
this.router.events.subscribe(
(event) => {
if ( event instanceof NavigationEnd )
{
if ( this.sidebarService.getSidebar('navbar') )
{
this.sidebarService.getSidebar('navbar').close();
}
}
}
);
}
ngOnDestroy()
{
if ( this.fusePerfectScrollbarUpdateTimeout )
{
clearTimeout(this.fusePerfectScrollbarUpdateTimeout);
}
if ( this.navigationServiceWatcher )
{
this.navigationServiceWatcher.unsubscribe();
}
}
toggleSidebarOpened()
{
this.sidebarService.getSidebar('navbar').toggleOpen();
}
toggleSidebarFolded()
{
this.sidebarService.getSidebar('navbar').toggleFold();
}
}

View File

@ -1,41 +0,0 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector : 'fuse-quick-panel',
templateUrl : './quick-panel.component.html',
styleUrls : ['./quick-panel.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FuseQuickPanelComponent implements OnInit
{
date: Date;
settings: any;
notes: any[];
events: any[];
constructor(private http: HttpClient)
{
this.date = new Date();
this.settings = {
notify: true,
cloud : false,
retro : true
};
}
ngOnInit()
{
this.http.get('api/quick-panel-notes')
.subscribe((response: any) => {
this.notes = response;
});
this.http.get('api/quick-panel-events')
.subscribe((response: any) => {
this.events = response;
});
}
}

View File

@ -1,119 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { NavigationEnd, NavigationStart, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import * as _ from 'lodash';
import { FuseConfigService } from '@fuse/services/config.service';
import { FuseSidebarService } from '@fuse/components/sidebar/sidebar.service';
import { navigation } from 'app/navigation/navigation';
@Component({
selector : 'fuse-toolbar',
templateUrl: './toolbar.component.html',
styleUrls : ['./toolbar.component.scss']
})
export class FuseToolbarComponent implements OnInit
{
userStatusOptions: any[];
languages: any;
selectedLanguage: any;
showLoadingBar: boolean;
horizontalNav: boolean;
noNav: boolean;
navigation: any;
constructor(
private router: Router,
private fuseConfig: FuseConfigService,
private sidebarService: FuseSidebarService,
private translate: TranslateService
)
{
this.userStatusOptions = [
{
'title': 'Online',
'icon' : 'icon-checkbox-marked-circle',
'color': '#4CAF50'
},
{
'title': 'Away',
'icon' : 'icon-clock',
'color': '#FFC107'
},
{
'title': 'Do not Disturb',
'icon' : 'icon-minus-circle',
'color': '#F44336'
},
{
'title': 'Invisible',
'icon' : 'icon-checkbox-blank-circle-outline',
'color': '#BDBDBD'
},
{
'title': 'Offline',
'icon' : 'icon-checkbox-blank-circle-outline',
'color': '#616161'
}
];
this.languages = [
{
id : 'en',
title: 'English',
flag : 'us'
},
{
id : 'tr',
title: 'Turkish',
flag : 'tr'
}
];
router.events.subscribe(
(event) => {
if ( event instanceof NavigationStart )
{
this.showLoadingBar = true;
}
if ( event instanceof NavigationEnd )
{
this.showLoadingBar = false;
}
});
this.fuseConfig.onConfigChanged.subscribe((settings) => {
this.horizontalNav = settings.layout.navigation === 'top';
this.noNav = settings.layout.navigation === 'none';
});
this.navigation = navigation;
}
ngOnInit()
{
this.selectedLanguage = _.find(this.languages, {'id': this.translate.currentLang});
}
toggleSidebarOpened(key)
{
this.sidebarService.getSidebar(key).toggleOpen();
}
search(value)
{
// Do your search here...
console.log(value);
}
setLanguage(langId)
{
// Set the selected language for toolbar
this.selectedLanguage = _.find(this.languages, {'id': langId});
// Use the selected language for translations
this.translate.use(langId);
}
}

View File

@ -0,0 +1,77 @@
<mat-sidenav-container>
<div id="main-content">
<!-- TOOLBAR: Above -->
<ng-container *ngIf="fuseConfig.layout.toolbar === 'above'">
<toolbar class="above" [ngClass]="fuseConfig.colorClasses.toolbar"></toolbar>
</ng-container>
<!-- / TOOLBAR: Above -->
<!-- NAVBAR: Top -->
<navbar layout="horizontal"
class="top-navbar" fxHide fxShow.gt-md
[ngClass]="fuseConfig.colorClasses.navbar"
*ngIf="fuseConfig.layout.navigation.position === 'top'">
</navbar>
<!-- / NAVBAR: Top -->
<div id="wrapper">
<!-- NAVBAR: Left -->
<fuse-sidebar [name]="'navbar'"
[folded]="fuseConfig.layout.navigation.folded"
[lockedOpen]="'gt-md'"
class="left-navbar" [ngClass]="fuseConfig.colorClasses.navbar"
*ngIf="fuseConfig.layout.navigation.position === 'left' || fuseConfig.layout.navigation.position === 'top'">
<navbar layout="vertical"></navbar>
</fuse-sidebar>
<!-- / NAVBAR: Left -->
<div class="content-wrapper">
<!-- TOOLBAR: Below -->
<ng-container *ngIf="fuseConfig.layout.toolbar === 'below'">
<toolbar class="below" [ngClass]="fuseConfig.colorClasses.toolbar"></toolbar>
</ng-container>
<!-- / TOOLBAR: Below -->
<content></content>
<!-- FOOTER: Below -->
<ng-container *ngIf="fuseConfig.layout.footer === 'below'">
<footer class="below" [ngClass]="fuseConfig.colorClasses.footer"></footer>
</ng-container>
<!-- / FOOTER: Below -->
</div>
<!-- NAVBAR: Right -->
<fuse-sidebar [name]="'navbar'" [align]="'right'"
[folded]="fuseConfig.layout.navigation.folded"
[lockedOpen]="'gt-md'"
class="right-navbar" [ngClass]="fuseConfig.colorClasses.navbar"
*ngIf="fuseConfig.layout.navigation.position === 'right'">
<navbar layout="vertical"></navbar>
</fuse-sidebar>
<!-- / NAVBAR: Right -->
</div>
<!-- FOOTER: Above -->
<ng-container *ngIf="fuseConfig.layout.footer === 'above'">
<footer class="above" [ngClass]="fuseConfig.colorClasses.footer"></footer>
</ng-container>
<!-- FOOTER: Above -->
</div>
<!-- QUICK PANEL -->
<mat-sidenav fuseMatSidenavHelper="quick-panel" position="end">
<quick-panel></quick-panel>
</mat-sidenav>
<!-- / QUICK PANEL -->
</mat-sidenav-container>
<fuse-theme-options [navigation]="navigation"></fuse-theme-options>

View File

@ -1,6 +1,6 @@
@import "src/@fuse/scss/fuse"; @import "src/@fuse/scss/fuse";
fuse-vertical-nav-basic-layout { vertical-nav-basic-layout {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
@ -21,7 +21,7 @@ fuse-vertical-nav-basic-layout {
height: auto !important; height: auto !important;
} }
#fuse-main-content { #main-content {
display: flex; display: flex;
flex: 1; flex: 1;
flex-direction: column; flex-direction: column;
@ -39,7 +39,7 @@ fuse-vertical-nav-basic-layout {
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;
fuse-content { content {
position: relative; position: relative;
display: flex; display: flex;
flex: 1; flex: 1;

View File

@ -0,0 +1,64 @@
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseConfigService } from '@fuse/services/config.service';
import { navigation } from 'app/navigation/navigation';
@Component({
selector : 'vertical-nav-basic-layout',
templateUrl : './basic.component.html',
styleUrls : ['./basic.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class VerticalNavBasicLayoutComponent implements OnInit, OnDestroy
{
fuseConfig: any;
navigation: any;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {FuseConfigService} _fuseConfigService
*/
constructor(
private _fuseConfigService: FuseConfigService
)
{
// Set the defaults
this.navigation = navigation;
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this.fuseConfig = config;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -0,0 +1,38 @@
import { NgModule } from '@angular/core';
import { MatSidenavModule } from '@angular/material';
import { FuseSidebarModule, FuseThemeOptionsModule } from '@fuse/components';
import { FuseSharedModule } from '@fuse/shared.module';
import { ContentModule } from 'app/layout/blocks/content/content.module';
import { FooterModule } from 'app/layout/blocks/footer/footer.module';
import { NavbarModule } from 'app/layout/blocks/navbar/navbar.module';
import { QuickPanelModule } from 'app/layout/blocks/quick-panel/quick-panel.module';
import { ToolbarModule } from 'app/layout/blocks/toolbar/toolbar.module';
import { VerticalNavBasicLayoutComponent } from 'app/layout/vertical/basic/basic.component';
@NgModule({
declarations: [
VerticalNavBasicLayoutComponent
],
imports : [
MatSidenavModule,
FuseSharedModule,
FuseSidebarModule,
FuseThemeOptionsModule,
ContentModule,
FooterModule,
NavbarModule,
QuickPanelModule,
ToolbarModule
],
exports : [
VerticalNavBasicLayoutComponent
]
})
export class VerticalNavBasicLayoutModule
{
}

View File

@ -5,22 +5,23 @@ import { MatButtonModule, MatFormFieldModule, MatIconModule, MatInputModule, Mat
import { FuseSharedModule } from '@fuse/shared.module'; import { FuseSharedModule } from '@fuse/shared.module';
import { FuseAcademyCoursesComponent } from './courses/courses.component'; import { AcademyCoursesComponent } from 'app/main/apps/academy/courses/courses.component';
import { FuseAcademyCourseComponent } from './course/course.component'; import { AcademyCourseComponent } from 'app/main/apps/academy/course/course.component';
import { AcademyCoursesService } from './courses.service'; import { AcademyCoursesService } from 'app/main/apps/academy/courses.service';
import { AcademyCourseService } from './course.service'; import { AcademyCourseService } from 'app/main/apps/academy/course.service';
const routes = [ const routes = [
{ {
path : 'courses', path : 'courses',
component: FuseAcademyCoursesComponent, component: AcademyCoursesComponent,
resolve : { resolve : {
academy: AcademyCoursesService academy: AcademyCoursesService
} }
}, },
{ {
path : 'courses/:courseId/:courseSlug', path : 'courses/:courseId/:courseSlug',
component: FuseAcademyCourseComponent, component: AcademyCourseComponent,
resolve : { resolve : {
academy: AcademyCourseService academy: AcademyCourseService
} }
@ -33,8 +34,8 @@ const routes = [
@NgModule({ @NgModule({
declarations: [ declarations: [
FuseAcademyCoursesComponent, AcademyCoursesComponent,
FuseAcademyCourseComponent AcademyCourseComponent
], ],
imports : [ imports : [
RouterModule.forChild(routes), RouterModule.forChild(routes),
@ -53,6 +54,6 @@ const routes = [
AcademyCourseService AcademyCourseService
] ]
}) })
export class FuseAcademyModule export class AcademyModule
{ {
} }

View File

@ -8,12 +8,23 @@ export class AcademyCourseService implements Resolve<any>
{ {
onCourseChanged: BehaviorSubject<any> = new BehaviorSubject({}); onCourseChanged: BehaviorSubject<any> = new BehaviorSubject({});
constructor(private http: HttpClient) /**
* Constructor
*
* @param {HttpClient} _httpClient
*/
constructor(
private _httpClient: HttpClient
)
{ {
} }
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/** /**
* The Academy App Main Resolver * Resolver
* *
* @param {ActivatedRouteSnapshot} route * @param {ActivatedRouteSnapshot} route
* @param {RouterStateSnapshot} state * @param {RouterStateSnapshot} state
@ -34,10 +45,17 @@ export class AcademyCourseService implements Resolve<any>
}); });
} }
/**
* Get course
*
* @param courseId
* @param courseSlug
* @returns {Promise<any>}
*/
getCourse(courseId, courseSlug): Promise<any> getCourse(courseId, courseSlug): Promise<any>
{ {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.http.get('api/academy-course/' + courseId + '/' + courseSlug) this._httpClient.get('api/academy-course/' + courseId + '/' + courseSlug)
.subscribe((response: any) => { .subscribe((response: any) => {
this.onCourseChanged.next(response); this.onCourseChanged.next(response);
resolve(response); resolve(response);

View File

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

View File

@ -9,12 +9,23 @@ export class AcademyCoursesService implements Resolve<any>
onCategoriesChanged: BehaviorSubject<any> = new BehaviorSubject({}); onCategoriesChanged: BehaviorSubject<any> = new BehaviorSubject({});
onCoursesChanged: BehaviorSubject<any> = new BehaviorSubject({}); onCoursesChanged: BehaviorSubject<any> = new BehaviorSubject({});
constructor(private http: HttpClient) /**
* Constructor
*
* @param {HttpClient} _httpClient
*/
constructor(
private _httpClient: HttpClient
)
{ {
} }
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/** /**
* The Academy App Main Resolver * Resolver
* *
* @param {ActivatedRouteSnapshot} route * @param {ActivatedRouteSnapshot} route
* @param {RouterStateSnapshot} state * @param {RouterStateSnapshot} state
@ -36,10 +47,15 @@ export class AcademyCoursesService implements Resolve<any>
}); });
} }
/**
* Get categories
*
* @returns {Promise<any>}
*/
getCategories(): Promise<any> getCategories(): Promise<any>
{ {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.http.get('api/academy-categories') this._httpClient.get('api/academy-categories')
.subscribe((response: any) => { .subscribe((response: any) => {
this.onCategoriesChanged.next(response); this.onCategoriesChanged.next(response);
resolve(response); resolve(response);
@ -47,10 +63,15 @@ export class AcademyCoursesService implements Resolve<any>
}); });
} }
/**
* Get courses
*
* @returns {Promise<any>}
*/
getCourses(): Promise<any> getCourses(): Promise<any>
{ {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.http.get('api/academy-courses') this._httpClient.get('api/academy-courses')
.subscribe((response: any) => { .subscribe((response: any) => {
this.onCoursesChanged.next(response); this.onCoursesChanged.next(response);
resolve(response); resolve(response);

View File

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

View File

@ -1,18 +1,16 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { FuseAngularMaterialModule } from '../components/angular-material/angular-material.module';
import { FuseSharedModule } from '@fuse/shared.module'; import { FuseSharedModule } from '@fuse/shared.module';
const routes = [ const routes = [
{ {
path : 'dashboards/analytics', path : 'dashboards/analytics',
loadChildren: './dashboards/analytics/analytics.module#FuseAnalyticsDashboardModule' loadChildren: './dashboards/analytics/analytics.module#AnalyticsDashboardModule'
}, },
{ {
path : 'dashboards/project', path : 'dashboards/project',
loadChildren: './dashboards/project/project.module#FuseProjectDashboardModule' loadChildren: './dashboards/project/project.module#ProjectDashboardModule'
}, },
{ {
path : 'mail', path : 'mail',
@ -24,19 +22,19 @@ const routes = [
}, },
{ {
path : 'chat', path : 'chat',
loadChildren: './chat/chat.module#FuseChatModule' loadChildren: './chat/chat.module#ChatModule'
}, },
{ {
path : 'calendar', path : 'calendar',
loadChildren: './calendar/calendar.module#FuseCalendarModule' loadChildren: './calendar/calendar.module#CalendarModule'
}, },
{ {
path : 'e-commerce', path : 'e-commerce',
loadChildren: './e-commerce/e-commerce.module#FuseEcommerceModule' loadChildren: './e-commerce/e-commerce.module#EcommerceModule'
}, },
{ {
path : 'academy', path : 'academy',
loadChildren: './academy/academy.module#FuseAcademyModule' loadChildren: './academy/academy.module#AcademyModule'
}, },
{ {
path : 'todo', path : 'todo',
@ -44,11 +42,11 @@ const routes = [
}, },
{ {
path : 'file-manager', path : 'file-manager',
loadChildren: './file-manager/file-manager.module#FuseFileManagerModule' loadChildren: './file-manager/file-manager.module#FileManagerModule'
}, },
{ {
path : 'contacts', path : 'contacts',
loadChildren: './contacts/contacts.module#FuseContactsModule' loadChildren: './contacts/contacts.module#ContactsModule'
}, },
{ {
path : 'scrumboard', path : 'scrumboard',
@ -58,12 +56,10 @@ const routes = [
@NgModule({ @NgModule({
imports : [ imports : [
FuseSharedModule,
RouterModule.forChild(routes), RouterModule.forChild(routes),
FuseAngularMaterialModule FuseSharedModule
], ]
declarations: []
}) })
export class FuseAppsModule export class AppsModule
{ {
} }

View File

@ -8,34 +8,35 @@ import { CalendarEvent, CalendarEventAction, CalendarEventTimesChangedEvent, Cal
import { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component'; import { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component';
import { fuseAnimations } from '@fuse/animations'; import { fuseAnimations } from '@fuse/animations';
import { FuseCalendarEventFormDialogComponent } from './event-form/event-form.component'; import { CalendarService } from 'app/main/apps/calendar/calendar.service';
import { CalendarEventModel } from './event.model'; import { CalendarEventModel } from 'app/main/apps/calendar/event.model';
import { CalendarService } from './calendar.service'; import { CalendarEventFormDialogComponent } from 'app/main/apps/calendar/event-form/event-form.component';
@Component({ @Component({
selector : 'fuse-calendar', selector : 'calendar',
templateUrl : './calendar.component.html', templateUrl : './calendar.component.html',
styleUrls : ['./calendar.component.scss'], styleUrls : ['./calendar.component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
animations : fuseAnimations animations : fuseAnimations
}) })
export class FuseCalendarComponent implements OnInit export class CalendarComponent implements OnInit
{ {
actions: CalendarEventAction[];
activeDayIsOpen: boolean;
confirmDialogRef: MatDialogRef<FuseConfirmDialogComponent>;
dialogRef: any;
events: CalendarEvent[];
refresh: Subject<any> = new Subject();
selectedDay: any;
view: string; view: string;
viewDate: Date; viewDate: Date;
events: CalendarEvent[];
public actions: CalendarEventAction[];
activeDayIsOpen: boolean;
refresh: Subject<any> = new Subject();
dialogRef: any;
confirmDialogRef: MatDialogRef<FuseConfirmDialogComponent>;
selectedDay: any;
constructor( constructor(
public dialog: MatDialog, private _matDialog: MatDialog,
public calendarService: CalendarService private _calendarService: CalendarService
) )
{ {
// Set the defaults
this.view = 'month'; this.view = 'month';
this.viewDate = new Date(); this.viewDate = new Date();
this.activeDayIsOpen = true; this.activeDayIsOpen = true;
@ -62,29 +63,41 @@ export class FuseCalendarComponent implements OnInit
this.setEvents(); this.setEvents();
} }
ngOnInit() // -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{ {
/** /**
* Watch re-render-refresh for updating db * Watch re-render-refresh for updating db
*/ */
this.refresh.subscribe(updateDB => { this.refresh.subscribe(updateDB => {
// console.warn('REFRESH');
if ( updateDB ) if ( updateDB )
{ {
// console.warn('UPDATE DB'); this._calendarService.updateEvents(this.events);
this.calendarService.updateEvents(this.events);
} }
}); });
this.calendarService.onEventsUpdated.subscribe(events => { this._calendarService.onEventsUpdated.subscribe(events => {
this.setEvents(); this.setEvents();
this.refresh.next(); this.refresh.next();
}); });
} }
setEvents() // -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Set events
*/
setEvents(): void
{ {
this.events = this.calendarService.events.map(item => { this.events = this._calendarService.events.map(item => {
item.actions = this.actions; item.actions = this.actions;
return new CalendarEventModel(item); return new CalendarEventModel(item);
}); });
@ -92,10 +105,11 @@ export class FuseCalendarComponent implements OnInit
/** /**
* Before View Renderer * Before View Renderer
*
* @param {any} header * @param {any} header
* @param {any} body * @param {any} body
*/ */
beforeMonthViewRender({header, body}) beforeMonthViewRender({header, body}): void
{ {
// console.info('beforeMonthViewRender'); // console.info('beforeMonthViewRender');
/** /**
@ -118,6 +132,7 @@ export class FuseCalendarComponent implements OnInit
/** /**
* Day clicked * Day clicked
*
* @param {MonthViewDay} day * @param {MonthViewDay} day
*/ */
dayClicked(day: CalendarMonthViewDay): void dayClicked(day: CalendarMonthViewDay): void
@ -144,6 +159,7 @@ export class FuseCalendarComponent implements OnInit
/** /**
* Event times changed * Event times changed
* Event dropped or resized * Event dropped or resized
*
* @param {CalendarEvent} event * @param {CalendarEvent} event
* @param {Date} newStart * @param {Date} newStart
* @param {Date} newEnd * @param {Date} newEnd
@ -158,11 +174,12 @@ export class FuseCalendarComponent implements OnInit
/** /**
* Delete Event * Delete Event
*
* @param event * @param event
*/ */
deleteEvent(event) deleteEvent(event): void
{ {
this.confirmDialogRef = this.dialog.open(FuseConfirmDialogComponent, { this.confirmDialogRef = this._matDialog.open(FuseConfirmDialogComponent, {
disableClose: false disableClose: false
}); });
@ -182,14 +199,15 @@ export class FuseCalendarComponent implements OnInit
/** /**
* Edit Event * Edit Event
*
* @param {string} action * @param {string} action
* @param {CalendarEvent} event * @param {CalendarEvent} event
*/ */
editEvent(action: string, event: CalendarEvent) editEvent(action: string, event: CalendarEvent): void
{ {
const eventIndex = this.events.indexOf(event); const eventIndex = this.events.indexOf(event);
this.dialogRef = this.dialog.open(FuseCalendarEventFormDialogComponent, { this.dialogRef = this._matDialog.open(CalendarEventFormDialogComponent, {
panelClass: 'event-form-dialog', panelClass: 'event-form-dialog',
data : { data : {
event : event, event : event,
@ -233,7 +251,7 @@ export class FuseCalendarComponent implements OnInit
*/ */
addEvent(): void addEvent(): void
{ {
this.dialogRef = this.dialog.open(FuseCalendarEventFormDialogComponent, { this.dialogRef = this._matDialog.open(CalendarEventFormDialogComponent, {
panelClass: 'event-form-dialog', panelClass: 'event-form-dialog',
data : { data : {
action: 'new', action: 'new',

View File

@ -1,22 +1,20 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { MatButtonModule, MatDatepickerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatSlideToggleModule, MatToolbarModule } from '@angular/material'; import { MatButtonModule, MatDatepickerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatSlideToggleModule, MatToolbarModule } from '@angular/material';
import { CalendarModule } from 'angular-calendar';
import { ColorPickerModule } from 'ngx-color-picker'; import { ColorPickerModule } from 'ngx-color-picker';
import { CalendarModule as AngularCalendarModule } from 'angular-calendar';
import { FuseSharedModule } from '@fuse/shared.module'; import { FuseSharedModule } from '@fuse/shared.module';
import { FuseConfirmDialogModule } from '@fuse/components'; import { FuseConfirmDialogModule } from '@fuse/components';
import { CalendarService } from './calendar.service'; import { CalendarComponent } from 'app/main/apps/calendar/calendar.component';
import { FuseCalendarComponent } from './calendar.component'; import { CalendarService } from 'app/main/apps/calendar/calendar.service';
import { FuseCalendarEventFormDialogComponent } from './event-form/event-form.component'; import { CalendarEventFormDialogComponent } from 'app/main/apps/calendar/event-form/event-form.component';
const routes: Routes = [ const routes: Routes = [
{ {
path : '**', path : '**',
component: FuseCalendarComponent, component: CalendarComponent,
children : [], children : [],
resolve : { resolve : {
chat: CalendarService chat: CalendarService
@ -26,8 +24,8 @@ const routes: Routes = [
@NgModule({ @NgModule({
declarations : [ declarations : [
FuseCalendarComponent, CalendarComponent,
FuseCalendarEventFormDialogComponent CalendarEventFormDialogComponent
], ],
imports : [ imports : [
RouterModule.forChild(routes), RouterModule.forChild(routes),
@ -40,7 +38,7 @@ const routes: Routes = [
MatSlideToggleModule, MatSlideToggleModule,
MatToolbarModule, MatToolbarModule,
CalendarModule.forRoot(), AngularCalendarModule.forRoot(),
ColorPickerModule, ColorPickerModule,
FuseSharedModule, FuseSharedModule,
@ -49,8 +47,10 @@ const routes: Routes = [
providers : [ providers : [
CalendarService CalendarService
], ],
entryComponents: [FuseCalendarEventFormDialogComponent] entryComponents: [
CalendarEventFormDialogComponent
]
}) })
export class FuseCalendarModule export class CalendarModule
{ {
} }

View File

@ -9,11 +9,29 @@ export class CalendarService implements Resolve<any>
events: any; events: any;
onEventsUpdated = new Subject<any>(); onEventsUpdated = new Subject<any>();
constructor(private http: HttpClient) /**
* Constructor
*
* @param {HttpClient} _httpClient
*/
constructor(
private _httpClient: HttpClient
)
{ {
} }
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param {ActivatedRouteSnapshot} route
* @param {RouterStateSnapshot} state
* @returns {Observable<any> | Promise<any> | any}
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any
{ {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -28,11 +46,16 @@ export class CalendarService implements Resolve<any>
}); });
} }
getEvents() /**
* Get events
*
* @returns {Promise<any>}
*/
getEvents(): Promise<any>
{ {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.http.get('api/calendar/events') this._httpClient.get('api/calendar/events')
.subscribe((response: any) => { .subscribe((response: any) => {
this.events = response.data; this.events = response.data;
this.onEventsUpdated.next(this.events); this.onEventsUpdated.next(this.events);
@ -41,10 +64,16 @@ export class CalendarService implements Resolve<any>
}); });
} }
updateEvents(events) /**
* Update events
*
* @param events
* @returns {Promise<any>}
*/
updateEvents(events): Promise<any>
{ {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.http.post('api/calendar/events', { this._httpClient.post('api/calendar/events', {
id : 'events', id : 'events',
data: [...events] data: [...events]
}) })

View File

@ -1,11 +1,11 @@
import { Component, Inject, ViewEncapsulation } from '@angular/core'; import { Component, Inject, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { CalendarEvent } from 'angular-calendar';
import { MatColors } from '@fuse/mat-colors'; import { MatColors } from '@fuse/mat-colors';
import { CalendarEvent } from 'angular-calendar'; import { CalendarEventModel } from 'app/main/apps/calendar/event.model';
import { CalendarEventModel } from '../event.model';
@Component({ @Component({
selector : 'fuse-calendar-event-form-dialog', selector : 'fuse-calendar-event-form-dialog',
@ -14,22 +14,29 @@ import { CalendarEventModel } from '../event.model';
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class FuseCalendarEventFormDialogComponent export class CalendarEventFormDialogComponent
{ {
event: CalendarEvent;
dialogTitle: string;
eventForm: FormGroup;
action: string; action: string;
event: CalendarEvent;
eventForm: FormGroup;
dialogTitle: string;
presetColors = MatColors.presets; presetColors = MatColors.presets;
/**
* Constructor
*
* @param {MatDialogRef<CalendarEventFormDialogComponent>} dialogRef
* @param _data
* @param {FormBuilder} _formBuilder
*/
constructor( constructor(
public dialogRef: MatDialogRef<FuseCalendarEventFormDialogComponent>, public dialogRef: MatDialogRef<CalendarEventFormDialogComponent>,
@Inject(MAT_DIALOG_DATA) private data: any, @Inject(MAT_DIALOG_DATA) private _data: any,
private formBuilder: FormBuilder private _formBuilder: FormBuilder
) )
{ {
this.event = data.event; this.event = _data.event;
this.action = data.action; this.action = _data.action;
if ( this.action === 'edit' ) if ( this.action === 'edit' )
{ {
@ -39,27 +46,36 @@ export class FuseCalendarEventFormDialogComponent
{ {
this.dialogTitle = 'New Event'; this.dialogTitle = 'New Event';
this.event = new CalendarEventModel({ this.event = new CalendarEventModel({
start: data.date, start: _data.date,
end : data.date end : _data.date
}); });
} }
this.eventForm = this.createEventForm(); this.eventForm = this.createEventForm();
} }
createEventForm() // -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Create the event form
*
* @returns {FormGroup}
*/
createEventForm(): FormGroup
{ {
return new FormGroup({ return new FormGroup({
title : new FormControl(this.event.title), title : new FormControl(this.event.title),
start : new FormControl(this.event.start), start : new FormControl(this.event.start),
end : new FormControl(this.event.end), end : new FormControl(this.event.end),
allDay: new FormControl(this.event.allDay), allDay: new FormControl(this.event.allDay),
color : this.formBuilder.group({ color : this._formBuilder.group({
primary : new FormControl(this.event.color.primary), primary : new FormControl(this.event.color.primary),
secondary: new FormControl(this.event.color.secondary) secondary: new FormControl(this.event.color.secondary)
}), }),
meta : meta :
this.formBuilder.group({ this._formBuilder.group({
location: new FormControl(this.event.meta.location), location: new FormControl(this.event.meta.location),
notes : new FormControl(this.event.meta.notes) notes : new FormControl(this.event.meta.notes)
}) })

View File

@ -23,6 +23,11 @@ export class CalendarEventModel
notes: string notes: string
}; };
/**
* Constructor
*
* @param data
*/
constructor(data?) constructor(data?)
{ {
data = data || {}; data = data || {};

View File

@ -3,12 +3,12 @@ import { Component } from '@angular/core';
import { fuseAnimations } from '@fuse/animations'; import { fuseAnimations } from '@fuse/animations';
@Component({ @Component({
selector : 'fuse-chat-start', selector : 'chat-start',
templateUrl: './chat-start.component.html', templateUrl: './chat-start.component.html',
styleUrls : ['./chat-start.component.scss'], styleUrls : ['./chat-start.component.scss'],
animations : fuseAnimations animations : fuseAnimations
}) })
export class FuseChatStartComponent export class ChatStartComponent
{ {
constructor() constructor()
{ {

View File

@ -87,7 +87,7 @@
<!-- / CHAT CONTENT --> <!-- / CHAT CONTENT -->
<!-- CHAT FOOTER --> <!-- CHAT FOOTER -->
<div class="chat-footer" fxLayout="row" fxLayoutAlign="center center"> <div class="chat-footer" fxFlex="1 0 auto" fxLayout="row" fxLayoutAlign="center center">
<!-- REPLY FORM --> <!-- REPLY FORM -->
<form #replyForm="ngForm" <form #replyForm="ngForm"
@ -97,18 +97,20 @@
fxLayout="row" fxLayout="row"
fxLayoutAlign="start center"> fxLayoutAlign="start center">
<mat-form-field class="" fxFlex floatLabel="never"> <mat-form-field fxFlex floatLabel="never">
<textarea matInput #replyInput placeholder="Type and hit enter to send message" <textarea matInput #replyInput placeholder="Type and hit enter to send message"
ngModel name="message"></textarea> ngModel name="message"></textarea>
</mat-form-field> </mat-form-field>
<button mat-fab class="" type="submit" aria-label="Send message"> <button mat-fab type="submit" aria-label="Send message">
<mat-icon>send</mat-icon> <mat-icon>send</mat-icon>
</button> </button>
</form> </form>
<!-- / REPLY FORM --> <!-- / REPLY FORM -->
</div> </div>
<!-- / CHAT FOOTER--> <!-- / CHAT FOOTER-->
</div> </div>
<!-- / CHAT --> <!-- / CHAT -->

View File

@ -99,7 +99,7 @@
} }
.chat-footer { .chat-footer {
min-height: 64px; min-height: 72px;
max-height: 96px; max-height: 96px;
background-color: #F3F4F5; background-color: #F3F4F5;
color: rgba(0, 0, 0, 0.87); color: rgba(0, 0, 0, 0.87);
@ -116,6 +116,7 @@
overflow: auto; overflow: auto;
max-height: 80px; max-height: 80px;
transition: height 200ms ease; transition: height 200ms ease;
&.grow { &.grow {
height: 80px; height: 80px;
} }

View File

@ -1,16 +1,18 @@
import { AfterViewInit, Component, OnInit, ViewChild, ViewChildren } from '@angular/core'; import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild, ViewChildren } from '@angular/core';
import { NgForm } from '@angular/forms'; 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 { FusePerfectScrollbarDirective } from '@fuse/directives/fuse-perfect-scrollbar/fuse-perfect-scrollbar.directive';
import { ChatService } from '../chat.service'; import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({ @Component({
selector : 'fuse-chat-view', selector : 'chat-view',
templateUrl: './chat-view.component.html', templateUrl: './chat-view.component.html',
styleUrls : ['./chat-view.component.scss'] styleUrls : ['./chat-view.component.scss']
}) })
export class FuseChatViewComponent implements OnInit, AfterViewInit export class ChatViewComponent implements OnInit, OnDestroy, AfterViewInit
{ {
user: any; user: any;
chat: any; chat: any;
@ -18,18 +20,44 @@ export class FuseChatViewComponent implements OnInit, AfterViewInit
contact: any; contact: any;
replyInput: any; replyInput: any;
selectedChat: any; selectedChat: any;
@ViewChild(FusePerfectScrollbarDirective) directiveScroll: FusePerfectScrollbarDirective;
@ViewChildren('replyInput') replyInputField;
@ViewChild('replyForm') replyForm: NgForm;
constructor(private chatService: ChatService) @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();
} }
ngOnInit() // -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{ {
this.user = this.chatService.user; this.user = this._chatService.user;
this.chatService.onChatSelected this._chatService.onChatSelected
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(chatData => { .subscribe(chatData => {
if ( chatData ) if ( chatData )
{ {
@ -41,18 +69,41 @@ export class FuseChatViewComponent implements OnInit, AfterViewInit
}); });
} }
ngAfterViewInit() /**
* After view init
*/
ngAfterViewInit(): void
{ {
this.replyInput = this.replyInputField.first.nativeElement; this.replyInput = this.replyInputField.first.nativeElement;
this.readyToReply(); this.readyToReply();
} }
selectContact() /**
* On destroy
*/
ngOnDestroy(): void
{ {
this.chatService.selectContact(this.contact); // Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
} }
readyToReply() // -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Select contact
*/
selectContact(): void
{
this._chatService.selectContact(this.contact);
}
/**
* Ready to reply
*/
readyToReply(): void
{ {
setTimeout(() => { setTimeout(() => {
this.replyForm.reset(); this.replyForm.reset();
@ -62,14 +113,22 @@ export class FuseChatViewComponent implements OnInit, AfterViewInit
} }
focusReplyInput() /**
* Focus to the reply input
*/
focusReplyInput(): void
{ {
setTimeout(() => { setTimeout(() => {
this.replyInput.focus(); this.replyInput.focus();
}); });
} }
scrollToBottom(speed?: number) /**
* Scroll to the bottom
*
* @param {number} speed
*/
scrollToBottom(speed?: number): void
{ {
speed = speed || 400; speed = speed || 400;
if ( this.directiveScroll ) if ( this.directiveScroll )
@ -82,7 +141,10 @@ export class FuseChatViewComponent implements OnInit, AfterViewInit
} }
} }
reply(event) /**
* Reply
*/
reply(): void
{ {
// Message // Message
const message = { const message = {
@ -95,9 +157,8 @@ export class FuseChatViewComponent implements OnInit, AfterViewInit
this.dialog.push(message); this.dialog.push(message);
// Update the server // Update the server
this.chatService.updateDialog(this.selectedChat.chatId, this.dialog).then(response => { this._chatService.updateDialog(this.selectedChat.chatId, this.dialog).then(response => {
this.readyToReply(); this.readyToReply();
}); });
} }
} }

View File

@ -15,20 +15,20 @@
<!-- LEFT SIDENAV --> <!-- LEFT SIDENAV -->
<mat-sidenav class="sidenav" position="start" opened="true" mode="side" <mat-sidenav class="sidenav" position="start" opened="true" mode="side"
fuseMatSidenavHelper="chat-left-sidenav" mat-is-locked-open="gt-md"> fuseMatSidenavHelper="chat-left-sidenav" mat-is-locked-open="gt-md">
<fuse-chat-left-sidenav></fuse-chat-left-sidenav> <chat-left-sidenav></chat-left-sidenav>
</mat-sidenav> </mat-sidenav>
<!-- / LEFT SIDENAV --> <!-- / LEFT SIDENAV -->
<!-- CONTENT --> <!-- CONTENT -->
<fuse-chat-start *ngIf="!selectedChat"></fuse-chat-start> <chat-start *ngIf="!selectedChat"></chat-start>
<fuse-chat-view *ngIf="selectedChat"></fuse-chat-view> <chat-view *ngIf="selectedChat"></chat-view>
<!-- / CONTENT --> <!-- / CONTENT -->
<!-- RIGHT SIDENAV --> <!-- RIGHT SIDENAV -->
<mat-sidenav class="sidenav" position="end" opened="false" mode="over" <mat-sidenav class="sidenav" position="end" opened="false" mode="over"
fuseMatSidenavHelper="chat-right-sidenav"> fuseMatSidenavHelper="chat-right-sidenav">
<fuse-chat-right-sidenav></fuse-chat-right-sidenav> <chat-right-sidenav></chat-right-sidenav>
</mat-sidenav> </mat-sidenav>
<!-- / RIGHT SIDENAV --> <!-- / RIGHT SIDENAV -->

View File

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

View File

@ -5,20 +5,20 @@ import { MatButtonModule, MatCardModule, MatFormFieldModule, MatIconModule, MatI
import { FuseSharedModule } from '@fuse/shared.module'; import { FuseSharedModule } from '@fuse/shared.module';
import { ChatService } from './chat.service'; import { ChatService } from 'app/main/apps/chat/chat.service';
import { FuseChatComponent } from './chat.component'; import { ChatComponent } from 'app/main/apps/chat/chat.component';
import { FuseChatViewComponent } from './chat-view/chat-view.component'; import { ChatStartComponent } from 'app/main/apps/chat/chat-start/chat-start.component';
import { FuseChatStartComponent } from './chat-start/chat-start.component'; import { ChatViewComponent } from 'app/main/apps/chat/chat-view/chat-view.component';
import { FuseChatChatsSidenavComponent } from './sidenavs/left/chats/chats.component'; import { ChatChatsSidenavComponent } from 'app/main/apps/chat/sidenavs/left/chats/chats.component';
import { FuseChatUserSidenavComponent } from './sidenavs/left/user/user.component'; import { ChatUserSidenavComponent } from 'app/main/apps/chat/sidenavs/left/user/user.component';
import { FuseChatLeftSidenavComponent } from './sidenavs/left/left.component'; import { ChatLeftSidenavComponent } from 'app/main/apps/chat/sidenavs/left/left.component';
import { FuseChatRightSidenavComponent } from './sidenavs/right/right.component'; import { ChatRightSidenavComponent } from 'app/main/apps/chat/sidenavs/right/right.component';
import { FuseChatContactSidenavComponent } from './sidenavs/right/contact/contact.component'; import { ChatContactSidenavComponent } from 'app/main/apps/chat/sidenavs/right/contact/contact.component';
const routes: Routes = [ const routes: Routes = [
{ {
path : '**', path : '**',
component: FuseChatComponent, component: ChatComponent,
children : [], children : [],
resolve : { resolve : {
chat: ChatService chat: ChatService
@ -28,14 +28,14 @@ const routes: Routes = [
@NgModule({ @NgModule({
declarations: [ declarations: [
FuseChatComponent, ChatComponent,
FuseChatViewComponent, ChatViewComponent,
FuseChatStartComponent, ChatStartComponent,
FuseChatChatsSidenavComponent, ChatChatsSidenavComponent,
FuseChatUserSidenavComponent, ChatUserSidenavComponent,
FuseChatLeftSidenavComponent, ChatLeftSidenavComponent,
FuseChatRightSidenavComponent, ChatRightSidenavComponent,
FuseChatContactSidenavComponent ChatContactSidenavComponent
], ],
imports : [ imports : [
RouterModule.forChild(routes), RouterModule.forChild(routes),
@ -57,6 +57,6 @@ const routes: Routes = [
ChatService ChatService
] ]
}) })
export class FuseChatModule export class ChatModule
{ {
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

@ -2,37 +2,41 @@ import { Component, Inject, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms'; import { FormBuilder, FormGroup } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { CalendarEvent } from 'angular-calendar'; import { Contact } from 'app/main/apps/contacts/contact.model';
import { Contact } from '../contact.model';
@Component({ @Component({
selector : 'fuse-contacts-contact-form-dialog', selector : 'contacts-contact-form-dialog',
templateUrl : './contact-form.component.html', templateUrl : './contact-form.component.html',
styleUrls : ['./contact-form.component.scss'], styleUrls : ['./contact-form.component.scss'],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class FuseContactsContactFormDialogComponent export class ContactsContactFormDialogComponent
{ {
event: CalendarEvent;
dialogTitle: string;
contactForm: FormGroup;
action: string; action: string;
contact: Contact; contact: Contact;
contactForm: FormGroup;
dialogTitle: string;
/**
* Constructor
*
* @param {MatDialogRef<ContactsContactFormDialogComponent>} _dialogRef
* @param _data
* @param {FormBuilder} _formBuilder
*/
constructor( constructor(
public dialogRef: MatDialogRef<FuseContactsContactFormDialogComponent>, private _dialogRef: MatDialogRef<ContactsContactFormDialogComponent>,
@Inject(MAT_DIALOG_DATA) private data: any, @Inject(MAT_DIALOG_DATA) private _data: any,
private formBuilder: FormBuilder private _formBuilder: FormBuilder
) )
{ {
this.action = data.action; this.action = _data.action;
if ( this.action === 'edit' ) if ( this.action === 'edit' )
{ {
this.dialogTitle = 'Edit Contact'; this.dialogTitle = 'Edit Contact';
this.contact = data.contact; this.contact = _data.contact;
} }
else else
{ {
@ -43,9 +47,18 @@ export class FuseContactsContactFormDialogComponent
this.contactForm = this.createContactForm(); this.contactForm = this.createContactForm();
} }
createContactForm() // -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Create contact form
*
* @returns {FormGroup}
*/
createContactForm(): FormGroup
{ {
return this.formBuilder.group({ return this._formBuilder.group({
id : [this.contact.id], id : [this.contact.id],
name : [this.contact.name], name : [this.contact.name],
lastName: [this.contact.lastName], lastName: [this.contact.lastName],

View File

@ -1,6 +1,6 @@
@import "src/@fuse/scss/fuse"; @import "src/@fuse/scss/fuse";
fuse-contacts-contact-list { contacts-contact-list {
display: flex; display: flex;
flex: 1 1 auto; flex: 1 1 auto;
width: 100%; width: 100%;

View File

@ -2,24 +2,26 @@ import { Component, OnDestroy, OnInit, TemplateRef, ViewChild, ViewEncapsulation
import { FormGroup } from '@angular/forms'; import { FormGroup } from '@angular/forms';
import { MatDialog, MatDialogRef } from '@angular/material'; import { MatDialog, MatDialogRef } from '@angular/material';
import { DataSource } from '@angular/cdk/collections'; import { DataSource } from '@angular/cdk/collections';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations'; import { fuseAnimations } from '@fuse/animations';
import { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component'; import { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component';
import { FuseContactsContactFormDialogComponent } from '../contact-form/contact-form.component'; import { ContactsService } from 'app/main/apps/contacts/contacts.service';
import { ContactsService } from '../contacts.service'; import { ContactsContactFormDialogComponent } from 'app/main/apps/contacts/contact-form/contact-form.component';
@Component({ @Component({
selector : 'fuse-contacts-contact-list', selector : 'contacts-contact-list',
templateUrl : './contact-list.component.html', templateUrl : './contact-list.component.html',
styleUrls : ['./contact-list.component.scss'], styleUrls : ['./contact-list.component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
animations : fuseAnimations animations : fuseAnimations
}) })
export class FuseContactsContactListComponent implements OnInit, OnDestroy export class ContactsContactListComponent implements OnInit, OnDestroy
{ {
@ViewChild('dialogContent') dialogContent: TemplateRef<any>; @ViewChild('dialogContent')
dialogContent: TemplateRef<any>;
contacts: any; contacts: any;
user: any; user: any;
@ -27,24 +29,41 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
displayedColumns = ['checkbox', 'avatar', 'name', 'email', 'phone', 'jobTitle', 'buttons']; displayedColumns = ['checkbox', 'avatar', 'name', 'email', 'phone', 'jobTitle', 'buttons'];
selectedContacts: any[]; selectedContacts: any[];
checkboxes: {}; checkboxes: {};
onContactsChangedSubscription: Subscription;
onFilterChangedSubscription: Subscription;
onSelectedContactsChangedSubscription: Subscription;
onUserDataChangedSubscription: Subscription;
dialogRef: any; dialogRef: any;
confirmDialogRef: MatDialogRef<FuseConfirmDialogComponent>; confirmDialogRef: MatDialogRef<FuseConfirmDialogComponent>;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ContactsService} _contactsService
* @param {MatDialog} _matDialog
*/
constructor( constructor(
private contactsService: ContactsService, private _contactsService: ContactsService,
public dialog: MatDialog public _matDialog: MatDialog
) )
{ {
this.onContactsChangedSubscription = // Set the private defaults
this.contactsService.onContactsChanged.subscribe(contacts => { 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.contacts = contacts;
this.checkboxes = {}; this.checkboxes = {};
@ -53,8 +72,9 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
}); });
}); });
this.onSelectedContactsChangedSubscription = this._contactsService.onSelectedContactsChanged
this.contactsService.onSelectedContactsChanged.subscribe(selectedContacts => { .pipe(takeUntil(this._unsubscribeAll))
.subscribe(selectedContacts => {
for ( const id in this.checkboxes ) for ( const id in this.checkboxes )
{ {
if ( !this.checkboxes.hasOwnProperty(id) ) if ( !this.checkboxes.hasOwnProperty(id) )
@ -67,33 +87,41 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
this.selectedContacts = selectedContacts; this.selectedContacts = selectedContacts;
}); });
this.onUserDataChangedSubscription = this._contactsService.onUserDataChanged
this.contactsService.onUserDataChanged.subscribe(user => { .pipe(takeUntil(this._unsubscribeAll))
.subscribe(user => {
this.user = user; this.user = user;
}); });
this.onFilterChangedSubscription = this._contactsService.onFilterChanged
this.contactsService.onFilterChanged.subscribe(() => { .pipe(takeUntil(this._unsubscribeAll))
this.contactsService.deselectContacts(); .subscribe(() => {
this._contactsService.deselectContacts();
}); });
} }
ngOnInit() /**
* On destroy
*/
ngOnDestroy(): void
{ {
this.dataSource = new FilesDataSource(this.contactsService); // Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
} }
ngOnDestroy() // -----------------------------------------------------------------------------------------------------
{ // @ Public methods
this.onContactsChangedSubscription.unsubscribe(); // -----------------------------------------------------------------------------------------------------
this.onFilterChangedSubscription.unsubscribe();
this.onSelectedContactsChangedSubscription.unsubscribe();
this.onUserDataChangedSubscription.unsubscribe();
}
editContact(contact) /**
* Edit contact
*
* @param contact
*/
editContact(contact): void
{ {
this.dialogRef = this.dialog.open(FuseContactsContactFormDialogComponent, { this.dialogRef = this._matDialog.open(ContactsContactFormDialogComponent, {
panelClass: 'contact-form-dialog', panelClass: 'contact-form-dialog',
data : { data : {
contact: contact, contact: contact,
@ -116,7 +144,7 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
*/ */
case 'save': case 'save':
this.contactsService.updateContact(formData.getRawValue()); this._contactsService.updateContact(formData.getRawValue());
break; break;
/** /**
@ -134,9 +162,9 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
/** /**
* Delete Contact * Delete Contact
*/ */
deleteContact(contact) deleteContact(contact): void
{ {
this.confirmDialogRef = this.dialog.open(FuseConfirmDialogComponent, { this.confirmDialogRef = this._matDialog.open(FuseConfirmDialogComponent, {
disableClose: false disableClose: false
}); });
@ -145,19 +173,29 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
this.confirmDialogRef.afterClosed().subscribe(result => { this.confirmDialogRef.afterClosed().subscribe(result => {
if ( result ) if ( result )
{ {
this.contactsService.deleteContact(contact); this._contactsService.deleteContact(contact);
} }
this.confirmDialogRef = null; this.confirmDialogRef = null;
}); });
} }
onSelectedChange(contactId) /**
* On selected change
*
* @param contactId
*/
onSelectedChange(contactId): void
{ {
this.contactsService.toggleSelectedContact(contactId); this._contactsService.toggleSelectedContact(contactId);
} }
toggleStar(contactId) /**
* Toggle star
*
* @param contactId
*/
toggleStar(contactId): void
{ {
if ( this.user.starred.includes(contactId) ) if ( this.user.starred.includes(contactId) )
{ {
@ -168,24 +206,37 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
this.user.starred.push(contactId); this.user.starred.push(contactId);
} }
this.contactsService.updateUserData(this.user); this._contactsService.updateUserData(this.user);
} }
} }
export class FilesDataSource extends DataSource<any> export class FilesDataSource extends DataSource<any>
{ {
constructor(private contactsService: ContactsService) /**
* Constructor
*
* @param {ContactsService} _contactsService
*/
constructor(
private _contactsService: ContactsService
)
{ {
super(); super();
} }
/** Connect function called by the table to retrieve one stream containing the data to render. */ /**
* Connect function called by the table to retrieve one stream containing the data to render.
* @returns {Observable<any[]>}
*/
connect(): Observable<any[]> connect(): Observable<any[]>
{ {
return this.contactsService.onContactsChanged; return this._contactsService.onContactsChanged;
} }
disconnect() /**
* Disconnect
*/
disconnect(): void
{ {
} }
} }

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