chore: update to nextgen
This commit is contained in:
@@ -8,7 +8,7 @@ import Lara from '@primeuix/themes/lara';
|
||||
import Nora from '@primeuix/themes/nora';
|
||||
import { PrimeNG } from 'primeng/config';
|
||||
import { SelectButtonModule } from 'primeng/selectbutton';
|
||||
import { LayoutService } from '../service/layout.service';
|
||||
import { LayoutService } from '@/app/layout/service/layout.service';
|
||||
|
||||
const presets = {
|
||||
Aura,
|
||||
|
||||
@@ -2,7 +2,7 @@ import {Component, computed, inject, input} from '@angular/core';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { StyleClassModule } from 'primeng/styleclass';
|
||||
import { AppConfigurator } from './app.configurator';
|
||||
import { LayoutService } from '../service/layout.service';
|
||||
import { LayoutService } from '@/app/layout/service/layout.service';
|
||||
import {CommonModule} from "@angular/common";
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { Component, Renderer2, ViewChild } from '@angular/core';
|
||||
import { Component, computed, effect, inject } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NavigationEnd, Router, RouterModule } from '@angular/router';
|
||||
import { filter, Subscription } from 'rxjs';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AppTopbar } from './app.topbar';
|
||||
import { AppSidebar } from './app.sidebar';
|
||||
import { AppFooter } from './app.footer';
|
||||
import { LayoutService } from '../service/layout.service';
|
||||
import { LayoutService } from '@/app/layout/service/layout.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-layout',
|
||||
standalone: true,
|
||||
imports: [CommonModule, AppTopbar, AppSidebar, RouterModule, AppFooter],
|
||||
template: `<div class="layout-wrapper" [ngClass]="containerClass">
|
||||
template: `<div class="layout-wrapper" [ngClass]="containerClass()">
|
||||
<app-topbar></app-topbar>
|
||||
<app-sidebar></app-sidebar>
|
||||
<div class="layout-main-container">
|
||||
@@ -20,92 +19,32 @@ import { LayoutService } from '../service/layout.service';
|
||||
</div>
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
<div class="layout-mask animate-fadein"></div>
|
||||
<div class="layout-mask"></div>
|
||||
</div> `
|
||||
})
|
||||
export class AppLayout {
|
||||
overlayMenuOpenSubscription: Subscription;
|
||||
layoutService = inject(LayoutService);
|
||||
|
||||
menuOutsideClickListener: any;
|
||||
|
||||
@ViewChild(AppSidebar) appSidebar!: AppSidebar;
|
||||
|
||||
@ViewChild(AppTopbar) appTopBar!: AppTopbar;
|
||||
|
||||
constructor(
|
||||
public layoutService: LayoutService,
|
||||
public renderer: Renderer2,
|
||||
public router: Router
|
||||
) {
|
||||
this.overlayMenuOpenSubscription = this.layoutService.overlayOpen$.subscribe(() => {
|
||||
if (!this.menuOutsideClickListener) {
|
||||
this.menuOutsideClickListener = this.renderer.listen('document', 'click', (event) => {
|
||||
if (this.isOutsideClicked(event)) {
|
||||
this.hideMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (this.layoutService.layoutState().staticMenuMobileActive) {
|
||||
this.blockBodyScroll();
|
||||
constructor() {
|
||||
effect(() => {
|
||||
const state = this.layoutService.layoutState();
|
||||
if (state.mobileMenuActive) {
|
||||
document.body.classList.add('blocked-scroll');
|
||||
} else {
|
||||
document.body.classList.remove('blocked-scroll');
|
||||
}
|
||||
});
|
||||
|
||||
this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe(() => {
|
||||
this.hideMenu();
|
||||
});
|
||||
}
|
||||
|
||||
isOutsideClicked(event: MouseEvent) {
|
||||
const sidebarEl = document.querySelector('.layout-sidebar');
|
||||
const topbarEl = document.querySelector('.layout-menu-button');
|
||||
const eventTarget = event.target as Node;
|
||||
|
||||
return !(sidebarEl?.isSameNode(eventTarget) || sidebarEl?.contains(eventTarget) || topbarEl?.isSameNode(eventTarget) || topbarEl?.contains(eventTarget));
|
||||
}
|
||||
|
||||
hideMenu() {
|
||||
this.layoutService.layoutState.update((prev) => ({ ...prev, overlayMenuActive: false, staticMenuMobileActive: false, menuHoverActive: false }));
|
||||
if (this.menuOutsideClickListener) {
|
||||
this.menuOutsideClickListener();
|
||||
this.menuOutsideClickListener = null;
|
||||
}
|
||||
this.unblockBodyScroll();
|
||||
}
|
||||
|
||||
blockBodyScroll(): void {
|
||||
if (document.body.classList) {
|
||||
document.body.classList.add('blocked-scroll');
|
||||
} else {
|
||||
document.body.className += ' blocked-scroll';
|
||||
}
|
||||
}
|
||||
|
||||
unblockBodyScroll(): void {
|
||||
if (document.body.classList) {
|
||||
document.body.classList.remove('blocked-scroll');
|
||||
} else {
|
||||
document.body.className = document.body.className.replace(new RegExp('(^|\\b)' + 'blocked-scroll'.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
|
||||
}
|
||||
}
|
||||
|
||||
get containerClass() {
|
||||
containerClass = computed(() => {
|
||||
const config = this.layoutService.layoutConfig();
|
||||
const state = this.layoutService.layoutState();
|
||||
return {
|
||||
'layout-overlay': this.layoutService.layoutConfig().menuMode === 'overlay',
|
||||
'layout-static': this.layoutService.layoutConfig().menuMode === 'static',
|
||||
'layout-static-inactive': this.layoutService.layoutState().staticMenuDesktopInactive && this.layoutService.layoutConfig().menuMode === 'static',
|
||||
'layout-overlay-active': this.layoutService.layoutState().overlayMenuActive,
|
||||
'layout-mobile-active': this.layoutService.layoutState().staticMenuMobileActive
|
||||
'layout-overlay': config.menuMode === 'overlay',
|
||||
'layout-static': config.menuMode === 'static',
|
||||
'layout-static-inactive': state.staticMenuDesktopInactive && config.menuMode === 'static',
|
||||
'layout-overlay-active': state.overlayMenuActive,
|
||||
'layout-mobile-active': state.mobileMenuActive
|
||||
};
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.overlayMenuOpenSubscription) {
|
||||
this.overlayMenuOpenSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
if (this.menuOutsideClickListener) {
|
||||
this.menuOutsideClickListener();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,11 +9,14 @@ import { AppMenuitem } from './app.menuitem';
|
||||
standalone: true,
|
||||
imports: [CommonModule, AppMenuitem, RouterModule],
|
||||
template: `<ul class="layout-menu">
|
||||
<ng-container *ngFor="let item of model; let i = index">
|
||||
<li app-menuitem *ngIf="!item.separator" [item]="item" [index]="i" [root]="true"></li>
|
||||
<li *ngIf="item.separator" class="menu-separator"></li>
|
||||
</ng-container>
|
||||
</ul> `
|
||||
@for (item of model; track item.label) {
|
||||
@if (!item.separator) {
|
||||
<li app-menuitem [item]="item" [root]="true"></li>
|
||||
} @else {
|
||||
<li class="menu-separator"></li>
|
||||
}
|
||||
}
|
||||
</ul> `,
|
||||
})
|
||||
export class AppMenu {
|
||||
model: MenuItem[] = [];
|
||||
@@ -47,7 +50,7 @@ export class AppMenu {
|
||||
{
|
||||
label: 'Pages',
|
||||
icon: 'pi pi-fw pi-briefcase',
|
||||
routerLink: ['/pages'],
|
||||
path: '/pages',
|
||||
items: [
|
||||
{
|
||||
label: 'Landing',
|
||||
@@ -57,6 +60,7 @@ export class AppMenu {
|
||||
{
|
||||
label: 'Auth',
|
||||
icon: 'pi pi-fw pi-user',
|
||||
path: '/auth',
|
||||
items: [
|
||||
{
|
||||
label: 'Login',
|
||||
@@ -94,14 +98,17 @@ export class AppMenu {
|
||||
},
|
||||
{
|
||||
label: 'Hierarchy',
|
||||
path: '/hierarchy',
|
||||
items: [
|
||||
{
|
||||
label: 'Submenu 1',
|
||||
icon: 'pi pi-fw pi-bookmark',
|
||||
path: '/hierarchy/submenu_1',
|
||||
items: [
|
||||
{
|
||||
label: 'Submenu 1.1',
|
||||
icon: 'pi pi-fw pi-bookmark',
|
||||
path: '/hierarchy/submenu_1/submenu_1_1',
|
||||
items: [
|
||||
{ label: 'Submenu 1.1.1', icon: 'pi pi-fw pi-bookmark' },
|
||||
{ label: 'Submenu 1.1.2', icon: 'pi pi-fw pi-bookmark' },
|
||||
@@ -111,6 +118,7 @@ export class AppMenu {
|
||||
{
|
||||
label: 'Submenu 1.2',
|
||||
icon: 'pi pi-fw pi-bookmark',
|
||||
path: '/hierarchy/submenu_1/submenu_1_2',
|
||||
items: [{ label: 'Submenu 1.2.1', icon: 'pi pi-fw pi-bookmark' }]
|
||||
}
|
||||
]
|
||||
@@ -118,10 +126,12 @@ export class AppMenu {
|
||||
{
|
||||
label: 'Submenu 2',
|
||||
icon: 'pi pi-fw pi-bookmark',
|
||||
path: '/hierarchy/submenu_2',
|
||||
items: [
|
||||
{
|
||||
label: 'Submenu 2.1',
|
||||
icon: 'pi pi-fw pi-bookmark',
|
||||
path: '/hierarchy/submenu_2/submenu_2_1',
|
||||
items: [
|
||||
{ label: 'Submenu 2.1.1', icon: 'pi pi-fw pi-bookmark' },
|
||||
{ label: 'Submenu 2.1.2', icon: 'pi pi-fw pi-bookmark' }
|
||||
@@ -130,6 +140,7 @@ export class AppMenu {
|
||||
{
|
||||
label: 'Submenu 2.2',
|
||||
icon: 'pi pi-fw pi-bookmark',
|
||||
path: '/hierarchy/submenu_2/submenu_2_2',
|
||||
items: [{ label: 'Submenu 2.2.1', icon: 'pi pi-fw pi-bookmark' }]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,170 +1,209 @@
|
||||
import { Component, HostBinding, Input } from '@angular/core';
|
||||
import { Component, computed, inject, input, signal } from '@angular/core';
|
||||
import { NavigationEnd, Router, RouterModule } from '@angular/router';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RippleModule } from 'primeng/ripple';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { LayoutService } from '../service/layout.service';
|
||||
import { LayoutService } from '@/app/layout/service/layout.service';
|
||||
import { filter } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
// eslint-disable-next-line @angular-eslint/component-selector
|
||||
selector: '[app-menuitem]',
|
||||
imports: [CommonModule, RouterModule, RippleModule],
|
||||
template: `
|
||||
<ng-container>
|
||||
<div *ngIf="root && item.visible !== false" class="layout-menuitem-root-text">{{ item.label }}</div>
|
||||
<a *ngIf="(!item.routerLink || item.items) && item.visible !== false" [attr.href]="item.url" (click)="itemClick($event)" [ngClass]="item.styleClass" [attr.target]="item.target" tabindex="0" pRipple>
|
||||
<i [ngClass]="item.icon" class="layout-menuitem-icon"></i>
|
||||
<span class="layout-menuitem-text">{{ item.label }}</span>
|
||||
<i class="pi pi-fw pi-angle-down layout-submenu-toggler" *ngIf="item.items"></i>
|
||||
@if (root() && isVisible()) {
|
||||
<div class="layout-menuitem-root-text">{{ item().label }}</div>
|
||||
}
|
||||
@if ((!hasRouterLink() || hasChildren()) && isVisible()) {
|
||||
<a [attr.href]="item().url" (click)="itemClick($event)" [ngClass]="item().class" [attr.target]="item().target" tabindex="0" pRipple>
|
||||
<i [ngClass]="item().icon" class="layout-menuitem-icon"></i>
|
||||
<span class="layout-menuitem-text">{{ item().label }}</span>
|
||||
@if (hasChildren()) {
|
||||
<i class="pi pi-fw pi-angle-down layout-submenu-toggler"></i>
|
||||
}
|
||||
</a>
|
||||
}
|
||||
@if (hasRouterLink() && !hasChildren() && isVisible()) {
|
||||
<a
|
||||
*ngIf="item.routerLink && !item.items && item.visible !== false"
|
||||
(click)="itemClick($event)"
|
||||
[ngClass]="item.styleClass"
|
||||
[routerLink]="item.routerLink"
|
||||
[ngClass]="item().class"
|
||||
[routerLink]="item().routerLink"
|
||||
routerLinkActive="active-route"
|
||||
[routerLinkActiveOptions]="item.routerLinkActiveOptions || { paths: 'exact', queryParams: 'ignored', matrixParams: 'ignored', fragment: 'ignored' }"
|
||||
[fragment]="item.fragment"
|
||||
[queryParamsHandling]="item.queryParamsHandling"
|
||||
[preserveFragment]="item.preserveFragment"
|
||||
[skipLocationChange]="item.skipLocationChange"
|
||||
[replaceUrl]="item.replaceUrl"
|
||||
[state]="item.state"
|
||||
[queryParams]="item.queryParams"
|
||||
[attr.target]="item.target"
|
||||
[routerLinkActiveOptions]="item().routerLinkActiveOptions || { paths: 'exact', queryParams: 'ignored', matrixParams: 'ignored', fragment: 'ignored' }"
|
||||
[fragment]="item().fragment"
|
||||
[queryParamsHandling]="item().queryParamsHandling"
|
||||
[preserveFragment]="item().preserveFragment"
|
||||
[skipLocationChange]="item().skipLocationChange"
|
||||
[replaceUrl]="item().replaceUrl"
|
||||
[state]="item().state"
|
||||
[queryParams]="item().queryParams"
|
||||
[attr.target]="item().target"
|
||||
tabindex="0"
|
||||
pRipple
|
||||
>
|
||||
<i [ngClass]="item.icon" class="layout-menuitem-icon"></i>
|
||||
<span class="layout-menuitem-text">{{ item.label }}</span>
|
||||
<i class="pi pi-fw pi-angle-down layout-submenu-toggler" *ngIf="item.items"></i>
|
||||
<i [ngClass]="item().icon" class="layout-menuitem-icon"></i>
|
||||
<span class="layout-menuitem-text">{{ item().label }}</span>
|
||||
@if (hasChildren()) {
|
||||
<i class="pi pi-fw pi-angle-down layout-submenu-toggler"></i>
|
||||
}
|
||||
</a>
|
||||
|
||||
<ul *ngIf="item.items && item.visible !== false" [@children]="submenuAnimation">
|
||||
<ng-template ngFor let-child let-i="index" [ngForOf]="item.items">
|
||||
<li app-menuitem [item]="child" [index]="i" [parentKey]="key" [class]="child['badgeClass']"></li>
|
||||
</ng-template>
|
||||
}
|
||||
@if (hasChildren() && isVisible() && (root() || isActive())) {
|
||||
<ul [animate.enter]="initialized() ? 'p-submenu-enter' : null" [animate.leave]="'p-submenu-leave'" [class.layout-root-submenulist]="root()">
|
||||
@for (child of item().items; track child?.label) {
|
||||
<li app-menuitem [item]="child" [parentPath]="fullPath()" [root]="false" [class]="child['badgeClass']"></li>
|
||||
}
|
||||
</ul>
|
||||
</ng-container>
|
||||
}
|
||||
`,
|
||||
animations: [
|
||||
trigger('children', [
|
||||
state(
|
||||
'collapsed',
|
||||
style({
|
||||
height: '0'
|
||||
})
|
||||
),
|
||||
state(
|
||||
'expanded',
|
||||
style({
|
||||
height: '*'
|
||||
})
|
||||
),
|
||||
transition('collapsed <=> expanded', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
|
||||
])
|
||||
],
|
||||
providers: [LayoutService]
|
||||
host: {
|
||||
'[class.active-menuitem]': 'isActive()',
|
||||
'[class.layout-root-menuitem]': 'root()'
|
||||
},
|
||||
styles: [
|
||||
`
|
||||
.p-submenu-enter {
|
||||
animation: p-animate-submenu-expand 450ms cubic-bezier(0.86, 0, 0.07, 1) forwards;
|
||||
}
|
||||
|
||||
.p-submenu-leave {
|
||||
animation: p-animate-submenu-collapse 450ms cubic-bezier(0.86, 0, 0.07, 1) forwards;
|
||||
}
|
||||
|
||||
@keyframes p-animate-submenu-expand {
|
||||
from {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
to {
|
||||
max-height: 1000px;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes p-animate-submenu-collapse {
|
||||
from {
|
||||
max-height: 1000px;
|
||||
overflow: hidden;
|
||||
}
|
||||
to {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
`
|
||||
]
|
||||
})
|
||||
export class AppMenuitem {
|
||||
@Input() item!: MenuItem;
|
||||
layoutService = inject(LayoutService);
|
||||
|
||||
@Input() index!: number;
|
||||
router = inject(Router);
|
||||
|
||||
@Input() @HostBinding('class.layout-root-menuitem') root!: boolean;
|
||||
item = input<any>(null);
|
||||
|
||||
@Input() parentKey!: string;
|
||||
root = input<boolean>(false);
|
||||
|
||||
active = false;
|
||||
parentPath = input<string | null>(null);
|
||||
|
||||
menuSourceSubscription: Subscription;
|
||||
isVisible = computed(() => this.item()?.visible !== false);
|
||||
|
||||
menuResetSubscription: Subscription;
|
||||
hasChildren = computed(() => this.item()?.items && this.item()?.items.length > 0);
|
||||
|
||||
key: string = '';
|
||||
hasRouterLink = computed(() => !!this.item()?.routerLink);
|
||||
|
||||
constructor(
|
||||
public router: Router,
|
||||
private layoutService: LayoutService
|
||||
) {
|
||||
this.menuSourceSubscription = this.layoutService.menuSource$.subscribe((value) => {
|
||||
Promise.resolve(null).then(() => {
|
||||
if (value.routeEvent) {
|
||||
this.active = value.key === this.key || value.key.startsWith(this.key + '-') ? true : false;
|
||||
} else {
|
||||
if (value.key !== this.key && !value.key.startsWith(this.key + '-')) {
|
||||
this.active = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
fullPath = computed(() => {
|
||||
const itemPath = this.item()?.path;
|
||||
if (!itemPath) return this.parentPath();
|
||||
const parent = this.parentPath();
|
||||
if (parent && !itemPath.startsWith(parent)) {
|
||||
return parent + itemPath;
|
||||
}
|
||||
return itemPath;
|
||||
});
|
||||
|
||||
this.menuResetSubscription = this.layoutService.resetSource$.subscribe(() => {
|
||||
this.active = false;
|
||||
});
|
||||
isActive = computed(() => {
|
||||
const activePath = this.layoutService.layoutState().activePath;
|
||||
if (this.item()?.path) {
|
||||
return activePath?.startsWith(this.fullPath() ?? '') ?? false;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe((params) => {
|
||||
if (this.item.routerLink) {
|
||||
initialized = signal<boolean>(false);
|
||||
|
||||
constructor() {
|
||||
this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe(() => {
|
||||
if (this.item()?.routerLink) {
|
||||
this.updateActiveStateFromRoute();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.key = this.parentKey ? this.parentKey + '-' + this.index : String(this.index);
|
||||
|
||||
if (this.item.routerLink) {
|
||||
if (this.item()?.routerLink) {
|
||||
this.updateActiveStateFromRoute();
|
||||
}
|
||||
}
|
||||
|
||||
updateActiveStateFromRoute() {
|
||||
let activeRoute = this.router.isActive(this.item.routerLink[0], { paths: 'exact', queryParams: 'ignored', matrixParams: 'ignored', fragment: 'ignored' });
|
||||
ngAfterViewInit() {
|
||||
setTimeout(() => {
|
||||
this.initialized.set(true);
|
||||
});
|
||||
}
|
||||
|
||||
if (activeRoute) {
|
||||
this.layoutService.onMenuStateChange({ key: this.key, routeEvent: true });
|
||||
updateActiveStateFromRoute() {
|
||||
const item = this.item();
|
||||
if (!item?.routerLink) return;
|
||||
|
||||
const isRouteActive = this.router.isActive(item.routerLink[0], {
|
||||
paths: 'exact',
|
||||
queryParams: 'ignored',
|
||||
matrixParams: 'ignored',
|
||||
fragment: 'ignored'
|
||||
});
|
||||
|
||||
if (isRouteActive) {
|
||||
const parentPath = this.parentPath();
|
||||
if (parentPath) {
|
||||
this.layoutService.layoutState.update((val) => ({
|
||||
...val,
|
||||
activePath: parentPath
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemClick(event: Event) {
|
||||
// avoid processing disabled items
|
||||
if (this.item.disabled) {
|
||||
const item = this.item();
|
||||
|
||||
if (item?.disabled) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// execute command
|
||||
if (this.item.command) {
|
||||
this.item.command({ originalEvent: event, item: this.item });
|
||||
if (item?.command) {
|
||||
item.command({ originalEvent: event, item: item });
|
||||
}
|
||||
|
||||
// toggle active state
|
||||
if (this.item.items) {
|
||||
this.active = !this.active;
|
||||
}
|
||||
|
||||
this.layoutService.onMenuStateChange({ key: this.key });
|
||||
}
|
||||
|
||||
get submenuAnimation() {
|
||||
return this.root ? 'expanded' : this.active ? 'expanded' : 'collapsed';
|
||||
}
|
||||
|
||||
@HostBinding('class.active-menuitem')
|
||||
get activeClass() {
|
||||
return this.active && !this.root;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.menuSourceSubscription) {
|
||||
this.menuSourceSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
if (this.menuResetSubscription) {
|
||||
this.menuResetSubscription.unsubscribe();
|
||||
if (this.hasChildren()) {
|
||||
if (this.isActive()) {
|
||||
this.layoutService.layoutState.update((val) => ({
|
||||
...val,
|
||||
activePath: this.parentPath()
|
||||
}));
|
||||
} else {
|
||||
this.layoutService.layoutState.update((val) => ({
|
||||
...val,
|
||||
activePath: this.fullPath(),
|
||||
menuHoverActive: true
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
this.layoutService.layoutState.update((val) => ({
|
||||
...val,
|
||||
overlayMenuActive: false,
|
||||
staticMenuMobileActive: false,
|
||||
mobileMenuActive: false,
|
||||
menuHoverActive: false
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,115 @@
|
||||
import { Component, ElementRef } from '@angular/core';
|
||||
import { Component, computed, effect, ElementRef, inject, OnDestroy, OnInit } from '@angular/core';
|
||||
import { NavigationEnd, Router, RouterModule } from '@angular/router';
|
||||
import { filter, Subject, takeUntil } from 'rxjs';
|
||||
import { AppMenu } from './app.menu';
|
||||
import { LayoutService } from '@/app/layout/service/layout.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-sidebar',
|
||||
standalone: true,
|
||||
imports: [AppMenu],
|
||||
template: ` <div class="layout-sidebar">
|
||||
<app-menu></app-menu>
|
||||
</div>`
|
||||
imports: [AppMenu, RouterModule],
|
||||
template: `
|
||||
<div class="layout-sidebar">
|
||||
<app-menu></app-menu>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class AppSidebar {
|
||||
constructor(public el: ElementRef) {}
|
||||
export class AppSidebar implements OnInit, OnDestroy {
|
||||
layoutService = inject(LayoutService);
|
||||
|
||||
router = inject(Router);
|
||||
|
||||
el = inject(ElementRef);
|
||||
|
||||
private outsideClickListener: ((event: MouseEvent) => void) | null = null;
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
const state = this.layoutService.layoutState();
|
||||
|
||||
if (this.layoutService.isDesktop()) {
|
||||
if (state.overlayMenuActive) {
|
||||
this.bindOutsideClickListener();
|
||||
} else {
|
||||
this.unbindOutsideClickListener();
|
||||
}
|
||||
} else {
|
||||
if (state.mobileMenuActive) {
|
||||
this.bindOutsideClickListener();
|
||||
} else {
|
||||
this.unbindOutsideClickListener();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.router.events
|
||||
.pipe(
|
||||
filter((event) => event instanceof NavigationEnd),
|
||||
takeUntil(this.destroy$)
|
||||
)
|
||||
.subscribe((event) => {
|
||||
const navEvent = event as NavigationEnd;
|
||||
this.onRouteChange(navEvent.urlAfterRedirects);
|
||||
});
|
||||
|
||||
this.onRouteChange(this.router.url);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
this.unbindOutsideClickListener();
|
||||
}
|
||||
|
||||
private onRouteChange(path: string) {
|
||||
this.layoutService.layoutState.update((val) => ({
|
||||
...val,
|
||||
activePath: path,
|
||||
overlayMenuActive: false,
|
||||
staticMenuMobileActive: false,
|
||||
mobileMenuActive: false,
|
||||
menuHoverActive: false
|
||||
}));
|
||||
}
|
||||
|
||||
private bindOutsideClickListener() {
|
||||
if (!this.outsideClickListener) {
|
||||
this.outsideClickListener = (event: MouseEvent) => {
|
||||
if (this.isOutsideClicked(event)) {
|
||||
this.layoutService.layoutState.update((val) => ({
|
||||
...val,
|
||||
overlayMenuActive: false,
|
||||
staticMenuMobileActive: false,
|
||||
mobileMenuActive: false,
|
||||
menuHoverActive: false
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', this.outsideClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
private unbindOutsideClickListener() {
|
||||
if (this.outsideClickListener) {
|
||||
document.removeEventListener('click', this.outsideClickListener);
|
||||
this.outsideClickListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
private isOutsideClicked(event: MouseEvent): boolean {
|
||||
const topbarButtonEl = document.querySelector('.topbar-start > button');
|
||||
const sidebarEl = this.el.nativeElement;
|
||||
|
||||
return !(
|
||||
sidebarEl?.isSameNode(event.target as Node) ||
|
||||
sidebarEl?.contains(event.target as Node) ||
|
||||
topbarButtonEl?.isSameNode(event.target as Node) ||
|
||||
topbarButtonEl?.contains(event.target as Node)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { StyleClassModule } from 'primeng/styleclass';
|
||||
import { AppConfigurator } from './app.configurator';
|
||||
import { LayoutService } from '../service/layout.service';
|
||||
import { LayoutService } from '@/app/layout/service/layout.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-topbar',
|
||||
@@ -84,9 +84,12 @@ import { LayoutService } from '../service/layout.service';
|
||||
export class AppTopbar {
|
||||
items!: MenuItem[];
|
||||
|
||||
constructor(public layoutService: LayoutService) {}
|
||||
layoutService = inject(LayoutService);
|
||||
|
||||
toggleDarkMode() {
|
||||
this.layoutService.layoutConfig.update((state) => ({ ...state, darkTheme: !state.darkTheme }));
|
||||
this.layoutService.layoutConfig.update((state) => ({
|
||||
...state,
|
||||
darkTheme: !state.darkTheme
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +1,46 @@
|
||||
import { Injectable, effect, signal, computed } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
export interface layoutConfig {
|
||||
preset?: string;
|
||||
primary?: string;
|
||||
surface?: string | undefined | null;
|
||||
darkTheme?: boolean;
|
||||
menuMode?: string;
|
||||
export interface LayoutConfig {
|
||||
preset: string;
|
||||
primary: string;
|
||||
surface: string | undefined | null;
|
||||
darkTheme: boolean;
|
||||
menuMode: string;
|
||||
}
|
||||
|
||||
interface LayoutState {
|
||||
staticMenuDesktopInactive?: boolean;
|
||||
overlayMenuActive?: boolean;
|
||||
configSidebarVisible?: boolean;
|
||||
staticMenuMobileActive?: boolean;
|
||||
menuHoverActive?: boolean;
|
||||
}
|
||||
|
||||
interface MenuChangeEvent {
|
||||
key: string;
|
||||
routeEvent?: boolean;
|
||||
staticMenuDesktopInactive: boolean;
|
||||
overlayMenuActive: boolean;
|
||||
configSidebarVisible: boolean;
|
||||
mobileMenuActive: boolean;
|
||||
menuHoverActive: boolean;
|
||||
activePath: string | null;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class LayoutService {
|
||||
_config: layoutConfig = {
|
||||
layoutConfig = signal<LayoutConfig>({
|
||||
preset: 'Aura',
|
||||
primary: 'emerald',
|
||||
surface: null,
|
||||
darkTheme: false,
|
||||
menuMode: 'static'
|
||||
};
|
||||
});
|
||||
|
||||
_state: LayoutState = {
|
||||
layoutState = signal<LayoutState>({
|
||||
staticMenuDesktopInactive: false,
|
||||
overlayMenuActive: false,
|
||||
configSidebarVisible: false,
|
||||
staticMenuMobileActive: false,
|
||||
menuHoverActive: false
|
||||
};
|
||||
mobileMenuActive: false,
|
||||
menuHoverActive: false,
|
||||
activePath: null
|
||||
});
|
||||
|
||||
layoutConfig = signal<layoutConfig>(this._config);
|
||||
theme = computed(() => (this.layoutConfig().darkTheme ? 'light' : 'dark'));
|
||||
|
||||
layoutState = signal<LayoutState>(this._state);
|
||||
|
||||
private configUpdate = new Subject<layoutConfig>();
|
||||
|
||||
private overlayOpen = new Subject<any>();
|
||||
|
||||
private menuSource = new Subject<MenuChangeEvent>();
|
||||
|
||||
private resetSource = new Subject();
|
||||
|
||||
menuSource$ = this.menuSource.asObservable();
|
||||
|
||||
resetSource$ = this.resetSource.asObservable();
|
||||
|
||||
configUpdate$ = this.configUpdate.asObservable();
|
||||
|
||||
overlayOpen$ = this.overlayOpen.asObservable();
|
||||
|
||||
theme = computed(() => (this.layoutConfig()?.darkTheme ? 'light' : 'dark'));
|
||||
|
||||
isSidebarActive = computed(() => this.layoutState().overlayMenuActive || this.layoutState().staticMenuMobileActive);
|
||||
isSidebarActive = computed(() => this.layoutState().overlayMenuActive || this.layoutState().mobileMenuActive);
|
||||
|
||||
isDarkTheme = computed(() => this.layoutConfig().darkTheme);
|
||||
|
||||
@@ -79,13 +55,6 @@ export class LayoutService {
|
||||
private initialized = false;
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
const config = this.layoutConfig();
|
||||
if (config) {
|
||||
this.onConfigUpdate();
|
||||
}
|
||||
});
|
||||
|
||||
effect(() => {
|
||||
const config = this.layoutConfig();
|
||||
|
||||
@@ -98,28 +67,23 @@ export class LayoutService {
|
||||
});
|
||||
}
|
||||
|
||||
private handleDarkModeTransition(config: layoutConfig): void {
|
||||
if ((document as any).startViewTransition) {
|
||||
private handleDarkModeTransition(config: LayoutConfig): void {
|
||||
const supportsViewTransition = 'startViewTransition' in document;
|
||||
|
||||
if (supportsViewTransition) {
|
||||
this.startViewTransition(config);
|
||||
} else {
|
||||
this.toggleDarkMode(config);
|
||||
this.onTransitionEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private startViewTransition(config: layoutConfig): void {
|
||||
const transition = (document as any).startViewTransition(() => {
|
||||
private startViewTransition(config: LayoutConfig): void {
|
||||
document.startViewTransition(() => {
|
||||
this.toggleDarkMode(config);
|
||||
});
|
||||
|
||||
transition.ready
|
||||
.then(() => {
|
||||
this.onTransitionEnd();
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
toggleDarkMode(config?: layoutConfig): void {
|
||||
toggleDarkMode(config?: LayoutConfig): void {
|
||||
const _config = config || this.layoutConfig();
|
||||
if (_config.darkTheme) {
|
||||
document.documentElement.classList.add('app-dark');
|
||||
@@ -128,33 +92,26 @@ export class LayoutService {
|
||||
}
|
||||
}
|
||||
|
||||
private onTransitionEnd() {
|
||||
this.transitionComplete.set(true);
|
||||
setTimeout(() => {
|
||||
this.transitionComplete.set(false);
|
||||
});
|
||||
}
|
||||
|
||||
onMenuToggle() {
|
||||
if (this.isOverlay()) {
|
||||
this.layoutState.update((prev) => ({ ...prev, overlayMenuActive: !this.layoutState().overlayMenuActive }));
|
||||
|
||||
if (this.layoutState().overlayMenuActive) {
|
||||
this.overlayOpen.next(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isDesktop()) {
|
||||
this.layoutState.update((prev) => ({ ...prev, staticMenuDesktopInactive: !this.layoutState().staticMenuDesktopInactive }));
|
||||
} else {
|
||||
this.layoutState.update((prev) => ({ ...prev, staticMenuMobileActive: !this.layoutState().staticMenuMobileActive }));
|
||||
|
||||
if (this.layoutState().staticMenuMobileActive) {
|
||||
this.overlayOpen.next(null);
|
||||
}
|
||||
this.layoutState.update((prev) => ({ ...prev, mobileMenuActive: !this.layoutState().mobileMenuActive }));
|
||||
}
|
||||
}
|
||||
|
||||
showConfigSidebar() {
|
||||
this.layoutState.update((prev) => ({ ...prev, configSidebarVisible: true }));
|
||||
}
|
||||
|
||||
hideConfigSidebar() {
|
||||
this.layoutState.update((prev) => ({ ...prev, configSidebarVisible: false }));
|
||||
}
|
||||
|
||||
isDesktop() {
|
||||
return window.innerWidth > 991;
|
||||
}
|
||||
@@ -162,17 +119,4 @@ export class LayoutService {
|
||||
isMobile() {
|
||||
return !this.isDesktop();
|
||||
}
|
||||
|
||||
onConfigUpdate() {
|
||||
this._config = { ...this.layoutConfig() };
|
||||
this.configUpdate.next(this.layoutConfig());
|
||||
}
|
||||
|
||||
onMenuStateChange(event: MenuChangeEvent) {
|
||||
this.menuSource.next(event);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.resetSource.next(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import { TagModule } from 'primeng/tag';
|
||||
import { InputIconModule } from 'primeng/inputicon';
|
||||
import { IconFieldModule } from 'primeng/iconfield';
|
||||
import { ConfirmDialogModule } from 'primeng/confirmdialog';
|
||||
import { Product, ProductService } from '../service/product.service';
|
||||
import { Product, ProductService } from '@/app/pages/service/product.service';
|
||||
|
||||
interface Column {
|
||||
field: string;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { RippleModule } from 'primeng/ripple';
|
||||
import { TableModule } from 'primeng/table';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Product, ProductService } from '../../service/product.service';
|
||||
import { Product, ProductService } from '@/app/pages/service/product.service';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -11,7 +11,7 @@ import { Product, ProductService } from '../../service/product.service';
|
||||
imports: [CommonModule, TableModule, ButtonModule, RippleModule],
|
||||
template: `<div class="card mb-8!">
|
||||
<div class="font-semibold text-xl mb-4">Recent Sales</div>
|
||||
<p-table [value]="products" [paginator]="true" [rows]="5" responsiveLayout="scroll">
|
||||
<p-table [value]="products()" [paginator]="true" [rows]="5" responsiveLayout="scroll">
|
||||
<ng-template #header>
|
||||
<tr>
|
||||
<th>Image</th>
|
||||
@@ -37,11 +37,11 @@ import { Product, ProductService } from '../../service/product.service';
|
||||
providers: [ProductService]
|
||||
})
|
||||
export class RecentSalesWidget {
|
||||
products!: Product[];
|
||||
products = signal<Product[]>([]);
|
||||
|
||||
constructor(private productService: ProductService) {}
|
||||
productService = inject(ProductService);
|
||||
|
||||
ngOnInit() {
|
||||
this.productService.getProductsSmall().then((data) => (this.products = data));
|
||||
this.productService.getProductsSmall().then((data) => (this.products.set(data)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { afterNextRender, Component, effect, inject, signal } from '@angular/core';
|
||||
import { ChartModule } from 'primeng/chart';
|
||||
import { debounceTime, Subscription } from 'rxjs';
|
||||
import { LayoutService } from '../../../layout/service/layout.service';
|
||||
import { LayoutService } from '@/app/layout/service/layout.service';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -9,24 +8,29 @@ import { LayoutService } from '../../../layout/service/layout.service';
|
||||
imports: [ChartModule],
|
||||
template: `<div class="card mb-8!">
|
||||
<div class="font-semibold text-xl mb-4">Revenue Stream</div>
|
||||
<p-chart type="bar" [data]="chartData" [options]="chartOptions" class="h-100" />
|
||||
<p-chart type="bar" [data]="chartData()" [options]="chartOptions()" class="h-100" />
|
||||
</div>`
|
||||
})
|
||||
export class RevenueStreamWidget {
|
||||
chartData: any;
|
||||
layoutService = inject(LayoutService);
|
||||
|
||||
chartOptions: any;
|
||||
chartData = signal<any>(null);
|
||||
|
||||
subscription!: Subscription;
|
||||
chartOptions = signal<any>(null);
|
||||
|
||||
constructor(public layoutService: LayoutService) {
|
||||
this.subscription = this.layoutService.configUpdate$.pipe(debounceTime(25)).subscribe(() => {
|
||||
this.initChart();
|
||||
constructor() {
|
||||
afterNextRender(() => {
|
||||
setTimeout(() => {
|
||||
this.initChart();
|
||||
}, 150);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initChart();
|
||||
effect(() => {
|
||||
this.layoutService.layoutConfig().darkTheme;
|
||||
setTimeout(() => {
|
||||
this.initChart();
|
||||
}, 150);
|
||||
});
|
||||
}
|
||||
|
||||
initChart() {
|
||||
@@ -35,7 +39,7 @@ export class RevenueStreamWidget {
|
||||
const borderColor = documentStyle.getPropertyValue('--surface-border');
|
||||
const textMutedColor = documentStyle.getPropertyValue('--text-color-secondary');
|
||||
|
||||
this.chartData = {
|
||||
this.chartData.set({
|
||||
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
|
||||
datasets: [
|
||||
{
|
||||
@@ -67,9 +71,9 @@ export class RevenueStreamWidget {
|
||||
barThickness: 32
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
this.chartOptions = {
|
||||
this.chartOptions.set({
|
||||
maintainAspectRatio: false,
|
||||
aspectRatio: 0.8,
|
||||
plugins: {
|
||||
@@ -102,12 +106,6 @@ export class RevenueStreamWidget {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.subscription) {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Component } from '@angular/core';
|
||||
<div class="card">
|
||||
<div class="font-semibold text-2xl mb-4">Documentation</div>
|
||||
<div class="font-semibold text-xl mb-4">Get Started</div>
|
||||
<p class="text-lg mb-4">Sakai is an application template for Angular and is distributed as a CLI project. Current versions is Angular v20 with PrimeNG v20. In case CLI is not installed already, use the command below to set it up.</p>
|
||||
<p class="text-lg mb-4">Sakai is an application template for Angular and is distributed as a CLI project. Current versions is Angular v21 with PrimeNG v21. In case CLI is not installed already, use the command below to set it up.</p>
|
||||
<pre class="app-code">
|
||||
<code>npm install -g @angular/cli</code></pre>
|
||||
<p class="text-lg mb-4">
|
||||
|
||||
@@ -3,7 +3,7 @@ import { StyleClassModule } from 'primeng/styleclass';
|
||||
import { Router, RouterModule } from '@angular/router';
|
||||
import { RippleModule } from 'primeng/ripple';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import {AppFloatingConfigurator} from "@/layout/component/app.floatingconfigurator";
|
||||
import {AppFloatingConfigurator} from "@/app/layout/component/app.floatingconfigurator";
|
||||
|
||||
@Component({
|
||||
selector: 'topbar-widget',
|
||||
|
||||
@@ -1,96 +1,96 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class PhotoService {
|
||||
getData() {
|
||||
return [
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria1.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria1s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria1.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria1s.jpg',
|
||||
alt: 'Description for Image 1',
|
||||
title: 'Title 1'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria2.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria2s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria2.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria2s.jpg',
|
||||
alt: 'Description for Image 2',
|
||||
title: 'Title 2'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria3.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria3s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria3.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria3s.jpg',
|
||||
alt: 'Description for Image 3',
|
||||
title: 'Title 3'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria4.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria4s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria4.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria4s.jpg',
|
||||
alt: 'Description for Image 4',
|
||||
title: 'Title 4'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria5.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria5s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria5.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria5s.jpg',
|
||||
alt: 'Description for Image 5',
|
||||
title: 'Title 5'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria6.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria6s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria6.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria6s.jpg',
|
||||
alt: 'Description for Image 6',
|
||||
title: 'Title 6'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria7.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria7s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria7.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria7s.jpg',
|
||||
alt: 'Description for Image 7',
|
||||
title: 'Title 7'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria8.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria8s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria8.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria8s.jpg',
|
||||
alt: 'Description for Image 8',
|
||||
title: 'Title 8'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria9.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria9s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria9.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria9s.jpg',
|
||||
alt: 'Description for Image 9',
|
||||
title: 'Title 9'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria10.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria10s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria10.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria10s.jpg',
|
||||
alt: 'Description for Image 10',
|
||||
title: 'Title 10'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria11.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria11s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria11.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria11s.jpg',
|
||||
alt: 'Description for Image 11',
|
||||
title: 'Title 11'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria12.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria12s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria12.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria12s.jpg',
|
||||
alt: 'Description for Image 12',
|
||||
title: 'Title 12'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria13.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria13s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria13.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria13s.jpg',
|
||||
alt: 'Description for Image 13',
|
||||
title: 'Title 13'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria14.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria14s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria14.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria14s.jpg',
|
||||
alt: 'Description for Image 14',
|
||||
title: 'Title 14'
|
||||
},
|
||||
{
|
||||
itemImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria15.jpg',
|
||||
thumbnailImageSrc: 'https://primefaces.org/cdn/primeng/images/galleria/galleria15s.jpg',
|
||||
itemImageSrc: '/demo/images/galleria/galleria15.jpg',
|
||||
thumbnailImageSrc: '/demo/images/galleria/galleria15s.jpg',
|
||||
alt: 'Description for Image 15',
|
||||
title: 'Title 15'
|
||||
}
|
||||
|
||||
@@ -1,86 +1,80 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { ChartModule } from 'primeng/chart';
|
||||
import { FluidModule } from 'primeng/fluid';
|
||||
import { debounceTime, Subscription } from 'rxjs';
|
||||
import { LayoutService } from '../../layout/service/layout.service';
|
||||
import {Component, effect, inject, signal} from '@angular/core';
|
||||
import {ChartModule} from 'primeng/chart';
|
||||
import {FluidModule} from 'primeng/fluid';
|
||||
import {LayoutService} from '@/app/layout/service/layout.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-chart-demo',
|
||||
standalone: true,
|
||||
imports: [CommonModule, ChartModule, FluidModule],
|
||||
imports: [ChartModule, FluidModule],
|
||||
template: `
|
||||
<p-fluid class="grid grid-cols-12 gap-8">
|
||||
<div class="col-span-12 xl:col-span-6">
|
||||
<div class="card">
|
||||
<div class="font-semibold text-xl mb-4">Linear</div>
|
||||
<p-chart type="line" [data]="lineData" [options]="lineOptions"></p-chart>
|
||||
<div class="font-semibold text-xl mb-6">Linear</div>
|
||||
<p-chart type="line" [data]="lineData()" [options]="lineOptions()"></p-chart>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-span-12 xl:col-span-6">
|
||||
<div class="card">
|
||||
<div class="font-semibold text-xl mb-4">Bar</div>
|
||||
<p-chart type="bar" [data]="barData" [options]="barOptions"></p-chart>
|
||||
<div class="font-semibold text-xl mb-6">Bar</div>
|
||||
<p-chart type="bar" [data]="barData()" [options]="barOptions()"></p-chart>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-span-12 xl:col-span-6">
|
||||
<div class="card flex flex-col items-center">
|
||||
<div class="font-semibold text-xl mb-4">Pie</div>
|
||||
<p-chart type="pie" [data]="pieData" [options]="pieOptions"></p-chart>
|
||||
<div class="font-semibold text-xl mb-6">Pie</div>
|
||||
<p-chart type="pie" [data]="pieData()" [options]="pieOptions()"></p-chart>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-span-12 xl:col-span-6">
|
||||
<div class="card flex flex-col items-center">
|
||||
<div class="font-semibold text-xl mb-4">Doughnut</div>
|
||||
<p-chart type="doughnut" [data]="pieData" [options]="pieOptions"></p-chart>
|
||||
<div class="font-semibold text-xl mb-6">Doughnut</div>
|
||||
<p-chart type="doughnut" [data]="pieData()" [options]="pieOptions()"></p-chart>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-span-12 xl:col-span-6">
|
||||
<div class="card flex flex-col items-center">
|
||||
<div class="font-semibold text-xl mb-4">Polar Area</div>
|
||||
<p-chart type="polarArea" [data]="polarData" [options]="polarOptions"></p-chart>
|
||||
<div class="font-semibold text-xl mb-6">Polar Area</div>
|
||||
<p-chart type="polarArea" [data]="polarData()" [options]="polarOptions()"></p-chart>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-span-12 xl:col-span-6">
|
||||
<div class="card flex flex-col items-center">
|
||||
<div class="font-semibold text-xl mb-4">Radar</div>
|
||||
<p-chart type="radar" [data]="radarData" [options]="radarOptions"></p-chart>
|
||||
<div class="font-semibold text-xl mb-6">Radar</div>
|
||||
<p-chart type="radar" [data]="radarData()" [options]="radarOptions()"></p-chart>
|
||||
</div>
|
||||
</div>
|
||||
</p-fluid>
|
||||
`
|
||||
})
|
||||
export class ChartDemo {
|
||||
lineData: any;
|
||||
layoutService = inject(LayoutService);
|
||||
|
||||
barData: any;
|
||||
lineData = signal<any>(null);
|
||||
|
||||
barData = signal<any>(null);
|
||||
|
||||
pieData = signal<any>(null);
|
||||
|
||||
polarData = signal<any>(null);
|
||||
|
||||
radarData = signal<any>(null);
|
||||
|
||||
pieData: any;
|
||||
lineOptions = signal<any>(null);
|
||||
|
||||
barOptions = signal<any>(null);
|
||||
|
||||
pieOptions = signal<any>(null);
|
||||
|
||||
polarOptions = signal<any>(null);
|
||||
|
||||
radarOptions = signal<any>(null);
|
||||
|
||||
polarData: any;
|
||||
|
||||
radarData: any;
|
||||
|
||||
lineOptions: any;
|
||||
|
||||
barOptions: any;
|
||||
|
||||
pieOptions: any;
|
||||
|
||||
polarOptions: any;
|
||||
|
||||
radarOptions: any;
|
||||
|
||||
subscription: Subscription;
|
||||
constructor(private layoutService: LayoutService) {
|
||||
this.subscription = this.layoutService.configUpdate$.pipe(debounceTime(25)).subscribe(() => {
|
||||
this.initCharts();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initCharts();
|
||||
}
|
||||
chartEffect = effect(() => {
|
||||
this.layoutService.layoutConfig().darkTheme;
|
||||
setTimeout(() => this.initCharts(), 150);
|
||||
})
|
||||
|
||||
initCharts() {
|
||||
const documentStyle = getComputedStyle(document.documentElement);
|
||||
@@ -88,7 +82,7 @@ export class ChartDemo {
|
||||
const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary');
|
||||
const surfaceBorder = documentStyle.getPropertyValue('--surface-border');
|
||||
|
||||
this.barData = {
|
||||
this.barData.set({
|
||||
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
|
||||
datasets: [
|
||||
{
|
||||
@@ -104,9 +98,9 @@ export class ChartDemo {
|
||||
data: [28, 48, 40, 19, 86, 27, 90]
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
this.barOptions = {
|
||||
this.barOptions.set({
|
||||
maintainAspectRatio: false,
|
||||
aspectRatio: 0.8,
|
||||
plugins: {
|
||||
@@ -139,9 +133,9 @@ export class ChartDemo {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
this.pieData = {
|
||||
this.pieData.set({
|
||||
labels: ['A', 'B', 'C'],
|
||||
datasets: [
|
||||
{
|
||||
@@ -150,9 +144,9 @@ export class ChartDemo {
|
||||
hoverBackgroundColor: [documentStyle.getPropertyValue('--p-indigo-400'), documentStyle.getPropertyValue('--p-purple-400'), documentStyle.getPropertyValue('--p-teal-400')]
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
this.pieOptions = {
|
||||
this.pieOptions.set({
|
||||
plugins: {
|
||||
legend: {
|
||||
labels: {
|
||||
@@ -161,9 +155,9 @@ export class ChartDemo {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
this.lineData = {
|
||||
this.lineData.set({
|
||||
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
|
||||
datasets: [
|
||||
{
|
||||
@@ -183,9 +177,9 @@ export class ChartDemo {
|
||||
tension: 0.4
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
this.lineOptions = {
|
||||
this.lineOptions.set({
|
||||
maintainAspectRatio: false,
|
||||
aspectRatio: 0.8,
|
||||
plugins: {
|
||||
@@ -215,9 +209,9 @@ export class ChartDemo {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
this.polarData = {
|
||||
this.polarData.set({
|
||||
datasets: [
|
||||
{
|
||||
data: [11, 16, 7, 3],
|
||||
@@ -226,9 +220,9 @@ export class ChartDemo {
|
||||
}
|
||||
],
|
||||
labels: ['Indigo', 'Purple', 'Teal', 'Orange']
|
||||
};
|
||||
});
|
||||
|
||||
this.polarOptions = {
|
||||
this.polarOptions.set({
|
||||
plugins: {
|
||||
legend: {
|
||||
labels: {
|
||||
@@ -239,17 +233,17 @@ export class ChartDemo {
|
||||
scales: {
|
||||
r: {
|
||||
grid: {
|
||||
color: surfaceBorder,
|
||||
color: surfaceBorder
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
color: textColorSecondary
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.radarData = {
|
||||
this.radarData.set({
|
||||
labels: ['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running'],
|
||||
datasets: [
|
||||
{
|
||||
@@ -271,9 +265,9 @@ export class ChartDemo {
|
||||
data: [28, 48, 40, 19, 96, 27, 100]
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
this.radarOptions = {
|
||||
this.radarOptions.set({
|
||||
plugins: {
|
||||
legend: {
|
||||
labels: {
|
||||
@@ -291,12 +285,6 @@ export class ChartDemo {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.subscription) {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,10 @@ import { ListboxModule } from 'primeng/listbox';
|
||||
import { InputGroupAddonModule } from 'primeng/inputgroupaddon';
|
||||
import { TextareaModule } from 'primeng/textarea';
|
||||
import { ToggleButtonModule } from 'primeng/togglebutton';
|
||||
import { CountryService } from '../service/country.service';
|
||||
import { NodeService } from '../service/node.service';
|
||||
import { CountryService } from '@/app/pages/service/country.service';
|
||||
import { NodeService } from '@/app/pages/service/node.service';
|
||||
import { TreeNode } from 'primeng/api';
|
||||
import { Country } from '../service/customer.service';
|
||||
import { Country } from '@/app/pages/service/customer.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-input-demo',
|
||||
|
||||
@@ -7,7 +7,7 @@ import { OrderListModule } from 'primeng/orderlist';
|
||||
import { PickListModule } from 'primeng/picklist';
|
||||
import { SelectButtonModule } from 'primeng/selectbutton';
|
||||
import { TagModule } from 'primeng/tag';
|
||||
import { Product, ProductService } from '../service/product.service';
|
||||
import { Product, ProductService } from '@/app/pages/service/product.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-list-demo',
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, inject, OnInit, signal } from '@angular/core';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { CarouselModule } from 'primeng/carousel';
|
||||
import { GalleriaModule } from 'primeng/galleria';
|
||||
import { ImageModule } from 'primeng/image';
|
||||
import { TagModule } from 'primeng/tag';
|
||||
import { PhotoService } from '../service/photo.service';
|
||||
import { Product, ProductService } from '../service/product.service';
|
||||
import { PhotoService } from '@/app/pages/service/photo.service';
|
||||
import { Product, ProductService } from '@/app/pages/service/product.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-media-demo',
|
||||
@@ -14,7 +14,7 @@ import { Product, ProductService } from '../service/product.service';
|
||||
imports: [CommonModule, CarouselModule, ButtonModule, GalleriaModule, ImageModule, TagModule],
|
||||
template: `<div class="card">
|
||||
<div class="font-semibold text-xl mb-4">Carousel</div>
|
||||
<p-carousel [value]="products" [numVisible]="3" [numScroll]="3" [circular]="false" [responsiveOptions]="carouselResponsiveOptions">
|
||||
<p-carousel [value]="products()" [numVisible]="3" [numScroll]="3" [circular]="false" [responsiveOptions]="carouselResponsiveOptions">
|
||||
<ng-template let-product #item>
|
||||
<div class="border border-surface rounded-border m-2 p-4">
|
||||
<div class="mb-4">
|
||||
@@ -45,7 +45,7 @@ import { Product, ProductService } from '../service/product.service';
|
||||
|
||||
<div class="card">
|
||||
<div class="font-semibold text-xl mb-4">Galleria</div>
|
||||
<p-galleria [value]="images" [responsiveOptions]="galleriaResponsiveOptions" [containerStyle]="{ 'max-width': '640px' }" [numVisible]="5">
|
||||
<p-galleria [value]="images()" [responsiveOptions]="galleriaResponsiveOptions" [containerStyle]="{ 'max-width': '640px' }" [numVisible]="5">
|
||||
<ng-template #item let-item>
|
||||
<img [src]="item.itemImageSrc" style="width:100%" />
|
||||
</ng-template>
|
||||
@@ -57,9 +57,13 @@ import { Product, ProductService } from '../service/product.service';
|
||||
providers: [ProductService, PhotoService]
|
||||
})
|
||||
export class MediaDemo implements OnInit {
|
||||
products!: Product[];
|
||||
productService = inject(ProductService);
|
||||
|
||||
images!: any[];
|
||||
photoService = inject(PhotoService);
|
||||
|
||||
products = signal<Product[]>([]);
|
||||
|
||||
images = signal<any[]>([]);
|
||||
|
||||
galleriaResponsiveOptions: any[] = [
|
||||
{
|
||||
@@ -98,19 +102,9 @@ export class MediaDemo implements OnInit {
|
||||
}
|
||||
];
|
||||
|
||||
constructor(
|
||||
private productService: ProductService,
|
||||
private photoService: PhotoService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.productService.getProductsSmall().then((products) => {
|
||||
this.products = products;
|
||||
});
|
||||
|
||||
this.photoService.getImages().then((images) => {
|
||||
this.images = images;
|
||||
});
|
||||
this.productService.getProductsSmall().then((products) => this.products.set(products));
|
||||
this.photoService.getImages().then((images) => this.images.set(images));
|
||||
}
|
||||
|
||||
getSeverity(status: string) {
|
||||
|
||||
@@ -10,7 +10,7 @@ import { InputTextModule } from 'primeng/inputtext';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { TooltipModule } from 'primeng/tooltip';
|
||||
import { TableModule } from 'primeng/table';
|
||||
import { Product, ProductService } from '../service/product.service';
|
||||
import { Product, ProductService } from '@/app/pages/service/product.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-overlay-demo',
|
||||
|
||||
@@ -16,8 +16,8 @@ import { RippleModule } from 'primeng/ripple';
|
||||
import { InputIconModule } from 'primeng/inputicon';
|
||||
import { IconFieldModule } from 'primeng/iconfield';
|
||||
import { TagModule } from 'primeng/tag';
|
||||
import { Customer, CustomerService, Representative } from '../service/customer.service';
|
||||
import { Product, ProductService } from '../service/product.service';
|
||||
import { Customer, CustomerService, Representative } from '@/app/pages/service/customer.service';
|
||||
import { Product, ProductService } from '@/app/pages/service/product.service';
|
||||
import {ObjectUtils} from "primeng/utils";
|
||||
|
||||
interface expandedRows {
|
||||
|
||||
@@ -63,7 +63,7 @@ import {ButtonModule} from 'primeng/button';
|
||||
</ng-template>
|
||||
<ng-template #content let-event>
|
||||
<p-card [header]="event.status" [subheader]="event.date">
|
||||
<img *ngIf="event.image" [src]="'/images/product/' + event.image" [alt]="event.name" width="200" class="shadow" />
|
||||
<img *ngIf="event.image" [src]="'/demo/images/product/' + event.image" [alt]="event.name" width="200" class="shadow" />
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse,
|
||||
cupiditate neque quas!
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { Component, inject, OnInit, signal } from '@angular/core';
|
||||
import { TreeNode } from 'primeng/api';
|
||||
import { TreeModule } from 'primeng/tree';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { TreeTableModule } from 'primeng/treetable';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NodeService } from '../service/node.service';
|
||||
import { NodeService } from '@/app/pages/service/node.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tree-demo',
|
||||
@@ -13,12 +13,12 @@ import { NodeService } from '../service/node.service';
|
||||
template: `
|
||||
<div class="card">
|
||||
<div class="font-semibold text-xl">Tree</div>
|
||||
<p-tree [value]="treeValue" selectionMode="checkbox" [(selection)]="selectedTreeValue"></p-tree>
|
||||
<p-tree [value]="treeValue()" selectionMode="checkbox" [(selection)]="selectedTreeValue"></p-tree>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="font-semibold text-xl mb-4">TreeTable</div>
|
||||
<p-treetable [value]="treeTableValue" [columns]="cols" selectionMode="checkbox" [(selectionKeys)]="selectedTreeTableValue" dataKey="key" [scrollable]="true" [tableStyle]="{ 'min-width': '50rem' }">
|
||||
<p-treetable [value]="treeTableValue()" [columns]="cols" selectionMode="checkbox" [(selectionKeys)]="selectedTreeTableValue" dataKey="key" [scrollable]="true" [tableStyle]="{ 'min-width': '50rem' }">
|
||||
<ng-template #header let-columns>
|
||||
<tr>
|
||||
<th *ngFor="let col of columns">
|
||||
@@ -43,9 +43,9 @@ import { NodeService } from '../service/node.service';
|
||||
providers: [NodeService]
|
||||
})
|
||||
export class TreeDemo implements OnInit {
|
||||
treeValue: TreeNode[] = [];
|
||||
treeValue = signal<TreeNode[]>([]);
|
||||
|
||||
treeTableValue: TreeNode[] = [];
|
||||
treeTableValue = signal<TreeNode[]>([]);
|
||||
|
||||
selectedTreeValue: TreeNode[] = [];
|
||||
|
||||
@@ -56,8 +56,8 @@ export class TreeDemo implements OnInit {
|
||||
nodeService = inject(NodeService);
|
||||
|
||||
ngOnInit() {
|
||||
this.nodeService.getFiles().then((files) => (this.treeValue = files));
|
||||
this.nodeService.getTreeTableNodes().then((files: any) => (this.treeTableValue = files));
|
||||
this.nodeService.getFiles().then((files) => this.treeValue.set(files));
|
||||
this.nodeService.getTreeTableNodes().then((files: any) => this.treeTableValue.set(files));
|
||||
|
||||
this.cols = [
|
||||
{ field: 'name', header: 'Name' },
|
||||
|
||||
Reference in New Issue
Block a user