@memberjunction/ng-dashboards 2.122.1 → 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.
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts +79 -0
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts.map +1 -0
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +195 -0
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +1 -0
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts +67 -1
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts.map +1 -1
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js +377 -79
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +87 -4
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +517 -209
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.d.ts +13 -2
- package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.js +3 -0
- package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.d.ts +2 -2
- package/dist/DataExplorer/services/explorer-state.service.d.ts.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
- package/dist/module.d.ts +28 -26
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +10 -3
- package/dist/module.js.map +1 -1
- package/package.json +35 -29
|
@@ -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
|
|
180
|
-
i0.ɵɵ
|
|
181
|
-
|
|
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
|
|
197
|
+
function ViewConfigPanelComponent_Conditional_24_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
191
198
|
const _r13 = i0.ɵɵgetCurrentView();
|
|
192
|
-
i0.ɵɵelementStart(0, "div",
|
|
193
|
-
i0.ɵɵ
|
|
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(
|
|
196
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
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(
|
|
199
|
-
i0.ɵɵelementStart(
|
|
200
|
-
i0.ɵɵelement(
|
|
201
|
-
i0.ɵɵelementStart(
|
|
202
|
-
i0.ɵɵtext(
|
|
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(
|
|
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 ?
|
|
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
|
|
213
|
-
i0.ɵɵelementStart(0, "
|
|
214
|
-
i0.ɵɵtext(
|
|
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",
|
|
220
|
-
i0.ɵɵ
|
|
221
|
-
i0.ɵɵelementStart(
|
|
222
|
-
i0.ɵɵ
|
|
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(
|
|
225
|
-
i0.ɵɵ
|
|
314
|
+
i0.ɵɵelementStart(5, "div", 60)(6, "span", 61);
|
|
315
|
+
i0.ɵɵtext(7, "Smart Filter");
|
|
226
316
|
i0.ɵɵelementEnd();
|
|
227
|
-
i0.ɵɵelementStart(8, "span",
|
|
228
|
-
i0.ɵɵtext(9);
|
|
229
|
-
i0.ɵɵelementEnd()()
|
|
230
|
-
i0.ɵɵtemplate(10, ViewConfigPanelComponent_Conditional_24_Conditional_10_Template,
|
|
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(
|
|
233
|
-
i0.ɵɵ
|
|
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.ɵɵ
|
|
238
|
-
i0.ɵɵ
|
|
239
|
-
i0.ɵɵ
|
|
240
|
-
i0.ɵɵ
|
|
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.ɵɵ
|
|
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.
|
|
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
|
|
254
|
-
i0.ɵɵelementStart(0, "div",
|
|
255
|
-
i0.ɵɵelement(2, "i",
|
|
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",
|
|
260
|
-
i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_25_Conditional_26_Template_button_click_5_listener() { i0.ɵɵrestoreView(
|
|
261
|
-
i0.ɵɵelement(6, "i",
|
|
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
|
|
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",
|
|
375
|
+
i0.ɵɵelementStart(6, "div", 94)(7, "label", 95);
|
|
274
376
|
i0.ɵɵtext(8, "Name");
|
|
275
377
|
i0.ɵɵelementEnd();
|
|
276
|
-
i0.ɵɵelementStart(9, "input",
|
|
277
|
-
i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_25_Template_input_ngModelChange_9_listener($event) { i0.ɵɵrestoreView(
|
|
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",
|
|
381
|
+
i0.ɵɵelementStart(10, "div", 94)(11, "label", 97);
|
|
280
382
|
i0.ɵɵtext(12, "Description");
|
|
281
383
|
i0.ɵɵelementEnd();
|
|
282
|
-
i0.ɵɵelementStart(13, "textarea",
|
|
283
|
-
i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_25_Template_textarea_ngModelChange_13_listener($event) { i0.ɵɵrestoreView(
|
|
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",
|
|
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",
|
|
291
|
-
i0.ɵɵtwoWayListener("ngModelChange", function ViewConfigPanelComponent_Conditional_25_Template_input_ngModelChange_20_listener($event) { i0.ɵɵrestoreView(
|
|
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",
|
|
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",
|
|
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
|
|
317
|
-
i0.ɵɵelementStart(0, "button",
|
|
318
|
-
i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_30_Template_button_click_0_listener() { i0.ɵɵrestoreView(
|
|
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
|
|
328
|
-
i0.ɵɵelementStart(0, "button",
|
|
329
|
-
i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_31_Template_button_click_0_listener() { i0.ɵɵrestoreView(
|
|
330
|
-
i0.ɵɵelement(1, "i",
|
|
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
|
|
339
|
-
i0.ɵɵelementStart(0, "button",
|
|
340
|
-
i0.ɵɵlistener("click", function ViewConfigPanelComponent_Conditional_32_Template_button_click_0_listener() { i0.ɵɵrestoreView(
|
|
341
|
-
i0.ɵɵelement(1, "i",
|
|
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-
|
|
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,
|
|
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:
|
|
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
|