Second pass through for standalone components.

This commit is contained in:
Sercan Yemen 2023-05-15 14:36:38 +03:00
parent b2cb20634e
commit 5d42763f1b
224 changed files with 24369 additions and 27001 deletions

46712
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,66 +1,66 @@
{
"name": "fuse-angular",
"version": "18.0.0",
"description": "Fuse - Angular Admin Template and Starter Project",
"author": "https://themeforest.net/user/srcn",
"license": "https://themeforest.net/licenses/standard",
"private": true,
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"dependencies": {
"@angular/animations": "15.2.9",
"@angular/cdk": "15.2.9",
"@angular/common": "15.2.9",
"@angular/compiler": "15.2.9",
"@angular/core": "15.2.9",
"@angular/forms": "15.2.9",
"@angular/material": "15.2.9",
"@angular/material-luxon-adapter": "15.2.9",
"@angular/platform-browser": "15.2.9",
"@angular/platform-browser-dynamic": "15.2.9",
"@angular/router": "15.2.9",
"@ngneat/transloco": "4.2.6",
"apexcharts": "3.40.0",
"crypto-js": "3.3.0",
"highlight.js": "11.8.0",
"lodash-es": "4.17.21",
"luxon": "3.3.0",
"ng-apexcharts": "1.7.6",
"ngx-quill": "21.0.0",
"perfect-scrollbar": "1.5.5",
"quill": "1.3.7",
"rxjs": "7.8.1",
"tslib": "2.5.0",
"zone.js": "0.13.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "15.2.8",
"@angular/cli": "15.2.8",
"@angular/compiler-cli": "15.2.9",
"@tailwindcss/typography": "0.5.9",
"@types/chroma-js": "2.4.0",
"@types/crypto-js": "3.1.47",
"@types/highlight.js": "10.1.0",
"@types/jasmine": "4.3.1",
"@types/lodash": "4.14.194",
"@types/lodash-es": "4.17.7",
"@types/luxon": "3.3.0",
"autoprefixer": "10.4.14",
"chroma-js": "2.4.2",
"jasmine-core": "4.6.0",
"karma": "6.4.2",
"karma-chrome-launcher": "3.2.0",
"karma-coverage": "2.2.0",
"karma-jasmine": "5.1.0",
"karma-jasmine-html-reporter": "2.0.0",
"lodash": "4.17.21",
"postcss": "8.4.23",
"tailwindcss": "3.3.2",
"typescript": "4.9.5"
}
}
"name": "fuse-angular",
"version": "18.0.0",
"description": "Fuse - Angular Admin Template and Starter Project",
"author": "https://themeforest.net/user/srcn",
"license": "https://themeforest.net/licenses/standard",
"private": true,
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"dependencies": {
"@angular/animations": "16.0.0",
"@angular/cdk": "16.0.0",
"@angular/common": "16.0.0",
"@angular/compiler": "16.0.0",
"@angular/core": "16.0.0",
"@angular/forms": "16.0.0",
"@angular/material": "16.0.0",
"@angular/material-luxon-adapter": "16.0.0",
"@angular/platform-browser": "16.0.0",
"@angular/platform-browser-dynamic": "16.0.0",
"@angular/router": "16.0.0",
"@ngneat/transloco": "4.2.6",
"apexcharts": "3.40.0",
"crypto-js": "3.3.0",
"highlight.js": "11.8.0",
"lodash-es": "4.17.21",
"luxon": "3.3.0",
"ng-apexcharts": "1.7.6",
"ngx-quill": "21.0.0",
"perfect-scrollbar": "1.5.5",
"quill": "1.3.7",
"rxjs": "7.8.1",
"tslib": "2.5.0",
"zone.js": "0.13.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "16.0.0",
"@angular/cli": "16.0.0",
"@angular/compiler-cli": "16.0.0",
"@tailwindcss/typography": "0.5.9",
"@types/chroma-js": "2.4.0",
"@types/crypto-js": "3.1.47",
"@types/highlight.js": "10.1.0",
"@types/jasmine": "4.3.1",
"@types/lodash": "4.14.194",
"@types/lodash-es": "4.17.7",
"@types/luxon": "3.3.0",
"autoprefixer": "10.4.14",
"chroma-js": "2.4.2",
"jasmine-core": "4.6.0",
"karma": "6.4.2",
"karma-chrome-launcher": "3.2.0",
"karma-coverage": "2.2.0",
"karma-jasmine": "5.1.0",
"karma-jasmine-html-reporter": "2.0.0",
"lodash": "4.17.21",
"postcss": "8.4.23",
"tailwindcss": "3.3.2",
"typescript": "4.9.5"
}
}

View File

@ -128,7 +128,6 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
)
.subscribe(() =>
{
// Dismiss the alert
this.dismiss();
});
@ -141,7 +140,6 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
)
.subscribe(() =>
{
// Show the alert
this.show();
});

View File

@ -381,7 +381,6 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
// Once the animation is done...
this._player.onDone(() =>
{
// If the overlay still exists...
if ( this._overlay )
{

View File

@ -63,7 +63,6 @@ export class FuseHighlightService
lines.filter(line => line.length)
.forEach((line, index) =>
{
// Always get the indentation of the first line so we can
// have something to compare with
if ( index === 0 )

View File

@ -70,7 +70,6 @@ export class FuseHorizontalNavigationBasicItemComponent implements OnInit, OnDes
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Mark for check
this._changeDetectorRef.markForCheck();
});

View File

@ -59,7 +59,6 @@ export class FuseHorizontalNavigationBranchItemComponent implements OnInit, OnDe
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Mark for check
this._changeDetectorRef.markForCheck();
});

View File

@ -47,7 +47,6 @@ export class FuseHorizontalNavigationDividerItemComponent implements OnInit, OnD
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Mark for check
this._changeDetectorRef.markForCheck();
});

View File

@ -47,7 +47,6 @@ export class FuseHorizontalNavigationSpacerItemComponent implements OnInit, OnDe
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Mark for check
this._changeDetectorRef.markForCheck();
});

View File

@ -84,7 +84,6 @@ export class FuseVerticalNavigationAsideItemComponent implements OnChanges, OnIn
)
.subscribe((event: NavigationEnd) =>
{
// Mark if active
this._markIfActive(event.urlAfterRedirects);
});
@ -97,7 +96,6 @@ export class FuseVerticalNavigationAsideItemComponent implements OnChanges, OnIn
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Mark for check
this._changeDetectorRef.markForCheck();
});

View File

@ -69,7 +69,6 @@ export class FuseVerticalNavigationBasicItemComponent implements OnInit, OnDestr
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Mark for check
this._changeDetectorRef.markForCheck();
});

View File

@ -97,7 +97,6 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((collapsedItem) =>
{
// Check if the collapsed item is null
if ( collapsedItem === null )
{
@ -118,7 +117,6 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((expandedItem) =>
{
// Check if the expanded item is null
if ( expandedItem === null )
{
@ -156,7 +154,6 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
)
.subscribe((event: NavigationEnd) =>
{
// If the item has a children that has a matching url with the current url, expand...
if ( this._hasActiveChild(this.item, event.urlAfterRedirects) )
{
@ -178,7 +175,6 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Mark for check
this._changeDetectorRef.markForCheck();
});

View File

@ -47,7 +47,6 @@ export class FuseVerticalNavigationDividerItemComponent implements OnInit, OnDes
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Mark for check
this._changeDetectorRef.markForCheck();
});

View File

@ -58,7 +58,6 @@ export class FuseVerticalNavigationGroupItemComponent implements OnInit, OnDestr
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Mark for check
this._changeDetectorRef.markForCheck();
});

View File

@ -47,7 +47,6 @@ export class FuseVerticalNavigationSpacerItemComponent implements OnInit, OnDest
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Mark for check
this._changeDetectorRef.markForCheck();
});

View File

