@memberjunction/ng-dashboards 2.122.2 → 2.123.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.
Files changed (24) hide show
  1. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts +79 -0
  2. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts.map +1 -0
  3. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +195 -0
  4. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +1 -0
  5. package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts +67 -1
  6. package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts.map +1 -1
  7. package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js +377 -79
  8. package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js.map +1 -1
  9. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +87 -4
  10. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  11. package/dist/DataExplorer/data-explorer-dashboard.component.js +517 -209
  12. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  13. package/dist/DataExplorer/models/explorer-state.interface.d.ts +13 -2
  14. package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -1
  15. package/dist/DataExplorer/models/explorer-state.interface.js +3 -0
  16. package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -1
  17. package/dist/DataExplorer/services/explorer-state.service.d.ts +2 -2
  18. package/dist/DataExplorer/services/explorer-state.service.d.ts.map +1 -1
  19. package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
  20. package/dist/module.d.ts +28 -26
  21. package/dist/module.d.ts.map +1 -1
  22. package/dist/module.js +10 -3
  23. package/dist/module.js.map +1 -1
  24. package/package.json +25 -24
@@ -1,5 +1,6 @@
1
1
  import { Component, Input, Output, EventEmitter, HostListener } from '@angular/core';
2
2
  import { Metadata } from '@memberjunction/core';
3
+ import { createEmptyFilter } from '@memberjunction/ng-filter-builder';
3
4
  import * as i0 from "@angular/core";
4
5
  import * as i1 from "@angular/forms";
5
6
  const _forTrack0 = ($index, $item) => $item.ID;
@@ -176,9 +177,15 @@ function ViewConfigPanelComponent_Conditional_23_Template(rf, ctx) { if (rf & 1)
176
177
  i0.ɵɵadvance(2);
177
178
  i0.ɵɵconditional(ctx_r1.hiddenColumns.length === 0 ? 35 : -1);
178
179
  } }
179
- function ViewConfigPanelComponent_Conditional_24_Conditional_10_Conditional_4_Template(rf, ctx) { if (rf & 1) {
180
- i0.ɵɵelementStart(0, "div", 65);
181
- i0.ɵɵelement(1, "i", 50);
180
+ function ViewConfigPanelComponent_Conditional_24_Conditional_10_Template(rf, ctx) { if (rf & 1) {
181
+ i0.ɵɵelement(0, "i", 63);
182
+ } }
183
+ function ViewConfigPanelComponent_Conditional_24_Conditional_19_Template(rf, ctx) { if (rf & 1) {
184
+ i0.ɵɵelement(0, "i", 63);
185
+ } }
186
+ function ViewConfigPanelComponent_Conditional_24_Conditional_20_Conditional_5_Template(rf, ctx) { if (rf & 1) {
187
+ i0.ɵɵelementStart(0, "div", 70);
188
+ i0.ɵɵelement(1, "i", 81);
182
189
  i0.ɵɵelementStart(2, "span");
183
190
  i0.ɵɵtext(3);
184
191
  i0.ɵɵelementEnd()();
@@ -187,116 +194,211 @@ function ViewConfigPanelComponent_Conditional_24_Conditional_10_Conditional_4_Te
187
194
  i0.ɵɵadvance(3);
188
195
  i0.ɵɵtextInterpolate(ctx_r1.smartFilterExplanation);
189
196
  } }
190
- function ViewConfigPanelComponent_Conditional_24_Conditional_10_Template(rf, ctx) { if (rf & 1) {
197
+ function ViewConfigPanelComponent_Conditional_24_Conditional_20_Template(rf, ctx) { if (rf & 1) {
191
198
  const _r13 = i0.ɵɵgetCurrentView();
192
- i0.ɵɵelementStart(0, "div", 62)(1, "label", 63);
193
- i0.ɵɵtext(2, "Natural Language Filter");
199
+ i0.ɵɵelementStart(0, "div", 65)(1, "div", 67)(2, "div", 68);
200
+ i0.ɵɵelement(3, "i", 59);
194
201
  i0.ɵɵelementEnd();
195
- i0.ɵɵelementStart(3, "textarea", 64);
196
- i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_24_Conditional_10_Template_textarea_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.smartFilterPrompt, $event) || (ctx_r1.smartFilterPrompt = $event); return i0.ɵɵresetView($event); });
202
+ i0.ɵɵelementStart(4, "textarea", 69);
203
+ i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_24_Conditional_20_Template_textarea_ngModelChange_4_listener($event) { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.smartFilterPrompt, $event) || (ctx_r1.smartFilterPrompt = $event); return i0.ɵɵresetView($event); });
197
204
  i0.ɵɵelementEnd()();
198
- i0.ɵɵtemplate(4, ViewConfigPanelComponent_Conditional_24_Conditional_10_Conditional_4_Template, 4, 1, "div", 65);
199
- i0.ɵɵelementStart(5, "div", 66);
200
- i0.ɵɵelement(6, "i", 67);
201
- i0.ɵɵelementStart(7, "span");
202
- i0.ɵɵtext(8, "Tip: The AI will interpret your natural language and create the appropriate filter when you save the view.");
205
+ i0.ɵɵtemplate(5, ViewConfigPanelComponent_Conditional_24_Conditional_20_Conditional_5_Template, 4, 1, "div", 70);
206
+ i0.ɵɵelementStart(6, "div", 71)(7, "div", 72);
207
+ i0.ɵɵelement(8, "i", 73);
208
+ i0.ɵɵelementStart(9, "span");
209
+ i0.ɵɵtext(10, "Try these examples:");
203
210
  i0.ɵɵelementEnd()();
211
+ i0.ɵɵelementStart(11, "div", 74)(12, "button", 75);
212
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_24_Conditional_20_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.applySmartFilterExample("Show records created in the last 30 days")); });
213
+ i0.ɵɵelement(13, "i", 76);
214
+ i0.ɵɵtext(14, " Last 30 days ");
215
+ i0.ɵɵelementEnd();
216
+ i0.ɵɵelementStart(15, "button", 75);
217
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_24_Conditional_20_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.applySmartFilterExample("Active records only")); });
218
+ i0.ɵɵelement(16, "i", 77);
219
+ i0.ɵɵtext(17, " Active only ");
220
+ i0.ɵɵelementEnd();
221
+ i0.ɵɵelementStart(18, "button", 75);
222
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_24_Conditional_20_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.applySmartFilterExample("Records with high priority")); });
223
+ i0.ɵɵelement(19, "i", 78);
224
+ i0.ɵɵtext(20, " High priority ");
225
+ i0.ɵɵelementEnd();
226
+ i0.ɵɵelementStart(21, "button", 75);
227
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_24_Conditional_20_Template_button_click_21_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.applySmartFilterExample("Records modified this week")); });
228
+ i0.ɵɵelement(22, "i", 79);
229
+ i0.ɵɵtext(23, " Modified this week ");
230
+ i0.ɵɵelementEnd()()();
231
+ i0.ɵɵelementStart(24, "div", 80);
232
+ i0.ɵɵelement(25, "i", 50);
233
+ i0.ɵɵelementStart(26, "span");
234
+ i0.ɵɵtext(27, "The AI will interpret your description and create the appropriate filter when you save the view.");
235
+ i0.ɵɵelementEnd()()();
204
236
  } if (rf & 2) {
205
237
  const ctx_r1 = i0.ɵɵnextContext(2);
206
- i0.ɵɵadvance(3);
238
+ i0.ɵɵadvance(4);
207
239
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.smartFilterPrompt);
208
240
  i0.ɵɵproperty("disabled", !ctx_r1.canEdit);
209
241
  i0.ɵɵadvance();
210
- i0.ɵɵconditional(ctx_r1.smartFilterExplanation ? 4 : -1);
242
+ i0.ɵɵconditional(ctx_r1.smartFilterExplanation ? 5 : -1);
243
+ i0.ɵɵadvance(7);
244
+ i0.ɵɵproperty("disabled", !ctx_r1.canEdit);
245
+ i0.ɵɵadvance(3);
246
+ i0.ɵɵproperty("disabled", !ctx_r1.canEdit);
247
+ i0.ɵɵadvance(3);
248
+ i0.ɵɵproperty("disabled", !ctx_r1.canEdit);
249
+ i0.ɵɵadvance(3);
250
+ i0.ɵɵproperty("disabled", !ctx_r1.canEdit);
251
+ } }
252
+ function ViewConfigPanelComponent_Conditional_24_Conditional_21_Conditional_4_Template(rf, ctx) { if (rf & 1) {
253
+ i0.ɵɵelementStart(0, "span", 91);
254
+ i0.ɵɵtext(1);
255
+ i0.ɵɵelementEnd();
256
+ i0.ɵɵelementStart(2, "span", 92);
257
+ i0.ɵɵtext(3);
258
+ i0.ɵɵelementEnd();
259
+ } if (rf & 2) {
260
+ const ctx_r1 = i0.ɵɵnextContext(3);
261
+ i0.ɵɵadvance();
262
+ i0.ɵɵtextInterpolate(ctx_r1.getFilterCount());
263
+ i0.ɵɵadvance(2);
264
+ i0.ɵɵtextInterpolate(ctx_r1.getFilterSummary());
211
265
  } }
212
- function ViewConfigPanelComponent_Conditional_24_Conditional_11_Template(rf, ctx) { if (rf & 1) {
213
- i0.ɵɵelementStart(0, "div", 60)(1, "p");
214
- i0.ɵɵtext(2, "Enable Smart Filter to use natural language filtering. The AI will interpret your description and create the appropriate SQL filter.");
215
- i0.ɵɵelementEnd()();
266
+ function ViewConfigPanelComponent_Conditional_24_Conditional_21_Conditional_5_Template(rf, ctx) { if (rf & 1) {
267
+ i0.ɵɵelementStart(0, "span", 85);
268
+ i0.ɵɵtext(1, "No filters configured");
269
+ i0.ɵɵelementEnd();
270
+ } }
271
+ function ViewConfigPanelComponent_Conditional_24_Conditional_21_Conditional_7_Template(rf, ctx) { if (rf & 1) {
272
+ const _r15 = i0.ɵɵgetCurrentView();
273
+ i0.ɵɵelementStart(0, "button", 93);
274
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_24_Conditional_21_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.clearFilters()); });
275
+ i0.ɵɵelement(1, "i", 6);
276
+ i0.ɵɵtext(2, " Clear ");
277
+ i0.ɵɵelementEnd();
278
+ } }
279
+ function ViewConfigPanelComponent_Conditional_24_Conditional_21_Template(rf, ctx) { if (rf & 1) {
280
+ const _r14 = i0.ɵɵgetCurrentView();
281
+ i0.ɵɵelementStart(0, "div", 66)(1, "div", 82)(2, "div", 83)(3, "div", 84);
282
+ i0.ɵɵtemplate(4, ViewConfigPanelComponent_Conditional_24_Conditional_21_Conditional_4_Template, 4, 2)(5, ViewConfigPanelComponent_Conditional_24_Conditional_21_Conditional_5_Template, 2, 0, "span", 85);
283
+ i0.ɵɵelementEnd();
284
+ i0.ɵɵelementStart(6, "div", 86);
285
+ i0.ɵɵtemplate(7, ViewConfigPanelComponent_Conditional_24_Conditional_21_Conditional_7_Template, 3, 0, "button", 87);
286
+ i0.ɵɵelementStart(8, "button", 88);
287
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_24_Conditional_21_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.openFilterDialog()); });
288
+ i0.ɵɵelement(9, "i", 89);
289
+ i0.ɵɵtext(10);
290
+ i0.ɵɵelementEnd()()()();
291
+ i0.ɵɵelementStart(11, "div", 90);
292
+ i0.ɵɵelement(12, "i", 50);
293
+ i0.ɵɵelementStart(13, "span");
294
+ i0.ɵɵtext(14, "Build precise filters by selecting fields, operators, and values. Use groups for complex AND/OR logic.");
295
+ i0.ɵɵelementEnd()()();
296
+ } if (rf & 2) {
297
+ const ctx_r1 = i0.ɵɵnextContext(2);
298
+ i0.ɵɵadvance(4);
299
+ i0.ɵɵconditional(ctx_r1.getFilterCount() > 0 ? 4 : 5);
300
+ i0.ɵɵadvance(3);
301
+ i0.ɵɵconditional(ctx_r1.getFilterCount() > 0 && ctx_r1.canEdit ? 7 : -1);
302
+ i0.ɵɵadvance();
303
+ i0.ɵɵproperty("disabled", !ctx_r1.canEdit && ctx_r1.getFilterCount() === 0);
304
+ i0.ɵɵadvance(2);
305
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.getFilterCount() > 0 ? "Edit Filters" : "Add Filters", " ");
216
306
  } }
217
307
  function ViewConfigPanelComponent_Conditional_24_Template(rf, ctx) { if (rf & 1) {
218
308
  const _r12 = i0.ɵɵgetCurrentView();
219
- i0.ɵɵelementStart(0, "div", 13)(1, "div", 20)(2, "div", 21);
220
- i0.ɵɵelement(3, "i", 56);
221
- i0.ɵɵelementStart(4, "span");
222
- i0.ɵɵtext(5, "Smart Filter");
309
+ i0.ɵɵelementStart(0, "div", 13)(1, "div", 56)(2, "button", 57);
310
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_24_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setFilterMode("smart")); });
311
+ i0.ɵɵelementStart(3, "div", 58);
312
+ i0.ɵɵelement(4, "i", 59);
223
313
  i0.ɵɵelementEnd();
224
- i0.ɵɵelementStart(6, "label", 57)(7, "input", 58);
225
- i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_24_Template_input_ngModelChange_7_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.smartFilterEnabled, $event) || (ctx_r1.smartFilterEnabled = $event); return i0.ɵɵresetView($event); });
314
+ i0.ɵɵelementStart(5, "div", 60)(6, "span", 61);
315
+ i0.ɵɵtext(7, "Smart Filter");
226
316
  i0.ɵɵelementEnd();
