@es.framework/ng.ui.theme 2.0.59 → 2.0.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -18,7 +18,7 @@ import { ButtonModule } from 'primeng/button';
|
|
|
18
18
|
import { OverlayModule } from 'primeng/overlay';
|
|
19
19
|
import { VisibleDirective, HasPermissionDirective, ReplaceableTemplateDirective } from '@es.framework/ng.core/directives';
|
|
20
20
|
import { TranslatePipe, ToInjectorPipe } from '@es.framework/ng.core/pipes';
|
|
21
|
-
import { toSignal } from '@angular/core/rxjs-interop';
|
|
21
|
+
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
22
22
|
import * as i2$1 from '@angular/forms';
|
|
23
23
|
import { FormsModule } from '@angular/forms';
|
|
24
24
|
import { SelectModule } from 'primeng/select';
|
|
@@ -210,36 +210,36 @@ class LanguagesComponent {
|
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: LanguagesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
213
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: LanguagesComponent, isStandalone: true, selector: "abp-languages", ngImport: i0, template: `
|
|
214
|
-
@if (languages(); as langs) {
|
|
215
|
-
<div>
|
|
216
|
-
<!-- -->
|
|
217
|
-
<button
|
|
218
|
-
pButton
|
|
219
|
-
type="button"
|
|
220
|
-
icon="pi pi-globe"
|
|
221
|
-
class="p-button-text"
|
|
222
|
-
[title]="'اختر اللغة'"
|
|
223
|
-
(click)="overlay.toggle($event)"
|
|
224
|
-
></button>
|
|
225
|
-
<p-popover #overlay >
|
|
226
|
-
<ul class="w-48">
|
|
227
|
-
@for (lang of langs; track lang) {
|
|
228
|
-
<li
|
|
229
|
-
class="flex items-center justify-between px-3 py-2 cursor-pointer hover:bg-gray-100"
|
|
230
|
-
(click)="onSelectLanguage(lang.cultureName ?? ''); overlay.hide()"
|
|
231
|
-
>
|
|
232
|
-
<span>{{ lang.displayName }}</span>
|
|
233
|
-
@if (lang.cultureName === selectedLang()) {
|
|
234
|
-
<i class="pi pi-check text-green-500"></i>
|
|
235
|
-
}
|
|
236
|
-
</li>
|
|
237
|
-
}
|
|
238
|
-
</ul>
|
|
239
|
-
</p-popover>
|
|
240
|
-
</div>
|
|
241
|
-
}
|
|
242
|
-
|
|
213
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: LanguagesComponent, isStandalone: true, selector: "abp-languages", ngImport: i0, template: `
|
|
214
|
+
@if (languages(); as langs) {
|
|
215
|
+
<div>
|
|
216
|
+
<!-- -->
|
|
217
|
+
<button
|
|
218
|
+
pButton
|
|
219
|
+
type="button"
|
|
220
|
+
icon="pi pi-globe"
|
|
221
|
+
class="p-button-text"
|
|
222
|
+
[title]="'اختر اللغة'"
|
|
223
|
+
(click)="overlay.toggle($event)"
|
|
224
|
+
></button>
|
|
225
|
+
<p-popover #overlay >
|
|
226
|
+
<ul class="w-48">
|
|
227
|
+
@for (lang of langs; track lang) {
|
|
228
|
+
<li
|
|
229
|
+
class="flex items-center justify-between px-3 py-2 cursor-pointer hover:bg-gray-100"
|
|
230
|
+
(click)="onSelectLanguage(lang.cultureName ?? ''); overlay.hide()"
|
|
231
|
+
>
|
|
232
|
+
<span>{{ lang.displayName }}</span>
|
|
233
|
+
@if (lang.cultureName === selectedLang()) {
|
|
234
|
+
<i class="pi pi-check text-green-500"></i>
|
|
235
|
+
}
|
|
236
|
+
</li>
|
|
237
|
+
}
|
|
238
|
+
</ul>
|
|
239
|
+
</p-popover>
|
|
240
|
+
</div>
|
|
241
|
+
}
|
|
242
|
+
|
|
243
243
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i1.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }] });
|
|
244
244
|
}
|
|
245
245
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: LanguagesComponent, decorators: [{
|
|
@@ -248,36 +248,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
248
248
|
selector: 'abp-languages',
|
|
249
249
|
standalone: true,
|
|
250
250
|
imports: [SelectModule, FormsModule, PopoverModule, ButtonModule],
|
|
251
|
-
template: `
|
|
252
|
-
@if (languages(); as langs) {
|
|
253
|
-
<div>
|
|
254
|
-
<!-- -->
|
|
255
|
-
<button
|
|
256
|
-
pButton
|
|
257
|
-
type="button"
|
|
258
|
-
icon="pi pi-globe"
|
|
259
|
-
class="p-button-text"
|
|
260
|
-
[title]="'اختر اللغة'"
|
|
261
|
-
(click)="overlay.toggle($event)"
|
|
262
|
-
></button>
|
|
263
|
-
<p-popover #overlay >
|
|
264
|
-
<ul class="w-48">
|
|
265
|
-
@for (lang of langs; track lang) {
|
|
266
|
-
<li
|
|
267
|
-
class="flex items-center justify-between px-3 py-2 cursor-pointer hover:bg-gray-100"
|
|
268
|
-
(click)="onSelectLanguage(lang.cultureName ?? ''); overlay.hide()"
|
|
269
|
-
>
|
|
270
|
-
<span>{{ lang.displayName }}</span>
|
|
271
|
-
@if (lang.cultureName === selectedLang()) {
|
|
272
|
-
<i class="pi pi-check text-green-500"></i>
|
|
273
|
-
}
|
|
274
|
-
</li>
|
|
275
|
-
}
|
|
276
|
-
</ul>
|
|
277
|
-
</p-popover>
|
|
278
|
-
</div>
|
|
279
|
-
}
|
|
280
|
-
|
|
251
|
+
template: `
|
|
252
|
+
@if (languages(); as langs) {
|
|
253
|
+
<div>
|
|
254
|
+
<!-- -->
|
|
255
|
+
<button
|
|
256
|
+
pButton
|
|
257
|
+
type="button"
|
|
258
|
+
icon="pi pi-globe"
|
|
259
|
+
class="p-button-text"
|
|
260
|
+
[title]="'اختر اللغة'"
|
|
261
|
+
(click)="overlay.toggle($event)"
|
|
262
|
+
></button>
|
|
263
|
+
<p-popover #overlay >
|
|
264
|
+
<ul class="w-48">
|
|
265
|
+
@for (lang of langs; track lang) {
|
|
266
|
+
<li
|
|
267
|
+
class="flex items-center justify-between px-3 py-2 cursor-pointer hover:bg-gray-100"
|
|
268
|
+
(click)="onSelectLanguage(lang.cultureName ?? ''); overlay.hide()"
|
|
269
|
+
>
|
|
270
|
+
<span>{{ lang.displayName }}</span>
|
|
271
|
+
@if (lang.cultureName === selectedLang()) {
|
|
272
|
+
<i class="pi pi-check text-green-500"></i>
|
|
273
|
+
}
|
|
274
|
+
</li>
|
|
275
|
+
}
|
|
276
|
+
</ul>
|
|
277
|
+
</p-popover>
|
|
278
|
+
</div>
|
|
279
|
+
}
|
|
280
|
+
|
|
281
281
|
`
|
|
282
282
|
}]
|
|
283
283
|
}], ctorParameters: () => [] });
|
|
@@ -452,7 +452,45 @@ class AppConfigurator {
|
|
|
452
452
|
primaryColors = computed(() => {
|
|
453
453
|
const presetPalette = presets[this.layoutService.layoutConfig().preset].primitive;
|
|
454
454
|
const colors = ['blue', 'green', 'lime', 'orange', 'amber', 'yellow', 'teal', 'cyan', 'sky', 'emerald', 'indigo', 'violet', 'purple', 'fuchsia', 'pink', 'rose'];
|
|
455
|
-
const
|
|
455
|
+
const customColors = [
|
|
456
|
+
{
|
|
457
|
+
name: 'ghazali',
|
|
458
|
+
palette: {
|
|
459
|
+
50: '#fbf7f2',
|
|
460
|
+
100: '#f4eadf',
|
|
461
|
+
200: '#e8d3bf',
|
|
462
|
+
300: '#d8b596',
|
|
463
|
+
400: '#c99572',
|
|
464
|
+
500: '#b97855',
|
|
465
|
+
600: '#a45f3f',
|
|
466
|
+
700: '#884a34',
|
|
467
|
+
800: '#713d2f',
|
|
468
|
+
900: '#5e342b',
|
|
469
|
+
950: '#351914'
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
name: 'brown',
|
|
474
|
+
palette: {
|
|
475
|
+
50: '#faf6f3',
|
|
476
|
+
100: '#f1e5dc',
|
|
477
|
+
200: '#e2c9b8',
|
|
478
|
+
300: '#cea58a',
|
|
479
|
+
400: '#b97e5d',
|
|
480
|
+
500: '#9f6244',
|
|
481
|
+
600: '#814a34',
|
|
482
|
+
700: '#6a3d2e',
|
|
483
|
+
800: '#59342a',
|
|
484
|
+
900: '#4c2e27',
|
|
485
|
+
950: '#2b1712'
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
];
|
|
489
|
+
// const palettes: SurfacesType[] = [{ name: 'noir', palette: {} }];
|
|
490
|
+
const palettes = [
|
|
491
|
+
{ name: 'noir', palette: {} },
|
|
492
|
+
...customColors
|
|
493
|
+
];
|
|
456
494
|
colors.forEach((color) => {
|
|
457
495
|
palettes.push({
|
|
458
496
|
name: color,
|
|
@@ -636,53 +674,53 @@ class AppConfigurator {
|
|
|
636
674
|
this.layoutService.layoutConfig.update((prev) => ({ ...prev, menuMode: event }));
|
|
637
675
|
}
|
|
638
676
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AppConfigurator, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
639
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: AppConfigurator, isStandalone: true, selector: "app-configurator", ngImport: i0, template: `
|
|
640
|
-
<div class="flex flex-col gap-4">
|
|
641
|
-
<div>
|
|
642
|
-
<span class="text-sm text-muted-color font-semibold">Primary</span>
|
|
643
|
-
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
644
|
-
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
645
|
-
<button
|
|
646
|
-
type="button"
|
|
647
|
-
[title]="primaryColor.name"
|
|
648
|
-
(click)="updateColors($event, 'primary', primaryColor)"
|
|
649
|
-
[ngClass]="{ 'outline-primary': primaryColor.name === selectedPrimaryColor() }"
|
|
650
|
-
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
651
|
-
[style]="{
|
|
652
|
-
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
653
|
-
}"
|
|
654
|
-
></button>
|
|
655
|
-
}
|
|
656
|
-
</div>
|
|
657
|
-
</div>
|
|
658
|
-
<div>
|
|
659
|
-
<span class="text-sm text-muted-color font-semibold">Surface</span>
|
|
660
|
-
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
661
|
-
@for (surface of surfaces; track surface.name) {
|
|
662
|
-
<button
|
|
663
|
-
type="button"
|
|
664
|
-
[title]="surface.name"
|
|
665
|
-
(click)="updateColors($event, 'surface', surface)"
|
|
666
|
-
[ngClass]="{ 'outline-primary': selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : layoutService.layoutConfig().darkTheme ? surface.name === 'zinc' : surface.name === 'slate' }"
|
|
667
|
-
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
668
|
-
[style]="{
|
|
669
|
-
'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
|
|
670
|
-
}"
|
|
671
|
-
></button>
|
|
672
|
-
}
|
|
673
|
-
</div>
|
|
674
|
-
</div>
|
|
675
|
-
<div class="flex flex-col gap-2">
|
|
676
|
-
<span class="text-sm text-muted-color font-semibold">Presets</span>
|
|
677
|
-
<p-selectbutton [options]="presets" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false" size="small" />
|
|
678
|
-
</div>
|
|
679
|
-
@if (showMenuModeButton()) {
|
|
680
|
-
<div class="flex flex-col gap-2">
|
|
681
|
-
<span class="text-sm text-muted-color font-semibold">Menu Mode</span>
|
|
682
|
-
<p-selectbutton [ngModel]="menuMode()" (ngModelChange)="onMenuModeChange($event)" [options]="menuModeOptions" [allowEmpty]="false" size="small" />
|
|
683
|
-
</div>
|
|
684
|
-
}
|
|
685
|
-
</div>
|
|
677
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: AppConfigurator, isStandalone: true, selector: "app-configurator", ngImport: i0, template: `
|
|
678
|
+
<div class="flex flex-col gap-4">
|
|
679
|
+
<div>
|
|
680
|
+
<span class="text-sm text-muted-color font-semibold">Primary</span>
|
|
681
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
682
|
+
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
683
|
+
<button
|
|
684
|
+
type="button"
|
|
685
|
+
[title]="primaryColor.name"
|
|
686
|
+
(click)="updateColors($event, 'primary', primaryColor)"
|
|
687
|
+
[ngClass]="{ 'outline-primary': primaryColor.name === selectedPrimaryColor() }"
|
|
688
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
689
|
+
[style]="{
|
|
690
|
+
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
691
|
+
}"
|
|
692
|
+
></button>
|
|
693
|
+
}
|
|
694
|
+
</div>
|
|
695
|
+
</div>
|
|
696
|
+
<div>
|
|
697
|
+
<span class="text-sm text-muted-color font-semibold">Surface</span>
|
|
698
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
699
|
+
@for (surface of surfaces; track surface.name) {
|
|
700
|
+
<button
|
|
701
|
+
type="button"
|
|
702
|
+
[title]="surface.name"
|
|
703
|
+
(click)="updateColors($event, 'surface', surface)"
|
|
704
|
+
[ngClass]="{ 'outline-primary': selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : layoutService.layoutConfig().darkTheme ? surface.name === 'zinc' : surface.name === 'slate' }"
|
|
705
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
706
|
+
[style]="{
|
|
707
|
+
'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
|
|
708
|
+
}"
|
|
709
|
+
></button>
|
|
710
|
+
}
|
|
711
|
+
</div>
|
|
712
|
+
</div>
|
|
713
|
+
<div class="flex flex-col gap-2">
|
|
714
|
+
<span class="text-sm text-muted-color font-semibold">Presets</span>
|
|
715
|
+
<p-selectbutton [options]="presets" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false" size="small" />
|
|
716
|
+
</div>
|
|
717
|
+
@if (showMenuModeButton()) {
|
|
718
|
+
<div class="flex flex-col gap-2">
|
|
719
|
+
<span class="text-sm text-muted-color font-semibold">Menu Mode</span>
|
|
720
|
+
<p-selectbutton [ngModel]="menuMode()" (ngModelChange)="onMenuModeChange($event)" [options]="menuModeOptions" [allowEmpty]="false" size="small" />
|
|
721
|
+
</div>
|
|
722
|
+
}
|
|
723
|
+
</div>
|
|
686
724
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i3.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }] });
|
|
687
725
|
}
|
|
688
726
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AppConfigurator, decorators: [{
|
|
@@ -691,53 +729,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
691
729
|
selector: 'app-configurator',
|
|
692
730
|
standalone: true,
|
|
693
731
|
imports: [CommonModule, FormsModule, SelectButtonModule],
|
|
694
|
-
template: `
|
|
695
|
-
<div class="flex flex-col gap-4">
|
|
696
|
-
<div>
|
|
697
|
-
<span class="text-sm text-muted-color font-semibold">Primary</span>
|
|
698
|
-
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
699
|
-
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
700
|
-
<button
|
|
701
|
-
type="button"
|
|
702
|
-
[title]="primaryColor.name"
|
|
703
|
-
(click)="updateColors($event, 'primary', primaryColor)"
|
|
704
|
-
[ngClass]="{ 'outline-primary': primaryColor.name === selectedPrimaryColor() }"
|
|
705
|
-
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
706
|
-
[style]="{
|
|
707
|
-
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
708
|
-
}"
|
|
709
|
-
></button>
|
|
710
|
-
}
|
|
711
|
-
</div>
|
|
712
|
-
</div>
|
|
713
|
-
<div>
|
|
714
|
-
<span class="text-sm text-muted-color font-semibold">Surface</span>
|
|
715
|
-
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
716
|
-
@for (surface of surfaces; track surface.name) {
|
|
717
|
-
<button
|
|
718
|
-
type="button"
|
|
719
|
-
[title]="surface.name"
|
|
720
|
-
(click)="updateColors($event, 'surface', surface)"
|
|
721
|
-
[ngClass]="{ 'outline-primary': selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : layoutService.layoutConfig().darkTheme ? surface.name === 'zinc' : surface.name === 'slate' }"
|
|
722
|
-
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
723
|
-
[style]="{
|
|
724
|
-
'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
|
|
725
|
-
}"
|
|
726
|
-
></button>
|
|
727
|
-
}
|
|
728
|
-
</div>
|
|
729
|
-
</div>
|
|
730
|
-
<div class="flex flex-col gap-2">
|
|
731
|
-
<span class="text-sm text-muted-color font-semibold">Presets</span>
|
|
732
|
-
<p-selectbutton [options]="presets" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false" size="small" />
|
|
733
|
-
</div>
|
|
734
|
-
@if (showMenuModeButton()) {
|
|
735
|
-
<div class="flex flex-col gap-2">
|
|
736
|
-
<span class="text-sm text-muted-color font-semibold">Menu Mode</span>
|
|
737
|
-
<p-selectbutton [ngModel]="menuMode()" (ngModelChange)="onMenuModeChange($event)" [options]="menuModeOptions" [allowEmpty]="false" size="small" />
|
|
738
|
-
</div>
|
|
739
|
-
}
|
|
740
|
-
</div>
|
|
732
|
+
template: `
|
|
733
|
+
<div class="flex flex-col gap-4">
|
|
734
|
+
<div>
|
|
735
|
+
<span class="text-sm text-muted-color font-semibold">Primary</span>
|
|
736
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
737
|
+
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
738
|
+
<button
|
|
739
|
+
type="button"
|
|
740
|
+
[title]="primaryColor.name"
|
|
741
|
+
(click)="updateColors($event, 'primary', primaryColor)"
|
|
742
|
+
[ngClass]="{ 'outline-primary': primaryColor.name === selectedPrimaryColor() }"
|
|
743
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
744
|
+
[style]="{
|
|
745
|
+
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
746
|
+
}"
|
|
747
|
+
></button>
|
|
748
|
+
}
|
|
749
|
+
</div>
|
|
750
|
+
</div>
|
|
751
|
+
<div>
|
|
752
|
+
<span class="text-sm text-muted-color font-semibold">Surface</span>
|
|
753
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
754
|
+
@for (surface of surfaces; track surface.name) {
|
|
755
|
+
<button
|
|
756
|
+
type="button"
|
|
757
|
+
[title]="surface.name"
|
|
758
|
+
(click)="updateColors($event, 'surface', surface)"
|
|
759
|
+
[ngClass]="{ 'outline-primary': selectedSurfaceColor() ? selectedSurfaceColor() === surface.name : layoutService.layoutConfig().darkTheme ? surface.name === 'zinc' : surface.name === 'slate' }"
|
|
760
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
761
|
+
[style]="{
|
|
762
|
+
'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
|
|
763
|
+
}"
|
|
764
|
+
></button>
|
|
765
|
+
}
|
|
766
|
+
</div>
|
|
767
|
+
</div>
|
|
768
|
+
<div class="flex flex-col gap-2">
|
|
769
|
+
<span class="text-sm text-muted-color font-semibold">Presets</span>
|
|
770
|
+
<p-selectbutton [options]="presets" [ngModel]="selectedPreset()" (ngModelChange)="onPresetChange($event)" [allowEmpty]="false" size="small" />
|
|
771
|
+
</div>
|
|
772
|
+
@if (showMenuModeButton()) {
|
|
773
|
+
<div class="flex flex-col gap-2">
|
|
774
|
+
<span class="text-sm text-muted-color font-semibold">Menu Mode</span>
|
|
775
|
+
<p-selectbutton [ngModel]="menuMode()" (ngModelChange)="onMenuModeChange($event)" [options]="menuModeOptions" [allowEmpty]="false" size="small" />
|
|
776
|
+
</div>
|
|
777
|
+
}
|
|
778
|
+
</div>
|
|
741
779
|
`,
|
|
742
780
|
}]
|
|
743
781
|
}] });
|
|
@@ -868,167 +906,167 @@ class NavItemsComponent {
|
|
|
868
906
|
this.authService.navigateToLogin();
|
|
869
907
|
}
|
|
870
908
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: NavItemsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
871
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: NavItemsComponent, isStandalone: true, selector: "app-nav-items", ngImport: i0, template: `
|
|
872
|
-
<header class="flex items-center justify-between px-6 h-16 bg-white shadow sticky top-0 z-9">
|
|
873
|
-
<!-- Left: Logo / Title -->
|
|
874
|
-
<div class="flex items-center space-x-3 rtl:space-x-reverse">
|
|
875
|
-
<img src="assets/logo.png" alt="Logo" class="h-8 w-8" />
|
|
876
|
-
<span class="text-lg font-semibold text-gray-800">{{ '' | translate }}</span>
|
|
877
|
-
</div>
|
|
878
|
-
|
|
879
|
-
<!-- Center: Nav Items -->
|
|
880
|
-
<div class="flex items-center space-x-4 rtl:space-x-reverse">
|
|
881
|
-
<ul class="flex space-x-4">
|
|
882
|
-
@for (item of navItems.items$ | async; track item.id) {
|
|
883
|
-
@if (!item.visible || item.visible(item)) {
|
|
884
|
-
<ng-container *frameworkVisible="!item.visible || item.visible(item)">
|
|
885
|
-
<li class="flex items-center">
|
|
886
|
-
@if (item.component) {
|
|
887
|
-
<ng-container
|
|
888
|
-
[ngComponentOutlet]="item.component"
|
|
889
|
-
[ngComponentOutletInjector]="item | toInjector"
|
|
890
|
-
></ng-container>
|
|
891
|
-
} @else {
|
|
892
|
-
<button
|
|
893
|
-
pButton
|
|
894
|
-
type="button"
|
|
895
|
-
class="p-button-text hover:bg-gray-100 focus:outline-none flex items-center"
|
|
896
|
-
(click)="item.action?.()"
|
|
897
|
-
>
|
|
898
|
-
<span [innerHTML]="item.html"></span>
|
|
899
|
-
</button>
|
|
900
|
-
}
|
|
901
|
-
</li>
|
|
902
|
-
</ng-container>
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
</ul>
|
|
906
|
-
</div>
|
|
907
|
-
|
|
908
|
-
<!-- Right: Actions -->
|
|
909
|
-
<div class="flex items-center rtl:space-x-reverse">
|
|
910
|
-
<!-- Configurator -->
|
|
911
|
-
|
|
912
|
-
<div>
|
|
913
|
-
<!-- -->
|
|
914
|
-
<button
|
|
915
|
-
pButton
|
|
916
|
-
type="button"
|
|
917
|
-
icon="pi pi-palette"
|
|
918
|
-
class="p-button-text"
|
|
919
|
-
[title]="''"
|
|
920
|
-
(click)="overlay.toggle($event)"
|
|
921
|
-
>
|
|
922
|
-
</button>
|
|
923
|
-
|
|
924
|
-
<p-popover #overlay >
|
|
925
|
-
<app-configurator />
|
|
926
|
-
</p-popover>
|
|
927
|
-
</div>
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
<!-- Dark Mode Toggle -->
|
|
931
|
-
<button
|
|
932
|
-
pButton
|
|
933
|
-
type="button"
|
|
934
|
-
[icon]="layoutService.isDarkTheme() ?'pi pi-moon': 'pi pi-sun'"
|
|
935
|
-
class="p-button-text"
|
|
936
|
-
(click)="toggleDarkMode()">
|
|
937
|
-
</button>
|
|
938
|
-
|
|
939
|
-
<!-- Language Switcher -->
|
|
940
|
-
<abp-languages></abp-languages>
|
|
941
|
-
|
|
942
|
-
<!-- User Menu -->
|
|
943
|
-
<div class="relative">
|
|
944
|
-
<button
|
|
945
|
-
class="p-link p-2"
|
|
946
|
-
(click)="menu.toggle($event)"
|
|
947
|
-
aria-label="User menu"
|
|
948
|
-
>
|
|
949
|
-
<p-avatar
|
|
950
|
-
[label]="loading ? '' : userName"
|
|
951
|
-
[icon]="loading ? 'pi pi-spinner' : ''"
|
|
952
|
-
[class]="{'pi-spin': loading}"
|
|
953
|
-
shape="circle"
|
|
954
|
-
class="bg-blue-600 text-white cursor-pointer"
|
|
955
|
-
[title]="(currentUser$ | async)?.name || ''"
|
|
956
|
-
></p-avatar>
|
|
957
|
-
</button>
|
|
958
|
-
|
|
959
|
-
<p-menu
|
|
960
|
-
#menu
|
|
961
|
-
[model]="userMenuItems"
|
|
962
|
-
[popup]="true"
|
|
963
|
-
[appendTo]="'body'"
|
|
964
|
-
styleClass="w-64 sm:w-72 shadow-lg rounded-md"
|
|
965
|
-
>
|
|
966
|
-
<ng-template pTemplate="start">
|
|
967
|
-
<div class="px-5 py-4 border-b border-gray-200 bg-gray-50 flex flex-col items-center text-center">
|
|
968
|
-
<p-avatar
|
|
969
|
-
[label]="userName"
|
|
970
|
-
shape="circle"
|
|
971
|
-
size="xlarge"
|
|
972
|
-
styleClass="bg-blue-600 text-white mb-3 shadow-lg"
|
|
973
|
-
[title]="(currentUser$ | async)?.name || ''"
|
|
974
|
-
></p-avatar>
|
|
975
|
-
<h5 class="text-xl font-semibold text-gray-800 leading-tight">
|
|
976
|
-
{{ (currentUser$ | async)?.name || 'اسم المستخدم' }}
|
|
977
|
-
</h5>
|
|
978
|
-
<p class="text-sm text-gray-600 truncate max-w-full">
|
|
979
|
-
{{ (currentUser$ | async)?.email || 'لا يوجد بريد إلكتروني' }}
|
|
980
|
-
</p>
|
|
981
|
-
@if ((selectedTenant$ | async); as tenant) {
|
|
982
|
-
<span
|
|
983
|
-
class="inline-block mt-2 px-3 py-1 text-xs rounded-full font-semibold"
|
|
984
|
-
[ngClass]="{
|
|
985
|
-
'bg-green-100 text-green-800': true
|
|
986
|
-
}"
|
|
987
|
-
>
|
|
988
|
-
{{ tenant?.name || '_' }}
|
|
989
|
-
</span>
|
|
990
|
-
}
|
|
991
|
-
</div>
|
|
992
|
-
</ng-template>
|
|
993
|
-
|
|
994
|
-
<ng-template pTemplate="item" let-item>
|
|
995
|
-
<!-- *frameworkVisible="!item.visible || item.visible(item)" -->
|
|
996
|
-
<ng-container >
|
|
997
|
-
<!-- *hasPermission="item.requiredPolicy" -->
|
|
998
|
-
<a
|
|
999
|
-
|
|
1000
|
-
class="p-menuitem-link flex items-center space-x-3 rtl:space-x-reverse px-5 py-2 hover:bg-gray-100 rounded-md"
|
|
1001
|
-
[ngClass]="item.styleClass || ''"
|
|
1002
|
-
(click)="item.command ? item.command() : null"
|
|
1003
|
-
[routerLink]="item.routerLink ? item.routerLink : null"
|
|
1004
|
-
tabindex="0"
|
|
1005
|
-
>
|
|
1006
|
-
@if (item.component) {
|
|
1007
|
-
<ng-container
|
|
1008
|
-
[ngComponentOutlet]="item.component"
|
|
1009
|
-
[ngComponentOutletInjector]="item | toInjector"
|
|
1010
|
-
></ng-container>
|
|
1011
|
-
} @else {
|
|
1012
|
-
<i [class]="item.icon + ' text-lg text-gray-600'"></i>
|
|
1013
|
-
<span class="text-gray-700">{{ item.label | translate }}</span>
|
|
1014
|
-
}
|
|
1015
|
-
</a>
|
|
1016
|
-
</ng-container>
|
|
1017
|
-
</ng-template>
|
|
1018
|
-
</p-menu>
|
|
1019
|
-
</div>
|
|
1020
|
-
|
|
1021
|
-
<!-- Logout Button (separate from menu) -->
|
|
1022
|
-
<!-- <button
|
|
1023
|
-
type="button"
|
|
1024
|
-
class="layout-topbar-action"
|
|
1025
|
-
(click)="logout()"
|
|
1026
|
-
title="تسجيل الخروج"
|
|
1027
|
-
>
|
|
1028
|
-
<i class="pi pi-sign-out"></i>
|
|
1029
|
-
</button> -->
|
|
1030
|
-
</div>
|
|
1031
|
-
</header>
|
|
909
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: NavItemsComponent, isStandalone: true, selector: "app-nav-items", ngImport: i0, template: `
|
|
910
|
+
<header class="flex items-center justify-between px-6 h-16 bg-white shadow sticky top-0 z-9">
|
|
911
|
+
<!-- Left: Logo / Title -->
|
|
912
|
+
<div class="flex items-center space-x-3 rtl:space-x-reverse">
|
|
913
|
+
<img src="assets/logo.png" alt="Logo" class="h-8 w-8" />
|
|
914
|
+
<span class="text-lg font-semibold text-gray-800">{{ '' | translate }}</span>
|
|
915
|
+
</div>
|
|
916
|
+
|
|
917
|
+
<!-- Center: Nav Items -->
|
|
918
|
+
<div class="flex items-center space-x-4 rtl:space-x-reverse">
|
|
919
|
+
<ul class="flex space-x-4">
|
|
920
|
+
@for (item of navItems.items$ | async; track item.id) {
|
|
921
|
+
@if (!item.visible || item.visible(item)) {
|
|
922
|
+
<ng-container *frameworkVisible="!item.visible || item.visible(item)">
|
|
923
|
+
<li class="flex items-center">
|
|
924
|
+
@if (item.component) {
|
|
925
|
+
<ng-container
|
|
926
|
+
[ngComponentOutlet]="item.component"
|
|
927
|
+
[ngComponentOutletInjector]="item | toInjector"
|
|
928
|
+
></ng-container>
|
|
929
|
+
} @else {
|
|
930
|
+
<button
|
|
931
|
+
pButton
|
|
932
|
+
type="button"
|
|
933
|
+
class="p-button-text hover:bg-gray-100 focus:outline-none flex items-center"
|
|
934
|
+
(click)="item.action?.()"
|
|
935
|
+
>
|
|
936
|
+
<span [innerHTML]="item.html"></span>
|
|
937
|
+
</button>
|
|
938
|
+
}
|
|
939
|
+
</li>
|
|
940
|
+
</ng-container>
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
</ul>
|
|
944
|
+
</div>
|
|
945
|
+
|
|
946
|
+
<!-- Right: Actions -->
|
|
947
|
+
<div class="flex items-center rtl:space-x-reverse">
|
|
948
|
+
<!-- Configurator -->
|
|
949
|
+
|
|
950
|
+
<div>
|
|
951
|
+
<!-- -->
|
|
952
|
+
<button
|
|
953
|
+
pButton
|
|
954
|
+
type="button"
|
|
955
|
+
icon="pi pi-palette"
|
|
956
|
+
class="p-button-text"
|
|
957
|
+
[title]="''"
|
|
958
|
+
(click)="overlay.toggle($event)"
|
|
959
|
+
>
|
|
960
|
+
</button>
|
|
961
|
+
|
|
962
|
+
<p-popover #overlay >
|
|
963
|
+
<app-configurator />
|
|
964
|
+
</p-popover>
|
|
965
|
+
</div>
|
|
966
|
+
|
|
967
|
+
|
|
968
|
+
<!-- Dark Mode Toggle -->
|
|
969
|
+
<button
|
|
970
|
+
pButton
|
|
971
|
+
type="button"
|
|
972
|
+
[icon]="layoutService.isDarkTheme() ?'pi pi-moon': 'pi pi-sun'"
|
|
973
|
+
class="p-button-text"
|
|
974
|
+
(click)="toggleDarkMode()">
|
|
975
|
+
</button>
|
|
976
|
+
|
|
977
|
+
<!-- Language Switcher -->
|
|
978
|
+
<abp-languages></abp-languages>
|
|
979
|
+
|
|
980
|
+
<!-- User Menu -->
|
|
981
|
+
<div class="relative">
|
|
982
|
+
<button
|
|
983
|
+
class="p-link p-2"
|
|
984
|
+
(click)="menu.toggle($event)"
|
|
985
|
+
aria-label="User menu"
|
|
986
|
+
>
|
|
987
|
+
<p-avatar
|
|
988
|
+
[label]="loading ? '' : userName"
|
|
989
|
+
[icon]="loading ? 'pi pi-spinner' : ''"
|
|
990
|
+
[class]="{'pi-spin': loading}"
|
|
991
|
+
shape="circle"
|
|
992
|
+
class="bg-blue-600 text-white cursor-pointer"
|
|
993
|
+
[title]="(currentUser$ | async)?.name || ''"
|
|
994
|
+
></p-avatar>
|
|
995
|
+
</button>
|
|
996
|
+
|
|
997
|
+
<p-menu
|
|
998
|
+
#menu
|
|
999
|
+
[model]="userMenuItems"
|
|
1000
|
+
[popup]="true"
|
|
1001
|
+
[appendTo]="'body'"
|
|
1002
|
+
styleClass="w-64 sm:w-72 shadow-lg rounded-md"
|
|
1003
|
+
>
|
|
1004
|
+
<ng-template pTemplate="start">
|
|
1005
|
+
<div class="px-5 py-4 border-b border-gray-200 bg-gray-50 flex flex-col items-center text-center">
|
|
1006
|
+
<p-avatar
|
|
1007
|
+
[label]="userName"
|
|
1008
|
+
shape="circle"
|
|
1009
|
+
size="xlarge"
|
|
1010
|
+
styleClass="bg-blue-600 text-white mb-3 shadow-lg"
|
|
1011
|
+
[title]="(currentUser$ | async)?.name || ''"
|
|
1012
|
+
></p-avatar>
|
|
1013
|
+
<h5 class="text-xl font-semibold text-gray-800 leading-tight">
|
|
1014
|
+
{{ (currentUser$ | async)?.name || 'اسم المستخدم' }}
|
|
1015
|
+
</h5>
|
|
1016
|
+
<p class="text-sm text-gray-600 truncate max-w-full">
|
|
1017
|
+
{{ (currentUser$ | async)?.email || 'لا يوجد بريد إلكتروني' }}
|
|
1018
|
+
</p>
|
|
1019
|
+
@if ((selectedTenant$ | async); as tenant) {
|
|
1020
|
+
<span
|
|
1021
|
+
class="inline-block mt-2 px-3 py-1 text-xs rounded-full font-semibold"
|
|
1022
|
+
[ngClass]="{
|
|
1023
|
+
'bg-green-100 text-green-800': true
|
|
1024
|
+
}"
|
|
1025
|
+
>
|
|
1026
|
+
{{ tenant?.name || '_' }}
|
|
1027
|
+
</span>
|
|
1028
|
+
}
|
|
1029
|
+
</div>
|
|
1030
|
+
</ng-template>
|
|
1031
|
+
|
|
1032
|
+
<ng-template pTemplate="item" let-item>
|
|
1033
|
+
<!-- *frameworkVisible="!item.visible || item.visible(item)" -->
|
|
1034
|
+
<ng-container >
|
|
1035
|
+
<!-- *hasPermission="item.requiredPolicy" -->
|
|
1036
|
+
<a
|
|
1037
|
+
|
|
1038
|
+
class="p-menuitem-link flex items-center space-x-3 rtl:space-x-reverse px-5 py-2 hover:bg-gray-100 rounded-md"
|
|
1039
|
+
[ngClass]="item.styleClass || ''"
|
|
1040
|
+
(click)="item.command ? item.command() : null"
|
|
1041
|
+
[routerLink]="item.routerLink ? item.routerLink : null"
|
|
1042
|
+
tabindex="0"
|
|
1043
|
+
>
|
|
1044
|
+
@if (item.component) {
|
|
1045
|
+
<ng-container
|
|
1046
|
+
[ngComponentOutlet]="item.component"
|
|
1047
|
+
[ngComponentOutletInjector]="item | toInjector"
|
|
1048
|
+
></ng-container>
|
|
1049
|
+
} @else {
|
|
1050
|
+
<i [class]="item.icon + ' text-lg text-gray-600'"></i>
|
|
1051
|
+
<span class="text-gray-700">{{ item.label | translate }}</span>
|
|
1052
|
+
}
|
|
1053
|
+
</a>
|
|
1054
|
+
</ng-container>
|
|
1055
|
+
</ng-template>
|
|
1056
|
+
</p-menu>
|
|
1057
|
+
</div>
|
|
1058
|
+
|
|
1059
|
+
<!-- Logout Button (separate from menu) -->
|
|
1060
|
+
<!-- <button
|
|
1061
|
+
type="button"
|
|
1062
|
+
class="layout-topbar-action"
|
|
1063
|
+
(click)="logout()"
|
|
1064
|
+
title="تسجيل الخروج"
|
|
1065
|
+
>
|
|
1066
|
+
<i class="pi pi-sign-out"></i>
|
|
1067
|
+
</button> -->
|
|
1068
|
+
</div>
|
|
1069
|
+
</header>
|
|
1032
1070
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "component", type: AppConfigurator, selector: "app-configurator" }, { kind: "component", type: LanguagesComponent, selector: "abp-languages" }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i3$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "directive", type: i4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: MenuModule }, { kind: "component", type: i5.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaLabel", "ariaLabelledBy", "id", "tabindex", "appendTo"], outputs: ["onShow", "onHide", "onBlur", "onFocus"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: VisibleDirective, selector: "[frameworkVisible]", inputs: ["frameworkVisible"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i1.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: ToInjectorPipe, name: "toInjector" }] });
|
|
1033
1071
|
}
|
|
1034
1072
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: NavItemsComponent, decorators: [{
|
|
@@ -1052,292 +1090,281 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1052
1090
|
ToInjectorPipe,
|
|
1053
1091
|
PopoverModule
|
|
1054
1092
|
],
|
|
1055
|
-
template: `
|
|
1056
|
-
<header class="flex items-center justify-between px-6 h-16 bg-white shadow sticky top-0 z-9">
|
|
1057
|
-
<!-- Left: Logo / Title -->
|
|
1058
|
-
<div class="flex items-center space-x-3 rtl:space-x-reverse">
|
|
1059
|
-
<img src="assets/logo.png" alt="Logo" class="h-8 w-8" />
|
|
1060
|
-
<span class="text-lg font-semibold text-gray-800">{{ '' | translate }}</span>
|
|
1061
|
-
</div>
|
|
1062
|
-
|
|
1063
|
-
<!-- Center: Nav Items -->
|
|
1064
|
-
<div class="flex items-center space-x-4 rtl:space-x-reverse">
|
|
1065
|
-
<ul class="flex space-x-4">
|
|
1066
|
-
@for (item of navItems.items$ | async; track item.id) {
|
|
1067
|
-
@if (!item.visible || item.visible(item)) {
|
|
1068
|
-
<ng-container *frameworkVisible="!item.visible || item.visible(item)">
|
|
1069
|
-
<li class="flex items-center">
|
|
1070
|
-
@if (item.component) {
|
|
1071
|
-
<ng-container
|
|
1072
|
-
[ngComponentOutlet]="item.component"
|
|
1073
|
-
[ngComponentOutletInjector]="item | toInjector"
|
|
1074
|
-
></ng-container>
|
|
1075
|
-
} @else {
|
|
1076
|
-
<button
|
|
1077
|
-
pButton
|
|
1078
|
-
type="button"
|
|
1079
|
-
class="p-button-text hover:bg-gray-100 focus:outline-none flex items-center"
|
|
1080
|
-
(click)="item.action?.()"
|
|
1081
|
-
>
|
|
1082
|
-
<span [innerHTML]="item.html"></span>
|
|
1083
|
-
</button>
|
|
1084
|
-
}
|
|
1085
|
-
</li>
|
|
1086
|
-
</ng-container>
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
</ul>
|
|
1090
|
-
</div>
|
|
1091
|
-
|
|
1092
|
-
<!-- Right: Actions -->
|
|
1093
|
-
<div class="flex items-center rtl:space-x-reverse">
|
|
1094
|
-
<!-- Configurator -->
|
|
1095
|
-
|
|
1096
|
-
<div>
|
|
1097
|
-
<!-- -->
|
|
1098
|
-
<button
|
|
1099
|
-
pButton
|
|
1100
|
-
type="button"
|
|
1101
|
-
icon="pi pi-palette"
|
|
1102
|
-
class="p-button-text"
|
|
1103
|
-
[title]="''"
|
|
1104
|
-
(click)="overlay.toggle($event)"
|
|
1105
|
-
>
|
|
1106
|
-
</button>
|
|
1107
|
-
|
|
1108
|
-
<p-popover #overlay >
|
|
1109
|
-
<app-configurator />
|
|
1110
|
-
</p-popover>
|
|
1111
|
-
</div>
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
<!-- Dark Mode Toggle -->
|
|
1115
|
-
<button
|
|
1116
|
-
pButton
|
|
1117
|
-
type="button"
|
|
1118
|
-
[icon]="layoutService.isDarkTheme() ?'pi pi-moon': 'pi pi-sun'"
|
|
1119
|
-
class="p-button-text"
|
|
1120
|
-
(click)="toggleDarkMode()">
|
|
1121
|
-
</button>
|
|
1122
|
-
|
|
1123
|
-
<!-- Language Switcher -->
|
|
1124
|
-
<abp-languages></abp-languages>
|
|
1125
|
-
|
|
1126
|
-
<!-- User Menu -->
|
|
1127
|
-
<div class="relative">
|
|
1128
|
-
<button
|
|
1129
|
-
class="p-link p-2"
|
|
1130
|
-
(click)="menu.toggle($event)"
|
|
1131
|
-
aria-label="User menu"
|
|
1132
|
-
>
|
|
1133
|
-
<p-avatar
|
|
1134
|
-
[label]="loading ? '' : userName"
|
|
1135
|
-
[icon]="loading ? 'pi pi-spinner' : ''"
|
|
1136
|
-
[class]="{'pi-spin': loading}"
|
|
1137
|
-
shape="circle"
|
|
1138
|
-
class="bg-blue-600 text-white cursor-pointer"
|
|
1139
|
-
[title]="(currentUser$ | async)?.name || ''"
|
|
1140
|
-
></p-avatar>
|
|
1141
|
-
</button>
|
|
1142
|
-
|
|
1143
|
-
<p-menu
|
|
1144
|
-
#menu
|
|
1145
|
-
[model]="userMenuItems"
|
|
1146
|
-
[popup]="true"
|
|
1147
|
-
[appendTo]="'body'"
|
|
1148
|
-
styleClass="w-64 sm:w-72 shadow-lg rounded-md"
|
|
1149
|
-
>
|
|
1150
|
-
<ng-template pTemplate="start">
|
|
1151
|
-
<div class="px-5 py-4 border-b border-gray-200 bg-gray-50 flex flex-col items-center text-center">
|
|
1152
|
-
<p-avatar
|
|
1153
|
-
[label]="userName"
|
|
1154
|
-
shape="circle"
|
|
1155
|
-
size="xlarge"
|
|
1156
|
-
styleClass="bg-blue-600 text-white mb-3 shadow-lg"
|
|
1157
|
-
[title]="(currentUser$ | async)?.name || ''"
|
|
1158
|
-
></p-avatar>
|
|
1159
|
-
<h5 class="text-xl font-semibold text-gray-800 leading-tight">
|
|
1160
|
-
{{ (currentUser$ | async)?.name || 'اسم المستخدم' }}
|
|
1161
|
-
</h5>
|
|
1162
|
-
<p class="text-sm text-gray-600 truncate max-w-full">
|
|
1163
|
-
{{ (currentUser$ | async)?.email || 'لا يوجد بريد إلكتروني' }}
|
|
1164
|
-
</p>
|
|
1165
|
-
@if ((selectedTenant$ | async); as tenant) {
|
|
1166
|
-
<span
|
|
1167
|
-
class="inline-block mt-2 px-3 py-1 text-xs rounded-full font-semibold"
|
|
1168
|
-
[ngClass]="{
|
|
1169
|
-
'bg-green-100 text-green-800': true
|
|
1170
|
-
}"
|
|
1171
|
-
>
|
|
1172
|
-
{{ tenant?.name || '_' }}
|
|
1173
|
-
</span>
|
|
1174
|
-
}
|
|
1175
|
-
</div>
|
|
1176
|
-
</ng-template>
|
|
1177
|
-
|
|
1178
|
-
<ng-template pTemplate="item" let-item>
|
|
1179
|
-
<!-- *frameworkVisible="!item.visible || item.visible(item)" -->
|
|
1180
|
-
<ng-container >
|
|
1181
|
-
<!-- *hasPermission="item.requiredPolicy" -->
|
|
1182
|
-
<a
|
|
1183
|
-
|
|
1184
|
-
class="p-menuitem-link flex items-center space-x-3 rtl:space-x-reverse px-5 py-2 hover:bg-gray-100 rounded-md"
|
|
1185
|
-
[ngClass]="item.styleClass || ''"
|
|
1186
|
-
(click)="item.command ? item.command() : null"
|
|
1187
|
-
[routerLink]="item.routerLink ? item.routerLink : null"
|
|
1188
|
-
tabindex="0"
|
|
1189
|
-
>
|
|
1190
|
-
@if (item.component) {
|
|
1191
|
-
<ng-container
|
|
1192
|
-
[ngComponentOutlet]="item.component"
|
|
1193
|
-
[ngComponentOutletInjector]="item | toInjector"
|
|
1194
|
-
></ng-container>
|
|
1195
|
-
} @else {
|
|
1196
|
-
<i [class]="item.icon + ' text-lg text-gray-600'"></i>
|
|
1197
|
-
<span class="text-gray-700">{{ item.label | translate }}</span>
|
|
1198
|
-
}
|
|
1199
|
-
</a>
|
|
1200
|
-
</ng-container>
|
|
1201
|
-
</ng-template>
|
|
1202
|
-
</p-menu>
|
|
1203
|
-
</div>
|
|
1204
|
-
|
|
1205
|
-
<!-- Logout Button (separate from menu) -->
|
|
1206
|
-
<!-- <button
|
|
1207
|
-
type="button"
|
|
1208
|
-
class="layout-topbar-action"
|
|
1209
|
-
(click)="logout()"
|
|
1210
|
-
title="تسجيل الخروج"
|
|
1211
|
-
>
|
|
1212
|
-
<i class="pi pi-sign-out"></i>
|
|
1213
|
-
</button> -->
|
|
1214
|
-
</div>
|
|
1215
|
-
</header>
|
|
1093
|
+
template: `
|
|
1094
|
+
<header class="flex items-center justify-between px-6 h-16 bg-white shadow sticky top-0 z-9">
|
|
1095
|
+
<!-- Left: Logo / Title -->
|
|
1096
|
+
<div class="flex items-center space-x-3 rtl:space-x-reverse">
|
|
1097
|
+
<img src="assets/logo.png" alt="Logo" class="h-8 w-8" />
|
|
1098
|
+
<span class="text-lg font-semibold text-gray-800">{{ '' | translate }}</span>
|
|
1099
|
+
</div>
|
|
1100
|
+
|
|
1101
|
+
<!-- Center: Nav Items -->
|
|
1102
|
+
<div class="flex items-center space-x-4 rtl:space-x-reverse">
|
|
1103
|
+
<ul class="flex space-x-4">
|
|
1104
|
+
@for (item of navItems.items$ | async; track item.id) {
|
|
1105
|
+
@if (!item.visible || item.visible(item)) {
|
|
1106
|
+
<ng-container *frameworkVisible="!item.visible || item.visible(item)">
|
|
1107
|
+
<li class="flex items-center">
|
|
1108
|
+
@if (item.component) {
|
|
1109
|
+
<ng-container
|
|
1110
|
+
[ngComponentOutlet]="item.component"
|
|
1111
|
+
[ngComponentOutletInjector]="item | toInjector"
|
|
1112
|
+
></ng-container>
|
|
1113
|
+
} @else {
|
|
1114
|
+
<button
|
|
1115
|
+
pButton
|
|
1116
|
+
type="button"
|
|
1117
|
+
class="p-button-text hover:bg-gray-100 focus:outline-none flex items-center"
|
|
1118
|
+
(click)="item.action?.()"
|
|
1119
|
+
>
|
|
1120
|
+
<span [innerHTML]="item.html"></span>
|
|
1121
|
+
</button>
|
|
1122
|
+
}
|
|
1123
|
+
</li>
|
|
1124
|
+
</ng-container>
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
</ul>
|
|
1128
|
+
</div>
|
|
1129
|
+
|
|
1130
|
+
<!-- Right: Actions -->
|
|
1131
|
+
<div class="flex items-center rtl:space-x-reverse">
|
|
1132
|
+
<!-- Configurator -->
|
|
1133
|
+
|
|
1134
|
+
<div>
|
|
1135
|
+
<!-- -->
|
|
1136
|
+
<button
|
|
1137
|
+
pButton
|
|
1138
|
+
type="button"
|
|
1139
|
+
icon="pi pi-palette"
|
|
1140
|
+
class="p-button-text"
|
|
1141
|
+
[title]="''"
|
|
1142
|
+
(click)="overlay.toggle($event)"
|
|
1143
|
+
>
|
|
1144
|
+
</button>
|
|
1145
|
+
|
|
1146
|
+
<p-popover #overlay >
|
|
1147
|
+
<app-configurator />
|
|
1148
|
+
</p-popover>
|
|
1149
|
+
</div>
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
<!-- Dark Mode Toggle -->
|
|
1153
|
+
<button
|
|
1154
|
+
pButton
|
|
1155
|
+
type="button"
|
|
1156
|
+
[icon]="layoutService.isDarkTheme() ?'pi pi-moon': 'pi pi-sun'"
|
|
1157
|
+
class="p-button-text"
|
|
1158
|
+
(click)="toggleDarkMode()">
|
|
1159
|
+
</button>
|
|
1160
|
+
|
|
1161
|
+
<!-- Language Switcher -->
|
|
1162
|
+
<abp-languages></abp-languages>
|
|
1163
|
+
|
|
1164
|
+
<!-- User Menu -->
|
|
1165
|
+
<div class="relative">
|
|
1166
|
+
<button
|
|
1167
|
+
class="p-link p-2"
|
|
1168
|
+
(click)="menu.toggle($event)"
|
|
1169
|
+
aria-label="User menu"
|
|
1170
|
+
>
|
|
1171
|
+
<p-avatar
|
|
1172
|
+
[label]="loading ? '' : userName"
|
|
1173
|
+
[icon]="loading ? 'pi pi-spinner' : ''"
|
|
1174
|
+
[class]="{'pi-spin': loading}"
|
|
1175
|
+
shape="circle"
|
|
1176
|
+
class="bg-blue-600 text-white cursor-pointer"
|
|
1177
|
+
[title]="(currentUser$ | async)?.name || ''"
|
|
1178
|
+
></p-avatar>
|
|
1179
|
+
</button>
|
|
1180
|
+
|
|
1181
|
+
<p-menu
|
|
1182
|
+
#menu
|
|
1183
|
+
[model]="userMenuItems"
|
|
1184
|
+
[popup]="true"
|
|
1185
|
+
[appendTo]="'body'"
|
|
1186
|
+
styleClass="w-64 sm:w-72 shadow-lg rounded-md"
|
|
1187
|
+
>
|
|
1188
|
+
<ng-template pTemplate="start">
|
|
1189
|
+
<div class="px-5 py-4 border-b border-gray-200 bg-gray-50 flex flex-col items-center text-center">
|
|
1190
|
+
<p-avatar
|
|
1191
|
+
[label]="userName"
|
|
1192
|
+
shape="circle"
|
|
1193
|
+
size="xlarge"
|
|
1194
|
+
styleClass="bg-blue-600 text-white mb-3 shadow-lg"
|
|
1195
|
+
[title]="(currentUser$ | async)?.name || ''"
|
|
1196
|
+
></p-avatar>
|
|
1197
|
+
<h5 class="text-xl font-semibold text-gray-800 leading-tight">
|
|
1198
|
+
{{ (currentUser$ | async)?.name || 'اسم المستخدم' }}
|
|
1199
|
+
</h5>
|
|
1200
|
+
<p class="text-sm text-gray-600 truncate max-w-full">
|
|
1201
|
+
{{ (currentUser$ | async)?.email || 'لا يوجد بريد إلكتروني' }}
|
|
1202
|
+
</p>
|
|
1203
|
+
@if ((selectedTenant$ | async); as tenant) {
|
|
1204
|
+
<span
|
|
1205
|
+
class="inline-block mt-2 px-3 py-1 text-xs rounded-full font-semibold"
|
|
1206
|
+
[ngClass]="{
|
|
1207
|
+
'bg-green-100 text-green-800': true
|
|
1208
|
+
}"
|
|
1209
|
+
>
|
|
1210
|
+
{{ tenant?.name || '_' }}
|
|
1211
|
+
</span>
|
|
1212
|
+
}
|
|
1213
|
+
</div>
|
|
1214
|
+
</ng-template>
|
|
1215
|
+
|
|
1216
|
+
<ng-template pTemplate="item" let-item>
|
|
1217
|
+
<!-- *frameworkVisible="!item.visible || item.visible(item)" -->
|
|
1218
|
+
<ng-container >
|
|
1219
|
+
<!-- *hasPermission="item.requiredPolicy" -->
|
|
1220
|
+
<a
|
|
1221
|
+
|
|
1222
|
+
class="p-menuitem-link flex items-center space-x-3 rtl:space-x-reverse px-5 py-2 hover:bg-gray-100 rounded-md"
|
|
1223
|
+
[ngClass]="item.styleClass || ''"
|
|
1224
|
+
(click)="item.command ? item.command() : null"
|
|
1225
|
+
[routerLink]="item.routerLink ? item.routerLink : null"
|
|
1226
|
+
tabindex="0"
|
|
1227
|
+
>
|
|
1228
|
+
@if (item.component) {
|
|
1229
|
+
<ng-container
|
|
1230
|
+
[ngComponentOutlet]="item.component"
|
|
1231
|
+
[ngComponentOutletInjector]="item | toInjector"
|
|
1232
|
+
></ng-container>
|
|
1233
|
+
} @else {
|
|
1234
|
+
<i [class]="item.icon + ' text-lg text-gray-600'"></i>
|
|
1235
|
+
<span class="text-gray-700">{{ item.label | translate }}</span>
|
|
1236
|
+
}
|
|
1237
|
+
</a>
|
|
1238
|
+
</ng-container>
|
|
1239
|
+
</ng-template>
|
|
1240
|
+
</p-menu>
|
|
1241
|
+
</div>
|
|
1242
|
+
|
|
1243
|
+
<!-- Logout Button (separate from menu) -->
|
|
1244
|
+
<!-- <button
|
|
1245
|
+
type="button"
|
|
1246
|
+
class="layout-topbar-action"
|
|
1247
|
+
(click)="logout()"
|
|
1248
|
+
title="تسجيل الخروج"
|
|
1249
|
+
>
|
|
1250
|
+
<i class="pi pi-sign-out"></i>
|
|
1251
|
+
</button> -->
|
|
1252
|
+
</div>
|
|
1253
|
+
</header>
|
|
1216
1254
|
`
|
|
1217
1255
|
}]
|
|
1218
1256
|
}], ctorParameters: () => [] });
|
|
1219
1257
|
|
|
1220
|
-
class
|
|
1221
|
-
subSidebarVisible = false;
|
|
1222
|
-
sidebarVisible = true;
|
|
1223
|
-
isMobile = false;
|
|
1258
|
+
class RoutesMenuService {
|
|
1224
1259
|
router = inject(Router);
|
|
1225
|
-
localization = inject(LocalizationService);
|
|
1226
|
-
layoutService = inject(LayoutService);
|
|
1227
1260
|
routesService = inject(RoutesService);
|
|
1228
|
-
|
|
1229
|
-
|
|
1261
|
+
layoutService = inject(LayoutService);
|
|
1262
|
+
sidebarVisible = true;
|
|
1263
|
+
subSidebarVisible = false;
|
|
1264
|
+
isMobile = false;
|
|
1265
|
+
showTreeSearch = false;
|
|
1266
|
+
searchText = '';
|
|
1230
1267
|
_menuItemsSubject = new BehaviorSubject([]);
|
|
1231
|
-
|
|
1268
|
+
expandedStateBeforeSearch = null;
|
|
1232
1269
|
menuItems$ = this._menuItemsSubject.asObservable();
|
|
1233
|
-
|
|
1234
|
-
// this.menuItems$ = this.routesService.visible$.pipe(
|
|
1235
|
-
// map(routes => this.buildItems(routes).map(item => ({ ...item, expanded: true })))
|
|
1236
|
-
// );
|
|
1237
|
-
this.routesService.visible$.pipe(map(routes => this.buildItems(routes).map(item => ({ ...item, expanded: true })))).subscribe(items => this._menuItemsSubject.next(items));
|
|
1238
|
-
}
|
|
1239
|
-
ngOnInit() {
|
|
1240
|
-
this.checkViewport();
|
|
1241
|
-
this.secondToLastLevel$ = this.menuItems$.pipe(map(items => {
|
|
1242
|
-
const result = [];
|
|
1243
|
-
for (const item of items) {
|
|
1244
|
-
if (item.items && item.items.length > 0) {
|
|
1245
|
-
// إضافة جميع الأبناء المباشرين (المستوى الثاني)
|
|
1246
|
-
result.push(...item.items);
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
return result;
|
|
1250
|
-
}));
|
|
1251
|
-
// this.secondToLastLevel$ = this.menuItems$.pipe(
|
|
1252
|
-
// map(items => this.getSecondToLastLevel(items))
|
|
1253
|
-
// );
|
|
1254
|
-
}
|
|
1255
|
-
getSecondToLastLevel(items) {
|
|
1270
|
+
secondToLastLevel$ = this.menuItems$.pipe(map((items) => {
|
|
1256
1271
|
const result = [];
|
|
1257
|
-
const
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
// Check if any child has its own children
|
|
1261
|
-
const hasGrandChildren = node.items.some(c => c.items && c.items.length > 0);
|
|
1262
|
-
if (!hasGrandChildren) {
|
|
1263
|
-
// Node is right before the last level
|
|
1264
|
-
result.push(node);
|
|
1265
|
-
}
|
|
1266
|
-
else {
|
|
1267
|
-
traverse(node.items);
|
|
1268
|
-
}
|
|
1269
|
-
}
|
|
1272
|
+
for (const item of items) {
|
|
1273
|
+
if (item.items?.length) {
|
|
1274
|
+
result.push(...item.items);
|
|
1270
1275
|
}
|
|
1271
|
-
}
|
|
1272
|
-
traverse(items);
|
|
1276
|
+
}
|
|
1273
1277
|
return result;
|
|
1278
|
+
}));
|
|
1279
|
+
constructor() {
|
|
1280
|
+
this.routesService.visible$
|
|
1281
|
+
.pipe(map((routes) => this.buildItems(routes)), takeUntilDestroyed())
|
|
1282
|
+
.subscribe((items) => this.setItems(items));
|
|
1274
1283
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
if (this.
|
|
1296
|
-
this.
|
|
1297
|
-
this.subSidebarVisible = false;
|
|
1284
|
+
get items() {
|
|
1285
|
+
return this._menuItemsSubject.value;
|
|
1286
|
+
}
|
|
1287
|
+
setItems(items) {
|
|
1288
|
+
this.setExpandedByLevel(items);
|
|
1289
|
+
this._menuItemsSubject.next(items);
|
|
1290
|
+
}
|
|
1291
|
+
refresh() {
|
|
1292
|
+
this._menuItemsSubject.next([...this.items]);
|
|
1293
|
+
}
|
|
1294
|
+
expandAll() {
|
|
1295
|
+
this.setExpandedRecursive(this.items, true);
|
|
1296
|
+
this.subSidebarVisible = true;
|
|
1297
|
+
this.refresh();
|
|
1298
|
+
}
|
|
1299
|
+
collapseAll() {
|
|
1300
|
+
this.setExpandedRecursive(this.items, false);
|
|
1301
|
+
this.refresh();
|
|
1302
|
+
}
|
|
1303
|
+
search(keyword) {
|
|
1304
|
+
if (!this.expandedStateBeforeSearch) {
|
|
1305
|
+
this.expandedStateBeforeSearch = this.captureExpandedState(this.items);
|
|
1298
1306
|
}
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
this.
|
|
1307
|
+
this.searchText = keyword;
|
|
1308
|
+
if (!this.searchText.trim()) {
|
|
1309
|
+
this.restoreExpandedStateBeforeSearch();
|
|
1310
|
+
this.refresh();
|
|
1311
|
+
return;
|
|
1302
1312
|
}
|
|
1313
|
+
this.expandMatchedParents(this.items, this.searchText);
|
|
1314
|
+
this.refresh();
|
|
1303
1315
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1316
|
+
clearSearch() {
|
|
1317
|
+
this.searchText = '';
|
|
1318
|
+
this.restoreExpandedStateBeforeSearch();
|
|
1319
|
+
this.refresh();
|
|
1320
|
+
}
|
|
1321
|
+
toggleSearch() {
|
|
1322
|
+
this.showTreeSearch = !this.showTreeSearch;
|
|
1323
|
+
if (!this.showTreeSearch) {
|
|
1324
|
+
this.clearSearch();
|
|
1311
1325
|
}
|
|
1312
1326
|
}
|
|
1327
|
+
isSearchMatch(item) {
|
|
1328
|
+
const term = this.searchText.trim().toLowerCase();
|
|
1329
|
+
if (!term)
|
|
1330
|
+
return false;
|
|
1331
|
+
const label = String(item.label ?? '').toLowerCase();
|
|
1332
|
+
const title = String(item.title ?? '').toLowerCase();
|
|
1333
|
+
return label.includes(term) || title.includes(term);
|
|
1334
|
+
}
|
|
1335
|
+
closeMenu() {
|
|
1336
|
+
this.subSidebarVisible = false;
|
|
1337
|
+
this.sidebarVisible = false;
|
|
1338
|
+
}
|
|
1313
1339
|
openMenu() {
|
|
1314
1340
|
this.sidebarVisible = true;
|
|
1315
1341
|
this.subSidebarVisible = true;
|
|
1316
1342
|
}
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
item.expanded = true; // expand parent
|
|
1325
|
-
return true;
|
|
1326
|
-
}
|
|
1327
|
-
}
|
|
1343
|
+
syncViewport() {
|
|
1344
|
+
this.isMobile = window.innerWidth < 1024;
|
|
1345
|
+
this.layoutService.smallScreen = this.isMobile;
|
|
1346
|
+
if (this.isMobile) {
|
|
1347
|
+
this.sidebarVisible = false;
|
|
1348
|
+
this.subSidebarVisible = false;
|
|
1349
|
+
return;
|
|
1328
1350
|
}
|
|
1329
|
-
|
|
1351
|
+
this.sidebarVisible = true;
|
|
1352
|
+
this.subSidebarVisible = true;
|
|
1353
|
+
}
|
|
1354
|
+
toggleSidebar() {
|
|
1355
|
+
if (this.isMobile) {
|
|
1356
|
+
this.sidebarVisible = !this.sidebarVisible;
|
|
1357
|
+
this.subSidebarVisible = this.sidebarVisible;
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
this.subSidebarVisible = !this.subSidebarVisible;
|
|
1330
1361
|
}
|
|
1331
|
-
|
|
1332
|
-
const items = this._menuItemsSubject.value;
|
|
1362
|
+
activateItem(target) {
|
|
1333
1363
|
const isExternal = target.isExternal ?? false;
|
|
1334
1364
|
if (!target.items?.length) {
|
|
1335
1365
|
if (isExternal && target.url) {
|
|
1336
1366
|
window.open(target.url, '_blank', 'noopener,noreferrer');
|
|
1337
|
-
|
|
1338
|
-
this.closeMenu();
|
|
1339
|
-
this.expandPath(items, target);
|
|
1340
|
-
this._menuItemsSubject.next([...items]);
|
|
1367
|
+
this.afterNavigate(target);
|
|
1341
1368
|
return;
|
|
1342
1369
|
}
|
|
1343
1370
|
if (target.routerLink) {
|
|
@@ -1346,50 +1373,93 @@ class RoutesComponent {
|
|
|
1346
1373
|
? target.routerLink[0]
|
|
1347
1374
|
: target.routerLink;
|
|
1348
1375
|
if (currentUrl !== targetUrl) {
|
|
1349
|
-
this.router.navigate(Array.isArray(target.routerLink)
|
|
1376
|
+
this.router.navigate(Array.isArray(target.routerLink)
|
|
1377
|
+
? target.routerLink
|
|
1378
|
+
: [target.routerLink]);
|
|
1350
1379
|
}
|
|
1351
|
-
|
|
1352
|
-
this.closeMenu();
|
|
1353
|
-
this.expandPath(items, target);
|
|
1354
|
-
this._menuItemsSubject.next([...items]);
|
|
1380
|
+
this.afterNavigate(target);
|
|
1355
1381
|
return;
|
|
1356
1382
|
}
|
|
1357
1383
|
}
|
|
1358
1384
|
target.expanded = !target.expanded;
|
|
1359
|
-
this.subSidebarVisible =
|
|
1360
|
-
this.
|
|
1385
|
+
this.subSidebarVisible = true;
|
|
1386
|
+
this.refresh();
|
|
1387
|
+
}
|
|
1388
|
+
closeAfterNavigate() {
|
|
1389
|
+
if (this.isMobile) {
|
|
1390
|
+
this.closeMenu();
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
getLinkProps(item) {
|
|
1394
|
+
const isExternal = item.isExternal ?? false;
|
|
1395
|
+
return {
|
|
1396
|
+
isExternal,
|
|
1397
|
+
href: isExternal ? (item.url ?? null) : null,
|
|
1398
|
+
routerLink: !isExternal ? (item.routerLink ?? null) : null,
|
|
1399
|
+
addRoute: item.addRoute ?? '',
|
|
1400
|
+
};
|
|
1361
1401
|
}
|
|
1362
|
-
|
|
1402
|
+
expandPath(target) {
|
|
1403
|
+
const found = this.expandPathRecursive(this.items, target);
|
|
1404
|
+
this.refresh();
|
|
1405
|
+
return found;
|
|
1406
|
+
}
|
|
1407
|
+
toggleItem(item) {
|
|
1363
1408
|
item.expanded = !item.expanded;
|
|
1409
|
+
this.refresh();
|
|
1364
1410
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1411
|
+
setExpandedByLevel(items, level = 1) {
|
|
1412
|
+
for (const item of items) {
|
|
1413
|
+
item.expanded = level === 1;
|
|
1414
|
+
if (item.items?.length) {
|
|
1415
|
+
this.setExpandedByLevel(item.items, level + 1);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
captureExpandedState(items) {
|
|
1420
|
+
const state = new WeakMap();
|
|
1421
|
+
const traverse = (nodes) => {
|
|
1422
|
+
for (const node of nodes) {
|
|
1423
|
+
state.set(node, node.expanded === true);
|
|
1424
|
+
if (node.items?.length) {
|
|
1425
|
+
traverse(node.items);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
traverse(items);
|
|
1430
|
+
return state;
|
|
1431
|
+
}
|
|
1432
|
+
restoreExpandedStateBeforeSearch() {
|
|
1433
|
+
if (!this.expandedStateBeforeSearch)
|
|
1434
|
+
return;
|
|
1435
|
+
const traverse = (nodes) => {
|
|
1436
|
+
for (const node of nodes) {
|
|
1437
|
+
node.expanded = this.expandedStateBeforeSearch?.get(node) ?? false;
|
|
1438
|
+
if (node.items?.length) {
|
|
1439
|
+
traverse(node.items);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
};
|
|
1443
|
+
traverse(this.items);
|
|
1444
|
+
this.expandedStateBeforeSearch = null;
|
|
1445
|
+
}
|
|
1446
|
+
afterNavigate(target) {
|
|
1377
1447
|
if (this.isMobile) {
|
|
1378
1448
|
this.closeMenu();
|
|
1379
1449
|
}
|
|
1450
|
+
this.expandPath(target);
|
|
1380
1451
|
}
|
|
1381
1452
|
buildItems(routes) {
|
|
1382
1453
|
return routes
|
|
1383
|
-
.filter(
|
|
1384
|
-
.map(
|
|
1454
|
+
.filter((route) => !route.requiredPolicy || this.hasPermission(route.requiredPolicy))
|
|
1455
|
+
.map((route) => this.createItem(route));
|
|
1385
1456
|
}
|
|
1386
1457
|
createItem(route) {
|
|
1387
1458
|
const item = {
|
|
1388
1459
|
label: route.name,
|
|
1389
1460
|
icon: route.iconClass,
|
|
1390
|
-
// routerLink: route.path ? [route.path] : undefined,
|
|
1391
1461
|
title: route.name,
|
|
1392
|
-
expanded: false
|
|
1462
|
+
expanded: false,
|
|
1393
1463
|
};
|
|
1394
1464
|
if (route.isExternal) {
|
|
1395
1465
|
item.url = route.path;
|
|
@@ -1403,43 +1473,109 @@ class RoutesComponent {
|
|
|
1403
1473
|
if (this.routesService.hasChildren(route.name)) {
|
|
1404
1474
|
item.items = this.buildItems(route.children ?? []);
|
|
1405
1475
|
}
|
|
1406
|
-
else {
|
|
1407
|
-
// TODO: check if grant permission
|
|
1408
|
-
// if(){
|
|
1409
|
-
// item['actionButtons']= [
|
|
1410
|
-
// {
|
|
1411
|
-
// icon: 'pi pi-plus',
|
|
1412
|
-
// tooltip: 'ADD',
|
|
1413
|
-
// click: (item:any, event:any) => {
|
|
1414
|
-
// this.router.navigate([route.path,'add']);
|
|
1415
|
-
// },
|
|
1416
|
-
// visible: (item:any) => true
|
|
1417
|
-
// }
|
|
1418
|
-
// ];
|
|
1419
|
-
// }
|
|
1420
|
-
}
|
|
1421
1476
|
return item;
|
|
1422
1477
|
}
|
|
1423
1478
|
hasPermission(policy) {
|
|
1424
|
-
// implement using permission service
|
|
1425
1479
|
return true;
|
|
1426
1480
|
}
|
|
1427
|
-
|
|
1428
|
-
const
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1481
|
+
setExpandedRecursive(items, expanded) {
|
|
1482
|
+
for (const item of items) {
|
|
1483
|
+
item.expanded = expanded;
|
|
1484
|
+
if (item.items?.length) {
|
|
1485
|
+
this.setExpandedRecursive(item.items, expanded);
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
expandMatchedParents(items, keyword) {
|
|
1490
|
+
const term = keyword.trim().toLowerCase();
|
|
1491
|
+
let hasMatch = false;
|
|
1492
|
+
for (const item of items) {
|
|
1493
|
+
const label = String(item.label ?? '').toLowerCase();
|
|
1494
|
+
const title = String(item.title ?? '').toLowerCase();
|
|
1495
|
+
const selfMatch = label.includes(term) || title.includes(term);
|
|
1496
|
+
const childMatch = item.items?.length
|
|
1497
|
+
? this.expandMatchedParents(item.items, keyword)
|
|
1498
|
+
: false;
|
|
1499
|
+
item.expanded = !!childMatch || !!selfMatch;
|
|
1500
|
+
if (selfMatch || childMatch) {
|
|
1501
|
+
hasMatch = true;
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
return hasMatch;
|
|
1505
|
+
}
|
|
1506
|
+
expandPathRecursive(items, target) {
|
|
1507
|
+
for (const item of items) {
|
|
1508
|
+
if (item === target)
|
|
1509
|
+
return true;
|
|
1510
|
+
if (item.items?.length) {
|
|
1511
|
+
const found = this.expandPathRecursive(item.items, target);
|
|
1512
|
+
if (found) {
|
|
1513
|
+
item.expanded = true;
|
|
1514
|
+
return true;
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
return false;
|
|
1519
|
+
}
|
|
1520
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoutesMenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1521
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoutesMenuService });
|
|
1522
|
+
}
|
|
1523
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoutesMenuService, decorators: [{
|
|
1524
|
+
type: Injectable
|
|
1525
|
+
}], ctorParameters: () => [] });
|
|
1526
|
+
|
|
1527
|
+
class RoutesSearchComponent {
|
|
1528
|
+
menu = inject(RoutesMenuService);
|
|
1529
|
+
closeMenu() {
|
|
1530
|
+
this.menu.closeMenu();
|
|
1531
|
+
}
|
|
1532
|
+
expandAll() {
|
|
1533
|
+
this.menu.expandAll();
|
|
1534
|
+
}
|
|
1535
|
+
collapseAll() {
|
|
1536
|
+
this.menu.collapseAll();
|
|
1537
|
+
}
|
|
1538
|
+
toggleSearch() {
|
|
1539
|
+
this.menu.toggleSearch();
|
|
1540
|
+
}
|
|
1541
|
+
onSearchTextChange(value) {
|
|
1542
|
+
this.menu.search(value);
|
|
1543
|
+
}
|
|
1544
|
+
clearSearch() {
|
|
1545
|
+
this.menu.clearSearch();
|
|
1546
|
+
}
|
|
1547
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoutesSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1548
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: RoutesSearchComponent, isStandalone: true, selector: "app-routes-search", ngImport: i0, template: "<div class=\"mb-4 space-y-3\">\r\n <div class=\"flex items-center justify-between gap-3\">\r\n <button\r\n type=\"button\"\r\n (click)=\"closeMenu()\"\r\n class=\"inline-flex h-9 items-center gap-1.5 rounded-full px-2 ps-1.5 pe-3 text-sm font-bold text-slate-500 transition hover:bg-primary-50 hover:text-primary-600 dark:text-slate-300 dark:hover:bg-primary-500/10 dark:hover:text-primary-300\"\r\n >\r\n <i class=\"pi pi-angle-right text-sm\"></i>\r\n <span>{{ 'back' | translate }}</span>\r\n </button>\r\n\r\n <div class=\"inline-flex items-center gap-1\">\r\n <button\r\n type=\"button\"\r\n class=\"inline-flex h-8 w-8 items-center justify-center rounded-xl border border-slate-300/25 bg-slate-50/85 text-slate-500 transition hover:-translate-y-px hover:border-primary-500/25 hover:bg-primary-50 hover:text-primary-600 dark:border-slate-400/15 dark:bg-gray-800/75 dark:text-slate-300 dark:hover:bg-primary-500/10 dark:hover:text-primary-300\"\r\n (click)=\"expandAll()\"\r\n pTooltip=\"\u0641\u062A\u062D \u0627\u0644\u0634\u062C\u0631\u0629 \u0643\u0627\u0645\u0644\u0629\"\r\n tooltipPosition=\"top\"\r\n >\r\n <i class=\"pi pi-plus text-xs\"></i>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"inline-flex h-8 w-8 items-center justify-center rounded-xl border border-slate-300/25 bg-slate-50/85 text-slate-500 transition hover:-translate-y-px hover:border-primary-500/25 hover:bg-primary-50 hover:text-primary-600 dark:border-slate-400/15 dark:bg-gray-800/75 dark:text-slate-300 dark:hover:bg-primary-500/10 dark:hover:text-primary-300\"\r\n (click)=\"collapseAll()\"\r\n pTooltip=\"\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0634\u062C\u0631\u0629 \u0643\u0627\u0645\u0644\u0629\"\r\n tooltipPosition=\"top\"\r\n >\r\n <i class=\"pi pi-minus text-xs\"></i>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"inline-flex h-8 w-8 items-center justify-center rounded-xl border transition hover:-translate-y-px\"\r\n [ngClass]=\"\r\n menu.showTreeSearch\r\n ? 'border-transparent bg-primary-600 text-white shadow-lg shadow-primary-500/20'\r\n : 'border-primary-500/20 bg-primary-500/10 text-primary-600 hover:bg-primary-50 dark:text-primary-300 dark:hover:bg-primary-500/10'\r\n \"\r\n (click)=\"toggleSearch()\"\r\n pTooltip=\"\u0628\u062D\u062B \u062F\u0627\u062E\u0644 \u0627\u0644\u0634\u0627\u0634\u0627\u062A\"\r\n tooltipPosition=\"top\"\r\n >\r\n <i class=\"pi pi-search text-xs\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n @if (menu.showTreeSearch) {\r\n <div\r\n class=\"animate-slideIn rounded-2xl border border-white/45 bg-white/60 p-2 shadow-lg shadow-slate-900/10 backdrop-blur-xl dark:border-white/10 dark:bg-gray-900/70\"\r\n >\r\n <div class=\"relative flex items-center\">\r\n <i\r\n class=\"pi pi-search pointer-events-none absolute right-3 text-sm text-primary-500 dark:text-primary-300\"\r\n ></i>\r\n\r\n <input\r\n type=\"text\"\r\n [ngModel]=\"menu.searchText\"\r\n (ngModelChange)=\"onSearchTextChange($event)\"\r\n placeholder=\"\u0628\u062D\u062B \u062F\u0627\u062E\u0644 \u0627\u0644\u0634\u0627\u0634\u0627\u062A...\"\r\n class=\"h-10 w-full rounded-2xl border border-slate-300/30 bg-slate-50/85 py-0 pl-9 pr-10 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-primary-500/50 focus:bg-white focus:ring-4 focus:ring-primary-500/10 dark:border-slate-400/20 dark:bg-gray-800/80 dark:text-gray-100 dark:placeholder:text-slate-500 dark:focus:bg-gray-900\"\r\n />\r\n\r\n @if (menu.searchText) {\r\n <button\r\n type=\"button\"\r\n class=\"absolute left-2 inline-flex h-7 w-7 items-center justify-center rounded-full text-slate-400 transition hover:bg-primary-50 hover:text-primary-600 dark:text-slate-300 dark:hover:bg-primary-500/10 dark:hover:text-primary-300\"\r\n (click)=\"clearSearch()\"\r\n >\r\n <i class=\"pi pi-times text-xs\"></i>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3$2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1549
|
+
}
|
|
1550
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoutesSearchComponent, decorators: [{
|
|
1551
|
+
type: Component,
|
|
1552
|
+
args: [{ selector: 'app-routes-search', standalone: true, imports: [CommonModule, FormsModule, TooltipModule, TranslatePipe], template: "<div class=\"mb-4 space-y-3\">\r\n <div class=\"flex items-center justify-between gap-3\">\r\n <button\r\n type=\"button\"\r\n (click)=\"closeMenu()\"\r\n class=\"inline-flex h-9 items-center gap-1.5 rounded-full px-2 ps-1.5 pe-3 text-sm font-bold text-slate-500 transition hover:bg-primary-50 hover:text-primary-600 dark:text-slate-300 dark:hover:bg-primary-500/10 dark:hover:text-primary-300\"\r\n >\r\n <i class=\"pi pi-angle-right text-sm\"></i>\r\n <span>{{ 'back' | translate }}</span>\r\n </button>\r\n\r\n <div class=\"inline-flex items-center gap-1\">\r\n <button\r\n type=\"button\"\r\n class=\"inline-flex h-8 w-8 items-center justify-center rounded-xl border border-slate-300/25 bg-slate-50/85 text-slate-500 transition hover:-translate-y-px hover:border-primary-500/25 hover:bg-primary-50 hover:text-primary-600 dark:border-slate-400/15 dark:bg-gray-800/75 dark:text-slate-300 dark:hover:bg-primary-500/10 dark:hover:text-primary-300\"\r\n (click)=\"expandAll()\"\r\n pTooltip=\"\u0641\u062A\u062D \u0627\u0644\u0634\u062C\u0631\u0629 \u0643\u0627\u0645\u0644\u0629\"\r\n tooltipPosition=\"top\"\r\n >\r\n <i class=\"pi pi-plus text-xs\"></i>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"inline-flex h-8 w-8 items-center justify-center rounded-xl border border-slate-300/25 bg-slate-50/85 text-slate-500 transition hover:-translate-y-px hover:border-primary-500/25 hover:bg-primary-50 hover:text-primary-600 dark:border-slate-400/15 dark:bg-gray-800/75 dark:text-slate-300 dark:hover:bg-primary-500/10 dark:hover:text-primary-300\"\r\n (click)=\"collapseAll()\"\r\n pTooltip=\"\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0634\u062C\u0631\u0629 \u0643\u0627\u0645\u0644\u0629\"\r\n tooltipPosition=\"top\"\r\n >\r\n <i class=\"pi pi-minus text-xs\"></i>\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n class=\"inline-flex h-8 w-8 items-center justify-center rounded-xl border transition hover:-translate-y-px\"\r\n [ngClass]=\"\r\n menu.showTreeSearch\r\n ? 'border-transparent bg-primary-600 text-white shadow-lg shadow-primary-500/20'\r\n : 'border-primary-500/20 bg-primary-500/10 text-primary-600 hover:bg-primary-50 dark:text-primary-300 dark:hover:bg-primary-500/10'\r\n \"\r\n (click)=\"toggleSearch()\"\r\n pTooltip=\"\u0628\u062D\u062B \u062F\u0627\u062E\u0644 \u0627\u0644\u0634\u0627\u0634\u0627\u062A\"\r\n tooltipPosition=\"top\"\r\n >\r\n <i class=\"pi pi-search text-xs\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n @if (menu.showTreeSearch) {\r\n <div\r\n class=\"animate-slideIn rounded-2xl border border-white/45 bg-white/60 p-2 shadow-lg shadow-slate-900/10 backdrop-blur-xl dark:border-white/10 dark:bg-gray-900/70\"\r\n >\r\n <div class=\"relative flex items-center\">\r\n <i\r\n class=\"pi pi-search pointer-events-none absolute right-3 text-sm text-primary-500 dark:text-primary-300\"\r\n ></i>\r\n\r\n <input\r\n type=\"text\"\r\n [ngModel]=\"menu.searchText\"\r\n (ngModelChange)=\"onSearchTextChange($event)\"\r\n placeholder=\"\u0628\u062D\u062B \u062F\u0627\u062E\u0644 \u0627\u0644\u0634\u0627\u0634\u0627\u062A...\"\r\n class=\"h-10 w-full rounded-2xl border border-slate-300/30 bg-slate-50/85 py-0 pl-9 pr-10 text-sm text-slate-700 outline-none transition placeholder:text-slate-400 focus:border-primary-500/50 focus:bg-white focus:ring-4 focus:ring-primary-500/10 dark:border-slate-400/20 dark:bg-gray-800/80 dark:text-gray-100 dark:placeholder:text-slate-500 dark:focus:bg-gray-900\"\r\n />\r\n\r\n @if (menu.searchText) {\r\n <button\r\n type=\"button\"\r\n class=\"absolute left-2 inline-flex h-7 w-7 items-center justify-center rounded-full text-slate-400 transition hover:bg-primary-50 hover:text-primary-600 dark:text-slate-300 dark:hover:bg-primary-500/10 dark:hover:text-primary-300\"\r\n (click)=\"clearSearch()\"\r\n >\r\n <i class=\"pi pi-times text-xs\"></i>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n" }]
|
|
1553
|
+
}] });
|
|
1554
|
+
|
|
1555
|
+
class RoutesComponent {
|
|
1556
|
+
menu = inject(RoutesMenuService);
|
|
1557
|
+
ngOnInit() {
|
|
1558
|
+
this.checkViewport();
|
|
1559
|
+
}
|
|
1560
|
+
onResize() {
|
|
1561
|
+
this.checkViewport();
|
|
1562
|
+
}
|
|
1563
|
+
checkViewport() {
|
|
1564
|
+
this.menu.syncViewport();
|
|
1435
1565
|
}
|
|
1436
1566
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoutesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1437
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: RoutesComponent, isStandalone: true, selector: "app-routes", host: { listeners: { "window:resize": "onResize()" } }, ngImport: i0, template: "<aside class=\"flex h-screen bg-white dark:bg-gray-900 transition-all duration-300\"\n [ngClass]=\"{ 'w-0 overflow-hidden': !sidebarVisible && isMobile }\">\n\n <!-- \uD83C\uDFA8 \u0627\u0644\u0634\u0631\u064A\u0637 \u0627\u0644\u062C\u0627\u0646\u0628\u064A \u0627\u0644\u0631\u0626\u064A\u0633\u064A -->\n <div\n class=\"flex flex-col justify-between pt-4 pb-2 w-16 border-l shadow-xl\n bg-gradient-to-b from-primary-500 via-primary-600 to-primary-700\n text-white rounded-r-3xl\">\n\n <!-- \uD83D\uDD1D \u0627\u0644\u0623\u0639\u0644\u0649 -->\n <div class=\"flex flex-col items-center gap-4\">\n <img src=\"/assets/logo.png\" alt=\"Logo\"\n class=\"w-9 h-9 mt-1 rounded-lg shadow-sm\"/>\n\n <!-- \u0632\u0631 \u0627\u0644\u0642\u0627\u0626\u0645\u0629 -->\n <!-- [pTooltip]=\"'TOGGLE_MENU' | translate\" -->\n <button (click)=\"toggleAll()\"\n tooltipPosition=\"right\"\n class=\"text-white hover:scale-110 transition-transform duration-200\">\n <i class=\"pi pi-bars text-lg\"></i>\n </button>\n\n <!-- \u0623\u064A\u0642\u0648\u0646\u0627\u062A -->\n @for (item of secondToLastLevel$ | async; track item) {\n <div class=\"relative flex flex-col items-center\">\n <!-- \u0627\u0644\u0623\u064A\u0642\u0648\u0646\u0629 -->\n <div (click)=\"onMainClick(item)\"\n [pTooltip]=\"item.label | translate\"\n tooltipPosition=\"right\"\n class=\"relative flex items-center justify-center w-10 h-10 rounded-xl cursor-pointer\n hover:bg-white/20 transition-all duration-200\"\n [ngClass]=\"{ 'bg-white/30 scale-105 shadow-inner': item.expanded }\">\n <i [class]=\"item.icon + ' text-xl'\"></i>\n </div>\n </div>\n }\n </div>\n\n <!-- \u2699\uFE0F \u0627\u0644\u0623\u0633\u0641\u0644 -->\n <div class=\"flex flex-col items-center pb-3 text-white/80\">\n <i class=\"pi pi-cog text-lg hover:text-white cursor-pointer transition\"></i>\n </div>\n </div>\n\n <!-- \uD83D\uDCCB \u0627\u0644\u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0641\u0631\u0639\u064A\u0629 -->\n @if (subSidebarVisible) {\n <div\n class=\"w-[290px] max-w-[290px] min-w-[260px] border-l border-gray-200 dark:border-gray-700 glass-bg animate-slideIn\n shadow-2xl rounded-l-3xl p-4 rtl:text-right overflow-y-auto overflow-x-hidden transition-all duration-300\"\n [ngClass]=\"{ 'absolute top-0 right-16 h-full z-40': isMobile }\">\n <!-- \u0632\u0631 \u0631\u062C\u0648\u0639 -->\n <button (click)=\"closeMenu()\"\n class=\"flex items-center gap-2 mb-4 text-gray-500 dark:text-gray-300 hover:text-primary-600 transition\">\n <i class=\"pi\" [ngClass]=\"isMobile ? 'pi-angle-right' : 'pi-angle-right'\"></i>\n <span>{{ 'back' | translate }}</span>\n </button>\n <!-- Recursive rendering -->\n @if (menuItems$ | async; as menuItems) {\n <ng-container *ngTemplateOutlet=\"renderMenu; context:{ $implicit: menuItems, level: 1 }\"></ng-container>\n}\n\n<ng-template #renderMenu let-items let-level=\"level\">\n @for (item of items; track item) {\n\n @if (!item.items?.length) {\n @let link = getLinkProps(item);\n <div class=\"mb-1\">\n @if (link.isExternal) {\n <a [href]=\"link.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n (click)=\"$event.stopPropagation()\"\n class=\"flex items-center gap-2 px-3 py-2 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\">\n <i [class]=\"item.icon + ' text-base'\"></i>\n <span class=\"min-w-0 break-words whitespace-normal\">{{ item.label | translate }}</span>\n <i class=\"pi pi-external-link text-[10px] opacity-50\"></i>\n </a>\n } @else {\n <div class=\"flex items-center gap-2\">\n <a [routerLink]=\"link.routerLink\"\n (click)=\"onNavigate()\"\n routerLinkActive=\"active-link\"\n class=\"flex-1 min-w-0 flex items-center gap-2 px-2 py-1 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\">\n <i [class]=\"item.icon + ' text-base'\"></i>\n <span class=\"min-w-0 break-words whitespace-normal\">\n {{ item.label | translate }}</span>\n </a>\n\n@if (link.addRoute) {\n <a\n [routerLink]=\"[link.addRoute]\"\n (click)=\"$event.stopPropagation(); onNavigate()\"\n class=\"shrink-0 inline-flex items-center justify-center w-7 h-7 rounded-full text-gray-400 hover:text-primary-500 hover:bg-primary-50 dark:text-gray-500 dark:hover:text-primary-400 dark:hover:bg-primary-900/20 transition-all duration-200\"\n [pTooltip]=\"'ADD' | translate\"\n tooltipPosition=\"top\">\n <i class=\"pi pi-plus text-xs\"></i>\n </a>\n}\n </div>\n }\n</div>\n}\n\n @if (item.items?.length) {\n <div class=\"mb-1\">\n\n <div\n (click)=\"onParentClick(item)\"\n [style.font-size.rem]=\"1.1 - (level * 0.05)\"\n [ngClass]=\"{\n 'font-bold': level === 1,\n 'font-semibold': level === 2,\n 'font-medium': level >= 3,\n 'bg-primary-50 text-primary-700 border-r-4 border-primary-500': item.expanded\n }\"\n class=\"flex justify-between items-center py-2 px-3 rounded-lg cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 transition text-gray-800 dark:text-gray-200\">\n\n <div class=\"flex items-center gap-2\">\n\n <i [class]=\"item.icon + ' text-base'\"></i>\n\n <span>\n {{ item.label | translate }}\n </span>\n\n </div>\n\n <i\n class=\"pi\"\n [ngClass]=\"item.expanded ? 'pi-chevron-down' : 'pi-chevron-left'\"\n style=\"font-size:0.6rem;\">\n </i>\n\n </div>\n\n @if (item.expanded) {\n <div class=\"mr-4 border-r border-gray-200 dark:border-gray-700 pr-2 mt-1\">\n\n <ng-container\n *ngTemplateOutlet=\"renderMenu; context:{ $implicit: item.items, level: level + 1 }\">\n </ng-container>\n\n </div>\n }\n\n </div>\n }\n\n }\n</ng-template>\n\n </div>\n}\n\n</aside>\n\n<!-- \uD83C\uDF1F \u0627\u0644\u0632\u0631 \u0627\u0644\u0639\u0627\u0626\u0645 \u0627\u0644\u062D\u062F\u064A\u062B -->\n@if (isMobile && !sidebarVisible) {\n <button\n class=\"floating-btn\"\n (click)=\"openMenu()\"\n pTooltip=\"{{ 'MENU.OPEN' | translate }}\"\n tooltipPosition=\"top\">\n <img src=\"/assets/logo.png\" alt=\"App Icon\" />\n </button>\n}\n", styles: ["@charset \"UTF-8\";@keyframes slideIn{0%{transform:translate(60px);opacity:0}to{transform:translate(0);opacity:1}}.animate-slideIn{animation:slideIn .35s cubic-bezier(.25,1,.5,1)}.glass-bg{background:#ffffffbf;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);border:1px solid rgba(255,255,255,.25)}@media(max-width:1024px){aside{position:fixed;top:0;right:0;height:100vh;z-index:50}}.floating-btn{position:fixed;bottom:1.25rem;right:1.25rem;z-index:60;width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,var(--p-primary-500),var(--p-primary-700));box-shadow:0 4px 18px #00000040;display:flex;align-items:center;justify-content:center;transition:all .3s ease}.floating-btn:hover{transform:scale(1.1) rotate(5deg)}.floating-btn img{width:28px;height:28px;border-radius:10px}.active-link{background-color:var(--p-primary-500)!important;color:#fff!important;font-weight:600;box-shadow:0 4px 6px -1px #0000001a;transform:translate(-3px)}.active-link i{color:#fff!important}.active-item-link{background:linear-gradient(to left,var(--p-primary-50),transparent);color:var(--p-primary-600)!important;position:relative;border-right:3px solid var(--p-primary-500);border-radius:0 12px 12px 0}.active-item-link i{color:var(--p-primary-500);filter:drop-shadow(0 0 5px rgba(var(--p-primary-500-rgb),.4))}.active-item-link span{font-weight:700}.animate-slideIn{animation:slideIn .3s ease-out}@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.glass-bg::-webkit-scrollbar{width:4px}.glass-bg::-webkit-scrollbar-thumb{background:#0000001a;border-radius:10px}.active-link{background-color:var(--p-primary-50)!important;color:var(--p-primary-700)!important;border-right:4px solid var(--p-primary-500)!important;border-radius:4px 12px 12px 4px!important}.active-link span{font-weight:800!important}.active-link i{color:var(--p-primary-600)!important;transform:scale(1.1)}aside{-webkit-font-smoothing:antialiased;letter-spacing:-.01em}.dark .active-link{background-color:rgba(var(--p-primary-500-rgb),.15)!important;color:var(--p-primary-300)!important}.submenu{animation:menuOpen .25s ease}@keyframes menuOpen{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}aside{box-shadow:0 10px 40px #00000026}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2$2.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3$2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1567
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: RoutesComponent, isStandalone: true, selector: "app-routes", host: { listeners: { "window:resize": "onResize()" } }, providers: [RoutesMenuService], ngImport: i0, template: "<aside\r\n class=\"flex h-screen bg-white dark:bg-gray-900 transition-all duration-300\"\r\n [ngClass]=\"{ 'w-0 overflow-hidden': !menu.sidebarVisible && menu.isMobile }\"\r\n>\r\n <div\r\n class=\"flex flex-col justify-between pt-4 pb-2 w-16 border-l shadow-xl bg-gradient-to-b from-primary-500 via-primary-600 to-primary-700 text-white rounded-r-3xl\"\r\n >\r\n <div class=\"flex flex-col items-center gap-4\">\r\n <img\r\n src=\"/assets/logo.png\"\r\n alt=\"Logo\"\r\n class=\"w-9 h-9 mt-1 rounded-lg shadow-sm\"\r\n />\r\n\r\n <button\r\n (click)=\"menu.toggleSidebar()\"\r\n tooltipPosition=\"right\"\r\n class=\"text-white hover:scale-110 transition-transform duration-200\"\r\n >\r\n <i class=\"pi pi-bars text-lg\"></i>\r\n </button>\r\n @for (item of menu.secondToLastLevel$ | async; track item) {\r\n <div class=\"relative flex flex-col items-center\">\r\n <div\r\n (click)=\"menu.activateItem(item)\"\r\n [pTooltip]=\"item.label | translate\"\r\n tooltipPosition=\"right\"\r\n class=\"relative flex items-center justify-center w-10 h-10 rounded-xl cursor-pointer hover:bg-white/20 transition-all duration-200\"\r\n [ngClass]=\"{ 'bg-white/30 scale-105 shadow-inner': item.expanded }\"\r\n >\r\n <i [class]=\"item.icon + ' text-xl'\"></i>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"flex flex-col items-center pb-3 text-white/80\">\r\n <i\r\n class=\"pi pi-cog text-lg hover:text-white cursor-pointer transition\"\r\n ></i>\r\n </div>\r\n </div>\r\n @if (menu.subSidebarVisible) {\r\n <div\r\n class=\"w-[290px] max-w-[290px] min-w-[260px] border-l border-gray-200 dark:border-gray-700 glass-bg animate-slideIn shadow-2xl rounded-l-3xl p-4 rtl:text-right overflow-y-auto overflow-x-hidden transition-all duration-300\"\r\n [ngClass]=\"{ 'absolute top-0 right-16 h-full z-40': menu.isMobile }\"\r\n >\r\n <app-routes-search></app-routes-search>\r\n\r\n <!-- Recursive rendering -->\r\n @if (menu.menuItems$ | async; as menuItems) {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n renderMenu;\r\n context: { $implicit: menuItems, level: 1 }\r\n \"\r\n ></ng-container>\r\n }\r\n\r\n <ng-template #renderMenu let-items let-level=\"level\">\r\n @for (item of items; track item) {\r\n @if (!item.items?.length) {\r\n @let link = menu.getLinkProps(item);\r\n <div class=\"mb-1\">\r\n @if (link.isExternal) {\r\n <a\r\n [href]=\"link.href\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"flex items-center gap-2 px-3 py-2 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\"\r\n >\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n <span class=\"min-w-0 break-words whitespace-normal\">{{\r\n item.label | translate\r\n }}</span>\r\n <i class=\"pi pi-external-link text-[10px] opacity-50\"></i>\r\n </a>\r\n } @else {\r\n <div class=\"flex items-center gap-2\">\r\n <a\r\n [routerLink]=\"link.routerLink\"\r\n (click)=\"menu.closeAfterNavigate()\"\r\n routerLinkActive=\"active-link\"\r\n [ngClass]=\"{ 'search-match': menu.isSearchMatch(item) }\"\r\n class=\"flex-1 min-w-0 flex items-center gap-2 px-2 py-1 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\"\r\n >\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n <span class=\"min-w-0 break-words whitespace-normal\">\r\n {{ item.label | translate }}</span\r\n >\r\n </a>\r\n\r\n @if (link.addRoute) {\r\n <a\r\n [routerLink]=\"[link.addRoute]\"\r\n (click)=\"\r\n $event.stopPropagation(); menu.closeAfterNavigate()\r\n \"\r\n class=\"shrink-0 inline-flex items-center justify-center w-7 h-7 rounded-full text-gray-400 hover:text-primary-500 hover:bg-primary-50 dark:text-gray-500 dark:hover:text-primary-400 dark:hover:bg-primary-900/20 transition-all duration-200\"\r\n [pTooltip]=\"'ADD' | translate\"\r\n tooltipPosition=\"top\"\r\n >\r\n <i class=\"pi pi-plus text-xs\"></i>\r\n </a>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (item.items?.length) {\r\n <div class=\"mb-1\">\r\n <div\r\n (click)=\"menu.toggleItem(item)\"\r\n [style.font-size.rem]=\"1.1 - level * 0.05\"\r\n [ngClass]=\"{\r\n 'font-bold': level === 1,\r\n 'font-semibold': level === 2,\r\n 'font-medium': level >= 3,\r\n 'bg-primary-50 text-primary-700 border-r-4 border-primary-500':\r\n item.expanded,\r\n 'search-match': menu.isSearchMatch(item),\r\n }\"\r\n class=\"flex justify-between items-center py-2 px-3 rounded-lg cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 transition text-gray-800 dark:text-gray-200\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n\r\n <span>\r\n {{ item.label | translate }}\r\n </span>\r\n </div>\r\n\r\n <i\r\n class=\"pi\"\r\n [ngClass]=\"\r\n item.expanded ? 'pi-chevron-down' : 'pi-chevron-left'\r\n \"\r\n style=\"font-size: 0.6rem\"\r\n >\r\n </i>\r\n </div>\r\n\r\n @if (item.expanded) {\r\n <div\r\n class=\"mr-4 border-r border-gray-200 dark:border-gray-700 pr-2 mt-1\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n renderMenu;\r\n context: { $implicit: item.items, level: level + 1 }\r\n \"\r\n >\r\n </ng-container>\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </ng-template>\r\n </div>\r\n }\r\n</aside>\r\n@if (menu.isMobile && !menu.sidebarVisible) {\r\n <button\r\n class=\"floating-btn\"\r\n (click)=\"menu.openMenu()\"\r\n pTooltip=\"{{ 'MENU.OPEN' | translate }}\"\r\n tooltipPosition=\"top\"\r\n >\r\n <img src=\"/assets/logo.png\" alt=\"App Icon\" />\r\n </button>\r\n}\r\n", styles: ["@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.animate-slideIn{animation:slideIn .3s ease-out}.glass-bg{background-color:#ffffffbf;--tw-backdrop-blur: blur(24px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.glass-bg:is(.dark *){background-color:#111827cc}.glass-bg{-webkit-backdrop-filter:blur(16px) saturate(180%);backdrop-filter:blur(16px) saturate(180%)}.glass-bg::-webkit-scrollbar{width:4px}.glass-bg::-webkit-scrollbar-thumb{border-radius:9999px;background-color:#94a3b84d}@media(max-width:1024px){aside{position:fixed;right:0;top:0;z-index:50;height:100vh}}.floating-btn{position:fixed;bottom:1.25rem;right:1.25rem;z-index:60;display:flex;height:60px;width:60px;align-items:center;justify-content:center;border-radius:9999px;--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s;background:linear-gradient(135deg,var(--p-primary-500),var(--p-primary-700))}.floating-btn:hover{transform:scale(1.1) rotate(5deg)}.floating-btn img{height:1.75rem;width:1.75rem;border-radius:.5rem}.active-link{border-radius:.5rem;--tw-bg-opacity: 1;background-color:color-mix(in srgb,var(--p-primary-50) calc(100% * var(--tw-bg-opacity, 1)),transparent);font-weight:600;--tw-text-opacity: 1;color:color-mix(in srgb,var(--p-primary-700) calc(100% * var(--tw-text-opacity, 1)),transparent);--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.active-link:is(.dark *){background-color:color-mix(in srgb,var(--p-primary-500) 15%,transparent);--tw-text-opacity: 1;color:color-mix(in srgb,var(--p-primary-300) calc(100% * var(--tw-text-opacity, 1)),transparent)}.active-link{border-right:4px solid var(--p-primary-500)}.active-link span{font-weight:800}.active-link i{--tw-scale-x: 1.1;--tw-scale-y: 1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-text-opacity: 1;color:color-mix(in srgb,var(--p-primary-600) calc(100% * var(--tw-text-opacity, 1)),transparent)}.active-link i:is(.dark *){--tw-text-opacity: 1;color:color-mix(in srgb,var(--p-primary-300) calc(100% * var(--tw-text-opacity, 1)),transparent)}.search-match{color:var(--p-primary-700)!important;background:linear-gradient(to left,rgba(var(--p-primary-500-rgb),.16),transparent)!important;border-right:3px solid var(--p-primary-500)!important;box-shadow:inset 0 0 0 1px rgba(var(--p-primary-500-rgb),.08)}.search-match span{font-weight:800}.search-match i{color:var(--p-primary-600)!important}.dark .search-match{color:var(--p-primary-300)!important;background:rgba(var(--p-primary-500-rgb),.18)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2$2.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3$2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "component", type: RoutesSearchComponent, selector: "app-routes-search" }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1438
1568
|
}
|
|
1439
1569
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RoutesComponent, decorators: [{
|
|
1440
1570
|
type: Component,
|
|
1441
|
-
args: [{ selector: 'app-routes', standalone: true, imports: [
|
|
1442
|
-
|
|
1571
|
+
args: [{ selector: 'app-routes', standalone: true, imports: [
|
|
1572
|
+
CommonModule,
|
|
1573
|
+
RouterModule,
|
|
1574
|
+
TooltipModule,
|
|
1575
|
+
TranslatePipe,
|
|
1576
|
+
RoutesSearchComponent,
|
|
1577
|
+
], providers: [RoutesMenuService], template: "<aside\r\n class=\"flex h-screen bg-white dark:bg-gray-900 transition-all duration-300\"\r\n [ngClass]=\"{ 'w-0 overflow-hidden': !menu.sidebarVisible && menu.isMobile }\"\r\n>\r\n <div\r\n class=\"flex flex-col justify-between pt-4 pb-2 w-16 border-l shadow-xl bg-gradient-to-b from-primary-500 via-primary-600 to-primary-700 text-white rounded-r-3xl\"\r\n >\r\n <div class=\"flex flex-col items-center gap-4\">\r\n <img\r\n src=\"/assets/logo.png\"\r\n alt=\"Logo\"\r\n class=\"w-9 h-9 mt-1 rounded-lg shadow-sm\"\r\n />\r\n\r\n <button\r\n (click)=\"menu.toggleSidebar()\"\r\n tooltipPosition=\"right\"\r\n class=\"text-white hover:scale-110 transition-transform duration-200\"\r\n >\r\n <i class=\"pi pi-bars text-lg\"></i>\r\n </button>\r\n @for (item of menu.secondToLastLevel$ | async; track item) {\r\n <div class=\"relative flex flex-col items-center\">\r\n <div\r\n (click)=\"menu.activateItem(item)\"\r\n [pTooltip]=\"item.label | translate\"\r\n tooltipPosition=\"right\"\r\n class=\"relative flex items-center justify-center w-10 h-10 rounded-xl cursor-pointer hover:bg-white/20 transition-all duration-200\"\r\n [ngClass]=\"{ 'bg-white/30 scale-105 shadow-inner': item.expanded }\"\r\n >\r\n <i [class]=\"item.icon + ' text-xl'\"></i>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"flex flex-col items-center pb-3 text-white/80\">\r\n <i\r\n class=\"pi pi-cog text-lg hover:text-white cursor-pointer transition\"\r\n ></i>\r\n </div>\r\n </div>\r\n @if (menu.subSidebarVisible) {\r\n <div\r\n class=\"w-[290px] max-w-[290px] min-w-[260px] border-l border-gray-200 dark:border-gray-700 glass-bg animate-slideIn shadow-2xl rounded-l-3xl p-4 rtl:text-right overflow-y-auto overflow-x-hidden transition-all duration-300\"\r\n [ngClass]=\"{ 'absolute top-0 right-16 h-full z-40': menu.isMobile }\"\r\n >\r\n <app-routes-search></app-routes-search>\r\n\r\n <!-- Recursive rendering -->\r\n @if (menu.menuItems$ | async; as menuItems) {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n renderMenu;\r\n context: { $implicit: menuItems, level: 1 }\r\n \"\r\n ></ng-container>\r\n }\r\n\r\n <ng-template #renderMenu let-items let-level=\"level\">\r\n @for (item of items; track item) {\r\n @if (!item.items?.length) {\r\n @let link = menu.getLinkProps(item);\r\n <div class=\"mb-1\">\r\n @if (link.isExternal) {\r\n <a\r\n [href]=\"link.href\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n (click)=\"$event.stopPropagation()\"\r\n class=\"flex items-center gap-2 px-3 py-2 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\"\r\n >\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n <span class=\"min-w-0 break-words whitespace-normal\">{{\r\n item.label | translate\r\n }}</span>\r\n <i class=\"pi pi-external-link text-[10px] opacity-50\"></i>\r\n </a>\r\n } @else {\r\n <div class=\"flex items-center gap-2\">\r\n <a\r\n [routerLink]=\"link.routerLink\"\r\n (click)=\"menu.closeAfterNavigate()\"\r\n routerLinkActive=\"active-link\"\r\n [ngClass]=\"{ 'search-match': menu.isSearchMatch(item) }\"\r\n class=\"flex-1 min-w-0 flex items-center gap-2 px-2 py-1 rounded-lg transition-all hover:bg-primary-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200\"\r\n >\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n <span class=\"min-w-0 break-words whitespace-normal\">\r\n {{ item.label | translate }}</span\r\n >\r\n </a>\r\n\r\n @if (link.addRoute) {\r\n <a\r\n [routerLink]=\"[link.addRoute]\"\r\n (click)=\"\r\n $event.stopPropagation(); menu.closeAfterNavigate()\r\n \"\r\n class=\"shrink-0 inline-flex items-center justify-center w-7 h-7 rounded-full text-gray-400 hover:text-primary-500 hover:bg-primary-50 dark:text-gray-500 dark:hover:text-primary-400 dark:hover:bg-primary-900/20 transition-all duration-200\"\r\n [pTooltip]=\"'ADD' | translate\"\r\n tooltipPosition=\"top\"\r\n >\r\n <i class=\"pi pi-plus text-xs\"></i>\r\n </a>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (item.items?.length) {\r\n <div class=\"mb-1\">\r\n <div\r\n (click)=\"menu.toggleItem(item)\"\r\n [style.font-size.rem]=\"1.1 - level * 0.05\"\r\n [ngClass]=\"{\r\n 'font-bold': level === 1,\r\n 'font-semibold': level === 2,\r\n 'font-medium': level >= 3,\r\n 'bg-primary-50 text-primary-700 border-r-4 border-primary-500':\r\n item.expanded,\r\n 'search-match': menu.isSearchMatch(item),\r\n }\"\r\n class=\"flex justify-between items-center py-2 px-3 rounded-lg cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 transition text-gray-800 dark:text-gray-200\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i [class]=\"item.icon + ' text-base'\"></i>\r\n\r\n <span>\r\n {{ item.label | translate }}\r\n </span>\r\n </div>\r\n\r\n <i\r\n class=\"pi\"\r\n [ngClass]=\"\r\n item.expanded ? 'pi-chevron-down' : 'pi-chevron-left'\r\n \"\r\n style=\"font-size: 0.6rem\"\r\n >\r\n </i>\r\n </div>\r\n\r\n @if (item.expanded) {\r\n <div\r\n class=\"mr-4 border-r border-gray-200 dark:border-gray-700 pr-2 mt-1\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n renderMenu;\r\n context: { $implicit: item.items, level: level + 1 }\r\n \"\r\n >\r\n </ng-container>\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </ng-template>\r\n </div>\r\n }\r\n</aside>\r\n@if (menu.isMobile && !menu.sidebarVisible) {\r\n <button\r\n class=\"floating-btn\"\r\n (click)=\"menu.openMenu()\"\r\n pTooltip=\"{{ 'MENU.OPEN' | translate }}\"\r\n tooltipPosition=\"top\"\r\n >\r\n <img src=\"/assets/logo.png\" alt=\"App Icon\" />\r\n </button>\r\n}\r\n", styles: ["@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.animate-slideIn{animation:slideIn .3s ease-out}.glass-bg{background-color:#ffffffbf;--tw-backdrop-blur: blur(24px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.glass-bg:is(.dark *){background-color:#111827cc}.glass-bg{-webkit-backdrop-filter:blur(16px) saturate(180%);backdrop-filter:blur(16px) saturate(180%)}.glass-bg::-webkit-scrollbar{width:4px}.glass-bg::-webkit-scrollbar-thumb{border-radius:9999px;background-color:#94a3b84d}@media(max-width:1024px){aside{position:fixed;right:0;top:0;z-index:50;height:100vh}}.floating-btn{position:fixed;bottom:1.25rem;right:1.25rem;z-index:60;display:flex;height:60px;width:60px;align-items:center;justify-content:center;border-radius:9999px;--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s;background:linear-gradient(135deg,var(--p-primary-500),var(--p-primary-700))}.floating-btn:hover{transform:scale(1.1) rotate(5deg)}.floating-btn img{height:1.75rem;width:1.75rem;border-radius:.5rem}.active-link{border-radius:.5rem;--tw-bg-opacity: 1;background-color:color-mix(in srgb,var(--p-primary-50) calc(100% * var(--tw-bg-opacity, 1)),transparent);font-weight:600;--tw-text-opacity: 1;color:color-mix(in srgb,var(--p-primary-700) calc(100% * var(--tw-text-opacity, 1)),transparent);--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.active-link:is(.dark *){background-color:color-mix(in srgb,var(--p-primary-500) 15%,transparent);--tw-text-opacity: 1;color:color-mix(in srgb,var(--p-primary-300) calc(100% * var(--tw-text-opacity, 1)),transparent)}.active-link{border-right:4px solid var(--p-primary-500)}.active-link span{font-weight:800}.active-link i{--tw-scale-x: 1.1;--tw-scale-y: 1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-text-opacity: 1;color:color-mix(in srgb,var(--p-primary-600) calc(100% * var(--tw-text-opacity, 1)),transparent)}.active-link i:is(.dark *){--tw-text-opacity: 1;color:color-mix(in srgb,var(--p-primary-300) calc(100% * var(--tw-text-opacity, 1)),transparent)}.search-match{color:var(--p-primary-700)!important;background:linear-gradient(to left,rgba(var(--p-primary-500-rgb),.16),transparent)!important;border-right:3px solid var(--p-primary-500)!important;box-shadow:inset 0 0 0 1px rgba(var(--p-primary-500-rgb),.08)}.search-match span{font-weight:800}.search-match i{color:var(--p-primary-600)!important}.dark .search-match{color:var(--p-primary-300)!important;background:rgba(var(--p-primary-500-rgb),.18)!important}\n"] }]
|
|
1578
|
+
}], propDecorators: { onResize: [{
|
|
1443
1579
|
type: HostListener,
|
|
1444
1580
|
args: ['window:resize']
|
|
1445
1581
|
}] } });
|
|
@@ -1447,11 +1583,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
1447
1583
|
class AuthWrapperComponent {
|
|
1448
1584
|
constructor() { }
|
|
1449
1585
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AuthWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1450
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: AuthWrapperComponent, isStandalone: true, selector: "abp-auth-wrapper", ngImport: i0, template: " <ng-content></ng-content>\n\n\n<!-- <div class=\"row\">\n <div class=\"mx-auto col col-md-5\">\n @if ((service.isMultiTenancyEnabled$ | async) && service.isTenantBoxVisible) {\n <abp-tenant-box\n *abpReplaceableTemplate=\"{ componentKey: service.tenantBoxKey }\"\n ></abp-tenant-box>\n }\n\n <div class=\"abp-account-container\">\n @if (service.enableLocalLogin$ | async) {\n <div class=\"card mt-3 shadow-sm rounded\">\n <div class=\"card-body p-5\">\n <ng-content></ng-content>\n </div>\n </div>\n } @else {\n <div class=\"alert alert-warning\">\n <strong>{{ 'AbpAccount::InvalidLoginRequest' | localize }}</strong>\n {{ 'AbpAccount::ThereAreNoLoginSchemesConfiguredForThisClient' | localize }}\n </div>\n }\n </div>\n </div>\n</div> -->\n" });
|
|
1586
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: AuthWrapperComponent, isStandalone: true, selector: "abp-auth-wrapper", ngImport: i0, template: " <ng-content></ng-content>\r\n\r\n\r\n<!-- <div class=\"row\">\r\n <div class=\"mx-auto col col-md-5\">\r\n @if ((service.isMultiTenancyEnabled$ | async) && service.isTenantBoxVisible) {\r\n <abp-tenant-box\r\n *abpReplaceableTemplate=\"{ componentKey: service.tenantBoxKey }\"\r\n ></abp-tenant-box>\r\n }\r\n\r\n <div class=\"abp-account-container\">\r\n @if (service.enableLocalLogin$ | async) {\r\n <div class=\"card mt-3 shadow-sm rounded\">\r\n <div class=\"card-body p-5\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"alert alert-warning\">\r\n <strong>{{ 'AbpAccount::InvalidLoginRequest' | localize }}</strong>\r\n {{ 'AbpAccount::ThereAreNoLoginSchemesConfiguredForThisClient' | localize }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</div> -->\r\n" });
|
|
1451
1587
|
}
|
|
1452
1588
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AuthWrapperComponent, decorators: [{
|
|
1453
1589
|
type: Component,
|
|
1454
|
-
args: [{ standalone: true, imports: [], selector: 'abp-auth-wrapper', template: " <ng-content></ng-content>\n\n\n<!-- <div class=\"row\">\n <div class=\"mx-auto col col-md-5\">\n @if ((service.isMultiTenancyEnabled$ | async) && service.isTenantBoxVisible) {\n <abp-tenant-box\n *abpReplaceableTemplate=\"{ componentKey: service.tenantBoxKey }\"\n ></abp-tenant-box>\n }\n\n <div class=\"abp-account-container\">\n @if (service.enableLocalLogin$ | async) {\n <div class=\"card mt-3 shadow-sm rounded\">\n <div class=\"card-body p-5\">\n <ng-content></ng-content>\n </div>\n </div>\n } @else {\n <div class=\"alert alert-warning\">\n <strong>{{ 'AbpAccount::InvalidLoginRequest' | localize }}</strong>\n {{ 'AbpAccount::ThereAreNoLoginSchemesConfiguredForThisClient' | localize }}\n </div>\n }\n </div>\n </div>\n</div> -->\n" }]
|
|
1590
|
+
args: [{ standalone: true, imports: [], selector: 'abp-auth-wrapper', template: " <ng-content></ng-content>\r\n\r\n\r\n<!-- <div class=\"row\">\r\n <div class=\"mx-auto col col-md-5\">\r\n @if ((service.isMultiTenancyEnabled$ | async) && service.isTenantBoxVisible) {\r\n <abp-tenant-box\r\n *abpReplaceableTemplate=\"{ componentKey: service.tenantBoxKey }\"\r\n ></abp-tenant-box>\r\n }\r\n\r\n <div class=\"abp-account-container\">\r\n @if (service.enableLocalLogin$ | async) {\r\n <div class=\"card mt-3 shadow-sm rounded\">\r\n <div class=\"card-body p-5\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"alert alert-warning\">\r\n <strong>{{ 'AbpAccount::InvalidLoginRequest' | localize }}</strong>\r\n {{ 'AbpAccount::ThereAreNoLoginSchemesConfiguredForThisClient' | localize }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n</div> -->\r\n" }]
|
|
1455
1591
|
}], ctorParameters: () => [] });
|
|
1456
1592
|
|
|
1457
1593
|
class AccountLayoutComponent {
|
|
@@ -1466,11 +1602,11 @@ class AccountLayoutComponent {
|
|
|
1466
1602
|
// this.service.subscribeWindowSize();
|
|
1467
1603
|
}
|
|
1468
1604
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AccountLayoutComponent, deps: [{ token: LayoutService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1469
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: AccountLayoutComponent, isStandalone: true, selector: "abp-layout-account", providers: [LayoutService, SubscriptionService], ngImport: i0, template: " <abp-auth-wrapper\n *abpReplaceableTemplate=\"{\n componentKey: authWrapperKey\n }\"\n >\n <router-outlet #outlet=\"outlet\"></router-outlet>\n </abp-auth-wrapper>\n", dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: AuthWrapperComponent, selector: "abp-auth-wrapper" }, { kind: "directive", type: ReplaceableTemplateDirective, selector: "[abpReplaceableTemplate]", inputs: ["abpReplaceableTemplate"] }] });
|
|
1605
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: AccountLayoutComponent, isStandalone: true, selector: "abp-layout-account", providers: [LayoutService, SubscriptionService], ngImport: i0, template: " <abp-auth-wrapper\r\n *abpReplaceableTemplate=\"{\r\n componentKey: authWrapperKey\r\n }\"\r\n >\r\n <router-outlet #outlet=\"outlet\"></router-outlet>\r\n </abp-auth-wrapper>\r\n", dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: AuthWrapperComponent, selector: "abp-auth-wrapper" }, { kind: "directive", type: ReplaceableTemplateDirective, selector: "[abpReplaceableTemplate]", inputs: ["abpReplaceableTemplate"] }] });
|
|
1470
1606
|
}
|
|
1471
1607
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AccountLayoutComponent, decorators: [{
|
|
1472
1608
|
type: Component,
|
|
1473
|
-
args: [{ standalone: true, imports: [RoutesComponent, NavItemsComponent, RouterOutlet, AuthWrapperComponent, ReplaceableTemplateDirective], selector: 'abp-layout-account', providers: [LayoutService, SubscriptionService], template: " <abp-auth-wrapper\n *abpReplaceableTemplate=\"{\n componentKey: authWrapperKey\n }\"\n >\n <router-outlet #outlet=\"outlet\"></router-outlet>\n </abp-auth-wrapper>\n" }]
|
|
1609
|
+
args: [{ standalone: true, imports: [RoutesComponent, NavItemsComponent, RouterOutlet, AuthWrapperComponent, ReplaceableTemplateDirective], selector: 'abp-layout-account', providers: [LayoutService, SubscriptionService], template: " <abp-auth-wrapper\r\n *abpReplaceableTemplate=\"{\r\n componentKey: authWrapperKey\r\n }\"\r\n >\r\n <router-outlet #outlet=\"outlet\"></router-outlet>\r\n </abp-auth-wrapper>\r\n" }]
|
|
1474
1610
|
}], ctorParameters: () => [{ type: LayoutService }] });
|
|
1475
1611
|
|
|
1476
1612
|
class ApplicationLayoutComponent {
|
|
@@ -1646,11 +1782,11 @@ class ApplicationLayoutComponent {
|
|
|
1646
1782
|
}
|
|
1647
1783
|
}
|
|
1648
1784
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ApplicationLayoutComponent, deps: [{ token: LayoutService }, { token: i0.Renderer2 }, { token: i2$2.Router }, { token: i0.NgZone }, { token: i3$3.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1649
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: ApplicationLayoutComponent, isStandalone: true, selector: "abp-layout-application", providers: [LayoutService, SubscriptionService], ngImport: i0, template: "\n\n<div class=\"flex h-screen overflow-hidden\">\n\n <!-- Sidebar stays fixed -->\n\n <app-routes\n *abpReplaceableTemplate=\"{\n componentKey: service.routesComponentKey,\n inputs: { smallScreen: { value: service.smallScreen } }\n }\"\n class=\"mb-2 md:mb-0\"\n ></app-routes>\n\n <!-- Main content scrolls -->\n <main class=\"flex-1 flex flex-col overflow-hidden\">\n\n <!-- Optional Topbar -->\n <!-- @if (showTopbar) { -->\n\n <app-nav-items\n *abpReplaceableTemplate=\"{\n componentKey: service.navItemsComponentKey\n }\"\n ></app-nav-items>\n\n <!-- p-6 space-y-6 -->\n <div class=\"flex-1 overflow-y-auto\">\n <router-outlet #outlet=\"outlet\"></router-outlet>\n </div>\n\n <!-- <app-footer></app-footer> -->\n\n </main>\n\n </div>\n\n", dependencies: [{ kind: "component", type: RoutesComponent, selector: "app-routes" }, { kind: "component", type: NavItemsComponent, selector: "app-nav-items" }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: ReplaceableTemplateDirective, selector: "[abpReplaceableTemplate]", inputs: ["abpReplaceableTemplate"] }], animations: [ /* slideFromBottom, */ /* appModuleAnimation() */] });
|
|
1785
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: ApplicationLayoutComponent, isStandalone: true, selector: "abp-layout-application", providers: [LayoutService, SubscriptionService], ngImport: i0, template: "\r\n\r\n<div class=\"flex h-screen overflow-hidden\">\r\n\r\n <!-- Sidebar stays fixed -->\r\n\r\n <app-routes\r\n *abpReplaceableTemplate=\"{\r\n componentKey: service.routesComponentKey,\r\n inputs: { smallScreen: { value: service.smallScreen } }\r\n }\"\r\n class=\"mb-2 md:mb-0\"\r\n ></app-routes>\r\n\r\n <!-- Main content scrolls -->\r\n <main class=\"flex-1 flex flex-col overflow-hidden\">\r\n\r\n <!-- Optional Topbar -->\r\n <!-- @if (showTopbar) { -->\r\n\r\n <app-nav-items\r\n *abpReplaceableTemplate=\"{\r\n componentKey: service.navItemsComponentKey\r\n }\"\r\n ></app-nav-items>\r\n\r\n <!-- p-6 space-y-6 -->\r\n <div class=\"flex-1 overflow-y-auto\">\r\n <router-outlet #outlet=\"outlet\"></router-outlet>\r\n </div>\r\n\r\n <!-- <app-footer></app-footer> -->\r\n\r\n </main>\r\n\r\n </div>\r\n\r\n", dependencies: [{ kind: "component", type: RoutesComponent, selector: "app-routes" }, { kind: "component", type: NavItemsComponent, selector: "app-nav-items" }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: ReplaceableTemplateDirective, selector: "[abpReplaceableTemplate]", inputs: ["abpReplaceableTemplate"] }], animations: [ /* slideFromBottom, */ /* appModuleAnimation() */] });
|
|
1650
1786
|
}
|
|
1651
1787
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ApplicationLayoutComponent, decorators: [{
|
|
1652
1788
|
type: Component,
|
|
1653
|
-
args: [{ standalone: true, imports: [RoutesComponent, NavItemsComponent, RouterOutlet, ReplaceableTemplateDirective], selector: 'abp-layout-application', animations: [ /* slideFromBottom, */ /* appModuleAnimation() */], providers: [LayoutService, SubscriptionService], template: "\n\n<div class=\"flex h-screen overflow-hidden\">\n\n <!-- Sidebar stays fixed -->\n\n <app-routes\n *abpReplaceableTemplate=\"{\n componentKey: service.routesComponentKey,\n inputs: { smallScreen: { value: service.smallScreen } }\n }\"\n class=\"mb-2 md:mb-0\"\n ></app-routes>\n\n <!-- Main content scrolls -->\n <main class=\"flex-1 flex flex-col overflow-hidden\">\n\n <!-- Optional Topbar -->\n <!-- @if (showTopbar) { -->\n\n <app-nav-items\n *abpReplaceableTemplate=\"{\n componentKey: service.navItemsComponentKey\n }\"\n ></app-nav-items>\n\n <!-- p-6 space-y-6 -->\n <div class=\"flex-1 overflow-y-auto\">\n <router-outlet #outlet=\"outlet\"></router-outlet>\n </div>\n\n <!-- <app-footer></app-footer> -->\n\n </main>\n\n </div>\n\n" }]
|
|
1789
|
+
args: [{ standalone: true, imports: [RoutesComponent, NavItemsComponent, RouterOutlet, ReplaceableTemplateDirective], selector: 'abp-layout-application', animations: [ /* slideFromBottom, */ /* appModuleAnimation() */], providers: [LayoutService, SubscriptionService], template: "\r\n\r\n<div class=\"flex h-screen overflow-hidden\">\r\n\r\n <!-- Sidebar stays fixed -->\r\n\r\n <app-routes\r\n *abpReplaceableTemplate=\"{\r\n componentKey: service.routesComponentKey,\r\n inputs: { smallScreen: { value: service.smallScreen } }\r\n }\"\r\n class=\"mb-2 md:mb-0\"\r\n ></app-routes>\r\n\r\n <!-- Main content scrolls -->\r\n <main class=\"flex-1 flex flex-col overflow-hidden\">\r\n\r\n <!-- Optional Topbar -->\r\n <!-- @if (showTopbar) { -->\r\n\r\n <app-nav-items\r\n *abpReplaceableTemplate=\"{\r\n componentKey: service.navItemsComponentKey\r\n }\"\r\n ></app-nav-items>\r\n\r\n <!-- p-6 space-y-6 -->\r\n <div class=\"flex-1 overflow-y-auto\">\r\n <router-outlet #outlet=\"outlet\"></router-outlet>\r\n </div>\r\n\r\n <!-- <app-footer></app-footer> -->\r\n\r\n </main>\r\n\r\n </div>\r\n\r\n" }]
|
|
1654
1790
|
}], ctorParameters: () => [{ type: LayoutService }, { type: i0.Renderer2 }, { type: i2$2.Router }, { type: i0.NgZone }, { type: i3$3.LocalizationService }] });
|
|
1655
1791
|
|
|
1656
1792
|
class EmptyLayoutComponent {
|