orgnanization onboarding stepper form changes, code refactor for custom data-table grid
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
@if (loadingService.isLoading()) {
|
||||
<div class="fixed inset-0 z-[9999] flex items-center justify-center bg-black/20">
|
||||
<button type="button" class="ti-btn ti-btn-disabled ti-btn-primary-full" disabled>
|
||||
<span class="ti-spinner text-white" role="status" aria-label="loading"></span>
|
||||
<span>Loading...</span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Component,inject } from '@angular/core';
|
||||
import { LoadingService } from '../../../core/services/loading.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-loader',
|
||||
imports: [],
|
||||
standalone: true,
|
||||
templateUrl: './app-loader.html',
|
||||
styleUrl: './app-loader.scss',
|
||||
})
|
||||
export class AppLoader {
|
||||
readonly loadingService = inject(LoadingService);
|
||||
}
|
||||
@@ -23,9 +23,7 @@
|
||||
}
|
||||
|
||||
:host-context(.modern-modal-footer) button.ti-btn-primary-full,
|
||||
:host-context(.modern-modal-footer) button.ti-btn-success-full,
|
||||
:host-context(.onboarding-action-footer) button.ti-btn-primary-full,
|
||||
:host-context(.onboarding-action-footer) button.ti-btn-success-full {
|
||||
:host-context(.modern-modal-footer) button.ti-btn-success-full {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
@@ -36,17 +34,13 @@
|
||||
}
|
||||
|
||||
:host-context(.modern-modal-footer) button.ti-btn-primary-full:hover:not(:disabled),
|
||||
:host-context(.modern-modal-footer) button.ti-btn-success-full:hover:not(:disabled),
|
||||
:host-context(.onboarding-action-footer) button.ti-btn-primary-full:hover:not(:disabled),
|
||||
:host-context(.onboarding-action-footer) button.ti-btn-success-full:hover:not(:disabled) {
|
||||
:host-context(.modern-modal-footer) button.ti-btn-success-full:hover:not(:disabled) {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 12px 28px rgba(37, 99, 235, .45);
|
||||
}
|
||||
|
||||
:host-context(.modern-modal-footer) button.ti-btn-primary-full::before,
|
||||
:host-context(.modern-modal-footer) button.ti-btn-success-full::before,
|
||||
:host-context(.onboarding-action-footer) button.ti-btn-primary-full::before,
|
||||
:host-context(.onboarding-action-footer) button.ti-btn-success-full::before {
|
||||
:host-context(.modern-modal-footer) button.ti-btn-success-full::before{
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -58,21 +52,20 @@
|
||||
animation: saveButtonShine 2s infinite;
|
||||
}
|
||||
|
||||
:host-context(.modern-modal-footer) button:disabled,
|
||||
:host-context(.onboarding-action-footer) button:disabled {
|
||||
:host-context(.modern-modal-footer) button:disabled {
|
||||
opacity: .55;
|
||||
cursor: not-allowed;
|
||||
transform: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
:host-context(.onboarding-action-footer) button.onboarding-nav-btn {
|
||||
:host-context(.modern-modal-footer) button.onboarding-nav-btn {
|
||||
height: 34px;
|
||||
padding: 0 12px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
:host-context(.onboarding-action-footer) button.onboarding-save-btn:hover:not(:disabled) {
|
||||
:host-context(.modern-modal-footer) button.onboarding-save-btn:hover:not(:disabled) {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 12px 28px rgba(37, 99, 235, .45);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
import { DestroyRef, inject, Injectable, signal } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { Subject, Observable, of } from 'rxjs';
|
||||
import { switchMap, catchError, tap, debounceTime } from 'rxjs/operators';
|
||||
import { DataTableQueryState } from './data-table-query.state';
|
||||
import {
|
||||
DataTablePageEvent,
|
||||
DataTableQuery,
|
||||
DataTableRecord,
|
||||
DataTableResult,
|
||||
DataTableSortEvent
|
||||
} from './data-table.types';
|
||||
|
||||
export interface DataTableStoreOptions<TItem, TRow extends DataTableRecord> {
|
||||
fetcher: (query: DataTableQuery) => Observable<DataTableResult<TItem>>;
|
||||
mapRow?: (item: TItem, serialNumber: number, query: DataTableQuery) => TRow;
|
||||
onError?: (error: unknown) => void;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class DataTableStore<TItem, TRow extends DataTableRecord = TItem & DataTableRecord> {
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
private readonly querySubject$ = new Subject<DataTableQuery>();
|
||||
|
||||
readonly queryState = new DataTableQueryState();
|
||||
readonly rows = signal<TRow[]>([]);
|
||||
readonly totalRecords = signal<number>(0);
|
||||
readonly filteredRecords = signal<number>(0);
|
||||
readonly loading = signal<boolean>(false);
|
||||
|
||||
readonly showModal = signal<boolean>(false);
|
||||
readonly modalMode = signal<'create' | 'edit' | 'view'>('create');
|
||||
readonly selectedItem = signal<TItem | null>(null);
|
||||
readonly saving = signal<boolean>(false);
|
||||
|
||||
initialize(options: DataTableStoreOptions<TItem, TRow>): void {
|
||||
this.querySubject$
|
||||
.pipe(
|
||||
debounceTime(50),
|
||||
tap(() => this.loading.set(true)),
|
||||
switchMap(query =>
|
||||
options.fetcher(query).pipe(
|
||||
catchError(err => {
|
||||
this.rows.set([]);
|
||||
this.totalRecords.set(0);
|
||||
this.filteredRecords.set(0);
|
||||
if (options.onError) {
|
||||
options.onError(err);
|
||||
}
|
||||
return of(null);
|
||||
})
|
||||
)
|
||||
),
|
||||
takeUntilDestroyed(this.destroyRef)
|
||||
)
|
||||
.subscribe(response => {
|
||||
this.loading.set(false);
|
||||
if (!response) return;
|
||||
|
||||
const currentQuery = this.queryState.getQuery();
|
||||
if (response.draw !== currentQuery.draw) return;
|
||||
|
||||
const mappedRows: TRow[] = response.rows.map((item, index) => {
|
||||
const serialNumber = (currentQuery.page - 1) * currentQuery.pageSize + index + 1;
|
||||
if (options.mapRow) {
|
||||
return options.mapRow(item, serialNumber, currentQuery);
|
||||
}
|
||||
return {
|
||||
...(item as unknown as TRow),
|
||||
serialNumber
|
||||
};
|
||||
});
|
||||
|
||||
this.rows.set(mappedRows);
|
||||
this.totalRecords.set(response.total);
|
||||
this.filteredRecords.set(response.filtered);
|
||||
});
|
||||
|
||||
this.load(this.queryState.getQuery());
|
||||
}
|
||||
|
||||
load(query: DataTableQuery): void {
|
||||
this.querySubject$.next(query);
|
||||
}
|
||||
|
||||
onSearch(value: string): void {
|
||||
const query = this.queryState.setSearch(value.trim());
|
||||
this.load(query);
|
||||
}
|
||||
|
||||
onPageChange(event: DataTablePageEvent): void {
|
||||
const query = this.queryState.setPage(event);
|
||||
this.load(query);
|
||||
}
|
||||
|
||||
onSortChange(event: DataTableSortEvent): void {
|
||||
const query = this.queryState.setSort(event);
|
||||
this.load(query);
|
||||
}
|
||||
|
||||
refresh(): void {
|
||||
const query = this.queryState.getQuery();
|
||||
this.load(query);
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
const query = this.queryState.reset();
|
||||
this.load(query);
|
||||
}
|
||||
|
||||
openCreateModal(): void {
|
||||
this.modalMode.set('create');
|
||||
this.selectedItem.set(null);
|
||||
this.showModal.set(true);
|
||||
}
|
||||
|
||||
openEditModal(item: TItem): void {
|
||||
this.modalMode.set('edit');
|
||||
this.selectedItem.set(item);
|
||||
this.showModal.set(true);
|
||||
}
|
||||
|
||||
openViewModal(item: TItem): void {
|
||||
this.modalMode.set('view');
|
||||
this.selectedItem.set(item);
|
||||
this.showModal.set(true);
|
||||
}
|
||||
|
||||
closeModal(): void {
|
||||
if (this.saving()) return;
|
||||
this.showModal.set(false);
|
||||
this.selectedItem.set(null);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<!-- Footer Start -->
|
||||
<footer
|
||||
class="footer mt-auto xl:ps-[15rem] font-normal font-inter bg-white text-defaultsize leading-normal text-[0.813] shadow-[0_0_0.4rem_rgba(0,0,0,0.1)] dark:!bg-bodybg py-4 text-center">
|
||||
<div class="container">
|
||||
<span class=" dark:text-defaulttextcolor/50"> Copyright © <span id="year">{{fullyear}}</span> <a
|
||||
href="javascript:void(0);" class="text-defaulttextcolor font-semibold dark:text-defaulttextcolor"> Ynex</a>.
|
||||
Designed with <span class="bi bi-heart-fill text-danger"></span> by <a href="javascript:void(0);">
|
||||
<span class="font-semibold text-primary underline">Spruko</span>
|
||||
</a> All
|
||||
rights
|
||||
reserved
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
<!-- Footer End -->
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-footer',
|
||||
templateUrl: './footer.html',
|
||||
styleUrl: './footer.scss'
|
||||
})
|
||||
export class Footer {
|
||||
fullyear=new Date().getFullYear()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,524 +0,0 @@
|
||||
<!-- Start::Header -->
|
||||
<header class="app-header">
|
||||
<nav class="main-header !h-[3.75rem]" aria-label="Global">
|
||||
<div class="main-header-container ps-[0.725rem] pe-[1rem] ">
|
||||
|
||||
<div class="header-content-left">
|
||||
<!-- Start::header-element -->
|
||||
<div class="header-element">
|
||||
<div class="horizontal-logo">
|
||||
<a routerLink="/dashboards/crm" class="header-logo">
|
||||
<img src="./assets/images/brand-logos/desktop-logo.png" alt="logo" class="desktop-logo">
|
||||
<img src="./assets/images/brand-logos/toggle-logo.png" alt="logo" class="toggle-logo">
|
||||
<img src="./assets/images/brand-logos/desktop-dark.png" alt="logo" class="desktop-dark">
|
||||
<img src="./assets/images/brand-logos/toggle-dark.png" alt="logo" class="toggle-dark">
|
||||
<img src="./assets/images/brand-logos/desktop-white.png" alt="logo" class="desktop-white">
|
||||
<img src="./assets/images/brand-logos/toggle-white.png" alt="logo" class="toggle-white">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End::header-element -->
|
||||
<!-- Start::header-element -->
|
||||
<div class="header-element md:px-[0.325rem] !items-center">
|
||||
<!-- Start::header-link -->
|
||||
<a aria-label="Hide Sidebar"
|
||||
class="sidemenu-toggle animated-arrow hor-toggle horizontal-navtoggle inline-flex items-center focus-visible:outline-none"
|
||||
(click)="toggleSidebar()" href="javascript:void(0);"><span></span></a>
|
||||
<!-- End::header-link -->
|
||||
</div>
|
||||
<!-- End::header-element -->
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="header-content-right">
|
||||
|
||||
<div class="header-element py-[1rem] md:px-[0.65rem] px-2 header-search">
|
||||
<button aria-label="button" type="button" data-hs-overlay="#search-modal"
|
||||
class="inline-flex flex-shrink-0 justify-center items-center gap-2 rounded-full font-medium focus:ring-offset-0 focus:ring-offset-white transition-all text-xs dark:bg-bgdark dark:hover:bg-black/20 dark:text-[#8c9097] dark:text-white/50 dark:hover:text-white dark:focus:ring-white/10 dark:focus:ring-offset-white/10">
|
||||
<i class="bx bx-search-alt-2 header-link-icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- start header country -->
|
||||
<div
|
||||
class="header-element py-[1rem] md:px-[0.65rem] px-2 header-country hs-dropdown ti-dropdown hidden sm:block [--placement:bottom-right] rtl:[--placement:bottom-left]">
|
||||
<button id="dropdown-flag" type="button"
|
||||
class="hs-dropdown-toggle ti-dropdown-toggle !p-0 flex-shrink-0 !border-0 !rounded-full !shadow-none">
|
||||
<img src="./assets/images/flags/us_flag.jpg" alt="flag-img" class="h-[1.25rem] w-[1.25rem] rounded-full">
|
||||
</button>
|
||||
|
||||
<div class="hs-dropdown-menu ti-dropdown-menu min-w-[10rem] hidden !-mt-3" aria-labelledby="dropdown-flag">
|
||||
<div class="ti-dropdown-divider divide-y divide-gray-200 dark:divide-white/10">
|
||||
<div class="py-2 first:pt-0 last:pb-0">
|
||||
@for (lang of headeData.languages; track $index) {
|
||||
<div class="ti-dropdown-item !p-[0.65rem] hover:cursor-pointer">
|
||||
<div class="flex items-center space-x-2 w-full">
|
||||
<div class="h-[1.375rem] w-[1.375rem] flex items-center rounded-full">
|
||||
<img [src]="lang.flag" [alt]="lang.name + ' flag'" class="h-[1rem] w-[1rem] rounded-full">
|
||||
</div>
|
||||
<div>
|
||||
<p class="!text-[0.8125rem] font-medium">
|
||||
{{ lang.name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end header country -->
|
||||
|
||||
<!-- light and dark theme -->
|
||||
<div class="header-element header-theme-mode hidden !items-center sm:block !py-[1rem] md:!px-[0.65rem] px-2">
|
||||
<a aria-label="anchor"
|
||||
class="hs-dark-mode-active:hidden flex hs-dark-mode group flex-shrink-0 justify-center items-center gap-2 rounded-full font-medium transition-all text-xs dark:bg-bgdark dark:hover:bg-black/20 dark:text-[#8c9097] dark:text-white/50 dark:hover:text-white dark:focus:ring-white/10 dark:focus:ring-offset-white/10"
|
||||
href="javascript:void(0);" (click)="updateTheme('dark')">
|
||||
<i class="bx bx-moon header-link-icon"></i>
|
||||
</a>
|
||||
<a aria-label="anchor"
|
||||
class="hs-dark-mode-active:flex hidden hs-dark-mode group flex-shrink-0 justify-center items-center gap-2 rounded-full font-medium text-defaulttextcolor transition-all text-xs dark:bg-bodybg dark:bg-bgdark dark:hover:bg-black/20 dark:text-[#8c9097] dark:text-white/50 dark:hover:text-white dark:focus:ring-white/10 dark:focus:ring-offset-white/10"
|
||||
href="javascript:void(0);" (click)="updateTheme('light')">
|
||||
<i class="bx bx-sun header-link-icon"></i>
|
||||
</a>
|
||||
</div>
|
||||
<!-- End light and dark theme -->
|
||||
|
||||
<!-- Header Cart item -->
|
||||
<div
|
||||
class="header-element cart-dropdown hs-dropdown ti-dropdown md:!block !hidden py-[1rem] md:px-[0.65rem] px-2 [--placement:bottom-right] [--auto-close:true] rtl:[--placement:bottom-left] ">
|
||||
<button id="dropdown-cart" type="button"
|
||||
class="hs-dropdown-toggle relative ti-dropdown-toggle !p-0 !border-0 flex-shrink-0 !rounded-full !shadow-none align-middle text-xs">
|
||||
<i class="bx bx-cart header-link-icon"></i>
|
||||
<span class="flex absolute h-5 w-5 -top-[0.25rem] end-0 -me-[0.6rem]">
|
||||
<span
|
||||
class="relative inline-flex rounded-full h-[14.7px] w-[14px] text-[0.625rem] bg-primary text-white justify-center items-center"
|
||||
id="cart-icon-badge">{{ cartItemCount }}</span>
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
class="main-header-dropdown bg-white !-mt-3 !p-0 hs-dropdown-menu ti-dropdown-menu w-[22rem] border-0 border-defaultborder hidden"
|
||||
aria-labelledby="dropdown-cart">
|
||||
<div class="ti-dropdown-header !bg-transparent flex justify-between items-center !m-0 !p-4">
|
||||
<p class="text-defaulttextcolor !text-[1.0625rem] dark:text-[#8c9097] dark:text-white/50 font-semibold">
|
||||
Cart Items</p>
|
||||
<a href="javascript:void(0);"
|
||||
class="font-[600] py-[0.25/2rem] px-[0.45rem] rounded-[0.25rem] bg-success/10 text-success text-[0.75em] "
|
||||
id="cart-data">{{ cartItemCount }} Items</a>
|
||||
</div>
|
||||
<div>
|
||||
<hr class="dropdown-divider dark:border-white/10">
|
||||
</div>
|
||||
@if(headeData.cartItems.length>0){
|
||||
<ul class="list-none mb-0" id="header-cart-items-scroll">
|
||||
@for (item of headeData.cartItems; track $index) {
|
||||
<li class="ti-dropdown-item border-b dark:border-defaultborder/10 border-defaultborder" [id]="item.id">
|
||||
<div class="flex items-start cart-dropdown-item">
|
||||
|
||||
<img [src]="item.img" alt="img"
|
||||
class="!h-[1.75rem] !w-[1.75rem] leading-[1.75rem] text-[0.65rem] rounded-[50%] br-5 me-3">
|
||||
|
||||
<div class="grow">
|
||||
<div class="flex items-start justify-between mb-0">
|
||||
<div
|
||||
class="mb-0 !text-[0.8125rem] text-[#232323] font-semibold dark:text-[#8c9097] dark:text-white">
|
||||
<a href="javascript:void(0);">{{ item.name }}</a>
|
||||
</div>
|
||||
|
||||
<div class="inline-flex">
|
||||
<span class="text-black mb-1 font-semibold! dark:text-white ">{{ item.price }}</span>
|
||||
<a aria-label="anchor" (click)="removeRow(item.id,$event)"
|
||||
class="header-cart-remove ltr:float-right rtl:float-left dropdown-item-close">
|
||||
<i class="ti ti-trash"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="min-w-fit flex items-start justify-between">
|
||||
<ul class="header-product-item dark:text-white/50 flex gap-2">
|
||||
@for (tag of item.tags; track $index) {
|
||||
<li>{{ tag }}</li>
|
||||
}
|
||||
@if (item.freeShipping) {
|
||||
<li>
|
||||
<span
|
||||
class="font-[600] py-[0.25rem] px-[0.45rem] rounded-[0.25rem] bg-pink/10 text-pink text-[0.625rem]">
|
||||
Free shipping
|
||||
</span>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
@if(cartItemCount > 0){
|
||||
|
||||
<div class="p-3 empty-header-item ">
|
||||
<div class="grid">
|
||||
<a href="javascript:void(0);" class="w-full ti-btn ti-btn-primary-full p-2">Proceed to
|
||||
checkout</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@else {
|
||||
<div class="p-[3rem] empty-item ">
|
||||
<div class="text-center">
|
||||
<span class="!w-[4rem] !h-[4rem] !leading-[4rem] rounded-[50%] avatar bg-warning/10 !text-warning">
|
||||
<i class="ri-shopping-cart-2-line text-[2rem]"></i>
|
||||
</span>
|
||||
<h6 class="font-bold mb-1 mt-3 text-[1rem] text-defaulttextcolor dark:text-white">Your Cart is Empty
|
||||
</h6>
|
||||
<span
|
||||
class="mb-3 !font-normal text-[0.8125rem] block text-defaulttextcolor dark:text-[#8c9097] dark:text-white/50">Add
|
||||
some items to make me happy :)</span>
|
||||
<a href="javascript:void(0);"
|
||||
class="ti-btn ti-btn-primary btn-wave ti-btn-wave btn-sm m-1 !text-[0.75rem] !py-[0.25rem] !px-[0.5rem]"
|
||||
data-abc="true">continue shopping <i class="bi bi-arrow-right ms-1"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!--End Header cart item -->
|
||||
|
||||
<!--Header Notifictaion -->
|
||||
<div
|
||||
class="header-element py-[1rem] md:px-[0.65rem] px-2 notifications-dropdown header-notification hs-dropdown ti-dropdown !hidden md:!block [--placement:bottom-right] rtl:[--placement:bottom-left]">
|
||||
<button id="dropdown-notification" type="button"
|
||||
class="hs-dropdown-toggle relative ti-dropdown-toggle !p-0 !border-0 flex-shrink-0 !rounded-full !shadow-none align-middle text-xs">
|
||||
<i class="bx bx-bell header-link-icon text-[1.125rem]"></i>
|
||||
<span class="flex absolute h-5 w-5 -top-[0.25rem] end-0 -me-[0.6rem]">
|
||||
<span
|
||||
class="animate-slow-ping absolute inline-flex -top-[2px] -start-[2px] h-full w-full rounded-full bg-secondary/40 opacity-75"></span>
|
||||
<span
|
||||
class="relative inline-flex justify-center items-center rounded-full h-[14.7px] w-[14px] bg-secondary text-[0.625rem] text-white"
|
||||
id="notification-icon-badge">{{notificationItemCount}}</span>
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
class="main-header-dropdown !-mt-3 !p-0 hs-dropdown-menu ti-dropdown-menu bg-white !w-[22rem] border-0 border-defaultborder dark:!border-defaultborder/10 hidden !m-0"
|
||||
aria-labelledby="dropdown-notification">
|
||||
|
||||
<div class="ti-dropdown-header !m-0 !p-4 !bg-transparent flex justify-between items-center">
|
||||
<p
|
||||
class="mb-0 text-[1.0625rem] text-defaulttextcolor font-semibold dark:text-[#8c9097] dark:text-white/50">
|
||||
Notifications</p>
|
||||
<span
|
||||
class="text-[0.75em] py-[0.25rem/2] px-[0.45rem] font-[600] rounded-sm bg-secondary/10 text-secondary"
|
||||
id="notifiation-data">{{notificationItemCount}} Unread</span>
|
||||
</div>
|
||||
<div class="dropdown-divider "></div>
|
||||
<ul class="list-none !m-0 !p-0 end-0" id="header-notification-scroll" (click)="handleCardClick($event)">
|
||||
@for (item of headeData.notifications; track $index) {
|
||||
<li class="ti-dropdown-item dropdown-item !block">
|
||||
<div class="flex items-start">
|
||||
<div class="pe-2">
|
||||
<span
|
||||
[class]="`inline-flex justify-center items-center !w-[2.5rem] !h-[2.5rem] !leading-[2.5rem] !text-[0.8rem] rounded-[50%] ${item.colorClass} ${item.bgClass}`">
|
||||
<i [class]="`ti ${item.icon} text-[1.125rem]`"></i>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="grow flex items-center justify-between">
|
||||
<div>
|
||||
<p class="mb-0 text-defaulttextcolor dark:text-white text-[0.8125rem] font-semibold">
|
||||
<a href="javascript:void(0);">{{ item.title }} </a>
|
||||
@if(item.orderId){
|
||||
<span [class]="item.colorClass">ID:{{item.orderId}}</span>
|
||||
}
|
||||
</p>
|
||||
<span class="text-[#8c9097] dark:text-white/50 font-normal text-[0.75rem]">
|
||||
{{ item.description }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a href="javascript:void(0);" (click)="removeNotification(item.id, $event)"
|
||||
class="min-w-fit text-[#8c9097] dark:text-white/50 me-1">
|
||||
<i class="ti ti-x text-[1rem]"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
@if (headeData.notifications.length > 0){
|
||||
<div class="p-4 empty-header-item1 mt-2 border-t border-defaultborder dark:border-defaultborder/10">
|
||||
<div class="grid">
|
||||
<a href="javascript:void(0);" class="ti-btn ti-btn-primary-full !m-0 w-full p-2">View All</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (headeData.notifications.length === 0){
|
||||
|
||||
<div class="p-[3rem] empty-item1 ">
|
||||
<div class="text-center">
|
||||
<span
|
||||
class="!h-[4rem] !w-[4rem] avatar !leading-[4rem] !rounded-full !bg-secondary/10 !text-secondary">
|
||||
<i class="ri-notification-off-line text-[2rem] "></i>
|
||||
</span>
|
||||
<h6 class="font-semibold mt-3 text-defaulttextcolor dark:text-white text-[1rem]">No New Notifications
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<!--End Header Notifictaion -->
|
||||
|
||||
<!-- Related Apps -->
|
||||
<div
|
||||
class="header-element header-apps dark:text-[#8c9097] dark:text-white/50 py-[1rem] md:px-[0.65rem] px-2 hs-dropdown ti-dropdown md:!block !hidden [--placement:bottom-left] [--auto-close:true]">
|
||||
|
||||
<button aria-label="button" id="dropdown-apps" type="button"
|
||||
class="hs-dropdown-toggle ti-dropdown-toggle !p-0 !border-0 flex-shrink-0 !rounded-full !shadow-none text-xs">
|
||||
<i class="bx bx-grid-alt header-link-icon text-[1.125rem]"></i>
|
||||
</button>
|
||||
|
||||
<div
|
||||
class="main-header-dropdown !-mt-3 hs-dropdown-menu ti-dropdown-menu !w-[22rem] border-0 border-defaultborder hidden"
|
||||
aria-labelledby="dropdown-apps">
|
||||
|
||||
<div class="p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<p
|
||||
class="mb-0 text-defaulttextcolor text-[1.0625rem] dark:text-[#8c9097] dark:text-white/50 font-semibold">
|
||||
Related Apps</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown-divider mb-0"></div>
|
||||
<div class="ti-dropdown-divider divide-y divide-gray-200 dark:divide-white/10 main-header-shortcuts p-2"
|
||||
id="header-shortcut-scroll">
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
@for (app of headeData.relatedApps; track $index) {
|
||||
<div class="">
|
||||
<a href="javascript:void(0);"
|
||||
class="p-4 items-center related-app block text-center rounded-sm hover:!bg-gray-100 dark:hover:!bg-black/20">
|
||||
<div>
|
||||
<img [src]="app.img" [alt]="app.alt"
|
||||
class="!h-[1.75rem] !w-[1.75rem] text-2xl avatar text-primary flex justify-center items-center mx-auto">
|
||||
<div class="text-[0.75rem] text-defaulttextcolor dark:text-[#8c9097] dark:text-white/50">
|
||||
{{ app.name }}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-4 first:pt-0 border-t border-defaultborder dark:border-defaultborder/10">
|
||||
<a class="w-full ti-btn ti-btn-primary-full p-2 !m-0" href="javascript:void(0);">
|
||||
View All
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!--End Related Apps -->
|
||||
|
||||
<!-- Fullscreen -->
|
||||
<div class="header-element header-fullscreen py-[1rem] md:px-[0.65rem] px-2" appFullscreen>
|
||||
<!-- Start::header-link -->
|
||||
<a aria-label="anchor" (click)="toggleFullscreen()" href="javascript:void(0);"
|
||||
class="inline-flex flex-shrink-0 justify-center items-center gap-2 !rounded-full font-medium dark:hover:bg-black/20 dark:text-[#8c9097] dark:text-white/50 dark:hover:text-white dark:focus:ring-white/10 dark:focus:ring-offset-white/10">
|
||||
@if (isFullscreen) {
|
||||
<i class="bx bx-exit-fullscreen full-screen-close header-link-icon hidden"></i>
|
||||
} @else {
|
||||
<i class="bx bx-fullscreen full-screen-open header-link-icon"></i>
|
||||
}
|
||||
</a>
|
||||
<!-- End::header-link -->
|
||||
</div>
|
||||
<!-- End Full screen -->
|
||||
|
||||
<!-- Header Profile -->
|
||||
<div
|
||||
class="header-element md:!px-[0.65rem] px-2 hs-dropdown !items-center ti-dropdown [--placement:bottom-right]">
|
||||
|
||||
<button id="dropdown-profile" type="button"
|
||||
class="hs-dropdown-toggle ti-dropdown-toggle !gap-2 !p-0 flex-shrink-0 !rounded-full !shadow-none text-xs align-middle !border-0 !shadow-transparent hover:!bg-transparent ">
|
||||
<img class="inline-block rounded-full " src="./assets/images/faces/9.jpg" width="32" height="32"
|
||||
alt="Image Description">
|
||||
<div class="md:block hidden dropdown-profile">
|
||||
<p class="font-semibold mb-0 leading-none text-[#536485] text-[0.813rem] ">{{ getDisplayName() }}</p>
|
||||
<span class="opacity-[0.7] font-normal text-[#536485] block text-[0.6875rem] ">{{ getPrimaryRole() }}</span>
|
||||
</div>
|
||||
</button>
|
||||
<div
|
||||
class="hs-dropdown-menu ti-dropdown-menu !-mt-3 border-0 w-[11rem] !p-0 border-defaultborder hidden main-header-dropdown pt-0 overflow-hidden header-profile-dropdown dropdown-menu-end"
|
||||
aria-labelledby="dropdown-profile">
|
||||
|
||||
<ul class="text-defaulttextcolor font-medium dark:text-[#8c9097] dark:text-white/50">
|
||||
@for (item of headeData.menuItems; track $index) {
|
||||
<li>
|
||||
<a href="javascript:void(0);" (click)="handleProfileItemClick(item, $event)"
|
||||
class="w-full ti-dropdown-item !text-[0.8125rem] !gap-x-0 !p-[0.65rem] !inline-flex">
|
||||
|
||||
<i class="ti {{ item.icon }} text-[1.125rem] me-2 opacity-[0.7]"></i>
|
||||
|
||||
{{ item.label }}
|
||||
|
||||
@if (item.badge) {
|
||||
<span
|
||||
class="!py-1 !px-[0.45rem] !font-semibold !rounded-sm text-success text-[0.75em] bg-success/10 ms-auto">
|
||||
{{ item.badge }}
|
||||
</span>
|
||||
}
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Header Profile -->
|
||||
|
||||
<!-- Switcher Icon -->
|
||||
<div class="header-element md:px-[0.48rem]">
|
||||
<button aria-label="button" type="button"
|
||||
class="hs-dropdown-toggle switcher-icon focus-visible:outline-none inline-flex flex-shrink-0 justify-center items-center gap-2 rounded-full font-medium align-middle transition-all text-xs dark:text-[#8c9097] dark:text-white/50 dark:hover:text-white dark:focus:ring-white/10 dark:focus:ring-offset-white/10"
|
||||
data-hs-overlay="#hs-overlay-switcher" data-hs-overlay-options='{
|
||||
"backdrop": true,
|
||||
"isClosePrev": true
|
||||
}'>
|
||||
<i class="bx bx-cog header-link-icon animate-spin-slow !p-0 !block"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Switcher Icon -->
|
||||
|
||||
|
||||
<!-- End::header-element -->
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<!-- End::Header -->
|
||||
|
||||
|
||||
|
||||
<div id="search-modal"
|
||||
class="hs-overlay ti-modal hidden mt-[1.75rem] hs-overlay-backdrop-open:!bg-[#32325180] dark:hs-overlay-backdrop-open:!bg-[#323251cc] pointer-events-none">
|
||||
<div class="ti-modal-box pointer-events-auto">
|
||||
<div class="ti-modal-content !border !border-defaultborder dark:!border-defaultborder/10 !rounded-[0.5rem]">
|
||||
<div class="ti-modal-body">
|
||||
|
||||
<div class="input-group border-[2px] border-primary rounded-[0.25rem] w-full flex">
|
||||
<a aria-label="anchor" href="javascript:void(0);"
|
||||
class="input-group-text flex items-center bg-light border-e-[#dee2e6] !py-[0.375rem] border-0! !px-[0.75rem] !rounded-none !text-[0.875rem]"
|
||||
id="Search-Grid">
|
||||
<i class="fe fe-search header-link-icon text-[0.875rem]"></i>
|
||||
</a>
|
||||
|
||||
<input type="search" class="form-control border-0! px-2 !text-[0.8rem] w-full focus:ring-transparent"
|
||||
placeholder="Search" aria-label="Username" [(ngModel)]="text" (keyup)="Search(text)" type="search">
|
||||
|
||||
<a aria-label="anchor" href="javascript:void(0);"
|
||||
class="flex items-center input-group-text bg-light !py-[0.375rem] !px-[0.75rem]" id="voice-search"><i
|
||||
class="fe fe-mic header-link-icon"></i></a>
|
||||
<div class="hs-dropdown ti-dropdown">
|
||||
<a aria-label="anchor" href="javascript:void(0);"
|
||||
class="flex items-center hs-dropdown-toggle ti-dropdown-toggle border-0! border-defaultborder dark:border-defaultborder/10 btn btn-light btn-icon !bg-light !py-[0.375rem] !rounded-none !px-[0.75rem] text-[0.95rem] h-[2.413rem] w-[2.313rem]">
|
||||
<i class="fe fe-more-vertical"></i>
|
||||
</a>
|
||||
|
||||
<ul class="absolute hs-dropdown-menu ti-dropdown-menu !-mt-2 !p-0 hidden">
|
||||
<li><a
|
||||
class="ti-dropdown-item flex text-defaulttextcolor dark:text-defaulttextcolor/70 !py-[0.5rem] !px-[0.9375rem] !text-[0.8125rem] font-medium"
|
||||
href="javascript:void(0);">Action</a></li>
|
||||
<li><a
|
||||
class="ti-dropdown-item flex text-defaulttextcolor dark:text-defaulttextcolor/70 !py-[0.5rem] !px-[0.9375rem] !text-[0.8125rem] font-medium"
|
||||
href="javascript:void(0);">Another action</a></li>
|
||||
<li><a
|
||||
class="ti-dropdown-item flex text-defaulttextcolor dark:text-defaulttextcolor/70 !py-[0.5rem] !px-[0.9375rem] !text-[0.8125rem] font-medium"
|
||||
href="javascript:void(0);">Something else here</a></li>
|
||||
<li>
|
||||
<hr class="dropdown-divider">
|
||||
</li>
|
||||
<li><a
|
||||
class="ti-dropdown-item flex text-defaulttextcolor dark:text-defaulttextcolor/70 !py-[0.5rem] !px-[0.9375rem] !text-[0.8125rem] font-medium"
|
||||
href="javascript:void(0);">Separated link</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mt-5">
|
||||
<p class="font-normal text-[#8c9097] dark:text-white/50 text-[0.813rem] dark:text-gray-200 mb-2">Are You
|
||||
Looking For...</p>
|
||||
@if (menuItems && menuItems.length > 0) {
|
||||
|
||||
<div
|
||||
class=" w-full mb-2! bg-white dark:!bg-bodybg shadow-md top-[2.5rem] !rounded-s rounded-md border border-defaultborder dark:!border-defaultborder/10">
|
||||
|
||||
<ul class="divide-y divide-gray-200">
|
||||
@for (menuItem of menuItems | slice:0:5;track $index) {
|
||||
|
||||
<li [routerLink]="menuItem?.path"
|
||||
class="p-3 dark:!border-defaultborder/10 cursor-pointer flex items-center hover:bg-primary hover:text-white "
|
||||
(click)="clearSearch()">
|
||||
<i class="fe fe-chevrons-right mx-1 customsearcharrow rtl:rotate-[180deg]"></i>
|
||||
<span class="truncate">{{ menuItem?.title }}</span>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
@for (tag of headeData.searchTags; track tag.id) {
|
||||
<span class="search-tags text-[0.75rem] !py-[0rem] !px-[0.55rem] border-defaultborder dark:!border-defaultborder/10">
|
||||
<i class="fe {{tag.icon}} me-2"></i> {{tag.label}}
|
||||
<a href="javascript:void(0);" (click)="removeAlert(headeData.searchTags,tag.id)" class="tag-addon header-remove-btn">
|
||||
<span class="sr-only">Remove badge</span><i class="fe fe-x text-[10px]"></i>
|
||||
</a>
|
||||
</span>
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="my-[1.5rem]">
|
||||
<p class="font-normal text-[#8c9097] dark:text-white/50 text-[0.813rem] mb-2">Recent Search :</p>
|
||||
|
||||
@for (alert of headeData.alertItems; track alert.id) {
|
||||
<div role="alert"
|
||||
class="!p-2 border border-defaultborder dark:border-defaultborder/10 rounded-[0.3125rem] flex items-center text-defaulttextcolor dark:text-defaulttextcolor/70 !mb-2 !text-[0.8125rem] alert">
|
||||
|
||||
<a [routerLink]="alert.link">
|
||||
<span>{{ alert.label }}</span>
|
||||
</a>
|
||||
|
||||
<a (click)="removeAlert(headeData.alertItems,alert.id)" aria-label="anchor"
|
||||
class="ms-auto leading-none cursor-pointer" href="javascript:void(0);">
|
||||
<i class="fe fe-x !text-[0.8125rem] text-[#8c9097] dark:text-white/50"></i>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ti-modal-footer !border !border-defaultborder dark:!border-defaultborder/10 !py-[1rem] !px-[1.25rem]">
|
||||
<div class="inline-flex rounded-md shadow-sm">
|
||||
<button type="button"
|
||||
class="ti-btn-group focus-visible:outline-none !px-[0.75rem] !py-[0.45rem] rounded-s-[0.25rem] !rounded-e-none ti-btn-primary !text-[0.75rem] dark:border-white/10">
|
||||
Search
|
||||
</button>
|
||||
<button type="button"
|
||||
class="ti-btn-group ti-btn-primary-full rounded-e-[0.25rem] dark:border-white/10 !text-[0.75rem] !rounded-s-none !px-[0.75rem] !py-[0.45rem]">
|
||||
Clear Recents
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1,318 +0,0 @@
|
||||
import { Component, DOCUMENT, ElementRef, Renderer2, inject } from '@angular/core';
|
||||
import { Menu, NavService } from '../../services/nav.service';
|
||||
import * as headeData from "./headerdata"
|
||||
import { AppStateService } from '../../services/app-state.service';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { FullscreenDirective } from '../../directives/fullscreen.directive';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { SlicePipe } from '@angular/common';
|
||||
import { AuthService } from '../../../core/auth/auth.service';
|
||||
interface Item {
|
||||
id: number;
|
||||
name: string;
|
||||
type: string;
|
||||
title: string;
|
||||
// Add other properties as needed
|
||||
}
|
||||
declare const HSStaticMethods: any;
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
templateUrl: './header.html',
|
||||
styleUrls: ['./header.scss'],
|
||||
imports: [RouterLink, FullscreenDirective, FormsModule, SlicePipe]
|
||||
})
|
||||
|
||||
export class Header {
|
||||
headeData = headeData;
|
||||
public menuItems!: Menu[];
|
||||
public menuitemsSubscribe$!: Subscription;
|
||||
public NavServices = inject(NavService)
|
||||
private appStateService = inject(AppStateService)
|
||||
private readonly authService = inject(AuthService);
|
||||
private readonly router = inject(Router);
|
||||
readonly currentUser = this.authService.currentUserSignal;
|
||||
Selector = (selector: any) => document.querySelector(selector);
|
||||
|
||||
SelectorAll = (selector: any) => document.querySelectorAll(selector);
|
||||
|
||||
private doc = inject(DOCUMENT);
|
||||
toggleSidebar() {
|
||||
const html = this.doc.documentElement;
|
||||
// Check the window width
|
||||
if (window.innerWidth <= 992) {
|
||||
let dataToggled = html.getAttribute("data-toggled");
|
||||
|
||||
if (dataToggled == "open") {
|
||||
html.setAttribute("data-toggled", "close");
|
||||
} else {
|
||||
html.setAttribute("data-toggled", "open");
|
||||
}
|
||||
}
|
||||
else {
|
||||
let menuNavLayoutType = html.getAttribute("data-nav-style");
|
||||
let verticalStyleType = html.getAttribute("data-vertical-style");
|
||||
|
||||
if (menuNavLayoutType) {
|
||||
let dataToggled = html.getAttribute("data-toggled");
|
||||
if (dataToggled) {
|
||||
html.removeAttribute("data-toggled");
|
||||
} else {
|
||||
html.setAttribute(
|
||||
"data-toggled",
|
||||
menuNavLayoutType + "-closed",
|
||||
);
|
||||
}
|
||||
} else if (verticalStyleType) {
|
||||
let dataToggled = html.getAttribute("data-toggled");
|
||||
|
||||
if (verticalStyleType == "doublemenu") {
|
||||
if (
|
||||
html.getAttribute("data-toggled") === "double-menu-open" && this.Selector(".double-menu-active")) {
|
||||
html.setAttribute("data-toggled", "double-menu-close");
|
||||
} else {
|
||||
if (this.Selector(".double-menu-active")) { html.setAttribute("data-toggled", "double-menu-open"); }
|
||||
}
|
||||
} else if (dataToggled) {
|
||||
html.removeAttribute("data-toggled");
|
||||
} else {
|
||||
switch (verticalStyleType) {
|
||||
case "closed":
|
||||
html.setAttribute(
|
||||
"data-toggled",
|
||||
"close-menu-close",
|
||||
);
|
||||
break;
|
||||
case "icontext":
|
||||
html.setAttribute(
|
||||
"data-toggled",
|
||||
"icon-text-close",
|
||||
);
|
||||
break;
|
||||
case "overlay":
|
||||
html.setAttribute(
|
||||
"data-toggled",
|
||||
"icon-overlay-close",
|
||||
);
|
||||
break;
|
||||
case "detached":
|
||||
html.setAttribute("data-toggled", "detached-close");
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public items: Menu[] = []; // Your full menu data (source)
|
||||
public text: string = '';
|
||||
public SearchResultEmpty: boolean = false;
|
||||
public isDropdownVisible: boolean = false;
|
||||
Search(searchText: string) {
|
||||
// 2. Safety Check: If search is empty or source data hasn't loaded
|
||||
if (!searchText || !this.items) {
|
||||
this.menuItems = [];
|
||||
this.SearchResultEmpty = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const results: Menu[] = [];
|
||||
const query = searchText.toLowerCase().trim();
|
||||
|
||||
// 3. Deep search through 3 levels of menu
|
||||
this.items.forEach((level1: Menu) => {
|
||||
// Check Level 1
|
||||
if (level1.title?.toLowerCase().includes(query)) {
|
||||
results.push(level1);
|
||||
}
|
||||
|
||||
// Check Level 2 (Children)
|
||||
if (level1.children) {
|
||||
level1.children.forEach((level2: Menu) => {
|
||||
if (level2.title?.toLowerCase().includes(query)) {
|
||||
results.push(level2);
|
||||
}
|
||||
|
||||
// Check Level 3 (Sub-children)
|
||||
if (level2.children) {
|
||||
level2.children.forEach((level3: Menu) => {
|
||||
if (level3.title?.toLowerCase().includes(query)) {
|
||||
results.push(level3);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 4. Update UI State
|
||||
this.menuItems = results;
|
||||
this.SearchResultEmpty = results.length === 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Used to clear previous search result
|
||||
clearSearch() {
|
||||
const headerSearch = this.Selector('.header-search');
|
||||
if (headerSearch) {
|
||||
headerSearch.classList.remove('searchdrop');
|
||||
}
|
||||
this.text = '';
|
||||
this.menuItems = [];
|
||||
this.SearchResultEmpty = false;
|
||||
return this.text, this.menuItems;
|
||||
|
||||
}
|
||||
|
||||
updateTheme(theme: string) {
|
||||
|
||||
|
||||
this.appStateService.updateState({ theme, menuColor: theme, headerColor: theme });
|
||||
if (theme == 'light') {
|
||||
this.appStateService.updateState({ theme, themeBackground: '', headerColor: 'light', menuColor: 'dark' });
|
||||
let html = document.querySelector('html');
|
||||
html?.style.removeProperty('--color-bodybg');
|
||||
html?.style.removeProperty('--color-bodybg2');
|
||||
html?.style.removeProperty('--color-light');
|
||||
html?.style.removeProperty('--color-formcontrolbg');
|
||||
html?.style.removeProperty('--color-inputborder');
|
||||
html?.style.removeProperty('--color-gray3');
|
||||
if (window.innerWidth <= 992) {
|
||||
html?.setAttribute('data-toggled', 'close');
|
||||
}
|
||||
}
|
||||
if (theme == 'dark') {
|
||||
this.appStateService.updateState({ theme, themeBackground: '', headerColor: 'dark', menuColor: 'dark' });
|
||||
let html = document.querySelector('html');
|
||||
html?.style.removeProperty('--color-bodybg');
|
||||
html?.style.removeProperty('--color-bodybg2');
|
||||
html?.style.removeProperty('--color-light');
|
||||
html?.style.removeProperty('--color-formcontrolbg');
|
||||
html?.style.removeProperty('--color-inputborder');
|
||||
html?.style.removeProperty('--color-gray3');
|
||||
if (window.innerWidth <= 992) {
|
||||
html?.setAttribute('data-toggled', 'close');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cartItemCount = this.headeData.cartItems.length;
|
||||
notificationItemCount = this.headeData.notifications.length;
|
||||
handleCardClick(event: MouseEvent) {
|
||||
// Prevent the click event from propagating to the container
|
||||
event.stopPropagation();
|
||||
}
|
||||
removeRow(itemId: string,event: MouseEvent) {
|
||||
const index = this.headeData.cartItems.findIndex(i => i.id === itemId);
|
||||
if (index !== -1) {
|
||||
this.headeData.cartItems.splice(index, 1);
|
||||
}
|
||||
this.updateCartItemCount();
|
||||
event.stopPropagation();
|
||||
}
|
||||
updateCartItemCount() {
|
||||
this.cartItemCount = this.headeData.cartItems.length;
|
||||
}
|
||||
|
||||
removeNotification(id: number, event: Event): void {
|
||||
event.preventDefault(); // Prevent link navigation
|
||||
this.headeData.notifications.splice(
|
||||
this.headeData.notifications.findIndex(item => item.id === id),
|
||||
1
|
||||
);
|
||||
|
||||
this.updatenotificationsItemCount();
|
||||
}
|
||||
|
||||
updatenotificationsItemCount() {
|
||||
this.notificationItemCount = this.headeData.notifications.length;
|
||||
}
|
||||
|
||||
isFullscreen: boolean = false;
|
||||
toggleFullscreen() {
|
||||
|
||||
this.isFullscreen = !this.isFullscreen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
removeAlert<T extends { id: string }>(array: T[], id: string): void {
|
||||
const index = array.findIndex(item => item.id === id);
|
||||
|
||||
if (index !== -1) {
|
||||
array.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.NavServices.items.subscribe((menuItems) => {
|
||||
this.items = menuItems;
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
HSStaticMethods.autoInit();
|
||||
}
|
||||
|
||||
getDisplayName(): string {
|
||||
const email = this.currentUser()?.email?.trim();
|
||||
if (email) {
|
||||
const localPart = email.split('@')[0];
|
||||
const formatted = localPart
|
||||
.replace(/[._-]+/g, ' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
|
||||
if (formatted) {
|
||||
return formatted
|
||||
.split(' ')
|
||||
.filter(Boolean)
|
||||
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
||||
.join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
return this.currentUser()?.displayName?.trim() || 'User';
|
||||
}
|
||||
|
||||
getPrimaryRole(): string {
|
||||
const roles = this.currentUser()?.roles;
|
||||
if (roles && roles.length > 0) {
|
||||
const role = roles[0].trim();
|
||||
if (role) {
|
||||
return role
|
||||
.replace(/[_-]+/g, ' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.split(' ')
|
||||
.filter(Boolean)
|
||||
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
||||
.join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
return 'User';
|
||||
}
|
||||
|
||||
handleProfileItemClick(item: { label?: string; link?: string | null }, event: MouseEvent): void {
|
||||
event.preventDefault();
|
||||
|
||||
if (item.label === 'Log Out') {
|
||||
this.logout();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.link) {
|
||||
void this.router.navigateByUrl(item.link);
|
||||
}
|
||||
}
|
||||
|
||||
logout(): void {
|
||||
this.authService.logout();
|
||||
void this.router.navigate(['/auth/login']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
export const languages = [
|
||||
{ name: 'English', flag: './assets/images/flags/us_flag.jpg' },
|
||||
{ name: 'Spanish', flag: './assets/images/flags/spain_flag.jpg' },
|
||||
{ name: 'French', flag: './assets/images/flags/french_flag.jpg' },
|
||||
{ name: 'German', flag: './assets/images/flags/germany_flag.jpg' },
|
||||
{ name: 'Italian', flag: './assets/images/flags/italy_flag.jpg' },
|
||||
{ name: 'Russian', flag: './assets/images/flags/russia_flag.jpg' }
|
||||
];
|
||||
|
||||
|
||||
export const cartItems = [
|
||||
{ id: 'row1', name: 'SomeThing Phone', price: '$1,299.00', img: './assets/images/ecommerce/jpg/1.jpg', tags: ['Metallic Blue', '6gb Ram'] },
|
||||
{ id: 'row2', name: 'Stop Watch', price: '$179.29', img: './assets/images/ecommerce/jpg/3.jpg', tags: ['Analog'], freeShipping: true },
|
||||
{ id: 'row3', name: 'Photo Frame', price: '$29.00', img: './assets/images/ecommerce/jpg/5.jpg', tags: ['Decorative'] },
|
||||
{ id: 'row4', name: 'Kikon Camera', price: '$4,999.00', img: './assets/images/ecommerce/jpg/4.jpg', tags: ['Black', '50MM'] },
|
||||
{ id: 'row5', name: 'Canvas Shoes', price: '$129.00', img: './assets/images/ecommerce/jpg/6.jpg', tags: ['Gray', 'Sports'] },
|
||||
];
|
||||
|
||||
|
||||
|
||||
export const notifications = [
|
||||
{
|
||||
id: 1,
|
||||
type: 'shipment',
|
||||
icon: 'ti-gift',
|
||||
colorClass: 'text-primary',
|
||||
bgClass: 'bg-primary/10',
|
||||
title: 'Your Order Has Been Shipped',
|
||||
description: 'Order No: 123456 Has Shipped To Your Delivery Address', },
|
||||
{
|
||||
id: 2,
|
||||
type: 'discount',
|
||||
icon: 'ti-discount-2',
|
||||
colorClass: 'text-secondary',
|
||||
bgClass: 'bg-secondary/10',
|
||||
title: 'Discount Available',
|
||||
description: 'Discount Available On Selected Products', },
|
||||
{
|
||||
id: 3,
|
||||
type: 'verify',
|
||||
icon: 'ti-user-check',
|
||||
colorClass: 'text-pink',
|
||||
bgClass: 'bg-pink/10',
|
||||
title: 'Account Has Been Verified',
|
||||
description: 'Your Account Has Been Verified Successfully', },
|
||||
{
|
||||
id: 4,
|
||||
type: 'placed',
|
||||
icon: 'ti-circle-check',
|
||||
colorClass: 'text-warning',
|
||||
bgClass: 'bg-warning/10',
|
||||
title: 'Order Placed',
|
||||
description: 'Order Placed Successfully',
|
||||
orderId: '#1116773'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
type: 'delayed',
|
||||
icon: 'ti-clock',
|
||||
colorClass: 'text-success',
|
||||
bgClass: 'bg-success/10',
|
||||
title: 'Order Delayed',
|
||||
description: 'Order Delayed Unfortunately',
|
||||
orderId: '7731116'
|
||||
}
|
||||
];
|
||||
|
||||
export const relatedApps = [
|
||||
{ name: 'Figma', img: './assets/images/apps/figma.png', alt: 'figma' },
|
||||
{ name: 'Power Point', img: './assets/images/apps/microsoft-powerpoint.png', alt: 'microsoft' },
|
||||
{ name: 'MS Word', img: './assets/images/apps/microsoft-word.png', alt: 'msword' },
|
||||
{ name: 'Calendar', img: './assets/images/apps/calender.png', alt: 'calendar' },
|
||||
{ name: 'Sketch', img: './assets/images/apps/sketch.png', alt: 'sketch' },
|
||||
{ name: 'Docs', img: './assets/images/apps/google-docs.png', alt: 'docs' },
|
||||
{ name: 'Google', img: './assets/images/apps/google.png', alt: 'google' },
|
||||
{ name: 'Translate', img: './assets/images/apps/translate.png', alt: 'translate' },
|
||||
{ name: 'Sheets', img: './assets/images/apps/google-sheets.png', alt: 'sheets' }
|
||||
];
|
||||
|
||||
|
||||
export const menuItems = [
|
||||
{ label: 'Profile', link: '/pages/profile', icon: 'ti-user-circle' },
|
||||
{ label: 'Inbox', link: '/pages/email/mailapp', icon: 'ti-inbox', badge: '25' },
|
||||
{ label: 'Task Manager', link: '/pages/todolist', icon: 'ti-clipboard-check' },
|
||||
{ label: 'Settings', link: '/pages/email/mailsettings', icon: 'ti-adjustments-horizontal' },
|
||||
{ label: 'Bal: $7,12,950', link: null, icon: 'ti-wallet' }, // Special case for non-router link
|
||||
{ label: 'Support', link: '/pages/chat', icon: 'ti-headset' },
|
||||
{ label: 'Log Out', link: '/authentication/sign-in/cover', icon: 'ti-logout' },
|
||||
];
|
||||
|
||||
export const searchTags = [
|
||||
{ id: 'tag1', label: 'People', icon: 'fe-user' },
|
||||
{ id: 'tag2', label: 'Pages', icon: 'fe-file-text' },
|
||||
{ id: 'tag3', label: 'Articles', icon: 'fe-align-left' },
|
||||
{ id: 'tag4', label: 'Tags', icon: 'fe-server' }
|
||||
];
|
||||
|
||||
export const alertItems = [
|
||||
{ id: 'tag5', label: 'Notifications', link: '/pages/notifications' },
|
||||
{ id: 'tag6', label: 'Alerts', link: '/uielements/alerts' },
|
||||
{ id: 'tag7', label: 'Mail', link: '/pages/email/mailapp' }
|
||||
];
|
||||
@@ -1,36 +0,0 @@
|
||||
@if(childTitle){
|
||||
<div class="block justify-between page-header md:flex">
|
||||
<div>
|
||||
<h3
|
||||
class="!text-defaulttextcolor dark:!text-defaulttextcolor/70 dark:text-white dark:hover:text-white text-[1.125rem]! font-semibold">
|
||||
{{childTitle}}</h3>
|
||||
</div>
|
||||
<ol class="flex items-center whitespace-nowrap min-w-0">
|
||||
@if(parentTitle){
|
||||
<li class="text-[0.813rem] sm:ps-[0.5rem] ps-0">
|
||||
<a class="flex items-center text-primary hover:text-primary dark:text-primary truncate"
|
||||
href="javascript:void(0);">
|
||||
{{parentTitle}}
|
||||
<i
|
||||
class="ti ti-chevrons-right !text-defaulttextcolor dark:!text-defaulttextcolor/70 px-[0.5rem] overflow-visible rtl:rotate-180"></i>
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
@if(subParentTitle){
|
||||
<li class="text-[0.813rem] ps-[0.5rem]">
|
||||
<a class="flex items-center text-primary hover:text-primary dark:text-primary truncate"
|
||||
href="javascript:void(0);">
|
||||
{{subParentTitle}}
|
||||
<i
|
||||
class="ti ti-chevrons-right flex-shrink-0 !text-defaulttextcolor dark:!text-defaulttextcolor/70 px-[0.5rem] overflow-visible rtl:rotate-180"></i>
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
<li
|
||||
class="text-[0.813rem] !text-defaulttextcolor dark:!text-defaulttextcolor/70 font-semibold hover:!text-primary "
|
||||
aria-current="page">
|
||||
{{childTitle}}
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import { Component, input } from '@angular/core';
|
||||
import { ChildrenOutletContexts, NavigationEnd, Router } from '@angular/router';
|
||||
import { filter } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-page-header',
|
||||
templateUrl: './page-header.html',
|
||||
styleUrls: ['./page-header.scss']
|
||||
})
|
||||
export class PageHeader {
|
||||
parentTitle?: string;
|
||||
subParentTitle?: string;
|
||||
childTitle?: string;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private childrenOutletContexts: ChildrenOutletContexts
|
||||
) {
|
||||
this.router.events
|
||||
.pipe(filter(event => event instanceof NavigationEnd))
|
||||
.subscribe(() => {
|
||||
const context = this.childrenOutletContexts.getContext('primary');
|
||||
const routeData = context?.route?.snapshot?.data;
|
||||
if (routeData) {
|
||||
this.childTitle = routeData['childTitle'] ?? '';
|
||||
this.parentTitle = routeData['parentTitle'] ?? '';
|
||||
this.subParentTitle = routeData['subParentTitle'] ?? '';
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-problem-details-toast',
|
||||
standalone: true,
|
||||
template: `
|
||||
<div class="rounded-lg border border-danger/20 bg-danger/10 p-3 text-sm text-danger">
|
||||
<div class="font-semibold">{{ title }}</div>
|
||||
<div>{{ detail }}</div>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class ProblemDetailsToast {
|
||||
@Input() title = 'Request failed';
|
||||
@Input() detail = 'An unexpected error occurred.';
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
<aside class="app-sidebar" id="sidebar" [ngClass]="{ 'sticky-pin': scrolled }">
|
||||
|
||||
<!-- Start::main-sidebar-header -->
|
||||
<div class="main-sidebar-header">
|
||||
<a routerLink="/dashboards/crm" class="header-logo">
|
||||
<!-- <img src="./assets/images/brand-logos/desktop-logo.png" alt="logo" class="desktop-logo">
|
||||
<img src="./assets/images/brand-logos/toggle-logo.png" alt="logo" class="toggle-logo">
|
||||
<img src="./assets/images/brand-logos/desktop-dark.png" alt="logo" class="desktop-dark">
|
||||
<img src="./assets/images/brand-logos/toggle-dark.png" alt="logo" class="toggle-dark">
|
||||
<img src="./assets/images/brand-logos/desktop-white.png" alt="logo" class="desktop-white">
|
||||
<img src="./assets/images/brand-logos/toggle-white.png" alt="logo" class="toggle-white"> -->
|
||||
|
||||
<img src="assets/images/brand-logos/erp-logo-icon.png" alt="ERP Logo" class="desktop-logo" />
|
||||
|
||||
<img src="assets/images/brand-logos/erp-logo-icon.png" alt="ERP Logo" class="toggle-logo" />
|
||||
|
||||
<img src="assets/images/brand-logos/erp-logo-icon.png" alt="ERP Logo" class="desktop-dark" />
|
||||
|
||||
<img src="assets/images/brand-logos/erp-logo-icon.png" alt="ERP Logo" class="toggle-dark" />
|
||||
|
||||
<img src="assets/images/brand-logos/erp-logo-icon.png" alt="ERP Logo" class="desktop-white" />
|
||||
|
||||
<img src="assets/images/brand-logos/erp-logo-icon.png" alt="ERP Logo" class="toggle-white" />
|
||||
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<ngx-simplebar [options]="options" class="main-sidebar" id="sidebar-scroll">
|
||||
<nav class="main-menu-container nav nav-pills flex-column sub-open">
|
||||
<div class="slide-left" id="slide-left" (click)="leftArrowFn()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="#7b8191" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path d="M13.293 6.293 7.586 12l5.707 5.707 1.414-1.414L10.414 12l4.293-4.293z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<ul class="main-menu" [ngStyle]="{ display: 'block' }">
|
||||
@for (menuItem of menuItems; track menuItem) {
|
||||
<li class="slide" #activeMenuItems [ngClass]="{'slide__category':menuItem.headTitle,
|
||||
'slide has-sub':menuItem.title,
|
||||
'open': menuItem.active,
|
||||
'active': menuItem.selected}">
|
||||
<!-- head title -->
|
||||
@if(menuItem.headTitle){
|
||||
|
||||
<span class="category-name">{{ menuItem.headTitle }}</span>
|
||||
}
|
||||
<!-- has-Link -->
|
||||
@if (menuItem.type === 'link') {
|
||||
<a class="side-menu__item" [routerLink]="!menuItem.type ? null : [menuItem.path]" routerLinkActive="active"
|
||||
(click)="setNavActive($event, menuItem.path ?? '')">
|
||||
@if (menuItem.icon) {
|
||||
<span [appSvgReplace]="menuItem.icon" class="iconclick"></span>
|
||||
}
|
||||
<span class="side-menu__label">{{ menuItem.title }}
|
||||
@if(menuItem.badgeValue){
|
||||
|
||||
<span class="badge bg-{{ menuItem.badgeClass }} text-{{menuItem.badgeText}}">{{menuItem.badgeValue
|
||||
}}</span>
|
||||
}
|
||||
</span>
|
||||
</a>
|
||||
}
|
||||
<!-- has-empty -->
|
||||
@if (menuItem.type === 'empty') {
|
||||
<a class="side-menu__item" href="javascript:;" (click)="setNavActive($event, menuItem.path ?? '')">
|
||||
@if (menuItem.icon) {
|
||||
<span [appSvgReplace]="menuItem.icon" class="iconclick"></span>
|
||||
}
|
||||
<span class="side-menu__label">{{menuItem.title}} <span class="badge bg-warning ms-2">hot</span>
|
||||
</span>
|
||||
</a>
|
||||
}
|
||||
<!-- has-Sub -->
|
||||
@if (menuItem.type === 'sub') {
|
||||
<a class="side-menu__item" [routerLink]="menuItem.type ? null: [menuItem.path]"
|
||||
[ngClass]="{active: menuItem.selected}" (click)="toggleNavActive($event, menuItem )">
|
||||
@if (menuItem.icon) {
|
||||
<span [appSvgReplace]="menuItem.icon" class="iconclick"></span>
|
||||
}
|
||||
<span class="side-menu__label">{{menuItem.title}}
|
||||
@if(menuItem.badgeValue){
|
||||
<span
|
||||
class="badge bg-{{ menuItem.badgeClass }} text-{{menuItem.badgeText}} ms-2">{{menuItem.badgeValue}}</span>
|
||||
}
|
||||
</span>
|
||||
<i class="fe fe-chevron-right side-menu__angle"></i>
|
||||
</a>
|
||||
}
|
||||
<!-- 2nd Level menu -->
|
||||
@if (menuItem.children) {
|
||||
<ul class="slide-menu child1"
|
||||
[ngClass]="{'active':menuItem.active,'double-menu-active':menuItem.active, 'force-left' : menuItem.dirchange}"
|
||||
[ngStyle]="{ display: menuItem.active ? 'block' : 'none' }">
|
||||
<li class="slide side-menu__label1"><a href="javascript:void(0)">{{menuItem.title}}</a></li>
|
||||
@for (childrenItem of menuItem.children; track childrenItem) {
|
||||
<li class="slide" activeMenuItems [ngClass]="{'active':childrenItem.selected}" appDropdownPosition
|
||||
[ngClass]="{'has-sub': childrenItem.type === 'sub','open':childrenItem.active}">
|
||||
<!-- link -->
|
||||
@if (childrenItem.type === 'link') {
|
||||
<a class="side-menu__item" [routerLink]="!childrenItem.type ? null : [childrenItem.path] "
|
||||
routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}"
|
||||
(click)="setNavActive($event, childrenItem.path ?? '')">
|
||||
{{childrenItem.title}}
|
||||
@if(childrenItem.badgeClass){
|
||||
|
||||
<span class="m-1 badge bg-{{ menuItem.badgeClass }}">{{menuItem.badgeValue }}</span>
|
||||
}
|
||||
|
||||
</a>
|
||||
}
|
||||
<!-- empty -->
|
||||
@if (childrenItem.type === 'empty' ) {
|
||||
<a class="side-menu__item " href="javascript:;" (click)="setNavActive($event, childrenItem.path ?? '')">
|
||||
{{childrenItem.title }}
|
||||
</a>
|
||||
}
|
||||
<!-- sub -->
|
||||
@if (childrenItem.type === 'sub') {
|
||||
<a class="side-menu__item " [ngClass]="{'active': childrenItem.selected}"
|
||||
[routerLink]="childrenItem.type ? null : [childrenItem.path]"
|
||||
(click)="toggleNavActive($event, childrenItem)">
|
||||
<span class="">{{childrenItem.title}}</span>
|
||||
<i class="fe fe-chevron-right side-menu__angle"></i>
|
||||
</a>
|
||||
}
|
||||
<!-- 3rd Level menu -->
|
||||
@if (childrenItem.children) {
|
||||
<ul class="slide-menu child2" force [ngClass]="{'force-left' : childrenItem.dirchange}" [ngStyle]="{
|
||||
display: childrenItem.active ? 'block' : 'none',
|
||||
right: localdata['dir'] == 'rtl' ? 'auto' : '',
|
||||
left: localdata['dir'] == 'rtl' ? '100%' : ''
|
||||
}">
|
||||
@for (childrenSubItem of childrenItem.children; track childrenSubItem) {
|
||||
<li class="slide" activeMenuItems appDropdownPosition [ngClass]="{open:childrenSubItem.active}">
|
||||
@if (childrenSubItem.type === 'link') {
|
||||
<a class="side-menu__item" routerLinkActive="active"
|
||||
[routerLink]="!childrenSubItem.type ? null : [childrenSubItem.path]"
|
||||
[routerLinkActiveOptions]="{exact : true}">
|
||||
{{childrenSubItem.title}}
|
||||
</a>
|
||||
}
|
||||
@if (childrenSubItem.type === 'empty') {
|
||||
<a class="side-menu__item" href="javascript:;">
|
||||
{{childrenSubItem.title}}
|
||||
</a>
|
||||
}
|
||||
|
||||
@if (childrenSubItem.type === 'sub') {
|
||||
<a class="side-menu__item " [ngClass]="{'active': childrenSubItem.active}"
|
||||
[routerLink]="childrenSubItem.type ? null : [childrenSubItem.path]" routerLinkActive="active"
|
||||
(click)="toggleNavActive($event, childrenSubItem)">
|
||||
<span class="">{{childrenSubItem.title}}</span>
|
||||
<i class="fe fe-chevron-right side-menu__angle"></i>
|
||||
</a>
|
||||
}
|
||||
<!-- 3rd Level menu -->
|
||||
@if (childrenSubItem.children) {
|
||||
<ul class="slide-menu child2" [ngClass]="{'force-left' : childrenItem.dirchange}" [ngStyle]="{
|
||||
display: childrenSubItem.active ? 'block' : 'none',
|
||||
|
||||
}">
|
||||
@for (childrenSubItem1 of childrenSubItem.children; track childrenSubItem1) {
|
||||
<li class="slide" activeMenuItems [ngClass]="{'open': childrenSubItem1.active}">
|
||||
@if (childrenSubItem1.type === 'link') {
|
||||
<a class="side-menu__item" routerLinkActive="active"
|
||||
[routerLink]="!childrenSubItem1.type ? null : [childrenSubItem1.path]"
|
||||
[routerLinkActiveOptions]="{exact : true}">
|
||||
{{childrenSubItem1.title}}
|
||||
</a>
|
||||
}
|
||||
@if (childrenSubItem1.type === 'empty') {
|
||||
<a class="side-menu__item" href="javascript:;">
|
||||
{{childrenSubItem1.title}}
|
||||
</a>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</li>
|
||||
@if (menuItem.type === 'external') {
|
||||
<a class="side-menu__item" target="_blank" [routerLink]="!menuItem.type ? null : [menuItem.path]"
|
||||
routerLinkActive="active" (click)="setNavActive($event, menuItem.path ?? '')">
|
||||
@if (menuItem.icon) {
|
||||
<span [appSvgReplace]="menuItem.icon" class="iconclick"></span>
|
||||
}
|
||||
<span class="side-menu__label">{{ menuItem.title }}
|
||||
@if(menuItem.badgeValue){
|
||||
<span
|
||||
class="badge bg-{{ menuItem.badgeClass }} text-{{menuItem.badgeText}} float-end">{{menuItem.badgeValue
|
||||
}}</span>
|
||||
}
|
||||
</span>
|
||||
</a>
|
||||
}
|
||||
}
|
||||
<!-- End::slide -->
|
||||
</ul>
|
||||
<div class="slide-right" id="slide-right" (click)="rightArrowFn()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="#7b8191" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path d="M10.707 17.707 16.414 12l-5.707-5.707-1.414 1.414L13.586 12l-4.293 4.293z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</nav>
|
||||
</ngx-simplebar>
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
@@ -1,526 +0,0 @@
|
||||
import { Component, Renderer2, HostListener, ElementRef, } from '@angular/core';
|
||||
import { Menu, NavService } from '../../services/nav.service';
|
||||
import { Subscription, fromEvent } from 'rxjs';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { NavigationEnd, Router, RouterLink, RouterLinkActive } from '@angular/router';
|
||||
import { AppStateService } from '../../services/app-state.service';
|
||||
import { NgClass, NgStyle } from '@angular/common';
|
||||
import { SimplebarAngularModule } from 'simplebar-angular';
|
||||
import { SvgReplaceDirective } from '../../directives/svgReplace.directive';
|
||||
@Component({
|
||||
selector: 'app-sidebar',
|
||||
templateUrl: './sidebar.html',
|
||||
styleUrl: './sidebar.scss',
|
||||
imports: [NgClass, RouterLink, SimplebarAngularModule, NgStyle, RouterLinkActive, SvgReplaceDirective]
|
||||
})
|
||||
|
||||
export class Sidebar {
|
||||
doublemenuTooltiPosition = 'right'
|
||||
eventTriggered: boolean = false;
|
||||
screenWidth!: number;
|
||||
public localdata = localStorage;
|
||||
public windowSubscribe$!: Subscription;
|
||||
options = { autoHide: false, scrollbarMinSize: 100 };
|
||||
public menuItems!: Menu[];
|
||||
public menuitemsSubscribe$!: Subscription;
|
||||
constructor(
|
||||
private navServices: NavService,
|
||||
public router: Router,
|
||||
public renderer: Renderer2,
|
||||
private sanitizer: DomSanitizer,
|
||||
private appStateService: AppStateService,
|
||||
private elementRef: ElementRef
|
||||
) { }
|
||||
isDoubleMenu(): boolean {
|
||||
const htmlElement = document.querySelector('[data-vertical-style="doublemenu"]');
|
||||
return htmlElement !== null;
|
||||
}
|
||||
|
||||
// Method to determine if tooltip should be shown
|
||||
shouldShowTooltip(menuItem: any): boolean {
|
||||
return this.isDoubleMenu() && menuItem.title !== '';
|
||||
}
|
||||
clearNavDropdown() {
|
||||
this.menuItems?.forEach((a: any) => {
|
||||
a.active = false;
|
||||
a?.children?.forEach((b: any) => {
|
||||
b.active = false;
|
||||
b?.children?.forEach((c: any) => {
|
||||
c.active = false;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
let bodyElement: any = document.querySelector('.main-content');
|
||||
bodyElement.onclick = () => {
|
||||
if (localStorage.getItem('layoutStyles') == 'icontext' || localStorage.getItem('layoutStyles') == 'icon-hover') {
|
||||
document.querySelector('html')?.removeAttribute('data-icon-text')
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.menuitemsSubscribe$ = this.navServices.items.subscribe((items) => {
|
||||
this.menuItems = items;
|
||||
});
|
||||
|
||||
this.setNavActive(null, this.router.url);
|
||||
this.router.events.subscribe((event) => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
this.setNavActive(null, this.router.url);
|
||||
}
|
||||
});
|
||||
|
||||
const WindowResize = fromEvent(window, 'resize');
|
||||
// subscribing the Observable
|
||||
if (WindowResize) {
|
||||
this.windowSubscribe$ = WindowResize.subscribe(() => {
|
||||
// to check and adjst the menu on screen size change
|
||||
// checkHoriMenu();
|
||||
});
|
||||
}
|
||||
|
||||
if (document.querySelector('html')?.getAttribute('data-nav-layout') == 'horizontal' && window.innerWidth >= 992) { this.clearNavDropdown(); }
|
||||
}
|
||||
// Start of Set menu Active event
|
||||
setNavActive(event: any, currentPath: string, menuData = this.menuItems) {
|
||||
if (event) {
|
||||
if (event?.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let html = this.elementRef.nativeElement.ownerDocument.documentElement;
|
||||
//if (html.getAttribute('data-nav-style') != "icon-hover" && html.getAttribute('data-nav-style') != "menu-hover") {
|
||||
// if (!event?.ctrlKey) {
|
||||
for (const item of menuData) {
|
||||
if (item.path === currentPath) {
|
||||
item.active = true;
|
||||
item.selected = true;
|
||||
this.setMenuAncestorsActive(item);
|
||||
} else if (!item.active && !item.selected) {
|
||||
item.active = false; // Set active to false for items not matching the target
|
||||
item.selected = false; // Set active to false for items not matching the target
|
||||
} else {
|
||||
this.removeActiveOtherMenus(item);
|
||||
}
|
||||
if (item.children && item.children.length > 0) {
|
||||
this.setNavActive(event, currentPath, item.children);
|
||||
}
|
||||
}
|
||||
// }
|
||||
//}
|
||||
if (window.innerWidth <= 996) {
|
||||
html?.setAttribute('data-toggled', html?.getAttribute('data-toggled') == 'close' ? 'close' : 'close');
|
||||
}
|
||||
|
||||
if (html?.getAttribute('data-vertical-style') == "icontext" && html?.getAttribute('data-icon-text') == 'open' && window.innerWidth >= 992) { html?.setAttribute('data-icon-text', 'close') }
|
||||
|
||||
|
||||
}
|
||||
|
||||
getParentObject(obj: any, childObject: Menu) {
|
||||
for (const key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
if (typeof obj[key] === 'object' && JSON.stringify(obj[key]) === JSON.stringify(childObject)) {
|
||||
return obj; // Return the parent object
|
||||
}
|
||||
if (typeof obj[key] === 'object') {
|
||||
const parentObject: any = this.getParentObject(obj[key], childObject);
|
||||
if (parentObject !== null) {
|
||||
return parentObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null; // Object not found
|
||||
}
|
||||
|
||||
hasParent = false;
|
||||
hasParentLevel = 0;
|
||||
|
||||
setMenuAncestorsActive(targetObject: Menu) {
|
||||
const parent = this.getParentObject(this.menuItems, targetObject);
|
||||
let html = document.documentElement;
|
||||
if (parent) {
|
||||
if (this.hasParentLevel >= 2) {
|
||||
this.hasParent = true;
|
||||
}
|
||||
parent.active = true;
|
||||
parent.selected = true;
|
||||
this.hasParentLevel += 1;
|
||||
this.setMenuAncestorsActive(parent);
|
||||
}
|
||||
else if (!this.hasParent) {
|
||||
this.hasParentLevel = 0;
|
||||
if (html.getAttribute('data-vertical-style') == 'doublemenu') {
|
||||
if (window.innerWidth < 992) {
|
||||
html.setAttribute('data-toggled', 'close');
|
||||
} else {
|
||||
html.setAttribute('data-toggled', 'double-menu-close');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.hasParentLevel = 0;
|
||||
this.hasParent = false;
|
||||
}
|
||||
}
|
||||
removeActiveOtherMenus(item: any) {
|
||||
if (item) {
|
||||
if (Array.isArray(item)) {
|
||||
for (const val of item) {
|
||||
val.active = false;
|
||||
val.selected = false;
|
||||
}
|
||||
}
|
||||
item.active = false;
|
||||
item.selected = false;
|
||||
|
||||
if (item.children && item.children.length > 0) {
|
||||
this.removeActiveOtherMenus(item.children);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Start of Toggle menu event
|
||||
toggleNavActive(event: any, targetObject: Menu, menuData = this.menuItems, state?: any) {
|
||||
let html = document.documentElement;
|
||||
let element = event.target;
|
||||
if (html.getAttribute('data-nav-style') != "icon-hover" && html.getAttribute('data-nav-style') != "menu-hover" || (window.innerWidth < 992) || (html.getAttribute('data-nav-layout') != "horizontal") && (html.getAttribute('data-nav-style') != "icon-hover-closed" && html.getAttribute('data-nav-style') != "menu-hover-closed")) {
|
||||
for (const item of menuData) {
|
||||
if (item === targetObject) {
|
||||
if (html.getAttribute('data-vertical-style') == 'doublemenu' && item.active && window.innerWidth > 992 && state) { return }
|
||||
item.active = !item.active;
|
||||
if (item.active) {
|
||||
this.closeOtherMenus(menuData, item);
|
||||
}
|
||||
this.setAncestorsActive(menuData, item);
|
||||
|
||||
} else if (!item.active) {
|
||||
if (html.getAttribute('data-vertical-style') != 'doublemenu') {
|
||||
item.active = false; // Set active to false for items not matching the target
|
||||
}
|
||||
}
|
||||
if (item.children && item.children.length > 0) {
|
||||
this.toggleNavActive(event, targetObject, item.children);
|
||||
}
|
||||
}
|
||||
if (targetObject?.children && targetObject.active) {
|
||||
if (html.getAttribute('data-vertical-style') == 'doublemenu' && html.getAttribute('data-toggled') != 'double-menu-open') {
|
||||
html.setAttribute('data-toggled', 'double-menu-open');
|
||||
}
|
||||
}
|
||||
|
||||
if (element && html.getAttribute("data-nav-layout") == 'horizontal' && (html.getAttribute("data-nav-style") == 'menu-click' || html.getAttribute("data-nav-style") == 'icon-click')) {
|
||||
const listItem = element.closest("li");
|
||||
if (listItem) {
|
||||
// Find the first sibling <ul> element
|
||||
const siblingUL = listItem.querySelector("ul");
|
||||
let outterUlWidth = 0;
|
||||
let listItemUL = listItem.closest('ul:not(.main-menu)');
|
||||
while (listItemUL) {
|
||||
listItemUL = listItemUL.parentElement.closest('ul:not(.main-menu)');
|
||||
if (listItemUL) {
|
||||
outterUlWidth += listItemUL.clientWidth;
|
||||
}
|
||||
}
|
||||
if (siblingUL) {
|
||||
// You've found the sibling <ul> element
|
||||
let siblingULRect = listItem.getBoundingClientRect();
|
||||
if (html.getAttribute('dir') == 'rtl') {
|
||||
if ((siblingULRect.left - siblingULRect.width - outterUlWidth + 150 < 0 && outterUlWidth < window.innerWidth) && (outterUlWidth + siblingULRect.width + siblingULRect.width < window.innerWidth)) {
|
||||
targetObject.dirchange = true;
|
||||
} else {
|
||||
targetObject.dirchange = false;
|
||||
}
|
||||
} else {
|
||||
if ((outterUlWidth + siblingULRect.right + siblingULRect.width + 50 > window.innerWidth && siblingULRect.right >= 0) && (outterUlWidth + siblingULRect.width + siblingULRect.width < window.innerWidth)) {
|
||||
targetObject.dirchange = true;
|
||||
} else {
|
||||
targetObject.dirchange = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
let computedValue = siblingUL.getBoundingClientRect();
|
||||
if ((computedValue.bottom) > window.innerHeight) {
|
||||
siblingUL.style.height = (window.innerHeight - computedValue.top - 8) + 'px !important';
|
||||
siblingUL.style.overflow = 'auto !important';
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const item of menuData) {
|
||||
if (item === targetObject) {
|
||||
if (html.getAttribute('data-vertical-style') == 'doublemenu' && item.active && window.innerWidth > 992 && state) { return }
|
||||
item.active = !item.active;
|
||||
if (item.active) {
|
||||
this.closeOtherMenus(menuData, item);
|
||||
}
|
||||
this.setAncestorsActive(menuData, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (html.getAttribute('data-vertical-style') == 'icontext') {
|
||||
document.querySelector('html')?.setAttribute('data-icon-text', 'open')
|
||||
} else {
|
||||
document.querySelector('html')?.removeAttribute('data-icon-text')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
setAncestorsActive(menuData: Menu[], targetObject: Menu) {
|
||||
let html = document.documentElement;
|
||||
const parent = this.findParent(menuData, targetObject);
|
||||
|
||||
if (parent) {
|
||||
parent.active = true;
|
||||
if (parent.active) {
|
||||
html.setAttribute('data-toggled', 'double-menu-open');
|
||||
}
|
||||
this.setAncestorsActive(menuData, parent);
|
||||
}
|
||||
}
|
||||
closeOtherMenus(menuData: Menu[], targetObject: Menu) {
|
||||
for (const item of menuData) {
|
||||
if (item !== targetObject) {
|
||||
item.active = false;
|
||||
if (item.children && item.children.length > 0) {
|
||||
this.closeOtherMenus(item.children, targetObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
findParent(menuData: Menu[], targetObject: Menu) {
|
||||
for (const item of menuData) {
|
||||
if (item.children && item.children.includes(targetObject)) {
|
||||
return item;
|
||||
}
|
||||
if (item.children && item.children.length > 0) {
|
||||
const parent: any = this.findParent(item.children, targetObject);
|
||||
if (parent) {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// End of Toggle menu event
|
||||
HoverToggleInnerMenuFn(event: Event, item: Menu) {
|
||||
let html = document.documentElement;
|
||||
let element = event.target as HTMLElement;
|
||||
if (element && html.getAttribute("data-nav-layout") == 'horizontal' && (html.getAttribute("data-nav-style") == 'menu-hover' || html.getAttribute("data-nav-style") == 'icon-hover')) {
|
||||
const listItem = element.closest("li");
|
||||
if (listItem) {
|
||||
// Find the first sibling <ul> element
|
||||
const siblingUL = listItem.querySelector("ul");
|
||||
let outterUlWidth = 0;
|
||||
let listItemUL: any = listItem.closest('ul:not(.main-menu)');
|
||||
while (listItemUL) {
|
||||
listItemUL = listItemUL.parentElement?.closest('ul:not(.main-menu)');
|
||||
if (listItemUL) {
|
||||
outterUlWidth += listItemUL.clientWidth;
|
||||
}
|
||||
}
|
||||
if (siblingUL) {
|
||||
// You've found the sibling <ul> element
|
||||
let siblingULRect = listItem.getBoundingClientRect();
|
||||
if (html.getAttribute('dir') == 'rtl') {
|
||||
if ((siblingULRect.left - siblingULRect.width - outterUlWidth + 150 < 0 && outterUlWidth < window.innerWidth) && (outterUlWidth + siblingULRect.width + siblingULRect.width < window.innerWidth)) {
|
||||
item.dirchange = true;
|
||||
} else {
|
||||
item.dirchange = false;
|
||||
}
|
||||
} else {
|
||||
if ((outterUlWidth + siblingULRect.right + siblingULRect.width + 50 > window.innerWidth && siblingULRect.right >= 0) && (outterUlWidth + siblingULRect.width + siblingULRect.width < window.innerWidth)) {
|
||||
item.dirchange = true;
|
||||
} else {
|
||||
item.dirchange = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
//Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.
|
||||
//Add 'implements AfterViewInit' to the class.
|
||||
// checkHoriMenu();
|
||||
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.menuitemsSubscribe$.unsubscribe();
|
||||
this.windowSubscribe$.unsubscribe();
|
||||
document.querySelector('html')?.setAttribute('data-vertical-style', 'overlay');
|
||||
document.querySelector('html')?.setAttribute('data-nav-layout', 'vertical');
|
||||
}
|
||||
|
||||
leftArrowFn() {
|
||||
// Used to move the slide of the menu in Horizontal and also remove the arrows after click if there was no space
|
||||
// Used to Slide the menu to Left side
|
||||
let slideLeft = document.querySelector('.slide-left') as HTMLElement;
|
||||
let slideRight = document.querySelector('.slide-right') as HTMLElement;
|
||||
let menuNav = document.querySelector('.main-menu') as HTMLElement;
|
||||
let mainContainer1 = document.querySelector('.main-sidebar') as HTMLElement;
|
||||
let marginRightValue = Math.ceil(Number(window.getComputedStyle(menuNav).marginInlineStart.split('px')[0]));
|
||||
let mainContainer1Width = mainContainer1.offsetWidth;
|
||||
if (menuNav.scrollWidth > mainContainer1.offsetWidth) {
|
||||
if (marginRightValue < 0 && !(Math.abs(marginRightValue) < mainContainer1Width)) {
|
||||
menuNav.style.marginInlineStart = Number(menuNav.style.marginInlineStart.split('px')[0]) + Math.abs(mainContainer1Width) + 'px';
|
||||
slideRight.classList.remove('d-none');
|
||||
} else if (marginRightValue >= 0) {
|
||||
menuNav.style.marginInlineStart = '0px';
|
||||
slideLeft.classList.add('d-none');
|
||||
slideRight.classList.remove('d-none');
|
||||
} else {
|
||||
menuNav.style.marginInlineStart = '0px';
|
||||
slideLeft.classList.add('d-none');
|
||||
slideRight.classList.remove('d-none');
|
||||
}
|
||||
}
|
||||
else {
|
||||
menuNav.style.marginInlineStart = "0px";
|
||||
slideLeft.classList.add('d-none');
|
||||
}
|
||||
|
||||
let element = document.querySelector(".main-menu > .slide.open") as HTMLElement;
|
||||
let element1 = document.querySelector(".main-menu > .slide.open >ul") as HTMLElement;
|
||||
if (element) {
|
||||
element.classList.remove("open")
|
||||
}
|
||||
if (element1) {
|
||||
element1.style.display = "none"
|
||||
}
|
||||
}
|
||||
rightArrowFn() {
|
||||
// Used to move the slide of the menu in Horizontal and also remove the arrows after click if there was no space
|
||||
// Used to Slide the menu to Right side
|
||||
let slideLeft = document.querySelector('.slide-left') as HTMLElement;
|
||||
let slideRight = document.querySelector('.slide-right') as HTMLElement;
|
||||
let menuNav = document.querySelector('.main-menu') as HTMLElement;
|
||||
let mainContainer1 = document.querySelector('.main-sidebar') as HTMLElement;
|
||||
let marginRightValue = Math.ceil(Number(window.getComputedStyle(menuNav).marginInlineStart.split('px')[0]));
|
||||
let check = menuNav.scrollWidth - mainContainer1.offsetWidth;
|
||||
let mainContainer1Width = mainContainer1.offsetWidth;
|
||||
if (menuNav.scrollWidth > mainContainer1.offsetWidth) {
|
||||
if (Math.abs(check) > Math.abs(marginRightValue)) {
|
||||
if (!(Math.abs(check) > Math.abs(marginRightValue) + mainContainer1Width)) {
|
||||
mainContainer1Width = Math.abs(check) - Math.abs(marginRightValue);
|
||||
slideRight.classList.add('d-none');
|
||||
}
|
||||
menuNav.style.marginInlineStart = Number(menuNav.style.marginInlineStart.split('px')[0]) - Math.abs(mainContainer1Width) + 'px';
|
||||
slideLeft.classList.remove('d-none');
|
||||
}
|
||||
}
|
||||
|
||||
let element = document.querySelector(".main-menu > .slide.open") as HTMLElement
|
||||
let element1 = document.querySelector(".main-menu > .slide.open >ul") as HTMLElement
|
||||
if (element) {
|
||||
element.classList.remove("open")
|
||||
}
|
||||
if (element1) {
|
||||
element1.style.display = "none"
|
||||
}
|
||||
}
|
||||
|
||||
// Addding sticky-pin
|
||||
scrolled = false;
|
||||
|
||||
@HostListener('window:scroll', [])
|
||||
onWindowScroll() {
|
||||
this.scrolled = window.scrollY > 10;
|
||||
|
||||
const sections = document.querySelectorAll('.side-menu__item');
|
||||
const scrollPos =
|
||||
window.pageYOffset ||
|
||||
document.documentElement.scrollTop ||
|
||||
document.body.scrollTop;
|
||||
|
||||
sections.forEach((ele, i) => {
|
||||
const currLink = sections[i];
|
||||
const val: any = currLink.getAttribute('value');
|
||||
const refElement: any = document.querySelector('#' + val);
|
||||
|
||||
// Add a null check here before accessing properties of refElement
|
||||
if (refElement !== null) {
|
||||
const scrollTopMinus = scrollPos + 73;
|
||||
if (
|
||||
refElement.offsetTop <= scrollTopMinus &&
|
||||
refElement.offsetTop + refElement.offsetHeight > scrollTopMinus
|
||||
) {
|
||||
document.querySelector('.nav-scroll')?.classList.remove('active');
|
||||
currLink.classList.add('active');
|
||||
} else {
|
||||
currLink.classList.remove('active');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('window:resize', ['$event'])
|
||||
onResize(event: any): void {
|
||||
this.menuResizeFn();
|
||||
|
||||
this.screenWidth = window.innerWidth;
|
||||
|
||||
// Check if the event hasn't been triggered and the screen width is less than or equal to your breakpoint
|
||||
if (!this.eventTriggered && this.screenWidth <= 992) {
|
||||
document.documentElement?.setAttribute('data-toggled', 'close')
|
||||
|
||||
|
||||
// Trigger your event or perform any action here
|
||||
this.eventTriggered = true; // Set the flag to true to prevent further triggering
|
||||
} else if (this.screenWidth > 992) {
|
||||
// Reset the flag when the screen width goes beyond the breakpoint
|
||||
this.eventTriggered = false;
|
||||
}
|
||||
}
|
||||
WindowPreSize: number[] = [window.innerWidth];
|
||||
|
||||
menuResizeFn(): void {
|
||||
this.WindowPreSize.push(window.innerWidth);
|
||||
const html = document.documentElement;
|
||||
|
||||
if (this.WindowPreSize.length > 2) {
|
||||
this.WindowPreSize.shift();
|
||||
}
|
||||
if (this.WindowPreSize.length > 1) {
|
||||
|
||||
if (this.WindowPreSize[this.WindowPreSize.length - 1] < 996 && this.WindowPreSize[this.WindowPreSize.length - 2] >= 996) {
|
||||
// less than 996
|
||||
html.setAttribute('data-toggled', 'close');
|
||||
}
|
||||
|
||||
if (this.WindowPreSize[this.WindowPreSize.length - 1] >= 996 && this.WindowPreSize[this.WindowPreSize.length - 2] < 996) {
|
||||
// greater than 996
|
||||
html.removeAttribute('data-toggled');
|
||||
document.querySelector('#responsive-overlay')?.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
if ((this.WindowPreSize[this.WindowPreSize.length - 1] >= 996) && (this.WindowPreSize[this.WindowPreSize.length - 2] < 996)) {
|
||||
if (html.getAttribute('data-vertical-style') === 'doublemenu') {
|
||||
const doublemenuactive = document.querySelectorAll(".double-menu-active .active");
|
||||
if (doublemenuactive.length > 0) {
|
||||
html.setAttribute('data-toggled', 'double-menu-open');
|
||||
|
||||
} else {
|
||||
html.setAttribute('data-toggled', 'double-menu-close');
|
||||
}
|
||||
} else {
|
||||
html.setAttribute('data-toggled', '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,543 +0,0 @@
|
||||
<div id="hs-overlay-switcher"
|
||||
class="hs-overlay hidden ti-offcanvas border-defaultborder dark:border-defaultborder/10 ti-offcanvas-right hs-overlay-backdrop-open:bg-[#32325180] dark:hs-overlay-backdrop-open:bg-[#323251cc]"
|
||||
data-hs-overlay-backdrop="false">
|
||||
<div
|
||||
class="ti-offcanvas-header border-defaultborder dark:border-defaultborder/10 z-10 relative items-center !block !p-0">
|
||||
<div class="flex items-center justify-between p-3">
|
||||
<h5 class="ti-offcanvas-title">
|
||||
Switcher
|
||||
</h5>
|
||||
<button type="button"
|
||||
class="ti-btn flex-shrink-0 p-0 transition-none text-defaulttextcolor dark:text-defaulttextcolor/70 hover:text-gray-700 focus:ring-gray-400 focus:ring-offset-white dark:hover:text-white/80 dark:focus:ring-white/10 dark:focus:ring-offset-white/10 !m-0"
|
||||
data-hs-overlay="#hs-overlay-switcher">
|
||||
<span class="sr-only">Close modal</span>
|
||||
<i class="ri-close-circle-line leading-none items-center text-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
<nav class="flex border-t border-defaultborder dark:border-defaultborder/10 " aria-label="Tabs" role="tablist">
|
||||
|
||||
<button type="button"
|
||||
class="hs-tab-active:bg-success/20 w-full !py-2 !px-4 hs-tab-active:border-b-transparent text-defaultsize border-0 hs-tab-active:!text-success dark:hs-tab-active:!bg-success/20 dark:hs-tab-active:border-b-white/10 dark:hs-tab-active:!text-success -mb-px font-semibold text-center text-defaulttextcolor dark:text-defaulttextcolor/70 rounded-none dark:bg-bodybg dark:border-white/10 cursor-pointer active"
|
||||
id="switcher-item-1" data-hs-tab="#switcher-1" aria-controls="switcher-1" role="tab">
|
||||
Theme Style
|
||||
</button>
|
||||
<button type="button"
|
||||
class="hs-tab-active:bg-success/20 w-full !py-2 !px-4 hs-tab-active:border-b-transparent text-defaultsize border-0 hs-tab-active:!text-success dark:hs-tab-active:!bg-success/20 dark:hs-tab-active:border-b-white/10 dark:hs-tab-active:!text-success -mb-px font-semibold text-center text-defaulttextcolor dark:text-defaulttextcolor/70 rounded-none dark:bg-bodybg dark:border-white/10 cursor-pointer"
|
||||
id="switcher-item-2" data-hs-tab="#switcher-2" aria-controls="switcher-2" role="tab">
|
||||
Theme Colors
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
<div class="ti-offcanvas-body overflow-auto border-defaultborder dark:border-defaultborder/10 relative "
|
||||
id="switcher-body">
|
||||
|
||||
<div id="switcher-1" role="tabpanel" aria-labelledby="switcher-item-1" class="">
|
||||
<div class="">
|
||||
<p class="switcher-style-head">Theme Color Mode:</p>
|
||||
<div class="grid grid-cols-3 switcher-style">
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="theme-style" class="ti-form-radio form-check-input" id="switcher-light-theme"
|
||||
(click)="updateTheme('light')" [checked]="localdata['theme'] == 'light'">
|
||||
<label for="switcher-light-theme"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Light</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="theme-style" class="ti-form-radio form-check-input" id="switcher-dark-theme"
|
||||
(click)="updateTheme('dark')" [checked]="localdata['theme'] == 'dark'">
|
||||
<label for="switcher-dark-theme"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Dark</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="switcher-style-head">Directions:</p>
|
||||
<div class="grid grid-cols-3 switcher-style">
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="direction" class="ti-form-radio form-check-input" id="switcher-ltr"
|
||||
(click)="updateDirection('ltr')" [checked]="localdata['direction'] != 'rtl'">
|
||||
<label for="switcher-ltr"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">LTR</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="direction" class="ti-form-radio form-check-input" id="switcher-rtl"
|
||||
(click)="updateDirection('rtl')" [checked]="localdata['direction'] == 'rtl'">
|
||||
<label for="switcher-rtl"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">RTL</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="switcher-style-head">Navigation Styles:</p>
|
||||
<div class="grid grid-cols-3 switcher-style">
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="navigation-style" class="ti-form-radio form-check-input" id="switcher-vertical"
|
||||
[checked]="localdata['navigationStyles'] == 'vertical'" (click)="updatemenuType('vertical')">
|
||||
<label for="switcher-vertical"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Vertical</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="navigation-style" class="ti-form-radio form-check-input" id="switcher-horizontal"
|
||||
[checked]="localdata['navigationStyles'] == 'horizontal'" (click)="updatemenuType('horizontal')">
|
||||
<label for="switcher-horizontal"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Horizontal</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="switcher-style-head">Navigation Menu Style:</p>
|
||||
<div class="grid grid-cols-2 gap-2 switcher-style">
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="navigation-data-menu-styles" class="ti-form-radio form-check-input"
|
||||
id="switcher-menu-click" (click)="updatemenuStyle('menu-click')"
|
||||
[checked]="localdata['menuStyles'] == 'menu-click'">
|
||||
<label for="switcher-menu-click"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Menu
|
||||
Click</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="navigation-data-menu-styles" class="ti-form-radio form-check-input"
|
||||
id="switcher-menu-hover" (click)="updatemenuStyle('menu-hover')"
|
||||
[checked]="localdata['menuStyles'] == 'menu-hover'">
|
||||
<label for="switcher-menu-hover"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Menu
|
||||
Hover</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="navigation-data-menu-styles" class="ti-form-radio form-check-input"
|
||||
id="switcher-icon-click" (click)="updatemenuStyle('icon-click')"
|
||||
[checked]="localdata['menuStyles'] == 'icon-click'">
|
||||
<label for="switcher-icon-click"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Icon
|
||||
Click</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="navigation-data-menu-styles" class="ti-form-radio form-check-input"
|
||||
id="switcher-icon-hover" (click)="updatemenuStyle('icon-hover')"
|
||||
[checked]="localdata['menuStyles'] == 'icon-hover'">
|
||||
<label for="switcher-icon-hover"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Icon
|
||||
Hover</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4 text-secondary text-xs"><b class="me-2">Note:</b>Works same for both Vertical and
|
||||
Horizontal
|
||||
</div>
|
||||
</div>
|
||||
<div class=" sidemenu-layout-styles">
|
||||
<p class="switcher-style-head">Sidemenu Layout Syles:</p>
|
||||
<div class="grid grid-cols-2 gap-2 switcher-style">
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="sidemenu-layout-styles" class="ti-form-radio form-check-input"
|
||||
id="switcher-default-menu" (click)="updatelayoutStyles('default')"
|
||||
[checked]="localdata['layoutStyles'] == 'default'">
|
||||
<label for="switcher-default-menu"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold ">Default
|
||||
Menu</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="sidemenu-layout-styles" class="ti-form-radio form-check-input"
|
||||
id="switcher-closed-menu" (click)="updatelayoutStyles('closed')"
|
||||
[checked]="localdata['layoutStyles'] == 'closed'">
|
||||
<label for="switcher-closed-menu"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold ">
|
||||
Closed
|
||||
Menu</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="sidemenu-layout-styles" class="ti-form-radio form-check-input"
|
||||
id="switcher-icontext-menu" (click)="updatelayoutStyles('icontext')"
|
||||
[checked]="localdata['layoutStyles'] == 'icontext'">
|
||||
<label for="switcher-icontext-menu"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold ">Icon
|
||||
Text</label>
|
||||
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="sidemenu-layout-styles" class="ti-form-radio form-check-input"
|
||||
id="switcher-icon-overlay" (click)="updatelayoutStyles('overlay')"
|
||||
[checked]="localdata['layoutStyles'] == 'overlay'">
|
||||
<label for="switcher-icon-overlay"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold ">Icon
|
||||
Overlay</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="sidemenu-layout-styles" class="ti-form-radio form-check-input"
|
||||
id="switcher-detached" (click)="updatelayoutStyles('detached')"
|
||||
[checked]="localdata['layoutStyles'] == 'detached'">
|
||||
<label for="switcher-detached"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold ">Detached</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="sidemenu-layout-styles" class="ti-form-radio form-check-input"
|
||||
id="switcher-double-menu" (click)="updatelayoutStyles('doublemenu')"
|
||||
[checked]="localdata['layoutStyles'] == 'doublemenu'">
|
||||
<label for="switcher-double-menu"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Double
|
||||
Menu</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4 text-secondary text-xs"><b class="me-2">Note:</b>Navigation menu styles won't work
|
||||
here.</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="switcher-style-head">Page Styles:</p>
|
||||
<div class="grid grid-cols-3 switcher-style">
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="data-page-styles" class="ti-form-radio form-check-input" id="switcher-regular"
|
||||
(click)="updatepageStyles('regular')" [checked]="localdata['pageStyles'] != 'classic'">
|
||||
<label for="switcher-regular"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Regular</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="data-page-styles" class="ti-form-radio form-check-input" id="switcher-classic"
|
||||
(click)="updatepageStyles('classic')" [checked]="localdata['pageStyles'] == 'classic'">
|
||||
<label for="switcher-classic"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Classic</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="data-page-styles" class="ti-form-radio form-check-input" id="switcher-modern"
|
||||
(click)="updatepageStyles('modern')" [checked]="localdata['pageStyles'] == 'modern'">
|
||||
<label for="switcher-modern"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">
|
||||
Modern</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="switcher-style-head">Layout Width Styles:</p>
|
||||
<div class="grid grid-cols-3 switcher-style">
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="layout-width" class="ti-form-radio form-check-input" id="switcher-full-width"
|
||||
(click)="updatewidthStyles('full-width')" [checked]="localdata['widthStyles'] != 'full-width'">
|
||||
<label for="switcher-full-width"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">FullWidth</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="layout-width" class="ti-form-radio form-check-input" id="switcher-boxed"
|
||||
(click)="updatewidthStyles('boxed')" [checked]="localdata['widthStyles'] == 'boxed'">
|
||||
<label for="switcher-boxed"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Boxed</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="switcher-style-head">Menu Positions:</p>
|
||||
<div class="grid grid-cols-3 switcher-style">
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="data-menu-positions" class="ti-form-radio form-check-input"
|
||||
id="switcher-menu-fixed" (click)="updatemenuPosition('fixed')"
|
||||
[checked]="localdata['menuPosition'] != 'scrollable'">
|
||||
<label for="switcher-menu-fixed"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Fixed</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="data-menu-positions" class="ti-form-radio form-check-input"
|
||||
id="switcher-menu-scroll" (click)="updatemenuPosition('scrollable')"
|
||||
[checked]="localdata['menuPosition'] == 'scrollable'">
|
||||
<label for="switcher-menu-scroll"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Scrollable
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="switcher-style-head">Header Positions:</p>
|
||||
<div class="grid grid-cols-3 switcher-style">
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="data-header-positions" class="ti-form-radio form-check-input"
|
||||
id="switcher-header-fixed" (click)="updateheaderPosition('fixed')"
|
||||
[checked]="localdata['headerPosition'] != 'scrollable'">
|
||||
<label for="switcher-header-fixed"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">
|
||||
Fixed</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input type="radio" name="data-header-positions" class="ti-form-radio form-check-input"
|
||||
id="switcher-header-scroll" (click)="updateheaderPosition('scrollable')"
|
||||
[checked]="localdata['headerPosition'] == 'scrollable'">
|
||||
<label for="switcher-header-scroll"
|
||||
class="text-defaultsize text-defaulttextcolor dark:text-defaulttextcolor/70 ms-2 font-semibold">Scrollable
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div id="switcher-2" class="hidden" role="tabpanel" aria-labelledby="switcher-item-2">
|
||||
<div class="theme-colors">
|
||||
<p class="switcher-style-head">Menu Colors:</p>
|
||||
<div class="flex switcher-style space-x-3 ">
|
||||
<div class="hs-tooltip ti-main-tooltip ti-form-radio switch-select ">
|
||||
<input class="hs-tooltip-toggle ti-form-radio form-check-input color-input color-white" type="radio"
|
||||
name="menu-colors" id="switcher-menu-light" checked (click)="updatemenuColor('light')"
|
||||
[checked]="localdata['menuColor'] == 'light'">
|
||||
<span
|
||||
class="hs-tooltip-content ti-main-tooltip-content !py-1 !px-2 !bg-black text-xs font-medium !text-white shadow-sm dark:!bg-black"
|
||||
role="tooltip">
|
||||
Light Menu
|
||||
</span>
|
||||
</div>
|
||||
<div class="hs-tooltip ti-main-tooltip ti-form-radio switch-select ">
|
||||
<input class="hs-tooltip-toggle ti-form-radio form-check-input color-input color-dark" type="radio"
|
||||
name="menu-colors" id="switcher-menu-dark" (click)="updatemenuColor('dark')"
|
||||
[checked]="localdata['menuColor'] == 'dark'">
|
||||
<span
|
||||
class="hs-tooltip-content ti-main-tooltip-content !py-1 !px-2 !bg-black text-xs font-medium !text-white shadow-sm dark:!bg-black"
|
||||
role="tooltip">
|
||||
Dark Menu
|
||||
</span>
|
||||
</div>
|
||||
<div class="hs-tooltip ti-main-tooltip ti-form-radio switch-select ">
|
||||
<input class="hs-tooltip-toggle ti-form-radio form-check-input color-input color-primary" type="radio"
|
||||
name="menu-colors" id="switcher-menu-primary" (click)="updatemenuColor('color')"
|
||||
[checked]="localdata['menuColor'] == 'color'">
|
||||
<span
|
||||
class="hs-tooltip-content ti-main-tooltip-content !py-1 !px-2 !bg-black text-xs font-medium !text-white shadow-sm dark:!bg-black"
|
||||
role="tooltip">
|
||||
Color Menu
|
||||
</span>
|
||||
</div>
|
||||
<div class="hs-tooltip ti-main-tooltip ti-form-radio switch-select ">
|
||||
<input class="hs-tooltip-toggle ti-form-radio form-check-input color-input color-gradient" type="radio"
|
||||
name="menu-colors" id="switcher-menu-gradient" (click)="updatemenuColor('gradient')"
|
||||
[checked]="localdata['menuColor'] == 'gradient'">
|
||||
<span
|
||||
class="hs-tooltip-content ti-main-tooltip-content !py-1 !px-2 !bg-black text-xs font-medium !text-white shadow-sm dark:!bg-black"
|
||||
role="tooltip">
|
||||
Gradient Menu
|
||||
</span>
|
||||
</div>
|
||||
<div class="hs-tooltip ti-main-tooltip ti-form-radio switch-select ">
|
||||
<input class="hs-tooltip-toggle ti-form-radio form-check-input color-input color-transparent" type="radio"
|
||||
name="menu-colors" id="switcher-menu-transparent" (click)="updatemenuColor('transparent')"
|
||||
[checked]="localdata['menuColor'] == 'transparent'">
|
||||
<span
|
||||
class="hs-tooltip-content ti-main-tooltip-content !py-1 !px-2 !bg-black text-xs font-medium !text-white shadow-sm dark:!bg-black"
|
||||
role="tooltip">
|
||||
Transparent Menu
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4 text-[#8c9097] dark:text-white/50 text-[.6875rem]"><b class="me-2">Note:</b>If you want to
|
||||
change color Menu
|
||||
dynamically
|
||||
change from below Theme Primary color picker.</div>
|
||||
</div>
|
||||
<div class="theme-colors">
|
||||
<p class="switcher-style-head">Header Colors:</p>
|
||||
<div class="flex switcher-style space-x-3 ">
|
||||
<div class="hs-tooltip ti-main-tooltip ti-form-radio switch-select ">
|
||||
<input class="hs-tooltip-toggle ti-form-radio form-check-input color-input color-white !border"
|
||||
type="radio" name="header-colors" id="switcher-header-light" checked (click)="updateheaderColor('light')"
|
||||
[checked]="localdata['headerColor'] == 'light'">
|
||||
<span
|
||||
class="hs-tooltip-content ti-main-tooltip-content !py-1 !px-2 !bg-black text-xs font-medium !text-white shadow-sm dark:!bg-black"
|
||||
role="tooltip">
|
||||
Light Header
|
||||
</span>
|
||||
</div>
|
||||
<div class="hs-tooltip ti-main-tooltip ti-form-radio switch-select ">
|
||||
<input class="hs-tooltip-toggle ti-form-radio form-check-input color-input color-dark" type="radio"
|
||||
name="header-colors" id="switcher-header-dark" (click)="updateheaderColor('dark')"
|
||||
[checked]="localdata['headerColor'] == 'dark'">
|
||||
<span
|
||||
class="hs-tooltip-content ti-main-tooltip-content !py-1 !px-2 !bg-black text-xs font-medium !text-white shadow-sm dark:!bg-black"
|
||||
role="tooltip">
|
||||
Dark Header
|
||||
</span>
|
||||
</div>
|
||||
<div class="hs-tooltip ti-main-tooltip ti-form-radio switch-select ">
|
||||
<input class="hs-tooltip-toggle ti-form-radio form-check-input color-input color-primary" type="radio"
|
||||
name="header-colors" id="switcher-header-primary" (click)="updateheaderColor('color')"
|
||||
[checked]="localdata['headerColor'] == 'color'">
|
||||
<span
|
||||
class="hs-tooltip-content ti-main-tooltip-content !py-1 !px-2 !bg-black text-xs font-medium !text-white shadow-sm dark:!bg-black"
|
||||
role="tooltip">
|
||||
Color Header
|
||||
</span>
|
||||
</div>
|
||||
<div class="hs-tooltip ti-main-tooltip ti-form-radio switch-select ">
|
||||
<input class="hs-tooltip-toggle ti-form-radio form-check-input color-input color-gradient" type="radio"
|
||||
name="header-colors" id="switcher-header-gradient" (click)="updateheaderColor('gradient')"
|
||||
[checked]="localdata['headerColor'] == 'gradient'">
|
||||
<span
|
||||
class="hs-tooltip-content ti-main-tooltip-content !py-1 !px-2 !bg-black text-xs font-medium !text-white shadow-sm dark:!bg-black"
|
||||
role="tooltip">
|
||||
Gradient Header
|
||||
</span>
|
||||
</div>
|
||||
<div class="hs-tooltip ti-main-tooltip ti-form-radio switch-select ">
|
||||
<input class="hs-tooltip-toggle ti-form-radio form-check-input color-input color-transparent"
|
||||
type="radio" name="header-colors" id="switcher-header-transparent"
|
||||
(click)="updateheaderColor('transparent')" [checked]="localdata['headerColor'] == 'transparent'">
|
||||
<span
|
||||
class="hs-tooltip-content ti-main-tooltip-content !py-1 !px-2 !bg-black text-xs font-medium !text-white shadow-sm dark:!bg-black"
|
||||
role="tooltip">
|
||||
Transparent Header
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4 text-[#8c9097] dark:text-white/50 text-[.6875rem]"><b class="me-2">Note:</b>If you want to
|
||||
change color
|
||||
Header dynamically
|
||||
change from below Theme Primary color picker.</div>
|
||||
</div>
|
||||
<div class="theme-colors">
|
||||
<p class="switcher-style-head">Theme Primary:</p>
|
||||
<div class="flex switcher-style space-x-3 ">
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio form-check-input color-input color-primary-1" type="radio" name="theme-primary"
|
||||
id="switcher-primary" (click)="updateprimary('58,88,146')"
|
||||
[checked]="localdata['themePrimary'] == 'rgb(58,88,146)'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio form-check-input color-input color-primary-2" type="radio" name="theme-primary"
|
||||
id="switcher-primary1" (click)="updateprimary('92,144,163')"
|
||||
[checked]="localdata['themePrimary'] == 'rgb(92,144,163)'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio form-check-input color-input color-primary-3" type="radio" name="theme-primary"
|
||||
id="switcher-primary2" (click)="updateprimary('161,90,223')"
|
||||
[checked]="localdata['themePrimary'] == 'rgb(161,90,223)'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio form-check-input color-input color-primary-4" type="radio" name="theme-primary"
|
||||
id="switcher-primary3" (click)="updateprimary('78,172,76')"
|
||||
[checked]="localdata['themePrimary'] == 'rgb(78,172,76)'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio form-check-input color-input color-primary-5" type="radio" name="theme-primary"
|
||||
id="switcher-primary4" (click)="updateprimary('223,90,90')"
|
||||
[checked]="localdata['themePrimary'] == 'rgb(223,90,90)'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select color-primary-light">
|
||||
<div class="theme-container-primary"></div>
|
||||
<div class="pickr-container-primary">
|
||||
|
||||
<div class="pickr">
|
||||
<button type="button" type="button" role="button" aria-label="toggle color picker dialog"
|
||||
class="color-bg-transparent pcr-button" style="--pcr-color: rgba(132, 90, 223, 1);"
|
||||
[style.background]="defaultPrimary" [cpAlphaChannel]="'disabled'" [cpOutputFormat]="'rgba'"
|
||||
[(colorPicker)]="defaultPrimary" (cpSliderDragEnd)="dynamicLightPrimary($event)"></button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="theme-colors">
|
||||
<p class="switcher-style-head">Theme Background:</p>
|
||||
<div class="flex switcher-style space-x-3 ">
|
||||
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio form-check-input color-input color-bg-1" type="radio" name="theme-background"
|
||||
id="switcher-background" (click)="
|
||||
updateBackground({
|
||||
main: '20,30,96',
|
||||
secondary: '25, 38, 101',
|
||||
accent: '25, 38, 101',
|
||||
overlay: 'rgba(255,255,255,0.1)',
|
||||
primary:'rgba(255,255,255,0.1)',
|
||||
theme: 'dark'
|
||||
})
|
||||
" [checked]="localdata['themeBackground']?.['main'] === 'rgb(20,30,96)'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio color-input form-check-input color-bg-2" type="radio" name="theme-background"
|
||||
id="switcher-background1" (click)="
|
||||
updateBackground({
|
||||
main: '8,78,115',
|
||||
secondary: ' 13, 86, 120',
|
||||
accent: '13, 86, 120',
|
||||
overlay: 'rgba(255,255,255,0.1)',
|
||||
primary:'rgba(255,255,255,0.1)',
|
||||
theme: 'dark'
|
||||
})
|
||||
" [checked]="localdata['themeBackground']?.['main'] === 'rgb(8,78,115)'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio color-input form-check-input color-bg-3" type="radio" name="theme-background"
|
||||
id="switcher-background2" (click)="
|
||||
updateBackground({
|
||||
main: '90,37,135',
|
||||
secondary: '95, 45, 140',
|
||||
accent: '95, 45, 140',
|
||||
overlay: 'rgb(95, 45, 140)',
|
||||
primary:'rgb(95, 45, 140)',
|
||||
theme: 'dark'
|
||||
})
|
||||
" [checked]="localdata['themeBackground']?.['main'] === 'rgb(90,37,135)'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio color-input form-check-input color-bg-4" type="radio" name="theme-background"
|
||||
id="switcher-background3" (click)="
|
||||
updateBackground({
|
||||
main: '24,101,51',
|
||||
secondary: '29, 109, 56',
|
||||
accent: '29, 109, 56',
|
||||
overlay: 'rgba(255,255,255,0.1)',
|
||||
primary:'rgba(255,255,255,0.1)',
|
||||
theme: 'dark'
|
||||
})
|
||||
" [checked]="localdata['themeBackground']?.['main'] === 'rgb(24,101,51)'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio color-input form-check-input color-bg-5" type="radio" name="theme-background"
|
||||
id="switcher-background4" (click)="
|
||||
updateBackground({ main: '120, 66, 20', secondary: '125, 74, 25', accent: '125, 74, 25', overlay: 'rgba(255,255,255,0.1)', primary:'rgba(255,255,255,0.1)', theme: 'dark' })
|
||||
" [checked]="localdata['themeBackground']?.['main'] === 'rgb(120,66,20)'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select color-bg-transparent">
|
||||
<div class="theme-container-background hidden"></div>
|
||||
<div class="pickr-container-background">
|
||||
<div class="pickr">
|
||||
<button type="button" role="button" aria-label="toggle color picker dialog"
|
||||
class="color-bg-transparent pcr-button" style="--pcr-color: rgba(132, 90, 223, 1);"
|
||||
[style.background]="defaultBg" [cpAlphaChannel]="'disabled'" [cpOutputFormat]="'rgba'"
|
||||
[(colorPicker)]="defaultBg" (cpSliderDragEnd)="dynamicTranparentBgPrimary($event)"></button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-image theme-colors">
|
||||
<p class="switcher-style-head">Menu With Background Image:</p>
|
||||
<div class="flex switcher-style space-x-3 flex-wrap gap-3">
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio bgimage-input form-check-input bg-img1" type="radio" name="theme-images"
|
||||
id="switcher-bg-img" (click)="updateBgImage('bgimg1')"
|
||||
[checked]="localdata['backgroundImage'] == 'bgimg1'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio bgimage-input form-check-input bg-img2" type="radio" name="theme-images"
|
||||
id="switcher-bg-img1" (click)="updateBgImage('bgimg2')"
|
||||
[checked]="localdata['backgroundImage'] == 'bgimg2'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio bgimage-input form-check-input bg-img3" type="radio" name="theme-images"
|
||||
id="switcher-bg-img2" (click)="updateBgImage('bgimg3')"
|
||||
[checked]="localdata['backgroundImage'] == 'bgimg3'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio bgimage-input form-check-input bg-img4" type="radio" name="theme-images"
|
||||
id="switcher-bg-img3" (click)="updateBgImage('bgimg4')"
|
||||
[checked]="localdata['backgroundImage'] == 'bgimg4'">
|
||||
</div>
|
||||
<div class="ti-form-radio switch-select">
|
||||
<input class="ti-form-radio bgimage-input form-check-input bg-img5" type="radio" name="theme-images"
|
||||
id="switcher-bg-img4" (click)="updateBgImage('bgimg5')"
|
||||
[checked]="localdata['backgroundImage'] == 'bgimg5'">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ti-offcanvas-footer sm:flex justify-between">
|
||||
<a href="javascript:void(0);" id="reset-all" class=" ti-btn ti-btn-danger-full m-1 w-full"
|
||||
(click)="reset()">Reset</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ========== END Switcher ========== -->
|
||||
@@ -1,191 +0,0 @@
|
||||
import { Component, DOCUMENT, ElementRef, inject, Renderer2 } from '@angular/core';
|
||||
import { AppStateService } from '../../services/app-state.service';
|
||||
import { ColorPickerDirective } from 'ngx-color-picker';
|
||||
@Component({
|
||||
selector: 'app-switcher',
|
||||
templateUrl: './switcher.html',
|
||||
styleUrls: ['./switcher.scss'],
|
||||
imports: [ColorPickerDirective]
|
||||
})
|
||||
export class Switcher {
|
||||
public localdata: any;
|
||||
private document = inject<Document>(DOCUMENT);
|
||||
constructor(
|
||||
private elementRef: ElementRef,
|
||||
private appStateService: AppStateService,
|
||||
private renderer: Renderer2
|
||||
) {
|
||||
this.appStateService.state$.subscribe(state => {
|
||||
this.localdata = state;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
updateTheme(theme: string) {
|
||||
|
||||
this.appStateService.updateState({ theme, menuColor: theme, headerColor: theme });
|
||||
if (theme == 'light') {
|
||||
this.appStateService.updateState({ theme, themeBackground: '', headerColor: 'light', menuColor: 'dark' });
|
||||
let html = document.querySelector('html');
|
||||
html?.style.removeProperty('--color-bodybg');
|
||||
html?.style.removeProperty('--color-bodybg2');
|
||||
html?.style.removeProperty('--color-light');
|
||||
html?.style.removeProperty('--color-formcontrolbg');
|
||||
html?.style.removeProperty('--color-inputborder');
|
||||
html?.style.removeProperty('--color-gray3');
|
||||
if (window.innerWidth <= 992) {
|
||||
html?.setAttribute('data-toggled', 'close');
|
||||
}
|
||||
}
|
||||
if (theme == 'dark') {
|
||||
this.appStateService.updateState({ theme, themeBackground: '', headerColor: 'dark', menuColor: 'dark' });
|
||||
let html = document.querySelector('html');
|
||||
html?.style.removeProperty('--color-bodybg');
|
||||
html?.style.removeProperty('--color-bodybg2');
|
||||
html?.style.removeProperty('--color-light');
|
||||
html?.style.removeProperty('--color-formcontrolbg');
|
||||
html?.style.removeProperty('--color-inputborder');
|
||||
html?.style.removeProperty('--color-gray3');
|
||||
if (window.innerWidth <= 992) {
|
||||
html?.setAttribute('data-toggled', 'close');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updateDirection(direction: string) {
|
||||
let html = this.elementRef.nativeElement.ownerDocument.documentElement;
|
||||
this.appStateService.updateState({ direction });
|
||||
}
|
||||
updatemenuType(navigationStyles: string) {
|
||||
|
||||
|
||||
this.appStateService.updateState({ navigationStyles });
|
||||
if (navigationStyles == 'horizontal') {
|
||||
this.appStateService.updateState({ navigationStyles, menuStyles: 'menu-click', layoutStyles: '', });
|
||||
const menuclickclosed = document.getElementById(
|
||||
'switcher-menu-click'
|
||||
) as HTMLInputElement;
|
||||
|
||||
menuclickclosed.checked = true;
|
||||
setTimeout(() => {
|
||||
const mainContentElement = document.querySelector(".main-content") as HTMLElement | null;
|
||||
if (mainContentElement) {
|
||||
mainContentElement.click();
|
||||
}
|
||||
}, 100);
|
||||
} else if (navigationStyles == 'vertical') {
|
||||
this.appStateService.updateState({ navigationStyles, menuStyles: '', layoutStyles: 'default', });
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
updatemenuStyle(menuStyles: string) {
|
||||
|
||||
this.appStateService.updateState({ menuStyles, layoutStyles: '' });
|
||||
|
||||
|
||||
const navStyle = document.documentElement.getAttribute('data-nav-style');
|
||||
|
||||
if (navStyle === 'icon-hover') {
|
||||
document.querySelector('.double-menu-active')?.setAttribute('style', 'display: none;');
|
||||
const Sidebar: any = document.querySelector(".main-menu");
|
||||
if (Sidebar) {
|
||||
Sidebar.style.marginInline = "0px";
|
||||
}
|
||||
}
|
||||
|
||||
if (navStyle === 'icon-click') {
|
||||
const Sidebar: any = document.querySelector(".main-menu");
|
||||
if (Sidebar) {
|
||||
Sidebar.style.marginInline = "0px";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
updatelayoutStyles(layoutStyles: string) {
|
||||
this.appStateService.updateState({ layoutStyles, menuStyles: '', navigationStyles: '' });
|
||||
if (document.querySelector('html')?.getAttribute('data-vertical-style') == 'doublemenu') {
|
||||
document.querySelector('.slide-menu')?.classList.add('double-menu-active');
|
||||
}
|
||||
else {
|
||||
document.querySelector('.slide-menu')?.classList.remove('double-menu-active');
|
||||
}
|
||||
}
|
||||
updatepageStyles(pageStyles: string) {
|
||||
this.appStateService.updateState({ pageStyles });
|
||||
}
|
||||
updatewidthStyles(widthStyles: string) {
|
||||
this.appStateService.updateState({ widthStyles });
|
||||
}
|
||||
updatemenuPosition(menuPosition: string) {
|
||||
this.appStateService.updateState({ menuPosition });
|
||||
}
|
||||
updateheaderPosition(headerPosition: string) {
|
||||
this.appStateService.updateState({ headerPosition });
|
||||
}
|
||||
updatemenuColor(menuColor: string) {
|
||||
this.appStateService.updateState({ menuColor });
|
||||
}
|
||||
updateheaderColor(headerColor: string) {
|
||||
this.appStateService.updateState({ headerColor: headerColor });
|
||||
}
|
||||
updateprimary(themePrimary: string) {
|
||||
this.appStateService.updateState({ themePrimary: `rgb(${themePrimary})` });
|
||||
}
|
||||
updateBackground(themeBackground: any) {
|
||||
const background = {
|
||||
main: `rgb(${themeBackground.main})`,
|
||||
secondary: `rgb(${themeBackground.secondary})`,
|
||||
accent: `rgb(${themeBackground.accent})`,
|
||||
overlay: themeBackground.overlay,
|
||||
primary: themeBackground.primary,
|
||||
theme: themeBackground.theme
|
||||
}
|
||||
this.appStateService.updateState({ themeBackground: background, menuColor: 'dark', headerColor: 'dark', theme: "dark" });
|
||||
}
|
||||
updateBgImage(backgroundImage: string) {
|
||||
this.appStateService.updateState({ backgroundImage });
|
||||
}
|
||||
|
||||
|
||||
defaultPrimary = '#6c5ffc';
|
||||
public dynamicLightPrimary(data: any): void {
|
||||
this.defaultPrimary = data.color;
|
||||
let primaryColor = this.convertRgbToIndividual(this.defaultPrimary)
|
||||
|
||||
this.updateprimary(primaryColor);
|
||||
|
||||
}
|
||||
|
||||
//background theme change
|
||||
convertRgbToIndividual(value: string): string {
|
||||
// Use a regular expression to extract the numeric values
|
||||
const numericValues = value.match(/\d+/g) || [];
|
||||
// Join the numeric values with spaces to get the desired format
|
||||
return numericValues.join(' ');
|
||||
}
|
||||
public defaultBg = '#6c5ffc';
|
||||
public dynamicTranparentBgPrimary(data: any): void {
|
||||
this.defaultBg = data.color;
|
||||
let bgRgb = this.convertRgbToIndividual(this.defaultBg);
|
||||
let bgRgb2 = this.convertRgbToIndividual(this.defaultBg);
|
||||
let bg1Update = bgRgb.split(' ').join(', ');
|
||||
let bg2Update: any = bgRgb2.split(' ');
|
||||
bg2Update[0] = Number(bg2Update[0]) + 14;
|
||||
bg2Update[1] = Number(bg2Update[1]) + 14;
|
||||
bg2Update[2] = Number(bg2Update[2]) + 14;
|
||||
let bgColor = {
|
||||
main: bg1Update, secondary: bg2Update.join(', '),
|
||||
accent: bg2Update.join(', '), overlay: 'rgba(255,255,255,0.1)',
|
||||
theme: 'dark',
|
||||
}
|
||||
this.updateBackground(bgColor);
|
||||
}
|
||||
reset() {
|
||||
this.appStateService.applyReset();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
<!-- Back To Top -->
|
||||
<div class="scrollToTop" (click)="taptotop()"
|
||||
[ngStyle]="{ display: show ? 'block' : 'none' }"
|
||||
style="display: flex">
|
||||
<span class="arrow"><i class="ri-arrow-up-s-fill text-xl leading-loose"></i></span>
|
||||
</div>
|
||||
@@ -1,35 +0,0 @@
|
||||
import { ViewportScroller, NgStyle } from '@angular/common';
|
||||
import { Component, HostListener, inject } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tab-to-top',
|
||||
templateUrl: './tab-to-top.html',
|
||||
styleUrl: './tab-to-top.scss',
|
||||
imports: [NgStyle]
|
||||
})
|
||||
export class TabToTop {
|
||||
private viewScroller = inject(ViewportScroller);
|
||||
|
||||
public show: boolean = false;
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
@HostListener("window:scroll", [])
|
||||
|
||||
onWindowScroll() {
|
||||
let number = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
|
||||
if (number > 150) {
|
||||
this.show = true;
|
||||
} else {
|
||||
this.show = false;
|
||||
}
|
||||
}
|
||||
|
||||
taptotop() {
|
||||
let body: any = document.querySelector('body')
|
||||
body.style.scrollBehavior = 'smooth';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
<router-outlet />
|
||||
@@ -1,14 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-authentication-layout',
|
||||
templateUrl: './authentication-layout.html',
|
||||
styleUrl: './authentication-layout.scss',
|
||||
imports: [RouterOutlet]
|
||||
})
|
||||
export class AuthenticationLayout {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<app-switcher />
|
||||
<app-loader />
|
||||
<div class="page">
|
||||
<app-header />
|
||||
<app-sidebar appHoverEffectSidebar />
|
||||
<div class="content">
|
||||
<div class="main-content" (click)="clickOnBody()">
|
||||
|
||||
<app-page-header />
|
||||
<router-outlet />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<app-footer />
|
||||
<app-tab-to-top />
|
||||
|
||||
</div>
|
||||
<div #responsiveoverlay id="responsive-overlay" (click)="clearToggle()"></div>
|
||||
|
||||
@if (sessionTimeoutService.showWarning()) {
|
||||
<div
|
||||
class="hs-overlay ti-modal mt-[1.75rem] hs-overlay-backdrop-open:!bg-[#32325180] dark:hs-overlay-backdrop-open:!bg-[#323251cc] pointer-events-none !block">
|
||||
<div class="ti-modal-box pointer-events-auto">
|
||||
<div class="ti-modal-content !border !border-defaultborder dark:!border-defaultborder/10 !rounded-[0.5rem]">
|
||||
<div class="ti-modal-body !p-[1.5rem]">
|
||||
<div class="flex items-start gap-4">
|
||||
<span class="!w-[3rem] !h-[3rem] !leading-[3rem] rounded-[50%] avatar bg-warning/10 !text-warning text-center">
|
||||
<i class="fe fe-alert-triangle text-[1.125rem]"></i>
|
||||
</span>
|
||||
<div>
|
||||
<p class="text-[1rem] font-semibold text-defaulttextcolor dark:text-defaulttextcolor/70 mb-2">Session Expiring Soon</p>
|
||||
<p class="text-[#8c9097] dark:text-white/50 text-[0.875rem] mb-0">
|
||||
You have been inactive. You will be signed out in {{ sessionTimeoutService.remainingSeconds() }} seconds unless you continue your session.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ti-modal-footer !border !border-defaultborder dark:!border-defaultborder/10 !py-[1rem] !px-[1.25rem] justify-end gap-2">
|
||||
<button type="button" class="ti-btn ti-btn-light" (click)="sessionTimeoutService.logoutNow()">Log Out</button>
|
||||
<button type="button" class="ti-btn ti-btn-primary-full" (click)="sessionTimeoutService.staySignedIn()">Stay Signed In</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
import { Component, DOCUMENT, ElementRef, Renderer2, ViewChild, inject } from '@angular/core';
|
||||
import { Menu, NavService } from '../../services/nav.service';
|
||||
import { Router, RouterOutlet } from '@angular/router';
|
||||
import { AppStateService } from '../../services/app-state.service';
|
||||
import { Switcher } from '../../components/switcher/switcher';
|
||||
import { Header } from '../../components/header/header';
|
||||
import { Sidebar } from '../../components/sidebar/sidebar';
|
||||
import { HoverEffectSidebarDirective } from '../../directives/hover-effect-sidebar.directive';
|
||||
import { PageHeader } from '../../components/page-header/page-header';
|
||||
import { Footer } from '../../components/footer/footer';
|
||||
import { TabToTop } from '../../components/tab-to-top/tab-to-top';
|
||||
import { AppLoader } from '../../components/app-loader/app-loader';
|
||||
import { SessionTimeoutService } from '../../../core/services/session-timeout.service';
|
||||
import { AppContextService } from '../../../core/services/app-context.service';
|
||||
import { AuthService } from '../../../core/auth/auth.service';
|
||||
@Component({
|
||||
selector: 'app-content-layout',
|
||||
templateUrl: './content-layout.html',
|
||||
styleUrl: './content-layout.scss',
|
||||
providers: [SessionTimeoutService],
|
||||
imports: [
|
||||
Switcher,
|
||||
Header,
|
||||
Sidebar,
|
||||
HoverEffectSidebarDirective,
|
||||
PageHeader,
|
||||
RouterOutlet,
|
||||
Footer,
|
||||
TabToTop,
|
||||
AppLoader,
|
||||
],
|
||||
})
|
||||
export class ContentLayout {
|
||||
navServices = inject(NavService);
|
||||
sessionTimeoutService = inject(SessionTimeoutService);
|
||||
private readonly appContextService = inject(AppContextService);
|
||||
private readonly authService = inject(AuthService);
|
||||
private document = inject<Document>(DOCUMENT);
|
||||
private appStateService = inject(AppStateService);
|
||||
private elementRef = inject(ElementRef);
|
||||
private renderer = inject(Renderer2);
|
||||
@ViewChild('responsiveoverlay') responsiveoverlay!: ElementRef<HTMLDivElement>;
|
||||
public menuItems!: Menu[];
|
||||
|
||||
constructor() {
|
||||
this.sessionTimeoutService.start();
|
||||
|
||||
if (this.authService.isLoggedIn) {
|
||||
this.appContextService.ensureMenuInitialized().subscribe();
|
||||
}
|
||||
|
||||
this.navServices.items.subscribe((menuItems: any) => {
|
||||
this.menuItems = menuItems;
|
||||
});
|
||||
let html = this.document.documentElement;
|
||||
this.appStateService.state$.subscribe(state => {
|
||||
if (state) {
|
||||
if (window.innerWidth <= 996) {
|
||||
html?.setAttribute('data-toggled', html?.getAttribute('data-toggled') == 'close' ? 'close' : 'close');
|
||||
}
|
||||
if (state.menuStyles == 'menu-hover' || state.menuStyles == 'icon-hover') {
|
||||
this.clearNavDropdown()
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
clearNavDropdown() {
|
||||
|
||||
|
||||
this.menuItems?.forEach((a: any) => {
|
||||
a.active = false;
|
||||
a?.children?.forEach((b: any) => {
|
||||
b.active = false;
|
||||
b?.children?.forEach((c: any) => {
|
||||
c.active = false;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
clickOnBody() {
|
||||
this.responsiveoverlay.nativeElement.classList.remove('active');
|
||||
const htmlElement = this.document.documentElement;
|
||||
this.renderer.removeAttribute(htmlElement, 'data-icon-overlay');
|
||||
if (window.innerWidth <= 996) {
|
||||
htmlElement?.setAttribute('data-toggled', htmlElement?.getAttribute('data-toggled') == 'close' ? 'close' : 'close');
|
||||
}
|
||||
const navStyle = htmlElement.getAttribute('data-nav-style');
|
||||
|
||||
if (htmlElement.getAttribute('data-toggled') == 'icon-text-close') {
|
||||
this.renderer.removeAttribute(htmlElement, 'data-icon-text');
|
||||
}
|
||||
if (htmlElement.getAttribute('data-nav-layout') == 'horizontal'
|
||||
&& window.innerWidth > 996) {
|
||||
this.clearNavDropdown();
|
||||
}
|
||||
else
|
||||
if (navStyle === 'menu-click' || navStyle === 'menu-hover' || navStyle === 'icon-click' || navStyle === 'icon-hover') {
|
||||
document.querySelector('.double-menu-active')?.setAttribute('style', 'display: none;');
|
||||
}
|
||||
|
||||
const switcher = this.elementRef.nativeElement.querySelector('.switcher');
|
||||
if (switcher) {
|
||||
this.renderer.removeClass(switcher, 'show');
|
||||
this.responsiveoverlay.nativeElement.classList.add('active');
|
||||
} else {
|
||||
this.responsiveoverlay.nativeElement.classList.remove('active');
|
||||
}
|
||||
const sidebar = this.elementRef.nativeElement.querySelector('.sidebar');
|
||||
if (sidebar) {
|
||||
this.renderer.removeClass(sidebar, 'show');
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
closeMenu() {
|
||||
this.menuItems?.forEach((a: any) => {
|
||||
if (this.menuItems) {
|
||||
a.active = false;
|
||||
}
|
||||
a?.children?.forEach((b: any) => {
|
||||
if (a.children) {
|
||||
b.active = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
clearToggle() {
|
||||
let html = this.elementRef.nativeElement.ownerDocument.documentElement;
|
||||
html?.setAttribute('data-toggled', 'close');
|
||||
document.querySelector('#responsive-overlay')?.classList.remove('active');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,321 +0,0 @@
|
||||
import { DOCUMENT, ElementRef, inject, Injectable, Renderer2 } from '@angular/core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
interface StateType {
|
||||
direction: string;
|
||||
theme: string;
|
||||
navigationStyles: string, // vertical, horizontal
|
||||
menuStyles: string, // menu-click, menu-hover, icon-click, icon-hover
|
||||
layoutStyles: string, // double-menu, detached, icon-overlay, icontext-menu, closed-menu, default-menu
|
||||
pageStyles: string, // regular, classic, modern
|
||||
widthStyles: string, // fullwidth, boxed
|
||||
menuPosition: string, // fixed, scrollable
|
||||
headerPosition: string, // fixed, scrollable
|
||||
menuColor: string, // light, dark, color, gradient, transparent
|
||||
headerColor: string, // light, dark, color, gradient, transparent
|
||||
themePrimary: string, // '58, 88, 146', '92, 144, 163', '161, 90, 223', '78, 172, 76', '223, 90, 90'
|
||||
themeBackground: string,
|
||||
backgroundImage: string,
|
||||
};
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AppStateService {
|
||||
private readonly localStorageKey = 'Ynex-ng'; // Customize this key
|
||||
private initialState: StateType = {
|
||||
theme: 'light', // light, dark
|
||||
direction: 'ltr', // ltr, rtl
|
||||
navigationStyles: 'vertical', // vertical, horizontal
|
||||
menuStyles: '', // menu-click, menu-hover, icon-click, icon-hover
|
||||
layoutStyles: 'default', // double-menu, detached, icon-overlay, icontext-menu, closed-menu, default-menu
|
||||
pageStyles: 'regular', // regular, classic, modern
|
||||
widthStyles: 'fullwidth', // fullwidth, boxed
|
||||
menuPosition: 'fixed', // fixed, scrollable
|
||||
headerPosition: 'fixed', // fixed, scrollable
|
||||
menuColor: 'dark', // light, dark, color, gradient, transparent
|
||||
headerColor: 'light', // light, dark, color, gradient, transparent
|
||||
themePrimary: '', // '58, 88, 146', '92, 144, 163', '161, 90, 223', '78, 172, 76', '223, 90, 90'
|
||||
themeBackground: '',
|
||||
backgroundImage: '', // bgimg1, bgimg2, bgimg3, bgimg4, bgimg5
|
||||
} // Store initial state
|
||||
private stateSubject = new BehaviorSubject<StateType>(this.initialState); // Use any for initial null value
|
||||
state$ = this.stateSubject.asObservable();
|
||||
private document = inject(DOCUMENT);
|
||||
navigationStyles: any;
|
||||
private html = this.document.documentElement;
|
||||
|
||||
constructor() {
|
||||
|
||||
const initialState: StateType = this.getInitialStateFromLocalStorage();
|
||||
// this.initializeState();
|
||||
this.stateSubject.next(initialState);
|
||||
|
||||
}
|
||||
|
||||
private getInitialStateFromLocalStorage(): StateType {
|
||||
try {
|
||||
const storedState = localStorage.getItem(this.localStorageKey);
|
||||
if (storedState) {
|
||||
return JSON.parse(storedState);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error retrieving initial state from local storage:', error);
|
||||
}
|
||||
return this.initialState;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
getupdateState() {
|
||||
const currentState = this.stateSubject.getValue();
|
||||
return currentState
|
||||
}
|
||||
|
||||
updateState(newState?: Partial<any>) { // Use any for partial updates
|
||||
const currentState = this.stateSubject.getValue(); // Get current state
|
||||
|
||||
if (!currentState) {
|
||||
|
||||
// Handle initial update case (no state emitted yet)
|
||||
this.updateStateAndEmit(newState);
|
||||
return;
|
||||
}
|
||||
if (newState) {
|
||||
|
||||
const updatedState = { ...currentState, ...newState }; // Merge updates
|
||||
this.updateStateAndEmit(updatedState); // Update and emit combined state
|
||||
} else {
|
||||
this.updateStateAndEmit(currentState);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private state: { [key: string]: any } = {};
|
||||
getState(menuStyles: string): any {
|
||||
return this.state[menuStyles];
|
||||
}
|
||||
private applyThemeBackgroundSpecificChanges(background: any) {
|
||||
|
||||
this.html?.style.setProperty('--color-bodybg', background.main);
|
||||
this.html?.style.setProperty('--color-bodybg2', background.secondary);
|
||||
this.html?.style.setProperty('--color-light', background.accent);
|
||||
this.html?.style.setProperty('--color-formcontrolbg', `rgba(${background.accent})`);
|
||||
this.html?.style.setProperty('--color-inputborder', background.overlay);
|
||||
this.html?.style.setProperty('--color-gray3', background.primary);
|
||||
this.applythemeSpecificChanges(background.theme);
|
||||
}
|
||||
|
||||
|
||||
private applyDirectionSpecificChanges(direction: string) {
|
||||
|
||||
|
||||
this.html?.setAttribute('dir', direction);
|
||||
|
||||
}
|
||||
private applythemeSpecificChanges(theme: string) {
|
||||
|
||||
|
||||
this.html?.setAttribute('class', theme); //setting theme style
|
||||
this.html?.setAttribute('data-header-styles', theme); //setting header style
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private applyNavigationStylesSpecificChanges(navigationStyles: string) {
|
||||
|
||||
|
||||
|
||||
this.html?.setAttribute('data-nav-layout', navigationStyles);
|
||||
if (navigationStyles == 'horizontal') {
|
||||
this.html?.setAttribute('data-nav-style', 'menu-click');
|
||||
this.html?.removeAttribute('data-vertical-style');
|
||||
|
||||
}
|
||||
}
|
||||
private applyMenuStylesSpecificChanges(menuStyles: string) {
|
||||
|
||||
|
||||
|
||||
this.html?.setAttribute('data-nav-style', menuStyles);
|
||||
this.html?.setAttribute('data-toggled', menuStyles + '-closed');
|
||||
this.html?.removeAttribute('data-vertical-style');
|
||||
}
|
||||
private applyLayoutStylesSpecificChanges(layoutStyles: string) {
|
||||
|
||||
this.html?.setAttribute('data-vertical-style', layoutStyles);
|
||||
this.html?.removeAttribute('data-nav-style');
|
||||
switch (layoutStyles) {
|
||||
case 'default':
|
||||
this.html?.setAttribute('data-vertical-style', 'overlay');
|
||||
this.html?.setAttribute('data-toggled', '');
|
||||
break;
|
||||
case 'closed':
|
||||
this.html?.setAttribute('data-toggled', 'close-menu-close');
|
||||
break;
|
||||
case 'icontext':
|
||||
this.html?.setAttribute('data-toggled', 'icon-text-close');
|
||||
break;
|
||||
case 'overlay':
|
||||
this.html?.setAttribute('data-toggled', 'icon-overlay-close');
|
||||
break;
|
||||
case 'detached':
|
||||
this.html?.setAttribute('data-toggled', 'detached-close');
|
||||
break;
|
||||
case 'doublemenu':
|
||||
this.html?.setAttribute('data-toggled', 'double-menu-open');
|
||||
break;
|
||||
}
|
||||
if (layoutStyles === 'icon-text') {
|
||||
this.html?.setAttribute('icon-text', 'open');
|
||||
} else {
|
||||
// If not 'icon-text', remove the icon-text attribute
|
||||
this.html?.removeAttribute('icon-text');
|
||||
}
|
||||
}
|
||||
private applypageStylesSpecificChanges(pageStyles: string) {
|
||||
|
||||
this.html?.setAttribute('data-page-style', pageStyles);
|
||||
|
||||
const slideRight = document.querySelector('.slide-right') as HTMLElement | null;
|
||||
if (slideRight) {
|
||||
// If the element exists, toggle the 'd-none' class
|
||||
if (slideRight.classList.contains('d-none')) {
|
||||
slideRight.classList.remove('d-none');
|
||||
} else {
|
||||
slideRight.classList.add('d-none');
|
||||
}
|
||||
} else {
|
||||
// If the element does not exist (is null), create a safe fallback by adding 'd-none'
|
||||
const dummySlideRight = document.createElement('div');
|
||||
dummySlideRight.classList.add('slide-right', 'd-none'); // Add classes to the new element
|
||||
document.body.appendChild(dummySlideRight); // Append it to the DOM as a fallback
|
||||
}
|
||||
}
|
||||
private applywidthStylesSpecificChanges(widthStyles: string) {
|
||||
|
||||
this.html?.setAttribute('data-width', widthStyles);
|
||||
}
|
||||
private applymenuPositionSpecificChanges(menuPosition: string) {
|
||||
|
||||
this.html?.setAttribute('data-menu-position', menuPosition);
|
||||
}
|
||||
private applyheaderPositionSpecificChanges(headerPosition: string) {
|
||||
|
||||
this.html?.setAttribute('data-header-position', headerPosition);
|
||||
}
|
||||
private applyheaderColorSpecificChanges(headerColor: string) {
|
||||
|
||||
this.html?.setAttribute('data-header-styles', headerColor);
|
||||
}
|
||||
private applymenuColorSpecificChanges(menuColor: string) {
|
||||
|
||||
this.html?.setAttribute('data-menu-styles', menuColor);
|
||||
}
|
||||
private applyPrimarySpecificChanges(primary: string) {
|
||||
|
||||
this.html?.style.setProperty('--color-primaryrgb', primary);
|
||||
this.html?.style.setProperty('--color-primary', primary);
|
||||
}
|
||||
private applybackgroundImageSpecificChanges(backgroundImage: string) {
|
||||
|
||||
this.html?.setAttribute('bg-img', backgroundImage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public applyReset() {
|
||||
|
||||
if (this.html) {
|
||||
this.html?.style.removeProperty('--color-bodybg');
|
||||
this.html?.style.removeProperty('--color-gray3');
|
||||
this.html?.style.removeProperty('--color-bodybg2');
|
||||
this.html?.style.removeProperty('--color-light');
|
||||
this.html?.style.removeProperty('--color-formcontrolbg');
|
||||
this.html?.style.removeProperty('--color-inputborder');
|
||||
this.html?.style.removeProperty('--color-primary');
|
||||
this.html?.style.removeProperty('--color-primaryrgb');
|
||||
|
||||
}
|
||||
this.html?.removeAttribute('bg-img');
|
||||
this.html?.setAttribute('data-vertical-style', 'overlay');
|
||||
this.stateSubject.next(this.initialState);
|
||||
this.updateStateAndEmit(this.initialState);
|
||||
localStorage.clear();
|
||||
|
||||
if (window.innerWidth <= 992) {
|
||||
this.html?.setAttribute('data-toggled', 'close');
|
||||
}
|
||||
}
|
||||
|
||||
private updateStateAndEmit(state: any) {
|
||||
// Conditional logic based on direction changes
|
||||
|
||||
const currentState = this.stateSubject.getValue(); // Get current state
|
||||
// Conditional logic based on theme changes
|
||||
if (state['theme']) {
|
||||
|
||||
this.applythemeSpecificChanges(state['theme']);
|
||||
}
|
||||
if (state['direction']) {
|
||||
|
||||
this.applyDirectionSpecificChanges(state['direction']);
|
||||
}
|
||||
// Conditional logic based on theme changes
|
||||
if (state['navigationStyles']) {
|
||||
this.applyNavigationStylesSpecificChanges(state['navigationStyles']);
|
||||
}
|
||||
// Conditional logic based on theme changes
|
||||
if (state['menuStyles'] && !state['layoutStyles']) {
|
||||
this.applyMenuStylesSpecificChanges(state['menuStyles']);
|
||||
}
|
||||
if (state['layoutStyles'] && !state['menuStyles']) {
|
||||
this.applyLayoutStylesSpecificChanges(state['layoutStyles']);
|
||||
}
|
||||
if (state['pageStyles']) {
|
||||
this.applypageStylesSpecificChanges(state['pageStyles']);
|
||||
}
|
||||
if (state['widthStyles']) {
|
||||
this.applywidthStylesSpecificChanges(state['widthStyles']);
|
||||
}
|
||||
if (state['menuPosition']) {
|
||||
this.applymenuPositionSpecificChanges(state['menuPosition']);
|
||||
}
|
||||
if (state['headerPosition']) {
|
||||
this.applyheaderPositionSpecificChanges(state['headerPosition']);
|
||||
}
|
||||
if (state['themePrimary']) {
|
||||
this.applyPrimarySpecificChanges(state['themePrimary']);
|
||||
}
|
||||
if (state['themeBackground']) {
|
||||
this.applyThemeBackgroundSpecificChanges(state['themeBackground']);
|
||||
}
|
||||
if (state['headerColor']) {
|
||||
this.applyheaderColorSpecificChanges(state['headerColor']);
|
||||
}
|
||||
if (state['menuColor']) {
|
||||
this.applymenuColorSpecificChanges(state['menuColor']);
|
||||
}
|
||||
if (state['backgroundImage']) {
|
||||
this.applybackgroundImageSpecificChanges(state['backgroundImage']);
|
||||
}
|
||||
|
||||
this.stateSubject.next(state);
|
||||
this.updateLocalStorage(state);
|
||||
}
|
||||
|
||||
private updateLocalStorage(state: any) {
|
||||
try {
|
||||
localStorage.setItem(this.localStorageKey, JSON.stringify(state));
|
||||
} catch (error) {
|
||||
console.error('Error saving state to local storage:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
import { Injectable, NgZone, inject } from '@angular/core';
|
||||
import { AngularFireModule } from '@angular/fire/compat';
|
||||
import { AngularFireAuth } from '@angular/fire/compat/auth';
|
||||
import { Router } from '@angular/router';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { AngularFirestoreDocument } from '@angular/fire/compat/firestore';
|
||||
export interface User {
|
||||
uid: string;
|
||||
email: string;
|
||||
displayName: string;
|
||||
photoURL: string;
|
||||
emailVerified: boolean;
|
||||
}
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AuthService {
|
||||
private afu = inject(AngularFireAuth);
|
||||
private router = inject(Router);
|
||||
ngZone = inject(NgZone);
|
||||
|
||||
authState: any;
|
||||
afAuth: any;
|
||||
afs: any;
|
||||
public showLoader:boolean=false;
|
||||
|
||||
constructor() {
|
||||
this.afu.authState.subscribe((auth: any) => {
|
||||
this.authState = auth;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// all firebase getdata functions
|
||||
|
||||
get isUserAnonymousLoggedIn(): boolean {
|
||||
return this.authState !== null ? this.authState.isAnonymous : false;
|
||||
}
|
||||
|
||||
get currentUserId(): string {
|
||||
return this.authState !== null ? this.authState.uid : '';
|
||||
}
|
||||
|
||||
get currentUserName(): string {
|
||||
return this.authState['email'];
|
||||
}
|
||||
|
||||
get currentUser(): any {
|
||||
return this.authState !== null ? this.authState : null;
|
||||
}
|
||||
|
||||
get isUserEmailLoggedIn(): boolean {
|
||||
if (this.authState !== null && !this.isUserAnonymousLoggedIn) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
registerWithEmail(email: string, password: string) {
|
||||
return this.afu
|
||||
.createUserWithEmailAndPassword(email, password)
|
||||
.then((user: any) => {
|
||||
this.authState = user;
|
||||
})
|
||||
.catch((_error: any) => {
|
||||
console.log(_error);
|
||||
throw _error;
|
||||
});
|
||||
}
|
||||
|
||||
loginWithEmail(email: string, password: string) {
|
||||
return this.afu
|
||||
.signInWithEmailAndPassword(email, password)
|
||||
.then((user: any) => {
|
||||
this.authState = user;
|
||||
})
|
||||
.catch((_error: any) => {
|
||||
console.log(_error);
|
||||
throw _error;
|
||||
});
|
||||
}
|
||||
|
||||
singout(): void {
|
||||
this.afu.signOut();
|
||||
this.router.navigate(['/login']);
|
||||
}
|
||||
|
||||
|
||||
// Sign up with email/password
|
||||
SignUp(email:any, password:any) {
|
||||
return this.afAuth.createUserWithEmailAndPassword(email, password)
|
||||
.then((result:any) => {
|
||||
/* Call the SendVerificaitonMail() function when new user sign
|
||||
up and returns promise */
|
||||
this.SendVerificationMail();
|
||||
this.SetUserData(result.user);
|
||||
}).catch((error:any) => {
|
||||
window.alert(error.message)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// main verification function
|
||||
SendVerificationMail() {
|
||||
return this.afAuth.currentUser.then((u:any) => u.sendEmailVerification()).then(() => {
|
||||
this.router.navigate(['/dashboard']);
|
||||
})
|
||||
}
|
||||
// Set user
|
||||
SetUserData(user:any) {
|
||||
const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${user.uid}`);
|
||||
const userData: User = {
|
||||
email: user.email,
|
||||
displayName: user.displayName,
|
||||
uid: user.uid,
|
||||
photoURL: user.photoURL || 'src/favicon.ico',
|
||||
emailVerified: user.emailVerified
|
||||
};
|
||||
userRef.delete().then(function () {})
|
||||
.catch(function (error:any) {});
|
||||
return userRef.set(userData, {
|
||||
merge: true
|
||||
});
|
||||
}
|
||||
// sign in function
|
||||
SignIn(email:any, password:any) {
|
||||
return this.afAuth.signInWithEmailAndPassword(email, password)
|
||||
.then((result:any) => {
|
||||
if (result.user.emailVerified !== true) {
|
||||
this.SetUserData(result.user);
|
||||
this.SendVerificationMail();
|
||||
this.showLoader = true;
|
||||
} else {
|
||||
this.showLoader = false;
|
||||
this.ngZone.run(() => {
|
||||
this.router.navigate(['/auth/login']);
|
||||
});
|
||||
}
|
||||
}).catch((error:any) => {
|
||||
throw error;
|
||||
})
|
||||
}
|
||||
ForgotPassword(passwordResetEmail:any) {
|
||||
return this.afAuth.sendPasswordResetEmail(passwordResetEmail)
|
||||
.then(() => {
|
||||
window.alert('Password reset email sent, check your inbox.');
|
||||
}).catch((error:any) => {
|
||||
window.alert(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AngularFireModule } from '@angular/fire/compat';
|
||||
import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
|
||||
import { AngularFireDatabaseModule } from '@angular/fire/compat/database';
|
||||
import { AngularFireAuthModule } from '@angular/fire/compat/auth';
|
||||
import { environment } from '../../../environments/environment';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class FirebaseService {
|
||||
constructor() {
|
||||
AngularFireModule.initializeApp(environment.firebase);
|
||||
}
|
||||
|
||||
getFirestore() {
|
||||
return AngularFirestoreModule;
|
||||
}
|
||||
|
||||
getDatabase() {
|
||||
return AngularFireDatabaseModule;
|
||||
}
|
||||
|
||||
getAuth() {
|
||||
return AngularFireAuthModule;
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
import { Injectable, OnDestroy } from '@angular/core';
|
||||
import { Subject, BehaviorSubject, fromEvent } from 'rxjs';
|
||||
import { takeUntil, debounceTime } from 'rxjs/operators';
|
||||
import { Router } from '@angular/router';
|
||||
// Menu
|
||||
export interface Menu {
|
||||
headTitle?: string;
|
||||
headTitle2?: string;
|
||||
path?: string;
|
||||
title?: string;
|
||||
icon?: string;
|
||||
type?: string;
|
||||
badgeValue?: string;
|
||||
badgeClass?: string;
|
||||
badgeText?: string;
|
||||
active?: boolean;
|
||||
selected?: boolean;
|
||||
bookmark?: boolean;
|
||||
children?: Menu[];
|
||||
children2?: Menu[];
|
||||
Menusub?: boolean;
|
||||
target?: boolean;
|
||||
menutype?: string,
|
||||
dirchange?: boolean,
|
||||
nochild?: any
|
||||
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class NavService implements OnDestroy {
|
||||
private unsubscriber: Subject<any> = new Subject();
|
||||
public screenWidth: BehaviorSubject<number> = new BehaviorSubject(
|
||||
window.innerWidth
|
||||
);
|
||||
|
||||
// Search Box
|
||||
public search = false;
|
||||
|
||||
// Language
|
||||
public language = false;
|
||||
|
||||
// Mega Menu
|
||||
public megaMenu = false;
|
||||
public levelMenu = false;
|
||||
public megaMenuColapse: boolean = window.innerWidth < 1199 ? true : false;
|
||||
|
||||
// Collapse Sidebar
|
||||
public collapseSidebar: boolean = window.innerWidth < 991 ? true : false;
|
||||
|
||||
// For Horizontal Layout Mobile
|
||||
public horizontal: boolean = window.innerWidth < 991 ? false : true;
|
||||
|
||||
// Full screen
|
||||
public fullScreen = false;
|
||||
active: any;
|
||||
|
||||
constructor(private router: Router) {
|
||||
this.setScreenWidth(window.innerWidth);
|
||||
fromEvent(window, 'resize')
|
||||
.pipe(debounceTime(1000), takeUntil(this.unsubscriber))
|
||||
.subscribe((evt: any) => {
|
||||
this.setScreenWidth(evt.target.innerWidth);
|
||||
if (evt.target.innerWidth < 991) {
|
||||
this.collapseSidebar = true;
|
||||
this.megaMenu = false;
|
||||
this.levelMenu = false;
|
||||
}
|
||||
if (evt.target.innerWidth < 1199) {
|
||||
this.megaMenuColapse = true;
|
||||
}
|
||||
});
|
||||
if (window.innerWidth < 991) {
|
||||
// Detect Route change sidebar close
|
||||
this.router.events.subscribe((event) => {
|
||||
this.collapseSidebar = true;
|
||||
this.megaMenu = false;
|
||||
this.levelMenu = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unsubscriber.next;
|
||||
this.unsubscriber.complete();
|
||||
}
|
||||
|
||||
private setScreenWidth(width: number): void {
|
||||
this.screenWidth.next(width);
|
||||
}
|
||||
|
||||
items = new BehaviorSubject<Menu[]>([]);
|
||||
|
||||
setMenuItems(menuItems: Menu[]): void {
|
||||
this.items.next(menuItems);
|
||||
}
|
||||
|
||||
clearMenuItems(): void {
|
||||
this.items.next([]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user