@memberjunction/ng-explorer-core 2.98.0 → 2.99.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.
@@ -5,77 +5,896 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { Component } from '@angular/core';
8
- import { ItemType } from '../../generic/Item.types';
9
8
  import { BaseNavigationComponent } from '@memberjunction/ng-shared';
10
- import { BaseBrowserComponent } from '../base-browser-component/base-browser-component';
11
- import { Metadata } from '@memberjunction/core';
9
+ import { Metadata, RunView } from '@memberjunction/core';
12
10
  import { RegisterClass } from '@memberjunction/global';
11
+ import { Subject } from 'rxjs';
12
+ import { debounceTime, takeUntil } from 'rxjs/operators';
13
13
  import * as i0 from "@angular/core";
14
14
  import * as i1 from "@angular/router";
15
15
  import * as i2 from "@memberjunction/ng-shared";
16
- import * as i3 from "../resource-browser/resource-browser.component";
17
- let QueryBrowserComponent = class QueryBrowserComponent extends BaseBrowserComponent {
16
+ import * as i3 from "@angular/forms";
17
+ import * as i4 from "@progress/kendo-angular-dropdowns";
18
+ const _forTrack0 = ($index, $item) => $item.id;
19
+ const _forTrack1 = ($index, $item) => $item.ID;
20
+ function QueryBrowserComponent_Conditional_29_Template(rf, ctx) { if (rf & 1) {
21
+ const _r1 = i0.ɵɵgetCurrentView();
22
+ i0.ɵɵelementStart(0, "button", 27);
23
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Conditional_29_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.clearAllFilters()); });
24
+ i0.ɵɵelement(1, "i", 28);
25
+ i0.ɵɵtext(2, " Clear Filters ");
26
+ i0.ɵɵelementEnd();
27
+ } }
28
+ function QueryBrowserComponent_Conditional_30_Template(rf, ctx) { if (rf & 1) {
29
+ i0.ɵɵelementStart(0, "div", 22);
30
+ i0.ɵɵelement(1, "i", 29);
31
+ i0.ɵɵtext(2, " Loading queries... ");
32
+ i0.ɵɵelementEnd();
33
+ } }
34
+ function QueryBrowserComponent_Conditional_32_For_5_Template(rf, ctx) { if (rf & 1) {
35
+ const _r4 = i0.ɵɵgetCurrentView();
36
+ i0.ɵɵelement(0, "i", 35);
37
+ i0.ɵɵelementStart(1, "span", 31);
38
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Conditional_32_For_5_Template_span_click_1_listener() { const pathItem_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.navigateToCategory(pathItem_r5.id)); });
39
+ i0.ɵɵtext(2);
40
+ i0.ɵɵelementEnd();
41
+ } if (rf & 2) {
42
+ const pathItem_r5 = ctx.$implicit;
43
+ const ctx_r1 = i0.ɵɵnextContext(2);
44
+ i0.ɵɵadvance();
45
+ i0.ɵɵclassProp("current", pathItem_r5.id === ctx_r1.currentCategoryId);
46
+ i0.ɵɵadvance();
47
+ i0.ɵɵtextInterpolate1(" ", pathItem_r5.name, " ");
48
+ } }
49
+ function QueryBrowserComponent_Conditional_32_Conditional_6_For_6_Conditional_4_Template(rf, ctx) { if (rf & 1) {
50
+ i0.ɵɵelementStart(0, "span", 43);
51
+ i0.ɵɵtext(1);
52
+ i0.ɵɵelementEnd();
53
+ } if (rf & 2) {
54
+ const category_r7 = i0.ɵɵnextContext().$implicit;
55
+ i0.ɵɵadvance();
56
+ i0.ɵɵtextInterpolate(category_r7.QueryCount);
57
+ } }
58
+ function QueryBrowserComponent_Conditional_32_Conditional_6_For_6_Template(rf, ctx) { if (rf & 1) {
59
+ const _r6 = i0.ɵɵgetCurrentView();
60
+ i0.ɵɵelementStart(0, "div", 40);
61
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Conditional_32_Conditional_6_For_6_Template_div_click_0_listener() { const category_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.navigateToCategory(category_r7.ID)); });
62
+ i0.ɵɵelement(1, "i", 41);
63
+ i0.ɵɵelementStart(2, "span", 42);
64
+ i0.ɵɵtext(3);
65
+ i0.ɵɵelementEnd();
66
+ i0.ɵɵtemplate(4, QueryBrowserComponent_Conditional_32_Conditional_6_For_6_Conditional_4_Template, 2, 1, "span", 43);
67
+ i0.ɵɵelementEnd();
68
+ } if (rf & 2) {
69
+ const category_r7 = ctx.$implicit;
70
+ i0.ɵɵproperty("title", category_r7.Description || category_r7.Name);
71
+ i0.ɵɵadvance(3);
72
+ i0.ɵɵtextInterpolate(category_r7.Name);
73
+ i0.ɵɵadvance();
74
+ i0.ɵɵconditional(category_r7.QueryCount && category_r7.QueryCount > 0 ? 4 : -1);
75
+ } }
76
+ function QueryBrowserComponent_Conditional_32_Conditional_6_Template(rf, ctx) { if (rf & 1) {
77
+ i0.ɵɵelementStart(0, "div", 32)(1, "h4", 36);
78
+ i0.ɵɵelement(2, "i", 37);
79
+ i0.ɵɵtext(3, " Categories ");
80
+ i0.ɵɵelementEnd();
81
+ i0.ɵɵelementStart(4, "div", 38);
82
+ i0.ɵɵrepeaterCreate(5, QueryBrowserComponent_Conditional_32_Conditional_6_For_6_Template, 5, 3, "div", 39, _forTrack1);
83
+ i0.ɵɵelementEnd()();
84
+ } if (rf & 2) {
85
+ const ctx_r1 = i0.ɵɵnextContext(2);
86
+ i0.ɵɵadvance(5);
87
+ i0.ɵɵrepeater(ctx_r1.filteredCategories);
88
+ } }
89
+ function QueryBrowserComponent_Conditional_32_Conditional_7_For_8_Conditional_6_Template(rf, ctx) { if (rf & 1) {
90
+ i0.ɵɵelementStart(0, "div", 53);
91
+ i0.ɵɵtext(1);
92
+ i0.ɵɵelementEnd();
93
+ } if (rf & 2) {
94
+ const query_r9 = i0.ɵɵnextContext().$implicit;
95
+ i0.ɵɵadvance();
96
+ i0.ɵɵtextInterpolate(query_r9.Description);
97
+ } }
98
+ function QueryBrowserComponent_Conditional_32_Conditional_7_For_8_Template(rf, ctx) { if (rf & 1) {
99
+ const _r8 = i0.ɵɵgetCurrentView();
100
+ i0.ɵɵelementStart(0, "div", 48);
101
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Conditional_32_Conditional_7_For_8_Template_div_click_0_listener() { const query_r9 = i0.ɵɵrestoreView(_r8).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectQuery(query_r9)); });
102
+ i0.ɵɵelementStart(1, "div", 49);
103
+ i0.ɵɵelement(2, "i", 50);
104
+ i0.ɵɵelementEnd();
105
+ i0.ɵɵelementStart(3, "div", 51)(4, "div", 52);
106
+ i0.ɵɵtext(5);
107
+ i0.ɵɵelementEnd();
108
+ i0.ɵɵtemplate(6, QueryBrowserComponent_Conditional_32_Conditional_7_For_8_Conditional_6_Template, 2, 1, "div", 53);
109
+ i0.ɵɵelementEnd();
110
+ i0.ɵɵelementStart(7, "div", 54);
111
+ i0.ɵɵtext(8);
112
+ i0.ɵɵelementEnd()();
113
+ } if (rf & 2) {
114
+ const query_r9 = ctx.$implicit;
115
+ const ctx_r1 = i0.ɵɵnextContext(3);
116
+ i0.ɵɵclassProp("selected", (ctx_r1.selectedQuery == null ? null : ctx_r1.selectedQuery.ID) === query_r9.ID);
117
+ i0.ɵɵadvance(5);
118
+ i0.ɵɵtextInterpolate(query_r9.Name);
119
+ i0.ɵɵadvance();
120
+ i0.ɵɵconditional(query_r9.Description ? 6 : -1);
121
+ i0.ɵɵadvance();
122
+ i0.ɵɵclassMap("status-" + (query_r9.Status || "pending").toLowerCase());
123
+ i0.ɵɵadvance();
124
+ i0.ɵɵtextInterpolate1(" ", query_r9.Status || "Pending", " ");
125
+ } }
126
+ function QueryBrowserComponent_Conditional_32_Conditional_7_Template(rf, ctx) { if (rf & 1) {
127
+ i0.ɵɵelementStart(0, "div", 33)(1, "h4", 36);
128
+ i0.ɵɵelement(2, "i", 44);
129
+ i0.ɵɵtext(3, " Queries ");
130
+ i0.ɵɵelementStart(4, "span", 45);
131
+ i0.ɵɵtext(5);
132
+ i0.ɵɵelementEnd()();
133
+ i0.ɵɵelementStart(6, "div", 46);
134
+ i0.ɵɵrepeaterCreate(7, QueryBrowserComponent_Conditional_32_Conditional_7_For_8_Template, 9, 7, "div", 47, _forTrack1);
135
+ i0.ɵɵelementEnd()();
136
+ } if (rf & 2) {
137
+ const ctx_r1 = i0.ɵɵnextContext(2);
138
+ i0.ɵɵadvance(5);
139
+ i0.ɵɵtextInterpolate1("(", ctx_r1.filteredQueries.length, ")");
140
+ i0.ɵɵadvance(2);
141
+ i0.ɵɵrepeater(ctx_r1.filteredQueries);
142
+ } }
143
+ function QueryBrowserComponent_Conditional_32_Conditional_8_Template(rf, ctx) { if (rf & 1) {
144
+ i0.ɵɵelementStart(0, "div", 34);
145
+ i0.ɵɵelement(1, "i", 55);
146
+ i0.ɵɵelementStart(2, "p");
147
+ i0.ɵɵtext(3, "No categories or queries found");
148
+ i0.ɵɵelementEnd()();
149
+ } }
150
+ function QueryBrowserComponent_Conditional_32_Template(rf, ctx) { if (rf & 1) {
151
+ const _r3 = i0.ɵɵgetCurrentView();
152
+ i0.ɵɵelementStart(0, "div", 24)(1, "div", 30)(2, "span", 31);
153
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Conditional_32_Template_span_click_2_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.navigateToRoot()); });
154
+ i0.ɵɵtext(3, " ./ ");
155
+ i0.ɵɵelementEnd();
156
+ i0.ɵɵrepeaterCreate(4, QueryBrowserComponent_Conditional_32_For_5_Template, 3, 3, null, null, _forTrack0);
157
+ i0.ɵɵelementEnd();
158
+ i0.ɵɵtemplate(6, QueryBrowserComponent_Conditional_32_Conditional_6_Template, 7, 0, "div", 32)(7, QueryBrowserComponent_Conditional_32_Conditional_7_Template, 9, 1, "div", 33)(8, QueryBrowserComponent_Conditional_32_Conditional_8_Template, 4, 0, "div", 34);
159
+ i0.ɵɵelementEnd();
160
+ } if (rf & 2) {
161
+ const ctx_r1 = i0.ɵɵnextContext();
162
+ i0.ɵɵadvance(4);
163
+ i0.ɵɵrepeater(ctx_r1.currentCategoryPath);
164
+ i0.ɵɵadvance(2);
165
+ i0.ɵɵconditional(ctx_r1.filteredCategories.length > 0 ? 6 : -1);
166
+ i0.ɵɵadvance();
167
+ i0.ɵɵconditional(ctx_r1.filteredQueries.length > 0 ? 7 : -1);
168
+ i0.ɵɵadvance();
169
+ i0.ɵɵconditional(ctx_r1.filteredCategories.length === 0 && ctx_r1.filteredQueries.length === 0 ? 8 : -1);
170
+ } }
171
+ function QueryBrowserComponent_Conditional_33_Conditional_1_For_15_Template(rf, ctx) { if (rf & 1) {
172
+ const _r10 = i0.ɵɵgetCurrentView();
173
+ i0.ɵɵelementStart(0, "div", 65);
174
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Conditional_33_Conditional_1_For_15_Template_div_click_0_listener() { const query_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectQuery(query_r11)); });
175
+ i0.ɵɵelementStart(1, "div", 57);
176
+ i0.ɵɵelement(2, "i", 50);
177
+ i0.ɵɵtext(3);
178
+ i0.ɵɵelementEnd();
179
+ i0.ɵɵelementStart(4, "div", 58);
180
+ i0.ɵɵtext(5);
181
+ i0.ɵɵelementEnd();
182
+ i0.ɵɵelementStart(6, "div", 59);
183
+ i0.ɵɵtext(7);
184
+ i0.ɵɵelementEnd();
185
+ i0.ɵɵelementStart(8, "div", 60)(9, "span", 66);
186
+ i0.ɵɵtext(10);
187
+ i0.ɵɵelementEnd()();
188
+ i0.ɵɵelementStart(11, "div", 61);
189
+ i0.ɵɵtext(12);
190
+ i0.ɵɵelementEnd();
191
+ i0.ɵɵelementStart(13, "div", 62)(14, "button", 67);
192
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Conditional_33_Conditional_1_For_15_Template_button_click_14_listener($event) { const query_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.runQuery(query_r11, $event)); });
193
+ i0.ɵɵelement(15, "i", 68);
194
+ i0.ɵɵelementEnd();
195
+ i0.ɵɵelementStart(16, "button", 69);
196
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Conditional_33_Conditional_1_For_15_Template_button_click_16_listener($event) { const query_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.deleteQuery(query_r11, $event)); });
197
+ i0.ɵɵelement(17, "i", 70);
198
+ i0.ɵɵelementEnd()()();
199
+ } if (rf & 2) {
200
+ const query_r11 = ctx.$implicit;
201
+ const ctx_r1 = i0.ɵɵnextContext(3);
202
+ i0.ɵɵclassProp("selected", (ctx_r1.selectedQuery == null ? null : ctx_r1.selectedQuery.ID) === query_r11.ID);
203
+ i0.ɵɵadvance(3);
204
+ i0.ɵɵtextInterpolate1(" ", query_r11.Name, " ");
205
+ i0.ɵɵadvance(2);
206
+ i0.ɵɵtextInterpolate1(" ", query_r11.Description || "-", " ");
207
+ i0.ɵɵadvance(2);
208
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.getCategoryName(query_r11.CategoryID) || "-", " ");
209
+ i0.ɵɵadvance(2);
210
+ i0.ɵɵclassMap("status-" + (query_r11.Status || "pending").toLowerCase());
211
+ i0.ɵɵadvance();
212
+ i0.ɵɵtextInterpolate1(" ", query_r11.Status || "Pending", " ");
213
+ i0.ɵɵadvance(2);
214
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.formatDate(query_r11.__mj_UpdatedAt), " ");
215
+ } }
216
+ function QueryBrowserComponent_Conditional_33_Conditional_1_Template(rf, ctx) { if (rf & 1) {
217
+ i0.ɵɵelementStart(0, "div", 56)(1, "div", 57);
218
+ i0.ɵɵtext(2, "Name");
219
+ i0.ɵɵelementEnd();
220
+ i0.ɵɵelementStart(3, "div", 58);
221
+ i0.ɵɵtext(4, "Description");
222
+ i0.ɵɵelementEnd();
223
+ i0.ɵɵelementStart(5, "div", 59);
224
+ i0.ɵɵtext(6, "Category");
225
+ i0.ɵɵelementEnd();
226
+ i0.ɵɵelementStart(7, "div", 60);
227
+ i0.ɵɵtext(8, "Status");
228
+ i0.ɵɵelementEnd();
229
+ i0.ɵɵelementStart(9, "div", 61);
230
+ i0.ɵɵtext(10, "Last Updated");
231
+ i0.ɵɵelementEnd();
232
+ i0.ɵɵelementStart(11, "div", 62);
233
+ i0.ɵɵtext(12, "Actions");
234
+ i0.ɵɵelementEnd()();
235
+ i0.ɵɵelementStart(13, "div", 63);
236
+ i0.ɵɵrepeaterCreate(14, QueryBrowserComponent_Conditional_33_Conditional_1_For_15_Template, 18, 9, "div", 64, _forTrack1);
237
+ i0.ɵɵelementEnd();
238
+ } if (rf & 2) {
239
+ const ctx_r1 = i0.ɵɵnextContext(2);
240
+ i0.ɵɵadvance(14);
241
+ i0.ɵɵrepeater(ctx_r1.filteredQueries);
242
+ } }
243
+ function QueryBrowserComponent_Conditional_33_Conditional_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
244
+ i0.ɵɵelementStart(0, "p", 71);
245
+ i0.ɵɵtext(1, "Try adjusting your filters");
246
+ i0.ɵɵelementEnd();
247
+ } }
248
+ function QueryBrowserComponent_Conditional_33_Conditional_2_Template(rf, ctx) { if (rf & 1) {
249
+ i0.ɵɵelementStart(0, "div", 34);
250
+ i0.ɵɵelement(1, "i", 4);
251
+ i0.ɵɵelementStart(2, "p");
252
+ i0.ɵɵtext(3, "No queries found");
253
+ i0.ɵɵelementEnd();
254
+ i0.ɵɵtemplate(4, QueryBrowserComponent_Conditional_33_Conditional_2_Conditional_4_Template, 2, 0, "p", 71);
255
+ i0.ɵɵelementEnd();
256
+ } if (rf & 2) {
257
+ const ctx_r1 = i0.ɵɵnextContext(2);
258
+ i0.ɵɵadvance(4);
259
+ i0.ɵɵconditional(ctx_r1.searchText || ctx_r1.selectedStatus !== "all" ? 4 : -1);
260
+ } }
261
+ function QueryBrowserComponent_Conditional_33_Template(rf, ctx) { if (rf & 1) {
262
+ i0.ɵɵelementStart(0, "div", 25);
263
+ i0.ɵɵtemplate(1, QueryBrowserComponent_Conditional_33_Conditional_1_Template, 16, 0)(2, QueryBrowserComponent_Conditional_33_Conditional_2_Template, 5, 1, "div", 34);
264
+ i0.ɵɵelementEnd();
265
+ } if (rf & 2) {
266
+ const ctx_r1 = i0.ɵɵnextContext();
267
+ i0.ɵɵadvance();
268
+ i0.ɵɵconditional(ctx_r1.filteredQueries.length > 0 ? 1 : 2);
269
+ } }
270
+ function QueryBrowserComponent_Conditional_34_Conditional_1_For_2_Conditional_7_Template(rf, ctx) { if (rf & 1) {
271
+ i0.ɵɵelementStart(0, "div", 77);
272
+ i0.ɵɵtext(1);
273
+ i0.ɵɵelementEnd();
274
+ } if (rf & 2) {
275
+ const query_r13 = i0.ɵɵnextContext().$implicit;
276
+ i0.ɵɵadvance();
277
+ i0.ɵɵtextInterpolate1(" ", query_r13.Description, " ");
278
+ } }
279
+ function QueryBrowserComponent_Conditional_34_Conditional_1_For_2_Conditional_15_Template(rf, ctx) { if (rf & 1) {
280
+ i0.ɵɵelementStart(0, "span", 83);
281
+ i0.ɵɵelement(1, "i", 37);
282
+ i0.ɵɵtext(2);
283
+ i0.ɵɵelementEnd();
284
+ } if (rf & 2) {
285
+ const query_r13 = i0.ɵɵnextContext().$implicit;
286
+ const ctx_r1 = i0.ɵɵnextContext(3);
287
+ i0.ɵɵadvance(2);
288
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.getCategoryName(query_r13.CategoryID), " ");
289
+ } }
290
+ function QueryBrowserComponent_Conditional_34_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
291
+ const _r12 = i0.ɵɵgetCurrentView();
292
+ i0.ɵɵelementStart(0, "div", 74);
293
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Conditional_34_Conditional_1_For_2_Template_div_click_0_listener() { const query_r13 = i0.ɵɵrestoreView(_r12).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectQuery(query_r13)); });
294
+ i0.ɵɵelementStart(1, "div", 75)(2, "div", 76);
295
+ i0.ɵɵelement(3, "i", 50);
296
+ i0.ɵɵtext(4);
297
+ i0.ɵɵelementEnd();
298
+ i0.ɵɵelementStart(5, "span", 66);
299
+ i0.ɵɵtext(6);
300
+ i0.ɵɵelementEnd()();
301
+ i0.ɵɵtemplate(7, QueryBrowserComponent_Conditional_34_Conditional_1_For_2_Conditional_7_Template, 2, 1, "div", 77);
302
+ i0.ɵɵelementStart(8, "div", 78)(9, "div", 79);
303
+ i0.ɵɵtext(10, "SQL Preview:");
304
+ i0.ɵɵelementEnd();
305
+ i0.ɵɵelementStart(11, "pre", 80);
306
+ i0.ɵɵtext(12);
307
+ i0.ɵɵelementEnd()();
308
+ i0.ɵɵelementStart(13, "div", 81)(14, "div", 82);
309
+ i0.ɵɵtemplate(15, QueryBrowserComponent_Conditional_34_Conditional_1_For_2_Conditional_15_Template, 3, 1, "span", 83);
310
+ i0.ɵɵelementStart(16, "span", 83);
311
+ i0.ɵɵelement(17, "i", 84);
312
+ i0.ɵɵtext(18);
313
+ i0.ɵɵelementEnd()();
314
+ i0.ɵɵelementStart(19, "div", 85)(20, "button", 67);
315
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Conditional_34_Conditional_1_For_2_Template_button_click_20_listener($event) { const query_r13 = i0.ɵɵrestoreView(_r12).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.runQuery(query_r13, $event)); });
316
+ i0.ɵɵelement(21, "i", 68);
317
+ i0.ɵɵelementEnd()()()();
318
+ } if (rf & 2) {
319
+ const query_r13 = ctx.$implicit;
320
+ const ctx_r1 = i0.ɵɵnextContext(3);
321
+ i0.ɵɵclassProp("selected", (ctx_r1.selectedQuery == null ? null : ctx_r1.selectedQuery.ID) === query_r13.ID);
322
+ i0.ɵɵadvance(4);
323
+ i0.ɵɵtextInterpolate1(" ", query_r13.Name, " ");
324
+ i0.ɵɵadvance();
325
+ i0.ɵɵclassMap("status-" + (query_r13.Status || "pending").toLowerCase());
326
+ i0.ɵɵadvance();
327
+ i0.ɵɵtextInterpolate1(" ", query_r13.Status || "Pending", " ");
328
+ i0.ɵɵadvance();
329
+ i0.ɵɵconditional(query_r13.Description ? 7 : -1);
330
+ i0.ɵɵadvance(5);
331
+ i0.ɵɵtextInterpolate(ctx_r1.getQueryPreview(query_r13.SQL));
332
+ i0.ɵɵadvance(3);
333
+ i0.ɵɵconditional(query_r13.CategoryID ? 15 : -1);
334
+ i0.ɵɵadvance(3);
335
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.formatDate(query_r13.__mj_UpdatedAt), " ");
336
+ } }
337
+ function QueryBrowserComponent_Conditional_34_Conditional_1_Template(rf, ctx) { if (rf & 1) {
338
+ i0.ɵɵelementStart(0, "div", 72);
339
+ i0.ɵɵrepeaterCreate(1, QueryBrowserComponent_Conditional_34_Conditional_1_For_2_Template, 22, 10, "div", 73, _forTrack1);
340
+ i0.ɵɵelementEnd();
341
+ } if (rf & 2) {
342
+ const ctx_r1 = i0.ɵɵnextContext(2);
343
+ i0.ɵɵadvance();
344
+ i0.ɵɵrepeater(ctx_r1.filteredQueries);
345
+ } }
346
+ function QueryBrowserComponent_Conditional_34_Conditional_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
347
+ i0.ɵɵelementStart(0, "p", 71);
348
+ i0.ɵɵtext(1, "Try adjusting your filters");
349
+ i0.ɵɵelementEnd();
350
+ } }
351
+ function QueryBrowserComponent_Conditional_34_Conditional_2_Template(rf, ctx) { if (rf & 1) {
352
+ i0.ɵɵelementStart(0, "div", 34);
353
+ i0.ɵɵelement(1, "i", 15);
354
+ i0.ɵɵelementStart(2, "p");
355
+ i0.ɵɵtext(3, "No queries to display");
356
+ i0.ɵɵelementEnd();
357
+ i0.ɵɵtemplate(4, QueryBrowserComponent_Conditional_34_Conditional_2_Conditional_4_Template, 2, 0, "p", 71);
358
+ i0.ɵɵelementEnd();
359
+ } if (rf & 2) {
360
+ const ctx_r1 = i0.ɵɵnextContext(2);
361
+ i0.ɵɵadvance(4);
362
+ i0.ɵɵconditional(ctx_r1.searchText || ctx_r1.selectedStatus !== "all" ? 4 : -1);
363
+ } }
364
+ function QueryBrowserComponent_Conditional_34_Template(rf, ctx) { if (rf & 1) {
365
+ i0.ɵɵelementStart(0, "div", 26);
366
+ i0.ɵɵtemplate(1, QueryBrowserComponent_Conditional_34_Conditional_1_Template, 3, 0, "div", 72)(2, QueryBrowserComponent_Conditional_34_Conditional_2_Template, 5, 1, "div", 34);
367
+ i0.ɵɵelementEnd();
368
+ } if (rf & 2) {
369
+ const ctx_r1 = i0.ɵɵnextContext();
370
+ i0.ɵɵadvance();
371
+ i0.ɵɵconditional(ctx_r1.filteredQueries.length > 0 ? 1 : 2);
372
+ } }
373
+ let QueryBrowserComponent = class QueryBrowserComponent extends BaseNavigationComponent {
18
374
  router;
19
375
  route;
20
376
  sharedService;
21
- NewItemOptions = [];
377
+ // View mode state
378
+ viewMode = 'list';
379
+ // Data
380
+ allQueries = [];
381
+ allCategories = [];
382
+ filteredQueries = [];
383
+ filteredCategories = [];
384
+ // Selection state
385
+ selectedQuery = null;
386
+ currentCategoryId = null;
387
+ currentCategoryPath = [];
388
+ // Filter state
389
+ searchText = '';
390
+ selectedStatus = 'all';
391
+ selectedSort = 'updated-desc';
392
+ activeFilters = [];
393
+ // Loading state
394
+ isLoading = false;
395
+ // Category counts cache
396
+ categoryCounts = new Map();
397
+ // Options for dropdowns
398
+ statusOptions = [
399
+ { text: 'All Statuses', value: 'all' },
400
+ { text: 'Pending', value: 'Pending' },
401
+ { text: 'Approved', value: 'Approved' },
402
+ { text: 'Rejected', value: 'Rejected' },
403
+ { text: 'Expired', value: 'Expired' }
404
+ ];
405
+ sortOptions = [
406
+ { text: 'Name (A-Z)', value: 'name-asc' },
407
+ { text: 'Name (Z-A)', value: 'name-desc' },
408
+ { text: 'Recently Updated', value: 'updated-desc' },
409
+ { text: 'Oldest Updated', value: 'updated-asc' },
410
+ { text: 'Status', value: 'status' }
411
+ ];
412
+ // Search debouncing
413
+ searchSubject = new Subject();
414
+ destroy$ = new Subject();
22
415
  constructor(router, route, sharedService) {
23
416
  super();
24
417
  this.router = router;
25
418
  this.route = route;
26
419
  this.sharedService = sharedService;
27
- this.pageName = "Queries";
28
- this.routeName = "queries";
29
- this.routeNameSingular = "query";
30
- this.itemEntityName = "Queries";
31
- this.categoryEntityName = "Query Categories";
32
- const params = this.router.getCurrentNavigation()?.extractedUrl.queryParams;
33
- super.InitPathAndQueryData(params, this.route);
34
420
  }
35
421
  async ngOnInit() {
36
- //doing this "manually" rather than calling super.InitForResource
37
- //because BaseBrowserComponent's resource filter includes a filter for UserID
38
- //which doesnt exist on queries
39
- this.route.paramMap.subscribe(async (params) => {
40
- this.selectedFolderID = params.get('folderID');
422
+ // Set up search debouncing
423
+ this.searchSubject
424
+ .pipe(debounceTime(300), takeUntil(this.destroy$))
425
+ .subscribe(searchText => {
426
+ this.performSearch(searchText);
427
+ });
428
+ // Load initial data
429
+ await this.loadData();
430
+ // Check for view mode from route params
431
+ this.route.queryParams.subscribe(params => {
432
+ if (params['view'] && ['category', 'list', 'panel'].includes(params['view'])) {
433
+ this.viewMode = params['view'];
434
+ // Reapply filters when view mode changes from route
435
+ this.applyFilters();
436
+ }
437
+ });
438
+ }
439
+ ngOnDestroy() {
440
+ this.destroy$.next();
441
+ this.destroy$.complete();
442
+ }
443
+ async loadData() {
444
+ this.isLoading = true;
445
+ try {
41
446
  const md = new Metadata();
42
- let categoryFilter = this.selectedFolderID ? `CategoryID = '${this.selectedFolderID}'` : `CategoryID IS NULL`;
43
- let resourceFilter = `${categoryFilter}`;
44
- let resourceCategoryFilter = this.selectedFolderID ? `ParentID = '${this.selectedFolderID}'` : `ParentID IS NULL`;
45
- await this.LoadData({
46
- sortItemsAfterLoad: true,
47
- categoryItemFilter: resourceCategoryFilter,
48
- entityItemFilter: resourceFilter,
49
- showLoader: true
447
+ const rv = new RunView();
448
+ // Load queries and categories in parallel
449
+ const [queriesResult, categoriesResult] = await Promise.all([
450
+ rv.RunView({
451
+ EntityName: 'Queries',
452
+ OrderBy: '__mj_UpdatedAt DESC',
453
+ ResultType: 'entity_object'
454
+ }),
455
+ rv.RunView({
456
+ EntityName: 'Query Categories',
457
+ OrderBy: 'Name',
458
+ ResultType: 'entity_object'
459
+ })
460
+ ]);
461
+ if (queriesResult.Success) {
462
+ this.allQueries = queriesResult.Results || [];
463
+ }
464
+ if (categoriesResult.Success) {
465
+ this.allCategories = categoriesResult.Results || [];
466
+ this.calculateCategoryCounts();
467
+ }
468
+ // Apply initial filters
469
+ this.applyFilters();
470
+ }
471
+ catch (error) {
472
+ console.error('Error loading data:', error);
473
+ this.sharedService.CreateSimpleNotification('Error loading queries', 'error', 3000);
474
+ }
475
+ finally {
476
+ this.isLoading = false;
477
+ }
478
+ }
479
+ calculateCategoryCounts() {
480
+ // Count queries per category
481
+ const counts = new Map();
482
+ for (const query of this.allQueries) {
483
+ if (query.CategoryID) {
484
+ const current = counts.get(query.CategoryID) || 0;
485
+ counts.set(query.CategoryID, current + 1);
486
+ }
487
+ }
488
+ // Count queries recursively for each category (including subcategories)
489
+ const getRecursiveCount = (categoryId) => {
490
+ let count = counts.get(categoryId) || 0;
491
+ // Add counts from all child categories
492
+ const children = this.allCategories.filter(c => c.ParentID === categoryId);
493
+ for (const child of children) {
494
+ count += getRecursiveCount(child.ID);
495
+ }
496
+ return count;
497
+ };
498
+ // Don't set filteredCategories here - let applyFilters handle it
499
+ // Just store the counts for later use
500
+ this.categoryCounts = new Map();
501
+ for (const cat of this.allCategories) {
502
+ this.categoryCounts.set(cat.ID, getRecursiveCount(cat.ID));
503
+ }
504
+ }
505
+ setViewMode(mode) {
506
+ this.viewMode = mode;
507
+ // Update URL with view mode
508
+ this.router.navigate([], {
509
+ relativeTo: this.route,
510
+ queryParams: { view: mode },
511
+ queryParamsHandling: 'merge'
512
+ });
513
+ // Reapply filters to update the view
514
+ this.applyFilters();
515
+ }
516
+ onSearchChange(searchText) {
517
+ this.searchSubject.next(searchText);
518
+ }
519
+ performSearch(searchText) {
520
+ this.searchText = searchText;
521
+ this.applyFilters();
522
+ }
523
+ // New clean filter/sort handlers
524
+ getSelectedStatusOption() {
525
+ return this.statusOptions.find(opt => opt.value === this.selectedStatus) || this.statusOptions[0];
526
+ }
527
+ getSelectedSortOption() {
528
+ return this.sortOptions.find(opt => opt.value === this.selectedSort) || this.sortOptions[2];
529
+ }
530
+ handleStatusChange(option) {
531
+ if (option && option.value !== undefined) {
532
+ this.selectedStatus = option.value;
533
+ this.applyFilters();
534
+ }
535
+ }
536
+ handleSortChange(option) {
537
+ if (option && option.value !== undefined) {
538
+ this.selectedSort = option.value;
539
+ this.applySortAndFilter();
540
+ }
541
+ }
542
+ hasActiveFilters() {
543
+ return this.searchText !== '' || this.selectedStatus !== 'all';
544
+ }
545
+ clearAllFilters() {
546
+ this.searchText = '';
547
+ this.selectedStatus = 'all';
548
+ this.applyFilters();
549
+ }
550
+ applyFilters() {
551
+ // Start with all queries
552
+ let filtered = [...this.allQueries];
553
+ // Clear active filters tracking
554
+ this.activeFilters = [];
555
+ // 1. Apply search filter if present
556
+ if (this.searchText && this.searchText.trim() !== '') {
557
+ const searchLower = this.searchText.toLowerCase().trim();
558
+ filtered = filtered.filter(q => {
559
+ const nameMatch = q.Name?.toLowerCase().includes(searchLower) || false;
560
+ const descMatch = q.Description?.toLowerCase().includes(searchLower) || false;
561
+ const sqlMatch = q.SQL?.toLowerCase().includes(searchLower) || false;
562
+ return nameMatch || descMatch || sqlMatch;
50
563
  });
564
+ this.activeFilters.push(`Search: ${this.searchText}`);
565
+ }
566
+ // 2. Apply status filter if not "all"
567
+ if (this.selectedStatus && this.selectedStatus !== 'all') {
568
+ filtered = filtered.filter(q => q.Status === this.selectedStatus);
569
+ this.activeFilters.push(`Status: ${this.selectedStatus}`);
570
+ }
571
+ // 3. Apply category-based filtering in category view mode
572
+ if (this.viewMode === 'category') {
573
+ filtered = filtered.filter(q => {
574
+ if (this.currentCategoryId === null) {
575
+ // At root: show only queries without a category
576
+ return !q.CategoryID || q.CategoryID === null || q.CategoryID === '';
577
+ }
578
+ else {
579
+ // Inside a category: show only queries in this specific category
580
+ return q.CategoryID === this.currentCategoryId;
581
+ }
582
+ });
583
+ }
584
+ // Set the filtered queries
585
+ this.filteredQueries = filtered;
586
+ // Update categories for category view
587
+ this.updateFilteredCategories();
588
+ // Apply sorting to the filtered results
589
+ this.applySort();
590
+ }
591
+ updateFilteredCategories() {
592
+ // Filter categories based on current parent
593
+ let filtered = this.allCategories.filter(cat => {
594
+ if (this.currentCategoryId === null) {
595
+ // At root: show categories with no parent
596
+ return !cat.ParentID;
597
+ }
598
+ else {
599
+ // In a category: show child categories
600
+ return cat.ParentID === this.currentCategoryId;
601
+ }
602
+ });
603
+ // Apply search to categories if in category mode
604
+ if (this.searchText && this.viewMode === 'category') {
605
+ const search = this.searchText.toLowerCase();
606
+ filtered = filtered.filter(cat => cat.Name?.toLowerCase().includes(search) ||
607
+ cat.Description?.toLowerCase().includes(search));
608
+ }
609
+ // Convert to CategoryWithCount and use cached counts
610
+ this.filteredCategories = filtered.map(cat => {
611
+ const count = this.categoryCounts.get(cat.ID) || 0;
612
+ return {
613
+ ...cat.GetAll(), // Use GetAll() to get plain object with all properties
614
+ QueryCount: count
615
+ };
616
+ });
617
+ }
618
+ applySort() {
619
+ // Create a copy to avoid mutation issues
620
+ const queries = [...this.filteredQueries];
621
+ switch (this.selectedSort) {
622
+ case 'name-asc':
623
+ queries.sort((a, b) => {
624
+ const nameA = a.Name || '';
625
+ const nameB = b.Name || '';
626
+ return nameA.localeCompare(nameB);
627
+ });
628
+ break;
629
+ case 'name-desc':
630
+ queries.sort((a, b) => {
631
+ const nameA = a.Name || '';
632
+ const nameB = b.Name || '';
633
+ return nameB.localeCompare(nameA);
634
+ });
635
+ break;
636
+ case 'updated-desc':
637
+ queries.sort((a, b) => {
638
+ const dateA = a.__mj_UpdatedAt ? new Date(a.__mj_UpdatedAt).getTime() : 0;
639
+ const dateB = b.__mj_UpdatedAt ? new Date(b.__mj_UpdatedAt).getTime() : 0;
640
+ return dateB - dateA;
641
+ });
642
+ break;
643
+ case 'updated-asc':
644
+ queries.sort((a, b) => {
645
+ const dateA = a.__mj_UpdatedAt ? new Date(a.__mj_UpdatedAt).getTime() : 0;
646
+ const dateB = b.__mj_UpdatedAt ? new Date(b.__mj_UpdatedAt).getTime() : 0;
647
+ return dateA - dateB;
648
+ });
649
+ break;
650
+ case 'status':
651
+ queries.sort((a, b) => {
652
+ const statusA = a.Status || 'Pending';
653
+ const statusB = b.Status || 'Pending';
654
+ return statusA.localeCompare(statusB);
655
+ });
656
+ break;
657
+ default:
658
+ // Default to recent updates
659
+ queries.sort((a, b) => {
660
+ const dateA = a.__mj_UpdatedAt ? new Date(a.__mj_UpdatedAt).getTime() : 0;
661
+ const dateB = b.__mj_UpdatedAt ? new Date(b.__mj_UpdatedAt).getTime() : 0;
662
+ return dateB - dateA;
663
+ });
664
+ break;
665
+ }
666
+ // Assign the sorted array
667
+ this.filteredQueries = queries;
668
+ }
669
+ // Helper to apply both sort and filter
670
+ applySortAndFilter() {
671
+ this.applyFilters(); // This calls applySort internally
672
+ }
673
+ navigateToRoot() {
674
+ this.currentCategoryId = null;
675
+ this.currentCategoryPath = [];
676
+ this.applyFilters();
677
+ }
678
+ navigateToCategory(categoryId) {
679
+ if (categoryId === null) {
680
+ this.navigateToRoot();
681
+ return;
682
+ }
683
+ this.currentCategoryId = categoryId;
684
+ this.buildBreadcrumb(categoryId);
685
+ this.applyFilters();
686
+ }
687
+ buildBreadcrumb(categoryId) {
688
+ const path = [];
689
+ let currentId = categoryId;
690
+ while (currentId) {
691
+ const category = this.allCategories.find(c => c.ID === currentId);
692
+ if (category) {
693
+ path.unshift({
694
+ id: category.ID,
695
+ name: category.Name
696
+ });
697
+ currentId = category.ParentID;
698
+ }
699
+ else {
700
+ break;
701
+ }
702
+ }
703
+ this.currentCategoryPath = path;
704
+ }
705
+ selectQuery(query) {
706
+ // Strip quotes from ID if present
707
+ let queryId = query.ID;
708
+ if (queryId && typeof queryId === 'string') {
709
+ queryId = queryId.replace(/^['"]|['"]$/g, '');
710
+ }
711
+ // Navigate to the entity form using the resource/record pattern
712
+ // Format: /resource/record/ID|{queryId}?Entity=Queries
713
+ const routeSegment = `ID|${queryId}`;
714
+ this.router.navigate(['resource', 'record', routeSegment], {
715
+ queryParams: {
716
+ Entity: 'Queries',
717
+ viewMode: this.viewMode // Preserve the current view mode
718
+ }
719
+ });
720
+ }
721
+ async runQuery(query, event) {
722
+ event.stopPropagation();
723
+ let queryId = query.ID;
724
+ if (queryId && typeof queryId === 'string') {
725
+ queryId = queryId.replace(/^['\"]|['\"]$/g, '');
726
+ }
727
+ // Navigate to the query form with run=true parameter
728
+ // This will trigger the run dialog in the query form component
729
+ const routeSegment = `ID|${queryId}`;
730
+ this.router.navigate(['resource', 'record', routeSegment], {
731
+ queryParams: {
732
+ Entity: 'Queries',
733
+ run: 'true' // This will trigger the run dialog to open
734
+ }
51
735
  });
52
736
  }
53
- //this could exist in the BaseBrowserComponent class, but
54
- //the class would need a reference or dependency on the router
55
- //which i dont think is needed
56
- itemClick(item) {
57
- let dataID = "";
58
- if (item.Type === ItemType.Resource) {
59
- let query = item.Data;
60
- dataID = query.FirstPrimaryKey.Value;
737
+ async deleteQuery(query, event) {
738
+ event.stopPropagation();
739
+ if (!confirm(`Are you sure you want to delete "${query.Name}"?`)) {
740
+ return;
741
+ }
742
+ try {
743
+ let result = false;
744
+ // First try to delete directly if the query has a Delete method
745
+ if (query && typeof query.Delete === 'function') {
746
+ result = await query.Delete();
747
+ }
748
+ else {
749
+ // If not, load the entity properly and then delete
750
+ const md = new Metadata();
751
+ const queryEntity = await md.GetEntityObject('Queries');
752
+ // Load the existing record
753
+ const loaded = await queryEntity.Load(query.ID);
754
+ if (!loaded) {
755
+ this.sharedService.CreateSimpleNotification('Query not found', 'error', 3000);
756
+ return;
757
+ }
758
+ // Now delete the loaded entity
759
+ result = await queryEntity.Delete();
760
+ }
761
+ if (result) {
762
+ this.sharedService.CreateSimpleNotification('Query deleted successfully', 'success', 3000);
763
+ await this.loadData();
764
+ }
765
+ else {
766
+ // Check if there's a specific error message
767
+ const errorMsg = query.LatestResult?.Message || 'Failed to delete query';
768
+ this.sharedService.CreateSimpleNotification(errorMsg, 'error', 5000);
769
+ console.error('Delete failed:', query.LatestResult);
770
+ }
771
+ }
772
+ catch (error) {
773
+ console.error('Error deleting query:', error);
774
+ const errorMessage = error instanceof Error ? error.message : 'Error deleting query';
775
+ this.sharedService.CreateSimpleNotification(errorMessage, 'error', 5000);
61
776
  }
62
- super.Navigate(item, this.router, dataID);
63
777
  }
64
- onBeforeUpdateItemEvent(event) {
65
- event.Cancel = true;
66
- let item = event.Item;
67
- let query = item.Data;
68
- this.router.navigate(['resource', this.routeNameSingular, query.ID], { queryParams: { edit: true } });
778
+ async createNewQuery() {
779
+ // Navigate to the query form with an empty primary key for new record
780
+ // Using empty string as the third parameter to match MJ's convention
781
+ const queryParams = {
782
+ Entity: 'Queries'
783
+ };
784
+ // Include category context if we're in category view
785
+ // This can be used to pre-populate the CategoryID field
786
+ if (this.viewMode === 'category' && this.currentCategoryId) {
787
+ // Pass initial field values in query params
788
+ queryParams.NewRecordValues = `CategoryID|${this.currentCategoryId}`;
789
+ }
790
+ // Navigate with empty string as third param for new record
791
+ this.router.navigate(['resource', 'record', ''], // Empty string indicates new record
792
+ { queryParams });
793
+ }
794
+ getCategoryName(categoryId) {
795
+ if (!categoryId)
796
+ return '';
797
+ const category = this.allCategories.find(c => c.ID === categoryId);
798
+ return category?.Name || '';
799
+ }
800
+ formatDate(date) {
801
+ if (!date)
802
+ return '-';
803
+ const d = typeof date === 'string' ? new Date(date) : date;
804
+ if (isNaN(d.getTime()))
805
+ return '-';
806
+ // Format as MM/DD/YYYY HH:MM
807
+ return d.toLocaleDateString() + ' ' + d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
808
+ }
809
+ getQueryPreview(sql) {
810
+ if (!sql)
811
+ return 'No SQL query defined';
812
+ // Get first 3 lines or 150 characters, whichever is shorter
813
+ const lines = sql.split('\n').slice(0, 3);
814
+ let preview = lines.join('\n');
815
+ if (preview.length > 150) {
816
+ preview = preview.substring(0, 150) + '...';
817
+ }
818
+ else if (sql.length > preview.length) {
819
+ preview += '\n...';
820
+ }
821
+ return preview;
69
822
  }
70
823
  static ɵfac = function QueryBrowserComponent_Factory(t) { return new (t || QueryBrowserComponent)(i0.ɵɵdirectiveInject(i1.Router), i0.ɵɵdirectiveInject(i1.ActivatedRoute), i0.ɵɵdirectiveInject(i2.SharedService)); };
71
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: QueryBrowserComponent, selectors: [["mj-query-browser"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 5, consts: [["resourceBrowserQueries", ""], ["ResourceTypeName", "Queries", "Title", "Queries", "DisplayMode", "Tile", 3, "ResourceSelected", "EditItemEvent", "EnableCategories", "EnableItemEdit", "EnableItemDelete", "CurrentCategoryID", "NewItemOptions"]], template: function QueryBrowserComponent_Template(rf, ctx) { if (rf & 1) {
72
- const _r1 = i0.ɵɵgetCurrentView();
73
- i0.ɵɵelementStart(0, "mj-resource-browser", 1, 0);
74
- i0.ɵɵlistener("ResourceSelected", function QueryBrowserComponent_Template_mj_resource_browser_ResourceSelected_0_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.itemClick($event)); })("EditItemEvent", function QueryBrowserComponent_Template_mj_resource_browser_EditItemEvent_0_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onBeforeUpdateItemEvent($event)); });
824
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: QueryBrowserComponent, selectors: [["mj-query-browser"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 35, vars: 22, consts: [[1, "query-browser-container"], [1, "query-browser-header"], [1, "header-left"], [1, "page-title"], [1, "fa-solid", "fa-database"], [1, "header-right"], [1, "search-container"], [1, "fa-solid", "fa-search", "search-icon"], ["type", "text", "placeholder", "Search queries...", 1, "search-input", 3, "ngModelChange", "ngModel"], [1, "view-mode-toggles"], ["title", "Category View", 1, "view-mode-btn", 3, "click"], [1, "fa-solid", "fa-folder-tree"], ["title", "List View", 1, "view-mode-btn", 3, "click"], [1, "fa-solid", "fa-list"], ["title", "Panel View", 1, "view-mode-btn", 3, "click"], [1, "fa-solid", "fa-grip"], [1, "btn", "btn-primary", "create-query-btn", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "filter-bar"], [1, "filter-group"], ["textField", "text", "valueField", "value", 3, "valueChange", "data", "value"], [1, "clear-filters-btn"], [1, "loading-container"], [1, "query-browser-content"], [1, "category-view"], [1, "list-view"], [1, "panel-view"], [1, "clear-filters-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "breadcrumb"], [1, "breadcrumb-item", 3, "click"], [1, "category-folders"], [1, "category-queries"], [1, "empty-state"], [1, "fa-solid", "fa-chevron-right", "breadcrumb-separator"], [1, "section-title"], [1, "fa-solid", "fa-folder"], [1, "folder-grid"], [1, "folder-item", 3, "title"], [1, "folder-item", 3, "click", "title"], [1, "fa-solid", "fa-folder", "folder-icon"], [1, "folder-name"], [1, "item-count"], [1, "fa-solid", "fa-file-code"], [1, "count"], [1, "query-list"], [1, "query-list-item", 3, "selected"], [1, "query-list-item", 3, "click"], [1, "query-icon"], [1, "fa-solid", "fa-code"], [1, "query-info"], [1, "query-name"], [1, "query-description"], [1, "query-status"], [1, "fa-solid", "fa-folder-open"], [1, "list-header"], [1, "col-name"], [1, "col-description"], [1, "col-category"], [1, "col-status"], [1, "col-updated"], [1, "col-actions"], [1, "list-body"], [1, "list-row", 3, "selected"], [1, "list-row", 3, "click"], [1, "status-badge"], ["title", "Run", 1, "action-btn", 3, "click"], [1, "fa-solid", "fa-play"], ["title", "Delete", 1, "action-btn", "danger", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "empty-hint"], [1, "panel-grid"], [1, "query-panel", 3, "selected"], [1, "query-panel", 3, "click"], [1, "panel-header"], [1, "panel-title"], [1, "panel-description"], [1, "panel-sql-preview"], [1, "sql-label"], [1, "sql-code"], [1, "panel-footer"], [1, "panel-meta"], [1, "meta-item"], [1, "fa-solid", "fa-clock"], [1, "panel-actions"]], template: function QueryBrowserComponent_Template(rf, ctx) { if (rf & 1) {
825
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "h2", 3);
826
+ i0.ɵɵelement(4, "i", 4);
827
+ i0.ɵɵtext(5, " Queries ");
828
+ i0.ɵɵelementEnd()();
829
+ i0.ɵɵelementStart(6, "div", 5)(7, "div", 6);
830
+ i0.ɵɵelement(8, "i", 7);
831
+ i0.ɵɵelementStart(9, "input", 8);
832
+ i0.ɵɵtwoWayListener("ngModelChange", function QueryBrowserComponent_Template_input_ngModelChange_9_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.searchText, $event) || (ctx.searchText = $event); return $event; });
833
+ i0.ɵɵlistener("ngModelChange", function QueryBrowserComponent_Template_input_ngModelChange_9_listener($event) { return ctx.onSearchChange($event); });
834
+ i0.ɵɵelementEnd()();
835
+ i0.ɵɵelementStart(10, "div", 9)(11, "button", 10);
836
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Template_button_click_11_listener() { return ctx.setViewMode("category"); });
837
+ i0.ɵɵelement(12, "i", 11);
838
+ i0.ɵɵelementEnd();
839
+ i0.ɵɵelementStart(13, "button", 12);
840
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Template_button_click_13_listener() { return ctx.setViewMode("list"); });
841
+ i0.ɵɵelement(14, "i", 13);
842
+ i0.ɵɵelementEnd();
843
+ i0.ɵɵelementStart(15, "button", 14);
844
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Template_button_click_15_listener() { return ctx.setViewMode("panel"); });
845
+ i0.ɵɵelement(16, "i", 15);
846
+ i0.ɵɵelementEnd()();
847
+ i0.ɵɵelementStart(17, "button", 16);
848
+ i0.ɵɵlistener("click", function QueryBrowserComponent_Template_button_click_17_listener() { return ctx.createNewQuery(); });
849
+ i0.ɵɵelement(18, "i", 17);
850
+ i0.ɵɵtext(19, " New Query ");
851
+ i0.ɵɵelementEnd()()();
852
+ i0.ɵɵelementStart(20, "div", 18)(21, "div", 19)(22, "label");
853
+ i0.ɵɵtext(23, "Status:");
854
+ i0.ɵɵelementEnd();
855
+ i0.ɵɵelementStart(24, "kendo-dropdownlist", 20);
856
+ i0.ɵɵlistener("valueChange", function QueryBrowserComponent_Template_kendo_dropdownlist_valueChange_24_listener($event) { return ctx.handleStatusChange($event); });
857
+ i0.ɵɵelementEnd()();
858
+ i0.ɵɵelementStart(25, "div", 19)(26, "label");
859
+ i0.ɵɵtext(27, "Sort by:");
860
+ i0.ɵɵelementEnd();
861
+ i0.ɵɵelementStart(28, "kendo-dropdownlist", 20);
862
+ i0.ɵɵlistener("valueChange", function QueryBrowserComponent_Template_kendo_dropdownlist_valueChange_28_listener($event) { return ctx.handleSortChange($event); });
863
+ i0.ɵɵelementEnd()();
864
+ i0.ɵɵtemplate(29, QueryBrowserComponent_Conditional_29_Template, 3, 0, "button", 21);
75
865
  i0.ɵɵelementEnd();
866
+ i0.ɵɵtemplate(30, QueryBrowserComponent_Conditional_30_Template, 3, 0, "div", 22);
867
+ i0.ɵɵelementStart(31, "div", 23);
868
+ i0.ɵɵtemplate(32, QueryBrowserComponent_Conditional_32_Template, 9, 3, "div", 24)(33, QueryBrowserComponent_Conditional_33_Template, 3, 1, "div", 25)(34, QueryBrowserComponent_Conditional_34_Template, 3, 1, "div", 26);
869
+ i0.ɵɵelementEnd()();
76
870
  } if (rf & 2) {
77
- i0.ɵɵproperty("EnableCategories", false)("EnableItemEdit", false)("EnableItemDelete", false)("CurrentCategoryID", ctx.selectedFolderID)("NewItemOptions", ctx.NewItemOptions);
78
- } }, dependencies: [i3.ResourceBrowserComponent], styles: [".k-card-body[_ngcontent-%COMP%] {\n height: 80px;\n }"] });
871
+ i0.ɵɵadvance(9);
872
+ i0.ɵɵtwoWayProperty("ngModel", ctx.searchText);
873
+ i0.ɵɵadvance(2);
874
+ i0.ɵɵclassProp("active", ctx.viewMode === "category");
875
+ i0.ɵɵadvance(2);
876
+ i0.ɵɵclassProp("active", ctx.viewMode === "list");
877
+ i0.ɵɵadvance(2);
878
+ i0.ɵɵclassProp("active", ctx.viewMode === "panel");
879
+ i0.ɵɵadvance(9);
880
+ i0.ɵɵstyleProp("width", 150, "px");
881
+ i0.ɵɵproperty("data", ctx.statusOptions)("value", ctx.getSelectedStatusOption());
882
+ i0.ɵɵadvance(4);
883
+ i0.ɵɵstyleProp("width", 200, "px");
884
+ i0.ɵɵproperty("data", ctx.sortOptions)("value", ctx.getSelectedSortOption());
885
+ i0.ɵɵadvance();
886
+ i0.ɵɵconditional(ctx.hasActiveFilters() ? 29 : -1);
887
+ i0.ɵɵadvance();
888
+ i0.ɵɵconditional(ctx.isLoading ? 30 : -1);
889
+ i0.ɵɵadvance();
890
+ i0.ɵɵclassProp("loading", ctx.isLoading);
891
+ i0.ɵɵadvance();
892
+ i0.ɵɵconditional(ctx.viewMode === "category" && !ctx.isLoading ? 32 : -1);
893
+ i0.ɵɵadvance();
894
+ i0.ɵɵconditional(ctx.viewMode === "list" && !ctx.isLoading ? 33 : -1);
895
+ i0.ɵɵadvance();
896
+ i0.ɵɵconditional(ctx.viewMode === "panel" && !ctx.isLoading ? 34 : -1);
897
+ } }, dependencies: [i3.DefaultValueAccessor, i3.NgControlStatus, i3.NgModel, i4.DropDownListComponent], styles: ["\n\n.query-browser-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f5f5f5;\n}\n\n\n\n.query-browser-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1rem 1.5rem;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n}\n\n.header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n}\n\n.page-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.5rem;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.page-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #4a90e2;\n}\n\n.header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n\n\n.search-container[_ngcontent-%COMP%] {\n position: relative;\n width: 300px;\n}\n\n.search-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 0.5rem 1rem 0.5rem 2.5rem;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 0.875rem;\n transition: border-color 0.2s;\n}\n\n.search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #4a90e2;\n box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.1);\n}\n\n.search-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 0.75rem;\n top: 50%;\n transform: translateY(-50%);\n color: #999;\n font-size: 0.875rem;\n}\n\n\n\n.view-mode-toggles[_ngcontent-%COMP%] {\n display: flex;\n background: #f8f8f8;\n border: 1px solid #ddd;\n border-radius: 4px;\n overflow: hidden;\n}\n\n.view-mode-btn[_ngcontent-%COMP%] {\n padding: 0.5rem 1rem;\n background: transparent;\n border: none;\n color: #666;\n cursor: pointer;\n font-size: 1rem;\n transition: all 0.2s;\n border-right: 1px solid #ddd;\n}\n\n.view-mode-btn[_ngcontent-%COMP%]:last-child {\n border-right: none;\n}\n\n.view-mode-btn[_ngcontent-%COMP%]:hover {\n background: #e8e8e8;\n color: #333;\n}\n\n.view-mode-btn.active[_ngcontent-%COMP%] {\n background: #4a90e2;\n color: white;\n}\n\n\n\n.create-query-btn[_ngcontent-%COMP%] {\n padding: 0.5rem 1rem;\n background: #4a90e2;\n color: white;\n border: none;\n border-radius: 4px;\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n transition: background 0.2s;\n}\n\n.create-query-btn[_ngcontent-%COMP%]:hover {\n background: #357abd;\n}\n\n\n\n.filter-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 1.5rem;\n padding: 1rem 1.5rem;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n}\n\n.filter-group[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.filter-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n font-weight: 500;\n color: #666;\n}\n\n.clear-filters-btn[_ngcontent-%COMP%] {\n margin-left: auto;\n padding: 0.375rem 0.75rem;\n background: #f44336;\n color: white;\n border: none;\n border-radius: 4px;\n font-size: 0.875rem;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 0.375rem;\n transition: background 0.2s;\n}\n\n.clear-filters-btn[_ngcontent-%COMP%]:hover {\n background: #d32f2f;\n}\n\n\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.75rem;\n padding: 3rem;\n color: #666;\n font-size: 1rem;\n}\n\n.loading-container[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n color: #4a90e2;\n}\n\n\n\n.query-browser-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 1.5rem;\n transition: opacity 0.2s;\n}\n\n.query-browser-content.loading[_ngcontent-%COMP%] {\n opacity: 0.5;\n pointer-events: none;\n}\n\n\n\n.category-view[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n\n\n.breadcrumb[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem;\n background: white;\n border-radius: 4px;\n font-size: 0.875rem;\n}\n\n.breadcrumb-item[_ngcontent-%COMP%] {\n color: #4a90e2;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 0.375rem;\n transition: color 0.2s;\n}\n\n.breadcrumb-item[_ngcontent-%COMP%]:hover {\n color: #357abd;\n text-decoration: underline;\n}\n\n.breadcrumb-item.current[_ngcontent-%COMP%] {\n color: #666;\n cursor: default;\n text-decoration: none;\n}\n\n.breadcrumb-separator[_ngcontent-%COMP%] {\n color: #999;\n font-size: 0.75rem;\n}\n\n\n\n.category-folders[_ngcontent-%COMP%] {\n background: white;\n border-radius: 8px;\n padding: 1.5rem;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n}\n\n.section-title[_ngcontent-%COMP%] {\n margin: 0 0 1rem 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.section-title[_ngcontent-%COMP%] .count[_ngcontent-%COMP%] {\n font-weight: normal;\n color: #666;\n font-size: 0.875rem;\n}\n\n.folder-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: 1rem;\n}\n\n.folder-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 1.5rem 1rem;\n background: #f8f8f8;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n position: relative;\n}\n\n.folder-item[_ngcontent-%COMP%]:hover {\n background: #e8f4fd;\n border-color: #4a90e2;\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);\n}\n\n.folder-icon[_ngcontent-%COMP%] {\n font-size: 2.5rem;\n color: #ffa726;\n margin-bottom: 0.5rem;\n}\n\n.folder-name[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n font-weight: 500;\n color: #333;\n text-align: center;\n word-break: break-word;\n}\n\n.item-count[_ngcontent-%COMP%] {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n background: #4a90e2;\n color: white;\n font-size: 0.75rem;\n padding: 0.125rem 0.375rem;\n border-radius: 12px;\n min-width: 20px;\n text-align: center;\n}\n\n\n\n.category-queries[_ngcontent-%COMP%] {\n background: white;\n border-radius: 8px;\n padding: 1.5rem;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n}\n\n.query-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.query-list-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 1rem;\n background: #f8f8f8;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.query-list-item[_ngcontent-%COMP%]:hover {\n background: #e8f4fd;\n border-color: #4a90e2;\n}\n\n.query-list-item.selected[_ngcontent-%COMP%] {\n background: #e3f2fd;\n border-color: #2196f3;\n}\n\n.query-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: white;\n border-radius: 4px;\n margin-right: 1rem;\n color: #4a90e2;\n font-size: 1.25rem;\n}\n\n.query-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.query-name[_ngcontent-%COMP%] {\n font-size: 1rem;\n font-weight: 500;\n color: #333;\n margin-bottom: 0.25rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.query-description[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: #666;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.query-status[_ngcontent-%COMP%] {\n padding: 0.25rem 0.75rem;\n border-radius: 4px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n\n\n.list-view[_ngcontent-%COMP%] {\n background: white;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n}\n\n.list-header[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 2fr 1.5fr 1fr 1.5fr 120px;\n padding: 1rem 1.5rem;\n background: #f8f8f8;\n border-bottom: 2px solid #e0e0e0;\n font-size: 0.875rem;\n font-weight: 600;\n color: #666;\n}\n\n.list-body[_ngcontent-%COMP%] {\n max-height: calc(100vh - 300px);\n overflow-y: auto;\n}\n\n.list-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 2fr 1.5fr 1fr 1.5fr 120px;\n padding: 1rem 1.5rem;\n border-bottom: 1px solid #e0e0e0;\n font-size: 0.875rem;\n cursor: pointer;\n transition: background 0.2s;\n align-items: center;\n}\n\n.list-row[_ngcontent-%COMP%]:hover {\n background: #f8f8f8;\n}\n\n.list-row.selected[_ngcontent-%COMP%] {\n background: #e3f2fd;\n}\n\n.col-name[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 500;\n color: #333;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.col-name[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #4a90e2;\n font-size: 1rem;\n}\n\n.col-description[_ngcontent-%COMP%], \n.col-category[_ngcontent-%COMP%] {\n color: #666;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.col-updated[_ngcontent-%COMP%] {\n color: #666;\n font-size: 0.8125rem;\n}\n\n.col-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n justify-content: flex-end;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #f8f8f8;\n border: 1px solid #ddd;\n border-radius: 4px;\n color: #666;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover {\n background: #4a90e2;\n border-color: #4a90e2;\n color: white;\n}\n\n.action-btn.danger[_ngcontent-%COMP%]:hover {\n background: #f44336;\n border-color: #f44336;\n}\n\n\n\n.panel-view[_ngcontent-%COMP%] {\n background: transparent;\n}\n\n.panel-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));\n gap: 1.5rem;\n}\n\n.query-panel[_ngcontent-%COMP%] {\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n padding: 1.5rem;\n cursor: pointer;\n transition: all 0.2s;\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.query-panel[_ngcontent-%COMP%]:hover {\n border-color: #4a90e2;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n}\n\n.query-panel.selected[_ngcontent-%COMP%] {\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 1rem;\n}\n\n.panel-title[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex: 1;\n}\n\n.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #4a90e2;\n}\n\n.panel-description[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: #666;\n line-height: 1.4;\n}\n\n.panel-sql-preview[_ngcontent-%COMP%] {\n background: #f8f8f8;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n padding: 0.75rem;\n}\n\n.sql-label[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n font-weight: 600;\n color: #666;\n margin-bottom: 0.5rem;\n text-transform: uppercase;\n}\n\n.sql-code[_ngcontent-%COMP%] {\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 0.8125rem;\n color: #333;\n background: white;\n padding: 0.5rem;\n border-radius: 2px;\n margin: 0;\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.panel-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-top: 1rem;\n border-top: 1px solid #e0e0e0;\n}\n\n.panel-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 1rem;\n font-size: 0.8125rem;\n color: #666;\n}\n\n.meta-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.meta-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: #999;\n}\n\n.panel-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n}\n\n\n\n.status-badge[_ngcontent-%COMP%] {\n padding: 0.25rem 0.75rem;\n border-radius: 4px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n.status-badge.status-pending[_ngcontent-%COMP%], \n.query-status.status-pending[_ngcontent-%COMP%] {\n background: #fff3cd;\n color: #856404;\n border: 1px solid #ffc107;\n}\n\n.status-badge.status-approved[_ngcontent-%COMP%], \n.query-status.status-approved[_ngcontent-%COMP%] {\n background: #d4edda;\n color: #155724;\n border: 1px solid #28a745;\n}\n\n.status-badge.status-rejected[_ngcontent-%COMP%], \n.query-status.status-rejected[_ngcontent-%COMP%] {\n background: #f8d7da;\n color: #721c24;\n border: 1px solid #dc3545;\n}\n\n.status-badge.status-expired[_ngcontent-%COMP%], \n.query-status.status-expired[_ngcontent-%COMP%] {\n background: #e0e0e0;\n color: #666;\n border: 1px solid #999;\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n color: #999;\n background: white;\n border-radius: 8px;\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 4rem;\n margin-bottom: 1rem;\n color: #ddd;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0.5rem 0;\n font-size: 1.125rem;\n color: #666;\n}\n\n.empty-hint[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: #999;\n}\n\n\n\n@media (max-width: 1200px) {\n .panel-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n }\n \n .list-header[_ngcontent-%COMP%], \n .list-row[_ngcontent-%COMP%] {\n grid-template-columns: 2fr 1.5fr 1fr 1fr 120px;\n }\n \n .col-description[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n@media (max-width: 768px) {\n .query-browser-header[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 1rem;\n padding: 1rem;\n }\n \n .header-right[_ngcontent-%COMP%] {\n width: 100%;\n flex-wrap: wrap;\n }\n \n .search-container[_ngcontent-%COMP%] {\n width: 100%;\n }\n \n .filter-bar[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n gap: 1rem;\n }\n \n .filter-group[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n }\n \n .panel-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n \n .folder-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\n }\n \n .list-header[_ngcontent-%COMP%], \n .list-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 0.5rem;\n }\n \n .list-header[_ngcontent-%COMP%] > *[_ngcontent-%COMP%]:not(.col-name), \n .list-row[_ngcontent-%COMP%] > *[_ngcontent-%COMP%]:not(.col-name) {\n display: none;\n }\n}\n\n\n\n.query-browser-content[_ngcontent-%COMP%]::-webkit-scrollbar, \n.list-body[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\n\n.query-browser-content[_ngcontent-%COMP%]::-webkit-scrollbar-track, \n.list-body[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: #f1f1f1;\n}\n\n.query-browser-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb, \n.list-body[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: #888;\n border-radius: 4px;\n}\n\n.query-browser-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover, \n.list-body[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: #555;\n}\n\n\n\n.k-card-body[_ngcontent-%COMP%] {\n height: 80px;\n}"] });
79
898
  };
80
899
  QueryBrowserComponent = __decorate([
81
900
  RegisterClass(BaseNavigationComponent, 'Queries')
@@ -83,7 +902,7 @@ QueryBrowserComponent = __decorate([
83
902
  export { QueryBrowserComponent };
84
903
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(QueryBrowserComponent, [{
85
904
  type: Component,
86
- args: [{ selector: 'mj-query-browser', template: "<mj-resource-browser\n #resourceBrowserQueries\n ResourceTypeName=\"Queries\"\n [EnableCategories]=\"false\"\n [EnableItemEdit]=\"false\"\n [EnableItemDelete]=\"false\"\n [CurrentCategoryID]=\"selectedFolderID\"\n Title=\"Queries\"\n DisplayMode=\"Tile\"\n [NewItemOptions]=\"NewItemOptions\"\n (ResourceSelected)=\"itemClick($event)\"\n (EditItemEvent)=\"onBeforeUpdateItemEvent($event)\"\n/>\n<!--\n<app-generic-browser-list \ntitle=\"Queries\" \nitemType=\"query\"\niconName=\"data\" \n[items]=\"items\"\naddText=\"Create New Query\"\nItemEntityName=\"Queries\"\nCategoryEntityName=\"Query Categories\"\n(itemClickEvent)=\"itemClick($event)\"\n(AfterAddFolderEvent)=\"onEvent($event)\"\n(AfterAddItemEvent)=\"onEvent($event)\"\n(AfterDeleteItemEvent)=\"onEvent($event)\"\n(AfterDeleteFolderEvent)=\"onEvent($event)\"\n[selectedFolderID]=\"selectedFolderID\"\n[showLoader]=\"showLoader\"\n[disableEditButton]=\"true\"\n(viewModeChangeEvent)=\"onViewModeChange($event)\"\n(BeforeUpdateItemEvent)=\"onBeforeUpdateItemEvent($event)\"\n/>\n-->", styles: [".k-card-body {\n height: 80px;\n }"] }]
905
+ args: [{ selector: 'mj-query-browser', template: "<div class=\"query-browser-container\">\n <!-- Header with Title and View Mode Toggles -->\n <div class=\"query-browser-header\">\n <div class=\"header-left\">\n <h2 class=\"page-title\">\n <i class=\"fa-solid fa-database\"></i>\n Queries\n </h2>\n </div>\n \n <div class=\"header-right\">\n <!-- Search Bar -->\n <div class=\"search-container\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input \n type=\"text\" \n class=\"search-input\" \n placeholder=\"Search queries...\" \n [(ngModel)]=\"searchText\"\n (ngModelChange)=\"onSearchChange($event)\"\n />\n </div>\n\n <!-- View Mode Toggles -->\n <div class=\"view-mode-toggles\">\n <button \n class=\"view-mode-btn\"\n [class.active]=\"viewMode === 'category'\"\n (click)=\"setViewMode('category')\"\n title=\"Category View\"\n >\n <i class=\"fa-solid fa-folder-tree\"></i>\n </button>\n <button \n class=\"view-mode-btn\"\n [class.active]=\"viewMode === 'list'\"\n (click)=\"setViewMode('list')\"\n title=\"List View\"\n >\n <i class=\"fa-solid fa-list\"></i>\n </button>\n <button \n class=\"view-mode-btn\"\n [class.active]=\"viewMode === 'panel'\"\n (click)=\"setViewMode('panel')\"\n title=\"Panel View\"\n >\n <i class=\"fa-solid fa-grip\"></i>\n </button>\n </div>\n\n <!-- Create New Query Button -->\n <button class=\"btn btn-primary create-query-btn\" (click)=\"createNewQuery()\">\n <i class=\"fa-solid fa-plus\"></i>\n New Query\n </button>\n </div>\n </div>\n\n <!-- Filter Bar -->\n <div class=\"filter-bar\">\n <div class=\"filter-group\">\n <label>Status:</label>\n <kendo-dropdownlist\n [data]=\"statusOptions\"\n [value]=\"getSelectedStatusOption()\"\n textField=\"text\"\n valueField=\"value\"\n (valueChange)=\"handleStatusChange($event)\"\n [style.width.px]=\"150\"\n >\n </kendo-dropdownlist>\n </div>\n\n <div class=\"filter-group\">\n <label>Sort by:</label>\n <kendo-dropdownlist\n [data]=\"sortOptions\"\n [value]=\"getSelectedSortOption()\"\n textField=\"text\"\n valueField=\"value\"\n (valueChange)=\"handleSortChange($event)\"\n [style.width.px]=\"200\"\n >\n </kendo-dropdownlist>\n </div>\n\n @if (hasActiveFilters()) {\n <button class=\"clear-filters-btn\" (click)=\"clearAllFilters()\">\n <i class=\"fa-solid fa-times\"></i>\n Clear Filters\n </button>\n }\n </div>\n\n <!-- Loading Indicator -->\n @if (isLoading) {\n <div class=\"loading-container\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading queries...\n </div>\n }\n\n <!-- Content Area -->\n <div class=\"query-browser-content\" [class.loading]=\"isLoading\">\n <!-- Category Path Mode -->\n @if (viewMode === 'category' && !isLoading) {\n <div class=\"category-view\">\n <!-- Breadcrumb -->\n <div class=\"breadcrumb\">\n <span class=\"breadcrumb-item\" (click)=\"navigateToRoot()\">\n ./\n </span>\n @for (pathItem of currentCategoryPath; track pathItem.id) {\n <i class=\"fa-solid fa-chevron-right breadcrumb-separator\"></i>\n <span \n class=\"breadcrumb-item\" \n [class.current]=\"pathItem.id === currentCategoryId\"\n (click)=\"navigateToCategory(pathItem.id)\"\n >\n {{ pathItem.name }}\n </span>\n }\n </div>\n\n <!-- Categories (Folders) -->\n @if (filteredCategories.length > 0) {\n <div class=\"category-folders\">\n <h4 class=\"section-title\">\n <i class=\"fa-solid fa-folder\"></i>\n Categories\n </h4>\n <div class=\"folder-grid\">\n @for (category of filteredCategories; track category.ID) {\n <div \n class=\"folder-item\"\n (click)=\"navigateToCategory(category.ID)\"\n [title]=\"category.Description || category.Name\"\n >\n <i class=\"fa-solid fa-folder folder-icon\"></i>\n <span class=\"folder-name\">{{ category.Name }}</span>\n @if (category.QueryCount && category.QueryCount > 0) {\n <span class=\"item-count\">{{ category.QueryCount }}</span>\n }\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Queries in Current Category -->\n @if (filteredQueries.length > 0) {\n <div class=\"category-queries\">\n <h4 class=\"section-title\">\n <i class=\"fa-solid fa-file-code\"></i>\n Queries\n <span class=\"count\">({{ filteredQueries.length }})</span>\n </h4>\n <div class=\"query-list\">\n @for (query of filteredQueries; track query.ID) {\n <div \n class=\"query-list-item\"\n (click)=\"selectQuery(query)\"\n [class.selected]=\"selectedQuery?.ID === query.ID\"\n >\n <div class=\"query-icon\">\n <i class=\"fa-solid fa-code\"></i>\n </div>\n <div class=\"query-info\">\n <div class=\"query-name\">{{ query.Name }}</div>\n @if (query.Description) {\n <div class=\"query-description\">{{ query.Description }}</div>\n }\n </div>\n <div class=\"query-status\" [class]=\"'status-' + (query.Status || 'pending').toLowerCase()\">\n {{ query.Status || 'Pending' }}\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n @if (filteredCategories.length === 0 && filteredQueries.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-folder-open\"></i>\n <p>No categories or queries found</p>\n </div>\n }\n </div>\n }\n\n <!-- List Mode -->\n @if (viewMode === 'list' && !isLoading) {\n <div class=\"list-view\">\n @if (filteredQueries.length > 0) {\n <div class=\"list-header\">\n <div class=\"col-name\">Name</div>\n <div class=\"col-description\">Description</div>\n <div class=\"col-category\">Category</div>\n <div class=\"col-status\">Status</div>\n <div class=\"col-updated\">Last Updated</div>\n <div class=\"col-actions\">Actions</div>\n </div>\n <div class=\"list-body\">\n @for (query of filteredQueries; track query.ID) {\n <div \n class=\"list-row\"\n (click)=\"selectQuery(query)\"\n [class.selected]=\"selectedQuery?.ID === query.ID\"\n >\n <div class=\"col-name\">\n <i class=\"fa-solid fa-code\"></i>\n {{ query.Name }}\n </div>\n <div class=\"col-description\">\n {{ query.Description || '-' }}\n </div>\n <div class=\"col-category\">\n {{ getCategoryName(query.CategoryID) || '-' }}\n </div>\n <div class=\"col-status\">\n <span class=\"status-badge\" [class]=\"'status-' + (query.Status || 'pending').toLowerCase()\">\n {{ query.Status || 'Pending' }}\n </span>\n </div>\n <div class=\"col-updated\">\n {{ formatDate(query.__mj_UpdatedAt) }}\n </div>\n <div class=\"col-actions\">\n <button \n class=\"action-btn\"\n (click)=\"runQuery(query, $event)\"\n title=\"Run\"\n >\n <i class=\"fa-solid fa-play\"></i>\n </button>\n <button \n class=\"action-btn danger\"\n (click)=\"deleteQuery(query, $event)\"\n title=\"Delete\"\n >\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-database\"></i>\n <p>No queries found</p>\n @if (searchText || selectedStatus !== 'all') {\n <p class=\"empty-hint\">Try adjusting your filters</p>\n }\n </div>\n }\n </div>\n }\n\n <!-- Panel Mode -->\n @if (viewMode === 'panel' && !isLoading) {\n <div class=\"panel-view\">\n @if (filteredQueries.length > 0) {\n <div class=\"panel-grid\">\n @for (query of filteredQueries; track query.ID) {\n <div \n class=\"query-panel\"\n (click)=\"selectQuery(query)\"\n [class.selected]=\"selectedQuery?.ID === query.ID\"\n >\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-code\"></i>\n {{ query.Name }}\n </div>\n <span class=\"status-badge\" [class]=\"'status-' + (query.Status || 'pending').toLowerCase()\">\n {{ query.Status || 'Pending' }}\n </span>\n </div>\n \n @if (query.Description) {\n <div class=\"panel-description\">\n {{ query.Description }}\n </div>\n }\n \n <div class=\"panel-sql-preview\">\n <div class=\"sql-label\">SQL Preview:</div>\n <pre class=\"sql-code\">{{ getQueryPreview(query.SQL) }}</pre>\n </div>\n \n <div class=\"panel-footer\">\n <div class=\"panel-meta\">\n @if (query.CategoryID) {\n <span class=\"meta-item\">\n <i class=\"fa-solid fa-folder\"></i>\n {{ getCategoryName(query.CategoryID) }}\n </span>\n }\n <span class=\"meta-item\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ formatDate(query.__mj_UpdatedAt) }}\n </span>\n </div>\n <div class=\"panel-actions\">\n <button \n class=\"action-btn\"\n (click)=\"runQuery(query, $event)\"\n title=\"Run\"\n >\n <i class=\"fa-solid fa-play\"></i>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-grip\"></i>\n <p>No queries to display</p>\n @if (searchText || selectedStatus !== 'all') {\n <p class=\"empty-hint\">Try adjusting your filters</p>\n }\n </div>\n }\n </div>\n }\n </div>\n</div>", styles: ["/* Container Styles */\n.query-browser-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f5f5f5;\n}\n\n/* Header Styles */\n.query-browser-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1rem 1.5rem;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n}\n\n.header-left {\n display: flex;\n align-items: center;\n}\n\n.page-title {\n margin: 0;\n font-size: 1.5rem;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.page-title i {\n color: #4a90e2;\n}\n\n.header-right {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n/* Search Bar */\n.search-container {\n position: relative;\n width: 300px;\n}\n\n.search-input {\n width: 100%;\n padding: 0.5rem 1rem 0.5rem 2.5rem;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 0.875rem;\n transition: border-color 0.2s;\n}\n\n.search-input:focus {\n outline: none;\n border-color: #4a90e2;\n box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.1);\n}\n\n.search-icon {\n position: absolute;\n left: 0.75rem;\n top: 50%;\n transform: translateY(-50%);\n color: #999;\n font-size: 0.875rem;\n}\n\n/* View Mode Toggles */\n.view-mode-toggles {\n display: flex;\n background: #f8f8f8;\n border: 1px solid #ddd;\n border-radius: 4px;\n overflow: hidden;\n}\n\n.view-mode-btn {\n padding: 0.5rem 1rem;\n background: transparent;\n border: none;\n color: #666;\n cursor: pointer;\n font-size: 1rem;\n transition: all 0.2s;\n border-right: 1px solid #ddd;\n}\n\n.view-mode-btn:last-child {\n border-right: none;\n}\n\n.view-mode-btn:hover {\n background: #e8e8e8;\n color: #333;\n}\n\n.view-mode-btn.active {\n background: #4a90e2;\n color: white;\n}\n\n/* Create Button */\n.create-query-btn {\n padding: 0.5rem 1rem;\n background: #4a90e2;\n color: white;\n border: none;\n border-radius: 4px;\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n transition: background 0.2s;\n}\n\n.create-query-btn:hover {\n background: #357abd;\n}\n\n/* Filter Bar */\n.filter-bar {\n display: flex;\n align-items: center;\n gap: 1.5rem;\n padding: 1rem 1.5rem;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n}\n\n.filter-group {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.filter-group label {\n font-size: 0.875rem;\n font-weight: 500;\n color: #666;\n}\n\n.clear-filters-btn {\n margin-left: auto;\n padding: 0.375rem 0.75rem;\n background: #f44336;\n color: white;\n border: none;\n border-radius: 4px;\n font-size: 0.875rem;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 0.375rem;\n transition: background 0.2s;\n}\n\n.clear-filters-btn:hover {\n background: #d32f2f;\n}\n\n/* Loading State */\n.loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.75rem;\n padding: 3rem;\n color: #666;\n font-size: 1rem;\n}\n\n.loading-container i {\n font-size: 1.25rem;\n color: #4a90e2;\n}\n\n/* Content Area */\n.query-browser-content {\n flex: 1;\n overflow: auto;\n padding: 1.5rem;\n transition: opacity 0.2s;\n}\n\n.query-browser-content.loading {\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* Category View Styles */\n.category-view {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n/* Breadcrumb */\n.breadcrumb {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem;\n background: white;\n border-radius: 4px;\n font-size: 0.875rem;\n}\n\n.breadcrumb-item {\n color: #4a90e2;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 0.375rem;\n transition: color 0.2s;\n}\n\n.breadcrumb-item:hover {\n color: #357abd;\n text-decoration: underline;\n}\n\n.breadcrumb-item.current {\n color: #666;\n cursor: default;\n text-decoration: none;\n}\n\n.breadcrumb-separator {\n color: #999;\n font-size: 0.75rem;\n}\n\n/* Category Folders */\n.category-folders {\n background: white;\n border-radius: 8px;\n padding: 1.5rem;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n}\n\n.section-title {\n margin: 0 0 1rem 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.section-title .count {\n font-weight: normal;\n color: #666;\n font-size: 0.875rem;\n}\n\n.folder-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: 1rem;\n}\n\n.folder-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 1.5rem 1rem;\n background: #f8f8f8;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n position: relative;\n}\n\n.folder-item:hover {\n background: #e8f4fd;\n border-color: #4a90e2;\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);\n}\n\n.folder-icon {\n font-size: 2.5rem;\n color: #ffa726;\n margin-bottom: 0.5rem;\n}\n\n.folder-name {\n font-size: 0.875rem;\n font-weight: 500;\n color: #333;\n text-align: center;\n word-break: break-word;\n}\n\n.item-count {\n position: absolute;\n top: 0.5rem;\n right: 0.5rem;\n background: #4a90e2;\n color: white;\n font-size: 0.75rem;\n padding: 0.125rem 0.375rem;\n border-radius: 12px;\n min-width: 20px;\n text-align: center;\n}\n\n/* Category Queries */\n.category-queries {\n background: white;\n border-radius: 8px;\n padding: 1.5rem;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n}\n\n.query-list {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.query-list-item {\n display: flex;\n align-items: center;\n padding: 1rem;\n background: #f8f8f8;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.query-list-item:hover {\n background: #e8f4fd;\n border-color: #4a90e2;\n}\n\n.query-list-item.selected {\n background: #e3f2fd;\n border-color: #2196f3;\n}\n\n.query-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n background: white;\n border-radius: 4px;\n margin-right: 1rem;\n color: #4a90e2;\n font-size: 1.25rem;\n}\n\n.query-info {\n flex: 1;\n min-width: 0;\n}\n\n.query-name {\n font-size: 1rem;\n font-weight: 500;\n color: #333;\n margin-bottom: 0.25rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.query-description {\n font-size: 0.875rem;\n color: #666;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.query-status {\n padding: 0.25rem 0.75rem;\n border-radius: 4px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n/* List View Styles */\n.list-view {\n background: white;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n}\n\n.list-header {\n display: grid;\n grid-template-columns: 2fr 2fr 1.5fr 1fr 1.5fr 120px;\n padding: 1rem 1.5rem;\n background: #f8f8f8;\n border-bottom: 2px solid #e0e0e0;\n font-size: 0.875rem;\n font-weight: 600;\n color: #666;\n}\n\n.list-body {\n max-height: calc(100vh - 300px);\n overflow-y: auto;\n}\n\n.list-row {\n display: grid;\n grid-template-columns: 2fr 2fr 1.5fr 1fr 1.5fr 120px;\n padding: 1rem 1.5rem;\n border-bottom: 1px solid #e0e0e0;\n font-size: 0.875rem;\n cursor: pointer;\n transition: background 0.2s;\n align-items: center;\n}\n\n.list-row:hover {\n background: #f8f8f8;\n}\n\n.list-row.selected {\n background: #e3f2fd;\n}\n\n.col-name {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 500;\n color: #333;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.col-name i {\n color: #4a90e2;\n font-size: 1rem;\n}\n\n.col-description,\n.col-category {\n color: #666;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.col-updated {\n color: #666;\n font-size: 0.8125rem;\n}\n\n.col-actions {\n display: flex;\n gap: 0.5rem;\n justify-content: flex-end;\n}\n\n.action-btn {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #f8f8f8;\n border: 1px solid #ddd;\n border-radius: 4px;\n color: #666;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.action-btn:hover {\n background: #4a90e2;\n border-color: #4a90e2;\n color: white;\n}\n\n.action-btn.danger:hover {\n background: #f44336;\n border-color: #f44336;\n}\n\n/* Panel View Styles */\n.panel-view {\n background: transparent;\n}\n\n.panel-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));\n gap: 1.5rem;\n}\n\n.query-panel {\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n padding: 1.5rem;\n cursor: pointer;\n transition: all 0.2s;\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.query-panel:hover {\n border-color: #4a90e2;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n}\n\n.query-panel.selected {\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n}\n\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 1rem;\n}\n\n.panel-title {\n font-size: 1.125rem;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex: 1;\n}\n\n.panel-title i {\n color: #4a90e2;\n}\n\n.panel-description {\n font-size: 0.875rem;\n color: #666;\n line-height: 1.4;\n}\n\n.panel-sql-preview {\n background: #f8f8f8;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n padding: 0.75rem;\n}\n\n.sql-label {\n font-size: 0.75rem;\n font-weight: 600;\n color: #666;\n margin-bottom: 0.5rem;\n text-transform: uppercase;\n}\n\n.sql-code {\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 0.8125rem;\n color: #333;\n background: white;\n padding: 0.5rem;\n border-radius: 2px;\n margin: 0;\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.panel-footer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-top: 1rem;\n border-top: 1px solid #e0e0e0;\n}\n\n.panel-meta {\n display: flex;\n gap: 1rem;\n font-size: 0.8125rem;\n color: #666;\n}\n\n.meta-item {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.meta-item i {\n font-size: 0.875rem;\n color: #999;\n}\n\n.panel-actions {\n display: flex;\n gap: 0.5rem;\n}\n\n/* Status Badge Styles */\n.status-badge {\n padding: 0.25rem 0.75rem;\n border-radius: 4px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n.status-badge.status-pending,\n.query-status.status-pending {\n background: #fff3cd;\n color: #856404;\n border: 1px solid #ffc107;\n}\n\n.status-badge.status-approved,\n.query-status.status-approved {\n background: #d4edda;\n color: #155724;\n border: 1px solid #28a745;\n}\n\n.status-badge.status-rejected,\n.query-status.status-rejected {\n background: #f8d7da;\n color: #721c24;\n border: 1px solid #dc3545;\n}\n\n.status-badge.status-expired,\n.query-status.status-expired {\n background: #e0e0e0;\n color: #666;\n border: 1px solid #999;\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n color: #999;\n background: white;\n border-radius: 8px;\n text-align: center;\n}\n\n.empty-state i {\n font-size: 4rem;\n margin-bottom: 1rem;\n color: #ddd;\n}\n\n.empty-state p {\n margin: 0.5rem 0;\n font-size: 1.125rem;\n color: #666;\n}\n\n.empty-hint {\n font-size: 0.875rem;\n color: #999;\n}\n\n/* Responsive Design */\n@media (max-width: 1200px) {\n .panel-grid {\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n }\n \n .list-header,\n .list-row {\n grid-template-columns: 2fr 1.5fr 1fr 1fr 120px;\n }\n \n .col-description {\n display: none;\n }\n}\n\n@media (max-width: 768px) {\n .query-browser-header {\n flex-direction: column;\n gap: 1rem;\n padding: 1rem;\n }\n \n .header-right {\n width: 100%;\n flex-wrap: wrap;\n }\n \n .search-container {\n width: 100%;\n }\n \n .filter-bar {\n flex-direction: column;\n align-items: stretch;\n gap: 1rem;\n }\n \n .filter-group {\n flex-direction: column;\n align-items: stretch;\n }\n \n .panel-grid {\n grid-template-columns: 1fr;\n }\n \n .folder-grid {\n grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\n }\n \n .list-header,\n .list-row {\n grid-template-columns: 1fr;\n gap: 0.5rem;\n }\n \n .list-header > *:not(.col-name),\n .list-row > *:not(.col-name) {\n display: none;\n }\n}\n\n/* Scrollbar Styles */\n.query-browser-content::-webkit-scrollbar,\n.list-body::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\n\n.query-browser-content::-webkit-scrollbar-track,\n.list-body::-webkit-scrollbar-track {\n background: #f1f1f1;\n}\n\n.query-browser-content::-webkit-scrollbar-thumb,\n.list-body::-webkit-scrollbar-thumb {\n background: #888;\n border-radius: 4px;\n}\n\n.query-browser-content::-webkit-scrollbar-thumb:hover,\n.list-body::-webkit-scrollbar-thumb:hover {\n background: #555;\n}\n\n/* Legacy k-card style - keep for backward compatibility */\n.k-card-body {\n height: 80px;\n}"] }]
87
906
  }], () => [{ type: i1.Router }, { type: i1.ActivatedRoute }, { type: i2.SharedService }], null); })();
88
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(QueryBrowserComponent, { className: "QueryBrowserComponent", filePath: "src/lib/query-browser-component/query-browser.component.ts", lineNumber: 17 }); })();
907
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(QueryBrowserComponent, { className: "QueryBrowserComponent", filePath: "src/lib/query-browser-component/query-browser.component.ts", lineNumber: 28 }); })();
89
908
  //# sourceMappingURL=query-browser.component.js.map