@memberjunction/ng-action-gallery
Version:
MemberJunction Action Gallery - A beautiful, filterable gallery component for browsing and selecting actions
801 lines • 53.1 kB
JavaScript
import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Subject, BehaviorSubject, combineLatest, debounceTime, distinctUntilChanged, takeUntil } from 'rxjs';
import { RunView } from '@memberjunction/core';
import { UUIDsEqual } from '@memberjunction/global';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@memberjunction/ng-ui-components";
import * as i3 from "@memberjunction/ng-shared-generic";
import * as i4 from "@angular/common";
const _c0 = ["searchInput"];
const _forTrack0 = ($index, $item) => $item.id;
const _forTrack1 = ($index, $item) => $item.ID;
function ActionGalleryComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
const _r1 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "div", 2)(1, "div", 10)(2, "div", 11)(3, "div", 12);
i0.ɵɵelement(4, "i", 13)(5, "input", 14, 0);
i0.ɵɵelementEnd()();
i0.ɵɵelementStart(7, "div", 15)(8, "div", 16)(9, "button", 17);
i0.ɵɵpipe(10, "async");
i0.ɵɵlistener("click", function ActionGalleryComponent_Conditional_1_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleViewMode()); });
i0.ɵɵelement(11, "i", 18);
i0.ɵɵpipe(12, "async");
i0.ɵɵpipe(13, "async");
i0.ɵɵelementEnd()();
i0.ɵɵelementStart(14, "div", 19)(15, "span", 20);
i0.ɵɵelement(16, "i", 21);
i0.ɵɵtext(17);
i0.ɵɵpipe(18, "async");
i0.ɵɵelementEnd()()()()();
} if (rf & 2) {
let tmp_6_0;
const ctx_r1 = i0.ɵɵnextContext();
i0.ɵɵadvance(5);
i0.ɵɵproperty("formControl", ctx_r1.searchControl);
i0.ɵɵadvance(4);
i0.ɵɵproperty("title", i0.ɵɵpipeBind1(10, 8, ctx_r1.viewMode$) === "grid" ? "Switch to list view" : "Switch to grid view");
i0.ɵɵadvance(2);
i0.ɵɵclassProp("fa-th", i0.ɵɵpipeBind1(12, 10, ctx_r1.viewMode$) === "grid")("fa-list", i0.ɵɵpipeBind1(13, 12, ctx_r1.viewMode$) === "list");
i0.ɵɵadvance(6);
i0.ɵɵtextInterpolate2(" ", (tmp_6_0 = i0.ɵɵpipeBind1(18, 14, ctx_r1.filteredActions$)) == null ? null : tmp_6_0.length, " of ", ctx_r1.totalActions, " actions ");
} }
function ActionGalleryComponent_Conditional_3_For_3_Conditional_8_Template(rf, ctx) { if (rf & 1) {
const _r5 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "i", 30);
i0.ɵɵlistener("click", function ActionGalleryComponent_Conditional_3_For_3_Conditional_8_Template_i_click_0_listener($event) { i0.ɵɵrestoreView(_r5); const category_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); ctx_r1.toggleCategoryExpanded(category_r4.id); return i0.ɵɵresetView($event.stopPropagation()); });
i0.ɵɵelementEnd();
} if (rf & 2) {
const category_r4 = i0.ɵɵnextContext().$implicit;
const ctx_r1 = i0.ɵɵnextContext(2);
i0.ɵɵclassProp("expanded", ctx_r1.expandedCategories.has(category_r4.id));
} }
function ActionGalleryComponent_Conditional_3_For_3_Conditional_9_For_2_Template(rf, ctx) { if (rf & 1) {
const _r6 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "div", 32);
i0.ɵɵpipe(1, "async");
i0.ɵɵlistener("click", function ActionGalleryComponent_Conditional_3_For_3_Conditional_9_For_2_Template_div_click_0_listener($event) { const subCategory_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); ctx_r1.selectCategory(subCategory_r7.id); return i0.ɵɵresetView($event.stopPropagation()); });
i0.ɵɵelementStart(2, "div", 25);
i0.ɵɵelement(3, "i");
i0.ɵɵelementStart(4, "span", 26);
i0.ɵɵtext(5);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(6, "span", 27);
i0.ɵɵtext(7);
i0.ɵɵelementEnd()()();
} if (rf & 2) {
const subCategory_r7 = ctx.$implicit;
const ctx_r1 = i0.ɵɵnextContext(4);
i0.ɵɵclassProp("selected", i0.ɵɵpipeBind1(1, 7, ctx_r1.selectedCategory$) === subCategory_r7.id);
i0.ɵɵadvance(3);
i0.ɵɵclassMap(i0.ɵɵinterpolate1("fa-solid ", subCategory_r7.icon, " category-icon"));
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(subCategory_r7.name);
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(subCategory_r7.count);
} }
function ActionGalleryComponent_Conditional_3_For_3_Conditional_9_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 29);
i0.ɵɵrepeaterCreate(1, ActionGalleryComponent_Conditional_3_For_3_Conditional_9_For_2_Template, 8, 9, "div", 31, _forTrack0);
i0.ɵɵelementEnd();
} if (rf & 2) {
const category_r4 = i0.ɵɵnextContext().$implicit;
i0.ɵɵadvance();
i0.ɵɵrepeater(category_r4.children);
} }
function ActionGalleryComponent_Conditional_3_For_3_Template(rf, ctx) { if (rf & 1) {
const _r3 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "div", 24);
i0.ɵɵpipe(1, "async");
i0.ɵɵlistener("click", function ActionGalleryComponent_Conditional_3_For_3_Template_div_click_0_listener() { const category_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.selectCategory(category_r4.id)); });
i0.ɵɵelementStart(2, "div", 25);
i0.ɵɵelement(3, "i");
i0.ɵɵelementStart(4, "span", 26);
i0.ɵɵtext(5);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(6, "span", 27);
i0.ɵɵtext(7);
i0.ɵɵelementEnd();
i0.ɵɵconditionalCreate(8, ActionGalleryComponent_Conditional_3_For_3_Conditional_8_Template, 1, 2, "i", 28);
i0.ɵɵelementEnd();
i0.ɵɵconditionalCreate(9, ActionGalleryComponent_Conditional_3_For_3_Conditional_9_Template, 3, 0, "div", 29);
i0.ɵɵelementEnd();
} if (rf & 2) {
const category_r4 = ctx.$implicit;
const ctx_r1 = i0.ɵɵnextContext(2);
i0.ɵɵclassProp("selected", i0.ɵɵpipeBind1(1, 11, ctx_r1.selectedCategory$) === category_r4.id)("has-children", category_r4.children && category_r4.children.length > 0);
i0.ɵɵadvance(3);
i0.ɵɵclassMap(i0.ɵɵinterpolate1("fa-solid ", category_r4.icon, " category-icon"));
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(category_r4.name);
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(category_r4.count);
i0.ɵɵadvance();
i0.ɵɵconditional(category_r4.children && category_r4.children.length > 0 ? 8 : -1);
i0.ɵɵadvance();
i0.ɵɵconditional(category_r4.children && ctx_r1.expandedCategories.has(category_r4.id) ? 9 : -1);
} }
function ActionGalleryComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 4)(1, "div", 22);
i0.ɵɵrepeaterCreate(2, ActionGalleryComponent_Conditional_3_For_3_Template, 10, 13, "div", 23, _forTrack0);
i0.ɵɵpipe(4, "async");
i0.ɵɵelementEnd()();
} if (rf & 2) {
const ctx_r1 = i0.ɵɵnextContext();
i0.ɵɵadvance(2);
i0.ɵɵrepeater(i0.ɵɵpipeBind1(4, 0, ctx_r1.categoryTree$));
} }
function ActionGalleryComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 6);
i0.ɵɵelement(1, "mj-loading", 33);
i0.ɵɵelementEnd();
} }
function ActionGalleryComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
const _r8 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "mj-empty-state", 34);
i0.ɵɵlistener("Action", function ActionGalleryComponent_Conditional_7_Template_mj_empty_state_Action_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.clearSearch()); });
i0.ɵɵelementEnd();
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "span", 43);
i0.ɵɵelement(1, "i", 53);
i0.ɵɵtext(2);
i0.ɵɵelementEnd();
} if (rf & 2) {
const action_r10 = i0.ɵɵnextContext().$implicit;
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate1(" ", action_r10.Category, " ");
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_10_Template(rf, ctx) { if (rf & 1) {
const _r11 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "button", 54);
i0.ɵɵlistener("click", function ActionGalleryComponent_Conditional_10_For_2_Conditional_10_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r11); const action_r10 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.testAction(action_r10, $event)); });
i0.ɵɵelement(1, "i", 55);
i0.ɵɵelementEnd();
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_16_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "span", 50);
i0.ɵɵelement(1, "i", 56);
i0.ɵɵtext(2);
i0.ɵɵelementEnd();
} if (rf & 2) {
const action_r10 = i0.ɵɵnextContext().$implicit;
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate1(" ", (action_r10.parameters == null ? null : action_r10.parameters.length) || 0, " params ");
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_17_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "span", 50);
i0.ɵɵelement(1, "i", 57);
i0.ɵɵtext(2);
i0.ɵɵelementEnd();
} if (rf & 2) {
const action_r10 = i0.ɵɵnextContext().$implicit;
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate1(" ", (action_r10.resultCodes == null ? null : action_r10.resultCodes.length) || 0, " results ");
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_18_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "span", 50);
i0.ɵɵelement(1, "i", 58);
i0.ɵɵtext(2);
i0.ɵɵelementEnd();
} if (rf & 2) {
const action_r10 = i0.ɵɵnextContext().$implicit;
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate1(" ", action_r10.Type, " ");
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Conditional_1_For_6_Conditional_5_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "span", 64);
i0.ɵɵtext(1, "Required");
i0.ɵɵelementEnd();
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Conditional_1_For_6_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 61)(1, "span", 62);
i0.ɵɵtext(2);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(3, "span", 63);
i0.ɵɵtext(4);
i0.ɵɵelementEnd();
i0.ɵɵconditionalCreate(5, ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Conditional_1_For_6_Conditional_5_Template, 2, 0, "span", 64);
i0.ɵɵelementEnd();
} if (rf & 2) {
const param_r12 = ctx.$implicit;
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(param_r12.Name);
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(param_r12.Type);
i0.ɵɵadvance();
i0.ɵɵconditional(param_r12.IsRequired ? 5 : -1);
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Conditional_1_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 59)(1, "h4");
i0.ɵɵelement(2, "i", 56);
i0.ɵɵtext(3, " Parameters ");
i0.ɵɵelementEnd();
i0.ɵɵelementStart(4, "div", 60);
i0.ɵɵrepeaterCreate(5, ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Conditional_1_For_6_Template, 6, 3, "div", 61, _forTrack1);
i0.ɵɵelementEnd()();
} if (rf & 2) {
const action_r10 = i0.ɵɵnextContext(2).$implicit;
i0.ɵɵadvance(5);
i0.ɵɵrepeater(action_r10.parameters);
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Conditional_2_For_6_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 66)(1, "span", 67);
i0.ɵɵtext(2);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(3, "span", 68);
i0.ɵɵtext(4);
i0.ɵɵelementEnd()();
} if (rf & 2) {
const code_r13 = ctx.$implicit;
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(code_r13.ResultCode);
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(code_r13.Description);
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Conditional_2_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 59)(1, "h4");
i0.ɵɵelement(2, "i", 57);
i0.ɵɵtext(3, " Result Codes ");
i0.ɵɵelementEnd();
i0.ɵɵelementStart(4, "div", 65);
i0.ɵɵrepeaterCreate(5, ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Conditional_2_For_6_Template, 5, 2, "div", 66, _forTrack1);
i0.ɵɵelementEnd()();
} if (rf & 2) {
const action_r10 = i0.ɵɵnextContext(2).$implicit;
i0.ɵɵadvance(5);
i0.ɵɵrepeater(action_r10.resultCodes);
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 51);
i0.ɵɵconditionalCreate(1, ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Conditional_1_Template, 7, 0, "div", 59);
i0.ɵɵconditionalCreate(2, ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Conditional_2_Template, 7, 0, "div", 59);
i0.ɵɵelementEnd();
} if (rf & 2) {
const action_r10 = i0.ɵɵnextContext().$implicit;
i0.ɵɵadvance();
i0.ɵɵconditional(action_r10.parameters && action_r10.parameters.length > 0 ? 1 : -1);
i0.ɵɵadvance();
i0.ɵɵconditional(action_r10.resultCodes && action_r10.resultCodes.length > 0 ? 2 : -1);
} }
function ActionGalleryComponent_Conditional_10_For_2_Conditional_20_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 52);
i0.ɵɵelement(1, "i", 18);
i0.ɵɵelementEnd();
} if (rf & 2) {
const action_r10 = i0.ɵɵnextContext().$implicit;
i0.ɵɵadvance();
i0.ɵɵclassProp("fa-check-circle", action_r10.selected)("fa-circle", !action_r10.selected);
} }
function ActionGalleryComponent_Conditional_10_For_2_Template(rf, ctx) { if (rf & 1) {
const _r9 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "div", 37);
i0.ɵɵlistener("mouseenter", function ActionGalleryComponent_Conditional_10_For_2_Template_div_mouseenter_0_listener() { const action_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.hoveredAction = action_r10.ID); })("mouseleave", function ActionGalleryComponent_Conditional_10_For_2_Template_div_mouseleave_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.hoveredAction = null); })("click", function ActionGalleryComponent_Conditional_10_For_2_Template_div_click_0_listener() { const action_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleActionSelection(action_r10)); });
i0.ɵɵelementStart(1, "div", 38);
i0.ɵɵlistener("click", function ActionGalleryComponent_Conditional_10_For_2_Template_div_click_1_listener($event) { const action_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); ctx_r1.toggleActionExpanded(action_r10); return i0.ɵɵresetView($event.stopPropagation()); });
i0.ɵɵelementStart(2, "div", 39);
i0.ɵɵelement(3, "i");
i0.ɵɵelementEnd();
i0.ɵɵelementStart(4, "div", 40)(5, "h3", 41);
i0.ɵɵtext(6);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(7, "div", 42);
i0.ɵɵconditionalCreate(8, ActionGalleryComponent_Conditional_10_For_2_Conditional_8_Template, 3, 1, "span", 43);
i0.ɵɵelementEnd()();
i0.ɵɵelementStart(9, "div", 44);
i0.ɵɵconditionalCreate(10, ActionGalleryComponent_Conditional_10_For_2_Conditional_10_Template, 2, 0, "button", 45);
i0.ɵɵelement(11, "i", 46);
i0.ɵɵelementEnd()();
i0.ɵɵelementStart(12, "div", 47)(13, "p", 48);
i0.ɵɵtext(14);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(15, "div", 49);
i0.ɵɵconditionalCreate(16, ActionGalleryComponent_Conditional_10_For_2_Conditional_16_Template, 3, 1, "span", 50);
i0.ɵɵconditionalCreate(17, ActionGalleryComponent_Conditional_10_For_2_Conditional_17_Template, 3, 1, "span", 50);
i0.ɵɵconditionalCreate(18, ActionGalleryComponent_Conditional_10_For_2_Conditional_18_Template, 3, 1, "span", 50);
i0.ɵɵelementEnd()();
i0.ɵɵconditionalCreate(19, ActionGalleryComponent_Conditional_10_For_2_Conditional_19_Template, 3, 2, "div", 51);
i0.ɵɵconditionalCreate(20, ActionGalleryComponent_Conditional_10_For_2_Conditional_20_Template, 2, 4, "div", 52);
i0.ɵɵelementEnd();
} if (rf & 2) {
const action_r10 = ctx.$implicit;
const ctx_r1 = i0.ɵɵnextContext(2);
i0.ɵɵclassProp("expanded", action_r10.expanded)("selected", action_r10.selected)("animate", ctx_r1.animateCards)("hover", ctx_r1.hoveredAction === action_r10.ID);
i0.ɵɵadvance(3);
i0.ɵɵclassMap(i0.ɵɵinterpolate1("fa-solid ", ctx_r1.getActionIcon(action_r10)));
i0.ɵɵadvance(3);
i0.ɵɵtextInterpolate(action_r10.Name);
i0.ɵɵadvance(2);
i0.ɵɵconditional(action_r10.Category ? 8 : -1);
i0.ɵɵadvance(2);
i0.ɵɵconditional(ctx_r1.config.enableQuickTest ? 10 : -1);
i0.ɵɵadvance();
i0.ɵɵclassProp("fa-chevron-down", !action_r10.expanded)("fa-chevron-up", action_r10.expanded);
i0.ɵɵadvance(3);
i0.ɵɵtextInterpolate(action_r10.Description || "No description available");
i0.ɵɵadvance(2);
i0.ɵɵconditional((action_r10.parameters == null ? null : action_r10.parameters.length) ? 16 : -1);
i0.ɵɵadvance();
i0.ɵɵconditional((action_r10.resultCodes == null ? null : action_r10.resultCodes.length) ? 17 : -1);
i0.ɵɵadvance();
i0.ɵɵconditional(action_r10.Type ? 18 : -1);
i0.ɵɵadvance();
i0.ɵɵconditional(action_r10.expanded ? 19 : -1);
i0.ɵɵadvance();
i0.ɵɵconditional(ctx_r1.config.selectionMode ? 20 : -1);
} }
function ActionGalleryComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 35);
i0.ɵɵrepeaterCreate(1, ActionGalleryComponent_Conditional_10_For_2_Template, 21, 24, "div", 36, _forTrack1);
i0.ɵɵpipe(3, "async");
i0.ɵɵelementEnd();
} if (rf & 2) {
const ctx_r1 = i0.ɵɵnextContext();
i0.ɵɵstyleProp("grid-template-columns", "repeat(" + (ctx_r1.config.gridColumns || 3) + ", 1fr)");
i0.ɵɵadvance();
i0.ɵɵrepeater(i0.ɵɵpipeBind1(3, 2, ctx_r1.filteredActions$));
} }
function ActionGalleryComponent_Conditional_15_For_13_Conditional_11_Template(rf, ctx) { if (rf & 1) {
const _r16 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "button", 54);
i0.ɵɵlistener("click", function ActionGalleryComponent_Conditional_15_For_13_Conditional_11_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r16); const action_r15 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.testAction(action_r15, $event)); });
i0.ɵɵelement(1, "i", 55);
i0.ɵɵelementEnd();
} }
function ActionGalleryComponent_Conditional_15_For_13_Conditional_12_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 52);
i0.ɵɵelement(1, "i", 18);
i0.ɵɵelementEnd();
} if (rf & 2) {
const action_r15 = i0.ɵɵnextContext().$implicit;
i0.ɵɵadvance();
i0.ɵɵclassProp("fa-check-circle", action_r15.selected)("fa-circle", !action_r15.selected);
} }
function ActionGalleryComponent_Conditional_15_For_13_Template(rf, ctx) { if (rf & 1) {
const _r14 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "div", 76);
i0.ɵɵlistener("click", function ActionGalleryComponent_Conditional_15_For_13_Template_div_click_0_listener() { const action_r15 = i0.ɵɵrestoreView(_r14).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleActionSelection(action_r15)); });
i0.ɵɵelementStart(1, "span", 70);
i0.ɵɵelement(2, "i");
i0.ɵɵtext(3);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(4, "span", 71);
i0.ɵɵtext(5);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(6, "span", 72);
i0.ɵɵtext(7);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(8, "span", 73);
i0.ɵɵtext(9);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(10, "span", 74);
i0.ɵɵconditionalCreate(11, ActionGalleryComponent_Conditional_15_For_13_Conditional_11_Template, 2, 0, "button", 45);
i0.ɵɵelementEnd();
i0.ɵɵconditionalCreate(12, ActionGalleryComponent_Conditional_15_For_13_Conditional_12_Template, 2, 4, "div", 52);
i0.ɵɵelementEnd();
} if (rf & 2) {
const action_r15 = ctx.$implicit;
const ctx_r1 = i0.ɵɵnextContext(2);
i0.ɵɵclassProp("selected", action_r15.selected);
i0.ɵɵadvance(2);
i0.ɵɵclassMap(i0.ɵɵinterpolate1("fa-solid ", ctx_r1.getActionIcon(action_r15), " action-icon"));
i0.ɵɵadvance();
i0.ɵɵtextInterpolate1(" ", action_r15.Name, " ");
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(action_r15.Category || "-");
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(action_r15.Type || "-");
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate((action_r15.parameters == null ? null : action_r15.parameters.length) || 0);
i0.ɵɵadvance(2);
i0.ɵɵconditional(ctx_r1.config.enableQuickTest ? 11 : -1);
i0.ɵɵadvance();
i0.ɵɵconditional(ctx_r1.config.selectionMode ? 12 : -1);
} }
function ActionGalleryComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 9)(1, "div", 69)(2, "span", 70);
i0.ɵɵtext(3, "Name");
i0.ɵɵelementEnd();
i0.ɵɵelementStart(4, "span", 71);
i0.ɵɵtext(5, "Category");
i0.ɵɵelementEnd();
i0.ɵɵelementStart(6, "span", 72);
i0.ɵɵtext(7, "Type");
i0.ɵɵelementEnd();
i0.ɵɵelementStart(8, "span", 73);
i0.ɵɵtext(9, "Parameters");
i0.ɵɵelementEnd();
i0.ɵɵelementStart(10, "span", 74);
i0.ɵɵtext(11, "Actions");
i0.ɵɵelementEnd()();
i0.ɵɵrepeaterCreate(12, ActionGalleryComponent_Conditional_15_For_13_Template, 13, 11, "div", 75, _forTrack1);
i0.ɵɵpipe(14, "async");
i0.ɵɵelementEnd();
} if (rf & 2) {
const ctx_r1 = i0.ɵɵnextContext();
i0.ɵɵadvance(12);
i0.ɵɵrepeater(i0.ɵɵpipeBind1(14, 0, ctx_r1.filteredActions$));
} }
export class ActionGalleryComponent {
constructor() {
this.config = {
selectionMode: false,
multiSelect: false,
showCategories: true,
showSearch: true,
defaultView: 'grid',
gridColumns: 3,
enableQuickTest: true,
theme: 'light'
};
this.preSelectedActions = [];
this.actionSelected = new EventEmitter();
this.actionsSelected = new EventEmitter();
this.actionTestRequested = new EventEmitter();
// State management
this.destroy$ = new Subject();
this.actions$ = new BehaviorSubject([]);
this.categories$ = new BehaviorSubject([]);
this.filteredActions$ = new BehaviorSubject([]);
this.categoryTree$ = new BehaviorSubject([]);
this.selectedCategory$ = new BehaviorSubject('all');
this.viewMode$ = new BehaviorSubject('grid');
this.isLoading$ = new BehaviorSubject(false);
this.selectedActions$ = new BehaviorSubject(new Set());
// Form controls
this.searchControl = new FormControl('');
// UI state
this.expandedCategories = new Set();
this.hoveredAction = null;
this.animateCards = false;
// Statistics
this.totalActions = 0;
this.categoryCounts = new Map();
}
ngOnInit() {
// Set initial view mode
this.viewMode$.next(this.config.defaultView || 'grid');
// Load data
this.loadData();
// Set up filtering
combineLatest([
this.actions$,
this.searchControl.valueChanges.pipe(debounceTime(300), distinctUntilChanged()),
this.selectedCategory$
]).pipe(takeUntil(this.destroy$)).subscribe(([actions, searchTerm, category]) => {
this.filterActions(actions, searchTerm || '', category);
});
// Initialize with pre-selected actions
if (this.preSelectedActions.length > 0) {
this.selectedActions$.next(new Set(this.preSelectedActions));
}
// Enable animations after initial load
setTimeout(() => {
this.animateCards = true;
}, 100);
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
async loadData() {
this.isLoading$.next(true);
try {
const rv = new RunView();
// Load actions and categories in parallel
const [actionsResult, categoriesResult] = await rv.RunViews([
{
EntityName: 'MJ: Actions',
ResultType: 'entity_object',
OrderBy: 'Category, Name',
MaxRows: 5000
},
{
EntityName: 'MJ: Action Categories',
ResultType: 'entity_object',
OrderBy: 'Name',
MaxRows: 1000
}
]);
if (actionsResult.Success && categoriesResult.Success) {
const actions = actionsResult.Results || [];
const categories = categoriesResult.Results || [];
// Process actions
const actionsWithDetails = actions.map(action => ({
...action,
expanded: false,
selected: this.preSelectedActions.some(id => UUIDsEqual(id, action.ID))
}));
this.actions$.next(actionsWithDetails);
this.totalActions = actions.length;
// Process categories
this.categories$.next(categories);
this.buildCategoryTree(categories, actions);
// Initial filter
this.filterActions(actionsWithDetails, '', 'all');
}
}
catch (error) {
console.error('Error loading gallery data:', error);
}
finally {
this.isLoading$.next(false);
}
}
buildCategoryTree(categories, actions) {
// Count actions per category
this.categoryCounts.clear();
actions.forEach(action => {
const count = this.categoryCounts.get(action.Category || 'Uncategorized') || 0;
this.categoryCounts.set(action.Category || 'Uncategorized', count + 1);
});
// Build tree structure
const nodeMap = new Map();
const rootNodes = [];
// Create nodes
categories.forEach(cat => {
const node = {
id: cat.ID,
name: cat.Name,
parent: cat.ParentID || undefined,
children: [],
count: this.categoryCounts.get(cat.Name) || 0,
icon: this.getCategoryIcon(cat.Name)
};
nodeMap.set(cat.ID, node);
});
// Build hierarchy
nodeMap.forEach(node => {
if (node.parent && nodeMap.has(node.parent)) {
const parent = nodeMap.get(node.parent);
parent.children.push(node);
// Accumulate counts up the tree
parent.count = (parent.count || 0) + (node.count || 0);
}
else {
rootNodes.push(node);
}
});
// Add "All" category at the top
const allNode = {
id: 'all',
name: 'All Actions',
count: this.totalActions,
icon: 'fa-th'
};
// Add "Uncategorized" if needed
const uncategorizedCount = this.categoryCounts.get('Uncategorized') || 0;
if (uncategorizedCount > 0) {
const uncategorizedNode = {
id: 'uncategorized',
name: 'Uncategorized',
count: uncategorizedCount,
icon: 'fa-question-circle'
};
rootNodes.push(uncategorizedNode);
}
this.categoryTree$.next([allNode, ...rootNodes]);
}
getCategoryIcon(categoryName) {
const iconMap = {
'Data': 'fa-database',
'Communication': 'fa-envelope',
'Integration': 'fa-plug',
'Security': 'fa-shield',
'Workflow': 'fa-project-diagram',
'AI': 'fa-brain',
'Files': 'fa-file',
'Utilities': 'fa-tools',
'System': 'fa-cog',
'Analytics': 'fa-chart-line'
};
return iconMap[categoryName] || 'fa-folder';
}
getCategoryIconClass(category) {
// Ensure we have a valid icon
if (!category.icon) {
return 'fa-solid fa-folder category-icon';
}
return `fa-solid ${category.icon} category-icon`;
}
filterActions(actions, searchTerm, category) {
let filtered = [...actions];
// Category filter
if (category && category !== 'all') {
if (category === 'uncategorized') {
filtered = filtered.filter(a => !a.Category);
}
else {
const categoryName = this.getCategoryName(category);
filtered = filtered.filter(a => a.Category === categoryName);
}
}
// Search filter
if (searchTerm) {
const term = searchTerm.toLowerCase();
filtered = filtered.filter(action => action.Name.toLowerCase().includes(term) ||
action.Description?.toLowerCase().includes(term) ||
action.Category?.toLowerCase().includes(term));
}
this.filteredActions$.next(filtered);
}
getCategoryName(categoryId) {
const category = this.categories$.value.find(c => UUIDsEqual(c.ID, categoryId));
return category?.Name || '';
}
selectCategory(categoryId) {
this.selectedCategory$.next(categoryId);
}
toggleCategoryExpanded(categoryId) {
if (this.expandedCategories.has(categoryId)) {
this.expandedCategories.delete(categoryId);
}
else {
this.expandedCategories.add(categoryId);
}
}
toggleViewMode() {
const currentMode = this.viewMode$.value;
this.viewMode$.next(currentMode === 'grid' ? 'list' : 'grid');
}
async toggleActionExpanded(action) {
action.expanded = !action.expanded;
// Load details if expanding and not already loaded
if (action.expanded && !action.parameters) {
await this.loadActionDetails(action);
}
}
async loadActionDetails(action) {
const rv = new RunView();
try {
const [paramsResult, resultCodesResult] = await rv.RunViews([
{
EntityName: 'MJ: Action Params',
ExtraFilter: `ActionID='${action.ID}'`,
OrderBy: 'Sequence',
ResultType: 'entity_object',
MaxRows: 100
},
{
EntityName: 'MJ: Action Result Codes',
ExtraFilter: `ActionID='${action.ID}'`,
OrderBy: 'ResultCode',
ResultType: 'entity_object',
MaxRows: 100
}
]);
if (paramsResult.Success) {
action.parameters = paramsResult.Results || [];
}
if (resultCodesResult.Success) {
action.resultCodes = resultCodesResult.Results || [];
}
}
catch (error) {
console.error('Error loading action details:', error);
}
}
toggleActionSelection(action) {
if (!this.config.selectionMode)
return;
const selected = this.selectedActions$.value;
if (!this.config.multiSelect) {
// Single select mode
selected.clear();
if (!action.selected) {
selected.add(action.ID);
action.selected = true;
this.actionSelected.emit(action);
}
}
else {
// Multi-select mode
if (action.selected) {
selected.delete(action.ID);
action.selected = false;
}
else {
selected.add(action.ID);
action.selected = true;
}
}
this.selectedActions$.next(new Set(selected));
if (this.config.multiSelect) {
const selectedActions = this.actions$.value.filter(a => selected.has(a.ID));
this.actionsSelected.emit(selectedActions);
}
}
testAction(action, event) {
event.stopPropagation();
if (this.config.enableQuickTest) {
// TODO: Implement test harness integration
console.log('Test action:', action.Name);
}
this.actionTestRequested.emit(action);
}
// Backs the no-results empty-state "Clear Filters" CTA: resets every dimension
// the list narrows on — search AND the selected category — so the CTA actually
// returns results instead of appearing to do nothing.
clearSearch() {
this.searchControl.reset();
this.selectedCategory$.next('all');
if (this.searchInput) {
this.searchInput.nativeElement.focus();
}
}
getSelectedActions() {
const selected = this.selectedActions$.value;
return this.actions$.value.filter(a => selected.has(a.ID));
}
getActionIcon(action) {
const typeIcons = {
'Create': 'fa-plus-circle',
'Update': 'fa-edit',
'Delete': 'fa-trash',
'Query': 'fa-search',
'Process': 'fa-cogs',
'Email': 'fa-envelope',
'Report': 'fa-file-alt',
'Export': 'fa-file-export',
'Import': 'fa-file-import',
'API': 'fa-plug',
'Script': 'fa-code'
};
for (const [key, icon] of Object.entries(typeIcons)) {
if (action.Name.toLowerCase().includes(key.toLowerCase()) ||
action.Type?.toLowerCase().includes(key.toLowerCase())) {
return icon;
}
}
return 'fa-bolt';
}
static { this.ɵfac = function ActionGalleryComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ActionGalleryComponent)(); }; }
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ActionGalleryComponent, selectors: [["mj-action-gallery"]], viewQuery: function ActionGalleryComponent_Query(rf, ctx) { if (rf & 1) {
i0.ɵɵviewQuery(_c0, 5);
} if (rf & 2) {
let _t;
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.searchInput = _t.first);
} }, inputs: { config: "config", preSelectedActions: "preSelectedActions" }, outputs: { actionSelected: "actionSelected", actionsSelected: "actionsSelected", actionTestRequested: "actionTestRequested" }, standalone: false, decls: 20, vars: 34, consts: [["searchInput", ""], [1, "action-gallery"], [1, "gallery-header"], [1, "gallery-content"], [1, "category-sidebar"], [1, "actions-container"], [1, "loading-state"], ["Variant", "no-results", "Title", "No actions found", "Message", "Try adjusting your search criteria or selecting a different category", "ActionText", "Clear Filters"], [1, "actions-grid", 3, "grid-template-columns"], [1, "actions-list"], [1, "header-content"], [1, "search-section"], [1, "search-input-wrapper"], [1, "fa-solid", "fa-search"], ["placeholder", "Search actions by name, description, or category...", 1, "mj-input", "search-input", 3, "formControl"], [1, "header-actions"], [1, "view-toggle"], ["mjButton", "", "size", "sm", 3, "click", "title"], [1, "fa-solid"], [1, "stats"], [1, "stat-item"], [1, "fa-solid", "fa-bolt"], [1, "category-tree"], [1, "category-item", 3, "selected", "has-children"], [1, "category-item", 3, "click"], [1, "category-header"], [1, "category-name"], [1, "category-count"], [1, "fa-solid", "fa-chevron-right", "expand-icon", 3, "expanded"], [1, "sub-categories"], [1, "fa-solid", "fa-chevron-right", "expand-icon", 3, "click"], [1, "category-item", "sub-category", 3, "selected"], [1, "category-item", "sub-category", 3, "click"], ["text", "Loading actions...", "size", "large"], ["Variant", "no-results", "Title", "No actions found", "Message", "Try adjusting your search criteria or selecting a different category", "ActionText", "Clear Filters", 3, "Action"], [1, "actions-grid"], [1, "action-card", 3, "expanded", "selected", "animate", "hover"], [1, "action-card", 3, "mouseenter", "mouseleave", "click"], [1, "card-header", 3, "click"], [1, "action-icon"], [1, "action-info"], [1, "action-name"], [1, "action-meta"], [1, "category-badge"], [1, "card-actions"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Test this action"], [1, "fa-solid", "expand-indicator"], [1, "card-body"], [1, "action-description"], [1, "action-stats"], [1, "stat"], [1, "card-details"], [1, "selection-indicator"], [1, "fa-solid", "fa-folder"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Test this action", 3, "click"], [1, "fa-solid", "fa-play"], [1, "fa-solid", "fa-sliders"], [1, "fa-solid", "fa-code-branch"], [1, "fa-solid", "fa-tag"], [1, "detail-section"], [1, "parameters-list"], [1, "parameter-item"], [1, "param-name"], [1, "param-type"], [1, "param-required"], [1, "result-codes-list"], [1, "result-code-item"], [1, "code-value"], [1, "code-desc"], [1, "list-header"], [1, "col-name"], [1, "col-category"], [1, "col-type"], [1, "col-params"], [1, "col-actions"], [1, "list-item", 3, "selected"], [1, "list-item", 3, "click"]], template: function ActionGalleryComponent_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 1);
i0.ɵɵconditionalCreate(1, ActionGalleryComponent_Conditional_1_Template, 19, 16, "div", 2);
i0.ɵɵelementStart(2, "div", 3);
i0.ɵɵconditionalCreate(3, ActionGalleryComponent_Conditional_3_Template, 5, 2, "div", 4);
i0.ɵɵelementStart(4, "div", 5);
i0.ɵɵconditionalCreate(5, ActionGalleryComponent_Conditional_5_Template, 2, 0, "div", 6);
i0.ɵɵpipe(6, "async");
i0.ɵɵconditionalCreate(7, ActionGalleryComponent_Conditional_7_Template, 1, 0, "mj-empty-state", 7);
i0.ɵɵpipe(8, "async");
i0.ɵɵpipe(9, "async");
i0.ɵɵconditionalCreate(10, ActionGalleryComponent_Conditional_10_Template, 4, 4, "div", 8);
i0.ɵɵpipe(11, "async");
i0.ɵɵpipe(12, "async");
i0.ɵɵpipe(13, "async");
i0.ɵɵpipe(14, "async");
i0.ɵɵconditionalCreate(15, ActionGalleryComponent_Conditional_15_Template, 15, 2, "div", 9);
i0.ɵɵpipe(16, "async");
i0.ɵɵpipe(17, "async");
i0.ɵɵpipe(18, "async");
i0.ɵɵpipe(19, "async");
i0.ɵɵelementEnd()()();
} if (rf & 2) {
let tmp_6_0;
i0.ɵɵclassProp("dark-theme", ctx.config.theme === "dark")("selection-mode", ctx.config.selectionMode);
i0.ɵɵadvance();
i0.ɵɵconditional(ctx.config.showSearch ? 1 : -1);
i0.ɵɵadvance();
i0.ɵɵclassProp("no-categories", !ctx.config.showCategories);
i0.ɵɵadvance();
i0.ɵɵconditional(ctx.config.showCategories ? 3 : -1);
i0.ɵɵadvance(2);
i0.ɵɵconditional(i0.ɵɵpipeBind1(6, 12, ctx.isLoading$) ? 5 : -1);
i0.ɵɵadvance(2);
i0.ɵɵconditional(!i0.ɵɵpipeBind1(8, 14, ctx.isLoading$) && ((tmp_6_0 = i0.ɵɵpipeBind1(9, 16, ctx.filteredActions$)) == null ? null : tmp_6_0.length) === 0 ? 7 : -1);
i0.ɵɵadvance(3);
i0.ɵɵconditional(!i0.ɵɵpipeBind1(11, 18, ctx.isLoading$) && i0.ɵɵpipeBind1(12, 20, ctx.viewMode$) === "grid" && i0.ɵɵpipeBind1(13, 22, ctx.filteredActions$) && i0.ɵɵpipeBind1(14, 24, ctx.filteredActions$).length > 0 ? 10 : -1);
i0.ɵɵadvance(5);
i0.ɵɵconditional(!i0.ɵɵpipeBind1(16, 26, ctx.isLoading$) && i0.ɵɵpipeBind1(17, 28, ctx.viewMode$) === "list" && i0.ɵɵpipeBind1(18, 30, ctx.filteredActions$) && i0.ɵɵpipeBind1(19, 32, ctx.filteredActions$).length > 0 ? 15 : -1);
} }, dependencies: [i1.DefaultValueAccessor, i1.NgControlStatus, i1.FormControlDirective, i2.MJButtonDirective, i2.MJEmptyStateComponent, i3.LoadingComponent, i4.AsyncPipe], encapsulation: 2 }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ActionGalleryComponent, [{
type: Component,
args: [{ standalone: false, selector: 'mj-action-gallery', template: "<div class=\"action-gallery\" [class.dark-theme]=\"config.theme === 'dark'\" [class.selection-mode]=\"config.selectionMode\">\n <!-- Gallery Header -->\n @if (config.showSearch) {\n <div class=\"gallery-header\">\n <div class=\"header-content\">\n <div class=\"search-section\">\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-search\"></i>\n <input\n #searchInput\n class=\"mj-input search-input\"\n [formControl]=\"searchControl\"\n placeholder=\"Search actions by name, description, or category...\"\n />\n </div>\n </div>\n \n <div class=\"header-actions\">\n <div class=\"view-toggle\">\n <button mjButton\n size=\"sm\"\n (click)=\"toggleViewMode()\"\n [title]=\"(viewMode$ | async) === 'grid' ? 'Switch to list view' : 'Switch to grid view'\">\n <i class=\"fa-solid\" [class.fa-th]=\"(viewMode$ | async) === 'grid'\" [class.fa-list]=\"(viewMode$ | async) === 'list'\"></i>\n </button>\n </div>\n <div class=\"stats\">\n <span class=\"stat-item\">\n <i class=\"fa-solid fa-bolt\"></i>\n {{ (filteredActions$ | async)?.length }} of {{ totalActions }} actions\n </span>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Main Content -->\n <div class=\"gallery-content\" [class.no-categories]=\"!config.showCategories\">\n <!-- Category Sidebar -->\n @if (config.showCategories) {\n <div class=\"category-sidebar\">\n <div class=\"category-tree\">\n @for (category of categoryTree$ | async; track category.id) {\n <div class=\"category-item\" \n [class.selected]=\"(selectedCategory$ | async) === category.id\"\n [class.has-children]=\"category.children && category.children.length > 0\"\n (click)=\"selectCategory(category.id)\">\n \n <div class=\"category-header\">\n <i class=\"fa-solid {{ category.icon }} category-icon\"></i>\n <span class=\"category-name\">{{ category.name }}</span>\n <span class=\"category-count\">{{ category.count }}</span>\n @if (category.children && category.children.length > 0) {\n <i class=\"fa-solid fa-chevron-right expand-icon\" \n [class.expanded]=\"expandedCategories.has(category.id)\"\n (click)=\"toggleCategoryExpanded(category.id); $event.stopPropagation()\"></i>\n }\n </div>\n \n <!-- Sub-categories -->\n @if (category.children && expandedCategories.has(category.id)) {\n <div class=\"sub-categories\">\n @for (subCategory of category.children; track subCategory.id) {\n <div class=\"category-item sub-category\" \n [class.selected]=\"(selectedCategory$ | async) === subCategory.id\"\n (click)=\"selectCategory(subCategory.id); $event.stopPropagation()\">\n <div class=\"category-header\">\n <i class=\"fa-solid {{ subCategory.icon }} category-icon\"></i>\n <span class=\"category-name\">{{ subCategory.name }}</span>\n <span class=\"category-count\">{{ subCategory.count }}</span>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Actions Display -->\n <div class=\"actions-container\">\n <!-- Loading State -->\n @if (isLoading$ | async) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading actions...\" size=\"large\"></mj-loading>\n </div>\n }\n\n <!-- Empty State -->\n @if (!(isLoading$ | async) && (filteredActions$ | async)?.length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Title=\"No actions found\"\n Message=\"Try adjusting your search criteria or selecting a different category\"\n ActionText=\"Clear Filters\"\n (Action)=\"clearSearch()\" />\n }\n\n <!-- Grid View -->\n @if (!(isLoading$ | async) && (viewMode$ | async) === 'grid' && (filteredActions$ | async) && (filteredActions$ | async)!.length > 0) {\n <div class=\"actions-grid\" \n [style.grid-template-columns]=\"'repeat(' + (config.gridColumns || 3) + ', 1fr)'\">\n \n @for (action of filteredActions$ | async; track action.ID) {\n <div class=\"action-card\" \n [class.expanded]=\"action.expanded\"\n [class.selected]=\"action.selected\"\n [class.animate]=\"animateCards\"\n [class.hover]=\"hoveredAction === action.ID\"\n (mouseenter)=\"hoveredAction = action.ID\"\n (mouseleave)=\"hoveredAction = null\"\n (click)=\"toggleActionSelection(action)\">\n \n <!-- Card Header -->\n <div class=\"card-header\" (click)=\"toggleActionExpanded(action); $event.stopPropagation()\">\n <div class=\"action-icon\">\n <i class=\"fa-solid {{ getActionIcon(action) }}\"></i>\n </div>\n <div class=\"action-info\">\n <h3 class=\"action-name\">{{ action.Name }}</h3>\n <div class=\"action-meta\">\n @if (action.Category) {\n <span class=\"category-badge\">\n <i class=\"fa-solid fa-folder\"></i>\n {{ action.Category }}\n </span>\n }\n </div>\n </div>\n <div class=\"card-actions\">\n @if (config.enableQuickTest) {\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"testAction(action, $event)\"\n title=\"Test this action\">\n <i class=\"fa-solid fa-play\"></i>\n </button>\n }\n <i class=\"fa-solid expand-indicator\"\n [class.fa-chevron-down]=\"!action.expanded\"\n [class.fa-chevron-up]=\"action.expanded\"></i>\n </div>\n </div>\n \n <!-- Card Body -->\n <div class=\"card-body\">\n <p class=\"action-description\">{{ action.Description || 'No description available' }}</p>\n \n <!-- Quick Stats -->\n <div class=\"action-stats\">\n @if (action.parameters?.length) {\n <span class=\"stat\">\n <i class=\"fa-solid fa-sliders\"></i>\n {{ action.parameters?.length || 0 }} params\n </span>\n }\n @if (action.resultCodes?.length) {\n <span class=\"stat\">\n <i class=\"fa-solid fa-code-branch\"></i>\n {{ action.resultCodes?.length || 0 }} results\n </span>\n }\n @if (action.Type) {\n <span class=\"stat\">\n <i class=\"fa-solid fa-tag\"></i>\n {{ action.Type }}\n </span>\n }\n </div>\n </div>\n \n <!-- Expanded Details -->\n @if (action.expanded) {\n <div class=\"card-details\">\n <!-- Parameters -->\n @if (action.parameters && action.parameters.length > 0) {\n <div class=\"detail-section\">\n <h4>\n <i class=\"fa-solid fa-sliders\"></i>\n Parameters\n </h4>\n <div class=\"parameters-list\">\n @for (param of action.parameters; track param.ID) {\n <div class=\"parameter-item\">\n <span class=\"param-name\">{{ param.Name }}</span>\n <span class=\"param-type\">{{ param.Type }}</span>\n @if (param.IsRequired) {\n <span class=\"param-required\">Required</span>\n }\n </div>\n }\n </div>\n </div>\n }\n \n <!-- Result Codes -->\n @if (action.resultCodes && action.resultCodes.length > 0) {\n <div class=\"detail-section\">\n <h4>\n <i class=\"fa-solid fa-code-branch\"></i>\n Result Codes\n </h4>\n <div class=\"result-codes-list\">\n @for (code of action.resultCodes; track code.ID) {\n <div class=\"result-code-item\">\n <span class=\"code-value\">{{ code.ResultCode }}</span>\n <span class=\"code-desc\">{{ code.Description }}</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n \n <!-- Selection Indicator -->\n @if (config.selectionMode) {\n <div class=\"selection-indicator\">\n <i class=\"fa-solid\" [class.fa-check-circle]=\"action.selected\" [class.fa-circle]=\"!action.selected\"></i>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- List View -->\n @if (!(isLoading$ | async) && (viewMode$ | async) === 'list' && (filteredActions$ | async) && (filteredActions$ | async)!.length > 0) {\n <div class=\"actions-list\">\n \n <div class=\"list-header\">\n <span class=\"col-name\">Name</span>\n <span class=\"col-category\">Category</span>\n <span class=\"col-type\">Type</span>\n <span class=\"col-params\">Parameters</span>\n <span