@memberjunction/ng-dashboards 2.131.0 → 2.133.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/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts +2 -2
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +46 -14
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +644 -446
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.d.ts +66 -0
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -0
- package/dist/Lists/components/lists-browse-resource.component.js +704 -0
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -0
- package/dist/Lists/components/lists-categories-resource.component.d.ts +68 -0
- package/dist/Lists/components/lists-categories-resource.component.d.ts.map +1 -0
- package/dist/Lists/components/lists-categories-resource.component.js +949 -0
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -0
- package/dist/Lists/components/lists-my-lists-resource.component.d.ts +113 -0
- package/dist/Lists/components/lists-my-lists-resource.component.d.ts.map +1 -0
- package/dist/Lists/components/lists-my-lists-resource.component.js +1442 -0
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -0
- package/dist/Lists/index.d.ts +5 -0
- package/dist/Lists/index.d.ts.map +1 -0
- package/dist/Lists/index.js +14 -0
- package/dist/Lists/index.js.map +1 -0
- package/dist/module.d.ts +51 -47
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +38 -10
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +5 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +30 -27
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts +0 -245
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts.map +0 -1
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js +0 -1143
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js.map +0 -1
|
@@ -0,0 +1,949 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Component, ViewEncapsulation } from '@angular/core';
|
|
8
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
9
|
+
import { BaseResourceComponent } from '@memberjunction/ng-shared';
|
|
10
|
+
import { Metadata, RunView } from '@memberjunction/core';
|
|
11
|
+
import { Subject } from 'rxjs';
|
|
12
|
+
import * as i0 from "@angular/core";
|
|
13
|
+
import * as i1 from "@memberjunction/ng-notifications";
|
|
14
|
+
import * as i2 from "@angular/common";
|
|
15
|
+
import * as i3 from "@angular/forms";
|
|
16
|
+
import * as i4 from "@memberjunction/ng-shared-generic";
|
|
17
|
+
const _c0 = a0 => ({ vm: a0 });
|
|
18
|
+
function ListsCategoriesResource_div_11_Template(rf, ctx) { if (rf & 1) {
|
|
19
|
+
i0.ɵɵelementStart(0, "div", 12);
|
|
20
|
+
i0.ɵɵelement(1, "mj-loading", 13);
|
|
21
|
+
i0.ɵɵelementEnd();
|
|
22
|
+
} }
|
|
23
|
+
function ListsCategoriesResource_div_12_Template(rf, ctx) { if (rf & 1) {
|
|
24
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
25
|
+
i0.ɵɵelementStart(0, "div", 14)(1, "div", 15);
|
|
26
|
+
i0.ɵɵelement(2, "div", 16)(3, "i", 17);
|
|
27
|
+
i0.ɵɵelementEnd();
|
|
28
|
+
i0.ɵɵelementStart(4, "h3");
|
|
29
|
+
i0.ɵɵtext(5, "No Categories Yet");
|
|
30
|
+
i0.ɵɵelementEnd();
|
|
31
|
+
i0.ɵɵelementStart(6, "p");
|
|
32
|
+
i0.ɵɵtext(7, "Categories help you organize lists into logical groups.");
|
|
33
|
+
i0.ɵɵelementEnd();
|
|
34
|
+
i0.ɵɵelementStart(8, "div", 18)(9, "div", 19);
|
|
35
|
+
i0.ɵɵelement(10, "i", 20);
|
|
36
|
+
i0.ɵɵelementStart(11, "span");
|
|
37
|
+
i0.ɵɵtext(12, "Create hierarchical folder structures");
|
|
38
|
+
i0.ɵɵelementEnd()();
|
|
39
|
+
i0.ɵɵelementStart(13, "div", 19);
|
|
40
|
+
i0.ɵɵelement(14, "i", 20);
|
|
41
|
+
i0.ɵɵelementStart(15, "span");
|
|
42
|
+
i0.ɵɵtext(16, "Quickly find related lists");
|
|
43
|
+
i0.ɵɵelementEnd()()();
|
|
44
|
+
i0.ɵɵelementStart(17, "button", 21);
|
|
45
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_12_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.createCategory()); });
|
|
46
|
+
i0.ɵɵelement(18, "i", 7);
|
|
47
|
+
i0.ɵɵtext(19, " Create Your First Category ");
|
|
48
|
+
i0.ɵɵelementEnd()();
|
|
49
|
+
} }
|
|
50
|
+
function ListsCategoriesResource_div_13_ng_container_9_ng_container_1_Template(rf, ctx) { if (rf & 1) {
|
|
51
|
+
i0.ɵɵelementContainer(0);
|
|
52
|
+
} }
|
|
53
|
+
function ListsCategoriesResource_div_13_ng_container_9_Template(rf, ctx) { if (rf & 1) {
|
|
54
|
+
i0.ɵɵelementContainerStart(0);
|
|
55
|
+
i0.ɵɵtemplate(1, ListsCategoriesResource_div_13_ng_container_9_ng_container_1_Template, 1, 0, "ng-container", 31);
|
|
56
|
+
i0.ɵɵelementContainerEnd();
|
|
57
|
+
} if (rf & 2) {
|
|
58
|
+
const vm_r4 = ctx.$implicit;
|
|
59
|
+
i0.ɵɵnextContext(2);
|
|
60
|
+
const categoryNodeTemplate_r5 = i0.ɵɵreference(15);
|
|
61
|
+
i0.ɵɵadvance();
|
|
62
|
+
i0.ɵɵproperty("ngTemplateOutlet", categoryNodeTemplate_r5)("ngTemplateOutletContext", i0.ɵɵpureFunction1(2, _c0, vm_r4));
|
|
63
|
+
} }
|
|
64
|
+
function ListsCategoriesResource_div_13_div_10_div_15_Template(rf, ctx) { if (rf & 1) {
|
|
65
|
+
i0.ɵɵelementStart(0, "div", 39)(1, "label");
|
|
66
|
+
i0.ɵɵtext(2, "Description");
|
|
67
|
+
i0.ɵɵelementEnd();
|
|
68
|
+
i0.ɵɵelementStart(3, "span", 40);
|
|
69
|
+
i0.ɵɵtext(4);
|
|
70
|
+
i0.ɵɵelementEnd()();
|
|
71
|
+
} if (rf & 2) {
|
|
72
|
+
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
73
|
+
i0.ɵɵadvance(4);
|
|
74
|
+
i0.ɵɵtextInterpolate(ctx_r2.selectedCategory.Description);
|
|
75
|
+
} }
|
|
76
|
+
function ListsCategoriesResource_div_13_div_10_div_32_div_4_Template(rf, ctx) { if (rf & 1) {
|
|
77
|
+
i0.ɵɵelementStart(0, "div", 50);
|
|
78
|
+
i0.ɵɵelement(1, "i", 51);
|
|
79
|
+
i0.ɵɵelementStart(2, "span");
|
|
80
|
+
i0.ɵɵtext(3);
|
|
81
|
+
i0.ɵɵelementEnd()();
|
|
82
|
+
} if (rf & 2) {
|
|
83
|
+
const list_r7 = ctx.$implicit;
|
|
84
|
+
i0.ɵɵadvance(3);
|
|
85
|
+
i0.ɵɵtextInterpolate(list_r7.Name);
|
|
86
|
+
} }
|
|
87
|
+
function ListsCategoriesResource_div_13_div_10_div_32_Template(rf, ctx) { if (rf & 1) {
|
|
88
|
+
i0.ɵɵelementStart(0, "div", 47)(1, "h4");
|
|
89
|
+
i0.ɵɵtext(2, "Lists in this category");
|
|
90
|
+
i0.ɵɵelementEnd();
|
|
91
|
+
i0.ɵɵelementStart(3, "div", 48);
|
|
92
|
+
i0.ɵɵtemplate(4, ListsCategoriesResource_div_13_div_10_div_32_div_4_Template, 4, 1, "div", 49);
|
|
93
|
+
i0.ɵɵelementEnd()();
|
|
94
|
+
} if (rf & 2) {
|
|
95
|
+
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
96
|
+
i0.ɵɵadvance(4);
|
|
97
|
+
i0.ɵɵproperty("ngForOf", ctx_r2.selectedCategoryLists);
|
|
98
|
+
} }
|
|
99
|
+
function ListsCategoriesResource_div_13_div_10_Template(rf, ctx) { if (rf & 1) {
|
|
100
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
101
|
+
i0.ɵɵelementStart(0, "div", 32)(1, "div", 25)(2, "h3");
|
|
102
|
+
i0.ɵɵtext(3, "Category Details");
|
|
103
|
+
i0.ɵɵelementEnd();
|
|
104
|
+
i0.ɵɵelementStart(4, "div", 33)(5, "button", 34);
|
|
105
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_13_div_10_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.editCategory()); });
|
|
106
|
+
i0.ɵɵelement(6, "i", 35);
|
|
107
|
+
i0.ɵɵelementEnd();
|
|
108
|
+
i0.ɵɵelementStart(7, "button", 36);
|
|
109
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_13_div_10_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.deleteCategory()); });
|
|
110
|
+
i0.ɵɵelement(8, "i", 37);
|
|
111
|
+
i0.ɵɵelementEnd()()();
|
|
112
|
+
i0.ɵɵelementStart(9, "div", 38)(10, "div", 39)(11, "label");
|
|
113
|
+
i0.ɵɵtext(12, "Name");
|
|
114
|
+
i0.ɵɵelementEnd();
|
|
115
|
+
i0.ɵɵelementStart(13, "span", 40);
|
|
116
|
+
i0.ɵɵtext(14);
|
|
117
|
+
i0.ɵɵelementEnd()();
|
|
118
|
+
i0.ɵɵtemplate(15, ListsCategoriesResource_div_13_div_10_div_15_Template, 5, 1, "div", 41);
|
|
119
|
+
i0.ɵɵelementStart(16, "div", 39)(17, "label");
|
|
120
|
+
i0.ɵɵtext(18, "Parent Category");
|
|
121
|
+
i0.ɵɵelementEnd();
|
|
122
|
+
i0.ɵɵelementStart(19, "span", 40);
|
|
123
|
+
i0.ɵɵtext(20);
|
|
124
|
+
i0.ɵɵelementEnd()();
|
|
125
|
+
i0.ɵɵelementStart(21, "div", 42)(22, "div", 43)(23, "span", 44);
|
|
126
|
+
i0.ɵɵtext(24);
|
|
127
|
+
i0.ɵɵelementEnd();
|
|
128
|
+
i0.ɵɵelementStart(25, "span", 45);
|
|
129
|
+
i0.ɵɵtext(26, "Lists");
|
|
130
|
+
i0.ɵɵelementEnd()();
|
|
131
|
+
i0.ɵɵelementStart(27, "div", 43)(28, "span", 44);
|
|
132
|
+
i0.ɵɵtext(29);
|
|
133
|
+
i0.ɵɵelementEnd();
|
|
134
|
+
i0.ɵɵelementStart(30, "span", 45);
|
|
135
|
+
i0.ɵɵtext(31, "Subcategories");
|
|
136
|
+
i0.ɵɵelementEnd()()();
|
|
137
|
+
i0.ɵɵtemplate(32, ListsCategoriesResource_div_13_div_10_div_32_Template, 5, 1, "div", 46);
|
|
138
|
+
i0.ɵɵelementEnd()();
|
|
139
|
+
} if (rf & 2) {
|
|
140
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
141
|
+
i0.ɵɵadvance(14);
|
|
142
|
+
i0.ɵɵtextInterpolate(ctx_r2.selectedCategory.Name);
|
|
143
|
+
i0.ɵɵadvance();
|
|
144
|
+
i0.ɵɵproperty("ngIf", ctx_r2.selectedCategory.Description);
|
|
145
|
+
i0.ɵɵadvance(5);
|
|
146
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r2.getParentCategoryName(ctx_r2.selectedCategory) || "(Top Level)", " ");
|
|
147
|
+
i0.ɵɵadvance(4);
|
|
148
|
+
i0.ɵɵtextInterpolate(ctx_r2.getSelectedCategoryListCount());
|
|
149
|
+
i0.ɵɵadvance(5);
|
|
150
|
+
i0.ɵɵtextInterpolate(ctx_r2.getSelectedCategoryChildCount());
|
|
151
|
+
i0.ɵɵadvance(3);
|
|
152
|
+
i0.ɵɵproperty("ngIf", ctx_r2.selectedCategoryLists.length > 0);
|
|
153
|
+
} }
|
|
154
|
+
function ListsCategoriesResource_div_13_div_11_Template(rf, ctx) { if (rf & 1) {
|
|
155
|
+
i0.ɵɵelementStart(0, "div", 52)(1, "div", 53);
|
|
156
|
+
i0.ɵɵelement(2, "i", 54);
|
|
157
|
+
i0.ɵɵelementStart(3, "p");
|
|
158
|
+
i0.ɵɵtext(4, "Select a category to view details");
|
|
159
|
+
i0.ɵɵelementEnd()()();
|
|
160
|
+
} }
|
|
161
|
+
function ListsCategoriesResource_div_13_Template(rf, ctx) { if (rf & 1) {
|
|
162
|
+
i0.ɵɵelementStart(0, "div", 22)(1, "div", 23)(2, "div", 24)(3, "div", 25)(4, "h3");
|
|
163
|
+
i0.ɵɵtext(5, "Categories");
|
|
164
|
+
i0.ɵɵelementEnd();
|
|
165
|
+
i0.ɵɵelementStart(6, "span", 26);
|
|
166
|
+
i0.ɵɵtext(7);
|
|
167
|
+
i0.ɵɵelementEnd()();
|
|
168
|
+
i0.ɵɵelementStart(8, "div", 27);
|
|
169
|
+
i0.ɵɵtemplate(9, ListsCategoriesResource_div_13_ng_container_9_Template, 2, 4, "ng-container", 28);
|
|
170
|
+
i0.ɵɵelementEnd()();
|
|
171
|
+
i0.ɵɵtemplate(10, ListsCategoriesResource_div_13_div_10_Template, 33, 6, "div", 29)(11, ListsCategoriesResource_div_13_div_11_Template, 5, 0, "div", 30);
|
|
172
|
+
i0.ɵɵelementEnd()();
|
|
173
|
+
} if (rf & 2) {
|
|
174
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
175
|
+
i0.ɵɵadvance(7);
|
|
176
|
+
i0.ɵɵtextInterpolate(ctx_r2.categories.length);
|
|
177
|
+
i0.ɵɵadvance(2);
|
|
178
|
+
i0.ɵɵproperty("ngForOf", ctx_r2.getTopLevelCategories());
|
|
179
|
+
i0.ɵɵadvance();
|
|
180
|
+
i0.ɵɵproperty("ngIf", ctx_r2.selectedCategory);
|
|
181
|
+
i0.ɵɵadvance();
|
|
182
|
+
i0.ɵɵproperty("ngIf", !ctx_r2.selectedCategory);
|
|
183
|
+
} }
|
|
184
|
+
function ListsCategoriesResource_ng_template_14_button_2_Template(rf, ctx) { if (rf & 1) {
|
|
185
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
186
|
+
i0.ɵɵelementStart(0, "button", 63);
|
|
187
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_ng_template_14_button_2_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r10); const vm_r9 = i0.ɵɵnextContext().vm; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleExpand($event, vm_r9)); });
|
|
188
|
+
i0.ɵɵelement(1, "i");
|
|
189
|
+
i0.ɵɵelementEnd();
|
|
190
|
+
} if (rf & 2) {
|
|
191
|
+
const vm_r9 = i0.ɵɵnextContext().vm;
|
|
192
|
+
i0.ɵɵadvance();
|
|
193
|
+
i0.ɵɵclassMap(vm_r9.isExpanded ? "fa-solid fa-chevron-down" : "fa-solid fa-chevron-right");
|
|
194
|
+
} }
|
|
195
|
+
function ListsCategoriesResource_ng_template_14_span_3_Template(rf, ctx) { if (rf & 1) {
|
|
196
|
+
i0.ɵɵelement(0, "span", 64);
|
|
197
|
+
} }
|
|
198
|
+
function ListsCategoriesResource_ng_template_14_div_9_ng_container_1_ng_container_1_Template(rf, ctx) { if (rf & 1) {
|
|
199
|
+
i0.ɵɵelementContainer(0);
|
|
200
|
+
} }
|
|
201
|
+
function ListsCategoriesResource_ng_template_14_div_9_ng_container_1_Template(rf, ctx) { if (rf & 1) {
|
|
202
|
+
i0.ɵɵelementContainerStart(0);
|
|
203
|
+
i0.ɵɵtemplate(1, ListsCategoriesResource_ng_template_14_div_9_ng_container_1_ng_container_1_Template, 1, 0, "ng-container", 31);
|
|
204
|
+
i0.ɵɵelementContainerEnd();
|
|
205
|
+
} if (rf & 2) {
|
|
206
|
+
const childVm_r11 = ctx.$implicit;
|
|
207
|
+
i0.ɵɵnextContext(3);
|
|
208
|
+
const categoryNodeTemplate_r5 = i0.ɵɵreference(15);
|
|
209
|
+
i0.ɵɵadvance();
|
|
210
|
+
i0.ɵɵproperty("ngTemplateOutlet", categoryNodeTemplate_r5)("ngTemplateOutletContext", i0.ɵɵpureFunction1(2, _c0, childVm_r11));
|
|
211
|
+
} }
|
|
212
|
+
function ListsCategoriesResource_ng_template_14_div_9_Template(rf, ctx) { if (rf & 1) {
|
|
213
|
+
i0.ɵɵelementStart(0, "div", 65);
|
|
214
|
+
i0.ɵɵtemplate(1, ListsCategoriesResource_ng_template_14_div_9_ng_container_1_Template, 2, 4, "ng-container", 28);
|
|
215
|
+
i0.ɵɵelementEnd();
|
|
216
|
+
} if (rf & 2) {
|
|
217
|
+
const vm_r9 = i0.ɵɵnextContext().vm;
|
|
218
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
219
|
+
i0.ɵɵadvance();
|
|
220
|
+
i0.ɵɵproperty("ngForOf", ctx_r2.getChildCategories(vm_r9.category));
|
|
221
|
+
} }
|
|
222
|
+
function ListsCategoriesResource_ng_template_14_Template(rf, ctx) { if (rf & 1) {
|
|
223
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
224
|
+
i0.ɵɵelementStart(0, "div", 55)(1, "div", 56);
|
|
225
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_ng_template_14_Template_div_click_1_listener() { const vm_r9 = i0.ɵɵrestoreView(_r8).vm; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.selectCategory(vm_r9.category)); })("keydown.enter", function ListsCategoriesResource_ng_template_14_Template_div_keydown_enter_1_listener() { const vm_r9 = i0.ɵɵrestoreView(_r8).vm; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.selectCategory(vm_r9.category)); })("keydown.space", function ListsCategoriesResource_ng_template_14_Template_div_keydown_space_1_listener($event) { const vm_r9 = i0.ɵɵrestoreView(_r8).vm; const ctx_r2 = i0.ɵɵnextContext(); ctx_r2.selectCategory(vm_r9.category); return i0.ɵɵresetView($event.preventDefault()); })("keydown.arrowRight", function ListsCategoriesResource_ng_template_14_Template_div_keydown_arrowRight_1_listener($event) { const vm_r9 = i0.ɵɵrestoreView(_r8).vm; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.expandNode($event, vm_r9)); })("keydown.arrowLeft", function ListsCategoriesResource_ng_template_14_Template_div_keydown_arrowLeft_1_listener($event) { const vm_r9 = i0.ɵɵrestoreView(_r8).vm; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.collapseNode($event, vm_r9)); });
|
|
226
|
+
i0.ɵɵtemplate(2, ListsCategoriesResource_ng_template_14_button_2_Template, 2, 2, "button", 57)(3, ListsCategoriesResource_ng_template_14_span_3_Template, 1, 0, "span", 58);
|
|
227
|
+
i0.ɵɵelement(4, "i", 59);
|
|
228
|
+
i0.ɵɵelementStart(5, "span", 60);
|
|
229
|
+
i0.ɵɵtext(6);
|
|
230
|
+
i0.ɵɵelementEnd();
|
|
231
|
+
i0.ɵɵelementStart(7, "span", 61);
|
|
232
|
+
i0.ɵɵtext(8);
|
|
233
|
+
i0.ɵɵelementEnd()();
|
|
234
|
+
i0.ɵɵtemplate(9, ListsCategoriesResource_ng_template_14_div_9_Template, 2, 1, "div", 62);
|
|
235
|
+
i0.ɵɵelementEnd();
|
|
236
|
+
} if (rf & 2) {
|
|
237
|
+
const vm_r9 = ctx.vm;
|
|
238
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
239
|
+
i0.ɵɵstyleProp("padding-left", vm_r9.depth * 20, "px");
|
|
240
|
+
i0.ɵɵadvance();
|
|
241
|
+
i0.ɵɵclassProp("selected", (ctx_r2.selectedCategory == null ? null : ctx_r2.selectedCategory.ID) === vm_r9.category.ID);
|
|
242
|
+
i0.ɵɵattribute("aria-expanded", ctx_r2.hasChildren(vm_r9.category) ? vm_r9.isExpanded : null)("aria-selected", (ctx_r2.selectedCategory == null ? null : ctx_r2.selectedCategory.ID) === vm_r9.category.ID)("aria-label", vm_r9.category.Name + " - " + vm_r9.listCount + " lists");
|
|
243
|
+
i0.ɵɵadvance();
|
|
244
|
+
i0.ɵɵproperty("ngIf", ctx_r2.hasChildren(vm_r9.category));
|
|
245
|
+
i0.ɵɵadvance();
|
|
246
|
+
i0.ɵɵproperty("ngIf", !ctx_r2.hasChildren(vm_r9.category));
|
|
247
|
+
i0.ɵɵadvance();
|
|
248
|
+
i0.ɵɵclassProp("fa-folder-open", vm_r9.isExpanded);
|
|
249
|
+
i0.ɵɵadvance(2);
|
|
250
|
+
i0.ɵɵtextInterpolate(vm_r9.category.Name);
|
|
251
|
+
i0.ɵɵadvance(2);
|
|
252
|
+
i0.ɵɵtextInterpolate(vm_r9.listCount);
|
|
253
|
+
i0.ɵɵadvance();
|
|
254
|
+
i0.ɵɵproperty("ngIf", vm_r9.isExpanded && ctx_r2.hasChildren(vm_r9.category));
|
|
255
|
+
} }
|
|
256
|
+
function ListsCategoriesResource_div_16_option_21_Template(rf, ctx) { if (rf & 1) {
|
|
257
|
+
i0.ɵɵelementStart(0, "option", 82);
|
|
258
|
+
i0.ɵɵtext(1);
|
|
259
|
+
i0.ɵɵelementEnd();
|
|
260
|
+
} if (rf & 2) {
|
|
261
|
+
const parent_r13 = ctx.$implicit;
|
|
262
|
+
i0.ɵɵproperty("ngValue", parent_r13.ID);
|
|
263
|
+
i0.ɵɵadvance();
|
|
264
|
+
i0.ɵɵtextInterpolate(parent_r13.displayName);
|
|
265
|
+
} }
|
|
266
|
+
function ListsCategoriesResource_div_16_i_24_Template(rf, ctx) { if (rf & 1) {
|
|
267
|
+
i0.ɵɵelement(0, "i", 83);
|
|
268
|
+
} }
|
|
269
|
+
function ListsCategoriesResource_div_16_Template(rf, ctx) { if (rf & 1) {
|
|
270
|
+
const _r12 = i0.ɵɵgetCurrentView();
|
|
271
|
+
i0.ɵɵelementStart(0, "div", 66);
|
|
272
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_16_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeDialog()); });
|
|
273
|
+
i0.ɵɵelementStart(1, "div", 67);
|
|
274
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_16_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r12); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
275
|
+
i0.ɵɵelementStart(2, "div", 68)(3, "h3");
|
|
276
|
+
i0.ɵɵtext(4);
|
|
277
|
+
i0.ɵɵelementEnd();
|
|
278
|
+
i0.ɵɵelementStart(5, "button", 69);
|
|
279
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_16_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeDialog()); });
|
|
280
|
+
i0.ɵɵelement(6, "i", 70);
|
|
281
|
+
i0.ɵɵelementEnd()();
|
|
282
|
+
i0.ɵɵelementStart(7, "div", 71)(8, "div", 72)(9, "div", 73)(10, "label");
|
|
283
|
+
i0.ɵɵtext(11, "Name *");
|
|
284
|
+
i0.ɵɵelementEnd();
|
|
285
|
+
i0.ɵɵelementStart(12, "input", 74);
|
|
286
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ListsCategoriesResource_div_16_Template_input_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.dialogName, $event) || (ctx_r2.dialogName = $event); return i0.ɵɵresetView($event); });
|
|
287
|
+
i0.ɵɵelementEnd()();
|
|
288
|
+
i0.ɵɵelementStart(13, "div", 73)(14, "label");
|
|
289
|
+
i0.ɵɵtext(15, "Description");
|
|
290
|
+
i0.ɵɵelementEnd();
|
|
291
|
+
i0.ɵɵelementStart(16, "textarea", 75);
|
|
292
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ListsCategoriesResource_div_16_Template_textarea_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.dialogDescription, $event) || (ctx_r2.dialogDescription = $event); return i0.ɵɵresetView($event); });
|
|
293
|
+
i0.ɵɵelementEnd()();
|
|
294
|
+
i0.ɵɵelementStart(17, "div", 73)(18, "label");
|
|
295
|
+
i0.ɵɵtext(19, "Parent Category");
|
|
296
|
+
i0.ɵɵelementEnd();
|
|
297
|
+
i0.ɵɵelementStart(20, "select", 76);
|
|
298
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ListsCategoriesResource_div_16_Template_select_ngModelChange_20_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.dialogParentId, $event) || (ctx_r2.dialogParentId = $event); return i0.ɵɵresetView($event); });
|
|
299
|
+
i0.ɵɵtemplate(21, ListsCategoriesResource_div_16_option_21_Template, 2, 2, "option", 77);
|
|
300
|
+
i0.ɵɵelementEnd()()()();
|
|
301
|
+
i0.ɵɵelementStart(22, "div", 78)(23, "button", 79);
|
|
302
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_16_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.saveCategory()); });
|
|
303
|
+
i0.ɵɵtemplate(24, ListsCategoriesResource_div_16_i_24_Template, 1, 0, "i", 80);
|
|
304
|
+
i0.ɵɵtext(25);
|
|
305
|
+
i0.ɵɵelementEnd();
|
|
306
|
+
i0.ɵɵelementStart(26, "button", 81);
|
|
307
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_16_Template_button_click_26_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeDialog()); });
|
|
308
|
+
i0.ɵɵtext(27, "Cancel");
|
|
309
|
+
i0.ɵɵelementEnd()()()();
|
|
310
|
+
} if (rf & 2) {
|
|
311
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
312
|
+
i0.ɵɵadvance(4);
|
|
313
|
+
i0.ɵɵtextInterpolate(ctx_r2.editingCategory ? "Edit Category" : "Create Category");
|
|
314
|
+
i0.ɵɵadvance();
|
|
315
|
+
i0.ɵɵproperty("disabled", ctx_r2.isSaving);
|
|
316
|
+
i0.ɵɵadvance(7);
|
|
317
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r2.dialogName);
|
|
318
|
+
i0.ɵɵadvance(4);
|
|
319
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r2.dialogDescription);
|
|
320
|
+
i0.ɵɵadvance(4);
|
|
321
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r2.dialogParentId);
|
|
322
|
+
i0.ɵɵadvance();
|
|
323
|
+
i0.ɵɵproperty("ngForOf", ctx_r2.availableParents);
|
|
324
|
+
i0.ɵɵadvance(2);
|
|
325
|
+
i0.ɵɵproperty("disabled", !ctx_r2.dialogName || ctx_r2.isSaving);
|
|
326
|
+
i0.ɵɵadvance();
|
|
327
|
+
i0.ɵɵproperty("ngIf", ctx_r2.isSaving);
|
|
328
|
+
i0.ɵɵadvance();
|
|
329
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r2.isSaving ? "Saving..." : ctx_r2.editingCategory ? "Save" : "Create", " ");
|
|
330
|
+
i0.ɵɵadvance();
|
|
331
|
+
i0.ɵɵproperty("disabled", ctx_r2.isSaving);
|
|
332
|
+
} }
|
|
333
|
+
function ListsCategoriesResource_div_17_Template(rf, ctx) { if (rf & 1) {
|
|
334
|
+
const _r14 = i0.ɵɵgetCurrentView();
|
|
335
|
+
i0.ɵɵelementStart(0, "div", 66);
|
|
336
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_17_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.cancelDelete()); });
|
|
337
|
+
i0.ɵɵelementStart(1, "div", 84);
|
|
338
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_17_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r14); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
339
|
+
i0.ɵɵelementStart(2, "div", 85)(3, "h3");
|
|
340
|
+
i0.ɵɵtext(4, "Delete Category");
|
|
341
|
+
i0.ɵɵelementEnd();
|
|
342
|
+
i0.ɵɵelementStart(5, "button", 86);
|
|
343
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_17_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.cancelDelete()); });
|
|
344
|
+
i0.ɵɵelement(6, "i", 70);
|
|
345
|
+
i0.ɵɵelementEnd()();
|
|
346
|
+
i0.ɵɵelementStart(7, "div", 71)(8, "p");
|
|
347
|
+
i0.ɵɵtext(9);
|
|
348
|
+
i0.ɵɵelementEnd()();
|
|
349
|
+
i0.ɵɵelementStart(10, "div", 78)(11, "button", 87);
|
|
350
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_17_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.confirmDelete()); });
|
|
351
|
+
i0.ɵɵtext(12, " Delete ");
|
|
352
|
+
i0.ɵɵelementEnd();
|
|
353
|
+
i0.ɵɵelementStart(13, "button", 88);
|
|
354
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_div_17_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.cancelDelete()); });
|
|
355
|
+
i0.ɵɵtext(14, "Cancel");
|
|
356
|
+
i0.ɵɵelementEnd()()()();
|
|
357
|
+
} if (rf & 2) {
|
|
358
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
359
|
+
i0.ɵɵadvance(9);
|
|
360
|
+
i0.ɵɵtextInterpolate(ctx_r2.deleteConfirmMessage);
|
|
361
|
+
} }
|
|
362
|
+
export function LoadListsCategoriesResource() {
|
|
363
|
+
// tree shaker
|
|
364
|
+
}
|
|
365
|
+
let ListsCategoriesResource = class ListsCategoriesResource extends BaseResourceComponent {
|
|
366
|
+
cdr;
|
|
367
|
+
notificationService;
|
|
368
|
+
destroy$ = new Subject();
|
|
369
|
+
isLoading = true;
|
|
370
|
+
categories = [];
|
|
371
|
+
categoryViewModels = [];
|
|
372
|
+
selectedCategory = null;
|
|
373
|
+
selectedCategoryLists = [];
|
|
374
|
+
// Dialog
|
|
375
|
+
showDialog = false;
|
|
376
|
+
editingCategory = null;
|
|
377
|
+
dialogName = '';
|
|
378
|
+
dialogDescription = '';
|
|
379
|
+
dialogParentId = null;
|
|
380
|
+
availableParents = [];
|
|
381
|
+
// Operation states
|
|
382
|
+
isSaving = false;
|
|
383
|
+
// Delete confirmation dialog
|
|
384
|
+
showDeleteConfirm = false;
|
|
385
|
+
deleteConfirmMessage = '';
|
|
386
|
+
categoryToDelete = null;
|
|
387
|
+
listsByCategoryId = new Map();
|
|
388
|
+
categoryMap = new Map();
|
|
389
|
+
constructor(cdr, notificationService) {
|
|
390
|
+
super();
|
|
391
|
+
this.cdr = cdr;
|
|
392
|
+
this.notificationService = notificationService;
|
|
393
|
+
}
|
|
394
|
+
async ngOnInit() {
|
|
395
|
+
await this.loadData();
|
|
396
|
+
this.NotifyLoadComplete();
|
|
397
|
+
}
|
|
398
|
+
ngOnDestroy() {
|
|
399
|
+
this.destroy$.next();
|
|
400
|
+
this.destroy$.complete();
|
|
401
|
+
}
|
|
402
|
+
async loadData() {
|
|
403
|
+
this.isLoading = true;
|
|
404
|
+
try {
|
|
405
|
+
const md = new Metadata();
|
|
406
|
+
const rv = new RunView();
|
|
407
|
+
const userId = md.CurrentUser?.ID;
|
|
408
|
+
const [categoriesResult, listsResult] = await rv.RunViews([
|
|
409
|
+
{
|
|
410
|
+
EntityName: 'List Categories',
|
|
411
|
+
OrderBy: 'Name',
|
|
412
|
+
ResultType: 'entity_object',
|
|
413
|
+
CacheLocal: true // Categories rarely change, cache for performance
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
EntityName: 'Lists',
|
|
417
|
+
ExtraFilter: userId ? `UserID = '${userId}'` : '',
|
|
418
|
+
ResultType: 'entity_object'
|
|
419
|
+
}
|
|
420
|
+
]);
|
|
421
|
+
if (!categoriesResult.Success) {
|
|
422
|
+
console.error('Failed to load categories');
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
this.categories = categoriesResult.Results;
|
|
426
|
+
const lists = listsResult.Results;
|
|
427
|
+
// Build category map
|
|
428
|
+
this.categoryMap.clear();
|
|
429
|
+
for (const cat of this.categories) {
|
|
430
|
+
this.categoryMap.set(cat.ID, cat);
|
|
431
|
+
}
|
|
432
|
+
// Group lists by category
|
|
433
|
+
this.listsByCategoryId.clear();
|
|
434
|
+
for (const list of lists) {
|
|
435
|
+
if (list.CategoryID) {
|
|
436
|
+
const existing = this.listsByCategoryId.get(list.CategoryID) || [];
|
|
437
|
+
existing.push(list);
|
|
438
|
+
this.listsByCategoryId.set(list.CategoryID, existing);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
// Build view models
|
|
442
|
+
this.buildCategoryViewModels();
|
|
443
|
+
this.buildAvailableParents();
|
|
444
|
+
}
|
|
445
|
+
catch (error) {
|
|
446
|
+
console.error('Error loading categories:', error);
|
|
447
|
+
}
|
|
448
|
+
finally {
|
|
449
|
+
this.isLoading = false;
|
|
450
|
+
this.cdr.detectChanges();
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
buildCategoryViewModels() {
|
|
454
|
+
this.categoryViewModels = [];
|
|
455
|
+
const buildVm = (category, depth) => {
|
|
456
|
+
const lists = this.listsByCategoryId.get(category.ID) || [];
|
|
457
|
+
const children = this.categories.filter(c => c.ParentID === category.ID);
|
|
458
|
+
return {
|
|
459
|
+
category,
|
|
460
|
+
listCount: lists.length,
|
|
461
|
+
childCount: children.length,
|
|
462
|
+
depth,
|
|
463
|
+
isExpanded: true
|
|
464
|
+
};
|
|
465
|
+
};
|
|
466
|
+
const processCategory = (category, depth) => {
|
|
467
|
+
this.categoryViewModels.push(buildVm(category, depth));
|
|
468
|
+
const children = this.categories.filter(c => c.ParentID === category.ID);
|
|
469
|
+
for (const child of children) {
|
|
470
|
+
processCategory(child, depth + 1);
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
const topLevel = this.categories.filter(c => !c.ParentID);
|
|
474
|
+
for (const cat of topLevel) {
|
|
475
|
+
processCategory(cat, 0);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
buildAvailableParents() {
|
|
479
|
+
this.availableParents = [{ ID: null, displayName: '(Top Level)' }];
|
|
480
|
+
const addCategory = (cat, prefix) => {
|
|
481
|
+
// Exclude the editing category and its descendants
|
|
482
|
+
if (this.editingCategory && this.isDescendantOf(cat, this.editingCategory)) {
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
this.availableParents.push({ ID: cat.ID, displayName: prefix + cat.Name });
|
|
486
|
+
const children = this.categories.filter(c => c.ParentID === cat.ID);
|
|
487
|
+
for (const child of children) {
|
|
488
|
+
addCategory(child, prefix + '\u00A0\u00A0');
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
const topLevel = this.categories.filter(c => !c.ParentID);
|
|
492
|
+
for (const cat of topLevel) {
|
|
493
|
+
if (this.editingCategory?.ID !== cat.ID) {
|
|
494
|
+
addCategory(cat, '');
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
isDescendantOf(category, ancestor) {
|
|
499
|
+
if (category.ID === ancestor.ID)
|
|
500
|
+
return true;
|
|
501
|
+
if (!category.ParentID)
|
|
502
|
+
return false;
|
|
503
|
+
const parent = this.categoryMap.get(category.ParentID);
|
|
504
|
+
return parent ? this.isDescendantOf(parent, ancestor) : false;
|
|
505
|
+
}
|
|
506
|
+
getTopLevelCategories() {
|
|
507
|
+
return this.categoryViewModels.filter(vm => !vm.category.ParentID);
|
|
508
|
+
}
|
|
509
|
+
getChildCategories(parent) {
|
|
510
|
+
return this.categoryViewModels.filter(vm => vm.category.ParentID === parent.ID);
|
|
511
|
+
}
|
|
512
|
+
hasChildren(category) {
|
|
513
|
+
return this.categories.some(c => c.ParentID === category.ID);
|
|
514
|
+
}
|
|
515
|
+
toggleExpand(event, vm) {
|
|
516
|
+
event.stopPropagation();
|
|
517
|
+
vm.isExpanded = !vm.isExpanded;
|
|
518
|
+
}
|
|
519
|
+
expandNode(event, vm) {
|
|
520
|
+
event.preventDefault();
|
|
521
|
+
if (this.hasChildren(vm.category) && !vm.isExpanded) {
|
|
522
|
+
vm.isExpanded = true;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
collapseNode(event, vm) {
|
|
526
|
+
event.preventDefault();
|
|
527
|
+
if (vm.isExpanded) {
|
|
528
|
+
vm.isExpanded = false;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
selectCategory(category) {
|
|
532
|
+
this.selectedCategory = category;
|
|
533
|
+
this.selectedCategoryLists = this.listsByCategoryId.get(category.ID) || [];
|
|
534
|
+
}
|
|
535
|
+
getParentCategoryName(category) {
|
|
536
|
+
if (!category.ParentID)
|
|
537
|
+
return null;
|
|
538
|
+
return this.categoryMap.get(category.ParentID)?.Name || null;
|
|
539
|
+
}
|
|
540
|
+
getSelectedCategoryListCount() {
|
|
541
|
+
if (!this.selectedCategory)
|
|
542
|
+
return 0;
|
|
543
|
+
return this.listsByCategoryId.get(this.selectedCategory.ID)?.length || 0;
|
|
544
|
+
}
|
|
545
|
+
getSelectedCategoryChildCount() {
|
|
546
|
+
if (!this.selectedCategory)
|
|
547
|
+
return 0;
|
|
548
|
+
return this.categories.filter(c => c.ParentID === this.selectedCategory.ID).length;
|
|
549
|
+
}
|
|
550
|
+
createCategory() {
|
|
551
|
+
this.editingCategory = null;
|
|
552
|
+
this.dialogName = '';
|
|
553
|
+
this.dialogDescription = '';
|
|
554
|
+
this.dialogParentId = null;
|
|
555
|
+
this.buildAvailableParents();
|
|
556
|
+
this.showDialog = true;
|
|
557
|
+
}
|
|
558
|
+
editCategory() {
|
|
559
|
+
if (!this.selectedCategory)
|
|
560
|
+
return;
|
|
561
|
+
this.editingCategory = this.selectedCategory;
|
|
562
|
+
this.dialogName = this.selectedCategory.Name;
|
|
563
|
+
this.dialogDescription = this.selectedCategory.Description || '';
|
|
564
|
+
this.dialogParentId = this.selectedCategory.ParentID || null;
|
|
565
|
+
this.buildAvailableParents();
|
|
566
|
+
this.showDialog = true;
|
|
567
|
+
}
|
|
568
|
+
deleteCategory() {
|
|
569
|
+
if (!this.selectedCategory)
|
|
570
|
+
return;
|
|
571
|
+
this.categoryToDelete = this.selectedCategory;
|
|
572
|
+
const categoryName = this.categoryToDelete.Name;
|
|
573
|
+
const listsInCategory = this.listsByCategoryId.get(this.categoryToDelete.ID) || [];
|
|
574
|
+
const childCategories = this.categories.filter(c => c.ParentID === this.categoryToDelete.ID);
|
|
575
|
+
let message = `Are you sure you want to delete "${categoryName}"?`;
|
|
576
|
+
if (listsInCategory.length > 0) {
|
|
577
|
+
message += ` ${listsInCategory.length} list(s) will be uncategorized.`;
|
|
578
|
+
}
|
|
579
|
+
if (childCategories.length > 0) {
|
|
580
|
+
message += ` ${childCategories.length} subcategory(ies) will become top-level.`;
|
|
581
|
+
}
|
|
582
|
+
this.deleteConfirmMessage = message;
|
|
583
|
+
this.showDeleteConfirm = true;
|
|
584
|
+
}
|
|
585
|
+
cancelDelete() {
|
|
586
|
+
this.showDeleteConfirm = false;
|
|
587
|
+
this.categoryToDelete = null;
|
|
588
|
+
this.deleteConfirmMessage = '';
|
|
589
|
+
}
|
|
590
|
+
async confirmDelete() {
|
|
591
|
+
if (!this.categoryToDelete)
|
|
592
|
+
return;
|
|
593
|
+
const categoryName = this.categoryToDelete.Name;
|
|
594
|
+
const categoryToDelete = this.categoryToDelete;
|
|
595
|
+
this.showDeleteConfirm = false;
|
|
596
|
+
this.isLoading = true;
|
|
597
|
+
this.cdr.detectChanges();
|
|
598
|
+
try {
|
|
599
|
+
const deleted = await categoryToDelete.Delete();
|
|
600
|
+
if (deleted) {
|
|
601
|
+
this.notificationService.CreateSimpleNotification(`"${categoryName}" deleted`, 'success', 3000);
|
|
602
|
+
}
|
|
603
|
+
else {
|
|
604
|
+
// Get the detailed error message from LatestResult
|
|
605
|
+
const errorMessage = categoryToDelete.LatestResult?.Message || 'Unknown error occurred';
|
|
606
|
+
console.error('Failed to delete category:', categoryToDelete.LatestResult);
|
|
607
|
+
this.notificationService.CreateSimpleNotification(`Failed to delete category: ${errorMessage}`, 'error', 6000);
|
|
608
|
+
}
|
|
609
|
+
this.selectedCategory = null;
|
|
610
|
+
this.categoryToDelete = null;
|
|
611
|
+
await this.loadData();
|
|
612
|
+
}
|
|
613
|
+
catch (error) {
|
|
614
|
+
console.error('Error deleting category:', error);
|
|
615
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
616
|
+
this.notificationService.CreateSimpleNotification(`Error deleting category: ${errorMessage}`, 'error', 6000);
|
|
617
|
+
}
|
|
618
|
+
finally {
|
|
619
|
+
this.isLoading = false;
|
|
620
|
+
this.cdr.detectChanges();
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
closeDialog() {
|
|
624
|
+
this.showDialog = false;
|
|
625
|
+
this.editingCategory = null;
|
|
626
|
+
}
|
|
627
|
+
async saveCategory() {
|
|
628
|
+
this.isSaving = true;
|
|
629
|
+
this.cdr.detectChanges();
|
|
630
|
+
const isEditing = !!this.editingCategory;
|
|
631
|
+
const categoryName = this.dialogName;
|
|
632
|
+
try {
|
|
633
|
+
const md = new Metadata();
|
|
634
|
+
let category;
|
|
635
|
+
if (this.editingCategory) {
|
|
636
|
+
category = this.editingCategory;
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
category = await md.GetEntityObject('List Categories');
|
|
640
|
+
category.UserID = md.CurrentUser.ID;
|
|
641
|
+
}
|
|
642
|
+
category.Name = this.dialogName;
|
|
643
|
+
category.Description = this.dialogDescription || null;
|
|
644
|
+
category.ParentID = this.dialogParentId || null;
|
|
645
|
+
const saved = await category.Save();
|
|
646
|
+
if (saved) {
|
|
647
|
+
this.notificationService.CreateSimpleNotification(isEditing ? `"${categoryName}" updated` : `"${categoryName}" created`, 'success', 3000);
|
|
648
|
+
this.closeDialog();
|
|
649
|
+
await this.loadData();
|
|
650
|
+
// Re-select the saved category
|
|
651
|
+
if (isEditing) {
|
|
652
|
+
this.selectedCategory = category;
|
|
653
|
+
this.selectedCategoryLists = this.listsByCategoryId.get(category.ID) || [];
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
else {
|
|
657
|
+
// Get the detailed error message from LatestResult
|
|
658
|
+
const errorMessage = category.LatestResult?.Message || 'Unknown error occurred';
|
|
659
|
+
const action = isEditing ? 'update' : 'create';
|
|
660
|
+
console.error(`Failed to ${action} category:`, category.LatestResult);
|
|
661
|
+
this.notificationService.CreateSimpleNotification(`Failed to ${action} category: ${errorMessage}`, 'error', 6000);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
catch (error) {
|
|
665
|
+
console.error('Error saving category:', error);
|
|
666
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
667
|
+
this.notificationService.CreateSimpleNotification(`Error saving category: ${errorMessage}`, 'error', 6000);
|
|
668
|
+
}
|
|
669
|
+
finally {
|
|
670
|
+
this.isSaving = false;
|
|
671
|
+
this.cdr.detectChanges();
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
async GetResourceDisplayName(data) {
|
|
675
|
+
return 'Categories';
|
|
676
|
+
}
|
|
677
|
+
async GetResourceIconClass(data) {
|
|
678
|
+
return 'fa-solid fa-tags';
|
|
679
|
+
}
|
|
680
|
+
static ɵfac = function ListsCategoriesResource_Factory(t) { return new (t || ListsCategoriesResource)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.MJNotificationService)); };
|
|
681
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ListsCategoriesResource, selectors: [["mj-lists-categories-resource"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 18, vars: 5, consts: [["categoryNodeTemplate", ""], [1, "lists-categories-container"], [1, "categories-header"], [1, "header-title"], [1, "fa-solid", "fa-tags"], [1, "header-actions"], [1, "btn-create", 3, "click"], [1, "fa-solid", "fa-plus"], ["class", "loading-container", 4, "ngIf"], ["class", "empty-state", 4, "ngIf"], ["class", "categories-content", 4, "ngIf"], ["class", "modal-overlay", 3, "click", 4, "ngIf"], [1, "loading-container"], ["text", "Loading categories...", "size", "medium"], [1, "empty-state"], [1, "empty-state-icon-wrapper"], [1, "icon-bg"], [1, "fa-solid", "fa-folder-tree"], [1, "empty-state-features"], [1, "feature-item"], [1, "fa-solid", "fa-check-circle"], [1, "btn-create-large", 3, "click"], [1, "categories-content"], [1, "categories-layout"], [1, "category-tree-panel"], [1, "panel-header"], [1, "count-badge"], ["role", "tree", "aria-label", "Category tree", 1, "tree-content"], [4, "ngFor", "ngForOf"], ["class", "category-detail-panel", 4, "ngIf"], ["class", "category-detail-panel empty", 4, "ngIf"], [4, "ngTemplateOutlet", "ngTemplateOutletContext"], [1, "category-detail-panel"], [1, "panel-actions"], ["title", "Edit", 1, "icon-btn", 3, "click"], [1, "fa-solid", "fa-pen"], ["title", "Delete", 1, "icon-btn", "danger", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "detail-content"], [1, "detail-field"], [1, "field-value"], ["class", "detail-field", 4, "ngIf"], [1, "detail-stats"], [1, "stat-item"], [1, "stat-value"], [1, "stat-label"], ["class", "category-lists", 4, "ngIf"], [1, "category-lists"], [1, "mini-list"], ["class", "mini-list-item", 4, "ngFor", "ngForOf"], [1, "mini-list-item"], [1, "fa-solid", "fa-list"], [1, "category-detail-panel", "empty"], [1, "no-selection"], [1, "fa-solid", "fa-arrow-left"], [1, "category-node"], ["tabindex", "0", "role", "treeitem", 1, "node-content", 3, "click", "keydown.enter", "keydown.space", "keydown.arrowRight", "keydown.arrowLeft"], ["class", "expand-btn", "tabindex", "-1", "aria-hidden", "true", 3, "click", 4, "ngIf"], ["class", "expand-placeholder", 4, "ngIf"], ["aria-hidden", "true", 1, "fa-solid", "fa-folder"], [1, "node-name"], ["aria-hidden", "true", 1, "node-count"], ["class", "node-children", "role", "group", 4, "ngIf"], ["tabindex", "-1", "aria-hidden", "true", 1, "expand-btn", 3, "click"], [1, "expand-placeholder"], ["role", "group", 1, "node-children"], [1, "modal-overlay", 3, "click"], [1, "modal-dialog", 3, "click"], [1, "modal-header"], [1, "modal-close", 3, "click", "disabled"], [1, "fa-solid", "fa-times"], [1, "modal-body"], [1, "category-form"], [1, "form-group"], ["type", "text", "placeholder", "Enter category name", 1, "form-input", 3, "ngModelChange", "ngModel"], ["placeholder", "Optional description", "rows", "3", 1, "form-input", 3, "ngModelChange", "ngModel"], [1, "form-input", 3, "ngModelChange", "ngModel"], [3, "ngValue", 4, "ngFor", "ngForOf"], [1, "modal-footer"], [1, "btn-primary", 3, "click", "disabled"], ["class", "fa-solid fa-spinner fa-spin", 4, "ngIf"], [1, "btn-secondary", 3, "click", "disabled"], [3, "ngValue"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "modal-dialog", "modal-sm", 3, "click"], [1, "modal-header", "danger"], [1, "modal-close", 3, "click"], [1, "btn-danger", 3, "click"], [1, "btn-secondary", 3, "click"]], template: function ListsCategoriesResource_Template(rf, ctx) { if (rf & 1) {
|
|
682
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
683
|
+
i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3);
|
|
684
|
+
i0.ɵɵelement(3, "i", 4);
|
|
685
|
+
i0.ɵɵelementStart(4, "h2");
|
|
686
|
+
i0.ɵɵtext(5, "List Categories");
|
|
687
|
+
i0.ɵɵelementEnd()();
|
|
688
|
+
i0.ɵɵelementStart(6, "div", 5)(7, "button", 6);
|
|
689
|
+
i0.ɵɵlistener("click", function ListsCategoriesResource_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.createCategory()); });
|
|
690
|
+
i0.ɵɵelement(8, "i", 7);
|
|
691
|
+
i0.ɵɵelementStart(9, "span");
|
|
692
|
+
i0.ɵɵtext(10, "New Category");
|
|
693
|
+
i0.ɵɵelementEnd()()()();
|
|
694
|
+
i0.ɵɵtemplate(11, ListsCategoriesResource_div_11_Template, 2, 0, "div", 8)(12, ListsCategoriesResource_div_12_Template, 20, 0, "div", 9)(13, ListsCategoriesResource_div_13_Template, 12, 4, "div", 10)(14, ListsCategoriesResource_ng_template_14_Template, 10, 14, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor)(16, ListsCategoriesResource_div_16_Template, 28, 10, "div", 11)(17, ListsCategoriesResource_div_17_Template, 15, 1, "div", 11);
|
|
695
|
+
i0.ɵɵelementEnd();
|
|
696
|
+
} if (rf & 2) {
|
|
697
|
+
i0.ɵɵadvance(11);
|
|
698
|
+
i0.ɵɵproperty("ngIf", ctx.isLoading);
|
|
699
|
+
i0.ɵɵadvance();
|
|
700
|
+
i0.ɵɵproperty("ngIf", !ctx.isLoading && ctx.categoryViewModels.length === 0);
|
|
701
|
+
i0.ɵɵadvance();
|
|
702
|
+
i0.ɵɵproperty("ngIf", !ctx.isLoading && ctx.categoryViewModels.length > 0);
|
|
703
|
+
i0.ɵɵadvance(3);
|
|
704
|
+
i0.ɵɵproperty("ngIf", ctx.showDialog);
|
|
705
|
+
i0.ɵɵadvance();
|
|
706
|
+
i0.ɵɵproperty("ngIf", ctx.showDeleteConfirm);
|
|
707
|
+
} }, dependencies: [i2.NgForOf, i2.NgIf, i2.NgTemplateOutlet, i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i3.DefaultValueAccessor, i3.SelectControlValueAccessor, i3.NgControlStatus, i3.NgModel, i4.LoadingComponent], styles: ["\n :host {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n }\n\n .lists-categories-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f5f7fa;\n overflow: hidden;\n }\n\n /* Header */\n .categories-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 24px;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n }\n\n .header-title {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .header-title i {\n font-size: 24px;\n color: #2196F3;\n }\n\n .header-title h2 {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n }\n\n .btn-create {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: #2196F3;\n color: white;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s;\n }\n\n .btn-create:hover {\n background: #1976D2;\n }\n\n /* Loading */\n .loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n }\n\n /* Empty State */\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n padding: 48px 40px;\n text-align: center;\n max-width: 420px;\n margin: 0 auto;\n }\n\n .empty-state-icon-wrapper {\n position: relative;\n margin-bottom: 24px;\n }\n\n .empty-state-icon-wrapper .icon-bg {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 100px;\n height: 100px;\n border-radius: 50%;\n background: linear-gradient(135deg, rgba(33, 150, 243, 0.1) 0%, rgba(33, 150, 243, 0.05) 100%);\n }\n\n .empty-state-icon-wrapper > i {\n position: relative;\n font-size: 48px;\n color: #2196F3;\n z-index: 1;\n }\n\n .empty-state h3 {\n margin: 0 0 12px;\n font-size: 22px;\n font-weight: 600;\n color: #333;\n }\n\n .empty-state p {\n margin: 0 0 8px;\n color: #666;\n font-size: 15px;\n line-height: 1.5;\n }\n\n .empty-state-features {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin: 16px 0 24px;\n text-align: left;\n }\n\n .feature-item {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 14px;\n color: #555;\n }\n\n .feature-item i {\n font-size: 14px !important;\n color: #4CAF50 !important;\n }\n\n .btn-create-large {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 28px;\n background: linear-gradient(135deg, #2196F3 0%, #1976D2 100%);\n color: white;\n border: none;\n border-radius: 8px;\n font-size: 15px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.3);\n }\n\n .btn-create-large:hover {\n background: linear-gradient(135deg, #1976D2 0%, #1565C0 100%);\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.4);\n }\n\n /* Content Layout */\n .categories-content {\n flex: 1;\n padding: 16px 24px;\n overflow: hidden;\n }\n\n .categories-layout {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 16px;\n height: 100%;\n }\n\n .category-tree-panel,\n .category-detail-panel {\n background: white;\n border-radius: 8px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.08);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n border-bottom: 1px solid #e0e0e0;\n background: #fafafa;\n }\n\n .panel-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n }\n\n .count-badge {\n font-size: 12px;\n color: #999;\n background: #f0f0f0;\n padding: 2px 8px;\n border-radius: 10px;\n }\n\n .panel-actions {\n display: flex;\n gap: 4px;\n }\n\n .icon-btn {\n background: none;\n border: none;\n padding: 6px 8px;\n color: #666;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.15s;\n }\n\n .icon-btn:hover {\n background: #f0f0f0;\n color: #333;\n }\n\n .icon-btn.danger:hover {\n background: #ffebee;\n color: #d32f2f;\n }\n\n /* Tree Content */\n .tree-content {\n flex: 1;\n overflow-y: auto;\n padding: 8px 0;\n }\n\n .category-node {\n user-select: none;\n }\n\n .node-content {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n cursor: pointer;\n transition: background 0.15s;\n }\n\n .node-content:hover {\n background: #f5f5f5;\n }\n\n .node-content:focus {\n outline: none;\n background: #e8f4fd;\n }\n\n .node-content:focus-visible {\n outline: 2px solid #2196F3;\n outline-offset: -2px;\n background: #e8f4fd;\n }\n\n .node-content.selected {\n background: #e3f2fd;\n }\n\n .node-content.selected:focus-visible {\n outline: 2px solid #1976D2;\n }\n\n .expand-btn {\n background: none;\n border: none;\n padding: 2px;\n color: #999;\n cursor: pointer;\n width: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .expand-btn:hover {\n color: #666;\n }\n\n .expand-placeholder {\n width: 20px;\n }\n\n .node-content .fa-folder,\n .node-content .fa-folder-open {\n color: #ffc107;\n }\n\n .node-name {\n flex: 1;\n font-size: 14px;\n color: #333;\n }\n\n .node-count {\n font-size: 12px;\n color: #999;\n background: #f0f0f0;\n padding: 1px 6px;\n border-radius: 8px;\n }\n\n /* Detail Panel */\n .detail-content {\n flex: 1;\n padding: 16px;\n overflow-y: auto;\n }\n\n .detail-field {\n margin-bottom: 16px;\n }\n\n .detail-field label {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: #999;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 4px;\n }\n\n .field-value {\n font-size: 14px;\n color: #333;\n }\n\n .detail-stats {\n display: flex;\n gap: 24px;\n margin: 24px 0;\n padding: 16px;\n background: #f5f7fa;\n border-radius: 8px;\n }\n\n .stat-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .stat-value {\n font-size: 24px;\n font-weight: 600;\n color: #2196F3;\n }\n\n .stat-label {\n font-size: 12px;\n color: #999;\n }\n\n .category-lists h4 {\n margin: 0 0 12px;\n font-size: 13px;\n font-weight: 600;\n color: #666;\n }\n\n .mini-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n .mini-list-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #f5f7fa;\n border-radius: 4px;\n font-size: 13px;\n color: #333;\n }\n\n .mini-list-item i {\n color: #999;\n }\n\n /* No Selection */\n .category-detail-panel.empty {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .no-selection {\n text-align: center;\n color: #999;\n }\n\n .no-selection i {\n font-size: 32px;\n margin-bottom: 12px;\n }\n\n .no-selection p {\n margin: 0;\n }\n\n /* Form */\n .category-form {\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n\n .form-group {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .form-group label {\n font-size: 13px;\n font-weight: 500;\n color: #666;\n }\n\n .form-input {\n padding: 8px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 14px;\n }\n\n .form-input:focus {\n outline: none;\n border-color: #2196F3;\n }\n\n /* Modal Styles */\n .modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n animation: fadeIn 0.15s ease-out;\n }\n\n @keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n .modal-dialog {\n background: white;\n border-radius: 8px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n width: 450px;\n max-width: 90vw;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n animation: slideIn 0.2s ease-out;\n }\n\n .modal-dialog.modal-sm {\n width: 400px;\n }\n\n @keyframes slideIn {\n from { transform: translateY(-20px); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n }\n\n .modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid #e0e0e0;\n }\n\n .modal-header.danger {\n background: #ffebee;\n border-bottom-color: #ffcdd2;\n }\n\n .modal-header.danger h3 {\n color: #c62828;\n }\n\n .modal-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #333;\n }\n\n .modal-close {\n background: none;\n border: none;\n padding: 4px 8px;\n color: #999;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.15s;\n }\n\n .modal-close:hover:not(:disabled) {\n background: #f0f0f0;\n color: #333;\n }\n\n .modal-close:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .modal-body {\n padding: 20px;\n overflow-y: auto;\n }\n\n .modal-body p {\n margin: 0;\n color: #666;\n line-height: 1.6;\n }\n\n .modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n padding: 16px 20px;\n border-top: 1px solid #e0e0e0;\n background: #fafafa;\n }\n\n .btn-secondary {\n padding: 8px 16px;\n background: white;\n border: 1px solid #ddd;\n border-radius: 6px;\n color: #666;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .btn-secondary:hover:not(:disabled) {\n background: #f5f5f5;\n border-color: #ccc;\n }\n\n .btn-secondary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-primary {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: #2196F3;\n border: none;\n border-radius: 6px;\n color: white;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .btn-primary:hover:not(:disabled) {\n background: #1976D2;\n }\n\n .btn-primary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-danger {\n padding: 8px 16px;\n background: #d32f2f;\n border: none;\n border-radius: 6px;\n color: white;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .btn-danger:hover {\n background: #c62828;\n }\n\n /* Responsive */\n @media (max-width: 768px) {\n .categories-layout {\n grid-template-columns: 1fr;\n }\n\n .category-detail-panel.empty {\n display: none;\n }\n\n .modal-dialog {\n width: 95vw;\n }\n }\n "], encapsulation: 2 });
|
|
708
|
+
};
|
|
709
|
+
ListsCategoriesResource = __decorate([
|
|
710
|
+
RegisterClass(BaseResourceComponent, 'ListsCategoriesResource')
|
|
711
|
+
], ListsCategoriesResource);
|
|
712
|
+
export { ListsCategoriesResource };
|
|
713
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ListsCategoriesResource, [{
|
|
714
|
+
type: Component,
|
|
715
|
+
args: [{ selector: 'mj-lists-categories-resource', template: `
|
|
716
|
+
<div class="lists-categories-container">
|
|
717
|
+
<!-- Header -->
|
|
718
|
+
<div class="categories-header">
|
|
719
|
+
<div class="header-title">
|
|
720
|
+
<i class="fa-solid fa-tags"></i>
|
|
721
|
+
<h2>List Categories</h2>
|
|
722
|
+
</div>
|
|
723
|
+
<div class="header-actions">
|
|
724
|
+
<button class="btn-create" (click)="createCategory()">
|
|
725
|
+
<i class="fa-solid fa-plus"></i>
|
|
726
|
+
<span>New Category</span>
|
|
727
|
+
</button>
|
|
728
|
+
</div>
|
|
729
|
+
</div>
|
|
730
|
+
|
|
731
|
+
<!-- Loading State -->
|
|
732
|
+
<div class="loading-container" *ngIf="isLoading">
|
|
733
|
+
<mj-loading text="Loading categories..." size="medium"></mj-loading>
|
|
734
|
+
</div>
|
|
735
|
+
|
|
736
|
+
<!-- Empty State -->
|
|
737
|
+
<div class="empty-state" *ngIf="!isLoading && categoryViewModels.length === 0">
|
|
738
|
+
<div class="empty-state-icon-wrapper">
|
|
739
|
+
<div class="icon-bg"></div>
|
|
740
|
+
<i class="fa-solid fa-folder-tree"></i>
|
|
741
|
+
</div>
|
|
742
|
+
<h3>No Categories Yet</h3>
|
|
743
|
+
<p>Categories help you organize lists into logical groups.</p>
|
|
744
|
+
<div class="empty-state-features">
|
|
745
|
+
<div class="feature-item">
|
|
746
|
+
<i class="fa-solid fa-check-circle"></i>
|
|
747
|
+
<span>Create hierarchical folder structures</span>
|
|
748
|
+
</div>
|
|
749
|
+
<div class="feature-item">
|
|
750
|
+
<i class="fa-solid fa-check-circle"></i>
|
|
751
|
+
<span>Quickly find related lists</span>
|
|
752
|
+
</div>
|
|
753
|
+
</div>
|
|
754
|
+
<button class="btn-create-large" (click)="createCategory()">
|
|
755
|
+
<i class="fa-solid fa-plus"></i>
|
|
756
|
+
Create Your First Category
|
|
757
|
+
</button>
|
|
758
|
+
</div>
|
|
759
|
+
|
|
760
|
+
<!-- Categories Content -->
|
|
761
|
+
<div class="categories-content" *ngIf="!isLoading && categoryViewModels.length > 0">
|
|
762
|
+
<div class="categories-layout">
|
|
763
|
+
<!-- Category Tree -->
|
|
764
|
+
<div class="category-tree-panel">
|
|
765
|
+
<div class="panel-header">
|
|
766
|
+
<h3>Categories</h3>
|
|
767
|
+
<span class="count-badge">{{categories.length}}</span>
|
|
768
|
+
</div>
|
|
769
|
+
<div class="tree-content" role="tree" aria-label="Category tree">
|
|
770
|
+
<ng-container *ngFor="let vm of getTopLevelCategories()">
|
|
771
|
+
<ng-container *ngTemplateOutlet="categoryNodeTemplate; context: { vm: vm }"></ng-container>
|
|
772
|
+
</ng-container>
|
|
773
|
+
</div>
|
|
774
|
+
</div>
|
|
775
|
+
|
|
776
|
+
<!-- Category Details -->
|
|
777
|
+
<div class="category-detail-panel" *ngIf="selectedCategory">
|
|
778
|
+
<div class="panel-header">
|
|
779
|
+
<h3>Category Details</h3>
|
|
780
|
+
<div class="panel-actions">
|
|
781
|
+
<button class="icon-btn" (click)="editCategory()" title="Edit">
|
|
782
|
+
<i class="fa-solid fa-pen"></i>
|
|
783
|
+
</button>
|
|
784
|
+
<button class="icon-btn danger" (click)="deleteCategory()" title="Delete">
|
|
785
|
+
<i class="fa-solid fa-trash"></i>
|
|
786
|
+
</button>
|
|
787
|
+
</div>
|
|
788
|
+
</div>
|
|
789
|
+
<div class="detail-content">
|
|
790
|
+
<div class="detail-field">
|
|
791
|
+
<label>Name</label>
|
|
792
|
+
<span class="field-value">{{selectedCategory.Name}}</span>
|
|
793
|
+
</div>
|
|
794
|
+
<div class="detail-field" *ngIf="selectedCategory.Description">
|
|
795
|
+
<label>Description</label>
|
|
796
|
+
<span class="field-value">{{selectedCategory.Description}}</span>
|
|
797
|
+
</div>
|
|
798
|
+
<div class="detail-field">
|
|
799
|
+
<label>Parent Category</label>
|
|
800
|
+
<span class="field-value">
|
|
801
|
+
{{getParentCategoryName(selectedCategory) || '(Top Level)'}}
|
|
802
|
+
</span>
|
|
803
|
+
</div>
|
|
804
|
+
<div class="detail-stats">
|
|
805
|
+
<div class="stat-item">
|
|
806
|
+
<span class="stat-value">{{getSelectedCategoryListCount()}}</span>
|
|
807
|
+
<span class="stat-label">Lists</span>
|
|
808
|
+
</div>
|
|
809
|
+
<div class="stat-item">
|
|
810
|
+
<span class="stat-value">{{getSelectedCategoryChildCount()}}</span>
|
|
811
|
+
<span class="stat-label">Subcategories</span>
|
|
812
|
+
</div>
|
|
813
|
+
</div>
|
|
814
|
+
|
|
815
|
+
<!-- Lists in this category -->
|
|
816
|
+
<div class="category-lists" *ngIf="selectedCategoryLists.length > 0">
|
|
817
|
+
<h4>Lists in this category</h4>
|
|
818
|
+
<div class="mini-list">
|
|
819
|
+
<div class="mini-list-item" *ngFor="let list of selectedCategoryLists">
|
|
820
|
+
<i class="fa-solid fa-list"></i>
|
|
821
|
+
<span>{{list.Name}}</span>
|
|
822
|
+
</div>
|
|
823
|
+
</div>
|
|
824
|
+
</div>
|
|
825
|
+
</div>
|
|
826
|
+
</div>
|
|
827
|
+
|
|
828
|
+
<!-- No Selection State -->
|
|
829
|
+
<div class="category-detail-panel empty" *ngIf="!selectedCategory">
|
|
830
|
+
<div class="no-selection">
|
|
831
|
+
<i class="fa-solid fa-arrow-left"></i>
|
|
832
|
+
<p>Select a category to view details</p>
|
|
833
|
+
</div>
|
|
834
|
+
</div>
|
|
835
|
+
</div>
|
|
836
|
+
</div>
|
|
837
|
+
|
|
838
|
+
<!-- Category Node Template -->
|
|
839
|
+
<ng-template #categoryNodeTemplate let-vm="vm">
|
|
840
|
+
<div class="category-node" [style.padding-left.px]="vm.depth * 20">
|
|
841
|
+
<div
|
|
842
|
+
class="node-content"
|
|
843
|
+
[class.selected]="selectedCategory?.ID === vm.category.ID"
|
|
844
|
+
(click)="selectCategory(vm.category)"
|
|
845
|
+
(keydown.enter)="selectCategory(vm.category)"
|
|
846
|
+
(keydown.space)="selectCategory(vm.category); $event.preventDefault()"
|
|
847
|
+
(keydown.arrowRight)="expandNode($event, vm)"
|
|
848
|
+
(keydown.arrowLeft)="collapseNode($event, vm)"
|
|
849
|
+
tabindex="0"
|
|
850
|
+
role="treeitem"
|
|
851
|
+
[attr.aria-expanded]="hasChildren(vm.category) ? vm.isExpanded : null"
|
|
852
|
+
[attr.aria-selected]="selectedCategory?.ID === vm.category.ID"
|
|
853
|
+
[attr.aria-label]="vm.category.Name + ' - ' + vm.listCount + ' lists'">
|
|
854
|
+
<button
|
|
855
|
+
class="expand-btn"
|
|
856
|
+
*ngIf="hasChildren(vm.category)"
|
|
857
|
+
(click)="toggleExpand($event, vm)"
|
|
858
|
+
tabindex="-1"
|
|
859
|
+
aria-hidden="true">
|
|
860
|
+
<i [class]="vm.isExpanded ? 'fa-solid fa-chevron-down' : 'fa-solid fa-chevron-right'"></i>
|
|
861
|
+
</button>
|
|
862
|
+
<span class="expand-placeholder" *ngIf="!hasChildren(vm.category)"></span>
|
|
863
|
+
<i class="fa-solid fa-folder" [class.fa-folder-open]="vm.isExpanded" aria-hidden="true"></i>
|
|
864
|
+
<span class="node-name">{{vm.category.Name}}</span>
|
|
865
|
+
<span class="node-count" aria-hidden="true">{{vm.listCount}}</span>
|
|
866
|
+
</div>
|
|
867
|
+
<div class="node-children" *ngIf="vm.isExpanded && hasChildren(vm.category)" role="group">
|
|
868
|
+
<ng-container *ngFor="let childVm of getChildCategories(vm.category)">
|
|
869
|
+
<ng-container *ngTemplateOutlet="categoryNodeTemplate; context: { vm: childVm }"></ng-container>
|
|
870
|
+
</ng-container>
|
|
871
|
+
</div>
|
|
872
|
+
</div>
|
|
873
|
+
</ng-template>
|
|
874
|
+
|
|
875
|
+
<!-- Create/Edit Dialog -->
|
|
876
|
+
<div class="modal-overlay" *ngIf="showDialog" (click)="closeDialog()">
|
|
877
|
+
<div class="modal-dialog" (click)="$event.stopPropagation()">
|
|
878
|
+
<div class="modal-header">
|
|
879
|
+
<h3>{{editingCategory ? 'Edit Category' : 'Create Category'}}</h3>
|
|
880
|
+
<button class="modal-close" (click)="closeDialog()" [disabled]="isSaving">
|
|
881
|
+
<i class="fa-solid fa-times"></i>
|
|
882
|
+
</button>
|
|
883
|
+
</div>
|
|
884
|
+
<div class="modal-body">
|
|
885
|
+
<div class="category-form">
|
|
886
|
+
<div class="form-group">
|
|
887
|
+
<label>Name *</label>
|
|
888
|
+
<input
|
|
889
|
+
type="text"
|
|
890
|
+
[(ngModel)]="dialogName"
|
|
891
|
+
placeholder="Enter category name"
|
|
892
|
+
class="form-input" />
|
|
893
|
+
</div>
|
|
894
|
+
<div class="form-group">
|
|
895
|
+
<label>Description</label>
|
|
896
|
+
<textarea
|
|
897
|
+
[(ngModel)]="dialogDescription"
|
|
898
|
+
placeholder="Optional description"
|
|
899
|
+
class="form-input"
|
|
900
|
+
rows="3"></textarea>
|
|
901
|
+
</div>
|
|
902
|
+
<div class="form-group">
|
|
903
|
+
<label>Parent Category</label>
|
|
904
|
+
<select
|
|
905
|
+
[(ngModel)]="dialogParentId"
|
|
906
|
+
class="form-input">
|
|
907
|
+
<option *ngFor="let parent of availableParents" [ngValue]="parent.ID">{{parent.displayName}}</option>
|
|
908
|
+
</select>
|
|
909
|
+
</div>
|
|
910
|
+
</div>
|
|
911
|
+
</div>
|
|
912
|
+
<div class="modal-footer">
|
|
913
|
+
<button
|
|
914
|
+
class="btn-primary"
|
|
915
|
+
(click)="saveCategory()"
|
|
916
|
+
[disabled]="!dialogName || isSaving">
|
|
917
|
+
<i *ngIf="isSaving" class="fa-solid fa-spinner fa-spin"></i>
|
|
918
|
+
{{isSaving ? 'Saving...' : (editingCategory ? 'Save' : 'Create')}}
|
|
919
|
+
</button>
|
|
920
|
+
<button class="btn-secondary" (click)="closeDialog()" [disabled]="isSaving">Cancel</button>
|
|
921
|
+
</div>
|
|
922
|
+
</div>
|
|
923
|
+
</div>
|
|
924
|
+
|
|
925
|
+
<!-- Delete Confirmation Dialog -->
|
|
926
|
+
<div class="modal-overlay" *ngIf="showDeleteConfirm" (click)="cancelDelete()">
|
|
927
|
+
<div class="modal-dialog modal-sm" (click)="$event.stopPropagation()">
|
|
928
|
+
<div class="modal-header danger">
|
|
929
|
+
<h3>Delete Category</h3>
|
|
930
|
+
<button class="modal-close" (click)="cancelDelete()">
|
|
931
|
+
<i class="fa-solid fa-times"></i>
|
|
932
|
+
</button>
|
|
933
|
+
</div>
|
|
934
|
+
<div class="modal-body">
|
|
935
|
+
<p>{{deleteConfirmMessage}}</p>
|
|
936
|
+
</div>
|
|
937
|
+
<div class="modal-footer">
|
|
938
|
+
<button class="btn-danger" (click)="confirmDelete()">
|
|
939
|
+
Delete
|
|
940
|
+
</button>
|
|
941
|
+
<button class="btn-secondary" (click)="cancelDelete()">Cancel</button>
|
|
942
|
+
</div>
|
|
943
|
+
</div>
|
|
944
|
+
</div>
|
|
945
|
+
</div>
|
|
946
|
+
`, encapsulation: ViewEncapsulation.None, styles: ["\n :host {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n }\n\n .lists-categories-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f5f7fa;\n overflow: hidden;\n }\n\n /* Header */\n .categories-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 24px;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n }\n\n .header-title {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .header-title i {\n font-size: 24px;\n color: #2196F3;\n }\n\n .header-title h2 {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n }\n\n .btn-create {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: #2196F3;\n color: white;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.2s;\n }\n\n .btn-create:hover {\n background: #1976D2;\n }\n\n /* Loading */\n .loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n }\n\n /* Empty State */\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n padding: 48px 40px;\n text-align: center;\n max-width: 420px;\n margin: 0 auto;\n }\n\n .empty-state-icon-wrapper {\n position: relative;\n margin-bottom: 24px;\n }\n\n .empty-state-icon-wrapper .icon-bg {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 100px;\n height: 100px;\n border-radius: 50%;\n background: linear-gradient(135deg, rgba(33, 150, 243, 0.1) 0%, rgba(33, 150, 243, 0.05) 100%);\n }\n\n .empty-state-icon-wrapper > i {\n position: relative;\n font-size: 48px;\n color: #2196F3;\n z-index: 1;\n }\n\n .empty-state h3 {\n margin: 0 0 12px;\n font-size: 22px;\n font-weight: 600;\n color: #333;\n }\n\n .empty-state p {\n margin: 0 0 8px;\n color: #666;\n font-size: 15px;\n line-height: 1.5;\n }\n\n .empty-state-features {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin: 16px 0 24px;\n text-align: left;\n }\n\n .feature-item {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 14px;\n color: #555;\n }\n\n .feature-item i {\n font-size: 14px !important;\n color: #4CAF50 !important;\n }\n\n .btn-create-large {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 28px;\n background: linear-gradient(135deg, #2196F3 0%, #1976D2 100%);\n color: white;\n border: none;\n border-radius: 8px;\n font-size: 15px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.3);\n }\n\n .btn-create-large:hover {\n background: linear-gradient(135deg, #1976D2 0%, #1565C0 100%);\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.4);\n }\n\n /* Content Layout */\n .categories-content {\n flex: 1;\n padding: 16px 24px;\n overflow: hidden;\n }\n\n .categories-layout {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 16px;\n height: 100%;\n }\n\n .category-tree-panel,\n .category-detail-panel {\n background: white;\n border-radius: 8px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.08);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n border-bottom: 1px solid #e0e0e0;\n background: #fafafa;\n }\n\n .panel-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n }\n\n .count-badge {\n font-size: 12px;\n color: #999;\n background: #f0f0f0;\n padding: 2px 8px;\n border-radius: 10px;\n }\n\n .panel-actions {\n display: flex;\n gap: 4px;\n }\n\n .icon-btn {\n background: none;\n border: none;\n padding: 6px 8px;\n color: #666;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.15s;\n }\n\n .icon-btn:hover {\n background: #f0f0f0;\n color: #333;\n }\n\n .icon-btn.danger:hover {\n background: #ffebee;\n color: #d32f2f;\n }\n\n /* Tree Content */\n .tree-content {\n flex: 1;\n overflow-y: auto;\n padding: 8px 0;\n }\n\n .category-node {\n user-select: none;\n }\n\n .node-content {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n cursor: pointer;\n transition: background 0.15s;\n }\n\n .node-content:hover {\n background: #f5f5f5;\n }\n\n .node-content:focus {\n outline: none;\n background: #e8f4fd;\n }\n\n .node-content:focus-visible {\n outline: 2px solid #2196F3;\n outline-offset: -2px;\n background: #e8f4fd;\n }\n\n .node-content.selected {\n background: #e3f2fd;\n }\n\n .node-content.selected:focus-visible {\n outline: 2px solid #1976D2;\n }\n\n .expand-btn {\n background: none;\n border: none;\n padding: 2px;\n color: #999;\n cursor: pointer;\n width: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .expand-btn:hover {\n color: #666;\n }\n\n .expand-placeholder {\n width: 20px;\n }\n\n .node-content .fa-folder,\n .node-content .fa-folder-open {\n color: #ffc107;\n }\n\n .node-name {\n flex: 1;\n font-size: 14px;\n color: #333;\n }\n\n .node-count {\n font-size: 12px;\n color: #999;\n background: #f0f0f0;\n padding: 1px 6px;\n border-radius: 8px;\n }\n\n /* Detail Panel */\n .detail-content {\n flex: 1;\n padding: 16px;\n overflow-y: auto;\n }\n\n .detail-field {\n margin-bottom: 16px;\n }\n\n .detail-field label {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: #999;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 4px;\n }\n\n .field-value {\n font-size: 14px;\n color: #333;\n }\n\n .detail-stats {\n display: flex;\n gap: 24px;\n margin: 24px 0;\n padding: 16px;\n background: #f5f7fa;\n border-radius: 8px;\n }\n\n .stat-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .stat-value {\n font-size: 24px;\n font-weight: 600;\n color: #2196F3;\n }\n\n .stat-label {\n font-size: 12px;\n color: #999;\n }\n\n .category-lists h4 {\n margin: 0 0 12px;\n font-size: 13px;\n font-weight: 600;\n color: #666;\n }\n\n .mini-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n .mini-list-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #f5f7fa;\n border-radius: 4px;\n font-size: 13px;\n color: #333;\n }\n\n .mini-list-item i {\n color: #999;\n }\n\n /* No Selection */\n .category-detail-panel.empty {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .no-selection {\n text-align: center;\n color: #999;\n }\n\n .no-selection i {\n font-size: 32px;\n margin-bottom: 12px;\n }\n\n .no-selection p {\n margin: 0;\n }\n\n /* Form */\n .category-form {\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n\n .form-group {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .form-group label {\n font-size: 13px;\n font-weight: 500;\n color: #666;\n }\n\n .form-input {\n padding: 8px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 14px;\n }\n\n .form-input:focus {\n outline: none;\n border-color: #2196F3;\n }\n\n /* Modal Styles */\n .modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n animation: fadeIn 0.15s ease-out;\n }\n\n @keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n .modal-dialog {\n background: white;\n border-radius: 8px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n width: 450px;\n max-width: 90vw;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n animation: slideIn 0.2s ease-out;\n }\n\n .modal-dialog.modal-sm {\n width: 400px;\n }\n\n @keyframes slideIn {\n from { transform: translateY(-20px); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n }\n\n .modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid #e0e0e0;\n }\n\n .modal-header.danger {\n background: #ffebee;\n border-bottom-color: #ffcdd2;\n }\n\n .modal-header.danger h3 {\n color: #c62828;\n }\n\n .modal-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #333;\n }\n\n .modal-close {\n background: none;\n border: none;\n padding: 4px 8px;\n color: #999;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.15s;\n }\n\n .modal-close:hover:not(:disabled) {\n background: #f0f0f0;\n color: #333;\n }\n\n .modal-close:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .modal-body {\n padding: 20px;\n overflow-y: auto;\n }\n\n .modal-body p {\n margin: 0;\n color: #666;\n line-height: 1.6;\n }\n\n .modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n padding: 16px 20px;\n border-top: 1px solid #e0e0e0;\n background: #fafafa;\n }\n\n .btn-secondary {\n padding: 8px 16px;\n background: white;\n border: 1px solid #ddd;\n border-radius: 6px;\n color: #666;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .btn-secondary:hover:not(:disabled) {\n background: #f5f5f5;\n border-color: #ccc;\n }\n\n .btn-secondary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-primary {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: #2196F3;\n border: none;\n border-radius: 6px;\n color: white;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .btn-primary:hover:not(:disabled) {\n background: #1976D2;\n }\n\n .btn-primary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-danger {\n padding: 8px 16px;\n background: #d32f2f;\n border: none;\n border-radius: 6px;\n color: white;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .btn-danger:hover {\n background: #c62828;\n }\n\n /* Responsive */\n @media (max-width: 768px) {\n .categories-layout {\n grid-template-columns: 1fr;\n }\n\n .category-detail-panel.empty {\n display: none;\n }\n\n .modal-dialog {\n width: 95vw;\n }\n }\n "] }]
|
|
947
|
+
}], () => [{ type: i0.ChangeDetectorRef }, { type: i1.MJNotificationService }], null); })();
|
|
948
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ListsCategoriesResource, { className: "ListsCategoriesResource", filePath: "src/Lists/components/lists-categories-resource.component.ts", lineNumber: 891 }); })();
|
|
949
|
+
//# sourceMappingURL=lists-categories-resource.component.js.map
|