@memberjunction/ng-agent-requests 6.1.0-edge.5 → 6.1.0-edge.7

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.
@@ -17,19 +17,19 @@ import { AgentRequestPanelComponent } from './panels/agent-request-panel/agent-r
17
17
  import { AgentRequestDialogComponent } from './dialogs/agent-request-dialog.component';
18
18
  import * as i0 from "@angular/core";
19
19
  export class AgentRequestsModule {
20
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AgentRequestsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
21
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.3", ngImport: i0, type: AgentRequestsModule, declarations: [AgentRequestPanelComponent,
20
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: AgentRequestsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
21
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.22", ngImport: i0, type: AgentRequestsModule, declarations: [AgentRequestPanelComponent,
22
22
  AgentRequestDialogComponent], imports: [CommonModule,
23
23
  FormsModule,
24
24
  SharedGenericModule,
25
25
  DynamicFormsModule], exports: [AgentRequestPanelComponent,
26
26
  AgentRequestDialogComponent] });
27
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AgentRequestsModule, imports: [CommonModule,
27
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: AgentRequestsModule, imports: [CommonModule,
28
28
  FormsModule,
29
29
  SharedGenericModule,
30
30
  DynamicFormsModule] });
31
31
  }
32
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AgentRequestsModule, decorators: [{
32
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: AgentRequestsModule, decorators: [{
33
33
  type: NgModule,
34
34
  args: [{
35
35
  declarations: [
@@ -1 +1 @@
1
- {"version":3,"file":"agent-requests.module.js","sourceRoot":"","sources":["../../src/lib/agent-requests.module.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,yBAAyB;AACzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,mBAAmB;AACnB,OAAO,EAAE,0BAA0B,EAAE,MAAM,4DAA4D,CAAC;AAExG,oBAAoB;AACpB,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;;AAkBvF,MAAM,OAAO,mBAAmB;uGAAnB,mBAAmB;wGAAnB,mBAAmB,iBAdxB,0BAA0B;YAC1B,2BAA2B,aAG3B,YAAY;YACZ,WAAW;YACX,mBAAmB;YACnB,kBAAkB,aAGlB,0BAA0B;YAC1B,2BAA2B;wGAGtB,mBAAmB,YAVxB,YAAY;YACZ,WAAW;YACX,mBAAmB;YACnB,kBAAkB;;2FAOb,mBAAmB;kBAhB/B,QAAQ;mBAAC;oBACN,YAAY,EAAE;wBACV,0BAA0B;wBAC1B,2BAA2B;qBAC9B;oBACD,OAAO,EAAE;wBACL,YAAY;wBACZ,WAAW;wBACX,mBAAmB;wBACnB,kBAAkB;qBACrB;oBACD,OAAO,EAAE;wBACL,0BAA0B;wBAC1B,2BAA2B;qBAC9B;iBACJ","sourcesContent":["/**\n * @fileoverview Agent Requests Module\n *\n * Angular module providing reusable components for viewing and responding\n * to AI agent feedback requests. Supports both embedded panel and modal\n * dialog usage patterns.\n */\n\nimport { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\n\n// MemberJunction modules\nimport { SharedGenericModule } from '@memberjunction/ng-shared-generic';\nimport { DynamicFormsModule } from '@memberjunction/ng-forms';\n\n// Panel components\nimport { AgentRequestPanelComponent } from './panels/agent-request-panel/agent-request-panel.component';\n\n// Dialog components\nimport { AgentRequestDialogComponent } from './dialogs/agent-request-dialog.component';\n\n@NgModule({\n declarations: [\n AgentRequestPanelComponent,\n AgentRequestDialogComponent\n ],\n imports: [\n CommonModule,\n FormsModule,\n SharedGenericModule,\n DynamicFormsModule\n ],\n exports: [\n AgentRequestPanelComponent,\n AgentRequestDialogComponent\n ]\n})\nexport class AgentRequestsModule { }\n"]}
1
+ {"version":3,"file":"agent-requests.module.js","sourceRoot":"","sources":["../../src/lib/agent-requests.module.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,yBAAyB;AACzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,mBAAmB;AACnB,OAAO,EAAE,0BAA0B,EAAE,MAAM,4DAA4D,CAAC;AAExG,oBAAoB;AACpB,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;;AAkBvF,MAAM,OAAO,mBAAmB;wGAAnB,mBAAmB;yGAAnB,mBAAmB,iBAdxB,0BAA0B;YAC1B,2BAA2B,aAG3B,YAAY;YACZ,WAAW;YACX,mBAAmB;YACnB,kBAAkB,aAGlB,0BAA0B;YAC1B,2BAA2B;yGAGtB,mBAAmB,YAVxB,YAAY;YACZ,WAAW;YACX,mBAAmB;YACnB,kBAAkB;;4FAOb,mBAAmB;kBAhB/B,QAAQ;mBAAC;oBACN,YAAY,EAAE;wBACV,0BAA0B;wBAC1B,2BAA2B;qBAC9B;oBACD,OAAO,EAAE;wBACL,YAAY;wBACZ,WAAW;wBACX,mBAAmB;wBACnB,kBAAkB;qBACrB;oBACD,OAAO,EAAE;wBACL,0BAA0B;wBAC1B,2BAA2B;qBAC9B;iBACJ","sourcesContent":["/**\n * @fileoverview Agent Requests Module\n *\n * Angular module providing reusable components for viewing and responding\n * to AI agent feedback requests. Supports both embedded panel and modal\n * dialog usage patterns.\n */\n\nimport { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\n\n// MemberJunction modules\nimport { SharedGenericModule } from '@memberjunction/ng-shared-generic';\nimport { DynamicFormsModule } from '@memberjunction/ng-forms';\n\n// Panel components\nimport { AgentRequestPanelComponent } from './panels/agent-request-panel/agent-request-panel.component';\n\n// Dialog components\nimport { AgentRequestDialogComponent } from './dialogs/agent-request-dialog.component';\n\n@NgModule({\n declarations: [\n AgentRequestPanelComponent,\n AgentRequestDialogComponent\n ],\n imports: [\n CommonModule,\n FormsModule,\n SharedGenericModule,\n DynamicFormsModule\n ],\n exports: [\n AgentRequestPanelComponent,\n AgentRequestDialogComponent\n ]\n})\nexport class AgentRequestsModule { }\n"]}
@@ -68,8 +68,8 @@ export class AgentRequestDialogComponent extends BaseAngularComponent {
68
68
  this.Close.emit(result);
69
69
  this.cdr.markForCheck();
70
70
  }
71
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AgentRequestDialogComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
72
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: AgentRequestDialogComponent, isStandalone: false, selector: "mj-agent-request-dialog", inputs: { Visible: "Visible", Request: "Request" }, outputs: { Close: "Close" }, viewQueries: [{ propertyName: "requestPanel", first: true, predicate: ["requestPanel"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
71
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: AgentRequestDialogComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
72
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: AgentRequestDialogComponent, isStandalone: false, selector: "mj-agent-request-dialog", inputs: { Visible: "Visible", Request: "Request" }, outputs: { Close: "Close" }, viewQueries: [{ propertyName: "requestPanel", first: true, predicate: ["requestPanel"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
73
73
  @if (Visible) {
74
74
  @if (IsLoading) {
75
75
  <div class="loading-backdrop">
@@ -87,7 +87,7 @@ export class AgentRequestDialogComponent extends BaseAngularComponent {
87
87
  }
88
88
  `, isInline: true, styles: ["\n .loading-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n }\n "], dependencies: [{ kind: "component", type: i1.LoadingComponent, selector: "mj-loading", inputs: ["text", "showText", "animationDuration", "size", "textColor", "logoColor", "logoGradient", "animation"] }, { kind: "component", type: i2.AgentRequestPanelComponent, selector: "mj-agent-request-panel", inputs: ["Request", "RequestTypes", "IsOpen"], outputs: ["Close"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
89
89
  }
90
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AgentRequestDialogComponent, decorators: [{
90
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: AgentRequestDialogComponent, decorators: [{
91
91
  type: Component,
92
92
  args: [{ standalone: false, selector: 'mj-agent-request-dialog', template: `
93
93
  @if (Visible) {
@@ -1 +1 @@
1
- {"version":3,"file":"agent-request-dialog.component.js","sourceRoot":"","sources":["../../../src/lib/dialogs/agent-request-dialog.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Agent Request Dialog Component\n *\n * A dialog wrapper for the AgentRequestPanelComponent that provides\n * a convenient way to view and respond to agent requests in a modal context.\n */\n\nimport {\n Component, Input, Output, EventEmitter, ChangeDetectorRef,\n ChangeDetectionStrategy, ViewChild, OnInit, OnChanges, SimpleChanges\n} from '@angular/core';\nimport { MJAIAgentRequestEntity, MJAIAgentRequestTypeEntity } from '@memberjunction/core-entities';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { RunView } from '@memberjunction/core';\nimport { AgentRequestPanelComponent, AgentRequestPanelResult } from '../panels/agent-request-panel/agent-request-panel.component';\n\n@Component({\n standalone: false,\n selector: 'mj-agent-request-dialog',\n template: `\n @if (Visible) {\n @if (IsLoading) {\n <div class=\"loading-backdrop\">\n <mj-loading text=\"Loading request types...\"></mj-loading>\n </div>\n } @else {\n <mj-agent-request-panel\n #requestPanel\n [Request]=\"Request\"\n [RequestTypes]=\"requestTypes\"\n [IsOpen]=\"Visible\"\n (Close)=\"OnPanelClose($event)\">\n </mj-agent-request-panel>\n }\n }\n `,\n styles: [`\n .loading-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class AgentRequestDialogComponent extends BaseAngularComponent implements OnInit, OnChanges {\n @ViewChild('requestPanel') requestPanel!: AgentRequestPanelComponent;\n\n @Input() Visible = false;\n @Input() Request: MJAIAgentRequestEntity | null = null;\n\n @Output() Close = new EventEmitter<AgentRequestPanelResult>();\n\n public IsLoading = false;\n public requestTypes: MJAIAgentRequestTypeEntity[] = [];\n\n constructor(private cdr: ChangeDetectorRef) {\n super();}\n\n ngOnInit(): void {\n if (this.Visible) {\n this.loadRequestTypes();\n }\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['Visible'] && changes['Visible'].currentValue === true) {\n this.loadRequestTypes().then(() => {\n this.cdr.detectChanges();\n setTimeout(() => {\n if (this.requestPanel && this.Request) {\n this.requestPanel.Open(this.Request);\n }\n }, 0);\n });\n }\n }\n\n private async loadRequestTypes(): Promise<void> {\n if (this.requestTypes.length > 0) return;\n\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<MJAIAgentRequestTypeEntity>({\n EntityName: 'MJ: AI Agent Request Types',\n OrderBy: 'Name',\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n this.requestTypes = result.Results;\n }\n } catch (error) {\n console.error('Error loading request types:', error);\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n public OnPanelClose(result: AgentRequestPanelResult): void {\n this.Visible = false;\n this.Close.emit(result);\n this.cdr.markForCheck();\n }\n}\n"]}
1
+ {"version":3,"file":"agent-request-dialog.component.js","sourceRoot":"","sources":["../../../src/lib/dialogs/agent-request-dialog.component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACH,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EACtC,uBAAuB,EAAE,SAAS,EACrC,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;;;;AAuC/C,MAAM,OAAO,2BAA4B,SAAQ,oBAAoB;IAW7C;IAVO,YAAY,CAA8B;IAE5D,OAAO,GAAG,KAAK,CAAC;IAChB,OAAO,GAAkC,IAAI,CAAC;IAE7C,KAAK,GAAG,IAAI,YAAY,EAA2B,CAAC;IAEvD,SAAS,GAAG,KAAK,CAAC;IAClB,YAAY,GAAiC,EAAE,CAAC;IAEvD,YAAoB,GAAsB;QACtC,KAAK,EAAE,CAAC;QADQ,QAAG,GAAH,GAAG,CAAmB;IAC9B,CAAC;IAEb,QAAQ;QACJ,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC5B,CAAC;IACL,CAAC;IAED,WAAW,CAAC,OAAsB;QAC9B,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YACjE,IAAI,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;gBAC9B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;gBACzB,UAAU,CAAC,GAAG,EAAE;oBACZ,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;wBACpC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACzC,CAAC;gBACL,CAAC,EAAE,CAAC,CAAC,CAAC;YACV,CAAC,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,gBAAgB;QAC1B,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO;QAEzC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAExB,IAAI,CAAC;YACD,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC5D,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAA6B;gBACxD,UAAU,EAAE,4BAA4B;gBACxC,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,eAAe;aAC9B,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC;YACvC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;QACzD,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;IACL,CAAC;IAEM,YAAY,CAAC,MAA+B;QAC/C,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;wGA9DQ,2BAA2B;4FAA3B,2BAA2B,+TAjC1B;;;;;;;;;;;;;;;;KAgBT;;4FAiBQ,2BAA2B;kBApCvC,SAAS;iCACM,KAAK,YACP,yBAAyB,YACzB;;;;;;;;;;;;;;;;KAgBT,mBAegB,uBAAuB,CAAC,MAAM;;sBAG9C,SAAS;uBAAC,cAAc;;sBAExB,KAAK;;sBACL,KAAK;;sBAEL,MAAM","sourcesContent":["/**\n * @fileoverview Agent Request Dialog Component\n *\n * A dialog wrapper for the AgentRequestPanelComponent that provides\n * a convenient way to view and respond to agent requests in a modal context.\n */\n\nimport {\n Component, Input, Output, EventEmitter, ChangeDetectorRef,\n ChangeDetectionStrategy, ViewChild, OnInit, OnChanges, SimpleChanges\n} from '@angular/core';\nimport { MJAIAgentRequestEntity, MJAIAgentRequestTypeEntity } from '@memberjunction/core-entities';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { RunView } from '@memberjunction/core';\nimport { AgentRequestPanelComponent, AgentRequestPanelResult } from '../panels/agent-request-panel/agent-request-panel.component';\n\n@Component({\n standalone: false,\n selector: 'mj-agent-request-dialog',\n template: `\n @if (Visible) {\n @if (IsLoading) {\n <div class=\"loading-backdrop\">\n <mj-loading text=\"Loading request types...\"></mj-loading>\n </div>\n } @else {\n <mj-agent-request-panel\n #requestPanel\n [Request]=\"Request\"\n [RequestTypes]=\"requestTypes\"\n [IsOpen]=\"Visible\"\n (Close)=\"OnPanelClose($event)\">\n </mj-agent-request-panel>\n }\n }\n `,\n styles: [`\n .loading-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class AgentRequestDialogComponent extends BaseAngularComponent implements OnInit, OnChanges {\n @ViewChild('requestPanel') requestPanel!: AgentRequestPanelComponent;\n\n @Input() Visible = false;\n @Input() Request: MJAIAgentRequestEntity | null = null;\n\n @Output() Close = new EventEmitter<AgentRequestPanelResult>();\n\n public IsLoading = false;\n public requestTypes: MJAIAgentRequestTypeEntity[] = [];\n\n constructor(private cdr: ChangeDetectorRef) {\n super();}\n\n ngOnInit(): void {\n if (this.Visible) {\n this.loadRequestTypes();\n }\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['Visible'] && changes['Visible'].currentValue === true) {\n this.loadRequestTypes().then(() => {\n this.cdr.detectChanges();\n setTimeout(() => {\n if (this.requestPanel && this.Request) {\n this.requestPanel.Open(this.Request);\n }\n }, 0);\n });\n }\n }\n\n private async loadRequestTypes(): Promise<void> {\n if (this.requestTypes.length > 0) return;\n\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<MJAIAgentRequestTypeEntity>({\n EntityName: 'MJ: AI Agent Request Types',\n OrderBy: 'Name',\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n this.requestTypes = result.Results;\n }\n } catch (error) {\n console.error('Error loading request types:', error);\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n public OnPanelClose(result: AgentRequestPanelResult): void {\n this.Visible = false;\n this.Close.emit(result);\n this.cdr.markForCheck();\n }\n}\n"]}
@@ -389,10 +389,10 @@ export class AgentRequestPanelComponent extends BaseAngularComponent {
389
389
  this.cdr.markForCheck();
390
390
  }
391
391
  }
392
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AgentRequestPanelComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.MJNotificationService }], target: i0.ɵɵFactoryTarget.Component });
393
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: AgentRequestPanelComponent, isStandalone: false, selector: "mj-agent-request-panel", inputs: { Request: "Request", RequestTypes: "RequestTypes", IsOpen: "IsOpen" }, outputs: { Close: "Close" }, host: { listeners: { "document:keydown.escape": "OnEscapeKey()" } }, viewQueries: [{ propertyName: "dynamicForm", first: true, predicate: ["dynamicForm"], descendants: true }, { propertyName: "panelElement", first: true, predicate: ["panelElement"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (IsOpen && Request) {\n <div class=\"panel-backdrop\" (click)=\"OnBackdropClick()\">\n <div class=\"request-panel\" #panelElement [class.open]=\"IsOpen\" [class.resizing]=\"IsResizing\" [style.width.px]=\"PanelWidth\" (click)=\"$event.stopPropagation()\">\n <!-- Resize Handle (left edge) -->\n <div class=\"resize-handle\" (mousedown)=\"OnResizeStart($event)\">\n <div class=\"resize-grip\"></div>\n </div>\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-content\">\n <div class=\"header-title-row\">\n @if (RequestType?.Icon) {\n <i class=\"{{ RequestType!.Icon }} header-icon\"></i>\n }\n <h3 class=\"panel-title\">{{ RequestType?.Name || 'Agent Request' }}</h3>\n <span class=\"priority-badge\" [class]=\"PriorityClass\">{{ PriorityLabel }}</span>\n <span class=\"status-badge status-{{ Request.Status.toLowerCase() }}\">{{ Request.Status }}</span>\n </div>\n @if (Request.Agent) {\n <span class=\"agent-name\">\n <i class=\"fa-solid fa-robot\"></i> {{ Request.Agent }}\n </span>\n }\n </div>\n <button class=\"close-btn\" (click)=\"OnCancel()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Body -->\n <div class=\"panel-body\">\n <!-- Request Details -->\n <div class=\"section\">\n <h4 class=\"section-title\">Request</h4>\n <p class=\"request-text\">{{ Request.Request }}</p>\n </div>\n\n <!-- Metadata -->\n <div class=\"section metadata-section\">\n <div class=\"metadata-grid\">\n @if (Request.ExpiresAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Expires</span>\n <span class=\"metadata-value\" [class.expired]=\"IsExpired\">\n {{ Request.ExpiresAt | date:'medium' }}\n @if (IsExpired) {\n <span class=\"expired-tag\">Expired</span>\n }\n </span>\n </div>\n }\n @if (Request.__mj_CreatedAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Created</span>\n <span class=\"metadata-value\">{{ Request.__mj_CreatedAt | date:'medium' }}</span>\n </div>\n }\n @if (Request.RespondedAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Responded</span>\n <span class=\"metadata-value\">{{ Request.RespondedAt | date:'medium' }}</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Dynamic Response Form (from ResponseSchema) -->\n @if (HasResponseForm && IsActionable && ResponseFormDefinition) {\n <div class=\"section\">\n <mj-dynamic-form #dynamicForm\n [FormDefinition]=\"ResponseFormDefinition\"\n [Disabled]=\"IsSaving\">\n </mj-dynamic-form>\n </div>\n }\n\n <!-- Free-text response (always available for actionable requests) -->\n @if (IsActionable) {\n <div class=\"section\">\n <h4 class=\"section-title\">\n @if (HasResponseForm) {\n Additional Comments\n } @else {\n Response\n }\n </h4>\n <textarea\n class=\"response-textarea\"\n [(ngModel)]=\"ResponseText\"\n placeholder=\"Type your response here...\"\n rows=\"4\">\n </textarea>\n </div>\n }\n\n <!-- Show existing response for already-handled requests -->\n @if (!IsActionable && (Request.Response || Request.ResponseData)) {\n @if (Request.ResponseData) {\n <div class=\"section\">\n <mj-dynamic-form-response\n [FormDefinition]=\"ResponseFormDefinition\"\n [ResponseData]=\"Request.ResponseData\"\n DisplayMode=\"card\">\n </mj-dynamic-form-response>\n </div>\n }\n @if (Request.Response) {\n <div class=\"section\">\n <h4 class=\"section-title\">\n @if (Request.ResponseData) {\n Additional Comments\n } @else {\n Response\n }\n </h4>\n <p class=\"response-text\">{{ Request.Response }}</p>\n </div>\n }\n }\n </div>\n\n <!-- Footer (action buttons) -->\n @if (IsActionable && !IsExpired) {\n <div class=\"panel-footer\">\n @if (IsApprovalType) {\n <button\n class=\"btn btn-approve\"\n (click)=\"OnApprove()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-check\"></i> Approve\n </button>\n <button\n class=\"btn btn-reject\"\n (click)=\"OnReject()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-times\"></i> Reject\n </button>\n } @else {\n <button\n class=\"btn btn-respond\"\n (click)=\"OnRespond()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-paper-plane\"></i> Submit Response\n </button>\n }\n <button\n class=\"btn btn-reassign\"\n (click)=\"OnReassignClick()\"\n [disabled]=\"IsSaving\"\n title=\"Reassign to another user\">\n <i class=\"fa-solid fa-user-plus\"></i> Reassign\n </button>\n <button\n class=\"btn btn-cancel\"\n (click)=\"OnCancel()\"\n [disabled]=\"IsSaving\">\n Cancel\n </button>\n </div>\n } @else if (IsExpired) {\n <div class=\"panel-footer\">\n <div class=\"expired-notice\">\n <i class=\"fa-solid fa-clock\"></i> This request has expired and can no longer be responded to.\n </div>\n <button class=\"btn btn-cancel\" (click)=\"OnCancel()\">Close</button>\n </div>\n } @else {\n <div class=\"panel-footer\">\n <button class=\"btn btn-cancel\" (click)=\"OnCancel()\">Close</button>\n </div>\n }\n </div>\n </div>\n\n <!-- Reassign Dialog Overlay -->\n @if (ShowReassignDialog) {\n <div class=\"reassign-overlay\" (click)=\"OnReassignCancel()\">\n <div class=\"reassign-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"reassign-header\">\n <h4 class=\"reassign-title\">\n <i class=\"fa-solid fa-user-plus\"></i> Reassign Request\n </h4>\n <button class=\"close-btn\" (click)=\"OnReassignCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"reassign-body\">\n <!-- User Search -->\n <div class=\"reassign-field\">\n <label class=\"field-label\">Search User</label>\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input\n type=\"text\"\n class=\"field-input search-input\"\n placeholder=\"Type a name or email...\"\n [value]=\"ReassignSearchTerm\"\n (input)=\"OnReassignSearchChange($any($event.target).value)\">\n </div>\n </div>\n\n <!-- Search Results -->\n @if (IsSearchingUsers) {\n <div class=\"search-status\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Searching...\n </div>\n }\n @if (ReassignUsers.length > 0) {\n <div class=\"user-results\">\n @for (user of ReassignUsers; track user.ID) {\n <button\n class=\"user-result-item\"\n [class.selected]=\"SelectedReassignUser?.ID === user.ID\"\n (click)=\"OnSelectReassignUser(user)\">\n <i class=\"fa-solid fa-user user-avatar\"></i>\n <div class=\"user-info\">\n <span class=\"user-name\">{{ user.Name }}</span>\n <span class=\"user-email\">{{ user.Email }}</span>\n </div>\n @if (SelectedReassignUser?.ID === user.ID) {\n <i class=\"fa-solid fa-check selected-check\"></i>\n }\n </button>\n }\n </div>\n } @else if (ReassignSearchTerm.length >= 2 && !IsSearchingUsers) {\n <div class=\"search-status\">No users found</div>\n }\n\n <!-- Note -->\n <div class=\"reassign-field\">\n <label class=\"field-label\">Note (optional)</label>\n <textarea\n class=\"field-textarea\"\n [(ngModel)]=\"ReassignNote\"\n placeholder=\"Add a reason for reassignment...\"\n rows=\"2\">\n </textarea>\n </div>\n </div>\n\n <div class=\"reassign-footer\">\n <button\n class=\"btn btn-respond\"\n (click)=\"OnReassignSubmit()\"\n [disabled]=\"!SelectedReassignUser || IsReassigning\">\n @if (IsReassigning) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Reassigning...\n } @else {\n <i class=\"fa-solid fa-user-plus\"></i> Reassign\n }\n </button>\n <button\n class=\"btn btn-cancel\"\n (click)=\"OnReassignCancel()\"\n [disabled]=\"IsReassigning\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n}\n", styles: ["/* Panel Backdrop */\n.panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n justify-content: flex-end;\n z-index: 10000;\n}\n\n/* Slide-in Panel */\n.request-panel {\n max-width: 90vw;\n min-width: 360px;\n height: 100%;\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n transform: translateX(100%);\n transition: transform 0.25s ease-out;\n position: relative;\n}\n\n.request-panel.open {\n transform: translateX(0);\n}\n\n.request-panel.resizing {\n transition: none;\n}\n\n/* Resize Handle */\n.resize-handle {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: col-resize;\n z-index: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.resize-handle:hover,\n.resize-handle:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.resize-grip {\n width: 2px;\n height: 32px;\n border-radius: 1px;\n background: var(--mj-border-strong);\n opacity: 0;\n transition: opacity 0.15s;\n}\n\n.resize-handle:hover .resize-grip,\n.resize-handle:active .resize-grip {\n opacity: 1;\n}\n\n/* Header */\n.panel-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.header-content {\n display: flex;\n flex-direction: column;\n gap: 4px;\n flex: 1;\n min-width: 0;\n}\n\n.header-title-row {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.header-icon {\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.panel-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.agent-name {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.close-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px 8px;\n color: var(--mj-text-muted);\n font-size: 16px;\n border-radius: 4px;\n}\n\n.close-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Status Badge */\n.status-badge {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.status-requested {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n border: 1px solid var(--mj-status-info-border);\n}\n\n.status-approved {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.status-rejected,\n.status-canceled {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.status-responded {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.status-expired {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning-border);\n}\n\n/* Priority Badge */\n.priority-badge {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.priority-low {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.priority-normal {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n}\n\n.priority-high {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n}\n\n.priority-critical {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n/* Body */\n.panel-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n.section {\n margin-bottom: 20px;\n}\n\n.section-title {\n margin: 0 0 8px 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.request-text {\n margin: 0;\n font-size: 14px;\n line-height: 1.6;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n}\n\n.response-text {\n margin: 0;\n font-size: 14px;\n line-height: 1.6;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n background: var(--mj-bg-surface-sunken);\n padding: 12px;\n border-radius: 6px;\n}\n\n/* Metadata */\n.metadata-section {\n background: var(--mj-bg-surface-card);\n padding: 12px;\n border-radius: 6px;\n}\n\n.metadata-grid {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.metadata-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.metadata-label {\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: 500;\n}\n\n.metadata-value {\n font-size: 12px;\n color: var(--mj-text-primary);\n}\n\n.metadata-value.expired {\n color: var(--mj-status-error-text);\n}\n\n.expired-tag {\n display: inline-block;\n margin-left: 6px;\n padding: 1px 6px;\n border-radius: 8px;\n font-size: 10px;\n font-weight: 600;\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n/* Shared field styles (used by reassign dialog and free-text response) */\n.field-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.field-input,\n.field-textarea {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n transition: border-color 0.15s;\n}\n\n.field-input:focus,\n.field-textarea:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.field-textarea {\n resize: vertical;\n min-height: 60px;\n}\n\n.response-textarea {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n font-family: inherit;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n resize: vertical;\n box-sizing: border-box;\n}\n\n.response-textarea:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n/* Footer */\n.panel-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.btn {\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: background-color 0.15s;\n}\n\n.btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-approve {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.btn-approve:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-success) 85%, black);\n}\n\n.btn-reject {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n.btn-reject:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 85%, black);\n}\n\n.btn-respond {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-respond:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.btn-cancel {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n margin-left: auto;\n}\n\n.btn-cancel:hover:not(:disabled) {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n}\n\n.btn-reassign {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n.btn-reassign:hover:not(:disabled) {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-strong);\n}\n\n.expired-notice {\n font-size: 13px;\n color: var(--mj-status-warning-text);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n/* Reassign Dialog */\n.reassign-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10001;\n}\n\n.reassign-dialog {\n width: 420px;\n max-width: 90vw;\n max-height: 80vh;\n background: var(--mj-bg-surface);\n border-radius: 10px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.reassign-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.reassign-title {\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.reassign-body {\n padding: 16px 20px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n.reassign-field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.search-input-wrapper {\n position: relative;\n}\n\n.search-icon {\n position: absolute;\n left: 10px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.search-input {\n padding-left: 32px;\n}\n\n.search-status {\n font-size: 13px;\n color: var(--mj-text-muted);\n padding: 8px 0;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.user-results {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 200px;\n overflow-y: auto;\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n}\n\n.user-result-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 12px;\n background: none;\n border: none;\n cursor: pointer;\n text-align: left;\n width: 100%;\n transition: background-color 0.1s;\n}\n\n.user-result-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-result-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.user-avatar {\n color: var(--mj-text-muted);\n font-size: 14px;\n width: 20px;\n text-align: center;\n}\n\n.user-info {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n}\n\n.user-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.user-email {\n font-size: 12px;\n color: var(--mj-text-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.selected-check {\n color: var(--mj-brand-primary);\n font-size: 13px;\n}\n\n.reassign-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n"], dependencies: [{ kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.DynamicFormComponent, selector: "mj-dynamic-form", inputs: ["FormDefinition", "Disabled", "Visible"], outputs: ["FormSubmitted"] }, { kind: "component", type: i3.DynamicFormResponseComponent, selector: "mj-dynamic-form-response", inputs: ["FormDefinition", "ResponseData", "Title", "DisplayMode"] }, { kind: "pipe", type: i4.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
392
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: AgentRequestPanelComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.MJNotificationService }], target: i0.ɵɵFactoryTarget.Component });
393
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: AgentRequestPanelComponent, isStandalone: false, selector: "mj-agent-request-panel", inputs: { Request: "Request", RequestTypes: "RequestTypes", IsOpen: "IsOpen" }, outputs: { Close: "Close" }, host: { listeners: { "document:keydown.escape": "OnEscapeKey()" } }, viewQueries: [{ propertyName: "dynamicForm", first: true, predicate: ["dynamicForm"], descendants: true }, { propertyName: "panelElement", first: true, predicate: ["panelElement"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (IsOpen && Request) {\n <div class=\"panel-backdrop\" (click)=\"OnBackdropClick()\">\n <div class=\"request-panel\" #panelElement [class.open]=\"IsOpen\" [class.resizing]=\"IsResizing\" [style.width.px]=\"PanelWidth\" (click)=\"$event.stopPropagation()\">\n <!-- Resize Handle (left edge) -->\n <div class=\"resize-handle\" (mousedown)=\"OnResizeStart($event)\">\n <div class=\"resize-grip\"></div>\n </div>\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-content\">\n <div class=\"header-title-row\">\n @if (RequestType?.Icon) {\n <i class=\"{{ RequestType!.Icon }} header-icon\"></i>\n }\n <h3 class=\"panel-title\">{{ RequestType?.Name || 'Agent Request' }}</h3>\n <span class=\"priority-badge\" [class]=\"PriorityClass\">{{ PriorityLabel }}</span>\n <span class=\"status-badge status-{{ Request.Status.toLowerCase() }}\">{{ Request.Status }}</span>\n </div>\n @if (Request.Agent) {\n <span class=\"agent-name\">\n <i class=\"fa-solid fa-robot\"></i> {{ Request.Agent }}\n </span>\n }\n </div>\n <button class=\"close-btn\" (click)=\"OnCancel()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Body -->\n <div class=\"panel-body\">\n <!-- Request Details -->\n <div class=\"section\">\n <h4 class=\"section-title\">Request</h4>\n <p class=\"request-text\">{{ Request.Request }}</p>\n </div>\n\n <!-- Metadata -->\n <div class=\"section metadata-section\">\n <div class=\"metadata-grid\">\n @if (Request.ExpiresAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Expires</span>\n <span class=\"metadata-value\" [class.expired]=\"IsExpired\">\n {{ Request.ExpiresAt | date:'medium' }}\n @if (IsExpired) {\n <span class=\"expired-tag\">Expired</span>\n }\n </span>\n </div>\n }\n @if (Request.__mj_CreatedAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Created</span>\n <span class=\"metadata-value\">{{ Request.__mj_CreatedAt | date:'medium' }}</span>\n </div>\n }\n @if (Request.RespondedAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Responded</span>\n <span class=\"metadata-value\">{{ Request.RespondedAt | date:'medium' }}</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Dynamic Response Form (from ResponseSchema) -->\n @if (HasResponseForm && IsActionable && ResponseFormDefinition) {\n <div class=\"section\">\n <mj-dynamic-form #dynamicForm\n [FormDefinition]=\"ResponseFormDefinition\"\n [Disabled]=\"IsSaving\">\n </mj-dynamic-form>\n </div>\n }\n\n <!-- Free-text response (always available for actionable requests) -->\n @if (IsActionable) {\n <div class=\"section\">\n <h4 class=\"section-title\">\n @if (HasResponseForm) {\n Additional Comments\n } @else {\n Response\n }\n </h4>\n <textarea\n class=\"response-textarea\"\n [(ngModel)]=\"ResponseText\"\n placeholder=\"Type your response here...\"\n rows=\"4\">\n </textarea>\n </div>\n }\n\n <!-- Show existing response for already-handled requests -->\n @if (!IsActionable && (Request.Response || Request.ResponseData)) {\n @if (Request.ResponseData) {\n <div class=\"section\">\n <mj-dynamic-form-response\n [FormDefinition]=\"ResponseFormDefinition\"\n [ResponseData]=\"Request.ResponseData\"\n DisplayMode=\"card\">\n </mj-dynamic-form-response>\n </div>\n }\n @if (Request.Response) {\n <div class=\"section\">\n <h4 class=\"section-title\">\n @if (Request.ResponseData) {\n Additional Comments\n } @else {\n Response\n }\n </h4>\n <p class=\"response-text\">{{ Request.Response }}</p>\n </div>\n }\n }\n </div>\n\n <!-- Footer (action buttons) -->\n @if (IsActionable && !IsExpired) {\n <div class=\"panel-footer\">\n @if (IsApprovalType) {\n <button\n class=\"btn btn-approve\"\n (click)=\"OnApprove()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-check\"></i> Approve\n </button>\n <button\n class=\"btn btn-reject\"\n (click)=\"OnReject()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-times\"></i> Reject\n </button>\n } @else {\n <button\n class=\"btn btn-respond\"\n (click)=\"OnRespond()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-paper-plane\"></i> Submit Response\n </button>\n }\n <button\n class=\"btn btn-reassign\"\n (click)=\"OnReassignClick()\"\n [disabled]=\"IsSaving\"\n title=\"Reassign to another user\">\n <i class=\"fa-solid fa-user-plus\"></i> Reassign\n </button>\n <button\n class=\"btn btn-cancel\"\n (click)=\"OnCancel()\"\n [disabled]=\"IsSaving\">\n Cancel\n </button>\n </div>\n } @else if (IsExpired) {\n <div class=\"panel-footer\">\n <div class=\"expired-notice\">\n <i class=\"fa-solid fa-clock\"></i> This request has expired and can no longer be responded to.\n </div>\n <button class=\"btn btn-cancel\" (click)=\"OnCancel()\">Close</button>\n </div>\n } @else {\n <div class=\"panel-footer\">\n <button class=\"btn btn-cancel\" (click)=\"OnCancel()\">Close</button>\n </div>\n }\n </div>\n </div>\n\n <!-- Reassign Dialog Overlay -->\n @if (ShowReassignDialog) {\n <div class=\"reassign-overlay\" (click)=\"OnReassignCancel()\">\n <div class=\"reassign-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"reassign-header\">\n <h4 class=\"reassign-title\">\n <i class=\"fa-solid fa-user-plus\"></i> Reassign Request\n </h4>\n <button class=\"close-btn\" (click)=\"OnReassignCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"reassign-body\">\n <!-- User Search -->\n <div class=\"reassign-field\">\n <label class=\"field-label\">Search User</label>\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input\n type=\"text\"\n class=\"field-input search-input\"\n placeholder=\"Type a name or email...\"\n [value]=\"ReassignSearchTerm\"\n (input)=\"OnReassignSearchChange($any($event.target).value)\">\n </div>\n </div>\n\n <!-- Search Results -->\n @if (IsSearchingUsers) {\n <div class=\"search-status\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Searching...\n </div>\n }\n @if (ReassignUsers.length > 0) {\n <div class=\"user-results\">\n @for (user of ReassignUsers; track user.ID) {\n <button\n class=\"user-result-item\"\n [class.selected]=\"SelectedReassignUser?.ID === user.ID\"\n (click)=\"OnSelectReassignUser(user)\">\n <i class=\"fa-solid fa-user user-avatar\"></i>\n <div class=\"user-info\">\n <span class=\"user-name\">{{ user.Name }}</span>\n <span class=\"user-email\">{{ user.Email }}</span>\n </div>\n @if (SelectedReassignUser?.ID === user.ID) {\n <i class=\"fa-solid fa-check selected-check\"></i>\n }\n </button>\n }\n </div>\n } @else if (ReassignSearchTerm.length >= 2 && !IsSearchingUsers) {\n <div class=\"search-status\">No users found</div>\n }\n\n <!-- Note -->\n <div class=\"reassign-field\">\n <label class=\"field-label\">Note (optional)</label>\n <textarea\n class=\"field-textarea\"\n [(ngModel)]=\"ReassignNote\"\n placeholder=\"Add a reason for reassignment...\"\n rows=\"2\">\n </textarea>\n </div>\n </div>\n\n <div class=\"reassign-footer\">\n <button\n class=\"btn btn-respond\"\n (click)=\"OnReassignSubmit()\"\n [disabled]=\"!SelectedReassignUser || IsReassigning\">\n @if (IsReassigning) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Reassigning...\n } @else {\n <i class=\"fa-solid fa-user-plus\"></i> Reassign\n }\n </button>\n <button\n class=\"btn btn-cancel\"\n (click)=\"OnReassignCancel()\"\n [disabled]=\"IsReassigning\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n}\n", styles: ["/* Panel Backdrop */\n.panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n justify-content: flex-end;\n z-index: 10000;\n}\n\n/* Slide-in Panel */\n.request-panel {\n max-width: 90vw;\n min-width: 360px;\n height: 100%;\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n transform: translateX(100%);\n transition: transform 0.25s ease-out;\n position: relative;\n}\n\n.request-panel.open {\n transform: translateX(0);\n}\n\n.request-panel.resizing {\n transition: none;\n}\n\n/* Resize Handle */\n.resize-handle {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: col-resize;\n z-index: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.resize-handle:hover,\n.resize-handle:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.resize-grip {\n width: 2px;\n height: 32px;\n border-radius: 1px;\n background: var(--mj-border-strong);\n opacity: 0;\n transition: opacity 0.15s;\n}\n\n.resize-handle:hover .resize-grip,\n.resize-handle:active .resize-grip {\n opacity: 1;\n}\n\n/* Header */\n.panel-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.header-content {\n display: flex;\n flex-direction: column;\n gap: 4px;\n flex: 1;\n min-width: 0;\n}\n\n.header-title-row {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.header-icon {\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.panel-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.agent-name {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.close-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px 8px;\n color: var(--mj-text-muted);\n font-size: 16px;\n border-radius: 4px;\n}\n\n.close-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Status Badge */\n.status-badge {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.status-requested {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n border: 1px solid var(--mj-status-info-border);\n}\n\n.status-approved {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.status-rejected,\n.status-canceled {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.status-responded {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.status-expired {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning-border);\n}\n\n/* Priority Badge */\n.priority-badge {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.priority-low {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.priority-normal {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n}\n\n.priority-high {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n}\n\n.priority-critical {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n/* Body */\n.panel-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n.section {\n margin-bottom: 20px;\n}\n\n.section-title {\n margin: 0 0 8px 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.request-text {\n margin: 0;\n font-size: 14px;\n line-height: 1.6;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n}\n\n.response-text {\n margin: 0;\n font-size: 14px;\n line-height: 1.6;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n background: var(--mj-bg-surface-sunken);\n padding: 12px;\n border-radius: 6px;\n}\n\n/* Metadata */\n.metadata-section {\n background: var(--mj-bg-surface-card);\n padding: 12px;\n border-radius: 6px;\n}\n\n.metadata-grid {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.metadata-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.metadata-label {\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: 500;\n}\n\n.metadata-value {\n font-size: 12px;\n color: var(--mj-text-primary);\n}\n\n.metadata-value.expired {\n color: var(--mj-status-error-text);\n}\n\n.expired-tag {\n display: inline-block;\n margin-left: 6px;\n padding: 1px 6px;\n border-radius: 8px;\n font-size: 10px;\n font-weight: 600;\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n/* Shared field styles (used by reassign dialog and free-text response) */\n.field-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.field-input,\n.field-textarea {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n transition: border-color 0.15s;\n}\n\n.field-input:focus,\n.field-textarea:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.field-textarea {\n resize: vertical;\n min-height: 60px;\n}\n\n.response-textarea {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n font-family: inherit;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n resize: vertical;\n box-sizing: border-box;\n}\n\n.response-textarea:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n/* Footer */\n.panel-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.btn {\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: background-color 0.15s;\n}\n\n.btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-approve {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.btn-approve:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-success) 85%, black);\n}\n\n.btn-reject {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n.btn-reject:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 85%, black);\n}\n\n.btn-respond {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-respond:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.btn-cancel {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n margin-left: auto;\n}\n\n.btn-cancel:hover:not(:disabled) {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n}\n\n.btn-reassign {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n.btn-reassign:hover:not(:disabled) {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-strong);\n}\n\n.expired-notice {\n font-size: 13px;\n color: var(--mj-status-warning-text);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n/* Reassign Dialog */\n.reassign-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10001;\n}\n\n.reassign-dialog {\n width: 420px;\n max-width: 90vw;\n max-height: 80vh;\n background: var(--mj-bg-surface);\n border-radius: 10px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.reassign-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.reassign-title {\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.reassign-body {\n padding: 16px 20px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n.reassign-field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.search-input-wrapper {\n position: relative;\n}\n\n.search-icon {\n position: absolute;\n left: 10px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.search-input {\n padding-left: 32px;\n}\n\n.search-status {\n font-size: 13px;\n color: var(--mj-text-muted);\n padding: 8px 0;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.user-results {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 200px;\n overflow-y: auto;\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n}\n\n.user-result-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 12px;\n background: none;\n border: none;\n cursor: pointer;\n text-align: left;\n width: 100%;\n transition: background-color 0.1s;\n}\n\n.user-result-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-result-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.user-avatar {\n color: var(--mj-text-muted);\n font-size: 14px;\n width: 20px;\n text-align: center;\n}\n\n.user-info {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n}\n\n.user-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.user-email {\n font-size: 12px;\n color: var(--mj-text-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.selected-check {\n color: var(--mj-brand-primary);\n font-size: 13px;\n}\n\n.reassign-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n"], dependencies: [{ kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.DynamicFormComponent, selector: "mj-dynamic-form", inputs: ["FormDefinition", "Disabled", "Visible"], outputs: ["FormSubmitted"] }, { kind: "component", type: i3.DynamicFormResponseComponent, selector: "mj-dynamic-form-response", inputs: ["FormDefinition", "ResponseData", "Title", "DisplayMode"] }, { kind: "pipe", type: i4.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
394
394
  }
395
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AgentRequestPanelComponent, decorators: [{
395
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: AgentRequestPanelComponent, decorators: [{
396
396
  type: Component,
397
397
  args: [{ standalone: false, selector: 'mj-agent-request-panel', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (IsOpen && Request) {\n <div class=\"panel-backdrop\" (click)=\"OnBackdropClick()\">\n <div class=\"request-panel\" #panelElement [class.open]=\"IsOpen\" [class.resizing]=\"IsResizing\" [style.width.px]=\"PanelWidth\" (click)=\"$event.stopPropagation()\">\n <!-- Resize Handle (left edge) -->\n <div class=\"resize-handle\" (mousedown)=\"OnResizeStart($event)\">\n <div class=\"resize-grip\"></div>\n </div>\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-content\">\n <div class=\"header-title-row\">\n @if (RequestType?.Icon) {\n <i class=\"{{ RequestType!.Icon }} header-icon\"></i>\n }\n <h3 class=\"panel-title\">{{ RequestType?.Name || 'Agent Request' }}</h3>\n <span class=\"priority-badge\" [class]=\"PriorityClass\">{{ PriorityLabel }}</span>\n <span class=\"status-badge status-{{ Request.Status.toLowerCase() }}\">{{ Request.Status }}</span>\n </div>\n @if (Request.Agent) {\n <span class=\"agent-name\">\n <i class=\"fa-solid fa-robot\"></i> {{ Request.Agent }}\n </span>\n }\n </div>\n <button class=\"close-btn\" (click)=\"OnCancel()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Body -->\n <div class=\"panel-body\">\n <!-- Request Details -->\n <div class=\"section\">\n <h4 class=\"section-title\">Request</h4>\n <p class=\"request-text\">{{ Request.Request }}</p>\n </div>\n\n <!-- Metadata -->\n <div class=\"section metadata-section\">\n <div class=\"metadata-grid\">\n @if (Request.ExpiresAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Expires</span>\n <span class=\"metadata-value\" [class.expired]=\"IsExpired\">\n {{ Request.ExpiresAt | date:'medium' }}\n @if (IsExpired) {\n <span class=\"expired-tag\">Expired</span>\n }\n </span>\n </div>\n }\n @if (Request.__mj_CreatedAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Created</span>\n <span class=\"metadata-value\">{{ Request.__mj_CreatedAt | date:'medium' }}</span>\n </div>\n }\n @if (Request.RespondedAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Responded</span>\n <span class=\"metadata-value\">{{ Request.RespondedAt | date:'medium' }}</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Dynamic Response Form (from ResponseSchema) -->\n @if (HasResponseForm && IsActionable && ResponseFormDefinition) {\n <div class=\"section\">\n <mj-dynamic-form #dynamicForm\n [FormDefinition]=\"ResponseFormDefinition\"\n [Disabled]=\"IsSaving\">\n </mj-dynamic-form>\n </div>\n }\n\n <!-- Free-text response (always available for actionable requests) -->\n @if (IsActionable) {\n <div class=\"section\">\n <h4 class=\"section-title\">\n @if (HasResponseForm) {\n Additional Comments\n } @else {\n Response\n }\n </h4>\n <textarea\n class=\"response-textarea\"\n [(ngModel)]=\"ResponseText\"\n placeholder=\"Type your response here...\"\n rows=\"4\">\n </textarea>\n </div>\n }\n\n <!-- Show existing response for already-handled requests -->\n @if (!IsActionable && (Request.Response || Request.ResponseData)) {\n @if (Request.ResponseData) {\n <div class=\"section\">\n <mj-dynamic-form-response\n [FormDefinition]=\"ResponseFormDefinition\"\n [ResponseData]=\"Request.ResponseData\"\n DisplayMode=\"card\">\n </mj-dynamic-form-response>\n </div>\n }\n @if (Request.Response) {\n <div class=\"section\">\n <h4 class=\"section-title\">\n @if (Request.ResponseData) {\n Additional Comments\n } @else {\n Response\n }\n </h4>\n <p class=\"response-text\">{{ Request.Response }}</p>\n </div>\n }\n }\n </div>\n\n <!-- Footer (action buttons) -->\n @if (IsActionable && !IsExpired) {\n <div class=\"panel-footer\">\n @if (IsApprovalType) {\n <button\n class=\"btn btn-approve\"\n (click)=\"OnApprove()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-check\"></i> Approve\n </button>\n <button\n class=\"btn btn-reject\"\n (click)=\"OnReject()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-times\"></i> Reject\n </button>\n } @else {\n <button\n class=\"btn btn-respond\"\n (click)=\"OnRespond()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-paper-plane\"></i> Submit Response\n </button>\n }\n <button\n class=\"btn btn-reassign\"\n (click)=\"OnReassignClick()\"\n [disabled]=\"IsSaving\"\n title=\"Reassign to another user\">\n <i class=\"fa-solid fa-user-plus\"></i> Reassign\n </button>\n <button\n class=\"btn btn-cancel\"\n (click)=\"OnCancel()\"\n [disabled]=\"IsSaving\">\n Cancel\n </button>\n </div>\n } @else if (IsExpired) {\n <div class=\"panel-footer\">\n <div class=\"expired-notice\">\n <i class=\"fa-solid fa-clock\"></i> This request has expired and can no longer be responded to.\n </div>\n <button class=\"btn btn-cancel\" (click)=\"OnCancel()\">Close</button>\n </div>\n } @else {\n <div class=\"panel-footer\">\n <button class=\"btn btn-cancel\" (click)=\"OnCancel()\">Close</button>\n </div>\n }\n </div>\n </div>\n\n <!-- Reassign Dialog Overlay -->\n @if (ShowReassignDialog) {\n <div class=\"reassign-overlay\" (click)=\"OnReassignCancel()\">\n <div class=\"reassign-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"reassign-header\">\n <h4 class=\"reassign-title\">\n <i class=\"fa-solid fa-user-plus\"></i> Reassign Request\n </h4>\n <button class=\"close-btn\" (click)=\"OnReassignCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"reassign-body\">\n <!-- User Search -->\n <div class=\"reassign-field\">\n <label class=\"field-label\">Search User</label>\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input\n type=\"text\"\n class=\"field-input search-input\"\n placeholder=\"Type a name or email...\"\n [value]=\"ReassignSearchTerm\"\n (input)=\"OnReassignSearchChange($any($event.target).value)\">\n </div>\n </div>\n\n <!-- Search Results -->\n @if (IsSearchingUsers) {\n <div class=\"search-status\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Searching...\n </div>\n }\n @if (ReassignUsers.length > 0) {\n <div class=\"user-results\">\n @for (user of ReassignUsers; track user.ID) {\n <button\n class=\"user-result-item\"\n [class.selected]=\"SelectedReassignUser?.ID === user.ID\"\n (click)=\"OnSelectReassignUser(user)\">\n <i class=\"fa-solid fa-user user-avatar\"></i>\n <div class=\"user-info\">\n <span class=\"user-name\">{{ user.Name }}</span>\n <span class=\"user-email\">{{ user.Email }}</span>\n </div>\n @if (SelectedReassignUser?.ID === user.ID) {\n <i class=\"fa-solid fa-check selected-check\"></i>\n }\n </button>\n }\n </div>\n } @else if (ReassignSearchTerm.length >= 2 && !IsSearchingUsers) {\n <div class=\"search-status\">No users found</div>\n }\n\n <!-- Note -->\n <div class=\"reassign-field\">\n <label class=\"field-label\">Note (optional)</label>\n <textarea\n class=\"field-textarea\"\n [(ngModel)]=\"ReassignNote\"\n placeholder=\"Add a reason for reassignment...\"\n rows=\"2\">\n </textarea>\n </div>\n </div>\n\n <div class=\"reassign-footer\">\n <button\n class=\"btn btn-respond\"\n (click)=\"OnReassignSubmit()\"\n [disabled]=\"!SelectedReassignUser || IsReassigning\">\n @if (IsReassigning) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Reassigning...\n } @else {\n <i class=\"fa-solid fa-user-plus\"></i> Reassign\n }\n </button>\n <button\n class=\"btn btn-cancel\"\n (click)=\"OnReassignCancel()\"\n [disabled]=\"IsReassigning\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n}\n", styles: ["/* Panel Backdrop */\n.panel-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n justify-content: flex-end;\n z-index: 10000;\n}\n\n/* Slide-in Panel */\n.request-panel {\n max-width: 90vw;\n min-width: 360px;\n height: 100%;\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);\n transform: translateX(100%);\n transition: transform 0.25s ease-out;\n position: relative;\n}\n\n.request-panel.open {\n transform: translateX(0);\n}\n\n.request-panel.resizing {\n transition: none;\n}\n\n/* Resize Handle */\n.resize-handle {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: col-resize;\n z-index: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.resize-handle:hover,\n.resize-handle:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.resize-grip {\n width: 2px;\n height: 32px;\n border-radius: 1px;\n background: var(--mj-border-strong);\n opacity: 0;\n transition: opacity 0.15s;\n}\n\n.resize-handle:hover .resize-grip,\n.resize-handle:active .resize-grip {\n opacity: 1;\n}\n\n/* Header */\n.panel-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.header-content {\n display: flex;\n flex-direction: column;\n gap: 4px;\n flex: 1;\n min-width: 0;\n}\n\n.header-title-row {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.header-icon {\n color: var(--mj-brand-primary);\n font-size: 16px;\n}\n\n.panel-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.agent-name {\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.close-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px 8px;\n color: var(--mj-text-muted);\n font-size: 16px;\n border-radius: 4px;\n}\n\n.close-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* Status Badge */\n.status-badge {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.status-requested {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n border: 1px solid var(--mj-status-info-border);\n}\n\n.status-approved {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.status-rejected,\n.status-canceled {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.status-responded {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n.status-expired {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning-border);\n}\n\n/* Priority Badge */\n.priority-badge {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.priority-low {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.priority-normal {\n background: var(--mj-status-info-bg);\n color: var(--mj-status-info-text);\n}\n\n.priority-high {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n}\n\n.priority-critical {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n/* Body */\n.panel-body {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n}\n\n.section {\n margin-bottom: 20px;\n}\n\n.section-title {\n margin: 0 0 8px 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.request-text {\n margin: 0;\n font-size: 14px;\n line-height: 1.6;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n}\n\n.response-text {\n margin: 0;\n font-size: 14px;\n line-height: 1.6;\n color: var(--mj-text-primary);\n white-space: pre-wrap;\n background: var(--mj-bg-surface-sunken);\n padding: 12px;\n border-radius: 6px;\n}\n\n/* Metadata */\n.metadata-section {\n background: var(--mj-bg-surface-card);\n padding: 12px;\n border-radius: 6px;\n}\n\n.metadata-grid {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.metadata-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.metadata-label {\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: 500;\n}\n\n.metadata-value {\n font-size: 12px;\n color: var(--mj-text-primary);\n}\n\n.metadata-value.expired {\n color: var(--mj-status-error-text);\n}\n\n.expired-tag {\n display: inline-block;\n margin-left: 6px;\n padding: 1px 6px;\n border-radius: 8px;\n font-size: 10px;\n font-weight: 600;\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n}\n\n/* Shared field styles (used by reassign dialog and free-text response) */\n.field-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.field-input,\n.field-textarea {\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n transition: border-color 0.15s;\n}\n\n.field-input:focus,\n.field-textarea:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.field-textarea {\n resize: vertical;\n min-height: 60px;\n}\n\n.response-textarea {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n font-size: 14px;\n font-family: inherit;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n resize: vertical;\n box-sizing: border-box;\n}\n\n.response-textarea:focus {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n/* Footer */\n.panel-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.btn {\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: background-color 0.15s;\n}\n\n.btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-approve {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.btn-approve:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-success) 85%, black);\n}\n\n.btn-reject {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n}\n\n.btn-reject:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 85%, black);\n}\n\n.btn-respond {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-respond:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.btn-cancel {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n margin-left: auto;\n}\n\n.btn-cancel:hover:not(:disabled) {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n}\n\n.btn-reassign {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n.btn-reassign:hover:not(:disabled) {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-strong);\n}\n\n.expired-notice {\n font-size: 13px;\n color: var(--mj-status-warning-text);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n/* Reassign Dialog */\n.reassign-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10001;\n}\n\n.reassign-dialog {\n width: 420px;\n max-width: 90vw;\n max-height: 80vh;\n background: var(--mj-bg-surface);\n border-radius: 10px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.reassign-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n\n.reassign-title {\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.reassign-body {\n padding: 16px 20px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n.reassign-field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.search-input-wrapper {\n position: relative;\n}\n\n.search-icon {\n position: absolute;\n left: 10px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.search-input {\n padding-left: 32px;\n}\n\n.search-status {\n font-size: 13px;\n color: var(--mj-text-muted);\n padding: 8px 0;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.user-results {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 200px;\n overflow-y: auto;\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n}\n\n.user-result-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 12px;\n background: none;\n border: none;\n cursor: pointer;\n text-align: left;\n width: 100%;\n transition: background-color 0.1s;\n}\n\n.user-result-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-result-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.user-avatar {\n color: var(--mj-text-muted);\n font-size: 14px;\n width: 20px;\n text-align: center;\n}\n\n.user-info {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n}\n\n.user-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.user-email {\n font-size: 12px;\n color: var(--mj-text-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.selected-check {\n color: var(--mj-brand-primary);\n font-size: 13px;\n}\n\n.reassign-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 20px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n}\n"] }]
398
398
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.MJNotificationService }], propDecorators: { Request: [{
@@ -1 +1 @@
1
- {"version":3,"file":"agent-request-panel.component.js","sourceRoot":"","sources":["../../../../src/lib/panels/agent-request-panel/agent-request-panel.component.ts","../../../../src/lib/panels/agent-request-panel/agent-request-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Agent Request Panel Component\n *\n * Slide-in panel for viewing and responding to AI agent feedback requests.\n * Displays request details, renders ResponseSchema as a dynamic form,\n * and submits ResponseData back to the request entity.\n */\n\nimport {\n Component, Input, Output, EventEmitter, ChangeDetectorRef,\n ChangeDetectionStrategy, OnInit, OnDestroy, HostListener, ViewChild, ElementRef\n} from '@angular/core';\nimport { MJAIAgentRequestEntity, MJAIAgentRequestTypeEntity } from '@memberjunction/core-entities';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { RunView } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { AgentResponseForm } from '@memberjunction/ai-core-plus';\nimport { DynamicFormComponent } from '@memberjunction/ng-forms';\n\nconst PANEL_WIDTH_SETTING_KEY = 'Explorer.AgentRequestPanelWidth';\nconst DEFAULT_PANEL_WIDTH = 520;\nconst MIN_PANEL_WIDTH = 360;\nconst MAX_PANEL_WIDTH = 900;\n\n/**\n * Result returned when the panel closes after an action\n */\nexport interface AgentRequestPanelResult {\n /** Whether an action was taken (responded, approved, rejected) */\n Success: boolean;\n /** The updated request entity */\n Request?: MJAIAgentRequestEntity;\n /** The action that was taken */\n Action: 'responded' | 'approved' | 'rejected' | 'cancelled';\n}\n\n@Component({\n standalone: false,\n selector: 'mj-agent-request-panel',\n templateUrl: './agent-request-panel.component.html',\n styleUrls: ['./agent-request-panel.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class AgentRequestPanelComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n @Input() Request: MJAIAgentRequestEntity | null = null;\n @Input() RequestTypes: MJAIAgentRequestTypeEntity[] = [];\n @Input() IsOpen = false;\n\n @Output() Close = new EventEmitter<AgentRequestPanelResult>();\n\n @ViewChild('dynamicForm') dynamicForm: DynamicFormComponent | undefined;\n @ViewChild('panelElement') panelElement: ElementRef<HTMLDivElement> | undefined;\n\n public IsLoading = false;\n public IsSaving = false;\n public ResponseText = '';\n public ResponseFormDefinition: AgentResponseForm | null = null;\n public PanelWidth = DEFAULT_PANEL_WIDTH;\n\n /** Tracks whether a response was submitted so the Close event carries the right result */\n private completedAction: 'responded' | 'approved' | 'rejected' | null = null;\n\n // Resize state\n public IsResizing = false;\n private resizeStartX = 0;\n private resizeStartWidth = 0;\n private boundOnResizeMove: ((e: MouseEvent) => void) | null = null;\n private boundOnResizeEnd: (() => void) | null = null;\n\n // Reassign state\n public ShowReassignDialog = false;\n public ReassignSearchTerm = '';\n public ReassignNote = '';\n public ReassignUsers: Array<{ ID: string; Name: string; Email: string }> = [];\n public SelectedReassignUser: { ID: string; Name: string; Email: string } | null = null;\n public IsSearchingUsers = false;\n public IsReassigning = false;\n\n private reassignSearchTimeout: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n private cdr: ChangeDetectorRef,\n private notificationService: MJNotificationService\n ) {\n super();}\n\n ngOnInit(): void {\n this.loadPanelWidth();\n if (this.Request) {\n this.initializeForm();\n }\n }\n\n ngOnDestroy(): void {\n this.cleanupResizeListeners();\n }\n\n @HostListener('document:keydown.escape')\n public OnEscapeKey(): void {\n if (this.IsOpen) {\n this.OnCancel();\n }\n }\n\n /** The request type entity for the current request */\n public get RequestType(): MJAIAgentRequestTypeEntity | null {\n if (!this.Request?.RequestTypeID) return null;\n return this.RequestTypes.find(t => UUIDsEqual(t.ID, this.Request!.RequestTypeID!)) ?? null;\n }\n\n /** Whether this request is still actionable (status = Requested) */\n public get IsActionable(): boolean {\n return this.Request?.Status === 'Requested';\n }\n\n /** Whether this is an approval-type request (show approve/reject buttons) */\n public get IsApprovalType(): boolean {\n const typeName = this.RequestType?.Name;\n return typeName === 'Approval';\n }\n\n /** Whether the request has a structured response form */\n public get HasResponseForm(): boolean {\n return this.ResponseFormDefinition != null && (this.ResponseFormDefinition.questions?.length ?? 0) > 0;\n }\n\n /** Priority display label */\n public get PriorityLabel(): string {\n if (!this.Request) return '';\n const p = this.Request.Priority;\n if (p <= 25) return 'Low';\n if (p <= 50) return 'Normal';\n if (p <= 75) return 'High';\n return 'Critical';\n }\n\n /** Priority CSS class */\n public get PriorityClass(): string {\n if (!this.Request) return '';\n const p = this.Request.Priority;\n if (p <= 25) return 'priority-low';\n if (p <= 50) return 'priority-normal';\n if (p <= 75) return 'priority-high';\n return 'priority-critical';\n }\n\n /** Whether the request is expired */\n public get IsExpired(): boolean {\n if (!this.Request?.ExpiresAt) return false;\n return new Date(this.Request.ExpiresAt) < new Date();\n }\n\n /**\n * Opens the panel with a specific request\n */\n public Open(request: MJAIAgentRequestEntity): void {\n this.Request = request;\n this.IsOpen = true;\n this.ResponseText = '';\n this.completedAction = null;\n this.initializeForm();\n this.cdr.markForCheck();\n }\n\n /**\n * Approve the request\n */\n public async OnApprove(): Promise<void> {\n await this.submitResponse('Approved', 'approved');\n }\n\n /**\n * Reject the request\n */\n public async OnReject(): Promise<void> {\n await this.submitResponse('Rejected', 'rejected');\n }\n\n /**\n * Submit a response (for non-approval types)\n */\n public async OnRespond(): Promise<void> {\n await this.submitResponse('Responded', 'responded');\n }\n\n /**\n * Cancel / close the panel without action\n */\n public OnCancel(): void {\n this.IsOpen = false;\n if (this.completedAction) {\n // A response was submitted — tell the parent about the action taken\n this.Close.emit({ Success: true, Request: this.Request!, Action: this.completedAction });\n this.completedAction = null;\n } else {\n this.Close.emit({ Success: false, Action: 'cancelled' });\n }\n this.cdr.markForCheck();\n }\n\n public OnBackdropClick(): void {\n this.OnCancel();\n }\n\n /** Open the reassign dialog */\n public OnReassignClick(): void {\n this.ShowReassignDialog = true;\n this.ReassignSearchTerm = '';\n this.ReassignNote = '';\n this.ReassignUsers = [];\n this.SelectedReassignUser = null;\n this.cdr.markForCheck();\n }\n\n /** Close the reassign dialog */\n public OnReassignCancel(): void {\n this.ShowReassignDialog = false;\n this.cdr.markForCheck();\n }\n\n /** Search users by name/email for reassignment */\n public OnReassignSearchChange(term: string): void {\n this.ReassignSearchTerm = term;\n if (this.reassignSearchTimeout) {\n clearTimeout(this.reassignSearchTimeout);\n }\n if (term.length < 2) {\n this.ReassignUsers = [];\n this.cdr.markForCheck();\n return;\n }\n this.reassignSearchTimeout = setTimeout(() => this.searchUsers(term), 300);\n }\n\n /** Select a user from the search results */\n public OnSelectReassignUser(user: { ID: string; Name: string; Email: string }): void {\n this.SelectedReassignUser = user;\n this.cdr.markForCheck();\n }\n\n /** Submit the reassignment */\n public async OnReassignSubmit(): Promise<void> {\n if (!this.Request || !this.SelectedReassignUser || this.IsReassigning) return;\n\n this.IsReassigning = true;\n this.cdr.markForCheck();\n\n try {\n this.Request.RequestForUserID = this.SelectedReassignUser.ID;\n\n // Append reassignment note to Comments\n const timestamp = new Date().toISOString();\n const reassignEntry = `[${timestamp}] Reassigned to ${this.SelectedReassignUser.Name || this.SelectedReassignUser.Email}${this.ReassignNote ? ` — \"${this.ReassignNote}\"` : ''}`;\n this.Request.Comments = this.Request.Comments\n ? `${this.Request.Comments}\\n${reassignEntry}`\n : reassignEntry;\n\n const saved = await this.Request.Save();\n if (saved) {\n this.notificationService.CreateSimpleNotification(\n `Request reassigned to ${this.SelectedReassignUser.Name || this.SelectedReassignUser.Email}`, 'success', 3000\n );\n this.ShowReassignDialog = false;\n this.IsOpen = false;\n this.Close.emit({ Success: true, Request: this.Request, Action: 'cancelled' });\n } else {\n this.notificationService.CreateSimpleNotification(\n 'Failed to reassign request. Please try again.', 'error', 5000\n );\n }\n } catch (error) {\n console.error('Error reassigning request:', error);\n this.notificationService.CreateSimpleNotification(\n 'An unexpected error occurred.', 'error', 5000\n );\n } finally {\n this.IsReassigning = false;\n this.cdr.markForCheck();\n }\n }\n\n private async searchUsers(term: string): Promise<void> {\n this.IsSearchingUsers = true;\n this.cdr.markForCheck();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<{ ID: string; Name: string; Email: string }>({\n EntityName: 'Users',\n ExtraFilter: `(Name LIKE '%${term.replace(/'/g, \"''\")}%' OR Email LIKE '%${term.replace(/'/g, \"''\")}%')`,\n OrderBy: 'Name',\n MaxRows: 10,\n Fields: ['ID', 'Name', 'Email'],\n ResultType: 'simple'\n });\n this.ReassignUsers = result.Success ? result.Results : [];\n } catch {\n this.ReassignUsers = [];\n } finally {\n this.IsSearchingUsers = false;\n this.cdr.markForCheck();\n }\n }\n\n // ========================================================================\n // Resize\n // ========================================================================\n\n /** Begin resizing when the user mousedowns on the resize handle */\n public OnResizeStart(event: MouseEvent): void {\n event.preventDefault();\n this.IsResizing = true;\n this.resizeStartX = event.clientX;\n this.resizeStartWidth = this.PanelWidth;\n\n this.boundOnResizeMove = (e: MouseEvent) => this.onResizeMove(e);\n this.boundOnResizeEnd = () => this.onResizeEnd();\n document.addEventListener('mousemove', this.boundOnResizeMove);\n document.addEventListener('mouseup', this.boundOnResizeEnd);\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n }\n\n private onResizeMove(event: MouseEvent): void {\n // Panel is on the right, so dragging left (negative deltaX) increases width\n const deltaX = this.resizeStartX - event.clientX;\n const newWidth = Math.max(MIN_PANEL_WIDTH, Math.min(MAX_PANEL_WIDTH, this.resizeStartWidth + deltaX));\n this.PanelWidth = newWidth;\n this.cdr.markForCheck();\n }\n\n private onResizeEnd(): void {\n this.IsResizing = false;\n this.cleanupResizeListeners();\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n this.savePanelWidth();\n this.cdr.markForCheck();\n }\n\n private cleanupResizeListeners(): void {\n if (this.boundOnResizeMove) {\n document.removeEventListener('mousemove', this.boundOnResizeMove);\n this.boundOnResizeMove = null;\n }\n if (this.boundOnResizeEnd) {\n document.removeEventListener('mouseup', this.boundOnResizeEnd);\n this.boundOnResizeEnd = null;\n }\n }\n\n private loadPanelWidth(): void {\n try {\n const saved = UserInfoEngine.Instance.GetSetting(PANEL_WIDTH_SETTING_KEY);\n if (saved) {\n const parsed = parseInt(saved, 10);\n if (!isNaN(parsed) && parsed >= MIN_PANEL_WIDTH && parsed <= MAX_PANEL_WIDTH) {\n this.PanelWidth = parsed;\n }\n }\n } catch {\n // UserInfoEngine may not be initialized yet — use default\n }\n }\n\n private savePanelWidth(): void {\n try {\n UserInfoEngine.Instance.SetSettingDebounced(PANEL_WIDTH_SETTING_KEY, String(this.PanelWidth));\n } catch {\n // Silently ignore save failures\n }\n }\n\n // ========================================================================\n // Form handling\n // ========================================================================\n\n /**\n * Parse the ResponseSchema JSON into an AgentResponseForm for the dynamic form component.\n */\n private initializeForm(): void {\n this.ResponseFormDefinition = null;\n\n if (!this.Request?.ResponseSchema) return;\n\n try {\n const schema = JSON.parse(this.Request.ResponseSchema) as AgentResponseForm;\n if (schema?.questions && Array.isArray(schema.questions)) {\n this.ResponseFormDefinition = schema;\n }\n } catch {\n // If schema is invalid JSON, ignore — user can still provide free-text response\n }\n }\n\n /**\n * Collect current form values from the DynamicFormComponent's reactive FormGroup.\n * This reads values directly so the user doesn't need to click the form's\n * internal submit button before clicking the panel's action buttons.\n */\n private collectFormData(): Record<string, unknown> | null {\n if (!this.dynamicForm?.FormGroup) return null;\n const values = this.dynamicForm.FormGroup.value;\n if (values && Object.keys(values).length > 0) {\n return values;\n }\n return null;\n }\n\n /**\n * Shared logic for submitting any response type\n */\n private async submitResponse(\n status: 'Approved' | 'Rejected' | 'Responded',\n action: 'approved' | 'rejected' | 'responded'\n ): Promise<void> {\n if (!this.Request || this.IsSaving) return;\n\n this.IsSaving = true;\n this.cdr.markForCheck();\n\n try {\n this.Request.Status = status;\n this.Request.Response = this.ResponseText || null;\n this.Request.RespondedAt = new Date();\n\n const formData = this.collectFormData();\n if (formData) {\n this.Request.ResponseData = JSON.stringify(formData);\n }\n\n const saved = await this.Request.Save();\n if (saved) {\n this.notificationService.CreateSimpleNotification(\n `Agent request has been ${action} successfully.`, 'success', 3000\n );\n // Keep panel open so the user can see their submitted response.\n // Template auto-switches to read-only mode since IsActionable becomes false.\n this.completedAction = action;\n } else {\n this.notificationService.CreateSimpleNotification(\n 'Failed to save response. Please try again.', 'error', 5000\n );\n }\n } catch (error) {\n console.error('Error submitting response:', error);\n this.notificationService.CreateSimpleNotification(\n 'An unexpected error occurred while saving the response.', 'error', 5000\n );\n } finally {\n this.IsSaving = false;\n this.cdr.markForCheck();\n }\n }\n}\n","@if (IsOpen && Request) {\n <div class=\"panel-backdrop\" (click)=\"OnBackdropClick()\">\n <div class=\"request-panel\" #panelElement [class.open]=\"IsOpen\" [class.resizing]=\"IsResizing\" [style.width.px]=\"PanelWidth\" (click)=\"$event.stopPropagation()\">\n <!-- Resize Handle (left edge) -->\n <div class=\"resize-handle\" (mousedown)=\"OnResizeStart($event)\">\n <div class=\"resize-grip\"></div>\n </div>\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-content\">\n <div class=\"header-title-row\">\n @if (RequestType?.Icon) {\n <i class=\"{{ RequestType!.Icon }} header-icon\"></i>\n }\n <h3 class=\"panel-title\">{{ RequestType?.Name || 'Agent Request' }}</h3>\n <span class=\"priority-badge\" [class]=\"PriorityClass\">{{ PriorityLabel }}</span>\n <span class=\"status-badge status-{{ Request.Status.toLowerCase() }}\">{{ Request.Status }}</span>\n </div>\n @if (Request.Agent) {\n <span class=\"agent-name\">\n <i class=\"fa-solid fa-robot\"></i> {{ Request.Agent }}\n </span>\n }\n </div>\n <button class=\"close-btn\" (click)=\"OnCancel()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Body -->\n <div class=\"panel-body\">\n <!-- Request Details -->\n <div class=\"section\">\n <h4 class=\"section-title\">Request</h4>\n <p class=\"request-text\">{{ Request.Request }}</p>\n </div>\n\n <!-- Metadata -->\n <div class=\"section metadata-section\">\n <div class=\"metadata-grid\">\n @if (Request.ExpiresAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Expires</span>\n <span class=\"metadata-value\" [class.expired]=\"IsExpired\">\n {{ Request.ExpiresAt | date:'medium' }}\n @if (IsExpired) {\n <span class=\"expired-tag\">Expired</span>\n }\n </span>\n </div>\n }\n @if (Request.__mj_CreatedAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Created</span>\n <span class=\"metadata-value\">{{ Request.__mj_CreatedAt | date:'medium' }}</span>\n </div>\n }\n @if (Request.RespondedAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Responded</span>\n <span class=\"metadata-value\">{{ Request.RespondedAt | date:'medium' }}</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Dynamic Response Form (from ResponseSchema) -->\n @if (HasResponseForm && IsActionable && ResponseFormDefinition) {\n <div class=\"section\">\n <mj-dynamic-form #dynamicForm\n [FormDefinition]=\"ResponseFormDefinition\"\n [Disabled]=\"IsSaving\">\n </mj-dynamic-form>\n </div>\n }\n\n <!-- Free-text response (always available for actionable requests) -->\n @if (IsActionable) {\n <div class=\"section\">\n <h4 class=\"section-title\">\n @if (HasResponseForm) {\n Additional Comments\n } @else {\n Response\n }\n </h4>\n <textarea\n class=\"response-textarea\"\n [(ngModel)]=\"ResponseText\"\n placeholder=\"Type your response here...\"\n rows=\"4\">\n </textarea>\n </div>\n }\n\n <!-- Show existing response for already-handled requests -->\n @if (!IsActionable && (Request.Response || Request.ResponseData)) {\n @if (Request.ResponseData) {\n <div class=\"section\">\n <mj-dynamic-form-response\n [FormDefinition]=\"ResponseFormDefinition\"\n [ResponseData]=\"Request.ResponseData\"\n DisplayMode=\"card\">\n </mj-dynamic-form-response>\n </div>\n }\n @if (Request.Response) {\n <div class=\"section\">\n <h4 class=\"section-title\">\n @if (Request.ResponseData) {\n Additional Comments\n } @else {\n Response\n }\n </h4>\n <p class=\"response-text\">{{ Request.Response }}</p>\n </div>\n }\n }\n </div>\n\n <!-- Footer (action buttons) -->\n @if (IsActionable && !IsExpired) {\n <div class=\"panel-footer\">\n @if (IsApprovalType) {\n <button\n class=\"btn btn-approve\"\n (click)=\"OnApprove()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-check\"></i> Approve\n </button>\n <button\n class=\"btn btn-reject\"\n (click)=\"OnReject()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-times\"></i> Reject\n </button>\n } @else {\n <button\n class=\"btn btn-respond\"\n (click)=\"OnRespond()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-paper-plane\"></i> Submit Response\n </button>\n }\n <button\n class=\"btn btn-reassign\"\n (click)=\"OnReassignClick()\"\n [disabled]=\"IsSaving\"\n title=\"Reassign to another user\">\n <i class=\"fa-solid fa-user-plus\"></i> Reassign\n </button>\n <button\n class=\"btn btn-cancel\"\n (click)=\"OnCancel()\"\n [disabled]=\"IsSaving\">\n Cancel\n </button>\n </div>\n } @else if (IsExpired) {\n <div class=\"panel-footer\">\n <div class=\"expired-notice\">\n <i class=\"fa-solid fa-clock\"></i> This request has expired and can no longer be responded to.\n </div>\n <button class=\"btn btn-cancel\" (click)=\"OnCancel()\">Close</button>\n </div>\n } @else {\n <div class=\"panel-footer\">\n <button class=\"btn btn-cancel\" (click)=\"OnCancel()\">Close</button>\n </div>\n }\n </div>\n </div>\n\n <!-- Reassign Dialog Overlay -->\n @if (ShowReassignDialog) {\n <div class=\"reassign-overlay\" (click)=\"OnReassignCancel()\">\n <div class=\"reassign-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"reassign-header\">\n <h4 class=\"reassign-title\">\n <i class=\"fa-solid fa-user-plus\"></i> Reassign Request\n </h4>\n <button class=\"close-btn\" (click)=\"OnReassignCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"reassign-body\">\n <!-- User Search -->\n <div class=\"reassign-field\">\n <label class=\"field-label\">Search User</label>\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input\n type=\"text\"\n class=\"field-input search-input\"\n placeholder=\"Type a name or email...\"\n [value]=\"ReassignSearchTerm\"\n (input)=\"OnReassignSearchChange($any($event.target).value)\">\n </div>\n </div>\n\n <!-- Search Results -->\n @if (IsSearchingUsers) {\n <div class=\"search-status\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Searching...\n </div>\n }\n @if (ReassignUsers.length > 0) {\n <div class=\"user-results\">\n @for (user of ReassignUsers; track user.ID) {\n <button\n class=\"user-result-item\"\n [class.selected]=\"SelectedReassignUser?.ID === user.ID\"\n (click)=\"OnSelectReassignUser(user)\">\n <i class=\"fa-solid fa-user user-avatar\"></i>\n <div class=\"user-info\">\n <span class=\"user-name\">{{ user.Name }}</span>\n <span class=\"user-email\">{{ user.Email }}</span>\n </div>\n @if (SelectedReassignUser?.ID === user.ID) {\n <i class=\"fa-solid fa-check selected-check\"></i>\n }\n </button>\n }\n </div>\n } @else if (ReassignSearchTerm.length >= 2 && !IsSearchingUsers) {\n <div class=\"search-status\">No users found</div>\n }\n\n <!-- Note -->\n <div class=\"reassign-field\">\n <label class=\"field-label\">Note (optional)</label>\n <textarea\n class=\"field-textarea\"\n [(ngModel)]=\"ReassignNote\"\n placeholder=\"Add a reason for reassignment...\"\n rows=\"2\">\n </textarea>\n </div>\n </div>\n\n <div class=\"reassign-footer\">\n <button\n class=\"btn btn-respond\"\n (click)=\"OnReassignSubmit()\"\n [disabled]=\"!SelectedReassignUser || IsReassigning\">\n @if (IsReassigning) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Reassigning...\n } @else {\n <i class=\"fa-solid fa-user-plus\"></i> Reassign\n }\n </button>\n <button\n class=\"btn btn-cancel\"\n (click)=\"OnReassignCancel()\"\n [disabled]=\"IsReassigning\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n}\n"]}
1
+ {"version":3,"file":"agent-request-panel.component.js","sourceRoot":"","sources":["../../../../src/lib/panels/agent-request-panel/agent-request-panel.component.ts","../../../../src/lib/panels/agent-request-panel/agent-request-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Agent Request Panel Component\n *\n * Slide-in panel for viewing and responding to AI agent feedback requests.\n * Displays request details, renders ResponseSchema as a dynamic form,\n * and submits ResponseData back to the request entity.\n */\n\nimport {\n Component, Input, Output, EventEmitter, ChangeDetectorRef,\n ChangeDetectionStrategy, OnInit, OnDestroy, HostListener, ViewChild, ElementRef\n} from '@angular/core';\nimport { MJAIAgentRequestEntity, MJAIAgentRequestTypeEntity } from '@memberjunction/core-entities';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { RunView } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { AgentResponseForm } from '@memberjunction/ai-core-plus';\nimport { DynamicFormComponent } from '@memberjunction/ng-forms';\n\nconst PANEL_WIDTH_SETTING_KEY = 'Explorer.AgentRequestPanelWidth';\nconst DEFAULT_PANEL_WIDTH = 520;\nconst MIN_PANEL_WIDTH = 360;\nconst MAX_PANEL_WIDTH = 900;\n\n/**\n * Result returned when the panel closes after an action\n */\nexport interface AgentRequestPanelResult {\n /** Whether an action was taken (responded, approved, rejected) */\n Success: boolean;\n /** The updated request entity */\n Request?: MJAIAgentRequestEntity;\n /** The action that was taken */\n Action: 'responded' | 'approved' | 'rejected' | 'cancelled';\n}\n\n@Component({\n standalone: false,\n selector: 'mj-agent-request-panel',\n templateUrl: './agent-request-panel.component.html',\n styleUrls: ['./agent-request-panel.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class AgentRequestPanelComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n @Input() Request: MJAIAgentRequestEntity | null = null;\n @Input() RequestTypes: MJAIAgentRequestTypeEntity[] = [];\n @Input() IsOpen = false;\n\n @Output() Close = new EventEmitter<AgentRequestPanelResult>();\n\n @ViewChild('dynamicForm') dynamicForm: DynamicFormComponent | undefined;\n @ViewChild('panelElement') panelElement: ElementRef<HTMLDivElement> | undefined;\n\n public IsLoading = false;\n public IsSaving = false;\n public ResponseText = '';\n public ResponseFormDefinition: AgentResponseForm | null = null;\n public PanelWidth = DEFAULT_PANEL_WIDTH;\n\n /** Tracks whether a response was submitted so the Close event carries the right result */\n private completedAction: 'responded' | 'approved' | 'rejected' | null = null;\n\n // Resize state\n public IsResizing = false;\n private resizeStartX = 0;\n private resizeStartWidth = 0;\n private boundOnResizeMove: ((e: MouseEvent) => void) | null = null;\n private boundOnResizeEnd: (() => void) | null = null;\n\n // Reassign state\n public ShowReassignDialog = false;\n public ReassignSearchTerm = '';\n public ReassignNote = '';\n public ReassignUsers: Array<{ ID: string; Name: string; Email: string }> = [];\n public SelectedReassignUser: { ID: string; Name: string; Email: string } | null = null;\n public IsSearchingUsers = false;\n public IsReassigning = false;\n\n private reassignSearchTimeout: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n private cdr: ChangeDetectorRef,\n private notificationService: MJNotificationService\n ) {\n super();}\n\n ngOnInit(): void {\n this.loadPanelWidth();\n if (this.Request) {\n this.initializeForm();\n }\n }\n\n ngOnDestroy(): void {\n this.cleanupResizeListeners();\n }\n\n @HostListener('document:keydown.escape')\n public OnEscapeKey(): void {\n if (this.IsOpen) {\n this.OnCancel();\n }\n }\n\n /** The request type entity for the current request */\n public get RequestType(): MJAIAgentRequestTypeEntity | null {\n if (!this.Request?.RequestTypeID) return null;\n return this.RequestTypes.find(t => UUIDsEqual(t.ID, this.Request!.RequestTypeID!)) ?? null;\n }\n\n /** Whether this request is still actionable (status = Requested) */\n public get IsActionable(): boolean {\n return this.Request?.Status === 'Requested';\n }\n\n /** Whether this is an approval-type request (show approve/reject buttons) */\n public get IsApprovalType(): boolean {\n const typeName = this.RequestType?.Name;\n return typeName === 'Approval';\n }\n\n /** Whether the request has a structured response form */\n public get HasResponseForm(): boolean {\n return this.ResponseFormDefinition != null && (this.ResponseFormDefinition.questions?.length ?? 0) > 0;\n }\n\n /** Priority display label */\n public get PriorityLabel(): string {\n if (!this.Request) return '';\n const p = this.Request.Priority;\n if (p <= 25) return 'Low';\n if (p <= 50) return 'Normal';\n if (p <= 75) return 'High';\n return 'Critical';\n }\n\n /** Priority CSS class */\n public get PriorityClass(): string {\n if (!this.Request) return '';\n const p = this.Request.Priority;\n if (p <= 25) return 'priority-low';\n if (p <= 50) return 'priority-normal';\n if (p <= 75) return 'priority-high';\n return 'priority-critical';\n }\n\n /** Whether the request is expired */\n public get IsExpired(): boolean {\n if (!this.Request?.ExpiresAt) return false;\n return new Date(this.Request.ExpiresAt) < new Date();\n }\n\n /**\n * Opens the panel with a specific request\n */\n public Open(request: MJAIAgentRequestEntity): void {\n this.Request = request;\n this.IsOpen = true;\n this.ResponseText = '';\n this.completedAction = null;\n this.initializeForm();\n this.cdr.markForCheck();\n }\n\n /**\n * Approve the request\n */\n public async OnApprove(): Promise<void> {\n await this.submitResponse('Approved', 'approved');\n }\n\n /**\n * Reject the request\n */\n public async OnReject(): Promise<void> {\n await this.submitResponse('Rejected', 'rejected');\n }\n\n /**\n * Submit a response (for non-approval types)\n */\n public async OnRespond(): Promise<void> {\n await this.submitResponse('Responded', 'responded');\n }\n\n /**\n * Cancel / close the panel without action\n */\n public OnCancel(): void {\n this.IsOpen = false;\n if (this.completedAction) {\n // A response was submitted — tell the parent about the action taken\n this.Close.emit({ Success: true, Request: this.Request!, Action: this.completedAction });\n this.completedAction = null;\n } else {\n this.Close.emit({ Success: false, Action: 'cancelled' });\n }\n this.cdr.markForCheck();\n }\n\n public OnBackdropClick(): void {\n this.OnCancel();\n }\n\n /** Open the reassign dialog */\n public OnReassignClick(): void {\n this.ShowReassignDialog = true;\n this.ReassignSearchTerm = '';\n this.ReassignNote = '';\n this.ReassignUsers = [];\n this.SelectedReassignUser = null;\n this.cdr.markForCheck();\n }\n\n /** Close the reassign dialog */\n public OnReassignCancel(): void {\n this.ShowReassignDialog = false;\n this.cdr.markForCheck();\n }\n\n /** Search users by name/email for reassignment */\n public OnReassignSearchChange(term: string): void {\n this.ReassignSearchTerm = term;\n if (this.reassignSearchTimeout) {\n clearTimeout(this.reassignSearchTimeout);\n }\n if (term.length < 2) {\n this.ReassignUsers = [];\n this.cdr.markForCheck();\n return;\n }\n this.reassignSearchTimeout = setTimeout(() => this.searchUsers(term), 300);\n }\n\n /** Select a user from the search results */\n public OnSelectReassignUser(user: { ID: string; Name: string; Email: string }): void {\n this.SelectedReassignUser = user;\n this.cdr.markForCheck();\n }\n\n /** Submit the reassignment */\n public async OnReassignSubmit(): Promise<void> {\n if (!this.Request || !this.SelectedReassignUser || this.IsReassigning) return;\n\n this.IsReassigning = true;\n this.cdr.markForCheck();\n\n try {\n this.Request.RequestForUserID = this.SelectedReassignUser.ID;\n\n // Append reassignment note to Comments\n const timestamp = new Date().toISOString();\n const reassignEntry = `[${timestamp}] Reassigned to ${this.SelectedReassignUser.Name || this.SelectedReassignUser.Email}${this.ReassignNote ? ` — \"${this.ReassignNote}\"` : ''}`;\n this.Request.Comments = this.Request.Comments\n ? `${this.Request.Comments}\\n${reassignEntry}`\n : reassignEntry;\n\n const saved = await this.Request.Save();\n if (saved) {\n this.notificationService.CreateSimpleNotification(\n `Request reassigned to ${this.SelectedReassignUser.Name || this.SelectedReassignUser.Email}`, 'success', 3000\n );\n this.ShowReassignDialog = false;\n this.IsOpen = false;\n this.Close.emit({ Success: true, Request: this.Request, Action: 'cancelled' });\n } else {\n this.notificationService.CreateSimpleNotification(\n 'Failed to reassign request. Please try again.', 'error', 5000\n );\n }\n } catch (error) {\n console.error('Error reassigning request:', error);\n this.notificationService.CreateSimpleNotification(\n 'An unexpected error occurred.', 'error', 5000\n );\n } finally {\n this.IsReassigning = false;\n this.cdr.markForCheck();\n }\n }\n\n private async searchUsers(term: string): Promise<void> {\n this.IsSearchingUsers = true;\n this.cdr.markForCheck();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<{ ID: string; Name: string; Email: string }>({\n EntityName: 'Users',\n ExtraFilter: `(Name LIKE '%${term.replace(/'/g, \"''\")}%' OR Email LIKE '%${term.replace(/'/g, \"''\")}%')`,\n OrderBy: 'Name',\n MaxRows: 10,\n Fields: ['ID', 'Name', 'Email'],\n ResultType: 'simple'\n });\n this.ReassignUsers = result.Success ? result.Results : [];\n } catch {\n this.ReassignUsers = [];\n } finally {\n this.IsSearchingUsers = false;\n this.cdr.markForCheck();\n }\n }\n\n // ========================================================================\n // Resize\n // ========================================================================\n\n /** Begin resizing when the user mousedowns on the resize handle */\n public OnResizeStart(event: MouseEvent): void {\n event.preventDefault();\n this.IsResizing = true;\n this.resizeStartX = event.clientX;\n this.resizeStartWidth = this.PanelWidth;\n\n this.boundOnResizeMove = (e: MouseEvent) => this.onResizeMove(e);\n this.boundOnResizeEnd = () => this.onResizeEnd();\n document.addEventListener('mousemove', this.boundOnResizeMove);\n document.addEventListener('mouseup', this.boundOnResizeEnd);\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n }\n\n private onResizeMove(event: MouseEvent): void {\n // Panel is on the right, so dragging left (negative deltaX) increases width\n const deltaX = this.resizeStartX - event.clientX;\n const newWidth = Math.max(MIN_PANEL_WIDTH, Math.min(MAX_PANEL_WIDTH, this.resizeStartWidth + deltaX));\n this.PanelWidth = newWidth;\n this.cdr.markForCheck();\n }\n\n private onResizeEnd(): void {\n this.IsResizing = false;\n this.cleanupResizeListeners();\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n this.savePanelWidth();\n this.cdr.markForCheck();\n }\n\n private cleanupResizeListeners(): void {\n if (this.boundOnResizeMove) {\n document.removeEventListener('mousemove', this.boundOnResizeMove);\n this.boundOnResizeMove = null;\n }\n if (this.boundOnResizeEnd) {\n document.removeEventListener('mouseup', this.boundOnResizeEnd);\n this.boundOnResizeEnd = null;\n }\n }\n\n private loadPanelWidth(): void {\n try {\n const saved = UserInfoEngine.Instance.GetSetting(PANEL_WIDTH_SETTING_KEY);\n if (saved) {\n const parsed = parseInt(saved, 10);\n if (!isNaN(parsed) && parsed >= MIN_PANEL_WIDTH && parsed <= MAX_PANEL_WIDTH) {\n this.PanelWidth = parsed;\n }\n }\n } catch {\n // UserInfoEngine may not be initialized yet — use default\n }\n }\n\n private savePanelWidth(): void {\n try {\n UserInfoEngine.Instance.SetSettingDebounced(PANEL_WIDTH_SETTING_KEY, String(this.PanelWidth));\n } catch {\n // Silently ignore save failures\n }\n }\n\n // ========================================================================\n // Form handling\n // ========================================================================\n\n /**\n * Parse the ResponseSchema JSON into an AgentResponseForm for the dynamic form component.\n */\n private initializeForm(): void {\n this.ResponseFormDefinition = null;\n\n if (!this.Request?.ResponseSchema) return;\n\n try {\n const schema = JSON.parse(this.Request.ResponseSchema) as AgentResponseForm;\n if (schema?.questions && Array.isArray(schema.questions)) {\n this.ResponseFormDefinition = schema;\n }\n } catch {\n // If schema is invalid JSON, ignore — user can still provide free-text response\n }\n }\n\n /**\n * Collect current form values from the DynamicFormComponent's reactive FormGroup.\n * This reads values directly so the user doesn't need to click the form's\n * internal submit button before clicking the panel's action buttons.\n */\n private collectFormData(): Record<string, unknown> | null {\n if (!this.dynamicForm?.FormGroup) return null;\n const values = this.dynamicForm.FormGroup.value;\n if (values && Object.keys(values).length > 0) {\n return values;\n }\n return null;\n }\n\n /**\n * Shared logic for submitting any response type\n */\n private async submitResponse(\n status: 'Approved' | 'Rejected' | 'Responded',\n action: 'approved' | 'rejected' | 'responded'\n ): Promise<void> {\n if (!this.Request || this.IsSaving) return;\n\n this.IsSaving = true;\n this.cdr.markForCheck();\n\n try {\n this.Request.Status = status;\n this.Request.Response = this.ResponseText || null;\n this.Request.RespondedAt = new Date();\n\n const formData = this.collectFormData();\n if (formData) {\n this.Request.ResponseData = JSON.stringify(formData);\n }\n\n const saved = await this.Request.Save();\n if (saved) {\n this.notificationService.CreateSimpleNotification(\n `Agent request has been ${action} successfully.`, 'success', 3000\n );\n // Keep panel open so the user can see their submitted response.\n // Template auto-switches to read-only mode since IsActionable becomes false.\n this.completedAction = action;\n } else {\n this.notificationService.CreateSimpleNotification(\n 'Failed to save response. Please try again.', 'error', 5000\n );\n }\n } catch (error) {\n console.error('Error submitting response:', error);\n this.notificationService.CreateSimpleNotification(\n 'An unexpected error occurred while saving the response.', 'error', 5000\n );\n } finally {\n this.IsSaving = false;\n this.cdr.markForCheck();\n }\n }\n}\n","@if (IsOpen && Request) {\n <div class=\"panel-backdrop\" (click)=\"OnBackdropClick()\">\n <div class=\"request-panel\" #panelElement [class.open]=\"IsOpen\" [class.resizing]=\"IsResizing\" [style.width.px]=\"PanelWidth\" (click)=\"$event.stopPropagation()\">\n <!-- Resize Handle (left edge) -->\n <div class=\"resize-handle\" (mousedown)=\"OnResizeStart($event)\">\n <div class=\"resize-grip\"></div>\n </div>\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-content\">\n <div class=\"header-title-row\">\n @if (RequestType?.Icon) {\n <i class=\"{{ RequestType!.Icon }} header-icon\"></i>\n }\n <h3 class=\"panel-title\">{{ RequestType?.Name || 'Agent Request' }}</h3>\n <span class=\"priority-badge\" [class]=\"PriorityClass\">{{ PriorityLabel }}</span>\n <span class=\"status-badge status-{{ Request.Status.toLowerCase() }}\">{{ Request.Status }}</span>\n </div>\n @if (Request.Agent) {\n <span class=\"agent-name\">\n <i class=\"fa-solid fa-robot\"></i> {{ Request.Agent }}\n </span>\n }\n </div>\n <button class=\"close-btn\" (click)=\"OnCancel()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Body -->\n <div class=\"panel-body\">\n <!-- Request Details -->\n <div class=\"section\">\n <h4 class=\"section-title\">Request</h4>\n <p class=\"request-text\">{{ Request.Request }}</p>\n </div>\n\n <!-- Metadata -->\n <div class=\"section metadata-section\">\n <div class=\"metadata-grid\">\n @if (Request.ExpiresAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Expires</span>\n <span class=\"metadata-value\" [class.expired]=\"IsExpired\">\n {{ Request.ExpiresAt | date:'medium' }}\n @if (IsExpired) {\n <span class=\"expired-tag\">Expired</span>\n }\n </span>\n </div>\n }\n @if (Request.__mj_CreatedAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Created</span>\n <span class=\"metadata-value\">{{ Request.__mj_CreatedAt | date:'medium' }}</span>\n </div>\n }\n @if (Request.RespondedAt) {\n <div class=\"metadata-item\">\n <span class=\"metadata-label\">Responded</span>\n <span class=\"metadata-value\">{{ Request.RespondedAt | date:'medium' }}</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Dynamic Response Form (from ResponseSchema) -->\n @if (HasResponseForm && IsActionable && ResponseFormDefinition) {\n <div class=\"section\">\n <mj-dynamic-form #dynamicForm\n [FormDefinition]=\"ResponseFormDefinition\"\n [Disabled]=\"IsSaving\">\n </mj-dynamic-form>\n </div>\n }\n\n <!-- Free-text response (always available for actionable requests) -->\n @if (IsActionable) {\n <div class=\"section\">\n <h4 class=\"section-title\">\n @if (HasResponseForm) {\n Additional Comments\n } @else {\n Response\n }\n </h4>\n <textarea\n class=\"response-textarea\"\n [(ngModel)]=\"ResponseText\"\n placeholder=\"Type your response here...\"\n rows=\"4\">\n </textarea>\n </div>\n }\n\n <!-- Show existing response for already-handled requests -->\n @if (!IsActionable && (Request.Response || Request.ResponseData)) {\n @if (Request.ResponseData) {\n <div class=\"section\">\n <mj-dynamic-form-response\n [FormDefinition]=\"ResponseFormDefinition\"\n [ResponseData]=\"Request.ResponseData\"\n DisplayMode=\"card\">\n </mj-dynamic-form-response>\n </div>\n }\n @if (Request.Response) {\n <div class=\"section\">\n <h4 class=\"section-title\">\n @if (Request.ResponseData) {\n Additional Comments\n } @else {\n Response\n }\n </h4>\n <p class=\"response-text\">{{ Request.Response }}</p>\n </div>\n }\n }\n </div>\n\n <!-- Footer (action buttons) -->\n @if (IsActionable && !IsExpired) {\n <div class=\"panel-footer\">\n @if (IsApprovalType) {\n <button\n class=\"btn btn-approve\"\n (click)=\"OnApprove()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-check\"></i> Approve\n </button>\n <button\n class=\"btn btn-reject\"\n (click)=\"OnReject()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-times\"></i> Reject\n </button>\n } @else {\n <button\n class=\"btn btn-respond\"\n (click)=\"OnRespond()\"\n [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-paper-plane\"></i> Submit Response\n </button>\n }\n <button\n class=\"btn btn-reassign\"\n (click)=\"OnReassignClick()\"\n [disabled]=\"IsSaving\"\n title=\"Reassign to another user\">\n <i class=\"fa-solid fa-user-plus\"></i> Reassign\n </button>\n <button\n class=\"btn btn-cancel\"\n (click)=\"OnCancel()\"\n [disabled]=\"IsSaving\">\n Cancel\n </button>\n </div>\n } @else if (IsExpired) {\n <div class=\"panel-footer\">\n <div class=\"expired-notice\">\n <i class=\"fa-solid fa-clock\"></i> This request has expired and can no longer be responded to.\n </div>\n <button class=\"btn btn-cancel\" (click)=\"OnCancel()\">Close</button>\n </div>\n } @else {\n <div class=\"panel-footer\">\n <button class=\"btn btn-cancel\" (click)=\"OnCancel()\">Close</button>\n </div>\n }\n </div>\n </div>\n\n <!-- Reassign Dialog Overlay -->\n @if (ShowReassignDialog) {\n <div class=\"reassign-overlay\" (click)=\"OnReassignCancel()\">\n <div class=\"reassign-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"reassign-header\">\n <h4 class=\"reassign-title\">\n <i class=\"fa-solid fa-user-plus\"></i> Reassign Request\n </h4>\n <button class=\"close-btn\" (click)=\"OnReassignCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"reassign-body\">\n <!-- User Search -->\n <div class=\"reassign-field\">\n <label class=\"field-label\">Search User</label>\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input\n type=\"text\"\n class=\"field-input search-input\"\n placeholder=\"Type a name or email...\"\n [value]=\"ReassignSearchTerm\"\n (input)=\"OnReassignSearchChange($any($event.target).value)\">\n </div>\n </div>\n\n <!-- Search Results -->\n @if (IsSearchingUsers) {\n <div class=\"search-status\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Searching...\n </div>\n }\n @if (ReassignUsers.length > 0) {\n <div class=\"user-results\">\n @for (user of ReassignUsers; track user.ID) {\n <button\n class=\"user-result-item\"\n [class.selected]=\"SelectedReassignUser?.ID === user.ID\"\n (click)=\"OnSelectReassignUser(user)\">\n <i class=\"fa-solid fa-user user-avatar\"></i>\n <div class=\"user-info\">\n <span class=\"user-name\">{{ user.Name }}</span>\n <span class=\"user-email\">{{ user.Email }}</span>\n </div>\n @if (SelectedReassignUser?.ID === user.ID) {\n <i class=\"fa-solid fa-check selected-check\"></i>\n }\n </button>\n }\n </div>\n } @else if (ReassignSearchTerm.length >= 2 && !IsSearchingUsers) {\n <div class=\"search-status\">No users found</div>\n }\n\n <!-- Note -->\n <div class=\"reassign-field\">\n <label class=\"field-label\">Note (optional)</label>\n <textarea\n class=\"field-textarea\"\n [(ngModel)]=\"ReassignNote\"\n placeholder=\"Add a reason for reassignment...\"\n rows=\"2\">\n </textarea>\n </div>\n </div>\n\n <div class=\"reassign-footer\">\n <button\n class=\"btn btn-respond\"\n (click)=\"OnReassignSubmit()\"\n [disabled]=\"!SelectedReassignUser || IsReassigning\">\n @if (IsReassigning) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Reassigning...\n } @else {\n <i class=\"fa-solid fa-user-plus\"></i> Reassign\n }\n </button>\n <button\n class=\"btn btn-cancel\"\n (click)=\"OnReassignCancel()\"\n [disabled]=\"IsReassigning\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-agent-requests",
3
- "version": "6.1.0-edge.5",
3
+ "version": "6.1.0-edge.7",
4
4
  "description": "MemberJunction: Angular components for AI agent request management - panels and dialogs for viewing and responding to agent feedback requests",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -17,25 +17,25 @@
17
17
  "author": "",
18
18
  "license": "BUSL-1.1",
19
19
  "devDependencies": {
20
- "@angular/compiler": "21.1.3",
21
- "@angular/compiler-cli": "21.1.3",
22
- "@memberjunction/ng-test-utils": "6.1.0-edge.5",
20
+ "@angular/compiler": "21.2.22",
21
+ "@angular/compiler-cli": "21.2.22",
22
+ "@memberjunction/ng-test-utils": "6.1.0-edge.7",
23
23
  "vitest": "^4.0.18"
24
24
  },
25
25
  "peerDependencies": {
26
- "@angular/common": "^21.1.3",
27
- "@angular/core": "^21.1.3",
28
- "@angular/forms": "^21.1.3"
26
+ "@angular/common": "^21.2.22",
27
+ "@angular/core": "^21.2.22",
28
+ "@angular/forms": "^21.2.22"
29
29
  },
30
30
  "dependencies": {
31
- "@memberjunction/ai-core-plus": "6.1.0-edge.5",
32
- "@memberjunction/core": "6.1.0-edge.5",
33
- "@memberjunction/core-entities": "6.1.0-edge.5",
34
- "@memberjunction/global": "6.1.0-edge.5",
35
- "@memberjunction/ng-base-types": "6.1.0-edge.5",
36
- "@memberjunction/ng-forms": "6.1.0-edge.5",
37
- "@memberjunction/ng-notifications": "6.1.0-edge.5",
38
- "@memberjunction/ng-shared-generic": "6.1.0-edge.5",
31
+ "@memberjunction/ai-core-plus": "6.1.0-edge.7",
32
+ "@memberjunction/core": "6.1.0-edge.7",
33
+ "@memberjunction/core-entities": "6.1.0-edge.7",
34
+ "@memberjunction/global": "6.1.0-edge.7",
35
+ "@memberjunction/ng-base-types": "6.1.0-edge.7",
36
+ "@memberjunction/ng-forms": "6.1.0-edge.7",
37
+ "@memberjunction/ng-notifications": "6.1.0-edge.7",
38
+ "@memberjunction/ng-shared-generic": "6.1.0-edge.7",
39
39
  "rxjs": "^7.8.2",
40
40
  "tslib": "^2.8.1"
41
41
  },