227
- i0.ɵɵelementStart(8, "span", 59);
228
- i0.ɵɵtext(9);
229
- i0.ɵɵelementEnd()()();
230
- i0.ɵɵtemplate(10, ViewConfigPanelComponent_Conditional_24_Conditional_10_Template, 9, 3)(11, ViewConfigPanelComponent_Conditional_24_Conditional_11_Template, 3, 0, "div", 60);
317
+ i0.ɵɵelementStart(8, "span", 62);
318
+ i0.ɵɵtext(9, "Use AI to filter with natural language");
319
+ i0.ɵɵelementEnd()();
320
+ i0.ɵɵtemplate(10, ViewConfigPanelComponent_Conditional_24_Conditional_10_Template, 1, 0, "i", 63);
321
+ i0.ɵɵelementEnd();
322
+ i0.ɵɵelementStart(11, "button", 57);
323
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_24_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.setFilterMode("traditional")); });
324
+ i0.ɵɵelementStart(12, "div", 58);
325
+ i0.ɵɵelement(13, "i", 64);
326
+ i0.ɵɵelementEnd();
327
+ i0.ɵɵelementStart(14, "div", 60)(15, "span", 61);
328
+ i0.ɵɵtext(16, "Traditional Filter");
231
329
  i0.ɵɵelementEnd();
232
- i0.ɵɵelementStart(12, "div", 20)(13, "div", 21);
233
- i0.ɵɵelement(14, "i", 10);
234
- i0.ɵɵelementStart(15, "span");
235
- i0.ɵɵtext(16, "Traditional Filters");
330
+ i0.ɵɵelementStart(17, "span", 62);
331
+ i0.ɵɵtext(18, "Build filters with field/operator/value");
236
332
  i0.ɵɵelementEnd()();
237
- i0.ɵɵelementStart(17, "div", 61);
238
- i0.ɵɵelement(18, "i", 4);
239
- i0.ɵɵelementStart(19, "p");
240
- i0.ɵɵtext(20, "Traditional filter editing is coming soon. For now, use Smart Filter above or the filter builder in the grid view.");
241
- i0.ɵɵelementEnd()()()();
333
+ i0.ɵɵtemplate(19, ViewConfigPanelComponent_Conditional_24_Conditional_19_Template, 1, 0, "i", 63);
334
+ i0.ɵɵelementEnd()();
335
+ i0.ɵɵtemplate(20, ViewConfigPanelComponent_Conditional_24_Conditional_20_Template, 28, 7, "div", 65)(21, ViewConfigPanelComponent_Conditional_24_Conditional_21_Template, 15, 4, "div", 66);
336
+ i0.ɵɵelementEnd();
242
337
  } if (rf & 2) {
243
338
  const ctx_r1 = i0.ɵɵnextContext();
244
- i0.ɵɵadvance(7);
245
- i0.ɵɵtwoWayProperty("ngModel", ctx_r1.smartFilterEnabled);
246
- i0.ɵɵproperty("disabled", !ctx_r1.canEdit);
247
339
  i0.ɵɵadvance(2);
248
- i0.ɵɵtextInterpolate(ctx_r1.smartFilterEnabled ? "Enabled" : "Disabled");
340
+ i0.ɵɵclassProp("active", ctx_r1.filterMode === "smart");
341
+ i0.ɵɵproperty("disabled", !ctx_r1.canEdit);
342
+ i0.ɵɵadvance(8);
343
+ i0.ɵɵconditional(ctx_r1.filterMode === "smart" ? 10 : -1);
344
+ i0.ɵɵadvance();
345
+ i0.ɵɵclassProp("active", ctx_r1.filterMode === "traditional");
346
+ i0.ɵɵproperty("disabled", !ctx_r1.canEdit);
347
+ i0.ɵɵadvance(8);
348
+ i0.ɵɵconditional(ctx_r1.filterMode === "traditional" ? 19 : -1);
349
+ i0.ɵɵadvance();
350
+ i0.ɵɵconditional(ctx_r1.filterMode === "smart" ? 20 : -1);
249
351
  i0.ɵɵadvance();
250
- i0.ɵɵconditional(ctx_r1.smartFilterEnabled ? 10 : 11);
352
+ i0.ɵɵconditional(ctx_r1.filterMode === "traditional" ? 21 : -1);
251
353
  } }
252
354
  function ViewConfigPanelComponent_Conditional_25_Conditional_26_Template(rf, ctx) { if (rf & 1) {
253
- const _r15 = i0.ɵɵgetCurrentView();
254
- i0.ɵɵelementStart(0, "div", 75)(1, "div", 21);
255
- i0.ɵɵelement(2, "i", 76);
355
+ const _r17 = i0.ɵɵgetCurrentView();
356
+ i0.ɵɵelementStart(0, "div", 103)(1, "div", 21);
357
+ i0.ɵɵelement(2, "i", 104);
256
358
  i0.ɵɵelementStart(3, "span");
257
359
  i0.ɵɵtext(4, "Danger Zone");
258
360
  i0.ɵɵelementEnd()();
259
- i0.ɵɵelementStart(5, "button", 77);
260
- i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_25_Conditional_26_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDelete()); });
261
- i0.ɵɵelement(6, "i", 78);
361
+ i0.ɵɵelementStart(5, "button", 105);
362
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_25_Conditional_26_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onDelete()); });
363
+ i0.ɵɵelement(6, "i", 106);
262
364
  i0.ɵɵelementStart(7, "span");
263
365
  i0.ɵɵtext(8, "Delete View");
264
366
  i0.ɵɵelementEnd()()();
265
367
  } }
266
368
  function ViewConfigPanelComponent_Conditional_25_Template(rf, ctx) { if (rf & 1) {
267
- const _r14 = i0.ɵɵgetCurrentView();
369
+ const _r16 = i0.ɵɵgetCurrentView();
268
370
  i0.ɵɵelementStart(0, "div", 13)(1, "div", 20)(2, "div", 21);
269
371
  i0.ɵɵelement(3, "i", 50);
270
372
  i0.ɵɵelementStart(4, "span");
271
373
  i0.ɵɵtext(5, "View Details");
272
374
  i0.ɵɵelementEnd()();
273
- i0.ɵɵelementStart(6, "div", 62)(7, "label", 68);
375
+ i0.ɵɵelementStart(6, "div", 94)(7, "label", 95);
274
376
  i0.ɵɵtext(8, "Name");
275
377
  i0.ɵɵelementEnd();
276
- i0.ɵɵelementStart(9, "input", 69);
277
- i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_25_Template_input_ngModelChange_9_listener($event) { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.viewName, $event) || (ctx_r1.viewName = $event); return i0.ɵɵresetView($event); });
378
+ i0.ɵɵelementStart(9, "input", 96);
379
+ i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_25_Template_input_ngModelChange_9_listener($event) { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.viewName, $event) || (ctx_r1.viewName = $event); return i0.ɵɵresetView($event); });
278
380
  i0.ɵɵelementEnd()();
279
- i0.ɵɵelementStart(10, "div", 62)(11, "label", 70);
381
+ i0.ɵɵelementStart(10, "div", 94)(11, "label", 97);
280
382
  i0.ɵɵtext(12, "Description");
281
383
  i0.ɵɵelementEnd();
282
- i0.ɵɵelementStart(13, "textarea", 71);
283
- i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_25_Template_textarea_ngModelChange_13_listener($event) { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.viewDescription, $event) || (ctx_r1.viewDescription = $event); return i0.ɵɵresetView($event); });
384
+ i0.ɵɵelementStart(13, "textarea", 98);
385
+ i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_25_Template_textarea_ngModelChange_13_listener($event) { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.viewDescription, $event) || (ctx_r1.viewDescription = $event); return i0.ɵɵresetView($event); });
284
386
  i0.ɵɵelementEnd()()();
285
387
  i0.ɵɵelementStart(14, "div", 20)(15, "div", 21);
286
- i0.ɵɵelement(16, "i", 72);
388
+ i0.ɵɵelement(16, "i", 99);
287
389
  i0.ɵɵelementStart(17, "span");
288
390
  i0.ɵɵtext(18, "Sharing");
289
391
  i0.ɵɵelementEnd()();
290
- i0.ɵɵelementStart(19, "label", 73)(20, "input", 58);
291
- i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_25_Template_input_ngModelChange_20_listener($event) { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.isShared, $event) || (ctx_r1.isShared = $event); return i0.ɵɵresetView($event); });
392
+ i0.ɵɵelementStart(19, "label", 100)(20, "input", 101);
393
+ i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_25_Template_input_ngModelChange_20_listener($event) { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.isShared, $event) || (ctx_r1.isShared = $event); return i0.ɵɵresetView($event); });
292
394
  i0.ɵɵelementEnd();
293
- i0.ɵɵelementStart(21, "span", 74)(22, "strong");
395
+ i0.ɵɵelementStart(21, "span", 102)(22, "strong");
294
396
  i0.ɵɵtext(23, "Share with others");
295
397
  i0.ɵɵelementEnd();
296
398
  i0.ɵɵelementStart(24, "small");
297
399
  i0.ɵɵtext(25, "Allow other users to use this view");
298
400
  i0.ɵɵelementEnd()()()();
299
- i0.ɵɵtemplate(26, ViewConfigPanelComponent_Conditional_25_Conditional_26_Template, 9, 0, "div", 75);
401
+ i0.ɵɵtemplate(26, ViewConfigPanelComponent_Conditional_25_Conditional_26_Template, 9, 0, "div", 103);
300
402
  i0.ɵɵelementEnd();
301
403
  } if (rf & 2) {
302
404
  const ctx_r1 = i0.ɵɵnextContext();
@@ -313,9 +415,9 @@ function ViewConfigPanelComponent_Conditional_25_Template(rf, ctx) { if (rf & 1)
313
415
  i0.ɵɵconditional(ctx_r1.viewEntity && ctx_r1.canDelete ? 26 : -1);
314
416
  } }
315
417
  function ViewConfigPanelComponent_Conditional_30_Template(rf, ctx) { if (rf & 1) {
316
- const _r16 = i0.ɵɵgetCurrentView();
317
- i0.ɵɵelementStart(0, "button", 79);
318
- i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_30_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSaveAsNew()); });
418
+ const _r18 = i0.ɵɵgetCurrentView();
419
+ i0.ɵɵelementStart(0, "button", 107);
420
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_30_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSaveAsNew()); });
319
421
  i0.ɵɵelement(1, "i", 54);
320
422
  i0.ɵɵtext(2, " Save As New ");
321
423
  i0.ɵɵelementEnd();
@@ -324,10 +426,10 @@ function ViewConfigPanelComponent_Conditional_30_Template(rf, ctx) { if (rf & 1)
324
426
  i0.ɵɵproperty("disabled", ctx_r1.isSaving);
325
427
  } }
326
428
  function ViewConfigPanelComponent_Conditional_31_Template(rf, ctx) { if (rf & 1) {
327
- const _r17 = i0.ɵɵgetCurrentView();
328
- i0.ɵɵelementStart(0, "button", 80);
329
- i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_31_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSave()); });
330
- i0.ɵɵelement(1, "i", 81);
429
+ const _r19 = i0.ɵɵgetCurrentView();
430
+ i0.ɵɵelementStart(0, "button", 108);
431
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_31_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSave()); });
432
+ i0.ɵɵelement(1, "i", 109);
331
433
  i0.ɵɵtext(2, " Save ");
332
434
  i0.ɵɵelementEnd();
333
435
  } if (rf & 2) {
@@ -335,10 +437,10 @@ function ViewConfigPanelComponent_Conditional_31_Template(rf, ctx) { if (rf & 1)
335
437
  i0.ɵɵproperty("disabled", ctx_r1.isSaving || !ctx_r1.viewName);
336
438
  } }
337
439
  function ViewConfigPanelComponent_Conditional_32_Template(rf, ctx) { if (rf & 1) {
338
- const _r18 = i0.ɵɵgetCurrentView();
339
- i0.ɵɵelementStart(0, "button", 80);
340
- i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_32_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSaveAsNew()); });
341
- i0.ɵɵelement(1, "i", 81);
440
+ const _r20 = i0.ɵɵgetCurrentView();
441
+ i0.ɵɵelementStart(0, "button", 108);
442
+ i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_32_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSaveAsNew()); });
443
+ i0.ɵɵelement(1, "i", 109);
342
444
  i0.ɵɵtext(2, " Create View ");
343
445
  i0.ɵɵelementEnd();
