diff --git a/jambotron-ui/src/app/components/breadcrumb/breadcrumb.component.html b/jambotron-ui/src/app/components/breadcrumb/breadcrumb.component.html new file mode 100644 index 0000000..77f0cb0 --- /dev/null +++ b/jambotron-ui/src/app/components/breadcrumb/breadcrumb.component.html @@ -0,0 +1,43 @@ +@for (breadcrumb of navigationList; track breadcrumb; let last = $last) { + @if (last && breadcrumb.breadcrumbs !== false) { + + } +} diff --git a/jambotron-ui/src/app/components/breadcrumb/breadcrumb.component.scss b/jambotron-ui/src/app/components/breadcrumb/breadcrumb.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/components/breadcrumb/breadcrumb.component.ts b/jambotron-ui/src/app/components/breadcrumb/breadcrumb.component.ts new file mode 100644 index 0000000..d824924 --- /dev/null +++ b/jambotron-ui/src/app/components/breadcrumb/breadcrumb.component.ts @@ -0,0 +1,103 @@ +// Angular Import +import { Component, Input, inject, input } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { NavigationEnd, Router, RouterModule, Event } from '@angular/router'; +import { Title } from '@angular/platform-browser'; + +// project import +//import { NavigationItem, NavigationItems } from 'src/app/theme/layouts/admin-layout/navigation/navigation'; + +// icons +import { IconService } from '@ant-design/icons-angular'; +import { GlobalOutline, NodeExpandOutline } from '@ant-design/icons-angular/icons'; +import {NavigationItem, NavigationItems} from '../../layouts/admin-layout/navigation/navigation'; + +interface titleType { + // eslint-disable-next-line + url: any; + title: string; + breadcrumbs: unknown; + type: string; + link?: string | undefined; + description?: string | undefined; + path?: string | undefined; +} + +@Component({ + selector: 'app-breadcrumb', + imports: [CommonModule, RouterModule], + templateUrl: './breadcrumb.component.html', + styleUrls: ['./breadcrumb.component.scss'] +}) +export class BreadcrumbComponent { + private route = inject(Router); + private titleService = inject(Title); + private iconService = inject(IconService); + + // public props + @Input() type: string; + dashboard = input(true); + Component = input(false); + + navigations: NavigationItem[]; + ComponentNavigations: NavigationItem[] = []; + breadcrumbList: Array = []; + navigationList!: titleType[]; + componentList!: titleType[]; + + // constructor + constructor() { + this.navigations = NavigationItems; + this.type = 'theme1'; + this.setBreadcrumb(); + this.iconService.addIcon(...[GlobalOutline, NodeExpandOutline]); + } + + // public method + setBreadcrumb() { + this.route.events.subscribe((router: Event) => { + if (router instanceof NavigationEnd) { + const activeLink = router.url; + const breadcrumbList = this.filterNavigation(this.navigations, activeLink); + + this.navigationList = breadcrumbList;//breadcrumbList.slice(breadcrumbList.length - 1, breadcrumbList.length); + const title = breadcrumbList[breadcrumbList.length - 1]?.title || 'Welcome'; + this.titleService.setTitle(title + ' | Mantis Angular Admin Template'); + } + }); + } + + filterNavigation(navItems: NavigationItem[], activeLink: string): titleType[] { + for (const navItem of navItems) { + if (navItem.type === 'item' && 'url' in navItem && navItem.url === activeLink) { + return [ + { + url: 'url' in navItem ? navItem.url : false, + title: navItem.title, + link: navItem.link, + description: navItem.description, + path: navItem.path, + breadcrumbs: 'breadcrumbs' in navItem ? navItem.breadcrumbs : true, + type: navItem.type + } + ]; + } + if ((navItem.type === 'group' || navItem.type === 'collapse') && 'children' in navItem) { + const breadcrumbList = this.filterNavigation(navItem.children!, activeLink); + if (breadcrumbList.length > 0) { + breadcrumbList.unshift({ + url: 'url' in navItem ? navItem.url : false, + title: navItem.title, + link: navItem.link, + path: navItem.path, + description: navItem.description, + breadcrumbs: 'breadcrumbs' in navItem ? navItem.breadcrumbs : true, + type: navItem.type + }); + return breadcrumbList; + } + } + } + return []; + } +} diff --git a/jambotron-ui/src/app/components/spinner/spinkit-css/sk-line-material.scss b/jambotron-ui/src/app/components/spinner/spinkit-css/sk-line-material.scss new file mode 100644 index 0000000..cab74fb --- /dev/null +++ b/jambotron-ui/src/app/components/spinner/spinkit-css/sk-line-material.scss @@ -0,0 +1,64 @@ +.sk-line-material { + top: 0; + position: relative; + margin: auto; + width: 100%; +} + +.sk-line-material .sk-child { + width: 100%; + height: 4px; + position: absolute; + top: 0; + display: inline-block; + transform-origin: 0% 0%; + -webkit-animation: sk-line-material 2s ease-in-out 0s infinite both; + animation: sk-line-material 2s ease-in-out 0s infinite both; +} + +@-webkit-keyframes sk-line-material { + 0%, + 80%, + 100% { + -webkit-transform: scaleX(0); + transform: scaleX(0); + } + 40% { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} + +@keyframes sk-line-material { + 0% { + -webkit-transform: scaleX(0); + transform: scaleX(0); + } + 100% { + -webkit-transform: scaleX(1); + transform: scaleX(1); + } +} + +#http-loader { + top: 0; + left: 0; + height: 100%; + width: 100%; + position: fixed; + z-index: 9999; +} + +.loader-bg { + height: 100%; + width: 100%; + position: absolute; + filter: alpha(opacity=70); + opacity: 1; + background-color: rgba(0, 0, 0, 0); +} + +.colored-parent, +.colored > div { + background-color: rgba(26, 188, 156, 0.8); +} diff --git a/jambotron-ui/src/app/components/spinner/spinkits.ts b/jambotron-ui/src/app/components/spinner/spinkits.ts new file mode 100644 index 0000000..87d5d5c --- /dev/null +++ b/jambotron-ui/src/app/components/spinner/spinkits.ts @@ -0,0 +1,11 @@ +export const Spinkit = { + skChasingDots: 'sk-chasing-dots', + skCubeGrid: 'sk-cube-grid', + skDoubleBounce: 'sk-double-bounce', + skRotatingPlane: 'sk-rotationg-plane', + skSpinnerPulse: 'sk-spinner-pulse', + skThreeBounce: 'sk-three-bounce', + skWanderingCubes: 'sk-wandering-cubes', + skWave: 'sk-wave', + skLine: 'sk-line-material' +}; diff --git a/jambotron-ui/src/app/components/spinner/spinner.component.html b/jambotron-ui/src/app/components/spinner/spinner.component.html new file mode 100644 index 0000000..7a4c0db --- /dev/null +++ b/jambotron-ui/src/app/components/spinner/spinner.component.html @@ -0,0 +1,11 @@ +@if (isSpinnerVisible) { +
+
+ @if (spinner() === Spinkit.skLine) { +
+
+
+ } +
+
+} diff --git a/jambotron-ui/src/app/components/spinner/spinner.component.scss b/jambotron-ui/src/app/components/spinner/spinner.component.scss new file mode 100644 index 0000000..8bb2921 --- /dev/null +++ b/jambotron-ui/src/app/components/spinner/spinner.component.scss @@ -0,0 +1,22 @@ +#http-loader { + top: 0; + left: 0; + height: 100%; + width: 100%; + position: fixed; + z-index: 9999; +} + +.loader-bg { + height: 100%; + width: 100%; + position: absolute; + filter: alpha(opacity=70); + opacity: 0.7; + background-color: #f1f1f1; +} + +.colored-parent, +.colored > div { + background-color: #333; +} diff --git a/jambotron-ui/src/app/components/spinner/spinner.component.ts b/jambotron-ui/src/app/components/spinner/spinner.component.ts new file mode 100644 index 0000000..a003f94 --- /dev/null +++ b/jambotron-ui/src/app/components/spinner/spinner.component.ts @@ -0,0 +1,46 @@ +// Angular import +import { Component, OnDestroy, ViewEncapsulation, inject, input } from '@angular/core'; +import { Router, NavigationStart, NavigationEnd, NavigationCancel, NavigationError } from '@angular/router'; +import { DOCUMENT } from '@angular/common'; + +// project import +import { Spinkit } from './spinkits'; + +@Component({ + selector: 'app-spinner', + templateUrl: './spinner.component.html', + styleUrls: ['./spinner.component.scss', './spinkit-css/sk-line-material.scss'], + encapsulation: ViewEncapsulation.None +}) +export class SpinnerComponent implements OnDestroy { + private router = inject(Router); + private document = inject(DOCUMENT); + + // public props + isSpinnerVisible = true; + Spinkit = Spinkit; + backgroundColor = input('#1890ff'); + spinner = input(Spinkit.skLine); + + // Constructor + constructor() { + this.router.events.subscribe( + (event) => { + if (event instanceof NavigationStart) { + this.isSpinnerVisible = true; + } else if (event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError) { + + this.isSpinnerVisible = false; + } + }, + () => { + this.isSpinnerVisible = false; + } + ); + } + + // life cycle event + ngOnDestroy(): void { + this.isSpinnerVisible = false; + } +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/admin-layout.component.html b/jambotron-ui/src/app/layouts/admin-layout/admin-layout.component.html new file mode 100644 index 0000000..e36c8f4 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/admin-layout.component.html @@ -0,0 +1,50 @@ + + + + +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+ + diff --git a/jambotron-ui/src/app/layouts/admin-layout/admin-layout.component.scss b/jambotron-ui/src/app/layouts/admin-layout/admin-layout.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/layouts/admin-layout/admin-layout.component.ts b/jambotron-ui/src/app/layouts/admin-layout/admin-layout.component.ts new file mode 100644 index 0000000..597a5b6 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/admin-layout.component.ts @@ -0,0 +1,51 @@ +// Angular import +import { Component } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; + +// Project import + +import { NavBarComponent } from './nav-bar/nav-bar.component'; +import { NavigationComponent } from './navigation/navigation.component'; +import { ConfigurationComponent } from './configuration/configuration.component'; +import {BreadcrumbComponent} from '../../components/breadcrumb/breadcrumb.component'; +//import { BreadcrumbComponent } from 'src/app/theme/shared/components/breadcrumb/breadcrumb.component'; + +@Component({ + selector: 'app-admin', + imports: [CommonModule, BreadcrumbComponent, NavigationComponent, NavBarComponent, RouterModule, ConfigurationComponent, NavigationComponent], + templateUrl: './admin-layout.component.html', + styleUrls: ['./admin-layout.component.scss'] +}) +export class AdminComponent { + // public props + navCollapsed: boolean = true; + navCollapsedMob: boolean = true; + + // public method + navMobClick() { + if (this.navCollapsedMob && !document.querySelector('app-navigation.pc-sidebar')?.classList.contains('mob-open')) { + this.navCollapsedMob = !this.navCollapsedMob; + setTimeout(() => { + this.navCollapsedMob = !this.navCollapsedMob; + }, 100); + } else { + this.navCollapsedMob = !this.navCollapsedMob; + } + if (document.querySelector('app-navigation.pc-sidebar')?.classList.contains('navbar-collapsed')) { + document.querySelector('app-navigation.pc-sidebar')?.classList.remove('navbar-collapsed'); + } + } + + handleKeyDown(event: KeyboardEvent): void { + if (event.key === 'Escape') { + this.closeMenu(); + } + } + + closeMenu() { + if (document.querySelector('app-navigation.pc-sidebar')?.classList.contains('mob-open')) { + document.querySelector('app-navigation.pc-sidebar')?.classList.remove('mob-open'); + } + } +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/configuration/configuration.component.html b/jambotron-ui/src/app/layouts/admin-layout/configuration/configuration.component.html new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/layouts/admin-layout/configuration/configuration.component.scss b/jambotron-ui/src/app/layouts/admin-layout/configuration/configuration.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/layouts/admin-layout/configuration/configuration.component.ts b/jambotron-ui/src/app/layouts/admin-layout/configuration/configuration.component.ts new file mode 100644 index 0000000..abfc887 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/configuration/configuration.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-configuration', + imports: [], + templateUrl: './configuration.component.html', + styleUrl: './configuration.component.scss' +}) +export class ConfigurationComponent {} diff --git a/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-bar.component.html b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-bar.component.html new file mode 100644 index 0000000..99f375e --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-bar.component.html @@ -0,0 +1,10 @@ +
+
+
+ +
+
+ +
+
+
diff --git a/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-bar.component.scss b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-bar.component.scss new file mode 100644 index 0000000..e4f45fd --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-bar.component.scss @@ -0,0 +1,3 @@ +.pc-header{ + left: 0; +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-bar.component.ts b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-bar.component.ts new file mode 100644 index 0000000..7c7ebaf --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-bar.component.ts @@ -0,0 +1,49 @@ +// angular import +import {Component, inject, OnInit, output} from '@angular/core'; + +// project import + +import { NavLeftComponent } from './nav-left/nav-left.component'; +import { NavRightComponent } from './nav-right/nav-right.component'; +import {DOCUMENT} from '@angular/common'; + +@Component({ + selector: 'app-nav-bar', + imports: [NavLeftComponent, NavRightComponent], + templateUrl: './nav-bar.component.html', + styleUrls: ['./nav-bar.component.scss'] +}) +export class NavBarComponent implements OnInit{ + private document = inject(DOCUMENT); + // public props + NavCollapse = output(); + NavCollapsedMob = output(); + + navCollapsed: boolean = false; + windowWidth: number | undefined = 1000; + navCollapsedMob: boolean; + + // Constructor + constructor() { + + this.navCollapsedMob = false; + } + + ngOnInit(): void { + this.windowWidth = this.document.defaultView?.innerWidth; + } + + // public method + navCollapse() { + if (!!this.windowWidth && this.windowWidth >= 1025) { + this.navCollapsed = !this.navCollapsed; + this.NavCollapse.emit(); + } + } + + navCollapseMob() { + if (!!this.windowWidth && this.windowWidth < 1025) { + this.NavCollapsedMob.emit(); + } + } +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-left/nav-left.component.html b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-left/nav-left.component.html new file mode 100644 index 0000000..d7991d8 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-left/nav-left.component.html @@ -0,0 +1,43 @@ + diff --git a/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-left/nav-left.component.scss b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-left/nav-left.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-left/nav-left.component.ts b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-left/nav-left.component.ts new file mode 100644 index 0000000..4dfb288 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-left/nav-left.component.ts @@ -0,0 +1,37 @@ +// Angular import +import {CommonModule, DOCUMENT} from '@angular/common'; +import { Component, inject, input, output } from '@angular/core'; + +// project import + +// icons +import { IconService, IconDirective } from '@ant-design/icons-angular'; +import { MenuUnfoldOutline, MenuFoldOutline, SearchOutline } from '@ant-design/icons-angular/icons'; + +@Component({ + selector: 'app-nav-left', + imports: [IconDirective, CommonModule], + templateUrl: './nav-left.component.html', + styleUrls: ['./nav-left.component.scss'] +}) +export class NavLeftComponent { + private iconService = inject(IconService); + private document = inject(DOCUMENT); + + // public props + navCollapsed = input.required(); + NavCollapse = output(); + NavCollapsedMob = output(); + windowWidth: number | undefined = 1000; + + // Constructor + constructor() { + this.windowWidth = this.document.defaultView?.innerWidth; + this.iconService.addIcon(...[MenuUnfoldOutline, MenuFoldOutline, SearchOutline]); + } + + // public method + navCollapse() { + this.NavCollapse.emit(); + } +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-right/nav-right.component.html b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-right/nav-right.component.html new file mode 100644 index 0000000..97bcd93 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-right/nav-right.component.html @@ -0,0 +1,147 @@ + diff --git a/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-right/nav-right.component.scss b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-right/nav-right.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-right/nav-right.component.ts b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-right/nav-right.component.ts new file mode 100644 index 0000000..baf2a8c --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/nav-bar/nav-right/nav-right.component.ts @@ -0,0 +1,121 @@ +// angular import +import {Component, inject, input, OnInit, output} from '@angular/core'; +import { RouterModule } from '@angular/router'; + +// project import + +// icon +import { IconService, IconDirective } from '@ant-design/icons-angular'; +import { + BellOutline, + SettingOutline, + GiftOutline, + MessageOutline, + PhoneOutline, + CheckCircleOutline, + LogoutOutline, + EditOutline, + UserOutline, + ProfileOutline, + WalletOutline, + QuestionCircleOutline, + LockOutline, + CommentOutline, + UnorderedListOutline, + ArrowRightOutline, + GithubOutline +} from '@ant-design/icons-angular/icons'; +import { NgbDropdownModule, NgbNavModule } from '@ng-bootstrap/ng-bootstrap'; +import { NgScrollbarModule } from 'ngx-scrollbar'; +import {DOCUMENT} from '@angular/common'; + +@Component({ + selector: 'app-nav-right', + imports: [IconDirective, RouterModule, NgScrollbarModule, NgbNavModule, NgbDropdownModule], + templateUrl: './nav-right.component.html', + styleUrls: ['./nav-right.component.scss'] +}) +export class NavRightComponent implements OnInit{ + private iconService = inject(IconService); + private document = inject(DOCUMENT); + //private window = inject(Window); + styleSelectorToggle = input(); + Customize = output(); + windowWidth: number | undefined = 1000; + screenFull: boolean = true; + + constructor() { + + this.iconService.addIcon( + ...[ + CheckCircleOutline, + GiftOutline, + MessageOutline, + SettingOutline, + PhoneOutline, + LogoutOutline, + UserOutline, + EditOutline, + ProfileOutline, + QuestionCircleOutline, + LockOutline, + CommentOutline, + UnorderedListOutline, + ArrowRightOutline, + BellOutline, + GithubOutline, + WalletOutline + ] + ); + } + + ngOnInit(): void { + this.windowWidth = this.document.defaultView?.innerWidth; + } + + profile = [ + { + icon: 'edit', + title: 'Edit Profile' + }, + { + icon: 'user', + title: 'View Profile' + }, + { + icon: 'profile', + title: 'Social Profile' + }, + { + icon: 'wallet', + title: 'Billing' + }, + { + icon: 'logout', + title: 'Logout' + } + ]; + + setting = [ + { + icon: 'question-circle', + title: 'Support' + }, + { + icon: 'user', + title: 'Account Settings' + }, + { + icon: 'lock', + title: 'Privacy Center' + }, + { + icon: 'comment', + title: 'Feedback' + }, + { + icon: 'unordered-list', + title: 'History' + } + ]; +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-collapse/nav-collapse.component.html b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-collapse/nav-collapse.component.html new file mode 100644 index 0000000..cf6308b --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-collapse/nav-collapse.component.html @@ -0,0 +1,21 @@ + diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-collapse/nav-collapse.component.scss b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-collapse/nav-collapse.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-collapse/nav-collapse.component.ts b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-collapse/nav-collapse.component.ts new file mode 100644 index 0000000..5623fc2 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-collapse/nav-collapse.component.ts @@ -0,0 +1,88 @@ +// Angular import +import {Component, inject, Input, OnInit, output} from '@angular/core'; +import { animate, style, transition, trigger } from '@angular/animations'; +import {CommonModule, DOCUMENT} from '@angular/common'; +import { RouterModule } from '@angular/router'; + +// project import +import { NavigationItem } from '../../navigation'; + +import { NavItemComponent } from '../nav-item/nav-item.component'; +import { IconDirective } from '@ant-design/icons-angular'; + +@Component({ + selector: 'app-nav-collapse', + imports: [CommonModule, IconDirective, RouterModule, NavItemComponent], + templateUrl: './nav-collapse.component.html', + styleUrls: ['./nav-collapse.component.scss'], + animations: [ + trigger('slideInOut', [ + transition(':enter', [ + style({ transform: 'translateY(-100%)', display: 'block' }), + animate('250ms ease-in', style({ transform: 'translateY(0%)' })) + ]), + transition(':leave', [animate('250ms ease-in', style({ transform: 'translateY(-100%)' }))]) + ]) + ] +}) +export class NavCollapseComponent implements OnInit{ + + private document = inject(DOCUMENT); + + // public props + + // Compact Menu in use For Sub Child Open in sidebar menu + showCollapseItem = output(); + + // all Version Get Item(Component Name Take) + @Input() item!: NavigationItem; + + windowWidth: number | undefined = 1000; + + // Constructor + constructor() { + //this.windowWidth = window.innerWidth; + } + + ngOnInit(): void { + this.windowWidth = this.document.defaultView?.innerWidth;throw new Error('Method not implemented.'); + } + + // public method + navCollapse(e: MouseEvent) { + let parent = e.target as HTMLElement; + + if (parent?.tagName === 'SPAN') { + parent = parent.parentElement!; + } + + parent = (parent as HTMLElement).parentElement as HTMLElement; + + const sections = document.querySelectorAll('.coded-hasmenu'); + for (let i = 0; i < sections.length; i++) { + if (sections[i] !== parent) { + sections[i].classList.remove('coded-trigger'); + } + } + + let first_parent = parent.parentElement; + let pre_parent = ((parent as HTMLElement).parentElement as HTMLElement).parentElement as HTMLElement; + if (first_parent?.classList.contains('coded-hasmenu')) { + do { + first_parent?.classList.add('coded-trigger'); + first_parent = ((first_parent as HTMLElement).parentElement as HTMLElement).parentElement as HTMLElement; + } while (first_parent.classList.contains('coded-hasmenu')); + } else if (pre_parent.classList.contains('coded-submenu')) { + do { + pre_parent?.parentElement?.classList.add('coded-trigger'); + pre_parent = (((pre_parent as HTMLElement).parentElement as HTMLElement).parentElement as HTMLElement).parentElement as HTMLElement; + } while (pre_parent.classList.contains('coded-submenu')); + } + parent.classList.toggle('coded-trigger'); + } + + // for Compact Menu + subMenuCollapse(item: void) { + this.showCollapseItem.emit(item); + } +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-content.component.html b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-content.component.html new file mode 100644 index 0000000..6bb18f4 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-content.component.html @@ -0,0 +1,34 @@ + + + + diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-content.component.scss b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-content.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-content.component.ts b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-content.component.ts new file mode 100644 index 0000000..38a475e --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-content.component.ts @@ -0,0 +1,106 @@ +// Angular import +import { Component, OnInit, inject, output } from '@angular/core'; +import {CommonModule, DOCUMENT, Location, LocationStrategy} from '@angular/common'; +import { RouterModule } from '@angular/router'; + +// project import +import { NavigationItem, NavigationItems } from '../navigation'; +//import { environment } from 'src/environments/environment'; + +import { NavGroupComponent } from './nav-group/nav-group.component'; + +// icon +import { IconService } from '@ant-design/icons-angular'; +import { + DashboardOutline, + CreditCardOutline, + LoginOutline, + QuestionOutline, + ChromeOutline, + FontSizeOutline, + ProfileOutline, + BgColorsOutline, + AntDesignOutline +} from '@ant-design/icons-angular/icons'; +import { NgScrollbarModule } from 'ngx-scrollbar'; + +@Component({ + selector: 'app-nav-content', + imports: [CommonModule, RouterModule, NavGroupComponent, NgScrollbarModule], + templateUrl: './nav-content.component.html', + styleUrls: ['./nav-content.component.scss'] +}) +export class NavContentComponent implements OnInit { + private location = inject(Location); + private locationStrategy = inject(LocationStrategy); + private iconService = inject(IconService) + private document = inject(DOCUMENT); + + // public props + NavCollapsedMob = output(); + + navigations: NavigationItem[]; + + // version + title = 'Demo application for version numbering'; + //currentApplicationVersion = environment.appVersion; + + navigation = NavigationItems; + windowWidth: number | undefined = 1000; + + // Constructor + constructor() { + this.iconService.addIcon( + ...[ + DashboardOutline, + CreditCardOutline, + FontSizeOutline, + LoginOutline, + ProfileOutline, + BgColorsOutline, + AntDesignOutline, + ChromeOutline, + QuestionOutline + ] + ); + this.navigations = NavigationItems; + } + + // Life cycle events + ngOnInit() { + if (!!this.windowWidth && this.windowWidth < 1025) { + (this.document.querySelector('.coded-navbar') as HTMLDivElement)?.classList.add('menupos-static'); + } + } + + fireOutClick() { + let current_url = this.location.path(); + const baseHref = this.locationStrategy.getBaseHref(); + if (baseHref) { + current_url = baseHref + this.location.path(); + } + const link = "a.nav-link[ href='" + current_url + "' ]"; + const ele = document?.querySelector(link); + if (ele !== null && ele !== undefined) { + const parent = ele.parentElement; + const up_parent = parent?.parentElement?.parentElement; + const last_parent = up_parent?.parentElement; + if (parent?.classList.contains('coded-hasmenu')) { + parent.classList.add('coded-trigger'); + parent.classList.add('active'); + } else if (up_parent?.classList.contains('coded-hasmenu')) { + up_parent.classList.add('coded-trigger'); + up_parent.classList.add('active'); + } else if (last_parent?.classList.contains('coded-hasmenu')) { + last_parent.classList.add('coded-trigger'); + last_parent.classList.add('active'); + } + } + } + + navMob() { + if (!!this.windowWidth && this.windowWidth < 1025 && document.querySelector('app-navigation.coded-navbar')?.classList.contains('mob-open')) { + this.NavCollapsedMob.emit(); + } + } +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-group/nav-group.component.html b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-group/nav-group.component.html new file mode 100644 index 0000000..98289c9 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-group/nav-group.component.html @@ -0,0 +1,10 @@ + +@for (item of item().children; track item) { + @if (item.type === 'collapse') { + + } @else if (item.type === 'item') { + + } +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-group/nav-group.component.scss b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-group/nav-group.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-group/nav-group.component.ts b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-group/nav-group.component.ts new file mode 100644 index 0000000..7a7edcf --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-group/nav-group.component.ts @@ -0,0 +1,67 @@ +// Angular import +import { Component, OnInit, inject, input } from '@angular/core'; +import {CommonModule, DOCUMENT, Location} from '@angular/common'; + +// project import +import { NavigationItem } from '../../navigation'; + +import { NavCollapseComponent } from '../nav-collapse/nav-collapse.component'; +import { NavItemComponent } from '../nav-item/nav-item.component'; + +@Component({ + selector: 'app-nav-group', + imports: [CommonModule, NavCollapseComponent, NavItemComponent], + templateUrl: './nav-group.component.html', + styleUrls: ['./nav-group.component.scss'] +}) +export class NavGroupComponent implements OnInit { + private location = inject(Location); + private document = inject(DOCUMENT); + // public props + + // All Version in Group Name + item = input.required(); + + // Life cycle events + ngOnInit() { + // at reload time active and trigger link + let current_url: string | any = this.location.path(); + // eslint-disable-next-line + // @ts-ignore + if (this.location['_baseHref']) { + // eslint-disable-next-line + + + // @ts-ignore + current_url = this.location['_baseHref'] + this.location.path(); + } + + const link = "a.nav-link[ href='" + current_url + "' ]"; + //if(this.document === undefined) return; + const ele = this.document?.querySelector(link); + if (ele !== null && ele !== undefined) { + const parent = ele.parentElement; + const up_parent = parent?.parentElement?.parentElement; + const pre_parent = up_parent?.parentElement; + const last_parent = up_parent?.parentElement?.parentElement?.parentElement?.parentElement; + if (parent?.classList.contains('coded-hasmenu')) { + parent?.classList.add('coded-trigger'); + parent?.classList.add('active'); + } else if (up_parent?.classList.contains('coded-hasmenu')) { + up_parent?.classList.add('coded-trigger'); + up_parent?.classList.add('active'); + } else if (pre_parent?.classList.contains('coded-hasmenu')) { + pre_parent?.classList.add('coded-trigger'); + pre_parent?.classList.add('active'); + } + + if (last_parent?.classList.contains('coded-hasmenu')) { + last_parent?.classList.add('coded-trigger'); + if (pre_parent?.classList.contains('coded-hasmenu')) { + pre_parent?.classList.add('coded-trigger'); + } + } + last_parent?.classList.add('active'); + } + } +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-item/nav-item.component.html b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-item/nav-item.component.html new file mode 100644 index 0000000..f60f5f7 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-item/nav-item.component.html @@ -0,0 +1,32 @@ +@if (item.url && !item.external) { +
  • + + @if (item.icon) { + + + + } + @if (item.icon) { + {{ item.title }} + } @else { + {{ item.title }} + } + +
  • +} +@if (item.url && item.external) { +
  • + + @if (item.icon) { + + + + } + @if (item.icon) { + {{ item.title }} + } @else { + {{ item.title }} + } + +
  • +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-item/nav-item.component.scss b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-item/nav-item.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-item/nav-item.component.ts b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-item/nav-item.component.ts new file mode 100644 index 0000000..6347047 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/navigation/nav-content/nav-item/nav-item.component.ts @@ -0,0 +1,51 @@ +// Angular import +import {Component, inject, Input} from '@angular/core'; +import {CommonModule, DOCUMENT} from '@angular/common'; +import { RouterModule } from '@angular/router'; + +// Project import +import { NavigationItem } from '../../navigation'; + +import { IconDirective } from '@ant-design/icons-angular'; + +@Component({ + selector: 'app-nav-item', + imports: [CommonModule, IconDirective, RouterModule], + templateUrl: './nav-item.component.html', + styleUrls: ['./nav-item.component.scss'] +}) +export class NavItemComponent { + private document = inject(DOCUMENT); + + // public props + @Input() item!: NavigationItem; + + // public method + closeOtherMenu(event: MouseEvent) { + const ele = event.target as HTMLElement; + if (ele !== null && ele !== undefined) { + const parent = ele.parentElement as HTMLElement; + const up_parent = ((parent.parentElement as HTMLElement).parentElement as HTMLElement).parentElement as HTMLElement; + const last_parent = up_parent.parentElement; + const sections = this.document.querySelectorAll('.coded-hasmenu'); + for (let i = 0; i < sections.length; i++) { + sections[i].classList.remove('active'); + sections[i].classList.remove('coded-trigger'); + } + + if (parent.classList.contains('coded-hasmenu')) { + parent.classList.add('coded-trigger'); + parent.classList.add('active'); + } else if (up_parent.classList.contains('coded-hasmenu')) { + up_parent.classList.add('coded-trigger'); + up_parent.classList.add('active'); + } else if (last_parent?.classList.contains('coded-hasmenu')) { + last_parent.classList.add('coded-trigger'); + last_parent.classList.add('active'); + } + } + if ((document.querySelector('app-navigation.pc-sidebar') as HTMLDivElement).classList.contains('mob-open')) { + (document.querySelector('app-navigation.pc-sidebar') as HTMLDivElement).classList.remove('mob-open'); + } + } +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/navigation.component.html b/jambotron-ui/src/app/layouts/admin-layout/navigation/navigation.component.html new file mode 100644 index 0000000..8d9ddf6 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/navigation/navigation.component.html @@ -0,0 +1,10 @@ + diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/navigation.component.scss b/jambotron-ui/src/app/layouts/admin-layout/navigation/navigation.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/navigation.component.ts b/jambotron-ui/src/app/layouts/admin-layout/navigation/navigation.component.ts new file mode 100644 index 0000000..3821a53 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/navigation/navigation.component.ts @@ -0,0 +1,49 @@ +// Angular import +import {Component, EventEmitter, inject, OnInit, Output, output} from '@angular/core'; +import {CommonModule, DOCUMENT} from '@angular/common'; +import {NavContentComponent} from './nav-content/nav-content.component'; + +// project import + +//import { NavContentComponent } from './nav-content/nav-content.component'; + +@Component({ + selector: 'app-navigation', + // imports: [ CommonModule], + templateUrl: './navigation.component.html', + imports: [ + NavContentComponent + ], + styleUrls: ['./navigation.component.scss'] +}) +export class NavigationComponent implements OnInit{ + + private document = inject(DOCUMENT); + + // media 1025 After Use Menu Open + NavCollapsedMob = output(); + + navCollapsedMob:boolean; + windowWidth: number | undefined = 1000; + + // Constructor + constructor() { + //window. + // this.windowWidth = !document ? 0 : !document.defaultView ? 0 : document.defaultView?.innerWidth; + //this.windowWidth = document.defaultView !== null? document.defaultView.innerWidth : 1000;//window.innerWidth; + this.navCollapsedMob = false; + } + + ngOnInit(): void { + this.windowWidth = this.document.defaultView?.innerWidth; + } + + // public method + // @Output() NavCollapse = new EventEmitter(); + @Output() NavCollapse = new EventEmitter(); + navCollapseMob() { + if (!!this.windowWidth && this.windowWidth < 1025) { + this.NavCollapsedMob.emit(); + } + } +} diff --git a/jambotron-ui/src/app/layouts/admin-layout/navigation/navigation.ts b/jambotron-ui/src/app/layouts/admin-layout/navigation/navigation.ts new file mode 100644 index 0000000..1673226 --- /dev/null +++ b/jambotron-ui/src/app/layouts/admin-layout/navigation/navigation.ts @@ -0,0 +1,140 @@ +export interface NavigationItem { + id: string; + title: string; + type: 'item' | 'collapse' | 'group'; + translate?: string; + icon?: string; + hidden?: boolean; + url?: string; + classes?: string; + groupClasses?: string; + exactMatch?: boolean; + external?: boolean; + target?: boolean; + breadcrumbs?: boolean; + children?: NavigationItem[]; + link?: string; + description?: string; + path?: string; +} + +export const NavigationItems: NavigationItem[] = [ + { + id: 'admin', + title: 'Admin', + type: 'group', + icon: 'icon-navigation', + url: '/main/admin/welcome', + target: true, + children: [ + { + id: 'settings', + title: 'Settings', + type: 'item', + classes: 'nav-item', + url: '/main/admin/settings', + icon: 'dashboard', + // breadcrumbs: false + }, + { + id: 'system', + title: 'System', + type: 'item', + classes: 'nav-item', + url: '/main/admin/system', + icon: 'dashboard', + // breadcrumbs: false + } + ] + }/*, + { + id: 'authentication', + title: 'Authentication', + type: 'group', + icon: 'icon-navigation', + children: [ + { + id: 'login', + title: 'Login', + type: 'item', + classes: 'nav-item', + url: '/login', + icon: 'login', + target: true, + breadcrumbs: false + }, + { + id: 'register', + title: 'Register', + type: 'item', + classes: 'nav-item', + url: '/register', + icon: 'profile', + target: true, + breadcrumbs: false + }*/ + // ] + // } + /*, + { + id: 'utilities', + title: 'UI Components', + type: 'group', + icon: 'icon-navigation', + children: [ + { + id: 'typography', + title: 'Typography', + type: 'item', + classes: 'nav-item', + url: '/typography', + icon: 'font-size' + }, + { + id: 'color', + title: 'Colors', + type: 'item', + classes: 'nav-item', + url: '/color', + icon: 'bg-colors' + }, + { + id: 'ant-icons', + title: 'Ant Icons', + type: 'item', + classes: 'nav-item', + url: 'https://ant.design/components/icon', + icon: 'ant-design', + target: true, + external: true + } + ] + }, + + { + id: 'other', + title: 'Other', + type: 'group', + icon: 'icon-navigation', + children: [ + { + id: 'sample-page', + title: 'Sample Page', + type: 'item', + url: '/sample-page', + classes: 'nav-item', + icon: 'chrome' + }, + { + id: 'document', + title: 'Document', + type: 'item', + classes: 'nav-item', + url: 'https://codedthemes.gitbook.io/mantis-angular/', + icon: 'question', + target: true, + external: true + } + ] + }*/ +]; diff --git a/jambotron-ui/src/app/layouts/guest-layout/guest-layout.component.html b/jambotron-ui/src/app/layouts/guest-layout/guest-layout.component.html new file mode 100644 index 0000000..0680b43 --- /dev/null +++ b/jambotron-ui/src/app/layouts/guest-layout/guest-layout.component.html @@ -0,0 +1 @@ + diff --git a/jambotron-ui/src/app/layouts/guest-layout/guest-layout.component.scss b/jambotron-ui/src/app/layouts/guest-layout/guest-layout.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/jambotron-ui/src/app/layouts/guest-layout/guest-layout.component.ts b/jambotron-ui/src/app/layouts/guest-layout/guest-layout.component.ts new file mode 100644 index 0000000..7582ad4 --- /dev/null +++ b/jambotron-ui/src/app/layouts/guest-layout/guest-layout.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +@Component({ + selector: 'app-guest-layout', + imports: [RouterModule], + templateUrl: './guest-layout.component.html', + styleUrl: './guest-layout.component.scss' +}) +export class GuestLayoutComponent {}