Add new components, styles, and services for user management and navigation

This commit is contained in:
liosha84
2025-06-25 13:50:14 +03:00
parent 13a8ff4494
commit 5dc79438b7
42 changed files with 1439 additions and 0 deletions
@@ -0,0 +1,21 @@
<li data-username="mantis dashboard" class="nav-item coded-hasmenu" [routerLinkActive]="['active']">
<a [routerLinkActive]="['active']" (click)="navCollapse($event)">
@if (item.icon) {
<span class="coded-micon">
<i antIcon type="{{ item.icon }}" theme="outline"></i>
</span>
}
<span class="coded-mtext">
{{ item.title }}
</span>
</a>
<ul class="coded-submenu" [routerLinkActive]="['active']" [ngClass]="item.classes!">
@for (item of item.children; track item) {
@if (item.type === 'item') {
<app-nav-item [item]="item"></app-nav-item>
} @else if (item.type === 'collapse') {
<app-nav-collapse [item]="item"></app-nav-collapse>
}
}
</ul>
</li>
@@ -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);
}
}
@@ -0,0 +1,34 @@
<!-- Vertical layout -->
<ng-scrollbar style="height: calc(100vh - 49px)" visibility="hover" id="nav-ps-mantis">
<div class="navbar-content">
<ul class="nav coded-inner-navbar" (clickOutside)="fireOutClick()" (mouseleave)="navMob()">
@for (item of navigations; track item) {
@if (item.type === 'group') {
<app-nav-group [item]="item"></app-nav-group>
}
}
</ul>
<div class="m-4 mb-0">
<div class="card nav-card">
<div class="card-body">
<div class="d-flex flex-column align-items-center">
<img src="assets/images/avatar-group.png" alt="user" class="img-fluid" />
<div class="m-t-20 text-center">
<h5 class="mb-0">Mantis Pro</h5>
<span class="text-muted">Checkout pro features</span>
</div>
<div class="m-t-20 text-center">
<a
href="https://codedthemes.com/item/mantis-angular-admin-template/?utm_source=free_demo&utm_medium=codedthemes&utm_campaign=button_download_premium"
target="_blank"
class="btn btn-primary text-white"
>
Pro
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-scrollbar>
@@ -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();
}
}
}
@@ -0,0 +1,10 @@
<li class="nav-item coded-menu-caption">
<label>{{ item().title }}</label>
</li>
@for (item of item().children; track item) {
@if (item.type === 'collapse') {
<app-nav-collapse [item]="item"></app-nav-collapse>
} @else if (item.type === 'item') {
<app-nav-item [item]="item"></app-nav-item>
}
}
@@ -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<NavigationItem>();
// 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');
}
}
}
@@ -0,0 +1,32 @@
@if (item.url && !item.external) {
<li [ngClass]="item.classes!" [routerLinkActive]="['active']">
<a [target]="item.target ? '_blank' : '_self'" [routerLink]="[item.url]" (click)="closeOtherMenu($event)">
@if (item.icon) {
<span class="coded-micon">
<i antIcon type="{{ item.icon }}" theme="outline"></i>
</span>
}
@if (item.icon) {
<span class="coded-mtext">{{ item.title }}</span>
} @else {
{{ item.title }}
}
</a>
</li>
}
@if (item.url && item.external) {
<li [ngClass]="item.classes!">
<a [target]="item.target ? '_blank' : '_self'" [href]="item.url">
@if (item.icon) {
<span class="coded-micon">
<i antIcon type="{{ item.icon }}" theme="outline"></i>
</span>
}
@if (item.icon) {
<span class="coded-mtext">{{ item.title }}</span>
} @else {
{{ item.title }}
}
</a>
</li>
}
@@ -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');
}
}
}