@memberjunction/ng-dashboards 5.34.0 → 5.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AI/components/agents/agent-configuration.component.d.ts +51 -0
- package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-configuration.component.js +399 -292
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.d.ts +8 -2
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js +87 -85
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts +75 -0
- package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.js +400 -89
- package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
- package/dist/AI/components/analytics/analytics-filter-bar.component.d.ts +5 -0
- package/dist/AI/components/analytics/analytics-filter-bar.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/analytics-filter-bar.component.js +184 -135
- package/dist/AI/components/analytics/analytics-filter-bar.component.js.map +1 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +8 -2
- 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 +104 -103
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -1
- package/dist/AI/components/analytics/error-analysis/error-analysis.component.d.ts +8 -2
- package/dist/AI/components/analytics/error-analysis/error-analysis.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/error-analysis/error-analysis.component.js +76 -74
- package/dist/AI/components/analytics/error-analysis/error-analysis.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 +67 -87
- 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 +12 -19
- 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 +96 -203
- 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.map +1 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +110 -126
- 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.map +1 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +61 -77
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +990 -992
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +6 -3
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +493 -490
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.d.ts +17 -0
- package/dist/AI/components/models/model-management.component.d.ts.map +1 -1
- package/dist/AI/components/models/model-management.component.js +370 -425
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.d.ts +17 -0
- package/dist/AI/components/prompts/prompt-management.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +317 -357
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/requests/agent-requests-resource.component.d.ts +11 -0
- package/dist/AI/components/requests/agent-requests-resource.component.d.ts.map +1 -1
- package/dist/AI/components/requests/agent-requests-resource.component.js +170 -175
- package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.d.ts +19 -0
- package/dist/AI/components/system/system-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +403 -362
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +781 -783
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +8 -3
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +547 -521
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.d.ts +6 -0
- package/dist/Actions/components/actions-overview.component.d.ts.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +79 -30
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.d.ts +9 -3
- package/dist/Actions/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +196 -142
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.d.ts +41 -1
- package/dist/Actions/components/explorer/action-explorer.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +388 -94
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Actions/components/explorer/index.d.ts +0 -1
- package/dist/Actions/components/explorer/index.d.ts.map +1 -1
- package/dist/Actions/components/explorer/index.js +0 -1
- package/dist/Actions/components/explorer/index.js.map +1 -1
- package/dist/Admin/admin-data-schema.component.js +32 -40
- package/dist/Admin/admin-data-schema.component.js.map +1 -1
- package/dist/Admin/admin-dev-tools-resource.component.js +32 -40
- package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
- package/dist/Admin/admin-identity-access.component.js +32 -40
- package/dist/Admin/admin-identity-access.component.js.map +1 -1
- package/dist/Admin/admin-monitoring.component.js +32 -40
- package/dist/Admin/admin-monitoring.component.js.map +1 -1
- package/dist/ApplicationRoles/application-roles-resource.component.js +76 -82
- package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
- package/dist/Archiving/components/archive-config-resource.component.d.ts.map +1 -1
- package/dist/Archiving/components/archive-config-resource.component.js +24 -5
- package/dist/Archiving/components/archive-config-resource.component.js.map +1 -1
- package/dist/Archiving/components/archive-runs-resource.component.d.ts.map +1 -1
- package/dist/Archiving/components/archive-runs-resource.component.js +24 -5
- package/dist/Archiving/components/archive-runs-resource.component.js.map +1 -1
- package/dist/Communication/communication-logs-resource.component.d.ts +1 -1
- package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-logs-resource.component.js +80 -99
- package/dist/Communication/communication-logs-resource.component.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +127 -106
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-providers-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-providers-resource.component.js +44 -45
- package/dist/Communication/communication-providers-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +60 -58
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.d.ts +1 -1
- package/dist/Communication/communication-templates-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js +139 -162
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.d.ts +7 -0
- package/dist/Credentials/components/credentials-audit-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.js +310 -297
- package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +245 -266
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.d.ts +7 -0
- package/dist/Credentials/components/credentials-list-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +381 -399
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +222 -228
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.d.ts +6 -0
- package/dist/Credentials/components/credentials-types-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +294 -305
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.d.ts +8 -0
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.d.ts.map +1 -1
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +21 -0
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js.map +1 -1
- package/dist/DatabaseDesigner/components/entity-list.component.js +147 -160
- package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js +19 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +20 -16
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.d.ts +6 -0
- package/dist/Home/home-dashboard.component.d.ts.map +1 -1
- package/dist/Home/home-dashboard.component.js +521 -485
- package/dist/Home/home-dashboard.component.js.map +1 -1
- package/dist/Integration/components/activity/activity.component.d.ts +8 -0
- package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
- package/dist/Integration/components/activity/activity.component.js +309 -318
- package/dist/Integration/components/activity/activity.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +866 -847
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +234 -233
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
- package/dist/Integration/components/overview/overview.component.js +182 -163
- package/dist/Integration/components/overview/overview.component.js.map +1 -1
- package/dist/Integration/components/pipelines/pipelines.component.d.ts +2 -0
- package/dist/Integration/components/pipelines/pipelines.component.d.ts.map +1 -1
- package/dist/Integration/components/pipelines/pipelines.component.js +610 -606
- package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -1
- package/dist/Integration/components/schedules/schedules.component.js +241 -241
- package/dist/Integration/components/schedules/schedules.component.js.map +1 -1
- package/dist/Integration/integration.module.d.ts +1 -1
- package/dist/Integration/integration.module.d.ts.map +1 -1
- package/dist/Integration/integration.module.js +28 -1
- package/dist/Integration/integration.module.js.map +1 -1
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +673 -674
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +54 -51
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +745 -703
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.d.ts +12 -1
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +191 -120
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.d.ts +18 -1
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +486 -532
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +152 -160
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +302 -319
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +234 -246
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.d.ts +20 -0
- package/dist/MCP/mcp-dashboard.component.d.ts.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +1248 -1338
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/MCP/mcp.module.d.ts +1 -1
- package/dist/MCP/mcp.module.d.ts.map +1 -1
- package/dist/MCP/mcp.module.js +34 -1
- package/dist/MCP/mcp.module.js.map +1 -1
- package/dist/Permissions/audit-log-resource.component.js +76 -85
- package/dist/Permissions/audit-log-resource.component.js.map +1 -1
- package/dist/Permissions/resource-access-resource.component.js +64 -69
- package/dist/Permissions/resource-access-resource.component.js.map +1 -1
- package/dist/Permissions/user-access-resource.component.js +63 -74
- package/dist/Permissions/user-access-resource.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +2 -2
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity-resource.component.d.ts +2 -1
- package/dist/Scheduling/components/scheduling-activity-resource.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-activity-resource.component.js +11 -12
- package/dist/Scheduling/components/scheduling-activity-resource.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.d.ts +9 -1
- package/dist/Scheduling/components/scheduling-activity.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.js +250 -197
- package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs-resource.component.d.ts +2 -1
- package/dist/Scheduling/components/scheduling-jobs-resource.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs-resource.component.js +11 -12
- package/dist/Scheduling/components/scheduling-jobs-resource.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.d.ts +9 -1
- package/dist/Scheduling/components/scheduling-jobs.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js +203 -147
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview-resource.component.d.ts +2 -1
- package/dist/Scheduling/components/scheduling-overview-resource.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-overview-resource.component.js +11 -12
- package/dist/Scheduling/components/scheduling-overview-resource.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.d.ts +3 -1
- package/dist/Scheduling/components/scheduling-overview.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js +224 -190
- package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.d.ts +19 -6
- package/dist/Scheduling/scheduling-dashboard.component.d.ts.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js +262 -104
- package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
- package/dist/SystemDiagnostics/system-diagnostics.component.d.ts +4 -0
- package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
- package/dist/SystemDiagnostics/system-diagnostics.component.js +812 -784
- package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
- package/dist/Testing/components/testing-analytics-resource.component.d.ts +2 -1
- package/dist/Testing/components/testing-analytics-resource.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-analytics-resource.component.js +7 -14
- package/dist/Testing/components/testing-analytics-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-analytics.component.d.ts +3 -1
- package/dist/Testing/components/testing-analytics.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-analytics.component.js +420 -393
- package/dist/Testing/components/testing-analytics.component.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.d.ts +2 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.js +16 -19
- package/dist/Testing/components/testing-dashboard-tab-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab.component.d.ts +3 -1
- package/dist/Testing/components/testing-dashboard-tab.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab.component.js +157 -122
- package/dist/Testing/components/testing-dashboard-tab.component.js.map +1 -1
- package/dist/Testing/components/testing-explorer-resource.component.d.ts +2 -1
- package/dist/Testing/components/testing-explorer-resource.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer-resource.component.js +7 -12
- package/dist/Testing/components/testing-explorer-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts +8 -1
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +587 -608
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-review-resource.component.d.ts +4 -1
- package/dist/Testing/components/testing-review-resource.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-review-resource.component.js +9 -12
- package/dist/Testing/components/testing-review-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-review.component.d.ts +3 -1
- package/dist/Testing/components/testing-review.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-review.component.js +310 -274
- package/dist/Testing/components/testing-review.component.js.map +1 -1
- package/dist/Testing/components/testing-runs-resource.component.d.ts +2 -1
- package/dist/Testing/components/testing-runs-resource.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-runs-resource.component.js +16 -19
- package/dist/Testing/components/testing-runs-resource.component.js.map +1 -1
- package/dist/Testing/components/testing-runs.component.d.ts +3 -1
- package/dist/Testing/components/testing-runs.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-runs.component.js +307 -273
- package/dist/Testing/components/testing-runs.component.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.d.ts +2 -0
- package/dist/Testing/testing-dashboard.component.d.ts.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +107 -93
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/VersionHistory/components/diff-resource.component.js +185 -188
- package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/graph-resource.component.js +154 -184
- package/dist/VersionHistory/components/graph-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.d.ts +7 -0
- package/dist/VersionHistory/components/labels-resource.component.d.ts.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.js +350 -354
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.js +163 -169
- package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
- package/dist/actions-dashboards.module.d.ts +15 -16
- package/dist/actions-dashboards.module.d.ts.map +1 -1
- package/dist/actions-dashboards.module.js +34 -11
- package/dist/actions-dashboards.module.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +45 -48
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +36 -10
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/archiving-dashboards.module.d.ts +2 -1
- package/dist/archiving-dashboards.module.d.ts.map +1 -1
- package/dist/archiving-dashboards.module.js +12 -2
- package/dist/archiving-dashboards.module.js.map +1 -1
- package/dist/communication-dashboards.module.d.ts +2 -1
- package/dist/communication-dashboards.module.d.ts.map +1 -1
- package/dist/communication-dashboards.module.js +24 -3
- package/dist/communication-dashboards.module.js.map +1 -1
- package/dist/core-dashboards.module.d.ts +1 -1
- package/dist/core-dashboards.module.d.ts.map +1 -1
- package/dist/core-dashboards.module.js +31 -1
- package/dist/core-dashboards.module.js.map +1 -1
- package/dist/credentials-dashboards.module.d.ts +1 -1
- package/dist/credentials-dashboards.module.d.ts.map +1 -1
- package/dist/credentials-dashboards.module.js +28 -1
- package/dist/credentials-dashboards.module.js.map +1 -1
- package/dist/lists-dashboards.module.d.ts +1 -1
- package/dist/lists-dashboards.module.d.ts.map +1 -1
- package/dist/lists-dashboards.module.js +28 -1
- package/dist/lists-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +2 -2
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +3 -3
- package/dist/public-api.js.map +1 -1
- package/dist/scheduling-dashboards.module.d.ts +1 -1
- package/dist/scheduling-dashboards.module.d.ts.map +1 -1
- package/dist/scheduling-dashboards.module.js +31 -1
- package/dist/scheduling-dashboards.module.js.map +1 -1
- package/dist/testing-dashboards.module.d.ts +8 -7
- package/dist/testing-dashboards.module.d.ts.map +1 -1
- package/dist/testing-dashboards.module.js +30 -0
- package/dist/testing-dashboards.module.js.map +1 -1
- package/package.json +52 -52
- package/dist/AI/components/agents/agent-filter-panel.component.d.ts +0 -56
- package/dist/AI/components/agents/agent-filter-panel.component.d.ts.map +0 -1
- package/dist/AI/components/agents/agent-filter-panel.component.js +0 -285
- package/dist/AI/components/agents/agent-filter-panel.component.js.map +0 -1
- package/dist/AI/components/prompts/prompt-filter-panel.component.d.ts +0 -49
- package/dist/AI/components/prompts/prompt-filter-panel.component.d.ts.map +0 -1
- package/dist/AI/components/prompts/prompt-filter-panel.component.js +0 -184
- package/dist/AI/components/prompts/prompt-filter-panel.component.js.map +0 -1
- package/dist/AI/components/system/system-config-filter-panel.component.d.ts +0 -33
- package/dist/AI/components/system/system-config-filter-panel.component.d.ts.map +0 -1
- package/dist/AI/components/system/system-config-filter-panel.component.js +0 -144
- package/dist/AI/components/system/system-config-filter-panel.component.js.map +0 -1
- package/dist/Actions/components/explorer/action-toolbar.component.d.ts +0 -63
- package/dist/Actions/components/explorer/action-toolbar.component.d.ts.map +0 -1
- package/dist/Actions/components/explorer/action-toolbar.component.js +0 -463
- package/dist/Actions/components/explorer/action-toolbar.component.js.map +0 -1
|
@@ -14,36 +14,38 @@ import * as i2 from "@angular/forms";
|
|
|
14
14
|
import * as i3 from "@memberjunction/ng-ui-components";
|
|
15
15
|
import * as i4 from "@memberjunction/ng-shared-generic";
|
|
16
16
|
const _forTrack0 = ($index, $item) => $item.ID;
|
|
17
|
-
function
|
|
18
|
-
i0.ɵɵelement(0, "i",
|
|
17
|
+
function ApplicationRolesResourceComponent_Conditional_3_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
18
|
+
i0.ɵɵelement(0, "i", 12);
|
|
19
19
|
i0.ɵɵtext(1, " Saving... ");
|
|
20
20
|
} }
|
|
21
|
-
function
|
|
22
|
-
i0.ɵɵelement(0, "i",
|
|
21
|
+
function ApplicationRolesResourceComponent_Conditional_3_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
22
|
+
i0.ɵɵelement(0, "i", 13);
|
|
23
23
|
i0.ɵɵtext(1, " Save Changes ");
|
|
24
24
|
} }
|
|
25
|
-
function
|
|
25
|
+
function ApplicationRolesResourceComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
26
26
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
27
|
-
i0.ɵɵ
|
|
28
|
-
i0.ɵɵ
|
|
29
|
-
i0.ɵɵ
|
|
30
|
-
i0.ɵɵ
|
|
27
|
+
i0.ɵɵelement(0, "mj-stat-badge", 8);
|
|
28
|
+
i0.ɵɵelementStart(1, "button", 9);
|
|
29
|
+
i0.ɵɵlistener("click", function ApplicationRolesResourceComponent_Conditional_3_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.DiscardChanges()); });
|
|
30
|
+
i0.ɵɵelement(2, "i", 10);
|
|
31
|
+
i0.ɵɵtext(3, " Discard ");
|
|
31
32
|
i0.ɵɵelementEnd();
|
|
32
|
-
i0.ɵɵelementStart(
|
|
33
|
-
i0.ɵɵlistener("click", function
|
|
34
|
-
i0.ɵɵconditionalCreate(
|
|
33
|
+
i0.ɵɵelementStart(4, "button", 11);
|
|
34
|
+
i0.ɵɵlistener("click", function ApplicationRolesResourceComponent_Conditional_3_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SaveChanges()); });
|
|
35
|
+
i0.ɵɵconditionalCreate(5, ApplicationRolesResourceComponent_Conditional_3_Conditional_5_Template, 2, 0)(6, ApplicationRolesResourceComponent_Conditional_3_Conditional_6_Template, 2, 0);
|
|
35
36
|
i0.ɵɵelementEnd();
|
|
36
37
|
} if (rf & 2) {
|
|
37
38
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
39
|
+
i0.ɵɵadvance();
|
|
38
40
|
i0.ɵɵproperty("disabled", ctx_r1.IsSaving);
|
|
39
41
|
i0.ɵɵadvance(3);
|
|
40
42
|
i0.ɵɵproperty("disabled", ctx_r1.IsSaving);
|
|
41
43
|
i0.ɵɵadvance();
|
|
42
|
-
i0.ɵɵconditional(ctx_r1.IsSaving ?
|
|
44
|
+
i0.ɵɵconditional(ctx_r1.IsSaving ? 5 : 6);
|
|
43
45
|
} }
|
|
44
|
-
function
|
|
45
|
-
i0.ɵɵelementStart(0, "div",
|
|
46
|
-
i0.ɵɵelement(1, "i",
|
|
46
|
+
function ApplicationRolesResourceComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
47
|
+
i0.ɵɵelementStart(0, "div", 5);
|
|
48
|
+
i0.ɵɵelement(1, "i", 14);
|
|
47
49
|
i0.ɵɵtext(2);
|
|
48
50
|
i0.ɵɵelementEnd();
|
|
49
51
|
} if (rf & 2) {
|
|
@@ -51,9 +53,9 @@ function ApplicationRolesResourceComponent_Conditional_11_Template(rf, ctx) { if
|
|
|
51
53
|
i0.ɵɵadvance(2);
|
|
52
54
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.ErrorMessage, " ");
|
|
53
55
|
} }
|
|
54
|
-
function
|
|
55
|
-
i0.ɵɵelementStart(0, "div",
|
|
56
|
-
i0.ɵɵelement(1, "i",
|
|
56
|
+
function ApplicationRolesResourceComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
57
|
+
i0.ɵɵelementStart(0, "div", 6);
|
|
58
|
+
i0.ɵɵelement(1, "i", 15);
|
|
57
59
|
i0.ɵɵtext(2);
|
|
58
60
|
i0.ɵɵelementEnd();
|
|
59
61
|
} if (rf & 2) {
|
|
@@ -61,29 +63,29 @@ function ApplicationRolesResourceComponent_Conditional_12_Template(rf, ctx) { if
|
|
|
61
63
|
i0.ɵɵadvance(2);
|
|
62
64
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.SuccessMessage, " ");
|
|
63
65
|
} }
|
|
64
|
-
function
|
|
65
|
-
i0.ɵɵelement(0, "mj-loading",
|
|
66
|
+
function ApplicationRolesResourceComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
67
|
+
i0.ɵɵelement(0, "mj-loading", 7);
|
|
66
68
|
} }
|
|
67
|
-
function
|
|
69
|
+
function ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Conditional_1_For_13_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
68
70
|
i0.ɵɵelementStart(0, "span", 40);
|
|
69
71
|
i0.ɵɵtext(1, "new");
|
|
70
72
|
i0.ɵɵelementEnd();
|
|
71
73
|
} }
|
|
72
|
-
function
|
|
74
|
+
function ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Conditional_1_For_13_Template(rf, ctx) { if (rf & 1) {
|
|
73
75
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
74
76
|
i0.ɵɵelementStart(0, "tr")(1, "td", 34);
|
|
75
77
|
i0.ɵɵelement(2, "i", 39);
|
|
76
78
|
i0.ɵɵtext(3);
|
|
77
|
-
i0.ɵɵconditionalCreate(4,
|
|
79
|
+
i0.ɵɵconditionalCreate(4, ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Conditional_1_For_13_Conditional_4_Template, 2, 0, "span", 40);
|
|
78
80
|
i0.ɵɵelementEnd();
|
|
79
81
|
i0.ɵɵelementStart(5, "td", 35)(6, "input", 41);
|
|
80
|
-
i0.ɵɵlistener("change", function
|
|
82
|
+
i0.ɵɵlistener("change", function ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Conditional_1_For_13_Template_input_change_6_listener() { const row_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.ToggleCanAccess(row_r7)); });
|
|
81
83
|
i0.ɵɵelementEnd()();
|
|
82
84
|
i0.ɵɵelementStart(7, "td", 36)(8, "input", 41);
|
|
83
|
-
i0.ɵɵlistener("change", function
|
|
85
|
+
i0.ɵɵlistener("change", function ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Conditional_1_For_13_Template_input_change_8_listener() { const row_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.ToggleCanAdmin(row_r7)); });
|
|
84
86
|
i0.ɵɵelementEnd()();
|
|
85
87
|
i0.ɵɵelementStart(9, "td", 37)(10, "button", 42);
|
|
86
|
-
i0.ɵɵlistener("click", function
|
|
88
|
+
i0.ɵɵlistener("click", function ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Conditional_1_For_13_Template_button_click_10_listener() { const row_r7 = i0.ɵɵrestoreView(_r6).$implicit; const group_r4 = i0.ɵɵnextContext(3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.RemoveRole(group_r4, row_r7)); });
|
|
87
89
|
i0.ɵɵelement(11, "i", 43);
|
|
88
90
|
i0.ɵɵelementEnd()()();
|
|
89
91
|
} if (rf & 2) {
|
|
@@ -98,8 +100,8 @@ function ApplicationRolesResourceComponent_Conditional_14_For_4_Conditional_8_Co
|
|
|
98
100
|
i0.ɵɵadvance(2);
|
|
99
101
|
i0.ɵɵproperty("checked", row_r7.CanAdmin);
|
|
100
102
|
} }
|
|
101
|
-
function
|
|
102
|
-
i0.ɵɵelementStart(0, "table",
|
|
103
|
+
function ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
104
|
+
i0.ɵɵelementStart(0, "table", 26)(1, "thead")(2, "tr")(3, "th", 34);
|
|
103
105
|
i0.ɵɵtext(4, "Role");
|
|
104
106
|
i0.ɵɵelementEnd();
|
|
105
107
|
i0.ɵɵelementStart(5, "th", 35);
|
|
@@ -112,21 +114,21 @@ function ApplicationRolesResourceComponent_Conditional_14_For_4_Conditional_8_Co
|
|
|
112
114
|
i0.ɵɵtext(10, "Actions");
|
|
113
115
|
i0.ɵɵelementEnd()()();
|
|
114
116
|
i0.ɵɵelementStart(11, "tbody");
|
|
115
|
-
i0.ɵɵrepeaterCreate(12,
|
|
117
|
+
i0.ɵɵrepeaterCreate(12, ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Conditional_1_For_13_Template, 12, 8, "tr", 38, i0.ɵɵcomponentInstance().TrackByRoleRow, true);
|
|
116
118
|
i0.ɵɵelementEnd()();
|
|
117
119
|
} if (rf & 2) {
|
|
118
120
|
const group_r4 = i0.ɵɵnextContext(2).$implicit;
|
|
119
121
|
i0.ɵɵadvance(12);
|
|
120
122
|
i0.ɵɵrepeater(group_r4.Roles);
|
|
121
123
|
} }
|
|
122
|
-
function
|
|
123
|
-
i0.ɵɵelementStart(0, "div",
|
|
124
|
+
function ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
125
|
+
i0.ɵɵelementStart(0, "div", 27);
|
|
124
126
|
i0.ɵɵelement(1, "i", 44);
|
|
125
127
|
i0.ɵɵtext(2, " No role restrictions \u2014 all authenticated users can access this application. ");
|
|
126
128
|
i0.ɵɵelementEnd();
|
|
127
129
|
} }
|
|
128
|
-
function
|
|
129
|
-
i0.ɵɵelementStart(0, "option",
|
|
130
|
+
function ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
131
|
+
i0.ɵɵelementStart(0, "option", 31);
|
|
130
132
|
i0.ɵɵtext(1);
|
|
131
133
|
i0.ɵɵelementEnd();
|
|
132
134
|
} if (rf & 2) {
|
|
@@ -135,19 +137,19 @@ function ApplicationRolesResourceComponent_Conditional_14_For_4_Conditional_8_Fo
|
|
|
135
137
|
i0.ɵɵadvance();
|
|
136
138
|
i0.ɵɵtextInterpolate(role_r8.Name);
|
|
137
139
|
} }
|
|
138
|
-
function
|
|
140
|
+
function ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
139
141
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
140
|
-
i0.ɵɵelementStart(0, "div",
|
|
141
|
-
i0.ɵɵconditionalCreate(1,
|
|
142
|
-
i0.ɵɵelementStart(3, "div",
|
|
143
|
-
i0.ɵɵlistener("change", function
|
|
144
|
-
i0.ɵɵelementStart(5, "option",
|
|
142
|
+
i0.ɵɵelementStart(0, "div", 25);
|
|
143
|
+
i0.ɵɵconditionalCreate(1, ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Conditional_1_Template, 14, 0, "table", 26)(2, ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Conditional_2_Template, 3, 0, "div", 27);
|
|
144
|
+
i0.ɵɵelementStart(3, "div", 28)(4, "select", 29);
|
|
145
|
+
i0.ɵɵlistener("change", function ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Template_select_change_4_listener($event) { i0.ɵɵrestoreView(_r5); const group_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnAddRoleSelect(group_r4, $event.target.value)); });
|
|
146
|
+
i0.ɵɵelementStart(5, "option", 30);
|
|
145
147
|
i0.ɵɵtext(6, "Select a role to add...");
|
|
146
148
|
i0.ɵɵelementEnd();
|
|
147
|
-
i0.ɵɵrepeaterCreate(7,
|
|
149
|
+
i0.ɵɵrepeaterCreate(7, ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_For_8_Template, 2, 2, "option", 31, _forTrack0);
|
|
148
150
|
i0.ɵɵelementEnd();
|
|
149
|
-
i0.ɵɵelementStart(9, "button",
|
|
150
|
-
i0.ɵɵlistener("click", function
|
|
151
|
+
i0.ɵɵelementStart(9, "button", 32);
|
|
152
|
+
i0.ɵɵlistener("click", function ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r5); const group_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.AddRole(group_r4)); });
|
|
151
153
|
i0.ɵɵelement(10, "i", 33);
|
|
152
154
|
i0.ɵɵtext(11, " Add Role ");
|
|
153
155
|
i0.ɵɵelementEnd()()();
|
|
@@ -163,19 +165,19 @@ function ApplicationRolesResourceComponent_Conditional_14_For_4_Conditional_8_Te
|
|
|
163
165
|
i0.ɵɵadvance(2);
|
|
164
166
|
i0.ɵɵproperty("disabled", !ctx_r1.SelectedRoleIdToAdd.get(group_r4.ApplicationID));
|
|
165
167
|
} }
|
|
166
|
-
function
|
|
168
|
+
function ApplicationRolesResourceComponent_Conditional_9_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
167
169
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
168
|
-
i0.ɵɵelementStart(0, "div",
|
|
169
|
-
i0.ɵɵlistener("click", function
|
|
170
|
-
i0.ɵɵelementStart(2, "div",
|
|
171
|
-
i0.ɵɵelement(3, "i",
|
|
172
|
-
i0.ɵɵelementStart(4, "span",
|
|
170
|
+
i0.ɵɵelementStart(0, "div", 19)(1, "div", 20);
|
|
171
|
+
i0.ɵɵlistener("click", function ApplicationRolesResourceComponent_Conditional_9_For_4_Template_div_click_1_listener() { const group_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ToggleGroup(group_r4)); });
|
|
172
|
+
i0.ɵɵelementStart(2, "div", 21);
|
|
173
|
+
i0.ɵɵelement(3, "i", 22);
|
|
174
|
+
i0.ɵɵelementStart(4, "span", 23);
|
|
173
175
|
i0.ɵɵtext(5);
|
|
174
176
|
i0.ɵɵelementEnd();
|
|
175
|
-
i0.ɵɵelementStart(6, "span",
|
|
177
|
+
i0.ɵɵelementStart(6, "span", 24);
|
|
176
178
|
i0.ɵɵtext(7);
|
|
177
179
|
i0.ɵɵelementEnd()()();
|
|
178
|
-
i0.ɵɵconditionalCreate(8,
|
|
180
|
+
i0.ɵɵconditionalCreate(8, ApplicationRolesResourceComponent_Conditional_9_For_4_Conditional_8_Template, 12, 3, "div", 25);
|
|
179
181
|
i0.ɵɵelementEnd();
|
|
180
182
|
} if (rf & 2) {
|
|
181
183
|
const group_r4 = ctx.$implicit;
|
|
@@ -192,12 +194,12 @@ function ApplicationRolesResourceComponent_Conditional_14_For_4_Template(rf, ctx
|
|
|
192
194
|
i0.ɵɵadvance();
|
|
193
195
|
i0.ɵɵconditional(group_r4.Expanded ? 8 : -1);
|
|
194
196
|
} }
|
|
195
|
-
function
|
|
196
|
-
i0.ɵɵelementStart(0, "p",
|
|
197
|
+
function ApplicationRolesResourceComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
198
|
+
i0.ɵɵelementStart(0, "p", 16);
|
|
197
199
|
i0.ɵɵtext(1, " Configure which roles can access each application. Applications with no role assignments are open to all users (backwards compatible). ");
|
|
198
200
|
i0.ɵɵelementEnd();
|
|
199
|
-
i0.ɵɵelementStart(2, "div",
|
|
200
|
-
i0.ɵɵrepeaterCreate(3,
|
|
201
|
+
i0.ɵɵelementStart(2, "div", 17);
|
|
202
|
+
i0.ɵɵrepeaterCreate(3, ApplicationRolesResourceComponent_Conditional_9_For_4_Template, 9, 10, "div", 18, i0.ɵɵcomponentInstance().TrackByAppId, true);
|
|
201
203
|
i0.ɵɵelementEnd();
|
|
202
204
|
} if (rf & 2) {
|
|
203
205
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
@@ -481,40 +483,32 @@ let ApplicationRolesResourceComponent = class ApplicationRolesResourceComponent
|
|
|
481
483
|
this.SelectedRoleIdToAdd.set(group.ApplicationID, roleId);
|
|
482
484
|
}
|
|
483
485
|
static ɵfac = function ApplicationRolesResourceComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ApplicationRolesResourceComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
484
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ApplicationRolesResourceComponent, selectors: [["mj-application-roles-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
486
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ApplicationRolesResourceComponent, selectors: [["mj-application-roles-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 10, vars: 7, consts: [[1, "app-roles-container"], [1, "sticky-header"], ["role", "toolbar", "aria-label", "Application roles actions", 1, "action-buttons"], [3, "Clicked", "Loading", "Disabled"], [1, "scrollable-content"], [1, "message", "error-message"], [1, "message", "success-message"], ["text", "Loading application roles..."], ["Icon", "fa-solid fa-circle-exclamation", "Label", "Unsaved changes", "Variant", "warning"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click", "disabled"], [1, "fa-solid", "fa-rotate-left"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click", "disabled"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-floppy-disk"], [1, "fa-solid", "fa-circle-exclamation"], [1, "fa-solid", "fa-circle-check"], [1, "description"], [1, "app-groups"], [1, "app-group", 3, "expanded", "has-roles"], [1, "app-group"], [1, "app-group-header", 3, "click"], [1, "app-header-left"], [1, "fa-solid", 3, "ngClass"], [1, "app-name"], [1, "role-count-badge"], [1, "app-group-content"], [1, "roles-table"], [1, "no-roles-message"], [1, "add-role-row"], [1, "mj-input", "add-role-select", 3, "change", "value"], ["value", "", "disabled", ""], [3, "value"], ["mjButton", "", "variant", "secondary", 3, "click", "disabled"], [1, "fa-solid", "fa-plus"], [1, "col-role"], [1, "col-access"], [1, "col-admin"], [1, "col-actions"], [3, "dirty", "new-row"], [1, "fa-solid", "fa-shield-halved", "role-icon"], [1, "new-badge"], ["type", "checkbox", 1, "mj-checkbox", 3, "change", "checked"], ["title", "Remove role assignment", 1, "remove-btn", 3, "click"], [1, "fa-solid", "fa-trash-can"], [1, "fa-solid", "fa-unlock"]], template: function ApplicationRolesResourceComponent_Template(rf, ctx) { if (rf & 1) {
|
|
485
487
|
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2);
|
|
486
|
-
i0.ɵɵ
|
|
487
|
-
i0.ɵɵelementStart(4, "
|
|
488
|
-
i0.ɵɵ
|
|
489
|
-
i0.ɵɵelementEnd()();
|
|
490
|
-
i0.ɵɵelementStart(6, "div", 5);
|
|
491
|
-
i0.ɵɵconditionalCreate(7, ApplicationRolesResourceComponent_Conditional_7_Template, 6, 3);
|
|
492
|
-
i0.ɵɵelementStart(8, "button", 6);
|
|
493
|
-
i0.ɵɵlistener("click", function ApplicationRolesResourceComponent_Template_button_click_8_listener() { return ctx.loadData(); });
|
|
494
|
-
i0.ɵɵelement(9, "i", 7);
|
|
495
|
-
i0.ɵɵtext(10, " Refresh ");
|
|
488
|
+
i0.ɵɵconditionalCreate(3, ApplicationRolesResourceComponent_Conditional_3_Template, 7, 3);
|
|
489
|
+
i0.ɵɵelementStart(4, "mj-refresh-button", 3);
|
|
490
|
+
i0.ɵɵlistener("Clicked", function ApplicationRolesResourceComponent_Template_mj_refresh_button_Clicked_4_listener() { return ctx.loadData(); });
|
|
496
491
|
i0.ɵɵelementEnd()()();
|
|
497
|
-
i0.ɵɵ
|
|
498
|
-
i0.ɵɵconditionalCreate(
|
|
499
|
-
i0.ɵɵconditionalCreate(
|
|
500
|
-
i0.ɵɵconditionalCreate(
|
|
501
|
-
i0.ɵɵ
|
|
492
|
+
i0.ɵɵelementStart(5, "div", 4);
|
|
493
|
+
i0.ɵɵconditionalCreate(6, ApplicationRolesResourceComponent_Conditional_6_Template, 3, 1, "div", 5);
|
|
494
|
+
i0.ɵɵconditionalCreate(7, ApplicationRolesResourceComponent_Conditional_7_Template, 3, 1, "div", 6);
|
|
495
|
+
i0.ɵɵconditionalCreate(8, ApplicationRolesResourceComponent_Conditional_8_Template, 1, 0, "mj-loading", 7);
|
|
496
|
+
i0.ɵɵconditionalCreate(9, ApplicationRolesResourceComponent_Conditional_9_Template, 5, 0);
|
|
497
|
+
i0.ɵɵelementEnd()();
|
|
502
498
|
} if (rf & 2) {
|
|
503
|
-
i0.ɵɵadvance(
|
|
504
|
-
i0.ɵɵconditional(ctx.HasUnsavedChanges ?
|
|
505
|
-
i0.ɵɵadvance();
|
|
506
|
-
i0.ɵɵproperty("disabled", ctx.IsLoading || ctx.IsSaving);
|
|
499
|
+
i0.ɵɵadvance(3);
|
|
500
|
+
i0.ɵɵconditional(ctx.HasUnsavedChanges ? 3 : -1);
|
|
507
501
|
i0.ɵɵadvance();
|
|
508
|
-
i0.ɵɵ
|
|
502
|
+
i0.ɵɵproperty("Loading", ctx.IsLoading)("Disabled", ctx.IsSaving);
|
|
509
503
|
i0.ɵɵadvance(2);
|
|
510
|
-
i0.ɵɵconditional(ctx.ErrorMessage ?
|
|
504
|
+
i0.ɵɵconditional(ctx.ErrorMessage ? 6 : -1);
|
|
511
505
|
i0.ɵɵadvance();
|
|
512
|
-
i0.ɵɵconditional(ctx.SuccessMessage ?
|
|
506
|
+
i0.ɵɵconditional(ctx.SuccessMessage ? 7 : -1);
|
|
513
507
|
i0.ɵɵadvance();
|
|
514
|
-
i0.ɵɵconditional(ctx.IsLoading ?
|
|
508
|
+
i0.ɵɵconditional(ctx.IsLoading ? 8 : -1);
|
|
515
509
|
i0.ɵɵadvance();
|
|
516
|
-
i0.ɵɵconditional(!ctx.IsLoading ?
|
|
517
|
-
} }, dependencies: [i1.NgClass, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i3.MJButtonDirective, i4.LoadingComponent], styles: [".app-roles-container[_ngcontent-%COMP%] {\n
|
|
510
|
+
i0.ɵɵconditional(!ctx.IsLoading ? 9 : -1);
|
|
511
|
+
} }, dependencies: [i1.NgClass, i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i3.MJButtonDirective, i3.MJStatBadgeComponent, i3.MJRefreshButtonComponent, i4.LoadingComponent], styles: ["\n\n.app-roles-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n background: var(--mj-bg-page);\n}\n\n\n\n.sticky-header[_ngcontent-%COMP%] {\n flex-shrink: 0;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n z-index: 10;\n}\n\n.action-buttons[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n justify-content: flex-end;\n padding: var(--mj-space-3) var(--mj-space-6);\n}\n\n@media (max-width: 639px) {\n .action-buttons[_ngcontent-%COMP%] {\n justify-content: center;\n flex-wrap: wrap;\n }\n}\n\n\n\n.scrollable-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: var(--mj-space-6);\n}\n\n\n\n.message[_ngcontent-%COMP%] {\n padding: 10px 14px;\n border-radius: 6px;\n margin-bottom: 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n}\n\n.error-message[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.success-message[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n\n\n.description[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: 14px;\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n\n\n.app-groups[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.app-group[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.app-group.expanded[_ngcontent-%COMP%] {\n border-color: var(--mj-border-strong);\n}\n\n.app-group-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n cursor: pointer;\n user-select: none;\n background: var(--mj-bg-surface-card);\n transition: background 0.15s;\n}\n\n.app-group-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.app-header-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.app-header-left[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n width: 14px;\n text-align: center;\n}\n\n.app-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 15px;\n color: var(--mj-text-primary);\n}\n\n.role-count-badge[_ngcontent-%COMP%] {\n font-size: 12px;\n padding: 2px 8px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.role-count-badge.open-access[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success-text);\n}\n\n\n\n.app-group-content[_ngcontent-%COMP%] {\n padding: 16px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n\n\n.roles-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n margin-bottom: 12px;\n}\n\n.roles-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n padding: 8px 12px;\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.roles-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-size: 14px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.roles-table[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:last-child td[_ngcontent-%COMP%] {\n border-bottom: none;\n}\n\n.roles-table[_ngcontent-%COMP%] tr.dirty[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 6%, var(--mj-bg-surface));\n}\n\n.roles-table[_ngcontent-%COMP%] tr.new-row[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 6%, var(--mj-bg-surface));\n}\n\n.col-role[_ngcontent-%COMP%] {\n width: 40%;\n}\n\n.col-access[_ngcontent-%COMP%], \n.col-admin[_ngcontent-%COMP%] {\n width: 20%;\n text-align: center;\n}\n\n.col-actions[_ngcontent-%COMP%] {\n width: 20%;\n text-align: center;\n}\n\n.roles-table[_ngcontent-%COMP%] th.col-access[_ngcontent-%COMP%], \n.roles-table[_ngcontent-%COMP%] th.col-admin[_ngcontent-%COMP%], \n.roles-table[_ngcontent-%COMP%] th.col-actions[_ngcontent-%COMP%] {\n text-align: center;\n}\n\n.role-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n margin-right: 6px;\n}\n\n.new-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n padding: 1px 6px;\n border-radius: 8px;\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n margin-left: 6px;\n text-transform: uppercase;\n font-weight: 600;\n}\n\n.remove-btn[_ngcontent-%COMP%] {\n border: none;\n background: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.15s;\n}\n\n.remove-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-status-error);\n background: var(--mj-status-error-bg);\n}\n\n\n\n.no-roles-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n font-size: 14px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n margin-bottom: 12px;\n}\n\n.no-roles-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n\n\n.add-role-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.add-role-select[_ngcontent-%COMP%] {\n flex: 1;\n max-width: 300px;\n padding: 6px 10px;\n font-size: 14px;\n}"] });
|
|
518
512
|
};
|
|
519
513
|
ApplicationRolesResourceComponent = __decorate([
|
|
520
514
|
RegisterClass(BaseResourceComponent, 'ApplicationRolesResource')
|
|
@@ -522,7 +516,7 @@ ApplicationRolesResourceComponent = __decorate([
|
|
|
522
516
|
export { ApplicationRolesResourceComponent };
|
|
523
517
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ApplicationRolesResourceComponent, [{
|
|
524
518
|
type: Component,
|
|
525
|
-
args: [{ standalone: false, selector: 'mj-application-roles-resource', template: "<div class=\"app-roles-container\">\n <!-- Header -->\n <div class=\"header\">\n <div class=\"header-left\">\n <i class=\"fa-solid fa-user-shield header-icon\"></i>\n <h2 class=\"header-title\">Application Roles</h2>\n </div>\n <div class=\"header-actions\">\n @if (HasUnsavedChanges) {\n <button mjButton variant=\"secondary\" (click)=\"DiscardChanges()\" [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-rotate-left\"></i> Discard\n </button>\n <button mjButton variant=\"primary\" (click)=\"SaveChanges()\" [disabled]=\"IsSaving\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-floppy-disk\"></i> Save Changes\n }\n </button>\n }\n <button mjButton variant=\"secondary\" (click)=\"loadData()\" [disabled]=\"IsLoading || IsSaving\">\n <i class=\"fa-solid fa-arrows-rotate\" [class.fa-spin]=\"IsLoading\"></i> Refresh\n </button>\n </div>\n </div>\n\n <!-- Status Messages -->\n @if (ErrorMessage) {\n <div class=\"message error-message\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ ErrorMessage }}\n </div>\n }\n @if (SuccessMessage) {\n <div class=\"message success-message\">\n <i class=\"fa-solid fa-circle-check\"></i>\n {{ SuccessMessage }}\n </div>\n }\n\n <!-- Loading State -->\n @if (IsLoading) {\n <mj-loading text=\"Loading application roles...\"></mj-loading>\n }\n\n <!-- Main Content -->\n @if (!IsLoading) {\n <p class=\"description\">\n Configure which roles can access each application. Applications with no role assignments are open to all users (backwards compatible).\n </p>\n\n <div class=\"app-groups\">\n @for (group of ApplicationGroups; track TrackByAppId($index, group)) {\n <div class=\"app-group\" [class.expanded]=\"group.Expanded\" [class.has-roles]=\"group.Roles.length > 0\">\n <!-- Application Header Row -->\n <div class=\"app-group-header\" (click)=\"ToggleGroup(group)\">\n <div class=\"app-header-left\">\n <i class=\"fa-solid\" [ngClass]=\"group.Expanded ? 'fa-chevron-down' : 'fa-chevron-right'\"></i>\n <span class=\"app-name\">{{ group.ApplicationName }}</span>\n <span class=\"role-count-badge\" [class.open-access]=\"group.Roles.length === 0\">\n {{ GetRoleCountLabel(group) }}\n </span>\n </div>\n </div>\n\n <!-- Expanded Content -->\n @if (group.Expanded) {\n <div class=\"app-group-content\">\n <!-- Existing Role Assignments -->\n @if (group.Roles.length > 0) {\n <table class=\"roles-table\">\n <thead>\n <tr>\n <th class=\"col-role\">Role</th>\n <th class=\"col-access\">Can Access</th>\n <th class=\"col-admin\">Can Admin</th>\n <th class=\"col-actions\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (row of group.Roles; track TrackByRoleRow($index, row)) {\n <tr [class.dirty]=\"row.IsDirty\" [class.new-row]=\"row.IsNew\">\n <td class=\"col-role\">\n <i class=\"fa-solid fa-shield-halved role-icon\"></i>\n {{ row.RoleName }}\n @if (row.IsNew) {\n <span class=\"new-badge\">new</span>\n }\n </td>\n <td class=\"col-access\">\n <input type=\"checkbox\"\n class=\"mj-checkbox\"\n [checked]=\"row.CanAccess\"\n (change)=\"ToggleCanAccess(row)\">\n </td>\n <td class=\"col-admin\">\n <input type=\"checkbox\"\n class=\"mj-checkbox\"\n [checked]=\"row.CanAdmin\"\n (change)=\"ToggleCanAdmin(row)\">\n </td>\n <td class=\"col-actions\">\n <button class=\"remove-btn\" (click)=\"RemoveRole(group, row)\" title=\"Remove role assignment\">\n <i class=\"fa-solid fa-trash-can\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"no-roles-message\">\n <i class=\"fa-solid fa-unlock\"></i>\n No role restrictions \u2014 all authenticated users can access this application.\n </div>\n }\n\n <!-- Add Role -->\n <div class=\"add-role-row\">\n <select class=\"mj-input add-role-select\"\n [value]=\"SelectedRoleIdToAdd.get(group.ApplicationID) || ''\"\n (change)=\"OnAddRoleSelect(group, $any($event.target).value)\">\n <option value=\"\" disabled>Select a role to add...</option>\n @for (role of GetUnassignedRoles(group); track role.ID) {\n <option [value]=\"role.ID\">{{ role.Name }}</option>\n }\n </select>\n <button mjButton\n variant=\"secondary\"\n (click)=\"AddRole(group)\"\n [disabled]=\"!SelectedRoleIdToAdd.get(group.ApplicationID)\">\n <i class=\"fa-solid fa-plus\"></i> Add Role\n </button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".app-roles-container {\n padding: 24px;\n max-width: 960px;\n margin: 0 auto;\n}\n\n/* Header */\n.header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n}\n\n.header-left {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.header-icon {\n font-size: 24px;\n color: var(--mj-brand-primary);\n}\n\n.header-title {\n margin: 0;\n font-size: 22px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n/* Messages */\n.message {\n padding: 10px 14px;\n border-radius: 6px;\n margin-bottom: 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n}\n\n.error-message {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.success-message {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n/* Description */\n.description {\n color: var(--mj-text-secondary);\n font-size: 14px;\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n/* Application Groups */\n.app-groups {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.app-group {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.app-group.expanded {\n border-color: var(--mj-border-strong);\n}\n\n.app-group-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n cursor: pointer;\n user-select: none;\n background: var(--mj-bg-surface-card);\n transition: background 0.15s;\n}\n\n.app-group-header:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.app-header-left {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.app-header-left > i {\n font-size: 12px;\n color: var(--mj-text-muted);\n width: 14px;\n text-align: center;\n}\n\n.app-name {\n font-weight: 600;\n font-size: 15px;\n color: var(--mj-text-primary);\n}\n\n.role-count-badge {\n font-size: 12px;\n padding: 2px 8px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.role-count-badge.open-access {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success-text);\n}\n\n/* Expanded Content */\n.app-group-content {\n padding: 16px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n/* Table */\n.roles-table {\n width: 100%;\n border-collapse: collapse;\n margin-bottom: 12px;\n}\n\n.roles-table th {\n text-align: left;\n padding: 8px 12px;\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.roles-table td {\n padding: 10px 12px;\n font-size: 14px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.roles-table tr:last-child td {\n border-bottom: none;\n}\n\n.roles-table tr.dirty td {\n background: color-mix(in srgb, var(--mj-status-warning) 6%, var(--mj-bg-surface));\n}\n\n.roles-table tr.new-row td {\n background: color-mix(in srgb, var(--mj-status-success) 6%, var(--mj-bg-surface));\n}\n\n.col-role {\n width: 40%;\n}\n\n.col-access,\n.col-admin {\n width: 20%;\n text-align: center;\n}\n\n.col-actions {\n width: 20%;\n text-align: center;\n}\n\n.roles-table th.col-access,\n.roles-table th.col-admin,\n.roles-table th.col-actions {\n text-align: center;\n}\n\n.role-icon {\n color: var(--mj-text-muted);\n margin-right: 6px;\n}\n\n.new-badge {\n font-size: 10px;\n padding: 1px 6px;\n border-radius: 8px;\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n margin-left: 6px;\n text-transform: uppercase;\n font-weight: 600;\n}\n\n.remove-btn {\n border: none;\n background: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.15s;\n}\n\n.remove-btn:hover {\n color: var(--mj-status-error);\n background: var(--mj-status-error-bg);\n}\n\n/* No Roles Message */\n.no-roles-message {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n font-size: 14px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n margin-bottom: 12px;\n}\n\n.no-roles-message i {\n color: var(--mj-status-success);\n}\n\n/* Add Role Row */\n.add-role-row {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.add-role-select {\n flex: 1;\n max-width: 300px;\n padding: 6px 10px;\n font-size: 14px;\n}\n"] }]
|
|
519
|
+
args: [{ standalone: false, selector: 'mj-application-roles-resource', template: "<div class=\"app-roles-container\">\n <!--\n Sticky Header \u2014 action row only, matching the UserManagement / RoleManagement\n pattern. No <mj-page-header> here: ApplicationRoles renders inside Admin's\n \"Identity & Access\" left-nav shell, which owns its own <mj-page-header>.\n Adding one here would produce the doubled-header pattern Section 9b defers.\n See plans/explorer-chrome-conventions.md Section 10.\n -->\n <div class=\"sticky-header\">\n <div class=\"action-buttons\" role=\"toolbar\" aria-label=\"Application roles actions\">\n @if (HasUnsavedChanges) {\n <mj-stat-badge\n Icon=\"fa-solid fa-circle-exclamation\"\n Label=\"Unsaved changes\"\n Variant=\"warning\">\n </mj-stat-badge>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"DiscardChanges()\" [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-rotate-left\"></i> Discard\n </button>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"SaveChanges()\" [disabled]=\"IsSaving\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-floppy-disk\"></i> Save Changes\n }\n </button>\n }\n <mj-refresh-button [Loading]=\"IsLoading\" [Disabled]=\"IsSaving\" (Clicked)=\"loadData()\"></mj-refresh-button>\n </div>\n </div>\n\n <!-- Scrollable Content -->\n <div class=\"scrollable-content\">\n <!-- Status Messages -->\n @if (ErrorMessage) {\n <div class=\"message error-message\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ ErrorMessage }}\n </div>\n }\n @if (SuccessMessage) {\n <div class=\"message success-message\">\n <i class=\"fa-solid fa-circle-check\"></i>\n {{ SuccessMessage }}\n </div>\n }\n\n <!-- Loading State -->\n @if (IsLoading) {\n <mj-loading text=\"Loading application roles...\"></mj-loading>\n }\n\n <!-- Main Content -->\n @if (!IsLoading) {\n <p class=\"description\">\n Configure which roles can access each application. Applications with no role assignments are open to all users (backwards compatible).\n </p>\n\n <div class=\"app-groups\">\n @for (group of ApplicationGroups; track TrackByAppId($index, group)) {\n <div class=\"app-group\" [class.expanded]=\"group.Expanded\" [class.has-roles]=\"group.Roles.length > 0\">\n <!-- Application Header Row -->\n <div class=\"app-group-header\" (click)=\"ToggleGroup(group)\">\n <div class=\"app-header-left\">\n <i class=\"fa-solid\" [ngClass]=\"group.Expanded ? 'fa-chevron-down' : 'fa-chevron-right'\"></i>\n <span class=\"app-name\">{{ group.ApplicationName }}</span>\n <span class=\"role-count-badge\" [class.open-access]=\"group.Roles.length === 0\">\n {{ GetRoleCountLabel(group) }}\n </span>\n </div>\n </div>\n\n <!-- Expanded Content -->\n @if (group.Expanded) {\n <div class=\"app-group-content\">\n <!-- Existing Role Assignments -->\n @if (group.Roles.length > 0) {\n <table class=\"roles-table\">\n <thead>\n <tr>\n <th class=\"col-role\">Role</th>\n <th class=\"col-access\">Can Access</th>\n <th class=\"col-admin\">Can Admin</th>\n <th class=\"col-actions\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (row of group.Roles; track TrackByRoleRow($index, row)) {\n <tr [class.dirty]=\"row.IsDirty\" [class.new-row]=\"row.IsNew\">\n <td class=\"col-role\">\n <i class=\"fa-solid fa-shield-halved role-icon\"></i>\n {{ row.RoleName }}\n @if (row.IsNew) {\n <span class=\"new-badge\">new</span>\n }\n </td>\n <td class=\"col-access\">\n <input type=\"checkbox\"\n class=\"mj-checkbox\"\n [checked]=\"row.CanAccess\"\n (change)=\"ToggleCanAccess(row)\">\n </td>\n <td class=\"col-admin\">\n <input type=\"checkbox\"\n class=\"mj-checkbox\"\n [checked]=\"row.CanAdmin\"\n (change)=\"ToggleCanAdmin(row)\">\n </td>\n <td class=\"col-actions\">\n <button class=\"remove-btn\" (click)=\"RemoveRole(group, row)\" title=\"Remove role assignment\">\n <i class=\"fa-solid fa-trash-can\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"no-roles-message\">\n <i class=\"fa-solid fa-unlock\"></i>\n No role restrictions \u2014 all authenticated users can access this application.\n </div>\n }\n\n <!-- Add Role -->\n <div class=\"add-role-row\">\n <select class=\"mj-input add-role-select\"\n [value]=\"SelectedRoleIdToAdd.get(group.ApplicationID) || ''\"\n (change)=\"OnAddRoleSelect(group, $any($event.target).value)\">\n <option value=\"\" disabled>Select a role to add...</option>\n @for (role of GetUnassignedRoles(group); track role.ID) {\n <option [value]=\"role.ID\">{{ role.Name }}</option>\n }\n </select>\n <button mjButton\n variant=\"secondary\"\n (click)=\"AddRole(group)\"\n [disabled]=\"!SelectedRoleIdToAdd.get(group.ApplicationID)\">\n <i class=\"fa-solid fa-plus\"></i> Add Role\n </button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n</div>\n", styles: ["/* Container \u2014 flex-column workspace inside Admin's left-nav shell. */\n.app-roles-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n background: var(--mj-bg-page);\n}\n\n/* Sticky Header \u2014 action row only (no title; Admin shell provides it). */\n.sticky-header {\n flex-shrink: 0;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n z-index: 10;\n}\n\n.action-buttons {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n justify-content: flex-end;\n padding: var(--mj-space-3) var(--mj-space-6);\n}\n\n@media (max-width: 639px) {\n .action-buttons {\n justify-content: center;\n flex-wrap: wrap;\n }\n}\n\n/* Scrollable Content */\n.scrollable-content {\n flex: 1;\n overflow-y: auto;\n padding: var(--mj-space-6);\n}\n\n/* Messages */\n.message {\n padding: 10px 14px;\n border-radius: 6px;\n margin-bottom: 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n}\n\n.error-message {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n border: 1px solid var(--mj-status-error-border);\n}\n\n.success-message {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success-border);\n}\n\n/* Description */\n.description {\n color: var(--mj-text-secondary);\n font-size: 14px;\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n/* Application Groups */\n.app-groups {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.app-group {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.app-group.expanded {\n border-color: var(--mj-border-strong);\n}\n\n.app-group-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n cursor: pointer;\n user-select: none;\n background: var(--mj-bg-surface-card);\n transition: background 0.15s;\n}\n\n.app-group-header:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.app-header-left {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.app-header-left > i {\n font-size: 12px;\n color: var(--mj-text-muted);\n width: 14px;\n text-align: center;\n}\n\n.app-name {\n font-weight: 600;\n font-size: 15px;\n color: var(--mj-text-primary);\n}\n\n.role-count-badge {\n font-size: 12px;\n padding: 2px 8px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.role-count-badge.open-access {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success-text);\n}\n\n/* Expanded Content */\n.app-group-content {\n padding: 16px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n/* Table */\n.roles-table {\n width: 100%;\n border-collapse: collapse;\n margin-bottom: 12px;\n}\n\n.roles-table th {\n text-align: left;\n padding: 8px 12px;\n font-size: 12px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.roles-table td {\n padding: 10px 12px;\n font-size: 14px;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.roles-table tr:last-child td {\n border-bottom: none;\n}\n\n.roles-table tr.dirty td {\n background: color-mix(in srgb, var(--mj-status-warning) 6%, var(--mj-bg-surface));\n}\n\n.roles-table tr.new-row td {\n background: color-mix(in srgb, var(--mj-status-success) 6%, var(--mj-bg-surface));\n}\n\n.col-role {\n width: 40%;\n}\n\n.col-access,\n.col-admin {\n width: 20%;\n text-align: center;\n}\n\n.col-actions {\n width: 20%;\n text-align: center;\n}\n\n.roles-table th.col-access,\n.roles-table th.col-admin,\n.roles-table th.col-actions {\n text-align: center;\n}\n\n.role-icon {\n color: var(--mj-text-muted);\n margin-right: 6px;\n}\n\n.new-badge {\n font-size: 10px;\n padding: 1px 6px;\n border-radius: 8px;\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n margin-left: 6px;\n text-transform: uppercase;\n font-weight: 600;\n}\n\n.remove-btn {\n border: none;\n background: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.15s;\n}\n\n.remove-btn:hover {\n color: var(--mj-status-error);\n background: var(--mj-status-error-bg);\n}\n\n/* No Roles Message */\n.no-roles-message {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n font-size: 14px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n margin-bottom: 12px;\n}\n\n.no-roles-message i {\n color: var(--mj-status-success);\n}\n\n/* Add Role Row */\n.add-role-row {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.add-role-select {\n flex: 1;\n max-width: 300px;\n padding: 6px 10px;\n font-size: 14px;\n}\n"] }]
|
|
526
520
|
}], () => [{ type: i0.ChangeDetectorRef }], null); })();
|
|
527
521
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ApplicationRolesResourceComponent, { className: "ApplicationRolesResourceComponent", filePath: "src/ApplicationRoles/application-roles-resource.component.ts", lineNumber: 43 }); })();
|
|
528
522
|
/** Tree-shaking prevention */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application-roles-resource.component.js","sourceRoot":"","sources":["../../src/ApplicationRoles/application-roles-resource.component.ts","../../src/ApplicationRoles/application-roles-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { RegisterClass, UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { CompositeKey, Metadata, RunView } from '@memberjunction/core';\nimport { ResourceData } from '@memberjunction/core-entities';\n\n/**\n * Represents an application's role assignment for display in the grid.\n */\ninterface ApplicationRoleRow {\n ID: string;\n ApplicationID: string;\n ApplicationName: string;\n RoleID: string;\n RoleName: string;\n CanAccess: boolean;\n CanAdmin: boolean;\n IsDirty: boolean;\n IsNew: boolean;\n}\n\n/**\n * Represents an application with its role assignments grouped.\n */\ninterface ApplicationGroup {\n ApplicationID: string;\n ApplicationName: string;\n Roles: ApplicationRoleRow[];\n Expanded: boolean;\n}\n\n/**\n * Admin dashboard for managing Application Role assignments.\n * Shows which roles can access and administer each application.\n */\n@RegisterClass(BaseResourceComponent, 'ApplicationRolesResource')\n@Component({\n standalone: false,\n selector: 'mj-application-roles-resource',\n templateUrl: './application-roles-resource.component.html',\n styleUrls: ['./application-roles-resource.component.css']\n})\nexport class ApplicationRolesResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n ApplicationGroups: ApplicationGroup[] = [];\n AvailableRoles: { ID: string; Name: string }[] = [];\n IsLoading = true;\n IsSaving = false;\n HasUnsavedChanges = false;\n ErrorMessage: string | null = null;\n SuccessMessage: string | null = null;\n\n // For the \"Add Role\" dropdown per application\n SelectedRoleIdToAdd: Map<string, string> = new Map();\n\n constructor(private cdr: ChangeDetectorRef) {\n super();\n }\n\n override async GetResourceDisplayName(_data: ResourceData): Promise<string> {\n return 'App Roles';\n }\n\n override async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-user-shield';\n }\n\n override async ngOnInit(): Promise<void> {\n super.ngOnInit();\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n override ngOnDestroy(): void {\n super.ngOnDestroy();\n }\n\n /**\n * Load all application role data and available roles.\n */\n async loadData(): Promise<void> {\n this.IsLoading = true;\n this.ErrorMessage = null;\n this.cdr.detectChanges();\n\n try {\n const md = this.ProviderToUse;\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n\n // Load available roles from metadata\n this.AvailableRoles = md.Roles.map(r => ({ ID: r.ID, Name: r.Name }))\n .sort((a, b) => a.Name.localeCompare(b.Name));\n\n // Load existing ApplicationRole records\n const result = await rv.RunView<{ ID: string; ApplicationID: string; Application: string; RoleID: string; Role: string; CanAccess: boolean; CanAdmin: boolean }>({\n EntityName: 'MJ: Application Roles',\n ResultType: 'simple',\n });\n\n if (!result.Success) {\n this.ErrorMessage = result.ErrorMessage || 'Failed to load application roles.';\n this.IsLoading = false;\n this.cdr.detectChanges();\n return;\n }\n\n // Build grouped structure\n const appMap = new Map<string, ApplicationGroup>();\n\n // Seed all applications so we can show apps without any role records\n for (const app of md.Applications) {\n appMap.set(app.ID, {\n ApplicationID: app.ID,\n ApplicationName: app.Name,\n Roles: [],\n Expanded: false,\n });\n }\n\n // Populate role assignments\n for (const record of result.Results) {\n const group = appMap.get(record.ApplicationID);\n if (group) {\n group.Roles.push({\n ID: record.ID,\n ApplicationID: record.ApplicationID,\n ApplicationName: group.ApplicationName,\n RoleID: record.RoleID,\n RoleName: record.Role || '',\n CanAccess: record.CanAccess,\n CanAdmin: record.CanAdmin,\n IsDirty: false,\n IsNew: false,\n });\n }\n }\n\n // Sort roles within each group\n for (const group of appMap.values()) {\n group.Roles.sort((a, b) => a.RoleName.localeCompare(b.RoleName));\n }\n\n this.ApplicationGroups = Array.from(appMap.values())\n .sort((a, b) => a.ApplicationName.localeCompare(b.ApplicationName));\n } catch (e) {\n this.ErrorMessage = `Error loading data: ${e instanceof Error ? e.message : String(e)}`;\n }\n\n this.IsLoading = false;\n this.HasUnsavedChanges = false;\n this.cdr.detectChanges();\n }\n\n /**\n * Toggle the expanded/collapsed state of an application group.\n */\n ToggleGroup(group: ApplicationGroup): void {\n group.Expanded = !group.Expanded;\n this.cdr.detectChanges();\n }\n\n /**\n * Toggle CanAccess for a specific role assignment.\n */\n ToggleCanAccess(row: ApplicationRoleRow): void {\n row.CanAccess = !row.CanAccess;\n row.IsDirty = true;\n this.HasUnsavedChanges = true;\n this.cdr.detectChanges();\n }\n\n /**\n * Toggle CanAdmin for a specific role assignment.\n */\n ToggleCanAdmin(row: ApplicationRoleRow): void {\n row.CanAdmin = !row.CanAdmin;\n row.IsDirty = true;\n this.HasUnsavedChanges = true;\n this.cdr.detectChanges();\n }\n\n /**\n * Get roles not yet assigned to a specific application (for the \"Add Role\" dropdown).\n */\n GetUnassignedRoles(group: ApplicationGroup): { ID: string; Name: string }[] {\n const assignedRoleIds = new Set(group.Roles.map(r => r.RoleID.toLowerCase()));\n return this.AvailableRoles.filter(r => !assignedRoleIds.has(r.ID.toLowerCase()));\n }\n\n /**\n * Add a new role assignment to an application group.\n */\n AddRole(group: ApplicationGroup): void {\n const roleId = this.SelectedRoleIdToAdd.get(group.ApplicationID);\n if (!roleId) return;\n\n const role = this.AvailableRoles.find(r => UUIDsEqual(r.ID, roleId));\n if (!role) return;\n\n group.Roles.push({\n ID: '',\n ApplicationID: group.ApplicationID,\n ApplicationName: group.ApplicationName,\n RoleID: role.ID,\n RoleName: role.Name,\n CanAccess: true,\n CanAdmin: false,\n IsDirty: true,\n IsNew: true,\n });\n\n group.Roles.sort((a, b) => a.RoleName.localeCompare(b.RoleName));\n this.SelectedRoleIdToAdd.delete(group.ApplicationID);\n this.HasUnsavedChanges = true;\n this.cdr.detectChanges();\n }\n\n /**\n * Remove a role assignment (marks for deletion on save; removes immediately if new).\n */\n RemoveRole(group: ApplicationGroup, row: ApplicationRoleRow): void {\n const idx = group.Roles.indexOf(row);\n if (idx >= 0) {\n group.Roles.splice(idx, 1);\n }\n // If not new, we need to delete it on save — track via dirty state\n if (!row.IsNew) {\n this._pendingDeletes.push(row.ID);\n }\n this.HasUnsavedChanges = true;\n this.cdr.detectChanges();\n }\n\n private _pendingDeletes: string[] = [];\n\n /**\n * Save all unsaved changes (new records, modified records, deleted records).\n */\n async SaveChanges(): Promise<void> {\n this.IsSaving = true;\n this.ErrorMessage = null;\n this.SuccessMessage = null;\n this.cdr.detectChanges();\n\n try {\n const md = this.ProviderToUse;\n\n // Process deletes\n for (const deleteId of this._pendingDeletes) {\n const entity = await md.GetEntityObject('MJ: Application Roles');\n await entity.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: deleteId }]));\n const deleteResult = await entity.Delete();\n if (!deleteResult) {\n this.ErrorMessage = `Failed to delete role assignment: ${entity.LatestResult?.Message || 'Unknown error'}`;\n this.IsSaving = false;\n this.cdr.detectChanges();\n return;\n }\n }\n\n // Process new and modified records\n for (const group of this.ApplicationGroups) {\n for (const row of group.Roles) {\n if (!row.IsDirty) continue;\n\n if (row.IsNew) {\n const entity = await md.GetEntityObject('MJ: Application Roles');\n entity.NewRecord();\n entity.Set('ApplicationID', row.ApplicationID);\n entity.Set('RoleID', row.RoleID);\n entity.Set('CanAccess', row.CanAccess);\n entity.Set('CanAdmin', row.CanAdmin);\n const saveResult = await entity.Save();\n if (!saveResult) {\n this.ErrorMessage = `Failed to save new role assignment for ${row.RoleName}: ${entity.LatestResult?.Message || 'Unknown error'}`;\n this.IsSaving = false;\n this.cdr.detectChanges();\n return;\n }\n row.ID = entity.Get('ID');\n } else {\n const entity = await md.GetEntityObject('MJ: Application Roles');\n await entity.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: row.ID }]));\n entity.Set('CanAccess', row.CanAccess);\n entity.Set('CanAdmin', row.CanAdmin);\n const saveResult = await entity.Save();\n if (!saveResult) {\n this.ErrorMessage = `Failed to update role assignment for ${row.RoleName}: ${entity.LatestResult?.Message || 'Unknown error'}`;\n this.IsSaving = false;\n this.cdr.detectChanges();\n return;\n }\n }\n\n row.IsDirty = false;\n row.IsNew = false;\n }\n }\n\n this._pendingDeletes = [];\n this.HasUnsavedChanges = false;\n this.SuccessMessage = 'All changes saved successfully.';\n } catch (e) {\n this.ErrorMessage = `Error saving: ${e instanceof Error ? e.message : String(e)}`;\n }\n\n this.IsSaving = false;\n this.cdr.detectChanges();\n }\n\n /**\n * Discard all unsaved changes and reload data.\n */\n async DiscardChanges(): Promise<void> {\n this._pendingDeletes = [];\n await this.loadData();\n }\n\n /**\n * Track by function for application groups.\n */\n TrackByAppId(_index: number, group: ApplicationGroup): string {\n return group.ApplicationID;\n }\n\n /**\n * Track by function for role rows.\n */\n TrackByRoleRow(_index: number, row: ApplicationRoleRow): string {\n return row.IsNew ? `new-${row.RoleID}` : row.ID;\n }\n\n /**\n * Get the role count label for an application.\n */\n GetRoleCountLabel(group: ApplicationGroup): string {\n if (group.Roles.length === 0) return 'Open Access (no role restrictions)';\n return `${group.Roles.length} role${group.Roles.length === 1 ? '' : 's'} assigned`;\n }\n\n /**\n * Handle dropdown selection for adding roles.\n */\n OnAddRoleSelect(group: ApplicationGroup, roleId: string): void {\n this.SelectedRoleIdToAdd.set(group.ApplicationID, roleId);\n }\n}\n\n/** Tree-shaking prevention */\nexport function LoadApplicationRolesResource(): void {\n // Prevents tree-shaking\n}\n","<div class=\"app-roles-container\">\n <!-- Header -->\n <div class=\"header\">\n <div class=\"header-left\">\n <i class=\"fa-solid fa-user-shield header-icon\"></i>\n <h2 class=\"header-title\">Application Roles</h2>\n </div>\n <div class=\"header-actions\">\n @if (HasUnsavedChanges) {\n <button mjButton variant=\"secondary\" (click)=\"DiscardChanges()\" [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-rotate-left\"></i> Discard\n </button>\n <button mjButton variant=\"primary\" (click)=\"SaveChanges()\" [disabled]=\"IsSaving\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-floppy-disk\"></i> Save Changes\n }\n </button>\n }\n <button mjButton variant=\"secondary\" (click)=\"loadData()\" [disabled]=\"IsLoading || IsSaving\">\n <i class=\"fa-solid fa-arrows-rotate\" [class.fa-spin]=\"IsLoading\"></i> Refresh\n </button>\n </div>\n </div>\n\n <!-- Status Messages -->\n @if (ErrorMessage) {\n <div class=\"message error-message\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ ErrorMessage }}\n </div>\n }\n @if (SuccessMessage) {\n <div class=\"message success-message\">\n <i class=\"fa-solid fa-circle-check\"></i>\n {{ SuccessMessage }}\n </div>\n }\n\n <!-- Loading State -->\n @if (IsLoading) {\n <mj-loading text=\"Loading application roles...\"></mj-loading>\n }\n\n <!-- Main Content -->\n @if (!IsLoading) {\n <p class=\"description\">\n Configure which roles can access each application. Applications with no role assignments are open to all users (backwards compatible).\n </p>\n\n <div class=\"app-groups\">\n @for (group of ApplicationGroups; track TrackByAppId($index, group)) {\n <div class=\"app-group\" [class.expanded]=\"group.Expanded\" [class.has-roles]=\"group.Roles.length > 0\">\n <!-- Application Header Row -->\n <div class=\"app-group-header\" (click)=\"ToggleGroup(group)\">\n <div class=\"app-header-left\">\n <i class=\"fa-solid\" [ngClass]=\"group.Expanded ? 'fa-chevron-down' : 'fa-chevron-right'\"></i>\n <span class=\"app-name\">{{ group.ApplicationName }}</span>\n <span class=\"role-count-badge\" [class.open-access]=\"group.Roles.length === 0\">\n {{ GetRoleCountLabel(group) }}\n </span>\n </div>\n </div>\n\n <!-- Expanded Content -->\n @if (group.Expanded) {\n <div class=\"app-group-content\">\n <!-- Existing Role Assignments -->\n @if (group.Roles.length > 0) {\n <table class=\"roles-table\">\n <thead>\n <tr>\n <th class=\"col-role\">Role</th>\n <th class=\"col-access\">Can Access</th>\n <th class=\"col-admin\">Can Admin</th>\n <th class=\"col-actions\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (row of group.Roles; track TrackByRoleRow($index, row)) {\n <tr [class.dirty]=\"row.IsDirty\" [class.new-row]=\"row.IsNew\">\n <td class=\"col-role\">\n <i class=\"fa-solid fa-shield-halved role-icon\"></i>\n {{ row.RoleName }}\n @if (row.IsNew) {\n <span class=\"new-badge\">new</span>\n }\n </td>\n <td class=\"col-access\">\n <input type=\"checkbox\"\n class=\"mj-checkbox\"\n [checked]=\"row.CanAccess\"\n (change)=\"ToggleCanAccess(row)\">\n </td>\n <td class=\"col-admin\">\n <input type=\"checkbox\"\n class=\"mj-checkbox\"\n [checked]=\"row.CanAdmin\"\n (change)=\"ToggleCanAdmin(row)\">\n </td>\n <td class=\"col-actions\">\n <button class=\"remove-btn\" (click)=\"RemoveRole(group, row)\" title=\"Remove role assignment\">\n <i class=\"fa-solid fa-trash-can\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"no-roles-message\">\n <i class=\"fa-solid fa-unlock\"></i>\n No role restrictions — all authenticated users can access this application.\n </div>\n }\n\n <!-- Add Role -->\n <div class=\"add-role-row\">\n <select class=\"mj-input add-role-select\"\n [value]=\"SelectedRoleIdToAdd.get(group.ApplicationID) || ''\"\n (change)=\"OnAddRoleSelect(group, $any($event.target).value)\">\n <option value=\"\" disabled>Select a role to add...</option>\n @for (role of GetUnassignedRoles(group); track role.ID) {\n <option [value]=\"role.ID\">{{ role.Name }}</option>\n }\n </select>\n <button mjButton\n variant=\"secondary\"\n (click)=\"AddRole(group)\"\n [disabled]=\"!SelectedRoleIdToAdd.get(group.ApplicationID)\">\n <i class=\"fa-solid fa-plus\"></i> Add Role\n </button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"application-roles-resource.component.js","sourceRoot":"","sources":["../../src/ApplicationRoles/application-roles-resource.component.ts","../../src/ApplicationRoles/application-roles-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { RegisterClass, UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { CompositeKey, Metadata, RunView } from '@memberjunction/core';\nimport { ResourceData } from '@memberjunction/core-entities';\n\n/**\n * Represents an application's role assignment for display in the grid.\n */\ninterface ApplicationRoleRow {\n ID: string;\n ApplicationID: string;\n ApplicationName: string;\n RoleID: string;\n RoleName: string;\n CanAccess: boolean;\n CanAdmin: boolean;\n IsDirty: boolean;\n IsNew: boolean;\n}\n\n/**\n * Represents an application with its role assignments grouped.\n */\ninterface ApplicationGroup {\n ApplicationID: string;\n ApplicationName: string;\n Roles: ApplicationRoleRow[];\n Expanded: boolean;\n}\n\n/**\n * Admin dashboard for managing Application Role assignments.\n * Shows which roles can access and administer each application.\n */\n@RegisterClass(BaseResourceComponent, 'ApplicationRolesResource')\n@Component({\n standalone: false,\n selector: 'mj-application-roles-resource',\n templateUrl: './application-roles-resource.component.html',\n styleUrls: ['./application-roles-resource.component.css']\n})\nexport class ApplicationRolesResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n ApplicationGroups: ApplicationGroup[] = [];\n AvailableRoles: { ID: string; Name: string }[] = [];\n IsLoading = true;\n IsSaving = false;\n HasUnsavedChanges = false;\n ErrorMessage: string | null = null;\n SuccessMessage: string | null = null;\n\n // For the \"Add Role\" dropdown per application\n SelectedRoleIdToAdd: Map<string, string> = new Map();\n\n constructor(private cdr: ChangeDetectorRef) {\n super();\n }\n\n override async GetResourceDisplayName(_data: ResourceData): Promise<string> {\n return 'App Roles';\n }\n\n override async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-user-shield';\n }\n\n override async ngOnInit(): Promise<void> {\n super.ngOnInit();\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n override ngOnDestroy(): void {\n super.ngOnDestroy();\n }\n\n /**\n * Load all application role data and available roles.\n */\n async loadData(): Promise<void> {\n this.IsLoading = true;\n this.ErrorMessage = null;\n this.cdr.detectChanges();\n\n try {\n const md = this.ProviderToUse;\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n\n // Load available roles from metadata\n this.AvailableRoles = md.Roles.map(r => ({ ID: r.ID, Name: r.Name }))\n .sort((a, b) => a.Name.localeCompare(b.Name));\n\n // Load existing ApplicationRole records\n const result = await rv.RunView<{ ID: string; ApplicationID: string; Application: string; RoleID: string; Role: string; CanAccess: boolean; CanAdmin: boolean }>({\n EntityName: 'MJ: Application Roles',\n ResultType: 'simple',\n });\n\n if (!result.Success) {\n this.ErrorMessage = result.ErrorMessage || 'Failed to load application roles.';\n this.IsLoading = false;\n this.cdr.detectChanges();\n return;\n }\n\n // Build grouped structure\n const appMap = new Map<string, ApplicationGroup>();\n\n // Seed all applications so we can show apps without any role records\n for (const app of md.Applications) {\n appMap.set(app.ID, {\n ApplicationID: app.ID,\n ApplicationName: app.Name,\n Roles: [],\n Expanded: false,\n });\n }\n\n // Populate role assignments\n for (const record of result.Results) {\n const group = appMap.get(record.ApplicationID);\n if (group) {\n group.Roles.push({\n ID: record.ID,\n ApplicationID: record.ApplicationID,\n ApplicationName: group.ApplicationName,\n RoleID: record.RoleID,\n RoleName: record.Role || '',\n CanAccess: record.CanAccess,\n CanAdmin: record.CanAdmin,\n IsDirty: false,\n IsNew: false,\n });\n }\n }\n\n // Sort roles within each group\n for (const group of appMap.values()) {\n group.Roles.sort((a, b) => a.RoleName.localeCompare(b.RoleName));\n }\n\n this.ApplicationGroups = Array.from(appMap.values())\n .sort((a, b) => a.ApplicationName.localeCompare(b.ApplicationName));\n } catch (e) {\n this.ErrorMessage = `Error loading data: ${e instanceof Error ? e.message : String(e)}`;\n }\n\n this.IsLoading = false;\n this.HasUnsavedChanges = false;\n this.cdr.detectChanges();\n }\n\n /**\n * Toggle the expanded/collapsed state of an application group.\n */\n ToggleGroup(group: ApplicationGroup): void {\n group.Expanded = !group.Expanded;\n this.cdr.detectChanges();\n }\n\n /**\n * Toggle CanAccess for a specific role assignment.\n */\n ToggleCanAccess(row: ApplicationRoleRow): void {\n row.CanAccess = !row.CanAccess;\n row.IsDirty = true;\n this.HasUnsavedChanges = true;\n this.cdr.detectChanges();\n }\n\n /**\n * Toggle CanAdmin for a specific role assignment.\n */\n ToggleCanAdmin(row: ApplicationRoleRow): void {\n row.CanAdmin = !row.CanAdmin;\n row.IsDirty = true;\n this.HasUnsavedChanges = true;\n this.cdr.detectChanges();\n }\n\n /**\n * Get roles not yet assigned to a specific application (for the \"Add Role\" dropdown).\n */\n GetUnassignedRoles(group: ApplicationGroup): { ID: string; Name: string }[] {\n const assignedRoleIds = new Set(group.Roles.map(r => r.RoleID.toLowerCase()));\n return this.AvailableRoles.filter(r => !assignedRoleIds.has(r.ID.toLowerCase()));\n }\n\n /**\n * Add a new role assignment to an application group.\n */\n AddRole(group: ApplicationGroup): void {\n const roleId = this.SelectedRoleIdToAdd.get(group.ApplicationID);\n if (!roleId) return;\n\n const role = this.AvailableRoles.find(r => UUIDsEqual(r.ID, roleId));\n if (!role) return;\n\n group.Roles.push({\n ID: '',\n ApplicationID: group.ApplicationID,\n ApplicationName: group.ApplicationName,\n RoleID: role.ID,\n RoleName: role.Name,\n CanAccess: true,\n CanAdmin: false,\n IsDirty: true,\n IsNew: true,\n });\n\n group.Roles.sort((a, b) => a.RoleName.localeCompare(b.RoleName));\n this.SelectedRoleIdToAdd.delete(group.ApplicationID);\n this.HasUnsavedChanges = true;\n this.cdr.detectChanges();\n }\n\n /**\n * Remove a role assignment (marks for deletion on save; removes immediately if new).\n */\n RemoveRole(group: ApplicationGroup, row: ApplicationRoleRow): void {\n const idx = group.Roles.indexOf(row);\n if (idx >= 0) {\n group.Roles.splice(idx, 1);\n }\n // If not new, we need to delete it on save — track via dirty state\n if (!row.IsNew) {\n this._pendingDeletes.push(row.ID);\n }\n this.HasUnsavedChanges = true;\n this.cdr.detectChanges();\n }\n\n private _pendingDeletes: string[] = [];\n\n /**\n * Save all unsaved changes (new records, modified records, deleted records).\n */\n async SaveChanges(): Promise<void> {\n this.IsSaving = true;\n this.ErrorMessage = null;\n this.SuccessMessage = null;\n this.cdr.detectChanges();\n\n try {\n const md = this.ProviderToUse;\n\n // Process deletes\n for (const deleteId of this._pendingDeletes) {\n const entity = await md.GetEntityObject('MJ: Application Roles');\n await entity.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: deleteId }]));\n const deleteResult = await entity.Delete();\n if (!deleteResult) {\n this.ErrorMessage = `Failed to delete role assignment: ${entity.LatestResult?.Message || 'Unknown error'}`;\n this.IsSaving = false;\n this.cdr.detectChanges();\n return;\n }\n }\n\n // Process new and modified records\n for (const group of this.ApplicationGroups) {\n for (const row of group.Roles) {\n if (!row.IsDirty) continue;\n\n if (row.IsNew) {\n const entity = await md.GetEntityObject('MJ: Application Roles');\n entity.NewRecord();\n entity.Set('ApplicationID', row.ApplicationID);\n entity.Set('RoleID', row.RoleID);\n entity.Set('CanAccess', row.CanAccess);\n entity.Set('CanAdmin', row.CanAdmin);\n const saveResult = await entity.Save();\n if (!saveResult) {\n this.ErrorMessage = `Failed to save new role assignment for ${row.RoleName}: ${entity.LatestResult?.Message || 'Unknown error'}`;\n this.IsSaving = false;\n this.cdr.detectChanges();\n return;\n }\n row.ID = entity.Get('ID');\n } else {\n const entity = await md.GetEntityObject('MJ: Application Roles');\n await entity.InnerLoad(new CompositeKey([{ FieldName: 'ID', Value: row.ID }]));\n entity.Set('CanAccess', row.CanAccess);\n entity.Set('CanAdmin', row.CanAdmin);\n const saveResult = await entity.Save();\n if (!saveResult) {\n this.ErrorMessage = `Failed to update role assignment for ${row.RoleName}: ${entity.LatestResult?.Message || 'Unknown error'}`;\n this.IsSaving = false;\n this.cdr.detectChanges();\n return;\n }\n }\n\n row.IsDirty = false;\n row.IsNew = false;\n }\n }\n\n this._pendingDeletes = [];\n this.HasUnsavedChanges = false;\n this.SuccessMessage = 'All changes saved successfully.';\n } catch (e) {\n this.ErrorMessage = `Error saving: ${e instanceof Error ? e.message : String(e)}`;\n }\n\n this.IsSaving = false;\n this.cdr.detectChanges();\n }\n\n /**\n * Discard all unsaved changes and reload data.\n */\n async DiscardChanges(): Promise<void> {\n this._pendingDeletes = [];\n await this.loadData();\n }\n\n /**\n * Track by function for application groups.\n */\n TrackByAppId(_index: number, group: ApplicationGroup): string {\n return group.ApplicationID;\n }\n\n /**\n * Track by function for role rows.\n */\n TrackByRoleRow(_index: number, row: ApplicationRoleRow): string {\n return row.IsNew ? `new-${row.RoleID}` : row.ID;\n }\n\n /**\n * Get the role count label for an application.\n */\n GetRoleCountLabel(group: ApplicationGroup): string {\n if (group.Roles.length === 0) return 'Open Access (no role restrictions)';\n return `${group.Roles.length} role${group.Roles.length === 1 ? '' : 's'} assigned`;\n }\n\n /**\n * Handle dropdown selection for adding roles.\n */\n OnAddRoleSelect(group: ApplicationGroup, roleId: string): void {\n this.SelectedRoleIdToAdd.set(group.ApplicationID, roleId);\n }\n}\n\n/** Tree-shaking prevention */\nexport function LoadApplicationRolesResource(): void {\n // Prevents tree-shaking\n}\n","<div class=\"app-roles-container\">\n <!--\n Sticky Header — action row only, matching the UserManagement / RoleManagement\n pattern. No <mj-page-header> here: ApplicationRoles renders inside Admin's\n \"Identity & Access\" left-nav shell, which owns its own <mj-page-header>.\n Adding one here would produce the doubled-header pattern Section 9b defers.\n See plans/explorer-chrome-conventions.md Section 10.\n -->\n <div class=\"sticky-header\">\n <div class=\"action-buttons\" role=\"toolbar\" aria-label=\"Application roles actions\">\n @if (HasUnsavedChanges) {\n <mj-stat-badge\n Icon=\"fa-solid fa-circle-exclamation\"\n Label=\"Unsaved changes\"\n Variant=\"warning\">\n </mj-stat-badge>\n <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"DiscardChanges()\" [disabled]=\"IsSaving\">\n <i class=\"fa-solid fa-rotate-left\"></i> Discard\n </button>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"SaveChanges()\" [disabled]=\"IsSaving\">\n @if (IsSaving) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Saving...\n } @else {\n <i class=\"fa-solid fa-floppy-disk\"></i> Save Changes\n }\n </button>\n }\n <mj-refresh-button [Loading]=\"IsLoading\" [Disabled]=\"IsSaving\" (Clicked)=\"loadData()\"></mj-refresh-button>\n </div>\n </div>\n\n <!-- Scrollable Content -->\n <div class=\"scrollable-content\">\n <!-- Status Messages -->\n @if (ErrorMessage) {\n <div class=\"message error-message\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ ErrorMessage }}\n </div>\n }\n @if (SuccessMessage) {\n <div class=\"message success-message\">\n <i class=\"fa-solid fa-circle-check\"></i>\n {{ SuccessMessage }}\n </div>\n }\n\n <!-- Loading State -->\n @if (IsLoading) {\n <mj-loading text=\"Loading application roles...\"></mj-loading>\n }\n\n <!-- Main Content -->\n @if (!IsLoading) {\n <p class=\"description\">\n Configure which roles can access each application. Applications with no role assignments are open to all users (backwards compatible).\n </p>\n\n <div class=\"app-groups\">\n @for (group of ApplicationGroups; track TrackByAppId($index, group)) {\n <div class=\"app-group\" [class.expanded]=\"group.Expanded\" [class.has-roles]=\"group.Roles.length > 0\">\n <!-- Application Header Row -->\n <div class=\"app-group-header\" (click)=\"ToggleGroup(group)\">\n <div class=\"app-header-left\">\n <i class=\"fa-solid\" [ngClass]=\"group.Expanded ? 'fa-chevron-down' : 'fa-chevron-right'\"></i>\n <span class=\"app-name\">{{ group.ApplicationName }}</span>\n <span class=\"role-count-badge\" [class.open-access]=\"group.Roles.length === 0\">\n {{ GetRoleCountLabel(group) }}\n </span>\n </div>\n </div>\n\n <!-- Expanded Content -->\n @if (group.Expanded) {\n <div class=\"app-group-content\">\n <!-- Existing Role Assignments -->\n @if (group.Roles.length > 0) {\n <table class=\"roles-table\">\n <thead>\n <tr>\n <th class=\"col-role\">Role</th>\n <th class=\"col-access\">Can Access</th>\n <th class=\"col-admin\">Can Admin</th>\n <th class=\"col-actions\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (row of group.Roles; track TrackByRoleRow($index, row)) {\n <tr [class.dirty]=\"row.IsDirty\" [class.new-row]=\"row.IsNew\">\n <td class=\"col-role\">\n <i class=\"fa-solid fa-shield-halved role-icon\"></i>\n {{ row.RoleName }}\n @if (row.IsNew) {\n <span class=\"new-badge\">new</span>\n }\n </td>\n <td class=\"col-access\">\n <input type=\"checkbox\"\n class=\"mj-checkbox\"\n [checked]=\"row.CanAccess\"\n (change)=\"ToggleCanAccess(row)\">\n </td>\n <td class=\"col-admin\">\n <input type=\"checkbox\"\n class=\"mj-checkbox\"\n [checked]=\"row.CanAdmin\"\n (change)=\"ToggleCanAdmin(row)\">\n </td>\n <td class=\"col-actions\">\n <button class=\"remove-btn\" (click)=\"RemoveRole(group, row)\" title=\"Remove role assignment\">\n <i class=\"fa-solid fa-trash-can\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"no-roles-message\">\n <i class=\"fa-solid fa-unlock\"></i>\n No role restrictions — all authenticated users can access this application.\n </div>\n }\n\n <!-- Add Role -->\n <div class=\"add-role-row\">\n <select class=\"mj-input add-role-select\"\n [value]=\"SelectedRoleIdToAdd.get(group.ApplicationID) || ''\"\n (change)=\"OnAddRoleSelect(group, $any($event.target).value)\">\n <option value=\"\" disabled>Select a role to add...</option>\n @for (role of GetUnassignedRoles(group); track role.ID) {\n <option [value]=\"role.ID\">{{ role.Name }}</option>\n }\n </select>\n <button mjButton\n variant=\"secondary\"\n (click)=\"AddRole(group)\"\n [disabled]=\"!SelectedRoleIdToAdd.get(group.ApplicationID)\">\n <i class=\"fa-solid fa-plus\"></i> Add Role\n </button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n</div>\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-config-resource.component.d.ts","sourceRoot":"","sources":["../../../src/Archiving/components/archive-config-resource.component.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAa,aAAa,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;;AAElE,
|
|
1
|
+
{"version":3,"file":"archive-config-resource.component.d.ts","sourceRoot":"","sources":["../../../src/Archiving/components/archive-config-resource.component.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAa,aAAa,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;;AAElE,qBAkBa,8BAA+B,SAAQ,qBAAsB,YAAW,aAAa;IAC9F,eAAe,IAAI,IAAI;IAIjB,sBAAsB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAI5D,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;yCATvD,8BAA8B;2CAA9B,8BAA8B;CAY1C;AAED,wBAAgB,yBAAyB,SAExC"}
|
|
@@ -16,6 +16,7 @@ import { RegisterClass } from '@memberjunction/global';
|
|
|
16
16
|
import { BaseResourceComponent } from '@memberjunction/ng-shared';
|
|
17
17
|
import * as i0 from "@angular/core";
|
|
18
18
|
import * as i1 from "@memberjunction/ng-archive-manager";
|
|
19
|
+
import * as i2 from "@memberjunction/ng-ui-components";
|
|
19
20
|
let ArchiveConfigResourceComponent = class ArchiveConfigResourceComponent extends BaseResourceComponent {
|
|
20
21
|
ngAfterViewInit() {
|
|
21
22
|
this.NotifyLoadComplete();
|
|
@@ -27,9 +28,16 @@ let ArchiveConfigResourceComponent = class ArchiveConfigResourceComponent extend
|
|
|
27
28
|
return 'fa-solid fa-sliders';
|
|
28
29
|
}
|
|
29
30
|
static ɵfac = /*@__PURE__*/ (() => { let ɵArchiveConfigResourceComponent_BaseFactory; return function ArchiveConfigResourceComponent_Factory(__ngFactoryType__) { return (ɵArchiveConfigResourceComponent_BaseFactory || (ɵArchiveConfigResourceComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ArchiveConfigResourceComponent)))(__ngFactoryType__ || ArchiveConfigResourceComponent); }; })();
|
|
30
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ArchiveConfigResourceComponent, selectors: [["app-archive-config-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
31
|
-
i0.ɵɵ
|
|
32
|
-
|
|
31
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ArchiveConfigResourceComponent, selectors: [["app-archive-config-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 2, consts: [["Title", "Archive Configuration", "Icon", "fa-solid fa-sliders", "Subtitle", "Configure entity archiving policies and schedules"], [3, "Flex", "Padding"]], template: function ArchiveConfigResourceComponent_Template(rf, ctx) { if (rf & 1) {
|
|
32
|
+
i0.ɵɵelementStart(0, "mj-page-layout");
|
|
33
|
+
i0.ɵɵelement(1, "mj-page-header", 0);
|
|
34
|
+
i0.ɵɵelementStart(2, "mj-page-body", 1);
|
|
35
|
+
i0.ɵɵelement(3, "mj-archive-config-admin");
|
|
36
|
+
i0.ɵɵelementEnd()();
|
|
37
|
+
} if (rf & 2) {
|
|
38
|
+
i0.ɵɵadvance(2);
|
|
39
|
+
i0.ɵɵproperty("Flex", true)("Padding", false);
|
|
40
|
+
} }, dependencies: [i1.ArchiveConfigAdminComponent, i2.MJPageLayoutComponent, i2.MJPageHeaderComponent, i2.MJPageBodyComponent], styles: ["[_nghost-%COMP%] { display: block; height: 100%; width: 100%; }"] });
|
|
33
41
|
};
|
|
34
42
|
ArchiveConfigResourceComponent = __decorate([
|
|
35
43
|
RegisterClass(BaseResourceComponent, 'ArchiveConfigResource')
|
|
@@ -37,9 +45,20 @@ ArchiveConfigResourceComponent = __decorate([
|
|
|
37
45
|
export { ArchiveConfigResourceComponent };
|
|
38
46
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ArchiveConfigResourceComponent, [{
|
|
39
47
|
type: Component,
|
|
40
|
-
args: [{ standalone: false, selector: 'app-archive-config-resource', template:
|
|
48
|
+
args: [{ standalone: false, selector: 'app-archive-config-resource', template: `
|
|
49
|
+
<mj-page-layout>
|
|
50
|
+
<mj-page-header
|
|
51
|
+
Title="Archive Configuration"
|
|
52
|
+
Icon="fa-solid fa-sliders"
|
|
53
|
+
Subtitle="Configure entity archiving policies and schedules">
|
|
54
|
+
</mj-page-header>
|
|
55
|
+
<mj-page-body [Flex]="true" [Padding]="false">
|
|
56
|
+
<mj-archive-config-admin></mj-archive-config-admin>
|
|
57
|
+
</mj-page-body>
|
|
58
|
+
</mj-page-layout>
|
|
59
|
+
`, styles: [":host { display: block; height: 100%; width: 100%; }"] }]
|
|
41
60
|
}], null, null); })();
|
|
42
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ArchiveConfigResourceComponent, { className: "ArchiveConfigResourceComponent", filePath: "src/Archiving/components/archive-config-resource.component.ts", lineNumber:
|
|
61
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ArchiveConfigResourceComponent, { className: "ArchiveConfigResourceComponent", filePath: "src/Archiving/components/archive-config-resource.component.ts", lineNumber: 32 }); })();
|
|
43
62
|
export function LoadArchiveConfigResource() {
|
|
44
63
|
// Prevents tree-shaking
|
|
45
64
|
}
|