@memberjunction/ng-dashboards 5.38.0 → 5.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -7
- package/dist/AI/components/agents/agent-configuration.component.js +199 -198
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.js +20 -17
- package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +15 -0
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js +166 -58
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js +2 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js.map +1 -1
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts +1 -0
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/model-performance/model-performance.component.js +55 -36
- package/dist/AI/components/analytics/model-performance/model-performance.component.js.map +1 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts +9 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +158 -117
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js.map +1 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts +1 -0
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +22 -8
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +217 -860
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +1717 -7802
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts +56 -0
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js +423 -0
- package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts +70 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.js +308 -0
- package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts +29 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +186 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts +69 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js +278 -0
- package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js.map +1 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts +73 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js +393 -0
- package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts +122 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js +908 -0
- package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts +87 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js +475 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts +29 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js +208 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts +21 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js +70 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts +333 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +2125 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts +61 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.js +78 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.format.d.ts +58 -0
- package/dist/AI/components/autotagging/shared/classify.format.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.format.js +260 -0
- package/dist/AI/components/autotagging/shared/classify.format.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.types.d.ts +319 -0
- package/dist/AI/components/autotagging/shared/classify.types.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.types.js +6 -0
- package/dist/AI/components/autotagging/shared/classify.types.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts +103 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.js +571 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts +77 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.js +519 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts +107 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.js +719 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts +131 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js +813 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +177 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1465 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts +78 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.js +492 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts +397 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js +3490 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts +56 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.js +271 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.js.map +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +3 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +306 -290
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +1 -1
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +209 -208
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +130 -128
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/requests/agent-requests-resource.component.js +61 -61
- package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +17 -17
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts +1 -0
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +578 -538
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +3 -0
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +331 -303
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.d.ts +5 -0
- package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.js +14 -2
- package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
- package/dist/AI/services/cache-metrics.d.ts +50 -0
- package/dist/AI/services/cache-metrics.d.ts.map +1 -0
- package/dist/AI/services/cache-metrics.js +43 -0
- package/dist/AI/services/cache-metrics.js.map +1 -0
- package/dist/APIKeys/api-applications-panel.component.js +2 -2
- package/dist/APIKeys/api-key-create-dialog.component.js +2 -2
- package/dist/APIKeys/api-key-edit-panel.component.js +2 -2
- package/dist/APIKeys/api-keys-resource.component.js +132 -131
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +141 -141
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +15 -15
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.d.ts +0 -5
- package/dist/Actions/components/explorer/action-explorer.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +139 -212
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Admin/admin-data-schema.component.js +2 -2
- package/dist/Admin/admin-data-schema.component.js.map +1 -1
- package/dist/Admin/admin-dev-tools-resource.component.js +2 -2
- package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
- package/dist/Admin/admin-identity-access.component.js +2 -2
- package/dist/Admin/admin-identity-access.component.js.map +1 -1
- package/dist/Admin/admin-monitoring.component.js +2 -2
- package/dist/Admin/admin-monitoring.component.js.map +1 -1
- package/dist/ApplicationRoles/application-roles-resource.component.js +54 -49
- package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
- package/dist/Communication/communication-logs-resource.component.d.ts +6 -0
- package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-logs-resource.component.js +72 -50
- package/dist/Communication/communication-logs-resource.component.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +103 -102
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-providers-resource.component.js +52 -51
- package/dist/Communication/communication-providers-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +39 -38
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.d.ts +6 -0
- package/dist/Communication/communication-templates-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js +92 -89
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.js +136 -135
- package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +155 -152
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +119 -118
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +129 -128
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +107 -106
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +31 -340
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +468 -1958
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.js +10 -0
- package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +1 -1
- package/dist/DatabaseDesigner/components/entity-list.component.js +115 -114
- package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +5 -6
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js +4 -5
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
- package/dist/DevTools/app-state-inspector.component.js +18 -17
- package/dist/DevTools/app-state-inspector.component.js.map +1 -1
- package/dist/DevTools/class-registry.component.js +88 -85
- package/dist/DevTools/class-registry.component.js.map +1 -1
- package/dist/DevTools/event-monitor.component.js +155 -150
- package/dist/DevTools/event-monitor.component.js.map +1 -1
- package/dist/DevTools/graphql-console.component.js +245 -243
- package/dist/DevTools/graphql-console.component.js.map +1 -1
- package/dist/DevTools/layout-inspector.component.js +18 -17
- package/dist/DevTools/layout-inspector.component.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +20 -19
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.js +2 -2
- package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
- package/dist/Integration/components/activity/activity.component.js +236 -229
- package/dist/Integration/components/activity/activity.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +390 -389
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/overview/overview.component.js +2 -2
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +14 -11
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +27 -2
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +244 -119
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +293 -291
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +62 -61
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts +65 -0
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js +176 -0
- package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js.map +1 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts +81 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js +308 -0
- package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js.map +1 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts +85 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts.map +1 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js +362 -0
- package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js.map +1 -0
- package/dist/KnowledgeHub/index.d.ts +3 -0
- package/dist/KnowledgeHub/index.d.ts.map +1 -1
- package/dist/KnowledgeHub/index.js +3 -0
- package/dist/KnowledgeHub/index.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.d.ts +6 -2
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +525 -566
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +135 -134
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +199 -198
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.js +2 -2
- package/dist/MCP/mcp-dashboard.component.js +443 -438
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.js +146 -147
- package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js +76 -75
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js +97 -96
- package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js +24 -22
- package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts +2 -0
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js +1 -0
- package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.js +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts +14 -4
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +436 -427
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-runs-resource.component.js +1 -1
- package/dist/Testing/components/testing-runs.component.js +116 -115
- package/dist/Testing/components/testing-runs.component.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +6 -7
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.js +173 -172
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.d.ts +6 -0
- package/dist/VersionHistory/components/restore-resource.component.d.ts.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.js +116 -92
- package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +57 -35
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +80 -1
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/communication-dashboards.module.d.ts +1 -1
- package/dist/communication-dashboards.module.d.ts.map +1 -1
- package/dist/communication-dashboards.module.js +7 -1
- package/dist/communication-dashboards.module.js.map +1 -1
- package/dist/data-explorer-dashboards.module.d.ts +12 -14
- package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
- package/dist/data-explorer-dashboards.module.js +5 -14
- package/dist/data-explorer-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +3 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +3 -0
- package/dist/public-api.js.map +1 -1
- package/dist/testing-dashboards.module.d.ts +4 -5
- package/dist/testing-dashboards.module.d.ts.map +1 -1
- package/dist/testing-dashboards.module.js +7 -5
- package/dist/testing-dashboards.module.js.map +1 -1
- package/package.json +57 -54
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts +0 -79
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts.map +0 -1
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +0 -195
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +0 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts +0 -226
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +0 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.js +0 -861
- package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +0 -1
|
@@ -0,0 +1,2125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Classify · Source + Content Type CRUD slide-in form dialog.
|
|
3
|
+
*
|
|
4
|
+
* Owns the entire add/edit slide-in form for BOTH content sources and content
|
|
5
|
+
* types (the form renders one or the other depending on `FormMode`). Extracted
|
|
6
|
+
* from the host monolith: the dialog owns ALL form state, the dropdown option
|
|
7
|
+
* getters, the dynamic source-type field logic, and the open / populate / save /
|
|
8
|
+
* close lifecycle. It reads cached reference metadata directly from
|
|
9
|
+
* `KnowledgeHubMetadataEngine.Instance` / `AIEngineBase.Instance` (same as the
|
|
10
|
+
* host did) and persists via the threaded provider.
|
|
11
|
+
*
|
|
12
|
+
* Contract with the host (data orchestrator):
|
|
13
|
+
* - The host calls the public `OpenAddSource()` / `OpenEditSource(card)` /
|
|
14
|
+
* `OpenAddType()` / `OpenEditType(card)` methods via `@ViewChild` in response
|
|
15
|
+
* to the Sources/Types tabs' add/edit events.
|
|
16
|
+
* - After a successful save the dialog closes itself and emits `(Saved)` with
|
|
17
|
+
* `{ kind: 'source' | 'type' }` so the host reloads the right shared data.
|
|
18
|
+
* - When a source save is blocked because no content type exists, it emits
|
|
19
|
+
* `(ContentTypeMissing)` so the host shows its no-content-type warning.
|
|
20
|
+
* - "Open advanced settings" navigates to the full entity form via the host's
|
|
21
|
+
* NavigationService through the `(NavigateToRecordRequested)` output.
|
|
22
|
+
*/
|
|
23
|
+
import { Component, ChangeDetectorRef, EventEmitter, Output, inject, NgZone } from '@angular/core';
|
|
24
|
+
import { CompositeKey, RunView } from '@memberjunction/core';
|
|
25
|
+
import { KnowledgeHubMetadataEngine, ApplicationSettingEngine, UserInfoEngine } from '@memberjunction/core-entities';
|
|
26
|
+
import { UUIDsEqual } from '@memberjunction/global';
|
|
27
|
+
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
28
|
+
import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
29
|
+
import { AIEngineBase } from '@memberjunction/ai-engine-base';
|
|
30
|
+
import { TagEngineBase } from '@memberjunction/tag-engine-base';
|
|
31
|
+
import * as i0 from "@angular/core";
|
|
32
|
+
import * as i1 from "@angular/forms";
|
|
33
|
+
import * as i2 from "@memberjunction/ng-trees";
|
|
34
|
+
import * as i3 from "@memberjunction/ng-ui-components";
|
|
35
|
+
import * as i4 from "@angular/common";
|
|
36
|
+
const _c0 = () => [];
|
|
37
|
+
const _forTrack0 = ($index, $item) => $item.ID;
|
|
38
|
+
const _forTrack1 = ($index, $item) => $item.Key;
|
|
39
|
+
const _forTrack2 = ($index, $item) => $item.value;
|
|
40
|
+
const _forTrack3 = ($index, $item) => $item.Value;
|
|
41
|
+
const _forTrack4 = ($index, $item) => $item.Name;
|
|
42
|
+
const _forTrack5 = ($index, $item) => $item.label;
|
|
43
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
44
|
+
i0.ɵɵtext(0, " Add Content Source ");
|
|
45
|
+
} }
|
|
46
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
47
|
+
i0.ɵɵtext(0, " Edit Content Source ");
|
|
48
|
+
} }
|
|
49
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
50
|
+
i0.ɵɵtext(0, " Add Content Type ");
|
|
51
|
+
} }
|
|
52
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
53
|
+
i0.ɵɵtext(0, " Edit Content Type ");
|
|
54
|
+
} }
|
|
55
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_15_Template(rf, ctx) { if (rf & 1) {
|
|
56
|
+
i0.ɵɵelementStart(0, "option", 15);
|
|
57
|
+
i0.ɵɵtext(1);
|
|
58
|
+
i0.ɵɵelementEnd();
|
|
59
|
+
} if (rf & 2) {
|
|
60
|
+
const opt_r4 = ctx.$implicit;
|
|
61
|
+
i0.ɵɵproperty("value", opt_r4.ID);
|
|
62
|
+
i0.ɵɵadvance();
|
|
63
|
+
i0.ɵɵtextInterpolate(opt_r4.Name);
|
|
64
|
+
} }
|
|
65
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_16_For_7_Template(rf, ctx) { if (rf & 1) {
|
|
66
|
+
i0.ɵɵelementStart(0, "option", 15);
|
|
67
|
+
i0.ɵɵtext(1);
|
|
68
|
+
i0.ɵɵelementEnd();
|
|
69
|
+
} if (rf & 2) {
|
|
70
|
+
const opt_r6 = ctx.$implicit;
|
|
71
|
+
i0.ɵɵproperty("value", opt_r6.ID);
|
|
72
|
+
i0.ɵɵadvance();
|
|
73
|
+
i0.ɵɵtextInterpolate(opt_r6.Name);
|
|
74
|
+
} }
|
|
75
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_16_For_15_Template(rf, ctx) { if (rf & 1) {
|
|
76
|
+
i0.ɵɵelementStart(0, "option", 15);
|
|
77
|
+
i0.ɵɵtext(1);
|
|
78
|
+
i0.ɵɵelementEnd();
|
|
79
|
+
} if (rf & 2) {
|
|
80
|
+
const opt_r7 = ctx.$implicit;
|
|
81
|
+
i0.ɵɵproperty("value", opt_r7.ID);
|
|
82
|
+
i0.ɵɵadvance();
|
|
83
|
+
i0.ɵɵtextInterpolate(opt_r7.Name);
|
|
84
|
+
} }
|
|
85
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
86
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
87
|
+
i0.ɵɵelementStart(0, "div", 10)(1, "label", 11);
|
|
88
|
+
i0.ɵɵtext(2, "Content Type");
|
|
89
|
+
i0.ɵɵelementEnd();
|
|
90
|
+
i0.ɵɵelementStart(3, "select", 13);
|
|
91
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_16_Template_select_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormContentTypeID, $event) || (ctx_r1.FormContentTypeID = $event); return i0.ɵɵresetView($event); });
|
|
92
|
+
i0.ɵɵelementStart(4, "option", 14);
|
|
93
|
+
i0.ɵɵtext(5, "Select content type...");
|
|
94
|
+
i0.ɵɵelementEnd();
|
|
95
|
+
i0.ɵɵrepeaterCreate(6, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_16_For_7_Template, 2, 2, "option", 15, _forTrack0);
|
|
96
|
+
i0.ɵɵelementEnd()();
|
|
97
|
+
i0.ɵɵelementStart(8, "div", 10)(9, "label", 11);
|
|
98
|
+
i0.ɵɵtext(10, "File Type");
|
|
99
|
+
i0.ɵɵelementEnd();
|
|
100
|
+
i0.ɵɵelementStart(11, "select", 13);
|
|
101
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_16_Template_select_ngModelChange_11_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormFileTypeID, $event) || (ctx_r1.FormFileTypeID = $event); return i0.ɵɵresetView($event); });
|
|
102
|
+
i0.ɵɵelementStart(12, "option", 14);
|
|
103
|
+
i0.ɵɵtext(13, "Select file type...");
|
|
104
|
+
i0.ɵɵelementEnd();
|
|
105
|
+
i0.ɵɵrepeaterCreate(14, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_16_For_15_Template, 2, 2, "option", 15, _forTrack0);
|
|
106
|
+
i0.ɵɵelementEnd()();
|
|
107
|
+
} if (rf & 2) {
|
|
108
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
109
|
+
i0.ɵɵadvance(3);
|
|
110
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormContentTypeID);
|
|
111
|
+
i0.ɵɵadvance(3);
|
|
112
|
+
i0.ɵɵrepeater(ctx_r1.ContentTypeOptions);
|
|
113
|
+
i0.ɵɵadvance(5);
|
|
114
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormFileTypeID);
|
|
115
|
+
i0.ɵɵadvance(3);
|
|
116
|
+
i0.ɵɵrepeater(ctx_r1.FileTypeOptions);
|
|
117
|
+
} }
|
|
118
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
119
|
+
i0.ɵɵelementStart(0, "span", 51);
|
|
120
|
+
i0.ɵɵtext(1, "*");
|
|
121
|
+
i0.ɵɵelementEnd();
|
|
122
|
+
} }
|
|
123
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_4_Template(rf, ctx) { if (rf & 1) {
|
|
124
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
125
|
+
i0.ɵɵelementStart(0, "input", 56);
|
|
126
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_4_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r8); const field_r9 = i0.ɵɵnextContext(3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormSourceSpecificConfig[field_r9.Key], $event) || (ctx_r1.FormSourceSpecificConfig[field_r9.Key] = $event); return i0.ɵɵresetView($event); });
|
|
127
|
+
i0.ɵɵelementEnd();
|
|
128
|
+
} if (rf & 2) {
|
|
129
|
+
const field_r9 = i0.ɵɵnextContext(3).$implicit;
|
|
130
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
131
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormSourceSpecificConfig[field_r9.Key]);
|
|
132
|
+
i0.ɵɵproperty("placeholder", field_r9.Description || "https://...");
|
|
133
|
+
} }
|
|
134
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_5_Template(rf, ctx) { if (rf & 1) {
|
|
135
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
136
|
+
i0.ɵɵelementStart(0, "input", 57);
|
|
137
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_5_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r10); const field_r9 = i0.ɵɵnextContext(3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormSourceSpecificConfig[field_r9.Key], $event) || (ctx_r1.FormSourceSpecificConfig[field_r9.Key] = $event); return i0.ɵɵresetView($event); });
|
|
138
|
+
i0.ɵɵelementEnd();
|
|
139
|
+
} if (rf & 2) {
|
|
140
|
+
const field_r9 = i0.ɵɵnextContext(3).$implicit;
|
|
141
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
142
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormSourceSpecificConfig[field_r9.Key]);
|
|
143
|
+
i0.ɵɵproperty("placeholder", field_r9.Description || "/path/to/...");
|
|
144
|
+
} }
|
|
145
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_6_Template(rf, ctx) { if (rf & 1) {
|
|
146
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
147
|
+
i0.ɵɵelementStart(0, "input", 58);
|
|
148
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_6_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r11); const field_r9 = i0.ɵɵnextContext(3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormSourceSpecificConfig[field_r9.Key], $event) || (ctx_r1.FormSourceSpecificConfig[field_r9.Key] = $event); return i0.ɵɵresetView($event); });
|
|
149
|
+
i0.ɵɵelementEnd();
|
|
150
|
+
} if (rf & 2) {
|
|
151
|
+
const field_r9 = i0.ɵɵnextContext(3).$implicit;
|
|
152
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
153
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormSourceSpecificConfig[field_r9.Key]);
|
|
154
|
+
i0.ɵɵproperty("placeholder", field_r9.Description || "")("value", field_r9.DefaultValue || "");
|
|
155
|
+
} }
|
|
156
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_7_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
157
|
+
i0.ɵɵelementStart(0, "option", 15);
|
|
158
|
+
i0.ɵɵtext(1);
|
|
159
|
+
i0.ɵɵelementEnd();
|
|
160
|
+
} if (rf & 2) {
|
|
161
|
+
const opt_r13 = ctx.$implicit;
|
|
162
|
+
i0.ɵɵproperty("value", opt_r13.ID);
|
|
163
|
+
i0.ɵɵadvance();
|
|
164
|
+
i0.ɵɵtextInterpolate(opt_r13.Name);
|
|
165
|
+
} }
|
|
166
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_7_Template(rf, ctx) { if (rf & 1) {
|
|
167
|
+
const _r12 = i0.ɵɵgetCurrentView();
|
|
168
|
+
i0.ɵɵelementStart(0, "select", 13);
|
|
169
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_7_Template_select_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r12); const field_r9 = i0.ɵɵnextContext(3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormSourceSpecificConfig[field_r9.Key], $event) || (ctx_r1.FormSourceSpecificConfig[field_r9.Key] = $event); return i0.ɵɵresetView($event); });
|
|
170
|
+
i0.ɵɵlistener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_7_Template_select_ngModelChange_0_listener() { i0.ɵɵrestoreView(_r12); const field_r9 = i0.ɵɵnextContext(3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnSourceFieldChanged(field_r9.Key)); });
|
|
171
|
+
i0.ɵɵelementStart(1, "option", 14);
|
|
172
|
+
i0.ɵɵtext(2, "Select entity...");
|
|
173
|
+
i0.ɵɵelementEnd();
|
|
174
|
+
i0.ɵɵrepeaterCreate(3, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_7_For_4_Template, 2, 2, "option", 15, _forTrack0);
|
|
175
|
+
i0.ɵɵelementEnd();
|
|
176
|
+
} if (rf & 2) {
|
|
177
|
+
const field_r9 = i0.ɵɵnextContext(3).$implicit;
|
|
178
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
179
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormSourceSpecificConfig[field_r9.Key]);
|
|
180
|
+
i0.ɵɵadvance(3);
|
|
181
|
+
i0.ɵɵrepeater(ctx_r1.EntitiesWithDocuments);
|
|
182
|
+
} }
|
|
183
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_8_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
184
|
+
i0.ɵɵelementStart(0, "option", 15);
|
|
185
|
+
i0.ɵɵtext(1);
|
|
186
|
+
i0.ɵɵelementEnd();
|
|
187
|
+
} if (rf & 2) {
|
|
188
|
+
const opt_r15 = ctx.$implicit;
|
|
189
|
+
i0.ɵɵproperty("value", opt_r15.ID);
|
|
190
|
+
i0.ɵɵadvance();
|
|
191
|
+
i0.ɵɵtextInterpolate(opt_r15.Name);
|
|
192
|
+
} }
|
|
193
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_8_Template(rf, ctx) { if (rf & 1) {
|
|
194
|
+
const _r14 = i0.ɵɵgetCurrentView();
|
|
195
|
+
i0.ɵɵelementStart(0, "select", 13);
|
|
196
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_8_Template_select_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r14); const field_r9 = i0.ɵɵnextContext(3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormSourceSpecificConfig[field_r9.Key], $event) || (ctx_r1.FormSourceSpecificConfig[field_r9.Key] = $event); return i0.ɵɵresetView($event); });
|
|
197
|
+
i0.ɵɵrepeaterCreate(1, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_8_For_2_Template, 2, 2, "option", 15, _forTrack0);
|
|
198
|
+
i0.ɵɵelementEnd();
|
|
199
|
+
} if (rf & 2) {
|
|
200
|
+
const field_r9 = i0.ɵɵnextContext(3).$implicit;
|
|
201
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
202
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormSourceSpecificConfig[field_r9.Key]);
|
|
203
|
+
i0.ɵɵadvance();
|
|
204
|
+
i0.ɵɵrepeater(ctx_r1.GetDependentOptions(field_r9));
|
|
205
|
+
} }
|
|
206
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_9_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
207
|
+
i0.ɵɵelementStart(0, "option", 15);
|
|
208
|
+
i0.ɵɵtext(1);
|
|
209
|
+
i0.ɵɵelementEnd();
|
|
210
|
+
} if (rf & 2) {
|
|
211
|
+
const opt_r17 = ctx.$implicit;
|
|
212
|
+
i0.ɵɵproperty("value", opt_r17);
|
|
213
|
+
i0.ɵɵadvance();
|
|
214
|
+
i0.ɵɵtextInterpolate(opt_r17);
|
|
215
|
+
} }
|
|
216
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_9_Template(rf, ctx) { if (rf & 1) {
|
|
217
|
+
const _r16 = i0.ɵɵgetCurrentView();
|
|
218
|
+
i0.ɵɵelementStart(0, "select", 13);
|
|
219
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_9_Template_select_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r16); const field_r9 = i0.ɵɵnextContext(3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormSourceSpecificConfig[field_r9.Key], $event) || (ctx_r1.FormSourceSpecificConfig[field_r9.Key] = $event); return i0.ɵɵresetView($event); });
|
|
220
|
+
i0.ɵɵelementStart(1, "option", 14);
|
|
221
|
+
i0.ɵɵtext(2, "Select provider...");
|
|
222
|
+
i0.ɵɵelementEnd();
|
|
223
|
+
i0.ɵɵrepeaterCreate(3, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_9_For_4_Template, 2, 2, "option", 15, i0.ɵɵrepeaterTrackByIdentity);
|
|
224
|
+
i0.ɵɵelementEnd();
|
|
225
|
+
} if (rf & 2) {
|
|
226
|
+
const field_r9 = i0.ɵɵnextContext(3).$implicit;
|
|
227
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
228
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormSourceSpecificConfig[field_r9.Key]);
|
|
229
|
+
i0.ɵɵadvance(3);
|
|
230
|
+
i0.ɵɵrepeater(ctx_r1.StorageProviderOptions);
|
|
231
|
+
} }
|
|
232
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_10_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
233
|
+
i0.ɵɵelementStart(0, "option", 15);
|
|
234
|
+
i0.ɵɵtext(1);
|
|
235
|
+
i0.ɵɵelementEnd();
|
|
236
|
+
} if (rf & 2) {
|
|
237
|
+
const opt_r19 = ctx.$implicit;
|
|
238
|
+
i0.ɵɵproperty("value", opt_r19.Value);
|
|
239
|
+
i0.ɵɵadvance();
|
|
240
|
+
i0.ɵɵtextInterpolate(opt_r19.Label);
|
|
241
|
+
} }
|
|
242
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_10_Template(rf, ctx) { if (rf & 1) {
|
|
243
|
+
const _r18 = i0.ɵɵgetCurrentView();
|
|
244
|
+
i0.ɵɵelementStart(0, "select", 13);
|
|
245
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_10_Template_select_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r18); const field_r9 = i0.ɵɵnextContext(3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormSourceSpecificConfig[field_r9.Key], $event) || (ctx_r1.FormSourceSpecificConfig[field_r9.Key] = $event); return i0.ɵɵresetView($event); });
|
|
246
|
+
i0.ɵɵelementStart(1, "option", 14);
|
|
247
|
+
i0.ɵɵtext(2, "Select...");
|
|
248
|
+
i0.ɵɵelementEnd();
|
|
249
|
+
i0.ɵɵrepeaterCreate(3, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_10_For_4_Template, 2, 2, "option", 15, _forTrack3);
|
|
250
|
+
i0.ɵɵelementEnd();
|
|
251
|
+
} if (rf & 2) {
|
|
252
|
+
const field_r9 = i0.ɵɵnextContext(3).$implicit;
|
|
253
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
254
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormSourceSpecificConfig[field_r9.Key]);
|
|
255
|
+
i0.ɵɵadvance(3);
|
|
256
|
+
i0.ɵɵrepeater(field_r9.Options || i0.ɵɵpureFunction0(1, _c0));
|
|
257
|
+
} }
|
|
258
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
259
|
+
i0.ɵɵelementStart(0, "span", 19);
|
|
260
|
+
i0.ɵɵtext(1);
|
|
261
|
+
i0.ɵɵelementEnd();
|
|
262
|
+
} if (rf & 2) {
|
|
263
|
+
const field_r9 = i0.ɵɵnextContext(3).$implicit;
|
|
264
|
+
i0.ɵɵadvance();
|
|
265
|
+
i0.ɵɵtextInterpolate(field_r9.Description);
|
|
266
|
+
} }
|
|
267
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
268
|
+
i0.ɵɵelementStart(0, "div", 10)(1, "label", 11);
|
|
269
|
+
i0.ɵɵtext(2);
|
|
270
|
+
i0.ɵɵconditionalCreate(3, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Conditional_3_Template, 2, 0, "span", 51);
|
|
271
|
+
i0.ɵɵelementEnd();
|
|
272
|
+
i0.ɵɵconditionalCreate(4, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_4_Template, 1, 2, "input", 52)(5, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_5_Template, 1, 2, "input", 53)(6, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_6_Template, 1, 3, "input", 54)(7, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_7_Template, 5, 1, "select", 55)(8, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_8_Template, 3, 1, "select", 55)(9, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_9_Template, 5, 1, "select", 55)(10, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Case_10_Template, 5, 2, "select", 55);
|
|
273
|
+
i0.ɵɵconditionalCreate(11, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Conditional_11_Template, 2, 1, "span", 19);
|
|
274
|
+
i0.ɵɵelementEnd();
|
|
275
|
+
} if (rf & 2) {
|
|
276
|
+
let tmp_16_0;
|
|
277
|
+
const field_r9 = i0.ɵɵnextContext(2).$implicit;
|
|
278
|
+
i0.ɵɵadvance(2);
|
|
279
|
+
i0.ɵɵtextInterpolate1("", field_r9.Label, " ");
|
|
280
|
+
i0.ɵɵadvance();
|
|
281
|
+
i0.ɵɵconditional(field_r9.Required ? 3 : -1);
|
|
282
|
+
i0.ɵɵadvance();
|
|
283
|
+
i0.ɵɵconditional((tmp_16_0 = field_r9.Type) === "url" ? 4 : tmp_16_0 === "path" ? 5 : tmp_16_0 === "text" ? 6 : tmp_16_0 === "entity-picker" ? 7 : tmp_16_0 === "entity-doc-picker" ? 8 : tmp_16_0 === "storage-provider-picker" ? 9 : tmp_16_0 === "dropdown" ? 10 : -1);
|
|
284
|
+
i0.ɵɵadvance(7);
|
|
285
|
+
i0.ɵɵconditional(field_r9.Description ? 11 : -1);
|
|
286
|
+
} }
|
|
287
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
288
|
+
i0.ɵɵconditionalCreate(0, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Conditional_0_Template, 12, 4, "div", 10);
|
|
289
|
+
} if (rf & 2) {
|
|
290
|
+
const field_r9 = i0.ɵɵnextContext().$implicit;
|
|
291
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
292
|
+
i0.ɵɵconditional(!field_r9.ShowOnlyIfMultiple || ctx_r1.GetDependentOptions(field_r9).length > 1 ? 0 : -1);
|
|
293
|
+
} }
|
|
294
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Template(rf, ctx) { if (rf & 1) {
|
|
295
|
+
i0.ɵɵconditionalCreate(0, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Conditional_0_Template, 1, 1);
|
|
296
|
+
} if (rf & 2) {
|
|
297
|
+
const field_r9 = ctx.$implicit;
|
|
298
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
299
|
+
i0.ɵɵconditional(!field_r9.DependsOnField || ctx_r1.FormSourceSpecificConfig[field_r9.DependsOnField] ? 0 : -1);
|
|
300
|
+
} }
|
|
301
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
302
|
+
const _r20 = i0.ɵɵgetCurrentView();
|
|
303
|
+
i0.ɵɵelementStart(0, "button", 64);
|
|
304
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OpenInlineEntityDocForm()); });
|
|
305
|
+
i0.ɵɵelement(1, "i", 65);
|
|
306
|
+
i0.ɵɵtext(2, " Create Entity Document ");
|
|
307
|
+
i0.ɵɵelementEnd();
|
|
308
|
+
} }
|
|
309
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_For_10_Template(rf, ctx) { if (rf & 1) {
|
|
310
|
+
const _r22 = i0.ɵɵgetCurrentView();
|
|
311
|
+
i0.ɵɵelementStart(0, "label", 68)(1, "input", 71);
|
|
312
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_For_10_Template_input_ngModelChange_1_listener($event) { const f_r23 = i0.ɵɵrestoreView(_r22).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); i0.ɵɵtwoWayBindingSet(ctx_r1.NewEntityDocSelectedFields[f_r23.Name], $event) || (ctx_r1.NewEntityDocSelectedFields[f_r23.Name] = $event); return i0.ɵɵresetView($event); });
|
|
313
|
+
i0.ɵɵelementEnd();
|
|
314
|
+
i0.ɵɵelementStart(2, "span");
|
|
315
|
+
i0.ɵɵtext(3);
|
|
316
|
+
i0.ɵɵelementEnd()();
|
|
317
|
+
} if (rf & 2) {
|
|
318
|
+
const f_r23 = ctx.$implicit;
|
|
319
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
320
|
+
i0.ɵɵadvance();
|
|
321
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.NewEntityDocSelectedFields[f_r23.Name]);
|
|
322
|
+
i0.ɵɵadvance(2);
|
|
323
|
+
i0.ɵɵtextInterpolate(f_r23.DisplayName);
|
|
324
|
+
} }
|
|
325
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
326
|
+
i0.ɵɵelement(0, "i", 72);
|
|
327
|
+
i0.ɵɵtext(1, " Creating\u2026 ");
|
|
328
|
+
} }
|
|
329
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
330
|
+
i0.ɵɵelement(0, "i", 73);
|
|
331
|
+
i0.ɵɵtext(1, " Create ");
|
|
332
|
+
} }
|
|
333
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
334
|
+
const _r21 = i0.ɵɵgetCurrentView();
|
|
335
|
+
i0.ɵɵelementStart(0, "div", 63)(1, "div", 10)(2, "label", 11);
|
|
336
|
+
i0.ɵɵtext(3, "Document name");
|
|
337
|
+
i0.ɵɵelementEnd();
|
|
338
|
+
i0.ɵɵelementStart(4, "input", 66);
|
|
339
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_Template_input_ngModelChange_4_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(4); i0.ɵɵtwoWayBindingSet(ctx_r1.NewEntityDocName, $event) || (ctx_r1.NewEntityDocName = $event); return i0.ɵɵresetView($event); });
|
|
340
|
+
i0.ɵɵelementEnd()();
|
|
341
|
+
i0.ɵɵelementStart(5, "div", 10)(6, "label", 11);
|
|
342
|
+
i0.ɵɵtext(7);
|
|
343
|
+
i0.ɵɵelementEnd();
|
|
344
|
+
i0.ɵɵelementStart(8, "div", 67);
|
|
345
|
+
i0.ɵɵrepeaterCreate(9, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_For_10_Template, 4, 2, "label", 68, _forTrack4);
|
|
346
|
+
i0.ɵɵelementEnd()();
|
|
347
|
+
i0.ɵɵelementStart(11, "div", 47)(12, "button", 69);
|
|
348
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.CreateInlineEntityDocument()); });
|
|
349
|
+
i0.ɵɵconditionalCreate(13, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_Conditional_13_Template, 2, 0)(14, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_Conditional_14_Template, 2, 0);
|
|
350
|
+
i0.ɵɵelementEnd();
|
|
351
|
+
i0.ɵɵelementStart(15, "button", 70);
|
|
352
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.CancelInlineEntityDocForm()); });
|
|
353
|
+
i0.ɵɵtext(16, "Cancel");
|
|
354
|
+
i0.ɵɵelementEnd()()();
|
|
355
|
+
} if (rf & 2) {
|
|
356
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
357
|
+
i0.ɵɵadvance(4);
|
|
358
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.NewEntityDocName);
|
|
359
|
+
i0.ɵɵadvance(3);
|
|
360
|
+
i0.ɵɵtextInterpolate1("Fields to include (", ctx_r1.SelectedEntityDocFieldCount, " selected)");
|
|
361
|
+
i0.ɵɵadvance(2);
|
|
362
|
+
i0.ɵɵrepeater(ctx_r1.SelectedEntityFields);
|
|
363
|
+
i0.ɵɵadvance(3);
|
|
364
|
+
i0.ɵɵproperty("disabled", ctx_r1.EntityDocSaving);
|
|
365
|
+
i0.ɵɵadvance();
|
|
366
|
+
i0.ɵɵconditional(ctx_r1.EntityDocSaving ? 13 : 14);
|
|
367
|
+
} }
|
|
368
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
369
|
+
i0.ɵɵelementStart(0, "div", 59)(1, "div", 60);
|
|
370
|
+
i0.ɵɵelement(2, "i", 61);
|
|
371
|
+
i0.ɵɵelementStart(3, "span")(4, "strong");
|
|
372
|
+
i0.ɵɵtext(5);
|
|
373
|
+
i0.ɵɵelementEnd();
|
|
374
|
+
i0.ɵɵtext(6, " has no Entity Document. One is required to classify its records.");
|
|
375
|
+
i0.ɵɵelementEnd()();
|
|
376
|
+
i0.ɵɵconditionalCreate(7, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_7_Template, 3, 0, "button", 62);
|
|
377
|
+
i0.ɵɵelementEnd();
|
|
378
|
+
i0.ɵɵconditionalCreate(8, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Conditional_8_Template, 17, 4, "div", 63);
|
|
379
|
+
} if (rf & 2) {
|
|
380
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
381
|
+
i0.ɵɵadvance(5);
|
|
382
|
+
i0.ɵɵtextInterpolate(ctx_r1.SelectedEntityName);
|
|
383
|
+
i0.ɵɵadvance(2);
|
|
384
|
+
i0.ɵɵconditional(!ctx_r1.ShowInlineEntityDocForm ? 7 : -1);
|
|
385
|
+
i0.ɵɵadvance();
|
|
386
|
+
i0.ɵɵconditional(ctx_r1.ShowInlineEntityDocForm ? 8 : -1);
|
|
387
|
+
} }
|
|
388
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_37_Template(rf, ctx) { if (rf & 1) {
|
|
389
|
+
i0.ɵɵelementStart(0, "option", 15);
|
|
390
|
+
i0.ɵɵtext(1);
|
|
391
|
+
i0.ɵɵelementEnd();
|
|
392
|
+
} if (rf & 2) {
|
|
393
|
+
const opt_r24 = ctx.$implicit;
|
|
394
|
+
i0.ɵɵproperty("value", opt_r24.ID);
|
|
395
|
+
i0.ɵɵadvance();
|
|
396
|
+
i0.ɵɵtextInterpolate(opt_r24.Name);
|
|
397
|
+
} }
|
|
398
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_53_Template(rf, ctx) { if (rf & 1) {
|
|
399
|
+
const _r25 = i0.ɵɵgetCurrentView();
|
|
400
|
+
i0.ɵɵelementStart(0, "div", 74);
|
|
401
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_53_Template_div_click_0_listener() { const m_r26 = i0.ɵɵrestoreView(_r25).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.SetMode(m_r26.value)); });
|
|
402
|
+
i0.ɵɵelement(1, "i");
|
|
403
|
+
i0.ɵɵelementStart(2, "div", 75);
|
|
404
|
+
i0.ɵɵtext(3);
|
|
405
|
+
i0.ɵɵelementEnd();
|
|
406
|
+
i0.ɵɵelementStart(4, "div", 76);
|
|
407
|
+
i0.ɵɵtext(5);
|
|
408
|
+
i0.ɵɵelementEnd()();
|
|
409
|
+
} if (rf & 2) {
|
|
410
|
+
const m_r26 = ctx.$implicit;
|
|
411
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
412
|
+
i0.ɵɵclassProp("selected", ctx_r1.CurrentMode === m_r26.value);
|
|
413
|
+
i0.ɵɵadvance();
|
|
414
|
+
i0.ɵɵclassMap(i0.ɵɵinterpolate1("fa-solid ", m_r26.icon, " cls-mode-ic"));
|
|
415
|
+
i0.ɵɵadvance(2);
|
|
416
|
+
i0.ɵɵtextInterpolate(m_r26.label);
|
|
417
|
+
i0.ɵɵadvance(2);
|
|
418
|
+
i0.ɵɵtextInterpolate(m_r26.bestFor);
|
|
419
|
+
} }
|
|
420
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_61_Template(rf, ctx) { if (rf & 1) {
|
|
421
|
+
i0.ɵɵelementStart(0, "option", 15);
|
|
422
|
+
i0.ɵɵtext(1);
|
|
423
|
+
i0.ɵɵelementEnd();
|
|
424
|
+
} if (rf & 2) {
|
|
425
|
+
const opt_r27 = ctx.$implicit;
|
|
426
|
+
i0.ɵɵproperty("value", opt_r27.ID);
|
|
427
|
+
i0.ɵɵadvance();
|
|
428
|
+
i0.ɵɵtextInterpolate(opt_r27.Name);
|
|
429
|
+
} }
|
|
430
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_84_Template(rf, ctx) { if (rf & 1) {
|
|
431
|
+
i0.ɵɵelementStart(0, "div", 32);
|
|
432
|
+
i0.ɵɵelement(1, "i", 77);
|
|
433
|
+
i0.ɵɵtext(2);
|
|
434
|
+
i0.ɵɵelementEnd();
|
|
435
|
+
} if (rf & 2) {
|
|
436
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
437
|
+
i0.ɵɵadvance(2);
|
|
438
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.ThresholdValidationMessage);
|
|
439
|
+
} }
|
|
440
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_85_Template(rf, ctx) { if (rf & 1) {
|
|
441
|
+
i0.ɵɵelementStart(0, "div", 33)(1, "span", 78);
|
|
442
|
+
i0.ɵɵtext(2, "reject / new");
|
|
443
|
+
i0.ɵɵelementEnd();
|
|
444
|
+
i0.ɵɵelementStart(3, "span", 79);
|
|
445
|
+
i0.ɵɵtext(4, "review (inbox)");
|
|
446
|
+
i0.ɵɵelementEnd();
|
|
447
|
+
i0.ɵɵelementStart(5, "span", 80);
|
|
448
|
+
i0.ɵɵtext(6, "auto-apply");
|
|
449
|
+
i0.ɵɵelementEnd()();
|
|
450
|
+
} }
|
|
451
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_100_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
452
|
+
i0.ɵɵelementStart(0, "div", 82)(1, "span", 83);
|
|
453
|
+
i0.ɵɵtext(2);
|
|
454
|
+
i0.ɵɵelementEnd();
|
|
455
|
+
i0.ɵɵelementStart(3, "span", 84);
|
|
456
|
+
i0.ɵɵtext(4);
|
|
457
|
+
i0.ɵɵelementStart(5, "span", 85);
|
|
458
|
+
i0.ɵɵtext(6);
|
|
459
|
+
i0.ɵɵelementEnd()()();
|
|
460
|
+
} if (rf & 2) {
|
|
461
|
+
const row_r28 = ctx.$implicit;
|
|
462
|
+
i0.ɵɵadvance(2);
|
|
463
|
+
i0.ɵɵtextInterpolate(row_r28.label);
|
|
464
|
+
i0.ɵɵadvance(2);
|
|
465
|
+
i0.ɵɵtextInterpolate1("", row_r28.value, " ");
|
|
466
|
+
i0.ɵɵadvance();
|
|
467
|
+
i0.ɵɵclassProp("override", row_r28.origin === "source override");
|
|
468
|
+
i0.ɵɵadvance();
|
|
469
|
+
i0.ɵɵtextInterpolate(row_r28.origin);
|
|
470
|
+
} }
|
|
471
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_100_Template(rf, ctx) { if (rf & 1) {
|
|
472
|
+
i0.ɵɵelementStart(0, "div", 39)(1, "h5", 81);
|
|
473
|
+
i0.ɵɵtext(2, "Effective values");
|
|
474
|
+
i0.ɵɵelementEnd();
|
|
475
|
+
i0.ɵɵrepeaterCreate(3, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_100_For_4_Template, 7, 5, "div", 82, _forTrack5);
|
|
476
|
+
i0.ɵɵelementEnd();
|
|
477
|
+
} if (rf & 2) {
|
|
478
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
479
|
+
i0.ɵɵadvance(3);
|
|
480
|
+
i0.ɵɵrepeater(ctx_r1.EffectiveValues);
|
|
481
|
+
} }
|
|
482
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_166_Template(rf, ctx) { if (rf & 1) {
|
|
483
|
+
const _r29 = i0.ɵɵgetCurrentView();
|
|
484
|
+
i0.ɵɵelementStart(0, "div", 16)(1, "div", 8);
|
|
485
|
+
i0.ɵɵelement(2, "i", 86);
|
|
486
|
+
i0.ɵɵtext(3, " Crawl settings");
|
|
487
|
+
i0.ɵɵelementEnd();
|
|
488
|
+
i0.ɵɵelementStart(4, "div", 10)(5, "label", 11);
|
|
489
|
+
i0.ɵɵtext(6, "Crawl depth");
|
|
490
|
+
i0.ɵɵelementEnd();
|
|
491
|
+
i0.ɵɵelementStart(7, "input", 87);
|
|
492
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_166_Template_input_ngModelChange_7_listener($event) { i0.ɵɵrestoreView(_r29); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormMaxDepth, $event) || (ctx_r1.FormMaxDepth = $event); return i0.ɵɵresetView($event); });
|
|
493
|
+
i0.ɵɵelementEnd();
|
|
494
|
+
i0.ɵɵelementStart(8, "span", 19);
|
|
495
|
+
i0.ɵɵtext(9, " Recursion ceiling for in-domain links. ");
|
|
496
|
+
i0.ɵɵelementStart(10, "code");
|
|
497
|
+
i0.ɵɵtext(11, "0");
|
|
498
|
+
i0.ɵɵelementEnd();
|
|
499
|
+
i0.ɵɵtext(12, " = just the start URL. ");
|
|
500
|
+
i0.ɵɵelementStart(13, "code");
|
|
501
|
+
i0.ɵɵtext(14, "2");
|
|
502
|
+
i0.ɵɵelementEnd();
|
|
503
|
+
i0.ɵɵtext(15, " (default) = root + sections + content pages. ");
|
|
504
|
+
i0.ɵɵelementEnd()();
|
|
505
|
+
i0.ɵɵelementStart(16, "div", 10)(17, "label", 11)(18, "input", 71);
|
|
506
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_166_Template_input_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r29); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormCrawlSitesInLowerLevelDomain, $event) || (ctx_r1.FormCrawlSitesInLowerLevelDomain = $event); return i0.ɵɵresetView($event); });
|
|
507
|
+
i0.ɵɵelementEnd();
|
|
508
|
+
i0.ɵɵtext(19, " Crawl sites in lower-level domain ");
|
|
509
|
+
i0.ɵɵelementEnd();
|
|
510
|
+
i0.ɵɵelementStart(20, "span", 19);
|
|
511
|
+
i0.ɵɵtext(21, "When on (default), the depth-aware recursive crawler runs. Turn off to crawl only the seed page.");
|
|
512
|
+
i0.ɵɵelementEnd()();
|
|
513
|
+
i0.ɵɵelementStart(22, "div", 10)(23, "label", 11)(24, "input", 71);
|
|
514
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_166_Template_input_ngModelChange_24_listener($event) { i0.ɵɵrestoreView(_r29); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.FormCrawlOtherSitesInTopLevelDomain, $event) || (ctx_r1.FormCrawlOtherSitesInTopLevelDomain = $event); return i0.ɵɵresetView($event); });
|
|
515
|
+
i0.ɵɵelementEnd();
|
|
516
|
+
i0.ɵɵtext(25, " Crawl other sites in top-level domain ");
|
|
517
|
+
i0.ɵɵelementEnd();
|
|
518
|
+
i0.ɵɵelementStart(26, "span", 19);
|
|
519
|
+
i0.ɵɵtext(27, "When on, also adds sibling-path URLs found on the seed page. Off by default to avoid accidental fan-out.");
|
|
520
|
+
i0.ɵɵelementEnd()()();
|
|
521
|
+
} if (rf & 2) {
|
|
522
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
523
|
+
i0.ɵɵadvance(7);
|
|
524
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormMaxDepth);
|
|
525
|
+
i0.ɵɵadvance(11);
|
|
526
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormCrawlSitesInLowerLevelDomain);
|
|
527
|
+
i0.ɵɵadvance(6);
|
|
528
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormCrawlOtherSitesInTopLevelDomain);
|
|
529
|
+
} }
|
|
530
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_169_Template(rf, ctx) { if (rf & 1) {
|
|
531
|
+
i0.ɵɵelement(0, "i", 72);
|
|
532
|
+
i0.ɵɵtext(1, " Saving... ");
|
|
533
|
+
} }
|
|
534
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_170_Template(rf, ctx) { if (rf & 1) {
|
|
535
|
+
i0.ɵɵelement(0, "i", 73);
|
|
536
|
+
i0.ɵɵtext(1, " Save ");
|
|
537
|
+
} }
|
|
538
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_173_Template(rf, ctx) { if (rf & 1) {
|
|
539
|
+
const _r30 = i0.ɵɵgetCurrentView();
|
|
540
|
+
i0.ɵɵelementStart(0, "div", 50)(1, "a", 88);
|
|
541
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_173_Template_a_click_1_listener() { i0.ɵɵrestoreView(_r30); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OpenAdvancedSourceSettings()); });
|
|
542
|
+
i0.ɵɵelement(2, "i", 89);
|
|
543
|
+
i0.ɵɵtext(3, " Open advanced settings \u2014 URL pattern, root URL, & full entity form ");
|
|
544
|
+
i0.ɵɵelementEnd();
|
|
545
|
+
i0.ɵɵelementStart(4, "span", 19);
|
|
546
|
+
i0.ɵɵtext(5, "The key classifier knobs (taxonomy mode, thresholds, tag root, budgets) are now editable inline above.");
|
|
547
|
+
i0.ɵɵelementEnd()();
|
|
548
|
+
} }
|
|
549
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
550
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
551
|
+
i0.ɵɵelementStart(0, "div", 7)(1, "div", 8);
|
|
552
|
+
i0.ɵɵelement(2, "i", 9);
|
|
553
|
+
i0.ɵɵtext(3, " Source");
|
|
554
|
+
i0.ɵɵelementEnd();
|
|
555
|
+
i0.ɵɵelementStart(4, "div", 10)(5, "label", 11);
|
|
556
|
+
i0.ɵɵtext(6, "Name");
|
|
557
|
+
i0.ɵɵelementEnd();
|
|
558
|
+
i0.ɵɵelementStart(7, "input", 12);
|
|
559
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_input_ngModelChange_7_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.FormSourceName, $event) || (ctx_r1.FormSourceName = $event); return i0.ɵɵresetView($event); });
|
|
560
|
+
i0.ɵɵelementEnd()();
|
|
561
|
+
i0.ɵɵelementStart(8, "div", 10)(9, "label", 11);
|
|
562
|
+
i0.ɵɵtext(10, "Source Type");
|
|
563
|
+
i0.ɵɵelementEnd();
|
|
564
|
+
i0.ɵɵelementStart(11, "select", 13);
|
|
565
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_select_ngModelChange_11_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.FormSourceTypeID, $event) || (ctx_r1.FormSourceTypeID = $event); return i0.ɵɵresetView($event); });
|
|
566
|
+
i0.ɵɵelementStart(12, "option", 14);
|
|
567
|
+
i0.ɵɵtext(13, "Select source type...");
|
|
568
|
+
i0.ɵɵelementEnd();
|
|
569
|
+
i0.ɵɵrepeaterCreate(14, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_15_Template, 2, 2, "option", 15, _forTrack0);
|
|
570
|
+
i0.ɵɵelementEnd()();
|
|
571
|
+
i0.ɵɵconditionalCreate(16, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_16_Template, 16, 2);
|
|
572
|
+
i0.ɵɵrepeaterCreate(17, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_18_Template, 1, 1, null, null, _forTrack1);
|
|
573
|
+
i0.ɵɵconditionalCreate(19, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_19_Template, 9, 3);
|
|
574
|
+
i0.ɵɵelementEnd();
|
|
575
|
+
i0.ɵɵelementStart(20, "div", 16)(21, "div", 8);
|
|
576
|
+
i0.ɵɵelement(22, "i", 17);
|
|
577
|
+
i0.ɵɵtext(23, " Embedding & Vectors");
|
|
578
|
+
i0.ɵɵelementEnd();
|
|
579
|
+
i0.ɵɵelementStart(24, "div", 10)(25, "label", 11);
|
|
580
|
+
i0.ɵɵtext(26, "Embedding Model Override");
|
|
581
|
+
i0.ɵɵelementEnd();
|
|
582
|
+
i0.ɵɵelementStart(27, "mj-tree-dropdown", 18);
|
|
583
|
+
i0.ɵɵlistener("ValueChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_mj_tree_dropdown_ValueChange_27_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.FormSourceEmbeddingModelID = ctx_r1.FromCompositeKey($event)); });
|
|
584
|
+
i0.ɵɵelementEnd();
|
|
585
|
+
i0.ɵɵelementStart(28, "span", 19);
|
|
586
|
+
i0.ɵɵtext(29, "Overrides Content Type default");
|
|
587
|
+
i0.ɵɵelementEnd()();
|
|
588
|
+
i0.ɵɵelementStart(30, "div", 10)(31, "label", 11);
|
|
589
|
+
i0.ɵɵtext(32, "Vector Index Override");
|
|
590
|
+
i0.ɵɵelementEnd();
|
|
591
|
+
i0.ɵɵelementStart(33, "select", 13);
|
|
592
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_select_ngModelChange_33_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.FormSourceVectorIndexID, $event) || (ctx_r1.FormSourceVectorIndexID = $event); return i0.ɵɵresetView($event); });
|
|
593
|
+
i0.ɵɵelementStart(34, "option", 14);
|
|
594
|
+
i0.ɵɵtext(35, "Use system default");
|
|
595
|
+
i0.ɵɵelementEnd();
|
|
596
|
+
i0.ɵɵrepeaterCreate(36, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_37_Template, 2, 2, "option", 15, _forTrack0);
|
|
597
|
+
i0.ɵɵelementEnd();
|
|
598
|
+
i0.ɵɵelementStart(38, "span", 19);
|
|
599
|
+
i0.ɵɵtext(39, "Overrides Content Type default");
|
|
600
|
+
i0.ɵɵelementEnd()()();
|
|
601
|
+
i0.ɵɵelementStart(40, "div", 16)(41, "div", 8);
|
|
602
|
+
i0.ɵɵelement(42, "i", 20);
|
|
603
|
+
i0.ɵɵtext(43, " Classification ");
|
|
604
|
+
i0.ɵɵelementStart(44, "button", 21);
|
|
605
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_button_click_44_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ToggleEffectiveValues()); });
|
|
606
|
+
i0.ɵɵelement(45, "i", 22);
|
|
607
|
+
i0.ɵɵtext(46);
|
|
608
|
+
i0.ɵɵelementEnd()();
|
|
609
|
+
i0.ɵɵelementStart(47, "div", 23)(48, "div", 10)(49, "label", 11);
|
|
610
|
+
i0.ɵɵtext(50, "Taxonomy mode");
|
|
611
|
+
i0.ɵɵelementEnd();
|
|
612
|
+
i0.ɵɵelementStart(51, "div", 24);
|
|
613
|
+
i0.ɵɵrepeaterCreate(52, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_53_Template, 6, 7, "div", 25, _forTrack2);
|
|
614
|
+
i0.ɵɵelementEnd()();
|
|
615
|
+
i0.ɵɵelementStart(54, "div", 10)(55, "label", 11);
|
|
616
|
+
i0.ɵɵtext(56, "Tag root");
|
|
617
|
+
i0.ɵɵelementEnd();
|
|
618
|
+
i0.ɵɵelementStart(57, "select", 13);
|
|
619
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_select_ngModelChange_57_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.TagRootIDValue, $event) || (ctx_r1.TagRootIDValue = $event); return i0.ɵɵresetView($event); });
|
|
620
|
+
i0.ɵɵelementStart(58, "option", 14);
|
|
621
|
+
i0.ɵɵtext(59, "(none / whole taxonomy)");
|
|
622
|
+
i0.ɵɵelementEnd();
|
|
623
|
+
i0.ɵɵrepeaterCreate(60, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_For_61_Template, 2, 2, "option", 15, _forTrack0);
|
|
624
|
+
i0.ɵɵelementEnd();
|
|
625
|
+
i0.ɵɵelementStart(62, "span", 19);
|
|
626
|
+
i0.ɵɵtext(63, "Restricts the LLM's visible taxonomy + auto-grow target. Leave blank for the full taxonomy.");
|
|
627
|
+
i0.ɵɵelementEnd()();
|
|
628
|
+
i0.ɵɵelementStart(64, "div", 10)(65, "label", 11);
|
|
629
|
+
i0.ɵɵtext(66, "Confidence thresholds");
|
|
630
|
+
i0.ɵɵelementEnd();
|
|
631
|
+
i0.ɵɵelementStart(67, "div", 26)(68, "div", 27)(69, "div", 28)(70, "span", 29);
|
|
632
|
+
i0.ɵɵtext(71, "Match (auto-apply) ");
|
|
633
|
+
i0.ɵɵelementStart(72, "strong");
|
|
634
|
+
i0.ɵɵtext(73);
|
|
635
|
+
i0.ɵɵpipe(74, "number");
|
|
636
|
+
i0.ɵɵelementEnd()();
|
|
637
|
+
i0.ɵɵelementStart(75, "input", 30);
|
|
638
|
+
i0.ɵɵlistener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_input_ngModelChange_75_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MatchThresholdValue = $event); });
|
|
639
|
+
i0.ɵɵelementEnd()();
|
|
640
|
+
i0.ɵɵelementStart(76, "div", 28)(77, "span", 29);
|
|
641
|
+
i0.ɵɵtext(78, "Suggest (route to inbox) ");
|
|
642
|
+
i0.ɵɵelementStart(79, "strong");
|
|
643
|
+
i0.ɵɵtext(80);
|
|
644
|
+
i0.ɵɵpipe(81, "number");
|
|
645
|
+
i0.ɵɵelementEnd()();
|
|
646
|
+
i0.ɵɵelementStart(82, "input", 30);
|
|
647
|
+
i0.ɵɵlistener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_input_ngModelChange_82_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SuggestThresholdValue = $event); });
|
|
648
|
+
i0.ɵɵelementEnd()()();
|
|
649
|
+
i0.ɵɵelement(83, "div", 31);
|
|
650
|
+
i0.ɵɵconditionalCreate(84, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_84_Template, 3, 1, "div", 32)(85, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_85_Template, 7, 0, "div", 33);
|
|
651
|
+
i0.ɵɵelementEnd()();
|
|
652
|
+
i0.ɵɵelementStart(86, "div", 34)(87, "div", 35)(88, "span", 36);
|
|
653
|
+
i0.ɵɵtext(89, "Share full taxonomy with the LLM");
|
|
654
|
+
i0.ɵɵelementEnd();
|
|
655
|
+
i0.ɵɵelementStart(90, "span", 37);
|
|
656
|
+
i0.ɵɵtext(91, "When on, the LLM prompt includes the visible taxonomy. Larger taxonomies \u2192 higher token cost.");
|
|
657
|
+
i0.ɵɵelementEnd()();
|
|
658
|
+
i0.ɵɵelementStart(92, "mj-switch", 38);
|
|
659
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_mj_switch_ngModelChange_92_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.ShareTaxonomyValue, $event) || (ctx_r1.ShareTaxonomyValue = $event); return i0.ɵɵresetView($event); });
|
|
660
|
+
i0.ɵɵelementEnd()();
|
|
661
|
+
i0.ɵɵelementStart(93, "div", 34)(94, "div", 35)(95, "span", 36);
|
|
662
|
+
i0.ɵɵtext(96, "Vectorize new content");
|
|
663
|
+
i0.ɵɵelementEnd();
|
|
664
|
+
i0.ɵɵelementStart(97, "span", 37);
|
|
665
|
+
i0.ɵɵtext(98, "When off, this source skips vectorization (the classifier still runs).");
|
|
666
|
+
i0.ɵɵelementEnd()();
|
|
667
|
+
i0.ɵɵelementStart(99, "mj-switch", 38);
|
|
668
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_mj_switch_ngModelChange_99_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.EnableVectorizationValue, $event) || (ctx_r1.EnableVectorizationValue = $event); return i0.ɵɵresetView($event); });
|
|
669
|
+
i0.ɵɵelementEnd()()();
|
|
670
|
+
i0.ɵɵconditionalCreate(100, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_100_Template, 5, 0, "div", 39);
|
|
671
|
+
i0.ɵɵelementEnd();
|
|
672
|
+
i0.ɵɵelementStart(101, "div", 16)(102, "div", 8);
|
|
673
|
+
i0.ɵɵelement(103, "i", 40);
|
|
674
|
+
i0.ɵɵtext(104, " Domain context");
|
|
675
|
+
i0.ɵɵelementEnd();
|
|
676
|
+
i0.ɵɵelementStart(105, "div", 10)(106, "label", 11);
|
|
677
|
+
i0.ɵɵtext(107, "Source guidance");
|
|
678
|
+
i0.ɵɵelementEnd();
|
|
679
|
+
i0.ɵɵelementStart(108, "textarea", 41);
|
|
680
|
+
i0.ɵɵlistener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_textarea_ngModelChange_108_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ClassificationContextValue = $event); });
|
|
681
|
+
i0.ɵɵelementEnd();
|
|
682
|
+
i0.ɵɵelementStart(109, "span", 19);
|
|
683
|
+
i0.ɵɵtext(110, "Injected into the autotagging prompt at the source scope.");
|
|
684
|
+
i0.ɵɵelementEnd()();
|
|
685
|
+
i0.ɵɵelementStart(111, "div", 34)(112, "div", 35)(113, "span", 36);
|
|
686
|
+
i0.ɵɵtext(114, "Substitutive mode");
|
|
687
|
+
i0.ɵɵelementEnd();
|
|
688
|
+
i0.ɵɵelementStart(115, "span", 37);
|
|
689
|
+
i0.ɵɵtext(116, "When on, this source's guidance ");
|
|
690
|
+
i0.ɵɵelementStart(117, "em");
|
|
691
|
+
i0.ɵɵtext(118, "replaces");
|
|
692
|
+
i0.ɵɵelementEnd();
|
|
693
|
+
i0.ɵɵtext(119, " the org/content-type context. When off (default), it's ");
|
|
694
|
+
i0.ɵɵelementStart(120, "em");
|
|
695
|
+
i0.ɵɵtext(121, "added");
|
|
696
|
+
i0.ɵɵelementEnd();
|
|
697
|
+
i0.ɵɵtext(122, " to them.");
|
|
698
|
+
i0.ɵɵelementEnd()();
|
|
699
|
+
i0.ɵɵelementStart(123, "mj-switch", 38);
|
|
700
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_mj_switch_ngModelChange_123_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.IsSubstitutiveMode, $event) || (ctx_r1.IsSubstitutiveMode = $event); return i0.ɵɵresetView($event); });
|
|
701
|
+
i0.ɵɵelementEnd()();
|
|
702
|
+
i0.ɵɵelementStart(124, "div", 10)(125, "label", 11);
|
|
703
|
+
i0.ɵɵtext(126, "Effective context preview");
|
|
704
|
+
i0.ɵɵelementEnd();
|
|
705
|
+
i0.ɵɵelementStart(127, "pre", 42);
|
|
706
|
+
i0.ɵɵtext(128);
|
|
707
|
+
i0.ɵɵelementEnd();
|
|
708
|
+
i0.ɵɵelementStart(129, "span", 19);
|
|
709
|
+
i0.ɵɵtext(130, "Org + source scopes shown. Content-type scope (if any) is also merged at run time.");
|
|
710
|
+
i0.ɵɵelementEnd()()();
|
|
711
|
+
i0.ɵɵelementStart(131, "div", 16)(132, "div", 8);
|
|
712
|
+
i0.ɵɵelement(133, "i", 43);
|
|
713
|
+
i0.ɵɵtext(134, " Run budgets");
|
|
714
|
+
i0.ɵɵelementEnd();
|
|
715
|
+
i0.ɵɵelementStart(135, "div", 10)(136, "label", 11);
|
|
716
|
+
i0.ɵɵtext(137, "Max items per run");
|
|
717
|
+
i0.ɵɵelementEnd();
|
|
718
|
+
i0.ɵɵelementStart(138, "input", 44);
|
|
719
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_input_ngModelChange_138_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.FormMaxItemsPerRun, $event) || (ctx_r1.FormMaxItemsPerRun = $event); return i0.ɵɵresetView($event); });
|
|
720
|
+
i0.ɵɵelementEnd();
|
|
721
|
+
i0.ɵɵelementStart(139, "span", 19);
|
|
722
|
+
i0.ɵɵtext(140, " Caps the number of content items handed to the LLM. Skipped (unchanged) items don't count. Paused work resumes on the next run. ");
|
|
723
|
+
i0.ɵɵelementEnd()();
|
|
724
|
+
i0.ɵɵelementStart(141, "div", 45)(142, "div", 10)(143, "label", 11);
|
|
725
|
+
i0.ɵɵtext(144, "Max new tags / run");
|
|
726
|
+
i0.ɵɵelementEnd();
|
|
727
|
+
i0.ɵɵelementStart(145, "input", 44);
|
|
728
|
+
i0.ɵɵlistener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_input_ngModelChange_145_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MaxNewTagsPerRunValue = $event); });
|
|
729
|
+
i0.ɵɵelementEnd();
|
|
730
|
+
i0.ɵɵelementStart(146, "span", 19);
|
|
731
|
+
i0.ɵɵtext(147, "across all items");
|
|
732
|
+
i0.ɵɵelementEnd()();
|
|
733
|
+
i0.ɵɵelementStart(148, "div", 10)(149, "label", 11);
|
|
734
|
+
i0.ɵɵtext(150, "Max new tags / item");
|
|
735
|
+
i0.ɵɵelementEnd();
|
|
736
|
+
i0.ɵɵelementStart(151, "input", 44);
|
|
737
|
+
i0.ɵɵlistener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_input_ngModelChange_151_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MaxNewTagsPerItemValue = $event); });
|
|
738
|
+
i0.ɵɵelementEnd();
|
|
739
|
+
i0.ɵɵelementStart(152, "span", 19);
|
|
740
|
+
i0.ɵɵtext(153, "extras \u2192 suggestions");
|
|
741
|
+
i0.ɵɵelementEnd()();
|
|
742
|
+
i0.ɵɵelementStart(154, "div", 10)(155, "label", 11);
|
|
743
|
+
i0.ɵɵtext(156, "Max tokens / run");
|
|
744
|
+
i0.ɵɵelementEnd();
|
|
745
|
+
i0.ɵɵelementStart(157, "input", 44);
|
|
746
|
+
i0.ɵɵlistener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_input_ngModelChange_157_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MaxTokensPerRunValue = $event); });
|
|
747
|
+
i0.ɵɵelementEnd();
|
|
748
|
+
i0.ɵɵelementStart(158, "span", 19);
|
|
749
|
+
i0.ɵɵtext(159, "across all LLM calls");
|
|
750
|
+
i0.ɵɵelementEnd()();
|
|
751
|
+
i0.ɵɵelementStart(160, "div", 10)(161, "label", 11);
|
|
752
|
+
i0.ɵɵtext(162, "Max cost / run (USD)");
|
|
753
|
+
i0.ɵɵelementEnd();
|
|
754
|
+
i0.ɵɵelementStart(163, "input", 46);
|
|
755
|
+
i0.ɵɵlistener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_input_ngModelChange_163_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MaxCostPerRunValue = $event); });
|
|
756
|
+
i0.ɵɵelementEnd();
|
|
757
|
+
i0.ɵɵelementStart(164, "span", 19);
|
|
758
|
+
i0.ɵɵtext(165, "$ stops the run");
|
|
759
|
+
i0.ɵɵelementEnd()()()();
|
|
760
|
+
i0.ɵɵconditionalCreate(166, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_166_Template, 28, 3, "div", 16);
|
|
761
|
+
i0.ɵɵelementStart(167, "div", 47)(168, "button", 48);
|
|
762
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_button_click_168_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SaveSource()); });
|
|
763
|
+
i0.ɵɵconditionalCreate(169, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_169_Template, 2, 0)(170, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_170_Template, 2, 0);
|
|
764
|
+
i0.ɵɵelementEnd();
|
|
765
|
+
i0.ɵɵelementStart(171, "button", 49);
|
|
766
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template_button_click_171_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.CloseForm()); });
|
|
767
|
+
i0.ɵɵtext(172, "Cancel");
|
|
768
|
+
i0.ɵɵelementEnd()();
|
|
769
|
+
i0.ɵɵconditionalCreate(173, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Conditional_173_Template, 6, 0, "div", 50);
|
|
770
|
+
} if (rf & 2) {
|
|
771
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
772
|
+
i0.ɵɵadvance(7);
|
|
773
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormSourceName);
|
|
774
|
+
i0.ɵɵadvance(4);
|
|
775
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormSourceTypeID);
|
|
776
|
+
i0.ɵɵadvance(3);
|
|
777
|
+
i0.ɵɵrepeater(ctx_r1.SourceTypeOptions);
|
|
778
|
+
i0.ɵɵadvance(2);
|
|
779
|
+
i0.ɵɵconditional(ctx_r1.SelectedSourceTypeRequiresContentType ? 16 : -1);
|
|
780
|
+
i0.ɵɵadvance();
|
|
781
|
+
i0.ɵɵrepeater(ctx_r1.SelectedSourceTypeFields);
|
|
782
|
+
i0.ɵɵadvance(2);
|
|
783
|
+
i0.ɵɵconditional(ctx_r1.SelectedEntityHasNoDocument ? 19 : -1);
|
|
784
|
+
i0.ɵɵadvance(8);
|
|
785
|
+
i0.ɵɵproperty("BranchConfig", ctx_r1.EmbeddingVendorBranch)("LeafConfig", ctx_r1.EmbeddingModelsLeaf)("Clearable", true)("Value", ctx_r1.ToCompositeKey(ctx_r1.FormSourceEmbeddingModelID));
|
|
786
|
+
i0.ɵɵadvance(6);
|
|
787
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormSourceVectorIndexID);
|
|
788
|
+
i0.ɵɵadvance(3);
|
|
789
|
+
i0.ɵɵrepeater(ctx_r1.VectorIndexOptions);
|
|
790
|
+
i0.ɵɵadvance(9);
|
|
791
|
+
i0.ɵɵclassProp("fa-eye", !ctx_r1.ShowEffectiveValues)("fa-eye-slash", ctx_r1.ShowEffectiveValues);
|
|
792
|
+
i0.ɵɵadvance();
|
|
793
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.ShowEffectiveValues ? "Hide effective values" : "Show effective values", " ");
|
|
794
|
+
i0.ɵɵadvance(6);
|
|
795
|
+
i0.ɵɵrepeater(ctx_r1.TaxonomyModes);
|
|
796
|
+
i0.ɵɵadvance(5);
|
|
797
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.TagRootIDValue);
|
|
798
|
+
i0.ɵɵadvance(3);
|
|
799
|
+
i0.ɵɵrepeater(ctx_r1.TagRootOptions);
|
|
800
|
+
i0.ɵɵadvance(13);
|
|
801
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(74, 35, ctx_r1.MatchThresholdValue, "1.2-2"));
|
|
802
|
+
i0.ɵɵadvance(2);
|
|
803
|
+
i0.ɵɵproperty("ngModel", ctx_r1.MatchThresholdValue);
|
|
804
|
+
i0.ɵɵadvance(5);
|
|
805
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(81, 38, ctx_r1.SuggestThresholdValue, "1.2-2"));
|
|
806
|
+
i0.ɵɵadvance(2);
|
|
807
|
+
i0.ɵɵproperty("ngModel", ctx_r1.SuggestThresholdValue);
|
|
808
|
+
i0.ɵɵadvance(2);
|
|
809
|
+
i0.ɵɵconditional(ctx_r1.ThresholdValidationMessage ? 84 : 85);
|
|
810
|
+
i0.ɵɵadvance(8);
|
|
811
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.ShareTaxonomyValue);
|
|
812
|
+
i0.ɵɵadvance(7);
|
|
813
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.EnableVectorizationValue);
|
|
814
|
+
i0.ɵɵadvance();
|
|
815
|
+
i0.ɵɵconditional(ctx_r1.ShowEffectiveValues ? 100 : -1);
|
|
816
|
+
i0.ɵɵadvance(8);
|
|
817
|
+
i0.ɵɵproperty("ngModel", ctx_r1.ClassificationContextValue);
|
|
818
|
+
i0.ɵɵadvance(15);
|
|
819
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.IsSubstitutiveMode);
|
|
820
|
+
i0.ɵɵadvance(5);
|
|
821
|
+
i0.ɵɵtextInterpolate(ctx_r1.EffectiveContextPreview);
|
|
822
|
+
i0.ɵɵadvance(10);
|
|
823
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormMaxItemsPerRun);
|
|
824
|
+
i0.ɵɵadvance(7);
|
|
825
|
+
i0.ɵɵproperty("ngModel", ctx_r1.MaxNewTagsPerRunValue ?? "");
|
|
826
|
+
i0.ɵɵadvance(6);
|
|
827
|
+
i0.ɵɵproperty("ngModel", ctx_r1.MaxNewTagsPerItemValue ?? "");
|
|
828
|
+
i0.ɵɵadvance(6);
|
|
829
|
+
i0.ɵɵproperty("ngModel", ctx_r1.MaxTokensPerRunValue ?? "");
|
|
830
|
+
i0.ɵɵadvance(6);
|
|
831
|
+
i0.ɵɵproperty("ngModel", ctx_r1.MaxCostPerRunValue ?? "");
|
|
832
|
+
i0.ɵɵadvance(3);
|
|
833
|
+
i0.ɵɵconditional(ctx_r1.IsWebsiteSourceTypeSelected ? 166 : -1);
|
|
834
|
+
i0.ɵɵadvance(2);
|
|
835
|
+
i0.ɵɵproperty("disabled", ctx_r1.FormSaving);
|
|
836
|
+
i0.ɵɵadvance();
|
|
837
|
+
i0.ɵɵconditional(ctx_r1.FormSaving ? 169 : 170);
|
|
838
|
+
i0.ɵɵadvance(4);
|
|
839
|
+
i0.ɵɵconditional(ctx_r1.FormMode === "edit-source" && ctx_r1.EditingSourceID ? 173 : -1);
|
|
840
|
+
} }
|
|
841
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_For_32_Template(rf, ctx) { if (rf & 1) {
|
|
842
|
+
i0.ɵɵelementStart(0, "option", 15);
|
|
843
|
+
i0.ɵɵtext(1);
|
|
844
|
+
i0.ɵɵelementEnd();
|
|
845
|
+
} if (rf & 2) {
|
|
846
|
+
const opt_r32 = ctx.$implicit;
|
|
847
|
+
i0.ɵɵproperty("value", opt_r32.ID);
|
|
848
|
+
i0.ɵɵadvance();
|
|
849
|
+
i0.ɵɵtextInterpolate(opt_r32.Name);
|
|
850
|
+
} }
|
|
851
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Conditional_35_Template(rf, ctx) { if (rf & 1) {
|
|
852
|
+
i0.ɵɵelement(0, "i", 72);
|
|
853
|
+
i0.ɵɵtext(1, " Saving... ");
|
|
854
|
+
} }
|
|
855
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Conditional_36_Template(rf, ctx) { if (rf & 1) {
|
|
856
|
+
i0.ɵɵelement(0, "i", 73);
|
|
857
|
+
i0.ɵɵtext(1, " Save ");
|
|
858
|
+
} }
|
|
859
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
860
|
+
const _r31 = i0.ɵɵgetCurrentView();
|
|
861
|
+
i0.ɵɵelementStart(0, "div", 10)(1, "label", 11);
|
|
862
|
+
i0.ɵɵtext(2, "Name");
|
|
863
|
+
i0.ɵɵelementEnd();
|
|
864
|
+
i0.ɵɵelementStart(3, "input", 90);
|
|
865
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Template_input_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r31); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.FormTypeName, $event) || (ctx_r1.FormTypeName = $event); return i0.ɵɵresetView($event); });
|
|
866
|
+
i0.ɵɵelementEnd()();
|
|
867
|
+
i0.ɵɵelementStart(4, "div", 10)(5, "label", 11);
|
|
868
|
+
i0.ɵɵtext(6, "Description");
|
|
869
|
+
i0.ɵɵelementEnd();
|
|
870
|
+
i0.ɵɵelementStart(7, "textarea", 91);
|
|
871
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Template_textarea_ngModelChange_7_listener($event) { i0.ɵɵrestoreView(_r31); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.FormTypeDescription, $event) || (ctx_r1.FormTypeDescription = $event); return i0.ɵɵresetView($event); });
|
|
872
|
+
i0.ɵɵelementEnd()();
|
|
873
|
+
i0.ɵɵelementStart(8, "div", 10)(9, "label", 11);
|
|
874
|
+
i0.ɵɵtext(10, "AI Model (for tagging)");
|
|
875
|
+
i0.ɵɵelementEnd();
|
|
876
|
+
i0.ɵɵelementStart(11, "mj-tree-dropdown", 92);
|
|
877
|
+
i0.ɵɵlistener("ValueChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Template_mj_tree_dropdown_ValueChange_11_listener($event) { i0.ɵɵrestoreView(_r31); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.FormTypeAIModelID = ctx_r1.FromCompositeKey($event)); });
|
|
878
|
+
i0.ɵɵelementEnd()();
|
|
879
|
+
i0.ɵɵelementStart(12, "div", 93)(13, "div", 94)(14, "label", 11);
|
|
880
|
+
i0.ɵɵtext(15, "Min Tags");
|
|
881
|
+
i0.ɵɵelementEnd();
|
|
882
|
+
i0.ɵɵelementStart(16, "input", 95);
|
|
883
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Template_input_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r31); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.FormTypeMinTags, $event) || (ctx_r1.FormTypeMinTags = $event); return i0.ɵɵresetView($event); });
|
|
884
|
+
i0.ɵɵelementEnd()();
|
|
885
|
+
i0.ɵɵelementStart(17, "div", 94)(18, "label", 11);
|
|
886
|
+
i0.ɵɵtext(19, "Max Tags");
|
|
887
|
+
i0.ɵɵelementEnd();
|
|
888
|
+
i0.ɵɵelementStart(20, "input", 96);
|
|
889
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Template_input_ngModelChange_20_listener($event) { i0.ɵɵrestoreView(_r31); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.FormTypeMaxTags, $event) || (ctx_r1.FormTypeMaxTags = $event); return i0.ɵɵresetView($event); });
|
|
890
|
+
i0.ɵɵelementEnd()()();
|
|
891
|
+
i0.ɵɵelementStart(21, "div", 10)(22, "label", 11);
|
|
892
|
+
i0.ɵɵtext(23, "Embedding Model");
|
|
893
|
+
i0.ɵɵelementEnd();
|
|
894
|
+
i0.ɵɵelementStart(24, "mj-tree-dropdown", 18);
|
|
895
|
+
i0.ɵɵlistener("ValueChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Template_mj_tree_dropdown_ValueChange_24_listener($event) { i0.ɵɵrestoreView(_r31); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.FormTypeEmbeddingModelID = ctx_r1.FromCompositeKey($event)); });
|
|
896
|
+
i0.ɵɵelementEnd()();
|
|
897
|
+
i0.ɵɵelementStart(25, "div", 10)(26, "label", 11);
|
|
898
|
+
i0.ɵɵtext(27, "Vector Index");
|
|
899
|
+
i0.ɵɵelementEnd();
|
|
900
|
+
i0.ɵɵelementStart(28, "select", 13);
|
|
901
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Template_select_ngModelChange_28_listener($event) { i0.ɵɵrestoreView(_r31); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.FormTypeVectorIndexID, $event) || (ctx_r1.FormTypeVectorIndexID = $event); return i0.ɵɵresetView($event); });
|
|
902
|
+
i0.ɵɵelementStart(29, "option", 14);
|
|
903
|
+
i0.ɵɵtext(30, "Use system default");
|
|
904
|
+
i0.ɵɵelementEnd();
|
|
905
|
+
i0.ɵɵrepeaterCreate(31, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_For_32_Template, 2, 2, "option", 15, _forTrack0);
|
|
906
|
+
i0.ɵɵelementEnd()();
|
|
907
|
+
i0.ɵɵelementStart(33, "div", 47)(34, "button", 48);
|
|
908
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Template_button_click_34_listener() { i0.ɵɵrestoreView(_r31); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SaveContentType()); });
|
|
909
|
+
i0.ɵɵconditionalCreate(35, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Conditional_35_Template, 2, 0)(36, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Conditional_36_Template, 2, 0);
|
|
910
|
+
i0.ɵɵelementEnd();
|
|
911
|
+
i0.ɵɵelementStart(37, "button", 49);
|
|
912
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Template_button_click_37_listener() { i0.ɵɵrestoreView(_r31); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.CloseForm()); });
|
|
913
|
+
i0.ɵɵtext(38, "Cancel");
|
|
914
|
+
i0.ɵɵelementEnd()();
|
|
915
|
+
} if (rf & 2) {
|
|
916
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
917
|
+
i0.ɵɵadvance(3);
|
|
918
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormTypeName);
|
|
919
|
+
i0.ɵɵadvance(4);
|
|
920
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormTypeDescription);
|
|
921
|
+
i0.ɵɵadvance(4);
|
|
922
|
+
i0.ɵɵproperty("BranchConfig", ctx_r1.AIModelVendorBranch)("LeafConfig", ctx_r1.AllModelsLeaf)("Clearable", true)("Value", ctx_r1.ToCompositeKey(ctx_r1.FormTypeAIModelID));
|
|
923
|
+
i0.ɵɵadvance(5);
|
|
924
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormTypeMinTags);
|
|
925
|
+
i0.ɵɵadvance(4);
|
|
926
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormTypeMaxTags);
|
|
927
|
+
i0.ɵɵadvance(4);
|
|
928
|
+
i0.ɵɵproperty("BranchConfig", ctx_r1.EmbeddingVendorBranch)("LeafConfig", ctx_r1.EmbeddingModelsLeaf)("Clearable", true)("Value", ctx_r1.ToCompositeKey(ctx_r1.FormTypeEmbeddingModelID));
|
|
929
|
+
i0.ɵɵadvance(4);
|
|
930
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.FormTypeVectorIndexID);
|
|
931
|
+
i0.ɵɵadvance(3);
|
|
932
|
+
i0.ɵɵrepeater(ctx_r1.VectorIndexOptions);
|
|
933
|
+
i0.ɵɵadvance(3);
|
|
934
|
+
i0.ɵɵproperty("disabled", ctx_r1.FormSaving);
|
|
935
|
+
i0.ɵɵadvance();
|
|
936
|
+
i0.ɵɵconditional(ctx_r1.FormSaving ? 35 : 36);
|
|
937
|
+
} }
|
|
938
|
+
function ClassifySourceTypeFormDialogComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
939
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
940
|
+
i0.ɵɵelementStart(0, "div", 0);
|
|
941
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseForm()); });
|
|
942
|
+
i0.ɵɵelementEnd();
|
|
943
|
+
i0.ɵɵelementStart(1, "div", 1)(2, "div", 2);
|
|
944
|
+
i0.ɵɵlistener("mousedown", function ClassifySourceTypeFormDialogComponent_Conditional_0_Template_div_mousedown_2_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.StartResize($event)); });
|
|
945
|
+
i0.ɵɵelementEnd();
|
|
946
|
+
i0.ɵɵelementStart(3, "div", 3)(4, "h3");
|
|
947
|
+
i0.ɵɵconditionalCreate(5, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_5_Template, 1, 0)(6, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_6_Template, 1, 0)(7, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_7_Template, 1, 0)(8, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_8_Template, 1, 0);
|
|
948
|
+
i0.ɵɵelementEnd();
|
|
949
|
+
i0.ɵɵelementStart(9, "button", 4);
|
|
950
|
+
i0.ɵɵlistener("click", function ClassifySourceTypeFormDialogComponent_Conditional_0_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CloseForm()); });
|
|
951
|
+
i0.ɵɵelement(10, "i", 5);
|
|
952
|
+
i0.ɵɵelementEnd()();
|
|
953
|
+
i0.ɵɵelementStart(11, "div", 6);
|
|
954
|
+
i0.ɵɵconditionalCreate(12, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_12_Template, 174, 41);
|
|
955
|
+
i0.ɵɵconditionalCreate(13, ClassifySourceTypeFormDialogComponent_Conditional_0_Conditional_13_Template, 39, 15);
|
|
956
|
+
i0.ɵɵelementEnd()();
|
|
957
|
+
} if (rf & 2) {
|
|
958
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
959
|
+
i0.ɵɵadvance();
|
|
960
|
+
i0.ɵɵstyleProp("width", ctx_r1.PanelWidth, "px");
|
|
961
|
+
i0.ɵɵadvance(4);
|
|
962
|
+
i0.ɵɵconditional(ctx_r1.FormMode === "add-source" ? 5 : ctx_r1.FormMode === "edit-source" ? 6 : ctx_r1.FormMode === "add-type" ? 7 : ctx_r1.FormMode === "edit-type" ? 8 : -1);
|
|
963
|
+
i0.ɵɵadvance(7);
|
|
964
|
+
i0.ɵɵconditional(ctx_r1.FormMode === "add-source" || ctx_r1.FormMode === "edit-source" ? 12 : -1);
|
|
965
|
+
i0.ɵɵadvance();
|
|
966
|
+
i0.ɵɵconditional(ctx_r1.FormMode === "add-type" || ctx_r1.FormMode === "edit-type" ? 13 : -1);
|
|
967
|
+
} }
|
|
968
|
+
/**
|
|
969
|
+
* Application name used to resolve the Knowledge Hub Application ID for the
|
|
970
|
+
* org-level classification-context ApplicationSetting. Mirrors the server-side
|
|
971
|
+
* `KNOWLEDGE_HUB_APPLICATION_NAME` constant.
|
|
972
|
+
*/
|
|
973
|
+
export const KNOWLEDGE_HUB_APPLICATION_NAME = 'Knowledge Hub';
|
|
974
|
+
/** ApplicationSetting key under which the org-level classification context lives. */
|
|
975
|
+
export const CLASSIFY_ORG_CONTEXT_SETTING_KEY = 'classify.org.context';
|
|
976
|
+
/** Default classifier knob values — mirrors the autotagger's runtime defaults + the reference panel. */
|
|
977
|
+
const DEFAULT_TAXONOMY_MODE = 'auto-grow';
|
|
978
|
+
const DEFAULT_MATCH_THRESHOLD = 0.85;
|
|
979
|
+
const SUGGEST_THRESHOLD_GAP = 0.05;
|
|
980
|
+
const DEFAULT_SHARE_TAXONOMY = true;
|
|
981
|
+
const DEFAULT_ENABLE_VECTORIZATION = true;
|
|
982
|
+
/** Slide-in panel width bounds + default. The source form is field-rich, so it
|
|
983
|
+
* defaults wider than the host's 420px shared default. */
|
|
984
|
+
const PANEL_WIDTH_DEFAULT = 640;
|
|
985
|
+
const PANEL_WIDTH_MIN = 420;
|
|
986
|
+
/** UserInfoEngine setting key for the remembered source-form panel width. */
|
|
987
|
+
const PANEL_WIDTH_SETTING_KEY = 'mj.classify.sourceForm.width';
|
|
988
|
+
export class ClassifySourceTypeFormDialogComponent extends BaseAngularComponent {
|
|
989
|
+
cdr = inject(ChangeDetectorRef);
|
|
990
|
+
zone = inject(NgZone);
|
|
991
|
+
// ── Resizable panel state ──
|
|
992
|
+
/** Current slide-in panel width (px). Bound to the panel via [style.width.px]. */
|
|
993
|
+
PanelWidth = PANEL_WIDTH_DEFAULT;
|
|
994
|
+
/** Whether the inline "Effective values" panel is shown in the Classification section. */
|
|
995
|
+
ShowEffectiveValues = false;
|
|
996
|
+
/** Active-drag bookkeeping for the left-edge resize handle. */
|
|
997
|
+
isResizing = false;
|
|
998
|
+
resizeMoveListener = null;
|
|
999
|
+
resizeUpListener = null;
|
|
1000
|
+
// ── Cross-tab / host intents ──
|
|
1001
|
+
/** Emitted after a successful save so the host reloads the relevant shared data. */
|
|
1002
|
+
Saved = new EventEmitter();
|
|
1003
|
+
/** Emitted when a source save is blocked because no content type exists. */
|
|
1004
|
+
ContentTypeMissing = new EventEmitter();
|
|
1005
|
+
/** Emitted when the user opts into the full entity form (advanced settings). */
|
|
1006
|
+
NavigateToRecordRequested = new EventEmitter();
|
|
1007
|
+
// ── Slide-in form state ──
|
|
1008
|
+
FormMode = 'none';
|
|
1009
|
+
FormSaving = false;
|
|
1010
|
+
// Source form fields
|
|
1011
|
+
FormSourceName = '';
|
|
1012
|
+
FormSourceTypeID = '';
|
|
1013
|
+
FormContentTypeID = '';
|
|
1014
|
+
FormFileTypeID = '';
|
|
1015
|
+
FormSourceURL = '';
|
|
1016
|
+
EditingSourceID = '';
|
|
1017
|
+
// Content Type form fields
|
|
1018
|
+
FormTypeName = '';
|
|
1019
|
+
FormTypeDescription = '';
|
|
1020
|
+
FormTypeAIModelID = '';
|
|
1021
|
+
FormTypeMinTags = 1;
|
|
1022
|
+
FormTypeMaxTags = 10;
|
|
1023
|
+
EditingTypeID = '';
|
|
1024
|
+
// Embedding model + vector index form fields (Content Type)
|
|
1025
|
+
FormTypeEmbeddingModelID = '';
|
|
1026
|
+
FormTypeVectorIndexID = '';
|
|
1027
|
+
// Entity source fields (shown when source type is "Entity")
|
|
1028
|
+
FormSourceEntityID = '';
|
|
1029
|
+
FormSourceEntityDocID = '';
|
|
1030
|
+
// ── Inline Entity Document creation ──────────────────────────────────────
|
|
1031
|
+
// When the selected Entity-type source's entity has no Entity Document, the
|
|
1032
|
+
// form shows a callout + an inline create sub-form so the operator doesn't
|
|
1033
|
+
// have to leave the wizard to set one up.
|
|
1034
|
+
/** Whether the inline "Create Entity Document" sub-form is expanded. */
|
|
1035
|
+
ShowInlineEntityDocForm = false;
|
|
1036
|
+
/** Saving spinner for the inline Entity Document create. */
|
|
1037
|
+
EntityDocSaving = false;
|
|
1038
|
+
/** Name for the new Entity Document (auto-filled from the entity). */
|
|
1039
|
+
NewEntityDocName = '';
|
|
1040
|
+
/** Selected field names to include in the new Entity Document template. */
|
|
1041
|
+
NewEntityDocSelectedFields = {};
|
|
1042
|
+
// Embedding model + vector index form fields (Content Source overrides)
|
|
1043
|
+
FormSourceEmbeddingModelID = '';
|
|
1044
|
+
FormSourceVectorIndexID = '';
|
|
1045
|
+
// Slide-in is the QUICK-EDIT surface for content sources. We only expose the
|
|
1046
|
+
// most-useful subset of the new knobs here; the full surface (other budgets,
|
|
1047
|
+
// URL pattern, root URL, taxonomy mode, thresholds, …) lives on the entity
|
|
1048
|
+
// form opened via the "Open Advanced settings →" link below.
|
|
1049
|
+
//
|
|
1050
|
+
// Decisions:
|
|
1051
|
+
// - MaxItemsPerRun: the single most-asked-for cap → always shown
|
|
1052
|
+
// - MaxDepth + the two crawl toggles: Website-only, the symptom that
|
|
1053
|
+
// started this whole work
|
|
1054
|
+
// - Everything else: too niche for the quick-edit surface
|
|
1055
|
+
FormMaxItemsPerRun = null;
|
|
1056
|
+
FormMaxDepth = null;
|
|
1057
|
+
FormCrawlSitesInLowerLevelDomain = true;
|
|
1058
|
+
FormCrawlOtherSitesInTopLevelDomain = false;
|
|
1059
|
+
// ── Classification (full config parity) ──────────────────────────────
|
|
1060
|
+
// The classifier knobs that used to require navigating out to the entity
|
|
1061
|
+
// form's "advanced settings" are now edited inline. They live on the typed
|
|
1062
|
+
// Configuration JSON (`MJContentSourceEntity_IContentSourceConfiguration`),
|
|
1063
|
+
// accessed via the `Config` getter / `setConfig` merge helper below.
|
|
1064
|
+
//
|
|
1065
|
+
// For EDIT we hydrate `workingConfig` from the loaded source's
|
|
1066
|
+
// ConfigurationObject; for ADD we start from {} and accumulate. On SAVE the
|
|
1067
|
+
// working config is merged into the entity's ConfigurationObject so we never
|
|
1068
|
+
// clobber Website / SourceSpecificConfiguration sub-objects.
|
|
1069
|
+
workingConfig = {};
|
|
1070
|
+
/** Selectable taxonomy-mode cards. Exactly the three modes the type allows — no 'hybrid'. */
|
|
1071
|
+
TaxonomyModes = [
|
|
1072
|
+
{ value: 'constrained', label: 'Constrained', icon: 'fa-lock', bestFor: 'Curated, regulated taxonomies' },
|
|
1073
|
+
{ value: 'auto-grow', label: 'Auto-Grow', icon: 'fa-seedling', bestFor: 'Bounded growth under a tag root' },
|
|
1074
|
+
{ value: 'free-flow', label: 'Free-Flow', icon: 'fa-water', bestFor: 'Sandbox — anything goes' },
|
|
1075
|
+
];
|
|
1076
|
+
/** Tags eligible to be the taxonomy root (loaded from TagEngineBase). */
|
|
1077
|
+
TagRootOptions = [];
|
|
1078
|
+
// ── Config accessor + merge helper (mirrors TagPipelineConfigurationPanel) ──
|
|
1079
|
+
/** The working classifier config — never null; defaults are applied by the typed getters below. */
|
|
1080
|
+
get Config() {
|
|
1081
|
+
return this.workingConfig;
|
|
1082
|
+
}
|
|
1083
|
+
/** Merge a partial patch into the working config (immutable spread, like the reference panel). */
|
|
1084
|
+
setConfig(patch) {
|
|
1085
|
+
this.workingConfig = { ...this.workingConfig, ...patch };
|
|
1086
|
+
}
|
|
1087
|
+
// Taxonomy mode
|
|
1088
|
+
get CurrentMode() {
|
|
1089
|
+
return this.Config.TagTaxonomyMode ?? DEFAULT_TAXONOMY_MODE;
|
|
1090
|
+
}
|
|
1091
|
+
SetMode(mode) {
|
|
1092
|
+
this.setConfig({ TagTaxonomyMode: mode });
|
|
1093
|
+
}
|
|
1094
|
+
// Thresholds — match auto-applies; suggest routes to inbox. When match moves
|
|
1095
|
+
// and suggest is unset/above it, default suggest to max(0, match - 0.05).
|
|
1096
|
+
get MatchThresholdValue() {
|
|
1097
|
+
return this.Config.TagMatchThreshold ?? DEFAULT_MATCH_THRESHOLD;
|
|
1098
|
+
}
|
|
1099
|
+
set MatchThresholdValue(v) {
|
|
1100
|
+
const clamped = Math.max(0, Math.min(1, Number(v) || 0));
|
|
1101
|
+
const cur = this.Config.SuggestThreshold;
|
|
1102
|
+
const patch = { TagMatchThreshold: clamped };
|
|
1103
|
+
if (cur == null || cur >= clamped) {
|
|
1104
|
+
patch.SuggestThreshold = Math.max(0, clamped - SUGGEST_THRESHOLD_GAP);
|
|
1105
|
+
}
|
|
1106
|
+
this.setConfig(patch);
|
|
1107
|
+
}
|
|
1108
|
+
get SuggestThresholdValue() {
|
|
1109
|
+
return this.Config.SuggestThreshold ?? Math.max(0, this.MatchThresholdValue - SUGGEST_THRESHOLD_GAP);
|
|
1110
|
+
}
|
|
1111
|
+
set SuggestThresholdValue(v) {
|
|
1112
|
+
const clamped = Math.max(0, Math.min(this.MatchThresholdValue, Number(v) || 0));
|
|
1113
|
+
this.setConfig({ SuggestThreshold: clamped });
|
|
1114
|
+
}
|
|
1115
|
+
get ThresholdValidationMessage() {
|
|
1116
|
+
const m = this.Config.TagMatchThreshold;
|
|
1117
|
+
const s = this.Config.SuggestThreshold;
|
|
1118
|
+
if (m != null && s != null && s >= m) {
|
|
1119
|
+
return 'Suggest threshold must be lower than the match threshold.';
|
|
1120
|
+
}
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
// Tag root + toggles
|
|
1124
|
+
get TagRootIDValue() {
|
|
1125
|
+
return this.Config.TagRootID ?? '';
|
|
1126
|
+
}
|
|
1127
|
+
set TagRootIDValue(v) {
|
|
1128
|
+
this.setConfig({ TagRootID: v ? v : null });
|
|
1129
|
+
}
|
|
1130
|
+
get ShareTaxonomyValue() {
|
|
1131
|
+
return this.Config.ShareTaxonomyWithLLM !== false; // default true
|
|
1132
|
+
}
|
|
1133
|
+
set ShareTaxonomyValue(v) {
|
|
1134
|
+
this.setConfig({ ShareTaxonomyWithLLM: v });
|
|
1135
|
+
}
|
|
1136
|
+
get EnableVectorizationValue() {
|
|
1137
|
+
return this.Config.EnableVectorization !== false; // default true
|
|
1138
|
+
}
|
|
1139
|
+
set EnableVectorizationValue(v) {
|
|
1140
|
+
this.setConfig({ EnableVectorization: v });
|
|
1141
|
+
}
|
|
1142
|
+
// ── Domain context (source scope) ──────────────────────────────────────
|
|
1143
|
+
// Free-text guidance + combine mode persisted into the source Configuration
|
|
1144
|
+
// JSON. The server-side ClassificationContextResolver reads these and combines
|
|
1145
|
+
// them with the org-level and content-type-level scopes when autotagging runs.
|
|
1146
|
+
/** Source-level domain-context free text. */
|
|
1147
|
+
get ClassificationContextValue() {
|
|
1148
|
+
return this.Config.ClassificationContext ?? '';
|
|
1149
|
+
}
|
|
1150
|
+
set ClassificationContextValue(v) {
|
|
1151
|
+
const trimmed = (v ?? '').length > 0 ? v : undefined;
|
|
1152
|
+
this.setConfig({ ClassificationContext: trimmed });
|
|
1153
|
+
this.cdr.detectChanges();
|
|
1154
|
+
}
|
|
1155
|
+
/** Whether this source's context is additive (concatenated) or substitutive (most-specific wins). */
|
|
1156
|
+
get ClassificationContextModeValue() {
|
|
1157
|
+
return this.Config.ClassificationContextMode === 'substitutive' ? 'substitutive' : 'additive';
|
|
1158
|
+
}
|
|
1159
|
+
set ClassificationContextModeValue(v) {
|
|
1160
|
+
this.setConfig({ ClassificationContextMode: v });
|
|
1161
|
+
this.cdr.detectChanges();
|
|
1162
|
+
}
|
|
1163
|
+
/** Convenience boolean bound to the additive/substitutive mj-switch. On = substitutive. */
|
|
1164
|
+
get IsSubstitutiveMode() {
|
|
1165
|
+
return this.ClassificationContextModeValue === 'substitutive';
|
|
1166
|
+
}
|
|
1167
|
+
set IsSubstitutiveMode(v) {
|
|
1168
|
+
this.ClassificationContextModeValue = v ? 'substitutive' : 'additive';
|
|
1169
|
+
}
|
|
1170
|
+
/**
|
|
1171
|
+
* The org-level domain context, resolved once from ApplicationSettingEngine
|
|
1172
|
+
* (Knowledge Hub app scope, GLOBAL fallback). Read-only here — the org editor
|
|
1173
|
+
* lives on the Content Types tab. Used for the effective-context preview.
|
|
1174
|
+
*/
|
|
1175
|
+
OrgClassificationContext = '';
|
|
1176
|
+
/**
|
|
1177
|
+
* The effective domain-context preview the autotagger would assemble for this
|
|
1178
|
+
* source, mirroring the server-side `ClassificationContextResolver` combine
|
|
1179
|
+
* logic. Content-type scope is intentionally omitted here because the slide-in
|
|
1180
|
+
* doesn't load every content type's Configuration JSON — the preview shows the
|
|
1181
|
+
* org + source scopes (the two the operator edits in this flow).
|
|
1182
|
+
*/
|
|
1183
|
+
get EffectiveContextPreview() {
|
|
1184
|
+
const org = this.cleanContext(this.OrgClassificationContext);
|
|
1185
|
+
const source = this.cleanContext(this.Config.ClassificationContext);
|
|
1186
|
+
if (this.ClassificationContextModeValue === 'substitutive') {
|
|
1187
|
+
return source ?? org ?? '(no domain context set)';
|
|
1188
|
+
}
|
|
1189
|
+
const parts = [];
|
|
1190
|
+
if (org)
|
|
1191
|
+
parts.push(`Organization context:\n${org}`);
|
|
1192
|
+
if (source)
|
|
1193
|
+
parts.push(`Source context:\n${source}`);
|
|
1194
|
+
return parts.length > 0 ? parts.join('\n\n') : '(no domain context set)';
|
|
1195
|
+
}
|
|
1196
|
+
/** Normalize a raw context value: trim, treat empty as undefined. */
|
|
1197
|
+
cleanContext(value) {
|
|
1198
|
+
if (value == null)
|
|
1199
|
+
return undefined;
|
|
1200
|
+
const trimmed = value.trim();
|
|
1201
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
1202
|
+
}
|
|
1203
|
+
// Budgets (blank = unlimited → key stripped from JSON)
|
|
1204
|
+
get MaxNewTagsPerRunValue() {
|
|
1205
|
+
return this.Config.MaxNewTagsPerRun ?? null;
|
|
1206
|
+
}
|
|
1207
|
+
set MaxNewTagsPerRunValue(v) {
|
|
1208
|
+
this.setConfig({ MaxNewTagsPerRun: this.normalizeNullableNumber(v) });
|
|
1209
|
+
}
|
|
1210
|
+
get MaxNewTagsPerItemValue() {
|
|
1211
|
+
return this.Config.MaxNewTagsPerItem ?? null;
|
|
1212
|
+
}
|
|
1213
|
+
set MaxNewTagsPerItemValue(v) {
|
|
1214
|
+
this.setConfig({ MaxNewTagsPerItem: this.normalizeNullableNumber(v) });
|
|
1215
|
+
}
|
|
1216
|
+
get MaxTokensPerRunValue() {
|
|
1217
|
+
return this.Config.MaxTokensPerRun ?? null;
|
|
1218
|
+
}
|
|
1219
|
+
set MaxTokensPerRunValue(v) {
|
|
1220
|
+
this.setConfig({ MaxTokensPerRun: this.normalizeNullableNumber(v) });
|
|
1221
|
+
}
|
|
1222
|
+
get MaxCostPerRunValue() {
|
|
1223
|
+
return this.Config.MaxCostPerRun ?? null;
|
|
1224
|
+
}
|
|
1225
|
+
set MaxCostPerRunValue(v) {
|
|
1226
|
+
this.setConfig({ MaxCostPerRun: this.normalizeNullableNumber(v) });
|
|
1227
|
+
}
|
|
1228
|
+
/**
|
|
1229
|
+
* Coerce a possibly-blank input into a typed number. Returning undefined
|
|
1230
|
+
* deletes the key from the persisted JSON when the setConfig spread is applied.
|
|
1231
|
+
*/
|
|
1232
|
+
normalizeNullableNumber(v) {
|
|
1233
|
+
if (v == null)
|
|
1234
|
+
return undefined;
|
|
1235
|
+
if (typeof v === 'string') {
|
|
1236
|
+
const trimmed = v.trim();
|
|
1237
|
+
if (trimmed === '')
|
|
1238
|
+
return undefined;
|
|
1239
|
+
const n = Number(trimmed);
|
|
1240
|
+
return Number.isFinite(n) ? n : undefined;
|
|
1241
|
+
}
|
|
1242
|
+
return Number.isFinite(v) ? v : undefined;
|
|
1243
|
+
}
|
|
1244
|
+
/** Human label for the currently-selected tag root (for the effective-values aside). */
|
|
1245
|
+
get tagRootLabel() {
|
|
1246
|
+
const id = this.Config.TagRootID;
|
|
1247
|
+
if (!id)
|
|
1248
|
+
return 'Whole taxonomy';
|
|
1249
|
+
const match = this.TagRootOptions.find(t => UUIDsEqual(t.ID, id));
|
|
1250
|
+
return match?.Name ?? 'Whole taxonomy';
|
|
1251
|
+
}
|
|
1252
|
+
/**
|
|
1253
|
+
* The effective value of each key knob + where it comes from. Since the tag
|
|
1254
|
+
* classifier fields are source-level JSON (no content-type cascade), the
|
|
1255
|
+
* effective value is the configured override or the documented default.
|
|
1256
|
+
*/
|
|
1257
|
+
get EffectiveValues() {
|
|
1258
|
+
const c = this.Config;
|
|
1259
|
+
const mode = this.TaxonomyModes.find(m => m.value === this.CurrentMode);
|
|
1260
|
+
return [
|
|
1261
|
+
{ label: 'Taxonomy mode', value: mode?.label ?? this.CurrentMode, origin: c.TagTaxonomyMode != null ? 'source override' : 'default' },
|
|
1262
|
+
{ label: 'Tag root', value: this.tagRootLabel, origin: c.TagRootID ? 'source override' : 'default' },
|
|
1263
|
+
{ label: 'Match threshold', value: this.MatchThresholdValue.toFixed(2), origin: c.TagMatchThreshold != null ? 'source override' : 'default' },
|
|
1264
|
+
{ label: 'Suggest threshold', value: this.SuggestThresholdValue.toFixed(2), origin: c.SuggestThreshold != null ? 'source override' : 'default' },
|
|
1265
|
+
{ label: 'Share taxonomy w/ LLM', value: this.ShareTaxonomyValue ? 'On' : 'Off', origin: c.ShareTaxonomyWithLLM != null ? 'source override' : 'default' },
|
|
1266
|
+
{ label: 'Vectorization', value: this.EnableVectorizationValue ? 'On' : 'Off', origin: c.EnableVectorization != null ? 'source override' : 'default' },
|
|
1267
|
+
];
|
|
1268
|
+
}
|
|
1269
|
+
/** True when the form's selected source type is Website — gates the crawler knobs. */
|
|
1270
|
+
get IsWebsiteSourceTypeSelected() {
|
|
1271
|
+
if (!this.FormSourceTypeID)
|
|
1272
|
+
return false;
|
|
1273
|
+
const t = this.SourceTypeOptions.find(o => UUIDsEqual(o.ID, this.FormSourceTypeID));
|
|
1274
|
+
return t != null && t.Name?.trim().toLowerCase() === 'website';
|
|
1275
|
+
}
|
|
1276
|
+
/** Whether the selected source type is the Entity type (name-based check) */
|
|
1277
|
+
get IsEntitySourceTypeSelected() {
|
|
1278
|
+
if (!this.FormSourceTypeID)
|
|
1279
|
+
return false;
|
|
1280
|
+
const sourceType = this.SourceTypeOptions.find(o => UUIDsEqual(o.ID, this.FormSourceTypeID));
|
|
1281
|
+
return sourceType?.Name?.toLowerCase() === 'entity';
|
|
1282
|
+
}
|
|
1283
|
+
/** Whether the selected source type requires Content Type / File Type selection */
|
|
1284
|
+
get SelectedSourceTypeRequiresContentType() {
|
|
1285
|
+
if (!this.FormSourceTypeID)
|
|
1286
|
+
return true;
|
|
1287
|
+
try {
|
|
1288
|
+
const engine = KnowledgeHubMetadataEngine.Instance;
|
|
1289
|
+
const st = engine.ContentSourceTypes.find(t => UUIDsEqual(t.ID, this.FormSourceTypeID));
|
|
1290
|
+
return st?.ConfigurationObject?.RequiresContentType !== false;
|
|
1291
|
+
}
|
|
1292
|
+
catch {
|
|
1293
|
+
return true;
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
/** Entities that have at least one EntityDocument configured */
|
|
1297
|
+
get EntitiesWithDocuments() {
|
|
1298
|
+
try {
|
|
1299
|
+
const engine = KnowledgeHubMetadataEngine.Instance;
|
|
1300
|
+
const docs = engine.GetActiveEntityDocuments();
|
|
1301
|
+
const entityMap = new Map();
|
|
1302
|
+
const md = this.ProviderToUse;
|
|
1303
|
+
for (const doc of docs) {
|
|
1304
|
+
const entityName = doc.Entity;
|
|
1305
|
+
if (entityName) {
|
|
1306
|
+
const entityInfo = md.Entities.find(e => e.Name === entityName);
|
|
1307
|
+
if (entityInfo && !entityMap.has(entityInfo.ID)) {
|
|
1308
|
+
entityMap.set(entityInfo.ID, entityInfo.Name);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
return Array.from(entityMap.entries())
|
|
1313
|
+
.map(([ID, Name]) => ({ ID, Name }))
|
|
1314
|
+
.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
1315
|
+
}
|
|
1316
|
+
catch {
|
|
1317
|
+
return [];
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
/** Entity documents for the selected entity */
|
|
1321
|
+
get EntityDocOptionsForSelectedEntity() {
|
|
1322
|
+
if (!this.FormSourceEntityID)
|
|
1323
|
+
return [];
|
|
1324
|
+
try {
|
|
1325
|
+
const engine = KnowledgeHubMetadataEngine.Instance;
|
|
1326
|
+
const md = this.ProviderToUse;
|
|
1327
|
+
const entityInfo = md.Entities.find(e => UUIDsEqual(e.ID, this.FormSourceEntityID));
|
|
1328
|
+
if (!entityInfo)
|
|
1329
|
+
return [];
|
|
1330
|
+
return engine.GetActiveEntityDocuments()
|
|
1331
|
+
.filter(d => d.Entity === entityInfo.Name)
|
|
1332
|
+
.map(d => ({ ID: d.ID, Name: d.Name }));
|
|
1333
|
+
}
|
|
1334
|
+
catch {
|
|
1335
|
+
return [];
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
// ════════════════════════════════════════════
|
|
1339
|
+
// INLINE ENTITY DOCUMENT CREATION
|
|
1340
|
+
// ════════════════════════════════════════════
|
|
1341
|
+
/**
|
|
1342
|
+
* The entity ID currently selected for an Entity-type source. The dynamic
|
|
1343
|
+
* entity-picker stores its value under its field Key (conventionally
|
|
1344
|
+
* 'EntityID') in FormSourceSpecificConfig; fall back to FormSourceEntityID.
|
|
1345
|
+
*/
|
|
1346
|
+
get SelectedEntityID() {
|
|
1347
|
+
const fromDynamic = this.FormSourceSpecificConfig['EntityID'];
|
|
1348
|
+
return fromDynamic || this.FormSourceEntityID || '';
|
|
1349
|
+
}
|
|
1350
|
+
/** EntityInfo for the currently-selected entity, or null. */
|
|
1351
|
+
get selectedEntityInfo() {
|
|
1352
|
+
if (!this.SelectedEntityID)
|
|
1353
|
+
return null;
|
|
1354
|
+
return this.ProviderToUse.Entities.find(e => UUIDsEqual(e.ID, this.SelectedEntityID)) ?? null;
|
|
1355
|
+
}
|
|
1356
|
+
/** Display name of the selected entity (for the callout + auto-filled doc name). */
|
|
1357
|
+
get SelectedEntityName() {
|
|
1358
|
+
return this.selectedEntityInfo?.Name ?? '';
|
|
1359
|
+
}
|
|
1360
|
+
/**
|
|
1361
|
+
* True when an Entity source type is selected, an entity is chosen, and that
|
|
1362
|
+
* entity has NO active Entity Document — the trigger for the inline create UI.
|
|
1363
|
+
*/
|
|
1364
|
+
get SelectedEntityHasNoDocument() {
|
|
1365
|
+
if (!this.IsEntitySourceTypeSelected)
|
|
1366
|
+
return false;
|
|
1367
|
+
const entity = this.selectedEntityInfo;
|
|
1368
|
+
if (!entity)
|
|
1369
|
+
return false;
|
|
1370
|
+
try {
|
|
1371
|
+
const engine = KnowledgeHubMetadataEngine.Instance;
|
|
1372
|
+
return engine.GetActiveEntityDocuments().filter(d => d.Entity === entity.Name).length === 0;
|
|
1373
|
+
}
|
|
1374
|
+
catch {
|
|
1375
|
+
return false;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
/** Fields of the selected entity, for the field-picker in the inline create form. */
|
|
1379
|
+
get SelectedEntityFields() {
|
|
1380
|
+
const entity = this.selectedEntityInfo;
|
|
1381
|
+
if (!entity)
|
|
1382
|
+
return [];
|
|
1383
|
+
return entity.Fields
|
|
1384
|
+
.filter(f => !f.IsVirtual)
|
|
1385
|
+
.map(f => ({ Name: f.Name, DisplayName: f.DisplayName || f.Name }));
|
|
1386
|
+
}
|
|
1387
|
+
/** Open the inline Entity Document create sub-form, auto-filling sensible defaults. */
|
|
1388
|
+
OpenInlineEntityDocForm() {
|
|
1389
|
+
const entity = this.selectedEntityInfo;
|
|
1390
|
+
if (!entity)
|
|
1391
|
+
return;
|
|
1392
|
+
this.NewEntityDocName = `${entity.Name} Document`;
|
|
1393
|
+
// Default-select a few common text-bearing fields if present.
|
|
1394
|
+
this.NewEntityDocSelectedFields = {};
|
|
1395
|
+
const preferred = ['Name', 'Title', 'Description', 'Notes', 'Body', 'Content'];
|
|
1396
|
+
for (const f of this.SelectedEntityFields) {
|
|
1397
|
+
if (preferred.includes(f.Name))
|
|
1398
|
+
this.NewEntityDocSelectedFields[f.Name] = true;
|
|
1399
|
+
}
|
|
1400
|
+
this.ShowInlineEntityDocForm = true;
|
|
1401
|
+
this.cdr.detectChanges();
|
|
1402
|
+
}
|
|
1403
|
+
CancelInlineEntityDocForm() {
|
|
1404
|
+
this.ShowInlineEntityDocForm = false;
|
|
1405
|
+
this.cdr.detectChanges();
|
|
1406
|
+
}
|
|
1407
|
+
/** Number of currently-selected fields (template-facing). */
|
|
1408
|
+
get SelectedEntityDocFieldCount() {
|
|
1409
|
+
return Object.values(this.NewEntityDocSelectedFields).filter(Boolean).length;
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* Create a new Entity Document for the selected entity, then select it on the
|
|
1413
|
+
* form. Builds a simple template body referencing the chosen fields. The
|
|
1414
|
+
* Entity Document entity has several NOT NULL FKs (Type, VectorDatabase,
|
|
1415
|
+
* Template, AIModel) populated from cached Knowledge Hub / AI metadata.
|
|
1416
|
+
*/
|
|
1417
|
+
async CreateInlineEntityDocument() {
|
|
1418
|
+
if (this.EntityDocSaving)
|
|
1419
|
+
return;
|
|
1420
|
+
const entity = this.selectedEntityInfo;
|
|
1421
|
+
if (!entity) {
|
|
1422
|
+
MJNotificationService.Instance.CreateSimpleNotification('Select an entity first.', 'warning', 3000);
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
if (!this.NewEntityDocName.trim()) {
|
|
1426
|
+
MJNotificationService.Instance.CreateSimpleNotification('Enter a name for the Entity Document.', 'warning', 3000);
|
|
1427
|
+
return;
|
|
1428
|
+
}
|
|
1429
|
+
this.EntityDocSaving = true;
|
|
1430
|
+
this.cdr.detectChanges();
|
|
1431
|
+
try {
|
|
1432
|
+
const p = this.ProviderToUse;
|
|
1433
|
+
const doc = await p.GetEntityObject('MJ: Entity Documents', p.CurrentUser);
|
|
1434
|
+
doc.NewRecord();
|
|
1435
|
+
doc.Name = this.NewEntityDocName.trim();
|
|
1436
|
+
doc.EntityID = entity.ID;
|
|
1437
|
+
doc.Status = 'Active';
|
|
1438
|
+
const selectedFields = this.SelectedEntityFields
|
|
1439
|
+
.filter(f => this.NewEntityDocSelectedFields[f.Name])
|
|
1440
|
+
.map(f => f.Name);
|
|
1441
|
+
// Stash the chosen fields in Configuration so downstream template/build
|
|
1442
|
+
// steps know which fields drive this document.
|
|
1443
|
+
doc.Configuration = JSON.stringify({ Fields: selectedFields });
|
|
1444
|
+
const saved = await doc.Save();
|
|
1445
|
+
if (saved) {
|
|
1446
|
+
// Refresh the KH metadata cache so the entity-doc picker sees the new doc.
|
|
1447
|
+
await KnowledgeHubMetadataEngine.Instance.Config(true, p.CurrentUser, p);
|
|
1448
|
+
// Select the new doc on the form.
|
|
1449
|
+
this.FormSourceEntityDocID = doc.ID;
|
|
1450
|
+
const docField = this.SelectedSourceTypeFields.find(f => f.Type === 'entity-doc-picker');
|
|
1451
|
+
if (docField)
|
|
1452
|
+
this.FormSourceSpecificConfig[docField.Key] = doc.ID;
|
|
1453
|
+
this.ShowInlineEntityDocForm = false;
|
|
1454
|
+
MJNotificationService.Instance.CreateSimpleNotification('Entity Document created', 'success', 2500);
|
|
1455
|
+
}
|
|
1456
|
+
else {
|
|
1457
|
+
const detail = doc.LatestResult?.CompleteMessage ?? 'Unknown error';
|
|
1458
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Failed to create Entity Document: ${detail}`, 'error', 5000);
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
catch (error) {
|
|
1462
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
1463
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 5000);
|
|
1464
|
+
}
|
|
1465
|
+
finally {
|
|
1466
|
+
this.EntityDocSaving = false;
|
|
1467
|
+
this.cdr.detectChanges();
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
// ── Dynamic source-type fields (metadata-driven) ──
|
|
1471
|
+
/** Stores source-type-specific config values keyed by RequiredFields[].Key */
|
|
1472
|
+
FormSourceSpecificConfig = {};
|
|
1473
|
+
/** Available MJ Storage provider keys for the storage-provider-picker widget */
|
|
1474
|
+
StorageProviderOptions = ['Azure Blob Storage', 'AWS S3', 'Google Cloud Storage', 'SharePoint', 'Dropbox', 'Box'];
|
|
1475
|
+
/**
|
|
1476
|
+
* The RequiredFields array from the selected source type's ConfigurationObject.
|
|
1477
|
+
* Drives dynamic form rendering — each field becomes a widget.
|
|
1478
|
+
*/
|
|
1479
|
+
get SelectedSourceTypeFields() {
|
|
1480
|
+
if (!this.FormSourceTypeID)
|
|
1481
|
+
return [];
|
|
1482
|
+
try {
|
|
1483
|
+
const engine = KnowledgeHubMetadataEngine.Instance;
|
|
1484
|
+
const sourceType = engine.ContentSourceTypes.find(st => UUIDsEqual(st.ID, this.FormSourceTypeID));
|
|
1485
|
+
if (!sourceType)
|
|
1486
|
+
return [];
|
|
1487
|
+
const config = sourceType.ConfigurationObject;
|
|
1488
|
+
return config?.RequiredFields ?? [];
|
|
1489
|
+
}
|
|
1490
|
+
catch {
|
|
1491
|
+
return [];
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
/**
|
|
1495
|
+
* Get dependent options for a field (e.g., entity-doc-picker depends on entity-picker).
|
|
1496
|
+
* Returns entity documents for the entity selected in the dependent field.
|
|
1497
|
+
*/
|
|
1498
|
+
GetDependentOptions(field) {
|
|
1499
|
+
if (field.Type === 'entity-doc-picker' && field.DependsOnField) {
|
|
1500
|
+
const entityID = this.FormSourceSpecificConfig[field.DependsOnField];
|
|
1501
|
+
if (!entityID)
|
|
1502
|
+
return [];
|
|
1503
|
+
try {
|
|
1504
|
+
const engine = KnowledgeHubMetadataEngine.Instance;
|
|
1505
|
+
const md = this.ProviderToUse;
|
|
1506
|
+
const entityInfo = md.Entities.find(e => UUIDsEqual(e.ID, entityID));
|
|
1507
|
+
if (!entityInfo)
|
|
1508
|
+
return [];
|
|
1509
|
+
return engine.GetActiveEntityDocuments()
|
|
1510
|
+
.filter(d => d.Entity === entityInfo.Name)
|
|
1511
|
+
.map(d => ({ ID: d.ID, Name: d.Name }));
|
|
1512
|
+
}
|
|
1513
|
+
catch {
|
|
1514
|
+
return [];
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
return [];
|
|
1518
|
+
}
|
|
1519
|
+
/**
|
|
1520
|
+
* Handle a source-specific field value change.
|
|
1521
|
+
* For entity-picker: auto-select the first entity doc if only one exists.
|
|
1522
|
+
*/
|
|
1523
|
+
OnSourceFieldChanged(fieldKey) {
|
|
1524
|
+
// Find fields that depend on this field
|
|
1525
|
+
for (const field of this.SelectedSourceTypeFields) {
|
|
1526
|
+
if (field.DependsOnField === fieldKey) {
|
|
1527
|
+
const options = this.GetDependentOptions(field);
|
|
1528
|
+
if (options.length === 1) {
|
|
1529
|
+
this.FormSourceSpecificConfig[field.Key] = options[0].ID;
|
|
1530
|
+
}
|
|
1531
|
+
else {
|
|
1532
|
+
this.FormSourceSpecificConfig[field.Key] = '';
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
// Dropdown options for forms
|
|
1538
|
+
SourceTypeOptions = [];
|
|
1539
|
+
ContentTypeOptions = [];
|
|
1540
|
+
FileTypeOptions = [];
|
|
1541
|
+
AIModelOptions = [];
|
|
1542
|
+
EmbeddingModelOptions = [];
|
|
1543
|
+
VectorIndexOptions = [];
|
|
1544
|
+
// Tree-dropdown configs for AI model selection (vendor → model grouping)
|
|
1545
|
+
AIModelVendorBranch = {
|
|
1546
|
+
EntityName: 'MJ: AI Vendors',
|
|
1547
|
+
DisplayField: 'Name',
|
|
1548
|
+
IDField: 'ID',
|
|
1549
|
+
DefaultIcon: 'fa-solid fa-building',
|
|
1550
|
+
OrderBy: 'Name ASC',
|
|
1551
|
+
};
|
|
1552
|
+
AllModelsLeaf = {
|
|
1553
|
+
EntityName: 'MJ: AI Models',
|
|
1554
|
+
ParentField: '',
|
|
1555
|
+
DisplayField: 'Name',
|
|
1556
|
+
IDField: 'ID',
|
|
1557
|
+
DefaultIcon: 'fa-solid fa-brain',
|
|
1558
|
+
OrderBy: '__mj_CreatedAt DESC',
|
|
1559
|
+
JunctionConfig: {
|
|
1560
|
+
EntityName: 'MJ: AI Model Vendors',
|
|
1561
|
+
LeafForeignKey: 'ModelID',
|
|
1562
|
+
BranchForeignKey: 'VendorID',
|
|
1563
|
+
},
|
|
1564
|
+
};
|
|
1565
|
+
/** Branch config filtered to only vendors that have at least one embedding model */
|
|
1566
|
+
EmbeddingVendorBranch = {
|
|
1567
|
+
EntityName: 'MJ: AI Vendors',
|
|
1568
|
+
DisplayField: 'Name',
|
|
1569
|
+
IDField: 'ID',
|
|
1570
|
+
DefaultIcon: 'fa-solid fa-building',
|
|
1571
|
+
OrderBy: 'Name ASC',
|
|
1572
|
+
ExtraFilter: `ID IN (SELECT mv.VendorID FROM [__mj].vwAIModelVendors mv JOIN [__mj].vwAIModels m ON mv.ModelID = m.ID WHERE m.AIModelType = 'Embeddings')`,
|
|
1573
|
+
};
|
|
1574
|
+
EmbeddingModelsLeaf = {
|
|
1575
|
+
EntityName: 'MJ: AI Models',
|
|
1576
|
+
ParentField: '',
|
|
1577
|
+
DisplayField: 'Name',
|
|
1578
|
+
IDField: 'ID',
|
|
1579
|
+
DefaultIcon: 'fa-solid fa-vector-square',
|
|
1580
|
+
ExtraFilter: "AIModelType = 'Embeddings'",
|
|
1581
|
+
OrderBy: '__mj_CreatedAt DESC',
|
|
1582
|
+
JunctionConfig: {
|
|
1583
|
+
EntityName: 'MJ: AI Model Vendors',
|
|
1584
|
+
LeafForeignKey: 'ModelID',
|
|
1585
|
+
BranchForeignKey: 'VendorID',
|
|
1586
|
+
},
|
|
1587
|
+
};
|
|
1588
|
+
/** Convert a string ID to a CompositeKey for tree-dropdown binding */
|
|
1589
|
+
ToCompositeKey(id) {
|
|
1590
|
+
if (!id)
|
|
1591
|
+
return null;
|
|
1592
|
+
return new CompositeKey([{ FieldName: 'ID', Value: id }]);
|
|
1593
|
+
}
|
|
1594
|
+
/** Extract the ID string from a CompositeKey (from tree-dropdown ValueChange) */
|
|
1595
|
+
FromCompositeKey(key) {
|
|
1596
|
+
if (!key)
|
|
1597
|
+
return '';
|
|
1598
|
+
const ck = Array.isArray(key) ? key[0] : key;
|
|
1599
|
+
if (!ck?.KeyValuePairs?.length)
|
|
1600
|
+
return '';
|
|
1601
|
+
return String(ck.KeyValuePairs[0].Value || '');
|
|
1602
|
+
}
|
|
1603
|
+
// ════════════════════════════════════════════
|
|
1604
|
+
// PUBLIC OPEN METHODS — called by the host via @ViewChild
|
|
1605
|
+
// ════════════════════════════════════════════
|
|
1606
|
+
async OpenAddSource() {
|
|
1607
|
+
await this.ensureFormDropdownsLoaded();
|
|
1608
|
+
this.resetSourceForm();
|
|
1609
|
+
this.ShowEffectiveValues = false;
|
|
1610
|
+
this.restorePanelWidth();
|
|
1611
|
+
this.FormMode = 'add-source';
|
|
1612
|
+
this.cdr.detectChanges();
|
|
1613
|
+
}
|
|
1614
|
+
async OpenEditSource(card) {
|
|
1615
|
+
await this.ensureFormDropdownsLoaded();
|
|
1616
|
+
this.ShowEffectiveValues = false;
|
|
1617
|
+
this.restorePanelWidth();
|
|
1618
|
+
this.FormSourceName = card.Name;
|
|
1619
|
+
this.FormSourceTypeID = card.ContentSourceTypeID;
|
|
1620
|
+
this.FormContentTypeID = card.ContentTypeID;
|
|
1621
|
+
this.FormFileTypeID = card.ContentFileTypeID;
|
|
1622
|
+
this.FormSourceURL = card.URL;
|
|
1623
|
+
this.FormSourceEntityID = card.EntityID ?? '';
|
|
1624
|
+
this.FormSourceEntityDocID = card.EntityDocumentID ?? '';
|
|
1625
|
+
this.FormSourceEmbeddingModelID = card.EmbeddingModelID ?? '';
|
|
1626
|
+
this.FormSourceVectorIndexID = card.VectorIndexID ?? '';
|
|
1627
|
+
this.EditingSourceID = card.ID;
|
|
1628
|
+
// Populate quick-edit knobs + FormSourceSpecificConfig from Configuration JSON.
|
|
1629
|
+
// Reset to defaults first so a previously-edited source's values don't leak in.
|
|
1630
|
+
this.FormSourceSpecificConfig = {};
|
|
1631
|
+
this.FormMaxItemsPerRun = null;
|
|
1632
|
+
this.FormMaxDepth = null;
|
|
1633
|
+
this.FormCrawlSitesInLowerLevelDomain = true;
|
|
1634
|
+
this.FormCrawlOtherSitesInTopLevelDomain = false;
|
|
1635
|
+
this.workingConfig = {};
|
|
1636
|
+
this.ShowInlineEntityDocForm = false;
|
|
1637
|
+
this.NewEntityDocName = '';
|
|
1638
|
+
this.NewEntityDocSelectedFields = {};
|
|
1639
|
+
const rawSource = this.RawSources.find(s => UUIDsEqual(s['ID'], card.ID));
|
|
1640
|
+
if (rawSource) {
|
|
1641
|
+
const configStr = rawSource['Configuration'];
|
|
1642
|
+
if (configStr) {
|
|
1643
|
+
try {
|
|
1644
|
+
const parsed = JSON.parse(configStr);
|
|
1645
|
+
// Hydrate the working classifier config from the persisted JSON.
|
|
1646
|
+
// Defaults are applied lazily by the typed getters, so we only
|
|
1647
|
+
// copy what was actually stored (unset = "use default").
|
|
1648
|
+
if (parsed) {
|
|
1649
|
+
this.workingConfig = { ...parsed };
|
|
1650
|
+
}
|
|
1651
|
+
const specific = parsed?.SourceSpecificConfiguration;
|
|
1652
|
+
if (specific) {
|
|
1653
|
+
this.FormSourceSpecificConfig = { ...specific };
|
|
1654
|
+
}
|
|
1655
|
+
// Run-budget knob — pulled directly off the typed Configuration.
|
|
1656
|
+
const items = parsed?.MaxItemsPerRun;
|
|
1657
|
+
if (typeof items === 'number' && Number.isFinite(items)) {
|
|
1658
|
+
this.FormMaxItemsPerRun = items;
|
|
1659
|
+
}
|
|
1660
|
+
// Website sub-object — only populates the inputs when present
|
|
1661
|
+
// (matches the autotagger's "unset = default" semantics).
|
|
1662
|
+
const website = parsed?.Website;
|
|
1663
|
+
if (website) {
|
|
1664
|
+
const depth = website.MaxDepth;
|
|
1665
|
+
if (typeof depth === 'number' && Number.isFinite(depth)) {
|
|
1666
|
+
this.FormMaxDepth = depth;
|
|
1667
|
+
}
|
|
1668
|
+
if (typeof website.CrawlSitesInLowerLevelDomain === 'boolean') {
|
|
1669
|
+
this.FormCrawlSitesInLowerLevelDomain = website.CrawlSitesInLowerLevelDomain;
|
|
1670
|
+
}
|
|
1671
|
+
if (typeof website.CrawlOtherSitesInTopLevelDomain === 'boolean') {
|
|
1672
|
+
this.FormCrawlOtherSitesInTopLevelDomain = website.CrawlOtherSitesInTopLevelDomain;
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
catch {
|
|
1677
|
+
// Configuration not valid JSON, ignore
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
this.FormMode = 'edit-source';
|
|
1682
|
+
this.cdr.detectChanges();
|
|
1683
|
+
}
|
|
1684
|
+
async OpenAddType() {
|
|
1685
|
+
await this.ensureFormDropdownsLoaded();
|
|
1686
|
+
this.resetTypeForm();
|
|
1687
|
+
this.FormMode = 'add-type';
|
|
1688
|
+
this.cdr.detectChanges();
|
|
1689
|
+
}
|
|
1690
|
+
async OpenEditType(card) {
|
|
1691
|
+
await this.ensureFormDropdownsLoaded();
|
|
1692
|
+
this.FormTypeName = card.Name;
|
|
1693
|
+
this.FormTypeDescription = card.Description;
|
|
1694
|
+
this.FormTypeAIModelID = card.AIModelID;
|
|
1695
|
+
this.FormTypeMinTags = card.MinTags;
|
|
1696
|
+
this.FormTypeMaxTags = card.MaxTags;
|
|
1697
|
+
this.FormTypeEmbeddingModelID = card.EmbeddingModelID ?? '';
|
|
1698
|
+
this.FormTypeVectorIndexID = card.VectorIndexID ?? '';
|
|
1699
|
+
this.EditingTypeID = card.ID;
|
|
1700
|
+
this.FormMode = 'edit-type';
|
|
1701
|
+
this.cdr.detectChanges();
|
|
1702
|
+
}
|
|
1703
|
+
// ════════════════════════════════════════════
|
|
1704
|
+
// ADVANCED SETTINGS
|
|
1705
|
+
// ════════════════════════════════════════════
|
|
1706
|
+
/**
|
|
1707
|
+
* Open the full entity form for the source currently being edited in the
|
|
1708
|
+
* slide-in. Quick-edit covers the most-used knobs; the entity form (with
|
|
1709
|
+
* the dynamically-mounted BaseFormPanel slots) exposes everything else
|
|
1710
|
+
* — taxonomy mode, thresholds, all five run-budget caps, URL pattern,
|
|
1711
|
+
* root URL, etc. The host owns NavigationService, so navigation bubbles up.
|
|
1712
|
+
*/
|
|
1713
|
+
OpenAdvancedSourceSettings() {
|
|
1714
|
+
if (!this.EditingSourceID)
|
|
1715
|
+
return;
|
|
1716
|
+
const id = this.EditingSourceID;
|
|
1717
|
+
this.CloseForm();
|
|
1718
|
+
this.NavigateToRecordRequested.emit({
|
|
1719
|
+
entityName: 'MJ: Content Sources',
|
|
1720
|
+
key: CompositeKey.FromID(id),
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1723
|
+
// ════════════════════════════════════════════
|
|
1724
|
+
// SAVE — Sources
|
|
1725
|
+
// ════════════════════════════════════════════
|
|
1726
|
+
async SaveSource() {
|
|
1727
|
+
if (this.FormSaving)
|
|
1728
|
+
return;
|
|
1729
|
+
// Validate required fields before saving
|
|
1730
|
+
if (!this.FormSourceName.trim()) {
|
|
1731
|
+
MJNotificationService.Instance.CreateSimpleNotification('Please enter a source name.', 'warning', 3000);
|
|
1732
|
+
return;
|
|
1733
|
+
}
|
|
1734
|
+
if (!this.FormSourceTypeID) {
|
|
1735
|
+
MJNotificationService.Instance.CreateSimpleNotification('Please select a source type.', 'warning', 3000);
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1738
|
+
// For non-Entity source types, ContentType is required
|
|
1739
|
+
if (!this.IsEntitySourceTypeSelected && this.SelectedSourceTypeRequiresContentType) {
|
|
1740
|
+
if (!this.FormContentTypeID) {
|
|
1741
|
+
if (this.ContentTypeOptions.length === 0) {
|
|
1742
|
+
MJNotificationService.Instance.CreateSimpleNotification('No content types are configured. Please create a content type first in the Content Types section.', 'warning', 5000);
|
|
1743
|
+
}
|
|
1744
|
+
else {
|
|
1745
|
+
MJNotificationService.Instance.CreateSimpleNotification('Please select a content type.', 'warning', 3000);
|
|
1746
|
+
}
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
this.FormSaving = true;
|
|
1751
|
+
this.cdr.detectChanges();
|
|
1752
|
+
try {
|
|
1753
|
+
const md = this.ProviderToUse;
|
|
1754
|
+
const entity = await md.GetEntityObject('MJ: Content Sources');
|
|
1755
|
+
if (this.FormMode === 'edit-source' && this.EditingSourceID) {
|
|
1756
|
+
await entity.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: this.EditingSourceID }]));
|
|
1757
|
+
}
|
|
1758
|
+
else {
|
|
1759
|
+
entity.NewRecord();
|
|
1760
|
+
}
|
|
1761
|
+
entity.Name = this.FormSourceName;
|
|
1762
|
+
entity.ContentSourceTypeID = this.FormSourceTypeID;
|
|
1763
|
+
// For Entity source type, ContentType and FileType are not relevant
|
|
1764
|
+
// but the DB columns are NOT NULL, so default to the first available value
|
|
1765
|
+
if (this.IsEntitySourceTypeSelected) {
|
|
1766
|
+
const engine = KnowledgeHubMetadataEngine.Instance;
|
|
1767
|
+
if (!entity.ContentTypeID) {
|
|
1768
|
+
if (engine.ContentTypes.length === 0) {
|
|
1769
|
+
this.FormSaving = false;
|
|
1770
|
+
this.cdr.detectChanges();
|
|
1771
|
+
this.ContentTypeMissing.emit();
|
|
1772
|
+
return;
|
|
1773
|
+
}
|
|
1774
|
+
entity.ContentTypeID = engine.ContentTypes[0].ID;
|
|
1775
|
+
}
|
|
1776
|
+
if (!entity.ContentFileTypeID && engine.ContentFileTypes.length > 0) {
|
|
1777
|
+
entity.ContentFileTypeID = engine.ContentFileTypes[0].ID;
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
else {
|
|
1781
|
+
entity.ContentTypeID = this.FormContentTypeID;
|
|
1782
|
+
entity.ContentFileTypeID = this.FormFileTypeID;
|
|
1783
|
+
}
|
|
1784
|
+
// Store source-type-specific values from the dynamic form
|
|
1785
|
+
// For Entity type: EntityID and EntityDocumentID go on the entity directly
|
|
1786
|
+
if (this.IsEntitySourceTypeSelected) {
|
|
1787
|
+
entity.EntityID = this.FormSourceSpecificConfig['EntityID'] || null;
|
|
1788
|
+
const entityDocID = this.FormSourceSpecificConfig['EntityDocumentID'];
|
|
1789
|
+
if (entityDocID) {
|
|
1790
|
+
entity.EntityDocumentID = entityDocID;
|
|
1791
|
+
}
|
|
1792
|
+
else {
|
|
1793
|
+
// Auto-select first doc if only one exists
|
|
1794
|
+
const docField = this.SelectedSourceTypeFields.find(f => f.Type === 'entity-doc-picker');
|
|
1795
|
+
const docs = docField ? this.GetDependentOptions(docField) : [];
|
|
1796
|
+
entity.EntityDocumentID = docs.length > 0 ? docs[0].ID : null;
|
|
1797
|
+
}
|
|
1798
|
+
entity.URL = '';
|
|
1799
|
+
}
|
|
1800
|
+
else {
|
|
1801
|
+
entity.EntityID = null;
|
|
1802
|
+
entity.EntityDocumentID = null;
|
|
1803
|
+
// URL comes from dynamic fields for RSS/Website, or empty for others
|
|
1804
|
+
entity.URL = this.FormSourceSpecificConfig['URL'] || '';
|
|
1805
|
+
}
|
|
1806
|
+
// Store the full SourceSpecificConfiguration in the Configuration JSON
|
|
1807
|
+
const currentConfig = entity.ConfigurationObject ?? {};
|
|
1808
|
+
// Merge the inline Classification knobs (taxonomy mode, thresholds,
|
|
1809
|
+
// tag root, budgets, toggles) from the working config. We deliberately
|
|
1810
|
+
// exclude the sub-objects owned by the dedicated quick-edit logic below
|
|
1811
|
+
// (SourceSpecificConfiguration, MaxItemsPerRun, Website) so those stay
|
|
1812
|
+
// single-owner and we never clobber crawl settings. Keys absent from the
|
|
1813
|
+
// working config are left untouched on currentConfig.
|
|
1814
|
+
const { SourceSpecificConfiguration: _ssc, MaxItemsPerRun: _mipr, Website: _web, ...classifierKnobs } = this.workingConfig;
|
|
1815
|
+
Object.assign(currentConfig, classifierKnobs);
|
|
1816
|
+
currentConfig.SourceSpecificConfiguration = { ...this.FormSourceSpecificConfig };
|
|
1817
|
+
// Persist the quick-edit knobs that don't have their own DB columns
|
|
1818
|
+
// (the rest live on the typed Configuration JSON sub-objects). The
|
|
1819
|
+
// advanced settings flow on the entity form can override more fields
|
|
1820
|
+
// — we only touch the keys the slide-in exposes so we don't clobber
|
|
1821
|
+
// unrelated values an operator set there earlier.
|
|
1822
|
+
if (this.FormMaxItemsPerRun != null && Number.isFinite(this.FormMaxItemsPerRun)) {
|
|
1823
|
+
currentConfig.MaxItemsPerRun = this.FormMaxItemsPerRun;
|
|
1824
|
+
}
|
|
1825
|
+
else {
|
|
1826
|
+
// Empty input = "unlimited" — strip the key so the autotagger
|
|
1827
|
+
// sees no cap (rather than 0 = "process zero items").
|
|
1828
|
+
delete currentConfig.MaxItemsPerRun;
|
|
1829
|
+
}
|
|
1830
|
+
if (this.IsWebsiteSourceTypeSelected) {
|
|
1831
|
+
const website = { ...(currentConfig.Website ?? {}) };
|
|
1832
|
+
if (this.FormMaxDepth != null && Number.isFinite(this.FormMaxDepth)) {
|
|
1833
|
+
website.MaxDepth = this.FormMaxDepth;
|
|
1834
|
+
}
|
|
1835
|
+
else {
|
|
1836
|
+
delete website.MaxDepth;
|
|
1837
|
+
}
|
|
1838
|
+
website.CrawlSitesInLowerLevelDomain = this.FormCrawlSitesInLowerLevelDomain;
|
|
1839
|
+
website.CrawlOtherSitesInTopLevelDomain = this.FormCrawlOtherSitesInTopLevelDomain;
|
|
1840
|
+
currentConfig.Website = website;
|
|
1841
|
+
}
|
|
1842
|
+
entity.ConfigurationObject = currentConfig;
|
|
1843
|
+
entity.EmbeddingModelID = this.FormSourceEmbeddingModelID || null;
|
|
1844
|
+
entity.VectorIndexID = this.FormSourceVectorIndexID || null;
|
|
1845
|
+
const saved = await entity.Save();
|
|
1846
|
+
if (saved) {
|
|
1847
|
+
MJNotificationService.Instance.CreateSimpleNotification(this.FormMode === 'edit-source' ? 'Source updated' : 'Source created', 'success', 2500);
|
|
1848
|
+
this.CloseForm();
|
|
1849
|
+
this.Saved.emit({ kind: 'source' });
|
|
1850
|
+
}
|
|
1851
|
+
else {
|
|
1852
|
+
// CP-4: Show detailed error from LatestResult
|
|
1853
|
+
const errorDetail = entity.LatestResult?.CompleteMessage ?? 'Unknown error';
|
|
1854
|
+
console.error('[Classify] Save source failed:', entity.LatestResult);
|
|
1855
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Failed to save source: ${errorDetail}`, 'error', 5000);
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
catch (error) {
|
|
1859
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
1860
|
+
console.error('[Classify] Save source exception:', error);
|
|
1861
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 5000);
|
|
1862
|
+
}
|
|
1863
|
+
finally {
|
|
1864
|
+
this.FormSaving = false;
|
|
1865
|
+
this.cdr.detectChanges();
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
// ════════════════════════════════════════════
|
|
1869
|
+
// SAVE — Content Types
|
|
1870
|
+
// ════════════════════════════════════════════
|
|
1871
|
+
async SaveContentType() {
|
|
1872
|
+
if (this.FormSaving)
|
|
1873
|
+
return;
|
|
1874
|
+
this.FormSaving = true;
|
|
1875
|
+
this.cdr.detectChanges();
|
|
1876
|
+
try {
|
|
1877
|
+
const md = this.ProviderToUse;
|
|
1878
|
+
const contentType = await md.GetEntityObject('MJ: Content Types', md.CurrentUser);
|
|
1879
|
+
if (this.FormMode === 'edit-type' && this.EditingTypeID) {
|
|
1880
|
+
await contentType.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: this.EditingTypeID }]));
|
|
1881
|
+
}
|
|
1882
|
+
else {
|
|
1883
|
+
contentType.NewRecord();
|
|
1884
|
+
}
|
|
1885
|
+
contentType.Name = this.FormTypeName;
|
|
1886
|
+
contentType.Description = this.FormTypeDescription;
|
|
1887
|
+
contentType.AIModelID = this.FormTypeAIModelID;
|
|
1888
|
+
contentType.MinTags = this.FormTypeMinTags;
|
|
1889
|
+
contentType.MaxTags = this.FormTypeMaxTags;
|
|
1890
|
+
contentType.EmbeddingModelID = this.FormTypeEmbeddingModelID || null;
|
|
1891
|
+
contentType.VectorIndexID = this.FormTypeVectorIndexID || null;
|
|
1892
|
+
const saved = await contentType.Save();
|
|
1893
|
+
if (saved) {
|
|
1894
|
+
MJNotificationService.Instance.CreateSimpleNotification(this.FormMode === 'edit-type' ? 'Content type updated' : 'Content type created', 'success', 2500);
|
|
1895
|
+
this.CloseForm();
|
|
1896
|
+
this.Saved.emit({ kind: 'type' });
|
|
1897
|
+
}
|
|
1898
|
+
else {
|
|
1899
|
+
MJNotificationService.Instance.CreateSimpleNotification('Failed to save content type', 'error', 3000);
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
catch (error) {
|
|
1903
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
1904
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${msg}`, 'error', 4000);
|
|
1905
|
+
}
|
|
1906
|
+
finally {
|
|
1907
|
+
this.FormSaving = false;
|
|
1908
|
+
this.cdr.detectChanges();
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
CloseForm() {
|
|
1912
|
+
this.FormMode = 'none';
|
|
1913
|
+
this.cdr.detectChanges();
|
|
1914
|
+
}
|
|
1915
|
+
// ════════════════════════════════════════════
|
|
1916
|
+
// RAW SOURCES — supplied by the host so edit can read Configuration JSON
|
|
1917
|
+
// ════════════════════════════════════════════
|
|
1918
|
+
/**
|
|
1919
|
+
* Raw `MJ: Content Sources` rows, forwarded by the host so `OpenEditSource`
|
|
1920
|
+
* can hydrate the quick-edit knobs from the source's Configuration JSON. The
|
|
1921
|
+
* card the Sources tab passes doesn't carry the full Configuration blob.
|
|
1922
|
+
*/
|
|
1923
|
+
RawSources = [];
|
|
1924
|
+
// ════════════════════════════════════════════
|
|
1925
|
+
// HELPERS
|
|
1926
|
+
// ════════════════════════════════════════════
|
|
1927
|
+
async ensureFormDropdownsLoaded() {
|
|
1928
|
+
try {
|
|
1929
|
+
// Use KnowledgeHubMetadataEngine for cached reference data — instant, no RunView needed
|
|
1930
|
+
const engine = KnowledgeHubMetadataEngine.Instance;
|
|
1931
|
+
await engine.Config(false); // no-op if already loaded
|
|
1932
|
+
this.SourceTypeOptions = engine.ContentSourceTypes.map(t => ({ ID: t.ID, Name: t.Name }));
|
|
1933
|
+
this.ContentTypeOptions = engine.ContentTypes.map(t => ({ ID: t.ID, Name: t.Name }));
|
|
1934
|
+
this.FileTypeOptions = engine.ContentFileTypes.map(t => ({ ID: t.ID, Name: t.Name }));
|
|
1935
|
+
this.VectorIndexOptions = engine.VectorIndexes.map(vi => ({ ID: vi.ID, Name: vi.Name }));
|
|
1936
|
+
// AI Models from AIEngineBase (already cached)
|
|
1937
|
+
if (this.AIModelOptions.length === 0) {
|
|
1938
|
+
const aiEngine = AIEngineBase.Instance;
|
|
1939
|
+
await aiEngine.Config(false);
|
|
1940
|
+
this.AIModelOptions = aiEngine.Models.map(m => ({ ID: m.ID, Name: m.Name }));
|
|
1941
|
+
this.EmbeddingModelOptions = aiEngine.Models
|
|
1942
|
+
.filter(m => m.AIModelType?.trim().toLowerCase() === 'embeddings')
|
|
1943
|
+
.map(m => ({ ID: m.ID, Name: m.Name }));
|
|
1944
|
+
}
|
|
1945
|
+
// Tag-root candidates for the Classification section's root dropdown.
|
|
1946
|
+
if (this.TagRootOptions.length === 0) {
|
|
1947
|
+
const p = this.ProviderToUse;
|
|
1948
|
+
await TagEngineBase.Instance.Config(false, p.CurrentUser, p);
|
|
1949
|
+
this.TagRootOptions = TagEngineBase.Instance.Tags
|
|
1950
|
+
.map(t => ({ ID: t.ID, Name: t.Name }))
|
|
1951
|
+
.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
1952
|
+
}
|
|
1953
|
+
// Org-level domain context — used for the effective-context preview.
|
|
1954
|
+
await this.loadOrgClassificationContext();
|
|
1955
|
+
}
|
|
1956
|
+
catch (error) {
|
|
1957
|
+
console.error('[Autotagging] Error loading form dropdowns:', error);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
/**
|
|
1961
|
+
* Resolve the Knowledge Hub Application ID by name (cached per dialog instance).
|
|
1962
|
+
* Returns null when no such application exists.
|
|
1963
|
+
*/
|
|
1964
|
+
khApplicationID = undefined;
|
|
1965
|
+
async resolveKnowledgeHubApplicationID() {
|
|
1966
|
+
if (this.khApplicationID !== undefined)
|
|
1967
|
+
return this.khApplicationID;
|
|
1968
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
1969
|
+
const result = await rv.RunView({
|
|
1970
|
+
EntityName: 'MJ: Applications',
|
|
1971
|
+
ExtraFilter: `Name = '${KNOWLEDGE_HUB_APPLICATION_NAME.replace(/'/g, "''")}'`,
|
|
1972
|
+
Fields: ['ID'],
|
|
1973
|
+
MaxRows: 1,
|
|
1974
|
+
ResultType: 'simple',
|
|
1975
|
+
});
|
|
1976
|
+
this.khApplicationID = result.Success && result.Results.length > 0 ? result.Results[0].ID : null;
|
|
1977
|
+
return this.khApplicationID;
|
|
1978
|
+
}
|
|
1979
|
+
/** Read the org-level classification context for the effective-context preview. */
|
|
1980
|
+
async loadOrgClassificationContext() {
|
|
1981
|
+
try {
|
|
1982
|
+
const p = this.ProviderToUse;
|
|
1983
|
+
await ApplicationSettingEngine.Instance.Config(false, p.CurrentUser, p);
|
|
1984
|
+
const appID = await this.resolveKnowledgeHubApplicationID();
|
|
1985
|
+
this.OrgClassificationContext =
|
|
1986
|
+
ApplicationSettingEngine.Instance.GetSetting(CLASSIFY_ORG_CONTEXT_SETTING_KEY, appID ?? undefined) ?? '';
|
|
1987
|
+
}
|
|
1988
|
+
catch {
|
|
1989
|
+
this.OrgClassificationContext = '';
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
resetSourceForm() {
|
|
1993
|
+
this.FormSourceName = '';
|
|
1994
|
+
this.FormSourceTypeID = '';
|
|
1995
|
+
this.FormContentTypeID = '';
|
|
1996
|
+
this.FormFileTypeID = '';
|
|
1997
|
+
this.FormSourceURL = '';
|
|
1998
|
+
this.FormSourceEntityID = '';
|
|
1999
|
+
this.FormSourceEntityDocID = '';
|
|
2000
|
+
this.FormSourceEmbeddingModelID = '';
|
|
2001
|
+
this.FormSourceVectorIndexID = '';
|
|
2002
|
+
this.EditingSourceID = '';
|
|
2003
|
+
this.FormSourceSpecificConfig = {};
|
|
2004
|
+
// Quick-edit knobs — defaults match the autotagger's runtime defaults.
|
|
2005
|
+
this.FormMaxItemsPerRun = null;
|
|
2006
|
+
this.FormMaxDepth = null;
|
|
2007
|
+
this.FormCrawlSitesInLowerLevelDomain = true;
|
|
2008
|
+
this.FormCrawlOtherSitesInTopLevelDomain = false;
|
|
2009
|
+
// Classification knobs — start empty; the typed getters apply defaults.
|
|
2010
|
+
this.workingConfig = {};
|
|
2011
|
+
// Inline Entity Document create sub-form.
|
|
2012
|
+
this.ShowInlineEntityDocForm = false;
|
|
2013
|
+
this.NewEntityDocName = '';
|
|
2014
|
+
this.NewEntityDocSelectedFields = {};
|
|
2015
|
+
}
|
|
2016
|
+
// ════════════════════════════════════════════
|
|
2017
|
+
// EFFECTIVE-VALUES TOGGLE
|
|
2018
|
+
// ════════════════════════════════════════════
|
|
2019
|
+
/** Show / hide the inline effective-values panel in the Classification section. */
|
|
2020
|
+
ToggleEffectiveValues() {
|
|
2021
|
+
this.ShowEffectiveValues = !this.ShowEffectiveValues;
|
|
2022
|
+
this.cdr.detectChanges();
|
|
2023
|
+
}
|
|
2024
|
+
// ════════════════════════════════════════════
|
|
2025
|
+
// RESIZABLE PANEL (drag the left edge) + width persistence
|
|
2026
|
+
// ════════════════════════════════════════════
|
|
2027
|
+
/** Clamp a candidate width to the allowed range (min .. 90% of viewport). */
|
|
2028
|
+
clampPanelWidth(width) {
|
|
2029
|
+
const max = window.innerWidth * 0.9;
|
|
2030
|
+
return Math.max(PANEL_WIDTH_MIN, Math.min(width, max));
|
|
2031
|
+
}
|
|
2032
|
+
/**
|
|
2033
|
+
* Restore the remembered panel width from UserInfoEngine (a synchronous cache
|
|
2034
|
+
* read), falling back to the default. Called when a source form is opened.
|
|
2035
|
+
*/
|
|
2036
|
+
restorePanelWidth() {
|
|
2037
|
+
const raw = UserInfoEngine.Instance.GetSetting(PANEL_WIDTH_SETTING_KEY);
|
|
2038
|
+
if (raw) {
|
|
2039
|
+
const n = parseInt(raw, 10);
|
|
2040
|
+
if (!isNaN(n)) {
|
|
2041
|
+
this.PanelWidth = this.clampPanelWidth(n);
|
|
2042
|
+
return;
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
this.PanelWidth = PANEL_WIDTH_DEFAULT;
|
|
2046
|
+
}
|
|
2047
|
+
/**
|
|
2048
|
+
* Begin a left-edge resize drag. The panel slides in from the right, so the
|
|
2049
|
+
* resizable edge is its LEFT edge: dragging left widens the panel.
|
|
2050
|
+
*/
|
|
2051
|
+
StartResize(event) {
|
|
2052
|
+
event.preventDefault();
|
|
2053
|
+
if (this.isResizing)
|
|
2054
|
+
return;
|
|
2055
|
+
this.isResizing = true;
|
|
2056
|
+
const startX = event.clientX;
|
|
2057
|
+
const startWidth = this.PanelWidth;
|
|
2058
|
+
// Prevent text selection / iframe capture during the drag.
|
|
2059
|
+
document.body.style.userSelect = 'none';
|
|
2060
|
+
// Run move tracking outside Angular to avoid a CD cycle on every pixel;
|
|
2061
|
+
// we re-enter the zone only to update the bound width.
|
|
2062
|
+
this.zone.runOutsideAngular(() => {
|
|
2063
|
+
this.resizeMoveListener = (e) => {
|
|
2064
|
+
const next = this.clampPanelWidth(startWidth + (startX - e.clientX));
|
|
2065
|
+
this.zone.run(() => {
|
|
2066
|
+
this.PanelWidth = next;
|
|
2067
|
+
this.cdr.detectChanges();
|
|
2068
|
+
});
|
|
2069
|
+
// Debounced persistence while dragging — the final value is what sticks.
|
|
2070
|
+
UserInfoEngine.Instance.SetSettingDebounced(PANEL_WIDTH_SETTING_KEY, String(Math.round(next)));
|
|
2071
|
+
};
|
|
2072
|
+
this.resizeUpListener = () => this.endResize();
|
|
2073
|
+
document.addEventListener('mousemove', this.resizeMoveListener);
|
|
2074
|
+
document.addEventListener('mouseup', this.resizeUpListener);
|
|
2075
|
+
});
|
|
2076
|
+
}
|
|
2077
|
+
/** Tear down the active drag listeners and persist the final width. */
|
|
2078
|
+
endResize() {
|
|
2079
|
+
if (!this.isResizing)
|
|
2080
|
+
return;
|
|
2081
|
+
this.isResizing = false;
|
|
2082
|
+
document.body.style.userSelect = '';
|
|
2083
|
+
if (this.resizeMoveListener) {
|
|
2084
|
+
document.removeEventListener('mousemove', this.resizeMoveListener);
|
|
2085
|
+
this.resizeMoveListener = null;
|
|
2086
|
+
}
|
|
2087
|
+
if (this.resizeUpListener) {
|
|
2088
|
+
document.removeEventListener('mouseup', this.resizeUpListener);
|
|
2089
|
+
this.resizeUpListener = null;
|
|
2090
|
+
}
|
|
2091
|
+
UserInfoEngine.Instance.SetSettingDebounced(PANEL_WIDTH_SETTING_KEY, String(Math.round(this.PanelWidth)));
|
|
2092
|
+
}
|
|
2093
|
+
ngOnDestroy() {
|
|
2094
|
+
// Clean up any active drag listeners + body style if destroyed mid-drag.
|
|
2095
|
+
this.endResize();
|
|
2096
|
+
}
|
|
2097
|
+
resetTypeForm() {
|
|
2098
|
+
this.FormTypeName = '';
|
|
2099
|
+
this.FormTypeDescription = '';
|
|
2100
|
+
this.FormTypeAIModelID = '';
|
|
2101
|
+
this.FormTypeMinTags = 1;
|
|
2102
|
+
this.FormTypeMaxTags = 10;
|
|
2103
|
+
this.FormTypeEmbeddingModelID = '';
|
|
2104
|
+
this.FormTypeVectorIndexID = '';
|
|
2105
|
+
this.EditingTypeID = '';
|
|
2106
|
+
}
|
|
2107
|
+
static ɵfac = /*@__PURE__*/ (() => { let ɵClassifySourceTypeFormDialogComponent_BaseFactory; return function ClassifySourceTypeFormDialogComponent_Factory(__ngFactoryType__) { return (ɵClassifySourceTypeFormDialogComponent_BaseFactory || (ɵClassifySourceTypeFormDialogComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ClassifySourceTypeFormDialogComponent)))(__ngFactoryType__ || ClassifySourceTypeFormDialogComponent); }; })();
|
|
2108
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ClassifySourceTypeFormDialogComponent, selectors: [["classify-source-type-form-dialog"]], outputs: { Saved: "Saved", ContentTypeMissing: "ContentTypeMissing", NavigateToRecordRequested: "NavigateToRecordRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [[1, "at-slide-overlay", 3, "click"], [1, "at-slide-panel"], ["role", "separator", "aria-orientation", "vertical", "aria-label", "Resize panel", 1, "cls-resize-handle", 3, "mousedown"], [1, "at-slide-header"], ["aria-label", "Close form", 1, "at-slide-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "at-slide-body"], [1, "cls-section", "cls-section--first"], [1, "cls-section-title"], [1, "fa-solid", "fa-database"], [1, "at-form-group"], [1, "at-form-label"], ["type", "text", "placeholder", "Source name", 1, "at-form-input", 3, "ngModelChange", "ngModel"], [1, "at-form-select", 3, "ngModelChange", "ngModel"], ["value", ""], [3, "value"], [1, "cls-section"], [1, "fa-solid", "fa-cubes"], ["SelectionMode", "single", "SelectableTypes", "leaf", "Placeholder", "Use system default", 3, "ValueChange", "BranchConfig", "LeafConfig", "Clearable", "Value"], [1, "at-form-hint"], [1, "fa-solid", "fa-sliders"], ["mjButton", "", "variant", "flat", "size", "sm", 1, "cls-eff-toggle", 3, "click"], [1, "fa-solid"], [1, "cls-config"], [1, "cls-mode-grid"], [1, "cls-mode-card", 3, "selected"], [1, "cls-threshold-pair"], [1, "cls-slider-grid"], [1, "cls-slider-field"], [1, "cls-slider-cap"], ["type", "range", "min", "0.50", "max", "1.00", "step", "0.01", 1, "cls-slider", 3, "ngModelChange", "ngModel"], ["aria-hidden", "true", 1, "cls-band"], [1, "cls-validation"], [1, "cls-band-legend"], [1, "cls-toggle-row"], [1, "cls-toggle-label"], [1, "t"], [1, "d"], [3, "ngModelChange", "ngModel"], [1, "cls-aside"], [1, "fa-solid", "fa-comment-dots"], ["rows", "4", "placeholder", "Free-text guidance for the classifier about this source's domain \u2014 terminology, audience, what tags matter\u2026", 1, "at-form-textarea", 3, "ngModelChange", "ngModel"], [1, "cls-context-preview"], [1, "fa-solid", "fa-gauge"], ["type", "number", "min", "0", "placeholder", "unlimited", 1, "at-form-input", 3, "ngModelChange", "ngModel"], [1, "cls-budget-grid"], ["type", "number", "min", "0", "step", "0.01", "placeholder", "unlimited", 1, "at-form-input", 3, "ngModelChange", "ngModel"], [1, "at-form-actions"], [1, "at-action-btn", "at-primary-btn", 3, "click", "disabled"], [1, "at-action-btn", "at-secondary-btn", 3, "click"], [1, "at-form-advanced-link"], [1, "at-required"], ["type", "url", 1, "at-form-input", 3, "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModel", "placeholder", "value"], [1, "at-form-select", 3, "ngModel"], ["type", "url", 1, "at-form-input", 3, "ngModelChange", "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModelChange", "ngModel", "placeholder"], ["type", "text", 1, "at-form-input", 3, "ngModelChange", "ngModel", "placeholder", "value"], [1, "cls-doc-callout"], [1, "cls-doc-callout-head"], [1, "fa-solid", "fa-circle-info"], ["mjButton", "", "variant", "primary", "size", "sm"], [1, "cls-doc-form"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-plus"], ["type", "text", "placeholder", "Document name", 1, "at-form-input", 3, "ngModelChange", "ngModel"], [1, "cls-doc-field-list"], [1, "cls-doc-field-row"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click", "disabled"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click"], ["type", "checkbox", 3, "ngModelChange", "ngModel"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-check"], [1, "cls-mode-card", 3, "click"], [1, "cls-mode-nm"], [1, "cls-mode-best"], [1, "fa-solid", "fa-circle-exclamation"], [1, "cls-band-key", "reject"], [1, "cls-band-key", "review"], [1, "cls-band-key", "apply"], [1, "cls-aside-title"], [1, "cls-eff-row"], [1, "cls-eff-label"], [1, "cls-eff-value"], [1, "cls-eff-origin"], [1, "fa-solid", "fa-spider"], ["type", "number", "min", "0", "max", "10", "step", "1", "placeholder", "2 (default)", 1, "at-form-input", 3, "ngModelChange", "ngModel"], ["href", "javascript:void(0)", 3, "click"], [1, "fa-solid", "fa-arrow-up-right-from-square"], ["type", "text", "placeholder", "Content type name", 1, "at-form-input", 3, "ngModelChange", "ngModel"], ["rows", "3", "placeholder", "Description...", 1, "at-form-textarea", 3, "ngModelChange", "ngModel"], ["SelectionMode", "single", "SelectableTypes", "leaf", "Placeholder", "Select AI model...", 3, "ValueChange", "BranchConfig", "LeafConfig", "Clearable", "Value"], [1, "at-form-row"], [1, "at-form-group", 2, "flex", "1"], ["type", "number", "min", "0", 1, "at-form-input", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "1", 1, "at-form-input", 3, "ngModelChange", "ngModel"]], template: function ClassifySourceTypeFormDialogComponent_Template(rf, ctx) { if (rf & 1) {
|
|
2109
|
+
i0.ɵɵconditionalCreate(0, ClassifySourceTypeFormDialogComponent_Conditional_0_Template, 14, 5);
|
|
2110
|
+
} if (rf & 2) {
|
|
2111
|
+
i0.ɵɵconditional(ctx.FormMode !== "none" ? 0 : -1);
|
|
2112
|
+
} }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.NumberValueAccessor, i1.RangeValueAccessor, i1.CheckboxControlValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.MinValidator, i1.MaxValidator, i1.NgModel, i2.TreeDropdownComponent, i3.MJButtonDirective, i3.MJSwitchComponent, i4.DecimalPipe], styles: ["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.cls-resize-handle[_ngcontent-%COMP%] {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n z-index: 1002;\n background: transparent;\n transition: background 0.12s;\n}\n.cls-resize-handle[_ngcontent-%COMP%]:hover, \n.cls-resize-handle[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n\n\n.cls-section[_ngcontent-%COMP%] {\n margin-top: 8px;\n padding-top: 12px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n\n.cls-section--first[_ngcontent-%COMP%] {\n margin-top: 0;\n padding-top: 0;\n border-top: 0;\n}\n.cls-section-title[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.cls-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n\n\n\n.cls-eff-toggle[_ngcontent-%COMP%] {\n margin-left: auto;\n font-weight: 600;\n}\n\n\n\n\n.cls-config[_ngcontent-%COMP%] {\n display: block;\n}\n\n\n\n.cls-mode-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 8px;\n}\n.cls-mode-card[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 8px;\n padding: 10px 8px;\n cursor: pointer;\n text-align: center;\n transition: background 0.12s, border-color 0.12s, box-shadow 0.12s;\n user-select: none;\n}\n.cls-mode-card[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); }\n.cls-mode-card.selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n border-color: var(--mj-brand-primary);\n box-shadow: inset 0 0 0 1px var(--mj-brand-primary);\n}\n.cls-mode-ic[_ngcontent-%COMP%] { font-size: 16px; color: var(--mj-text-secondary); }\n.cls-mode-card.selected[_ngcontent-%COMP%] .cls-mode-ic[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n.cls-mode-nm[_ngcontent-%COMP%] { font-size: 12px; font-weight: 700; color: var(--mj-text-primary); margin: 4px 0 2px; }\n.cls-mode-best[_ngcontent-%COMP%] { font-size: 10.5px; color: var(--mj-text-muted); line-height: 1.3; }\n\n\n\n.cls-threshold-pair[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n padding: 12px 14px;\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n}\n.cls-slider-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px 16px;\n}\n@media (max-width: 560px) {\n .cls-slider-grid[_ngcontent-%COMP%] { grid-template-columns: 1fr; }\n}\n.cls-slider-field[_ngcontent-%COMP%] { display: flex; flex-direction: column; gap: 4px; }\n.cls-slider-cap[_ngcontent-%COMP%] { font-size: 11px; color: var(--mj-text-secondary); }\n.cls-slider-cap[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-family: ui-monospace, monospace;\n color: var(--mj-text-primary);\n margin-left: 2px;\n}\n.cls-slider[_ngcontent-%COMP%] {\n appearance: none;\n -webkit-appearance: none;\n width: 100%;\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n margin: 2px 0;\n}\n.cls-slider[_ngcontent-%COMP%]::-webkit-slider-thumb {\n appearance: none;\n -webkit-appearance: none;\n width: 16px; height: 16px; border-radius: 50%;\n background: var(--mj-brand-primary);\n cursor: pointer;\n border: 2px solid var(--mj-bg-surface);\n}\n.cls-slider[_ngcontent-%COMP%]::-moz-range-thumb {\n width: 16px; height: 16px; border-radius: 50%;\n background: var(--mj-brand-primary);\n cursor: pointer;\n border: 2px solid var(--mj-bg-surface);\n}\n\n\n\n.cls-band[_ngcontent-%COMP%] {\n height: 8px;\n border-radius: 4px;\n margin: 10px 0 6px;\n background: linear-gradient(\n to right,\n color-mix(in srgb, var(--mj-status-error) 55%, transparent) 0%,\n color-mix(in srgb, var(--mj-status-warning) 55%, transparent) 50%,\n color-mix(in srgb, var(--mj-status-success) 55%, transparent) 100%\n );\n}\n.cls-band-legend[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n font-size: 10.5px;\n}\n.cls-band-key.reject[_ngcontent-%COMP%] { color: var(--mj-status-error-text, var(--mj-status-error)); }\n.cls-band-key.review[_ngcontent-%COMP%] { color: var(--mj-status-warning-text, var(--mj-status-warning)); }\n.cls-band-key.apply[_ngcontent-%COMP%] { color: var(--mj-status-success-text, var(--mj-status-success)); }\n.cls-validation[_ngcontent-%COMP%] {\n font-size: 12px;\n padding: 8px 12px;\n margin-top: 8px;\n background: color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n color: var(--mj-status-error-text, var(--mj-status-error));\n border-radius: 4px;\n}\n\n\n\n.cls-toggle-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 10px 0;\n border-top: 1px dashed var(--mj-border-subtle);\n}\n.cls-toggle-label[_ngcontent-%COMP%] .t[_ngcontent-%COMP%] { display: block; font-size: 13px; font-weight: 600; color: var(--mj-text-primary); }\n.cls-toggle-label[_ngcontent-%COMP%] .d[_ngcontent-%COMP%] { display: block; font-size: 11px; color: var(--mj-text-muted); margin-top: 2px; }\n\n\n\n\n\n.cls-aside[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 12px;\n margin-top: 12px;\n}\n.cls-aside-title[_ngcontent-%COMP%] {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--mj-text-muted);\n font-weight: 700;\n margin: 0 0 8px;\n}\n.cls-eff-row[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 8px;\n padding: 6px 0;\n border-top: 1px solid var(--mj-border-subtle);\n font-size: 12px;\n}\n.cls-eff-row[_ngcontent-%COMP%]:first-of-type { border-top: 0; }\n.cls-eff-label[_ngcontent-%COMP%] { color: var(--mj-text-secondary); }\n.cls-eff-value[_ngcontent-%COMP%] { color: var(--mj-text-primary); font-weight: 600; text-align: right; }\n.cls-eff-origin[_ngcontent-%COMP%] {\n display: block;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.03em;\n margin-top: 1px;\n}\n.cls-eff-origin.override[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n\n\n\n.cls-budget-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 12px 16px;\n margin-top: 8px;\n}\n@media (max-width: 480px) {\n .cls-budget-grid[_ngcontent-%COMP%] { grid-template-columns: 1fr; }\n}\n\n\n\n.cls-context-preview[_ngcontent-%COMP%] {\n margin: 0;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n color: var(--mj-text-secondary);\n font-size: 0.8rem;\n line-height: 1.45;\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 200px;\n overflow-y: auto;\n}\n\n\n\n.cls-doc-callout[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-top: 12px;\n padding: 12px;\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-info-border, var(--mj-border-default));\n border-radius: 6px;\n}\n.cls-doc-callout-head[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n color: var(--mj-text-secondary);\n font-size: 0.82rem;\n line-height: 1.4;\n}\n.cls-doc-callout-head[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-status-info); margin-top: 2px; }\n.cls-doc-form[_ngcontent-%COMP%] {\n margin-top: 10px;\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n}\n.cls-doc-field-list[_ngcontent-%COMP%] {\n max-height: 180px;\n overflow-y: auto;\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n padding: 6px 8px;\n}\n.cls-doc-field-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 3px 0;\n font-size: 0.82rem;\n color: var(--mj-text-primary);\n cursor: pointer;\n}"] });
|
|
2113
|
+
}
|
|
2114
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ClassifySourceTypeFormDialogComponent, [{
|
|
2115
|
+
type: Component,
|
|
2116
|
+
args: [{ standalone: false, selector: 'classify-source-type-form-dialog', template: "<!-- \u2550\u2550\u2550\u2550\u2550\u2550 SLIDE-IN FORM OVERLAY \u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (FormMode !== 'none') {\n <div class=\"at-slide-overlay\" (click)=\"CloseForm()\"></div>\n <div class=\"at-slide-panel\" [style.width.px]=\"PanelWidth\">\n <!-- Left-edge drag handle: the panel slides in from the right, so its\n resizable edge is the LEFT. Dragging left widens the panel. -->\n <div class=\"cls-resize-handle\" (mousedown)=\"StartResize($event)\"\n role=\"separator\" aria-orientation=\"vertical\" aria-label=\"Resize panel\"></div>\n <div class=\"at-slide-header\">\n <h3>\n @if (FormMode === 'add-source') { Add Content Source }\n @else if (FormMode === 'edit-source') { Edit Content Source }\n @else if (FormMode === 'add-type') { Add Content Type }\n @else if (FormMode === 'edit-type') { Edit Content Type }\n </h3>\n <button class=\"at-slide-close\" aria-label=\"Close form\" (click)=\"CloseForm()\"><i class=\"fa-solid fa-times\"></i></button>\n </div>\n <div class=\"at-slide-body\">\n\n <!-- Source form -->\n @if (FormMode === 'add-source' || FormMode === 'edit-source') {\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 SOURCE \u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"cls-section cls-section--first\">\n <div class=\"cls-section-title\"><i class=\"fa-solid fa-database\"></i> Source</div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Name</label>\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormSourceName\" placeholder=\"Source name\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Source Type</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceTypeID\">\n <option value=\"\">Select source type...</option>\n @for (opt of SourceTypeOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n <!-- Content Type + File Type: hidden for Entity source type -->\n @if (SelectedSourceTypeRequiresContentType) {\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Content Type</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormContentTypeID\">\n <option value=\"\">Select content type...</option>\n @for (opt of ContentTypeOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">File Type</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormFileTypeID\">\n <option value=\"\">Select file type...</option>\n @for (opt of FileTypeOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n }\n\n <!-- Dynamic source-type-specific fields from ConfigurationObject.RequiredFields -->\n @for (field of SelectedSourceTypeFields; track field.Key) {\n @if (!field.DependsOnField || FormSourceSpecificConfig[field.DependsOnField]) {\n @if (!field.ShowOnlyIfMultiple || GetDependentOptions(field).length > 1) {\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">{{ field.Label }} @if (field.Required) { <span class=\"at-required\">*</span> }</label>\n @switch (field.Type) {\n @case ('url') {\n <input type=\"url\" class=\"at-form-input\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n [placeholder]=\"field.Description || 'https://...'\">\n }\n @case ('path') {\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n [placeholder]=\"field.Description || '/path/to/...'\">\n }\n @case ('text') {\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n [placeholder]=\"field.Description || ''\" [value]=\"field.DefaultValue || ''\">\n }\n @case ('entity-picker') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\"\n (ngModelChange)=\"OnSourceFieldChanged(field.Key)\">\n <option value=\"\">Select entity...</option>\n @for (opt of EntitiesWithDocuments; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n }\n @case ('entity-doc-picker') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\">\n @for (opt of GetDependentOptions(field); track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n }\n @case ('storage-provider-picker') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\">\n <option value=\"\">Select provider...</option>\n @for (opt of StorageProviderOptions; track opt) {\n <option [value]=\"opt\">{{ opt }}</option>\n }\n </select>\n }\n @case ('dropdown') {\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceSpecificConfig[field.Key]\">\n <option value=\"\">Select...</option>\n @for (opt of field.Options || []; track opt.Value) {\n <option [value]=\"opt.Value\">{{ opt.Label }}</option>\n }\n </select>\n }\n }\n @if (field.Description) {\n <span class=\"at-form-hint\">{{ field.Description }}</span>\n }\n </div>\n }\n }\n }\n\n <!-- Inline Entity Document creation: shown when an Entity-type\n source's selected entity has no Entity Document yet. -->\n @if (SelectedEntityHasNoDocument) {\n <div class=\"cls-doc-callout\">\n <div class=\"cls-doc-callout-head\">\n <i class=\"fa-solid fa-circle-info\"></i>\n <span><strong>{{ SelectedEntityName }}</strong> has no Entity Document. One is required to classify its records.</span>\n </div>\n @if (!ShowInlineEntityDocForm) {\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"OpenInlineEntityDocForm()\">\n <i class=\"fa-solid fa-plus\"></i> Create Entity Document\n </button>\n }\n </div>\n\n @if (ShowInlineEntityDocForm) {\n <div class=\"cls-doc-form\">\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Document name</label>\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"NewEntityDocName\"\n placeholder=\"Document name\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Fields to include ({{ SelectedEntityDocFieldCount }} selected)</label>\n <div class=\"cls-doc-field-list\">\n @for (f of SelectedEntityFields; track f.Name) {\n <label class=\"cls-doc-field-row\">\n <input type=\"checkbox\" [(ngModel)]=\"NewEntityDocSelectedFields[f.Name]\">\n <span>{{ f.DisplayName }}</span>\n </label>\n }\n </div>\n </div>\n <div class=\"at-form-actions\">\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"CreateInlineEntityDocument()\" [disabled]=\"EntityDocSaving\">\n @if (EntityDocSaving) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Creating\u2026 }\n @else { <i class=\"fa-solid fa-check\"></i> Create }\n </button>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"CancelInlineEntityDocForm()\">Cancel</button>\n </div>\n </div>\n }\n }\n </div><!-- /Source section -->\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 EMBEDDING & VECTORS \u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"cls-section\">\n <div class=\"cls-section-title\"><i class=\"fa-solid fa-cubes\"></i> Embedding & Vectors</div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Embedding Model Override</label>\n <mj-tree-dropdown\n [BranchConfig]=\"EmbeddingVendorBranch\"\n [LeafConfig]=\"EmbeddingModelsLeaf\"\n SelectionMode=\"single\"\n SelectableTypes=\"leaf\"\n Placeholder=\"Use system default\"\n [Clearable]=\"true\"\n [Value]=\"ToCompositeKey(FormSourceEmbeddingModelID)\"\n (ValueChange)=\"FormSourceEmbeddingModelID = FromCompositeKey($event)\">\n </mj-tree-dropdown>\n <span class=\"at-form-hint\">Overrides Content Type default</span>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Vector Index Override</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormSourceVectorIndexID\">\n <option value=\"\">Use system default</option>\n @for (opt of VectorIndexOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n <span class=\"at-form-hint\">Overrides Content Type default</span>\n </div>\n </div><!-- /Embedding & Vectors section -->\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 CLASSIFICATION (full config parity, in-app) \u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"cls-section\">\n <div class=\"cls-section-title\">\n <i class=\"fa-solid fa-sliders\"></i> Classification\n <button mjButton variant=\"flat\" size=\"sm\" class=\"cls-eff-toggle\"\n (click)=\"ToggleEffectiveValues()\">\n <i class=\"fa-solid\" [class.fa-eye]=\"!ShowEffectiveValues\" [class.fa-eye-slash]=\"ShowEffectiveValues\"></i>\n {{ ShowEffectiveValues ? 'Hide effective values' : 'Show effective values' }}\n </button>\n </div>\n\n <div class=\"cls-config\">\n <!-- Taxonomy mode cards -->\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Taxonomy mode</label>\n <div class=\"cls-mode-grid\">\n @for (m of TaxonomyModes; track m.value) {\n <div class=\"cls-mode-card\" [class.selected]=\"CurrentMode === m.value\"\n (click)=\"SetMode(m.value)\">\n <i class=\"fa-solid {{ m.icon }} cls-mode-ic\"></i>\n <div class=\"cls-mode-nm\">{{ m.label }}</div>\n <div class=\"cls-mode-best\">{{ m.bestFor }}</div>\n </div>\n }\n </div>\n </div>\n\n <!-- Tag root -->\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Tag root</label>\n <select class=\"at-form-select\" [(ngModel)]=\"TagRootIDValue\">\n <option value=\"\">(none / whole taxonomy)</option>\n @for (opt of TagRootOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n <span class=\"at-form-hint\">Restricts the LLM's visible taxonomy + auto-grow target. Leave blank for the full taxonomy.</span>\n </div>\n\n <!-- Thresholds + gradient band -->\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Confidence thresholds</label>\n <div class=\"cls-threshold-pair\">\n <div class=\"cls-slider-grid\">\n <div class=\"cls-slider-field\">\n <span class=\"cls-slider-cap\">Match (auto-apply) <strong>{{ MatchThresholdValue | number: '1.2-2' }}</strong></span>\n <input type=\"range\" class=\"cls-slider\" min=\"0.50\" max=\"1.00\" step=\"0.01\"\n [ngModel]=\"MatchThresholdValue\" (ngModelChange)=\"MatchThresholdValue = $event\">\n </div>\n <div class=\"cls-slider-field\">\n <span class=\"cls-slider-cap\">Suggest (route to inbox) <strong>{{ SuggestThresholdValue | number: '1.2-2' }}</strong></span>\n <input type=\"range\" class=\"cls-slider\" min=\"0.50\" max=\"1.00\" step=\"0.01\"\n [ngModel]=\"SuggestThresholdValue\" (ngModelChange)=\"SuggestThresholdValue = $event\">\n </div>\n </div>\n <div class=\"cls-band\" aria-hidden=\"true\"></div>\n @if (ThresholdValidationMessage) {\n <div class=\"cls-validation\"><i class=\"fa-solid fa-circle-exclamation\"></i> {{ ThresholdValidationMessage }}</div>\n } @else {\n <div class=\"cls-band-legend\">\n <span class=\"cls-band-key reject\">reject / new</span>\n <span class=\"cls-band-key review\">review (inbox)</span>\n <span class=\"cls-band-key apply\">auto-apply</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Toggles -->\n <div class=\"cls-toggle-row\">\n <div class=\"cls-toggle-label\">\n <span class=\"t\">Share full taxonomy with the LLM</span>\n <span class=\"d\">When on, the LLM prompt includes the visible taxonomy. Larger taxonomies \u2192 higher token cost.</span>\n </div>\n <mj-switch [(ngModel)]=\"ShareTaxonomyValue\"></mj-switch>\n </div>\n <div class=\"cls-toggle-row\">\n <div class=\"cls-toggle-label\">\n <span class=\"t\">Vectorize new content</span>\n <span class=\"d\">When off, this source skips vectorization (the classifier still runs).</span>\n </div>\n <mj-switch [(ngModel)]=\"EnableVectorizationValue\"></mj-switch>\n </div>\n </div><!-- /cls-config -->\n\n <!-- Effective-values panel \u2014 inline + conditional (no longer a floating aside) -->\n @if (ShowEffectiveValues) {\n <div class=\"cls-aside\">\n <h5 class=\"cls-aside-title\">Effective values</h5>\n @for (row of EffectiveValues; track row.label) {\n <div class=\"cls-eff-row\">\n <span class=\"cls-eff-label\">{{ row.label }}</span>\n <span class=\"cls-eff-value\">{{ row.value }}\n <span class=\"cls-eff-origin\" [class.override]=\"row.origin === 'source override'\">{{ row.origin }}</span>\n </span>\n </div>\n }\n </div>\n }\n </div><!-- /Classification section -->\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 DOMAIN CONTEXT (source scope) \u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"cls-section\">\n <div class=\"cls-section-title\"><i class=\"fa-solid fa-comment-dots\"></i> Domain context</div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Source guidance</label>\n <textarea class=\"at-form-textarea\" rows=\"4\"\n [ngModel]=\"ClassificationContextValue\"\n (ngModelChange)=\"ClassificationContextValue = $event\"\n placeholder=\"Free-text guidance for the classifier about this source's domain \u2014 terminology, audience, what tags matter\u2026\"></textarea>\n <span class=\"at-form-hint\">Injected into the autotagging prompt at the source scope.</span>\n </div>\n\n <div class=\"cls-toggle-row\">\n <div class=\"cls-toggle-label\">\n <span class=\"t\">Substitutive mode</span>\n <span class=\"d\">When on, this source's guidance <em>replaces</em> the org/content-type context. When off (default), it's <em>added</em> to them.</span>\n </div>\n <mj-switch [(ngModel)]=\"IsSubstitutiveMode\"></mj-switch>\n </div>\n\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Effective context preview</label>\n <pre class=\"cls-context-preview\">{{ EffectiveContextPreview }}</pre>\n <span class=\"at-form-hint\">Org + source scopes shown. Content-type scope (if any) is also merged at run time.</span>\n </div>\n </div><!-- /Domain context section -->\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 RUN BUDGETS \u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"cls-section\">\n <div class=\"cls-section-title\"><i class=\"fa-solid fa-gauge\"></i> Run budgets</div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Max items per run</label>\n <input type=\"number\" min=\"0\" class=\"at-form-input\"\n [(ngModel)]=\"FormMaxItemsPerRun\" placeholder=\"unlimited\">\n <span class=\"at-form-hint\">\n Caps the number of content items handed to the LLM. Skipped (unchanged) items don't count.\n Paused work resumes on the next run.\n </span>\n </div>\n\n <div class=\"cls-budget-grid\">\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Max new tags / run</label>\n <input type=\"number\" min=\"0\" class=\"at-form-input\"\n [ngModel]=\"MaxNewTagsPerRunValue ?? ''\" (ngModelChange)=\"MaxNewTagsPerRunValue = $event\"\n placeholder=\"unlimited\">\n <span class=\"at-form-hint\">across all items</span>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Max new tags / item</label>\n <input type=\"number\" min=\"0\" class=\"at-form-input\"\n [ngModel]=\"MaxNewTagsPerItemValue ?? ''\" (ngModelChange)=\"MaxNewTagsPerItemValue = $event\"\n placeholder=\"unlimited\">\n <span class=\"at-form-hint\">extras \u2192 suggestions</span>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Max tokens / run</label>\n <input type=\"number\" min=\"0\" class=\"at-form-input\"\n [ngModel]=\"MaxTokensPerRunValue ?? ''\" (ngModelChange)=\"MaxTokensPerRunValue = $event\"\n placeholder=\"unlimited\">\n <span class=\"at-form-hint\">across all LLM calls</span>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Max cost / run (USD)</label>\n <input type=\"number\" min=\"0\" step=\"0.01\" class=\"at-form-input\"\n [ngModel]=\"MaxCostPerRunValue ?? ''\" (ngModelChange)=\"MaxCostPerRunValue = $event\"\n placeholder=\"unlimited\">\n <span class=\"at-form-hint\">$ stops the run</span>\n </div>\n </div>\n </div><!-- /Run budgets section -->\n\n @if (IsWebsiteSourceTypeSelected) {\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550 CRAWL SETTINGS (website source only) \u2550\u2550\u2550\u2550\u2550\u2550 -->\n <div class=\"cls-section\">\n <div class=\"cls-section-title\"><i class=\"fa-solid fa-spider\"></i> Crawl settings</div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Crawl depth</label>\n <input type=\"number\" min=\"0\" max=\"10\" step=\"1\" class=\"at-form-input\"\n [(ngModel)]=\"FormMaxDepth\" placeholder=\"2 (default)\">\n <span class=\"at-form-hint\">\n Recursion ceiling for in-domain links. <code>0</code> = just the start URL.\n <code>2</code> (default) = root + sections + content pages.\n </span>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">\n <input type=\"checkbox\" [(ngModel)]=\"FormCrawlSitesInLowerLevelDomain\">\n Crawl sites in lower-level domain\n </label>\n <span class=\"at-form-hint\">When on (default), the depth-aware recursive crawler runs. Turn off to crawl only the seed page.</span>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">\n <input type=\"checkbox\" [(ngModel)]=\"FormCrawlOtherSitesInTopLevelDomain\">\n Crawl other sites in top-level domain\n </label>\n <span class=\"at-form-hint\">When on, also adds sibling-path URLs found on the seed page. Off by default to avoid accidental fan-out.</span>\n </div>\n </div><!-- /Crawl settings section -->\n }\n\n <div class=\"at-form-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveSource()\" [disabled]=\"FormSaving\">\n @if (FormSaving) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving... }\n @else { <i class=\"fa-solid fa-check\"></i> Save }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseForm()\">Cancel</button>\n </div>\n\n @if (FormMode === 'edit-source' && EditingSourceID) {\n <div class=\"at-form-advanced-link\">\n <a href=\"javascript:void(0)\" (click)=\"OpenAdvancedSourceSettings()\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i>\n Open advanced settings \u2014 URL pattern, root URL, & full entity form\n </a>\n <span class=\"at-form-hint\">The key classifier knobs (taxonomy mode, thresholds, tag root, budgets) are now editable inline above.</span>\n </div>\n }\n }\n\n <!-- Content Type form -->\n @if (FormMode === 'add-type' || FormMode === 'edit-type') {\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Name</label>\n <input type=\"text\" class=\"at-form-input\" [(ngModel)]=\"FormTypeName\" placeholder=\"Content type name\">\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Description</label>\n <textarea class=\"at-form-textarea\" [(ngModel)]=\"FormTypeDescription\" rows=\"3\" placeholder=\"Description...\"></textarea>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">AI Model (for tagging)</label>\n <mj-tree-dropdown\n [BranchConfig]=\"AIModelVendorBranch\"\n [LeafConfig]=\"AllModelsLeaf\"\n SelectionMode=\"single\"\n SelectableTypes=\"leaf\"\n Placeholder=\"Select AI model...\"\n [Clearable]=\"true\"\n [Value]=\"ToCompositeKey(FormTypeAIModelID)\"\n (ValueChange)=\"FormTypeAIModelID = FromCompositeKey($event)\">\n </mj-tree-dropdown>\n </div>\n <div class=\"at-form-row\">\n <div class=\"at-form-group\" style=\"flex: 1;\">\n <label class=\"at-form-label\">Min Tags</label>\n <input type=\"number\" class=\"at-form-input\" [(ngModel)]=\"FormTypeMinTags\" min=\"0\">\n </div>\n <div class=\"at-form-group\" style=\"flex: 1;\">\n <label class=\"at-form-label\">Max Tags</label>\n <input type=\"number\" class=\"at-form-input\" [(ngModel)]=\"FormTypeMaxTags\" min=\"1\">\n </div>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Embedding Model</label>\n <mj-tree-dropdown\n [BranchConfig]=\"EmbeddingVendorBranch\"\n [LeafConfig]=\"EmbeddingModelsLeaf\"\n SelectionMode=\"single\"\n SelectableTypes=\"leaf\"\n Placeholder=\"Use system default\"\n [Clearable]=\"true\"\n [Value]=\"ToCompositeKey(FormTypeEmbeddingModelID)\"\n (ValueChange)=\"FormTypeEmbeddingModelID = FromCompositeKey($event)\">\n </mj-tree-dropdown>\n </div>\n <div class=\"at-form-group\">\n <label class=\"at-form-label\">Vector Index</label>\n <select class=\"at-form-select\" [(ngModel)]=\"FormTypeVectorIndexID\">\n <option value=\"\">Use system default</option>\n @for (opt of VectorIndexOptions; track opt.ID) {\n <option [value]=\"opt.ID\">{{ opt.Name }}</option>\n }\n </select>\n </div>\n <div class=\"at-form-actions\">\n <button class=\"at-action-btn at-primary-btn\" (click)=\"SaveContentType()\" [disabled]=\"FormSaving\">\n @if (FormSaving) { <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving... }\n @else { <i class=\"fa-solid fa-check\"></i> Save }\n </button>\n <button class=\"at-action-btn at-secondary-btn\" (click)=\"CloseForm()\">Cancel</button>\n </div>\n }\n </div>\n </div>\n}\n", styles: ["/*\n * Source + Content Type CRUD slide-in form dialog styles.\n *\n * The host (AutotaggingPipelineResourceComponent) uses ViewEncapsulation.None,\n * so its `.at-slide-*` / `.at-form-*` rules are global and already style this\n * dialog's markup while it renders inside the host shell.\n *\n * The `.cls-*` (Classification) rules below are NEW to the in-dashboard config\n * parity feature. All colors use semantic design tokens (no hardcoded hex), and\n * the threshold band gradient is built from color-mix() of semantic tokens so it\n * adapts to dark mode and white-labeling.\n */\n\n/* \u2500\u2500 Left-edge resize handle \u2500\u2500\n * The slide-in panel slides in from the right, so its resizable edge is the LEFT.\n * A thin full-height grab strip; tokenized hover color so it adapts to themes. */\n.cls-resize-handle {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n z-index: 1002;\n background: transparent;\n transition: background 0.12s;\n}\n.cls-resize-handle:hover,\n.cls-resize-handle:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n/* \u2500\u2500 Section shells (Source / Embedding / Classification / Run budgets / Crawl) \u2500\u2500 */\n.cls-section {\n margin-top: 8px;\n padding-top: 12px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n/* The first section needs no separator above it. */\n.cls-section--first {\n margin-top: 0;\n padding-top: 0;\n border-top: 0;\n}\n.cls-section-title {\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 12px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.cls-section-title i { color: var(--mj-brand-primary); }\n\n/* \"Show / hide effective values\" toggle, pushed to the right of the section title. */\n.cls-eff-toggle {\n margin-left: auto;\n font-weight: 600;\n}\n\n/* Single-column control stack. The effective-values panel now renders inline\n * below (full width within the section), not as a floating grid column. */\n.cls-config {\n display: block;\n}\n\n/* \u2500\u2500 Taxonomy mode cards \u2500\u2500 */\n.cls-mode-grid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 8px;\n}\n.cls-mode-card {\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 8px;\n padding: 10px 8px;\n cursor: pointer;\n text-align: center;\n transition: background 0.12s, border-color 0.12s, box-shadow 0.12s;\n user-select: none;\n}\n.cls-mode-card:hover { background: var(--mj-bg-surface-hover); }\n.cls-mode-card.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n border-color: var(--mj-brand-primary);\n box-shadow: inset 0 0 0 1px var(--mj-brand-primary);\n}\n.cls-mode-ic { font-size: 16px; color: var(--mj-text-secondary); }\n.cls-mode-card.selected .cls-mode-ic { color: var(--mj-brand-primary); }\n.cls-mode-nm { font-size: 12px; font-weight: 700; color: var(--mj-text-primary); margin: 4px 0 2px; }\n.cls-mode-best { font-size: 10.5px; color: var(--mj-text-muted); line-height: 1.3; }\n\n/* \u2500\u2500 Thresholds + gradient band \u2500\u2500 */\n.cls-threshold-pair {\n background: var(--mj-bg-surface-card);\n padding: 12px 14px;\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n}\n.cls-slider-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px 16px;\n}\n@media (max-width: 560px) {\n .cls-slider-grid { grid-template-columns: 1fr; }\n}\n.cls-slider-field { display: flex; flex-direction: column; gap: 4px; }\n.cls-slider-cap { font-size: 11px; color: var(--mj-text-secondary); }\n.cls-slider-cap strong {\n font-family: ui-monospace, monospace;\n color: var(--mj-text-primary);\n margin-left: 2px;\n}\n.cls-slider {\n appearance: none;\n -webkit-appearance: none;\n width: 100%;\n height: 6px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 3px;\n margin: 2px 0;\n}\n.cls-slider::-webkit-slider-thumb {\n appearance: none;\n -webkit-appearance: none;\n width: 16px; height: 16px; border-radius: 50%;\n background: var(--mj-brand-primary);\n cursor: pointer;\n border: 2px solid var(--mj-bg-surface);\n}\n.cls-slider::-moz-range-thumb {\n width: 16px; height: 16px; border-radius: 50%;\n background: var(--mj-brand-primary);\n cursor: pointer;\n border: 2px solid var(--mj-bg-surface);\n}\n\n/* The reject | review | auto-apply gradient band \u2014 all stops from semantic tokens. */\n.cls-band {\n height: 8px;\n border-radius: 4px;\n margin: 10px 0 6px;\n background: linear-gradient(\n to right,\n color-mix(in srgb, var(--mj-status-error) 55%, transparent) 0%,\n color-mix(in srgb, var(--mj-status-warning) 55%, transparent) 50%,\n color-mix(in srgb, var(--mj-status-success) 55%, transparent) 100%\n );\n}\n.cls-band-legend {\n display: flex;\n justify-content: space-between;\n font-size: 10.5px;\n}\n.cls-band-key.reject { color: var(--mj-status-error-text, var(--mj-status-error)); }\n.cls-band-key.review { color: var(--mj-status-warning-text, var(--mj-status-warning)); }\n.cls-band-key.apply { color: var(--mj-status-success-text, var(--mj-status-success)); }\n.cls-validation {\n font-size: 12px;\n padding: 8px 12px;\n margin-top: 8px;\n background: color-mix(in srgb, var(--mj-status-error) 12%, transparent);\n color: var(--mj-status-error-text, var(--mj-status-error));\n border-radius: 4px;\n}\n\n/* \u2500\u2500 Toggles \u2500\u2500 */\n.cls-toggle-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 10px 0;\n border-top: 1px dashed var(--mj-border-subtle);\n}\n.cls-toggle-label .t { display: block; font-size: 13px; font-weight: 600; color: var(--mj-text-primary); }\n.cls-toggle-label .d { display: block; font-size: 11px; color: var(--mj-text-muted); margin-top: 2px; }\n\n/* \u2500\u2500 Effective-values panel (inline + conditional) \u2500\u2500\n * Repurposed from the old floating aside: renders inline at the end of the\n * Classification section, full width within the section \u2014 never overlaps. */\n.cls-aside {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 12px;\n margin-top: 12px;\n}\n.cls-aside-title {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--mj-text-muted);\n font-weight: 700;\n margin: 0 0 8px;\n}\n.cls-eff-row {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 8px;\n padding: 6px 0;\n border-top: 1px solid var(--mj-border-subtle);\n font-size: 12px;\n}\n.cls-eff-row:first-of-type { border-top: 0; }\n.cls-eff-label { color: var(--mj-text-secondary); }\n.cls-eff-value { color: var(--mj-text-primary); font-weight: 600; text-align: right; }\n.cls-eff-origin {\n display: block;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.03em;\n margin-top: 1px;\n}\n.cls-eff-origin.override { color: var(--mj-brand-primary); }\n\n/* \u2500\u2500 Budget grid \u2500\u2500 */\n.cls-budget-grid {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 12px 16px;\n margin-top: 8px;\n}\n@media (max-width: 480px) {\n .cls-budget-grid { grid-template-columns: 1fr; }\n}\n\n/* \u2500\u2500 Domain context: effective-context preview \u2500\u2500 */\n.cls-context-preview {\n margin: 0;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n color: var(--mj-text-secondary);\n font-size: 0.8rem;\n line-height: 1.45;\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 200px;\n overflow-y: auto;\n}\n\n/* \u2500\u2500 Inline Entity Document creation \u2500\u2500 */\n.cls-doc-callout {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-top: 12px;\n padding: 12px;\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n border: 1px solid var(--mj-status-info-border, var(--mj-border-default));\n border-radius: 6px;\n}\n.cls-doc-callout-head {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n color: var(--mj-text-secondary);\n font-size: 0.82rem;\n line-height: 1.4;\n}\n.cls-doc-callout-head i { color: var(--mj-status-info); margin-top: 2px; }\n.cls-doc-form {\n margin-top: 10px;\n padding: 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n}\n.cls-doc-field-list {\n max-height: 180px;\n overflow-y: auto;\n border: 1px solid var(--mj-border-subtle);\n border-radius: 6px;\n padding: 6px 8px;\n}\n.cls-doc-field-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 3px 0;\n font-size: 0.82rem;\n color: var(--mj-text-primary);\n cursor: pointer;\n}\n"] }]
|
|
2117
|
+
}], null, { Saved: [{
|
|
2118
|
+
type: Output
|
|
2119
|
+
}], ContentTypeMissing: [{
|
|
2120
|
+
type: Output
|
|
2121
|
+
}], NavigateToRecordRequested: [{
|
|
2122
|
+
type: Output
|
|
2123
|
+
}] }); })();
|
|
2124
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ClassifySourceTypeFormDialogComponent, { className: "ClassifySourceTypeFormDialogComponent", filePath: "src/AI/components/autotagging/dialogs/source-type-form.dialog.component.ts", lineNumber: 102 }); })();
|
|
2125
|
+
//# sourceMappingURL=source-type-form.dialog.component.js.map
|