@memberjunction/ng-core-entity-forms 5.39.0 → 5.40.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/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js +14 -7
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts +7 -0
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +583 -559
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-execution-log-form.component.js +2 -2
- package/dist/lib/custom/Actions/action-form.component.js +2 -2
- package/dist/lib/custom/Entities/entity-form.component.js +4 -4
- package/dist/lib/custom/Entities/entity-form.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +117 -97
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-visualization.component.js +2 -2
- package/dist/lib/custom/ai-agent-run/ai-agent-run-visualization.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js +59 -51
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js +28 -10
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAPIKey/mjapikey.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAPIKey/mjapikey.form.component.js +29 -21
- package/dist/lib/generated/Entities/MJAPIKey/mjapikey.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.js +47 -11
- package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJArtifact/mjartifact.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJArtifact/mjartifact.form.component.js +24 -6
- package/dist/lib/generated/Entities/MJArtifact/mjartifact.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJArtifactVersion/mjartifactversion.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJArtifactVersion/mjartifactversion.form.component.js +27 -9
- package/dist/lib/generated/Entities/MJArtifactVersion/mjartifactversion.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJClusterAnalysis/mjclusteranalysis.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJClusterAnalysis/mjclusteranalysis.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJClusterAnalysis/mjclusteranalysis.form.component.js +93 -0
- package/dist/lib/generated/Entities/MJClusterAnalysis/mjclusteranalysis.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJClusterAnalysisCluster/mjclusteranalysiscluster.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJClusterAnalysisCluster/mjclusteranalysiscluster.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJClusterAnalysisCluster/mjclusteranalysiscluster.form.component.js +66 -0
- package/dist/lib/generated/Entities/MJClusterAnalysisCluster/mjclusteranalysiscluster.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJCompany/mjcompany.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJCompany/mjcompany.form.component.js +27 -9
- package/dist/lib/generated/Entities/MJCompany/mjcompany.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentItemTag/mjcontentitemtag.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentItemTag/mjcontentitemtag.form.component.js +13 -3
- package/dist/lib/generated/Entities/MJContentItemTag/mjcontentitemtag.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js +29 -11
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +100 -64
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJMagicLinkInvite/mjmagiclinkinvite.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkInvite/mjmagiclinkinvite.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInvite/mjmagiclinkinvite.form.component.js +173 -0
- package/dist/lib/generated/Entities/MJMagicLinkInvite/mjmagiclinkinvite.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedDomain/mjmagiclinkinvitealloweddomain.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedDomain/mjmagiclinkinvitealloweddomain.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedDomain/mjmagiclinkinvitealloweddomain.form.component.js +58 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedDomain/mjmagiclinkinvitealloweddomain.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedPath/mjmagiclinkinviteallowedpath.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedPath/mjmagiclinkinviteallowedpath.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedPath/mjmagiclinkinviteallowedpath.form.component.js +58 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedPath/mjmagiclinkinviteallowedpath.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteApplication/mjmagiclinkinviteapplication.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteApplication/mjmagiclinkinviteapplication.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteApplication/mjmagiclinkinviteapplication.form.component.js +58 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteApplication/mjmagiclinkinviteapplication.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteRole/mjmagiclinkinviterole.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteRole/mjmagiclinkinviterole.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteRole/mjmagiclinkinviterole.form.component.js +58 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteRole/mjmagiclinkinviterole.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkRedemption/mjmagiclinkredemption.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkRedemption/mjmagiclinkredemption.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkRedemption/mjmagiclinkredemption.form.component.js +68 -0
- package/dist/lib/generated/Entities/MJMagicLinkRedemption/mjmagiclinkredemption.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJResourceType/mjresourcetype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJResourceType/mjresourcetype.form.component.js +26 -8
- package/dist/lib/generated/Entities/MJResourceType/mjresourcetype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js +52 -16
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJSignatureAccount/mjsignatureaccount.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureAccount/mjsignatureaccount.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureAccount/mjsignatureaccount.form.component.js +115 -0
- package/dist/lib/generated/Entities/MJSignatureAccount/mjsignatureaccount.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureProvider/mjsignatureprovider.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureProvider/mjsignatureprovider.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureProvider/mjsignatureprovider.form.component.js +101 -0
- package/dist/lib/generated/Entities/MJSignatureProvider/mjsignatureprovider.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequest/mjsignaturerequest.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureRequest/mjsignaturerequest.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequest/mjsignaturerequest.form.component.js +153 -0
- package/dist/lib/generated/Entities/MJSignatureRequest/mjsignaturerequest.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestDocument/mjsignaturerequestdocument.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureRequestDocument/mjsignaturerequestdocument.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestDocument/mjsignaturerequestdocument.form.component.js +78 -0
- package/dist/lib/generated/Entities/MJSignatureRequestDocument/mjsignaturerequestdocument.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestLog/mjsignaturerequestlog.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureRequestLog/mjsignaturerequestlog.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestLog/mjsignaturerequestlog.form.component.js +84 -0
- package/dist/lib/generated/Entities/MJSignatureRequestLog/mjsignaturerequestlog.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestRecipient/mjsignaturerequestrecipient.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureRequestRecipient/mjsignaturerequestrecipient.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestRecipient/mjsignaturerequestrecipient.form.component.js +88 -0
- package/dist/lib/generated/Entities/MJSignatureRequestRecipient/mjsignaturerequestrecipient.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js +156 -102
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.js +34 -26
- package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJViewType/mjviewtype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJViewType/mjviewtype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJViewType/mjviewtype.form.component.js +91 -0
- package/dist/lib/generated/Entities/MJViewType/mjviewtype.form.component.js.map +1 -0
- package/dist/lib/generated/generated-forms.module.d.ts +265 -250
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
- package/dist/lib/generated/generated-forms.module.js +224 -179
- package/dist/lib/generated/generated-forms.module.js.map +1 -1
- package/package.json +36 -36
|
@@ -2320,7 +2320,7 @@ let MJActionFormComponentExtended = class MJActionFormComponentExtended extends
|
|
|
2320
2320
|
i0.ɵɵconditional(ctx.record ? 0 : -1);
|
|
2321
2321
|
i0.ɵɵadvance();
|
|
2322
2322
|
i0.ɵɵproperty("Action", ctx.record)("ActionParams", ctx.actionParams)("IsOpen", ctx.showTestHarness);
|
|
2323
|
-
} }, dependencies: [i1.ɵNgNoValidate, i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgControlStatusGroup, i1.NgModel, i1.NgForm, i2.MJButtonDirective, i2.MJAccordionPanelComponent, i2.MJAccordionTitleDirective, i2.MJDropdownComponent, i2.MJSwitchComponent, i3.MjRecordFormContainerComponent, i4.CodeEditorComponent, i5.ActionTestHarnessDialogComponent, i6.DatePipe], styles: ["\n\n[_nghost-%COMP%] {\n display: block;\n height: 100%;\n}\n\n.record-form-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n}\n\n.record-form[_ngcontent-%COMP%] {\n min-height: 0 !important;\n}\n\n\n\n.action-hero-header[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n padding: 32px;\n margin: -20px -20px 24px -20px;\n border-radius: 0 0 var(--mj-radius-lg) var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n}\n\n.hero-content[_ngcontent-%COMP%] {\n max-width: 1400px;\n margin: 0 auto;\n}\n\n.action-identity[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 24px;\n margin-bottom: 24px;\n}\n\n.action-icon-wrapper[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n border-radius: var(--mj-radius-lg);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n backdrop-filter: blur(10px);\n}\n\n.action-icon-wrapper[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-4xl);\n}\n\n.action-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.action-title-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-bottom: 12px;\n flex-wrap: wrap;\n}\n\n.action-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 2em;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-inverse);\n}\n\n.action-name-input[_ngcontent-%COMP%] {\n font-size: 1.8em;\n font-weight: var(--mj-font-semibold);\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n color: var(--mj-text-inverse);\n padding: 8px 16px;\n border-radius: var(--mj-radius-md);\n min-width: 400px;\n}\n\n.action-name-input[_ngcontent-%COMP%]::placeholder {\n color: color-mix(in srgb, var(--mj-text-inverse) 60%, transparent);\n}\n\n.action-badges[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.status-badge[_ngcontent-%COMP%], .type-badge[_ngcontent-%COMP%], .approval-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n backdrop-filter: blur(10px);\n border: 1px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n}\n\n.action-category[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n color: color-mix(in srgb, var(--mj-text-inverse) 90%, transparent);\n font-size: 0.95em;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n margin-bottom: 12px;\n}\n\n.action-category[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-inverse);\n transform: translateX(4px);\n}\n\n.action-description[_ngcontent-%COMP%] {\n color: color-mix(in srgb, var(--mj-text-inverse) 90%, transparent);\n font-size: 1.05em;\n line-height: var(--mj-leading-relaxed);\n margin: 0;\n}\n\n.action-description-input[_ngcontent-%COMP%] {\n width: 100%;\n max-width: 600px;\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n color: var(--mj-text-inverse);\n border-radius: var(--mj-radius-md);\n}\n\n.action-description-input[_ngcontent-%COMP%]::placeholder {\n color: color-mix(in srgb, var(--mj-text-inverse) 60%, transparent);\n}\n\n\n\n.action-stats[_ngcontent-%COMP%] {\n display: flex;\n gap: 24px;\n margin-bottom: 24px;\n flex-wrap: wrap;\n}\n\n.stat-card[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-text-inverse) 10%, transparent);\n backdrop-filter: blur(10px);\n border: 1px solid color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border-radius: var(--mj-radius-lg);\n padding: 16px 24px;\n display: flex;\n align-items: center;\n gap: 16px;\n min-width: 160px;\n}\n\n.stat-card[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-2xl);\n color: color-mix(in srgb, var(--mj-text-inverse) 80%, transparent);\n}\n\n.stat-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 1.4em;\n font-weight: var(--mj-font-bold);\n color: var(--mj-text-inverse);\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n color: color-mix(in srgb, var(--mj-text-inverse) 70%, transparent);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n\n\n.hero-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.hero-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n backdrop-filter: blur(10px);\n}\n\n\n\n.action-content[_ngcontent-%COMP%] {\n padding: 0 20px 20px;\n}\n\n.content-section[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n margin-bottom: 20px;\n overflow: hidden;\n transition: all var(--mj-transition-base);\n}\n\n.content-section[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background: var(--mj-bg-surface-elevated);\n cursor: pointer;\n user-select: none;\n transition: background var(--mj-transition-base);\n}\n\n.section-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.section-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.3em;\n color: var(--mj-text-primary);\n flex: 1;\n}\n\n.section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:first-child {\n font-size: 1.2em;\n color: var(--mj-text-muted);\n}\n\n.section-count[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n}\n\n.toggle-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n transition: transform 0.3s;\n}\n\n.toggle-icon.rotated[_ngcontent-%COMP%] {\n transform: rotate(-90deg);\n}\n\n.section-content[_ngcontent-%COMP%] {\n padding: 24px;\n animation: _ngcontent-%COMP%_slideDown 0.3s ease;\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n.overview-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.overview-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.overview-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.required[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.full-width[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.overview-display[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 24px;\n}\n\n.display-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.display-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-muted);\n font-weight: var(--mj-font-semibold);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.display-value[_ngcontent-%COMP%] {\n font-size: 1.1em;\n color: var(--mj-text-primary);\n}\n\n.display-value.code[_ngcontent-%COMP%] {\n font-family: 'Courier New', monospace;\n background: var(--mj-bg-surface-sunken);\n padding: 4px 8px;\n border-radius: var(--mj-radius-sm);\n}\n\n.approval-date[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n margin-left: 8px;\n}\n\n\n\n.generation-panel[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 20px;\n margin-bottom: 24px;\n}\n\n.generation-panel[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n color: var(--mj-color-indigo-500);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.prompt-section[_ngcontent-%COMP%], .comments-section[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.prompt-section[_ngcontent-%COMP%] label[_ngcontent-%COMP%], .comments-section[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 8px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n}\n\n.generation-controls[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.code-locked-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: var(--mj-status-warning);\n color: var(--mj-color-warning-800);\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.code-editor-section[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n\n.code-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.code-toolbar[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.1em;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.code-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.code-comments[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-info) 30%, transparent);\n border-radius: var(--mj-radius-md);\n padding: 16px;\n margin-top: 16px;\n}\n\n.code-comments[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n color: var(--mj-status-info);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.code-comments[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n color: var(--mj-text-secondary);\n line-height: var(--mj-leading-relaxed);\n}\n\n.approval-comments[_ngcontent-%COMP%] {\n margin-top: 16px;\n}\n\n.approval-comments[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 8px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-status-error);\n}\n\n\n\n.params-section[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-lg);\n padding: 20px;\n}\n\n.params-section.params-section-compact[_ngcontent-%COMP%] {\n padding: 12px 20px;\n}\n\n.params-section-compact[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] {\n padding: 12px !important;\n}\n\n.params-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.params-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.params-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n\n.param-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 16px;\n transition: all var(--mj-transition-base);\n}\n\n.param-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.param-card.required[_ngcontent-%COMP%] {\n border-color: var(--mj-status-warning);\n}\n\n.param-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.param-card.clickable[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n transform: translateY(-1px);\n}\n\n.param-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.param-name[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.param-badges[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.param-edit-btn[_ngcontent-%COMP%], \n.param-delete-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n border-radius: var(--mj-radius-sm);\n transition: all var(--mj-transition-base);\n}\n\n.param-edit-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.param-delete-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.param-details[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.required-badge[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\n color: var(--mj-color-warning-800);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.array-badge[_ngcontent-%COMP%] {\n background: var(--mj-color-indigo-500);\n color: var(--mj-text-inverse);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.param-type[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n margin-bottom: 8px;\n}\n\n.param-description[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.4;\n margin-bottom: 8px;\n}\n\n.param-default[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.default-label[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n}\n\n.param-default[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-family: 'Courier New', monospace;\n color: var(--mj-color-error-400);\n}\n\n\n\n\n.result-codes-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n\n.result-code-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n transition: all var(--mj-transition-base);\n position: relative;\n}\n\n.result-code-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.result-code-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-md);\n}\n\n.result-code-card.success[_ngcontent-%COMP%] {\n border-color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n}\n\n.result-code-card.failure[_ngcontent-%COMP%] {\n border-color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n}\n\n.result-actions[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n gap: 4px;\n opacity: 0;\n transition: opacity var(--mj-transition-base);\n}\n\n.result-code-card[_ngcontent-%COMP%]:hover .result-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.result-edit-btn[_ngcontent-%COMP%], \n.result-delete-btn[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n padding: 4px 8px;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n font-size: var(--mj-text-sm);\n}\n\n.result-edit-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.result-delete-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border-color: var(--mj-status-error);\n}\n\n.result-icon[_ngcontent-%COMP%] {\n font-size: 1.5em;\n flex-shrink: 0;\n}\n\n.result-code-card.success[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.result-code-card.failure[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.result-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.result-code[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n font-family: 'Courier New', monospace;\n}\n\n.result-description[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.4;\n}\n\n\n\n.execution-stats-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 20px;\n margin-bottom: 32px;\n flex-wrap: wrap;\n}\n\n.stat-box[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 200px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 20px;\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.stat-box[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 2em;\n color: var(--mj-text-muted);\n}\n\n.stat-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.executions-table[_ngcontent-%COMP%] {\n overflow-x: auto;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n}\n\n.executions-table[_ngcontent-%COMP%] table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.executions-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-default);\n}\n\n.executions-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n.execution-row[_ngcontent-%COMP%] {\n transition: background var(--mj-transition-base);\n}\n\n.execution-row[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.execution-row.success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.running[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-style: italic;\n}\n\n.result-code[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 4px 8px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n font-family: 'Courier New', monospace;\n}\n\n.result-code.success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.result-code.failure[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n\n\n.config-subsection[_ngcontent-%COMP%] {\n margin-bottom: 32px;\n}\n\n.config-subsection[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.library-cards[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.library-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.library-card[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.library-card[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:first-child {\n font-size: 1.5em;\n color: var(--mj-text-muted);\n}\n\n.library-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.library-name[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.library-items[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n font-family: 'Courier New', monospace;\n}\n\n.related-entities-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n}\n\n.related-entity-link[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.related-entity-link[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-brand-primary);\n}\n\n.related-entity-link[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.2em;\n color: var(--mj-text-muted);\n}\n\n.related-entity-link[_ngcontent-%COMP%] span[_ngcontent-%COMP%]:first-of-type {\n flex: 1;\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n}\n\n.entity-count[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-sm);\n}\n\n\n\n.loading-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px;\n color: var(--mj-text-muted);\n}\n\n.loading-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 2em;\n margin-bottom: 12px;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px;\n color: var(--mj-text-muted);\n}\n\n.empty-state.mini[_ngcontent-%COMP%] {\n padding: 20px;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 3em;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.1em;\n}\n\n.empty-hint[_ngcontent-%COMP%] {\n margin-top: 8px !important;\n font-size: var(--mj-text-sm) !important;\n opacity: 0.7;\n}\n\n.no-params[_ngcontent-%COMP%] {\n text-align: center;\n padding: 20px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n.no-params[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n}\n\n\n\n@media (max-width: 768px) {\n .action-hero-header[_ngcontent-%COMP%] {\n padding: 20px;\n }\n\n .action-identity[_ngcontent-%COMP%] {\n flex-direction: column;\n text-align: center;\n }\n\n .action-icon-wrapper[_ngcontent-%COMP%] {\n margin: 0 auto;\n }\n\n .action-title-row[_ngcontent-%COMP%] {\n justify-content: center;\n }\n\n .action-stats[_ngcontent-%COMP%] {\n justify-content: center;\n }\n\n .params-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}\n\n\n\n\n\n .k-expander {\n background: var(--mj-bg-surface-card) !important;\n border-color: var(--mj-border-default) !important;\n color: var(--mj-text-primary) !important;\n}\n\n .k-expander-header {\n background: var(--mj-bg-surface-elevated) !important;\n color: var(--mj-text-primary) !important;\n border-color: var(--mj-border-default) !important;\n}\n\n .k-expander-header:hover {\n background: var(--mj-bg-surface-hover) !important;\n}\n\n .k-expander-title {\n color: var(--mj-text-primary) !important;\n}\n\n .k-expander-indicator .k-icon, \n .k-expander-indicator .k-svg-icon {\n color: var(--mj-text-muted) !important;\n}\n\n .k-expander-content-wrapper {\n border-color: var(--mj-border-default) !important;\n}\n\n .k-expander-content {\n background: var(--mj-bg-surface-card) !important;\n border-color: var(--mj-border-default) !important;\n color: var(--mj-text-primary) !important;\n}"] }); }
|
|
2323
|
+
} }, dependencies: [i1.ɵNgNoValidate, i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgControlStatusGroup, i1.NgModel, i1.NgForm, i2.MJButtonDirective, i2.MJAccordionPanelComponent, i2.MJAccordionTitleDirective, i2.MJDropdownComponent, i2.MJSwitchComponent, i3.MjRecordFormContainerComponent, i4.CodeEditorComponent, i5.ActionTestHarnessDialogComponent, i6.DatePipe], styles: ["\n\n[_nghost-%COMP%] {\n display: block;\n height: 100%;\n}\n\n.record-form-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n}\n\n.record-form[_ngcontent-%COMP%] {\n min-height: 0 !important;\n}\n\n\n\n.action-hero-header[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n padding: 32px;\n margin: -20px -20px 24px -20px;\n border-radius: 0 0 var(--mj-radius-lg) var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n}\n\n.hero-content[_ngcontent-%COMP%] {\n max-width: 1400px;\n margin: 0 auto;\n}\n\n.action-identity[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 24px;\n margin-bottom: 24px;\n}\n\n.action-icon-wrapper[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n border-radius: var(--mj-radius-lg);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n backdrop-filter: blur(10px);\n}\n\n.action-icon-wrapper[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-4xl);\n}\n\n.action-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.action-title-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-bottom: 12px;\n flex-wrap: wrap;\n}\n\n.action-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 2em;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-inverse);\n}\n\n.action-name-input[_ngcontent-%COMP%] {\n font-size: 1.8em;\n font-weight: var(--mj-font-semibold);\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n color: var(--mj-text-inverse);\n padding: 8px 16px;\n border-radius: var(--mj-radius-md);\n min-width: 400px;\n}\n\n.action-name-input[_ngcontent-%COMP%]::placeholder {\n color: color-mix(in srgb, var(--mj-text-inverse) 60%, transparent);\n}\n\n.action-badges[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.status-badge[_ngcontent-%COMP%], .type-badge[_ngcontent-%COMP%], .approval-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n backdrop-filter: blur(10px);\n border: 1px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n}\n\n.action-category[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n color: color-mix(in srgb, var(--mj-text-inverse) 90%, transparent);\n font-size: 0.95em;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n margin-bottom: 12px;\n}\n\n.action-category[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-inverse);\n transform: translateX(4px);\n}\n\n.action-description[_ngcontent-%COMP%] {\n color: color-mix(in srgb, var(--mj-text-inverse) 90%, transparent);\n font-size: 1.05em;\n line-height: var(--mj-leading-relaxed);\n margin: 0;\n}\n\n.action-description-input[_ngcontent-%COMP%] {\n width: 100%;\n max-width: 600px;\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n color: var(--mj-text-inverse);\n border-radius: var(--mj-radius-md);\n}\n\n.action-description-input[_ngcontent-%COMP%]::placeholder {\n color: color-mix(in srgb, var(--mj-text-inverse) 60%, transparent);\n}\n\n\n\n.action-stats[_ngcontent-%COMP%] {\n display: flex;\n gap: 24px;\n margin-bottom: 24px;\n flex-wrap: wrap;\n}\n\n.stat-card[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-text-inverse) 10%, transparent);\n backdrop-filter: blur(10px);\n border: 1px solid color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border-radius: var(--mj-radius-lg);\n padding: 16px 24px;\n display: flex;\n align-items: center;\n gap: 16px;\n min-width: 160px;\n}\n\n.stat-card[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-2xl);\n color: color-mix(in srgb, var(--mj-text-inverse) 80%, transparent);\n}\n\n.stat-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 1.4em;\n font-weight: var(--mj-font-bold);\n color: var(--mj-text-inverse);\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n color: color-mix(in srgb, var(--mj-text-inverse) 70%, transparent);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n\n\n.hero-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.hero-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n backdrop-filter: blur(10px);\n}\n\n\n\n.action-content[_ngcontent-%COMP%] {\n padding: 0 20px 20px;\n}\n\n.content-section[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n margin-bottom: 20px;\n overflow: hidden;\n transition: all var(--mj-transition-base);\n}\n\n.content-section[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background: var(--mj-bg-surface-elevated);\n cursor: pointer;\n user-select: none;\n transition: background var(--mj-transition-base);\n}\n\n.section-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.section-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.3em;\n color: var(--mj-text-primary);\n flex: 1;\n}\n\n.section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:first-child {\n font-size: 1.2em;\n color: var(--mj-text-muted);\n}\n\n.section-count[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n}\n\n.toggle-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n transition: transform 0.3s;\n}\n\n.toggle-icon.rotated[_ngcontent-%COMP%] {\n transform: rotate(-90deg);\n}\n\n.section-content[_ngcontent-%COMP%] {\n padding: 24px;\n animation: _ngcontent-%COMP%_slideDown 0.3s ease;\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n.overview-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.overview-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.overview-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.required[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.full-width[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.overview-display[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 24px;\n}\n\n.display-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.display-field[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-muted);\n font-weight: var(--mj-font-semibold);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.display-value[_ngcontent-%COMP%] {\n font-size: 1.1em;\n color: var(--mj-text-primary);\n}\n\n.display-value.code[_ngcontent-%COMP%] {\n font-family: 'Courier New', monospace;\n background: var(--mj-bg-surface-sunken);\n padding: 4px 8px;\n border-radius: var(--mj-radius-sm);\n}\n\n.approval-date[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n margin-left: 8px;\n}\n\n\n\n.generation-panel[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 20px;\n margin-bottom: 24px;\n}\n\n.generation-panel[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n color: var(--mj-color-indigo-500);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.prompt-section[_ngcontent-%COMP%], .comments-section[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n}\n\n.prompt-section[_ngcontent-%COMP%] label[_ngcontent-%COMP%], .comments-section[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 8px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n}\n\n.generation-controls[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.code-locked-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: var(--mj-status-warning);\n color: var(--mj-color-warning-800);\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.code-editor-section[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n\n.code-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.code-toolbar[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.1em;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.code-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.code-comments[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-info) 30%, transparent);\n border-radius: var(--mj-radius-md);\n padding: 16px;\n margin-top: 16px;\n}\n\n.code-comments[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n color: var(--mj-status-info);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.code-comments[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n color: var(--mj-text-secondary);\n line-height: var(--mj-leading-relaxed);\n}\n\n.approval-comments[_ngcontent-%COMP%] {\n margin-top: 16px;\n}\n\n.approval-comments[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 8px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-status-error);\n}\n\n\n\n.params-section[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-lg);\n padding: 20px;\n}\n\n.params-section.params-section-compact[_ngcontent-%COMP%] {\n padding: 12px 20px;\n}\n\n.params-section-compact[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] {\n padding: 12px !important;\n}\n\n.params-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.params-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.params-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n\n.param-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 16px;\n transition: all var(--mj-transition-base);\n}\n\n.param-card[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.param-card.required[_ngcontent-%COMP%] {\n border-color: var(--mj-status-warning);\n}\n\n.param-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.param-card.clickable[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n transform: translateY(-1px);\n}\n\n.param-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.param-name[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.param-badges[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.param-edit-btn[_ngcontent-%COMP%], \n.param-delete-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n border-radius: var(--mj-radius-sm);\n transition: all var(--mj-transition-base);\n}\n\n.param-edit-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.param-delete-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.param-details[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.required-badge[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\n color: var(--mj-color-warning-800);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.array-badge[_ngcontent-%COMP%] {\n background: var(--mj-color-indigo-500);\n color: var(--mj-text-inverse);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.param-type[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n margin-bottom: 8px;\n}\n\n.param-description[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.4;\n margin-bottom: 8px;\n}\n\n.param-default[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.default-label[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n}\n\n.param-default[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-family: 'Courier New', monospace;\n color: var(--mj-color-error-400);\n}\n\n\n\n\n.result-codes-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n\n.result-code-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n transition: all var(--mj-transition-base);\n position: relative;\n}\n\n.result-code-card.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.result-code-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-md);\n}\n\n.result-code-card.success[_ngcontent-%COMP%] {\n border-color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n}\n\n.result-code-card.failure[_ngcontent-%COMP%] {\n border-color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n}\n\n.result-actions[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n gap: 4px;\n opacity: 0;\n transition: opacity var(--mj-transition-base);\n}\n\n.result-code-card[_ngcontent-%COMP%]:hover .result-actions[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.result-edit-btn[_ngcontent-%COMP%], \n.result-delete-btn[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n padding: 4px 8px;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n font-size: var(--mj-text-sm);\n}\n\n.result-edit-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.result-delete-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border-color: var(--mj-status-error);\n}\n\n.result-icon[_ngcontent-%COMP%] {\n font-size: 1.5em;\n flex-shrink: 0;\n}\n\n.result-code-card.success[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.result-code-card.failure[_ngcontent-%COMP%] .result-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.result-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.result-code[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n font-family: 'Courier New', monospace;\n}\n\n.result-description[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.4;\n}\n\n\n\n.execution-stats-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 20px;\n margin-bottom: 32px;\n flex-wrap: wrap;\n}\n\n.stat-box[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 200px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 20px;\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.stat-box[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 2em;\n color: var(--mj-text-muted);\n}\n\n.stat-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.executions-table[_ngcontent-%COMP%] {\n overflow-x: auto;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n}\n\n.executions-table[_ngcontent-%COMP%] table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.executions-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-default);\n}\n\n.executions-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n.execution-row[_ngcontent-%COMP%] {\n transition: background var(--mj-transition-base);\n}\n\n.execution-row[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.execution-row.success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.running[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-style: italic;\n}\n\n.result-code[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 4px 8px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n font-family: 'Courier New', monospace;\n}\n\n.result-code.success[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.result-code.failure[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n\n\n.config-subsection[_ngcontent-%COMP%] {\n margin-bottom: 32px;\n}\n\n.config-subsection[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.library-cards[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.library-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.library-card[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.library-card[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:first-child {\n font-size: 1.5em;\n color: var(--mj-text-muted);\n}\n\n.library-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.library-name[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.library-items[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n font-family: 'Courier New', monospace;\n}\n\n.related-entities-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n}\n\n.related-entity-link[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.related-entity-link[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-brand-primary);\n}\n\n.related-entity-link[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.2em;\n color: var(--mj-text-muted);\n}\n\n.related-entity-link[_ngcontent-%COMP%] span[_ngcontent-%COMP%]:first-of-type {\n flex: 1;\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n}\n\n.entity-count[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-sm);\n}\n\n\n\n.loading-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px;\n color: var(--mj-text-muted);\n}\n\n.loading-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 2em;\n margin-bottom: 12px;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px;\n color: var(--mj-text-muted);\n}\n\n.empty-state.mini[_ngcontent-%COMP%] {\n padding: 20px;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 3em;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.1em;\n}\n\n.empty-hint[_ngcontent-%COMP%] {\n margin-top: 8px !important;\n font-size: var(--mj-text-sm) !important;\n opacity: 0.7;\n}\n\n.no-params[_ngcontent-%COMP%] {\n text-align: center;\n padding: 20px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n.no-params[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n}\n\n\n\n@media (max-width: 768px) {\n .action-hero-header[_ngcontent-%COMP%] {\n padding: 20px;\n }\n\n .action-identity[_ngcontent-%COMP%] {\n flex-direction: column;\n text-align: center;\n }\n\n .action-icon-wrapper[_ngcontent-%COMP%] {\n margin: 0 auto;\n }\n\n .action-title-row[_ngcontent-%COMP%] {\n justify-content: center;\n }\n\n .action-stats[_ngcontent-%COMP%] {\n justify-content: center;\n }\n\n .params-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}"] }); }
|
|
2324
2324
|
};
|
|
2325
2325
|
MJActionFormComponentExtended = __decorate([
|
|
2326
2326
|
RegisterClass(BaseFormComponent, 'MJ: Actions')
|
|
@@ -2328,7 +2328,7 @@ MJActionFormComponentExtended = __decorate([
|
|
|
2328
2328
|
export { MJActionFormComponentExtended };
|
|
2329
2329
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJActionFormComponentExtended, [{
|
|
2330
2330
|
type: Component,
|
|
2331
|
-
args: [{ standalone: false, selector: 'mj-action-form', template: "<!--\n NOTE: We wrap the form content in <mj-record-form-container> rather than\n using <mj-form-toolbar> directly. The container owns the toolbar AND the\n panels behind History/Tags/List buttons \u2014 without it those buttons emit\n events that nothing listens to and the features silently break. Follow\n this pattern for every custom entity form \u2014 see packages/Angular/CLAUDE.md.\n-->\n@if (record) {\n<mj-record-form-container [Record]=\"record\" [FormComponent]=\"this\"\n [ToolbarConfig]=\"toolbarConfig\"\n [WidthMode]=\"'full-width'\"\n (Navigate)=\"OnFormNavigate($event)\"\n (DeleteRequested)=\"OnDeleteRequested()\"\n (FavoriteToggled)=\"OnFavoriteToggled()\"\n (HistoryRequested)=\"OnHistoryRequested()\"\n (ListManagementRequested)=\"OnListManagementRequested()\">\n <form class=\"record-form\" #form=\"ngForm\" style=\"display: flex; flex-direction: column; height: 100%; overflow: hidden;\">\n\n <!-- Main Content Area -->\n <div class=\"action-main-area\" style=\"display: flex; flex-direction: column; flex: 1; min-height: 0; overflow-y: auto;\">\n \n <!-- Header Section -->\n <div class=\"action-header\" style=\"flex-shrink: 0; padding: 20px; background: var(--mj-bg-surface-card); border-bottom: 2px solid var(--mj-border-default);\">\n <div style=\"display: flex; justify-content: space-between; align-items: flex-start; gap: 20px;\">\n \n <!-- Left: Action Info -->\n <div style=\"flex: 1; min-width: 0;\">\n <div style=\"display: flex; align-items: center; gap: 12px; margin-bottom: 8px;\">\n <i [class]=\"getActionIcon()\" [style.color]=\"getTypeColor()\" style=\"font-size: 1.4em;\"></i>\n @if (EditMode) {\n <input type=\"text\" class=\"mj-input\"\n [(ngModel)]=\"record.Name\"\n name=\"actionName\"\n placeholder=\"Enter action name...\"\n style=\"font-size: 1.2em; font-weight: 600; min-width: 300px; flex: 1;\" />\n } @else {\n <h4 style=\"margin: 0; color: var(--mj-text-secondary); font-weight: 600; flex: 1;\">{{ record.Name || 'Untitled Action' }}</h4>\n <span class=\"status-chip\"\n [attr.data-color]=\"record.Status === 'Active' ? 'success' : record.Status === 'Pending' ? 'warning' : 'error'\">\n {{ record.Status }}\n </span>\n @if (hasCodeApproval && record.CodeApprovalStatus) {\n <span class=\"status-chip\"\n [attr.data-color]=\"record.CodeApprovalStatus === 'Approved' ? 'success' : record.CodeApprovalStatus === 'Pending' ? 'warning' : 'error'\"\n [title]=\"'Code ' + record.CodeApprovalStatus\">\n <i [class]=\"'fa-solid ' + getApprovalStatusIcon()\" style=\"margin-right: 4px;\"></i>\n {{ record.CodeApprovalStatus }}\n </span>\n }\n }\n </div>\n \n <!-- Status and Type Editors when in edit mode -->\n @if (EditMode) {\n <div style=\"display: flex; gap: 16px; margin-bottom: 12px; flex-wrap: wrap;\">\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">Status</label>\n <mj-dropdown [(ngModel)]=\"record.Status\"\n name=\"actionStatus\"\n [Data]=\"[{text: 'Active', value: 'Active'}, {text: 'Pending', value: 'Pending'}, {text: 'Disabled', value: 'Disabled'}]\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n style=\"width: 150px;\">\n </mj-dropdown>\n </div>\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">\n Type <span style=\"color: var(--mj-status-error);\">*</span>\n </label>\n <mj-dropdown [(ngModel)]=\"record.Type\"\n name=\"actionType\"\n [Data]=\"[{text: 'Generated', value: 'Generated'}, {text: 'Custom', value: 'Custom'}]\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n style=\"width: 150px;\">\n </mj-dropdown>\n </div>\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">\n Category <span style=\"color: var(--mj-status-error);\">*</span>\n </label>\n <mj-dropdown [(ngModel)]=\"record.CategoryID\"\n name=\"categoryID\"\n [Data]=\"[]\"\n Placeholder=\"Select category...\"\n style=\"width: 200px;\">\n </mj-dropdown>\n </div>\n @if (hasCodeApproval) {\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">\n <i [class]=\"'fa-solid ' + getApprovalStatusIcon()\" [style.color]=\"getApprovalStatusColor()\" style=\"margin-right: 4px;\"></i>\n Code Approval\n </label>\n <mj-dropdown [(ngModel)]=\"record.CodeApprovalStatus\"\n name=\"codeApprovalStatus\"\n [Data]=\"[{text: 'Approved', value: 'Approved'}, {text: 'Pending', value: 'Pending'}, {text: 'Rejected', value: 'Rejected'}]\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n style=\"width: 160px;\">\n </mj-dropdown>\n </div>\n }\n </div>\n }\n \n @if (EditMode) {\n <textarea class=\"mj-textarea\" [(ngModel)]=\"record.Description\" \n name=\"actionDescription\"\n [rows]=\"2\"\n placeholder=\"Enter action description...\"\n style=\"width: 100%; max-width: 600px; margin-bottom: 12px;\">\n </textarea>\n } @else if (record.Description) {\n <p style=\"margin: 0 0 12px 0; color: var(--mj-text-muted); font-size: 0.9em; line-height: 1.4;\">{{ record.Description }}</p>\n }\n \n <!-- Quick Config Row -->\n <div class=\"quick-config\" style=\"display: flex; align-items: center; gap: 16px; flex-wrap: wrap;\">\n @if (category) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-folder\" style=\"color: var(--mj-text-muted);\"></i>\n <span style=\"color: var(--mj-text-muted);\">Category:</span>\n <span style=\"color: var(--mj-text-secondary); font-weight: 500; cursor: pointer;\" (click)=\"navigateToCategory()\">\n {{ category.Name }}\n <i class=\"fa-solid fa-external-link\" style=\"font-size: 0.75em; margin-left: 4px;\"></i>\n </span>\n </div>\n }\n \n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-cube\" style=\"color: var(--mj-text-muted);\"></i>\n <span style=\"color: var(--mj-text-muted);\">Type:</span>\n <span style=\"color: var(--mj-text-secondary); font-weight: 500;\">{{ record.Type }}</span>\n </div>\n \n @if (hasCodeApproval && record.CodeApprovalStatus) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i [class]=\"'fa-solid ' + getApprovalStatusIcon()\" [style.color]=\"getApprovalStatusColor()\"></i>\n <span style=\"color: var(--mj-text-muted);\">Code:</span>\n <span [style.color]=\"getApprovalStatusColor()\" style=\"font-weight: 500;\">{{ record.CodeApprovalStatus }}</span>\n </div>\n }\n \n @if (actionParams.length > 0) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-sliders\" style=\"color: var(--mj-text-muted);\"></i>\n <span style=\"color: var(--mj-text-secondary); font-weight: 500;\">{{ actionParams.length }} Parameters</span>\n </div>\n }\n </div>\n </div>\n \n <!-- Right: Action Buttons -->\n <div class=\"action-buttons\" style=\"display: flex; flex-direction: column; gap: 8px; align-items: flex-end;\">\n <div style=\"display: flex; gap: 8px;\">\n @if (record.ID && !EditMode) {\n <button mjButton variant=\"primary\" size=\"lg\"\n (click)=\"openTestHarness()\"\n title=\"Open Run Harness\"\n [disabled]=\"record.Status !== 'Active'\">\n <i class=\"fa-solid fa-play\"></i> Run\n </button>\n }\n @if (EditMode && record.Type === 'Generated') {\n <button mjButton variant=\"outline\" size=\"md\"\n (click)=\"regenerateCode()\"\n title=\"Regenerate Code\">\n <i class=\"fa-solid fa-robot\"></i> Regenerate\n </button>\n }\n </div>\n \n @if (!EditMode && record.Status !== 'Active' && record.ID) {\n <div style=\"font-size: 0.75em; color: var(--mj-status-error); text-align: right;\">\n Action must be Active to execute\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Configuration Sections with Expansion Panels -->\n <div class=\"configuration-sections\" style=\"flex: 1; background: var(--mj-bg-surface-card); border-top: 2px solid var(--mj-border-default); padding: 16px; min-height: 0;\">\n \n <!-- Parameters Section (FIRST) -->\n <mj-accordion-panel\n [Expanded]=\"true\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-sliders\" style=\"color: var(--mj-text-muted);\"></i>\n Parameters\n @if (actionParams.length > 0) {\n <span style=\"background: var(--mj-status-info); color: var(--mj-text-inverse); padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n {{ actionParams.length }}\n </span>\n }\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n @if (isLoadingParams) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading parameters...\n </div>\n } @else if (actionParams.length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-sliders\" style=\"font-size: 2em; color: var(--mj-text-muted); opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: var(--mj-text-muted);\">No parameters defined</p>\n @if (EditMode && record.IsSaved) {\n <p style=\"margin: 8px 0 0 0; font-size: 0.85em; color: var(--mj-text-muted);\">Add parameters to define inputs and outputs for this action</p>\n }\n </div>\n } @else {\n <!-- Input Parameters Grid -->\n <div class=\"params-section\">\n <div class=\"params-header\">\n <h3><i class=\"fa-solid fa-sign-in-alt\"></i> Input Parameters</h3>\n @if (EditMode && record.IsSaved) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"addParameter('Input')\">\n <i class=\"fa-solid fa-plus\"></i> Add Input\n </button>\n }\n </div>\n \n @if (getInputParams().length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-inbox\" style=\"font-size: 2em; color: var(--mj-text-muted); opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: var(--mj-text-muted);\">No input parameters defined</p>\n </div>\n } @else {\n <div class=\"params-grid\">\n @for (param of getInputParams(); track param.ID) {\n <div class=\"param-card\" [class.required]=\"param.IsRequired\" \n [class.clickable]=\"true\"\n (click)=\"onParamClick(param, $event)\">\n <div class=\"param-header\">\n <span class=\"param-name\">{{ param.Name }}</span>\n <div class=\"param-badges\">\n @if (param.IsRequired) {\n <span class=\"required-badge\">Required</span>\n }\n @if (param.IsArray) {\n <span class=\"array-badge\">Array</span>\n }\n @if (EditMode) {\n <button class=\"param-edit-btn\" (click)=\"editParameter(param)\" title=\"Edit parameter\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"param-delete-btn\" (click)=\"deleteParameter(param)\" title=\"Delete parameter\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </div>\n <div class=\"param-details\">\n <div class=\"param-type\">{{ param.ValueType }}</div>\n @if (param.Description) {\n <div class=\"param-description\">{{ param.Description }}</div>\n }\n @if (param.DefaultValue) {\n <div class=\"param-default\">\n <span class=\"default-label\">Default:</span>\n <code>{{ param.DefaultValue }}</code>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Output Parameters Grid -->\n <div class=\"params-section\" style=\"margin-top: 24px;\" \n [class.params-section-compact]=\"getOutputParams().length === 0\">\n <div class=\"params-header\">\n <h3><i class=\"fa-solid fa-sign-out-alt\"></i> Output Parameters</h3>\n @if (EditMode && record.IsSaved) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"addParameter('Output')\">\n <i class=\"fa-solid fa-plus\"></i> Add Output\n </button>\n }\n </div>\n \n @if (getOutputParams().length === 0) {\n <div class=\"empty-state\" style=\"padding: 20px; text-align: center;\">\n <i class=\"fa-solid fa-inbox\" style=\"font-size: 2em; color: var(--mj-text-muted); opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: var(--mj-text-muted);\">No output parameters defined</p>\n </div>\n } @else {\n <div class=\"params-grid\">\n @for (param of getOutputParams(); track param.ID) {\n <div class=\"param-card\"\n [class.clickable]=\"true\"\n (click)=\"onParamClick(param, $event)\">\n <div class=\"param-header\">\n <span class=\"param-name\">{{ param.Name }}</span>\n <div class=\"param-badges\">\n @if (param.IsArray) {\n <span class=\"array-badge\">Array</span>\n }\n @if (EditMode) {\n <button class=\"param-edit-btn\" (click)=\"editParameter(param)\" title=\"Edit parameter\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"param-delete-btn\" (click)=\"deleteParameter(param)\" title=\"Delete parameter\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </div>\n <div class=\"param-details\">\n <div class=\"param-type\">{{ param.ValueType }}</div>\n @if (param.Description) {\n <div class=\"param-description\">{{ param.Description }}</div>\n }\n @if (param.DefaultValue) {\n <div class=\"param-default\">\n <span class=\"default-label\">Default:</span>\n <code>{{ param.DefaultValue }}</code>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </mj-accordion-panel>\n\n <!-- Code & Generation Section (Only for Generated type) -->\n @if (record.Type === 'Generated') {\n <mj-accordion-panel\n [Expanded]=\"expandedSections.code\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-code\" style=\"color: var(--mj-text-muted);\"></i>\n Code & Generation\n @if (record.CodeLocked) {\n <span style=\"background: var(--mj-status-warning); color: var(--mj-color-warning-800); padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n <i class=\"fa-solid fa-lock\"></i> Locked\n </span>\n }\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n @if (EditMode) {\n <div class=\"generation-panel\">\n <h3><i class=\"fa-solid fa-robot\"></i> AI Generation</h3>\n <div class=\"prompt-section\">\n <label>User Prompt</label>\n <textarea class=\"mj-textarea\" [(ngModel)]=\"record.UserPrompt\"\n name=\"userPrompt\"\n [rows]=\"8\"\n placeholder=\"Describe what this action should do...\"\n style=\"width: 100%; min-height: 120px;\">\n </textarea>\n </div>\n <div class=\"comments-section\">\n <label>Internal Comments (not sent to AI)</label>\n <textarea class=\"mj-textarea\" [(ngModel)]=\"record.UserComments\"\n name=\"userComments\"\n [rows]=\"2\"\n placeholder=\"Internal notes...\"\n style=\"width: 100%;\">\n </textarea>\n </div>\n <div class=\"generation-controls\">\n <mj-switch [(ngModel)]=\"record.CodeLocked\"\n name=\"codeLocked\">\n </mj-switch>\n <label style=\"margin-left: 8px;\">Lock Code (prevent regeneration)</label>\n </div>\n </div>\n }\n \n <div class=\"code-editor-section\">\n <div class=\"code-toolbar\">\n <h3><i class=\"fa-solid fa-file-code\"></i> Action Code</h3>\n <div class=\"code-actions\">\n @if (record.CodeComments) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"toggleCodeComments()\">\n <i class=\"fa-solid fa-comment\"></i> \n {{ showCodeComments ? 'Hide' : 'Show' }} AI Comments\n </button>\n }\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"copyToClipboard(record.Code || '')\">\n <i class=\"fa-solid fa-copy\"></i> Copy\n </button>\n </div>\n </div>\n <mj-code-editor \n [(ngModel)]=\"record.Code\"\n name=\"actionCode\"\n [readonly]=\"!EditMode || record.CodeLocked\"\n [language]=\"codeLanguage\"\n [lineWrapping]=\"true\"\n style=\"height: 400px; width: 100%;\">\n </mj-code-editor>\n \n @if (showCodeComments && record.CodeComments) {\n <div class=\"code-comments\">\n <h4><i class=\"fa-solid fa-robot\"></i> AI Explanation</h4>\n <p>{{ record.CodeComments }}</p>\n </div>\n }\n \n @if (EditMode && record.CodeApprovalStatus === 'Rejected') {\n <div class=\"approval-comments\">\n <label>Rejection Comments</label>\n <textarea class=\"mj-textarea\" [(ngModel)]=\"record.CodeApprovalComments\"\n name=\"codeApprovalComments\"\n [rows]=\"2\"\n placeholder=\"Explain why the code was rejected...\"\n style=\"width: 100%;\">\n </textarea>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n }\n\n <!-- Runtime Action Configuration Section (only for Type='Runtime') -->\n @if (isRuntimeAction) {\n <mj-accordion-panel\n [Expanded]=\"true\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-wand-magic-sparkles\" style=\"color: var(--mj-status-warning);\"></i>\n Runtime Configuration & Permissions\n <span style=\"color: var(--mj-text-muted); font-weight: 400; font-size: 0.85em;\">\n ({{ getRuntimeConfigSummary() }})\n </span>\n </span>\n </ng-template>\n\n <div style=\"padding: 16px;\">\n @if (!runtimeConfig) {\n <div style=\"padding: 12px; background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface)); border-left: 3px solid var(--mj-status-error); border-radius: 4px;\">\n <i class=\"fa-solid fa-triangle-exclamation\" style=\"color: var(--mj-status-error); margin-right: 8px;\"></i>\n <strong>Missing or malformed RuntimeActionConfiguration.</strong>\n This Runtime action cannot run until a valid configuration is supplied. Approval should not be granted in this state.\n </div>\n } @else {\n @if (getWildcardFlags().any) {\n <div style=\"padding: 12px; background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); border-left: 3px solid var(--mj-status-warning); border-radius: 4px; margin-bottom: 16px;\">\n <div style=\"font-weight: 600; margin-bottom: 4px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-triangle-exclamation\" style=\"color: var(--mj-status-warning); margin-right: 6px;\"></i>\n Wildcard permissions enabled\n </div>\n <div style=\"color: var(--mj-text-secondary); font-size: 0.9em;\">\n This runtime action has one or more wildcard flags set that bypass the specific allowlists below:\n @if (getWildcardFlags().entity) { <strong>allowAnyEntity</strong> }\n @if (getWildcardFlags().action) { <strong>allowAnyAction</strong> }\n @if (getWildcardFlags().agent) { <strong>allowAnyAgent</strong> }\n . Approving grants this action unrestricted access to that namespace on behalf of any user who invokes it. Only approve if the action is framework-authored or you have personally reviewed every place it touches those resources.\n </div>\n </div>\n }\n <!-- Declared permissions \u2014 the security contract an approver is blessing -->\n <div style=\"display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; margin-bottom: 20px;\">\n <!-- Entities -->\n <div style=\"border: 1px solid var(--mj-border-default); border-radius: 6px; padding: 12px; background: var(--mj-bg-surface-card);\">\n <div style=\"font-weight: 600; margin-bottom: 8px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-database\" style=\"margin-right: 6px; color: var(--mj-brand-primary);\"></i>\n Allowed Entities ({{ getAllowedEntities().length }})\n </div>\n @if (getAllowedEntities().length === 0) {\n <div style=\"color: var(--mj-text-muted); font-style: italic;\">None requested</div>\n } @else {\n <div style=\"display: flex; flex-direction: column; gap: 4px;\">\n @for (e of getAllowedEntities(); track e.id) {\n <span style=\"background: var(--mj-bg-surface-sunken); padding: 4px 8px; border-radius: 4px; font-size: 0.9em; color: var(--mj-text-primary);\">\n {{ e.name }}\n </span>\n }\n </div>\n }\n </div>\n\n <!-- Actions -->\n <div style=\"border: 1px solid var(--mj-border-default); border-radius: 6px; padding: 12px; background: var(--mj-bg-surface-card);\">\n <div style=\"font-weight: 600; margin-bottom: 8px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-bolt\" style=\"margin-right: 6px; color: var(--mj-brand-primary);\"></i>\n Allowed Actions ({{ getAllowedActions().length }})\n </div>\n @if (getAllowedActions().length === 0) {\n <div style=\"color: var(--mj-text-muted); font-style: italic;\">None requested</div>\n } @else {\n <div style=\"display: flex; flex-direction: column; gap: 4px;\">\n @for (a of getAllowedActions(); track a.id) {\n <span style=\"background: var(--mj-bg-surface-sunken); padding: 4px 8px; border-radius: 4px; font-size: 0.9em; color: var(--mj-text-primary);\">\n {{ a.name }}\n </span>\n }\n </div>\n }\n </div>\n\n <!-- Agents -->\n <div style=\"border: 1px solid var(--mj-border-default); border-radius: 6px; padding: 12px; background: var(--mj-bg-surface-card);\">\n <div style=\"font-weight: 600; margin-bottom: 8px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-robot\" style=\"margin-right: 6px; color: var(--mj-brand-primary);\"></i>\n Allowed Agents ({{ getAllowedAgents().length }})\n </div>\n @if (getAllowedAgents().length === 0) {\n <div style=\"color: var(--mj-text-muted); font-style: italic;\">None requested</div>\n } @else {\n <div style=\"display: flex; flex-direction: column; gap: 4px;\">\n @for (g of getAllowedAgents(); track g.id) {\n <span style=\"background: var(--mj-bg-surface-sunken); padding: 4px 8px; border-radius: 4px; font-size: 0.9em; color: var(--mj-text-primary);\">\n {{ g.name }}\n </span>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Limits + libraries -->\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px;\">\n <div>\n <div style=\"font-weight: 600; margin-bottom: 6px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-gauge-high\" style=\"margin-right: 6px; color: var(--mj-text-muted);\"></i>\n Resource Limits\n </div>\n <div style=\"color: var(--mj-text-secondary); font-size: 0.9em;\">\n <div>Max memory: {{ getRuntimeLimits().maxMemoryMB }} MB</div>\n <div>Max bridge calls: {{ getRuntimeLimits().maxBridgeCalls }}</div>\n @if (record.MaxExecutionTimeMS) {\n <div>Max execution time: {{ record.MaxExecutionTimeMS }} ms</div>\n }\n </div>\n </div>\n <div>\n <div style=\"font-weight: 600; margin-bottom: 6px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-book\" style=\"margin-right: 6px; color: var(--mj-text-muted);\"></i>\n Additional Libraries\n </div>\n @if (getRequestedLibraries().length === 0) {\n <div style=\"color: var(--mj-text-muted); font-style: italic;\">None (only default set: lodash, date-fns, uuid, validator)</div>\n } @else {\n <div style=\"display: flex; flex-wrap: wrap; gap: 4px;\">\n @for (lib of getRequestedLibraries(); track lib.name) {\n <span style=\"background: var(--mj-bg-surface-sunken); padding: 2px 8px; border-radius: 10px; font-size: 0.85em;\">\n {{ lib.name }}@if (lib.version) {<span style=\"color: var(--mj-text-muted);\"> @{{ lib.version }}</span>}\n </span>\n }\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Code payload -->\n <div>\n <div style=\"font-weight: 600; margin-bottom: 6px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-code\" style=\"margin-right: 6px; color: var(--mj-text-muted);\"></i>\n JavaScript Payload\n </div>\n <pre style=\"background: var(--mj-bg-surface-sunken); color: var(--mj-text-primary); padding: 12px; border-radius: 4px; overflow-x: auto; max-height: 400px; font-family: 'SF Mono', Monaco, Consolas, monospace; font-size: 0.85em; margin: 0;\"><code>{{ record.Code }}</code></pre>\n </div>\n\n <!-- Approval actions (Runtime-specific labels) -->\n @if (EditMode && record.CodeApprovalStatus === 'Pending') {\n <div style=\"margin-top: 16px; padding: 12px; background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface)); border-radius: 6px;\">\n <div style=\"font-weight: 600; margin-bottom: 8px;\">\n <i class=\"fa-solid fa-circle-exclamation\" style=\"color: var(--mj-status-warning); margin-right: 6px;\"></i>\n Approval required before this Runtime action can execute.\n </div>\n <div style=\"color: var(--mj-text-secondary); font-size: 0.9em; margin-bottom: 12px;\">\n Approving grants this action the permissions listed above on behalf of any user who invokes it. Review the code and permissions carefully before approving.\n </div>\n <div style=\"display: flex; gap: 8px;\">\n <button class=\"mj-button mj-button-primary\" (click)=\"approveCode()\">\n <i class=\"fa-solid fa-check\"></i> Approve\n </button>\n <button class=\"mj-button\" (click)=\"rejectCode()\">\n <i class=\"fa-solid fa-ban\"></i> Reject\n </button>\n </div>\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n\n <!-- Result Codes Section -->\n <mj-accordion-panel\n [Expanded]=\"expandedSections.resultCodes\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-flag-checkered\" style=\"color: var(--mj-text-muted);\"></i>\n Result Codes\n @if (resultCodes.length > 0) {\n <span style=\"background: var(--mj-status-success); color: var(--mj-text-inverse); padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n {{ resultCodes.length }}\n </span>\n }\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n <!-- Add Result Code Button -->\n @if (EditMode && record.IsSaved) {\n <div style=\"display: flex; justify-content: flex-end; margin-bottom: 12px;\">\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"addResultCode()\">\n <i class=\"fa-solid fa-plus\"></i> Add Result Code\n </button>\n </div>\n }\n \n @if (isLoadingResultCodes) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading result codes...\n </div>\n } @else if (resultCodes.length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-flag-checkered\" style=\"font-size: 2em; color: var(--mj-text-muted); opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: var(--mj-text-muted);\">No result codes defined</p>\n @if (EditMode && record.IsSaved) {\n <p style=\"margin: 8px 0 0 0; font-size: 0.85em; color: var(--mj-text-muted);\">Add result codes to define possible outcomes</p>\n }\n </div>\n } @else {\n <div class=\"result-codes-grid\">\n @for (code of resultCodes; track code.ID) {\n <div class=\"result-code-card\" \n [class.success]=\"code.IsSuccess\" \n [class.failure]=\"!code.IsSuccess\"\n [class.clickable]=\"true\"\n (click)=\"onResultCodeClick(code, $event)\">\n <div class=\"result-icon\">\n <i [class]=\"code.IsSuccess ? 'fa-solid fa-check-circle' : 'fa-solid fa-times-circle'\"></i>\n </div>\n <div class=\"result-content\">\n <div class=\"result-code\">{{ code.ResultCode }}</div>\n @if (code.Description) {\n <div class=\"result-description\">{{ code.Description }}</div>\n }\n </div>\n @if (EditMode) {\n <div class=\"result-actions\">\n <button class=\"result-edit-btn\" (click)=\"editResultCode(code); $event.stopPropagation()\" title=\"Edit result code\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"result-delete-btn\" (click)=\"deleteResultCode(code); $event.stopPropagation()\" title=\"Delete result code\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </mj-accordion-panel>\n\n <!-- Execution & Monitoring Section -->\n @if (record.IsSaved) {\n <mj-accordion-panel\n [Expanded]=\"expandedSections.execution\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-chart-line\" style=\"color: var(--mj-text-muted);\"></i>\n Execution & Monitoring\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n @if (isLoadingExecutions) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading executions...\n </div>\n } @else if (recentExecutions.length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-chart-line\" style=\"font-size: 2em; color: var(--mj-text-muted); opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: var(--mj-text-muted);\">No executions yet</p>\n </div>\n } @else {\n <div class=\"execution-stats-row\">\n <div class=\"stat-box\">\n <i class=\"fa-solid fa-tachometer-alt\"></i>\n <div class=\"stat-info\">\n <div class=\"stat-label\" style=\"color: var(--mj-text-primary);\">Avg Duration</div>\n <div class=\"stat-value\" style=\"color: var(--mj-text-primary);\">{{ formatDuration(executionStats.avgDuration) }}</div>\n </div>\n </div>\n <div class=\"stat-box\">\n <i class=\"fa-solid fa-check-circle\" [style.color]=\"getSuccessRateColor()\"></i>\n <div class=\"stat-info\">\n <div class=\"stat-label\" style=\"color: var(--mj-text-primary);\">Success Rate</div>\n <div class=\"stat-value\" [style.color]=\"getSuccessRateColor()\" style=\"font-weight: 600;\">{{ executionStats.successRate.toFixed(0) }}%</div>\n </div>\n </div>\n <div class=\"stat-box\">\n <i class=\"fa-solid fa-play-circle\"></i>\n <div class=\"stat-info\">\n <div class=\"stat-label\" style=\"color: var(--mj-text-primary);\">Total Runs</div>\n <div class=\"stat-value\" style=\"color: var(--mj-text-primary);\">{{ executionStats.totalRuns }}</div>\n </div>\n </div>\n </div>\n\n <h3 style=\"margin-top: 24px;\"><i class=\"fa-solid fa-history\"></i> Recent Executions</h3>\n <div class=\"executions-table\">\n <table>\n <thead>\n <tr>\n <th>Started</th>\n <th>Duration</th>\n <th>User</th>\n <th>Result</th>\n <th>Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (execution of recentExecutions; track execution.ID) {\n <tr class=\"execution-row\" [class.success]=\"isExecutionSuccess(execution)\">\n <td>{{ execution.StartedAt | date:'short' }}</td>\n <td>\n @if (execution.EndedAt) {\n {{ formatDuration(getExecutionDuration(execution)) }}\n } @else {\n <span class=\"running\">Running...</span>\n }\n </td>\n <td>{{ execution.User }}</td>\n <td>\n <span class=\"result-code\" \n [class.success]=\"isExecutionSuccess(execution)\"\n [class.failure]=\"!isExecutionSuccess(execution)\">\n {{ execution.ResultCode }}\n </span>\n </td>\n <td>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"navigateToExecution(execution.ID)\">\n <i class=\"fa-solid fa-external-link\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n\n <!-- Related Configuration Section -->\n @if (record.IsSaved) {\n <mj-accordion-panel\n [Expanded]=\"expandedSections.configuration\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-cogs\" style=\"color: var(--mj-text-muted);\"></i>\n Related Configuration\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n <!-- Libraries -->\n <div class=\"config-subsection\">\n <h3><i class=\"fa-solid fa-book\"></i> Libraries</h3>\n @if (isLoadingLibraries) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading libraries...\n </div>\n } @else if (actionLibraries.length === 0) {\n <div class=\"empty-state mini\">\n <p>No libraries configured</p>\n </div>\n } @else {\n <div class=\"library-cards\">\n @for (lib of libraries; track lib.ID; let i = $index) {\n <div class=\"library-card\" (click)=\"navigateToLibrary(lib.ID)\">\n <i class=\"fa-solid fa-book\"></i>\n <div class=\"library-info\">\n <div class=\"library-name\">{{ lib.Name }}</div>\n @if (actionLibraries[i].ItemsUsed) {\n <div class=\"library-items\">{{ actionLibraries[i].ItemsUsed }}</div>\n }\n </div>\n <i class=\"fa-solid fa-external-link\"></i>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Other Related Entities -->\n <div class=\"related-entities-grid\">\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-shield-alt\"></i>\n <span>Authorizations</span>\n <span class=\"entity-count\">View</span>\n </div>\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-layer-group\"></i>\n <span>Contexts</span>\n <span class=\"entity-count\">View</span>\n </div>\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-calendar\"></i>\n <span>Scheduled Actions</span>\n <span class=\"entity-count\">View</span>\n </div>\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-cube\"></i>\n <span>Entity Actions</span>\n <span class=\"entity-count\">View</span>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n }\n </div>\n </div>\n </form>\n</mj-record-form-container>\n}\n\n<!-- Action Test Harness Dialog -->\n<mj-action-test-harness-dialog\n [Action]=\"record\"\n [ActionParams]=\"actionParams\"\n [IsOpen]=\"showTestHarness\"\n (Close)=\"onTestHarnessVisibilityChanged(false)\">\n</mj-action-test-harness-dialog>", styles: ["/* Enable flex layout for full-height scrolling */\n:host {\n display: block;\n height: 100%;\n}\n\n.record-form-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n}\n\n.record-form {\n min-height: 0 !important;\n}\n\n/* Hero Header Section */\n.action-hero-header {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n padding: 32px;\n margin: -20px -20px 24px -20px;\n border-radius: 0 0 var(--mj-radius-lg) var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n}\n\n.hero-content {\n max-width: 1400px;\n margin: 0 auto;\n}\n\n.action-identity {\n display: flex;\n align-items: flex-start;\n gap: 24px;\n margin-bottom: 24px;\n}\n\n.action-icon-wrapper {\n width: 80px;\n height: 80px;\n border-radius: var(--mj-radius-lg);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n backdrop-filter: blur(10px);\n}\n\n.action-icon-wrapper i {\n font-size: var(--mj-text-4xl);\n}\n\n.action-info {\n flex: 1;\n min-width: 0;\n}\n\n.action-title-row {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-bottom: 12px;\n flex-wrap: wrap;\n}\n\n.action-title {\n margin: 0;\n font-size: 2em;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-inverse);\n}\n\n.action-name-input {\n font-size: 1.8em;\n font-weight: var(--mj-font-semibold);\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n color: var(--mj-text-inverse);\n padding: 8px 16px;\n border-radius: var(--mj-radius-md);\n min-width: 400px;\n}\n\n.action-name-input::placeholder {\n color: color-mix(in srgb, var(--mj-text-inverse) 60%, transparent);\n}\n\n.action-badges {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.status-badge, .type-badge, .approval-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n backdrop-filter: blur(10px);\n border: 1px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n}\n\n.action-category {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n color: color-mix(in srgb, var(--mj-text-inverse) 90%, transparent);\n font-size: 0.95em;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n margin-bottom: 12px;\n}\n\n.action-category:hover {\n color: var(--mj-text-inverse);\n transform: translateX(4px);\n}\n\n.action-description {\n color: color-mix(in srgb, var(--mj-text-inverse) 90%, transparent);\n font-size: 1.05em;\n line-height: var(--mj-leading-relaxed);\n margin: 0;\n}\n\n.action-description-input {\n width: 100%;\n max-width: 600px;\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n color: var(--mj-text-inverse);\n border-radius: var(--mj-radius-md);\n}\n\n.action-description-input::placeholder {\n color: color-mix(in srgb, var(--mj-text-inverse) 60%, transparent);\n}\n\n/* Quick Stats */\n.action-stats {\n display: flex;\n gap: 24px;\n margin-bottom: 24px;\n flex-wrap: wrap;\n}\n\n.stat-card {\n background: color-mix(in srgb, var(--mj-text-inverse) 10%, transparent);\n backdrop-filter: blur(10px);\n border: 1px solid color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border-radius: var(--mj-radius-lg);\n padding: 16px 24px;\n display: flex;\n align-items: center;\n gap: 16px;\n min-width: 160px;\n}\n\n.stat-card i {\n font-size: var(--mj-text-2xl);\n color: color-mix(in srgb, var(--mj-text-inverse) 80%, transparent);\n}\n\n.stat-content {\n display: flex;\n flex-direction: column;\n}\n\n.stat-value {\n font-size: 1.4em;\n font-weight: var(--mj-font-bold);\n color: var(--mj-text-inverse);\n}\n\n.stat-label {\n font-size: var(--mj-text-sm);\n color: color-mix(in srgb, var(--mj-text-inverse) 70%, transparent);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n/* Hero Actions */\n.hero-actions {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.hero-actions button {\n backdrop-filter: blur(10px);\n}\n\n/* Main Content Sections */\n.action-content {\n padding: 0 20px 20px;\n}\n\n.content-section {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n margin-bottom: 20px;\n overflow: hidden;\n transition: all var(--mj-transition-base);\n}\n\n.content-section:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.section-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background: var(--mj-bg-surface-elevated);\n cursor: pointer;\n user-select: none;\n transition: background var(--mj-transition-base);\n}\n\n.section-header:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.section-header h2 {\n margin: 0;\n font-size: 1.3em;\n color: var(--mj-text-primary);\n flex: 1;\n}\n\n.section-header i:first-child {\n font-size: 1.2em;\n color: var(--mj-text-muted);\n}\n\n.section-count {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n}\n\n.toggle-icon {\n color: var(--mj-text-muted);\n transition: transform 0.3s;\n}\n\n.toggle-icon.rotated {\n transform: rotate(-90deg);\n}\n\n.section-content {\n padding: 24px;\n animation: slideDown 0.3s ease;\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Overview Section */\n.overview-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.overview-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.overview-field label {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.required {\n color: var(--mj-status-error);\n}\n\n.full-width {\n width: 100%;\n}\n\n.overview-display {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 24px;\n}\n\n.display-field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.display-field label {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-muted);\n font-weight: var(--mj-font-semibold);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.display-value {\n font-size: 1.1em;\n color: var(--mj-text-primary);\n}\n\n.display-value.code {\n font-family: 'Courier New', monospace;\n background: var(--mj-bg-surface-sunken);\n padding: 4px 8px;\n border-radius: var(--mj-radius-sm);\n}\n\n.approval-date {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n margin-left: 8px;\n}\n\n/* Code Section */\n.generation-panel {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 20px;\n margin-bottom: 24px;\n}\n\n.generation-panel h3 {\n margin: 0 0 16px 0;\n color: var(--mj-color-indigo-500);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.prompt-section, .comments-section {\n margin-bottom: 16px;\n}\n\n.prompt-section label, .comments-section label {\n display: block;\n margin-bottom: 8px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n}\n\n.generation-controls {\n display: flex;\n align-items: center;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.code-locked-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: var(--mj-status-warning);\n color: var(--mj-color-warning-800);\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.code-editor-section {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n\n.code-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.code-toolbar h3 {\n margin: 0;\n font-size: 1.1em;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.code-actions {\n display: flex;\n gap: 8px;\n}\n\n.code-comments {\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-info) 30%, transparent);\n border-radius: var(--mj-radius-md);\n padding: 16px;\n margin-top: 16px;\n}\n\n.code-comments h4 {\n margin: 0 0 8px 0;\n color: var(--mj-status-info);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.code-comments p {\n margin: 0;\n color: var(--mj-text-secondary);\n line-height: var(--mj-leading-relaxed);\n}\n\n.approval-comments {\n margin-top: 16px;\n}\n\n.approval-comments label {\n display: block;\n margin-bottom: 8px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-status-error);\n}\n\n/* Parameters Section */\n.params-section {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-lg);\n padding: 20px;\n}\n\n.params-section.params-section-compact {\n padding: 12px 20px;\n}\n\n.params-section-compact .empty-state {\n padding: 12px !important;\n}\n\n.params-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.params-header h3 {\n margin: 0;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.params-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n\n.param-card {\n background: var(--mj-bg-surface);\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 16px;\n transition: all var(--mj-transition-base);\n}\n\n.param-card:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.param-card.required {\n border-color: var(--mj-status-warning);\n}\n\n.param-card.clickable {\n cursor: pointer;\n}\n\n.param-card.clickable:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n transform: translateY(-1px);\n}\n\n.param-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.param-name {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.param-badges {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.param-edit-btn,\n.param-delete-btn {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n border-radius: var(--mj-radius-sm);\n transition: all var(--mj-transition-base);\n}\n\n.param-edit-btn:hover {\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.param-delete-btn:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.param-details {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.required-badge {\n background: var(--mj-status-warning);\n color: var(--mj-color-warning-800);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.array-badge {\n background: var(--mj-color-indigo-500);\n color: var(--mj-text-inverse);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.param-type {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n margin-bottom: 8px;\n}\n\n.param-description {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.4;\n margin-bottom: 8px;\n}\n\n.param-default {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.default-label {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n}\n\n.param-default code {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-family: 'Courier New', monospace;\n color: var(--mj-color-error-400);\n}\n\n\n/* Result Codes Section */\n.result-codes-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n\n.result-code-card {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n transition: all var(--mj-transition-base);\n position: relative;\n}\n\n.result-code-card.clickable {\n cursor: pointer;\n}\n\n.result-code-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-md);\n}\n\n.result-code-card.success {\n border-color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n}\n\n.result-code-card.failure {\n border-color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n}\n\n.result-actions {\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n gap: 4px;\n opacity: 0;\n transition: opacity var(--mj-transition-base);\n}\n\n.result-code-card:hover .result-actions {\n opacity: 1;\n}\n\n.result-edit-btn,\n.result-delete-btn {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n padding: 4px 8px;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n font-size: var(--mj-text-sm);\n}\n\n.result-edit-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.result-delete-btn:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border-color: var(--mj-status-error);\n}\n\n.result-icon {\n font-size: 1.5em;\n flex-shrink: 0;\n}\n\n.result-code-card.success .result-icon {\n color: var(--mj-status-success);\n}\n\n.result-code-card.failure .result-icon {\n color: var(--mj-status-error);\n}\n\n.result-content {\n flex: 1;\n min-width: 0;\n}\n\n.result-code {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n font-family: 'Courier New', monospace;\n}\n\n.result-description {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.4;\n}\n\n/* Execution Section */\n.execution-stats-row {\n display: flex;\n gap: 20px;\n margin-bottom: 32px;\n flex-wrap: wrap;\n}\n\n.stat-box {\n flex: 1;\n min-width: 200px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 20px;\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.stat-box i {\n font-size: 2em;\n color: var(--mj-text-muted);\n}\n\n.stat-info {\n flex: 1;\n}\n\n.executions-table {\n overflow-x: auto;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n}\n\n.executions-table table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.executions-table th {\n background: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-default);\n}\n\n.executions-table td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n.execution-row {\n transition: background var(--mj-transition-base);\n}\n\n.execution-row:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.execution-row.success {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.running {\n color: var(--mj-status-warning);\n font-style: italic;\n}\n\n.result-code {\n display: inline-block;\n padding: 4px 8px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n font-family: 'Courier New', monospace;\n}\n\n.result-code.success {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.result-code.failure {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n/* Configuration Section */\n.config-subsection {\n margin-bottom: 32px;\n}\n\n.config-subsection h3 {\n margin: 0 0 16px 0;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.library-cards {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.library-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.library-card:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.library-card i:first-child {\n font-size: 1.5em;\n color: var(--mj-text-muted);\n}\n\n.library-info {\n flex: 1;\n min-width: 0;\n}\n\n.library-name {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.library-items {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n font-family: 'Courier New', monospace;\n}\n\n.related-entities-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n}\n\n.related-entity-link {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.related-entity-link:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-brand-primary);\n}\n\n.related-entity-link i {\n font-size: 1.2em;\n color: var(--mj-text-muted);\n}\n\n.related-entity-link span:first-of-type {\n flex: 1;\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n}\n\n.entity-count {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-sm);\n}\n\n/* Common States */\n.loading-state {\n text-align: center;\n padding: 60px;\n color: var(--mj-text-muted);\n}\n\n.loading-state i {\n font-size: 2em;\n margin-bottom: 12px;\n}\n\n.empty-state {\n text-align: center;\n padding: 60px;\n color: var(--mj-text-muted);\n}\n\n.empty-state.mini {\n padding: 20px;\n}\n\n.empty-state i {\n font-size: 3em;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.empty-state p {\n margin: 0;\n font-size: 1.1em;\n}\n\n.empty-hint {\n margin-top: 8px !important;\n font-size: var(--mj-text-sm) !important;\n opacity: 0.7;\n}\n\n.no-params {\n text-align: center;\n padding: 20px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n.no-params p {\n margin: 0;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .action-hero-header {\n padding: 20px;\n }\n\n .action-identity {\n flex-direction: column;\n text-align: center;\n }\n\n .action-icon-wrapper {\n margin: 0 auto;\n }\n\n .action-title-row {\n justify-content: center;\n }\n\n .action-stats {\n justify-content: center;\n }\n\n .params-grid {\n grid-template-columns: 1fr;\n }\n}\n\n/* ============================================\n KENDO EXPANSION PANEL OVERRIDES\n ============================================ */\n::ng-deep .k-expander {\n background: var(--mj-bg-surface-card) !important;\n border-color: var(--mj-border-default) !important;\n color: var(--mj-text-primary) !important;\n}\n\n::ng-deep .k-expander-header {\n background: var(--mj-bg-surface-elevated) !important;\n color: var(--mj-text-primary) !important;\n border-color: var(--mj-border-default) !important;\n}\n\n::ng-deep .k-expander-header:hover {\n background: var(--mj-bg-surface-hover) !important;\n}\n\n::ng-deep .k-expander-title {\n color: var(--mj-text-primary) !important;\n}\n\n::ng-deep .k-expander-indicator .k-icon,\n::ng-deep .k-expander-indicator .k-svg-icon {\n color: var(--mj-text-muted) !important;\n}\n\n::ng-deep .k-expander-content-wrapper {\n border-color: var(--mj-border-default) !important;\n}\n\n::ng-deep .k-expander-content {\n background: var(--mj-bg-surface-card) !important;\n border-color: var(--mj-border-default) !important;\n color: var(--mj-text-primary) !important;\n}\n"] }]
|
|
2331
|
+
args: [{ standalone: false, selector: 'mj-action-form', template: "<!--\n NOTE: We wrap the form content in <mj-record-form-container> rather than\n using <mj-form-toolbar> directly. The container owns the toolbar AND the\n panels behind History/Tags/List buttons \u2014 without it those buttons emit\n events that nothing listens to and the features silently break. Follow\n this pattern for every custom entity form \u2014 see packages/Angular/CLAUDE.md.\n-->\n@if (record) {\n<mj-record-form-container [Record]=\"record\" [FormComponent]=\"this\"\n [ToolbarConfig]=\"toolbarConfig\"\n [WidthMode]=\"'full-width'\"\n (Navigate)=\"OnFormNavigate($event)\"\n (DeleteRequested)=\"OnDeleteRequested()\"\n (FavoriteToggled)=\"OnFavoriteToggled()\"\n (HistoryRequested)=\"OnHistoryRequested()\"\n (ListManagementRequested)=\"OnListManagementRequested()\">\n <form class=\"record-form\" #form=\"ngForm\" style=\"display: flex; flex-direction: column; height: 100%; overflow: hidden;\">\n\n <!-- Main Content Area -->\n <div class=\"action-main-area\" style=\"display: flex; flex-direction: column; flex: 1; min-height: 0; overflow-y: auto;\">\n \n <!-- Header Section -->\n <div class=\"action-header\" style=\"flex-shrink: 0; padding: 20px; background: var(--mj-bg-surface-card); border-bottom: 2px solid var(--mj-border-default);\">\n <div style=\"display: flex; justify-content: space-between; align-items: flex-start; gap: 20px;\">\n \n <!-- Left: Action Info -->\n <div style=\"flex: 1; min-width: 0;\">\n <div style=\"display: flex; align-items: center; gap: 12px; margin-bottom: 8px;\">\n <i [class]=\"getActionIcon()\" [style.color]=\"getTypeColor()\" style=\"font-size: 1.4em;\"></i>\n @if (EditMode) {\n <input type=\"text\" class=\"mj-input\"\n [(ngModel)]=\"record.Name\"\n name=\"actionName\"\n placeholder=\"Enter action name...\"\n style=\"font-size: 1.2em; font-weight: 600; min-width: 300px; flex: 1;\" />\n } @else {\n <h4 style=\"margin: 0; color: var(--mj-text-secondary); font-weight: 600; flex: 1;\">{{ record.Name || 'Untitled Action' }}</h4>\n <span class=\"status-chip\"\n [attr.data-color]=\"record.Status === 'Active' ? 'success' : record.Status === 'Pending' ? 'warning' : 'error'\">\n {{ record.Status }}\n </span>\n @if (hasCodeApproval && record.CodeApprovalStatus) {\n <span class=\"status-chip\"\n [attr.data-color]=\"record.CodeApprovalStatus === 'Approved' ? 'success' : record.CodeApprovalStatus === 'Pending' ? 'warning' : 'error'\"\n [title]=\"'Code ' + record.CodeApprovalStatus\">\n <i [class]=\"'fa-solid ' + getApprovalStatusIcon()\" style=\"margin-right: 4px;\"></i>\n {{ record.CodeApprovalStatus }}\n </span>\n }\n }\n </div>\n \n <!-- Status and Type Editors when in edit mode -->\n @if (EditMode) {\n <div style=\"display: flex; gap: 16px; margin-bottom: 12px; flex-wrap: wrap;\">\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">Status</label>\n <mj-dropdown [(ngModel)]=\"record.Status\"\n name=\"actionStatus\"\n [Data]=\"[{text: 'Active', value: 'Active'}, {text: 'Pending', value: 'Pending'}, {text: 'Disabled', value: 'Disabled'}]\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n style=\"width: 150px;\">\n </mj-dropdown>\n </div>\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">\n Type <span style=\"color: var(--mj-status-error);\">*</span>\n </label>\n <mj-dropdown [(ngModel)]=\"record.Type\"\n name=\"actionType\"\n [Data]=\"[{text: 'Generated', value: 'Generated'}, {text: 'Custom', value: 'Custom'}]\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n style=\"width: 150px;\">\n </mj-dropdown>\n </div>\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">\n Category <span style=\"color: var(--mj-status-error);\">*</span>\n </label>\n <mj-dropdown [(ngModel)]=\"record.CategoryID\"\n name=\"categoryID\"\n [Data]=\"[]\"\n Placeholder=\"Select category...\"\n style=\"width: 200px;\">\n </mj-dropdown>\n </div>\n @if (hasCodeApproval) {\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">\n <i [class]=\"'fa-solid ' + getApprovalStatusIcon()\" [style.color]=\"getApprovalStatusColor()\" style=\"margin-right: 4px;\"></i>\n Code Approval\n </label>\n <mj-dropdown [(ngModel)]=\"record.CodeApprovalStatus\"\n name=\"codeApprovalStatus\"\n [Data]=\"[{text: 'Approved', value: 'Approved'}, {text: 'Pending', value: 'Pending'}, {text: 'Rejected', value: 'Rejected'}]\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n style=\"width: 160px;\">\n </mj-dropdown>\n </div>\n }\n </div>\n }\n \n @if (EditMode) {\n <textarea class=\"mj-textarea\" [(ngModel)]=\"record.Description\" \n name=\"actionDescription\"\n [rows]=\"2\"\n placeholder=\"Enter action description...\"\n style=\"width: 100%; max-width: 600px; margin-bottom: 12px;\">\n </textarea>\n } @else if (record.Description) {\n <p style=\"margin: 0 0 12px 0; color: var(--mj-text-muted); font-size: 0.9em; line-height: 1.4;\">{{ record.Description }}</p>\n }\n \n <!-- Quick Config Row -->\n <div class=\"quick-config\" style=\"display: flex; align-items: center; gap: 16px; flex-wrap: wrap;\">\n @if (category) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-folder\" style=\"color: var(--mj-text-muted);\"></i>\n <span style=\"color: var(--mj-text-muted);\">Category:</span>\n <span style=\"color: var(--mj-text-secondary); font-weight: 500; cursor: pointer;\" (click)=\"navigateToCategory()\">\n {{ category.Name }}\n <i class=\"fa-solid fa-external-link\" style=\"font-size: 0.75em; margin-left: 4px;\"></i>\n </span>\n </div>\n }\n \n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-cube\" style=\"color: var(--mj-text-muted);\"></i>\n <span style=\"color: var(--mj-text-muted);\">Type:</span>\n <span style=\"color: var(--mj-text-secondary); font-weight: 500;\">{{ record.Type }}</span>\n </div>\n \n @if (hasCodeApproval && record.CodeApprovalStatus) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i [class]=\"'fa-solid ' + getApprovalStatusIcon()\" [style.color]=\"getApprovalStatusColor()\"></i>\n <span style=\"color: var(--mj-text-muted);\">Code:</span>\n <span [style.color]=\"getApprovalStatusColor()\" style=\"font-weight: 500;\">{{ record.CodeApprovalStatus }}</span>\n </div>\n }\n \n @if (actionParams.length > 0) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-sliders\" style=\"color: var(--mj-text-muted);\"></i>\n <span style=\"color: var(--mj-text-secondary); font-weight: 500;\">{{ actionParams.length }} Parameters</span>\n </div>\n }\n </div>\n </div>\n \n <!-- Right: Action Buttons -->\n <div class=\"action-buttons\" style=\"display: flex; flex-direction: column; gap: 8px; align-items: flex-end;\">\n <div style=\"display: flex; gap: 8px;\">\n @if (record.ID && !EditMode) {\n <button mjButton variant=\"primary\" size=\"lg\"\n (click)=\"openTestHarness()\"\n title=\"Open Run Harness\"\n [disabled]=\"record.Status !== 'Active'\">\n <i class=\"fa-solid fa-play\"></i> Run\n </button>\n }\n @if (EditMode && record.Type === 'Generated') {\n <button mjButton variant=\"outline\" size=\"md\"\n (click)=\"regenerateCode()\"\n title=\"Regenerate Code\">\n <i class=\"fa-solid fa-robot\"></i> Regenerate\n </button>\n }\n </div>\n \n @if (!EditMode && record.Status !== 'Active' && record.ID) {\n <div style=\"font-size: 0.75em; color: var(--mj-status-error); text-align: right;\">\n Action must be Active to execute\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Configuration Sections with Expansion Panels -->\n <div class=\"configuration-sections\" style=\"flex: 1; background: var(--mj-bg-surface-card); border-top: 2px solid var(--mj-border-default); padding: 16px; min-height: 0;\">\n \n <!-- Parameters Section (FIRST) -->\n <mj-accordion-panel\n [Expanded]=\"true\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-sliders\" style=\"color: var(--mj-text-muted);\"></i>\n Parameters\n @if (actionParams.length > 0) {\n <span style=\"background: var(--mj-status-info); color: var(--mj-text-inverse); padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n {{ actionParams.length }}\n </span>\n }\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n @if (isLoadingParams) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading parameters...\n </div>\n } @else if (actionParams.length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-sliders\" style=\"font-size: 2em; color: var(--mj-text-muted); opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: var(--mj-text-muted);\">No parameters defined</p>\n @if (EditMode && record.IsSaved) {\n <p style=\"margin: 8px 0 0 0; font-size: 0.85em; color: var(--mj-text-muted);\">Add parameters to define inputs and outputs for this action</p>\n }\n </div>\n } @else {\n <!-- Input Parameters Grid -->\n <div class=\"params-section\">\n <div class=\"params-header\">\n <h3><i class=\"fa-solid fa-sign-in-alt\"></i> Input Parameters</h3>\n @if (EditMode && record.IsSaved) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"addParameter('Input')\">\n <i class=\"fa-solid fa-plus\"></i> Add Input\n </button>\n }\n </div>\n \n @if (getInputParams().length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-inbox\" style=\"font-size: 2em; color: var(--mj-text-muted); opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: var(--mj-text-muted);\">No input parameters defined</p>\n </div>\n } @else {\n <div class=\"params-grid\">\n @for (param of getInputParams(); track param.ID) {\n <div class=\"param-card\" [class.required]=\"param.IsRequired\" \n [class.clickable]=\"true\"\n (click)=\"onParamClick(param, $event)\">\n <div class=\"param-header\">\n <span class=\"param-name\">{{ param.Name }}</span>\n <div class=\"param-badges\">\n @if (param.IsRequired) {\n <span class=\"required-badge\">Required</span>\n }\n @if (param.IsArray) {\n <span class=\"array-badge\">Array</span>\n }\n @if (EditMode) {\n <button class=\"param-edit-btn\" (click)=\"editParameter(param)\" title=\"Edit parameter\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"param-delete-btn\" (click)=\"deleteParameter(param)\" title=\"Delete parameter\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </div>\n <div class=\"param-details\">\n <div class=\"param-type\">{{ param.ValueType }}</div>\n @if (param.Description) {\n <div class=\"param-description\">{{ param.Description }}</div>\n }\n @if (param.DefaultValue) {\n <div class=\"param-default\">\n <span class=\"default-label\">Default:</span>\n <code>{{ param.DefaultValue }}</code>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Output Parameters Grid -->\n <div class=\"params-section\" style=\"margin-top: 24px;\" \n [class.params-section-compact]=\"getOutputParams().length === 0\">\n <div class=\"params-header\">\n <h3><i class=\"fa-solid fa-sign-out-alt\"></i> Output Parameters</h3>\n @if (EditMode && record.IsSaved) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"addParameter('Output')\">\n <i class=\"fa-solid fa-plus\"></i> Add Output\n </button>\n }\n </div>\n \n @if (getOutputParams().length === 0) {\n <div class=\"empty-state\" style=\"padding: 20px; text-align: center;\">\n <i class=\"fa-solid fa-inbox\" style=\"font-size: 2em; color: var(--mj-text-muted); opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: var(--mj-text-muted);\">No output parameters defined</p>\n </div>\n } @else {\n <div class=\"params-grid\">\n @for (param of getOutputParams(); track param.ID) {\n <div class=\"param-card\"\n [class.clickable]=\"true\"\n (click)=\"onParamClick(param, $event)\">\n <div class=\"param-header\">\n <span class=\"param-name\">{{ param.Name }}</span>\n <div class=\"param-badges\">\n @if (param.IsArray) {\n <span class=\"array-badge\">Array</span>\n }\n @if (EditMode) {\n <button class=\"param-edit-btn\" (click)=\"editParameter(param)\" title=\"Edit parameter\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"param-delete-btn\" (click)=\"deleteParameter(param)\" title=\"Delete parameter\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n </div>\n </div>\n <div class=\"param-details\">\n <div class=\"param-type\">{{ param.ValueType }}</div>\n @if (param.Description) {\n <div class=\"param-description\">{{ param.Description }}</div>\n }\n @if (param.DefaultValue) {\n <div class=\"param-default\">\n <span class=\"default-label\">Default:</span>\n <code>{{ param.DefaultValue }}</code>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </mj-accordion-panel>\n\n <!-- Code & Generation Section (Only for Generated type) -->\n @if (record.Type === 'Generated') {\n <mj-accordion-panel\n [Expanded]=\"expandedSections.code\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-code\" style=\"color: var(--mj-text-muted);\"></i>\n Code & Generation\n @if (record.CodeLocked) {\n <span style=\"background: var(--mj-status-warning); color: var(--mj-color-warning-800); padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n <i class=\"fa-solid fa-lock\"></i> Locked\n </span>\n }\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n @if (EditMode) {\n <div class=\"generation-panel\">\n <h3><i class=\"fa-solid fa-robot\"></i> AI Generation</h3>\n <div class=\"prompt-section\">\n <label>User Prompt</label>\n <textarea class=\"mj-textarea\" [(ngModel)]=\"record.UserPrompt\"\n name=\"userPrompt\"\n [rows]=\"8\"\n placeholder=\"Describe what this action should do...\"\n style=\"width: 100%; min-height: 120px;\">\n </textarea>\n </div>\n <div class=\"comments-section\">\n <label>Internal Comments (not sent to AI)</label>\n <textarea class=\"mj-textarea\" [(ngModel)]=\"record.UserComments\"\n name=\"userComments\"\n [rows]=\"2\"\n placeholder=\"Internal notes...\"\n style=\"width: 100%;\">\n </textarea>\n </div>\n <div class=\"generation-controls\">\n <mj-switch [(ngModel)]=\"record.CodeLocked\"\n name=\"codeLocked\">\n </mj-switch>\n <label style=\"margin-left: 8px;\">Lock Code (prevent regeneration)</label>\n </div>\n </div>\n }\n \n <div class=\"code-editor-section\">\n <div class=\"code-toolbar\">\n <h3><i class=\"fa-solid fa-file-code\"></i> Action Code</h3>\n <div class=\"code-actions\">\n @if (record.CodeComments) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"toggleCodeComments()\">\n <i class=\"fa-solid fa-comment\"></i> \n {{ showCodeComments ? 'Hide' : 'Show' }} AI Comments\n </button>\n }\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"copyToClipboard(record.Code || '')\">\n <i class=\"fa-solid fa-copy\"></i> Copy\n </button>\n </div>\n </div>\n <mj-code-editor \n [(ngModel)]=\"record.Code\"\n name=\"actionCode\"\n [readonly]=\"!EditMode || record.CodeLocked\"\n [language]=\"codeLanguage\"\n [lineWrapping]=\"true\"\n style=\"height: 400px; width: 100%;\">\n </mj-code-editor>\n \n @if (showCodeComments && record.CodeComments) {\n <div class=\"code-comments\">\n <h4><i class=\"fa-solid fa-robot\"></i> AI Explanation</h4>\n <p>{{ record.CodeComments }}</p>\n </div>\n }\n \n @if (EditMode && record.CodeApprovalStatus === 'Rejected') {\n <div class=\"approval-comments\">\n <label>Rejection Comments</label>\n <textarea class=\"mj-textarea\" [(ngModel)]=\"record.CodeApprovalComments\"\n name=\"codeApprovalComments\"\n [rows]=\"2\"\n placeholder=\"Explain why the code was rejected...\"\n style=\"width: 100%;\">\n </textarea>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n }\n\n <!-- Runtime Action Configuration Section (only for Type='Runtime') -->\n @if (isRuntimeAction) {\n <mj-accordion-panel\n [Expanded]=\"true\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-wand-magic-sparkles\" style=\"color: var(--mj-status-warning);\"></i>\n Runtime Configuration & Permissions\n <span style=\"color: var(--mj-text-muted); font-weight: 400; font-size: 0.85em;\">\n ({{ getRuntimeConfigSummary() }})\n </span>\n </span>\n </ng-template>\n\n <div style=\"padding: 16px;\">\n @if (!runtimeConfig) {\n <div style=\"padding: 12px; background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface)); border-left: 3px solid var(--mj-status-error); border-radius: 4px;\">\n <i class=\"fa-solid fa-triangle-exclamation\" style=\"color: var(--mj-status-error); margin-right: 8px;\"></i>\n <strong>Missing or malformed RuntimeActionConfiguration.</strong>\n This Runtime action cannot run until a valid configuration is supplied. Approval should not be granted in this state.\n </div>\n } @else {\n @if (getWildcardFlags().any) {\n <div style=\"padding: 12px; background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); border-left: 3px solid var(--mj-status-warning); border-radius: 4px; margin-bottom: 16px;\">\n <div style=\"font-weight: 600; margin-bottom: 4px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-triangle-exclamation\" style=\"color: var(--mj-status-warning); margin-right: 6px;\"></i>\n Wildcard permissions enabled\n </div>\n <div style=\"color: var(--mj-text-secondary); font-size: 0.9em;\">\n This runtime action has one or more wildcard flags set that bypass the specific allowlists below:\n @if (getWildcardFlags().entity) { <strong>allowAnyEntity</strong> }\n @if (getWildcardFlags().action) { <strong>allowAnyAction</strong> }\n @if (getWildcardFlags().agent) { <strong>allowAnyAgent</strong> }\n . Approving grants this action unrestricted access to that namespace on behalf of any user who invokes it. Only approve if the action is framework-authored or you have personally reviewed every place it touches those resources.\n </div>\n </div>\n }\n <!-- Declared permissions \u2014 the security contract an approver is blessing -->\n <div style=\"display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; margin-bottom: 20px;\">\n <!-- Entities -->\n <div style=\"border: 1px solid var(--mj-border-default); border-radius: 6px; padding: 12px; background: var(--mj-bg-surface-card);\">\n <div style=\"font-weight: 600; margin-bottom: 8px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-database\" style=\"margin-right: 6px; color: var(--mj-brand-primary);\"></i>\n Allowed Entities ({{ getAllowedEntities().length }})\n </div>\n @if (getAllowedEntities().length === 0) {\n <div style=\"color: var(--mj-text-muted); font-style: italic;\">None requested</div>\n } @else {\n <div style=\"display: flex; flex-direction: column; gap: 4px;\">\n @for (e of getAllowedEntities(); track e.id) {\n <span style=\"background: var(--mj-bg-surface-sunken); padding: 4px 8px; border-radius: 4px; font-size: 0.9em; color: var(--mj-text-primary);\">\n {{ e.name }}\n </span>\n }\n </div>\n }\n </div>\n\n <!-- Actions -->\n <div style=\"border: 1px solid var(--mj-border-default); border-radius: 6px; padding: 12px; background: var(--mj-bg-surface-card);\">\n <div style=\"font-weight: 600; margin-bottom: 8px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-bolt\" style=\"margin-right: 6px; color: var(--mj-brand-primary);\"></i>\n Allowed Actions ({{ getAllowedActions().length }})\n </div>\n @if (getAllowedActions().length === 0) {\n <div style=\"color: var(--mj-text-muted); font-style: italic;\">None requested</div>\n } @else {\n <div style=\"display: flex; flex-direction: column; gap: 4px;\">\n @for (a of getAllowedActions(); track a.id) {\n <span style=\"background: var(--mj-bg-surface-sunken); padding: 4px 8px; border-radius: 4px; font-size: 0.9em; color: var(--mj-text-primary);\">\n {{ a.name }}\n </span>\n }\n </div>\n }\n </div>\n\n <!-- Agents -->\n <div style=\"border: 1px solid var(--mj-border-default); border-radius: 6px; padding: 12px; background: var(--mj-bg-surface-card);\">\n <div style=\"font-weight: 600; margin-bottom: 8px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-robot\" style=\"margin-right: 6px; color: var(--mj-brand-primary);\"></i>\n Allowed Agents ({{ getAllowedAgents().length }})\n </div>\n @if (getAllowedAgents().length === 0) {\n <div style=\"color: var(--mj-text-muted); font-style: italic;\">None requested</div>\n } @else {\n <div style=\"display: flex; flex-direction: column; gap: 4px;\">\n @for (g of getAllowedAgents(); track g.id) {\n <span style=\"background: var(--mj-bg-surface-sunken); padding: 4px 8px; border-radius: 4px; font-size: 0.9em; color: var(--mj-text-primary);\">\n {{ g.name }}\n </span>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Limits + libraries -->\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px;\">\n <div>\n <div style=\"font-weight: 600; margin-bottom: 6px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-gauge-high\" style=\"margin-right: 6px; color: var(--mj-text-muted);\"></i>\n Resource Limits\n </div>\n <div style=\"color: var(--mj-text-secondary); font-size: 0.9em;\">\n <div>Max memory: {{ getRuntimeLimits().maxMemoryMB }} MB</div>\n <div>Max bridge calls: {{ getRuntimeLimits().maxBridgeCalls }}</div>\n @if (record.MaxExecutionTimeMS) {\n <div>Max execution time: {{ record.MaxExecutionTimeMS }} ms</div>\n }\n </div>\n </div>\n <div>\n <div style=\"font-weight: 600; margin-bottom: 6px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-book\" style=\"margin-right: 6px; color: var(--mj-text-muted);\"></i>\n Additional Libraries\n </div>\n @if (getRequestedLibraries().length === 0) {\n <div style=\"color: var(--mj-text-muted); font-style: italic;\">None (only default set: lodash, date-fns, uuid, validator)</div>\n } @else {\n <div style=\"display: flex; flex-wrap: wrap; gap: 4px;\">\n @for (lib of getRequestedLibraries(); track lib.name) {\n <span style=\"background: var(--mj-bg-surface-sunken); padding: 2px 8px; border-radius: 10px; font-size: 0.85em;\">\n {{ lib.name }}@if (lib.version) {<span style=\"color: var(--mj-text-muted);\"> @{{ lib.version }}</span>}\n </span>\n }\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Code payload -->\n <div>\n <div style=\"font-weight: 600; margin-bottom: 6px; color: var(--mj-text-primary);\">\n <i class=\"fa-solid fa-code\" style=\"margin-right: 6px; color: var(--mj-text-muted);\"></i>\n JavaScript Payload\n </div>\n <pre style=\"background: var(--mj-bg-surface-sunken); color: var(--mj-text-primary); padding: 12px; border-radius: 4px; overflow-x: auto; max-height: 400px; font-family: 'SF Mono', Monaco, Consolas, monospace; font-size: 0.85em; margin: 0;\"><code>{{ record.Code }}</code></pre>\n </div>\n\n <!-- Approval actions (Runtime-specific labels) -->\n @if (EditMode && record.CodeApprovalStatus === 'Pending') {\n <div style=\"margin-top: 16px; padding: 12px; background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface)); border-radius: 6px;\">\n <div style=\"font-weight: 600; margin-bottom: 8px;\">\n <i class=\"fa-solid fa-circle-exclamation\" style=\"color: var(--mj-status-warning); margin-right: 6px;\"></i>\n Approval required before this Runtime action can execute.\n </div>\n <div style=\"color: var(--mj-text-secondary); font-size: 0.9em; margin-bottom: 12px;\">\n Approving grants this action the permissions listed above on behalf of any user who invokes it. Review the code and permissions carefully before approving.\n </div>\n <div style=\"display: flex; gap: 8px;\">\n <button class=\"mj-button mj-button-primary\" (click)=\"approveCode()\">\n <i class=\"fa-solid fa-check\"></i> Approve\n </button>\n <button class=\"mj-button\" (click)=\"rejectCode()\">\n <i class=\"fa-solid fa-ban\"></i> Reject\n </button>\n </div>\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n\n <!-- Result Codes Section -->\n <mj-accordion-panel\n [Expanded]=\"expandedSections.resultCodes\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-flag-checkered\" style=\"color: var(--mj-text-muted);\"></i>\n Result Codes\n @if (resultCodes.length > 0) {\n <span style=\"background: var(--mj-status-success); color: var(--mj-text-inverse); padding: 2px 6px; border-radius: 10px; font-size: 0.7em;\">\n {{ resultCodes.length }}\n </span>\n }\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n <!-- Add Result Code Button -->\n @if (EditMode && record.IsSaved) {\n <div style=\"display: flex; justify-content: flex-end; margin-bottom: 12px;\">\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"addResultCode()\">\n <i class=\"fa-solid fa-plus\"></i> Add Result Code\n </button>\n </div>\n }\n \n @if (isLoadingResultCodes) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading result codes...\n </div>\n } @else if (resultCodes.length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-flag-checkered\" style=\"font-size: 2em; color: var(--mj-text-muted); opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: var(--mj-text-muted);\">No result codes defined</p>\n @if (EditMode && record.IsSaved) {\n <p style=\"margin: 8px 0 0 0; font-size: 0.85em; color: var(--mj-text-muted);\">Add result codes to define possible outcomes</p>\n }\n </div>\n } @else {\n <div class=\"result-codes-grid\">\n @for (code of resultCodes; track code.ID) {\n <div class=\"result-code-card\" \n [class.success]=\"code.IsSuccess\" \n [class.failure]=\"!code.IsSuccess\"\n [class.clickable]=\"true\"\n (click)=\"onResultCodeClick(code, $event)\">\n <div class=\"result-icon\">\n <i [class]=\"code.IsSuccess ? 'fa-solid fa-check-circle' : 'fa-solid fa-times-circle'\"></i>\n </div>\n <div class=\"result-content\">\n <div class=\"result-code\">{{ code.ResultCode }}</div>\n @if (code.Description) {\n <div class=\"result-description\">{{ code.Description }}</div>\n }\n </div>\n @if (EditMode) {\n <div class=\"result-actions\">\n <button class=\"result-edit-btn\" (click)=\"editResultCode(code); $event.stopPropagation()\" title=\"Edit result code\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"result-delete-btn\" (click)=\"deleteResultCode(code); $event.stopPropagation()\" title=\"Delete result code\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </mj-accordion-panel>\n\n <!-- Execution & Monitoring Section -->\n @if (record.IsSaved) {\n <mj-accordion-panel\n [Expanded]=\"expandedSections.execution\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-chart-line\" style=\"color: var(--mj-text-muted);\"></i>\n Execution & Monitoring\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n @if (isLoadingExecutions) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading executions...\n </div>\n } @else if (recentExecutions.length === 0) {\n <div class=\"empty-state\" style=\"padding: 30px; text-align: center;\">\n <i class=\"fa-solid fa-chart-line\" style=\"font-size: 2em; color: var(--mj-text-muted); opacity: 0.3;\"></i>\n <p style=\"margin: 12px 0 0 0; color: var(--mj-text-muted);\">No executions yet</p>\n </div>\n } @else {\n <div class=\"execution-stats-row\">\n <div class=\"stat-box\">\n <i class=\"fa-solid fa-tachometer-alt\"></i>\n <div class=\"stat-info\">\n <div class=\"stat-label\" style=\"color: var(--mj-text-primary);\">Avg Duration</div>\n <div class=\"stat-value\" style=\"color: var(--mj-text-primary);\">{{ formatDuration(executionStats.avgDuration) }}</div>\n </div>\n </div>\n <div class=\"stat-box\">\n <i class=\"fa-solid fa-check-circle\" [style.color]=\"getSuccessRateColor()\"></i>\n <div class=\"stat-info\">\n <div class=\"stat-label\" style=\"color: var(--mj-text-primary);\">Success Rate</div>\n <div class=\"stat-value\" [style.color]=\"getSuccessRateColor()\" style=\"font-weight: 600;\">{{ executionStats.successRate.toFixed(0) }}%</div>\n </div>\n </div>\n <div class=\"stat-box\">\n <i class=\"fa-solid fa-play-circle\"></i>\n <div class=\"stat-info\">\n <div class=\"stat-label\" style=\"color: var(--mj-text-primary);\">Total Runs</div>\n <div class=\"stat-value\" style=\"color: var(--mj-text-primary);\">{{ executionStats.totalRuns }}</div>\n </div>\n </div>\n </div>\n\n <h3 style=\"margin-top: 24px;\"><i class=\"fa-solid fa-history\"></i> Recent Executions</h3>\n <div class=\"executions-table\">\n <table>\n <thead>\n <tr>\n <th>Started</th>\n <th>Duration</th>\n <th>User</th>\n <th>Result</th>\n <th>Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (execution of recentExecutions; track execution.ID) {\n <tr class=\"execution-row\" [class.success]=\"isExecutionSuccess(execution)\">\n <td>{{ execution.StartedAt | date:'short' }}</td>\n <td>\n @if (execution.EndedAt) {\n {{ formatDuration(getExecutionDuration(execution)) }}\n } @else {\n <span class=\"running\">Running...</span>\n }\n </td>\n <td>{{ execution.User }}</td>\n <td>\n <span class=\"result-code\" \n [class.success]=\"isExecutionSuccess(execution)\"\n [class.failure]=\"!isExecutionSuccess(execution)\">\n {{ execution.ResultCode }}\n </span>\n </td>\n <td>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"navigateToExecution(execution.ID)\">\n <i class=\"fa-solid fa-external-link\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n\n <!-- Related Configuration Section -->\n @if (record.IsSaved) {\n <mj-accordion-panel\n [Expanded]=\"expandedSections.configuration\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-cogs\" style=\"color: var(--mj-text-muted);\"></i>\n Related Configuration\n </span>\n </ng-template>\n \n <div style=\"padding: 16px;\">\n <!-- Libraries -->\n <div class=\"config-subsection\">\n <h3><i class=\"fa-solid fa-book\"></i> Libraries</h3>\n @if (isLoadingLibraries) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading libraries...\n </div>\n } @else if (actionLibraries.length === 0) {\n <div class=\"empty-state mini\">\n <p>No libraries configured</p>\n </div>\n } @else {\n <div class=\"library-cards\">\n @for (lib of libraries; track lib.ID; let i = $index) {\n <div class=\"library-card\" (click)=\"navigateToLibrary(lib.ID)\">\n <i class=\"fa-solid fa-book\"></i>\n <div class=\"library-info\">\n <div class=\"library-name\">{{ lib.Name }}</div>\n @if (actionLibraries[i].ItemsUsed) {\n <div class=\"library-items\">{{ actionLibraries[i].ItemsUsed }}</div>\n }\n </div>\n <i class=\"fa-solid fa-external-link\"></i>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Other Related Entities -->\n <div class=\"related-entities-grid\">\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-shield-alt\"></i>\n <span>Authorizations</span>\n <span class=\"entity-count\">View</span>\n </div>\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-layer-group\"></i>\n <span>Contexts</span>\n <span class=\"entity-count\">View</span>\n </div>\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-calendar\"></i>\n <span>Scheduled Actions</span>\n <span class=\"entity-count\">View</span>\n </div>\n <div class=\"related-entity-link\">\n <i class=\"fa-solid fa-cube\"></i>\n <span>Entity Actions</span>\n <span class=\"entity-count\">View</span>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n }\n </div>\n </div>\n </form>\n</mj-record-form-container>\n}\n\n<!-- Action Test Harness Dialog -->\n<mj-action-test-harness-dialog\n [Action]=\"record\"\n [ActionParams]=\"actionParams\"\n [IsOpen]=\"showTestHarness\"\n (Close)=\"onTestHarnessVisibilityChanged(false)\">\n</mj-action-test-harness-dialog>", styles: ["/* Enable flex layout for full-height scrolling */\n:host {\n display: block;\n height: 100%;\n}\n\n.record-form-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n}\n\n.record-form {\n min-height: 0 !important;\n}\n\n/* Hero Header Section */\n.action-hero-header {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n padding: 32px;\n margin: -20px -20px 24px -20px;\n border-radius: 0 0 var(--mj-radius-lg) var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n}\n\n.hero-content {\n max-width: 1400px;\n margin: 0 auto;\n}\n\n.action-identity {\n display: flex;\n align-items: flex-start;\n gap: 24px;\n margin-bottom: 24px;\n}\n\n.action-icon-wrapper {\n width: 80px;\n height: 80px;\n border-radius: var(--mj-radius-lg);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n backdrop-filter: blur(10px);\n}\n\n.action-icon-wrapper i {\n font-size: var(--mj-text-4xl);\n}\n\n.action-info {\n flex: 1;\n min-width: 0;\n}\n\n.action-title-row {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-bottom: 12px;\n flex-wrap: wrap;\n}\n\n.action-title {\n margin: 0;\n font-size: 2em;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-inverse);\n}\n\n.action-name-input {\n font-size: 1.8em;\n font-weight: var(--mj-font-semibold);\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n color: var(--mj-text-inverse);\n padding: 8px 16px;\n border-radius: var(--mj-radius-md);\n min-width: 400px;\n}\n\n.action-name-input::placeholder {\n color: color-mix(in srgb, var(--mj-text-inverse) 60%, transparent);\n}\n\n.action-badges {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.status-badge, .type-badge, .approval-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n backdrop-filter: blur(10px);\n border: 1px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n}\n\n.action-category {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n color: color-mix(in srgb, var(--mj-text-inverse) 90%, transparent);\n font-size: 0.95em;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n margin-bottom: 12px;\n}\n\n.action-category:hover {\n color: var(--mj-text-inverse);\n transform: translateX(4px);\n}\n\n.action-description {\n color: color-mix(in srgb, var(--mj-text-inverse) 90%, transparent);\n font-size: 1.05em;\n line-height: var(--mj-leading-relaxed);\n margin: 0;\n}\n\n.action-description-input {\n width: 100%;\n max-width: 600px;\n background: color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-text-inverse) 30%, transparent);\n color: var(--mj-text-inverse);\n border-radius: var(--mj-radius-md);\n}\n\n.action-description-input::placeholder {\n color: color-mix(in srgb, var(--mj-text-inverse) 60%, transparent);\n}\n\n/* Quick Stats */\n.action-stats {\n display: flex;\n gap: 24px;\n margin-bottom: 24px;\n flex-wrap: wrap;\n}\n\n.stat-card {\n background: color-mix(in srgb, var(--mj-text-inverse) 10%, transparent);\n backdrop-filter: blur(10px);\n border: 1px solid color-mix(in srgb, var(--mj-text-inverse) 20%, transparent);\n border-radius: var(--mj-radius-lg);\n padding: 16px 24px;\n display: flex;\n align-items: center;\n gap: 16px;\n min-width: 160px;\n}\n\n.stat-card i {\n font-size: var(--mj-text-2xl);\n color: color-mix(in srgb, var(--mj-text-inverse) 80%, transparent);\n}\n\n.stat-content {\n display: flex;\n flex-direction: column;\n}\n\n.stat-value {\n font-size: 1.4em;\n font-weight: var(--mj-font-bold);\n color: var(--mj-text-inverse);\n}\n\n.stat-label {\n font-size: var(--mj-text-sm);\n color: color-mix(in srgb, var(--mj-text-inverse) 70%, transparent);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n/* Hero Actions */\n.hero-actions {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.hero-actions button {\n backdrop-filter: blur(10px);\n}\n\n/* Main Content Sections */\n.action-content {\n padding: 0 20px 20px;\n}\n\n.content-section {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n margin-bottom: 20px;\n overflow: hidden;\n transition: all var(--mj-transition-base);\n}\n\n.content-section:hover {\n box-shadow: var(--mj-shadow-md);\n}\n\n.section-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background: var(--mj-bg-surface-elevated);\n cursor: pointer;\n user-select: none;\n transition: background var(--mj-transition-base);\n}\n\n.section-header:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.section-header h2 {\n margin: 0;\n font-size: 1.3em;\n color: var(--mj-text-primary);\n flex: 1;\n}\n\n.section-header i:first-child {\n font-size: 1.2em;\n color: var(--mj-text-muted);\n}\n\n.section-count {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n}\n\n.toggle-icon {\n color: var(--mj-text-muted);\n transition: transform 0.3s;\n}\n\n.toggle-icon.rotated {\n transform: rotate(-90deg);\n}\n\n.section-content {\n padding: 24px;\n animation: slideDown 0.3s ease;\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Overview Section */\n.overview-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n}\n\n.overview-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.overview-field label {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.required {\n color: var(--mj-status-error);\n}\n\n.full-width {\n width: 100%;\n}\n\n.overview-display {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 24px;\n}\n\n.display-field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.display-field label {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-muted);\n font-weight: var(--mj-font-semibold);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.display-value {\n font-size: 1.1em;\n color: var(--mj-text-primary);\n}\n\n.display-value.code {\n font-family: 'Courier New', monospace;\n background: var(--mj-bg-surface-sunken);\n padding: 4px 8px;\n border-radius: var(--mj-radius-sm);\n}\n\n.approval-date {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n margin-left: 8px;\n}\n\n/* Code Section */\n.generation-panel {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 20px;\n margin-bottom: 24px;\n}\n\n.generation-panel h3 {\n margin: 0 0 16px 0;\n color: var(--mj-color-indigo-500);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.prompt-section, .comments-section {\n margin-bottom: 16px;\n}\n\n.prompt-section label, .comments-section label {\n display: block;\n margin-bottom: 8px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n}\n\n.generation-controls {\n display: flex;\n align-items: center;\n gap: 12px;\n padding-top: 12px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.code-locked-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n background: var(--mj-status-warning);\n color: var(--mj-color-warning-800);\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.code-editor-section {\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n\n.code-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.code-toolbar h3 {\n margin: 0;\n font-size: 1.1em;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.code-actions {\n display: flex;\n gap: 8px;\n}\n\n.code-comments {\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-info) 30%, transparent);\n border-radius: var(--mj-radius-md);\n padding: 16px;\n margin-top: 16px;\n}\n\n.code-comments h4 {\n margin: 0 0 8px 0;\n color: var(--mj-status-info);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.code-comments p {\n margin: 0;\n color: var(--mj-text-secondary);\n line-height: var(--mj-leading-relaxed);\n}\n\n.approval-comments {\n margin-top: 16px;\n}\n\n.approval-comments label {\n display: block;\n margin-bottom: 8px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-status-error);\n}\n\n/* Parameters Section */\n.params-section {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-lg);\n padding: 20px;\n}\n\n.params-section.params-section-compact {\n padding: 12px 20px;\n}\n\n.params-section-compact .empty-state {\n padding: 12px !important;\n}\n\n.params-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.params-header h3 {\n margin: 0;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.params-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n\n.param-card {\n background: var(--mj-bg-surface);\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 16px;\n transition: all var(--mj-transition-base);\n}\n\n.param-card:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.param-card.required {\n border-color: var(--mj-status-warning);\n}\n\n.param-card.clickable {\n cursor: pointer;\n}\n\n.param-card.clickable:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n transform: translateY(-1px);\n}\n\n.param-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.param-name {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.param-badges {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.param-edit-btn,\n.param-delete-btn {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n border-radius: var(--mj-radius-sm);\n transition: all var(--mj-transition-base);\n}\n\n.param-edit-btn:hover {\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.param-delete-btn:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.param-details {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.required-badge {\n background: var(--mj-status-warning);\n color: var(--mj-color-warning-800);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.array-badge {\n background: var(--mj-color-indigo-500);\n color: var(--mj-text-inverse);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n}\n\n.param-type {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n margin-bottom: 8px;\n}\n\n.param-description {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.4;\n margin-bottom: 8px;\n}\n\n.param-default {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.default-label {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n}\n\n.param-default code {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: var(--mj-radius-sm);\n font-family: 'Courier New', monospace;\n color: var(--mj-color-error-400);\n}\n\n\n/* Result Codes Section */\n.result-codes-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n\n.result-code-card {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 16px;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n transition: all var(--mj-transition-base);\n position: relative;\n}\n\n.result-code-card.clickable {\n cursor: pointer;\n}\n\n.result-code-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-md);\n}\n\n.result-code-card.success {\n border-color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n}\n\n.result-code-card.failure {\n border-color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n}\n\n.result-actions {\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n gap: 4px;\n opacity: 0;\n transition: opacity var(--mj-transition-base);\n}\n\n.result-code-card:hover .result-actions {\n opacity: 1;\n}\n\n.result-edit-btn,\n.result-delete-btn {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n padding: 4px 8px;\n cursor: pointer;\n transition: all var(--mj-transition-base);\n font-size: var(--mj-text-sm);\n}\n\n.result-edit-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.result-delete-btn:hover {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n border-color: var(--mj-status-error);\n}\n\n.result-icon {\n font-size: 1.5em;\n flex-shrink: 0;\n}\n\n.result-code-card.success .result-icon {\n color: var(--mj-status-success);\n}\n\n.result-code-card.failure .result-icon {\n color: var(--mj-status-error);\n}\n\n.result-content {\n flex: 1;\n min-width: 0;\n}\n\n.result-code {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n font-family: 'Courier New', monospace;\n}\n\n.result-description {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.4;\n}\n\n/* Execution Section */\n.execution-stats-row {\n display: flex;\n gap: 20px;\n margin-bottom: 32px;\n flex-wrap: wrap;\n}\n\n.stat-box {\n flex: 1;\n min-width: 200px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 20px;\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.stat-box i {\n font-size: 2em;\n color: var(--mj-text-muted);\n}\n\n.stat-info {\n flex: 1;\n}\n\n.executions-table {\n overflow-x: auto;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n}\n\n.executions-table table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.executions-table th {\n background: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-default);\n}\n\n.executions-table td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n color: var(--mj-text-primary);\n}\n\n.execution-row {\n transition: background var(--mj-transition-base);\n}\n\n.execution-row:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.execution-row.success {\n background: color-mix(in srgb, var(--mj-status-success) 5%, transparent);\n}\n\n.running {\n color: var(--mj-status-warning);\n font-style: italic;\n}\n\n.result-code {\n display: inline-block;\n padding: 4px 8px;\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n font-family: 'Courier New', monospace;\n}\n\n.result-code.success {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.result-code.failure {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n/* Configuration Section */\n.config-subsection {\n margin-bottom: 32px;\n}\n\n.config-subsection h3 {\n margin: 0 0 16px 0;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.library-cards {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.library-card {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.library-card:hover {\n background: var(--mj-bg-surface-hover);\n transform: translateX(4px);\n}\n\n.library-card i:first-child {\n font-size: 1.5em;\n color: var(--mj-text-muted);\n}\n\n.library-info {\n flex: 1;\n min-width: 0;\n}\n\n.library-name {\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.library-items {\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n font-family: 'Courier New', monospace;\n}\n\n.related-entities-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n}\n\n.related-entity-link {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all var(--mj-transition-base);\n}\n\n.related-entity-link:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-brand-primary);\n}\n\n.related-entity-link i {\n font-size: 1.2em;\n color: var(--mj-text-muted);\n}\n\n.related-entity-link span:first-of-type {\n flex: 1;\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n}\n\n.entity-count {\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-sm);\n}\n\n/* Common States */\n.loading-state {\n text-align: center;\n padding: 60px;\n color: var(--mj-text-muted);\n}\n\n.loading-state i {\n font-size: 2em;\n margin-bottom: 12px;\n}\n\n.empty-state {\n text-align: center;\n padding: 60px;\n color: var(--mj-text-muted);\n}\n\n.empty-state.mini {\n padding: 20px;\n}\n\n.empty-state i {\n font-size: 3em;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.empty-state p {\n margin: 0;\n font-size: 1.1em;\n}\n\n.empty-hint {\n margin-top: 8px !important;\n font-size: var(--mj-text-sm) !important;\n opacity: 0.7;\n}\n\n.no-params {\n text-align: center;\n padding: 20px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n.no-params p {\n margin: 0;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .action-hero-header {\n padding: 20px;\n }\n\n .action-identity {\n flex-direction: column;\n text-align: center;\n }\n\n .action-icon-wrapper {\n margin: 0 auto;\n }\n\n .action-title-row {\n justify-content: center;\n }\n\n .action-stats {\n justify-content: center;\n }\n\n .params-grid {\n grid-template-columns: 1fr;\n }\n}\n\n"] }]
|
|
2332
2332
|
}], null, null); })();
|
|
2333
2333
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJActionFormComponentExtended, { className: "MJActionFormComponentExtended", filePath: "src/lib/custom/Actions/action-form.component.ts", lineNumber: 18 }); })();
|
|
2334
2334
|
//# sourceMappingURL=action-form.component.js.map
|