ngx-dev-toolbar 3.0.3 → 3.1.0
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.
- package/README.md +3 -3
- package/components/icons/edit-icon.component.d.ts +6 -0
- package/components/icons/icon.models.d.ts +1 -1
- package/components/step-view/step-view.component.d.ts +14 -0
- package/components/step-view/step-view.directive.d.ts +9 -0
- package/fesm2022/ngx-dev-toolbar.mjs +1213 -211
- package/fesm2022/ngx-dev-toolbar.mjs.map +1 -1
- package/index.d.ts +8 -62
- package/package.json +1 -1
- package/tools/presets-tool/presets-internal.service.d.ts +13 -1
- package/tools/presets-tool/presets-tool.component.d.ts +48 -11
- package/tools/presets-tool/presets.models.d.ts +12 -0
- package/tools/presets-tool/presets.service.d.ts +21 -2
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, signal, computed, Injectable, inject, ChangeDetectionStrategy, Component, input, model, ElementRef, output, viewChild, contentChild, effect, DestroyRef, ViewEncapsulation, EnvironmentInjector, createComponent } from '@angular/core';
|
|
2
|
+
import { InjectionToken, signal, computed, Injectable, inject, ChangeDetectionStrategy, Component, input, model, ElementRef, output, viewChild, contentChild, effect, DestroyRef, ViewEncapsulation, EnvironmentInjector, createComponent, TemplateRef, Directive, contentChildren } from '@angular/core';
|
|
3
3
|
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
4
|
import { BehaviorSubject, combineLatest, map, firstValueFrom, fromEvent } from 'rxjs';
|
|
5
5
|
import { trigger, state, transition, style, animate } from '@angular/animations';
|
|
6
|
-
import { CommonModule, DOCUMENT } from '@angular/common';
|
|
6
|
+
import { CommonModule, DOCUMENT, NgTemplateOutlet } from '@angular/common';
|
|
7
7
|
import { filter, throttleTime } from 'rxjs/operators';
|
|
8
8
|
import * as i1 from '@angular/forms';
|
|
9
9
|
import { FormsModule } from '@angular/forms';
|
|
@@ -1615,6 +1615,55 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
|
|
|
1615
1615
|
}]
|
|
1616
1616
|
}] });
|
|
1617
1617
|
|
|
1618
|
+
class EditIconComponent {
|
|
1619
|
+
constructor() {
|
|
1620
|
+
this.fill = input('#FFFF');
|
|
1621
|
+
}
|
|
1622
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: EditIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1623
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.7", type: EditIconComponent, isStandalone: true, selector: "ngt-edit-icon", inputs: { fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
1624
|
+
<svg
|
|
1625
|
+
[attr.fill]="fill()"
|
|
1626
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1627
|
+
width="24"
|
|
1628
|
+
height="24"
|
|
1629
|
+
viewBox="0 0 256 256"
|
|
1630
|
+
>
|
|
1631
|
+
<path
|
|
1632
|
+
d="M221.66,90.34,192,120,136,64l29.66-29.66a8,8,0,0,1,11.31,0L221.66,79A8,8,0,0,1,221.66,90.34Z"
|
|
1633
|
+
opacity="0.2"
|
|
1634
|
+
></path>
|
|
1635
|
+
<path
|
|
1636
|
+
d="M227.31,73.37,182.63,28.68a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H92.69A15.86,15.86,0,0,0,104,219.31L227.31,96a16,16,0,0,0,0-22.63ZM92.69,208H48V163.31l88-88L180.69,120ZM192,108.68,147.31,64l24-24L216,84.68Z"
|
|
1637
|
+
></path>
|
|
1638
|
+
</svg>
|
|
1639
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1640
|
+
}
|
|
1641
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: EditIconComponent, decorators: [{
|
|
1642
|
+
type: Component,
|
|
1643
|
+
args: [{
|
|
1644
|
+
selector: 'ngt-edit-icon',
|
|
1645
|
+
standalone: true,
|
|
1646
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1647
|
+
template: `
|
|
1648
|
+
<svg
|
|
1649
|
+
[attr.fill]="fill()"
|
|
1650
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1651
|
+
width="24"
|
|
1652
|
+
height="24"
|
|
1653
|
+
viewBox="0 0 256 256"
|
|
1654
|
+
>
|
|
1655
|
+
<path
|
|
1656
|
+
d="M221.66,90.34,192,120,136,64l29.66-29.66a8,8,0,0,1,11.31,0L221.66,79A8,8,0,0,1,221.66,90.34Z"
|
|
1657
|
+
opacity="0.2"
|
|
1658
|
+
></path>
|
|
1659
|
+
<path
|
|
1660
|
+
d="M227.31,73.37,182.63,28.68a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H92.69A15.86,15.86,0,0,0,104,219.31L227.31,96a16,16,0,0,0,0-22.63ZM92.69,208H48V163.31l88-88L180.69,120ZM192,108.68,147.31,64l24-24L216,84.68Z"
|
|
1661
|
+
></path>
|
|
1662
|
+
</svg>
|
|
1663
|
+
`,
|
|
1664
|
+
}]
|
|
1665
|
+
}] });
|
|
1666
|
+
|
|
1618
1667
|
class ExportIconComponent {
|
|
1619
1668
|
constructor() {
|
|
1620
1669
|
this.fill = input('#FFFF');
|
|
@@ -2604,6 +2653,8 @@ class ToolbarIconComponent {
|
|
|
2604
2653
|
<ngt-database-icon [fill]="fill()" />
|
|
2605
2654
|
} @case ('docs') {
|
|
2606
2655
|
<ngt-docs-icon [fill]="fill()" />
|
|
2656
|
+
} @case ('edit') {
|
|
2657
|
+
<ngt-edit-icon [fill]="fill()" />
|
|
2607
2658
|
} @case ('export') {
|
|
2608
2659
|
<ngt-export-icon [fill]="fill()" />
|
|
2609
2660
|
} @case ('filter') {
|
|
@@ -2649,7 +2700,7 @@ class ToolbarIconComponent {
|
|
|
2649
2700
|
} @case ('trash') {
|
|
2650
2701
|
<ngt-trash-icon [fill]="fill()" />
|
|
2651
2702
|
} }
|
|
2652
|
-
`, isInline: true, dependencies: [{ kind: "component", type: AngularIconComponent, selector: "ngt-angular-icon" }, { kind: "component", type: BoltIconComponent, selector: "ngt-bolt-icon", inputs: ["fill"] }, { kind: "component", type: BugIconComponent, selector: "ngt-bug-icon", inputs: ["fill"] }, { kind: "component", type: CodeIconComponent, selector: "ngt-code-icon", inputs: ["fill"] }, { kind: "component", type: DatabaseIconComponent, selector: "ngt-database-icon", inputs: ["fill"] }, { kind: "component", type: DocsIconComponent, selector: "ngt-docs-icon", inputs: ["fill"] }, { kind: "component", type: DiscordIconComponent, selector: "ngt-discord-icon", inputs: ["fill"] }, { kind: "component", type: ExportIconComponent, selector: "ngt-export-icon", inputs: ["fill"] }, { kind: "component", type: FilterIconComponent, selector: "ngt-filter-icon", inputs: ["fill"] }, { kind: "component", type: GaugeIconComponent, selector: "ngt-gauge-icon", inputs: ["fill"] }, { kind: "component", type: GearIconComponent, selector: "ngt-gear-icon", inputs: ["fill"] }, { kind: "component", type: GitBranchIconComponent, selector: "ngt-git-branch-icon", inputs: ["fill"] }, { kind: "component", type: ImportIconComponent, selector: "ngt-import-icon", inputs: ["fill"] }, { kind: "component", type: LayoutIconComponent, selector: "ngt-layout-icon", inputs: ["fill"] }, { kind: "component", type: LightbulbIconComponent, selector: "ngt-lightbulb-icon", inputs: ["fill"] }, { kind: "component", type: LightingIconComponent, selector: "ngt-lighting-icon", inputs: ["fill"] }, { kind: "component", type: LockIconComponent, selector: "ngt-lock-icon", inputs: ["fill"] }, { kind: "component", type: NetworkIconComponent, selector: "ngt-network-icon", inputs: ["fill"] }, { kind: "component", type: PuzzleIconComponent, selector: "ngt-puzzle-icon", inputs: ["fill"] }, { kind: "component", type: RefreshIconComponent, selector: "ngt-refresh-icon", inputs: ["fill"] }, { kind: "component", type: StarIconComponent, selector: "ngt-star-icon", inputs: ["fill"] }, { kind: "component", type: TerminalIconComponent, selector: "ngt-terminal-icon", inputs: ["fill"] }, { kind: "component", type: ToggleLeftIconComponent, selector: "ngt-toggle-left-icon", inputs: ["fill"] }, { kind: "component", type: UsersIconComponent, selector: "ngt-users-icon", inputs: ["fill"] }, { kind: "component", type: SunIconComponent, selector: "ngt-sun-icon", inputs: ["fill"] }, { kind: "component", type: MoonIconComponent, selector: "ngt-moon-icon", inputs: ["fill"] }, { kind: "component", type: TranslateIconComponent, selector: "ngt-translate-icon", inputs: ["fill"] }, { kind: "component", type: TrashIconComponent, selector: "ngt-trash-icon", inputs: ["fill"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2703
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AngularIconComponent, selector: "ngt-angular-icon" }, { kind: "component", type: BoltIconComponent, selector: "ngt-bolt-icon", inputs: ["fill"] }, { kind: "component", type: BugIconComponent, selector: "ngt-bug-icon", inputs: ["fill"] }, { kind: "component", type: CodeIconComponent, selector: "ngt-code-icon", inputs: ["fill"] }, { kind: "component", type: DatabaseIconComponent, selector: "ngt-database-icon", inputs: ["fill"] }, { kind: "component", type: DocsIconComponent, selector: "ngt-docs-icon", inputs: ["fill"] }, { kind: "component", type: DiscordIconComponent, selector: "ngt-discord-icon", inputs: ["fill"] }, { kind: "component", type: EditIconComponent, selector: "ngt-edit-icon", inputs: ["fill"] }, { kind: "component", type: ExportIconComponent, selector: "ngt-export-icon", inputs: ["fill"] }, { kind: "component", type: FilterIconComponent, selector: "ngt-filter-icon", inputs: ["fill"] }, { kind: "component", type: GaugeIconComponent, selector: "ngt-gauge-icon", inputs: ["fill"] }, { kind: "component", type: GearIconComponent, selector: "ngt-gear-icon", inputs: ["fill"] }, { kind: "component", type: GitBranchIconComponent, selector: "ngt-git-branch-icon", inputs: ["fill"] }, { kind: "component", type: ImportIconComponent, selector: "ngt-import-icon", inputs: ["fill"] }, { kind: "component", type: LayoutIconComponent, selector: "ngt-layout-icon", inputs: ["fill"] }, { kind: "component", type: LightbulbIconComponent, selector: "ngt-lightbulb-icon", inputs: ["fill"] }, { kind: "component", type: LightingIconComponent, selector: "ngt-lighting-icon", inputs: ["fill"] }, { kind: "component", type: LockIconComponent, selector: "ngt-lock-icon", inputs: ["fill"] }, { kind: "component", type: NetworkIconComponent, selector: "ngt-network-icon", inputs: ["fill"] }, { kind: "component", type: PuzzleIconComponent, selector: "ngt-puzzle-icon", inputs: ["fill"] }, { kind: "component", type: RefreshIconComponent, selector: "ngt-refresh-icon", inputs: ["fill"] }, { kind: "component", type: StarIconComponent, selector: "ngt-star-icon", inputs: ["fill"] }, { kind: "component", type: TerminalIconComponent, selector: "ngt-terminal-icon", inputs: ["fill"] }, { kind: "component", type: ToggleLeftIconComponent, selector: "ngt-toggle-left-icon", inputs: ["fill"] }, { kind: "component", type: UsersIconComponent, selector: "ngt-users-icon", inputs: ["fill"] }, { kind: "component", type: SunIconComponent, selector: "ngt-sun-icon", inputs: ["fill"] }, { kind: "component", type: MoonIconComponent, selector: "ngt-moon-icon", inputs: ["fill"] }, { kind: "component", type: TranslateIconComponent, selector: "ngt-translate-icon", inputs: ["fill"] }, { kind: "component", type: TrashIconComponent, selector: "ngt-trash-icon", inputs: ["fill"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2653
2704
|
}
|
|
2654
2705
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarIconComponent, decorators: [{
|
|
2655
2706
|
type: Component,
|
|
@@ -2664,6 +2715,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
|
|
|
2664
2715
|
DatabaseIconComponent,
|
|
2665
2716
|
DocsIconComponent,
|
|
2666
2717
|
DiscordIconComponent,
|
|
2718
|
+
EditIconComponent,
|
|
2667
2719
|
ExportIconComponent,
|
|
2668
2720
|
FilterIconComponent,
|
|
2669
2721
|
GaugeIconComponent,
|
|
@@ -2700,6 +2752,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
|
|
|
2700
2752
|
<ngt-database-icon [fill]="fill()" />
|
|
2701
2753
|
} @case ('docs') {
|
|
2702
2754
|
<ngt-docs-icon [fill]="fill()" />
|
|
2755
|
+
} @case ('edit') {
|
|
2756
|
+
<ngt-edit-icon [fill]="fill()" />
|
|
2703
2757
|
} @case ('export') {
|
|
2704
2758
|
<ngt-export-icon [fill]="fill()" />
|
|
2705
2759
|
} @case ('filter') {
|
|
@@ -4849,6 +4903,52 @@ class ToolbarInternalPresetsService {
|
|
|
4849
4903
|
getPresetById(presetId) {
|
|
4850
4904
|
return this.presetsSubject.value.find((p) => p.id === presetId);
|
|
4851
4905
|
}
|
|
4906
|
+
/**
|
|
4907
|
+
* Toggle favorite status for a preset
|
|
4908
|
+
*/
|
|
4909
|
+
toggleFavorite(presetId) {
|
|
4910
|
+
const presets = this.presetsSubject.value.map((p) => p.id === presetId ? { ...p, isFavorite: !p.isFavorite } : p);
|
|
4911
|
+
this.presetsSubject.next(presets);
|
|
4912
|
+
this.storageService.set(this.STORAGE_KEY, presets);
|
|
4913
|
+
}
|
|
4914
|
+
/**
|
|
4915
|
+
* Apply a preset with partial options (only selected categories)
|
|
4916
|
+
*/
|
|
4917
|
+
async partialApplyPreset(presetId, options) {
|
|
4918
|
+
const preset = this.presetsSubject.value.find((p) => p.id === presetId);
|
|
4919
|
+
if (!preset)
|
|
4920
|
+
return;
|
|
4921
|
+
if (options.applyFeatureFlags) {
|
|
4922
|
+
this.featureFlagsService.applyPresetFlags(preset.config.featureFlags);
|
|
4923
|
+
}
|
|
4924
|
+
if (options.applyLanguage) {
|
|
4925
|
+
await this.languageService.applyPresetLanguage(preset.config.language);
|
|
4926
|
+
}
|
|
4927
|
+
if (options.applyPermissions) {
|
|
4928
|
+
this.permissionsService.applyPresetPermissions(preset.config.permissions);
|
|
4929
|
+
}
|
|
4930
|
+
if (options.applyAppFeatures) {
|
|
4931
|
+
this.appFeaturesService.applyForcedState(preset.config.appFeatures);
|
|
4932
|
+
}
|
|
4933
|
+
}
|
|
4934
|
+
/**
|
|
4935
|
+
* Update only the metadata (name, description) of a preset without changing config
|
|
4936
|
+
*/
|
|
4937
|
+
updatePresetMetadata(presetId, name, description) {
|
|
4938
|
+
const presets = this.presetsSubject.value.map((preset) => {
|
|
4939
|
+
if (preset.id === presetId) {
|
|
4940
|
+
return {
|
|
4941
|
+
...preset,
|
|
4942
|
+
name,
|
|
4943
|
+
description,
|
|
4944
|
+
updatedAt: new Date().toISOString(),
|
|
4945
|
+
};
|
|
4946
|
+
}
|
|
4947
|
+
return preset;
|
|
4948
|
+
});
|
|
4949
|
+
this.presetsSubject.next(presets);
|
|
4950
|
+
this.storageService.set(this.STORAGE_KEY, presets);
|
|
4951
|
+
}
|
|
4852
4952
|
/**
|
|
4853
4953
|
* Capture current configuration from all tools
|
|
4854
4954
|
*/
|
|
@@ -4927,27 +5027,80 @@ class ToolbarPresetsToolComponent {
|
|
|
4927
5027
|
this.appFeaturesService = inject(ToolbarInternalAppFeaturesService);
|
|
4928
5028
|
this.languageService = inject(ToolbarInternalLanguageService);
|
|
4929
5029
|
this.state = inject(ToolbarStateService);
|
|
4930
|
-
//
|
|
5030
|
+
// View state signals
|
|
4931
5031
|
this.viewMode = signal('list');
|
|
4932
5032
|
this.searchQuery = signal('');
|
|
5033
|
+
// Create form signals
|
|
4933
5034
|
this.presetName = signal('');
|
|
4934
5035
|
this.presetDescription = signal('');
|
|
4935
5036
|
this.includeFeatureFlags = signal(true);
|
|
4936
5037
|
this.includePermissions = signal(true);
|
|
4937
5038
|
this.includeAppFeatures = signal(true);
|
|
4938
5039
|
this.includeLanguage = signal(true);
|
|
4939
|
-
// Track selected individual items
|
|
4940
5040
|
this.selectedFlagIds = signal(new Set());
|
|
4941
5041
|
this.selectedPermissionIds = signal(new Set());
|
|
4942
5042
|
this.selectedFeatureIds = signal(new Set());
|
|
5043
|
+
// Edit mode signals
|
|
5044
|
+
this.editingPresetId = signal(null);
|
|
5045
|
+
this.editName = signal('');
|
|
5046
|
+
this.editDescription = signal('');
|
|
5047
|
+
// Import mode signals
|
|
5048
|
+
this.importJson = signal('');
|
|
5049
|
+
this.importError = signal(null);
|
|
5050
|
+
this.isDragOver = signal(false);
|
|
5051
|
+
// Apply mode signals
|
|
5052
|
+
this.applyingPresetId = signal(null);
|
|
5053
|
+
this.applyFeatureFlags = signal(true);
|
|
5054
|
+
this.applyPermissions = signal(true);
|
|
5055
|
+
this.applyAppFeatures = signal(true);
|
|
5056
|
+
this.applyLanguage = signal(true);
|
|
5057
|
+
// Delete confirmation signals
|
|
5058
|
+
this.deletePresetId = signal(null);
|
|
5059
|
+
// Toast signals
|
|
5060
|
+
this.toastMessage = signal(null);
|
|
5061
|
+
this.toastType = signal('success');
|
|
5062
|
+
// Validation signals
|
|
5063
|
+
this.nameError = signal(null);
|
|
5064
|
+
// Auto-dismiss toast effect
|
|
5065
|
+
this.toastTimeout = null;
|
|
5066
|
+
// Computed values
|
|
4943
5067
|
this.presets = this.presetsService.presets;
|
|
4944
5068
|
this.filteredPresets = computed(() => {
|
|
4945
5069
|
const query = this.searchQuery().toLowerCase();
|
|
4946
5070
|
return this.presets().filter((preset) => preset.name.toLowerCase().includes(query) ||
|
|
4947
5071
|
preset.description?.toLowerCase().includes(query));
|
|
4948
5072
|
});
|
|
5073
|
+
this.sortedPresets = computed(() => {
|
|
5074
|
+
const presets = this.filteredPresets();
|
|
5075
|
+
return [...presets].sort((a, b) => {
|
|
5076
|
+
if (a.isFavorite && !b.isFavorite)
|
|
5077
|
+
return -1;
|
|
5078
|
+
if (!a.isFavorite && b.isFavorite)
|
|
5079
|
+
return 1;
|
|
5080
|
+
return 0;
|
|
5081
|
+
});
|
|
5082
|
+
});
|
|
4949
5083
|
this.hasNoPresets = computed(() => this.presets().length === 0);
|
|
4950
5084
|
this.hasNoFilteredPresets = computed(() => this.filteredPresets().length === 0);
|
|
5085
|
+
this.editingPreset = computed(() => {
|
|
5086
|
+
const id = this.editingPresetId();
|
|
5087
|
+
if (!id)
|
|
5088
|
+
return null;
|
|
5089
|
+
return this.presets().find((p) => p.id === id) || null;
|
|
5090
|
+
});
|
|
5091
|
+
this.applyingPreset = computed(() => {
|
|
5092
|
+
const id = this.applyingPresetId();
|
|
5093
|
+
if (!id)
|
|
5094
|
+
return null;
|
|
5095
|
+
return this.presets().find((p) => p.id === id) || null;
|
|
5096
|
+
});
|
|
5097
|
+
this.deletePresetName = computed(() => {
|
|
5098
|
+
const id = this.deletePresetId();
|
|
5099
|
+
if (!id)
|
|
5100
|
+
return '';
|
|
5101
|
+
const preset = this.presets().find((p) => p.id === id);
|
|
5102
|
+
return preset?.name || '';
|
|
5103
|
+
});
|
|
4951
5104
|
// Tool availability (based on config)
|
|
4952
5105
|
this.isFeatureFlagsEnabled = computed(() => this.state.config().showFeatureFlagsTool ?? true);
|
|
4953
5106
|
this.isPermissionsEnabled = computed(() => this.state.config().showPermissionsTool ?? true);
|
|
@@ -4972,15 +5125,38 @@ class ToolbarPresetsToolComponent {
|
|
|
4972
5125
|
id: 'ngt-presets',
|
|
4973
5126
|
isBeta: true,
|
|
4974
5127
|
};
|
|
5128
|
+
effect(() => {
|
|
5129
|
+
const message = this.toastMessage();
|
|
5130
|
+
if (message) {
|
|
5131
|
+
if (this.toastTimeout) {
|
|
5132
|
+
clearTimeout(this.toastTimeout);
|
|
5133
|
+
}
|
|
5134
|
+
this.toastTimeout = setTimeout(() => {
|
|
5135
|
+
this.toastMessage.set(null);
|
|
5136
|
+
}, 3000);
|
|
5137
|
+
}
|
|
5138
|
+
});
|
|
4975
5139
|
}
|
|
4976
|
-
//
|
|
5140
|
+
// Toast helper
|
|
5141
|
+
showToast(message, type = 'success') {
|
|
5142
|
+
this.toastMessage.set(message);
|
|
5143
|
+
this.toastType.set(type);
|
|
5144
|
+
}
|
|
5145
|
+
// View mode switching
|
|
4977
5146
|
onSearchChange(query) {
|
|
4978
5147
|
this.searchQuery.set(query);
|
|
4979
5148
|
}
|
|
5149
|
+
onSwitchToListMode() {
|
|
5150
|
+
this.viewMode.set('list');
|
|
5151
|
+
this.nameError.set(null);
|
|
5152
|
+
this.importError.set(null);
|
|
5153
|
+
this.deletePresetId.set(null);
|
|
5154
|
+
}
|
|
4980
5155
|
onSwitchToCreateMode() {
|
|
4981
5156
|
this.viewMode.set('create');
|
|
4982
5157
|
this.presetName.set('');
|
|
4983
5158
|
this.presetDescription.set('');
|
|
5159
|
+
this.nameError.set(null);
|
|
4984
5160
|
// Reset checkboxes - only enable categories that have forced items
|
|
4985
5161
|
this.includeFeatureFlags.set(this.getCurrentFlagsCount() > 0);
|
|
4986
5162
|
this.includePermissions.set(this.getCurrentPermissionsCount() > 0);
|
|
@@ -4992,14 +5168,33 @@ class ToolbarPresetsToolComponent {
|
|
|
4992
5168
|
this.selectedPermissionIds.set(new Set(this.forcedPermissions().map((p) => p.id)));
|
|
4993
5169
|
this.selectedFeatureIds.set(new Set(this.forcedAppFeatures().map((f) => f.id)));
|
|
4994
5170
|
}
|
|
4995
|
-
|
|
4996
|
-
this.viewMode.set('
|
|
5171
|
+
onSwitchToImportMode() {
|
|
5172
|
+
this.viewMode.set('import');
|
|
5173
|
+
this.importJson.set('');
|
|
5174
|
+
this.importError.set(null);
|
|
5175
|
+
this.isDragOver.set(false);
|
|
5176
|
+
}
|
|
5177
|
+
// Create preset
|
|
5178
|
+
onPresetNameChange(value) {
|
|
5179
|
+
this.presetName.set(value);
|
|
5180
|
+
if (value.trim()) {
|
|
5181
|
+
this.nameError.set(null);
|
|
5182
|
+
}
|
|
4997
5183
|
}
|
|
4998
5184
|
onSavePreset(event) {
|
|
4999
5185
|
event.preventDefault();
|
|
5000
|
-
|
|
5186
|
+
const name = this.presetName().trim();
|
|
5187
|
+
if (!name) {
|
|
5188
|
+
this.nameError.set('Name is required');
|
|
5189
|
+
return;
|
|
5190
|
+
}
|
|
5191
|
+
// Check for duplicate names
|
|
5192
|
+
const existingPreset = this.presets().find((p) => p.name.toLowerCase() === name.toLowerCase());
|
|
5193
|
+
if (existingPreset) {
|
|
5194
|
+
this.nameError.set('A preset with this name already exists');
|
|
5001
5195
|
return;
|
|
5002
|
-
|
|
5196
|
+
}
|
|
5197
|
+
this.presetsService.saveCurrentAsPreset(name, this.presetDescription(), {
|
|
5003
5198
|
includeFeatureFlags: this.includeFeatureFlags(),
|
|
5004
5199
|
includePermissions: this.includePermissions(),
|
|
5005
5200
|
includeAppFeatures: this.includeAppFeatures(),
|
|
@@ -5008,14 +5203,153 @@ class ToolbarPresetsToolComponent {
|
|
|
5008
5203
|
selectedPermissionIds: Array.from(this.selectedPermissionIds()),
|
|
5009
5204
|
selectedFeatureIds: Array.from(this.selectedFeatureIds()),
|
|
5010
5205
|
});
|
|
5206
|
+
this.showToast('Preset created successfully');
|
|
5011
5207
|
this.onSwitchToListMode();
|
|
5012
5208
|
}
|
|
5013
|
-
|
|
5014
|
-
|
|
5209
|
+
// Edit preset
|
|
5210
|
+
onStartEdit(presetId) {
|
|
5211
|
+
const preset = this.presets().find((p) => p.id === presetId);
|
|
5212
|
+
if (!preset)
|
|
5213
|
+
return;
|
|
5214
|
+
this.editingPresetId.set(presetId);
|
|
5215
|
+
this.editName.set(preset.name);
|
|
5216
|
+
this.editDescription.set(preset.description || '');
|
|
5217
|
+
this.nameError.set(null);
|
|
5218
|
+
this.viewMode.set('edit');
|
|
5219
|
+
}
|
|
5220
|
+
onEditNameChange(value) {
|
|
5221
|
+
this.editName.set(value);
|
|
5222
|
+
if (value.trim()) {
|
|
5223
|
+
this.nameError.set(null);
|
|
5224
|
+
}
|
|
5225
|
+
}
|
|
5226
|
+
onSaveEdit(event) {
|
|
5227
|
+
event.preventDefault();
|
|
5228
|
+
const name = this.editName().trim();
|
|
5229
|
+
const presetId = this.editingPresetId();
|
|
5230
|
+
if (!name) {
|
|
5231
|
+
this.nameError.set('Name is required');
|
|
5232
|
+
return;
|
|
5233
|
+
}
|
|
5234
|
+
if (!presetId)
|
|
5235
|
+
return;
|
|
5236
|
+
// Check for duplicate names (excluding current preset)
|
|
5237
|
+
const existingPreset = this.presets().find((p) => p.id !== presetId && p.name.toLowerCase() === name.toLowerCase());
|
|
5238
|
+
if (existingPreset) {
|
|
5239
|
+
this.nameError.set('A preset with this name already exists');
|
|
5240
|
+
return;
|
|
5241
|
+
}
|
|
5242
|
+
this.presetsService.updatePresetMetadata(presetId, name, this.editDescription());
|
|
5243
|
+
this.showToast('Preset updated successfully');
|
|
5244
|
+
this.onSwitchToListMode();
|
|
5245
|
+
}
|
|
5246
|
+
onReplaceConfig() {
|
|
5247
|
+
const presetId = this.editingPresetId();
|
|
5248
|
+
if (!presetId)
|
|
5249
|
+
return;
|
|
5250
|
+
this.presetsService.updatePreset(presetId);
|
|
5251
|
+
this.showToast('Configuration replaced with current state');
|
|
5252
|
+
}
|
|
5253
|
+
// Import preset
|
|
5254
|
+
onDragOver(event) {
|
|
5255
|
+
event.preventDefault();
|
|
5256
|
+
event.stopPropagation();
|
|
5257
|
+
this.isDragOver.set(true);
|
|
5258
|
+
}
|
|
5259
|
+
onDragLeave(event) {
|
|
5260
|
+
event.preventDefault();
|
|
5261
|
+
event.stopPropagation();
|
|
5262
|
+
this.isDragOver.set(false);
|
|
5015
5263
|
}
|
|
5264
|
+
onFileDrop(event) {
|
|
5265
|
+
event.preventDefault();
|
|
5266
|
+
event.stopPropagation();
|
|
5267
|
+
this.isDragOver.set(false);
|
|
5268
|
+
const files = event.dataTransfer?.files;
|
|
5269
|
+
if (files && files.length > 0) {
|
|
5270
|
+
this.processFile(files[0]);
|
|
5271
|
+
}
|
|
5272
|
+
}
|
|
5273
|
+
onFileSelect(event) {
|
|
5274
|
+
const input = event.target;
|
|
5275
|
+
if (input.files && input.files.length > 0) {
|
|
5276
|
+
this.processFile(input.files[0]);
|
|
5277
|
+
}
|
|
5278
|
+
}
|
|
5279
|
+
processFile(file) {
|
|
5280
|
+
if (!file.name.endsWith('.json')) {
|
|
5281
|
+
this.importError.set('Please select a .json file');
|
|
5282
|
+
return;
|
|
5283
|
+
}
|
|
5284
|
+
const reader = new FileReader();
|
|
5285
|
+
reader.onload = (e) => {
|
|
5286
|
+
const content = e.target?.result;
|
|
5287
|
+
this.importJson.set(content);
|
|
5288
|
+
this.importError.set(null);
|
|
5289
|
+
};
|
|
5290
|
+
reader.onerror = () => {
|
|
5291
|
+
this.importError.set('Failed to read file');
|
|
5292
|
+
};
|
|
5293
|
+
reader.readAsText(file);
|
|
5294
|
+
}
|
|
5295
|
+
onImportJsonChange(event) {
|
|
5296
|
+
const textarea = event.target;
|
|
5297
|
+
this.importJson.set(textarea.value);
|
|
5298
|
+
this.importError.set(null);
|
|
5299
|
+
}
|
|
5300
|
+
onImportPreset() {
|
|
5301
|
+
const json = this.importJson().trim();
|
|
5302
|
+
if (!json) {
|
|
5303
|
+
this.importError.set('Please provide JSON content');
|
|
5304
|
+
return;
|
|
5305
|
+
}
|
|
5306
|
+
try {
|
|
5307
|
+
const parsed = JSON.parse(json);
|
|
5308
|
+
// Validate required fields
|
|
5309
|
+
if (!parsed.name) {
|
|
5310
|
+
this.importError.set('Preset must have a name');
|
|
5311
|
+
return;
|
|
5312
|
+
}
|
|
5313
|
+
if (!parsed.config) {
|
|
5314
|
+
this.importError.set('Preset must have a config object');
|
|
5315
|
+
return;
|
|
5316
|
+
}
|
|
5317
|
+
this.presetsService.addPreset(parsed);
|
|
5318
|
+
this.showToast('Preset imported successfully');
|
|
5319
|
+
this.onSwitchToListMode();
|
|
5320
|
+
}
|
|
5321
|
+
catch {
|
|
5322
|
+
this.importError.set('Invalid JSON format');
|
|
5323
|
+
}
|
|
5324
|
+
}
|
|
5325
|
+
// Apply preset (partial)
|
|
5326
|
+
onStartApply(presetId) {
|
|
5327
|
+
this.applyingPresetId.set(presetId);
|
|
5328
|
+
this.applyFeatureFlags.set(true);
|
|
5329
|
+
this.applyPermissions.set(true);
|
|
5330
|
+
this.applyAppFeatures.set(true);
|
|
5331
|
+
this.applyLanguage.set(true);
|
|
5332
|
+
this.viewMode.set('apply');
|
|
5333
|
+
}
|
|
5334
|
+
onConfirmPartialApply() {
|
|
5335
|
+
const presetId = this.applyingPresetId();
|
|
5336
|
+
if (!presetId)
|
|
5337
|
+
return;
|
|
5338
|
+
this.presetsService.partialApplyPreset(presetId, {
|
|
5339
|
+
applyFeatureFlags: this.applyFeatureFlags(),
|
|
5340
|
+
applyPermissions: this.applyPermissions(),
|
|
5341
|
+
applyAppFeatures: this.applyAppFeatures(),
|
|
5342
|
+
applyLanguage: this.applyLanguage(),
|
|
5343
|
+
});
|
|
5344
|
+
this.showToast('Preset applied successfully');
|
|
5345
|
+
this.onSwitchToListMode();
|
|
5346
|
+
}
|
|
5347
|
+
// Update preset (with current state)
|
|
5016
5348
|
onUpdatePreset(presetId) {
|
|
5017
5349
|
this.presetsService.updatePreset(presetId);
|
|
5350
|
+
this.showToast('Preset updated with current state');
|
|
5018
5351
|
}
|
|
5352
|
+
// Export preset
|
|
5019
5353
|
onExportPreset(presetId) {
|
|
5020
5354
|
const preset = this.presets().find((p) => p.id === presetId);
|
|
5021
5355
|
if (!preset)
|
|
@@ -5028,11 +5362,25 @@ class ToolbarPresetsToolComponent {
|
|
|
5028
5362
|
link.download = `preset-${preset.name.toLowerCase().replace(/\s+/g, '-')}.json`;
|
|
5029
5363
|
link.click();
|
|
5030
5364
|
URL.revokeObjectURL(url);
|
|
5365
|
+
this.showToast('Preset exported');
|
|
5031
5366
|
}
|
|
5367
|
+
// Delete preset
|
|
5032
5368
|
onDeletePreset(presetId) {
|
|
5033
|
-
|
|
5369
|
+
this.deletePresetId.set(presetId);
|
|
5370
|
+
this.viewMode.set('delete');
|
|
5371
|
+
}
|
|
5372
|
+
onConfirmDelete() {
|
|
5373
|
+
const presetId = this.deletePresetId();
|
|
5374
|
+
if (presetId) {
|
|
5034
5375
|
this.presetsService.deletePreset(presetId);
|
|
5376
|
+
this.showToast('Preset deleted');
|
|
5035
5377
|
}
|
|
5378
|
+
this.deletePresetId.set(null);
|
|
5379
|
+
this.viewMode.set('list');
|
|
5380
|
+
}
|
|
5381
|
+
// Favorites
|
|
5382
|
+
onToggleFavorite(presetId) {
|
|
5383
|
+
this.presetsService.toggleFavorite(presetId);
|
|
5036
5384
|
}
|
|
5037
5385
|
// Protected methods
|
|
5038
5386
|
getCurrentFlagsCount() {
|
|
@@ -5053,9 +5401,44 @@ class ToolbarPresetsToolComponent {
|
|
|
5053
5401
|
formatDate(isoString) {
|
|
5054
5402
|
return new Date(isoString).toLocaleDateString();
|
|
5055
5403
|
}
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5404
|
+
getPresetTooltip(preset) {
|
|
5405
|
+
const lines = [];
|
|
5406
|
+
// Feature Flags
|
|
5407
|
+
const flagsEnabled = preset.config.featureFlags.enabled;
|
|
5408
|
+
const flagsDisabled = preset.config.featureFlags.disabled;
|
|
5409
|
+
if (flagsEnabled.length > 0 || flagsDisabled.length > 0) {
|
|
5410
|
+
lines.push('Feature Flags:');
|
|
5411
|
+
flagsEnabled.forEach(id => lines.push(` ✓ ${id}: ON`));
|
|
5412
|
+
flagsDisabled.forEach(id => lines.push(` ✗ ${id}: OFF`));
|
|
5413
|
+
}
|
|
5414
|
+
// Permissions
|
|
5415
|
+
const permsGranted = preset.config.permissions.granted;
|
|
5416
|
+
const permsDenied = preset.config.permissions.denied;
|
|
5417
|
+
if (permsGranted.length > 0 || permsDenied.length > 0) {
|
|
5418
|
+
if (lines.length > 0)
|
|
5419
|
+
lines.push('');
|
|
5420
|
+
lines.push('Permissions:');
|
|
5421
|
+
permsGranted.forEach(id => lines.push(` ✓ ${id}: GRANTED`));
|
|
5422
|
+
permsDenied.forEach(id => lines.push(` ✗ ${id}: DENIED`));
|
|
5423
|
+
}
|
|
5424
|
+
// App Features
|
|
5425
|
+
const featuresEnabled = preset.config.appFeatures.enabled;
|
|
5426
|
+
const featuresDisabled = preset.config.appFeatures.disabled;
|
|
5427
|
+
if (featuresEnabled.length > 0 || featuresDisabled.length > 0) {
|
|
5428
|
+
if (lines.length > 0)
|
|
5429
|
+
lines.push('');
|
|
5430
|
+
lines.push('App Features:');
|
|
5431
|
+
featuresEnabled.forEach(id => lines.push(` ✓ ${id}: ON`));
|
|
5432
|
+
featuresDisabled.forEach(id => lines.push(` ✗ ${id}: OFF`));
|
|
5433
|
+
}
|
|
5434
|
+
// Language
|
|
5435
|
+
if (preset.config.language) {
|
|
5436
|
+
if (lines.length > 0)
|
|
5437
|
+
lines.push('');
|
|
5438
|
+
lines.push(`Language: ${preset.config.language}`);
|
|
5439
|
+
}
|
|
5440
|
+
return lines.length > 0 ? lines.join('\n') : 'No configuration';
|
|
5441
|
+
}
|
|
5059
5442
|
toggleItemSelection(signal, itemId) {
|
|
5060
5443
|
const current = new Set(signal());
|
|
5061
5444
|
if (current.has(itemId)) {
|
|
@@ -5066,9 +5449,6 @@ class ToolbarPresetsToolComponent {
|
|
|
5066
5449
|
}
|
|
5067
5450
|
signal.set(current);
|
|
5068
5451
|
}
|
|
5069
|
-
/**
|
|
5070
|
-
* Check if an item is selected
|
|
5071
|
-
*/
|
|
5072
5452
|
isItemSelected(selectedSet, itemId) {
|
|
5073
5453
|
return selectedSet.has(itemId);
|
|
5074
5454
|
}
|
|
@@ -5076,8 +5456,17 @@ class ToolbarPresetsToolComponent {
|
|
|
5076
5456
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarPresetsToolComponent, isStandalone: true, selector: "ngt-presets-tool", ngImport: i0, template: `
|
|
5077
5457
|
<ngt-toolbar-tool [options]="options" title="Presets" icon="layout">
|
|
5078
5458
|
<div class="container">
|
|
5459
|
+
<!-- Toast Notification -->
|
|
5460
|
+
@if (toastMessage()) {
|
|
5461
|
+
<div class="toast" [class.toast--success]="toastType() === 'success'" [class.toast--error]="toastType() === 'error'">
|
|
5462
|
+
<span class="toast__icon">{{ toastType() === 'success' ? '✓' : '✕' }}</span>
|
|
5463
|
+
<span class="toast__message">{{ toastMessage() }}</span>
|
|
5464
|
+
</div>
|
|
5465
|
+
}
|
|
5466
|
+
|
|
5467
|
+
|
|
5079
5468
|
<!-- Mode Toggle -->
|
|
5080
|
-
@if (!hasNoPresets() || viewMode()
|
|
5469
|
+
@if (!hasNoPresets() || viewMode() !== 'list') {
|
|
5081
5470
|
<div class="tool-header">
|
|
5082
5471
|
@if (viewMode() === 'list') {
|
|
5083
5472
|
<ngt-input
|
|
@@ -5086,18 +5475,24 @@ class ToolbarPresetsToolComponent {
|
|
|
5086
5475
|
placeholder="Search presets..."
|
|
5087
5476
|
[ariaLabel]="'Search presets'"
|
|
5088
5477
|
/>
|
|
5478
|
+
<ngt-button
|
|
5479
|
+
(click)="onSwitchToImportMode()"
|
|
5480
|
+
[ariaLabel]="'Import preset'"
|
|
5481
|
+
>
|
|
5482
|
+
Import
|
|
5483
|
+
</ngt-button>
|
|
5089
5484
|
<ngt-button
|
|
5090
5485
|
(click)="onSwitchToCreateMode()"
|
|
5091
5486
|
[ariaLabel]="'Create new preset'"
|
|
5092
5487
|
>
|
|
5093
|
-
New
|
|
5488
|
+
New
|
|
5094
5489
|
</ngt-button>
|
|
5095
5490
|
} @else {
|
|
5096
5491
|
<ngt-button
|
|
5097
5492
|
(click)="onSwitchToListMode()"
|
|
5098
5493
|
[ariaLabel]="'Back to list'"
|
|
5099
5494
|
>
|
|
5100
|
-
← Back
|
|
5495
|
+
← Back
|
|
5101
5496
|
</ngt-button>
|
|
5102
5497
|
}
|
|
5103
5498
|
</div>
|
|
@@ -5106,13 +5501,20 @@ class ToolbarPresetsToolComponent {
|
|
|
5106
5501
|
<!-- Create Form -->
|
|
5107
5502
|
@if (viewMode() === 'create') {
|
|
5108
5503
|
<form (submit)="onSavePreset($event)" class="preset-form">
|
|
5109
|
-
<
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5504
|
+
<h3 class="form-title">Create Preset</h3>
|
|
5505
|
+
<p class="form-hint">This will save the current forced values from other tools. Only items you've explicitly set will be included.</p>
|
|
5506
|
+
<div class="form-field">
|
|
5507
|
+
<ngt-input
|
|
5508
|
+
label="Preset Name *"
|
|
5509
|
+
[value]="presetName()"
|
|
5510
|
+
(valueChange)="onPresetNameChange($event)"
|
|
5511
|
+
placeholder="e.g., Admin User - Full Access"
|
|
5512
|
+
[ariaLabel]="'Preset name'"
|
|
5513
|
+
/>
|
|
5514
|
+
@if (nameError()) {
|
|
5515
|
+
<span class="field-error">{{ nameError() }}</span>
|
|
5516
|
+
}
|
|
5517
|
+
</div>
|
|
5116
5518
|
<ngt-input
|
|
5117
5519
|
label="Description (optional)"
|
|
5118
5520
|
[value]="presetDescription()"
|
|
@@ -5240,11 +5642,301 @@ class ToolbarPresetsToolComponent {
|
|
|
5240
5642
|
</div>
|
|
5241
5643
|
|
|
5242
5644
|
<div class="form-actions">
|
|
5645
|
+
<ngt-button type="button" (click)="onSwitchToListMode()">Cancel</ngt-button>
|
|
5243
5646
|
<ngt-button type="submit">Save Preset</ngt-button>
|
|
5244
5647
|
</div>
|
|
5245
5648
|
</form>
|
|
5246
5649
|
}
|
|
5247
5650
|
|
|
5651
|
+
<!-- Edit Form -->
|
|
5652
|
+
@if (viewMode() === 'edit') {
|
|
5653
|
+
<form (submit)="onSaveEdit($event)" class="preset-form">
|
|
5654
|
+
<h3 class="form-title">Edit Preset</h3>
|
|
5655
|
+
<div class="form-field">
|
|
5656
|
+
<ngt-input
|
|
5657
|
+
label="Preset Name *"
|
|
5658
|
+
[value]="editName()"
|
|
5659
|
+
(valueChange)="onEditNameChange($event)"
|
|
5660
|
+
placeholder="e.g., Admin User - Full Access"
|
|
5661
|
+
[ariaLabel]="'Preset name'"
|
|
5662
|
+
/>
|
|
5663
|
+
@if (nameError()) {
|
|
5664
|
+
<span class="field-error">{{ nameError() }}</span>
|
|
5665
|
+
}
|
|
5666
|
+
</div>
|
|
5667
|
+
<ngt-input
|
|
5668
|
+
label="Description (optional)"
|
|
5669
|
+
[value]="editDescription()"
|
|
5670
|
+
(valueChange)="editDescription.set($event)"
|
|
5671
|
+
placeholder="Brief description of this preset"
|
|
5672
|
+
[ariaLabel]="'Preset description'"
|
|
5673
|
+
/>
|
|
5674
|
+
|
|
5675
|
+
<!-- Show saved configuration read-only -->
|
|
5676
|
+
@if (editingPreset()) {
|
|
5677
|
+
<div class="config-preview">
|
|
5678
|
+
<h4>Saved Configuration</h4>
|
|
5679
|
+
@if (editingPreset()!.config.featureFlags.enabled.length > 0 || editingPreset()!.config.featureFlags.disabled.length > 0) {
|
|
5680
|
+
<div class="config-category">
|
|
5681
|
+
<span class="config-category__title">Feature Flags ({{ editingPreset()!.config.featureFlags.enabled.length + editingPreset()!.config.featureFlags.disabled.length }})</span>
|
|
5682
|
+
<div class="config-items">
|
|
5683
|
+
@for (id of editingPreset()!.config.featureFlags.enabled; track id) {
|
|
5684
|
+
<span class="config-item config-item--on">{{ id }}: ON</span>
|
|
5685
|
+
}
|
|
5686
|
+
@for (id of editingPreset()!.config.featureFlags.disabled; track id) {
|
|
5687
|
+
<span class="config-item config-item--off">{{ id }}: OFF</span>
|
|
5688
|
+
}
|
|
5689
|
+
</div>
|
|
5690
|
+
</div>
|
|
5691
|
+
}
|
|
5692
|
+
@if (editingPreset()!.config.permissions.granted.length > 0 || editingPreset()!.config.permissions.denied.length > 0) {
|
|
5693
|
+
<div class="config-category">
|
|
5694
|
+
<span class="config-category__title">Permissions ({{ editingPreset()!.config.permissions.granted.length + editingPreset()!.config.permissions.denied.length }})</span>
|
|
5695
|
+
<div class="config-items">
|
|
5696
|
+
@for (id of editingPreset()!.config.permissions.granted; track id) {
|
|
5697
|
+
<span class="config-item config-item--on">{{ id }}: GRANTED</span>
|
|
5698
|
+
}
|
|
5699
|
+
@for (id of editingPreset()!.config.permissions.denied; track id) {
|
|
5700
|
+
<span class="config-item config-item--off">{{ id }}: DENIED</span>
|
|
5701
|
+
}
|
|
5702
|
+
</div>
|
|
5703
|
+
</div>
|
|
5704
|
+
}
|
|
5705
|
+
@if (editingPreset()!.config.appFeatures.enabled.length > 0 || editingPreset()!.config.appFeatures.disabled.length > 0) {
|
|
5706
|
+
<div class="config-category">
|
|
5707
|
+
<span class="config-category__title">App Features ({{ editingPreset()!.config.appFeatures.enabled.length + editingPreset()!.config.appFeatures.disabled.length }})</span>
|
|
5708
|
+
<div class="config-items">
|
|
5709
|
+
@for (id of editingPreset()!.config.appFeatures.enabled; track id) {
|
|
5710
|
+
<span class="config-item config-item--on">{{ id }}: ON</span>
|
|
5711
|
+
}
|
|
5712
|
+
@for (id of editingPreset()!.config.appFeatures.disabled; track id) {
|
|
5713
|
+
<span class="config-item config-item--off">{{ id }}: OFF</span>
|
|
5714
|
+
}
|
|
5715
|
+
</div>
|
|
5716
|
+
</div>
|
|
5717
|
+
}
|
|
5718
|
+
@if (editingPreset()!.config.language) {
|
|
5719
|
+
<div class="config-category">
|
|
5720
|
+
<span class="config-category__title">Language</span>
|
|
5721
|
+
<span class="config-item">{{ editingPreset()!.config.language }}</span>
|
|
5722
|
+
</div>
|
|
5723
|
+
}
|
|
5724
|
+
<button type="button" class="replace-config-button" (click)="onReplaceConfig()">
|
|
5725
|
+
↻ Replace with current toolbar state
|
|
5726
|
+
</button>
|
|
5727
|
+
</div>
|
|
5728
|
+
}
|
|
5729
|
+
|
|
5730
|
+
<div class="form-actions">
|
|
5731
|
+
<ngt-button type="button" (click)="onSwitchToListMode()">Cancel</ngt-button>
|
|
5732
|
+
<ngt-button type="submit">Save Changes</ngt-button>
|
|
5733
|
+
</div>
|
|
5734
|
+
</form>
|
|
5735
|
+
}
|
|
5736
|
+
|
|
5737
|
+
<!-- Import View -->
|
|
5738
|
+
@if (viewMode() === 'import') {
|
|
5739
|
+
<div class="import-view">
|
|
5740
|
+
<h3 class="form-title">Import Preset</h3>
|
|
5741
|
+
|
|
5742
|
+
<!-- File Drop Zone -->
|
|
5743
|
+
<div
|
|
5744
|
+
class="drop-zone"
|
|
5745
|
+
[class.drop-zone--active]="isDragOver()"
|
|
5746
|
+
(dragover)="onDragOver($event)"
|
|
5747
|
+
(dragleave)="onDragLeave($event)"
|
|
5748
|
+
(drop)="onFileDrop($event)"
|
|
5749
|
+
(click)="fileInput.click()"
|
|
5750
|
+
>
|
|
5751
|
+
<input
|
|
5752
|
+
#fileInput
|
|
5753
|
+
type="file"
|
|
5754
|
+
accept=".json"
|
|
5755
|
+
(change)="onFileSelect($event)"
|
|
5756
|
+
hidden
|
|
5757
|
+
/>
|
|
5758
|
+
<span class="drop-zone__icon">📁</span>
|
|
5759
|
+
<span class="drop-zone__text">Drop a .json file here</span>
|
|
5760
|
+
<span class="drop-zone__hint">or click to browse</span>
|
|
5761
|
+
</div>
|
|
5762
|
+
|
|
5763
|
+
<div class="divider">
|
|
5764
|
+
<span>or paste JSON</span>
|
|
5765
|
+
</div>
|
|
5766
|
+
|
|
5767
|
+
<!-- JSON Textarea -->
|
|
5768
|
+
<textarea
|
|
5769
|
+
class="json-textarea"
|
|
5770
|
+
[value]="importJson()"
|
|
5771
|
+
(input)="onImportJsonChange($event)"
|
|
5772
|
+
placeholder='{"name": "...", "config": { ... }}'
|
|
5773
|
+
></textarea>
|
|
5774
|
+
|
|
5775
|
+
@if (importError()) {
|
|
5776
|
+
<span class="field-error">{{ importError() }}</span>
|
|
5777
|
+
}
|
|
5778
|
+
|
|
5779
|
+
<div class="form-actions">
|
|
5780
|
+
<ngt-button type="button" (click)="onSwitchToListMode()">Cancel</ngt-button>
|
|
5781
|
+
<ngt-button (click)="onImportPreset()">Import Preset</ngt-button>
|
|
5782
|
+
</div>
|
|
5783
|
+
</div>
|
|
5784
|
+
}
|
|
5785
|
+
|
|
5786
|
+
<!-- Partial Apply View -->
|
|
5787
|
+
@if (viewMode() === 'apply') {
|
|
5788
|
+
<div class="apply-view">
|
|
5789
|
+
<h3 class="form-title">Apply: {{ applyingPreset()?.name }}</h3>
|
|
5790
|
+
<p class="apply-description">Select which parts to apply</p>
|
|
5791
|
+
|
|
5792
|
+
@if (applyingPreset()) {
|
|
5793
|
+
<div class="apply-categories">
|
|
5794
|
+
<!-- Feature Flags -->
|
|
5795
|
+
@if (applyingPreset()!.config.featureFlags.enabled.length > 0 || applyingPreset()!.config.featureFlags.disabled.length > 0) {
|
|
5796
|
+
<div class="apply-category" [class.apply-category--disabled]="!applyFeatureFlags()">
|
|
5797
|
+
<label class="apply-category__header">
|
|
5798
|
+
<input
|
|
5799
|
+
type="checkbox"
|
|
5800
|
+
[checked]="applyFeatureFlags()"
|
|
5801
|
+
(change)="applyFeatureFlags.set(!applyFeatureFlags())"
|
|
5802
|
+
/>
|
|
5803
|
+
<span>Feature Flags ({{ applyingPreset()!.config.featureFlags.enabled.length + applyingPreset()!.config.featureFlags.disabled.length }})</span>
|
|
5804
|
+
</label>
|
|
5805
|
+
@if (applyFeatureFlags()) {
|
|
5806
|
+
<div class="apply-diff">
|
|
5807
|
+
@for (id of applyingPreset()!.config.featureFlags.enabled; track id) {
|
|
5808
|
+
<div class="diff-item">
|
|
5809
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
5810
|
+
<span class="diff-item__arrow">→</span>
|
|
5811
|
+
<span class="diff-item__value diff-item__value--on">ON</span>
|
|
5812
|
+
</div>
|
|
5813
|
+
}
|
|
5814
|
+
@for (id of applyingPreset()!.config.featureFlags.disabled; track id) {
|
|
5815
|
+
<div class="diff-item">
|
|
5816
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
5817
|
+
<span class="diff-item__arrow">→</span>
|
|
5818
|
+
<span class="diff-item__value diff-item__value--off">OFF</span>
|
|
5819
|
+
</div>
|
|
5820
|
+
}
|
|
5821
|
+
</div>
|
|
5822
|
+
}
|
|
5823
|
+
</div>
|
|
5824
|
+
}
|
|
5825
|
+
|
|
5826
|
+
<!-- Permissions -->
|
|
5827
|
+
@if (applyingPreset()!.config.permissions.granted.length > 0 || applyingPreset()!.config.permissions.denied.length > 0) {
|
|
5828
|
+
<div class="apply-category" [class.apply-category--disabled]="!applyPermissions()">
|
|
5829
|
+
<label class="apply-category__header">
|
|
5830
|
+
<input
|
|
5831
|
+
type="checkbox"
|
|
5832
|
+
[checked]="applyPermissions()"
|
|
5833
|
+
(change)="applyPermissions.set(!applyPermissions())"
|
|
5834
|
+
/>
|
|
5835
|
+
<span>Permissions ({{ applyingPreset()!.config.permissions.granted.length + applyingPreset()!.config.permissions.denied.length }})</span>
|
|
5836
|
+
</label>
|
|
5837
|
+
@if (applyPermissions()) {
|
|
5838
|
+
<div class="apply-diff">
|
|
5839
|
+
@for (id of applyingPreset()!.config.permissions.granted; track id) {
|
|
5840
|
+
<div class="diff-item">
|
|
5841
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
5842
|
+
<span class="diff-item__arrow">→</span>
|
|
5843
|
+
<span class="diff-item__value diff-item__value--on">GRANTED</span>
|
|
5844
|
+
</div>
|
|
5845
|
+
}
|
|
5846
|
+
@for (id of applyingPreset()!.config.permissions.denied; track id) {
|
|
5847
|
+
<div class="diff-item">
|
|
5848
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
5849
|
+
<span class="diff-item__arrow">→</span>
|
|
5850
|
+
<span class="diff-item__value diff-item__value--off">DENIED</span>
|
|
5851
|
+
</div>
|
|
5852
|
+
}
|
|
5853
|
+
</div>
|
|
5854
|
+
}
|
|
5855
|
+
</div>
|
|
5856
|
+
}
|
|
5857
|
+
|
|
5858
|
+
<!-- App Features -->
|
|
5859
|
+
@if (applyingPreset()!.config.appFeatures.enabled.length > 0 || applyingPreset()!.config.appFeatures.disabled.length > 0) {
|
|
5860
|
+
<div class="apply-category" [class.apply-category--disabled]="!applyAppFeatures()">
|
|
5861
|
+
<label class="apply-category__header">
|
|
5862
|
+
<input
|
|
5863
|
+
type="checkbox"
|
|
5864
|
+
[checked]="applyAppFeatures()"
|
|
5865
|
+
(change)="applyAppFeatures.set(!applyAppFeatures())"
|
|
5866
|
+
/>
|
|
5867
|
+
<span>App Features ({{ applyingPreset()!.config.appFeatures.enabled.length + applyingPreset()!.config.appFeatures.disabled.length }})</span>
|
|
5868
|
+
</label>
|
|
5869
|
+
@if (applyAppFeatures()) {
|
|
5870
|
+
<div class="apply-diff">
|
|
5871
|
+
@for (id of applyingPreset()!.config.appFeatures.enabled; track id) {
|
|
5872
|
+
<div class="diff-item">
|
|
5873
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
5874
|
+
<span class="diff-item__arrow">→</span>
|
|
5875
|
+
<span class="diff-item__value diff-item__value--on">ON</span>
|
|
5876
|
+
</div>
|
|
5877
|
+
}
|
|
5878
|
+
@for (id of applyingPreset()!.config.appFeatures.disabled; track id) {
|
|
5879
|
+
<div class="diff-item">
|
|
5880
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
5881
|
+
<span class="diff-item__arrow">→</span>
|
|
5882
|
+
<span class="diff-item__value diff-item__value--off">OFF</span>
|
|
5883
|
+
</div>
|
|
5884
|
+
}
|
|
5885
|
+
</div>
|
|
5886
|
+
}
|
|
5887
|
+
</div>
|
|
5888
|
+
}
|
|
5889
|
+
|
|
5890
|
+
<!-- Language -->
|
|
5891
|
+
@if (applyingPreset()!.config.language) {
|
|
5892
|
+
<div class="apply-category" [class.apply-category--disabled]="!applyLanguage()">
|
|
5893
|
+
<label class="apply-category__header">
|
|
5894
|
+
<input
|
|
5895
|
+
type="checkbox"
|
|
5896
|
+
[checked]="applyLanguage()"
|
|
5897
|
+
(change)="applyLanguage.set(!applyLanguage())"
|
|
5898
|
+
/>
|
|
5899
|
+
<span>Language</span>
|
|
5900
|
+
</label>
|
|
5901
|
+
@if (applyLanguage()) {
|
|
5902
|
+
<div class="apply-diff">
|
|
5903
|
+
<div class="diff-item">
|
|
5904
|
+
<span class="diff-item__name">Language</span>
|
|
5905
|
+
<span class="diff-item__arrow">→</span>
|
|
5906
|
+
<span class="diff-item__value">{{ applyingPreset()!.config.language }}</span>
|
|
5907
|
+
</div>
|
|
5908
|
+
</div>
|
|
5909
|
+
}
|
|
5910
|
+
</div>
|
|
5911
|
+
}
|
|
5912
|
+
</div>
|
|
5913
|
+
}
|
|
5914
|
+
|
|
5915
|
+
<div class="form-actions">
|
|
5916
|
+
<ngt-button type="button" (click)="onSwitchToListMode()">Cancel</ngt-button>
|
|
5917
|
+
<ngt-button (click)="onConfirmPartialApply()">Apply Selected</ngt-button>
|
|
5918
|
+
</div>
|
|
5919
|
+
</div>
|
|
5920
|
+
}
|
|
5921
|
+
|
|
5922
|
+
<!-- Delete Confirmation View -->
|
|
5923
|
+
@if (viewMode() === 'delete') {
|
|
5924
|
+
<div class="delete-view">
|
|
5925
|
+
<div class="delete-view__content">
|
|
5926
|
+
<div class="delete-view__icon">🗑️</div>
|
|
5927
|
+
<h3 class="delete-view__title">Delete "{{ deletePresetName() }}"?</h3>
|
|
5928
|
+
<p class="delete-view__description">
|
|
5929
|
+
This preset will be permanently removed.
|
|
5930
|
+
This action cannot be undone.
|
|
5931
|
+
</p>
|
|
5932
|
+
</div>
|
|
5933
|
+
<div class="form-actions">
|
|
5934
|
+
<ngt-button type="button" (click)="onSwitchToListMode()">← Back</ngt-button>
|
|
5935
|
+
<button class="delete-button" (click)="onConfirmDelete()">Delete Preset</button>
|
|
5936
|
+
</div>
|
|
5937
|
+
</div>
|
|
5938
|
+
}
|
|
5939
|
+
|
|
5248
5940
|
<!-- Empty State -->
|
|
5249
5941
|
@if (viewMode() === 'list' && hasNoPresets()) {
|
|
5250
5942
|
<div class="empty">
|
|
@@ -5263,83 +5955,49 @@ class ToolbarPresetsToolComponent {
|
|
|
5263
5955
|
} @else if (viewMode() === 'list') {
|
|
5264
5956
|
<!-- Preset List -->
|
|
5265
5957
|
<div class="preset-list">
|
|
5266
|
-
@for (preset of
|
|
5267
|
-
<div class="preset-card">
|
|
5958
|
+
@for (preset of sortedPresets(); track preset.id) {
|
|
5959
|
+
<div class="preset-card" [title]="getPresetTooltip(preset)">
|
|
5268
5960
|
<div class="preset-card__header">
|
|
5269
|
-
<
|
|
5961
|
+
<button
|
|
5962
|
+
class="favorite-button"
|
|
5963
|
+
[class.favorite-button--active]="preset.isFavorite"
|
|
5964
|
+
(click)="onToggleFavorite(preset.id); $event.stopPropagation()"
|
|
5965
|
+
[attr.aria-label]="preset.isFavorite ? 'Remove from favorites' : 'Add to favorites'"
|
|
5966
|
+
>{{ preset.isFavorite ? '★' : '☆' }}</button>
|
|
5967
|
+
<span class="preset-card__name">{{ preset.name }}</span>
|
|
5968
|
+
@if (preset.isSystem) {<span class="system-badge">SYS</span>}
|
|
5969
|
+
<span class="preset-card__spacer"></span>
|
|
5270
5970
|
<div class="preset-card__actions">
|
|
5271
|
-
<button
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
>
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
class="icon-button"
|
|
5281
|
-
(click)="onUpdatePreset(preset.id)"
|
|
5282
|
-
[attr.aria-label]="'Update preset ' + preset.name"
|
|
5283
|
-
title="Update with current state"
|
|
5284
|
-
>
|
|
5285
|
-
<ngt-icon name="gear" />
|
|
5286
|
-
</button>
|
|
5287
|
-
<button
|
|
5288
|
-
class="icon-button"
|
|
5289
|
-
(click)="onExportPreset(preset.id)"
|
|
5290
|
-
[attr.aria-label]="'Export preset ' + preset.name"
|
|
5291
|
-
title="Export as JSON"
|
|
5292
|
-
>
|
|
5293
|
-
<ngt-icon name="export" />
|
|
5294
|
-
</button>
|
|
5295
|
-
<button
|
|
5296
|
-
class="icon-button"
|
|
5297
|
-
(click)="onDeletePreset(preset.id)"
|
|
5298
|
-
[attr.aria-label]="'Delete preset ' + preset.name"
|
|
5299
|
-
title="Delete preset"
|
|
5300
|
-
>
|
|
5301
|
-
<ngt-icon name="trash" />
|
|
5302
|
-
</button>
|
|
5971
|
+
<button class="icon-button" (click)="onStartApply(preset.id)"><ngt-icon name="refresh" /></button>
|
|
5972
|
+
@if (!preset.isSystem) {
|
|
5973
|
+
<button class="icon-button" (click)="onStartEdit(preset.id)"><ngt-icon name="edit" /></button>
|
|
5974
|
+
<button class="icon-button" (click)="onUpdatePreset(preset.id)"><ngt-icon name="gear" /></button>
|
|
5975
|
+
}
|
|
5976
|
+
<button class="icon-button" (click)="onExportPreset(preset.id)"><ngt-icon name="export" /></button>
|
|
5977
|
+
@if (!preset.isSystem) {
|
|
5978
|
+
<button class="icon-button" (click)="onDeletePreset(preset.id)"><ngt-icon name="trash" /></button>
|
|
5979
|
+
}
|
|
5303
5980
|
</div>
|
|
5304
5981
|
</div>
|
|
5305
5982
|
@if (preset.description) {
|
|
5306
|
-
<
|
|
5307
|
-
|
|
5308
|
-
<div class="preset-card__meta">
|
|
5309
|
-
<span>Updated: {{ formatDate(preset.updatedAt) }}</span>
|
|
5983
|
+
<div class="preset-card__row preset-card__row--meta">
|
|
5984
|
+
<span class="preset-card__description">{{ preset.description }}</span>
|
|
5310
5985
|
</div>
|
|
5311
|
-
|
|
5312
|
-
<div class="preset-
|
|
5313
|
-
@if (preset.config.featureFlags.enabled.length > 0 ||
|
|
5314
|
-
preset.config.featureFlags.disabled.length >
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
preset.config.featureFlags.disabled.length
|
|
5319
|
-
}}
|
|
5320
|
-
flags
|
|
5321
|
-
</span>
|
|
5322
|
-
} @if (preset.config.permissions.granted.length > 0 ||
|
|
5323
|
-
preset.config.permissions.denied.length > 0) {
|
|
5324
|
-
<span class="badge">
|
|
5325
|
-
{{
|
|
5326
|
-
preset.config.permissions.granted.length +
|
|
5327
|
-
preset.config.permissions.denied.length
|
|
5328
|
-
}}
|
|
5329
|
-
perms
|
|
5330
|
-
</span>
|
|
5331
|
-
} @if (preset.config.appFeatures.enabled.length > 0 ||
|
|
5332
|
-
preset.config.appFeatures.disabled.length > 0) {
|
|
5333
|
-
<span class="badge">
|
|
5334
|
-
{{
|
|
5335
|
-
preset.config.appFeatures.enabled.length +
|
|
5336
|
-
preset.config.appFeatures.disabled.length
|
|
5337
|
-
}}
|
|
5338
|
-
features
|
|
5339
|
-
</span>
|
|
5340
|
-
} @if (preset.config.language) {
|
|
5341
|
-
<span class="badge">{{ preset.config.language }}</span>
|
|
5986
|
+
}
|
|
5987
|
+
<div class="preset-card__row preset-card__row--badges">
|
|
5988
|
+
@if (preset.config.featureFlags.enabled.length > 0 || preset.config.featureFlags.disabled.length > 0) {
|
|
5989
|
+
<span class="badge">{{ preset.config.featureFlags.enabled.length + preset.config.featureFlags.disabled.length }} flags</span>
|
|
5990
|
+
}
|
|
5991
|
+
@if (preset.config.permissions.granted.length > 0 || preset.config.permissions.denied.length > 0) {
|
|
5992
|
+
<span class="badge">{{ preset.config.permissions.granted.length + preset.config.permissions.denied.length }} perms</span>
|
|
5342
5993
|
}
|
|
5994
|
+
@if (preset.config.appFeatures.enabled.length > 0 || preset.config.appFeatures.disabled.length > 0) {
|
|
5995
|
+
<span class="badge">{{ preset.config.appFeatures.enabled.length + preset.config.appFeatures.disabled.length }} features</span>
|
|
5996
|
+
}
|
|
5997
|
+
@if (preset.config.language) {
|
|
5998
|
+
<span class="badge badge--lang">{{ preset.config.language }}</span>
|
|
5999
|
+
}
|
|
6000
|
+
<span class="preset-card__date">{{ formatDate(preset.updatedAt) }}</span>
|
|
5343
6001
|
</div>
|
|
5344
6002
|
</div>
|
|
5345
6003
|
}
|
|
@@ -5347,7 +6005,7 @@ class ToolbarPresetsToolComponent {
|
|
|
5347
6005
|
}
|
|
5348
6006
|
</div>
|
|
5349
6007
|
</ngt-toolbar-tool>
|
|
5350
|
-
`, isInline: true, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ngt-spacing-sm);margin-bottom:var(--ngt-spacing-md);ngt-input{flex:1}ngt-button{flex-shrink:0}}.empty{display:flex;flex-direction:column;gap:var(--ngt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ngt-border-subtle);border-radius:var(--ngt-border-radius-medium);padding:var(--ngt-spacing-md);background:transparent;color:var(--ngt-text-muted);text-align:center;p{margin:0}.hint{font-size:var(--ngt-font-size-xs)}}.preset-list{display:flex;flex-direction:column;gap:var(--ngt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ngt-spacing-sm);&::-webkit-scrollbar{width:8px}&::-webkit-scrollbar-track{background:var(--ngt-background-secondary);border-radius:4px}&::-webkit-scrollbar-thumb{background:var(--ngt-border-primary);border-radius:4px;&:hover{background:var(--ngt-hover-bg)}}scrollbar-width:thin;scrollbar-color:var(--ngt-border-primary) var(--ngt-background-secondary)}.preset-card{background:var(--ngt-background-secondary);padding:var(--ngt-spacing-md);border-radius:var(--ngt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ngt-spacing-sm)}.preset-card__header{display:flex;justify-content:space-between;align-items:center;gap:var(--ngt-spacing-sm);h3{margin:0;font-size:var(--ngt-font-size-md);color:var(--ngt-text-primary);flex:1}}.preset-card__actions{display:flex;gap:var(--ngt-spacing-xs)}.icon-button{background:transparent;border:none;cursor:pointer;padding:var(--ngt-spacing-xs);border-radius:var(--ngt-border-radius-small);color:var(--ngt-text-secondary);display:flex;align-items:center;justify-content:center;&:hover{background:var(--ngt-hover-bg);color:var(--ngt-text-primary)}ngt-icon{width:16px;height:16px}}.preset-card__description{margin:0;font-size:var(--ngt-font-size-sm);color:var(--ngt-text-secondary)}.preset-card__meta{font-size:var(--ngt-font-size-xs);color:var(--ngt-text-muted);span{margin-right:var(--ngt-spacing-sm)}}.preset-card__preview{display:flex;gap:var(--ngt-spacing-xs);flex-wrap:wrap}.badge{background:var(--ngt-primary-color);color:#fff;padding:2px 8px;border-radius:12px;font-size:var(--ngt-font-size-xs);font-weight:500}.preset-form{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--ngt-spacing-md);padding:var(--ngt-spacing-md);ngt-input{width:100%}}.preset-summary{background:var(--ngt-background-secondary);padding:var(--ngt-spacing-md);border-radius:var(--ngt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ngt-spacing-sm);h4{margin:0;font-size:var(--ngt-font-size-sm);color:var(--ngt-text-primary)}}.category-section{display:flex;flex-direction:column;gap:var(--ngt-spacing-xs)}.checkbox-option{display:flex;align-items:center;gap:var(--ngt-spacing-sm);cursor:pointer;color:var(--ngt-text-secondary);font-size:var(--ngt-font-size-sm);input[type=checkbox]{cursor:pointer;width:16px;height:16px;accent-color:var(--ngt-primary);&:disabled{cursor:not-allowed;opacity:.5}}&:has(input:disabled){opacity:.6;cursor:not-allowed}}.forced-items-list{list-style:none;padding:0;margin:0 0 0 var(--ngt-spacing-lg);display:flex;flex-direction:column;gap:var(--ngt-spacing-xs);font-size:var(--ngt-font-size-xs);li{background:rgba(var(--ngt-primary-rgb),.05);border-radius:var(--ngt-border-radius-small);border-left:2px solid rgba(var(--ngt-primary-rgb),.3)}.item-checkbox{display:flex;justify-content:space-between;align-items:center;padding:var(--ngt-spacing-xs) var(--ngt-spacing-sm);cursor:pointer;gap:var(--ngt-spacing-sm);input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:var(--ngt-primary);flex-shrink:0}&:hover{background:rgba(var(--ngt-primary-rgb),.08)}}.item-name{color:var(--ngt-text-primary);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item-status{font-weight:600;padding:2px 6px;border-radius:var(--ngt-border-radius-small);font-size:10px;text-transform:uppercase;letter-spacing:.5px;flex-shrink:0;&.enabled{background:#22c55e26;color:#22c55e}&.disabled{background:#ef444426;color:#ef4444}}}.form-actions{display:flex;justify-content:flex-end;gap:var(--ngt-spacing-sm)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ToolbarToolComponent, selector: "ngt-toolbar-tool", inputs: ["options", "icon", "title", "badge"] }, { kind: "component", type: ToolbarInputComponent, selector: "ngt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarButtonComponent, selector: "ngt-button", inputs: ["type", "variant", "icon", "label", "ariaLabel", "isActive"] }, { kind: "component", type: ToolbarIconComponent, selector: "ngt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6008
|
+
`, isInline: true, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.toast{position:absolute;bottom:var(--ngt-spacing-md);left:var(--ngt-spacing-md);right:var(--ngt-spacing-md);z-index:10;display:flex;align-items:center;gap:var(--ngt-spacing-sm);padding:var(--ngt-spacing-sm) var(--ngt-spacing-md);border-radius:var(--ngt-border-radius-small);font-size:var(--ngt-font-size-sm);animation:slideUp .15s ease-out}.toast--success{background:#22c55e;color:#fff}.toast--error{background:#ef4444;color:#fff}.toast__icon{font-weight:700}@keyframes slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.delete-view{flex:1;display:flex;flex-direction:column;justify-content:center;padding:var(--ngt-spacing-md)}.delete-view__content{text-align:center;padding:var(--ngt-spacing-lg) var(--ngt-spacing-md)}.delete-view__icon{font-size:48px;margin-bottom:var(--ngt-spacing-md)}.delete-view__title{margin:0 0 var(--ngt-spacing-sm);font-size:var(--ngt-font-size-md);color:var(--ngt-text-primary)}.delete-view__description{margin:0;font-size:var(--ngt-font-size-sm);color:var(--ngt-text-secondary);line-height:1.5}.delete-button{background:#ef4444;color:#fff;border:none;padding:var(--ngt-spacing-sm) var(--ngt-spacing-md);border-radius:var(--ngt-border-radius-small);cursor:pointer;font-size:var(--ngt-font-size-sm);font-weight:500;transition:background .2s ease-out;&:hover{background:#dc2626}}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ngt-spacing-sm);margin-bottom:var(--ngt-spacing-md);ngt-input{flex:1}ngt-button{flex-shrink:0}}.empty{display:flex;flex-direction:column;gap:var(--ngt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ngt-border-subtle);border-radius:var(--ngt-border-radius-medium);padding:var(--ngt-spacing-md);background:transparent;color:var(--ngt-text-muted);text-align:center;p{margin:0}.hint{font-size:var(--ngt-font-size-xs)}}.preset-list{display:flex;flex-direction:column;gap:var(--ngt-spacing-xs);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ngt-spacing-xs);&::-webkit-scrollbar{width:8px}&::-webkit-scrollbar-track{background:var(--ngt-background-secondary);border-radius:4px}&::-webkit-scrollbar-thumb{background:var(--ngt-border-primary);border-radius:4px;&:hover{background:var(--ngt-hover-bg)}}scrollbar-width:thin;scrollbar-color:var(--ngt-border-primary) var(--ngt-background-secondary)}.preset-card{background:var(--ngt-background-secondary);padding:6px var(--ngt-spacing-sm);border-radius:var(--ngt-border-radius-medium);display:flex;flex-direction:column;gap:2px}.preset-card__header{display:flex;align-items:center;gap:6px;flex-wrap:nowrap}.preset-card__row{display:flex;align-items:center;gap:6px;min-height:18px}.preset-card__row--meta{padding-left:18px}.preset-card__row--badges{padding-left:18px;gap:4px}.preset-card__name{font-size:var(--ngt-font-size-sm);font-weight:600;color:var(--ngt-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__spacer{flex:1;min-width:8px}.system-badge{font-size:8px;font-weight:600;text-transform:uppercase;letter-spacing:.3px;padding:1px 4px;border-radius:3px;background:var(--ngt-border-primary);color:var(--ngt-text-muted);flex-shrink:0}.favorite-button{background:transparent;border:none;cursor:pointer;font-size:12px;color:var(--ngt-text-muted);padding:0;line-height:1;transition:color .15s ease-out;flex-shrink:0}.favorite-button:hover,.favorite-button--active{color:#f59e0b}.preset-card__actions{display:flex;gap:0;flex-shrink:0}.icon-button{appearance:none;background:none;border:none;cursor:pointer;margin:0;padding:4px;border-radius:4px;color:var(--ngt-text-muted);display:inline-flex;align-items:center;justify-content:center;opacity:.5;transition:opacity .15s ease-out,color .15s ease-out;line-height:0;&:hover{background:var(--ngt-hover-bg);color:var(--ngt-text-primary);opacity:1}ngt-icon,ngt-icon>*,svg{display:block;width:12px!important;height:12px!important}}.preset-card__description{font-size:11px;color:var(--ngt-text-secondary);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__date{font-size:10px;color:var(--ngt-text-muted);margin-left:auto;flex-shrink:0}.badge{background:#6366f126;color:#6366f1;padding:1px 6px;border-radius:8px;font-size:10px;font-weight:500;white-space:nowrap}.badge--lang{background:#22c55e26;color:#22c55e}.preset-form,.import-view,.apply-view{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--ngt-spacing-sm);padding:var(--ngt-spacing-sm);ngt-input{width:100%}}.form-title{margin:0;font-size:var(--ngt-font-size-sm);font-weight:600;color:var(--ngt-text-primary)}.form-hint{margin:0;font-size:11px;color:var(--ngt-text-muted);line-height:1.3}.form-field{display:flex;flex-direction:column;gap:2px}.field-error{color:#ef4444;font-size:11px}.preset-summary{background:var(--ngt-background-secondary);padding:var(--ngt-spacing-sm);border-radius:var(--ngt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ngt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ngt-text-secondary)}}.category-section{display:flex;flex-direction:column;gap:2px}.checkbox-option{display:flex;align-items:center;gap:var(--ngt-spacing-xs);cursor:pointer;color:var(--ngt-text-primary);font-size:var(--ngt-font-size-sm);padding:2px 0;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241);border-radius:3px;&:disabled{cursor:not-allowed;opacity:.4}}&:has(input:disabled){opacity:.5;cursor:not-allowed}}.forced-items-list{list-style:none;padding:0;margin:0 0 0 20px;display:flex;flex-direction:column;gap:2px;font-size:11px;max-height:100px;overflow-y:auto;li{background:#6366f10d;border-radius:3px;border-left:2px solid rgba(99,102,241,.3)}.item-checkbox{display:flex;justify-content:space-between;align-items:center;padding:3px 6px;cursor:pointer;gap:6px;input[type=checkbox]{cursor:pointer;width:12px;height:12px;accent-color:rgb(99,102,241);flex-shrink:0}&:hover{background:#6366f114}}.item-name{color:var(--ngt-text-primary);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item-status{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px;flex-shrink:0;&.enabled{background:#22c55e26;color:#22c55e}&.disabled{background:#ef444426;color:#ef4444}}}.form-actions{display:flex;justify-content:flex-end;gap:var(--ngt-spacing-sm);margin-top:auto;padding-top:var(--ngt-spacing-sm)}.config-preview{background:var(--ngt-background-secondary);padding:var(--ngt-spacing-sm);border-radius:var(--ngt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ngt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ngt-text-secondary)}}.config-category{display:flex;flex-direction:column;gap:2px}.config-category__title{font-size:10px;color:var(--ngt-text-muted);font-weight:500}.config-items{display:flex;flex-wrap:wrap;gap:4px}.config-item{font-size:10px;padding:1px 6px;border-radius:3px;background:var(--ngt-background-primary);color:var(--ngt-text-secondary)}.config-item--on{background:#22c55e1a;color:#22c55e}.config-item--off{background:#ef44441a;color:#ef4444}.replace-config-button{background:transparent;border:1px dashed var(--ngt-border-primary);padding:6px var(--ngt-spacing-sm);border-radius:var(--ngt-border-radius-small);color:var(--ngt-text-secondary);cursor:pointer;font-size:11px;transition:all .15s ease-out;&:hover{background:var(--ngt-hover-bg);border-color:#6366f1;color:#6366f1}}.drop-zone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:var(--ngt-spacing-md);border:2px dashed var(--ngt-border-primary);border-radius:var(--ngt-border-radius-medium);cursor:pointer;transition:all .15s ease-out}.drop-zone:hover,.drop-zone--active{border-color:#6366f1;background:#6366f10d}.drop-zone__icon{font-size:24px}.drop-zone__text{font-size:var(--ngt-font-size-sm);color:var(--ngt-text-primary)}.drop-zone__hint{font-size:11px;color:var(--ngt-text-muted)}.divider{display:flex;align-items:center;gap:var(--ngt-spacing-sm);color:var(--ngt-text-muted);font-size:10px;&:before,&:after{content:\"\";flex:1;height:1px;background:var(--ngt-border-primary)}}.json-textarea{width:100%;min-height:80px;padding:var(--ngt-spacing-xs);border:1px solid var(--ngt-border-primary);border-radius:var(--ngt-border-radius-small);background:var(--ngt-background-secondary);color:var(--ngt-text-primary);font-family:monospace;font-size:11px;resize:vertical;&:focus{outline:none;border-color:#6366f1}&::placeholder{color:var(--ngt-text-muted)}}.apply-description{margin:0;font-size:11px;color:var(--ngt-text-secondary)}.apply-categories{display:flex;flex-direction:column;gap:var(--ngt-spacing-xs)}.apply-category{background:var(--ngt-background-secondary);border-radius:var(--ngt-border-radius-small);overflow:hidden;transition:opacity .15s ease-out}.apply-category--disabled{opacity:.5}.apply-category__header{display:flex;align-items:center;gap:var(--ngt-spacing-xs);padding:6px var(--ngt-spacing-sm);cursor:pointer;font-size:var(--ngt-font-size-sm);color:var(--ngt-text-primary);font-weight:500;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241)}}.apply-diff{padding:0 var(--ngt-spacing-sm) 6px;display:flex;flex-direction:column;gap:2px}.diff-item{display:flex;align-items:center;gap:6px;font-size:11px;padding:3px 6px;background:var(--ngt-background-primary);border-radius:3px}.diff-item__name{flex:1;color:var(--ngt-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diff-item__arrow{color:var(--ngt-text-muted);font-size:10px}.diff-item__value{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px}.diff-item__value--on{background:#22c55e26;color:#22c55e}.diff-item__value--off{background:#ef444426;color:#ef4444}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ToolbarToolComponent, selector: "ngt-toolbar-tool", inputs: ["options", "icon", "title", "badge"] }, { kind: "component", type: ToolbarInputComponent, selector: "ngt-input", inputs: ["value", "type", "placeholder", "ariaLabel", "inputClass"], outputs: ["valueChange"] }, { kind: "component", type: ToolbarButtonComponent, selector: "ngt-button", inputs: ["type", "variant", "icon", "label", "ariaLabel", "isActive"] }, { kind: "component", type: ToolbarIconComponent, selector: "ngt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5351
6009
|
}
|
|
5352
6010
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarPresetsToolComponent, decorators: [{
|
|
5353
6011
|
type: Component,
|
|
@@ -5360,8 +6018,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
|
|
|
5360
6018
|
], template: `
|
|
5361
6019
|
<ngt-toolbar-tool [options]="options" title="Presets" icon="layout">
|
|
5362
6020
|
<div class="container">
|
|
6021
|
+
<!-- Toast Notification -->
|
|
6022
|
+
@if (toastMessage()) {
|
|
6023
|
+
<div class="toast" [class.toast--success]="toastType() === 'success'" [class.toast--error]="toastType() === 'error'">
|
|
6024
|
+
<span class="toast__icon">{{ toastType() === 'success' ? '✓' : '✕' }}</span>
|
|
6025
|
+
<span class="toast__message">{{ toastMessage() }}</span>
|
|
6026
|
+
</div>
|
|
6027
|
+
}
|
|
6028
|
+
|
|
6029
|
+
|
|
5363
6030
|
<!-- Mode Toggle -->
|
|
5364
|
-
@if (!hasNoPresets() || viewMode()
|
|
6031
|
+
@if (!hasNoPresets() || viewMode() !== 'list') {
|
|
5365
6032
|
<div class="tool-header">
|
|
5366
6033
|
@if (viewMode() === 'list') {
|
|
5367
6034
|
<ngt-input
|
|
@@ -5370,18 +6037,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
|
|
|
5370
6037
|
placeholder="Search presets..."
|
|
5371
6038
|
[ariaLabel]="'Search presets'"
|
|
5372
6039
|
/>
|
|
6040
|
+
<ngt-button
|
|
6041
|
+
(click)="onSwitchToImportMode()"
|
|
6042
|
+
[ariaLabel]="'Import preset'"
|
|
6043
|
+
>
|
|
6044
|
+
Import
|
|
6045
|
+
</ngt-button>
|
|
5373
6046
|
<ngt-button
|
|
5374
6047
|
(click)="onSwitchToCreateMode()"
|
|
5375
6048
|
[ariaLabel]="'Create new preset'"
|
|
5376
6049
|
>
|
|
5377
|
-
New
|
|
6050
|
+
New
|
|
5378
6051
|
</ngt-button>
|
|
5379
6052
|
} @else {
|
|
5380
6053
|
<ngt-button
|
|
5381
6054
|
(click)="onSwitchToListMode()"
|
|
5382
6055
|
[ariaLabel]="'Back to list'"
|
|
5383
6056
|
>
|
|
5384
|
-
← Back
|
|
6057
|
+
← Back
|
|
5385
6058
|
</ngt-button>
|
|
5386
6059
|
}
|
|
5387
6060
|
</div>
|
|
@@ -5390,13 +6063,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
|
|
|
5390
6063
|
<!-- Create Form -->
|
|
5391
6064
|
@if (viewMode() === 'create') {
|
|
5392
6065
|
<form (submit)="onSavePreset($event)" class="preset-form">
|
|
5393
|
-
<
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
6066
|
+
<h3 class="form-title">Create Preset</h3>
|
|
6067
|
+
<p class="form-hint">This will save the current forced values from other tools. Only items you've explicitly set will be included.</p>
|
|
6068
|
+
<div class="form-field">
|
|
6069
|
+
<ngt-input
|
|
6070
|
+
label="Preset Name *"
|
|
6071
|
+
[value]="presetName()"
|
|
6072
|
+
(valueChange)="onPresetNameChange($event)"
|
|
6073
|
+
placeholder="e.g., Admin User - Full Access"
|
|
6074
|
+
[ariaLabel]="'Preset name'"
|
|
6075
|
+
/>
|
|
6076
|
+
@if (nameError()) {
|
|
6077
|
+
<span class="field-error">{{ nameError() }}</span>
|
|
6078
|
+
}
|
|
6079
|
+
</div>
|
|
5400
6080
|
<ngt-input
|
|
5401
6081
|
label="Description (optional)"
|
|
5402
6082
|
[value]="presetDescription()"
|
|
@@ -5524,11 +6204,301 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
|
|
|
5524
6204
|
</div>
|
|
5525
6205
|
|
|
5526
6206
|
<div class="form-actions">
|
|
6207
|
+
<ngt-button type="button" (click)="onSwitchToListMode()">Cancel</ngt-button>
|
|
5527
6208
|
<ngt-button type="submit">Save Preset</ngt-button>
|
|
5528
6209
|
</div>
|
|
5529
6210
|
</form>
|
|
5530
6211
|
}
|
|
5531
6212
|
|
|
6213
|
+
<!-- Edit Form -->
|
|
6214
|
+
@if (viewMode() === 'edit') {
|
|
6215
|
+
<form (submit)="onSaveEdit($event)" class="preset-form">
|
|
6216
|
+
<h3 class="form-title">Edit Preset</h3>
|
|
6217
|
+
<div class="form-field">
|
|
6218
|
+
<ngt-input
|
|
6219
|
+
label="Preset Name *"
|
|
6220
|
+
[value]="editName()"
|
|
6221
|
+
(valueChange)="onEditNameChange($event)"
|
|
6222
|
+
placeholder="e.g., Admin User - Full Access"
|
|
6223
|
+
[ariaLabel]="'Preset name'"
|
|
6224
|
+
/>
|
|
6225
|
+
@if (nameError()) {
|
|
6226
|
+
<span class="field-error">{{ nameError() }}</span>
|
|
6227
|
+
}
|
|
6228
|
+
</div>
|
|
6229
|
+
<ngt-input
|
|
6230
|
+
label="Description (optional)"
|
|
6231
|
+
[value]="editDescription()"
|
|
6232
|
+
(valueChange)="editDescription.set($event)"
|
|
6233
|
+
placeholder="Brief description of this preset"
|
|
6234
|
+
[ariaLabel]="'Preset description'"
|
|
6235
|
+
/>
|
|
6236
|
+
|
|
6237
|
+
<!-- Show saved configuration read-only -->
|
|
6238
|
+
@if (editingPreset()) {
|
|
6239
|
+
<div class="config-preview">
|
|
6240
|
+
<h4>Saved Configuration</h4>
|
|
6241
|
+
@if (editingPreset()!.config.featureFlags.enabled.length > 0 || editingPreset()!.config.featureFlags.disabled.length > 0) {
|
|
6242
|
+
<div class="config-category">
|
|
6243
|
+
<span class="config-category__title">Feature Flags ({{ editingPreset()!.config.featureFlags.enabled.length + editingPreset()!.config.featureFlags.disabled.length }})</span>
|
|
6244
|
+
<div class="config-items">
|
|
6245
|
+
@for (id of editingPreset()!.config.featureFlags.enabled; track id) {
|
|
6246
|
+
<span class="config-item config-item--on">{{ id }}: ON</span>
|
|
6247
|
+
}
|
|
6248
|
+
@for (id of editingPreset()!.config.featureFlags.disabled; track id) {
|
|
6249
|
+
<span class="config-item config-item--off">{{ id }}: OFF</span>
|
|
6250
|
+
}
|
|
6251
|
+
</div>
|
|
6252
|
+
</div>
|
|
6253
|
+
}
|
|
6254
|
+
@if (editingPreset()!.config.permissions.granted.length > 0 || editingPreset()!.config.permissions.denied.length > 0) {
|
|
6255
|
+
<div class="config-category">
|
|
6256
|
+
<span class="config-category__title">Permissions ({{ editingPreset()!.config.permissions.granted.length + editingPreset()!.config.permissions.denied.length }})</span>
|
|
6257
|
+
<div class="config-items">
|
|
6258
|
+
@for (id of editingPreset()!.config.permissions.granted; track id) {
|
|
6259
|
+
<span class="config-item config-item--on">{{ id }}: GRANTED</span>
|
|
6260
|
+
}
|
|
6261
|
+
@for (id of editingPreset()!.config.permissions.denied; track id) {
|
|
6262
|
+
<span class="config-item config-item--off">{{ id }}: DENIED</span>
|
|
6263
|
+
}
|
|
6264
|
+
</div>
|
|
6265
|
+
</div>
|
|
6266
|
+
}
|
|
6267
|
+
@if (editingPreset()!.config.appFeatures.enabled.length > 0 || editingPreset()!.config.appFeatures.disabled.length > 0) {
|
|
6268
|
+
<div class="config-category">
|
|
6269
|
+
<span class="config-category__title">App Features ({{ editingPreset()!.config.appFeatures.enabled.length + editingPreset()!.config.appFeatures.disabled.length }})</span>
|
|
6270
|
+
<div class="config-items">
|
|
6271
|
+
@for (id of editingPreset()!.config.appFeatures.enabled; track id) {
|
|
6272
|
+
<span class="config-item config-item--on">{{ id }}: ON</span>
|
|
6273
|
+
}
|
|
6274
|
+
@for (id of editingPreset()!.config.appFeatures.disabled; track id) {
|
|
6275
|
+
<span class="config-item config-item--off">{{ id }}: OFF</span>
|
|
6276
|
+
}
|
|
6277
|
+
</div>
|
|
6278
|
+
</div>
|
|
6279
|
+
}
|
|
6280
|
+
@if (editingPreset()!.config.language) {
|
|
6281
|
+
<div class="config-category">
|
|
6282
|
+
<span class="config-category__title">Language</span>
|
|
6283
|
+
<span class="config-item">{{ editingPreset()!.config.language }}</span>
|
|
6284
|
+
</div>
|
|
6285
|
+
}
|
|
6286
|
+
<button type="button" class="replace-config-button" (click)="onReplaceConfig()">
|
|
6287
|
+
↻ Replace with current toolbar state
|
|
6288
|
+
</button>
|
|
6289
|
+
</div>
|
|
6290
|
+
}
|
|
6291
|
+
|
|
6292
|
+
<div class="form-actions">
|
|
6293
|
+
<ngt-button type="button" (click)="onSwitchToListMode()">Cancel</ngt-button>
|
|
6294
|
+
<ngt-button type="submit">Save Changes</ngt-button>
|
|
6295
|
+
</div>
|
|
6296
|
+
</form>
|
|
6297
|
+
}
|
|
6298
|
+
|
|
6299
|
+
<!-- Import View -->
|
|
6300
|
+
@if (viewMode() === 'import') {
|
|
6301
|
+
<div class="import-view">
|
|
6302
|
+
<h3 class="form-title">Import Preset</h3>
|
|
6303
|
+
|
|
6304
|
+
<!-- File Drop Zone -->
|
|
6305
|
+
<div
|
|
6306
|
+
class="drop-zone"
|
|
6307
|
+
[class.drop-zone--active]="isDragOver()"
|
|
6308
|
+
(dragover)="onDragOver($event)"
|
|
6309
|
+
(dragleave)="onDragLeave($event)"
|
|
6310
|
+
(drop)="onFileDrop($event)"
|
|
6311
|
+
(click)="fileInput.click()"
|
|
6312
|
+
>
|
|
6313
|
+
<input
|
|
6314
|
+
#fileInput
|
|
6315
|
+
type="file"
|
|
6316
|
+
accept=".json"
|
|
6317
|
+
(change)="onFileSelect($event)"
|
|
6318
|
+
hidden
|
|
6319
|
+
/>
|
|
6320
|
+
<span class="drop-zone__icon">📁</span>
|
|
6321
|
+
<span class="drop-zone__text">Drop a .json file here</span>
|
|
6322
|
+
<span class="drop-zone__hint">or click to browse</span>
|
|
6323
|
+
</div>
|
|
6324
|
+
|
|
6325
|
+
<div class="divider">
|
|
6326
|
+
<span>or paste JSON</span>
|
|
6327
|
+
</div>
|
|
6328
|
+
|
|
6329
|
+
<!-- JSON Textarea -->
|
|
6330
|
+
<textarea
|
|
6331
|
+
class="json-textarea"
|
|
6332
|
+
[value]="importJson()"
|
|
6333
|
+
(input)="onImportJsonChange($event)"
|
|
6334
|
+
placeholder='{"name": "...", "config": { ... }}'
|
|
6335
|
+
></textarea>
|
|
6336
|
+
|
|
6337
|
+
@if (importError()) {
|
|
6338
|
+
<span class="field-error">{{ importError() }}</span>
|
|
6339
|
+
}
|
|
6340
|
+
|
|
6341
|
+
<div class="form-actions">
|
|
6342
|
+
<ngt-button type="button" (click)="onSwitchToListMode()">Cancel</ngt-button>
|
|
6343
|
+
<ngt-button (click)="onImportPreset()">Import Preset</ngt-button>
|
|
6344
|
+
</div>
|
|
6345
|
+
</div>
|
|
6346
|
+
}
|
|
6347
|
+
|
|
6348
|
+
<!-- Partial Apply View -->
|
|
6349
|
+
@if (viewMode() === 'apply') {
|
|
6350
|
+
<div class="apply-view">
|
|
6351
|
+
<h3 class="form-title">Apply: {{ applyingPreset()?.name }}</h3>
|
|
6352
|
+
<p class="apply-description">Select which parts to apply</p>
|
|
6353
|
+
|
|
6354
|
+
@if (applyingPreset()) {
|
|
6355
|
+
<div class="apply-categories">
|
|
6356
|
+
<!-- Feature Flags -->
|
|
6357
|
+
@if (applyingPreset()!.config.featureFlags.enabled.length > 0 || applyingPreset()!.config.featureFlags.disabled.length > 0) {
|
|
6358
|
+
<div class="apply-category" [class.apply-category--disabled]="!applyFeatureFlags()">
|
|
6359
|
+
<label class="apply-category__header">
|
|
6360
|
+
<input
|
|
6361
|
+
type="checkbox"
|
|
6362
|
+
[checked]="applyFeatureFlags()"
|
|
6363
|
+
(change)="applyFeatureFlags.set(!applyFeatureFlags())"
|
|
6364
|
+
/>
|
|
6365
|
+
<span>Feature Flags ({{ applyingPreset()!.config.featureFlags.enabled.length + applyingPreset()!.config.featureFlags.disabled.length }})</span>
|
|
6366
|
+
</label>
|
|
6367
|
+
@if (applyFeatureFlags()) {
|
|
6368
|
+
<div class="apply-diff">
|
|
6369
|
+
@for (id of applyingPreset()!.config.featureFlags.enabled; track id) {
|
|
6370
|
+
<div class="diff-item">
|
|
6371
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
6372
|
+
<span class="diff-item__arrow">→</span>
|
|
6373
|
+
<span class="diff-item__value diff-item__value--on">ON</span>
|
|
6374
|
+
</div>
|
|
6375
|
+
}
|
|
6376
|
+
@for (id of applyingPreset()!.config.featureFlags.disabled; track id) {
|
|
6377
|
+
<div class="diff-item">
|
|
6378
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
6379
|
+
<span class="diff-item__arrow">→</span>
|
|
6380
|
+
<span class="diff-item__value diff-item__value--off">OFF</span>
|
|
6381
|
+
</div>
|
|
6382
|
+
}
|
|
6383
|
+
</div>
|
|
6384
|
+
}
|
|
6385
|
+
</div>
|
|
6386
|
+
}
|
|
6387
|
+
|
|
6388
|
+
<!-- Permissions -->
|
|
6389
|
+
@if (applyingPreset()!.config.permissions.granted.length > 0 || applyingPreset()!.config.permissions.denied.length > 0) {
|
|
6390
|
+
<div class="apply-category" [class.apply-category--disabled]="!applyPermissions()">
|
|
6391
|
+
<label class="apply-category__header">
|
|
6392
|
+
<input
|
|
6393
|
+
type="checkbox"
|
|
6394
|
+
[checked]="applyPermissions()"
|
|
6395
|
+
(change)="applyPermissions.set(!applyPermissions())"
|
|
6396
|
+
/>
|
|
6397
|
+
<span>Permissions ({{ applyingPreset()!.config.permissions.granted.length + applyingPreset()!.config.permissions.denied.length }})</span>
|
|
6398
|
+
</label>
|
|
6399
|
+
@if (applyPermissions()) {
|
|
6400
|
+
<div class="apply-diff">
|
|
6401
|
+
@for (id of applyingPreset()!.config.permissions.granted; track id) {
|
|
6402
|
+
<div class="diff-item">
|
|
6403
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
6404
|
+
<span class="diff-item__arrow">→</span>
|
|
6405
|
+
<span class="diff-item__value diff-item__value--on">GRANTED</span>
|
|
6406
|
+
</div>
|
|
6407
|
+
}
|
|
6408
|
+
@for (id of applyingPreset()!.config.permissions.denied; track id) {
|
|
6409
|
+
<div class="diff-item">
|
|
6410
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
6411
|
+
<span class="diff-item__arrow">→</span>
|
|
6412
|
+
<span class="diff-item__value diff-item__value--off">DENIED</span>
|
|
6413
|
+
</div>
|
|
6414
|
+
}
|
|
6415
|
+
</div>
|
|
6416
|
+
}
|
|
6417
|
+
</div>
|
|
6418
|
+
}
|
|
6419
|
+
|
|
6420
|
+
<!-- App Features -->
|
|
6421
|
+
@if (applyingPreset()!.config.appFeatures.enabled.length > 0 || applyingPreset()!.config.appFeatures.disabled.length > 0) {
|
|
6422
|
+
<div class="apply-category" [class.apply-category--disabled]="!applyAppFeatures()">
|
|
6423
|
+
<label class="apply-category__header">
|
|
6424
|
+
<input
|
|
6425
|
+
type="checkbox"
|
|
6426
|
+
[checked]="applyAppFeatures()"
|
|
6427
|
+
(change)="applyAppFeatures.set(!applyAppFeatures())"
|
|
6428
|
+
/>
|
|
6429
|
+
<span>App Features ({{ applyingPreset()!.config.appFeatures.enabled.length + applyingPreset()!.config.appFeatures.disabled.length }})</span>
|
|
6430
|
+
</label>
|
|
6431
|
+
@if (applyAppFeatures()) {
|
|
6432
|
+
<div class="apply-diff">
|
|
6433
|
+
@for (id of applyingPreset()!.config.appFeatures.enabled; track id) {
|
|
6434
|
+
<div class="diff-item">
|
|
6435
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
6436
|
+
<span class="diff-item__arrow">→</span>
|
|
6437
|
+
<span class="diff-item__value diff-item__value--on">ON</span>
|
|
6438
|
+
</div>
|
|
6439
|
+
}
|
|
6440
|
+
@for (id of applyingPreset()!.config.appFeatures.disabled; track id) {
|
|
6441
|
+
<div class="diff-item">
|
|
6442
|
+
<span class="diff-item__name">{{ id }}</span>
|
|
6443
|
+
<span class="diff-item__arrow">→</span>
|
|
6444
|
+
<span class="diff-item__value diff-item__value--off">OFF</span>
|
|
6445
|
+
</div>
|
|
6446
|
+
}
|
|
6447
|
+
</div>
|
|
6448
|
+
}
|
|
6449
|
+
</div>
|
|
6450
|
+
}
|
|
6451
|
+
|
|
6452
|
+
<!-- Language -->
|
|
6453
|
+
@if (applyingPreset()!.config.language) {
|
|
6454
|
+
<div class="apply-category" [class.apply-category--disabled]="!applyLanguage()">
|
|
6455
|
+
<label class="apply-category__header">
|
|
6456
|
+
<input
|
|
6457
|
+
type="checkbox"
|
|
6458
|
+
[checked]="applyLanguage()"
|
|
6459
|
+
(change)="applyLanguage.set(!applyLanguage())"
|
|
6460
|
+
/>
|
|
6461
|
+
<span>Language</span>
|
|
6462
|
+
</label>
|
|
6463
|
+
@if (applyLanguage()) {
|
|
6464
|
+
<div class="apply-diff">
|
|
6465
|
+
<div class="diff-item">
|
|
6466
|
+
<span class="diff-item__name">Language</span>
|
|
6467
|
+
<span class="diff-item__arrow">→</span>
|
|
6468
|
+
<span class="diff-item__value">{{ applyingPreset()!.config.language }}</span>
|
|
6469
|
+
</div>
|
|
6470
|
+
</div>
|
|
6471
|
+
}
|
|
6472
|
+
</div>
|
|
6473
|
+
}
|
|
6474
|
+
</div>
|
|
6475
|
+
}
|
|
6476
|
+
|
|
6477
|
+
<div class="form-actions">
|
|
6478
|
+
<ngt-button type="button" (click)="onSwitchToListMode()">Cancel</ngt-button>
|
|
6479
|
+
<ngt-button (click)="onConfirmPartialApply()">Apply Selected</ngt-button>
|
|
6480
|
+
</div>
|
|
6481
|
+
</div>
|
|
6482
|
+
}
|
|
6483
|
+
|
|
6484
|
+
<!-- Delete Confirmation View -->
|
|
6485
|
+
@if (viewMode() === 'delete') {
|
|
6486
|
+
<div class="delete-view">
|
|
6487
|
+
<div class="delete-view__content">
|
|
6488
|
+
<div class="delete-view__icon">🗑️</div>
|
|
6489
|
+
<h3 class="delete-view__title">Delete "{{ deletePresetName() }}"?</h3>
|
|
6490
|
+
<p class="delete-view__description">
|
|
6491
|
+
This preset will be permanently removed.
|
|
6492
|
+
This action cannot be undone.
|
|
6493
|
+
</p>
|
|
6494
|
+
</div>
|
|
6495
|
+
<div class="form-actions">
|
|
6496
|
+
<ngt-button type="button" (click)="onSwitchToListMode()">← Back</ngt-button>
|
|
6497
|
+
<button class="delete-button" (click)="onConfirmDelete()">Delete Preset</button>
|
|
6498
|
+
</div>
|
|
6499
|
+
</div>
|
|
6500
|
+
}
|
|
6501
|
+
|
|
5532
6502
|
<!-- Empty State -->
|
|
5533
6503
|
@if (viewMode() === 'list' && hasNoPresets()) {
|
|
5534
6504
|
<div class="empty">
|
|
@@ -5547,83 +6517,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
|
|
|
5547
6517
|
} @else if (viewMode() === 'list') {
|
|
5548
6518
|
<!-- Preset List -->
|
|
5549
6519
|
<div class="preset-list">
|
|
5550
|
-
@for (preset of
|
|
5551
|
-
<div class="preset-card">
|
|
6520
|
+
@for (preset of sortedPresets(); track preset.id) {
|
|
6521
|
+
<div class="preset-card" [title]="getPresetTooltip(preset)">
|
|
5552
6522
|
<div class="preset-card__header">
|
|
5553
|
-
<
|
|
6523
|
+
<button
|
|
6524
|
+
class="favorite-button"
|
|
6525
|
+
[class.favorite-button--active]="preset.isFavorite"
|
|
6526
|
+
(click)="onToggleFavorite(preset.id); $event.stopPropagation()"
|
|
6527
|
+
[attr.aria-label]="preset.isFavorite ? 'Remove from favorites' : 'Add to favorites'"
|
|
6528
|
+
>{{ preset.isFavorite ? '★' : '☆' }}</button>
|
|
6529
|
+
<span class="preset-card__name">{{ preset.name }}</span>
|
|
6530
|
+
@if (preset.isSystem) {<span class="system-badge">SYS</span>}
|
|
6531
|
+
<span class="preset-card__spacer"></span>
|
|
5554
6532
|
<div class="preset-card__actions">
|
|
5555
|
-
<button
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
>
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
class="icon-button"
|
|
5565
|
-
(click)="onUpdatePreset(preset.id)"
|
|
5566
|
-
[attr.aria-label]="'Update preset ' + preset.name"
|
|
5567
|
-
title="Update with current state"
|
|
5568
|
-
>
|
|
5569
|
-
<ngt-icon name="gear" />
|
|
5570
|
-
</button>
|
|
5571
|
-
<button
|
|
5572
|
-
class="icon-button"
|
|
5573
|
-
(click)="onExportPreset(preset.id)"
|
|
5574
|
-
[attr.aria-label]="'Export preset ' + preset.name"
|
|
5575
|
-
title="Export as JSON"
|
|
5576
|
-
>
|
|
5577
|
-
<ngt-icon name="export" />
|
|
5578
|
-
</button>
|
|
5579
|
-
<button
|
|
5580
|
-
class="icon-button"
|
|
5581
|
-
(click)="onDeletePreset(preset.id)"
|
|
5582
|
-
[attr.aria-label]="'Delete preset ' + preset.name"
|
|
5583
|
-
title="Delete preset"
|
|
5584
|
-
>
|
|
5585
|
-
<ngt-icon name="trash" />
|
|
5586
|
-
</button>
|
|
6533
|
+
<button class="icon-button" (click)="onStartApply(preset.id)"><ngt-icon name="refresh" /></button>
|
|
6534
|
+
@if (!preset.isSystem) {
|
|
6535
|
+
<button class="icon-button" (click)="onStartEdit(preset.id)"><ngt-icon name="edit" /></button>
|
|
6536
|
+
<button class="icon-button" (click)="onUpdatePreset(preset.id)"><ngt-icon name="gear" /></button>
|
|
6537
|
+
}
|
|
6538
|
+
<button class="icon-button" (click)="onExportPreset(preset.id)"><ngt-icon name="export" /></button>
|
|
6539
|
+
@if (!preset.isSystem) {
|
|
6540
|
+
<button class="icon-button" (click)="onDeletePreset(preset.id)"><ngt-icon name="trash" /></button>
|
|
6541
|
+
}
|
|
5587
6542
|
</div>
|
|
5588
6543
|
</div>
|
|
5589
6544
|
@if (preset.description) {
|
|
5590
|
-
<
|
|
5591
|
-
|
|
5592
|
-
<div class="preset-card__meta">
|
|
5593
|
-
<span>Updated: {{ formatDate(preset.updatedAt) }}</span>
|
|
6545
|
+
<div class="preset-card__row preset-card__row--meta">
|
|
6546
|
+
<span class="preset-card__description">{{ preset.description }}</span>
|
|
5594
6547
|
</div>
|
|
5595
|
-
|
|
5596
|
-
<div class="preset-
|
|
5597
|
-
@if (preset.config.featureFlags.enabled.length > 0 ||
|
|
5598
|
-
preset.config.featureFlags.disabled.length >
|
|
5599
|
-
<span class="badge">
|
|
5600
|
-
{{
|
|
5601
|
-
preset.config.featureFlags.enabled.length +
|
|
5602
|
-
preset.config.featureFlags.disabled.length
|
|
5603
|
-
}}
|
|
5604
|
-
flags
|
|
5605
|
-
</span>
|
|
5606
|
-
} @if (preset.config.permissions.granted.length > 0 ||
|
|
5607
|
-
preset.config.permissions.denied.length > 0) {
|
|
5608
|
-
<span class="badge">
|
|
5609
|
-
{{
|
|
5610
|
-
preset.config.permissions.granted.length +
|
|
5611
|
-
preset.config.permissions.denied.length
|
|
5612
|
-
}}
|
|
5613
|
-
perms
|
|
5614
|
-
</span>
|
|
5615
|
-
} @if (preset.config.appFeatures.enabled.length > 0 ||
|
|
5616
|
-
preset.config.appFeatures.disabled.length > 0) {
|
|
5617
|
-
<span class="badge">
|
|
5618
|
-
{{
|
|
5619
|
-
preset.config.appFeatures.enabled.length +
|
|
5620
|
-
preset.config.appFeatures.disabled.length
|
|
5621
|
-
}}
|
|
5622
|
-
features
|
|
5623
|
-
</span>
|
|
5624
|
-
} @if (preset.config.language) {
|
|
5625
|
-
<span class="badge">{{ preset.config.language }}</span>
|
|
6548
|
+
}
|
|
6549
|
+
<div class="preset-card__row preset-card__row--badges">
|
|
6550
|
+
@if (preset.config.featureFlags.enabled.length > 0 || preset.config.featureFlags.disabled.length > 0) {
|
|
6551
|
+
<span class="badge">{{ preset.config.featureFlags.enabled.length + preset.config.featureFlags.disabled.length }} flags</span>
|
|
5626
6552
|
}
|
|
6553
|
+
@if (preset.config.permissions.granted.length > 0 || preset.config.permissions.denied.length > 0) {
|
|
6554
|
+
<span class="badge">{{ preset.config.permissions.granted.length + preset.config.permissions.denied.length }} perms</span>
|
|
6555
|
+
}
|
|
6556
|
+
@if (preset.config.appFeatures.enabled.length > 0 || preset.config.appFeatures.disabled.length > 0) {
|
|
6557
|
+
<span class="badge">{{ preset.config.appFeatures.enabled.length + preset.config.appFeatures.disabled.length }} features</span>
|
|
6558
|
+
}
|
|
6559
|
+
@if (preset.config.language) {
|
|
6560
|
+
<span class="badge badge--lang">{{ preset.config.language }}</span>
|
|
6561
|
+
}
|
|
6562
|
+
<span class="preset-card__date">{{ formatDate(preset.updatedAt) }}</span>
|
|
5627
6563
|
</div>
|
|
5628
6564
|
</div>
|
|
5629
6565
|
}
|
|
@@ -5631,8 +6567,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
|
|
|
5631
6567
|
}
|
|
5632
6568
|
</div>
|
|
5633
6569
|
</ngt-toolbar-tool>
|
|
5634
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ngt-spacing-sm);margin-bottom:var(--ngt-spacing-md);ngt-input{flex:1}ngt-button{flex-shrink:0}}.empty{display:flex;flex-direction:column;gap:var(--ngt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ngt-border-subtle);border-radius:var(--ngt-border-radius-medium);padding:var(--ngt-spacing-md);background:transparent;color:var(--ngt-text-muted);text-align:center;p{margin:0}.hint{font-size:var(--ngt-font-size-xs)}}.preset-list{display:flex;flex-direction:column;gap:var(--ngt-spacing-md);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ngt-spacing-sm);&::-webkit-scrollbar{width:8px}&::-webkit-scrollbar-track{background:var(--ngt-background-secondary);border-radius:4px}&::-webkit-scrollbar-thumb{background:var(--ngt-border-primary);border-radius:4px;&:hover{background:var(--ngt-hover-bg)}}scrollbar-width:thin;scrollbar-color:var(--ngt-border-primary) var(--ngt-background-secondary)}.preset-card{background:var(--ngt-background-secondary);padding:var(--ngt-spacing-md);border-radius:var(--ngt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ngt-spacing-sm)}.preset-card__header{display:flex;justify-content:space-between;align-items:center;gap:var(--ngt-spacing-sm);h3{margin:0;font-size:var(--ngt-font-size-md);color:var(--ngt-text-primary);flex:1}}.preset-card__actions{display:flex;gap:var(--ngt-spacing-xs)}.icon-button{background:transparent;border:none;cursor:pointer;padding:var(--ngt-spacing-xs);border-radius:var(--ngt-border-radius-small);color:var(--ngt-text-secondary);display:flex;align-items:center;justify-content:center;&:hover{background:var(--ngt-hover-bg);color:var(--ngt-text-primary)}ngt-icon{width:16px;height:16px}}.preset-card__description{margin:0;font-size:var(--ngt-font-size-sm);color:var(--ngt-text-secondary)}.preset-card__meta{font-size:var(--ngt-font-size-xs);color:var(--ngt-text-muted);span{margin-right:var(--ngt-spacing-sm)}}.preset-card__preview{display:flex;gap:var(--ngt-spacing-xs);flex-wrap:wrap}.badge{background:var(--ngt-primary-color);color:#fff;padding:2px 8px;border-radius:12px;font-size:var(--ngt-font-size-xs);font-weight:500}.preset-form{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--ngt-spacing-md);padding:var(--ngt-spacing-md);ngt-input{width:100%}}.preset-summary{background:var(--ngt-background-secondary);padding:var(--ngt-spacing-md);border-radius:var(--ngt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ngt-spacing-sm);h4{margin:0;font-size:var(--ngt-font-size-sm);color:var(--ngt-text-primary)}}.category-section{display:flex;flex-direction:column;gap:var(--ngt-spacing-xs)}.checkbox-option{display:flex;align-items:center;gap:var(--ngt-spacing-sm);cursor:pointer;color:var(--ngt-text-secondary);font-size:var(--ngt-font-size-sm);input[type=checkbox]{cursor:pointer;width:16px;height:16px;accent-color:var(--ngt-primary);&:disabled{cursor:not-allowed;opacity:.5}}&:has(input:disabled){opacity:.6;cursor:not-allowed}}.forced-items-list{list-style:none;padding:0;margin:0 0 0 var(--ngt-spacing-lg);display:flex;flex-direction:column;gap:var(--ngt-spacing-xs);font-size:var(--ngt-font-size-xs);li{background:rgba(var(--ngt-primary-rgb),.05);border-radius:var(--ngt-border-radius-small);border-left:2px solid rgba(var(--ngt-primary-rgb),.3)}.item-checkbox{display:flex;justify-content:space-between;align-items:center;padding:var(--ngt-spacing-xs) var(--ngt-spacing-sm);cursor:pointer;gap:var(--ngt-spacing-sm);input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:var(--ngt-primary);flex-shrink:0}&:hover{background:rgba(var(--ngt-primary-rgb),.08)}}.item-name{color:var(--ngt-text-primary);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item-status{font-weight:600;padding:2px 6px;border-radius:var(--ngt-border-radius-small);font-size:10px;text-transform:uppercase;letter-spacing:.5px;flex-shrink:0;&.enabled{background:#22c55e26;color:#22c55e}&.disabled{background:#ef444426;color:#ef4444}}}.form-actions{display:flex;justify-content:flex-end;gap:var(--ngt-spacing-sm)}\n"] }]
|
|
5635
|
-
}] });
|
|
6570
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".container{position:relative;display:flex;flex-direction:column;height:100%;padding:0}.toast{position:absolute;bottom:var(--ngt-spacing-md);left:var(--ngt-spacing-md);right:var(--ngt-spacing-md);z-index:10;display:flex;align-items:center;gap:var(--ngt-spacing-sm);padding:var(--ngt-spacing-sm) var(--ngt-spacing-md);border-radius:var(--ngt-border-radius-small);font-size:var(--ngt-font-size-sm);animation:slideUp .15s ease-out}.toast--success{background:#22c55e;color:#fff}.toast--error{background:#ef4444;color:#fff}.toast__icon{font-weight:700}@keyframes slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.delete-view{flex:1;display:flex;flex-direction:column;justify-content:center;padding:var(--ngt-spacing-md)}.delete-view__content{text-align:center;padding:var(--ngt-spacing-lg) var(--ngt-spacing-md)}.delete-view__icon{font-size:48px;margin-bottom:var(--ngt-spacing-md)}.delete-view__title{margin:0 0 var(--ngt-spacing-sm);font-size:var(--ngt-font-size-md);color:var(--ngt-text-primary)}.delete-view__description{margin:0;font-size:var(--ngt-font-size-sm);color:var(--ngt-text-secondary);line-height:1.5}.delete-button{background:#ef4444;color:#fff;border:none;padding:var(--ngt-spacing-sm) var(--ngt-spacing-md);border-radius:var(--ngt-border-radius-small);cursor:pointer;font-size:var(--ngt-font-size-sm);font-weight:500;transition:background .2s ease-out;&:hover{background:#dc2626}}.tool-header{position:relative;flex-shrink:0;display:flex;gap:var(--ngt-spacing-sm);margin-bottom:var(--ngt-spacing-md);ngt-input{flex:1}ngt-button{flex-shrink:0}}.empty{display:flex;flex-direction:column;gap:var(--ngt-spacing-md);flex:1;min-height:0;justify-content:center;align-items:center;border:1px solid var(--ngt-border-subtle);border-radius:var(--ngt-border-radius-medium);padding:var(--ngt-spacing-md);background:transparent;color:var(--ngt-text-muted);text-align:center;p{margin:0}.hint{font-size:var(--ngt-font-size-xs)}}.preset-list{display:flex;flex-direction:column;gap:var(--ngt-spacing-xs);flex:1;min-height:0;overflow-y:auto;padding-right:var(--ngt-spacing-xs);&::-webkit-scrollbar{width:8px}&::-webkit-scrollbar-track{background:var(--ngt-background-secondary);border-radius:4px}&::-webkit-scrollbar-thumb{background:var(--ngt-border-primary);border-radius:4px;&:hover{background:var(--ngt-hover-bg)}}scrollbar-width:thin;scrollbar-color:var(--ngt-border-primary) var(--ngt-background-secondary)}.preset-card{background:var(--ngt-background-secondary);padding:6px var(--ngt-spacing-sm);border-radius:var(--ngt-border-radius-medium);display:flex;flex-direction:column;gap:2px}.preset-card__header{display:flex;align-items:center;gap:6px;flex-wrap:nowrap}.preset-card__row{display:flex;align-items:center;gap:6px;min-height:18px}.preset-card__row--meta{padding-left:18px}.preset-card__row--badges{padding-left:18px;gap:4px}.preset-card__name{font-size:var(--ngt-font-size-sm);font-weight:600;color:var(--ngt-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__spacer{flex:1;min-width:8px}.system-badge{font-size:8px;font-weight:600;text-transform:uppercase;letter-spacing:.3px;padding:1px 4px;border-radius:3px;background:var(--ngt-border-primary);color:var(--ngt-text-muted);flex-shrink:0}.favorite-button{background:transparent;border:none;cursor:pointer;font-size:12px;color:var(--ngt-text-muted);padding:0;line-height:1;transition:color .15s ease-out;flex-shrink:0}.favorite-button:hover,.favorite-button--active{color:#f59e0b}.preset-card__actions{display:flex;gap:0;flex-shrink:0}.icon-button{appearance:none;background:none;border:none;cursor:pointer;margin:0;padding:4px;border-radius:4px;color:var(--ngt-text-muted);display:inline-flex;align-items:center;justify-content:center;opacity:.5;transition:opacity .15s ease-out,color .15s ease-out;line-height:0;&:hover{background:var(--ngt-hover-bg);color:var(--ngt-text-primary);opacity:1}ngt-icon,ngt-icon>*,svg{display:block;width:12px!important;height:12px!important}}.preset-card__description{font-size:11px;color:var(--ngt-text-secondary);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preset-card__date{font-size:10px;color:var(--ngt-text-muted);margin-left:auto;flex-shrink:0}.badge{background:#6366f126;color:#6366f1;padding:1px 6px;border-radius:8px;font-size:10px;font-weight:500;white-space:nowrap}.badge--lang{background:#22c55e26;color:#22c55e}.preset-form,.import-view,.apply-view{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:var(--ngt-spacing-sm);padding:var(--ngt-spacing-sm);ngt-input{width:100%}}.form-title{margin:0;font-size:var(--ngt-font-size-sm);font-weight:600;color:var(--ngt-text-primary)}.form-hint{margin:0;font-size:11px;color:var(--ngt-text-muted);line-height:1.3}.form-field{display:flex;flex-direction:column;gap:2px}.field-error{color:#ef4444;font-size:11px}.preset-summary{background:var(--ngt-background-secondary);padding:var(--ngt-spacing-sm);border-radius:var(--ngt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ngt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ngt-text-secondary)}}.category-section{display:flex;flex-direction:column;gap:2px}.checkbox-option{display:flex;align-items:center;gap:var(--ngt-spacing-xs);cursor:pointer;color:var(--ngt-text-primary);font-size:var(--ngt-font-size-sm);padding:2px 0;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241);border-radius:3px;&:disabled{cursor:not-allowed;opacity:.4}}&:has(input:disabled){opacity:.5;cursor:not-allowed}}.forced-items-list{list-style:none;padding:0;margin:0 0 0 20px;display:flex;flex-direction:column;gap:2px;font-size:11px;max-height:100px;overflow-y:auto;li{background:#6366f10d;border-radius:3px;border-left:2px solid rgba(99,102,241,.3)}.item-checkbox{display:flex;justify-content:space-between;align-items:center;padding:3px 6px;cursor:pointer;gap:6px;input[type=checkbox]{cursor:pointer;width:12px;height:12px;accent-color:rgb(99,102,241);flex-shrink:0}&:hover{background:#6366f114}}.item-name{color:var(--ngt-text-primary);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item-status{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px;flex-shrink:0;&.enabled{background:#22c55e26;color:#22c55e}&.disabled{background:#ef444426;color:#ef4444}}}.form-actions{display:flex;justify-content:flex-end;gap:var(--ngt-spacing-sm);margin-top:auto;padding-top:var(--ngt-spacing-sm)}.config-preview{background:var(--ngt-background-secondary);padding:var(--ngt-spacing-sm);border-radius:var(--ngt-border-radius-medium);display:flex;flex-direction:column;gap:var(--ngt-spacing-xs);h4{margin:0;font-size:11px;font-weight:500;color:var(--ngt-text-secondary)}}.config-category{display:flex;flex-direction:column;gap:2px}.config-category__title{font-size:10px;color:var(--ngt-text-muted);font-weight:500}.config-items{display:flex;flex-wrap:wrap;gap:4px}.config-item{font-size:10px;padding:1px 6px;border-radius:3px;background:var(--ngt-background-primary);color:var(--ngt-text-secondary)}.config-item--on{background:#22c55e1a;color:#22c55e}.config-item--off{background:#ef44441a;color:#ef4444}.replace-config-button{background:transparent;border:1px dashed var(--ngt-border-primary);padding:6px var(--ngt-spacing-sm);border-radius:var(--ngt-border-radius-small);color:var(--ngt-text-secondary);cursor:pointer;font-size:11px;transition:all .15s ease-out;&:hover{background:var(--ngt-hover-bg);border-color:#6366f1;color:#6366f1}}.drop-zone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:var(--ngt-spacing-md);border:2px dashed var(--ngt-border-primary);border-radius:var(--ngt-border-radius-medium);cursor:pointer;transition:all .15s ease-out}.drop-zone:hover,.drop-zone--active{border-color:#6366f1;background:#6366f10d}.drop-zone__icon{font-size:24px}.drop-zone__text{font-size:var(--ngt-font-size-sm);color:var(--ngt-text-primary)}.drop-zone__hint{font-size:11px;color:var(--ngt-text-muted)}.divider{display:flex;align-items:center;gap:var(--ngt-spacing-sm);color:var(--ngt-text-muted);font-size:10px;&:before,&:after{content:\"\";flex:1;height:1px;background:var(--ngt-border-primary)}}.json-textarea{width:100%;min-height:80px;padding:var(--ngt-spacing-xs);border:1px solid var(--ngt-border-primary);border-radius:var(--ngt-border-radius-small);background:var(--ngt-background-secondary);color:var(--ngt-text-primary);font-family:monospace;font-size:11px;resize:vertical;&:focus{outline:none;border-color:#6366f1}&::placeholder{color:var(--ngt-text-muted)}}.apply-description{margin:0;font-size:11px;color:var(--ngt-text-secondary)}.apply-categories{display:flex;flex-direction:column;gap:var(--ngt-spacing-xs)}.apply-category{background:var(--ngt-background-secondary);border-radius:var(--ngt-border-radius-small);overflow:hidden;transition:opacity .15s ease-out}.apply-category--disabled{opacity:.5}.apply-category__header{display:flex;align-items:center;gap:var(--ngt-spacing-xs);padding:6px var(--ngt-spacing-sm);cursor:pointer;font-size:var(--ngt-font-size-sm);color:var(--ngt-text-primary);font-weight:500;input[type=checkbox]{cursor:pointer;width:14px;height:14px;accent-color:rgb(99,102,241)}}.apply-diff{padding:0 var(--ngt-spacing-sm) 6px;display:flex;flex-direction:column;gap:2px}.diff-item{display:flex;align-items:center;gap:6px;font-size:11px;padding:3px 6px;background:var(--ngt-background-primary);border-radius:3px}.diff-item__name{flex:1;color:var(--ngt-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.diff-item__arrow{color:var(--ngt-text-muted);font-size:10px}.diff-item__value{font-weight:600;padding:1px 4px;border-radius:3px;font-size:9px;text-transform:uppercase;letter-spacing:.3px}.diff-item__value--on{background:#22c55e26;color:#22c55e}.diff-item__value--off{background:#ef444426;color:#ef4444}\n"] }]
|
|
6571
|
+
}], ctorParameters: () => [] });
|
|
5636
6572
|
|
|
5637
6573
|
class ToolbarComponent {
|
|
5638
6574
|
constructor() {
|
|
@@ -5934,6 +6870,68 @@ function initToolbar(appRef, options) {
|
|
|
5934
6870
|
};
|
|
5935
6871
|
}
|
|
5936
6872
|
|
|
6873
|
+
class ToolbarStepDirective {
|
|
6874
|
+
constructor() {
|
|
6875
|
+
this.ngtStep = input.required();
|
|
6876
|
+
this.stepTitle = input('');
|
|
6877
|
+
this.templateRef = inject(TemplateRef);
|
|
6878
|
+
}
|
|
6879
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStepDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
6880
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.0.7", type: ToolbarStepDirective, isStandalone: true, selector: "[ngtStep]", inputs: { ngtStep: { classPropertyName: "ngtStep", publicName: "ngtStep", isSignal: true, isRequired: true, transformFunction: null }, stepTitle: { classPropertyName: "stepTitle", publicName: "stepTitle", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
|
|
6881
|
+
}
|
|
6882
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStepDirective, decorators: [{
|
|
6883
|
+
type: Directive,
|
|
6884
|
+
args: [{
|
|
6885
|
+
selector: '[ngtStep]',
|
|
6886
|
+
standalone: true,
|
|
6887
|
+
}]
|
|
6888
|
+
}] });
|
|
6889
|
+
|
|
6890
|
+
class ToolbarStepViewComponent {
|
|
6891
|
+
constructor() {
|
|
6892
|
+
this.currentStep = input.required();
|
|
6893
|
+
this.defaultStep = input('list');
|
|
6894
|
+
this.back = output();
|
|
6895
|
+
this.steps = contentChildren(ToolbarStepDirective);
|
|
6896
|
+
this.isDefaultStep = computed(() => this.currentStep() === this.defaultStep());
|
|
6897
|
+
this.activeStep = computed(() => this.steps().find((s) => s.ngtStep() === this.currentStep()));
|
|
6898
|
+
this.activeTitle = computed(() => this.activeStep()?.stepTitle() ?? '');
|
|
6899
|
+
this.activeTemplate = computed(() => this.activeStep()?.templateRef ?? null);
|
|
6900
|
+
}
|
|
6901
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStepViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6902
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.7", type: ToolbarStepViewComponent, isStandalone: true, selector: "ngt-step-view", inputs: { currentStep: { classPropertyName: "currentStep", publicName: "currentStep", isSignal: true, isRequired: true, transformFunction: null }, defaultStep: { classPropertyName: "defaultStep", publicName: "defaultStep", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { back: "back" }, queries: [{ propertyName: "steps", predicate: ToolbarStepDirective, isSignal: true }], ngImport: i0, template: `
|
|
6903
|
+
@if (!isDefaultStep()) {
|
|
6904
|
+
<div class="step-header">
|
|
6905
|
+
<ngt-button (click)="back.emit()" ariaLabel="Back">\u2190 Back</ngt-button>
|
|
6906
|
+
@if (activeTitle()) {
|
|
6907
|
+
<span class="step-title">{{ activeTitle() }}</span>
|
|
6908
|
+
}
|
|
6909
|
+
</div>
|
|
6910
|
+
}
|
|
6911
|
+
|
|
6912
|
+
@if (activeTemplate(); as tmpl) {
|
|
6913
|
+
<ng-container [ngTemplateOutlet]="tmpl" />
|
|
6914
|
+
}
|
|
6915
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column}.step-header{display:flex;align-items:center;gap:var(--ngt-spacing-sm);padding-bottom:var(--ngt-spacing-sm);margin-bottom:var(--ngt-spacing-sm);border-bottom:1px solid var(--ngt-border-primary)}.step-title{font-size:var(--ngt-font-size-md);font-weight:600;color:var(--ngt-text-primary)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ToolbarButtonComponent, selector: "ngt-button", inputs: ["type", "variant", "icon", "label", "ariaLabel", "isActive"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6916
|
+
}
|
|
6917
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImport: i0, type: ToolbarStepViewComponent, decorators: [{
|
|
6918
|
+
type: Component,
|
|
6919
|
+
args: [{ selector: 'ngt-step-view', standalone: true, imports: [NgTemplateOutlet, ToolbarButtonComponent], template: `
|
|
6920
|
+
@if (!isDefaultStep()) {
|
|
6921
|
+
<div class="step-header">
|
|
6922
|
+
<ngt-button (click)="back.emit()" ariaLabel="Back">\u2190 Back</ngt-button>
|
|
6923
|
+
@if (activeTitle()) {
|
|
6924
|
+
<span class="step-title">{{ activeTitle() }}</span>
|
|
6925
|
+
}
|
|
6926
|
+
</div>
|
|
6927
|
+
}
|
|
6928
|
+
|
|
6929
|
+
@if (activeTemplate(); as tmpl) {
|
|
6930
|
+
<ng-container [ngTemplateOutlet]="tmpl" />
|
|
6931
|
+
}
|
|
6932
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:flex;flex-direction:column}.step-header{display:flex;align-items:center;gap:var(--ngt-spacing-sm);padding-bottom:var(--ngt-spacing-sm);margin-bottom:var(--ngt-spacing-sm);border-bottom:1px solid var(--ngt-border-primary)}.step-title{font-size:var(--ngt-font-size-md);font-weight:600;color:var(--ngt-text-primary)}\n"] }]
|
|
6933
|
+
}] });
|
|
6934
|
+
|
|
5937
6935
|
/**
|
|
5938
6936
|
* Public service for managing dev toolbar presets.
|
|
5939
6937
|
* Allows developers to programmatically save, load, and manage presets.
|
|
@@ -5978,6 +6976,30 @@ class ToolbarPresetsService {
|
|
|
5978
6976
|
deletePreset(presetId) {
|
|
5979
6977
|
this.internalService.deletePreset(presetId);
|
|
5980
6978
|
}
|
|
6979
|
+
/**
|
|
6980
|
+
* Toggle favorite status for a preset
|
|
6981
|
+
* @param presetId - ID of the preset to toggle
|
|
6982
|
+
*/
|
|
6983
|
+
toggleFavorite(presetId) {
|
|
6984
|
+
this.internalService.toggleFavorite(presetId);
|
|
6985
|
+
}
|
|
6986
|
+
/**
|
|
6987
|
+
* Apply a preset with partial options (only selected categories)
|
|
6988
|
+
* @param presetId - ID of the preset to apply
|
|
6989
|
+
* @param options - Options for which categories to apply
|
|
6990
|
+
*/
|
|
6991
|
+
async partialApplyPreset(presetId, options) {
|
|
6992
|
+
return this.internalService.partialApplyPreset(presetId, options);
|
|
6993
|
+
}
|
|
6994
|
+
/**
|
|
6995
|
+
* Update only the metadata (name, description) of a preset
|
|
6996
|
+
* @param presetId - ID of the preset to update
|
|
6997
|
+
* @param name - New name for the preset
|
|
6998
|
+
* @param description - New description for the preset
|
|
6999
|
+
*/
|
|
7000
|
+
updatePresetMetadata(presetId, name, description) {
|
|
7001
|
+
this.internalService.updatePresetMetadata(presetId, name, description);
|
|
7002
|
+
}
|
|
5981
7003
|
/**
|
|
5982
7004
|
* Export a preset as JSON string
|
|
5983
7005
|
* @param presetId - ID of the preset to export
|
|
@@ -6002,9 +7024,10 @@ class ToolbarPresetsService {
|
|
|
6002
7024
|
/**
|
|
6003
7025
|
* Initialize presets with predefined configurations.
|
|
6004
7026
|
* Useful for setting up default presets that all developers can use.
|
|
7027
|
+
* Skips presets that already exist (by name) to avoid duplicates.
|
|
6005
7028
|
*
|
|
6006
7029
|
* @param presets - Array of preset configurations to initialize
|
|
6007
|
-
* @returns Array of created presets
|
|
7030
|
+
* @returns Array of created presets (only newly added ones)
|
|
6008
7031
|
*
|
|
6009
7032
|
* @example
|
|
6010
7033
|
* ```typescript
|
|
@@ -6053,10 +7076,15 @@ class ToolbarPresetsService {
|
|
|
6053
7076
|
* ```
|
|
6054
7077
|
*/
|
|
6055
7078
|
initializePresets(presets) {
|
|
6056
|
-
|
|
7079
|
+
const existingPresets = this.internalService.presets();
|
|
7080
|
+
const existingNames = new Set(existingPresets.map((p) => p.name.toLowerCase()));
|
|
7081
|
+
return presets
|
|
7082
|
+
.filter((preset) => !existingNames.has(preset.name.toLowerCase()))
|
|
7083
|
+
.map((preset) => this.internalService.addPreset({
|
|
6057
7084
|
id: '', // Will be generated
|
|
6058
7085
|
createdAt: '', // Will be generated
|
|
6059
7086
|
updatedAt: '', // Will be generated
|
|
7087
|
+
isSystem: true, // Mark as system preset (not editable)
|
|
6060
7088
|
...preset,
|
|
6061
7089
|
}));
|
|
6062
7090
|
}
|
|
@@ -6085,36 +7113,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.7", ngImpor
|
|
|
6085
7113
|
}] });
|
|
6086
7114
|
|
|
6087
7115
|
// Tree-shakeable tokens for dependency injection
|
|
6088
|
-
/** @deprecated Use TOOLBAR_FEATURE_FLAGS instead. Will be removed in v4.0 */
|
|
6089
|
-
const DEV_TOOLBAR_FEATURE_FLAGS = TOOLBAR_FEATURE_FLAGS;
|
|
6090
|
-
/** @deprecated Use TOOLBAR_PERMISSIONS instead. Will be removed in v4.0 */
|
|
6091
|
-
const DEV_TOOLBAR_PERMISSIONS = TOOLBAR_PERMISSIONS;
|
|
6092
|
-
/** @deprecated Use TOOLBAR_LANGUAGE instead. Will be removed in v4.0 */
|
|
6093
|
-
const DEV_TOOLBAR_LANGUAGE = TOOLBAR_LANGUAGE;
|
|
6094
|
-
/** @deprecated Use TOOLBAR_APP_FEATURES instead. Will be removed in v4.0 */
|
|
6095
|
-
const DEV_TOOLBAR_APP_FEATURES = TOOLBAR_APP_FEATURES;
|
|
6096
|
-
/** @deprecated Use provideToolbar instead. Will be removed in v4.0 */
|
|
6097
|
-
const provideDevToolbar = provideToolbar;
|
|
6098
|
-
/** @deprecated Use initToolbar instead. Will be removed in v4.0 */
|
|
6099
|
-
const initDevToolbar = initToolbar;
|
|
6100
|
-
/** @deprecated Use ToolbarComponent instead. Will be removed in v4.0 */
|
|
6101
|
-
const DevToolbarComponent = ToolbarComponent;
|
|
6102
|
-
/** @deprecated Use ToolbarToolComponent instead. Will be removed in v4.0 */
|
|
6103
|
-
const DevToolbarToolComponent = ToolbarToolComponent;
|
|
6104
|
-
/** @deprecated Use ToolbarFeatureFlagService instead. Will be removed in v4.0 */
|
|
6105
|
-
const DevToolbarFeatureFlagService = ToolbarFeatureFlagService;
|
|
6106
|
-
/** @deprecated Use ToolbarLanguageService instead. Will be removed in v4.0 */
|
|
6107
|
-
const DevToolbarLanguageService = ToolbarLanguageService;
|
|
6108
|
-
/** @deprecated Use ToolbarAppFeaturesService instead. Will be removed in v4.0 */
|
|
6109
|
-
const DevToolbarAppFeaturesService = ToolbarAppFeaturesService;
|
|
6110
|
-
/** @deprecated Use ToolbarPermissionsService instead. Will be removed in v4.0 */
|
|
6111
|
-
const DevToolbarPermissionsService = ToolbarPermissionsService;
|
|
6112
|
-
/** @deprecated Use ToolbarPresetsService instead. Will be removed in v4.0 */
|
|
6113
|
-
const DevToolbarPresetsService = ToolbarPresetsService;
|
|
6114
7116
|
|
|
6115
7117
|
/**
|
|
6116
7118
|
* Generated bundle index. Do not edit.
|
|
6117
7119
|
*/
|
|
6118
7120
|
|
|
6119
|
-
export {
|
|
7121
|
+
export { TOOLBAR_APP_FEATURES, TOOLBAR_FEATURE_FLAGS, TOOLBAR_LANGUAGE, TOOLBAR_PERMISSIONS, ToolbarAppFeaturesService, ToolbarAppFeaturesToolComponent, ToolbarButtonComponent, ToolbarCardComponent, ToolbarClickableCardComponent, ToolbarComponent, ToolbarFeatureFlagService, ToolbarIconComponent, ToolbarInputComponent, ToolbarLanguageService, ToolbarLinkButtonComponent, ToolbarListComponent, ToolbarListItemComponent, ToolbarPermissionsService, ToolbarPermissionsToolComponent, ToolbarPresetsService, ToolbarPresetsToolComponent, ToolbarSelectComponent, ToolbarStepDirective, ToolbarStepViewComponent, ToolbarToolComponent, initToolbar, provideToolbar };
|
|
6120
7122
|
//# sourceMappingURL=ngx-dev-toolbar.mjs.map
|