344
446
  } if (rf & 2) {
@@ -386,6 +488,14 @@ export class ViewConfigPanelComponent {
386
488
  * Emitted when the view should be deleted
387
489
  */
388
490
  delete = new EventEmitter();
491
+ /**
492
+ * Emitted when filter dialog should be opened (at dashboard level for full width)
493
+ */
494
+ openFilterDialogRequest = new EventEmitter();
495
+ /**
496
+ * Filter state from external dialog (set by parent after dialog closes)
497
+ */
498
+ externalFilterState = null;
389
499
  // Form state
390
500
  viewName = '';
391
501
  viewDescription = '';
@@ -397,6 +507,11 @@ export class ViewConfigPanelComponent {
397
507
  smartFilterEnabled = false;
398
508
  smartFilterPrompt = '';
399
509
  smartFilterExplanation = '';
510
+ // Traditional Filter state
511
+ filterState = createEmptyFilter();
512
+ filterFields = [];
513
+ // Filter mode: 'smart' or 'traditional' (mutually exclusive)
514
+ filterMode = 'smart';
400
515
  // UI state
401
516
  activeTab = 'columns';
402
517
  isSaving = false;
@@ -420,9 +535,19 @@ export class ViewConfigPanelComponent {
420
535
  this.initializeFromEntity();
421
536
  }
422
537
  ngOnChanges(changes) {
538
+ // Reset to first tab and clear search when panel opens
539
+ if (changes['isOpen'] && this.isOpen) {
540
+ this.activeTab = 'columns';
541
+ this.columnSearchText = '';
542
+ }
423
543
  if (changes['entity'] || changes['viewEntity'] || changes['currentGridState']) {
424
544
  this.initializeFromEntity();
425
545
  }
546
+ // Apply external filter state when it changes (from dashboard-level dialog)
547
+ if (changes['externalFilterState'] && this.externalFilterState) {
548
+ this.filterState = this.externalFilterState;
549
+ this.cdr.detectChanges();
550
+ }
426
551
  }
427
552
  /**
428
553
  * Initialize form state from entity and view
@@ -479,6 +604,8 @@ export class ViewConfigPanelComponent {
479
604
  this.sortDirection = sortInfo[0].direction === 'Desc' ? 'desc' : 'asc';
480
605
  }
481
606
  }
607
+ // Initialize filter fields from entity
608
+ this.filterFields = this.buildFilterFields();
482
609
  // Apply view entity metadata (name, description, etc.) if available
483
610
  if (this.viewEntity) {
484
611
  this.viewName = this.viewEntity.Name;
@@ -488,6 +615,20 @@ export class ViewConfigPanelComponent {
488
615
  this.smartFilterEnabled = this.viewEntity.SmartFilterEnabled || false;
489
616
  this.smartFilterPrompt = this.viewEntity.SmartFilterPrompt || '';
490
617
  this.smartFilterExplanation = this.viewEntity.SmartFilterExplanation || '';
618
+ // Apply view's traditional filter state
619
+ this.filterState = this.parseFilterState(this.viewEntity.FilterState);
620
+ // Set filter mode based on which type of filter is active
621
+ // Smart filter takes precedence if enabled
622
+ if (this.smartFilterEnabled && this.smartFilterPrompt) {
623
+ this.filterMode = 'smart';
624
+ }
625
+ else if (this.getFilterCount() > 0) {
626
+ this.filterMode = 'traditional';
627
+ }
628
+ else {
629
+ // Default to smart mode for new/empty filters (promote AI filtering)
630
+ this.filterMode = 'smart';
631
+ }
491
632
  }
492
633
  else {
493
634
  // Default view - use entity defaults
@@ -501,7 +642,124 @@ export class ViewConfigPanelComponent {
501
642
  this.smartFilterEnabled = false;
502
643
  this.smartFilterPrompt = '';
503
644
  this.smartFilterExplanation = '';
645
+ this.filterState = createEmptyFilter();
646
+ // Default to smart mode (promote AI filtering)
647
+ this.filterMode = 'smart';
648
+ }
649
+ this.cdr.detectChanges();
650
+ }
651
+ /**
652
+ * Build filter fields from entity fields
653
+ */
654
+ buildFilterFields() {
655
+ if (!this.entity)
656
+ return [];
657
+ return this.entity.Fields
658
+ .filter(f => !f.Name.startsWith('__mj_') && !f.IsBinaryFieldType)
659
+ .map(field => ({
660
+ name: field.Name,
661
+ displayName: field.DisplayNameOrName,
662
+ type: this.mapFieldType(field),
663
+ lookupEntityName: field.RelatedEntity || undefined,
664
+ valueList: field.ValueListType === 'List' && field.EntityFieldValues?.length > 0
665
+ ? field.EntityFieldValues.map(v => ({ value: v.Value, label: v.Value }))
666
+ : undefined
667
+ }));
668
+ }
669
+ /**
670
+ * Map entity field type to filter field type
671
+ */
672
+ mapFieldType(field) {
673
+ // Check for lookup first - RelatedEntity is a string (entity name) if it's a lookup field
674
+ if (field.RelatedEntity) {
675
+ return 'lookup';
676
+ }
677
+ // Map based on SQL type
678
+ const sqlType = field.Type.toLowerCase();
679
+ if (sqlType.includes('bit') || sqlType === 'boolean') {
680
+ return 'boolean';
681
+ }
682
+ if (sqlType.includes('date') || sqlType.includes('time')) {
683
+ return 'date';
684
+ }
685
+ if (sqlType.includes('int') || sqlType.includes('decimal') ||
686
+ sqlType.includes('numeric') || sqlType.includes('float') ||
687
+ sqlType.includes('real') || sqlType.includes('money')) {
688
+ return 'number';
689
+ }
690
+ return 'string';
691
+ }
692
+ /**
693
+ * Parse the filter state from JSON string
694
+ */
695
+ parseFilterState(filterStateJson) {
696
+ if (!filterStateJson) {
697
+ return createEmptyFilter();
698
+ }
699
+ try {
700
+ const parsed = JSON.parse(filterStateJson);
701
+ // Validate it has the expected structure
702
+ if (parsed && typeof parsed === 'object' && 'logic' in parsed && 'filters' in parsed) {
703
+ return parsed;
704
+ }
705
+ return createEmptyFilter();
706
+ }
707
+ catch {
708
+ return createEmptyFilter();
709
+ }
710
+ }
711
+ /**
712
+ * Handle filter state change from filter builder
713
+ */
714
+ onFilterChange(filter) {
715
+ this.filterState = filter;
716
+ this.cdr.detectChanges();
717
+ }
718
+ /**
719
+ * Open the filter dialog - emits event to parent (dashboard) which renders the dialog at viewport level
720
+ */
721
+ openFilterDialog() {
722
+ this.openFilterDialogRequest.emit({
723
+ filterState: this.filterState,
724
+ filterFields: this.filterFields
725
+ });
726
+ }
727
+ /**
728
+ * Get the count of active filter rules
729
+ */
730
+ getFilterCount() {
731
+ return this.countFilters(this.filterState);
732
+ }
733
+ /**
734
+ * Count filters recursively
735
+ */
736
+ countFilters(filter) {
737
+ let count = 0;
738
+ for (const item of filter.filters || []) {
739
+ if ('logic' in item && 'filters' in item) {
740
+ count += this.countFilters(item);
741
+ }
742
+ else if ('field' in item) {
743
+ count++;
744
+ }
504
745
  }
746
+ return count;
747
+ }
748
+ /**
749
+ * Get a human-readable summary of the filter state
750
+ */
751
+ getFilterSummary() {
752
+ const count = this.getFilterCount();
753
+ if (count === 0) {
754
+ return 'No filters applied';
755
+ }
756
+ return `${count} filter${count !== 1 ? 's' : ''} active`;
757
+ }
758
+ /**
759
+ * Clear all filters
760
+ */
761
+ clearFilters() {
762
+ this.filterState = createEmptyFilter();
505
763
  this.cdr.detectChanges();
506
764
  }
507
765
  /**
@@ -674,6 +932,12 @@ export class ViewConfigPanelComponent {
674
932
  onClose() {
675
933
  this.close.emit();
676
934
  }
935
+ /**
936
+ * Check if filter state has any active filters
937
+ */
938
+ hasActiveFilters() {
939
+ return this.filterState?.filters?.length > 0;
940
+ }
677
941
  /**
678
942
  * Save the view
679
943
  */
@@ -687,7 +951,8 @@ export class ViewConfigPanelComponent {
687
951
  sortField: this.sortField,
688
952
  sortDirection: this.sortDirection,
689
953
  smartFilterEnabled: this.smartFilterEnabled,
690
- smartFilterPrompt: this.smartFilterPrompt
954
+ smartFilterPrompt: this.smartFilterPrompt,
955
+ filterState: this.hasActiveFilters() ? this.filterState : null
691
956
  });
692
957
  }
693
958
  /**
@@ -703,7 +968,8 @@ export class ViewConfigPanelComponent {
703
968
  sortField: this.sortField,
704
969
  sortDirection: this.sortDirection,
705
970
  smartFilterEnabled: this.smartFilterEnabled,
706
- smartFilterPrompt: this.smartFilterPrompt
971
+ smartFilterPrompt: this.smartFilterPrompt,
972
+ filterState: this.hasActiveFilters() ? this.filterState : null
707
973
  });
708
974
  }
709
975
  /**
@@ -721,10 +987,38 @@ export class ViewConfigPanelComponent {
721
987
  this.activeTab = tab;
722
988
  this.cdr.detectChanges();
723
989
  }
990
+ /**
991
+ * Set the filter mode (smart or traditional)
992
+ * When switching modes, clear the other mode's settings
993
+ */
994
+ setFilterMode(mode) {
995
+ if (this.filterMode === mode)
996
+ return;
997
+ this.filterMode = mode;
998
+ // When switching to smart mode, clear traditional filters and enable smart filter
999
+ if (mode === 'smart') {
1000
+ this.smartFilterEnabled = true;
1001
+ this.filterState = createEmptyFilter();
1002
+ }
1003
+ // When switching to traditional mode, disable smart filter and clear its prompt
1004
+ else {
1005
+ this.smartFilterEnabled = false;
1006
+ this.smartFilterPrompt = '';
1007
+ this.smartFilterExplanation = '';
1008
+ }
1009
+ this.cdr.detectChanges();
1010
+ }
1011
+ /**
1012
+ * Apply a smart filter example to the prompt field
1013
+ */
1014
+ applySmartFilterExample(example) {
1015
+ this.smartFilterPrompt = example;
1016
+ this.cdr.detectChanges();
1017
+ }
724
1018
  static ɵfac = function ViewConfigPanelComponent_Factory(t) { return new (t || ViewConfigPanelComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
725
1019
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ViewConfigPanelComponent, selectors: [["mj-view-config-panel"]], hostBindings: function ViewConfigPanelComponent_HostBindings(rf, ctx) { if (rf & 1) {
726
1020
  i0.ɵɵlistener("keydown.escape", function ViewConfigPanelComponent_keydown_escape_HostBindingHandler() { return ctx.handleEscape(); }, false, i0.ɵɵresolveDocument);
727
- } }, inputs: { entity: "entity", viewEntity: "viewEntity", isOpen: "isOpen", currentGridState: "currentGridState" }, outputs: { close: "close", save: "save", delete: "delete" }, features: [i0.ɵɵNgOnChangesFeature], decls: 33, vars: 16, consts: [[1, "panel-backdrop"], [1, "config-panel"], [1, "panel-header"], [1, "header-title"], [1, "fa-solid", "fa-sliders-h"], ["title", "Close", 1, "close-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "tab-nav"], [1, "tab-btn", 3, "click"], [1, "fa-solid", "fa-columns"], [1, "fa-solid", "fa-filter"], [1, "fa-solid", "fa-cog"], [1, "panel-content"], [1, "tab-content"], [1, "panel-footer"], [1, "footer-btn", "cancel-btn", 3, "click"], [1, "footer-right"], [1, "footer-btn", "save-as-btn", 3, "disabled"], [1, "footer-btn", "save-btn", "primary", 3, "disabled"], [1, "panel-backdrop", 3, "click"], [1, "config-section"], [1, "section-header"], [1, "fa-solid", "fa-sort"], [1, "sort-config"], [1, "sort-field-select", 3, "ngModelChange", "ngModel"], [3, "value"], [1, "sort-direction-toggle"], [1, "fa-solid", "fa-eye"], [1, "column-count"], [1, "column-list", "visible-columns"], ["draggable", "true", 1, "column-item"], [1, "empty-list"], [1, "fa-solid", "fa-eye-slash"], [1, "column-search"], [1, "column-list", "hidden-columns"], [1, "column-item", "hidden"], ["title", "Ascending", 1, "direction-btn", 3, "click"], [1, "fa-solid", "fa-arrow-up"], ["title", "Descending", 1, "direction-btn", 3, "click"], [1, "fa-solid", "fa-arrow-down"], ["draggable", "true", 1, "column-item", 3, "dragstart", "dragover", "drop", "dragend"], [1, "drag-handle"], [1, "fa-solid", "fa-grip-vertical"], [1, "column-name"], [1, "column-actions"], ["title", "Move up", 1, "action-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-up"], ["title", "Move down", 1, "action-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-down"], ["title", "Hide column", 1, "action-btn", "hide-btn", 3, "click"], [1, "fa-solid", "fa-info-circle"], [1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Search columns...", 3, "ngModelChange", "ngModel"], ["title", "Show column", 1, "action-btn", "show-btn", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "fa-solid", "fa-check-circle"], [1, "fa-solid", "fa-magic"], [1, "smart-filter-toggle"], ["type", "checkbox", 3, "ngModelChange", "ngModel", "disabled"], [1, "toggle-label"], [1, "smart-filter-disabled-message"], [1, "filters-placeholder"], [1, "form-group"], ["for", "smartFilterPrompt"], ["id", "smartFilterPrompt", "placeholder", "Describe what records you want to see... e.g., 'Show me all records created this month' or 'Active customers with high revenue'", "rows", "3", 1, "form-input", "form-textarea", "smart-filter-textarea", 3, "ngModelChange", "ngModel", "disabled"], [1, "smart-filter-explanation"], [1, "tip"], [1, "fa-solid", "fa-lightbulb"], ["for", "viewName"], ["id", "viewName", "type", "text", "placeholder", "Enter view name...", 1, "form-input", 3, "ngModelChange", "ngModel", "disabled"], ["for", "viewDescription"], ["id", "viewDescription", "placeholder", "Describe this view...", "rows", "3", 1, "form-input", "form-textarea", 3, "ngModelChange", "ngModel", "disabled"], [1, "fa-solid", "fa-share-alt"], [1, "checkbox-label"], [1, "checkbox-text"], [1, "config-section", "danger-zone"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "delete-btn", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "footer-btn", "save-as-btn", 3, "click", "disabled"], [1, "footer-btn", "save-btn", "primary", 3, "click", "disabled"], [1, "fa-solid", "fa-save"]], template: function ViewConfigPanelComponent_Template(rf, ctx) { if (rf & 1) {
1021
+ } }, inputs: { entity: "entity", viewEntity: "viewEntity", isOpen: "isOpen", currentGridState: "currentGridState", externalFilterState: "externalFilterState" }, outputs: { close: "close", save: "save", delete: "delete", openFilterDialogRequest: "openFilterDialogRequest" }, features: [i0.ɵɵNgOnChangesFeature], decls: 33, vars: 16, consts: [[1, "panel-backdrop"], [1, "config-panel"], [1, "panel-header"], [1, "header-title"], [1, "fa-solid", "fa-sliders-h"], ["title", "Close", 1, "close-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "tab-nav"], [1, "tab-btn", 3, "click"], [1, "fa-solid", "fa-columns"], [1, "fa-solid", "fa-filter"], [1, "fa-solid", "fa-cog"], [1, "panel-content"], [1, "tab-content"], [1, "panel-footer"], [1, "footer-btn", "cancel-btn", 3, "click"], [1, "footer-right"], [1, "footer-btn", "save-as-btn", 3, "disabled"], [1, "footer-btn", "save-btn", "primary", 3, "disabled"], [1, "panel-backdrop", 3, "click"], [1, "config-section"], [1, "section-header"], [1, "fa-solid", "fa-sort"], [1, "sort-config"], [1, "sort-field-select", 3, "ngModelChange", "ngModel"], [3, "value"], [1, "sort-direction-toggle"], [1, "fa-solid", "fa-eye"], [1, "column-count"], [1, "column-list", "visible-columns"], ["draggable", "true", 1, "column-item"], [1, "empty-list"], [1, "fa-solid", "fa-eye-slash"], [1, "column-search"], [1, "column-list", "hidden-columns"], [1, "column-item", "hidden"], ["title", "Ascending", 1, "direction-btn", 3, "click"], [1, "fa-solid", "fa-arrow-up"], ["title", "Descending", 1, "direction-btn", 3, "click"], [1, "fa-solid", "fa-arrow-down"], ["draggable", "true", 1, "column-item", 3, "dragstart", "dragover", "drop", "dragend"], [1, "drag-handle"], [1, "fa-solid", "fa-grip-vertical"], [1, "column-name"], [1, "column-actions"], ["title", "Move up", 1, "action-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-up"], ["title", "Move down", 1, "action-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-down"], ["title", "Hide column", 1, "action-btn", "hide-btn", 3, "click"], [1, "fa-solid", "fa-info-circle"], [1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Search columns...", 3, "ngModelChange", "ngModel"], ["title", "Show column", 1, "action-btn", "show-btn", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "fa-solid", "fa-check-circle"], [1, "filter-mode-selector"], [1, "filter-mode-btn", 3, "click", "disabled"], [1, "mode-icon"], [1, "fa-solid", "fa-wand-magic-sparkles"], [1, "mode-content"], [1, "mode-title"], [1, "mode-subtitle"], [1, "fa-solid", "fa-check", "mode-check"], [1, "fa-solid", "fa-sliders"], [1, "config-section", "smart-filter-section"], [1, "config-section", "traditional-filter-section"], [1, "smart-filter-input-container"], [1, "smart-filter-icon"], ["id", "smartFilterPrompt", "placeholder", "Describe what you're looking for...", "rows", "3", 1, "smart-filter-textarea", 3, "ngModelChange", "ngModel", "disabled"], [1, "smart-filter-explanation"], [1, "smart-filter-examples"], [1, "examples-header"], [1, "fa-solid", "fa-lightbulb"], [1, "example-chips"], [1, "example-chip", 3, "click", "disabled"], [1, "fa-regular", "fa-calendar"], [1, "fa-solid", "fa-circle-check"], [1, "fa-solid", "fa-star"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "smart-filter-tip"], [1, "fa-solid", "fa-robot"], [1, "filter-summary-container"], [1, "filter-summary"], [1, "summary-info"], [1, "summary-text", "no-filters"], [1, "summary-actions"], ["title", "Clear all filters", 1, "summary-btn", "clear-btn"], ["title", "Edit filters", 1, "summary-btn", "edit-btn", "primary", 3, "click", "disabled"], [1, "fa-solid", "fa-pen"], [1, "traditional-filter-tip"], [1, "filter-badge"], [1, "summary-text"], ["title", "Clear all filters", 1, "summary-btn", "clear-btn", 3, "click"], [1, "form-group"], ["for", "viewName"], ["id", "viewName", "type", "text", "placeholder", "Enter view name...", 1, "form-input", 3, "ngModelChange", "ngModel", "disabled"], ["for", "viewDescription"], ["id", "viewDescription", "placeholder", "Describe this view...", "rows", "3", 1, "form-input", "form-textarea", 3, "ngModelChange", "ngModel", "disabled"], [1, "fa-solid", "fa-share-alt"], [1, "checkbox-label"], ["type", "checkbox", 3, "ngModelChange", "ngModel", "disabled"], [1, "checkbox-text"], [1, "config-section", "danger-zone"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "delete-btn", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "footer-btn", "save-as-btn", 3, "click", "disabled"], [1, "footer-btn", "save-btn", "primary", 3, "click", "disabled"], [1, "fa-solid", "fa-save"]], template: function ViewConfigPanelComponent_Template(rf, ctx) { if (rf & 1) {
728
1022
  i0.ɵɵtemplate(0, ViewConfigPanelComponent_Conditional_0_Template, 1, 0, "div", 0);
729
1023
  i0.ɵɵelementStart(1, "div", 1)(2, "div", 2)(3, "div", 3);
730
1024
  i0.ɵɵelement(4, "i", 4);
@@ -754,7 +1048,7 @@ export class ViewConfigPanelComponent {
754
1048
  i0.ɵɵtext(21, "Settings");
755
1049
  i0.ɵɵelementEnd()()();
756
1050
  i0.ɵɵelementStart(22, "div", 12);
757
- i0.ɵɵtemplate(23, ViewConfigPanelComponent_Conditional_23_Template, 36, 8, "div", 13)(24, ViewConfigPanelComponent_Conditional_24_Template, 21, 4, "div", 13)(25, ViewConfigPanelComponent_Conditional_25_Template, 27, 7, "div", 13);
1051
+ i0.ɵɵtemplate(23, ViewConfigPanelComponent_Conditional_23_Template, 36, 8, "div", 13)(24, ViewConfigPanelComponent_Conditional_24_Template, 22, 10, "div", 13)(25, ViewConfigPanelComponent_Conditional_25_Template, 27, 7, "div", 13);
758
1052
  i0.ɵɵelementEnd();
759
1053
  i0.ɵɵelementStart(26, "div", 14)(27, "button", 15);
760
1054
  i0.ɵɵlistener("click", function ViewConfigPanelComponent_Template_button_click_27_listener() { return ctx.onClose(); });
@@ -787,11 +1081,11 @@ export class ViewConfigPanelComponent {
787
1081
  i0.ɵɵconditional(ctx.viewEntity && ctx.canEdit ? 31 : -1);
788
1082
  i0.ɵɵadvance();
789
1083
  i0.ɵɵconditional(!ctx.viewEntity ? 32 : -1);
790
- } }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.CheckboxControlValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.NgModel], styles: ["\n\n.panel-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 1000;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n\n\n.config-panel[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: 0;\n width: 400px;\n max-width: 100vw;\n height: 100%;\n background: white;\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.25s ease;\n}\n\n.config-panel.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid #e0e0e0;\n background: #fafafa;\n flex-shrink: 0;\n}\n\n.header-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n}\n\n.header-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #1976d2;\n}\n\n.close-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n color: #666;\n transition: all 0.15s ease;\n}\n\n.close-btn[_ngcontent-%COMP%]:hover {\n background: #e0e0e0;\n color: #333;\n}\n\n\n\n.tab-nav[_ngcontent-%COMP%] {\n display: flex;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n}\n\n.tab-btn[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 16px;\n border: none;\n background: transparent;\n color: #666;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n border-bottom: 2px solid transparent;\n}\n\n.tab-btn[_ngcontent-%COMP%]:hover {\n background: #f5f5f5;\n color: #333;\n}\n\n.tab-btn.active[_ngcontent-%COMP%] {\n color: #1976d2;\n border-bottom-color: #1976d2;\n background: transparent;\n}\n\n.tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.tab-content[_ngcontent-%COMP%] {\n padding: 0 20px;\n}\n\n\n\n.config-section[_ngcontent-%COMP%] {\n margin-bottom: 24px;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: #333;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #1976d2;\n font-size: 12px;\n}\n\n.column-count[_ngcontent-%COMP%] {\n margin-left: auto;\n background: #e3f2fd;\n color: #1976d2;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n}\n\n\n\n.sort-config[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.sort-field-select[_ngcontent-%COMP%] {\n flex: 1;\n padding: 10px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n background: white;\n cursor: pointer;\n}\n\n.sort-field-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #1976d2;\n}\n\n.sort-direction-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 2px;\n}\n\n.direction-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #666;\n transition: all 0.15s ease;\n}\n\n.direction-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n}\n\n.direction-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n\n\n.column-list[_ngcontent-%COMP%] {\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n background: #fafafa;\n}\n\n.column-list.hidden-columns[_ngcontent-%COMP%] {\n max-height: 200px;\n overflow-y: auto;\n}\n\n.column-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: white;\n border-bottom: 1px solid #f0f0f0;\n transition: background 0.1s ease;\n}\n\n.column-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.column-item[_ngcontent-%COMP%]:hover {\n background: #f5f7fa;\n}\n\n.column-item.hidden[_ngcontent-%COMP%] {\n background: #fafafa;\n}\n\n.column-item.hidden[_ngcontent-%COMP%]:hover {\n background: #f0f0f0;\n}\n\n.drag-handle[_ngcontent-%COMP%] {\n cursor: grab;\n color: #999;\n padding: 4px;\n}\n\n.drag-handle[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.column-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n color: #333;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.column-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #999;\n transition: all 0.15s ease;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #e0e0e0;\n color: #333;\n}\n\n.action-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.action-btn.hide-btn[_ngcontent-%COMP%]:hover {\n background: #ffebee;\n color: #c62828;\n}\n\n.action-btn.show-btn[_ngcontent-%COMP%]:hover {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.empty-list[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: #999;\n font-size: 13px;\n}\n\n\n\n.column-search[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n margin-bottom: 8px;\n}\n\n.column-search[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #999;\n font-size: 12px;\n}\n\n.column-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n outline: none;\n font-size: 14px;\n}\n\n\n\n.filters-placeholder[_ngcontent-%COMP%] {\n text-align: center;\n padding: 32px 20px;\n background: #f5f7fa;\n border-radius: 8px;\n}\n\n.filters-placeholder[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n color: #1976d2;\n margin-bottom: 16px;\n}\n\n.filters-placeholder[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 16px;\n color: #333;\n}\n\n.filters-placeholder[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: #666;\n line-height: 1.5;\n}\n\n.tip[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 12px;\n background: #fff8e1;\n border-radius: 6px;\n font-size: 12px;\n color: #795548;\n text-align: left;\n}\n\n.tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #ffc107;\n font-size: 14px;\n margin-top: 1px;\n}\n\n\n\n.smart-filter-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n cursor: pointer;\n}\n\n.smart-filter-toggle[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.smart-filter-toggle[_ngcontent-%COMP%] .toggle-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: #666;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.smart-filter-textarea[_ngcontent-%COMP%] {\n min-height: 100px;\n font-family: inherit;\n line-height: 1.5;\n}\n\n.smart-filter-explanation[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 12px;\n background: #e3f2fd;\n border-radius: 6px;\n margin-bottom: 12px;\n font-size: 13px;\n color: #1565c0;\n}\n\n.smart-filter-explanation[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #1976d2;\n font-size: 14px;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.smart-filter-disabled-message[_ngcontent-%COMP%] {\n padding: 16px;\n background: #f5f7fa;\n border-radius: 6px;\n text-align: center;\n}\n\n.smart-filter-disabled-message[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.5;\n}\n\n\n\n.form-group[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.form-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 500;\n color: #333;\n}\n\n.form-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n transition: border-color 0.15s ease;\n}\n\n.form-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #1976d2;\n}\n\n.form-input[_ngcontent-%COMP%]:disabled {\n background: #f5f5f5;\n color: #999;\n}\n\n.form-textarea[_ngcontent-%COMP%] {\n resize: vertical;\n min-height: 80px;\n}\n\n\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n cursor: pointer;\n}\n\n.checkbox-label[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n margin-top: 2px;\n cursor: pointer;\n}\n\n.checkbox-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #333;\n}\n\n.checkbox-text[_ngcontent-%COMP%] small[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #666;\n}\n\n\n\n.danger-zone[_ngcontent-%COMP%] {\n padding-top: 16px;\n border-top: 1px solid #ffcdd2;\n}\n\n.danger-zone[_ngcontent-%COMP%] .section-header[_ngcontent-%COMP%] {\n color: #c62828;\n}\n\n.danger-zone[_ngcontent-%COMP%] .section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #c62828;\n}\n\n.delete-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n padding: 10px 16px;\n border: 1px solid #c62828;\n background: transparent;\n border-radius: 6px;\n color: #c62828;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.delete-btn[_ngcontent-%COMP%]:hover {\n background: #c62828;\n color: white;\n}\n\n\n\n.panel-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-top: 1px solid #e0e0e0;\n background: #fafafa;\n flex-shrink: 0;\n}\n\n.footer-right[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.footer-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px 16px;\n border: 1px solid #e0e0e0;\n background: white;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.footer-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #f0f0f0;\n border-color: #ccc;\n}\n\n.footer-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.footer-btn.primary[_ngcontent-%COMP%] {\n background: #1976d2;\n border-color: #1976d2;\n color: white;\n}\n\n.footer-btn.primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #1565c0;\n border-color: #1565c0;\n}\n\n.footer-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n@media (max-width: 768px) {\n .config-panel[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .tab-btn[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: none;\n }\n\n .tab-btn[_ngcontent-%COMP%] {\n padding: 14px;\n }\n\n .tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n}"] });
1084
+ } }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.CheckboxControlValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.NgModel], styles: ["\n\n.panel-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 1000;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n\n\n.config-panel[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n right: 0;\n width: 400px;\n max-width: 100vw;\n height: 100%;\n background: white;\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.25s ease;\n}\n\n.config-panel.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid #e0e0e0;\n background: #fafafa;\n flex-shrink: 0;\n}\n\n.header-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n}\n\n.header-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #1976d2;\n}\n\n.close-btn[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n color: #666;\n transition: all 0.15s ease;\n}\n\n.close-btn[_ngcontent-%COMP%]:hover {\n background: #e0e0e0;\n color: #333;\n}\n\n\n\n.tab-nav[_ngcontent-%COMP%] {\n display: flex;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n}\n\n.tab-btn[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 16px;\n border: none;\n background: transparent;\n color: #666;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n border-bottom: 2px solid transparent;\n}\n\n.tab-btn[_ngcontent-%COMP%]:hover {\n background: #f5f5f5;\n color: #333;\n}\n\n.tab-btn.active[_ngcontent-%COMP%] {\n color: #1976d2;\n border-bottom-color: #1976d2;\n background: transparent;\n}\n\n.tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n padding: 16px 0;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.tab-content[_ngcontent-%COMP%] {\n padding: 0 20px;\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow-y: auto;\n}\n\n\n\n.config-section[_ngcontent-%COMP%] {\n margin-bottom: 24px;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: #333;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #1976d2;\n font-size: 12px;\n}\n\n.column-count[_ngcontent-%COMP%] {\n margin-left: auto;\n background: #e3f2fd;\n color: #1976d2;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n}\n\n\n\n.sort-config[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.sort-field-select[_ngcontent-%COMP%] {\n flex: 1;\n padding: 10px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n background: white;\n cursor: pointer;\n}\n\n.sort-field-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #1976d2;\n}\n\n.sort-direction-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 2px;\n}\n\n.direction-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #666;\n transition: all 0.15s ease;\n}\n\n.direction-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n}\n\n.direction-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n\n\n.column-list[_ngcontent-%COMP%] {\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n background: #fafafa;\n}\n\n.column-list.visible-columns[_ngcontent-%COMP%] {\n max-height: 300px;\n overflow-y: auto;\n}\n\n.column-list.hidden-columns[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 100px;\n overflow-y: auto;\n}\n\n\n\n.config-section[_ngcontent-%COMP%]:last-child {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n margin-bottom: 0;\n}\n\n.column-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: white;\n border-bottom: 1px solid #f0f0f0;\n transition: background 0.1s ease;\n}\n\n.column-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.column-item[_ngcontent-%COMP%]:hover {\n background: #f5f7fa;\n}\n\n.column-item.hidden[_ngcontent-%COMP%] {\n background: #fafafa;\n}\n\n.column-item.hidden[_ngcontent-%COMP%]:hover {\n background: #f0f0f0;\n}\n\n.drag-handle[_ngcontent-%COMP%] {\n cursor: grab;\n color: #999;\n padding: 4px;\n}\n\n.drag-handle[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.column-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n color: #333;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.column-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #999;\n transition: all 0.15s ease;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #e0e0e0;\n color: #333;\n}\n\n.action-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.action-btn.hide-btn[_ngcontent-%COMP%]:hover {\n background: #ffebee;\n color: #c62828;\n}\n\n.action-btn.show-btn[_ngcontent-%COMP%]:hover {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.empty-list[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: #999;\n font-size: 13px;\n}\n\n\n\n.column-search[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n margin-bottom: 8px;\n}\n\n.column-search[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #999;\n font-size: 12px;\n}\n\n.column-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n outline: none;\n font-size: 14px;\n}\n\n\n\n.filter-summary-container[_ngcontent-%COMP%] {\n padding: 4px 0;\n}\n\n.filter-summary[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: #f5f7fa;\n border-radius: 8px;\n border: 1px solid #e8e8e8;\n}\n\n.summary-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.filter-badge[_ngcontent-%COMP%] {\n background: #1976d2;\n color: white;\n font-size: 12px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n min-width: 20px;\n text-align: center;\n}\n\n.summary-text[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #333;\n}\n\n.summary-text.no-filters[_ngcontent-%COMP%] {\n color: #999;\n}\n\n.summary-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.summary-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 6px 12px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.summary-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.summary-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.summary-btn.clear-btn[_ngcontent-%COMP%] {\n background: transparent;\n color: #c62828;\n border: 1px solid #e0e0e0;\n}\n\n.summary-btn.clear-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #ffebee;\n border-color: #c62828;\n}\n\n.summary-btn.edit-btn[_ngcontent-%COMP%] {\n background: #1976d2;\n color: white;\n}\n\n.summary-btn.edit-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #1565c0;\n}\n\n\n\n.filters-placeholder[_ngcontent-%COMP%] {\n text-align: center;\n padding: 32px 20px;\n background: #f5f7fa;\n border-radius: 8px;\n}\n\n.filters-placeholder[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n color: #1976d2;\n margin-bottom: 16px;\n}\n\n.filters-placeholder[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 16px;\n color: #333;\n}\n\n.filters-placeholder[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: #666;\n line-height: 1.5;\n}\n\n.tip[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 12px;\n background: #fff8e1;\n border-radius: 6px;\n font-size: 12px;\n color: #795548;\n text-align: left;\n}\n\n.tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #ffc107;\n font-size: 14px;\n margin-top: 1px;\n}\n\n\n\n.smart-filter-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n cursor: pointer;\n}\n\n.smart-filter-toggle[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.smart-filter-toggle[_ngcontent-%COMP%] .toggle-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: #666;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.smart-filter-textarea[_ngcontent-%COMP%] {\n min-height: 100px;\n font-family: inherit;\n line-height: 1.5;\n}\n\n.smart-filter-explanation[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 12px;\n background: #e3f2fd;\n border-radius: 6px;\n margin-bottom: 12px;\n font-size: 13px;\n color: #1565c0;\n}\n\n.smart-filter-explanation[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #1976d2;\n font-size: 14px;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.smart-filter-disabled-message[_ngcontent-%COMP%] {\n padding: 16px;\n background: #f5f7fa;\n border-radius: 6px;\n text-align: center;\n}\n\n.smart-filter-disabled-message[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.5;\n}\n\n\n\n\n\n\n.filter-mode-selector[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.filter-mode-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 14px 16px;\n border: 2px solid #e5e7eb;\n border-radius: 12px;\n background: white;\n cursor: pointer;\n transition: all 0.2s ease;\n text-align: left;\n}\n\n.filter-mode-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: #d1d5db;\n background: #f9fafb;\n}\n\n.filter-mode-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.filter-mode-btn.active[_ngcontent-%COMP%] {\n border-color: #3b82f6;\n background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);\n}\n\n.filter-mode-btn[_ngcontent-%COMP%] .mode-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n background: #f3f4f6;\n color: #6b7280;\n font-size: 16px;\n flex-shrink: 0;\n transition: all 0.2s ease;\n}\n\n.filter-mode-btn.active[_ngcontent-%COMP%] .mode-icon[_ngcontent-%COMP%] {\n background: #3b82f6;\n color: white;\n}\n\n.filter-mode-btn[_ngcontent-%COMP%] .mode-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.filter-mode-btn[_ngcontent-%COMP%] .mode-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: #1f2937;\n}\n\n.filter-mode-btn[_ngcontent-%COMP%] .mode-subtitle[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #6b7280;\n}\n\n.filter-mode-btn.active[_ngcontent-%COMP%] .mode-title[_ngcontent-%COMP%] {\n color: #1d4ed8;\n}\n\n.filter-mode-btn[_ngcontent-%COMP%] .mode-check[_ngcontent-%COMP%] {\n color: #3b82f6;\n font-size: 16px;\n flex-shrink: 0;\n}\n\n\n\n\n\n\n.smart-filter-section[_ngcontent-%COMP%] {\n padding: 0;\n border: none;\n background: transparent;\n}\n\n.smart-filter-input-container[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 16px;\n background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);\n border: 1px solid #bae6fd;\n border-radius: 12px;\n margin-bottom: 16px;\n}\n\n.smart-filter-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #3b82f6 0%, #6366f1 100%);\n border-radius: 10px;\n color: white;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.smart-filter-input-container[_ngcontent-%COMP%] .smart-filter-textarea[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n background: white;\n border-radius: 8px;\n padding: 12px;\n font-size: 14px;\n line-height: 1.5;\n resize: none;\n min-height: 60px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.smart-filter-input-container[_ngcontent-%COMP%] .smart-filter-textarea[_ngcontent-%COMP%]:focus {\n outline: none;\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3), 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.smart-filter-input-container[_ngcontent-%COMP%] .smart-filter-textarea[_ngcontent-%COMP%]::placeholder {\n color: #9ca3af;\n}\n\n\n\n.smart-filter-examples[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.examples-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 10px;\n font-size: 13px;\n font-weight: 500;\n color: #6b7280;\n}\n\n.examples-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #f59e0b;\n}\n\n.example-chips[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.example-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n border: 1px solid #e5e7eb;\n border-radius: 20px;\n background: white;\n font-size: 12px;\n font-weight: 500;\n color: #4b5563;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.example-chip[_ngcontent-%COMP%]:hover:not(:disabled) {\n border-color: #3b82f6;\n background: #eff6ff;\n color: #1d4ed8;\n}\n\n.example-chip[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.example-chip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #9ca3af;\n}\n\n.example-chip[_ngcontent-%COMP%]:hover:not(:disabled) i[_ngcontent-%COMP%] {\n color: #3b82f6;\n}\n\n\n\n.smart-filter-tip[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 12px 14px;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n color: #64748b;\n line-height: 1.5;\n}\n\n.smart-filter-tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #94a3b8;\n margin-top: 1px;\n flex-shrink: 0;\n}\n\n\n\n\n\n\n.traditional-filter-section[_ngcontent-%COMP%] {\n padding: 0;\n border: none;\n background: transparent;\n}\n\n.traditional-filter-tip[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 12px 14px;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n color: #64748b;\n line-height: 1.5;\n margin-top: 12px;\n}\n\n.traditional-filter-tip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #94a3b8;\n margin-top: 1px;\n flex-shrink: 0;\n}\n\n.summary-btn.edit-btn.primary[_ngcontent-%COMP%] {\n background: #3b82f6;\n color: white;\n border-color: #3b82f6;\n}\n\n.summary-btn.edit-btn.primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #2563eb;\n border-color: #2563eb;\n}\n\n\n\n.form-group[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.form-group[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 500;\n color: #333;\n}\n\n.form-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n transition: border-color 0.15s ease;\n}\n\n.form-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #1976d2;\n}\n\n.form-input[_ngcontent-%COMP%]:disabled {\n background: #f5f5f5;\n color: #999;\n}\n\n.form-textarea[_ngcontent-%COMP%] {\n resize: vertical;\n min-height: 80px;\n}\n\n\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n cursor: pointer;\n}\n\n.checkbox-label[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n margin-top: 2px;\n cursor: pointer;\n}\n\n.checkbox-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-text[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #333;\n}\n\n.checkbox-text[_ngcontent-%COMP%] small[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #666;\n}\n\n\n\n.danger-zone[_ngcontent-%COMP%] {\n padding-top: 16px;\n border-top: 1px solid #ffcdd2;\n}\n\n.danger-zone[_ngcontent-%COMP%] .section-header[_ngcontent-%COMP%] {\n color: #c62828;\n}\n\n.danger-zone[_ngcontent-%COMP%] .section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #c62828;\n}\n\n.delete-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n padding: 10px 16px;\n border: 1px solid #c62828;\n background: transparent;\n border-radius: 6px;\n color: #c62828;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.delete-btn[_ngcontent-%COMP%]:hover {\n background: #c62828;\n color: white;\n}\n\n\n\n.panel-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-top: 1px solid #e0e0e0;\n background: #fafafa;\n flex-shrink: 0;\n}\n\n.footer-right[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.footer-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px 16px;\n border: 1px solid #e0e0e0;\n background: white;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.footer-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #f0f0f0;\n border-color: #ccc;\n}\n\n.footer-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.footer-btn.primary[_ngcontent-%COMP%] {\n background: #1976d2;\n border-color: #1976d2;\n color: white;\n}\n\n.footer-btn.primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #1565c0;\n border-color: #1565c0;\n}\n\n.footer-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n\n\n@media (max-width: 768px) {\n .config-panel[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .tab-btn[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: none;\n }\n\n .tab-btn[_ngcontent-%COMP%] {\n padding: 14px;\n }\n\n .tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n }\n}"] });
791
1085
  }
