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": [
"src/favicon.ico",
"src/assets",
"src/app/main/content/components/angular-material"
"src/app/main/components/angular-material"
],
"styles": [
"src/styles.scss"

View File

@ -10,7 +10,14 @@ export class FuseConfirmDialogComponent
{
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 { interval } from 'rxjs';
import { map } from 'rxjs/operators';
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { interval, Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import * as moment from 'moment';
@Component({
@ -10,29 +8,52 @@ import * as moment from 'moment';
templateUrl: './countdown.component.html',
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;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*/
constructor()
{
// Set the defaults
this.countdown = {
days : '',
hours : '',
minutes: '',
seconds: ''
};
// Set the private defaults
this._unsubscribeAll = new Subject();
}
ngOnInit()
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
const currDate = moment();
const eventDate = moment(this.eventDate);
// Get the difference in between the current date and event date
let diff = eventDate.diff(currDate, 'seconds');
const countDown = interval(1000).pipe(
// Create a subscribable interval
const countDown = interval(1000)
.pipe(
map(value => {
return diff = diff - 1;
}),
@ -48,8 +69,21 @@ export class FuseCountdownComponent implements OnInit
})
);
countDown.subscribe(value => {
// Subscribe to the countdown interval
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
{
/**
* Constructor
*/
constructor()
{
}

View File

@ -7,6 +7,9 @@ import { Component } from '@angular/core';
})
export class FuseDemoSidenavComponent
{
/**
* 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 { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import * as Prism from 'prismjs/prism';
import './prism-languages';
import '@fuse/components/highlight/prism-languages';
@Component({
selector : 'fuse-highlight',
template : ' ',
template : '',
styleUrls: ['./highlight.component.scss']
})
export class FuseHighlightComponent implements OnInit
export class FuseHighlightComponent implements OnInit, OnDestroy
{
@ContentChild('source') source: ElementRef;
@Input('lang') lang: string;
@Input('path') path: string;
// Source
@ContentChild('source')
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(
private elementRef: ElementRef,
private http: HttpClient
private _elementRef: ElementRef,
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 ( !this.lang )
@ -34,7 +61,9 @@ export class FuseHighlightComponent implements OnInit
if ( this.path )
{
// 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
this.highlight(response);
@ -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
const sourceLines = sourceCode.split('\n');
@ -94,9 +142,8 @@ export class FuseHighlightComponent implements OnInit
const highlightedCode = Prism.highlight(source, Prism.languages[this.lang]);
// 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>';
}
}

View File

@ -2,7 +2,6 @@ export * from './confirm-dialog/confirm-dialog.module';
export * from './countdown/countdown.module';
export * from './demo/demo.module';
export * from './highlight/highlight.module';
export * from './layouts/layouts.module';
export * from './material-color-picker/material-color-picker.module';
export * from './navigation/navigation.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 { Subscription } from 'rxjs';
import { Component, HostBinding, HostListener, Input, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '../../../../animations/index';
import { FuseConfigService } from '../../../../services/config.service';
import { fuseAnimations } from '@fuse/animations';
import { FuseConfigService } from '@fuse/services/config.service';
@Component({
selector : 'fuse-nav-horizontal-collapse',
@ -10,42 +11,76 @@ import { FuseConfigService } from '../../../../services/config.service';
styleUrls : ['./nav-horizontal-collapse.component.scss'],
animations : fuseAnimations
})
export class FuseNavHorizontalCollapseComponent implements OnDestroy
export class FuseNavHorizontalCollapseComponent implements OnInit, OnDestroy
{
onConfigChanged: Subscription;
fuseSettings: any;
fuseConfig: any;
isOpen = false;
@HostBinding('class') classes = 'nav-item nav-collapse';
@Input() item: any;
@HostBinding('class')
classes = 'nav-item nav-collapse';
@HostListener('mouseenter')
open()
{
this.isOpen = true;
}
@Input()
item: any;
@HostListener('mouseleave')
close()
{
this.isOpen = false;
}
// Private
private _unsubscribeAll: Subject<any>;
constructor(
private fuseConfig: FuseConfigService
private _fuseConfigService: FuseConfigService
)
{
this.onConfigChanged =
this.fuseConfig.onConfigChanged
// 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(
(newSettings) => {
this.fuseSettings = newSettings;
(config) => {
this.fuseConfig = config;
}
);
}
ngOnDestroy()
/**
* On destroy
*/
ngOnDestroy(): void
{
this.onConfigChanged.unsubscribe();
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Open
*/
@HostListener('mouseenter')
open(): void
{
this.isOpen = true;
}
/**
* Close
*/
@HostListener('mouseleave')
close(): void
{
this.isOpen = false;
}
}

View File

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

View File

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

View File

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

View File

@ -1,7 +1,10 @@
import { Component, HostBinding, Input, OnInit } from '@angular/core';
import { FuseNavigationService } from '../../navigation.service';
import { Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
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({
selector : 'fuse-nav-vertical-collapse',
@ -9,22 +12,52 @@ import { fuseAnimations } from '../../../../animations/index';
styleUrls : ['./nav-vertical-collapse.component.scss'],
animations : fuseAnimations
})
export class FuseNavVerticalCollapseComponent implements OnInit
export class FuseNavVerticalCollapseComponent implements OnInit, OnDestroy
{
@Input() item: any;
@HostBinding('class') classes = 'nav-collapse nav-item';
@HostBinding('class.open') public isOpen = false;
@Input()
item: any;
@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(
private navigationService: FuseNavigationService,
private router: Router
private _fuseNavigationService: FuseNavigationService,
private _router: Router
)
{
// Listen for route changes
router.events.subscribe(
(event) => {
if ( event instanceof NavigationEnd )
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ 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) )
@ -35,12 +68,11 @@ export class FuseNavVerticalCollapseComponent implements OnInit
{
this.collapse();
}
}
}
);
});
// Listen for collapsing of any navigation item
this.navigationService.onItemCollapsed
this._fuseNavigationService.onItemCollapsed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(
(clickedItem) => {
if ( clickedItem && clickedItem.children )
@ -54,7 +86,7 @@ export class FuseNavVerticalCollapseComponent implements OnInit
// Check if the url can be found in
// one of the children of this item
if ( this.isUrlInChildren(this.item, this.router.url) )
if ( this.isUrlInChildren(this.item, this._router.url) )
{
return;
}
@ -67,13 +99,10 @@ export class FuseNavVerticalCollapseComponent implements OnInit
}
}
);
}
ngOnInit()
{
// Check if the url can be found in
// 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();
}
@ -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
*
* @param ev
*/
toggleOpen(ev)
toggleOpen(ev): void
{
ev.preventDefault();
this.isOpen = !this.isOpen;
// Navigation collapse toggled...
this.navigationService.onItemCollapsed.next(this.item);
this.navigationService.onItemCollapseToggled.next();
this._fuseNavigationService.onItemCollapsed.next(this.item);
this._fuseNavigationService.onItemCollapseToggled.next();
}
/**
* Expand the collapsable navigation
*/
expand()
expand(): void
{
if ( this.isOpen )
{
@ -110,13 +153,13 @@ export class FuseNavVerticalCollapseComponent implements OnInit
}
this.isOpen = true;
this.navigationService.onItemCollapseToggled.next();
this._fuseNavigationService.onItemCollapseToggled.next();
}
/**
* Collapse the collapsable navigation
*/
collapse()
collapse(): void
{
if ( !this.isOpen )
{
@ -124,7 +167,7 @@ export class FuseNavVerticalCollapseComponent implements OnInit
}
this.isOpen = false;
this.navigationService.onItemCollapseToggled.next();
this._fuseNavigationService.onItemCollapseToggled.next();
}
/**
@ -133,9 +176,9 @@ export class FuseNavVerticalCollapseComponent implements OnInit
*
* @param parent
* @param item
* @return {any}
* @returns {boolean}
*/
isChildrenOf(parent, item)
isChildrenOf(parent, item): boolean
{
if ( !parent.children )
{
@ -162,9 +205,9 @@ export class FuseNavVerticalCollapseComponent implements OnInit
*
* @param parent
* @param url
* @returns {any}
* @returns {boolean}
*/
isUrlInChildren(parent, url)
isUrlInChildren(parent, url): boolean
{
if ( !parent.children )
{

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
import { Component, ElementRef, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';
import { ObservableMedia } from '@angular/flex-layout';
import { Subscription } from 'rxjs';
import { Subject, Subscription } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { CookieService } from 'ngx-cookie-service';
import { FuseMatchMediaService } from '@fuse/services/match-media.service';
@ -21,42 +21,67 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
searching = false;
mobileShortcutsPanelActive = false;
toolbarColor: string;
matchMediaSubscription: Subscription;
onConfigChanged: Subscription;
@Input() navigation: any;
@Input()
navigation: any;
@ViewChild('searchInput') searchInputField;
@ViewChild('shortcuts') shortcutsEl: ElementRef;
@ViewChild('searchInput')
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(
private renderer: Renderer2,
private observableMedia: ObservableMedia,
private fuseMatchMedia: FuseMatchMediaService,
private fuseNavigationService: FuseNavigationService,
private fuseConfig: FuseConfigService,
private cookieService: CookieService
private _renderer: Renderer2,
private _cookieService: CookieService,
private _fuseMatchMediaService: FuseMatchMediaService,
private _fuseNavigationService: FuseNavigationService,
private _fuseConfigService: FuseConfigService,
private _observableMedia: ObservableMedia
)
{
this.onConfigChanged =
this.fuseConfig.onConfigChanged
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to config changes
this._fuseConfigService.config
.subscribe(
(newSettings) => {
this.toolbarColor = newSettings.colorClasses.toolbar;
(config) => {
this.toolbarColor = config.colorClasses.toolbar;
}
);
}
ngOnInit()
{
// Get the navigation items and flatten them
this.filteredNavigationItems = this.navigationItems = this.fuseNavigationService.getFlatNavigation(this.navigation);
this.filteredNavigationItems = this.navigationItems = this._fuseNavigationService.getFlatNavigation(this.navigation);
const cookieExists = this.cookieService.check('FUSE2.shortcuts');
const cookieExists = this._cookieService.check('FUSE2.shortcuts');
if ( cookieExists )
{
this.shortcutItems = JSON.parse(this.cookieService.get('FUSE2.shortcuts'));
this.shortcutItems = JSON.parse(this._cookieService.get('FUSE2.shortcuts'));
}
else
{
@ -89,21 +114,36 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
];
}
this.matchMediaSubscription =
this.fuseMatchMedia.onMediaChange.subscribe(() => {
if ( this.observableMedia.isActive('gt-sm') )
this._fuseMatchMediaService.onMediaChange
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
if ( this._observableMedia.isActive('gt-sm') )
{
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();
@ -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();
@ -133,7 +179,7 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
this.shortcutItems.splice(i, 1);
// Save to the cookies
this.cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems));
this._cookieService.set('FUSE2.shortcuts', JSON.stringify(this.shortcutItems));
return;
}
@ -142,32 +188,47 @@ export class FuseShortcutsComponent implements OnInit, OnDestroy
this.shortcutItems.push(itemToToggle);
// 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 item.url === navigationItem.url;
});
}
onMenuOpen()
/**
* On menu open
*/
onMenuOpen(): void
{
setTimeout(() => {
this.searchInputField.nativeElement.focus();
});
}
showMobileShortcutsPanel()
/**
* Show mobile shortcuts
*/
showMobileShortcutsPanel(): void
{
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.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 { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
import { ObservableMedia } from '@angular/flex-layout';
import { Subscription } from 'rxjs';
import { Subject, Subscription } from 'rxjs';
import { FuseSidebarService } from './sidebar.service';
import { FuseMatchMediaService } from '@fuse/services/match-media.service';
import { FuseConfigService } from '@fuse/services/config.service';
import { takeUntil } from 'rxjs/internal/operators';
@Component({
selector : 'fuse-sidebar',
@ -35,6 +36,52 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
@HostBinding('class.locked-open')
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
@HostBinding('class.folded')
@Input()
@ -59,12 +106,12 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
// Get the sibling and set the style rule
if ( this.align === 'left' )
{
sibling = this.elementRef.nativeElement.nextElementSibling;
sibling = this._elementRef.nativeElement.nextElementSibling;
styleRule = 'marginLeft';
}
else
{
sibling = this.elementRef.nativeElement.previousElementSibling;
sibling = this._elementRef.nativeElement.previousElementSibling;
styleRule = 'marginRight';
}
@ -78,13 +125,13 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
if ( value )
{
// Set the style
this.renderer.setStyle(sibling, styleRule, styleValue);
this._renderer.setStyle(sibling, styleRule, styleValue);
}
// If unfolded...
else
{
// 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;
}
// Folded unfolded
@HostBinding('class.unfolded')
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';
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to config changes
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config) => {
this._fuseConfig = config;
});
// Register the sidebar
this.fuseSidebarService.register(this.name, this);
this._fuseSidebarService.register(this.name, this);
// Setup alignment
this._setupAlignment();
@ -158,12 +178,17 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
}
// Unregister the sidebar
this.fuseSidebarService.unregister(this.name);
this._fuseSidebarService.unregister(this.name);
// Unsubscribe from the media watcher subscription
this._onMediaChangeSubscription.unsubscribe();
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Set the sidebar alignment
*
@ -175,11 +200,11 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
// element depending on the align attribute
if ( this.align === 'right' )
{
this.renderer.addClass(this.elementRef.nativeElement, 'right-aligned');
this._renderer.addClass(this._elementRef.nativeElement, 'right-aligned');
}
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;
// Act on every media change
this._onMediaChangeSubscription =
this.fuseMatchMediaService.onMediaChange.subscribe(() => {
this._fuseMatchMediaService.onMediaChange
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// 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 ( this._wasActive === isActive )
@ -224,7 +249,7 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
// Read the folded setting from the config
// and fold the sidebar if it's true
if ( this.fuseConfigService.config.layout.navigationFolded )
if ( this._fuseConfig.layout.navigation.folded )
{
this.fold();
}
@ -250,6 +275,10 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
});
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Open the sidebar
*/
@ -382,17 +411,17 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
showBackdrop(): void
{
// Create the backdrop element
this._backdrop = this.renderer.createElement('div');
this._backdrop = this._renderer.createElement('div');
// Add a class to the backdrop element
this._backdrop.classList.add('fuse-sidebar-overlay');
// 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
this._player =
this.animationBuilder
this._animationBuilder
.build([
animate('300ms ease', style({opacity: 1}))
]).create(this._backdrop);
@ -419,7 +448,7 @@ export class FuseSidebarComponent implements OnInit, OnDestroy
// Create the leave animation and attach it to the player
this._player =
this.animationBuilder
this._animationBuilder
.build([
animate('300ms ease', style({opacity: 0}))
]).create(this._backdrop);

View File

@ -13,7 +13,7 @@
<div class="theme-options-panel-inner" fxLayout="column" fxLayoutAlign="start start">
<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">
<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>
@ -21,7 +21,7 @@
</mat-radio-group>
<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">
<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>
@ -30,13 +30,13 @@
</mat-radio-group>
<h3>Navigation Fold (for vertical navigation):</h3>
<mat-slide-toggle [(ngModel)]="config.layout.navigationFolded"
(change)="onSettingsChange()">
<mat-slide-toggle [(ngModel)]="fuseConfig.layout.navigationFolded"
(change)="onConfigChange()">
Folded
</mat-slide-toggle>
<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">
<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>
@ -44,7 +44,7 @@
</mat-radio-group>
<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">
<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>
@ -52,7 +52,7 @@
</mat-radio-group>
<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">
<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>
@ -65,20 +65,20 @@
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
<h4 class="mr-8">Toolbar Color</h4>
<fuse-material-color-picker [(selectedClass)]="config.colorClasses.toolbar"
(onValueChange)="onSettingsChange()"></fuse-material-color-picker>
<fuse-material-color-picker [(selectedClass)]="fuseConfig.colorClasses.toolbar"
(onValueChange)="onConfigChange()"></fuse-material-color-picker>
</div>
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
<h4 class="mr-8">Navigation Bar Color</h4>
<fuse-material-color-picker [(selectedClass)]="config.colorClasses.navbar"
(onValueChange)="onSettingsChange()"></fuse-material-color-picker>
<fuse-material-color-picker [(selectedClass)]="fuseConfig.colorClasses.navbar"
(onValueChange)="onConfigChange()"></fuse-material-color-picker>
</div>
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
<h4 class="mr-8">Footer Color</h4>
<fuse-material-color-picker [(selectedClass)]="config.colorClasses.footer"
(onValueChange)="onSettingsChange()"></fuse-material-color-picker>
<fuse-material-color-picker [(selectedClass)]="fuseConfig.colorClasses.footer"
(onValueChange)="onConfigChange()"></fuse-material-color-picker>
</div>
</div>
@ -87,7 +87,7 @@
<h3>Router Animation:</h3>
<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">
None
</mat-option>

View File

@ -1,6 +1,7 @@
import { Component, ElementRef, HostBinding, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';
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 { FuseConfigService } from '@fuse/services/config.service';
@ -14,39 +15,59 @@ import { FuseNavigationService } from '@fuse/components/navigation/navigation.se
})
export class FuseThemeOptionsComponent implements OnInit, OnDestroy
{
@Input() navigation;
@ViewChild('openButton') openButton;
@ViewChild('panel') panel;
@ViewChild('overlay') overlay: ElementRef;
@Input()
navigation;
public player: AnimationPlayer;
config: any;
@ViewChild('openButton')
openButton;
onConfigChanged: Subscription;
@ViewChild('panel')
panel;
@ViewChild('overlay')
overlay: ElementRef;
player: AnimationPlayer;
fuseConfig: any;
@HostBinding('class.bar-closed') barClosed: boolean;
// Private
private _unsubscribeAll: Subject<any>;
constructor(
private animationBuilder: AnimationBuilder,
private fuseConfig: FuseConfigService,
private navigationService: FuseNavigationService,
private renderer: Renderer2
private _animationBuilder: AnimationBuilder,
private _fuseConfigService: FuseConfigService,
private _fuseNavigationService: FuseNavigationService,
private _renderer: Renderer2
)
{
// Set the defaults
this.barClosed = true;
this.onConfigChanged =
this.fuseConfig.onConfigChanged
.subscribe(
(newConfig) => {
this.config = newConfig;
}
);
// Set the private defaults
this._unsubscribeAll = new Subject();
}
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();
});
@ -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.animationBuilder
this._animationBuilder
.build([
style({transform: 'translate3d(0,0,0)'}),
animate('400ms ease', style({transform: 'translate3d(100%,0,0)'}))
@ -97,18 +150,4 @@ export class FuseThemeOptionsComponent implements OnInit, OnDestroy
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
{
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
{
@HostBinding('class.flipped') flipped = false;
@ContentChildren(FuseWidgetToggleDirective, {descendants: true}) toggleButtons: QueryList<FuseWidgetToggleDirective>;
@HostBinding('class.flipped')
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()
{
setTimeout(() => {
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* After content init
*/
ngAfterContentInit(): void
{
// Listen for the flip button click
setTimeout(() => {
this.toggleButtons.forEach(flipButton => {
this.renderer.listen(flipButton.el.nativeElement, 'click', (event) => {
this._renderer.listen(flipButton.elementRef.nativeElement, 'click', (event) => {
event.preventDefault();
event.stopPropagation();
this.toggle();
@ -31,7 +50,14 @@ export class FuseWidgetComponent implements AfterContentInit
});
}
toggle()
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle the flipped status
*/
toggle(): void
{
this.flipped = !this.flipped;
}

View File

@ -7,26 +7,40 @@ export class FuseIfOnDomDirective implements AfterContentChecked
{
isCreated = false;
/**
* Constructor
*
* @param {ElementRef} _elementRef
* @param {TemplateRef<any>} _templateRef
* @param {ViewContainerRef} _viewContainerRef
*/
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private element: ElementRef
private _elementRef: ElementRef,
private _templateRef: TemplateRef<any>,
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(() => {
this.viewContainer.createEmbeddedView(this.templateRef);
this._viewContainerRef.createEmbeddedView(this._templateRef);
}, 300);
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;
}
}

View File

@ -1,7 +1,8 @@
import { Directive, Input, OnInit, HostListener, OnDestroy, HostBinding } from '@angular/core';
import { MatSidenav } from '@angular/material';
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 { 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
{
matchMediaSubscription: Subscription;
@HostBinding('class.mat-is-locked-open') isLockedOpen = true;
@Input('fuseMatSidenavHelper') id: string;
@Input('mat-is-locked-open') matIsLockedOpenBreakpoint: string;
@HostBinding('class.mat-is-locked-open')
isLockedOpen = true;
@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(
private fuseMatSidenavService: FuseMatSidenavHelperService,
private fuseMatchMedia: FuseMatchMediaService,
private observableMedia: ObservableMedia,
private matSidenav: MatSidenav
private _fuseMatchMediaService: FuseMatchMediaService,
private _fuseMatSidenavHelperService: FuseMatSidenavHelperService,
private _matSidenav: MatSidenav,
private _observableMedia: ObservableMedia
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
ngOnInit()
{
this.fuseMatSidenavService.setSidenav(this.id, this.matSidenav);
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
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.matSidenav.mode = 'side';
this.matSidenav.toggle(true);
this._matSidenav.mode = 'side';
this._matSidenav.toggle(true);
}
else
{
this.isLockedOpen = false;
this.matSidenav.mode = 'over';
this.matSidenav.toggle(false);
this._matSidenav.mode = 'over';
this._matSidenav.toggle(false);
}
this.matchMediaSubscription = this.fuseMatchMedia.onMediaChange.subscribe(() => {
if ( this.observableMedia.isActive(this.matIsLockedOpenBreakpoint) )
this._fuseMatchMediaService.onMediaChange
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
if ( this._observableMedia.isActive(this.matIsLockedOpenBreakpoint) )
{
this.isLockedOpen = true;
this.matSidenav.mode = 'side';
this.matSidenav.toggle(true);
this._matSidenav.mode = 'side';
this._matSidenav.toggle(true);
}
else
{
this.isLockedOpen = false;
this.matSidenav.mode = 'over';
this.matSidenav.toggle(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
{
@Input('fuseMatSidenavToggler') id;
@Input('fuseMatSidenavToggler')
id;
constructor(private fuseMatSidenavService: FuseMatSidenavHelperService)
/**
* Constructor
*
* @param {FuseMatSidenavHelperService} _fuseMatSidenavHelperService
*/
constructor(
private _fuseMatSidenavHelperService: FuseMatSidenavHelperService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* On click
*/
@HostListener('click')
onClick()
{
this.fuseMatSidenavService.getSidenav(this.id).toggle();
this._fuseMatSidenavHelperService.getSidenav(this.id).toggle();
}
}

View File

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

View File

@ -1,6 +1,7 @@
import { AfterViewInit, Directive, ElementRef, HostListener, OnDestroy, OnInit } from '@angular/core';
import { Platform } from '@angular/cdk/platform';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import PerfectScrollbar from 'perfect-scrollbar';
@ -11,36 +12,58 @@ import { FuseConfigService } from '@fuse/services/config.service';
})
export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnDestroy
{
onConfigChanged: Subscription;
isDisableCustomScrollbars = false;
isMobile = false;
isInitialized = true;
ps: PerfectScrollbar;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ElementRef} elementRef
* @param {FuseConfigService} _fuseConfigService
* @param {Platform} _platform
*/
constructor(
public element: ElementRef,
private fuseConfig: FuseConfigService,
private platform: Platform
public elementRef: ElementRef,
private _fuseConfigService: FuseConfigService,
private _platform: Platform
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
ngOnInit()
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.onConfigChanged =
this.fuseConfig.onConfigChanged.subscribe(
this._fuseConfigService.config
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(
(settings) => {
this.isDisableCustomScrollbars = !settings.customScrollbars;
}
);
if ( this.platform.ANDROID || this.platform.IOS )
if ( this._platform.ANDROID || this._platform.IOS )
{
this.isMobile = true;
}
}
ngAfterViewInit()
/**
* After view init
*/
ngAfterViewInit(): void
{
if ( this.isMobile || this.isDisableCustomScrollbars )
{
@ -49,24 +72,38 @@ export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnD
}
// Initialize the perfect-scrollbar
this.ps = new PerfectScrollbar(this.element.nativeElement, {
this.ps = new PerfectScrollbar(this.elementRef.nativeElement, {
wheelPropagation: true
});
}
ngOnDestroy()
/**
* On destroy
*/
ngOnDestroy(): void
{
if ( !this.isInitialized || !this.ps )
{
return;
}
this.onConfigChanged.unsubscribe();
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
// Destroy the perfect-scrollbar
this.ps.destroy();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Document click
*
* @param {Event} event
*/
@HostListener('document:click', ['$event'])
documentClick(event: Event): void
{
@ -82,7 +119,10 @@ export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnD
this.ps.update();
}
update()
/**
* Update the scrollbar
*/
update(): void
{
if ( !this.isInitialized )
{
@ -93,62 +133,108 @@ export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnD
this.ps.update();
}
destroy()
/**
* Destroy the scrollbar
*/
destroy(): void
{
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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 )
{
this.element.nativeElement[target] = value;
this.elementRef.nativeElement[target] = value;
// PS has weird event sending order, this is a workaround for that
this.update();
this.update();
}
else if ( value !== this.element.nativeElement[target] )
else if ( value !== this.elementRef.nativeElement[target] )
{
let newValue = 0;
let scrollCount = 0;
let oldTimestamp = performance.now();
let oldValue = this.element.nativeElement[target];
let oldValue = this.elementRef.nativeElement[target];
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));
// 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 )
{
this.element.nativeElement[target] = value;
this.elementRef.nativeElement[target] = value;
// PS has weird event sending order, this is a workaround for that
this.update();
@ -171,7 +257,7 @@ export class FusePerfectScrollbarDirective implements OnInit, AfterViewInit, OnD
}
else
{
this.element.nativeElement[target] = oldValue = newValue;
this.elementRef.nativeElement[target] = oldValue = newValue;
oldTimestamp = newTimestamp;

View File

@ -3,7 +3,14 @@ import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'camelCaseToDash'})
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()}`) : '';
}

View File

@ -4,6 +4,14 @@ import { FuseUtils } from '@fuse/utils';
@Pipe({name: 'filter'})
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
{
return FuseUtils.filterArrayByString(mainArr, searchText);

View File

@ -6,6 +6,14 @@ import { Pipe, PipeTransform } from '@angular/core';
})
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
{
const foundItem = value.find(item => {

View File

@ -3,7 +3,14 @@ import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'htmlToPlaintext'})
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, '') : '';
}

View File

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

View File

@ -1,93 +1,96 @@
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 { BehaviorSubject } from 'rxjs';
import { BehaviorSubject, Observable } from 'rxjs';
import { filter } from 'rxjs/operators';
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');
@Injectable()
export class FuseConfigService
{
config: any;
defaultConfig: any;
isSetConfigRan = false;
onConfigChanged: BehaviorSubject<any>;
// Private
private _configSubject: BehaviorSubject<any>;
private readonly _defaultConfig: any;
/**
* Constructor
*
* @param router
* @param platform
* @param config
* @param {Platform} _platform
* @param {Router} _router
* @param _config
*/
constructor(
private router: Router,
public platform: Platform,
@Inject(FUSE_CONFIG) config
private _platform: Platform,
private _router: Router,
@Inject(FUSE_CONFIG) private _config
)
{
// Set the default config from the user provided one (forRoot)
this.defaultConfig = config;
// Set the default config from the user provided config (from forRoot)
this._defaultConfig = _config;
// Initialize the service
this._init();
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Disable Custom Scrollbars if Browser is Mobile
* Set and get the config
*/
if ( this.platform.ANDROID || this.platform.IOS )
set config(value)
{
this.defaultConfig.customScrollbars = false;
// Get the value from the behavior subject
let config = this._configSubject.getValue();
// Merge the new config
config = _.merge({}, config, value);
// Notify the observers
this._configSubject.next(config);
}
// 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 )
get config(): any | Observable<any>
{
this.isSetConfigRan = false;
return this._configSubject.asObservable();
}
if ( event instanceof NavigationEnd )
{
if ( this.isSetConfigRan )
{
return;
}
this.setConfig({
layout: this.defaultConfig.layout
}
);
}
}
);
// Create the behavior subject
this.onConfigChanged = new BehaviorSubject(this.config);
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Set the new config from given object
* Initialize
*
* @param config
* @private
*/
setConfig(config): void
private _init(): void
{
// Set the SetConfigRan true
this.isSetConfigRan = true;
/**
* Disable custom scrollbars if browser is mobile
*/
if ( this._platform.ANDROID || this._platform.IOS )
{
this._defaultConfig.customScrollbars = false;
}
// Merge the config
this.config = _.merge({}, this.config, config);
// Set the settings from the default settings
this._configSubject = new BehaviorSubject(_.cloneDeep(this._defaultConfig));
// Trigger the event
this.onConfigChanged.next(this.config);
// 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()
export class FuseCopierService
{
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
{
this.createTextareaAndSelect(text);
const copySuccessful = document.execCommand('copy');
this.removeFake();
this._removeFake();
return copySuccessful;
}
@ -28,8 +32,10 @@ export class FuseCopierService
/**
* Creates a hidden textarea element, sets its value from `text` property,
* 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
this.textarea = document.createElement('textarea');
@ -53,8 +59,12 @@ export class FuseCopierService
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 )
{

View File

@ -8,11 +8,36 @@ export class FuseMatchMediaService
activeMediaQuery: 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.observableMedia.subscribe((change: MediaChange) => {
// Initialize
this._init();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Initialize
*
* @private
*/
private _init(): void
{
this._observableMedia
.subscribe((change: MediaChange) => {
if ( this.activeMediaQuery !== change.mqAlias )
{
this.activeMediaQuery = change.mqAlias;

View File

@ -6,23 +6,45 @@ import { NavigationEnd, Router } from '@angular/router';
@Injectable()
export class FuseSplashScreenService
{
splashScreenEl;
public player: AnimationPlayer;
splashScreenEl: any;
player: AnimationPlayer;
/**
* Constructor
*
* @param {AnimationBuilder} _animationBuilder
* @param _document
* @param {Router} _router
*/
constructor(
private animationBuilder: AnimationBuilder,
@Inject(DOCUMENT) private document: any,
private router: Router
private _animationBuilder: AnimationBuilder,
@Inject(DOCUMENT) private _document: any,
private _router: Router
)
{
// Initialize
this._init();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Initialize
*
* @private
*/
private _init(): void
{
// 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 ( this.splashScreenEl )
{
// 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 )
{
setTimeout(() => {
@ -38,10 +60,17 @@ export class FuseSplashScreenService
}
}
show()
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Show the splash screen
*/
show(): void
{
this.player =
this.animationBuilder
this._animationBuilder
.build([
style({
opacity: '0',
@ -55,10 +84,13 @@ export class FuseSplashScreenService
}, 0);
}
hide()
/**
* Hide the splash screen
*/
hide(): void
{
this.player =
this.animationBuilder
this._animationBuilder
.build([
style({opacity: '1'}),
animate('400ms ease', style({

View File

@ -10,18 +10,34 @@ export interface Locale
@Injectable()
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];
locales.forEach((locale) => {
// use setTranslation() with the third argument set to true
// 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
{
public static filterArrayByString(mainArr, searchText)
/**
* Filter array by string
*
* @param mainArr
* @param searchText
* @returns {any}
*/
public static filterArrayByString(mainArr, searchText): any
{
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 )
{
@ -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 )
{
@ -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);
}
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)
.toString(16)
@ -90,7 +123,13 @@ export class FuseUtils
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 )
{
@ -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()
.replace(/\s+/g, '-') // Replace spaces with -

View File

@ -1,8 +1 @@
<!--<fuse-main></fuse-main>-->
<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>
<vertical-nav-basic-layout></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 { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { locale as navigationEnglish } from './navigation/i18n/en';
import { locale as navigationTurkish } from './navigation/i18n/tr';
import { navigation } from 'app/navigation/navigation';
import { locale as navigationEnglish } from 'app/navigation/i18n/en';
import { locale as navigationTurkish } from 'app/navigation/i18n/tr';
@Component({
selector : 'fuse-root',
@ -15,23 +16,36 @@ import { locale as navigationTurkish } from './navigation/i18n/tr';
})
export class AppComponent
{
navigation: any;
/**
* Constructor
*
* @param {FuseNavigationService} _fuseNavigationService
* @param {FuseSplashScreenService} _fuseSplashScreenService
* @param {FuseTranslationLoaderService} _fuseTranslationLoaderService
* @param {TranslateService} _translateService
*/
constructor(
private translate: TranslateService,
private fuseNavigationService: FuseNavigationService,
private fuseSplashScreen: FuseSplashScreenService,
private fuseTranslationLoader: FuseTranslationLoaderService
private _fuseNavigationService: FuseNavigationService,
private _fuseSplashScreenService: FuseSplashScreenService,
private _fuseTranslationLoaderService: FuseTranslationLoaderService,
private _translateService: TranslateService
)
{
// Navigation
this.navigation = navigation;
// Add languages
this.translate.addLangs(['en', 'tr']);
this._translateService.addLangs(['en', 'tr']);
// Set the default language
this.translate.setDefaultLang('en');
this._translateService.setDefaultLang('en');
// Set the navigation translations
this.fuseTranslationLoader.loadTranslations(navigationEnglish, navigationTurkish);
this._fuseTranslationLoaderService.loadTranslations(navigationEnglish, navigationTurkish);
// 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 { FuseModule } from '@fuse/fuse.module';
import { FuseLayoutsModule } from '@fuse/components';
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 './fuse-fake-db/fuse-fake-db.service';
import { AppStoreModule } from './store/store.module';
import { FuseFakeDbService } from 'app/fuse-fake-db/fuse-fake-db.service';
import { AppComponent } from 'app/app.component';
import { AppStoreModule } from 'app/store/store.module';
import { LayoutModule } from 'app/layout/layout.module';
const appRoutes: Routes = [
{
path : 'apps',
loadChildren: './main/apps/apps.module#FuseAppsModule'
loadChildren: './main/apps/apps.module#AppsModule'
},
{
path : 'pages',
loadChildren: './main/pages/pages.module#FusePagesModule'
loadChildren: './main/pages/pages.module#PagesModule'
},
{
path : 'ui',
@ -32,15 +32,15 @@ const appRoutes: Routes = [
},
{
path : 'services',
loadChildren: './main/services/services.module#FuseServicesModule'
loadChildren: './main/services/services.module#ServicesModule'
},
{
path : 'components',
loadChildren: './main/components/components.module#FuseComponentsModule'
loadChildren: './main/components/components.module#ComponentsModule'
},
{
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 : '**',
@ -64,11 +64,12 @@ const appRoutes: Routes = [
passThruUnknownUrl: true
}),
// Fuse Main and Shared modules
// Fuse modules
FuseModule.forRoot(fuseConfig),
FuseLayoutsModule,
FuseSharedModule,
// App modules
LayoutModule,
AppStoreModule
],
bootstrap : [

View File

@ -2,12 +2,12 @@
* Default Fuse Configuration
*
* 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.
*/
export const fuseConfig = {
layout : {
style : 'vertical',
style : 'vertical-basic',
navigation: {
position: 'left',
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 { FuseContentComponent } from 'app/layout/content/content.component';
import { ContentComponent } from 'app/layout/blocks/content/content.component';
@NgModule({
declarations: [
FuseContentComponent
ContentComponent
],
imports : [
RouterModule,
FuseSharedModule,
],
exports: [
FuseContentComponent
ContentComponent
]
})
export class FuseContentModule
export class ContentModule
{
}

View File

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

View File

@ -1,18 +1,15 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { MatButtonModule, MatIconModule, MatToolbarModule } from '@angular/material';
import { FuseSharedModule } from '@fuse/shared.module';
import { FuseFooterComponent } from 'app/layout/footer/footer.component';
import { FooterComponent } from 'app/layout/blocks/footer/footer.component';
@NgModule({
declarations: [
FuseFooterComponent
FooterComponent
],
imports : [
RouterModule,
MatButtonModule,
MatIconModule,
MatToolbarModule,
@ -20,9 +17,9 @@ import { FuseFooterComponent } from 'app/layout/footer/footer.component';
FuseSharedModule
],
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 {
@ -44,7 +44,7 @@ fuse-sidebar {
}
}
fuse-navbar {
navbar {
&:not(.top-navbar) {
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 { RouterModule } from '@angular/router';
import { MatButtonModule, MatIconModule } from '@angular/material';
import { FuseNavigationModule } from '@fuse/components';
import { FuseSharedModule } from '@fuse/shared.module';
import { FuseNavbarComponent } from 'app/layout/navbar/navbar.component';
import { FuseNavigationModule } from '@fuse/components';
import { NavbarComponent } from 'app/layout/blocks/navbar/navbar.component';
@NgModule({
declarations: [
FuseNavbarComponent
NavbarComponent
],
imports : [
RouterModule,
MatButtonModule,
MatIconModule,
@ -22,9 +18,9 @@ import { FuseNavigationModule } from '@fuse/components';
FuseNavigationModule
],
exports : [
FuseNavbarComponent
NavbarComponent
]
})
export class FuseNavbarModule
export class NavbarModule
{
}

View File

@ -1,4 +1,4 @@
fuse-quick-panel {
quick-panel {
display: flex;
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 { RouterModule } from '@angular/router';
import { MatDividerModule, MatListModule, MatSlideToggleModule } from '@angular/material';
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({
declarations: [
FuseQuickPanelComponent
QuickPanelComponent
],
imports : [
RouterModule,
MatDividerModule,
MatListModule,
MatSlideToggleModule,
@ -20,9 +17,9 @@ import { FuseQuickPanelComponent } from 'app/layout/quick-panel/quick-panel.comp
FuseSharedModule,
],
exports: [
FuseQuickPanelComponent
QuickPanelComponent
]
})
export class FuseQuickPanelModule
export class QuickPanelModule
{
}

View File

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

View File

@ -1,4 +1,4 @@
@import '../../../@fuse/scss/fuse';
@import "src/@fuse/scss/fuse";
:host {
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 { MatButtonModule, MatIconModule, MatMenuModule, MatProgressBarModule, MatToolbarModule } from '@angular/material';
import { FuseSearchBarModule, FuseShortcutsModule } from '@fuse/components';
import { FuseSharedModule } from '@fuse/shared.module';
import { FuseToolbarComponent } from 'app/layout/toolbar/toolbar.component';
import { FuseSearchBarModule, FuseShortcutsModule } from '@fuse/components';
import { ToolbarComponent } from 'app/layout/blocks/toolbar/toolbar.component';
@NgModule({
declarations: [
FuseToolbarComponent
ToolbarComponent
],
imports : [
RouterModule,
MatButtonModule,
MatIconModule,
MatMenuModule,
@ -25,9 +24,9 @@ import { FuseSearchBarModule, FuseShortcutsModule } from '@fuse/components';
FuseShortcutsModule
],
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";
fuse-vertical-nav-basic-layout {
vertical-nav-basic-layout {
display: flex;
flex-direction: column;
width: 100%;
@ -21,7 +21,7 @@ fuse-vertical-nav-basic-layout {
height: auto !important;
}
#fuse-main-content {
#main-content {
display: flex;
flex: 1;
flex-direction: column;
@ -39,7 +39,7 @@ fuse-vertical-nav-basic-layout {
flex: 1;
overflow: hidden;
fuse-content {
content {
position: relative;
display: flex;
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 { FuseAcademyCoursesComponent } from './courses/courses.component';
import { FuseAcademyCourseComponent } from './course/course.component';
import { AcademyCoursesService } from './courses.service';
import { AcademyCourseService } from './course.service';
import { AcademyCoursesComponent } from 'app/main/apps/academy/courses/courses.component';
import { AcademyCourseComponent } from 'app/main/apps/academy/course/course.component';
import { AcademyCoursesService } from 'app/main/apps/academy/courses.service';
import { AcademyCourseService } from 'app/main/apps/academy/course.service';
const routes = [
{
path : 'courses',
component: FuseAcademyCoursesComponent,
component: AcademyCoursesComponent,
resolve : {
academy: AcademyCoursesService
}
},
{
path : 'courses/:courseId/:courseSlug',
component: FuseAcademyCourseComponent,
component: AcademyCourseComponent,
resolve : {
academy: AcademyCourseService
}
@ -33,8 +34,8 @@ const routes = [
@NgModule({
declarations: [
FuseAcademyCoursesComponent,
FuseAcademyCourseComponent
AcademyCoursesComponent,
AcademyCourseComponent
],
imports : [
RouterModule.forChild(routes),
@ -53,6 +54,6 @@ const routes = [
AcademyCourseService
]
})
export class FuseAcademyModule
export class AcademyModule
{
}

View File

@ -8,12 +8,23 @@ export class AcademyCourseService implements Resolve<any>
{
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 {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>
{
return new Promise((resolve, reject) => {
this.http.get('api/academy-course/' + courseId + '/' + courseSlug)
this._httpClient.get('api/academy-course/' + courseId + '/' + courseSlug)
.subscribe((response: any) => {
this.onCourseChanged.next(response);
resolve(response);

View File

@ -1,71 +1,114 @@
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 { fuseAnimations } from '@fuse/animations';
import { AcademyCourseService } from '../course.service';
import { AcademyCourseService } from 'app/main/apps/academy/course.service';
@Component({
selector : 'fuse-academy-course',
selector : 'academy-course',
templateUrl : './course.component.html',
styleUrls : ['./course.component.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class FuseAcademyCourseComponent implements OnInit, OnDestroy, AfterViewInit
export class AcademyCourseComponent implements OnInit, OnDestroy, AfterViewInit
{
animationDirection: 'left' | 'right' | 'none';
course: any;
courseSubscription: Subscription;
currentStep = 0;
courseStepContent;
animationDirection: 'left' | 'right' | 'none' = 'none';
@ViewChildren(FusePerfectScrollbarDirective) fuseScrollbarDirectives: QueryList<FusePerfectScrollbarDirective>;
courseStepContent: any;
currentStep: number;
@ViewChildren(FusePerfectScrollbarDirective)
fuseScrollbarDirectives: QueryList<FusePerfectScrollbarDirective>;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {AcademyCourseService} _academyCourseService
* @param {ChangeDetectorRef} _changeDetectorRef
*/
constructor(
private courseService: AcademyCourseService,
private changeDetectorRef: ChangeDetectorRef
private _academyCourseService: AcademyCourseService,
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
this.courseSubscription =
this.courseService.onCourseChanged
this._academyCourseService.onCourseChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(course => {
this.course = course;
});
}
ngAfterViewInit()
/**
* After view init
*/
ngAfterViewInit(): void
{
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
this.animationDirection = this.currentStep < step ? 'left' : 'right';
// Run change detection so the change
// in the animation direction registered
this.changeDetectorRef.detectChanges();
this._changeDetectorRef.detectChanges();
// Set the current step
this.currentStep = step;
}
gotoNextStep()
/**
* Go to next step
*/
gotoNextStep(): void
{
if ( this.currentStep === this.course.totalSteps - 1 )
{
@ -77,13 +120,16 @@ export class FuseAcademyCourseComponent implements OnInit, OnDestroy, AfterViewI
// Run change detection so the change
// in the animation direction registered
this.changeDetectorRef.detectChanges();
this._changeDetectorRef.detectChanges();
// Increase the current step
this.currentStep++;
}
gotoPreviousStep()
/**
* Go to previous step
*/
gotoPreviousStep(): void
{
if ( this.currentStep === 0 )
{
@ -95,7 +141,7 @@ export class FuseAcademyCourseComponent implements OnInit, OnDestroy, AfterViewI
// Run change detection so the change
// in the animation direction registered
this.changeDetectorRef.detectChanges();
this._changeDetectorRef.detectChanges();
// Decrease the current step
this.currentStep--;

View File

@ -9,12 +9,23 @@ export class AcademyCoursesService implements Resolve<any>
onCategoriesChanged: 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 {RouterStateSnapshot} state
@ -36,10 +47,15 @@ export class AcademyCoursesService implements Resolve<any>
});
}
/**
* Get categories
*
* @returns {Promise<any>}
*/
getCategories(): Promise<any>
{
return new Promise((resolve, reject) => {
this.http.get('api/academy-categories')
this._httpClient.get('api/academy-categories')
.subscribe((response: any) => {
this.onCategoriesChanged.next(response);
resolve(response);
@ -47,10 +63,15 @@ export class AcademyCoursesService implements Resolve<any>
});
}
/**
* Get courses
*
* @returns {Promise<any>}
*/
getCourses(): Promise<any>
{
return new Promise((resolve, reject) => {
this.http.get('api/academy-courses')
this._httpClient.get('api/academy-courses')
.subscribe((response: any) => {
this.onCoursesChanged.next(response);
resolve(response);

View File

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

View File

@ -1,18 +1,16 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FuseAngularMaterialModule } from '../components/angular-material/angular-material.module';
import { FuseSharedModule } from '@fuse/shared.module';
const routes = [
{
path : 'dashboards/analytics',
loadChildren: './dashboards/analytics/analytics.module#FuseAnalyticsDashboardModule'
loadChildren: './dashboards/analytics/analytics.module#AnalyticsDashboardModule'
},
{
path : 'dashboards/project',
loadChildren: './dashboards/project/project.module#FuseProjectDashboardModule'
loadChildren: './dashboards/project/project.module#ProjectDashboardModule'
},
{
path : 'mail',
@ -24,19 +22,19 @@ const routes = [
},
{
path : 'chat',
loadChildren: './chat/chat.module#FuseChatModule'
loadChildren: './chat/chat.module#ChatModule'
},
{
path : 'calendar',
loadChildren: './calendar/calendar.module#FuseCalendarModule'
loadChildren: './calendar/calendar.module#CalendarModule'
},
{
path : 'e-commerce',
loadChildren: './e-commerce/e-commerce.module#FuseEcommerceModule'
loadChildren: './e-commerce/e-commerce.module#EcommerceModule'
},
{
path : 'academy',
loadChildren: './academy/academy.module#FuseAcademyModule'
loadChildren: './academy/academy.module#AcademyModule'
},
{
path : 'todo',
@ -44,11 +42,11 @@ const routes = [
},
{
path : 'file-manager',
loadChildren: './file-manager/file-manager.module#FuseFileManagerModule'
loadChildren: './file-manager/file-manager.module#FileManagerModule'
},
{
path : 'contacts',
loadChildren: './contacts/contacts.module#FuseContactsModule'
loadChildren: './contacts/contacts.module#ContactsModule'
},
{
path : 'scrumboard',
@ -58,12 +56,10 @@ const routes = [
@NgModule({
imports : [
FuseSharedModule,
RouterModule.forChild(routes),
FuseAngularMaterialModule
],
declarations: []
FuseSharedModule
]
})
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 { fuseAnimations } from '@fuse/animations';
import { FuseCalendarEventFormDialogComponent } from './event-form/event-form.component';
import { CalendarEventModel } from './event.model';
import { CalendarService } from './calendar.service';
import { CalendarService } from 'app/main/apps/calendar/calendar.service';
import { CalendarEventModel } from 'app/main/apps/calendar/event.model';
import { CalendarEventFormDialogComponent } from 'app/main/apps/calendar/event-form/event-form.component';
@Component({
selector : 'fuse-calendar',
selector : 'calendar',
templateUrl : './calendar.component.html',
styleUrls : ['./calendar.component.scss'],
encapsulation: ViewEncapsulation.None,
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;
viewDate: Date;
events: CalendarEvent[];
public actions: CalendarEventAction[];
activeDayIsOpen: boolean;
refresh: Subject<any> = new Subject();
dialogRef: any;
confirmDialogRef: MatDialogRef<FuseConfirmDialogComponent>;
selectedDay: any;
constructor(
public dialog: MatDialog,
public calendarService: CalendarService
private _matDialog: MatDialog,
private _calendarService: CalendarService
)
{
// Set the defaults
this.view = 'month';
this.viewDate = new Date();
this.activeDayIsOpen = true;
@ -62,29 +63,41 @@ export class FuseCalendarComponent implements OnInit
this.setEvents();
}
ngOnInit()
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
/**
* Watch re-render-refresh for updating db
*/
this.refresh.subscribe(updateDB => {
// console.warn('REFRESH');
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.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;
return new CalendarEventModel(item);
});
@ -92,10 +105,11 @@ export class FuseCalendarComponent implements OnInit
/**
* Before View Renderer
*
* @param {any} header
* @param {any} body
*/
beforeMonthViewRender({header, body})
beforeMonthViewRender({header, body}): void
{
// console.info('beforeMonthViewRender');
/**
@ -118,6 +132,7 @@ export class FuseCalendarComponent implements OnInit
/**
* Day clicked
*
* @param {MonthViewDay} day
*/
dayClicked(day: CalendarMonthViewDay): void
@ -144,6 +159,7 @@ export class FuseCalendarComponent implements OnInit
/**
* Event times changed
* Event dropped or resized
*
* @param {CalendarEvent} event
* @param {Date} newStart
* @param {Date} newEnd
@ -158,11 +174,12 @@ export class FuseCalendarComponent implements OnInit
/**
* Delete Event
*
* @param event
*/
deleteEvent(event)
deleteEvent(event): void
{
this.confirmDialogRef = this.dialog.open(FuseConfirmDialogComponent, {
this.confirmDialogRef = this._matDialog.open(FuseConfirmDialogComponent, {
disableClose: false
});
@ -182,14 +199,15 @@ export class FuseCalendarComponent implements OnInit
/**
* Edit Event
*
* @param {string} action
* @param {CalendarEvent} event
*/
editEvent(action: string, event: CalendarEvent)
editEvent(action: string, event: CalendarEvent): void
{
const eventIndex = this.events.indexOf(event);
this.dialogRef = this.dialog.open(FuseCalendarEventFormDialogComponent, {
this.dialogRef = this._matDialog.open(CalendarEventFormDialogComponent, {
panelClass: 'event-form-dialog',
data : {
event : event,
@ -233,7 +251,7 @@ export class FuseCalendarComponent implements OnInit
*/
addEvent(): void
{
this.dialogRef = this.dialog.open(FuseCalendarEventFormDialogComponent, {
this.dialogRef = this._matDialog.open(CalendarEventFormDialogComponent, {
panelClass: 'event-form-dialog',
data : {
action: 'new',

View File

@ -1,22 +1,20 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MatButtonModule, MatDatepickerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatSlideToggleModule, MatToolbarModule } from '@angular/material';
import { CalendarModule } from 'angular-calendar';
import { ColorPickerModule } from 'ngx-color-picker';
import { CalendarModule as AngularCalendarModule } from 'angular-calendar';
import { FuseSharedModule } from '@fuse/shared.module';
import { FuseConfirmDialogModule } from '@fuse/components';
import { CalendarService } from './calendar.service';
import { FuseCalendarComponent } from './calendar.component';
import { FuseCalendarEventFormDialogComponent } from './event-form/event-form.component';
import { CalendarComponent } from 'app/main/apps/calendar/calendar.component';
import { CalendarService } from 'app/main/apps/calendar/calendar.service';
import { CalendarEventFormDialogComponent } from 'app/main/apps/calendar/event-form/event-form.component';
const routes: Routes = [
{
path : '**',
component: FuseCalendarComponent,
component: CalendarComponent,
children : [],
resolve : {
chat: CalendarService
@ -26,8 +24,8 @@ const routes: Routes = [
@NgModule({
declarations : [
FuseCalendarComponent,
FuseCalendarEventFormDialogComponent
CalendarComponent,
CalendarEventFormDialogComponent
],
imports : [
RouterModule.forChild(routes),
@ -40,7 +38,7 @@ const routes: Routes = [
MatSlideToggleModule,
MatToolbarModule,
CalendarModule.forRoot(),
AngularCalendarModule.forRoot(),
ColorPickerModule,
FuseSharedModule,
@ -49,8 +47,10 @@ const routes: Routes = [
providers : [
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;
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
{
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) => {
this.http.get('api/calendar/events')
this._httpClient.get('api/calendar/events')
.subscribe((response: any) => {
this.events = response.data;
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) => {
this.http.post('api/calendar/events', {
this._httpClient.post('api/calendar/events', {
id : 'events',
data: [...events]
})

View File

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

View File

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

View File

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

View File

@ -87,7 +87,7 @@
<!-- / CHAT CONTENT -->
<!-- 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 -->
<form #replyForm="ngForm"
@ -97,18 +97,20 @@
fxLayout="row"
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"
ngModel name="message"></textarea>
</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>
</button>
</form>
<!-- / REPLY FORM -->
</div>
<!-- / CHAT FOOTER-->
</div>
<!-- / CHAT -->

View File

@ -99,7 +99,7 @@
}
.chat-footer {
min-height: 64px;
min-height: 72px;
max-height: 96px;
background-color: #F3F4F5;
color: rgba(0, 0, 0, 0.87);
@ -116,6 +116,7 @@
overflow: auto;
max-height: 80px;
transition: height 200ms ease;
&.grow {
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 { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
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({
selector : 'fuse-chat-view',
selector : 'chat-view',
templateUrl: './chat-view.component.html',
styleUrls : ['./chat-view.component.scss']
})
export class FuseChatViewComponent implements OnInit, AfterViewInit
export class ChatViewComponent implements OnInit, OnDestroy, AfterViewInit
{
user: any;
chat: any;
@ -18,18 +20,44 @@ export class FuseChatViewComponent implements OnInit, AfterViewInit
contact: any;
replyInput: 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.chatService.onChatSelected
this.user = this._chatService.user;
this._chatService.onChatSelected
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(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.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(() => {
this.replyForm.reset();
@ -62,14 +113,22 @@ export class FuseChatViewComponent implements OnInit, AfterViewInit
}
focusReplyInput()
/**
* Focus to the reply input
*/
focusReplyInput(): void
{
setTimeout(() => {
this.replyInput.focus();
});
}
scrollToBottom(speed?: number)
/**
* Scroll to the bottom
*
* @param {number} speed
*/
scrollToBottom(speed?: number): void
{
speed = speed || 400;
if ( this.directiveScroll )
@ -82,7 +141,10 @@ export class FuseChatViewComponent implements OnInit, AfterViewInit
}
}
reply(event)
/**
* Reply
*/
reply(): void
{
// Message
const message = {
@ -95,9 +157,8 @@ export class FuseChatViewComponent implements OnInit, AfterViewInit
this.dialog.push(message);
// 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();
});
}
}

View File

@ -15,20 +15,20 @@
<!-- LEFT SIDENAV -->
<mat-sidenav class="sidenav" position="start" opened="true" mode="side"
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>
<!-- / LEFT SIDENAV -->
<!-- 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 -->
<!-- RIGHT SIDENAV -->
<mat-sidenav class="sidenav" position="end" opened="false" mode="over"
fuseMatSidenavHelper="chat-right-sidenav">
<fuse-chat-right-sidenav></fuse-chat-right-sidenav>
<chat-right-sidenav></chat-right-sidenav>
</mat-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 { ChatService } from './chat.service';
import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({
selector : 'fuse-chat',
selector : 'chat',
templateUrl : './chat.component.html',
styleUrls : ['./chat.component.scss'],
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations
})
export class FuseChatComponent implements OnInit
export class ChatComponent implements OnInit, OnDestroy
{
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 => {
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 { ChatService } from './chat.service';
import { FuseChatComponent } from './chat.component';
import { FuseChatViewComponent } from './chat-view/chat-view.component';
import { FuseChatStartComponent } from './chat-start/chat-start.component';
import { FuseChatChatsSidenavComponent } from './sidenavs/left/chats/chats.component';
import { FuseChatUserSidenavComponent } from './sidenavs/left/user/user.component';
import { FuseChatLeftSidenavComponent } from './sidenavs/left/left.component';
import { FuseChatRightSidenavComponent } from './sidenavs/right/right.component';
import { FuseChatContactSidenavComponent } from './sidenavs/right/contact/contact.component';
import { ChatService } from 'app/main/apps/chat/chat.service';
import { ChatComponent } from 'app/main/apps/chat/chat.component';
import { ChatStartComponent } from 'app/main/apps/chat/chat-start/chat-start.component';
import { ChatViewComponent } from 'app/main/apps/chat/chat-view/chat-view.component';
import { ChatChatsSidenavComponent } from 'app/main/apps/chat/sidenavs/left/chats/chats.component';
import { ChatUserSidenavComponent } from 'app/main/apps/chat/sidenavs/left/user/user.component';
import { ChatLeftSidenavComponent } from 'app/main/apps/chat/sidenavs/left/left.component';
import { ChatRightSidenavComponent } from 'app/main/apps/chat/sidenavs/right/right.component';
import { ChatContactSidenavComponent } from 'app/main/apps/chat/sidenavs/right/contact/contact.component';
const routes: Routes = [
{
path : '**',
component: FuseChatComponent,
component: ChatComponent,
children : [],
resolve : {
chat: ChatService
@ -28,14 +28,14 @@ const routes: Routes = [
@NgModule({
declarations: [
FuseChatComponent,
FuseChatViewComponent,
FuseChatStartComponent,
FuseChatChatsSidenavComponent,
FuseChatUserSidenavComponent,
FuseChatLeftSidenavComponent,
FuseChatRightSidenavComponent,
FuseChatContactSidenavComponent
ChatComponent,
ChatViewComponent,
ChatStartComponent,
ChatChatsSidenavComponent,
ChatUserSidenavComponent,
ChatLeftSidenavComponent,
ChatRightSidenavComponent,
ChatContactSidenavComponent
],
imports : [
RouterModule.forChild(routes),
@ -57,6 +57,6 @@ const routes: Routes = [
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 { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { fuseAnimations } from '@fuse/animations';
import { FuseMatSidenavHelperService } from '@fuse/directives/fuse-mat-sidenav/fuse-mat-sidenav.service';
import { ChatService } from '../../../chat.service';
import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({
selector : 'fuse-chat-chats-sidenav',
selector : 'chat-chats-sidenav',
templateUrl: './chats.component.html',
styleUrls : ['./chats.component.scss'],
animations : fuseAnimations
})
export class FuseChatChatsSidenavComponent implements OnInit
export class ChatChatsSidenavComponent implements OnInit, OnDestroy
{
user: any;
chats: any[];
contacts: 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(
private chatService: ChatService,
private fuseMatSidenavService: FuseMatSidenavHelperService,
public media: ObservableMedia
private _chatService: ChatService,
private _fuseMatSidenavHelperService: FuseMatSidenavHelperService,
public _observableMedia: ObservableMedia
)
{
// Set the defaults
this.chatSearch = {
name: ''
};
this.searchText = '';
// Set the private defaults
this._unsubscribeAll = new Subject();
}
ngOnInit()
{
this.user = this.chatService.user;
this.chats = this.chatService.chats;
this.contacts = this.chatService.contacts;
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
this.chatService.onChatsUpdated.subscribe(updatedChats => {
/**
* On init
*/
ngOnInit(): void
{
this.user = this._chatService.user;
this.chats = this._chatService.chats;
this.contacts = this._chatService.contacts;
this._chatService.onChatsUpdated
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(updatedChats => {
this.chats = updatedChats;
});
this.chatService.onUserUpdated.subscribe(updatedUser => {
this._chatService.onUserUpdated
.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.fuseMatSidenavService.getSidenav('chat-left-sidenav').toggle();
this._chatService.getChat(contact);
if ( !this._observableMedia.isActive('gt-md') )
{
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');
}

View File

@ -1,11 +1,11 @@
<div [ngSwitch]="view" class="views">
<fuse-chat-chats-sidenav class="view"
<chat-chats-sidenav class="view"
*ngSwitchCase="'chats'"
[@slideInRight]>
</fuse-chat-chats-sidenav>
</chat-chats-sidenav>
<fuse-chat-user-sidenav class="view"
<chat-user-sidenav class="view"
*ngSwitchCase="'user'"
[@slideInLeft]>
</fuse-chat-user-sidenav>
</chat-user-sidenav>
</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 { ChatService } from '../../chat.service';
import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({
selector : 'fuse-chat-left-sidenav',
selector : 'chat-left-sidenav',
templateUrl: './left.component.html',
styleUrls : ['./left.component.scss'],
animations : fuseAnimations
})
export class FuseChatLeftSidenavComponent implements OnInit
export class ChatLeftSidenavComponent implements OnInit, OnDestroy
{
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';
// Set the private defaults
this._unsubscribeAll = new Subject();
}
ngOnInit()
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.chatService.onLeftSidenavViewChanged.subscribe(view => {
this._chatService.onLeftSidenavViewChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(view => {
this.view = view;
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -1,48 +1,87 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
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({
selector : 'fuse-chat-user-sidenav',
selector : 'chat-user-sidenav',
templateUrl: './user.component.html',
styleUrls : ['./user.component.scss']
})
export class FuseChatUserSidenavComponent implements OnInit, OnDestroy
export class ChatUserSidenavComponent implements OnInit, OnDestroy
{
user: any;
onFormChange: any;
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({
mood : new FormControl(this.user.mood),
status: new FormControl(this.user.status)
});
}
ngOnInit()
{
this.onFormChange = this.userForm.valueChanges.pipe(
this.userForm.valueChanges
.pipe(
takeUntil(this._unsubscribeAll),
debounceTime(500),
distinctUntilChanged()
).subscribe(data => {
)
.subscribe(data => {
this.user.mood = data.mood;
this.user.status = data.status;
this.chatService.updateUserData(this.user);
this._chatService.updateUserData(this.user);
});
}
changeLeftSidenavView(view)
/**
* On destroy
*/
ngOnDestroy(): void
{
this.chatService.onLeftSidenavViewChanged.next(view);
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
ngOnDestroy()
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Change left sidenav view
*
* @param view
*/
changeLeftSidenavView(view): void
{
this.onFormChange.unsubscribe();
this._chatService.onLeftSidenavViewChanged.next(view);
}
}

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({
selector : 'fuse-chat-contact-sidenav',
selector : 'chat-contact-sidenav',
templateUrl: './contact.component.html',
styleUrls : ['./contact.component.scss']
})
export class FuseChatContactSidenavComponent implements OnInit
export class ChatContactSidenavComponent implements OnInit, OnDestroy
{
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;
});
}
/**
* 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">
<fuse-chat-contact-sidenav class="view"
<chat-contact-sidenav class="view"
*ngSwitchCase="'contact'"
[@slideInRight]>
</fuse-chat-contact-sidenav>
</chat-contact-sidenav>
</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 { ChatService } from '../../chat.service';
import { ChatService } from 'app/main/apps/chat/chat.service';
@Component({
selector : 'fuse-chat-right-sidenav',
selector : 'chat-right-sidenav',
templateUrl: './right.component.html',
styleUrls : ['./right.component.scss'],
animations : fuseAnimations
})
export class FuseChatRightSidenavComponent implements OnInit
export class ChatRightSidenavComponent implements OnInit, OnDestroy
{
view: string;
constructor(private chatService: ChatService)
// Private
private _unsubscribeAll: Subject<any>;
constructor(
private _chatService: ChatService
)
{
// Set the defaults
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
.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 { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { CalendarEvent } from 'angular-calendar';
import { Contact } from '../contact.model';
import { Contact } from 'app/main/apps/contacts/contact.model';
@Component({
selector : 'fuse-contacts-contact-form-dialog',
selector : 'contacts-contact-form-dialog',
templateUrl : './contact-form.component.html',
styleUrls : ['./contact-form.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FuseContactsContactFormDialogComponent
export class ContactsContactFormDialogComponent
{
event: CalendarEvent;
dialogTitle: string;
contactForm: FormGroup;
action: string;
contact: Contact;
contactForm: FormGroup;
dialogTitle: string;
/**
* Constructor
*
* @param {MatDialogRef<ContactsContactFormDialogComponent>} _dialogRef
* @param _data
* @param {FormBuilder} _formBuilder
*/
constructor(
public dialogRef: MatDialogRef<FuseContactsContactFormDialogComponent>,
@Inject(MAT_DIALOG_DATA) private data: any,
private formBuilder: FormBuilder
private _dialogRef: MatDialogRef<ContactsContactFormDialogComponent>,
@Inject(MAT_DIALOG_DATA) private _data: any,
private _formBuilder: FormBuilder
)
{
this.action = data.action;
this.action = _data.action;
if ( this.action === 'edit' )
{
this.dialogTitle = 'Edit Contact';
this.contact = data.contact;
this.contact = _data.contact;
}
else
{
@ -43,9 +47,18 @@ export class FuseContactsContactFormDialogComponent
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],
name : [this.contact.name],
lastName: [this.contact.lastName],

View File

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

View File

@ -2,24 +2,26 @@ import { Component, OnDestroy, OnInit, TemplateRef, ViewChild, ViewEncapsulation
import { FormGroup } from '@angular/forms';
import { MatDialog, MatDialogRef } from '@angular/material';
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 { FuseConfirmDialogComponent } from '@fuse/components/confirm-dialog/confirm-dialog.component';
import { FuseContactsContactFormDialogComponent } from '../contact-form/contact-form.component';
import { ContactsService } from '../contacts.service';
import { ContactsService } from 'app/main/apps/contacts/contacts.service';
import { ContactsContactFormDialogComponent } from 'app/main/apps/contacts/contact-form/contact-form.component';
@Component({
selector : 'fuse-contacts-contact-list',
selector : 'contacts-contact-list',
templateUrl : './contact-list.component.html',
styleUrls : ['./contact-list.component.scss'],
encapsulation: ViewEncapsulation.None,
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;
user: any;
@ -27,24 +29,41 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
displayedColumns = ['checkbox', 'avatar', 'name', 'email', 'phone', 'jobTitle', 'buttons'];
selectedContacts: any[];
checkboxes: {};
onContactsChangedSubscription: Subscription;
onFilterChangedSubscription: Subscription;
onSelectedContactsChangedSubscription: Subscription;
onUserDataChangedSubscription: Subscription;
dialogRef: any;
confirmDialogRef: MatDialogRef<FuseConfirmDialogComponent>;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ContactsService} _contactsService
* @param {MatDialog} _matDialog
*/
constructor(
private contactsService: ContactsService,
public dialog: MatDialog
private _contactsService: ContactsService,
public _matDialog: MatDialog
)
{
this.onContactsChangedSubscription =
this.contactsService.onContactsChanged.subscribe(contacts => {
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
this.dataSource = new FilesDataSource(this._contactsService);
this._contactsService.onContactsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(contacts => {
this.contacts = contacts;
this.checkboxes = {};
@ -53,8 +72,9 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
});
});
this.onSelectedContactsChangedSubscription =
this.contactsService.onSelectedContactsChanged.subscribe(selectedContacts => {
this._contactsService.onSelectedContactsChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(selectedContacts => {
for ( const id in this.checkboxes )
{
if ( !this.checkboxes.hasOwnProperty(id) )
@ -67,33 +87,41 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
this.selectedContacts = selectedContacts;
});
this.onUserDataChangedSubscription =
this.contactsService.onUserDataChanged.subscribe(user => {
this._contactsService.onUserDataChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(user => {
this.user = user;
});
this.onFilterChangedSubscription =
this.contactsService.onFilterChanged.subscribe(() => {
this.contactsService.deselectContacts();
this._contactsService.onFilterChanged
.pipe(takeUntil(this._unsubscribeAll))
.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()
{
this.onContactsChangedSubscription.unsubscribe();
this.onFilterChangedSubscription.unsubscribe();
this.onSelectedContactsChangedSubscription.unsubscribe();
this.onUserDataChangedSubscription.unsubscribe();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
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',
data : {
contact: contact,
@ -116,7 +144,7 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
*/
case 'save':
this.contactsService.updateContact(formData.getRawValue());
this._contactsService.updateContact(formData.getRawValue());
break;
/**
@ -134,9 +162,9 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
/**
* Delete Contact
*/
deleteContact(contact)
deleteContact(contact): void
{
this.confirmDialogRef = this.dialog.open(FuseConfirmDialogComponent, {
this.confirmDialogRef = this._matDialog.open(FuseConfirmDialogComponent, {
disableClose: false
});
@ -145,19 +173,29 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
this.confirmDialogRef.afterClosed().subscribe(result => {
if ( result )
{
this.contactsService.deleteContact(contact);
this._contactsService.deleteContact(contact);
}
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) )
{
@ -168,24 +206,37 @@ export class FuseContactsContactListComponent implements OnInit, OnDestroy
this.user.starred.push(contactId);
}
this.contactsService.updateUserData(this.user);
this._contactsService.updateUserData(this.user);
}
}
export class FilesDataSource extends DataSource<any>
{
constructor(private contactsService: ContactsService)
/**
* Constructor
*
* @param {ContactsService} _contactsService
*/
constructor(
private _contactsService: ContactsService
)
{
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[]>
{
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