@ -160,7 +160,6 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
)
.subscribe(() =>
{
// Loop through the scrollbars and update them
fuseScrollbarDirectives.forEach((fuseScrollbarDirective) =>
{
@ -325,7 +324,6 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
)
.subscribe(() =>
{
// If the mode is 'over' and the navigation is opened...
if ( this.mode === 'over' && this.opened )
{
@ -379,7 +377,6 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
setTimeout(() =>
{
// Return if 'navigation content' element does not exist
if ( !this._navigationContentEl )
{
@ -405,7 +402,6 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
// Go through all the scrollbar directives
this._fuseScrollbarDirectives.forEach((fuseScrollbarDirective) =>
{
// Skip if not enabled
if ( !fuseScrollbarDirective.isEnabled() )
{
@ -675,7 +671,6 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
// Once the animation is done...
this._player.onDone(() =>
{
// If the overlay still exists...
if ( this._overlay )
{
@ -753,7 +748,6 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
// Once the animation is done...
this._player.onDone(() =>
{
// If the aside overlay still exists...
if ( this._asideOverlay )
{

View File

@ -36,7 +36,6 @@ export class FuseScrollResetDirective implements OnInit, OnDestroy
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Reset the element's scroll position to the top
this._elementRef.nativeElement.scrollTop = 0;
});

View File

@ -127,7 +127,6 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
)
.subscribe(() =>
{
// Update the PerfectScrollbar
this.update();
});

View File

@ -50,7 +50,6 @@ export class FuseMockApiInterceptor implements HttpInterceptor
delay(handler.delay ?? this._defaultDelay ?? 0),
switchMap((response) =>
{
// If there is no response data,
// throw an error response
if ( !response )

View File

@ -54,7 +54,6 @@ export class FuseMockApiService
// Iterate through the handlers
handlers.forEach((handler, handlerUrl) =>
{
// Skip if there is already a matching handler
if ( matchingHandler.handler )
{

View File

@ -22,7 +22,6 @@ export class FuseMediaWatcherService
switchMap(screens => this._breakpointObserver.observe(Object.values(screens)).pipe(
map((state) =>
{
// Prepare the observable values and set their defaults
const matchingAliases: string[] = [];
const matchingQueries: any = {};

File diff suppressed because one or more lines are too long

View File

@ -22,7 +22,6 @@ export class FuseValidators
{
return (formGroup: AbstractControl): ValidationErrors | null =>
{
// Get the control and matching control
const control = formGroup.get(controlPath);
const matchingControl = formGroup.get(matchingControlPath);

View File

@ -1,49 +1,25 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { inject } from '@angular/core';
import { NavigationService } from 'app/core/navigation/navigation.service';
import { MessagesService } from 'app/layout/common/messages/messages.service';
import { NotificationsService } from 'app/layout/common/notifications/notifications.service';
import { QuickChatService } from 'app/layout/common/quick-chat/quick-chat.service';
import { ShortcutsService } from 'app/layout/common/shortcuts/shortcuts.service';
import { forkJoin, Observable } from 'rxjs';
import { forkJoin } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class InitialDataResolver implements Resolve<any>
export const initialDataResolver = () =>
{
/**
* Constructor
*/
constructor(
private _messagesService: MessagesService,
private _navigationService: NavigationService,
private _notificationsService: NotificationsService,
private _quickChatService: QuickChatService,
private _shortcutsService: ShortcutsService,
)
{
}
const messagesService = inject(MessagesService);
const navigationService = inject(NavigationService);
const notificationsService = inject(NotificationsService);
const quickChatService = inject(QuickChatService);
const shortcutsService = inject(ShortcutsService);
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Use this resolver to resolve initial mock-api for the application
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any>
{
// Fork join multiple API endpoint calls to wait all of them to finish
return forkJoin([
this._navigationService.get(),
this._messagesService.getAll(),
this._notificationsService.getAll(),
this._quickChatService.getChats(),
this._shortcutsService.getAll(),
]);
}
}
// Fork join multiple API endpoint calls to wait all of them to finish
return forkJoin([
navigationService.get(),
messagesService.getAll(),
notificationsService.getAll(),
quickChatService.getChats(),
shortcutsService.getAll(),
]);
};

View File

@ -1,5 +1,5 @@
import { Route } from '@angular/router';
import { InitialDataResolver } from 'app/app.resolvers';
import { initialDataResolver } from 'app/app.resolvers';
import { AuthGuard } from 'app/core/auth/guards/auth.guard';
import { NoAuthGuard } from 'app/core/auth/guards/noAuth.guard';
import { LayoutComponent } from 'app/layout/layout.component';
@ -29,11 +29,11 @@ export const appRoutes: Route[] = [
layout: 'empty'
},
children: [
{path: 'confirmation-required', loadChildren: () => import('app/modules/auth/confirmation-required/confirmation-required.module').then(m => m.AuthConfirmationRequiredModule)},
{path: 'forgot-password', loadChildren: () => import('app/modules/auth/forgot-password/forgot-password.module').then(m => m.AuthForgotPasswordModule)},
{path: 'reset-password', loadChildren: () => import('app/modules/auth/reset-password/reset-password.module').then(m => m.AuthResetPasswordModule)},
{path: 'sign-in', loadChildren: () => import('app/modules/auth/sign-in/sign-in.module').then(m => m.AuthSignInModule)},
{path: 'sign-up', loadChildren: () => import('app/modules/auth/sign-up/sign-up.module').then(m => m.AuthSignUpModule)}
{path: 'confirmation-required', loadChildren: () => import('app/modules/auth/confirmation-required/confirmation-required.routes')},
{path: 'forgot-password', loadChildren: () => import('app/modules/auth/forgot-password/forgot-password.routes')},
{path: 'reset-password', loadChildren: () => import('app/modules/auth/reset-password/reset-password.routes')},
{path: 'sign-in', loadChildren: () => import('app/modules/auth/sign-in/sign-in.routes')},
{path: 'sign-up', loadChildren: () => import('app/modules/auth/sign-up/sign-up.routes')}
]
},
@ -47,8 +47,8 @@ export const appRoutes: Route[] = [
layout: 'empty'
},
children: [
{path: 'sign-out', loadChildren: () => import('app/modules/auth/sign-out/sign-out.module').then(m => m.AuthSignOutModule)},
{path: 'unlock-session', loadChildren: () => import('app/modules/auth/unlock-session/unlock-session.module').then(m => m.AuthUnlockSessionModule)}
{path: 'sign-out', loadChildren: () => import('app/modules/auth/sign-out/sign-out.routes')},
{path: 'unlock-session', loadChildren: () => import('app/modules/auth/unlock-session/unlock-session.routes')}
]
},
@ -60,7 +60,7 @@ export const appRoutes: Route[] = [
layout: 'empty'
},
children: [
{path: 'home', loadChildren: () => import('app/modules/landing/home/home.module').then(m => m.LandingHomeModule)},
{path: 'home', loadChildren: () => import('app/modules/landing/home/home.routes')},
]
},
@ -71,30 +71,30 @@ export const appRoutes: Route[] = [
canActivateChild: [AuthGuard],
component: LayoutComponent,
resolve: {
initialData: InitialDataResolver,
initialData: initialDataResolver
},
children: [
// Dashboards
{path: 'dashboards', children: [
{path: 'project', loadChildren: () => import('app/modules/admin/dashboards/project/project.module').then(m => m.ProjectModule)},
{path: 'analytics', loadChildren: () => import('app/modules/admin/dashboards/analytics/analytics.module').then(m => m.AnalyticsModule)},
{path: 'finance', loadChildren: () => import('app/modules/admin/dashboards/finance/finance.module').then(m => m.FinanceModule)},
{path: 'crypto', loadChildren: () => import('app/modules/admin/dashboards/crypto/crypto.module').then(m => m.CryptoModule)},
{path: 'project', loadChildren: () => import('app/modules/admin/dashboards/project/project.routes')},
{path: 'analytics', loadChildren: () => import('app/modules/admin/dashboards/analytics/analytics.routes')},
{path: 'finance', loadChildren: () => import('app/modules/admin/dashboards/finance/finance.routes')},
{path: 'crypto', loadChildren: () => import('app/modules/admin/dashboards/crypto/crypto.routes')},
]},
// Apps
{path: 'apps', children: [
{path: 'academy', loadChildren: () => import('app/modules/admin/apps/academy/academy.module').then(m => m.AcademyModule)},
{path: 'chat', loadChildren: () => import('app/modules/admin/apps/chat/chat.module').then(m => m.ChatModule)},
{path: 'contacts', loadChildren: () => import('app/modules/admin/apps/contacts/contacts.module').then(m => m.ContactsModule)},
{path: 'ecommerce', loadChildren: () => import('app/modules/admin/apps/ecommerce/ecommerce.module').then(m => m.ECommerceModule)},
{path: 'file-manager', loadChildren: () => import('app/modules/admin/apps/file-manager/file-manager.module').then(m => m.FileManagerModule)},
{path: 'help-center', loadChildren: () => import('app/modules/admin/apps/help-center/help-center.module').then(m => m.HelpCenterModule)},
{path: 'mailbox', loadChildren: () => import('app/modules/admin/apps/mailbox/mailbox.module').then(m => m.MailboxModule)},
{path: 'notes', loadChildren: () => import('app/modules/admin/apps/notes/notes.module').then(m => m.NotesModule)},
{path: 'scrumboard', loadChildren: () => import('app/modules/admin/apps/scrumboard/scrumboard.module').then(m => m.ScrumboardModule)},
{path: 'tasks', loadChildren: () => import('app/modules/admin/apps/tasks/tasks.module').then(m => m.TasksModule)},
{path: 'academy', loadChildren: () => import('app/modules/admin/apps/academy/academy.routes')},
{path: 'chat', loadChildren: () => import('app/modules/admin/apps/chat/chat.routes')},
{path: 'contacts', loadChildren: () => import('app/modules/admin/apps/contacts/contacts.routes')},
{path: 'ecommerce', loadChildren: () => import('app/modules/admin/apps/ecommerce/ecommerce.routes')},
{path: 'file-manager', loadChildren: () => import('app/modules/admin/apps/file-manager/file-manager.routes')},
{path: 'help-center', loadChildren: () => import('app/modules/admin/apps/help-center/help-center.routes')},
{path: 'mailbox', loadChildren: () => import('app/modules/admin/apps/mailbox/mailbox.routes')},
{path: 'notes', loadChildren: () => import('app/modules/admin/apps/notes/notes.routes')},
{path: 'scrumboard', loadChildren: () => import('app/modules/admin/apps/scrumboard/scrumboard.routes')},
{path: 'tasks', loadChildren: () => import('app/modules/admin/apps/tasks/tasks.routes')},
]},
// Pages

View File

@ -44,7 +44,6 @@ export class AuthInterceptor implements HttpInterceptor
return next.handle(newReq).pipe(
catchError((error) =>
{
// Catch "401 Unauthorized" responses
if ( error instanceof HttpErrorResponse && error.status === 401 )
{

View File

@ -76,7 +76,6 @@ export class AuthService
return this._httpClient.post('api/auth/sign-in', credentials).pipe(
switchMap((response: any) =>
{
// Store the access token in the local storage
this.accessToken = response.accessToken;
@ -108,7 +107,6 @@ export class AuthService
),
switchMap((response: any) =>
{
// Replace the access token with the new one if it's available on
// the response object.
//

View File

@ -11,7 +11,6 @@ export const AuthGuard: CanActivateFn | CanActivateChildFn = (route, state) =>
return inject(AuthService).check().pipe(
switchMap((authenticated) =>
{
// If the user is not authenticated...
if ( !authenticated )
{

View File

@ -11,7 +11,6 @@ export const NoAuthGuard: CanActivateFn | CanActivateChildFn = (route, state) =>
return inject(AuthService).check().pipe(
switchMap((authenticated) =>
{
// If the user is authenticated...
if ( authenticated )
{

View File

@ -47,7 +47,6 @@ export class LanguagesComponent implements OnInit, OnDestroy
// Subscribe to language changes
this._translocoService.langChanges$.subscribe((activeLang) =>
{
// Get the active lang
this.activeLang = activeLang;
@ -133,7 +132,6 @@ export class LanguagesComponent implements OnInit, OnDestroy
this._translocoService.selectTranslate('Project').pipe(take(1))
.subscribe((translation) =>
{
// Set the title
projectDashboardItem.title = translation;
@ -149,7 +147,6 @@ export class LanguagesComponent implements OnInit, OnDestroy
this._translocoService.selectTranslate('Analytics').pipe(take(1))
.subscribe((translation) =>
{
// Set the title
analyticsDashboardItem.title = translation;

View File

@ -55,7 +55,6 @@ export class MessagesComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((messages: Message[]) =>
{
// Load the messages
this.messages = messages;

View File

@ -58,7 +58,6 @@ export class MessagesService
switchMap(messages => this._httpClient.post<Message>('api/common/messages', {message}).pipe(
map((newMessage) =>
{
// Update the messages with the new message
this._messages.next([...messages, newMessage]);
@ -85,7 +84,6 @@ export class MessagesService
}).pipe(
map((updatedMessage: Message) =>
{
// Find the index of the updated message
const index = messages.findIndex(item => item.id === id);
@ -114,7 +112,6 @@ export class MessagesService
switchMap(messages => this._httpClient.delete<boolean>('api/common/messages', {params: {id}}).pipe(
map((isDeleted: boolean) =>
{
// Find the index of the deleted message
const index = messages.findIndex(item => item.id === id);
@ -141,7 +138,6 @@ export class MessagesService
switchMap(messages => this._httpClient.get<boolean>('api/common/messages/mark-all-as-read').pipe(
map((isUpdated: boolean) =>
{
// Go through all messages and set them as read
messages.forEach((message, index) =>
{

View File

@ -55,7 +55,6 @@ export class NotificationsComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((notifications: Notification[]) =>
{
// Load the notifications
this.notifications = notifications;

View File

@ -58,7 +58,6 @@ export class NotificationsService
switchMap(notifications => this._httpClient.post<Notification>('api/common/notifications', {notification}).pipe(
map((newNotification) =>
{
// Update the notifications with the new notification
this._notifications.next([...notifications, newNotification]);
@ -85,7 +84,6 @@ export class NotificationsService
}).pipe(
map((updatedNotification: Notification) =>
{
// Find the index of the updated notification
const index = notifications.findIndex(item => item.id === id);
@ -114,7 +112,6 @@ export class NotificationsService
switchMap(notifications => this._httpClient.delete<boolean>('api/common/notifications', {params: {id}}).pipe(
map((isDeleted: boolean) =>
{
// Find the index of the deleted notification
const index = notifications.findIndex(item => item.id === id);
@ -141,7 +138,6 @@ export class NotificationsService
switchMap(notifications => this._httpClient.get<boolean>('api/common/notifications/mark-all-as-read').pipe(
map((isUpdated: boolean) =>
{
// Go through all notifications and set them as read
notifications.forEach((notification, index) =>
{

View File

@ -72,10 +72,8 @@ export class QuickChatComponent implements OnInit, AfterViewInit, OnDestroy
// This doesn't need to trigger Angular's change detection by itself
this._ngZone.runOutsideAngular(() =>
{
setTimeout(() =>
{
// Set the height to 'auto' so we can correctly read the scrollHeight
this.messageInput.nativeElement.style.height = 'auto';

View File

@ -65,7 +65,6 @@ export class QuickChatService
return this._httpClient.get<Chat>('api/apps/chat/chat', {params: {id}}).pipe(
map((chat) =>
{
// Update the chat
this._chat.next(chat);
@ -74,7 +73,6 @@ export class QuickChatService
}),
switchMap((chat) =>
{
if ( !chat )
{
return throwError('Could not found chat with id of ' + id + '!');

View File

@ -76,7 +76,6 @@ export class SearchComponent implements OnChanges, OnInit, OnDestroy
// Give Angular time to complete the change detection cycle
setTimeout(() =>
{
// Focus to the input element
value.nativeElement.focus();
});
@ -126,7 +125,6 @@ export class SearchComponent implements OnChanges, OnInit, OnDestroy
takeUntil(this._unsubscribeAll),
map((value) =>
{
// Set the resultSets to null if there is no value or
// the length of the value is smaller than the minLength
// so the autocomplete panel can be closed
@ -147,7 +145,6 @@ export class SearchComponent implements OnChanges, OnInit, OnDestroy
this._httpClient.post('api/common/search', {query: value})
.subscribe((resultSets: any) =>
{
// Store the result sets
this.resultSets = resultSets;

View File

@ -67,7 +67,6 @@ export class SettingsComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config: AppConfig) =>
{
// Store the config
this.config = config;
});
@ -102,7 +101,6 @@ export class SettingsComponent implements OnInit, OnDestroy
queryParamsHandling: 'merge',
}).then(() =>
{
// Set the config
this._fuseConfigService.config = {layout};
});

View File

@ -71,7 +71,6 @@ export class ShortcutsComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((shortcuts: Shortcut[]) =>
{
// Load the shortcuts
this.shortcuts = shortcuts;

View File

@ -58,7 +58,6 @@ export class ShortcutsService
switchMap(shortcuts => this._httpClient.post<Shortcut>('api/common/shortcuts', {shortcut}).pipe(
map((newShortcut) =>
{
// Update the shortcuts with the new shortcut
this._shortcuts.next([...shortcuts, newShortcut]);
@ -85,7 +84,6 @@ export class ShortcutsService
}).pipe(
map((updatedShortcut: Shortcut) =>
{
// Find the index of the updated shortcut
const index = shortcuts.findIndex(item => item.id === id);
@ -114,7 +112,6 @@ export class ShortcutsService
switchMap(shortcuts => this._httpClient.delete<boolean>('api/common/shortcuts', {params: {id}}).pipe(
map((isDeleted: boolean) =>
{
// Find the index of the deleted shortcut
const index = shortcuts.findIndex(item => item.id === id);

View File

@ -69,7 +69,6 @@ export class LayoutComponent implements OnInit, OnDestroy
takeUntil(this._unsubscribeAll),
map(([config, mql]) =>
{
const options = {
scheme: config.scheme,
theme : config.theme,
@ -86,7 +85,6 @@ export class LayoutComponent implements OnInit, OnDestroy
}),
).subscribe((options) =>
{
// Store the options
this.scheme = options.scheme;
this.theme = options.theme;
@ -101,7 +99,6 @@ export class LayoutComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((config: AppConfig) =>
{
// Store the config
this.config = config;
@ -115,7 +112,6 @@ export class LayoutComponent implements OnInit, OnDestroy
takeUntil(this._unsubscribeAll),
).subscribe(() =>
{
// Update the layout
this._updateLayout();
});
@ -187,7 +183,6 @@ export class LayoutComponent implements OnInit, OnDestroy
const paths = route.pathFromRoot;
paths.forEach((path) =>
{
// Check if there is a 'layout' data
if ( path.routeConfig && path.routeConfig.data && path.routeConfig.data.layout )
{

View File

@ -77,7 +77,6 @@ export class CenteredLayoutComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Check if the screen is small
this.isScreenSmall = !matchingAliases.includes('md');
});

View File

@ -78,7 +78,6 @@ export class EnterpriseLayoutComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Check if the screen is small
this.isScreenSmall = !matchingAliases.includes('md');
});

View File

@ -77,7 +77,6 @@ export class MaterialLayoutComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Check if the screen is small
this.isScreenSmall = !matchingAliases.includes('md');
});

View File

@ -78,7 +78,6 @@ export class ModernLayoutComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Check if the screen is small
this.isScreenSmall = !matchingAliases.includes('md');
});

View File

@ -78,7 +78,6 @@ export class ClassicLayoutComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Check if the screen is small
this.isScreenSmall = !matchingAliases.includes('md');
});

View File

@ -90,7 +90,6 @@ export class ClassyLayoutComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Check if the screen is small
this.isScreenSmall = !matchingAliases.includes('md');
});

View File

@ -78,7 +78,6 @@ export class CompactLayoutComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Check if the screen is small
this.isScreenSmall = !matchingAliases.includes('md');
});

View File

@ -79,7 +79,6 @@ export class DenseLayoutComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Check if the screen is small
this.isScreenSmall = !matchingAliases.includes('md');

View File

@ -90,7 +90,6 @@ export class FuturisticLayoutComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Check if the screen is small
this.isScreenSmall = !matchingAliases.includes('md');
});

View File

@ -78,7 +78,6 @@ export class ThinLayoutComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Check if the screen is small
this.isScreenSmall = !matchingAliases.includes('md');
});

View File

@ -37,7 +37,6 @@ export class AcademyMockApi
.onGet('api/apps/academy/categories')
.reply(() =>
{
// Clone the categories
const categories = cloneDeep(this._categories);
@ -54,7 +53,6 @@ export class AcademyMockApi
.onGet('api/apps/academy/courses')
.reply(() =>
{
// Clone the courses
const courses = cloneDeep(this._courses);
@ -68,7 +66,6 @@ export class AcademyMockApi
.onGet('api/apps/academy/courses/course')
.reply(({request}) =>
{
// Get the id from the params
const id = request.params.get('id');

View File

@ -52,7 +52,6 @@ export class ChatMockApi
.onGet('api/apps/chat/chats')
.reply(() =>
{
// Clone the chats
const chats = cloneDeep(this._chats);
@ -67,7 +66,6 @@ export class ChatMockApi
.onGet('api/apps/chat/chat')
.reply(({request}) =>
{
// Get the chat id
const id = request.params.get('id');
@ -88,7 +86,6 @@ export class ChatMockApi
.onPatch('api/apps/chat/chat')
.reply(({request}) =>
{
// Get the id and chat
const id = request.body.id;
const chat = cloneDeep(request.body.chat);
@ -99,7 +96,6 @@ export class ChatMockApi
// Find the chat and update it
this._chats.forEach((item, index, chats) =>
{
if ( item.id === id )
{
// Update the chat
@ -121,7 +117,6 @@ export class ChatMockApi
.onGet('api/apps/chat/contacts')
.reply(() =>
{
// Clone the contacts
let contacts = cloneDeep(this._contacts);
@ -142,7 +137,6 @@ export class ChatMockApi
.onGet('api/apps/chat/contact')
.reply(({request}) =>
{
// Get the contact id
const id = request.params.get('id');
@ -163,7 +157,6 @@ export class ChatMockApi
.onGet('api/apps/chat/profile')
.reply(() =>
{
// Clone the profile
const profile = cloneDeep(this._profile);

View File

@ -38,7 +38,6 @@ export class ContactsMockApi
.onGet('api/apps/contacts/all')
.reply(() =>
{
// Clone the contacts
const contacts = cloneDeep(this._contacts);
@ -56,7 +55,6 @@ export class ContactsMockApi
.onGet('api/apps/contacts/search')
.reply(({request}) =>
{
// Get the search query
const query = request.params.get('query');
@ -84,7 +82,6 @@ export class ContactsMockApi
.onGet('api/apps/contacts/contact')
.reply(({request}) =>
{
// Get the id from the params
const id = request.params.get('id');
@ -105,7 +102,6 @@ export class ContactsMockApi
.onPost('api/apps/contacts/contact')
.reply(() =>
{
// Generate a new contact
const newContact = {
id : FuseMockApiUtils.guid(),
@ -137,7 +133,6 @@ export class ContactsMockApi
.onPatch('api/apps/contacts/contact')
.reply(({request}) =>
{
// Get the id and contact
const id = request.body.id;
const contact = cloneDeep(request.body.contact);
@ -148,7 +143,6 @@ export class ContactsMockApi
// Find the contact and update it
this._contacts.forEach((item, index, contacts) =>
{
if ( item.id === id )
{
// Update the contact
@ -170,14 +164,12 @@ export class ContactsMockApi
.onDelete('api/apps/contacts/contact')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
// Find the contact and delete it
this._contacts.forEach((item, index) =>
{
if ( item.id === id )
{
this._contacts.splice(index, 1);
@ -209,7 +201,6 @@ export class ContactsMockApi
.onPost('api/apps/contacts/tag')
.reply(({request}) =>
{
// Get the tag
const newTag = cloneDeep(request.body.tag);
@ -230,7 +221,6 @@ export class ContactsMockApi
.onPatch('api/apps/contacts/tag')
.reply(({request}) =>
{
// Get the id and tag
const id = request.body.id;
const tag = cloneDeep(request.body.tag);
@ -241,7 +231,6 @@ export class ContactsMockApi
// Find the tag and update it
this._tags.forEach((item, index, tags) =>
{
if ( item.id === id )
{
// Update the tag
@ -263,14 +252,12 @@ export class ContactsMockApi
.onDelete('api/apps/contacts/tag')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
// Find the tag and delete it
this._tags.forEach((item, index) =>
{
if ( item.id === id )
{
this._tags.splice(index, 1);
@ -304,7 +291,6 @@ export class ContactsMockApi
// Return a new promise
new Promise((resolve, reject) =>
{
// Create a new reader
const reader = new FileReader();
@ -329,7 +315,6 @@ export class ContactsMockApi
.onPost('api/apps/contacts/avatar')
.reply(({request}) =>
{
// Get the id and avatar
const id = request.body.id;
const avatar = request.body.avatar;
@ -346,11 +331,9 @@ export class ContactsMockApi
return from(readAsDataURL(avatar)).pipe(
map((path) =>
{
// Find the contact and update it
this._contacts.forEach((item, index, contacts) =>
{
if ( item.id === id )
{
// Update the avatar

View File

@ -53,7 +53,6 @@ export class ECommerceInventoryMockApi
.onGet('api/apps/ecommerce/inventory/products', 300)
.reply(({request}) =>
{
// Get available queries
const search = request.params.get('search');
const sort = request.params.get('sort') || 'name';
@ -141,7 +140,6 @@ export class ECommerceInventoryMockApi
.onGet('api/apps/ecommerce/inventory/product')
.reply(({request}) =>
{
// Get the id from the params
const id = request.params.get('id');
@ -162,7 +160,6 @@ export class ECommerceInventoryMockApi
.onPost('api/apps/ecommerce/inventory/product')
.reply(() =>
{
// Generate a new product
const newProduct = {
id : FuseMockApiUtils.guid(),
@ -200,7 +197,6 @@ export class ECommerceInventoryMockApi
.onPatch('api/apps/ecommerce/inventory/product')
.reply(({request}) =>
{
// Get the id and product
const id = request.body.id;
const product = cloneDeep(request.body.product);
@ -211,7 +207,6 @@ export class ECommerceInventoryMockApi
// Find the product and update it
this._products.forEach((item, index, products) =>
{
if ( item.id === id )
{
// Update the product
@ -233,14 +228,12 @@ export class ECommerceInventoryMockApi
.onDelete('api/apps/ecommerce/inventory/product')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
// Find the product and delete it
this._products.forEach((item, index) =>
{
if ( item.id === id )
{
this._products.splice(index, 1);
@ -265,7 +258,6 @@ export class ECommerceInventoryMockApi
.onPost('api/apps/ecommerce/inventory/tag')
.reply(({request}) =>
{
// Get the tag
const newTag = cloneDeep(request.body.tag);
@ -286,7 +278,6 @@ export class ECommerceInventoryMockApi
.onPatch('api/apps/ecommerce/inventory/tag')
.reply(({request}) =>
{
// Get the id and tag
const id = request.body.id;
const tag = cloneDeep(request.body.tag);
@ -297,7 +288,6 @@ export class ECommerceInventoryMockApi
// Find the tag and update it
this._tags.forEach((item, index, tags) =>
{
if ( item.id === id )
{
// Update the tag
@ -319,14 +309,12 @@ export class ECommerceInventoryMockApi
.onDelete('api/apps/ecommerce/inventory/tag')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
// Find the tag and delete it
this._tags.forEach((item, index) =>
{
if ( item.id === id )
{
this._tags.splice(index, 1);

View File

@ -35,7 +35,6 @@ export class FileManagerMockApi
.onGet('api/apps/file-manager')
.reply(({request}) =>
{
// Clone the items
let items = cloneDeep(this._items);

View File

@ -39,7 +39,6 @@ export class HelpCenterMockApi
.onGet('api/apps/help-center/faqs')
.reply(({request}) =>
{
// Get the category slug
const slug = request.params.get('slug');
@ -58,7 +57,6 @@ export class HelpCenterMockApi
// Go through each category and set the results
categories.forEach((category) =>
{
results.push(
{
...category,
@ -93,7 +91,6 @@ export class HelpCenterMockApi
.onGet('api/apps/help-center/guides')
.reply(({request}) =>
{
// Get the slug & limit
const slug = request.params.get('slug');
const limit = request.params.get('limit');
@ -116,7 +113,6 @@ export class HelpCenterMockApi
// Go through each category and set the results
categories.forEach((category) =>
{
results.push(
{
...category,
@ -153,7 +149,6 @@ export class HelpCenterMockApi
.onGet('api/apps/help-center/guide')
.reply(({request}) =>
{
// Get the slugs
const categorySlug = request.params.get('categorySlug');
const guideSlug = request.params.get('guideSlug');

View File

@ -46,7 +46,6 @@ export class MailboxMockApi
.onPatch('api/apps/mailbox/settings')
.reply(({request}) =>
{
// Get the settings
const settings = cloneDeep(request.body.settings);
@ -64,13 +63,11 @@ export class MailboxMockApi
.onGet('api/apps/mailbox/folders')
.reply(() =>
{
let count = 0;
// Iterate through the folders
this._folders.forEach((folder) =>
{
// Get the mails of this folder
const mails = this._mails.filter(mail => mail.folder === folder.id);
@ -92,7 +89,6 @@ export class MailboxMockApi
// Go through the mails and count the unread ones
mails.forEach((mail) =>
{
if ( mail.unread )
{
count++;
@ -132,7 +128,6 @@ export class MailboxMockApi
.onPost('api/apps/mailbox/label')
.reply(({request}) =>
{
// Get the label
const label = cloneDeep(request.body.label);
@ -177,7 +172,6 @@ export class MailboxMockApi
.onPatch('api/apps/mailbox/label')
.reply(({request}) =>
{
// Get the id and label
const id = request.body.id;
const label = cloneDeep(request.body.label);
@ -188,7 +182,6 @@ export class MailboxMockApi
// Find the label and update it
this._labels.forEach((item, index, labels) =>
{
if ( item.id === id )
{
// Update the slug
@ -216,7 +209,6 @@ export class MailboxMockApi
.onDelete('api/apps/mailbox/label')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
@ -244,7 +236,6 @@ export class MailboxMockApi
.onGet('api/apps/mailbox/mails', 625)
.reply(({request}) =>
{
// First, decide if mails are requested by folder, filter or label
const byFolder = request.params.get('folder');
const byFilter = request.params.get('filter');
@ -256,7 +247,6 @@ export class MailboxMockApi
// Filter the mails depending on the requested by type
mails = mails.filter((mail) =>
{
if ( byFolder )
{
return mail.folder === this._folders.find(folder => folder.slug === byFolder).id;
@ -342,7 +332,6 @@ export class MailboxMockApi
.onGet('api/apps/mailbox/mail')
.reply(({request}) =>
{
// Get the id from the params
const id = request.params.get('id');
@ -365,7 +354,6 @@ export class MailboxMockApi
.onPatch('api/apps/mailbox/mail')
.reply(({request}) =>
{
// Get the id and mail
const id = request.body.id;
const mail = cloneDeep(request.body.mail);
@ -376,7 +364,6 @@ export class MailboxMockApi
// Find the mail and update it
this._mails.forEach((item, index, mails) =>
{
if ( item.id === id )
{
// Update the mail

View File

@ -47,7 +47,6 @@ export class NotesMockApi
.onPost('api/apps/notes/labels')
.reply(({request}) =>
{
// Create a new label
const label = {
id : FuseMockApiUtils.guid(),
@ -70,7 +69,6 @@ export class NotesMockApi
.onPatch('api/apps/notes/labels')
.reply(({request}) =>
{
// Get label
const updatedLabel = request.body.label;
@ -101,7 +99,6 @@ export class NotesMockApi
.onDelete('api/apps/notes/labels')
.reply(({request}) =>
{
// Get label id
const id = request.params.get('id');
@ -127,7 +124,6 @@ export class NotesMockApi
.onPost('api/apps/notes/tasks')
.reply(({request}) =>
{
// Get note and task
let updatedNote = request.body.note;
const task = request.body.task;
@ -173,7 +169,6 @@ export class NotesMockApi
.onGet('api/apps/notes/all')
.reply(() =>
{
// Clone the labels and notes
const labels = cloneDeep(this._labels);
let notes = cloneDeep(this._notes);
@ -199,7 +194,6 @@ export class NotesMockApi
.onPost('api/apps/notes')
.reply(({request}) =>
{
// Get note
const note = request.body.note;
@ -222,7 +216,6 @@ export class NotesMockApi
.onPatch('api/apps/notes')
.reply(({request}) =>
{
// Get note
const updatedNote = request.body.updatedNote;
@ -252,14 +245,12 @@ export class NotesMockApi
.onDelete('api/apps/notes')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
// Find the note and delete it
this._notes.forEach((item, index) =>
{
if ( item.id === id )
{
this._notes.splice(index, 1);

View File

@ -40,7 +40,6 @@ export class ScrumboardMockApi
.onGet('api/apps/scrumboard/boards')
.reply(({request}) =>
{
// Clone the boards
let boards = cloneDeep(this._boards);
@ -63,7 +62,6 @@ export class ScrumboardMockApi
.onGet('api/apps/scrumboard/board')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
@ -104,7 +102,6 @@ export class ScrumboardMockApi
.onPost('api/apps/scrumboard/board/list')
.reply(({request}) =>
{
// Get the list
const newList = cloneDeep(request.body.list);
@ -127,7 +124,6 @@ export class ScrumboardMockApi
.onPatch('api/apps/scrumboard/board/list')
.reply(({request}) =>
{
// Get the list
const list = cloneDeep(request.body.list);
@ -137,7 +133,6 @@ export class ScrumboardMockApi
// Find the list and update it
this._lists.forEach((item, index, lists) =>
{
if ( item.id === list.id )
{
// Update the list
@ -161,7 +156,6 @@ export class ScrumboardMockApi
.onPatch('api/apps/scrumboard/board/lists')
.reply(({request}) =>
{
// Get the lists
const lists = cloneDeep(request.body.lists);
@ -171,7 +165,6 @@ export class ScrumboardMockApi
// Go through the lists
lists.forEach((item) =>
{
// Find the list
const index = this._lists.findIndex(list => item.id === list.id);
@ -195,7 +188,6 @@ export class ScrumboardMockApi
.onDelete('api/apps/scrumboard/board/list')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
@ -219,7 +211,6 @@ export class ScrumboardMockApi
.onPut('api/apps/scrumboard/board/card')
.reply(({request}) =>
{
// Get the card
const newCard = cloneDeep(request.body.card);
@ -242,7 +233,6 @@ export class ScrumboardMockApi
.onPatch('api/apps/scrumboard/board/card')
.reply(({request}) =>
{
// Get the id and card
const id = request.body.id;
const card = cloneDeep(request.body.card);
@ -256,7 +246,6 @@ export class ScrumboardMockApi
// Find the card and update it
this._cards.forEach((item, index, cards) =>
{
if ( item.id === id )
{
// Update the card
@ -283,7 +272,6 @@ export class ScrumboardMockApi
.onPatch('api/apps/scrumboard/board/cards')
.reply(({request}) =>
{
// Get the cards
const cards = cloneDeep(request.body.cards);
@ -293,7 +281,6 @@ export class ScrumboardMockApi
// Go through the cards
cards.forEach((item) =>
{
// Find the card
const index = this._cards.findIndex(card => item.id === card.id);
@ -323,7 +310,6 @@ export class ScrumboardMockApi
.onDelete('api/apps/scrumboard/board/card')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
@ -344,14 +330,12 @@ export class ScrumboardMockApi
.onPatch('api/apps/scrumboard/board/card/positions')
.reply(({request}) =>
{
// Get the cards
const cards = request.body.cards;
// Go through the cards
this._cards.forEach((card) =>
{
// Find this card's index within the cards array that comes with the request
// and assign that index as the new position number for the card
card.position = cards.findIndex(item => item.id === card.id && item.listId === card.listId && item.boardId === card.boardId);
@ -373,7 +357,6 @@ export class ScrumboardMockApi
.onGet('api/apps/scrumboard/board/labels')
.reply(({request}) =>
{
// Get the board id
const boardId = request.params.get('boardId');
@ -393,7 +376,6 @@ export class ScrumboardMockApi
.onPut('api/apps/scrumboard/board/label')
.reply(({request}) =>
{
// Get the label
const newLabel = cloneDeep(request.body.label);
@ -416,7 +398,6 @@ export class ScrumboardMockApi
.onPatch('api/apps/scrumboard/board/label')
.reply(({request}) =>
{
// Get the id and label
const id = request.body.id;
const label = cloneDeep(request.body.label);
@ -427,7 +408,6 @@ export class ScrumboardMockApi
// Find the label and update it
this._labels.forEach((item, index, labels) =>
{
if ( item.id === id )
{
// Update the label
@ -451,7 +431,6 @@ export class ScrumboardMockApi
.onDelete('api/apps/scrumboard/board/label')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');

View File

@ -47,7 +47,6 @@ export class TasksMockApi
.onPost('api/apps/tasks/tag')
.reply(({request}) =>
{
// Get the tag
const newTag = cloneDeep(request.body.tag);
@ -70,7 +69,6 @@ export class TasksMockApi
.onPatch('api/apps/tasks/tag')
.reply(({request}) =>
{
// Get the id and tag
const id = request.body.id;
const tag = cloneDeep(request.body.tag);
@ -81,7 +79,6 @@ export class TasksMockApi
// Find the tag and update it
this._tags.forEach((item, index, tags) =>
{
if ( item.id === id )
{
// Update the tag
@ -105,7 +102,6 @@ export class TasksMockApi
.onDelete('api/apps/tasks/tag')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
@ -135,7 +131,6 @@ export class TasksMockApi
.onGet('api/apps/tasks/all')
.reply(() =>
{
// Clone the tasks
const tasks = cloneDeep(this._tasks);
@ -155,7 +150,6 @@ export class TasksMockApi
.onGet('api/apps/tasks/search')
.reply(({request}) =>
{
// Get the search query
const query = request.params.get('query');
@ -201,14 +195,12 @@ export class TasksMockApi
.onPatch('api/apps/tasks/order')
.reply(({request}) =>
{
// Get the tasks
const tasks = request.body.tasks;
// Go through the tasks
this._tasks.forEach((task) =>
{
// Find this task's index within the tasks array that comes with the request
// and assign that index as the new order number for the task
task.order = tasks.findIndex((item: any) => item.id === task.id);
@ -230,7 +222,6 @@ export class TasksMockApi
.onGet('api/apps/tasks/task')
.reply(({request}) =>
{
// Get the id from the params
const id = request.params.get('id');
@ -253,7 +244,6 @@ export class TasksMockApi
.onPost('api/apps/tasks/task')
.reply(({request}) =>
{
// Generate a new task
const newTask = {
id : FuseMockApiUtils.guid(),
@ -289,7 +279,6 @@ export class TasksMockApi
.onPatch('api/apps/tasks/task')
.reply(({request}) =>
{
// Get the id and task
const id = request.body.id;
const task = cloneDeep(request.body.task);
@ -300,7 +289,6 @@ export class TasksMockApi
// Find the task and update it
this._tasks.forEach((item, index, tasks) =>
{
if ( item.id === id )
{
// Update the task
@ -324,7 +312,6 @@ export class TasksMockApi
.onDelete('api/apps/tasks/task')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');

View File

@ -66,7 +66,6 @@ export class AuthMockApi
.onPost('api/auth/sign-in', 1500)
.reply(({request}) =>
{
// Sign in successful
if ( request.body.email === 'hughes.brian@company.com' && request.body.password === 'admin' )
{
@ -94,7 +93,6 @@ export class AuthMockApi
.onPost('api/auth/sign-in-with-token')
.reply(({request}) =>
{
// Get the access token
const accessToken = request.body.accessToken;
@ -141,7 +139,6 @@ export class AuthMockApi
.onPost('api/auth/unlock-session', 1500)
.reply(({request}) =>
{
// Sign in successful
if ( request.body.email === 'hughes.brian@company.com' && request.body.password === 'admin' )
{

View File

@ -42,7 +42,6 @@ export class MessagesMockApi
.onPost('api/common/messages')
.reply(({request}) =>
{
// Get the message
const newMessage = cloneDeep(request.body.message);
@ -63,7 +62,6 @@ export class MessagesMockApi
.onPatch('api/common/messages')
.reply(({request}) =>
{
// Get the id and message
const id = request.body.id;
const message = cloneDeep(request.body.message);
@ -74,7 +72,6 @@ export class MessagesMockApi
// Find the message and update it
this._messages.forEach((item: any, index: number, messages: any[]) =>
{
if ( item.id === id )
{
// Update the message
@ -96,7 +93,6 @@ export class MessagesMockApi
.onDelete('api/common/messages')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
@ -123,11 +119,9 @@ export class MessagesMockApi
.onGet('api/common/messages/mark-all-as-read')
.reply(() =>
{
// Go through all messages
this._messages.forEach((item: any, index: number, messages: any[]) =>
{
// Mark it as read
messages[index].read = true;
messages[index].seen = true;
@ -144,7 +138,6 @@ export class MessagesMockApi
.onPost('api/common/messages/toggle-read-status')
.reply(({request}) =>
{
// Get the message
const message = cloneDeep(request.body.message);
@ -154,7 +147,6 @@ export class MessagesMockApi
// Find the message and update it
this._messages.forEach((item: any, index: number, messages: any[]) =>
{
if ( item.id === message.id )
{
// Update the message

View File

@ -39,7 +39,6 @@ export class NavigationMockApi
.onGet('api/common/navigation')
.reply(() =>
{
// Fill compact navigation children using the default navigation
this._compactNavigation.forEach((compactNavItem) =>
{

View File

@ -42,7 +42,6 @@ export class NotificationsMockApi
.onPost('api/common/notifications')
.reply(({request}) =>
{
// Get the notification
const newNotification = cloneDeep(request.body.notification);
@ -63,7 +62,6 @@ export class NotificationsMockApi
.onPatch('api/common/notifications')
.reply(({request}) =>
{
// Get the id and notification
const id = request.body.id;
const notification = cloneDeep(request.body.notification);
@ -74,7 +72,6 @@ export class NotificationsMockApi
// Find the notification and update it
this._notifications.forEach((item: any, index: number, notifications: any[]) =>
{
if ( item.id === id )
{
// Update the notification
@ -96,7 +93,6 @@ export class NotificationsMockApi
.onDelete('api/common/notifications')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');
@ -123,11 +119,9 @@ export class NotificationsMockApi
.onGet('api/common/notifications/mark-all-as-read')
.reply(() =>
{
// Go through all notifications
this._notifications.forEach((item: any, index: number, notifications: any[]) =>
{
// Mark it as read
notifications[index].read = true;
notifications[index].seen = true;
@ -144,7 +138,6 @@ export class NotificationsMockApi
.onPost('api/common/notifications/toggle-read-status')
.reply(({request}) =>
{
// Get the notification
const notification = cloneDeep(request.body.notification);
@ -154,7 +147,6 @@ export class NotificationsMockApi
// Find the notification and update it
this._notifications.forEach((item: any, index: number, notifications: any[]) =>
{
if ( item.id === notification.id )
{
// Update the notification

View File

@ -46,7 +46,6 @@ export class SearchMockApi
.onPost('api/common/search')
.reply(({request}) =>
{
// Get the search query
const query = cloneDeep(request.body.query.toLowerCase());
@ -78,7 +77,6 @@ export class SearchMockApi
// Normalize the results
contactsResults.forEach((result) =>
{
// Add a link
result.link = '/apps/contacts/' + result.id;
@ -100,7 +98,6 @@ export class SearchMockApi
// Normalize the results
pagesResults.forEach((result: any) =>
{
// Add the page title as the value
result.value = result.title;
});
@ -119,7 +116,6 @@ export class SearchMockApi
// Normalize the results
tasksResults.forEach((result) =>
{
// Add a link
result.link = '/apps/tasks/' + result.id;

View File

@ -42,7 +42,6 @@ export class ShortcutsMockApi
.onPost('api/common/shortcuts')
.reply(({request}) =>
{
// Get the shortcut
const newShortcut = cloneDeep(request.body.shortcut);
@ -63,7 +62,6 @@ export class ShortcutsMockApi
.onPatch('api/common/shortcuts')
.reply(({request}) =>
{
// Get the id and shortcut
const id = request.body.id;
const shortcut = cloneDeep(request.body.shortcut);
@ -74,7 +72,6 @@ export class ShortcutsMockApi
// Find the shortcut and update it
this._shortcuts.forEach((item: any, index: number, shortcuts: any[]) =>
{
if ( item.id === id )
{
// Update the shortcut
@ -96,7 +93,6 @@ export class ShortcutsMockApi
.onDelete('api/common/shortcuts')
.reply(({request}) =>
{
// Get the id
const id = request.params.get('id');

View File

@ -42,7 +42,6 @@ export class UserMockApi
.onPatch('api/common/user')
.reply(({request}) =>
{
// Get the user mock-api
const user = cloneDeep(request.body.user);

View File

@ -1,39 +0,0 @@
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatSelectModule } from '@angular/material/select';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatTabsModule } from '@angular/material/tabs';
import { MatTooltipModule } from '@angular/material/tooltip';
import { RouterModule } from '@angular/router';
import { AcademyComponent } from 'app/modules/admin/apps/academy/academy.component';
import { academyRoutes } from 'app/modules/admin/apps/academy/academy.routing';
import { AcademyDetailsComponent } from 'app/modules/admin/apps/academy/details/details.component';
import { AcademyListComponent } from 'app/modules/admin/apps/academy/list/list.component';
@NgModule({
imports: [
RouterModule.forChild(academyRoutes),
MatButtonModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatProgressBarModule,
MatSelectModule,
MatSidenavModule,
MatSlideToggleModule,
MatTooltipModule,
MatTabsModule,
AcademyComponent,
AcademyDetailsComponent,
AcademyListComponent,
],
})
export class AcademyModule
{
}

View File

@ -1,110 +0,0 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { AcademyService } from 'app/modules/admin/apps/academy/academy.service';
import { Category, Course } from 'app/modules/admin/apps/academy/academy.types';
import { catchError, Observable, throwError } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class AcademyCategoriesResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(private _academyService: AcademyService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Category[]>
{
return this._academyService.getCategories();
}
}
@Injectable({
providedIn: 'root',
})
export class AcademyCoursesResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(private _academyService: AcademyService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Course[]>
{
return this._academyService.getCourses();
}
}
@Injectable({
providedIn: 'root',
})
export class AcademyCourseResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(
private _router: Router,
private _academyService: AcademyService,
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Course>
{
return this._academyService.getCourseById(route.paramMap.get('id'))
.pipe(
// Error here means the requested task is not available
catchError((error) =>
{
// Log the error
console.error(error);
// Get the parent url
const parentUrl = state.url.split('/').slice(0, -1).join('/');
// Navigate to there
this._router.navigateByUrl(parentUrl);
// Throw an error
return throwError(error);
}),
);
}
}

View File

@ -0,0 +1,64 @@
import { inject } from '@angular/core';
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot, Routes } from '@angular/router';
import { AcademyComponent } from 'app/modules/admin/apps/academy/academy.component';
import { AcademyService } from 'app/modules/admin/apps/academy/academy.service';
import { AcademyDetailsComponent } from 'app/modules/admin/apps/academy/details/details.component';
import { AcademyListComponent } from 'app/modules/admin/apps/academy/list/list.component';
import { catchError, throwError } from 'rxjs';
/**
* Course resolver
*
* @param route
* @param state
*/
const courseResolver = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) =>
{
const academyService = inject(AcademyService);
const router = inject(Router);
return academyService.getCourseById(route.paramMap.get('id')).pipe(
// Error here means the requested course is not available
catchError((error) =>
{
// Log the error
console.error(error);
// Get the parent url
const parentUrl = state.url.split('/').slice(0, -1).join('/');
// Navigate to there
router.navigateByUrl(parentUrl);
// Throw an error
return throwError(error);
}),
);
};
export default [
{
path : '',
component: AcademyComponent,
resolve : {
categories: () => inject(AcademyService).getCategories(),
},
children : [
{
path : '',
pathMatch: 'full',
component: AcademyListComponent,
resolve : {
courses: () => inject(AcademyService).getCourses(),
},
},
{
path : ':id',
component: AcademyDetailsComponent,
resolve : {
course: courseResolver,
},
},
],
},
] as Routes;

View File

@ -1,32 +0,0 @@
import { Route } from '@angular/router';
import { AcademyComponent } from 'app/modules/admin/apps/academy/academy.component';
import { AcademyCategoriesResolver, AcademyCourseResolver, AcademyCoursesResolver } from 'app/modules/admin/apps/academy/academy.resolvers';
import { AcademyDetailsComponent } from 'app/modules/admin/apps/academy/details/details.component';
import { AcademyListComponent } from 'app/modules/admin/apps/academy/list/list.component';
export const academyRoutes: Route[] = [
{
path : '',
component: AcademyComponent,
resolve : {
categories: AcademyCategoriesResolver,
},
children : [
{
path : '',
pathMatch: 'full',
component: AcademyListComponent,
resolve : {
courses: AcademyCoursesResolver,
},
},
{
path : ':id',
component: AcademyDetailsComponent,
resolve : {
course: AcademyCourseResolver,
},
},
],
},
];

View File

@ -86,7 +86,6 @@ export class AcademyService
return this._httpClient.get<Course>('api/apps/academy/courses/course', {params: {id}}).pipe(
map((course) =>
{
// Update the course
this._course.next(course);
@ -95,7 +94,6 @@ export class AcademyService
}),
switchMap((course) =>
{
if ( !course )
{
return throwError('Could not found course with id of ' + id + '!');

View File

@ -58,7 +58,6 @@ export class AcademyDetailsComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((categories: Category[]) =>
{
// Get the categories
this.categories = categories;
@ -71,7 +70,6 @@ export class AcademyDetailsComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((course: Course) =>
{
// Get the course
this.course = course;
@ -87,7 +85,6 @@ export class AcademyDetailsComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Set the drawerMode and drawerOpened
if ( matchingAliases.includes('lg') )
{
@ -201,7 +198,6 @@ export class AcademyDetailsComponent implements OnInit, OnDestroy
// Wrap everything into setTimeout so we can make sure that the 'current-step' class points to correct element
setTimeout(() =>
{
// Get the current step element and scroll it into view
const currentStepElement = this._document.getElementsByClassName('current-step')[0];
if ( currentStepElement )

View File

@ -88,7 +88,6 @@ export class AcademyListComponent implements OnInit, OnDestroy
combineLatest([this.filters.categorySlug$, this.filters.query$, this.filters.hideCompleted$])
.subscribe(([categorySlug, query, hideCompleted]) =>
{
// Reset the filtered courses
this.filteredCourses = this.courses;

View File

@ -1,41 +0,0 @@
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { MatSidenavModule } from '@angular/material/sidenav';
import { RouterModule } from '@angular/router';
import { ChatComponent } from 'app/modules/admin/apps/chat/chat.component';
import { chatRoutes } from 'app/modules/admin/apps/chat/chat.routing';
import { ChatsComponent } from 'app/modules/admin/apps/chat/chats/chats.component';
import { ContactInfoComponent } from 'app/modules/admin/apps/chat/contact-info/contact-info.component';
import { ConversationComponent } from 'app/modules/admin/apps/chat/conversation/conversation.component';
import { EmptyConversationComponent } from 'app/modules/admin/apps/chat/empty-conversation/empty-conversation.component';
import { NewChatComponent } from 'app/modules/admin/apps/chat/new-chat/new-chat.component';
import { ProfileComponent } from 'app/modules/admin/apps/chat/profile/profile.component';
@NgModule({
imports: [
RouterModule.forChild(chatRoutes),
MatButtonModule,
MatCheckboxModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatMenuModule,
MatSidenavModule,
ChatComponent,
ChatsComponent,
ContactInfoComponent,
ConversationComponent,
EmptyConversationComponent,
NewChatComponent,
ProfileComponent,
],
})
export class ChatModule
{
}

View File

@ -1,147 +0,0 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { ChatService } from 'app/modules/admin/apps/chat/chat.service';
import { Chat, Contact, Profile } from 'app/modules/admin/apps/chat/chat.types';
import { catchError, Observable, throwError } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class ChatChatsResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(
private _chatService: ChatService,
private _router: Router,
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Chat[]> | any
{
return this._chatService.getChats();
}
}
@Injectable({
providedIn: 'root',
})
export class ChatChatResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(
private _chatService: ChatService,
private _router: Router,
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Chat>
{
return this._chatService.getChatById(route.paramMap.get('id'))
.pipe(
// Error here means the requested chat is not available
catchError((error) =>
{
// Log the error
console.error(error);
// Get the parent url
const parentUrl = state.url.split('/').slice(0, -1).join('/');
// Navigate to there
this._router.navigateByUrl(parentUrl);
// Throw an error
return throwError(error);
}),
);
}
}
@Injectable({
providedIn: 'root',
})
export class ChatContactsResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(
private _chatService: ChatService,
private _router: Router,
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Contact[]> | any
{
return this._chatService.getContacts();
}
}
@Injectable({
providedIn: 'root',
})
export class ChatProfileResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(
private _chatService: ChatService,
private _router: Router,
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Profile> | any
{
return this._chatService.getProfile();
}
}

View File

@ -0,0 +1,70 @@
import { inject } from '@angular/core';
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot, Routes } from '@angular/router';
import { ChatComponent } from 'app/modules/admin/apps/chat/chat.component';
import { ChatService } from 'app/modules/admin/apps/chat/chat.service';
import { ChatsComponent } from 'app/modules/admin/apps/chat/chats/chats.component';
import { ConversationComponent } from 'app/modules/admin/apps/chat/conversation/conversation.component';
import { EmptyConversationComponent } from 'app/modules/admin/apps/chat/empty-conversation/empty-conversation.component';
import { catchError, throwError } from 'rxjs';
/**
* Conversation resolver
*
* @param route
* @param state
*/
const conversationResolver = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) =>
{
const chatService = inject(ChatService);
const router = inject(Router);
return chatService.getChatById(route.paramMap.get('id')).pipe(
// Error here means the requested chat is not available
catchError((error) =>
{
// Log the error
console.error(error);
// Get the parent url
const parentUrl = state.url.split('/').slice(0, -1).join('/');
// Navigate to there
router.navigateByUrl(parentUrl);
// Throw an error
return throwError(error);
}),
);
};
export default [
{
path : '',
component: ChatComponent,
resolve : {
chats : () => inject(ChatService).getChats(),
contacts: () => inject(ChatService).getContacts(),
profile : () => inject(ChatService).getProfile(),
},
children : [
{
path : '',
component: ChatsComponent,
children : [
{
path : '',
pathMatch: 'full',
component: EmptyConversationComponent,
},
{
path : ':id',
component: ConversationComponent,
resolve : {
conversation: conversationResolver,
},
},
],
},
],
},
] as Routes;

View File

@ -1,38 +0,0 @@
import { Route } from '@angular/router';
import { ChatComponent } from 'app/modules/admin/apps/chat/chat.component';
import { ChatChatResolver, ChatChatsResolver, ChatContactsResolver, ChatProfileResolver } from 'app/modules/admin/apps/chat/chat.resolvers';
import { ChatsComponent } from 'app/modules/admin/apps/chat/chats/chats.component';
import { ConversationComponent } from 'app/modules/admin/apps/chat/conversation/conversation.component';
import { EmptyConversationComponent } from 'app/modules/admin/apps/chat/empty-conversation/empty-conversation.component';
export const chatRoutes: Route[] = [
{
path : '',
component: ChatComponent,
resolve : {
chats : ChatChatsResolver,
contacts: ChatContactsResolver,
profile : ChatProfileResolver,
},
children : [
{
path : '',
component: ChatsComponent,
children : [
{
path : '',
pathMatch: 'full',
component: EmptyConversationComponent,
},
{
path : ':id',
component: ConversationComponent,
resolve : {
conversation: ChatChatResolver,
},
},
],
},
],
},
];

View File

@ -133,7 +133,6 @@ export class ChatService
return this._httpClient.get<Chat>('api/apps/chat/chat', {params: {id}}).pipe(
map((chat) =>
{
// Update the chat
this._chat.next(chat);
@ -142,7 +141,6 @@ export class ChatService
}),
switchMap((chat) =>
{
if ( !chat )
{
return throwError('Could not found chat with id of ' + id + '!');
@ -169,7 +167,6 @@ export class ChatService
}).pipe(
map((updatedChat) =>
{
// Find the index of the updated chat
const index = chats.findIndex(item => item.id === id);
@ -187,7 +184,6 @@ export class ChatService
filter(item => item && item.id === id),
tap(() =>
{
// Update the chat if it's selected
this._chat.next(updatedChat);

View File

@ -58,10 +58,8 @@ export class ConversationComponent implements OnInit, OnDestroy
// This doesn't need to trigger Angular's change detection by itself
this._ngZone.runOutsideAngular(() =>
{
setTimeout(() =>
{
// Set the height to 'auto' so we can correctly read the scrollHeight
this.messageInput.nativeElement.style.height = 'auto';
@ -102,7 +100,6 @@ export class ConversationComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Set the drawerMode if the given breakpoint is active
if ( matchingAliases.includes('lg') )
{

View File

@ -1,4 +1,5 @@
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
import { MatLuxonDateModule } from '@angular/material-luxon-adapter';
import { RouterOutlet } from '@angular/router';
@Component({

View File

@ -1,47 +0,0 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot, UrlTree } from '@angular/router';
import { ContactsDetailsComponent } from 'app/modules/admin/apps/contacts/details/details.component';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class CanDeactivateContactsDetails implements CanDeactivate<ContactsDetailsComponent>
{
canDeactivate(
component: ContactsDetailsComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState: RouterStateSnapshot,
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree
{
// Get the next route
let nextRoute: ActivatedRouteSnapshot = nextState.root;
while ( nextRoute.firstChild )
{
nextRoute = nextRoute.firstChild;
}
// If the next state doesn't contain '/contacts'
// it means we are navigating away from the
// contacts app
if ( !nextState.url.includes('/contacts') )
{
// Let it navigate
return true;
}
// If we are navigating to another contact...
if ( nextRoute.paramMap.get('id') )
{
// Just navigate
return true;
}
// Otherwise...
else
{
// Close the drawer first, and then navigate
return component.closeDrawer().then(() => true);
}
}
}

View File

@ -1,67 +0,0 @@
import { NgModule } from '@angular/core';
import { MatLuxonDateModule } from '@angular/material-luxon-adapter';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MAT_DATE_FORMATS, MatRippleModule } from '@angular/material/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDividerModule } from '@angular/material/divider';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatRadioModule } from '@angular/material/radio';
import { MatSelectModule } from '@angular/material/select';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatTableModule } from '@angular/material/table';
import { MatTooltipModule } from '@angular/material/tooltip';
import { RouterModule } from '@angular/router';
import { ContactsComponent } from 'app/modules/admin/apps/contacts/contacts.component';
import { contactsRoutes } from 'app/modules/admin/apps/contacts/contacts.routing';
import { ContactsDetailsComponent } from 'app/modules/admin/apps/contacts/details/details.component';
import { ContactsListComponent } from 'app/modules/admin/apps/contacts/list/list.component';
@NgModule({
imports : [
RouterModule.forChild(contactsRoutes),
MatButtonModule,
MatCheckboxModule,
MatDatepickerModule,
MatDividerModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatLuxonDateModule,
MatMenuModule,
MatProgressBarModule,
MatRadioModule,
MatRippleModule,
MatSelectModule,
MatSidenavModule,
MatTableModule,
MatTooltipModule,
ContactsComponent,
ContactsListComponent,
ContactsDetailsComponent,
],
providers: [
{
provide : MAT_DATE_FORMATS,
useValue: {
parse : {
dateInput: 'D',
},
display: {
dateInput : 'DDD',
monthYearLabel : 'LLL yyyy',
dateA11yLabel : 'DD',
monthYearA11yLabel: 'LLLL yyyy',
},
},
},
],
})
export class ContactsModule
{
}

View File

@ -1,138 +0,0 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { ContactsService } from 'app/modules/admin/apps/contacts/contacts.service';
import { Contact, Country, Tag } from 'app/modules/admin/apps/contacts/contacts.types';
import { catchError, Observable, throwError } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class ContactsResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(private _contactsService: ContactsService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Contact[]>
{
return this._contactsService.getContacts();
}
}
@Injectable({
providedIn: 'root',
})
export class ContactsContactResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(
private _contactsService: ContactsService,
private _router: Router,
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Contact>
{
return this._contactsService.getContactById(route.paramMap.get('id'))
.pipe(
// Error here means the requested contact is not available
catchError((error) =>
{
// Log the error
console.error(error);
// Get the parent url
const parentUrl = state.url.split('/').slice(0, -1).join('/');
// Navigate to there
this._router.navigateByUrl(parentUrl);
// Throw an error
return throwError(error);
}),
);
}
}
@Injectable({
providedIn: 'root',
})
export class ContactsCountriesResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(private _contactsService: ContactsService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Country[]>
{
return this._contactsService.getCountries();
}
}
@Injectable({
providedIn: 'root',
})
export class ContactsTagsResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(private _contactsService: ContactsService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Tag[]>
{
return this._contactsService.getTags();
}
}

View File

@ -0,0 +1,110 @@
import { inject } from '@angular/core';
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot, Routes } from '@angular/router';
import { ContactsComponent } from 'app/modules/admin/apps/contacts/contacts.component';
import { ContactsService } from 'app/modules/admin/apps/contacts/contacts.service';
import { ContactsDetailsComponent } from 'app/modules/admin/apps/contacts/details/details.component';
import { ContactsListComponent } from 'app/modules/admin/apps/contacts/list/list.component';
import { catchError, throwError } from 'rxjs';
/**
* Contact resolver
*
* @param route
* @param state
*/
const contactResolver = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) =>
{
const contactsService = inject(ContactsService);
const router = inject(Router);
return contactsService.getContactById(route.paramMap.get('id'))
.pipe(
// Error here means the requested contact is not available
catchError((error) =>
{
// Log the error
console.error(error);
// Get the parent url
const parentUrl = state.url.split('/').slice(0, -1).join('/');
// Navigate to there
router.navigateByUrl(parentUrl);
// Throw an error
return throwError(error);
}),
);
};
/**
* Can deactivate contacts details
*
* @param component
* @param currentRoute
* @param currentState
* @param nextState
*/
const canDeactivateContactsDetails = (
component: ContactsDetailsComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState: RouterStateSnapshot) =>
{
// Get the next route
let nextRoute: ActivatedRouteSnapshot = nextState.root;
while ( nextRoute.firstChild )
{
nextRoute = nextRoute.firstChild;
}
// If the next state doesn't contain '/contacts'
// it means we are navigating away from the
// contacts app
if ( !nextState.url.includes('/contacts') )
{
// Let it navigate
return true;
}
// If we are navigating to another contact...
if ( nextRoute.paramMap.get('id') )
{
// Just navigate
return true;
}
// Otherwise, close the drawer first, and then navigate
return component.closeDrawer().then(() => true);
};
export default [
{
path : '',
component: ContactsComponent,
resolve : {
tags: () => inject(ContactsService).getTags(),
},
children : [
{
path : '',
component: ContactsListComponent,
resolve : {
contacts : () => inject(ContactsService).getContacts(),
countries: () => inject(ContactsService).getCountries(),
},
children : [
{
path : ':id',
component : ContactsDetailsComponent,
resolve : {
contact : contactResolver,
countries: () => inject(ContactsService).getCountries(),
},
canDeactivate: [canDeactivateContactsDetails],
},
],
},
],
},
] as Routes;

View File

@ -1,37 +0,0 @@
import { Route } from '@angular/router';
import { ContactsComponent } from 'app/modules/admin/apps/contacts/contacts.component';
import { CanDeactivateContactsDetails } from 'app/modules/admin/apps/contacts/contacts.guards';
import { ContactsContactResolver, ContactsCountriesResolver, ContactsResolver, ContactsTagsResolver } from 'app/modules/admin/apps/contacts/contacts.resolvers';
import { ContactsDetailsComponent } from 'app/modules/admin/apps/contacts/details/details.component';
import { ContactsListComponent } from 'app/modules/admin/apps/contacts/list/list.component';
export const contactsRoutes: Route[] = [
{
path : '',
component: ContactsComponent,
resolve : {
tags: ContactsTagsResolver,
},
children : [
{
path : '',
component: ContactsListComponent,
resolve : {
contacts : ContactsResolver,
countries: ContactsCountriesResolver,
},
children : [
{
path : ':id',
component : ContactsDetailsComponent,
resolve : {
contact : ContactsContactResolver,
countries: ContactsCountriesResolver,
},
canDeactivate: [CanDeactivateContactsDetails],
},
],
},
],
},
];

View File

@ -100,7 +100,6 @@ export class ContactsService
take(1),
map((contacts) =>
{
// Find the contact
const contact = contacts.find(item => item.id === id) || null;
@ -112,7 +111,6 @@ export class ContactsService
}),
switchMap((contact) =>
{
if ( !contact )
{
return throwError('Could not found contact with id of ' + id + '!');
@ -133,7 +131,6 @@ export class ContactsService
switchMap(contacts => this._httpClient.post<Contact>('api/apps/contacts/contact', {}).pipe(
map((newContact) =>
{
// Update the contacts with the new contact
this._contacts.next([newContact, ...contacts]);
@ -160,7 +157,6 @@ export class ContactsService
}).pipe(
map((updatedContact) =>
{
// Find the index of the updated contact
const index = contacts.findIndex(item => item.id === id);
@ -178,7 +174,6 @@ export class ContactsService
filter(item => item && item.id === id),
tap(() =>
{
// Update the contact if it's selected
this._contact.next(updatedContact);
@ -202,7 +197,6 @@ export class ContactsService
switchMap(contacts => this._httpClient.delete('api/apps/contacts/contact', {params: {id}}).pipe(
map((isDeleted: boolean) =>
{
// Find the index of the deleted contact
const index = contacts.findIndex(item => item.id === id);
@ -257,7 +251,6 @@ export class ContactsService
switchMap(tags => this._httpClient.post<Tag>('api/apps/contacts/tag', {tag}).pipe(
map((newTag) =>
{
// Update the tags with the new tag
this._tags.next([...tags, newTag]);
@ -284,7 +277,6 @@ export class ContactsService
}).pipe(
map((updatedTag) =>
{
// Find the index of the updated tag
const index = tags.findIndex(item => item.id === id);
@ -313,7 +305,6 @@ export class ContactsService
switchMap(tags => this._httpClient.delete('api/apps/contacts/tag', {params: {id}}).pipe(
map((isDeleted: boolean) =>
{
// Find the index of the deleted tag
const index = tags.findIndex(item => item.id === id);
@ -331,11 +322,9 @@ export class ContactsService
take(1),
map((contacts) =>
{
// Iterate through the contacts
contacts.forEach((contact) =>
{
const tagIndex = contact.tags.findIndex(tag => tag === id);
// If the contact has the tag, remove it
@ -374,7 +363,6 @@ export class ContactsService
}).pipe(
map((updatedContact) =>
{
// Find the index of the updated contact
const index = contacts.findIndex(item => item.id === id);
@ -392,7 +380,6 @@ export class ContactsService
filter(item => item && item.id === id),
tap(() =>
{
// Update the contact if it's selected
this._contact.next(updatedContact);

View File

@ -4,9 +4,10 @@ import { TextFieldModule } from '@angular/cdk/text-field';
import { DatePipe, NgClass, NgFor, NgIf } from '@angular/common';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, Renderer2, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
import { FormsModule, ReactiveFormsModule, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MatLuxonDateModule } from '@angular/material-luxon-adapter';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatOptionModule, MatRippleModule } from '@angular/material/core';
import { MAT_DATE_FORMATS, MatOptionModule, MatRippleModule } from '@angular/material/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
@ -28,7 +29,23 @@ import { debounceTime, Subject, takeUntil } from 'rxjs';
encapsulation : ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone : true,
imports : [NgIf, MatButtonModule, MatTooltipModule, RouterLink, MatIconModule, NgFor, FormsModule, ReactiveFormsModule, MatRippleModule, MatFormFieldModule, MatInputModule, MatCheckboxModule, NgClass, MatSelectModule, MatOptionModule, MatDatepickerModule, TextFieldModule, FuseFindByKeyPipe, DatePipe],
imports : [NgIf, MatLuxonDateModule, MatButtonModule, MatTooltipModule, RouterLink, MatIconModule, NgFor, FormsModule, ReactiveFormsModule, MatRippleModule, MatFormFieldModule, MatInputModule, MatCheckboxModule, NgClass, MatSelectModule, MatOptionModule, MatDatepickerModule, TextFieldModule, FuseFindByKeyPipe, DatePipe],
providers : [
{
provide : MAT_DATE_FORMATS,
useValue: {
parse : {
dateInput: 'D',
},
display: {
dateInput : 'DDD',
monthYearLabel : 'LLL yyyy',
dateA11yLabel : 'DD',
monthYearA11yLabel: 'LLLL yyyy',
},
},
},
],
})
export class ContactsDetailsComponent implements OnInit, OnDestroy
{
@ -108,7 +125,6 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((contact: Contact) =>
{
// Open the drawer in case it is closed
this._contactsListComponent.matDrawer.open();
@ -130,7 +146,6 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
// Iterate through them
contact.emails.forEach((email) =>
{
// Create an email form group
emailFormGroups.push(
this._formBuilder.group({
@ -165,7 +180,6 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
// Iterate through them
contact.phoneNumbers.forEach((phoneNumber) =>
{
// Create an email form group
phoneNumbersFormGroups.push(
this._formBuilder.group({
@ -289,7 +303,6 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
// Update the contact on the server
this._contactsService.updateContact(contact.id, contact).subscribe(() =>
{
// Toggle the edit mode off
this.toggleEditMode(false);
});
@ -314,7 +327,6 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
// Subscribe to the confirmation dialog closed action
confirmation.afterClosed().subscribe((result) =>
{
// If the confirm button pressed...
if ( result === 'confirmed' )
{
@ -330,7 +342,6 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
this._contactsService.deleteContact(id)
.subscribe((isDeleted) =>
{
// Return if the contact wasn't deleted...
if ( !isDeleted )
{
@ -431,7 +442,6 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
// Subscribe to the attachments observable
this._tagsPanelOverlayRef.attachments().subscribe(() =>
{
// Add a class to the origin
this._renderer2.addClass(this._tagsPanelOrigin.nativeElement, 'panel-opened');
@ -448,7 +458,6 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
// Subscribe to the backdrop click
this._tagsPanelOverlayRef.backdropClick().subscribe(() =>
{
// Remove the class from the origin
this._renderer2.removeClass(this._tagsPanelOrigin.nativeElement, 'panel-opened');
@ -554,7 +563,6 @@ export class ContactsDetailsComponent implements OnInit, OnDestroy
this._contactsService.createTag(tag)
.subscribe((response) =>
{
// Add the tag to the contact
this.addTagToContact(response);
});

View File

@ -63,7 +63,6 @@ export class ContactsListComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((contacts: Contact[]) =>
{
// Update the counts
this.contactsCount = contacts.length;
@ -76,7 +75,6 @@ export class ContactsListComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((contact: Contact) =>
{
// Update the selected contact
this.selectedContact = contact;
@ -89,7 +87,6 @@ export class ContactsListComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((countries: Country[]) =>
{
// Update the countries
this.countries = countries;
@ -127,7 +124,6 @@ export class ContactsListComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(({matchingAliases}) =>
{
// Set the drawerMode if the given breakpoint is active
if ( matchingAliases.includes('lg') )
{
@ -191,7 +187,6 @@ export class ContactsListComponent implements OnInit, OnDestroy
// Create the contact
this._contactsService.createContact().subscribe((newContact) =>
{
// Go to the new contact
this._router.navigate(['./', newContact.id], {relativeTo: this._activatedRoute});

View File

@ -1,43 +0,0 @@
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatRippleModule } from '@angular/material/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatSelectModule } from '@angular/material/select';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatSortModule } from '@angular/material/sort';
import { MatTooltipModule } from '@angular/material/tooltip';
import { RouterModule } from '@angular/router';
import { ecommerceRoutes } from 'app/modules/admin/apps/ecommerce/ecommerce.routing';
import { InventoryComponent } from 'app/modules/admin/apps/ecommerce/inventory/inventory.component';
import { InventoryListComponent } from 'app/modules/admin/apps/ecommerce/inventory/list/inventory.component';
@NgModule({
imports: [
RouterModule.forChild(ecommerceRoutes),
MatButtonModule,
MatCheckboxModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
MatMenuModule,
MatPaginatorModule,
MatProgressBarModule,
MatRippleModule,
MatSortModule,
MatSelectModule,
MatSlideToggleModule,
MatTooltipModule,
InventoryComponent,
InventoryListComponent,
],
})
export class ECommerceModule
{
}

View File

@ -0,0 +1,30 @@
import { inject } from '@angular/core';
import { Routes } from '@angular/router';
import { InventoryComponent } from 'app/modules/admin/apps/ecommerce/inventory/inventory.component';
import { InventoryService } from 'app/modules/admin/apps/ecommerce/inventory/inventory.service';
import { InventoryListComponent } from 'app/modules/admin/apps/ecommerce/inventory/list/inventory.component';
export default [
{
path : '',
pathMatch : 'full',
redirectTo: 'inventory',
},
{
path : 'inventory',
component: InventoryComponent,
children : [
{
path : '',
component: InventoryListComponent,
resolve : {
brands : () => inject(InventoryService).getBrands(),
categories: () => inject(InventoryService).getCategories(),
products : () => inject(InventoryService).getProducts(),
tags : () => inject(InventoryService).getTags(),
vendors : () => inject(InventoryService).getVendors(),
},
},
],
},
] as Routes;

View File

@ -1,50 +0,0 @@
import { Route } from '@angular/router';
import { InventoryComponent } from 'app/modules/admin/apps/ecommerce/inventory/inventory.component';
import { InventoryBrandsResolver, InventoryCategoriesResolver, InventoryProductsResolver, InventoryTagsResolver, InventoryVendorsResolver } from 'app/modules/admin/apps/ecommerce/inventory/inventory.resolvers';
import { InventoryListComponent } from 'app/modules/admin/apps/ecommerce/inventory/list/inventory.component';
export const ecommerceRoutes: Route[] = [
{
path : '',
pathMatch : 'full',
redirectTo: 'inventory',
},
{
path : 'inventory',
component: InventoryComponent,
children : [
{
path : '',
component: InventoryListComponent,
resolve : {
brands : InventoryBrandsResolver,
categories: InventoryCategoriesResolver,
products : InventoryProductsResolver,
tags : InventoryTagsResolver,
vendors : InventoryVendorsResolver,
},
},
],
/*children : [
{
path : '',
component: ContactsListComponent,
resolve : {
tasks : ContactsResolver,
countries: ContactsCountriesResolver
},
children : [
{
path : ':id',
component : ContactsDetailsComponent,
resolve : {
task : ContactsContactResolver,
countries: ContactsCountriesResolver
},
canDeactivate: [CanDeactivateContactsDetails]
}
]
}
]*/
},
];

View File

@ -1,194 +0,0 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { InventoryService } from 'app/modules/admin/apps/ecommerce/inventory/inventory.service';
import { InventoryBrand, InventoryCategory, InventoryPagination, InventoryProduct, InventoryTag, InventoryVendor } from 'app/modules/admin/apps/ecommerce/inventory/inventory.types';
import { catchError, Observable, throwError } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class InventoryBrandsResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(private _inventoryService: InventoryService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<InventoryBrand[]>
{
return this._inventoryService.getBrands();
}
}
@Injectable({
providedIn: 'root',
})
export class InventoryCategoriesResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(private _inventoryService: InventoryService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<InventoryCategory[]>
{
return this._inventoryService.getCategories();
}
}
@Injectable({
providedIn: 'root',
})
export class InventoryProductResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(
private _inventoryService: InventoryService,
private _router: Router,
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<InventoryProduct>
{
return this._inventoryService.getProductById(route.paramMap.get('id'))
.pipe(
// Error here means the requested product is not available
catchError((error) =>
{
// Log the error
console.error(error);
// Get the parent url
const parentUrl = state.url.split('/').slice(0, -1).join('/');
// Navigate to there
this._router.navigateByUrl(parentUrl);
// Throw an error
return throwError(error);
}),
);
}
}
@Injectable({
providedIn: 'root',
})
export class InventoryProductsResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(private _inventoryService: InventoryService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<{ pagination: InventoryPagination; products: InventoryProduct[] }>
{
return this._inventoryService.getProducts();
}
}
@Injectable({
providedIn: 'root',
})
export class InventoryTagsResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(private _inventoryService: InventoryService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<InventoryTag[]>
{
return this._inventoryService.getTags();
}
}
@Injectable({
providedIn: 'root',
})
export class InventoryVendorsResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(private _inventoryService: InventoryService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<InventoryVendor[]>
{
return this._inventoryService.getVendors();
}
}

View File

@ -153,7 +153,6 @@ export class InventoryService
take(1),
map((products) =>
{
// Find the product
const product = products.find(item => item.id === id) || null;
@ -165,7 +164,6 @@ export class InventoryService
}),
switchMap((product) =>
{
if ( !product )
{
return throwError('Could not found product with id of ' + id + '!');
@ -186,7 +184,6 @@ export class InventoryService
switchMap(products => this._httpClient.post<InventoryProduct>('api/apps/ecommerce/inventory/product', {}).pipe(
map((newProduct) =>
{
// Update the products with the new product
this._products.next([newProduct, ...products]);
@ -213,7 +210,6 @@ export class InventoryService
}).pipe(
map((updatedProduct) =>
{
// Find the index of the updated product
const index = products.findIndex(item => item.id === id);
@ -231,7 +227,6 @@ export class InventoryService
filter(item => item && item.id === id),
tap(() =>
{
// Update the product if it's selected
this._product.next(updatedProduct);
@ -255,7 +250,6 @@ export class InventoryService
switchMap(products => this._httpClient.delete('api/apps/ecommerce/inventory/product', {params: {id}}).pipe(
map((isDeleted: boolean) =>
{
// Find the index of the deleted product
const index = products.findIndex(item => item.id === id);
@ -297,7 +291,6 @@ export class InventoryService
switchMap(tags => this._httpClient.post<InventoryTag>('api/apps/ecommerce/inventory/tag', {tag}).pipe(
map((newTag) =>
{
// Update the tags with the new tag
this._tags.next([...tags, newTag]);
@ -324,7 +317,6 @@ export class InventoryService
}).pipe(
map((updatedTag) =>
{
// Find the index of the updated tag
const index = tags.findIndex(item => item.id === id);
@ -353,7 +345,6 @@ export class InventoryService
switchMap(tags => this._httpClient.delete('api/apps/ecommerce/inventory/tag', {params: {id}}).pipe(
map((isDeleted: boolean) =>
{
// Find the index of the deleted tag
const index = tags.findIndex(item => item.id === id);
@ -371,11 +362,9 @@ export class InventoryService
take(1),
map((products) =>
{
// Iterate through the contacts
products.forEach((product) =>
{
const tagIndex = product.tags.findIndex(tag => tag === id);
// If the contact has the tag, remove it
@ -405,52 +394,4 @@ export class InventoryService
}),
);
}
/**
* Update the avatar of the given contact
*
* @param id
* @param avatar
*/
/*uploadAvatar(id: string, avatar: File): Observable<Contact>
{
return this.contacts$.pipe(
take(1),
switchMap(contacts => this._httpClient.post<Contact>('api/apps/contacts/avatar', {
id,
avatar
}, {
headers: {
'Content-Type': avatar.type
}
}).pipe(
map((updatedContact) => {
// Find the index of the updated contact
const index = contacts.findIndex(item => item.id === id);
// Update the contact
contacts[index] = updatedContact;
// Update the contacts
this._contacts.next(contacts);
// Return the updated contact
return updatedContact;
}),
switchMap(updatedContact => this.contact$.pipe(
take(1),
filter(item => item && item.id === id),
tap(() => {
// Update the contact if it's selected
this._contact.next(updatedContact);
// Return the updated contact
return updatedContact;
})
))
))
);
}*/
}

View File

@ -118,7 +118,6 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((brands: InventoryBrand[]) =>
{
// Update the brands
this.brands = brands;
@ -131,7 +130,6 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((categories: InventoryCategory[]) =>
{
// Update the categories
this.categories = categories;
@ -144,7 +142,6 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((pagination: InventoryPagination) =>
{
// Update the pagination
this.pagination = pagination;
@ -160,7 +157,6 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((tags: InventoryTag[]) =>
{
// Update the tags
this.tags = tags;
this.filteredTags = tags;
@ -174,7 +170,6 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((vendors: InventoryVendor[]) =>
{
// Update the vendors
this.vendors = vendors;
@ -279,7 +274,6 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
this._inventoryService.getProductById(productId)
.subscribe((product) =>
{
// Set the selected product
this.selectedProduct = product;
@ -404,7 +398,6 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
this._inventoryService.createTag(tag)
.subscribe((response) =>
{
// Add the tag to the product
this.addTagToProduct(response);
});
@ -514,7 +507,6 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
// Create the product
this._inventoryService.createProduct().subscribe((newProduct) =>
{
// Go to new product
this.selectedProduct = newProduct;
@ -540,7 +532,6 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
// Update the product on the server
this._inventoryService.updateProduct(product.id, product).subscribe(() =>
{
// Show a success message
this.showFlashMessage('success');
});
@ -565,18 +556,15 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
// Subscribe to the confirmation dialog closed action
confirmation.afterClosed().subscribe((result) =>
{
// If the confirm button pressed...
if ( result === 'confirmed' )
{
// Get the product object
const product = this.selectedProductForm.getRawValue();
// Delete the product on the server
this._inventoryService.deleteProduct(product.id).subscribe(() =>
{
// Close the details
this.closeDetails();
});
@ -598,7 +586,6 @@ export class InventoryListComponent implements OnInit, AfterViewInit, OnDestroy
// Hide it after 3 seconds
setTimeout(() =>
{
this.flashMessage = null;
// Mark for check

View File

@ -50,7 +50,6 @@ export class FileManagerDetailsComponent implements OnInit, OnDestroy
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((item: Item) =>
{
// Open the drawer in case it is closed
this._fileManagerListComponent.matDrawer.open();

View File

@ -1,47 +0,0 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot, UrlTree } from '@angular/router';
import { FileManagerDetailsComponent } from 'app/modules/admin/apps/file-manager/details/details.component';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class CanDeactivateFileManagerDetails implements CanDeactivate<FileManagerDetailsComponent>
{
canDeactivate(
component: FileManagerDetailsComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState: RouterStateSnapshot,
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree
{
// Get the next route
let nextRoute: ActivatedRouteSnapshot = nextState.root;
while ( nextRoute.firstChild )
{
nextRoute = nextRoute.firstChild;
}
// If the next state doesn't contain '/file-manager'
// it means we are navigating away from the
// file manager app
if ( !nextState.url.includes('/file-manager') )
{
// Let it navigate
return true;
}
// If we are navigating to another item...
if ( nextState.url.includes('/details') )
{
// Just navigate
return true;
}
// Otherwise...
else
{
// Close the drawer first, and then navigate
return component.closeDrawer().then(() => true);
}
}
}

View File

@ -1,27 +0,0 @@
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatTooltipModule } from '@angular/material/tooltip';
import { RouterModule } from '@angular/router';
import { FileManagerDetailsComponent } from 'app/modules/admin/apps/file-manager/details/details.component';
import { FileManagerComponent } from 'app/modules/admin/apps/file-manager/file-manager.component';
import { fileManagerRoutes } from 'app/modules/admin/apps/file-manager/file-manager.routing';
import { FileManagerListComponent } from 'app/modules/admin/apps/file-manager/list/list.component';
@NgModule({
imports: [
RouterModule.forChild(fileManagerRoutes),
MatButtonModule,
MatIconModule,
MatSidenavModule,
MatTooltipModule,
FileManagerComponent,
FileManagerDetailsComponent,
FileManagerListComponent,
],
})
export class FileManagerModule
{
}

View File

@ -1,131 +0,0 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { FileManagerService } from 'app/modules/admin/apps/file-manager/file-manager.service';
import { Item } from 'app/modules/admin/apps/file-manager/file-manager.types';
import { catchError, Observable, throwError } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class FileManagerItemsResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(private _fileManagerService: FileManagerService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Item[]>
{
return this._fileManagerService.getItems();
}
}
@Injectable({
providedIn: 'root',
})
export class FileManagerFolderResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(
private _router: Router,
private _fileManagerService: FileManagerService,
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Item[]>
{
return this._fileManagerService.getItems(route.paramMap.get('folderId'))
.pipe(
// Error here means the requested task is not available
catchError((error) =>
{
// Log the error
console.error(error);
// Get the parent url
const parentUrl = state.url.split('/').slice(0, -1).join('/');
// Navigate to there
this._router.navigateByUrl(parentUrl);
// Throw an error
return throwError(error);
}),
);
}
}
@Injectable({
providedIn: 'root',
})
export class FileManagerItemResolver implements Resolve<any>
{
/**
* Constructor
*/
constructor(
private _router: Router,
private _fileManagerService: FileManagerService,
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Resolver
*
* @param route
* @param state
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Item>
{
return this._fileManagerService.getItemById(route.paramMap.get('id'))
.pipe(
// Error here means the requested task is not available
catchError((error) =>
{
// Log the error
console.error(error);
// Get the parent url
const parentUrl = state.url.split('/').slice(0, -1).join('/');
// Navigate to there
this._router.navigateByUrl(parentUrl);
// Throw an error
return throwError(error);
}),
);
}
}

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