ngx-t-forms 2.0.29 → 2.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/ngx-t-forms-auto-complete-input-element.component-DCKuXHAW.mjs +104 -0
- package/fesm2022/ngx-t-forms-auto-complete-input-element.component-DCKuXHAW.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-basic-input-input-element.component-Ce4ipSUc.mjs +85 -0
- package/fesm2022/ngx-t-forms-basic-input-input-element.component-Ce4ipSUc.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-calculated-field-rules.component-C5TPddVe.mjs +643 -0
- package/fesm2022/ngx-t-forms-calculated-field-rules.component-C5TPddVe.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-CICQaqz6.mjs +97 -0
- package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-CICQaqz6.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-CzisLSIP.mjs +195 -0
- package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-CzisLSIP.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-data-source-picker.component-Dzz_o6fJ.mjs +261 -0
- package/fesm2022/ngx-t-forms-data-source-picker.component-Dzz_o6fJ.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-date-picker-input-element.component-CYUbVyzP.mjs +85 -0
- package/fesm2022/ngx-t-forms-date-picker-input-element.component-CYUbVyzP.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-date-range-picker-input-element.component-CmoquQGV.mjs +156 -0
- package/fesm2022/ngx-t-forms-date-range-picker-input-element.component-CmoquQGV.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-CLUOXreG.mjs +368 -0
- package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-CLUOXreG.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-document-picker.component-qObjcqhE.mjs +704 -0
- package/fesm2022/ngx-t-forms-document-picker.component-qObjcqhE.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-editor-input-element.component-BLXlfb6F.mjs +294 -0
- package/fesm2022/ngx-t-forms-editor-input-element.component-BLXlfb6F.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-editor-js-input.component-BQL0AH7H.mjs +240 -0
- package/fesm2022/ngx-t-forms-editor-js-input.component-BQL0AH7H.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-file-upload-input-element.component-C7mMeEjF.mjs +205 -0
- package/fesm2022/ngx-t-forms-file-upload-input-element.component-C7mMeEjF.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-form-input-selector.component-C9u8zq9B.mjs +86 -0
- package/fesm2022/ngx-t-forms-form-input-selector.component-C9u8zq9B.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-form-json-view.component-856Hx1Bg.mjs +22 -0
- package/fesm2022/ngx-t-forms-form-json-view.component-856Hx1Bg.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-form-payload-projection.component-CDkTuX9S.mjs +179 -0
- package/fesm2022/ngx-t-forms-form-payload-projection.component-CDkTuX9S.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-form-section-stepper.component-Bs50-nEB.mjs +319 -0
- package/fesm2022/ngx-t-forms-form-section-stepper.component-Bs50-nEB.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-forms-builder-menu.component-qrhM0jGL.mjs +379 -0
- package/fesm2022/ngx-t-forms-forms-builder-menu.component-qrhM0jGL.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-geo-location.component-Bosp1UzR.mjs +124 -0
- package/fesm2022/ngx-t-forms-geo-location.component-Bosp1UzR.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-getInputIcon-B4ADgevZ.mjs +31 -0
- package/fesm2022/ngx-t-forms-getInputIcon-B4ADgevZ.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-image-capture-input-element.component-C1g7Z0cK.mjs +180 -0
- package/fesm2022/ngx-t-forms-image-capture-input-element.component-C1g7Z0cK.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-index-dDSobs6A.mjs +2 -0
- package/fesm2022/ngx-t-forms-index-dDSobs6A.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-input-custom.component-BkbHFAyR.mjs +105 -0
- package/fesm2022/ngx-t-forms-input-custom.component-BkbHFAyR.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-input-editor.component-BPUOM9kQ.mjs +181 -0
- package/fesm2022/ngx-t-forms-input-editor.component-BPUOM9kQ.mjs.map +1 -0
- package/fesm2022/{ngx-t-forms-map-mat-options-keys-CbdW82su.mjs → ngx-t-forms-map-mat-options-keys-B6hJ7Io5.mjs} +12 -14
- package/fesm2022/ngx-t-forms-map-mat-options-keys-B6hJ7Io5.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-c7uZT1sr.mjs +66 -0
- package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-c7uZT1sr.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-mat-slider-editor.component-CTSBrM-j.mjs +211 -0
- package/fesm2022/ngx-t-forms-mat-slider-editor.component-CTSBrM-j.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-CcYiwx-8.mjs +165 -0
- package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-CcYiwx-8.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-missing-form-configs.component-DrnH8qdG.mjs +38 -0
- package/fesm2022/ngx-t-forms-missing-form-configs.component-DrnH8qdG.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-C_abEBQ5.mjs +38 -0
- package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-C_abEBQ5.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-mscoa-error-display.component-99DpVSy7.mjs +126 -0
- package/fesm2022/ngx-t-forms-mscoa-error-display.component-99DpVSy7.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-mscoa-segment-config.component-C0qsMfsq.mjs +336 -0
- package/fesm2022/ngx-t-forms-mscoa-segment-config.component-C0qsMfsq.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-B1Z-IXSL.mjs +74 -0
- package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-B1Z-IXSL.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-multiple-input-input-element.component-C7y1OGPx.mjs +905 -0
- package/fesm2022/ngx-t-forms-multiple-input-input-element.component-C7y1OGPx.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-ngx-t-forms-u_kigDid.mjs +19461 -0
- package/fesm2022/ngx-t-forms-ngx-t-forms-u_kigDid.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-paginated-selection-table-AQZSMmhr.mjs +555 -0
- package/fesm2022/ngx-t-forms-paginated-selection-table-AQZSMmhr.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-pipeline-generator.component-DmNSc5aw.mjs +748 -0
- package/fesm2022/ngx-t-forms-pipeline-generator.component-DmNSc5aw.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-record-list-manager.component-CUMMvMch.mjs +358 -0
- package/fesm2022/ngx-t-forms-record-list-manager.component-CUMMvMch.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-required-inputs.component-Ch2yNcIS.mjs +272 -0
- package/fesm2022/ngx-t-forms-required-inputs.component-Ch2yNcIS.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-rest-api-call-setup.component-C_aFtdvW.mjs +398 -0
- package/fesm2022/ngx-t-forms-rest-api-call-setup.component-C_aFtdvW.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-search-field.component-B2ZO7lqO.mjs +38 -0
- package/fesm2022/ngx-t-forms-search-field.component-B2ZO7lqO.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-section-report.component-BxOhR6C0.mjs +98 -0
- package/fesm2022/ngx-t-forms-section-report.component-BxOhR6C0.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-select-input-element.component-DbgZdNoe.mjs +150 -0
- package/fesm2022/ngx-t-forms-select-input-element.component-DbgZdNoe.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-selection-options-editor.component-Dhln81DL.mjs +169 -0
- package/fesm2022/ngx-t-forms-selection-options-editor.component-Dhln81DL.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-t-workflow-picker.component-leBokXvM.mjs +204 -0
- package/fesm2022/ngx-t-forms-t-workflow-picker.component-leBokXvM.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-textarea-input-element.component-BEbXJjFA.mjs +95 -0
- package/fesm2022/ngx-t-forms-textarea-input-element.component-BEbXJjFA.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-toggle-input-element.component-DDErRUJd.mjs +82 -0
- package/fesm2022/ngx-t-forms-toggle-input-element.component-DDErRUJd.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-validators-config.component-oGjQVGE2.mjs +733 -0
- package/fesm2022/ngx-t-forms-validators-config.component-oGjQVGE2.mjs.map +1 -0
- package/fesm2022/ngx-t-forms-workflow-adjudication.component-CtU8dECN.mjs +1303 -0
- package/fesm2022/ngx-t-forms-workflow-adjudication.component-CtU8dECN.mjs.map +1 -0
- package/fesm2022/ngx-t-forms.mjs +2 -1
- package/fesm2022/ngx-t-forms.mjs.map +1 -1
- package/package.json +20 -18
- package/styles/_editor-mixins.scss +62 -0
- package/styles/_json-editor-syntax.scss +26 -0
- package/styles/_signature-pad.scss +26 -0
- package/styles/_tokens.scss +148 -0
- package/types/ngx-t-forms.d.ts +1767 -621
- package/fesm2022/ngx-t-forms-calculated-field-rules.component-D-SBMdYg.mjs +0 -313
- package/fesm2022/ngx-t-forms-calculated-field-rules.component-D-SBMdYg.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-1cpszpPN.mjs +0 -191
- package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-1cpszpPN.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-DFdAVWTg.mjs +0 -207
- package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-DFdAVWTg.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-data-source-picker.component-DxORinAD.mjs +0 -204
- package/fesm2022/ngx-t-forms-data-source-picker.component-DxORinAD.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-DcWS1txl.mjs +0 -289
- package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-DcWS1txl.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-form-input-selector.component-B2QEnvkq.mjs +0 -134
- package/fesm2022/ngx-t-forms-form-input-selector.component-B2QEnvkq.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-form-json-view.component-DePf44w6.mjs +0 -22
- package/fesm2022/ngx-t-forms-form-json-view.component-DePf44w6.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-form-section-stepper.component-BTkcSjg7.mjs +0 -270
- package/fesm2022/ngx-t-forms-form-section-stepper.component-BTkcSjg7.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-forms-builder-menu.component-Wamzf_sq.mjs +0 -345
- package/fesm2022/ngx-t-forms-forms-builder-menu.component-Wamzf_sq.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-input-editor.component-D4xHO76K.mjs +0 -147
- package/fesm2022/ngx-t-forms-input-editor.component-D4xHO76K.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-map-mat-options-keys-CbdW82su.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-DmTyO9Wi.mjs +0 -105
- package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-DmTyO9Wi.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-mat-slider-editor.component-DZ4TenrI.mjs +0 -109
- package/fesm2022/ngx-t-forms-mat-slider-editor.component-DZ4TenrI.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-DPyBYE4p.mjs +0 -155
- package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-DPyBYE4p.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-missing-form-configs.component-BRmnwAK6.mjs +0 -28
- package/fesm2022/ngx-t-forms-missing-form-configs.component-BRmnwAK6.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-D_umeAPL.mjs +0 -43
- package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-D_umeAPL.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-mscoa-error-display.component-CSX2NCNU.mjs +0 -116
- package/fesm2022/ngx-t-forms-mscoa-error-display.component-CSX2NCNU.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-mscoa-segment-config.component-B6IF8kGg.mjs +0 -296
- package/fesm2022/ngx-t-forms-mscoa-segment-config.component-B6IF8kGg.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-BPkjsRmH.mjs +0 -83
- package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-BPkjsRmH.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-ngx-t-forms-D9qmig6g.mjs +0 -16844
- package/fesm2022/ngx-t-forms-ngx-t-forms-D9qmig6g.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-pipeline-generator.component-DBJEyCbd.mjs +0 -613
- package/fesm2022/ngx-t-forms-pipeline-generator.component-DBJEyCbd.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-record-list-manager.component-Dgs9lNSr.mjs +0 -269
- package/fesm2022/ngx-t-forms-record-list-manager.component-Dgs9lNSr.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-required-inputs.component-CSIJvSHq.mjs +0 -190
- package/fesm2022/ngx-t-forms-required-inputs.component-CSIJvSHq.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-rest-api-call-setup.component-CY-JSkGs.mjs +0 -291
- package/fesm2022/ngx-t-forms-rest-api-call-setup.component-CY-JSkGs.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-section-report.component-12-KdKT6.mjs +0 -156
- package/fesm2022/ngx-t-forms-section-report.component-12-KdKT6.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-selection-options-editor.component-Be3QAG_L.mjs +0 -186
- package/fesm2022/ngx-t-forms-selection-options-editor.component-Be3QAG_L.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-t-workflow-picker.component-a4f1r8gH.mjs +0 -187
- package/fesm2022/ngx-t-forms-t-workflow-picker.component-a4f1r8gH.mjs.map +0 -1
- package/fesm2022/ngx-t-forms-validators-config.component-B3j9Dmgu.mjs +0 -215
- package/fesm2022/ngx-t-forms-validators-config.component-B3j9Dmgu.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngx-t-forms-pipeline-generator.component-DmNSc5aw.mjs","sources":["../../../projects/ngx-t-forms/src/lib/services/hhtpResources/Pipeline/pipeline.service.ts","../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/pipeline-generator/elements/aggregate-stage-editor/aggregate-stage-editor.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/pipeline-generator/elements/aggregate-stage-editor/aggregate-stage-editor.component.html","../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/pipeline-generator/pipeline-generator.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/pipeline-generator/pipeline-generator.component.html"],"sourcesContent":["import { HttpClient } from '@angular/common/http';\r\nimport { inject, Injectable, PLATFORM_ID } from '@angular/core';\r\nimport { isPlatformBrowser } from '@angular/common';\r\nimport { BehaviorSubject, catchError, combineLatest, filter, finalize, map, Observable, switchMap, take, tap, throwError } from 'rxjs';\r\nimport { PipelineStage } from 'mongoose'\r\n\r\nimport PipelineBuilder from \"db-aggregation-pipeline-builder\"\r\nimport { IPipelineGenerationError, IPipelineGenerationResponse, IRunPipelineResponse, PipelineStageEnum } from 'ngx-t-forms-types';\r\nexport interface IAllowedStage {\r\n stage: PipelineStageEnum,\r\n description: string,\r\n /**\r\n * Stage-specific configuration. MongoDB pipeline stages have heterogeneous shapes\r\n * (each `$stage` operator accepts its own option object), so this remains opaque\r\n * at this layer. Consumers narrow per `stage`.\r\n */\r\n config: unknown,\r\n valid?: boolean\r\n\r\n}\r\n\r\n/**\r\n * @deprecated\r\n *\r\n * Phase 2 layering: prefer `inject(PIPELINE_REPOSITORY)` and wire the\r\n * implementation via `withHttpPipeline()` (or your own `useClass` binding\r\n * against `PIPELINE_REPOSITORY`). This service is preserved as-is for I-1\r\n * parity — its self-contained `inject(HttpClient)` + UI-state surface\r\n * continues to work for current callers and does NOT require the consumer to\r\n * call `withHttpPipeline()`. Target removal: v3.0.0.\r\n *\r\n * Note for new code: the HTTP boundary lives on {@link PipelineRepository}\r\n * (`runPipeline` / `generatePipeline` / `getSchema`). The state-management\r\n * surface here (`pipeline$`, `chatHistory$`, etc.) is internal to the legacy\r\n * pipeline-generator UI and is not part of the repository contract.\r\n */\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class PipelineService {\r\n //LOADING INDICATORS\r\n isRunningPipeline: boolean = false\r\n aiIsGeneratingPipeline: boolean = false\r\n isLoadingAllowedStages: boolean = false\r\n isLoadingWorkflowSchema: boolean = false\r\n\r\n //States \r\n workflowId$ = new BehaviorSubject<string|undefined>(undefined)\r\n activeStage$ = new BehaviorSubject<number|undefined>(undefined)\r\n prompt$ = new BehaviorSubject<string|undefined>(undefined)\r\n schemaLoadError$ = new BehaviorSubject<string|undefined>(undefined)\r\n \r\n\r\n pipeline$ = new BehaviorSubject<PipelineStage[]>([])\r\n threadId$ = new BehaviorSubject<string|undefined>(undefined)\r\n schema$ = new BehaviorSubject<Object|undefined>(undefined)\r\n allowedStages$ = new BehaviorSubject<IAllowedStage[]>([])\r\n pipeLineResult$ = new BehaviorSubject<unknown>([])\r\n chatHistory$ = new BehaviorSubject<{\r\n user: string,\r\n assistance:IPipelineGenerationResponse,\r\n date:Date\r\n }[]>([])\r\n http = inject(HttpClient)\r\n readonly #platformId = inject(PLATFORM_ID);\r\n constructor() {\r\n //Set local storage threadId\r\n if (!isPlatformBrowser(this.#platformId)) return;\r\n const threadId = localStorage.getItem('threadId')\r\n if(threadId){\r\n this.threadId$.next(threadId)\r\n }\r\n }\r\n\r\n get config$() {\r\n return this.workflowId$.pipe(\r\n switchMap(workflowId => this.pipeline$.pipe(\r\n switchMap(pipeline => this.pipeLineResult$.pipe(\r\n map(responseBody => ({ workflowId, pipeline, responseBody }))\r\n ))\r\n ))\r\n );\r\n }\r\n /**\r\n * Fetch available pipeline stages for the user to select and generate pipelines.\r\n * Ideally, this could be static or fetched from a backend.\r\n */\r\n runPipeLine(pipeline: PipelineStage[],workflowId:string): Observable<IRunPipelineResponse> {\r\n const url = \"http://localhost:5000/api/v1/pipelineBuilder/runPipeline\"\r\n // For now, returning a static list of pipeline stages. In a real application, you can fetch from an API.\r\n\r\n this.isRunningPipeline = true\r\n return this.http.post<IRunPipelineResponse>(\r\n url,\r\n { pipeline,workflowId }\r\n ).pipe(\r\n take(1),\r\n catchError(this.handleError), // Error handling for the HTTP request,\r\n finalize(() => this.isRunningPipeline = false)\r\n );\r\n }\r\n\r\n /**\r\n * Generate a MongoDB pipeline based on the given user prompt.\r\n * \r\n * @param prompt The user's input or description of the desired pipeline.\r\n */\r\n private generatePipeline(query: string, schema: Object | undefined,\r\n threadId:string|undefined, existingPipeline: PipelineStage[],previousError:string): Observable<IPipelineGenerationResponse> {\r\n if (!schema) {\r\n throw new Error(\"Schema is required\")\r\n }\r\n const payload = { query, schema ,threadId, existingPipeline ,previousError};\r\n const url = \"http://localhost:5000/api/v1/pipelineBuilder/generatePipeline\";\r\n this.aiIsGeneratingPipeline = true\r\n return this.http.post<IPipelineGenerationResponse>(`${url}`, payload)\r\n .pipe(\r\n take(1),\r\n catchError(this.handleError),// Error handling for the HTTP request,\r\n finalize(() => this.aiIsGeneratingPipeline = false)\r\n );\r\n }\r\n\r\n /**\r\n * Handle any errors from the HTTP request.\r\n *\r\n * @param error The error response from the HTTP request\r\n */\r\n private handleError(error: unknown): Observable<never> {\r\n // Return an observable with a user-facing error message\r\n void error;\r\n return throwError(() => new Error('Something went wrong with the pipeline generation; please try again later.'));\r\n\r\n }\r\n\r\n\r\n private getSchema(workflowId: string): Observable<{\r\n schema: object\r\n }> {\r\n if(!workflowId){\r\n throw new Error(\"WorkflowId is required\")\r\n }\r\n const url = \"http://localhost:5000/api/v1/pipelineBuilder/getSchema\";\r\n return this.http.get<{ schema: object }>(`${url}`, { params: { workflowId: workflowId } }).pipe(\r\n take(1),\r\n catchError(this.handleError) // Error handling for the HTTP request\r\n )\r\n }\r\n/** OPERATIONS */\r\nisSchemaEmpty(object:object){\r\n\r\n}\r\n workflowChanged(event: string | undefined | null): void {\r\n this.workflowId$.next(event ?? undefined)\r\n if(!event){\r\n return\r\n }\r\n this.getSchema(event).pipe(\r\n take(1),\r\n tap(({ schema }) => {\r\n this.schema$.next(schema)\r\n const isEmptySchema = Object.keys( schema)[0] === \"\" && Object.values(schema)[0] === \"Array<>\"\r\n const error = isEmptySchema \r\n ? \"Document schema is missing. Please ensure at least one document exists for the selected workflow.\" \r\n : undefined\r\n this.schemaLoadError$.next(error)\r\n this.runActivePipeline()\r\n }),\r\n catchError((error) => {\r\n this.schemaLoadError$.next(\"Error loading schema\");\r\n return this.handleError(error);\r\n })\r\n ).subscribe()\r\n }\r\n\r\n \r\n setActiveStage(i:number|undefined){\r\n const index = this.activeStage$.getValue()\r\n if(index === i){\r\n this.activeStage$.next(undefined)\r\n return\r\n }\r\n this.activeStage$.next(i)\r\n\r\n \r\n }\r\n addStage(): void {\r\n // NOTE(phase-4): an empty object `{}` is not a valid `PipelineStage`; it acts as a sentinel\r\n // \"blank slot\" until the user picks a stage type. Tracked — proper fix is a discriminated\r\n // union `PipelineStage | { kind: 'blank' }` for the in-progress pipeline.\r\n const blankSlot = {} as PipelineStage;\r\n const newPipeline = this.pipeline$.getValue().concat(blankSlot);\r\n this.pipeline$.next(newPipeline)\r\n }\r\n onTextChange(event: string | undefined): void {\r\n this.prompt$.next(event)\r\n }\r\n promptSubmit() {\r\n // Use combineLatest to fetch the latest values from multiple sources\r\n combineLatest([this.schema$, this.threadId$, this.pipeline$,this.prompt$,this.chatHistory$])\r\n .pipe(\r\n take(1),\r\n tap(() => {}),\r\n filter(([schema,,,prompt]) => !!schema && !!prompt ),\r\n switchMap(([schema, threadId, pipeline,prompt,history]) => {\r\n // Use a shallow copy of the pipeline\r\n const previousError = history[history.length-1]?.assistance?.error ?? ''\r\n const pipelineCopy = pipeline.map(stage => JSON.parse(JSON.stringify(stage))) || [];\r\n // `prompt` is filtered to truthy above; assert via narrowing rather than `!`.\r\n const safePrompt: string = prompt ?? '';\r\n return this.generatePipeline(safePrompt, schema, threadId, pipelineCopy, previousError).pipe(\r\n map((response) => ({ ...response,history,prompt: safePrompt}))\r\n )\r\n }),\r\n tap((response) => {\r\n const { pipeline, threadId,history,prompt } = response;\r\n const historyRecord = {\r\n user: prompt,\r\n assistance: response,\r\n date:new Date()\r\n };\r\n \r\n // Use next with a concatenated value for chat history\r\n this.chatHistory$.next([...(history||[]), historyRecord]);\r\n this.pipeline$.next(pipeline);\r\n this.threadId$.next(threadId);\r\n\r\n // Store threadID locally\r\n if (isPlatformBrowser(this.#platformId)) {\r\n localStorage.setItem('threadId', threadId);\r\n }\r\n \r\n // Run the active pipeline after all state updates are complete\r\n this.runActivePipeline();\r\n }),\r\n catchError((error:IPipelineGenerationError) => {\r\n return this.handleError(error);\r\n })\r\n ).subscribe();\r\n\r\n }\r\n \r\n runActivePipeline() {\r\n const pipeline = [...(this.pipeline$.getValue().map(stage => (JSON.parse(JSON.stringify(stage))))||[])]\r\n const someAreNotValid = pipeline.some(stage=>Object.keys(stage).length ===0)\r\n if(pipeline.length === 0 || someAreNotValid ){\r\n return\r\n }\r\n try {\r\n PipelineBuilder.validatePipeline(pipeline)\r\n } catch {\r\n return\r\n }\r\n const workflowId = this.workflowId$.getValue()\r\n if (!workflowId) {\r\n return\r\n }\r\n \r\n this.runPipeLine(pipeline,workflowId).pipe(\r\n take(1),\r\n tap(({ results }) => {\r\n this.pipeLineResult$.next(results)\r\n }),\r\n catchError((error) => {\r\n const err = JSON.parse(JSON.stringify(error))\r\n const errorMessage = err.error\r\n if(errorMessage){\r\n this.pipelineErrorLogAndRetry(errorMessage)\r\n }\r\n return this.handleError(error);\r\n })\r\n ).subscribe()\r\n }\r\n\r\n pipelineErrorLogAndRetry(message: string): void {\r\n const history = this.chatHistory$.getValue();\r\n const prompt = this.prompt$.getValue();\r\n // NOTE(phase-4): the chatHistory `assistance` field is typed as a full\r\n // `IPipelineGenerationResponse`, but the error path only carries `message`.\r\n // Treat the partial record as a structural fill until the type is narrowed via\r\n // a discriminated union `{ kind: 'ok', response } | { kind: 'error', message }`.\r\n const partialAssistance: Partial<IPipelineGenerationResponse> = { message };\r\n const historyRecord = {\r\n user: prompt ?? '',\r\n assistance: partialAssistance as IPipelineGenerationResponse,\r\n date: new Date()\r\n };\r\n this.chatHistory$.next([...(history || []), historyRecord]);\r\n\r\n }\r\n get activeStage(): Observable<{ name: string; config: PipelineStage | undefined } | undefined> {\r\n return this.pipeline$.asObservable().pipe(\r\n switchMap(pipeline => this.activeStage$.pipe(\r\n map(activeIndex => {\r\n if (activeIndex === undefined) return undefined;\r\n // Each `PipelineStage` in the union has exactly one operator key (e.g. `$match`).\r\n // Read it through a typed `Record` lookup rather than casting the whole row.\r\n const stage: PipelineStage | undefined = pipeline[activeIndex];\r\n const stageRecord = (stage ?? {}) as Record<string, PipelineStage>;\r\n const name = Object.keys(stageRecord)[0] ?? '';\r\n return {\r\n name,\r\n config: stageRecord[name],\r\n };\r\n })\r\n ))\r\n )\r\n\r\n }\r\n saveStage(index: number, stage: IAllowedStage | undefined): void {\r\n const pipeline = this.pipeline$.getValue()\r\n if (index === undefined) {\r\n return\r\n }\r\n const newPipeline: PipelineStage[] = pipeline.map((s, i) => {\r\n if (i === index && stage) {\r\n // NOTE(phase-4): building a `PipelineStage` from `{ [stage.stage]: stage.config }` is\r\n // correct at runtime — the union member is keyed by the operator — but TS cannot prove\r\n // the dynamic key matches a specific variant. Tracked for a per-stage builder fn.\r\n const built: Record<string, unknown> = { [stage.stage]: stage.config };\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO(phase-4): per-stage builder fn would let TS narrow; internal-only service.\r\n return built as any;\r\n }\r\n return s;\r\n });\r\n\r\n this.pipeline$.next(newPipeline)\r\n this.activeStage$.next(undefined)\r\n this.runActivePipeline()\r\n\r\n }\r\n deleteStage(index: number): void {\r\n const pipeline = this.pipeline$.getValue()\r\n\r\n if (index === undefined) {\r\n return\r\n }\r\n const newPipeline: PipelineStage[] = pipeline.filter((_s, i) => i !== index);\r\n this.pipeline$.next(newPipeline)\r\n this.activeStage$.next(undefined)\r\n this.runActivePipeline()\r\n }\r\n get pipelineGeneralValid(){\r\n return this.pipeline$.asObservable().pipe(\r\n map(pipeline=>{\r\n const allHaveTypes = pipeline.every(stage=>Object.keys(stage).length === 1)\r\n if(!allHaveTypes){\r\n return {\r\n valid:false,\r\n message:\"All stages must be a valid pipeline stage\"\r\n }\r\n }\r\n const AllStagesMustHaveConfig = pipeline.every((stage) => {\r\n // Each PipelineStage union member has one operator key + value; reading via\r\n // `Object.entries` keeps us off an `as unknown as Record<…>` cast.\r\n const [firstEntry] = Object.entries(stage);\r\n return firstEntry !== undefined && firstEntry[1] !== undefined;\r\n })\r\n if(!AllStagesMustHaveConfig){\r\n return {\r\n valid:false,\r\n message:\"All stages must have a configuration\"\r\n }\r\n }\r\n return {\r\n valid:true\r\n }\r\n })\r\n )\r\n }\r\n}","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n output,\n signal,\n} from '@angular/core';\nimport PipelineBuilder from 'db-aggregation-pipeline-builder';\nimport { PipelineStageEnum } from 'ngx-t-forms-types';\n\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatCardModule } from '@angular/material/card';\nimport { MatDividerModule } from '@angular/material/divider';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatSelectModule, MatSelectChange } from '@angular/material/select';\nimport { MatTooltipModule } from '@angular/material/tooltip';\n\nimport { JsonEditorComponent, JsonEditorChange } from '../../../json-editor/json-editor.component';\nimport { IAllowedStage } from '../../../../../../services/hhtpResources/Pipeline/pipeline.service';\n\n/**\n * One row of the in-progress pipeline as surfaced by the pipeline generator:\n * the operator key (`name`/`stage`), its opaque config object, and a validity flag.\n */\nexport interface PipelineStageRow {\n /** Operator key, e.g. `$match`. Absent on a freshly added blank slot. */\n readonly name: string | undefined;\n /** Mirror of {@link name}; both keys exist for template/legacy parity. */\n readonly stage: string | undefined;\n /** Stage-specific configuration; heterogeneous per operator, hence opaque here. */\n readonly config: unknown;\n /** Whether the row currently passes stage-config validation. */\n readonly valid: boolean;\n}\n\n/** Selectable aggregate stage with its human description. */\ninterface AllowedStage {\n readonly stage: PipelineStageEnum;\n readonly description: string;\n}\n\n/** Working draft of the stage being edited. `stage` is absent until the user picks one. */\ninterface StageDraft {\n readonly stage: PipelineStageEnum | undefined;\n readonly config: unknown;\n readonly valid: boolean;\n}\n\n/**\n * Embedded aggregate-pipeline stage editor used inside `lib-pipeline-generator`.\n * Lets the user pick a `$stage` operator and edit its JSON configuration (via\n * `lib-json-editor`), validating the config against the pipeline builder.\n *\n * Not part of the public API.\n *\n * @example\n * <lib-aggregate-stage-editor\n * [selectedStage]=\"stage\"\n * [isRunningPipeline]=\"running\"\n * (saveStage)=\"onSave($event)\"\n * (deleteStage)=\"onDelete()\" />\n */\n@Component({\n selector: 'lib-aggregate-stage-editor',\n templateUrl: './aggregate-stage-editor.component.html',\n styleUrls: ['./aggregate-stage-editor.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: { 'class': 'lib-aggregate-stage-editor' },\n imports: [\n JsonEditorComponent,\n MatButtonModule,\n MatCardModule,\n MatDividerModule,\n MatIconModule,\n MatFormFieldModule,\n MatSelectModule,\n MatTooltipModule,\n ],\n})\nexport class AggregateStageEditorComponent {\n /** Stage currently being edited (one row of the pipeline generator state). */\n readonly selectedStage = input<PipelineStageRow | undefined>(undefined);\n\n /** When the parent pipeline is executing, destructive/save actions are disabled. */\n readonly isRunningPipeline = input<boolean>(false);\n\n /** Emits the prepared stage when the user saves a valid configuration. */\n readonly saveStage = output<IAllowedStage | undefined>();\n\n /** Emits when the user requests the active stage be removed. */\n readonly deleteStage = output<void>();\n\n /** Stages the user can choose from (loaded once from the pipeline builder). */\n protected readonly allowedStages: readonly AllowedStage[] =\n PipelineBuilder.getViewOnlyStages();\n\n /** Working draft of the stage being edited; `undefined` until the user edits. */\n readonly #draft = signal<StageDraft | undefined>(undefined);\n\n /** Validation message from the last config check, or `undefined` when valid. */\n protected readonly configValidationError = signal<string | undefined>(undefined);\n\n /** Resolved operator key for the select control (draft first, else the input). */\n protected readonly currentStage = computed<string | undefined>(\n () => this.#draft()?.stage ?? this.selectedStage()?.name,\n );\n\n /** Config value passed to the JSON editor (draft first, else the input). */\n protected readonly currentConfig = computed<object | undefined>(() => {\n const config = this.#draft()?.config ?? this.selectedStage()?.config;\n return this.#asObject(config);\n });\n\n /** Whether the editing surface (operator picker is set or config present) shows. */\n protected readonly showConfig = computed<boolean>(\n () => this.#draft() !== undefined || this.selectedStage()?.config !== undefined,\n );\n\n /** Human description for the currently selected operator, if any. */\n protected readonly activeDescription = computed<string | undefined>(\n () => this.allowedStages.find((s) => s.stage === this.currentStage())?.description,\n );\n\n /** Whether the Save action is enabled: a draft exists, is valid and error-free. */\n protected readonly canSave = computed<boolean>(() => {\n const draft = this.#draft();\n return draft !== undefined && draft.valid === true && this.configValidationError() === undefined;\n });\n\n protected handleStageChange(event: MatSelectChange): void {\n const stage = event.value as PipelineStageEnum;\n // BEHAVIOUR FIX: the previous implementation spread the source row AFTER\n // setting `stage`, which silently reverted the operator to its prior value.\n // Here the newly picked operator always wins; the existing config carries over.\n const config = this.#draft()?.config ?? this.selectedStage()?.config;\n this.#draft.set({ stage, config, valid: false });\n this.#validate();\n }\n\n protected handleConfigChange(change: JsonEditorChange): void {\n const stage = this.#draft()?.stage ?? this.#stageFromRow();\n this.#draft.set({ stage, config: change.value, valid: false });\n this.#validate();\n }\n\n protected saveConfiguration(): void {\n const draft = this.#draft();\n if (this.canSave() && draft?.stage) {\n this.saveStage.emit({\n stage: draft.stage,\n description: this.activeDescription() ?? '',\n config: draft.config,\n valid: draft.valid,\n });\n }\n }\n\n protected deleteActive(): void {\n this.deleteStage.emit();\n }\n\n protected trackByStage(stage: AllowedStage): string {\n return stage.stage;\n }\n\n /** Validates the working draft against the pipeline builder, updating state. */\n #validate(): void {\n this.configValidationError.set(undefined);\n const draft = this.#draft();\n if (!draft) return;\n\n const { config, stage } = draft;\n if ((config === undefined || config === null) || !stage) {\n this.#draft.set({ ...draft, valid: false });\n return;\n }\n\n try {\n const valid = PipelineBuilder.validateStageConfig(stage, config);\n this.#draft.set({ ...draft, valid });\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'An unknown error occurred';\n this.configValidationError.set(message);\n this.#draft.set({ ...draft, valid: false });\n }\n }\n\n /** Reads the operator key from the input row as a typed enum, if recognised. */\n #stageFromRow(): PipelineStageEnum | undefined {\n const name = this.selectedStage()?.name;\n return this.allowedStages.find((s) => s.stage === name)?.stage;\n }\n\n /** Narrows an opaque config value to the `object | undefined` the JSON editor accepts. */\n #asObject(value: unknown): object | undefined {\n return value !== null && typeof value === 'object' ? value : undefined;\n }\n}\n","<mat-card class=\"lib-aggregate-stage-editor__card\" appearance=\"outlined\">\n <mat-card-content>\n <p class=\"lib-aggregate-stage-editor__title\">Aggregate pipeline stage configuration</p>\n\n <mat-form-field\n class=\"lib-aggregate-stage-editor__field\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\">\n <mat-label>Select aggregate stage</mat-label>\n <mat-select\n [value]=\"currentStage()\"\n (selectionChange)=\"handleStageChange($event)\"\n placeholder=\"Choose a stage operator\">\n @for (stage of allowedStages; track trackByStage(stage)) {\n <mat-option [value]=\"stage.stage\">{{ stage.stage }}</mat-option>\n }\n </mat-select>\n <mat-hint>\n {{ activeDescription()\n ? 'Hover the info icon to view stage details.'\n : 'Select an aggregation operator from the list.' }}\n </mat-hint>\n @if (activeDescription(); as description) {\n <mat-icon\n class=\"lib-aggregate-stage-editor__hint-icon\"\n matSuffix\n matTooltipHideDelay=\"1000\"\n [matTooltip]=\"description\">info</mat-icon>\n }\n </mat-form-field>\n\n @if (configValidationError(); as error) {\n <div class=\"lib-aggregate-stage-editor__warning\" role=\"alert\">\n <mat-icon aria-hidden=\"true\">warning</mat-icon>\n <span>{{ error }}</span>\n </div>\n }\n\n @if (showConfig()) {\n <div class=\"lib-aggregate-stage-editor__config\">\n <lib-json-editor [value]=\"currentConfig()\" (valueChange)=\"handleConfigChange($event)\" />\n </div>\n }\n </mat-card-content>\n\n <mat-divider />\n\n <mat-card-actions class=\"lib-aggregate-stage-editor__actions\" align=\"end\">\n <button\n mat-button\n type=\"button\"\n color=\"warn\"\n [disabled]=\"isRunningPipeline()\"\n (click)=\"deleteActive()\">\n Delete\n <mat-icon>delete</mat-icon>\n </button>\n <button\n mat-flat-button\n type=\"button\"\n color=\"primary\"\n [disabled]=\"isRunningPipeline() || !canSave()\"\n (click)=\"saveConfiguration()\">\n Save\n <mat-icon>save</mat-icon>\n </button>\n </mat-card-actions>\n</mat-card>\n","import { isPlatformBrowser, JsonPipe } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n Input,\n OnDestroy,\n OnInit,\n Optional,\n PLATFORM_ID,\n Self,\n ViewEncapsulation,\n computed,\n inject,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';\nimport { FormsModule, NgControl } from '@angular/forms';\nimport { MatFormFieldControl } from '@angular/material/form-field';\nimport { distinctUntilChanged, map, Observable, Subject, take } from 'rxjs';\nimport type { PipelineStage } from 'mongoose';\nimport { IWorkflowOption, MongoDbPipeLineConfigInterface } from 'ngx-t-forms-types';\n\nimport { OverlayModule } from '@angular/cdk/overlay';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatDividerModule } from '@angular/material/divider';\nimport { MatExpansionModule } from '@angular/material/expansion';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatListModule } from '@angular/material/list';\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\nimport { MatToolbarModule } from '@angular/material/toolbar';\n\nimport type { IConfigElementError } from '../../t-dynamic-data-edit.component';\nimport { TDynamicDataViewComponent } from '../../../t-dynamic-data-view/t-dynamic-data-view.component';\nimport { TWorkflowPickerComponent } from '../t-workflow-picker/t-workflow-picker.component';\nimport { EmptyStateComponent } from '../_shared/empty-state/empty-state.component';\nimport { DaysAgoPipe } from '../../../../../lib/shared/pipes/date/days-ago.pipe';\nimport { IAllowedStage, PipelineService } from '../../../../../lib/services/hhtpResources/Pipeline/pipeline.service';\nimport { _isEqual } from '../../../../shared/functions/isEqual';\nimport {\n AggregateStageEditorComponent,\n PipelineStageRow,\n} from './elements/aggregate-stage-editor/aggregate-stage-editor.component';\n\n/** Property-suggestion chip surfaced under the AI prompt as the user types `$`. */\ninterface SchemaProperty {\n readonly label: string;\n readonly value: string;\n}\n\n/**\n * Internal editor for `editType = MongoPipelineBuilder`. Implements\n * `MatFormFieldControl` so it can be embedded inside a `mat-form-field`, and\n * drives a MongoDB aggregation-pipeline builder (stage list, results preview,\n * AI prompt) via a component-scoped {@link PipelineService}.\n *\n * Not part of the public API.\n *\n * @deprecated The MongoDB pipeline builder (`editType = MongoPipelineBuilder`)\n * is deprecated and no longer offered as a selectable editor option (filtered\n * out in `getSectionElements`). It is retained only to render already-configured\n * (legacy) inputs and the `data-source-picker` MongoDB-pipeline data source.\n * Do not wire it to any new editor option.\n */\n@Component({\n selector: 'lib-pipeline-generator',\n templateUrl: './pipeline-generator.component.html',\n styleUrls: ['./pipeline-generator.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n imports: [\n JsonPipe,\n FormsModule,\n OverlayModule,\n MatButtonModule,\n MatDividerModule,\n MatExpansionModule,\n MatIconModule,\n MatListModule,\n MatProgressSpinnerModule,\n MatToolbarModule,\n TWorkflowPickerComponent,\n TDynamicDataViewComponent,\n AggregateStageEditorComponent,\n EmptyStateComponent,\n DaysAgoPipe,\n ],\n // Each pipeline generator owns a private PipelineService instance so concurrent\n // editors never cross-pollinate state (stage list, chat history, results).\n providers: [\n PipelineService,\n // MatFormFieldControl pattern: useExisting + the @Input() value/disabled/id\n // members are framework wiring and stay together (CLAUDE.md MFC carve-out).\n { provide: MatFormFieldControl, useExisting: PipelineGeneratorComponent },\n ],\n host: {\n 'class': 'lib-pipeline-generator',\n '[id]': 'id',\n },\n})\nexport class PipelineGeneratorComponent\n implements OnInit, OnDestroy, MatFormFieldControl<MongoDbPipeLineConfigInterface>\n{\n static nextId = 0;\n\n readonly stateChanges = new Subject<void>();\n\n readonly #platformId = inject(PLATFORM_ID);\n readonly #destroyRef = inject(DestroyRef);\n readonly #pipeline = inject(PipelineService);\n\n // MFC requires a plain mutable `id` field (string) — cannot be a signal.\n id = `app-pipeline-generator-${PipelineGeneratorComponent.nextId++}`;\n\n placeholder = '';\n focused = false;\n required = false;\n touched = false;\n @Input() disabled = false;\n\n controlType = 'lib-pipeline-generator';\n autofilled?: boolean;\n userAriaDescribedBy?: string;\n disableAutomaticLabeling?: boolean;\n\n constructor(\n @Optional() @Self() public ngControl: NgControl,\n private readonly _elementRef: ElementRef<HTMLElement>,\n ) {}\n\n // ---- MatFormFieldControl value ------------------------------------------\n\n #value!: MongoDbPipeLineConfigInterface;\n\n // MFC value setter — kept as @Input() (framework wiring).\n @Input() set value(value: MongoDbPipeLineConfigInterface) {\n const workflowIdChanged = this.#value?.workflowId !== value?.workflowId;\n const pipelineChanged = !_isEqual(this.#value?.pipeline, value?.pipeline);\n if (workflowIdChanged || pipelineChanged) {\n this.#value = value;\n if (value?.workflowId) {\n this.workflowChanged(value.workflowId);\n }\n if (value?.pipeline) {\n this.#pipeline.pipeline$.next(value.pipeline as PipelineStage[]);\n }\n this.stateChanges.next();\n }\n }\n get value(): MongoDbPipeLineConfigInterface {\n return this.#value;\n }\n\n // ---- Other public inputs / outputs --------------------------------------\n\n #workflows$: Observable<IWorkflowOption[] | undefined> | undefined;\n /** Source of workflow options forwarded to the embedded workflow picker. */\n @Input() set getWorkflowOptions(options$: Observable<IWorkflowOption[] | undefined> | undefined) {\n this.#workflows$ = options$;\n }\n get getWorkflowOptions(): Observable<IWorkflowOption[] | undefined> | undefined {\n return this.#workflows$;\n }\n\n /** Display name of the current user (reserved for AI prompt attribution). */\n @Input() userName: string | undefined;\n\n /** Validation errors surfaced by the parent for error-state derivation. */\n @Input() set errors(value: IConfigElementError[] | undefined) {\n this.#errors = value;\n }\n get errors(): IConfigElementError[] | undefined {\n return this.#errors;\n }\n #errors: IConfigElementError[] | undefined = [];\n\n /** Emits the updated pipeline configuration whenever the builder state changes. */\n readonly valueChanged = output<MongoDbPipeLineConfigInterface>();\n\n // ---- MatFormFieldControl derived state ----------------------------------\n\n get empty(): boolean {\n return !this.#value;\n }\n get shouldLabelFloat(): boolean {\n return this.focused || !this.empty;\n }\n get errorState(): boolean {\n const externalError = (this.#errors?.length ?? 0) > 0 && this.touched;\n const ngControlError = this.ngControl?.control?.errors != null;\n return (!this.#value && this.required) || externalError || ngControlError;\n }\n\n setDescribedByIds(ids: string[]): void {\n if (!isPlatformBrowser(this.#platformId)) return;\n // DEFECT FIX: the original queried `.app-pipeline-generator`, a class that\n // never existed in the template, so describedBy was silently dropped. Apply\n // it to the host element instead.\n this._elementRef.nativeElement.setAttribute('aria-describedby', ids.join(' '));\n }\n\n onContainerClick(): void {\n this.markAsTouched();\n this.stateChanges.next();\n }\n\n onTouched = (): void => {};\n markAsTouched(): void {\n if (!this.touched) {\n this.onTouched();\n this.touched = true;\n }\n }\n\n // ---- Reactive view state (signals over | async) -------------------------\n\n protected readonly workflowId = toSignal(this.#pipeline.workflowId$, { initialValue: undefined });\n protected readonly activeStageIndex = toSignal(this.#pipeline.activeStage$, { initialValue: undefined });\n protected readonly pipeLineResults = toSignal(this.#pipeline.pipeLineResult$, { initialValue: undefined });\n protected readonly prompt = toSignal(this.#pipeline.prompt$, { initialValue: undefined });\n protected readonly schemaLoadError = toSignal(this.#pipeline.schemaLoadError$, { initialValue: undefined });\n protected readonly chatHistory = toSignal(this.#pipeline.chatHistory$, { initialValue: [] });\n\n /** Pipeline stages projected into the row shape the template + stage editor consume. */\n protected readonly stages = toSignal(\n this.#pipeline.pipeline$.pipe(\n map((stages) =>\n stages.map((stage, index): PipelineStageRow & { readonly id: number } => {\n const [name, config] = Object.entries(stage ?? {}).at(0) ?? [undefined, undefined];\n return {\n id: index,\n name,\n stage: name,\n config,\n valid: name !== undefined && config !== undefined,\n };\n }),\n ),\n ),\n { initialValue: [] },\n );\n\n /** Schema document properties filtered by the live suggestion search. */\n protected readonly schema = toSignal(this.#pipeline.schema$, { initialValue: undefined });\n protected readonly optionsSearch = signal('');\n protected readonly schemaProperties = computed<SchemaProperty[]>(() => {\n const search = this.optionsSearch().toLowerCase();\n return Object.keys(this.schema() ?? {})\n .map((key) => ({ label: key, value: key }))\n .filter((entry) => (search ? entry.label.toLowerCase().includes(search) : true));\n });\n\n protected get isRunningPipeline(): boolean {\n return this.#pipeline.isRunningPipeline;\n }\n protected get aiIsGeneratingPipeline(): boolean {\n return this.#pipeline.aiIsGeneratingPipeline;\n }\n\n protected readonly showSuggestions = signal(false);\n\n private readonly textareaRef = viewChild<ElementRef<HTMLTextAreaElement>>('textarea');\n\n // ---- Lifecycle: emit config changes -------------------------------------\n\n #initiated = false;\n\n ngOnInit(): void {\n // Skip the first (current) config emission so an inbound value does not\n // immediately echo back out as a \"change\".\n this.#pipeline.config$\n .pipe(\n distinctUntilChanged((prev, curr) => _isEqual(prev, curr)),\n takeUntilDestroyed(this.#destroyRef),\n )\n .subscribe((config) => {\n if (!this.#initiated) {\n this.#initiated = true;\n return;\n }\n const newConfig: MongoDbPipeLineConfigInterface = {\n ...this.#value,\n ...config,\n name: this.#workflowName ?? 'Unnamed Pipeline',\n source: 'mongoPipeline',\n } as MongoDbPipeLineConfigInterface;\n this.valueChanged.emit(newConfig);\n });\n }\n\n ngOnDestroy(): void {\n this.stateChanges.complete();\n }\n\n // ---- Workflow picker -----------------------------------------------------\n\n #workflowName: string | undefined;\n\n workflowChanged(workflowId: string | undefined): void {\n // BEHAVIOUR FLAG: switching to a *different* workflow clears the AI chat\n // history so prior suggestions for another collection do not leak into the\n // new context. Re-setting the same workflow (e.g. an inbound value echo)\n // leaves the chat intact.\n if (this.#pipeline.workflowId$.getValue() !== workflowId) {\n this.#pipeline.chatHistory$.next([]);\n }\n this.#pipeline.workflowChanged(workflowId);\n }\n\n workflowNameChanged(name: string | undefined): void {\n this.#workflowName = name;\n }\n\n // ---- Stage management ----------------------------------------------------\n\n protected trackByStageId(_index: number, stage: { readonly id: number }): number {\n return stage.id;\n }\n\n protected setActiveStage(index: number | undefined): void {\n this.#pipeline.setActiveStage(index);\n }\n protected addStage(): void {\n this.#pipeline.addStage();\n }\n protected deleteStage(index: number): void {\n this.#pipeline.deleteStage(index);\n }\n protected saveStage(index: number, stage: IAllowedStage | undefined): void {\n this.#pipeline.saveStage(index, stage);\n this.setActiveStage(undefined);\n }\n\n // ---- AI prompt -----------------------------------------------------------\n\n #cursorPosition = 0;\n\n protected onTextChange(event: Event): void {\n const textarea = this.textareaRef()?.nativeElement;\n if (!textarea) return;\n\n const newValue = (event.target as HTMLTextAreaElement).value;\n this.#cursorPosition = textarea.selectionStart ?? 0;\n\n const lastChar = newValue[this.#cursorPosition - 1];\n const match = newValue.slice(0, this.#cursorPosition).match(/\\$(\\w*)$/);\n\n if (lastChar === '$' || (match && match[1] !== undefined)) {\n this.showSuggestions.set(true);\n this.optionsSearch.set(match?.[1] ?? '');\n } else {\n this.showSuggestions.set(false);\n this.optionsSearch.set('');\n }\n\n this.#pipeline.onTextChange(newValue);\n }\n\n protected selectSuggestion(suggestion: string): void {\n this.#pipeline.prompt$\n .pipe(take(1), takeUntilDestroyed(this.#destroyRef))\n .subscribe((prompt) => {\n const match = prompt?.slice(0, this.#cursorPosition).match(/\\$(\\w*)$/);\n const beforeCursor = prompt?.slice(0, match ? match.index : this.#cursorPosition - 1) ?? '';\n const afterCursor = prompt?.slice(this.#cursorPosition) ?? '';\n const updated = `${beforeCursor}${suggestion} ${afterCursor}`;\n this.#pipeline.prompt$.next(updated);\n this.#applySuggestionToTextarea(suggestion);\n });\n }\n\n #applySuggestionToTextarea(suggestion: string): void {\n this.showSuggestions.set(false);\n if (!isPlatformBrowser(this.#platformId)) return;\n const textarea = this.textareaRef()?.nativeElement;\n if (!textarea) return;\n textarea.focus();\n const nextPosition = this.#cursorPosition + suggestion.length;\n setTimeout(() => textarea.setSelectionRange(nextPosition, nextPosition), 0);\n }\n\n protected promptSubmit(): void {\n this.#pipeline.promptSubmit();\n }\n}\n","<p class=\"lib-pipeline-generator__intro\">\n MongoDB aggregation pipeline builder for the selected workflow.\n</p>\n\n<lib-t-workflow-picker\n [getWorkflowOptions]=\"getWorkflowOptions\"\n [value]=\"workflowId() || undefined\"\n (valueChanged)=\"workflowChanged($event)\"\n (workflowNameChanged)=\"workflowNameChanged($event)\" />\n\n@if (workflowId()) {\n <mat-accordion class=\"lib-pipeline-generator__accordion\" multi>\n\n <!-- Pipeline stages -->\n <mat-expansion-panel value=\"pipeline\">\n <mat-expansion-panel-header>\n <mat-panel-title>\n @if (isRunningPipeline) {\n <mat-spinner class=\"lib-pipeline-generator__header-spinner\" diameter=\"20\" />\n }\n <mat-icon class=\"lib-pipeline-generator__title-icon\">dynamic_form</mat-icon>\n {{ isRunningPipeline ? 'Executing data pipeline…' : 'Data retrieval pipeline' }}\n </mat-panel-title>\n </mat-expansion-panel-header>\n\n <div class=\"lib-pipeline-generator__content\">\n @if (stages().length === 0) {\n <lib-empty-state\n icon=\"account_tree\"\n message=\"Add stages to the pipeline below. Each stage filters, groups, or calculates values; its output documents flow into the next stage.\" />\n }\n\n <mat-nav-list class=\"lib-pipeline-generator__stages\">\n @for (stage of stages(); track trackByStageId($index, stage)) {\n <mat-list-item\n class=\"lib-pipeline-generator__stage\"\n [class.lib-pipeline-generator__stage--active]=\"activeStageIndex() === $index\"\n [activated]=\"activeStageIndex() === $index\"\n (click)=\"setActiveStage($index)\">\n <span class=\"lib-pipeline-generator__stage-index\" matListItemAvatar>{{ $index + 1 }}</span>\n <div matListItemTitle>\n <div class=\"lib-pipeline-generator__stage-name\">{{ stage.name || 'Stage' }}</div>\n @if (!stage.name && activeStageIndex() !== $index) {\n <div class=\"lib-pipeline-generator__stage-hint\">Incomplete — click to edit</div>\n }\n </div>\n\n @if (activeStageIndex() === $index) {\n <mat-icon matListItemMeta color=\"primary\">check_circle</mat-icon>\n } @else if (!stage.valid) {\n <mat-icon matListItemMeta color=\"warn\">warning</mat-icon>\n }\n </mat-list-item>\n <mat-divider />\n\n @if (activeStageIndex() === $index) {\n <lib-aggregate-stage-editor\n [selectedStage]=\"stage\"\n [isRunningPipeline]=\"isRunningPipeline\"\n (deleteStage)=\"deleteStage($index)\"\n (saveStage)=\"saveStage($index, $event)\" />\n }\n }\n\n <mat-toolbar class=\"lib-pipeline-generator__toolbar\">\n <span class=\"lib-pipeline-generator__spacer\"></span>\n <button\n mat-flat-button\n type=\"button\"\n color=\"primary\"\n class=\"lib-pipeline-generator__add\"\n [disabled]=\"isRunningPipeline\"\n (click)=\"addStage()\">\n Add\n <mat-icon>add</mat-icon>\n </button>\n </mat-toolbar>\n </mat-nav-list>\n </div>\n </mat-expansion-panel>\n\n <!-- Results -->\n <mat-expansion-panel value=\"results\">\n <mat-expansion-panel-header>\n <mat-panel-title>\n @if (isRunningPipeline) {\n <mat-spinner class=\"lib-pipeline-generator__header-spinner\" diameter=\"20\" />\n }\n <mat-icon class=\"lib-pipeline-generator__title-icon\">dataset</mat-icon>\n {{ isRunningPipeline ? 'Running pipeline…' : 'Data results' }}\n </mat-panel-title>\n </mat-expansion-panel-header>\n\n <div class=\"lib-pipeline-generator__content\">\n @if (pipeLineResults(); as results) {\n <lib-t-dynamic-data-view [data]=\"results\" />\n } @else {\n <lib-empty-state icon=\"dataset\" message=\"No results available\" />\n }\n </div>\n </mat-expansion-panel>\n\n <!-- AI agent -->\n <mat-expansion-panel value=\"ai\">\n <mat-expansion-panel-header>\n <mat-panel-title>\n @if (aiIsGeneratingPipeline) {\n <mat-spinner class=\"lib-pipeline-generator__header-spinner\" diameter=\"20\" />\n }\n <mat-icon class=\"lib-pipeline-generator__title-icon\">tips_and_updates</mat-icon>\n {{ aiIsGeneratingPipeline ? 'Agent busy…' : 'AI agent prompt' }}\n </mat-panel-title>\n </mat-expansion-panel-header>\n\n <div class=\"lib-pipeline-generator__content\">\n @if (schemaLoadError(); as schemaLoadError) {\n <div class=\"lib-pipeline-generator__warning\" role=\"alert\">\n <mat-icon aria-hidden=\"true\">error</mat-icon>\n <span>{{ schemaLoadError }}</span>\n </div>\n }\n\n @for (chat of chatHistory(); track $index) {\n <div class=\"lib-pipeline-generator__chat\">\n <div class=\"lib-pipeline-generator__bubble lib-pipeline-generator__bubble--user\">\n <div>{{ chat.user }}</div>\n <div class=\"lib-pipeline-generator__bubble-meta\">\n {{ chat.date | daysAgo }}\n <mat-icon class=\"lib-pipeline-generator__sent-icon\">done_all</mat-icon>\n </div>\n </div>\n\n <div class=\"lib-pipeline-generator__assistant\">\n <mat-icon class=\"lib-pipeline-generator__assistant-icon\">smart_toy</mat-icon>\n @if (chat.assistance.error) {\n <div class=\"lib-pipeline-generator__bubble lib-pipeline-generator__bubble--error\">\n {{ chat.assistance.error }}\n </div>\n } @else {\n <div class=\"lib-pipeline-generator__bubble lib-pipeline-generator__bubble--bot\">\n <pre>{{ chat.assistance.pipeline | json }}</pre>\n </div>\n }\n </div>\n </div>\n }\n\n <div class=\"lib-pipeline-generator__composer\">\n <textarea\n #textarea\n class=\"lib-pipeline-generator__textarea\"\n [value]=\"prompt() || ''\"\n (input)=\"onTextChange($event)\"\n placeholder=\"Provide a pipeline generation prompt\"></textarea>\n <button\n mat-mini-fab\n type=\"button\"\n color=\"primary\"\n class=\"lib-pipeline-generator__send\"\n [disabled]=\"aiIsGeneratingPipeline\"\n (click)=\"promptSubmit()\">\n @if (aiIsGeneratingPipeline) {\n <mat-spinner class=\"lib-pipeline-generator__send-spinner\" diameter=\"24\" />\n } @else {\n <mat-icon>send</mat-icon>\n }\n </button>\n </div>\n\n @if (showSuggestions()) {\n <section class=\"lib-pipeline-generator__suggestions\">\n <mat-divider />\n <p class=\"lib-pipeline-generator__suggestions-label\">Collection document properties</p>\n <div class=\"lib-pipeline-generator__suggestion-list\">\n @for (property of schemaProperties(); track property.value) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"lib-pipeline-generator__suggestion\"\n (click)=\"selectSuggestion(property.value)\">\n {{ property.label }}\n </button>\n }\n </div>\n </section>\n }\n </div>\n </mat-expansion-panel>\n </mat-accordion>\n}\n\n<ng-template cdkConnectedOverlay [cdkConnectedOverlayOpen]=\"disabled\">\n <div class=\"lib-pipeline-generator__scrim\"></div>\n</ng-template>\n"],"names":["i2","i4","i5","i7","i1","i3","i6","i8"],"mappings":"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"}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import * as i4 from '@angular/cdk/portal';
|
|
2
|
+
import { ComponentPortal, PortalModule } from '@angular/cdk/portal';
|
|
3
|
+
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
4
|
+
import * as i0 from '@angular/core';
|
|
5
|
+
import { inject, ElementRef, DestroyRef, signal, input, output, computed, effect, Input, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
6
|
+
import { outputToObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
7
|
+
import { NgControl } from '@angular/forms';
|
|
8
|
+
import * as i1 from '@angular/material/button';
|
|
9
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
10
|
+
import { MatCardModule } from '@angular/material/card';
|
|
11
|
+
import { MatDividerModule } from '@angular/material/divider';
|
|
12
|
+
import * as i5 from '@angular/material/expansion';
|
|
13
|
+
import { MatExpansionModule } from '@angular/material/expansion';
|
|
14
|
+
import { MatFormFieldControl } from '@angular/material/form-field';
|
|
15
|
+
import * as i3 from '@angular/material/icon';
|
|
16
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
17
|
+
import * as i3$1 from '@angular/material/progress-spinner';
|
|
18
|
+
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
19
|
+
import * as i5$1 from '@angular/material/table';
|
|
20
|
+
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
|
21
|
+
import * as i5$2 from '@angular/material/tooltip';
|
|
22
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
23
|
+
import { Subject } from 'rxjs';
|
|
24
|
+
import { k as NESTED_EDITOR_COMPONENT, s as safeReturnDeepProperty, _ as _isEqual, a as assignDeepPropertyToObject, E as EmptyStateComponent } from './ngx-t-forms-ngx-t-forms-u_kigDid.mjs';
|
|
25
|
+
|
|
26
|
+
/** Synthetic column key for the per-row edit/delete action cell. */
|
|
27
|
+
const ACTIONS_COLUMN = 'actions';
|
|
28
|
+
/**
|
|
29
|
+
* Internal record-list manager. Implements `MatFormFieldControl<unknown[]>` and is
|
|
30
|
+
* embedded by `t-dynamic-data-edit` for `RecordListManager` editor types.
|
|
31
|
+
*
|
|
32
|
+
* Owns only its content (table + edit panel). The parent `mat-form-field` renders
|
|
33
|
+
* the label, hint, and validation errors, so this component adds neither a header
|
|
34
|
+
* nor an inline error list.
|
|
35
|
+
*
|
|
36
|
+
* Per-record editing is delegated to a dynamically-attached `TDynamicDataEditComponent`
|
|
37
|
+
* portal per inner-section element; the portal's `valueChange` output is patched back
|
|
38
|
+
* into the in-edit buffer via the element's `deepBind` path.
|
|
39
|
+
*
|
|
40
|
+
* NOTE: `MatFormFieldControl<T>` mandates plain mutable `value` / `disabled` /
|
|
41
|
+
* `required` / `placeholder` / `id` members, `@Input()` decorators, the
|
|
42
|
+
* `focused` / `touched` / `stateChanges` members, and the `useExisting` provider.
|
|
43
|
+
* These are framework wiring, not defects — the CLAUDE.md bans on `@Input()` /
|
|
44
|
+
* `useExisting` do not apply to MatFormFieldControl integration.
|
|
45
|
+
*
|
|
46
|
+
* @internal Not exported via public-api.ts.
|
|
47
|
+
*/
|
|
48
|
+
class RecordListManagerComponent {
|
|
49
|
+
static { this.nextId = 0; }
|
|
50
|
+
#disabled;
|
|
51
|
+
get disabled() {
|
|
52
|
+
return this.#disabled;
|
|
53
|
+
}
|
|
54
|
+
set disabled(value) {
|
|
55
|
+
this.#disabled = coerceBooleanProperty(value);
|
|
56
|
+
this.stateChanges.next();
|
|
57
|
+
}
|
|
58
|
+
#required;
|
|
59
|
+
get required() {
|
|
60
|
+
return this.#required;
|
|
61
|
+
}
|
|
62
|
+
set required(value) {
|
|
63
|
+
this.#required = coerceBooleanProperty(value);
|
|
64
|
+
this.stateChanges.next();
|
|
65
|
+
}
|
|
66
|
+
#placeholder;
|
|
67
|
+
get placeholder() {
|
|
68
|
+
return this.#placeholder;
|
|
69
|
+
}
|
|
70
|
+
set placeholder(value) {
|
|
71
|
+
this.#placeholder = value;
|
|
72
|
+
this.stateChanges.next();
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Record rows held by the table. Parent passes heterogeneous payloads
|
|
76
|
+
* (`{}` initial / arrays / null); non-array writes coerce to an empty list.
|
|
77
|
+
*/
|
|
78
|
+
get value() {
|
|
79
|
+
return this.#rows();
|
|
80
|
+
}
|
|
81
|
+
set value(val) {
|
|
82
|
+
const next = Array.isArray(val) ? val : [];
|
|
83
|
+
this.#rows.set(next);
|
|
84
|
+
this.onChange(next);
|
|
85
|
+
this.stateChanges.next();
|
|
86
|
+
}
|
|
87
|
+
get shouldLabelFloat() {
|
|
88
|
+
return this.focused || !this.empty;
|
|
89
|
+
}
|
|
90
|
+
get empty() {
|
|
91
|
+
return this.#rows().length === 0;
|
|
92
|
+
}
|
|
93
|
+
get errorState() {
|
|
94
|
+
const requiredUnset = this.empty && this.#required && this.touched;
|
|
95
|
+
const ngControlError = this.ngControl?.errors != null;
|
|
96
|
+
const externalError = (this.errors?.length ?? 0) > 0;
|
|
97
|
+
return requiredUnset || ngControlError || externalError;
|
|
98
|
+
}
|
|
99
|
+
#elementRef;
|
|
100
|
+
#destroyRef;
|
|
101
|
+
/** The component portalled per record — injected to avoid a circular import. */
|
|
102
|
+
#nestedEditor;
|
|
103
|
+
constructor() {
|
|
104
|
+
// --- MatFormFieldControl wiring (plain mutable members, framework-mandated) ---
|
|
105
|
+
this.stateChanges = new Subject();
|
|
106
|
+
this.controlType = 'lib-record-list-manager';
|
|
107
|
+
this.focused = false;
|
|
108
|
+
this.touched = false;
|
|
109
|
+
this.autofilled = false;
|
|
110
|
+
this.id = `lib-record-list-manager-${RecordListManagerComponent.nextId++}`;
|
|
111
|
+
this.describedBy = '';
|
|
112
|
+
/** Validation errors surfaced by the parent for error-state derivation. */
|
|
113
|
+
this.errors = [];
|
|
114
|
+
this.#disabled = false;
|
|
115
|
+
this.#required = false;
|
|
116
|
+
this.#placeholder = '';
|
|
117
|
+
// --- DI ---
|
|
118
|
+
this.ngControl = inject(NgControl, { self: true, optional: true });
|
|
119
|
+
this.#elementRef = inject(ElementRef);
|
|
120
|
+
this.#destroyRef = inject(DestroyRef);
|
|
121
|
+
/** The component portalled per record — injected to avoid a circular import. */
|
|
122
|
+
this.#nestedEditor = inject(NESTED_EDITOR_COMPONENT);
|
|
123
|
+
// --- ControlValueAccessor ---
|
|
124
|
+
this.onChange = () => {
|
|
125
|
+
/* noop until registered */
|
|
126
|
+
};
|
|
127
|
+
this.onTouched = () => {
|
|
128
|
+
/* noop until registered */
|
|
129
|
+
};
|
|
130
|
+
// --- Internal reactive state (signal-first) ---
|
|
131
|
+
/** Backing rows; the `MatTableDataSource` is kept in sync via an effect. */
|
|
132
|
+
this.#rows = signal([], ...(ngDevMode ? [{ debugName: "#rows" }] : /* istanbul ignore next */ []));
|
|
133
|
+
/** Table data source whose `.data` mirrors `#rows()`. */
|
|
134
|
+
this.dataSource = new MatTableDataSource([]);
|
|
135
|
+
/** Row currently being edited, or `null` when no edit is in progress. */
|
|
136
|
+
this.#inEdit = signal(null, ...(ngDevMode ? [{ debugName: "#inEdit" }] : /* istanbul ignore next */ []));
|
|
137
|
+
/** Inner editor sections derived from the active editor config. */
|
|
138
|
+
this.#sections = signal([], ...(ngDevMode ? [{ debugName: "#sections" }] : /* istanbul ignore next */ []));
|
|
139
|
+
/** Lazily-built portals keyed by inner-section element id. */
|
|
140
|
+
this.#portals = signal({}, ...(ngDevMode ? [{ debugName: "#portals" }] : /* istanbul ignore next */ []));
|
|
141
|
+
/** Active per-element portal output subscriptions, keyed by element id. */
|
|
142
|
+
this.#portalSubscriptions = new Map();
|
|
143
|
+
/** Form input definitions forwarded into the dynamic editor portals. */
|
|
144
|
+
this.formInputs = input([], ...(ngDevMode ? [{ debugName: "formInputs" }] : /* istanbul ignore next */ []));
|
|
145
|
+
/** Editor configuration for this record-list element. */
|
|
146
|
+
this.editorConfig = input(undefined, ...(ngDevMode ? [{ debugName: "editorConfig" }] : /* istanbul ignore next */ []));
|
|
147
|
+
/** Emits whenever the record list value changes. */
|
|
148
|
+
this.valueChange = output();
|
|
149
|
+
// --- Template-facing derived state ---
|
|
150
|
+
this.inEditRow = this.#inEdit.asReadonly();
|
|
151
|
+
this.sections = this.#sections.asReadonly();
|
|
152
|
+
this.portals = this.#portals.asReadonly();
|
|
153
|
+
this.tableColumns = computed(() => [
|
|
154
|
+
...(this.editorConfig()?.options ?? []).map((opt) => ({
|
|
155
|
+
label: String(opt.label),
|
|
156
|
+
value: String(opt.value),
|
|
157
|
+
})),
|
|
158
|
+
{ label: ' ', value: ACTIONS_COLUMN },
|
|
159
|
+
], ...(ngDevMode ? [{ debugName: "tableColumns" }] : /* istanbul ignore next */ []));
|
|
160
|
+
this.displayedColumns = computed(() => this.tableColumns().map((c) => c.value), ...(ngDevMode ? [{ debugName: "displayedColumns" }] : /* istanbul ignore next */ []));
|
|
161
|
+
this.rowCount = computed(() => this.#rows().length, ...(ngDevMode ? [{ debugName: "rowCount" }] : /* istanbul ignore next */ []));
|
|
162
|
+
this.isActionsColumn = (column) => column === ACTIONS_COLUMN;
|
|
163
|
+
/**
|
|
164
|
+
* Whether the in-edit record may be saved: every `required` inner element must
|
|
165
|
+
* resolve to a non-empty value via its `deepBind` path.
|
|
166
|
+
*/
|
|
167
|
+
this.canSaveRecord = computed(() => {
|
|
168
|
+
const editing = this.#inEdit();
|
|
169
|
+
if (!editing || !this.editorConfig()) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
for (const section of this.#sections()) {
|
|
173
|
+
for (const element of section.elements) {
|
|
174
|
+
if (!element.required) {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const { value } = safeReturnDeepProperty(editing, element.deepBind ?? []);
|
|
178
|
+
if (value == null || value === '') {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
}, ...(ngDevMode ? [{ debugName: "canSaveRecord" }] : /* istanbul ignore next */ []));
|
|
185
|
+
// --- Effects (framework-state sync, not signal writes within) ---
|
|
186
|
+
/** Mirror the rows signal into the Material table data source. */
|
|
187
|
+
this.tableSync = effect(() => {
|
|
188
|
+
this.dataSource.data = this.#rows();
|
|
189
|
+
}, ...(ngDevMode ? [{ debugName: "tableSync" }] : /* istanbul ignore next */ []));
|
|
190
|
+
/**
|
|
191
|
+
* Rebuild the inner-section list and portal map whenever the editor config
|
|
192
|
+
* changes. Portals are recreated per config so a stale `ComponentPortal`
|
|
193
|
+
* (already attached) is never re-used.
|
|
194
|
+
*/
|
|
195
|
+
this.configSync = effect(() => {
|
|
196
|
+
const next = this.editorConfig()?.secondaryElementEditorConfig ?? [];
|
|
197
|
+
if (_isEqual(this.#sections(), next)) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
this.#teardownPortalSubscriptions();
|
|
201
|
+
this.#sections.set(next);
|
|
202
|
+
const portals = {};
|
|
203
|
+
for (const section of next) {
|
|
204
|
+
for (const element of section.elements) {
|
|
205
|
+
portals[element.id] = new ComponentPortal(this.#nestedEditor);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
this.#portals.set(portals);
|
|
209
|
+
}, ...(ngDevMode ? [{ debugName: "configSync" }] : /* istanbul ignore next */ []));
|
|
210
|
+
if (this.ngControl != null) {
|
|
211
|
+
this.ngControl.valueAccessor = this;
|
|
212
|
+
}
|
|
213
|
+
this.#destroyRef.onDestroy(() => {
|
|
214
|
+
this.stateChanges.complete();
|
|
215
|
+
this.#teardownPortalSubscriptions();
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
writeValue(value) {
|
|
219
|
+
this.#rows.set(Array.isArray(value) ? value : []);
|
|
220
|
+
this.stateChanges.next();
|
|
221
|
+
}
|
|
222
|
+
registerOnChange(fn) {
|
|
223
|
+
this.onChange = fn;
|
|
224
|
+
}
|
|
225
|
+
registerOnTouched(fn) {
|
|
226
|
+
this.onTouched = fn;
|
|
227
|
+
}
|
|
228
|
+
setDisabledState(isDisabled) {
|
|
229
|
+
this.disabled = isDisabled;
|
|
230
|
+
}
|
|
231
|
+
setDescribedByIds(ids) {
|
|
232
|
+
this.describedBy = ids.join(' ');
|
|
233
|
+
this.#elementRef.nativeElement.setAttribute('aria-describedby', this.describedBy);
|
|
234
|
+
this.stateChanges.next();
|
|
235
|
+
}
|
|
236
|
+
onContainerClick() {
|
|
237
|
+
this.markAsTouched();
|
|
238
|
+
if (!this.focused) {
|
|
239
|
+
this.focused = true;
|
|
240
|
+
this.stateChanges.next();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
markAsTouched() {
|
|
244
|
+
if (!this.touched) {
|
|
245
|
+
this.touched = true;
|
|
246
|
+
this.onTouched();
|
|
247
|
+
this.stateChanges.next();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// --- Internal reactive state (signal-first) ---
|
|
251
|
+
/** Backing rows; the `MatTableDataSource` is kept in sync via an effect. */
|
|
252
|
+
#rows;
|
|
253
|
+
/** Row currently being edited, or `null` when no edit is in progress. */
|
|
254
|
+
#inEdit;
|
|
255
|
+
/** Inner editor sections derived from the active editor config. */
|
|
256
|
+
#sections;
|
|
257
|
+
/** Lazily-built portals keyed by inner-section element id. */
|
|
258
|
+
#portals;
|
|
259
|
+
/** Active per-element portal output subscriptions, keyed by element id. */
|
|
260
|
+
#portalSubscriptions;
|
|
261
|
+
// --- Record actions ---
|
|
262
|
+
addNewItem() {
|
|
263
|
+
this.#inEdit.set({});
|
|
264
|
+
}
|
|
265
|
+
editItem(row) {
|
|
266
|
+
this.#inEdit.set(row);
|
|
267
|
+
}
|
|
268
|
+
cancelEdit() {
|
|
269
|
+
this.#inEdit.set(null);
|
|
270
|
+
}
|
|
271
|
+
saveRecord() {
|
|
272
|
+
const editing = this.#inEdit();
|
|
273
|
+
if (!editing) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
let next;
|
|
277
|
+
if (editing.id != null) {
|
|
278
|
+
next = this.value.map((item) => (item.id === editing.id ? editing : item));
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
next = [...this.value, { ...editing, id: crypto.randomUUID() }];
|
|
282
|
+
}
|
|
283
|
+
this.value = next;
|
|
284
|
+
this.#inEdit.set(null);
|
|
285
|
+
this.valueChange.emit(this.value);
|
|
286
|
+
}
|
|
287
|
+
removeItem(item) {
|
|
288
|
+
this.value = this.value.filter((row) => row.id !== item.id);
|
|
289
|
+
if (this.#inEdit()?.id === item.id) {
|
|
290
|
+
this.#inEdit.set(null);
|
|
291
|
+
}
|
|
292
|
+
this.valueChange.emit(this.value);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Wire a freshly-attached per-record editor portal: push the current inputs in,
|
|
296
|
+
* and patch the in-edit buffer whenever the inner editor emits a value. The
|
|
297
|
+
* subscription is keyed by element id and torn down on config change / destroy.
|
|
298
|
+
*/
|
|
299
|
+
onPortalAttached(portalRef, element) {
|
|
300
|
+
const componentRef = portalRef;
|
|
301
|
+
componentRef.setInput('formInputs', this.formInputs());
|
|
302
|
+
componentRef.setInput('editorConfig', element);
|
|
303
|
+
componentRef.setInput('data', this.#inEdit());
|
|
304
|
+
this.#portalSubscriptions.get(element.id)?.unsubscribe();
|
|
305
|
+
const sub = outputToObservable(componentRef.instance.valueChange)
|
|
306
|
+
.pipe(takeUntilDestroyed(this.#destroyRef))
|
|
307
|
+
.subscribe((event) => {
|
|
308
|
+
const current = this.#inEdit();
|
|
309
|
+
const draft = (current ? structuredClone(current) : {});
|
|
310
|
+
const patched = assignDeepPropertyToObject(draft, element.deepBind ?? [], event);
|
|
311
|
+
this.#inEdit.set(patched);
|
|
312
|
+
componentRef.setInput('data', patched);
|
|
313
|
+
componentRef.changeDetectorRef.markForCheck();
|
|
314
|
+
});
|
|
315
|
+
this.#portalSubscriptions.set(element.id, sub);
|
|
316
|
+
}
|
|
317
|
+
#teardownPortalSubscriptions() {
|
|
318
|
+
this.#portalSubscriptions.forEach((sub) => sub.unsubscribe());
|
|
319
|
+
this.#portalSubscriptions.clear();
|
|
320
|
+
}
|
|
321
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: RecordListManagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
322
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: RecordListManagerComponent, isStandalone: true, selector: "lib-record-list-manager", inputs: { mapToData: { classPropertyName: "mapToData", publicName: "mapToData", isSignal: false, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: false, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: false, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: false, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null }, formInputs: { classPropertyName: "formInputs", publicName: "formInputs", isSignal: true, isRequired: false, transformFunction: null }, editorConfig: { classPropertyName: "editorConfig", publicName: "editorConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { properties: { "id": "id", "attr.aria-describedby": "describedBy", "class.lib-record-list-manager--floating": "shouldLabelFloat" }, classAttribute: "lib-record-list-manager" }, providers: [{ provide: MatFormFieldControl, useExisting: RecordListManagerComponent }], ngImport: i0, template: "<div class=\"lib-record-list-manager__table\">\n <table mat-table [dataSource]=\"dataSource\" class=\"lib-record-list-manager__grid\">\n @for (col of tableColumns(); track col.value) {\n <ng-container [matColumnDef]=\"col.value\">\n <th mat-header-cell *matHeaderCellDef>{{ col.label }}</th>\n <td mat-cell *matCellDef=\"let row\" class=\"lib-record-list-manager__cell\">\n @if (isActionsColumn(col.value)) {\n <button\n type=\"button\"\n mat-icon-button\n matTooltip=\"Edit\"\n aria-label=\"Edit record\"\n [disabled]=\"disabled\"\n (click)=\"editItem(row)\"\n >\n <mat-icon>edit</mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n color=\"warn\"\n matTooltip=\"Delete\"\n aria-label=\"Delete record\"\n [disabled]=\"disabled\"\n (click)=\"removeItem(row)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n } @else {\n {{ row[col.value] }}\n }\n </td>\n </ng-container>\n }\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns()\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns()\"\n class=\"lib-record-list-manager__row\"\n ></tr>\n </table>\n\n @if (rowCount() === 0) {\n <lib-empty-state\n icon=\"inbox\"\n message=\"No records yet. Use Add Record to get started.\"\n ></lib-empty-state>\n }\n</div>\n\n@if (inEditRow(); as editing) {\n <div class=\"lib-record-list-manager__editor\">\n <mat-accordion class=\"lib-record-list-manager__sections\" togglePosition=\"after\">\n @for (section of sections(); track section.id) {\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title class=\"lib-record-list-manager__section-title\">\n <span>{{ section.label }}</span>\n @if (section.showItemValue && editing[section.showItemValue] != null) {\n <span class=\"lib-record-list-manager__section-value\">\n {{ editing[section.showItemValue] }}\n </span>\n }\n </mat-panel-title>\n </mat-expansion-panel-header>\n\n @for (element of section.elements; track element.id) {\n <div class=\"lib-record-list-manager__field\">\n @defer (on viewport) {\n <ng-template\n [cdkPortalOutlet]=\"portals()[element.id]\"\n (attached)=\"onPortalAttached($event, element)\"\n ></ng-template>\n } @placeholder {\n <div class=\"lib-record-list-manager__loading\">\n <mat-spinner diameter=\"18\"></mat-spinner>\n </div>\n }\n </div>\n }\n </mat-expansion-panel>\n }\n </mat-accordion>\n\n <div class=\"lib-record-list-manager__actions\">\n <button type=\"button\" mat-button color=\"primary\" (click)=\"cancelEdit()\">Cancel</button>\n <button\n type=\"button\"\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!canSaveRecord()\"\n (click)=\"saveRecord()\"\n >\n {{ editing.id ? 'Update' : 'Save new' }} record\n <mat-icon>save</mat-icon>\n </button>\n </div>\n </div>\n} @else {\n <div class=\"lib-record-list-manager__actions lib-record-list-manager__actions--list\">\n <span class=\"lib-record-list-manager__count\">Records ({{ rowCount() }})</span>\n <button\n type=\"button\"\n mat-stroked-button\n color=\"primary\"\n matTooltip=\"Add a new record\"\n aria-label=\"Add a new record\"\n [disabled]=\"disabled\"\n (click)=\"addNewItem()\"\n >\n <mat-icon>add</mat-icon>\n Add Record\n </button>\n </div>\n}\n", styles: [":host{display:block}.lib-record-list-manager__table{background:var(--lib-forms-surface);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 15%,transparent);border-radius:var(--lib-forms-radius-lg, 12px);box-shadow:var(--lib-forms-shadow-resting);overflow:hidden}.lib-record-list-manager__grid{width:100%;background:transparent}.lib-record-list-manager__row{transition:background-color var(--lib-forms-duration-hover) var(--lib-forms-easing)}.lib-record-list-manager__row:hover{background:color-mix(in srgb,var(--lib-forms-primary) 6%,transparent)}.lib-record-list-manager__cell{color:var(--lib-forms-on-surface)}.mat-column-actions{width:6rem;max-width:6rem;padding-right:.5rem;text-align:right;white-space:nowrap}.lib-record-list-manager__editor{margin-top:1.5rem;display:flex;flex-direction:column;gap:1.5rem}.lib-record-list-manager__sections{display:block}.lib-record-list-manager__section-title{display:flex;align-items:center;gap:.75rem;width:100%}.lib-record-list-manager__section-value{margin-left:auto;font-size:.8125rem;color:var(--lib-forms-on-surface-variant)}.lib-record-list-manager__field{padding:.5rem 0 1.5rem}.lib-record-list-manager__loading{display:flex;align-items:center;justify-content:center;padding:2rem}.lib-record-list-manager__actions{display:flex;align-items:center;justify-content:flex-end;gap:.75rem}.lib-record-list-manager__actions--list{margin-top:1.5rem}.lib-record-list-manager__count{margin-right:auto;font-size:.8125rem;color:var(--lib-forms-on-surface-variant)}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i5.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i5.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i5.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i5.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i3$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i5$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i5$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i5$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i5$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i5$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i5$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i5$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i5$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i5$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i5$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: PortalModule }, { kind: "component", type: EmptyStateComponent, selector: "lib-empty-state", inputs: ["icon", "message"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [i4.CdkPortalOutlet]] }); }
|
|
323
|
+
}
|
|
324
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: RecordListManagerComponent, decorators: [{
|
|
325
|
+
type: Component,
|
|
326
|
+
args: [{ selector: 'lib-record-list-manager', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, imports: [
|
|
327
|
+
MatButtonModule,
|
|
328
|
+
MatCardModule,
|
|
329
|
+
MatDividerModule,
|
|
330
|
+
MatExpansionModule,
|
|
331
|
+
MatIconModule,
|
|
332
|
+
MatProgressSpinnerModule,
|
|
333
|
+
MatTableModule,
|
|
334
|
+
MatTooltipModule,
|
|
335
|
+
PortalModule,
|
|
336
|
+
EmptyStateComponent,
|
|
337
|
+
], providers: [{ provide: MatFormFieldControl, useExisting: RecordListManagerComponent }], host: {
|
|
338
|
+
'class': 'lib-record-list-manager',
|
|
339
|
+
'[id]': 'id',
|
|
340
|
+
'[attr.aria-describedby]': 'describedBy',
|
|
341
|
+
'[class.lib-record-list-manager--floating]': 'shouldLabelFloat',
|
|
342
|
+
}, template: "<div class=\"lib-record-list-manager__table\">\n <table mat-table [dataSource]=\"dataSource\" class=\"lib-record-list-manager__grid\">\n @for (col of tableColumns(); track col.value) {\n <ng-container [matColumnDef]=\"col.value\">\n <th mat-header-cell *matHeaderCellDef>{{ col.label }}</th>\n <td mat-cell *matCellDef=\"let row\" class=\"lib-record-list-manager__cell\">\n @if (isActionsColumn(col.value)) {\n <button\n type=\"button\"\n mat-icon-button\n matTooltip=\"Edit\"\n aria-label=\"Edit record\"\n [disabled]=\"disabled\"\n (click)=\"editItem(row)\"\n >\n <mat-icon>edit</mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n color=\"warn\"\n matTooltip=\"Delete\"\n aria-label=\"Delete record\"\n [disabled]=\"disabled\"\n (click)=\"removeItem(row)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n } @else {\n {{ row[col.value] }}\n }\n </td>\n </ng-container>\n }\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns()\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns()\"\n class=\"lib-record-list-manager__row\"\n ></tr>\n </table>\n\n @if (rowCount() === 0) {\n <lib-empty-state\n icon=\"inbox\"\n message=\"No records yet. Use Add Record to get started.\"\n ></lib-empty-state>\n }\n</div>\n\n@if (inEditRow(); as editing) {\n <div class=\"lib-record-list-manager__editor\">\n <mat-accordion class=\"lib-record-list-manager__sections\" togglePosition=\"after\">\n @for (section of sections(); track section.id) {\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title class=\"lib-record-list-manager__section-title\">\n <span>{{ section.label }}</span>\n @if (section.showItemValue && editing[section.showItemValue] != null) {\n <span class=\"lib-record-list-manager__section-value\">\n {{ editing[section.showItemValue] }}\n </span>\n }\n </mat-panel-title>\n </mat-expansion-panel-header>\n\n @for (element of section.elements; track element.id) {\n <div class=\"lib-record-list-manager__field\">\n @defer (on viewport) {\n <ng-template\n [cdkPortalOutlet]=\"portals()[element.id]\"\n (attached)=\"onPortalAttached($event, element)\"\n ></ng-template>\n } @placeholder {\n <div class=\"lib-record-list-manager__loading\">\n <mat-spinner diameter=\"18\"></mat-spinner>\n </div>\n }\n </div>\n }\n </mat-expansion-panel>\n }\n </mat-accordion>\n\n <div class=\"lib-record-list-manager__actions\">\n <button type=\"button\" mat-button color=\"primary\" (click)=\"cancelEdit()\">Cancel</button>\n <button\n type=\"button\"\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!canSaveRecord()\"\n (click)=\"saveRecord()\"\n >\n {{ editing.id ? 'Update' : 'Save new' }} record\n <mat-icon>save</mat-icon>\n </button>\n </div>\n </div>\n} @else {\n <div class=\"lib-record-list-manager__actions lib-record-list-manager__actions--list\">\n <span class=\"lib-record-list-manager__count\">Records ({{ rowCount() }})</span>\n <button\n type=\"button\"\n mat-stroked-button\n color=\"primary\"\n matTooltip=\"Add a new record\"\n aria-label=\"Add a new record\"\n [disabled]=\"disabled\"\n (click)=\"addNewItem()\"\n >\n <mat-icon>add</mat-icon>\n Add Record\n </button>\n </div>\n}\n", styles: [":host{display:block}.lib-record-list-manager__table{background:var(--lib-forms-surface);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 15%,transparent);border-radius:var(--lib-forms-radius-lg, 12px);box-shadow:var(--lib-forms-shadow-resting);overflow:hidden}.lib-record-list-manager__grid{width:100%;background:transparent}.lib-record-list-manager__row{transition:background-color var(--lib-forms-duration-hover) var(--lib-forms-easing)}.lib-record-list-manager__row:hover{background:color-mix(in srgb,var(--lib-forms-primary) 6%,transparent)}.lib-record-list-manager__cell{color:var(--lib-forms-on-surface)}.mat-column-actions{width:6rem;max-width:6rem;padding-right:.5rem;text-align:right;white-space:nowrap}.lib-record-list-manager__editor{margin-top:1.5rem;display:flex;flex-direction:column;gap:1.5rem}.lib-record-list-manager__sections{display:block}.lib-record-list-manager__section-title{display:flex;align-items:center;gap:.75rem;width:100%}.lib-record-list-manager__section-value{margin-left:auto;font-size:.8125rem;color:var(--lib-forms-on-surface-variant)}.lib-record-list-manager__field{padding:.5rem 0 1.5rem}.lib-record-list-manager__loading{display:flex;align-items:center;justify-content:center;padding:2rem}.lib-record-list-manager__actions{display:flex;align-items:center;justify-content:flex-end;gap:.75rem}.lib-record-list-manager__actions--list{margin-top:1.5rem}.lib-record-list-manager__count{margin-right:auto;font-size:.8125rem;color:var(--lib-forms-on-surface-variant)}\n"] }]
|
|
343
|
+
}], ctorParameters: () => [], propDecorators: { mapToData: [{
|
|
344
|
+
type: Input
|
|
345
|
+
}], errors: [{
|
|
346
|
+
type: Input
|
|
347
|
+
}], disabled: [{
|
|
348
|
+
type: Input
|
|
349
|
+
}], required: [{
|
|
350
|
+
type: Input
|
|
351
|
+
}], placeholder: [{
|
|
352
|
+
type: Input
|
|
353
|
+
}], value: [{
|
|
354
|
+
type: Input
|
|
355
|
+
}], formInputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "formInputs", required: false }] }], editorConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "editorConfig", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
356
|
+
|
|
357
|
+
export { RecordListManagerComponent };
|
|
358
|
+
//# sourceMappingURL=ngx-t-forms-record-list-manager.component-CUMMvMch.mjs.map
|