792
1086
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ViewConfigPanelComponent, [{
793
1087
  type: Component,
794
- args: [{ selector: 'mj-view-config-panel', template: "<!-- Backdrop -->\n@if (isOpen) {\n <div class=\"panel-backdrop\" (click)=\"onClose()\"></div>\n}\n\n<!-- Sliding Panel -->\n<div class=\"config-panel\" [class.open]=\"isOpen\">\n <!-- Panel Header -->\n <div class=\"panel-header\">\n <div class=\"header-title\">\n <i class=\"fa-solid fa-sliders-h\"></i>\n <span>{{ viewEntity ? 'Edit View' : 'Configure View' }}</span>\n </div>\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tab-nav\">\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'columns'\"\n (click)=\"setActiveTab('columns')\">\n <i class=\"fa-solid fa-columns\"></i>\n <span>Columns</span>\n </button>\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'filters'\"\n (click)=\"setActiveTab('filters')\">\n <i class=\"fa-solid fa-filter\"></i>\n <span>Filters</span>\n </button>\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'settings'\"\n (click)=\"setActiveTab('settings')\">\n <i class=\"fa-solid fa-cog\"></i>\n <span>Settings</span>\n </button>\n </div>\n\n <!-- Panel Content -->\n <div class=\"panel-content\">\n <!-- Columns Tab -->\n @if (activeTab === 'columns') {\n <div class=\"tab-content\">\n <!-- Sort Configuration -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-sort\"></i>\n <span>Default Sort</span>\n </div>\n <div class=\"sort-config\">\n <select\n class=\"sort-field-select\"\n [(ngModel)]=\"sortField\">\n <option [value]=\"null\">No default sort</option>\n @for (field of sortableFields; track field.ID) {\n <option [value]=\"field.Name\">{{ field.DisplayNameOrName }}</option>\n }\n </select>\n @if (sortField) {\n <div class=\"sort-direction-toggle\">\n <button\n class=\"direction-btn\"\n [class.active]=\"sortDirection === 'asc'\"\n (click)=\"sortDirection = 'asc'\"\n title=\"Ascending\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n </button>\n <button\n class=\"direction-btn\"\n [class.active]=\"sortDirection === 'desc'\"\n (click)=\"sortDirection = 'desc'\"\n title=\"Descending\">\n <i class=\"fa-solid fa-arrow-down\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n\n <!-- Visible Columns -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-eye\"></i>\n <span>Visible Columns</span>\n <span class=\"column-count\">{{ visibleColumns.length }}</span>\n </div>\n <div class=\"column-list visible-columns\">\n @for (column of visibleColumns; track column.fieldId; let i = $index) {\n <div\n class=\"column-item\"\n draggable=\"true\"\n (dragstart)=\"onDragStart($event, column)\"\n (dragover)=\"onDragOver($event, column)\"\n (drop)=\"onDrop($event, column)\"\n (dragend)=\"onDragEnd()\">\n <div class=\"drag-handle\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n <span class=\"column-name\">{{ column.displayName }}</span>\n <div class=\"column-actions\">\n <button\n class=\"action-btn\"\n [disabled]=\"i === 0\"\n (click)=\"moveColumnUp(column)\"\n title=\"Move up\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button\n class=\"action-btn\"\n [disabled]=\"i === visibleColumns.length - 1\"\n (click)=\"moveColumnDown(column)\"\n title=\"Move down\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n <button\n class=\"action-btn hide-btn\"\n (click)=\"toggleColumnVisibility(column)\"\n title=\"Hide column\">\n <i class=\"fa-solid fa-eye-slash\"></i>\n </button>\n </div>\n </div>\n }\n @if (visibleColumns.length === 0) {\n <div class=\"empty-list\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>No columns visible. Add columns from below.</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Hidden Columns -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-eye-slash\"></i>\n <span>Hidden Columns</span>\n <span class=\"column-count\">{{ hiddenColumns.length }}</span>\n </div>\n @if (hiddenColumns.length > 5) {\n <div class=\"column-search\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search columns...\"\n [(ngModel)]=\"columnSearchText\"\n />\n </div>\n }\n <div class=\"column-list hidden-columns\">\n @for (column of filteredHiddenColumns; track column.fieldId) {\n <div class=\"column-item hidden\">\n <span class=\"column-name\">{{ column.displayName }}</span>\n <button\n class=\"action-btn show-btn\"\n (click)=\"toggleColumnVisibility(column)\"\n title=\"Show column\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n </div>\n }\n @if (hiddenColumns.length === 0) {\n <div class=\"empty-list\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <span>All columns are visible</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Filters Tab -->\n @if (activeTab === 'filters') {\n <div class=\"tab-content\">\n <!-- Smart Filter Section -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-magic\"></i>\n <span>Smart Filter</span>\n <label class=\"smart-filter-toggle\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"smartFilterEnabled\"\n [disabled]=\"!canEdit\"\n />\n <span class=\"toggle-label\">{{ smartFilterEnabled ? 'Enabled' : 'Disabled' }}</span>\n </label>\n </div>\n @if (smartFilterEnabled) {\n <div class=\"form-group\">\n <label for=\"smartFilterPrompt\">Natural Language Filter</label>\n <textarea\n id=\"smartFilterPrompt\"\n class=\"form-input form-textarea smart-filter-textarea\"\n placeholder=\"Describe what records you want to see... e.g., 'Show me all records created this month' or 'Active customers with high revenue'\"\n [(ngModel)]=\"smartFilterPrompt\"\n [disabled]=\"!canEdit\"\n rows=\"3\"\n ></textarea>\n </div>\n @if (smartFilterExplanation) {\n <div class=\"smart-filter-explanation\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>{{ smartFilterExplanation }}</span>\n </div>\n }\n <div class=\"tip\">\n <i class=\"fa-solid fa-lightbulb\"></i>\n <span>Tip: The AI will interpret your natural language and create the appropriate filter when you save the view.</span>\n </div>\n } @else {\n <div class=\"smart-filter-disabled-message\">\n <p>Enable Smart Filter to use natural language filtering. The AI will interpret your description and create the appropriate SQL filter.</p>\n </div>\n }\n </div>\n\n <!-- Traditional Filter Section -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-filter\"></i>\n <span>Traditional Filters</span>\n </div>\n <div class=\"filters-placeholder\">\n <i class=\"fa-solid fa-sliders-h\"></i>\n <p>Traditional filter editing is coming soon. For now, use Smart Filter above or the filter builder in the grid view.</p>\n </div>\n </div>\n </div>\n }\n\n <!-- Settings Tab -->\n @if (activeTab === 'settings') {\n <div class=\"tab-content\">\n <!-- View Name & Description -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>View Details</span>\n </div>\n <div class=\"form-group\">\n <label for=\"viewName\">Name</label>\n <input\n id=\"viewName\"\n type=\"text\"\n class=\"form-input\"\n placeholder=\"Enter view name...\"\n [(ngModel)]=\"viewName\"\n [disabled]=\"!canEdit\"\n />\n </div>\n <div class=\"form-group\">\n <label for=\"viewDescription\">Description</label>\n <textarea\n id=\"viewDescription\"\n class=\"form-input form-textarea\"\n placeholder=\"Describe this view...\"\n [(ngModel)]=\"viewDescription\"\n [disabled]=\"!canEdit\"\n rows=\"3\"\n ></textarea>\n </div>\n </div>\n\n <!-- Sharing -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-share-alt\"></i>\n <span>Sharing</span>\n </div>\n <label class=\"checkbox-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"isShared\"\n [disabled]=\"!canEdit\"\n />\n <span class=\"checkbox-text\">\n <strong>Share with others</strong>\n <small>Allow other users to use this view</small>\n </span>\n </label>\n </div>\n\n <!-- Danger Zone -->\n @if (viewEntity && canDelete) {\n <div class=\"config-section danger-zone\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>Danger Zone</span>\n </div>\n <button class=\"delete-btn\" (click)=\"onDelete()\">\n <i class=\"fa-solid fa-trash\"></i>\n <span>Delete View</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Panel Footer -->\n <div class=\"panel-footer\">\n <button class=\"footer-btn cancel-btn\" (click)=\"onClose()\">\n Cancel\n </button>\n <div class=\"footer-right\">\n @if (canEdit || !viewEntity) {\n <button\n class=\"footer-btn save-as-btn\"\n (click)=\"onSaveAsNew()\"\n [disabled]=\"isSaving\">\n <i class=\"fa-solid fa-plus\"></i>\n Save As New\n </button>\n }\n @if (viewEntity && canEdit) {\n <button\n class=\"footer-btn save-btn primary\"\n (click)=\"onSave()\"\n [disabled]=\"isSaving || !viewName\">\n <i class=\"fa-solid fa-save\"></i>\n Save\n </button>\n }\n @if (!viewEntity) {\n <button\n class=\"footer-btn save-btn primary\"\n (click)=\"onSaveAsNew()\"\n [disabled]=\"isSaving || !viewName\">\n <i class=\"fa-solid fa-save\"></i>\n Create View\n </button>\n }\n </div>\n </div>\n</div>\n", styles: ["/* Backdrop */\n.panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 1000;\n animation: fadeIn 0.2s ease;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* Sliding Panel */\n.config-panel {\n position: fixed;\n top: 0;\n right: 0;\n width: 400px;\n max-width: 100vw;\n height: 100%;\n background: white;\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.25s ease;\n}\n\n.config-panel.open {\n transform: translateX(0);\n}\n\n/* Panel Header */\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid #e0e0e0;\n background: #fafafa;\n flex-shrink: 0;\n}\n\n.header-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n}\n\n.header-title i {\n color: #1976d2;\n}\n\n.close-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n color: #666;\n transition: all 0.15s ease;\n}\n\n.close-btn:hover {\n background: #e0e0e0;\n color: #333;\n}\n\n/* Tab Navigation */\n.tab-nav {\n display: flex;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n}\n\n.tab-btn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 16px;\n border: none;\n background: transparent;\n color: #666;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n border-bottom: 2px solid transparent;\n}\n\n.tab-btn:hover {\n background: #f5f5f5;\n color: #333;\n}\n\n.tab-btn.active {\n color: #1976d2;\n border-bottom-color: #1976d2;\n background: transparent;\n}\n\n.tab-btn i {\n font-size: 12px;\n}\n\n/* Panel Content */\n.panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.tab-content {\n padding: 0 20px;\n}\n\n/* Config Sections */\n.config-section {\n margin-bottom: 24px;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: #333;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-header i {\n color: #1976d2;\n font-size: 12px;\n}\n\n.column-count {\n margin-left: auto;\n background: #e3f2fd;\n color: #1976d2;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n}\n\n/* Sort Configuration */\n.sort-config {\n display: flex;\n gap: 8px;\n}\n\n.sort-field-select {\n flex: 1;\n padding: 10px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n background: white;\n cursor: pointer;\n}\n\n.sort-field-select:focus {\n outline: none;\n border-color: #1976d2;\n}\n\n.sort-direction-toggle {\n display: flex;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 2px;\n}\n\n.direction-btn {\n width: 36px;\n height: 36px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #666;\n transition: all 0.15s ease;\n}\n\n.direction-btn:hover {\n color: #333;\n}\n\n.direction-btn.active {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* Column Lists */\n.column-list {\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n background: #fafafa;\n}\n\n.column-list.hidden-columns {\n max-height: 200px;\n overflow-y: auto;\n}\n\n.column-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: white;\n border-bottom: 1px solid #f0f0f0;\n transition: background 0.1s ease;\n}\n\n.column-item:last-child {\n border-bottom: none;\n}\n\n.column-item:hover {\n background: #f5f7fa;\n}\n\n.column-item.hidden {\n background: #fafafa;\n}\n\n.column-item.hidden:hover {\n background: #f0f0f0;\n}\n\n.drag-handle {\n cursor: grab;\n color: #999;\n padding: 4px;\n}\n\n.drag-handle:active {\n cursor: grabbing;\n}\n\n.column-name {\n flex: 1;\n font-size: 14px;\n color: #333;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.column-actions {\n display: flex;\n gap: 4px;\n}\n\n.action-btn {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #999;\n transition: all 0.15s ease;\n}\n\n.action-btn:hover:not(:disabled) {\n background: #e0e0e0;\n color: #333;\n}\n\n.action-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.action-btn.hide-btn:hover {\n background: #ffebee;\n color: #c62828;\n}\n\n.action-btn.show-btn:hover {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.empty-list {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: #999;\n font-size: 13px;\n}\n\n/* Column Search */\n.column-search {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n margin-bottom: 8px;\n}\n\n.column-search i {\n color: #999;\n font-size: 12px;\n}\n\n.column-search input {\n flex: 1;\n border: none;\n outline: none;\n font-size: 14px;\n}\n\n/* Filters Placeholder */\n.filters-placeholder {\n text-align: center;\n padding: 32px 20px;\n background: #f5f7fa;\n border-radius: 8px;\n}\n\n.filters-placeholder i {\n font-size: 32px;\n color: #1976d2;\n margin-bottom: 16px;\n}\n\n.filters-placeholder h4 {\n margin: 0 0 8px 0;\n font-size: 16px;\n color: #333;\n}\n\n.filters-placeholder p {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: #666;\n line-height: 1.5;\n}\n\n.tip {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 12px;\n background: #fff8e1;\n border-radius: 6px;\n font-size: 12px;\n color: #795548;\n text-align: left;\n}\n\n.tip i {\n color: #ffc107;\n font-size: 14px;\n margin-top: 1px;\n}\n\n/* Smart Filter Styles */\n.smart-filter-toggle {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n cursor: pointer;\n}\n\n.smart-filter-toggle input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.smart-filter-toggle .toggle-label {\n font-size: 12px;\n font-weight: 500;\n color: #666;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.smart-filter-textarea {\n min-height: 100px;\n font-family: inherit;\n line-height: 1.5;\n}\n\n.smart-filter-explanation {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 12px;\n background: #e3f2fd;\n border-radius: 6px;\n margin-bottom: 12px;\n font-size: 13px;\n color: #1565c0;\n}\n\n.smart-filter-explanation i {\n color: #1976d2;\n font-size: 14px;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.smart-filter-disabled-message {\n padding: 16px;\n background: #f5f7fa;\n border-radius: 6px;\n text-align: center;\n}\n\n.smart-filter-disabled-message p {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.5;\n}\n\n/* Form Elements */\n.form-group {\n margin-bottom: 16px;\n}\n\n.form-group label {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 500;\n color: #333;\n}\n\n.form-input {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n transition: border-color 0.15s ease;\n}\n\n.form-input:focus {\n outline: none;\n border-color: #1976d2;\n}\n\n.form-input:disabled {\n background: #f5f5f5;\n color: #999;\n}\n\n.form-textarea {\n resize: vertical;\n min-height: 80px;\n}\n\n/* Checkbox */\n.checkbox-label {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n cursor: pointer;\n}\n\n.checkbox-label input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n margin-top: 2px;\n cursor: pointer;\n}\n\n.checkbox-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-text strong {\n font-size: 14px;\n color: #333;\n}\n\n.checkbox-text small {\n font-size: 12px;\n color: #666;\n}\n\n/* Danger Zone */\n.danger-zone {\n padding-top: 16px;\n border-top: 1px solid #ffcdd2;\n}\n\n.danger-zone .section-header {\n color: #c62828;\n}\n\n.danger-zone .section-header i {\n color: #c62828;\n}\n\n.delete-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n padding: 10px 16px;\n border: 1px solid #c62828;\n background: transparent;\n border-radius: 6px;\n color: #c62828;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.delete-btn:hover {\n background: #c62828;\n color: white;\n}\n\n/* Panel Footer */\n.panel-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-top: 1px solid #e0e0e0;\n background: #fafafa;\n flex-shrink: 0;\n}\n\n.footer-right {\n display: flex;\n gap: 8px;\n}\n\n.footer-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px 16px;\n border: 1px solid #e0e0e0;\n background: white;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.footer-btn:hover:not(:disabled) {\n background: #f0f0f0;\n border-color: #ccc;\n}\n\n.footer-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.footer-btn.primary {\n background: #1976d2;\n border-color: #1976d2;\n color: white;\n}\n\n.footer-btn.primary:hover:not(:disabled) {\n background: #1565c0;\n border-color: #1565c0;\n}\n\n.footer-btn i {\n font-size: 12px;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .config-panel {\n width: 100%;\n }\n\n .tab-btn span {\n display: none;\n }\n\n .tab-btn {\n padding: 14px;\n }\n\n .tab-btn i {\n font-size: 16px;\n }\n}\n"] }]
1088
+ args: [{ selector: 'mj-view-config-panel', template: "<!-- Backdrop -->\n@if (isOpen) {\n <div class=\"panel-backdrop\" (click)=\"onClose()\"></div>\n}\n\n<!-- Sliding Panel -->\n<div class=\"config-panel\" [class.open]=\"isOpen\">\n <!-- Panel Header -->\n <div class=\"panel-header\">\n <div class=\"header-title\">\n <i class=\"fa-solid fa-sliders-h\"></i>\n <span>{{ viewEntity ? 'Edit View' : 'Configure View' }}</span>\n </div>\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tab-nav\">\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'columns'\"\n (click)=\"setActiveTab('columns')\">\n <i class=\"fa-solid fa-columns\"></i>\n <span>Columns</span>\n </button>\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'filters'\"\n (click)=\"setActiveTab('filters')\">\n <i class=\"fa-solid fa-filter\"></i>\n <span>Filters</span>\n </button>\n <button\n class=\"tab-btn\"\n [class.active]=\"activeTab === 'settings'\"\n (click)=\"setActiveTab('settings')\">\n <i class=\"fa-solid fa-cog\"></i>\n <span>Settings</span>\n </button>\n </div>\n\n <!-- Panel Content -->\n <div class=\"panel-content\">\n <!-- Columns Tab -->\n @if (activeTab === 'columns') {\n <div class=\"tab-content\">\n <!-- Sort Configuration -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-sort\"></i>\n <span>Default Sort</span>\n </div>\n <div class=\"sort-config\">\n <select\n class=\"sort-field-select\"\n [(ngModel)]=\"sortField\">\n <option [value]=\"null\">No default sort</option>\n @for (field of sortableFields; track field.ID) {\n <option [value]=\"field.Name\">{{ field.DisplayNameOrName }}</option>\n }\n </select>\n @if (sortField) {\n <div class=\"sort-direction-toggle\">\n <button\n class=\"direction-btn\"\n [class.active]=\"sortDirection === 'asc'\"\n (click)=\"sortDirection = 'asc'\"\n title=\"Ascending\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n </button>\n <button\n class=\"direction-btn\"\n [class.active]=\"sortDirection === 'desc'\"\n (click)=\"sortDirection = 'desc'\"\n title=\"Descending\">\n <i class=\"fa-solid fa-arrow-down\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n\n <!-- Visible Columns -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-eye\"></i>\n <span>Visible Columns</span>\n <span class=\"column-count\">{{ visibleColumns.length }}</span>\n </div>\n <div class=\"column-list visible-columns\">\n @for (column of visibleColumns; track column.fieldId; let i = $index) {\n <div\n class=\"column-item\"\n draggable=\"true\"\n (dragstart)=\"onDragStart($event, column)\"\n (dragover)=\"onDragOver($event, column)\"\n (drop)=\"onDrop($event, column)\"\n (dragend)=\"onDragEnd()\">\n <div class=\"drag-handle\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n <span class=\"column-name\">{{ column.displayName }}</span>\n <div class=\"column-actions\">\n <button\n class=\"action-btn\"\n [disabled]=\"i === 0\"\n (click)=\"moveColumnUp(column)\"\n title=\"Move up\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button\n class=\"action-btn\"\n [disabled]=\"i === visibleColumns.length - 1\"\n (click)=\"moveColumnDown(column)\"\n title=\"Move down\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n <button\n class=\"action-btn hide-btn\"\n (click)=\"toggleColumnVisibility(column)\"\n title=\"Hide column\">\n <i class=\"fa-solid fa-eye-slash\"></i>\n </button>\n </div>\n </div>\n }\n @if (visibleColumns.length === 0) {\n <div class=\"empty-list\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>No columns visible. Add columns from below.</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Hidden Columns -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-eye-slash\"></i>\n <span>Hidden Columns</span>\n <span class=\"column-count\">{{ hiddenColumns.length }}</span>\n </div>\n @if (hiddenColumns.length > 5) {\n <div class=\"column-search\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n type=\"text\"\n placeholder=\"Search columns...\"\n [(ngModel)]=\"columnSearchText\"\n />\n </div>\n }\n <div class=\"column-list hidden-columns\">\n @for (column of filteredHiddenColumns; track column.fieldId) {\n <div class=\"column-item hidden\">\n <span class=\"column-name\">{{ column.displayName }}</span>\n <button\n class=\"action-btn show-btn\"\n (click)=\"toggleColumnVisibility(column)\"\n title=\"Show column\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n </div>\n }\n @if (hiddenColumns.length === 0) {\n <div class=\"empty-list\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <span>All columns are visible</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Filters Tab -->\n @if (activeTab === 'filters') {\n <div class=\"tab-content\">\n <!-- Filter Mode Selection -->\n <div class=\"filter-mode-selector\">\n <button\n class=\"filter-mode-btn\"\n [class.active]=\"filterMode === 'smart'\"\n (click)=\"setFilterMode('smart')\"\n [disabled]=\"!canEdit\">\n <div class=\"mode-icon\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i>\n </div>\n <div class=\"mode-content\">\n <span class=\"mode-title\">Smart Filter</span>\n <span class=\"mode-subtitle\">Use AI to filter with natural language</span>\n </div>\n @if (filterMode === 'smart') {\n <i class=\"fa-solid fa-check mode-check\"></i>\n }\n </button>\n <button\n class=\"filter-mode-btn\"\n [class.active]=\"filterMode === 'traditional'\"\n (click)=\"setFilterMode('traditional')\"\n [disabled]=\"!canEdit\">\n <div class=\"mode-icon\">\n <i class=\"fa-solid fa-sliders\"></i>\n </div>\n <div class=\"mode-content\">\n <span class=\"mode-title\">Traditional Filter</span>\n <span class=\"mode-subtitle\">Build filters with field/operator/value</span>\n </div>\n @if (filterMode === 'traditional') {\n <i class=\"fa-solid fa-check mode-check\"></i>\n }\n </button>\n </div>\n\n <!-- Smart Filter Section -->\n @if (filterMode === 'smart') {\n <div class=\"config-section smart-filter-section\">\n <div class=\"smart-filter-input-container\">\n <div class=\"smart-filter-icon\">\n <i class=\"fa-solid fa-wand-magic-sparkles\"></i>\n </div>\n <textarea\n id=\"smartFilterPrompt\"\n class=\"smart-filter-textarea\"\n placeholder=\"Describe what you're looking for...\"\n [(ngModel)]=\"smartFilterPrompt\"\n [disabled]=\"!canEdit\"\n rows=\"3\"\n ></textarea>\n </div>\n\n @if (smartFilterExplanation) {\n <div class=\"smart-filter-explanation\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>{{ smartFilterExplanation }}</span>\n </div>\n }\n\n <!-- Example Prompts -->\n <div class=\"smart-filter-examples\">\n <div class=\"examples-header\">\n <i class=\"fa-solid fa-lightbulb\"></i>\n <span>Try these examples:</span>\n </div>\n <div class=\"example-chips\">\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Show records created in the last 30 days')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-regular fa-calendar\"></i>\n Last 30 days\n </button>\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Active records only')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-solid fa-circle-check\"></i>\n Active only\n </button>\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Records with high priority')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-solid fa-star\"></i>\n High priority\n </button>\n <button\n class=\"example-chip\"\n (click)=\"applySmartFilterExample('Records modified this week')\"\n [disabled]=\"!canEdit\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n Modified this week\n </button>\n </div>\n </div>\n\n <div class=\"smart-filter-tip\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>The AI will interpret your description and create the appropriate filter when you save the view.</span>\n </div>\n </div>\n }\n\n <!-- Traditional Filter Section -->\n @if (filterMode === 'traditional') {\n <div class=\"config-section traditional-filter-section\">\n <div class=\"filter-summary-container\">\n <div class=\"filter-summary\">\n <div class=\"summary-info\">\n @if (getFilterCount() > 0) {\n <span class=\"filter-badge\">{{ getFilterCount() }}</span>\n <span class=\"summary-text\">{{ getFilterSummary() }}</span>\n } @else {\n <span class=\"summary-text no-filters\">No filters configured</span>\n }\n </div>\n <div class=\"summary-actions\">\n @if (getFilterCount() > 0 && canEdit) {\n <button\n class=\"summary-btn clear-btn\"\n (click)=\"clearFilters()\"\n title=\"Clear all filters\">\n <i class=\"fa-solid fa-times\"></i>\n Clear\n </button>\n }\n <button\n class=\"summary-btn edit-btn primary\"\n (click)=\"openFilterDialog()\"\n [disabled]=\"!canEdit && getFilterCount() === 0\"\n title=\"Edit filters\">\n <i class=\"fa-solid fa-pen\"></i>\n {{ getFilterCount() > 0 ? 'Edit Filters' : 'Add Filters' }}\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"traditional-filter-tip\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>Build precise filters by selecting fields, operators, and values. Use groups for complex AND/OR logic.</span>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Settings Tab -->\n @if (activeTab === 'settings') {\n <div class=\"tab-content\">\n <!-- View Name & Description -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>View Details</span>\n </div>\n <div class=\"form-group\">\n <label for=\"viewName\">Name</label>\n <input\n id=\"viewName\"\n type=\"text\"\n class=\"form-input\"\n placeholder=\"Enter view name...\"\n [(ngModel)]=\"viewName\"\n [disabled]=\"!canEdit\"\n />\n </div>\n <div class=\"form-group\">\n <label for=\"viewDescription\">Description</label>\n <textarea\n id=\"viewDescription\"\n class=\"form-input form-textarea\"\n placeholder=\"Describe this view...\"\n [(ngModel)]=\"viewDescription\"\n [disabled]=\"!canEdit\"\n rows=\"3\"\n ></textarea>\n </div>\n </div>\n\n <!-- Sharing -->\n <div class=\"config-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-share-alt\"></i>\n <span>Sharing</span>\n </div>\n <label class=\"checkbox-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"isShared\"\n [disabled]=\"!canEdit\"\n />\n <span class=\"checkbox-text\">\n <strong>Share with others</strong>\n <small>Allow other users to use this view</small>\n </span>\n </label>\n </div>\n\n <!-- Danger Zone -->\n @if (viewEntity && canDelete) {\n <div class=\"config-section danger-zone\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>Danger Zone</span>\n </div>\n <button class=\"delete-btn\" (click)=\"onDelete()\">\n <i class=\"fa-solid fa-trash\"></i>\n <span>Delete View</span>\n </button>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Panel Footer -->\n <div class=\"panel-footer\">\n <button class=\"footer-btn cancel-btn\" (click)=\"onClose()\">\n Cancel\n </button>\n <div class=\"footer-right\">\n @if (canEdit || !viewEntity) {\n <button\n class=\"footer-btn save-as-btn\"\n (click)=\"onSaveAsNew()\"\n [disabled]=\"isSaving\">\n <i class=\"fa-solid fa-plus\"></i>\n Save As New\n </button>\n }\n @if (viewEntity && canEdit) {\n <button\n class=\"footer-btn save-btn primary\"\n (click)=\"onSave()\"\n [disabled]=\"isSaving || !viewName\">\n <i class=\"fa-solid fa-save\"></i>\n Save\n </button>\n }\n @if (!viewEntity) {\n <button\n class=\"footer-btn save-btn primary\"\n (click)=\"onSaveAsNew()\"\n [disabled]=\"isSaving || !viewName\">\n <i class=\"fa-solid fa-save\"></i>\n Create View\n </button>\n }\n </div>\n </div>\n</div>\n", styles: ["/* Backdrop */\n.panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 1000;\n animation: fadeIn 0.2s ease;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* Sliding Panel */\n.config-panel {\n position: fixed;\n top: 0;\n right: 0;\n width: 400px;\n max-width: 100vw;\n height: 100%;\n background: white;\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.25s ease;\n}\n\n.config-panel.open {\n transform: translateX(0);\n}\n\n/* Panel Header */\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid #e0e0e0;\n background: #fafafa;\n flex-shrink: 0;\n}\n\n.header-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n}\n\n.header-title i {\n color: #1976d2;\n}\n\n.close-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n border-radius: 6px;\n cursor: pointer;\n color: #666;\n transition: all 0.15s ease;\n}\n\n.close-btn:hover {\n background: #e0e0e0;\n color: #333;\n}\n\n/* Tab Navigation */\n.tab-nav {\n display: flex;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n}\n\n.tab-btn {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 16px;\n border: none;\n background: transparent;\n color: #666;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n border-bottom: 2px solid transparent;\n}\n\n.tab-btn:hover {\n background: #f5f5f5;\n color: #333;\n}\n\n.tab-btn.active {\n color: #1976d2;\n border-bottom-color: #1976d2;\n background: transparent;\n}\n\n.tab-btn i {\n font-size: 12px;\n}\n\n/* Panel Content */\n.panel-content {\n flex: 1;\n overflow: hidden;\n padding: 16px 0;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.tab-content {\n padding: 0 20px;\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow-y: auto;\n}\n\n/* Config Sections */\n.config-section {\n margin-bottom: 24px;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n font-weight: 600;\n color: #333;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.section-header i {\n color: #1976d2;\n font-size: 12px;\n}\n\n.column-count {\n margin-left: auto;\n background: #e3f2fd;\n color: #1976d2;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n}\n\n/* Sort Configuration */\n.sort-config {\n display: flex;\n gap: 8px;\n}\n\n.sort-field-select {\n flex: 1;\n padding: 10px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n background: white;\n cursor: pointer;\n}\n\n.sort-field-select:focus {\n outline: none;\n border-color: #1976d2;\n}\n\n.sort-direction-toggle {\n display: flex;\n background: #f0f0f0;\n border-radius: 6px;\n padding: 2px;\n}\n\n.direction-btn {\n width: 36px;\n height: 36px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #666;\n transition: all 0.15s ease;\n}\n\n.direction-btn:hover {\n color: #333;\n}\n\n.direction-btn.active {\n background: white;\n color: #1976d2;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n/* Column Lists */\n.column-list {\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n background: #fafafa;\n}\n\n.column-list.visible-columns {\n max-height: 300px;\n overflow-y: auto;\n}\n\n.column-list.hidden-columns {\n flex: 1;\n min-height: 100px;\n overflow-y: auto;\n}\n\n/* Hidden columns section should expand to fill available space */\n.config-section:last-child {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-height: 0;\n margin-bottom: 0;\n}\n\n.column-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: white;\n border-bottom: 1px solid #f0f0f0;\n transition: background 0.1s ease;\n}\n\n.column-item:last-child {\n border-bottom: none;\n}\n\n.column-item:hover {\n background: #f5f7fa;\n}\n\n.column-item.hidden {\n background: #fafafa;\n}\n\n.column-item.hidden:hover {\n background: #f0f0f0;\n}\n\n.drag-handle {\n cursor: grab;\n color: #999;\n padding: 4px;\n}\n\n.drag-handle:active {\n cursor: grabbing;\n}\n\n.column-name {\n flex: 1;\n font-size: 14px;\n color: #333;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.column-actions {\n display: flex;\n gap: 4px;\n}\n\n.action-btn {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: 4px;\n cursor: pointer;\n color: #999;\n transition: all 0.15s ease;\n}\n\n.action-btn:hover:not(:disabled) {\n background: #e0e0e0;\n color: #333;\n}\n\n.action-btn:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.action-btn.hide-btn:hover {\n background: #ffebee;\n color: #c62828;\n}\n\n.action-btn.show-btn:hover {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.empty-list {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: #999;\n font-size: 13px;\n}\n\n/* Column Search */\n.column-search {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n margin-bottom: 8px;\n}\n\n.column-search i {\n color: #999;\n font-size: 12px;\n}\n\n.column-search input {\n flex: 1;\n border: none;\n outline: none;\n font-size: 14px;\n}\n\n/* Filter Summary Container */\n.filter-summary-container {\n padding: 4px 0;\n}\n\n.filter-summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background: #f5f7fa;\n border-radius: 8px;\n border: 1px solid #e8e8e8;\n}\n\n.summary-info {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.filter-badge {\n background: #1976d2;\n color: white;\n font-size: 12px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n min-width: 20px;\n text-align: center;\n}\n\n.summary-text {\n font-size: 14px;\n color: #333;\n}\n\n.summary-text.no-filters {\n color: #999;\n}\n\n.summary-actions {\n display: flex;\n gap: 8px;\n}\n\n.summary-btn {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 6px 12px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.summary-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.summary-btn i {\n font-size: 11px;\n}\n\n.summary-btn.clear-btn {\n background: transparent;\n color: #c62828;\n border: 1px solid #e0e0e0;\n}\n\n.summary-btn.clear-btn:hover:not(:disabled) {\n background: #ffebee;\n border-color: #c62828;\n}\n\n.summary-btn.edit-btn {\n background: #1976d2;\n color: white;\n}\n\n.summary-btn.edit-btn:hover:not(:disabled) {\n background: #1565c0;\n}\n\n/* Filters Placeholder (kept for reference) */\n.filters-placeholder {\n text-align: center;\n padding: 32px 20px;\n background: #f5f7fa;\n border-radius: 8px;\n}\n\n.filters-placeholder i {\n font-size: 32px;\n color: #1976d2;\n margin-bottom: 16px;\n}\n\n.filters-placeholder h4 {\n margin: 0 0 8px 0;\n font-size: 16px;\n color: #333;\n}\n\n.filters-placeholder p {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: #666;\n line-height: 1.5;\n}\n\n.tip {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 12px;\n background: #fff8e1;\n border-radius: 6px;\n font-size: 12px;\n color: #795548;\n text-align: left;\n}\n\n.tip i {\n color: #ffc107;\n font-size: 14px;\n margin-top: 1px;\n}\n\n/* Smart Filter Styles */\n.smart-filter-toggle {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n cursor: pointer;\n}\n\n.smart-filter-toggle input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.smart-filter-toggle .toggle-label {\n font-size: 12px;\n font-weight: 500;\n color: #666;\n text-transform: none;\n letter-spacing: normal;\n}\n\n.smart-filter-textarea {\n min-height: 100px;\n font-family: inherit;\n line-height: 1.5;\n}\n\n.smart-filter-explanation {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 12px;\n background: #e3f2fd;\n border-radius: 6px;\n margin-bottom: 12px;\n font-size: 13px;\n color: #1565c0;\n}\n\n.smart-filter-explanation i {\n color: #1976d2;\n font-size: 14px;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.smart-filter-disabled-message {\n padding: 16px;\n background: #f5f7fa;\n border-radius: 6px;\n text-align: center;\n}\n\n.smart-filter-disabled-message p {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.5;\n}\n\n/* ========================================\n FILTER MODE SELECTOR\n ======================================== */\n\n.filter-mode-selector {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.filter-mode-btn {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 14px 16px;\n border: 2px solid #e5e7eb;\n border-radius: 12px;\n background: white;\n cursor: pointer;\n transition: all 0.2s ease;\n text-align: left;\n}\n\n.filter-mode-btn:hover:not(:disabled) {\n border-color: #d1d5db;\n background: #f9fafb;\n}\n\n.filter-mode-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.filter-mode-btn.active {\n border-color: #3b82f6;\n background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);\n}\n\n.filter-mode-btn .mode-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n background: #f3f4f6;\n color: #6b7280;\n font-size: 16px;\n flex-shrink: 0;\n transition: all 0.2s ease;\n}\n\n.filter-mode-btn.active .mode-icon {\n background: #3b82f6;\n color: white;\n}\n\n.filter-mode-btn .mode-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.filter-mode-btn .mode-title {\n font-size: 14px;\n font-weight: 600;\n color: #1f2937;\n}\n\n.filter-mode-btn .mode-subtitle {\n font-size: 12px;\n color: #6b7280;\n}\n\n.filter-mode-btn.active .mode-title {\n color: #1d4ed8;\n}\n\n.filter-mode-btn .mode-check {\n color: #3b82f6;\n font-size: 16px;\n flex-shrink: 0;\n}\n\n/* ========================================\n SMART FILTER SECTION (ENHANCED)\n ======================================== */\n\n.smart-filter-section {\n padding: 0;\n border: none;\n background: transparent;\n}\n\n.smart-filter-input-container {\n display: flex;\n gap: 12px;\n padding: 16px;\n background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);\n border: 1px solid #bae6fd;\n border-radius: 12px;\n margin-bottom: 16px;\n}\n\n.smart-filter-icon {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: linear-gradient(135deg, #3b82f6 0%, #6366f1 100%);\n border-radius: 10px;\n color: white;\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.smart-filter-input-container .smart-filter-textarea {\n flex: 1;\n border: none;\n background: white;\n border-radius: 8px;\n padding: 12px;\n font-size: 14px;\n line-height: 1.5;\n resize: none;\n min-height: 60px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.smart-filter-input-container .smart-filter-textarea:focus {\n outline: none;\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3), 0 1px 3px rgba(0, 0, 0, 0.08);\n}\n\n.smart-filter-input-container .smart-filter-textarea::placeholder {\n color: #9ca3af;\n}\n\n/* Smart Filter Examples */\n.smart-filter-examples {\n margin-bottom: 16px;\n}\n\n.examples-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 10px;\n font-size: 13px;\n font-weight: 500;\n color: #6b7280;\n}\n\n.examples-header i {\n color: #f59e0b;\n}\n\n.example-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.example-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 12px;\n border: 1px solid #e5e7eb;\n border-radius: 20px;\n background: white;\n font-size: 12px;\n font-weight: 500;\n color: #4b5563;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.example-chip:hover:not(:disabled) {\n border-color: #3b82f6;\n background: #eff6ff;\n color: #1d4ed8;\n}\n\n.example-chip:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.example-chip i {\n font-size: 11px;\n color: #9ca3af;\n}\n\n.example-chip:hover:not(:disabled) i {\n color: #3b82f6;\n}\n\n/* Smart Filter Tip */\n.smart-filter-tip {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 12px 14px;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n color: #64748b;\n line-height: 1.5;\n}\n\n.smart-filter-tip i {\n color: #94a3b8;\n margin-top: 1px;\n flex-shrink: 0;\n}\n\n/* ========================================\n TRADITIONAL FILTER SECTION\n ======================================== */\n\n.traditional-filter-section {\n padding: 0;\n border: none;\n background: transparent;\n}\n\n.traditional-filter-tip {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 12px 14px;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font-size: 12px;\n color: #64748b;\n line-height: 1.5;\n margin-top: 12px;\n}\n\n.traditional-filter-tip i {\n color: #94a3b8;\n margin-top: 1px;\n flex-shrink: 0;\n}\n\n.summary-btn.edit-btn.primary {\n background: #3b82f6;\n color: white;\n border-color: #3b82f6;\n}\n\n.summary-btn.edit-btn.primary:hover:not(:disabled) {\n background: #2563eb;\n border-color: #2563eb;\n}\n\n/* Form Elements */\n.form-group {\n margin-bottom: 16px;\n}\n\n.form-group label {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 500;\n color: #333;\n}\n\n.form-input {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n font-size: 14px;\n transition: border-color 0.15s ease;\n}\n\n.form-input:focus {\n outline: none;\n border-color: #1976d2;\n}\n\n.form-input:disabled {\n background: #f5f5f5;\n color: #999;\n}\n\n.form-textarea {\n resize: vertical;\n min-height: 80px;\n}\n\n/* Checkbox */\n.checkbox-label {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n cursor: pointer;\n}\n\n.checkbox-label input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n margin-top: 2px;\n cursor: pointer;\n}\n\n.checkbox-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.checkbox-text strong {\n font-size: 14px;\n color: #333;\n}\n\n.checkbox-text small {\n font-size: 12px;\n color: #666;\n}\n\n/* Danger Zone */\n.danger-zone {\n padding-top: 16px;\n border-top: 1px solid #ffcdd2;\n}\n\n.danger-zone .section-header {\n color: #c62828;\n}\n\n.danger-zone .section-header i {\n color: #c62828;\n}\n\n.delete-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n padding: 10px 16px;\n border: 1px solid #c62828;\n background: transparent;\n border-radius: 6px;\n color: #c62828;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.delete-btn:hover {\n background: #c62828;\n color: white;\n}\n\n/* Panel Footer */\n.panel-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-top: 1px solid #e0e0e0;\n background: #fafafa;\n flex-shrink: 0;\n}\n\n.footer-right {\n display: flex;\n gap: 8px;\n}\n\n.footer-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 10px 16px;\n border: 1px solid #e0e0e0;\n background: white;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.footer-btn:hover:not(:disabled) {\n background: #f0f0f0;\n border-color: #ccc;\n}\n\n.footer-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.footer-btn.primary {\n background: #1976d2;\n border-color: #1976d2;\n color: white;\n}\n\n.footer-btn.primary:hover:not(:disabled) {\n background: #1565c0;\n border-color: #1565c0;\n}\n\n.footer-btn i {\n font-size: 12px;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .config-panel {\n width: 100%;\n }\n\n .tab-btn span {\n display: none;\n }\n\n .tab-btn {\n padding: 14px;\n }\n\n .tab-btn i {\n font-size: 16px;\n }\n}\n"] }]
795
1089
  }], () => [{ type: i0.ChangeDetectorRef }], { entity: [{
796
1090
  type: Input
797
1091
  }], viewEntity: [{
@@ -806,9 +1100,13 @@ export class ViewConfigPanelComponent {
806
1100
  type: Output
807
1101
  }], delete: [{
808
1102
  type: Output
1103
+ }], openFilterDialogRequest: [{
1104
+ type: Output
1105
+ }], externalFilterState: [{
1106
+ type: Input
809
1107
  }], handleEscape: [{
810
1108
  type: HostListener,
811
1109
  args: ['document:keydown.escape']
812
1110
  }] }); })();
813
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ViewConfigPanelComponent, { className: "ViewConfigPanelComponent", filePath: "src/DataExplorer/components/view-config-panel/view-config-panel.component.ts", lineNumber: 49 }); })();
1111
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ViewConfigPanelComponent, { className: "ViewConfigPanelComponent", filePath: "src/DataExplorer/components/view-config-panel/view-config-panel.component.ts", lineNumber: 57 }); })();
814
1112
  //# sourceMappingURL=view-config-panel.component.js.map