@memberjunction/ng-dashboards 5.4.1 → 5.6.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.js +4 -4
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +5 -4
- package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +3 -3
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +8 -7
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +3 -3
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +4 -4
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.d.ts.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.js +3 -2
- package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
- package/dist/APIKeys/api-keys-resource.component.js +2 -2
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.d.ts.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.js +4 -3
- package/dist/APIKeys/api-scopes-panel.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +3 -3
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js +3 -2
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +2 -2
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +2 -2
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/new-action-panel.component.js +3 -2
- package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.js +3 -2
- package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js +2 -2
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts +6 -0
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +19 -6
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts +4 -0
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +13 -4
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.d.ts +2 -0
- package/dist/Credentials/components/credentials-categories-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +13 -9
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +11 -11
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +3 -3
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.d.ts +2 -0
- package/dist/Credentials/components/credentials-types-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +13 -9
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js +11 -11
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js +4 -3
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +1 -1
- package/dist/DataExplorer/components/view-selector/view-selector.component.js +4 -3
- package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +11 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +140 -108
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-resource.component.js +4 -1
- package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.d.ts.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.js +9 -8
- package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +2 -2
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Home/home-application.js +2 -2
- package/dist/Home/home-application.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +3 -3
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.d.ts +1 -0
- package/dist/Lists/components/lists-categories-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +17 -14
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +2 -2
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.d.ts +1 -0
- package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +15 -12
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.d.ts.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.js +3 -2
- package/dist/MCP/components/mcp-connection-dialog.component.js.map +1 -1
- package/dist/MCP/components/mcp-test-tool-dialog.component.d.ts.map +1 -1
- package/dist/MCP/components/mcp-test-tool-dialog.component.js +8 -7
- package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +22 -22
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.d.ts +2 -0
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +14 -10
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js +2 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts +1 -0
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +22 -18
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-review.component.d.ts +1 -0
- package/dist/Testing/components/testing-review.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-review.component.js +14 -10
- package/dist/Testing/components/testing-review.component.js.map +1 -1
- package/dist/VersionHistory/components/diff-resource.component.js +6 -6
- package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/graph-resource.component.js +2 -2
- package/dist/VersionHistory/components/graph-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.js +3 -3
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/package.json +38 -38
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-keys-resource.component.js","sourceRoot":"","sources":["../../src/APIKeys/api-keys-resource.component.ts","../../src/APIKeys/api-keys-resource.component.html"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,SAAS,EAAqB,SAAS,EAAqB,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;;;;;;;;;;;;ICJ3B,gCAAoD;;;;IAoDtC,kCAAyD;IAA7B,wOAAS,yBAAkB,KAAC;IACtD,wBAAgC;IAChC,4BAAM;IAAA,gCAAgB;IACxB,AADwB,iBAAO,EACtB;;;;IA4BP,gCAA6D;IAAlC,uOAAS,oBAAa,SAAS,CAAC,KAAC;IAC1D,wBAA8C;IAC9C,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,2DACF;;;;IAGA,gCAAqE;IAAnC,uOAAS,oBAAa,UAAU,CAAC,KAAC;IAClE,wBAAiC;IACjC,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,uEACF;;;;IAGA,gCAAoE;IAArC,uOAAS,oBAAa,YAAY,CAAC,KAAC;IACjE,wBAA2C;IAC3C,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,gEACF;;;IAGA,gCAAwB;IACtB,wBAAwC;IACxC,kCACF;IAAA,iBAAO;;;IAwCT,+BAA+B;IAC7B,wBAAuC;IACzC,iBAAM;;;;IAuCA,+BAAmD;IAA7B,qQAAS,4BAAkB,KAAC;IAChD,+BAA+D;IAC7D,uBAA+B;IACjC,iBAAM;IAEJ,AADF,+BAAsB,cACG;IAAA,YAAa;IAAA,iBAAM;IAExC,AADF,+BAAsB,eACG;IAAA,YAAY;IAAA,iBAAO;IAC1C,gCAAuB;IAAA,aAAyB;IAEpD,AADE,AADkD,iBAAO,EACnD,EACF;IAEJ,AADF,gCAAwB,eACC;IAAA,aAA8B;IAAA,iBAAM;IAC3D,gCAA4D;IAC1D,aACF;IAEJ,AADE,AADE,iBAAM,EACF,EACF;;;;IAhBkB,cAAwC;IAAxC,oDAAwC;IAIrC,eAAa;IAAb,kCAAa;IAEX,eAAY;IAAZ,iCAAY;IACZ,eAAyB;IAAzB,mDAAyB;IAI3B,eAA8B;IAA9B,0DAA8B;IAC7B,cAAmC;IAAnC,2DAAmC;IACzD,cACF;IADE,0EACF;;;IAjBR,+BAAsB;IACpB,yKAmBC;IACH,iBAAM;;;IApBJ,cAmBC;IAnBD,iCAmBC;;;IAIH,+BAAyB;IACvB,uBAA+B;IAC/B,4BAAM;IAAA,gDAAgC;IACxC,AADwC,iBAAO,EACzC;;;;;IAqBE,6BAAc;IACZ,mCASI;IADF,2QAAS,6BAAkB,KAAC;IAR9B,iBASI;;;;;;IANF,cAA0B;;;;;IAkBhC,gCAAsD;IAA7B,yQAAS,6BAAkB,KAAC;IACnD,2BAAqE;IAEnE,AADF,gCAAyB,eACE;IACvB,oBAAgC;IAChC,YACF;IAAA,iBAAM;IACN,gCAA0B;IAAA,YAAqB;IACjD,AADiD,iBAAM,EACjD;IACN,yBAAsD;IACxD,iBAAM;;;IATsB,cAAoC;IAApC,kDAAoC;IAGvD,eAAwB;IAAxB,iCAAwB;IAC3B,cACF;IADE,kDACF;IAC0B,eAAqB;IAArB,oDAAqB;;;IAjCvD,AAFF,+BAAyB,cAEY;;IACjC,+BAA+C;IAC7C,6BAA+E;IAC/E,wLAaC;IACH,iBAAM;;IAEJ,AADF,+BAA0B,cACC;IAAA,YAAqB;IAAA,iBAAM;IACpD,+BAAyB;IAAA,2BAAU;IAEvC,AADE,AADqC,iBAAM,EACrC,EACF;IAEN,iCAA0B;IACxB,2KAYC;IAEL,AADE,iBAAM,EACF;;;IApCA,eAaC;IAbD,gCAaC;IAGwB,eAAqB;IAArB,8CAAqB;IAMhD,eAYC;IAZD,gCAYC;;;IAKL,+BAAyB;IACvB,wBAAyC;IACzC,4BAAM;IAAA,oCAAoB;IAC5B,AAD4B,iBAAO,EAC7B;;;IAyBM,iCAA4B;IAAA,YAAoB;IAAA,iBAAO;;;IAA3B,cAAoB;IAApB,+CAAoB;;;;IATxD,gCAA+D;IAApC,6QAAS,oCAAyB,KAAC;IAC5D,gCAAuE;IACrE,oBAAgD;IAClD,iBAAM;IAEJ,AADF,gCAA2B,eACE;IAAA,YAAqB;IAAA,iBAAM;IAEpD,AADF,gCAA2B,gBACK;IAAA,YAAmB;IAAA,iBAAO;IACxD,8JAAqB;IAIzB,AADE,iBAAM,EACF;IACN,iCAA2B;IACzB,aACF;IACF,AADE,iBAAM,EACF;;;;IAfuB,cAA2C;IAA3C,oEAA2C;IACjE,cAAwC;IAAxC,wDAAwC;IAGhB,eAAqB;IAArB,2CAAqB;IAEhB,eAAmB;IAAnB,yCAAmB;IACjD,cAEC;IAFD,4CAEC;IAIH,eACF;IADE,qEACF;;;IAjBN,+BAA2B;IACzB,2KAkBC;IACH,iBAAM;;;IAnBJ,cAkBC;IAlBD,oCAkBC;;;IAIH,+BAAyB;IACvB,yBAAiC;IACjC,4BAAM;IAAA,kCAAkB;IAC1B,AAD0B,iBAAO,EAC3B;;;;IAQV,AADF,+BAA2B,eACQ;IAAA,6BAAa;IAAA,iBAAM;IAElD,AADF,gCAAgC,kBAC4B;IAA7B,2OAAS,yBAAkB,KAAC;IACvD,wBAAgC;IAChC,4BAAM;IAAA,4BAAY;IACpB,AADoB,iBAAO,EAClB;IACT,mCAA2D;IAA9B,2OAAS,oBAAa,KAAK,CAAC,KAAC;IACxD,yBAAgC;IAChC,6BAAM;IAAA,8BAAa;IACrB,AADqB,iBAAO,EACnB;IACT,oCAAgE;IAAnC,4OAAS,oBAAa,UAAU,CAAC,KAAC;IAC7D,yBAAiC;IACjC,6BAAM;IAAA,8BAAa;IACrB,AADqB,iBAAO,EACnB;IACT,oCAAkE;IAArC,4OAAS,oBAAa,YAAY,CAAC,KAAC;IAC/D,yBAA2C;IAC3C,6BAAM;IAAA,2BAAU;IAGtB,AADE,AADE,AADkB,iBAAO,EAChB,EACL,EACF;;;;IAvSJ,AADF,AADF,+BAA6B,cACF,aACI;IAAA,mCAAmB;IAAA,iBAAK;IACnD,6BAA6B;IAAA,sEAAsD;IACrF,AADqF,iBAAI,EACnF;IAEJ,AADF,+BAA4B,iBACsC;IAApC,0NAAS,gBAAS,KAAC;IAC7C,wBAAmC;IACrC,iBAAS;IACT,yIAAyB;IAO7B,AADE,iBAAM,EACF;IAIF,AADF,AADF,gCAAwD,eAClB,eACH;;IAC7B,gCAAgD;IAM9C,AALA,4BAII,gBAMA;IACN,iBAAM;;IACN,gCAAgC;IAAA,aAAoB;IAExD,AADE,AADsD,iBAAM,EACtD,EACF;IAEJ,AADF,gCAAyB,eACG;IAAA,aAAoB;IAAA,iBAAM;IACpD,gCAA4B;IAC1B,yIAAuB;IAMvB,yIAA6B;IAM7B,yIAAyB;IAMzB,yIAA2E;IAQjF,AADE,AADE,iBAAM,EACF,EACF;IAGJ,AADF,gCAAqB,eAC2C;IAA9B,wNAAS,oBAAa,KAAK,CAAC,KAAC;IAC3D,gCAAsB;IACpB,wBAA+B;IACjC,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAa;IAAA,iBAAM;IAC1C,gCAAuB;IAAA,2BAAU;IACnC,AADmC,iBAAM,EACnC;IACN,gCAAuB;IACrB,yBAAuC;IAE3C,AADE,iBAAM,EACF;IACN,gCAAwE;IAAjC,wNAAS,oBAAa,QAAQ,CAAC,KAAC;IACrE,gCAAsB;IACpB,yBAAwC;IAC1C,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAc;IAAA,iBAAM;IAC3C,gCAAuB;IAAA,uBAAM;IAC/B,AAD+B,iBAAM,EAC/B;IAEJ,AADF,gCAA+B,gBACJ;IAAA,aAAoE;IAEjG,AADE,AAD+F,iBAAO,EAChG,EACF;IACN,gCAA2G;IAAnC,wNAAS,oBAAa,UAAU,CAAC,KAAC;IACxG,gCAAsB;IACpB,yBAAiC;IACnC,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAqB;IAAA,iBAAM;IAClD,gCAAuB;IAAA,8BAAa;IACtC,AADsC,iBAAM,EACtC;IACN,wIAA6B;IAK/B,iBAAM;IACN,gCAAmG;IAAlC,wNAAS,oBAAa,SAAS,CAAC,KAAC;IAChG,gCAAsB;IACpB,yBAA+B;IACjC,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAe;IAAA,iBAAM;IAC5C,gCAAuB;IAAA,wBAAO;IAElC,AADE,AADgC,iBAAM,EAChC,EACF;IACN,gCAA8D;IAA9B,wNAAS,iBAAU,QAAQ,CAAC,KAAC;IAC3D,gCAAsB;IACpB,yBAAyC;IAC3C,iBAAM;IAEJ,AADF,gCAAyB,eACA;IAAA,aAAqB;IAAA,iBAAM;IAClD,gCAAuB;IAAA,iCAAgB;IAG7C,AADE,AADE,AADyC,iBAAM,EACzC,EACF,EACF;IAMA,AADF,AADF,AAFF,gCAA0B,eAEM,eACF,eACC;IACvB,wBAA+B;IAC/B,6BAAM;IAAA,mCAAkB;IAC1B,AAD0B,iBAAO,EAC3B;IACN,mCAA2D;IAA9B,2NAAS,oBAAa,KAAK,CAAC,KAAC;IACxD,2BAAS;IAAA,yBAAuC;IAEpD,AADE,iBAAS,EACL;IACN,gCAAwB;IACtB,wIAA8B;IAwB9B,wIAAgC;IAOpC,AADE,iBAAM,EACF;IAIF,AADF,AADF,gCAA+B,eACH,eACC;IACvB,yBAAyC;IACzC,6BAAM;IAAA,kCAAiB;IACzB,AADyB,iBAAO,EAC1B;IACN,iCAA6B;IAAA,2CAA0B;IACzD,AADyD,iBAAO,EAC1D;IACN,gCAAwB;IACtB,yIAA6B;IA4C7B,wIAA+B;IAOnC,AADE,iBAAM,EACF;IAIF,AADF,AADF,gCAAkC,eACN,eACC;IACvB,0BAA6C;IAC7C,8BAAM;IAAA,iCAAe;IAEzB,AADE,AADuB,iBAAO,EACxB,EACF;IACN,iCAAwB;IACtB,0IAAiC;IAuBjC,0IAAmC;IAQzC,AADE,AADE,iBAAM,EACF,EACF;IAEN,2IAAyB;IAwBzB,iCAA6B;IAC3B,0BAAwC;IAEtC,AADF,iCAA4B,eAClB;IAAA,0CAAwB;IAAA,iBAAS;IACzC,kOAGF;IACF,AADE,iBAAM,EACF;;;IA3SF,eAKC;IALD,mDAKC;IAIsB,cAA4B;IAA5B,iDAA4B;IAU7C,eAAoD;;IAMxB,eAAoB;IAApB,6CAAoB;IAI5B,eAAoB;IAApB,6CAAoB;IAE5C,eAKC;IALD,kDAKC;IACD,cAKC;IALD,wDAKC;IACD,cAKC;IALD,oDAKC;IACD,cAKC;IALD,oHAKC;IAWsB,eAAa;IAAb,sCAAa;IAYb,gBAAc;IAAd,uCAAc;IAIZ,eAAoE;IAApE,oHAAoE;IAGjE,cAAuC;IAAvC,uDAAuC;IAK5C,eAAqB;IAArB,8CAAqB;IAG9C,eAIC;IAJD,wDAIC;IAE6B,cAAgC;IAAhC,gDAAgC;IAKrC,eAAe;IAAf,wCAAe;IASf,eAAqB;IAArB,8CAAqB;IAmB5C,gBAuBC;IAvBD,yDAuBC;IACD,cAKC;IALD,2DAKC;IAaD,gBA2CC;IA3CD,wDA2CC;IACD,cAKC;IALD,0DAKC;IAYD,eAsBC;IAtBD,6DAsBC;IACD,cAKC;IALD,+DAKC;IAKP,cAsBC;IAtBD,qDAsBC;;;;IAeC,AADF,gCAA8B,kBACsB;IAAzB,2NAAS,qBAAc,KAAC;IAC/C,yBAAsC;IACtC,kCACF;IACF,AADE,iBAAS,EACL;IACN,+CAGyC;IAAvC,AADA,sPAAe,4BAAqB,KAAC,2OAClB,yBAAkB,KAAC;IACxC,iBAAkB;;;IAHhB,eAAqB;IAArB,0CAAqB;;;IAjUzB,gHAAkC;IAyTlC,6GAA8B;;;IAzT9B,4DAuTC;IAED,cAYC;IAZD,wDAYC;;;;IAID,sDACyC;IAAvC,0PAAsB,sBAAe,KAAC;IACxC,iBAA4B;;;;IAI5B,gDACmC;IAAjC,wOAAgB,sBAAe,KAAC;IAClC,iBAAsB;;;IAItB,qCAAyC;;;;IAtX3C,AADF,AADF,8BAA2B,aACD,aACC;IACrB,uBAA+B;IAC/B,4BAAM;IAAA,wBAAQ;IAElB,AADE,AADgB,iBAAO,EACjB,EACF;IAEJ,AADF,8BAAuB,iBACgF;IAAxC,sKAAS,iBAAU,MAAM,CAAC,wBAAE,iBAAU,KAAC;IAClG,uBAA+B;IAC/B,gCAAwB;IAAA,yBAAQ;IAAA,iBAAO;IACvC,iCAAwB;IAAA,aAAa;IACvC,AADuC,iBAAO,EACrC;IACT,mCAAqH;IAAhD,uKAAS,iBAAU,cAAc,CAAC,wBAAE,iBAAU,KAAC;IAClH,yBAAgC;IAChC,iCAAwB;IAAA,6BAAY;IAAA,iBAAO;IAC3C,iCAAwB;IAAA,aAAoB;IAC9C,AAD8C,iBAAO,EAC5C;IACT,mCAAyG;IAA1C,uKAAS,iBAAU,QAAQ,CAAC,wBAAE,iBAAU,KAAC;IACtG,yBAAyC;IACzC,iCAAwB;IAAA,uBAAM;IAAA,iBAAO;IACrC,iCAAwB;IAAA,aAAc;IACxC,AADwC,iBAAO,EACtC;IACT,mCAAuG;IAAzC,uKAAS,iBAAU,OAAO,CAAC,wBAAE,iBAAU,KAAC;IACpG,yBAAsC;IACtC,iCAAwB;IAAA,gCAAe;IAG7C,AADE,AADE,AADyC,iBAAO,EACvC,EACL,EACF;IAGJ,AADF,gCAA+B,eACA;IAE3B,gGAA0B;IA0U1B,6HAAkC;IAMlC,uHAA4B;IAM5B,sHAA2B;IAI/B,AADE,iBAAM,EACF;IAEN,mCAAwD;IAAtB,6LAAS,kBAAW,KAAC;IACrD,yBAA8E;IAChF,iBAAS;IAET,gCAAqD;IAArB,0LAAS,iBAAU,KAAC;IAAC,iBAAM;;;IAzX9B,eAAmC;IAAnC,mDAAmC;IAGlC,eAAa;IAAb,sCAAa;IAEd,cAA2C;IAA3C,2DAA2C;IAG1C,eAAoB;IAApB,6CAAoB;IAErB,cAAqC;IAArC,qDAAqC;IAGpC,eAAc;IAAd,uCAAc;IAEf,cAAoC;IAApC,oDAAoC;IAU7D,eAwUC;IAxUD,qDAwUC;IAED,cAIC;IAJD,6DAIC;IAED,cAIC;IAJD,uDAIC;IAED,cAEC;IAFD,sDAEC;IAKiB,eAA0B;IAAC,AAA3B,0CAA0B,4BAA2B;;ADjW/E;;;;;;;GAOG;AAQI,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,qBAAqB;IACzC,gBAAgB,CAAkC;IAEhE,QAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;IAC/B,EAAE,GAAG,IAAI,QAAQ,EAAE,CAAC;IACpB,GAAG,CAAoB;IAE/B,aAAa;IACN,WAAW,GAAa,UAAU,CAAC;IACnC,UAAU,GAAiB,KAAK,CAAC;IACjC,OAAO,GAAY,MAAM,CAAC;IAC1B,OAAO,GAAG,KAAK,CAAC;IAEvB,8CAA8C;IACvC,gBAAgB,GAAG,CAAC,CAAC;IACrB,UAAU,GAAG,CAAC,CAAC;IAEtB,iBAAiB;IACV,SAAS,GAAG,IAAI,CAAC;IAExB,aAAa;IACN,SAAS,GAAG,CAAC,CAAC;IACd,UAAU,GAAG,CAAC,CAAC;IACf,WAAW,GAAG,CAAC,CAAC;IAChB,iBAAiB,GAAG,CAAC,CAAC;IACtB,WAAW,GAAG,CAAC,CAAC;IAChB,aAAa,GAAG,CAAC,CAAC;IAEzB,mBAAmB;IACZ,OAAO,GAAqB,EAAE,CAAC;IAC/B,cAAc,GAAmB,EAAE,CAAC;IACpC,UAAU,GAAgB,EAAE,CAAC;IAC7B,WAAW,GAAqB,EAAE,CAAC;IAE1C,gBAAgB;IACT,gBAAgB,GAAG,KAAK,CAAC;IACzB,aAAa,GAAG,KAAK,CAAC;IACtB,aAAa,GAAkB,IAAI,CAAC;IAE3C,kEAAkE;IACjD,eAAe,GAAG;QAC/B,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,SAAS;KACnB,CAAC;IAEF,qDAAqD;IAC7C,iBAAiB,GAAG,IAAI,GAAG,EAA2C,CAAC;IAE/E,mBAAmB;IACZ,iBAAiB,GAAG,KAAK,CAAC;IAC1B,iBAAiB,GAAG,KAAK,CAAC;IAEjC,YAAY,GAAsB;QAC9B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,QAAQ;QACV,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAED,WAAW;QACP,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,KAAmB;QAC5C,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,KAAmB;QAC1C,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,QAAQ;QACjB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACxB,IAAI,CAAC;YACD,MAAM,OAAO,CAAC,GAAG,CAAC;gBACd,IAAI,CAAC,WAAW,EAAE;gBAClB,IAAI,CAAC,cAAc,EAAE;gBACrB,IAAI,CAAC,kBAAkB,EAAE;gBACzB,IAAI,CAAC,UAAU,EAAE;gBACjB,IAAI,CAAC,gBAAgB,EAAE;aAC1B,CAAC,CAAC;YACH,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;QACnE,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,UAAU;QACd,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC;QACxC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QACjD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IACzC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,WAAW;QACrB,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAiB;YAC5C,UAAU,EAAE,cAAc;YAC1B,OAAO,EAAE,qBAAqB;YAC9B,UAAU,EAAE,eAAe;SAC9B,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAClC,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,cAAc;QAClB,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE3B,6CAA6C;QAC7C,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAClB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;gBAC9C,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE;oBACvC,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI;oBAChD,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,KAAK;iBACtD,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC;YAC3C,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE;YAC1E,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC;YAC5E,OAAO;gBACH,QAAQ;gBACR,KAAK;gBACL,UAAU,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7D,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,SAAS,EAAE,MAAM,CAAC,IAAI;aACzB,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB;QAC5B,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC;QAEzB,kBAAkB;QAClB,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,OAAO,CAAyB;YACzD,UAAU,EAAE,wBAAwB;YACpC,OAAO,EAAE,qBAAqB;YAC9B,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,eAAe;SAC9B,CAAC,CAAC;QAEH,MAAM,UAAU,GAAmB,EAAE,CAAC;QAEtC,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YACtB,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;gBACjD,UAAU,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,GAAG,CAAC,MAAM,IAAI,aAAa;oBACrC,MAAM,EAAE,MAAM;oBACd,IAAI,EAAE,GAAG,CAAC,MAAM,IAAI,QAAQ;oBAC5B,IAAI,EAAE,GAAG,CAAC,cAAc;oBACxB,KAAK,EAAE,GAAG,CAAC,QAAQ;iBACtB,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,+CAA+C;QAC/C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YAC1C,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC3B,UAAU,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,GAAG,CAAC,KAAK;oBACnB,MAAM,EAAE,SAAS;oBACjB,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,IAAI,EAAE,GAAG,CAAC,cAAc;oBACxB,KAAK,EAAE,GAAG,CAAC,EAAE;iBAChB,CAAC,CAAC;YACP,CAAC;iBAAM,CAAC;gBACJ,UAAU,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,GAAG,CAAC,KAAK;oBACnB,MAAM,EAAE,SAAS;oBACjB,IAAI,EAAE,GAAG,CAAC,aAAa;oBACvB,IAAI,EAAE,GAAG,CAAC,cAAc;oBACxB,KAAK,EAAE,GAAG,CAAC,EAAE;iBAChB,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,cAAc,GAAG,UAAU;aAC3B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;aACnD,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,gBAAgB;QAC1B,2CAA2C;QAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;QACzE,IAAI,UAAU,EAAE,CAAC;YACb,MAAM,WAAW,GAAG,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;YACtE,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC,SAAS,CAAC;YAC/C,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC,SAAS,CAAC;QACnD,CAAC;IACL,CAAC;IAED;;OAEG;IACK,mBAAmB;QACvB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,iBAAiB,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAE7E,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;QACzE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QAE3E,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACvC,CAAC,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,GAAG,CAC7C,CAAC,MAAM,CAAC;QAET,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC7C,CAAC,CAAC,MAAM,KAAK,QAAQ;YACrB,CAAC,CAAC,SAAS;YACX,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,GAAG;YAC3B,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,iBAAiB,CAC5C,CAAC,MAAM,CAAC;QAET,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACzC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,UAAU,CACzC,CAAC,MAAM,CAAC;QAET,qDAAqD;QACrD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO;aAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC;aAClD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACX,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAClE,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAClE,OAAO,KAAK,GAAG,KAAK,CAAC;QACzB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAO;QAChB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;QAC3C,CAAC;IACL,CAAC;IAED;;OAEG;IACI,YAAY,CAAC,SAAuB,KAAK;QAC5C,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,YAAY;QACf,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;IAClC,CAAC;IAED;;OAEG;IACI,gBAAgB;QACnB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;IACjC,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,YAAY,CAAC,MAA0B;QAChD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACzB,CAAC;IACL,CAAC;IAED;;OAEG;IACI,oBAAoB;QACvB,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;IAClC,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,GAAmB;QACpC,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,GAAmB;QACpC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,YAAY;QACrB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,YAAY;QACrB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,iBAAiB;QACpB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,cAAc;QACjB,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC;QAErC,IAAI,KAAK,GAAG,GAAG,CAAC;QAEhB,0BAA0B;QAC1B,KAAK,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;QAElD,2BAA2B;QAC3B,KAAK,IAAI,CAAC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;QAExD,sDAAsD;QACtD,KAAK,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;QAEpD,iCAAiC;QACjC,IAAI,IAAI,CAAC,UAAU,GAAG,EAAE,EAAE,CAAC;YACvB,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACI,cAAc;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACpC,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,oBAAoB,CAAC;QAC7C,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,eAAe,CAAC;QACxC,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,iBAAiB,CAAC;QAC1C,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,cAAc;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACpC,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC;QAC3B,IAAI,KAAK,IAAI,EAAE;YAAE,OAAO,gBAAgB,CAAC;QACzC,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,cAAc,CAAC,KAAa;QAC/B,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC;QACnD,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,MAAsB;QACvC,QAAQ,MAAM,EAAE,CAAC;YACb,KAAK,SAAS,CAAC,CAAC,OAAO,kBAAkB,CAAC;YAC1C,KAAK,SAAS,CAAC,CAAC,OAAO,oBAAoB,CAAC;YAC5C,KAAK,SAAS,CAAC,CAAC,OAAO,iBAAiB,CAAC;YACzC,KAAK,MAAM,CAAC,CAAC,OAAO,oCAAoC,CAAC;YACzD,KAAK,UAAU,CAAC,CAAC,OAAO,+BAA+B,CAAC;YACxD,OAAO,CAAC,CAAC,OAAO,oBAAoB,CAAC;QACzC,CAAC;IACL,CAAC;IAED;;OAEG;IACI,cAAc,CAAC,MAAsB;QACxC,QAAQ,MAAM,EAAE,CAAC;YACb,KAAK,SAAS,CAAC,CAAC,OAAO,gBAAgB,CAAC;YACxC,KAAK,SAAS,CAAC,CAAC,OAAO,gBAAgB,CAAC;YACxC,KAAK,SAAS,CAAC,CAAC,OAAO,gBAAgB,CAAC;YACxC,KAAK,MAAM,CAAC,CAAC,OAAO,aAAa,CAAC;YAClC,KAAK,UAAU,CAAC,CAAC,OAAO,iBAAiB,CAAC;YAC1C,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC;IACL,CAAC;IAED;;OAEG;IACI,UAAU,CAAC,IAAiB;QAC/B,IAAI,CAAC,IAAI;YAAE,OAAO,OAAO,CAAC;QAE1B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;QAEzC,IAAI,OAAO,GAAG,CAAC;YAAE,OAAO,UAAU,CAAC;QACnC,IAAI,OAAO,GAAG,EAAE;YAAE,OAAO,GAAG,OAAO,OAAO,CAAC;QAC3C,IAAI,KAAK,GAAG,EAAE;YAAE,OAAO,GAAG,KAAK,OAAO,CAAC;QACvC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,GAAG,IAAI,OAAO,CAAC;QAEpC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,kBAAkB,EAAE,CAAC;IAC/C,CAAC;IAED;;OAEG;IACI,gBAAgB,CAAC,IAAiB;QACrC,IAAI,CAAC,IAAI;YAAE,OAAO,eAAe,CAAC;QAElC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;QAEjD,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAE/B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,eAAe,CAAC;QACvC,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,kBAAkB,CAAC;QAC1C,IAAI,IAAI,GAAG,EAAE;YAAE,OAAO,cAAc,IAAI,OAAO,CAAC;QAEhD,OAAO,WAAW,SAAS,CAAC,kBAAkB,EAAE,EAAE,CAAC;IACvD,CAAC;IAED;;OAEG;IACI,kBAAkB,CAAC,GAAmB;QACzC,IAAI,CAAC,GAAG,CAAC,SAAS;YAAE,OAAO,EAAE,CAAC;QAE9B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;QAEzC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAC/B,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,mBAAmB,CAAC;QACzC,IAAI,IAAI,GAAG,EAAE;YAAE,OAAO,eAAe,CAAC;QACtC,OAAO,EAAE,CAAC;IACd,CAAC;IAED;;OAEG;IACI,eAAe,CAAC,QAAsB;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAI,GAAG,EAAE,CAAC;YACN,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;IACL,CAAC;IAED;;OAEG;IACI,YAAY,CAAC,KAAgB;QAChC,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,GAAY;QACzB,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,gDAAgD;QAChD,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAClC,CAAC;IACL,CAAC;IAED;;OAEG;IACI,SAAS;QACZ,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;IACjC,CAAC;IAED;;OAEG;IACI,QAAQ;QACX,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,aAAa;QACtB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;kHA9hBQ,wBAAwB;6DAAxB,wBAAwB;;;;;;YCnDrC,8BAAkH;YAChH,iGAAiB;YAIjB,kFAAkB;YAuYlB,mDAGoC;YAAlC,AADA,iIAAW,wBAAoB,IAAC,4GACtB,0BAAsB,IAAC;YACnC,iBAA2B;YAG3B,gDAKiC;YAA/B,AADA,AADA,wHAAW,kBAAc,IAAC,2GACf,kBAAc,IAAC,yGAChB,uBAAmB,IAAC;YAElC,AADE,iBAAwB,EACpB;;YA1ZiF,AAAvD,uEAAsD,yBAA2B;YAC/G,cAEC;YAFD,wCAEC;YAED,cAoYC;YApYD,yCAoYC;YAIC,cAA4B;YAA5B,8CAA4B;YAO5B,cAAyB;YACzB,AADA,2CAAyB,4BACF;;;ADlWd,wBAAwB;IAPpC,aAAa,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;GAO3C,wBAAwB,CA+hBpC;;iFA/hBY,wBAAwB;cANpC,SAAS;6BACI,KAAK,YACL,sBAAsB;;kBAK/B,SAAS;mBAAC,SAAS;;kFADX,wBAAwB","sourcesContent":["import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RegisterClass } from '@memberjunction/global';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJAPIKeyEntity, MJAPIScopeEntity, MJAPIKeyUsageLogEntity, MJAPIApplicationEntity, ResourceData } from '@memberjunction/core-entities';\nimport { APIKeysEngineBase, parseAPIScopeUIConfig } from '@memberjunction/api-keys-base';\nimport { Subject } from 'rxjs';\nimport { APIKeyFilter, APIKeyListComponent } from './api-key-list.component';\nimport { APIKeyCreateResult } from './api-key-create-dialog.component';\n\n/** Activity types for recent activity display */\ntype ActivityAction = 'Created' | 'Updated' | 'Revoked' | 'Used' | 'Extended';\n\n/** Interface for recent activity items */\ninterface ActivityItem {\n keyLabel: string;\n action: ActivityAction;\n user: string;\n date: Date;\n keyId: string;\n}\n\n/** Interface for scope statistics */\ninterface ScopeStat {\n category: string;\n count: number;\n percentage: number;\n color: string;\n iconClass: string;\n}\n\n/** Current view type */\ntype ViewType = 'overview' | 'list';\n\n/** Main tab type */\ntype MainTab = 'keys' | 'applications' | 'scopes' | 'usage';\n/**\n * API Keys Resource Component\n * Provides management interface for MJ API Keys including:\n * - Overview statistics and health monitoring\n * - Key listing with status filters\n * - Key creation and revocation\n * - Usage tracking and analytics\n */\n@RegisterClass(BaseResourceComponent, 'APIKeysResource')\n@Component({\n standalone: false,\n selector: 'mj-api-keys-resource',\n templateUrl: './api-keys-resource.component.html',\n styleUrls: ['./api-keys-resource.component.css']\n})\nexport class APIKeysResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n @ViewChild('keyList') keyListComponent: APIKeyListComponent | undefined;\n\n private destroy$ = new Subject<void>();\n private md = new Metadata();\n private cdr: ChangeDetectorRef;\n\n // View state\n public CurrentView: ViewType = 'overview';\n public ListFilter: APIKeyFilter = 'all';\n public MainTab: MainTab = 'keys';\n public NavOpen = false;\n\n // Application and scope counts for tab badges\n public ApplicationCount = 0;\n public ScopeCount = 0;\n\n // Loading states\n public IsLoading = true;\n\n // Statistics\n public TotalKeys = 0;\n public ActiveKeys = 0;\n public RevokedKeys = 0;\n public ExpiringSoonCount = 0;\n public ExpiredKeys = 0;\n public NeverUsedKeys = 0;\n\n // Data collections\n public APIKeys: MJAPIKeyEntity[] = [];\n public RecentActivity: ActivityItem[] = [];\n public ScopeStats: ScopeStat[] = [];\n public TopUsedKeys: MJAPIKeyEntity[] = [];\n\n // Dialog states\n public ShowCreateDialog = false;\n public ShowEditPanel = false;\n public SelectedKeyId: string | null = null;\n\n // Default UI config for categories without explicit configuration\n private readonly defaultUIConfig = {\n icon: 'fa-solid fa-ellipsis',\n color: '#6b7280'\n };\n\n // Dynamic category UI configs built from root scopes\n private categoryUIConfigs = new Map<string, { icon: string; color: string }>();\n\n // User permissions\n public UserCanCreateKeys = false;\n public UserCanRevokeKeys = false;\n\n constructor(cdr: ChangeDetectorRef) {\n super();\n this.cdr = cdr;\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n async GetResourceDisplayName(_data: ResourceData): Promise<string> {\n return 'API Keys';\n }\n\n async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-key';\n }\n\n /**\n * Load all dashboard data\n */\n public async loadData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.markForCheck();\n try {\n await Promise.all([\n this.loadAPIKeys(),\n this.loadScopeStats(),\n this.loadRecentActivity(),\n this.loadCounts(),\n this.checkPermissions()\n ]);\n this.calculateStatistics();\n } catch (error) {\n console.error('Error loading API Keys dashboard data:', error);\n } finally {\n this.IsLoading = false;\n this.NotifyLoadComplete();\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Load application and scope counts for tab badges.\n * Uses cached data from APIKeysEngineBase.\n */\n private loadCounts(): void {\n const base = APIKeysEngineBase.Instance;\n this.ApplicationCount = base.Applications.length;\n this.ScopeCount = base.Scopes.length;\n }\n\n /**\n * Load all API keys\n */\n private async loadAPIKeys(): Promise<void> {\n const rv = new RunView();\n const result = await rv.RunView<MJAPIKeyEntity>({\n EntityName: 'MJ: API Keys',\n OrderBy: '__mj_CreatedAt DESC',\n ResultType: 'entity_object'\n });\n if (result.Success) {\n this.APIKeys = result.Results;\n }\n }\n\n /**\n * Load scope statistics by category.\n * Uses cached data from APIKeysEngineBase.\n */\n private loadScopeStats(): void {\n const base = APIKeysEngineBase.Instance;\n const scopes = base.Scopes;\n\n // Build category UI configs from root scopes\n this.categoryUIConfigs.clear();\n for (const scope of scopes) {\n if (!scope.ParentID) {\n const uiConfig = parseAPIScopeUIConfig(scope);\n this.categoryUIConfigs.set(scope.Category, {\n icon: uiConfig.icon || this.defaultUIConfig.icon,\n color: uiConfig.color || this.defaultUIConfig.color\n });\n }\n }\n\n const categoryMap = new Map<string, number>();\n for (const scope of scopes) {\n const category = scope.Category || 'Other';\n categoryMap.set(category, (categoryMap.get(category) || 0) + 1);\n }\n\n const total = scopes.length;\n this.ScopeStats = Array.from(categoryMap.entries()).map(([category, count]) => {\n const config = this.categoryUIConfigs.get(category) || this.defaultUIConfig;\n return {\n category,\n count,\n percentage: total > 0 ? Math.round((count / total) * 100) : 0,\n color: config.color,\n iconClass: config.icon\n };\n });\n }\n\n /**\n * Load recent activity from usage logs and key changes\n */\n private async loadRecentActivity(): Promise<void> {\n const rv = new RunView();\n\n // Load usage logs\n const usageResult = await rv.RunView<MJAPIKeyUsageLogEntity>({\n EntityName: 'MJ: API Key Usage Logs',\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 20,\n ResultType: 'entity_object'\n });\n\n const activities: ActivityItem[] = [];\n\n if (usageResult.Success) {\n for (const log of usageResult.Results.slice(0, 10)) {\n activities.push({\n keyLabel: log.APIKey || 'Unknown Key',\n action: 'Used',\n user: log.APIKey || 'System',\n date: log.__mj_CreatedAt,\n keyId: log.APIKeyID\n });\n }\n }\n\n // Add key creation/update activities from keys\n for (const key of this.APIKeys.slice(0, 10)) {\n if (key.Status === 'Revoked') {\n activities.push({\n keyLabel: key.Label,\n action: 'Revoked',\n user: key.User,\n date: key.__mj_UpdatedAt,\n keyId: key.ID\n });\n } else {\n activities.push({\n keyLabel: key.Label,\n action: 'Created',\n user: key.CreatedByUser,\n date: key.__mj_CreatedAt,\n keyId: key.ID\n });\n }\n }\n\n // Sort by date and take top 10\n this.RecentActivity = activities\n .sort((a, b) => b.date.getTime() - a.date.getTime())\n .slice(0, 10);\n }\n\n /**\n * Check user permissions\n */\n private async checkPermissions(): Promise<void> {\n // Check if user can create/manage API keys\n const entityInfo = this.md.Entities.find(e => e.Name === 'MJ: API Keys');\n if (entityInfo) {\n const permissions = entityInfo.GetUserPermisions(this.md.CurrentUser);\n this.UserCanCreateKeys = permissions.CanCreate;\n this.UserCanRevokeKeys = permissions.CanUpdate;\n }\n }\n\n /**\n * Calculate dashboard statistics from loaded data\n */\n private calculateStatistics(): void {\n const now = new Date();\n const thirtyDaysFromNow = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000);\n\n this.TotalKeys = this.APIKeys.length;\n this.ActiveKeys = this.APIKeys.filter(k => k.Status === 'Active').length;\n this.RevokedKeys = this.APIKeys.filter(k => k.Status === 'Revoked').length;\n\n this.ExpiredKeys = this.APIKeys.filter(k =>\n k.ExpiresAt && new Date(k.ExpiresAt) < now\n ).length;\n\n this.ExpiringSoonCount = this.APIKeys.filter(k =>\n k.Status === 'Active' &&\n k.ExpiresAt &&\n new Date(k.ExpiresAt) > now &&\n new Date(k.ExpiresAt) < thirtyDaysFromNow\n ).length;\n\n this.NeverUsedKeys = this.APIKeys.filter(k =>\n k.Status === 'Active' && !k.LastUsedAt\n ).length;\n\n // Get top used keys (most recently used active keys)\n this.TopUsedKeys = this.APIKeys\n .filter(k => k.Status === 'Active' && k.LastUsedAt)\n .sort((a, b) => {\n const aDate = a.LastUsedAt ? new Date(a.LastUsedAt).getTime() : 0;\n const bDate = b.LastUsedAt ? new Date(b.LastUsedAt).getTime() : 0;\n return bDate - aDate;\n })\n .slice(0, 5);\n }\n\n /**\n * Refresh all data\n */\n public async refresh(): Promise<void> {\n await this.loadData();\n if (this.keyListComponent) {\n await this.keyListComponent.loadKeys();\n }\n }\n\n /**\n * Switch to list view\n */\n public showListView(filter: APIKeyFilter = 'all'): void {\n this.ListFilter = filter;\n this.CurrentView = 'list';\n }\n\n /**\n * Switch to overview\n */\n public showOverview(): void {\n this.CurrentView = 'overview';\n }\n\n /**\n * Open create dialog\n */\n public openCreateDialog(): void {\n this.ShowCreateDialog = true;\n }\n\n /**\n * Handle key created\n */\n public async onKeyCreated(result: APIKeyCreateResult): Promise<void> {\n if (result.success) {\n await this.refresh();\n }\n }\n\n /**\n * Handle create dialog closed\n */\n public onCreateDialogClosed(): void {\n this.ShowCreateDialog = false;\n }\n\n /**\n * Open edit panel for a key\n */\n public openEditPanel(key: MJAPIKeyEntity): void {\n this.SelectedKeyId = key.ID;\n this.ShowEditPanel = true;\n }\n\n /**\n * Handle key from list selected\n */\n public onKeySelected(key: MJAPIKeyEntity): void {\n this.openEditPanel(key);\n }\n\n /**\n * Handle key updated\n */\n public async onKeyUpdated(): Promise<void> {\n await this.refresh();\n }\n\n /**\n * Handle key revoked\n */\n public async onKeyRevoked(): Promise<void> {\n await this.refresh();\n }\n\n /**\n * Handle edit panel closed\n */\n public onEditPanelClosed(): void {\n this.ShowEditPanel = false;\n this.SelectedKeyId = null;\n }\n\n /**\n * Get health score (0-100) based on key status\n */\n public getHealthScore(): number {\n if (this.TotalKeys === 0) return 100;\n\n let score = 100;\n\n // Deduct for expired keys\n score -= (this.ExpiredKeys / this.TotalKeys) * 40;\n\n // Deduct for expiring soon\n score -= (this.ExpiringSoonCount / this.TotalKeys) * 20;\n\n // Deduct for never used active keys (might be leaked)\n score -= (this.NeverUsedKeys / this.TotalKeys) * 10;\n\n // Deduct if too many active keys\n if (this.ActiveKeys > 20) {\n score -= Math.min(15, (this.ActiveKeys - 20) * 0.5);\n }\n\n return Math.max(0, Math.round(score));\n }\n\n /**\n * Get health label based on score\n */\n public getHealthLabel(): string {\n const score = this.getHealthScore();\n if (score >= 90) return 'Excellent Security';\n if (score >= 75) return 'Good Security';\n if (score >= 50) return 'Needs Attention';\n return 'Critical Issues';\n }\n\n /**\n * Get CSS class for health banner\n */\n public getHealthClass(): string {\n const score = this.getHealthScore();\n if (score >= 75) return '';\n if (score >= 50) return 'health-warning';\n return 'health-critical';\n }\n\n /**\n * Get donut chart offset for segment\n */\n public getDonutOffset(index: number): number {\n let offset = 0;\n for (let i = 0; i < index; i++) {\n offset -= this.ScopeStats[i].percentage * 2.51;\n }\n return offset;\n }\n\n /**\n * Get activity icon based on action\n */\n public getActionIcon(action: ActivityAction): string {\n switch (action) {\n case 'Created': return 'fa-solid fa-plus';\n case 'Updated': return 'fa-solid fa-pencil';\n case 'Revoked': return 'fa-solid fa-ban';\n case 'Used': return 'fa-solid fa-arrow-right-to-bracket';\n case 'Extended': return 'fa-solid fa-clock-rotate-left';\n default: return 'fa-solid fa-circle';\n }\n }\n\n /**\n * Get CSS class for activity action\n */\n public getActionClass(action: ActivityAction): string {\n switch (action) {\n case 'Created': return 'action-created';\n case 'Updated': return 'action-updated';\n case 'Revoked': return 'action-revoked';\n case 'Used': return 'action-used';\n case 'Extended': return 'action-extended';\n default: return '';\n }\n }\n\n /**\n * Format date for display\n */\n public formatDate(date: Date | null): string {\n if (!date) return 'Never';\n\n const now = new Date();\n const diff = now.getTime() - new Date(date).getTime();\n const minutes = Math.floor(diff / 60000);\n const hours = Math.floor(diff / 3600000);\n const days = Math.floor(diff / 86400000);\n\n if (minutes < 1) return 'Just now';\n if (minutes < 60) return `${minutes}m ago`;\n if (hours < 24) return `${hours}h ago`;\n if (days < 7) return `${days}d ago`;\n\n return new Date(date).toLocaleDateString();\n }\n\n /**\n * Format expiration for display\n */\n public formatExpiration(date: Date | null): string {\n if (!date) return 'Never expires';\n\n const now = new Date();\n const expiresAt = new Date(date);\n const diff = expiresAt.getTime() - now.getTime();\n\n if (diff < 0) return 'Expired';\n\n const days = Math.floor(diff / 86400000);\n if (days === 0) return 'Expires today';\n if (days === 1) return 'Expires tomorrow';\n if (days < 30) return `Expires in ${days} days`;\n\n return `Expires ${expiresAt.toLocaleDateString()}`;\n }\n\n /**\n * Get expiration status class\n */\n public getExpirationClass(key: MJAPIKeyEntity): string {\n if (!key.ExpiresAt) return '';\n\n const now = new Date();\n const expiresAt = new Date(key.ExpiresAt);\n const diff = expiresAt.getTime() - now.getTime();\n const days = Math.floor(diff / 86400000);\n\n if (diff < 0) return 'expired';\n if (days < 7) return 'expiring-critical';\n if (days < 30) return 'expiring-soon';\n return '';\n }\n\n /**\n * View activity for a key\n */\n public onActivityClick(activity: ActivityItem): void {\n const key = this.APIKeys.find(k => k.ID === activity.keyId);\n if (key) {\n this.openEditPanel(key);\n }\n }\n\n /**\n * View scope details - now navigates to scopes tab\n */\n public onScopeClick(_stat: ScopeStat): void {\n this.MainTab = 'scopes';\n }\n\n /**\n * Switch to a main tab\n */\n public switchTab(tab: MainTab): void {\n this.MainTab = tab;\n // Reset to overview when switching back to keys\n if (tab === 'keys') {\n this.CurrentView = 'overview';\n }\n }\n\n /**\n * Toggle mobile navigation\n */\n public toggleNav(): void {\n this.NavOpen = !this.NavOpen;\n }\n\n /**\n * Close mobile navigation\n */\n public closeNav(): void {\n this.NavOpen = false;\n }\n\n /**\n * Handle updates from child panels\n */\n public async onDataUpdated(): Promise<void> {\n await this.loadCounts();\n this.cdr.markForCheck();\n }\n}\n","<div class=\"api-keys-dashboard\" [class.panel-open]=\"ShowCreateDialog || ShowEditPanel\" [class.nav-open]=\"NavOpen\">\n @if (IsLoading) {\n <mj-loading text=\"Loading API Keys...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Left Navigation Sidebar -->\n <div class=\"dashboard-nav\">\n <div class=\"nav-header\">\n <div class=\"nav-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>API Keys</span>\n </div>\n </div>\n <div class=\"nav-items\">\n <button class=\"nav-item\" [class.active]=\"MainTab === 'keys'\" (click)=\"switchTab('keys'); closeNav()\">\n <i class=\"fa-solid fa-key\"></i>\n <span class=\"nav-label\">API Keys</span>\n <span class=\"nav-badge\">{{TotalKeys}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'applications'\" (click)=\"switchTab('applications'); closeNav()\">\n <i class=\"fa-solid fa-cube\"></i>\n <span class=\"nav-label\">Applications</span>\n <span class=\"nav-badge\">{{ApplicationCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'scopes'\" (click)=\"switchTab('scopes'); closeNav()\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span class=\"nav-label\">Scopes</span>\n <span class=\"nav-badge\">{{ScopeCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'usage'\" (click)=\"switchTab('usage'); closeNav()\">\n <i class=\"fa-solid fa-chart-line\"></i>\n <span class=\"nav-label\">Usage Analytics</span>\n </button>\n </div>\n </div>\n <!-- Main Content Area -->\n <div class=\"dashboard-content\">\n <div class=\"content-wrapper\">\n <!-- Keys Tab Content -->\n @if (MainTab === 'keys') {\n <!-- Overview View -->\n @if (CurrentView === 'overview') {\n <!-- Header with Actions -->\n <div class=\"overview-header\">\n <div class=\"header-left\">\n <h2 class=\"overview-title\">API Keys Management</h2>\n <p class=\"overview-subtitle\">Manage API keys for external integrations and services</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-refresh\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n @if (UserCanCreateKeys) {\n <button class=\"btn-primary\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate New Key</span>\n </button>\n }\n </div>\n </div>\n <!-- Health Score Banner -->\n <div class=\"health-banner\" [ngClass]=\"getHealthClass()\">\n <div class=\"health-score-container\">\n <div class=\"health-score-ring\">\n <svg viewBox=\"0 0 36 36\" class=\"circular-chart\">\n <path class=\"circle-bg\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n <path class=\"circle\"\n [attr.stroke-dasharray]=\"getHealthScore() + ', 100'\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n </svg>\n <div class=\"health-score-value\">{{getHealthScore()}}</div>\n </div>\n </div>\n <div class=\"health-info\">\n <div class=\"health-label\">{{getHealthLabel()}}</div>\n <div class=\"health-details\">\n @if (ExpiredKeys > 0) {\n <span class=\"health-alert\" (click)=\"showListView('expired')\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ExpiredKeys}} expired\n </span>\n }\n @if (ExpiringSoonCount > 0) {\n <span class=\"health-warning-text\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ExpiringSoonCount}} expiring soon\n </span>\n }\n @if (NeverUsedKeys > 0) {\n <span class=\"health-info-text\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n {{NeverUsedKeys}} never used\n </span>\n }\n @if (ExpiredKeys === 0 && ExpiringSoonCount === 0 && NeverUsedKeys === 0) {\n <span class=\"health-ok\">\n <i class=\"fa-solid fa-check-circle\"></i>\n All keys healthy\n </span>\n }\n </div>\n </div>\n </div>\n <!-- KPI Cards Row -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card clickable\" (click)=\"showListView('all')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalKeys}}</div>\n <div class=\"kpi-label\">Total Keys</div>\n </div>\n <div class=\"kpi-trend\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n </div>\n <div class=\"kpi-card active clickable\" (click)=\"showListView('active')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ActiveKeys}}</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n <div class=\"kpi-trend success\">\n <span class=\"percentage\">{{TotalKeys > 0 ? (ActiveKeys / TotalKeys * 100).toFixed(0) : 100}}%</span>\n </div>\n </div>\n <div class=\"kpi-card clickable\" [class.warning]=\"ExpiringSoonCount > 0\" (click)=\"showListView('expiring')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-clock\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ExpiringSoonCount}}</div>\n <div class=\"kpi-label\">Expiring Soon</div>\n </div>\n @if (ExpiringSoonCount > 0) {\n <div class=\"kpi-trend warning\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n </div>\n <div class=\"kpi-card clickable\" [class.danger]=\"RevokedKeys > 0\" (click)=\"showListView('revoked')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-ban\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{RevokedKeys}}</div>\n <div class=\"kpi-label\">Revoked</div>\n </div>\n </div>\n <div class=\"kpi-card clickable\" (click)=\"switchTab('scopes')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ScopeStats.length}}</div>\n <div class=\"kpi-label\">Scope Categories</div>\n </div>\n </div>\n </div>\n <!-- Content Grid -->\n <div class=\"content-grid\">\n <!-- Recently Used Keys -->\n <div class=\"panel keys-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Recently Used Keys</span>\n </div>\n <button class=\"panel-action\" (click)=\"showListView('all')\">\n View All <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n </div>\n <div class=\"panel-body\">\n @if (TopUsedKeys.length > 0) {\n <div class=\"key-list\">\n @for (key of TopUsedKeys; track key) {\n <div class=\"key-item\" (click)=\"openEditPanel(key)\">\n <div class=\"key-icon\" [class.active]=\"key.Status === 'Active'\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"key-info\">\n <div class=\"key-label\">{{key.Label}}</div>\n <div class=\"key-meta\">\n <span class=\"key-user\">{{key.User}}</span>\n <span class=\"key-hash\">...{{key.Hash.slice(-8)}}</span>\n </div>\n </div>\n <div class=\"key-status\">\n <div class=\"last-used\">{{formatDate(key.LastUsedAt)}}</div>\n <div class=\"expiration\" [ngClass]=\"getExpirationClass(key)\">\n {{formatExpiration(key.ExpiresAt)}}\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (TopUsedKeys.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-key\"></i>\n <span>No active keys with recent usage</span>\n </div>\n }\n </div>\n </div>\n <!-- Scope Categories -->\n <div class=\"panel scope-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Permission Scopes</span>\n </div>\n <span class=\"panel-subtitle\">Available scope categories</span>\n </div>\n <div class=\"panel-body\">\n @if (ScopeStats.length > 0) {\n <div class=\"scope-chart\">\n <!-- Visual Donut Chart -->\n <div class=\"donut-chart-container\">\n <svg viewBox=\"0 0 100 100\" class=\"donut-chart\">\n <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"none\" stroke=\"#e5e7eb\" stroke-width=\"12\"/>\n @for (stat of ScopeStats; track stat; let i = $index) {\n <ng-container>\n <circle\n cx=\"50\" cy=\"50\" r=\"40\"\n fill=\"none\"\n [attr.stroke]=\"stat.color\"\n stroke-width=\"12\"\n [attr.stroke-dasharray]=\"stat.percentage * 2.51 + ' ' + (251 - stat.percentage * 2.51)\"\n [attr.stroke-dashoffset]=\"getDonutOffset(i)\"\n class=\"donut-segment\"\n (click)=\"onScopeClick(stat)\"\n />\n </ng-container>\n }\n </svg>\n <div class=\"donut-center\">\n <div class=\"donut-total\">{{ScopeStats.length}}</div>\n <div class=\"donut-label\">Categories</div>\n </div>\n </div>\n <!-- Legend -->\n <div class=\"scope-legend\">\n @for (stat of ScopeStats; track stat) {\n <div class=\"legend-item\" (click)=\"onScopeClick(stat)\">\n <div class=\"legend-color\" [style.backgroundColor]=\"stat.color\"></div>\n <div class=\"legend-info\">\n <div class=\"legend-name\">\n <i [class]=\"stat.iconClass\"></i>\n {{stat.category}}\n </div>\n <div class=\"legend-value\">{{stat.count}} scopes</div>\n </div>\n <i class=\"fa-solid fa-chevron-right legend-arrow\"></i>\n </div>\n }\n </div>\n </div>\n }\n @if (ScopeStats.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n </div>\n }\n </div>\n </div>\n <!-- Recent Activity -->\n <div class=\"panel activity-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n <span>Recent Activity</span>\n </div>\n </div>\n <div class=\"panel-body\">\n @if (RecentActivity.length > 0) {\n <div class=\"activity-list\">\n @for (activity of RecentActivity; track activity) {\n <div class=\"activity-item\" (click)=\"onActivityClick(activity)\">\n <div class=\"activity-icon\" [ngClass]=\"getActionClass(activity.action)\">\n <i [class]=\"getActionIcon(activity.action)\"></i>\n </div>\n <div class=\"activity-info\">\n <div class=\"activity-name\">{{activity.keyLabel}}</div>\n <div class=\"activity-meta\">\n <span class=\"activity-action\">{{activity.action}}</span>\n @if (activity.user) {\n <span class=\"activity-user\">by {{activity.user}}</span>\n }\n </div>\n </div>\n <div class=\"activity-time\">\n {{formatDate(activity.date)}}\n </div>\n </div>\n }\n </div>\n }\n @if (RecentActivity.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <span>No recent activity</span>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Quick Actions -->\n @if (UserCanCreateKeys) {\n <div class=\"quick-actions\">\n <div class=\"quick-actions-title\">Quick Actions</div>\n <div class=\"quick-actions-grid\">\n <button class=\"quick-action\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate Key</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('all')\">\n <i class=\"fa-solid fa-list\"></i>\n <span>View All Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n <span>Expiring Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n <span>Never Used</span>\n </button>\n </div>\n </div>\n }\n <!-- Security Notice -->\n <div class=\"security-notice\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div class=\"notice-content\">\n <strong>Security Best Practices:</strong>\n API keys should be rotated regularly and revoked when no longer needed.\n Keys are hashed and stored securely - the raw key is only shown once at creation time.\n All API key usage is logged for audit purposes.\n </div>\n </div>\n }\n <!-- List View -->\n @if (CurrentView === 'list') {\n <div class=\"list-view-header\">\n <button class=\"back-btn\" (click)=\"showOverview()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back to Overview\n </button>\n </div>\n <mj-api-key-list #keyList\n [Filter]=\"ListFilter\"\n (KeySelected)=\"onKeySelected($event)\"\n (CreateRequested)=\"openCreateDialog()\">\n </mj-api-key-list>\n }\n }\n <!-- Applications Tab Content -->\n @if (MainTab === 'applications') {\n <mj-api-applications-panel\n (ApplicationUpdated)=\"onDataUpdated()\">\n </mj-api-applications-panel>\n }\n <!-- Scopes Tab Content -->\n @if (MainTab === 'scopes') {\n <mj-api-scopes-panel\n (ScopeUpdated)=\"onDataUpdated()\">\n </mj-api-scopes-panel>\n }\n <!-- Usage Tab Content -->\n @if (MainTab === 'usage') {\n <mj-api-usage-panel></mj-api-usage-panel>\n }\n </div><!-- /.content-wrapper -->\n </div><!-- /.dashboard-content -->\n <!-- Mobile Navigation Toggle -->\n <button class=\"mobile-nav-toggle\" (click)=\"toggleNav()\">\n <i class=\"fa-solid\" [class.fa-bars]=\"!NavOpen\" [class.fa-times]=\"NavOpen\"></i>\n </button>\n <!-- Mobile Navigation Overlay -->\n <div class=\"mobile-nav-overlay\" (click)=\"closeNav()\"></div>\n }\n\n <!-- Create Dialog -->\n <mj-api-key-create-dialog\n [Visible]=\"ShowCreateDialog\"\n (Created)=\"onKeyCreated($event)\"\n (Closed)=\"onCreateDialogClosed()\">\n </mj-api-key-create-dialog>\n\n <!-- Edit Panel -->\n <mj-api-key-edit-panel\n [Visible]=\"ShowEditPanel\"\n [KeyId]=\"SelectedKeyId\"\n (Updated)=\"onKeyUpdated()\"\n (Revoked)=\"onKeyRevoked()\"\n (Closed)=\"onEditPanelClosed()\">\n </mj-api-key-edit-panel>\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"api-keys-resource.component.js","sourceRoot":"","sources":["../../src/APIKeys/api-keys-resource.component.ts","../../src/APIKeys/api-keys-resource.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RegisterClass , UUIDsEqual } from '@memberjunction/global';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJAPIKeyEntity, MJAPIScopeEntity, MJAPIKeyUsageLogEntity, MJAPIApplicationEntity, ResourceData } from '@memberjunction/core-entities';\nimport { APIKeysEngineBase, parseAPIScopeUIConfig } from '@memberjunction/api-keys-base';\nimport { Subject } from 'rxjs';\nimport { APIKeyFilter, APIKeyListComponent } from './api-key-list.component';\nimport { APIKeyCreateResult } from './api-key-create-dialog.component';\n\n/** Activity types for recent activity display */\ntype ActivityAction = 'Created' | 'Updated' | 'Revoked' | 'Used' | 'Extended';\n\n/** Interface for recent activity items */\ninterface ActivityItem {\n keyLabel: string;\n action: ActivityAction;\n user: string;\n date: Date;\n keyId: string;\n}\n\n/** Interface for scope statistics */\ninterface ScopeStat {\n category: string;\n count: number;\n percentage: number;\n color: string;\n iconClass: string;\n}\n\n/** Current view type */\ntype ViewType = 'overview' | 'list';\n\n/** Main tab type */\ntype MainTab = 'keys' | 'applications' | 'scopes' | 'usage';\n/**\n * API Keys Resource Component\n * Provides management interface for MJ API Keys including:\n * - Overview statistics and health monitoring\n * - Key listing with status filters\n * - Key creation and revocation\n * - Usage tracking and analytics\n */\n@RegisterClass(BaseResourceComponent, 'APIKeysResource')\n@Component({\n standalone: false,\n selector: 'mj-api-keys-resource',\n templateUrl: './api-keys-resource.component.html',\n styleUrls: ['./api-keys-resource.component.css']\n})\nexport class APIKeysResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n @ViewChild('keyList') keyListComponent: APIKeyListComponent | undefined;\n\n private destroy$ = new Subject<void>();\n private md = new Metadata();\n private cdr: ChangeDetectorRef;\n\n // View state\n public CurrentView: ViewType = 'overview';\n public ListFilter: APIKeyFilter = 'all';\n public MainTab: MainTab = 'keys';\n public NavOpen = false;\n\n // Application and scope counts for tab badges\n public ApplicationCount = 0;\n public ScopeCount = 0;\n\n // Loading states\n public IsLoading = true;\n\n // Statistics\n public TotalKeys = 0;\n public ActiveKeys = 0;\n public RevokedKeys = 0;\n public ExpiringSoonCount = 0;\n public ExpiredKeys = 0;\n public NeverUsedKeys = 0;\n\n // Data collections\n public APIKeys: MJAPIKeyEntity[] = [];\n public RecentActivity: ActivityItem[] = [];\n public ScopeStats: ScopeStat[] = [];\n public TopUsedKeys: MJAPIKeyEntity[] = [];\n\n // Dialog states\n public ShowCreateDialog = false;\n public ShowEditPanel = false;\n public SelectedKeyId: string | null = null;\n\n // Default UI config for categories without explicit configuration\n private readonly defaultUIConfig = {\n icon: 'fa-solid fa-ellipsis',\n color: '#6b7280'\n };\n\n // Dynamic category UI configs built from root scopes\n private categoryUIConfigs = new Map<string, { icon: string; color: string }>();\n\n // User permissions\n public UserCanCreateKeys = false;\n public UserCanRevokeKeys = false;\n\n constructor(cdr: ChangeDetectorRef) {\n super();\n this.cdr = cdr;\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n async GetResourceDisplayName(_data: ResourceData): Promise<string> {\n return 'API Keys';\n }\n\n async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-key';\n }\n\n /**\n * Load all dashboard data\n */\n public async loadData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.markForCheck();\n try {\n await Promise.all([\n this.loadAPIKeys(),\n this.loadScopeStats(),\n this.loadRecentActivity(),\n this.loadCounts(),\n this.checkPermissions()\n ]);\n this.calculateStatistics();\n } catch (error) {\n console.error('Error loading API Keys dashboard data:', error);\n } finally {\n this.IsLoading = false;\n this.NotifyLoadComplete();\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Load application and scope counts for tab badges.\n * Uses cached data from APIKeysEngineBase.\n */\n private loadCounts(): void {\n const base = APIKeysEngineBase.Instance;\n this.ApplicationCount = base.Applications.length;\n this.ScopeCount = base.Scopes.length;\n }\n\n /**\n * Load all API keys\n */\n private async loadAPIKeys(): Promise<void> {\n const rv = new RunView();\n const result = await rv.RunView<MJAPIKeyEntity>({\n EntityName: 'MJ: API Keys',\n OrderBy: '__mj_CreatedAt DESC',\n ResultType: 'entity_object'\n });\n if (result.Success) {\n this.APIKeys = result.Results;\n }\n }\n\n /**\n * Load scope statistics by category.\n * Uses cached data from APIKeysEngineBase.\n */\n private loadScopeStats(): void {\n const base = APIKeysEngineBase.Instance;\n const scopes = base.Scopes;\n\n // Build category UI configs from root scopes\n this.categoryUIConfigs.clear();\n for (const scope of scopes) {\n if (!scope.ParentID) {\n const uiConfig = parseAPIScopeUIConfig(scope);\n this.categoryUIConfigs.set(scope.Category, {\n icon: uiConfig.icon || this.defaultUIConfig.icon,\n color: uiConfig.color || this.defaultUIConfig.color\n });\n }\n }\n\n const categoryMap = new Map<string, number>();\n for (const scope of scopes) {\n const category = scope.Category || 'Other';\n categoryMap.set(category, (categoryMap.get(category) || 0) + 1);\n }\n\n const total = scopes.length;\n this.ScopeStats = Array.from(categoryMap.entries()).map(([category, count]) => {\n const config = this.categoryUIConfigs.get(category) || this.defaultUIConfig;\n return {\n category,\n count,\n percentage: total > 0 ? Math.round((count / total) * 100) : 0,\n color: config.color,\n iconClass: config.icon\n };\n });\n }\n\n /**\n * Load recent activity from usage logs and key changes\n */\n private async loadRecentActivity(): Promise<void> {\n const rv = new RunView();\n\n // Load usage logs\n const usageResult = await rv.RunView<MJAPIKeyUsageLogEntity>({\n EntityName: 'MJ: API Key Usage Logs',\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 20,\n ResultType: 'entity_object'\n });\n\n const activities: ActivityItem[] = [];\n\n if (usageResult.Success) {\n for (const log of usageResult.Results.slice(0, 10)) {\n activities.push({\n keyLabel: log.APIKey || 'Unknown Key',\n action: 'Used',\n user: log.APIKey || 'System',\n date: log.__mj_CreatedAt,\n keyId: log.APIKeyID\n });\n }\n }\n\n // Add key creation/update activities from keys\n for (const key of this.APIKeys.slice(0, 10)) {\n if (key.Status === 'Revoked') {\n activities.push({\n keyLabel: key.Label,\n action: 'Revoked',\n user: key.User,\n date: key.__mj_UpdatedAt,\n keyId: key.ID\n });\n } else {\n activities.push({\n keyLabel: key.Label,\n action: 'Created',\n user: key.CreatedByUser,\n date: key.__mj_CreatedAt,\n keyId: key.ID\n });\n }\n }\n\n // Sort by date and take top 10\n this.RecentActivity = activities\n .sort((a, b) => b.date.getTime() - a.date.getTime())\n .slice(0, 10);\n }\n\n /**\n * Check user permissions\n */\n private async checkPermissions(): Promise<void> {\n // Check if user can create/manage API keys\n const entityInfo = this.md.Entities.find(e => e.Name === 'MJ: API Keys');\n if (entityInfo) {\n const permissions = entityInfo.GetUserPermisions(this.md.CurrentUser);\n this.UserCanCreateKeys = permissions.CanCreate;\n this.UserCanRevokeKeys = permissions.CanUpdate;\n }\n }\n\n /**\n * Calculate dashboard statistics from loaded data\n */\n private calculateStatistics(): void {\n const now = new Date();\n const thirtyDaysFromNow = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000);\n\n this.TotalKeys = this.APIKeys.length;\n this.ActiveKeys = this.APIKeys.filter(k => k.Status === 'Active').length;\n this.RevokedKeys = this.APIKeys.filter(k => k.Status === 'Revoked').length;\n\n this.ExpiredKeys = this.APIKeys.filter(k =>\n k.ExpiresAt && new Date(k.ExpiresAt) < now\n ).length;\n\n this.ExpiringSoonCount = this.APIKeys.filter(k =>\n k.Status === 'Active' &&\n k.ExpiresAt &&\n new Date(k.ExpiresAt) > now &&\n new Date(k.ExpiresAt) < thirtyDaysFromNow\n ).length;\n\n this.NeverUsedKeys = this.APIKeys.filter(k =>\n k.Status === 'Active' && !k.LastUsedAt\n ).length;\n\n // Get top used keys (most recently used active keys)\n this.TopUsedKeys = this.APIKeys\n .filter(k => k.Status === 'Active' && k.LastUsedAt)\n .sort((a, b) => {\n const aDate = a.LastUsedAt ? new Date(a.LastUsedAt).getTime() : 0;\n const bDate = b.LastUsedAt ? new Date(b.LastUsedAt).getTime() : 0;\n return bDate - aDate;\n })\n .slice(0, 5);\n }\n\n /**\n * Refresh all data\n */\n public async refresh(): Promise<void> {\n await this.loadData();\n if (this.keyListComponent) {\n await this.keyListComponent.loadKeys();\n }\n }\n\n /**\n * Switch to list view\n */\n public showListView(filter: APIKeyFilter = 'all'): void {\n this.ListFilter = filter;\n this.CurrentView = 'list';\n }\n\n /**\n * Switch to overview\n */\n public showOverview(): void {\n this.CurrentView = 'overview';\n }\n\n /**\n * Open create dialog\n */\n public openCreateDialog(): void {\n this.ShowCreateDialog = true;\n }\n\n /**\n * Handle key created\n */\n public async onKeyCreated(result: APIKeyCreateResult): Promise<void> {\n if (result.success) {\n await this.refresh();\n }\n }\n\n /**\n * Handle create dialog closed\n */\n public onCreateDialogClosed(): void {\n this.ShowCreateDialog = false;\n }\n\n /**\n * Open edit panel for a key\n */\n public openEditPanel(key: MJAPIKeyEntity): void {\n this.SelectedKeyId = key.ID;\n this.ShowEditPanel = true;\n }\n\n /**\n * Handle key from list selected\n */\n public onKeySelected(key: MJAPIKeyEntity): void {\n this.openEditPanel(key);\n }\n\n /**\n * Handle key updated\n */\n public async onKeyUpdated(): Promise<void> {\n await this.refresh();\n }\n\n /**\n * Handle key revoked\n */\n public async onKeyRevoked(): Promise<void> {\n await this.refresh();\n }\n\n /**\n * Handle edit panel closed\n */\n public onEditPanelClosed(): void {\n this.ShowEditPanel = false;\n this.SelectedKeyId = null;\n }\n\n /**\n * Get health score (0-100) based on key status\n */\n public getHealthScore(): number {\n if (this.TotalKeys === 0) return 100;\n\n let score = 100;\n\n // Deduct for expired keys\n score -= (this.ExpiredKeys / this.TotalKeys) * 40;\n\n // Deduct for expiring soon\n score -= (this.ExpiringSoonCount / this.TotalKeys) * 20;\n\n // Deduct for never used active keys (might be leaked)\n score -= (this.NeverUsedKeys / this.TotalKeys) * 10;\n\n // Deduct if too many active keys\n if (this.ActiveKeys > 20) {\n score -= Math.min(15, (this.ActiveKeys - 20) * 0.5);\n }\n\n return Math.max(0, Math.round(score));\n }\n\n /**\n * Get health label based on score\n */\n public getHealthLabel(): string {\n const score = this.getHealthScore();\n if (score >= 90) return 'Excellent Security';\n if (score >= 75) return 'Good Security';\n if (score >= 50) return 'Needs Attention';\n return 'Critical Issues';\n }\n\n /**\n * Get CSS class for health banner\n */\n public getHealthClass(): string {\n const score = this.getHealthScore();\n if (score >= 75) return '';\n if (score >= 50) return 'health-warning';\n return 'health-critical';\n }\n\n /**\n * Get donut chart offset for segment\n */\n public getDonutOffset(index: number): number {\n let offset = 0;\n for (let i = 0; i < index; i++) {\n offset -= this.ScopeStats[i].percentage * 2.51;\n }\n return offset;\n }\n\n /**\n * Get activity icon based on action\n */\n public getActionIcon(action: ActivityAction): string {\n switch (action) {\n case 'Created': return 'fa-solid fa-plus';\n case 'Updated': return 'fa-solid fa-pencil';\n case 'Revoked': return 'fa-solid fa-ban';\n case 'Used': return 'fa-solid fa-arrow-right-to-bracket';\n case 'Extended': return 'fa-solid fa-clock-rotate-left';\n default: return 'fa-solid fa-circle';\n }\n }\n\n /**\n * Get CSS class for activity action\n */\n public getActionClass(action: ActivityAction): string {\n switch (action) {\n case 'Created': return 'action-created';\n case 'Updated': return 'action-updated';\n case 'Revoked': return 'action-revoked';\n case 'Used': return 'action-used';\n case 'Extended': return 'action-extended';\n default: return '';\n }\n }\n\n /**\n * Format date for display\n */\n public formatDate(date: Date | null): string {\n if (!date) return 'Never';\n\n const now = new Date();\n const diff = now.getTime() - new Date(date).getTime();\n const minutes = Math.floor(diff / 60000);\n const hours = Math.floor(diff / 3600000);\n const days = Math.floor(diff / 86400000);\n\n if (minutes < 1) return 'Just now';\n if (minutes < 60) return `${minutes}m ago`;\n if (hours < 24) return `${hours}h ago`;\n if (days < 7) return `${days}d ago`;\n\n return new Date(date).toLocaleDateString();\n }\n\n /**\n * Format expiration for display\n */\n public formatExpiration(date: Date | null): string {\n if (!date) return 'Never expires';\n\n const now = new Date();\n const expiresAt = new Date(date);\n const diff = expiresAt.getTime() - now.getTime();\n\n if (diff < 0) return 'Expired';\n\n const days = Math.floor(diff / 86400000);\n if (days === 0) return 'Expires today';\n if (days === 1) return 'Expires tomorrow';\n if (days < 30) return `Expires in ${days} days`;\n\n return `Expires ${expiresAt.toLocaleDateString()}`;\n }\n\n /**\n * Get expiration status class\n */\n public getExpirationClass(key: MJAPIKeyEntity): string {\n if (!key.ExpiresAt) return '';\n\n const now = new Date();\n const expiresAt = new Date(key.ExpiresAt);\n const diff = expiresAt.getTime() - now.getTime();\n const days = Math.floor(diff / 86400000);\n\n if (diff < 0) return 'expired';\n if (days < 7) return 'expiring-critical';\n if (days < 30) return 'expiring-soon';\n return '';\n }\n\n /**\n * View activity for a key\n */\n public onActivityClick(activity: ActivityItem): void {\n const key = this.APIKeys.find(k => UUIDsEqual(k.ID, activity.keyId));\n if (key) {\n this.openEditPanel(key);\n }\n }\n\n /**\n * View scope details - now navigates to scopes tab\n */\n public onScopeClick(_stat: ScopeStat): void {\n this.MainTab = 'scopes';\n }\n\n /**\n * Switch to a main tab\n */\n public switchTab(tab: MainTab): void {\n this.MainTab = tab;\n // Reset to overview when switching back to keys\n if (tab === 'keys') {\n this.CurrentView = 'overview';\n }\n }\n\n /**\n * Toggle mobile navigation\n */\n public toggleNav(): void {\n this.NavOpen = !this.NavOpen;\n }\n\n /**\n * Close mobile navigation\n */\n public closeNav(): void {\n this.NavOpen = false;\n }\n\n /**\n * Handle updates from child panels\n */\n public async onDataUpdated(): Promise<void> {\n await this.loadCounts();\n this.cdr.markForCheck();\n }\n}\n","<div class=\"api-keys-dashboard\" [class.panel-open]=\"ShowCreateDialog || ShowEditPanel\" [class.nav-open]=\"NavOpen\">\n @if (IsLoading) {\n <mj-loading text=\"Loading API Keys...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Left Navigation Sidebar -->\n <div class=\"dashboard-nav\">\n <div class=\"nav-header\">\n <div class=\"nav-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>API Keys</span>\n </div>\n </div>\n <div class=\"nav-items\">\n <button class=\"nav-item\" [class.active]=\"MainTab === 'keys'\" (click)=\"switchTab('keys'); closeNav()\">\n <i class=\"fa-solid fa-key\"></i>\n <span class=\"nav-label\">API Keys</span>\n <span class=\"nav-badge\">{{TotalKeys}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'applications'\" (click)=\"switchTab('applications'); closeNav()\">\n <i class=\"fa-solid fa-cube\"></i>\n <span class=\"nav-label\">Applications</span>\n <span class=\"nav-badge\">{{ApplicationCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'scopes'\" (click)=\"switchTab('scopes'); closeNav()\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span class=\"nav-label\">Scopes</span>\n <span class=\"nav-badge\">{{ScopeCount}}</span>\n </button>\n <button class=\"nav-item\" [class.active]=\"MainTab === 'usage'\" (click)=\"switchTab('usage'); closeNav()\">\n <i class=\"fa-solid fa-chart-line\"></i>\n <span class=\"nav-label\">Usage Analytics</span>\n </button>\n </div>\n </div>\n <!-- Main Content Area -->\n <div class=\"dashboard-content\">\n <div class=\"content-wrapper\">\n <!-- Keys Tab Content -->\n @if (MainTab === 'keys') {\n <!-- Overview View -->\n @if (CurrentView === 'overview') {\n <!-- Header with Actions -->\n <div class=\"overview-header\">\n <div class=\"header-left\">\n <h2 class=\"overview-title\">API Keys Management</h2>\n <p class=\"overview-subtitle\">Manage API keys for external integrations and services</p>\n </div>\n <div class=\"header-actions\">\n <button class=\"btn-refresh\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n @if (UserCanCreateKeys) {\n <button class=\"btn-primary\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate New Key</span>\n </button>\n }\n </div>\n </div>\n <!-- Health Score Banner -->\n <div class=\"health-banner\" [ngClass]=\"getHealthClass()\">\n <div class=\"health-score-container\">\n <div class=\"health-score-ring\">\n <svg viewBox=\"0 0 36 36\" class=\"circular-chart\">\n <path class=\"circle-bg\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n <path class=\"circle\"\n [attr.stroke-dasharray]=\"getHealthScore() + ', 100'\"\n d=\"M18 2.0845\n a 15.9155 15.9155 0 0 1 0 31.831\n a 15.9155 15.9155 0 0 1 0 -31.831\"\n />\n </svg>\n <div class=\"health-score-value\">{{getHealthScore()}}</div>\n </div>\n </div>\n <div class=\"health-info\">\n <div class=\"health-label\">{{getHealthLabel()}}</div>\n <div class=\"health-details\">\n @if (ExpiredKeys > 0) {\n <span class=\"health-alert\" (click)=\"showListView('expired')\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ExpiredKeys}} expired\n </span>\n }\n @if (ExpiringSoonCount > 0) {\n <span class=\"health-warning-text\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n {{ExpiringSoonCount}} expiring soon\n </span>\n }\n @if (NeverUsedKeys > 0) {\n <span class=\"health-info-text\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n {{NeverUsedKeys}} never used\n </span>\n }\n @if (ExpiredKeys === 0 && ExpiringSoonCount === 0 && NeverUsedKeys === 0) {\n <span class=\"health-ok\">\n <i class=\"fa-solid fa-check-circle\"></i>\n All keys healthy\n </span>\n }\n </div>\n </div>\n </div>\n <!-- KPI Cards Row -->\n <div class=\"kpi-row\">\n <div class=\"kpi-card clickable\" (click)=\"showListView('all')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{TotalKeys}}</div>\n <div class=\"kpi-label\">Total Keys</div>\n </div>\n <div class=\"kpi-trend\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n </div>\n <div class=\"kpi-card active clickable\" (click)=\"showListView('active')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-check-circle\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ActiveKeys}}</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n <div class=\"kpi-trend success\">\n <span class=\"percentage\">{{TotalKeys > 0 ? (ActiveKeys / TotalKeys * 100).toFixed(0) : 100}}%</span>\n </div>\n </div>\n <div class=\"kpi-card clickable\" [class.warning]=\"ExpiringSoonCount > 0\" (click)=\"showListView('expiring')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-clock\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ExpiringSoonCount}}</div>\n <div class=\"kpi-label\">Expiring Soon</div>\n </div>\n @if (ExpiringSoonCount > 0) {\n <div class=\"kpi-trend warning\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n </div>\n }\n </div>\n <div class=\"kpi-card clickable\" [class.danger]=\"RevokedKeys > 0\" (click)=\"showListView('revoked')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-ban\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{RevokedKeys}}</div>\n <div class=\"kpi-label\">Revoked</div>\n </div>\n </div>\n <div class=\"kpi-card clickable\" (click)=\"switchTab('scopes')\">\n <div class=\"kpi-icon\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-value\">{{ScopeStats.length}}</div>\n <div class=\"kpi-label\">Scope Categories</div>\n </div>\n </div>\n </div>\n <!-- Content Grid -->\n <div class=\"content-grid\">\n <!-- Recently Used Keys -->\n <div class=\"panel keys-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-key\"></i>\n <span>Recently Used Keys</span>\n </div>\n <button class=\"panel-action\" (click)=\"showListView('all')\">\n View All <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n </div>\n <div class=\"panel-body\">\n @if (TopUsedKeys.length > 0) {\n <div class=\"key-list\">\n @for (key of TopUsedKeys; track key) {\n <div class=\"key-item\" (click)=\"openEditPanel(key)\">\n <div class=\"key-icon\" [class.active]=\"key.Status === 'Active'\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"key-info\">\n <div class=\"key-label\">{{key.Label}}</div>\n <div class=\"key-meta\">\n <span class=\"key-user\">{{key.User}}</span>\n <span class=\"key-hash\">...{{key.Hash.slice(-8)}}</span>\n </div>\n </div>\n <div class=\"key-status\">\n <div class=\"last-used\">{{formatDate(key.LastUsedAt)}}</div>\n <div class=\"expiration\" [ngClass]=\"getExpirationClass(key)\">\n {{formatExpiration(key.ExpiresAt)}}\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (TopUsedKeys.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-key\"></i>\n <span>No active keys with recent usage</span>\n </div>\n }\n </div>\n </div>\n <!-- Scope Categories -->\n <div class=\"panel scope-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Permission Scopes</span>\n </div>\n <span class=\"panel-subtitle\">Available scope categories</span>\n </div>\n <div class=\"panel-body\">\n @if (ScopeStats.length > 0) {\n <div class=\"scope-chart\">\n <!-- Visual Donut Chart -->\n <div class=\"donut-chart-container\">\n <svg viewBox=\"0 0 100 100\" class=\"donut-chart\">\n <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"none\" stroke=\"#e5e7eb\" stroke-width=\"12\"/>\n @for (stat of ScopeStats; track stat; let i = $index) {\n <ng-container>\n <circle\n cx=\"50\" cy=\"50\" r=\"40\"\n fill=\"none\"\n [attr.stroke]=\"stat.color\"\n stroke-width=\"12\"\n [attr.stroke-dasharray]=\"stat.percentage * 2.51 + ' ' + (251 - stat.percentage * 2.51)\"\n [attr.stroke-dashoffset]=\"getDonutOffset(i)\"\n class=\"donut-segment\"\n (click)=\"onScopeClick(stat)\"\n />\n </ng-container>\n }\n </svg>\n <div class=\"donut-center\">\n <div class=\"donut-total\">{{ScopeStats.length}}</div>\n <div class=\"donut-label\">Categories</div>\n </div>\n </div>\n <!-- Legend -->\n <div class=\"scope-legend\">\n @for (stat of ScopeStats; track stat) {\n <div class=\"legend-item\" (click)=\"onScopeClick(stat)\">\n <div class=\"legend-color\" [style.backgroundColor]=\"stat.color\"></div>\n <div class=\"legend-info\">\n <div class=\"legend-name\">\n <i [class]=\"stat.iconClass\"></i>\n {{stat.category}}\n </div>\n <div class=\"legend-value\">{{stat.count}} scopes</div>\n </div>\n <i class=\"fa-solid fa-chevron-right legend-arrow\"></i>\n </div>\n }\n </div>\n </div>\n }\n @if (ScopeStats.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n </div>\n }\n </div>\n </div>\n <!-- Recent Activity -->\n <div class=\"panel activity-panel\">\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n <span>Recent Activity</span>\n </div>\n </div>\n <div class=\"panel-body\">\n @if (RecentActivity.length > 0) {\n <div class=\"activity-list\">\n @for (activity of RecentActivity; track activity) {\n <div class=\"activity-item\" (click)=\"onActivityClick(activity)\">\n <div class=\"activity-icon\" [ngClass]=\"getActionClass(activity.action)\">\n <i [class]=\"getActionIcon(activity.action)\"></i>\n </div>\n <div class=\"activity-info\">\n <div class=\"activity-name\">{{activity.keyLabel}}</div>\n <div class=\"activity-meta\">\n <span class=\"activity-action\">{{activity.action}}</span>\n @if (activity.user) {\n <span class=\"activity-user\">by {{activity.user}}</span>\n }\n </div>\n </div>\n <div class=\"activity-time\">\n {{formatDate(activity.date)}}\n </div>\n </div>\n }\n </div>\n }\n @if (RecentActivity.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\"></i>\n <span>No recent activity</span>\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Quick Actions -->\n @if (UserCanCreateKeys) {\n <div class=\"quick-actions\">\n <div class=\"quick-actions-title\">Quick Actions</div>\n <div class=\"quick-actions-grid\">\n <button class=\"quick-action\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>Generate Key</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('all')\">\n <i class=\"fa-solid fa-list\"></i>\n <span>View All Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('expiring')\">\n <i class=\"fa-solid fa-clock\"></i>\n <span>Expiring Keys</span>\n </button>\n <button class=\"quick-action\" (click)=\"showListView('never-used')\">\n <i class=\"fa-solid fa-question-circle\"></i>\n <span>Never Used</span>\n </button>\n </div>\n </div>\n }\n <!-- Security Notice -->\n <div class=\"security-notice\">\n <i class=\"fa-solid fa-shield-check\"></i>\n <div class=\"notice-content\">\n <strong>Security Best Practices:</strong>\n API keys should be rotated regularly and revoked when no longer needed.\n Keys are hashed and stored securely - the raw key is only shown once at creation time.\n All API key usage is logged for audit purposes.\n </div>\n </div>\n }\n <!-- List View -->\n @if (CurrentView === 'list') {\n <div class=\"list-view-header\">\n <button class=\"back-btn\" (click)=\"showOverview()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back to Overview\n </button>\n </div>\n <mj-api-key-list #keyList\n [Filter]=\"ListFilter\"\n (KeySelected)=\"onKeySelected($event)\"\n (CreateRequested)=\"openCreateDialog()\">\n </mj-api-key-list>\n }\n }\n <!-- Applications Tab Content -->\n @if (MainTab === 'applications') {\n <mj-api-applications-panel\n (ApplicationUpdated)=\"onDataUpdated()\">\n </mj-api-applications-panel>\n }\n <!-- Scopes Tab Content -->\n @if (MainTab === 'scopes') {\n <mj-api-scopes-panel\n (ScopeUpdated)=\"onDataUpdated()\">\n </mj-api-scopes-panel>\n }\n <!-- Usage Tab Content -->\n @if (MainTab === 'usage') {\n <mj-api-usage-panel></mj-api-usage-panel>\n }\n </div><!-- /.content-wrapper -->\n </div><!-- /.dashboard-content -->\n <!-- Mobile Navigation Toggle -->\n <button class=\"mobile-nav-toggle\" (click)=\"toggleNav()\">\n <i class=\"fa-solid\" [class.fa-bars]=\"!NavOpen\" [class.fa-times]=\"NavOpen\"></i>\n </button>\n <!-- Mobile Navigation Overlay -->\n <div class=\"mobile-nav-overlay\" (click)=\"closeNav()\"></div>\n }\n\n <!-- Create Dialog -->\n <mj-api-key-create-dialog\n [Visible]=\"ShowCreateDialog\"\n (Created)=\"onKeyCreated($event)\"\n (Closed)=\"onCreateDialogClosed()\">\n </mj-api-key-create-dialog>\n\n <!-- Edit Panel -->\n <mj-api-key-edit-panel\n [Visible]=\"ShowEditPanel\"\n [KeyId]=\"SelectedKeyId\"\n (Updated)=\"onKeyUpdated()\"\n (Revoked)=\"onKeyRevoked()\"\n (Closed)=\"onEditPanelClosed()\">\n </mj-api-key-edit-panel>\n</div>\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-scopes-panel.component.d.ts","sourceRoot":"","sources":["../../src/APIKeys/api-scopes-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,YAAY,EAAU,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;;
|
|
1
|
+
{"version":3,"file":"api-scopes-panel.component.d.ts","sourceRoot":"","sources":["../../src/APIKeys/api-scopes-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,YAAY,EAAU,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;;AAEjE,gCAAgC;AAChC,UAAU,aAAa;IACnB,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,qBAMa,uBAAwB,YAAW,MAAM;IACxC,YAAY,qBAA4B;IAElD,OAAO,CAAC,EAAE,CAAkB;IAC5B,OAAO,CAAC,GAAG,CAAoB;IAGxB,SAAS,UAAQ;IACjB,QAAQ,UAAS;IAGjB,SAAS,EAAE,aAAa,EAAE,CAAM;IAChC,UAAU,EAAE,gBAAgB,EAAE,CAAM;IAGpC,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IAC7C,QAAQ,SAAM;IACd,eAAe,SAAM;IACrB,YAAY,SAAM;IAClB,gBAAgB,SAAM;IACtB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IACnC,YAAY,UAAQ;IAGpB,gBAAgB,UAAS;IACzB,cAAc,UAAS;IACvB,mBAAmB,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IAGpD,cAAc,SAAM;IACpB,YAAY,SAAM;IAGzB,SAAgB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASpD;IAGF,SAAgB,aAAa,WAAkF;IAC/G,SAAgB,UAAU,WAA8F;gBAE5G,GAAG,EAAE,iBAAiB;IAI5B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/B;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBtC;;OAEG;IACH,OAAO,CAAC,SAAS;IA0CjB;;OAEG;IACI,gBAAgB,CAAC,WAAW,GAAE,gBAAgB,GAAG,IAAW,GAAG,IAAI;IAY1E;;OAEG;IACI,cAAc,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAcpD;;OAEG;IACU,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IA0CvC;;OAEG;IACI,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAIhD;;OAEG;IACI,SAAS,IAAI,IAAI;IAUxB;;OAEG;IACI,WAAW,IAAI,IAAI;IAU1B;;OAEG;IACI,YAAY,IAAI,IAAI;IAO3B;;OAEG;IACI,gBAAgB,IAAI,gBAAgB,EAAE;IAoB7C;;OAEG;IACI,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM;IAIxD;;OAEG;IACI,aAAa,IAAI,MAAM;IAI9B;;OAEG;IACI,cAAc,IAAI,MAAM;yCA/RtB,uBAAuB;2CAAvB,uBAAuB;CAkSnC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Component, EventEmitter, Output } from '@angular/core';
|
|
2
2
|
import { Metadata, RunView } from '@memberjunction/core';
|
|
3
|
+
import { UUIDsEqual } from '@memberjunction/global';
|
|
3
4
|
import * as i0 from "@angular/core";
|
|
4
5
|
import * as i1 from "@angular/common";
|
|
5
6
|
import * as i2 from "@angular/forms";
|
|
@@ -497,7 +498,7 @@ export class APIScopesPanelComponent {
|
|
|
497
498
|
this.EditParentId = scope.ParentID;
|
|
498
499
|
this.EditIsActive = scope.IsActive;
|
|
499
500
|
this.SelectedParentScope = scope.ParentID
|
|
500
|
-
? this.FlatScopes.find(s => s.ID
|
|
501
|
+
? this.FlatScopes.find(s => UUIDsEqual(s.ID, scope.ParentID)) || null
|
|
501
502
|
: null;
|
|
502
503
|
this.ShowEditDialog = true;
|
|
503
504
|
}
|
|
@@ -595,7 +596,7 @@ export class APIScopesPanelComponent {
|
|
|
595
596
|
const excludeIds = new Set([this.EditingScope.ID]);
|
|
596
597
|
const addDescendants = (parentId) => {
|
|
597
598
|
for (const scope of this.FlatScopes) {
|
|
598
|
-
if (scope.ParentID
|
|
599
|
+
if (UUIDsEqual(scope.ParentID, parentId) && !excludeIds.has(scope.ID)) {
|
|
599
600
|
excludeIds.add(scope.ID);
|
|
600
601
|
addDescendants(scope.ID);
|
|
601
602
|
}
|
|
@@ -644,5 +645,5 @@ export class APIScopesPanelComponent {
|
|
|
644
645
|
}], () => [{ type: i0.ChangeDetectorRef }], { ScopeUpdated: [{
|
|
645
646
|
type: Output
|
|
646
647
|
}] }); })();
|
|
647
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(APIScopesPanelComponent, { className: "APIScopesPanelComponent", filePath: "src/APIKeys/api-scopes-panel.component.ts", lineNumber:
|
|
648
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(APIScopesPanelComponent, { className: "APIScopesPanelComponent", filePath: "src/APIKeys/api-scopes-panel.component.ts", lineNumber: 23 }); })();
|
|
648
649
|
//# sourceMappingURL=api-scopes-panel.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-scopes-panel.component.js","sourceRoot":"","sources":["../../src/APIKeys/api-scopes-panel.component.ts","../../src/APIKeys/api-scopes-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, EventEmitter, Output, ChangeDetectorRef } from '@angular/core';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJAPIScopeEntity } from '@memberjunction/core-entities';\n/** Scope tree node structure */\ninterface ScopeTreeNode {\n scope: MJAPIScopeEntity;\n children: ScopeTreeNode[];\n expanded: boolean;\n level: number;\n}\n\n/**\n * API Scopes Panel Component\n * Manages API Scopes in a hierarchical tree structure\n */\n@Component({\n standalone: false,\n selector: 'mj-api-scopes-panel',\n templateUrl: './api-scopes-panel.component.html',\n styleUrls: ['./api-scopes-panel.component.css']\n})\nexport class APIScopesPanelComponent implements OnInit {\n @Output() ScopeUpdated = new EventEmitter<void>();\n\n private md = new Metadata();\n private cdr: ChangeDetectorRef;\n\n // Loading states\n public IsLoading = true;\n public IsSaving = false;\n\n // Data\n public ScopeTree: ScopeTreeNode[] = [];\n public FlatScopes: MJAPIScopeEntity[] = [];\n\n // Edit state\n public EditingScope: MJAPIScopeEntity | null = null;\n public EditName = '';\n public EditDescription = '';\n public EditCategory = '';\n public EditResourceType = '';\n public EditParentId: string | null = null;\n public EditIsActive = true;\n\n // Dialog states\n public ShowCreateDialog = false;\n public ShowEditDialog = false;\n public SelectedParentScope: MJAPIScopeEntity | null = null;\n\n // Messages\n public SuccessMessage = '';\n public ErrorMessage = '';\n\n // Category colors\n public readonly CategoryColors: Record<string, string> = {\n 'Entities': '#6366f1',\n 'Agents': '#10b981',\n 'Admin': '#f59e0b',\n 'Actions': '#8b5cf6',\n 'Queries': '#3b82f6',\n 'Reports': '#ef4444',\n 'Communication': '#ec4899',\n 'Other': '#6b7280'\n };\n\n // Resource type options\n public readonly ResourceTypes = ['Entity', 'Agent', 'Query', 'Mutation', 'Action', 'Report', 'Admin', 'Other'];\n public readonly Categories = ['Entities', 'Agents', 'Admin', 'Actions', 'Queries', 'Reports', 'Communication', 'Other'];\n\n constructor(cdr: ChangeDetectorRef) {\n this.cdr = cdr;\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadData();\n }\n\n /**\n * Load all scopes\n */\n public async loadData(): Promise<void> {\n this.IsLoading = true;\n try {\n const rv = new RunView();\n const result = await rv.RunView<MJAPIScopeEntity>({\n EntityName: 'MJ: API Scopes',\n OrderBy: 'FullPath',\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n this.FlatScopes = result.Results;\n this.buildTree();\n }\n } catch (error) {\n console.error('Error loading scopes:', error);\n this.ErrorMessage = 'Failed to load scopes';\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Build tree structure from flat scopes\n */\n private buildTree(): void {\n const scopeMap = new Map<string, ScopeTreeNode>();\n const rootNodes: ScopeTreeNode[] = [];\n\n // Create nodes\n for (const scope of this.FlatScopes) {\n scopeMap.set(scope.ID, {\n scope,\n children: [],\n expanded: true,\n level: 0\n });\n }\n\n // Build hierarchy\n for (const scope of this.FlatScopes) {\n const node = scopeMap.get(scope.ID)!;\n if (scope.ParentID) {\n const parent = scopeMap.get(scope.ParentID);\n if (parent) {\n parent.children.push(node);\n node.level = parent.level + 1;\n } else {\n rootNodes.push(node);\n }\n } else {\n rootNodes.push(node);\n }\n }\n\n // Calculate levels recursively\n const calculateLevels = (nodes: ScopeTreeNode[], level: number) => {\n for (const node of nodes) {\n node.level = level;\n calculateLevels(node.children, level + 1);\n }\n };\n calculateLevels(rootNodes, 0);\n\n this.ScopeTree = rootNodes;\n }\n\n /**\n * Open create dialog for new scope\n */\n public openCreateDialog(parentScope: MJAPIScopeEntity | null = null): void {\n this.EditName = '';\n this.EditDescription = '';\n this.EditCategory = parentScope?.Category || 'Entities';\n this.EditResourceType = '';\n this.EditParentId = parentScope?.ID || null;\n this.EditIsActive = true;\n this.EditingScope = null;\n this.SelectedParentScope = parentScope;\n this.ShowCreateDialog = true;\n }\n\n /**\n * Open edit dialog for existing scope\n */\n public openEditDialog(scope: MJAPIScopeEntity): void {\n this.EditingScope = scope;\n this.EditName = scope.Name;\n this.EditDescription = scope.Description || '';\n this.EditCategory = scope.Category || 'Entities';\n this.EditResourceType = scope.ResourceType || '';\n this.EditParentId = scope.ParentID;\n this.EditIsActive = scope.IsActive;\n this.SelectedParentScope = scope.ParentID\n ? this.FlatScopes.find(s => s.ID === scope.ParentID) || null\n : null;\n this.ShowEditDialog = true;\n }\n\n /**\n * Save scope (create or update)\n */\n public async saveScope(): Promise<void> {\n this.IsSaving = true;\n this.ErrorMessage = '';\n\n try {\n let scope: MJAPIScopeEntity;\n\n if (this.EditingScope) {\n scope = this.EditingScope;\n } else {\n scope = await this.md.GetEntityObject<MJAPIScopeEntity>('MJ: API Scopes');\n scope.NewRecord();\n }\n\n scope.Name = this.EditName.trim();\n scope.Description = this.EditDescription.trim() || null;\n scope.Category = this.EditCategory;\n scope.ResourceType = this.EditResourceType || null;\n scope.ParentID = this.EditParentId;\n scope.IsActive = this.EditIsActive;\n // FullPath is auto-computed by the trigger\n\n const result = await scope.Save();\n if (result) {\n this.SuccessMessage = this.EditingScope\n ? 'Scope updated successfully'\n : 'Scope created successfully';\n this.closeDialogs();\n await this.loadData();\n this.ScopeUpdated.emit();\n setTimeout(() => this.SuccessMessage = '', 3000);\n } else {\n this.ErrorMessage = 'Failed to save scope';\n }\n } catch (error) {\n console.error('Error saving scope:', error);\n this.ErrorMessage = 'An error occurred while saving';\n } finally {\n this.IsSaving = false;\n }\n }\n\n /**\n * Toggle node expansion\n */\n public toggleExpanded(node: ScopeTreeNode): void {\n node.expanded = !node.expanded;\n }\n\n /**\n * Expand all nodes\n */\n public expandAll(): void {\n const expand = (nodes: ScopeTreeNode[]) => {\n for (const node of nodes) {\n node.expanded = true;\n expand(node.children);\n }\n };\n expand(this.ScopeTree);\n }\n\n /**\n * Collapse all nodes\n */\n public collapseAll(): void {\n const collapse = (nodes: ScopeTreeNode[]) => {\n for (const node of nodes) {\n node.expanded = false;\n collapse(node.children);\n }\n };\n collapse(this.ScopeTree);\n }\n\n /**\n * Close all dialogs\n */\n public closeDialogs(): void {\n this.ShowCreateDialog = false;\n this.ShowEditDialog = false;\n this.EditingScope = null;\n this.SelectedParentScope = null;\n }\n\n /**\n * Get parent scopes for dropdown (exclude self and descendants)\n */\n public getParentOptions(): MJAPIScopeEntity[] {\n if (!this.EditingScope) {\n return this.FlatScopes;\n }\n\n // Exclude self and all descendants\n const excludeIds = new Set<string>([this.EditingScope.ID]);\n const addDescendants = (parentId: string) => {\n for (const scope of this.FlatScopes) {\n if (scope.ParentID === parentId && !excludeIds.has(scope.ID)) {\n excludeIds.add(scope.ID);\n addDescendants(scope.ID);\n }\n }\n };\n addDescendants(this.EditingScope.ID);\n\n return this.FlatScopes.filter(s => !excludeIds.has(s.ID));\n }\n\n /**\n * Get category color\n */\n public getCategoryColor(category: string | null): string {\n return this.CategoryColors[category || 'Other'] || this.CategoryColors['Other'];\n }\n\n /**\n * Get count of total scopes\n */\n public getTotalCount(): number {\n return this.FlatScopes.length;\n }\n\n /**\n * Get count of active scopes\n */\n public getActiveCount(): number {\n return this.FlatScopes.filter(s => s.IsActive).length;\n }\n}\n","<div class=\"scopes-panel\">\n @if (IsLoading) {\n <mj-loading text=\"Loading scopes...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-left\">\n <h3 class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n API Scopes\n </h3>\n <p class=\"panel-subtitle\">Manage hierarchical permission scopes for API access</p>\n </div>\n <div class=\"header-actions\">\n <div class=\"scope-stats\">\n <span class=\"stat\">\n <i class=\"fa-solid fa-shield\"></i>\n {{getTotalCount()}} total\n </span>\n <span class=\"stat active\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{getActiveCount()}} active\n </span>\n </div>\n <div class=\"tree-controls\">\n <button class=\"btn-icon\" (click)=\"expandAll()\" title=\"Expand All\">\n <i class=\"fa-solid fa-plus-square\"></i>\n </button>\n <button class=\"btn-icon\" (click)=\"collapseAll()\" title=\"Collapse All\">\n <i class=\"fa-solid fa-minus-square\"></i>\n </button>\n </div>\n <button class=\"btn-create\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n New Scope\n </button>\n </div>\n </div>\n <!-- Messages -->\n @if (SuccessMessage) {\n <div class=\"message success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{SuccessMessage}}\n </div>\n }\n @if (ErrorMessage) {\n <div class=\"message error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ErrorMessage}}\n </div>\n }\n <!-- Scope Tree -->\n <div class=\"scope-tree\">\n @for (node of ScopeTree; track node) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: node }\"></ng-container>\n }\n <!-- Empty State -->\n @if (ScopeTree.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n <p>Create scopes to define API access permissions</p>\n </div>\n }\n </div>\n <!-- Recursive Node Template -->\n <ng-template #scopeNode let-node=\"node\">\n <div class=\"scope-node\" [style.padding-left.px]=\"node.level * 24\">\n <div class=\"node-content\" [class.inactive]=\"!node.scope.IsActive\">\n @if (node.children.length > 0) {\n <button class=\"expand-btn\"\n (click)=\"toggleExpanded(node)\">\n <i class=\"fa-solid\"\n [class.fa-chevron-right]=\"!node.expanded\"\n [class.fa-chevron-down]=\"node.expanded\"></i>\n </button>\n }\n @if (node.children.length === 0) {\n <span class=\"expand-placeholder\"></span>\n }\n <div class=\"scope-info\" (click)=\"openEditDialog(node.scope)\">\n <div class=\"scope-icon\" [style.backgroundColor]=\"getCategoryColor(node.scope.Category)\">\n <i class=\"fa-solid fa-shield\"></i>\n </div>\n <div class=\"scope-details\">\n <div class=\"scope-name\">\n {{node.scope.Name}}\n @if (node.scope.FullPath && node.scope.FullPath !== node.scope.Name) {\n <span class=\"full-path\">\n {{node.scope.FullPath}}\n </span>\n }\n @if (!node.scope.IsActive) {\n <span class=\"status-badge\">Inactive</span>\n }\n </div>\n <div class=\"scope-meta\">\n <span class=\"category\" [style.color]=\"getCategoryColor(node.scope.Category)\">\n {{node.scope.Category}}\n </span>\n @if (node.scope.ResourceType) {\n <span class=\"resource-type\">\n {{node.scope.ResourceType}}\n </span>\n }\n @if (node.scope.Description) {\n <span class=\"description\">\n {{node.scope.Description}}\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"node-actions\">\n <button class=\"btn-node-action\" (click)=\"openCreateDialog(node.scope)\" title=\"Add Child Scope\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n <button class=\"btn-node-action\" (click)=\"openEditDialog(node.scope)\" title=\"Edit Scope\">\n <i class=\"fa-solid fa-pencil\"></i>\n </button>\n </div>\n </div>\n @if (node.expanded && node.children.length > 0) {\n <div class=\"children\">\n @for (child of node.children; track child) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: child }\"></ng-container>\n }\n </div>\n }\n </div>\n </ng-template>\n }\n\n <!-- Create/Edit Dialog -->\n @if (ShowCreateDialog || ShowEditDialog) {\n <kendo-window\n [width]=\"560\"\n [minWidth]=\"420\"\n [minHeight]=\"480\"\n [resizable]=\"true\"\n [draggable]=\"true\"\n [top]=\"80\"\n (close)=\"closeDialogs()\">\n <kendo-window-titlebar>\n <div class=\"dialog-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>{{EditingScope ? 'Edit Scope' : 'New Scope'}}</span>\n </div>\n <button kendoButton fillMode=\"flat\" (click)=\"closeDialogs()\" class=\"window-close-btn\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </kendo-window-titlebar>\n <div class=\"dialog-content\">\n <div class=\"form-field\">\n <label>Scope Name *</label>\n <input kendoTextBox [(ngModel)]=\"EditName\"\n placeholder=\"e.g., runview, create, execute\"\n class=\"form-input\" />\n <span class=\"field-hint\">Use lowercase, single word. Will be combined with parent for full path.</span>\n </div>\n <div class=\"form-field\">\n <label>Parent Scope</label>\n <kendo-dropdownlist [(ngModel)]=\"EditParentId\"\n [data]=\"getParentOptions()\"\n [textField]=\"'FullPath'\"\n [valueField]=\"'ID'\"\n [valuePrimitive]=\"true\"\n [defaultItem]=\"{ FullPath: '(No Parent - Root Level)', ID: null }\">\n </kendo-dropdownlist>\n @if (SelectedParentScope) {\n <span class=\"field-hint\">\n Full path will be: <code>{{SelectedParentScope.FullPath}}:{{EditName || '...'}}</code>\n </span>\n }\n </div>\n <div class=\"form-row\">\n <div class=\"form-field half\">\n <label>Category</label>\n <kendo-dropdownlist [(ngModel)]=\"EditCategory\"\n [data]=\"Categories\"\n [valuePrimitive]=\"true\">\n </kendo-dropdownlist>\n </div>\n <div class=\"form-field half\">\n <label>Resource Type</label>\n <kendo-dropdownlist [(ngModel)]=\"EditResourceType\"\n [data]=\"ResourceTypes\"\n [valuePrimitive]=\"true\"\n [defaultItem]=\"''\">\n </kendo-dropdownlist>\n </div>\n </div>\n <div class=\"form-field\">\n <label>Description</label>\n <textarea kendoTextArea [(ngModel)]=\"EditDescription\"\n placeholder=\"Describe what this scope allows...\"\n [rows]=\"3\"\n class=\"form-textarea\"></textarea>\n </div>\n <div class=\"form-field\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" kendoCheckBox [(ngModel)]=\"EditIsActive\" />\n <div>\n <span>Active</span>\n <span class=\"checkbox-hint\">Inactive scopes cannot be assigned to keys or applications</span>\n </div>\n </label>\n </div>\n <div class=\"dialog-actions\">\n <button kendoButton [themeColor]=\"'primary'\"\n [disabled]=\"!EditName.trim() || IsSaving\"\n (click)=\"saveScope()\">\n @if (IsSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsSaving) {\n <span>\n <i class=\"fa-solid fa-save\"></i>\n {{EditingScope ? 'Update' : 'Create'}}\n </span>\n }\n </button>\n <button kendoButton (click)=\"closeDialogs()\">Cancel</button>\n </div>\n </div>\n </kendo-window>\n }\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"api-scopes-panel.component.js","sourceRoot":"","sources":["../../src/APIKeys/api-scopes-panel.component.ts","../../src/APIKeys/api-scopes-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, EventEmitter, Output, ChangeDetectorRef } from '@angular/core';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJAPIScopeEntity } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\n/** Scope tree node structure */\ninterface ScopeTreeNode {\n scope: MJAPIScopeEntity;\n children: ScopeTreeNode[];\n expanded: boolean;\n level: number;\n}\n\n/**\n * API Scopes Panel Component\n * Manages API Scopes in a hierarchical tree structure\n */\n@Component({\n standalone: false,\n selector: 'mj-api-scopes-panel',\n templateUrl: './api-scopes-panel.component.html',\n styleUrls: ['./api-scopes-panel.component.css']\n})\nexport class APIScopesPanelComponent implements OnInit {\n @Output() ScopeUpdated = new EventEmitter<void>();\n\n private md = new Metadata();\n private cdr: ChangeDetectorRef;\n\n // Loading states\n public IsLoading = true;\n public IsSaving = false;\n\n // Data\n public ScopeTree: ScopeTreeNode[] = [];\n public FlatScopes: MJAPIScopeEntity[] = [];\n\n // Edit state\n public EditingScope: MJAPIScopeEntity | null = null;\n public EditName = '';\n public EditDescription = '';\n public EditCategory = '';\n public EditResourceType = '';\n public EditParentId: string | null = null;\n public EditIsActive = true;\n\n // Dialog states\n public ShowCreateDialog = false;\n public ShowEditDialog = false;\n public SelectedParentScope: MJAPIScopeEntity | null = null;\n\n // Messages\n public SuccessMessage = '';\n public ErrorMessage = '';\n\n // Category colors\n public readonly CategoryColors: Record<string, string> = {\n 'Entities': '#6366f1',\n 'Agents': '#10b981',\n 'Admin': '#f59e0b',\n 'Actions': '#8b5cf6',\n 'Queries': '#3b82f6',\n 'Reports': '#ef4444',\n 'Communication': '#ec4899',\n 'Other': '#6b7280'\n };\n\n // Resource type options\n public readonly ResourceTypes = ['Entity', 'Agent', 'Query', 'Mutation', 'Action', 'Report', 'Admin', 'Other'];\n public readonly Categories = ['Entities', 'Agents', 'Admin', 'Actions', 'Queries', 'Reports', 'Communication', 'Other'];\n\n constructor(cdr: ChangeDetectorRef) {\n this.cdr = cdr;\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadData();\n }\n\n /**\n * Load all scopes\n */\n public async loadData(): Promise<void> {\n this.IsLoading = true;\n try {\n const rv = new RunView();\n const result = await rv.RunView<MJAPIScopeEntity>({\n EntityName: 'MJ: API Scopes',\n OrderBy: 'FullPath',\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n this.FlatScopes = result.Results;\n this.buildTree();\n }\n } catch (error) {\n console.error('Error loading scopes:', error);\n this.ErrorMessage = 'Failed to load scopes';\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Build tree structure from flat scopes\n */\n private buildTree(): void {\n const scopeMap = new Map<string, ScopeTreeNode>();\n const rootNodes: ScopeTreeNode[] = [];\n\n // Create nodes\n for (const scope of this.FlatScopes) {\n scopeMap.set(scope.ID, {\n scope,\n children: [],\n expanded: true,\n level: 0\n });\n }\n\n // Build hierarchy\n for (const scope of this.FlatScopes) {\n const node = scopeMap.get(scope.ID)!;\n if (scope.ParentID) {\n const parent = scopeMap.get(scope.ParentID);\n if (parent) {\n parent.children.push(node);\n node.level = parent.level + 1;\n } else {\n rootNodes.push(node);\n }\n } else {\n rootNodes.push(node);\n }\n }\n\n // Calculate levels recursively\n const calculateLevels = (nodes: ScopeTreeNode[], level: number) => {\n for (const node of nodes) {\n node.level = level;\n calculateLevels(node.children, level + 1);\n }\n };\n calculateLevels(rootNodes, 0);\n\n this.ScopeTree = rootNodes;\n }\n\n /**\n * Open create dialog for new scope\n */\n public openCreateDialog(parentScope: MJAPIScopeEntity | null = null): void {\n this.EditName = '';\n this.EditDescription = '';\n this.EditCategory = parentScope?.Category || 'Entities';\n this.EditResourceType = '';\n this.EditParentId = parentScope?.ID || null;\n this.EditIsActive = true;\n this.EditingScope = null;\n this.SelectedParentScope = parentScope;\n this.ShowCreateDialog = true;\n }\n\n /**\n * Open edit dialog for existing scope\n */\n public openEditDialog(scope: MJAPIScopeEntity): void {\n this.EditingScope = scope;\n this.EditName = scope.Name;\n this.EditDescription = scope.Description || '';\n this.EditCategory = scope.Category || 'Entities';\n this.EditResourceType = scope.ResourceType || '';\n this.EditParentId = scope.ParentID;\n this.EditIsActive = scope.IsActive;\n this.SelectedParentScope = scope.ParentID\n ? this.FlatScopes.find(s => UUIDsEqual(s.ID, scope.ParentID)) || null\n : null;\n this.ShowEditDialog = true;\n }\n\n /**\n * Save scope (create or update)\n */\n public async saveScope(): Promise<void> {\n this.IsSaving = true;\n this.ErrorMessage = '';\n\n try {\n let scope: MJAPIScopeEntity;\n\n if (this.EditingScope) {\n scope = this.EditingScope;\n } else {\n scope = await this.md.GetEntityObject<MJAPIScopeEntity>('MJ: API Scopes');\n scope.NewRecord();\n }\n\n scope.Name = this.EditName.trim();\n scope.Description = this.EditDescription.trim() || null;\n scope.Category = this.EditCategory;\n scope.ResourceType = this.EditResourceType || null;\n scope.ParentID = this.EditParentId;\n scope.IsActive = this.EditIsActive;\n // FullPath is auto-computed by the trigger\n\n const result = await scope.Save();\n if (result) {\n this.SuccessMessage = this.EditingScope\n ? 'Scope updated successfully'\n : 'Scope created successfully';\n this.closeDialogs();\n await this.loadData();\n this.ScopeUpdated.emit();\n setTimeout(() => this.SuccessMessage = '', 3000);\n } else {\n this.ErrorMessage = 'Failed to save scope';\n }\n } catch (error) {\n console.error('Error saving scope:', error);\n this.ErrorMessage = 'An error occurred while saving';\n } finally {\n this.IsSaving = false;\n }\n }\n\n /**\n * Toggle node expansion\n */\n public toggleExpanded(node: ScopeTreeNode): void {\n node.expanded = !node.expanded;\n }\n\n /**\n * Expand all nodes\n */\n public expandAll(): void {\n const expand = (nodes: ScopeTreeNode[]) => {\n for (const node of nodes) {\n node.expanded = true;\n expand(node.children);\n }\n };\n expand(this.ScopeTree);\n }\n\n /**\n * Collapse all nodes\n */\n public collapseAll(): void {\n const collapse = (nodes: ScopeTreeNode[]) => {\n for (const node of nodes) {\n node.expanded = false;\n collapse(node.children);\n }\n };\n collapse(this.ScopeTree);\n }\n\n /**\n * Close all dialogs\n */\n public closeDialogs(): void {\n this.ShowCreateDialog = false;\n this.ShowEditDialog = false;\n this.EditingScope = null;\n this.SelectedParentScope = null;\n }\n\n /**\n * Get parent scopes for dropdown (exclude self and descendants)\n */\n public getParentOptions(): MJAPIScopeEntity[] {\n if (!this.EditingScope) {\n return this.FlatScopes;\n }\n\n // Exclude self and all descendants\n const excludeIds = new Set<string>([this.EditingScope.ID]);\n const addDescendants = (parentId: string) => {\n for (const scope of this.FlatScopes) {\n if (UUIDsEqual(scope.ParentID, parentId) && !excludeIds.has(scope.ID)) {\n excludeIds.add(scope.ID);\n addDescendants(scope.ID);\n }\n }\n };\n addDescendants(this.EditingScope.ID);\n\n return this.FlatScopes.filter(s => !excludeIds.has(s.ID));\n }\n\n /**\n * Get category color\n */\n public getCategoryColor(category: string | null): string {\n return this.CategoryColors[category || 'Other'] || this.CategoryColors['Other'];\n }\n\n /**\n * Get count of total scopes\n */\n public getTotalCount(): number {\n return this.FlatScopes.length;\n }\n\n /**\n * Get count of active scopes\n */\n public getActiveCount(): number {\n return this.FlatScopes.filter(s => s.IsActive).length;\n }\n}\n","<div class=\"scopes-panel\">\n @if (IsLoading) {\n <mj-loading text=\"Loading scopes...\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-left\">\n <h3 class=\"panel-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n API Scopes\n </h3>\n <p class=\"panel-subtitle\">Manage hierarchical permission scopes for API access</p>\n </div>\n <div class=\"header-actions\">\n <div class=\"scope-stats\">\n <span class=\"stat\">\n <i class=\"fa-solid fa-shield\"></i>\n {{getTotalCount()}} total\n </span>\n <span class=\"stat active\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{getActiveCount()}} active\n </span>\n </div>\n <div class=\"tree-controls\">\n <button class=\"btn-icon\" (click)=\"expandAll()\" title=\"Expand All\">\n <i class=\"fa-solid fa-plus-square\"></i>\n </button>\n <button class=\"btn-icon\" (click)=\"collapseAll()\" title=\"Collapse All\">\n <i class=\"fa-solid fa-minus-square\"></i>\n </button>\n </div>\n <button class=\"btn-create\" (click)=\"openCreateDialog()\">\n <i class=\"fa-solid fa-plus\"></i>\n New Scope\n </button>\n </div>\n </div>\n <!-- Messages -->\n @if (SuccessMessage) {\n <div class=\"message success\">\n <i class=\"fa-solid fa-check-circle\"></i>\n {{SuccessMessage}}\n </div>\n }\n @if (ErrorMessage) {\n <div class=\"message error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n {{ErrorMessage}}\n </div>\n }\n <!-- Scope Tree -->\n <div class=\"scope-tree\">\n @for (node of ScopeTree; track node) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: node }\"></ng-container>\n }\n <!-- Empty State -->\n @if (ScopeTree.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>No scopes configured</span>\n <p>Create scopes to define API access permissions</p>\n </div>\n }\n </div>\n <!-- Recursive Node Template -->\n <ng-template #scopeNode let-node=\"node\">\n <div class=\"scope-node\" [style.padding-left.px]=\"node.level * 24\">\n <div class=\"node-content\" [class.inactive]=\"!node.scope.IsActive\">\n @if (node.children.length > 0) {\n <button class=\"expand-btn\"\n (click)=\"toggleExpanded(node)\">\n <i class=\"fa-solid\"\n [class.fa-chevron-right]=\"!node.expanded\"\n [class.fa-chevron-down]=\"node.expanded\"></i>\n </button>\n }\n @if (node.children.length === 0) {\n <span class=\"expand-placeholder\"></span>\n }\n <div class=\"scope-info\" (click)=\"openEditDialog(node.scope)\">\n <div class=\"scope-icon\" [style.backgroundColor]=\"getCategoryColor(node.scope.Category)\">\n <i class=\"fa-solid fa-shield\"></i>\n </div>\n <div class=\"scope-details\">\n <div class=\"scope-name\">\n {{node.scope.Name}}\n @if (node.scope.FullPath && node.scope.FullPath !== node.scope.Name) {\n <span class=\"full-path\">\n {{node.scope.FullPath}}\n </span>\n }\n @if (!node.scope.IsActive) {\n <span class=\"status-badge\">Inactive</span>\n }\n </div>\n <div class=\"scope-meta\">\n <span class=\"category\" [style.color]=\"getCategoryColor(node.scope.Category)\">\n {{node.scope.Category}}\n </span>\n @if (node.scope.ResourceType) {\n <span class=\"resource-type\">\n {{node.scope.ResourceType}}\n </span>\n }\n @if (node.scope.Description) {\n <span class=\"description\">\n {{node.scope.Description}}\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"node-actions\">\n <button class=\"btn-node-action\" (click)=\"openCreateDialog(node.scope)\" title=\"Add Child Scope\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n <button class=\"btn-node-action\" (click)=\"openEditDialog(node.scope)\" title=\"Edit Scope\">\n <i class=\"fa-solid fa-pencil\"></i>\n </button>\n </div>\n </div>\n @if (node.expanded && node.children.length > 0) {\n <div class=\"children\">\n @for (child of node.children; track child) {\n <ng-container *ngTemplateOutlet=\"scopeNode; context: { node: child }\"></ng-container>\n }\n </div>\n }\n </div>\n </ng-template>\n }\n\n <!-- Create/Edit Dialog -->\n @if (ShowCreateDialog || ShowEditDialog) {\n <kendo-window\n [width]=\"560\"\n [minWidth]=\"420\"\n [minHeight]=\"480\"\n [resizable]=\"true\"\n [draggable]=\"true\"\n [top]=\"80\"\n (close)=\"closeDialogs()\">\n <kendo-window-titlebar>\n <div class=\"dialog-title\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>{{EditingScope ? 'Edit Scope' : 'New Scope'}}</span>\n </div>\n <button kendoButton fillMode=\"flat\" (click)=\"closeDialogs()\" class=\"window-close-btn\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </kendo-window-titlebar>\n <div class=\"dialog-content\">\n <div class=\"form-field\">\n <label>Scope Name *</label>\n <input kendoTextBox [(ngModel)]=\"EditName\"\n placeholder=\"e.g., runview, create, execute\"\n class=\"form-input\" />\n <span class=\"field-hint\">Use lowercase, single word. Will be combined with parent for full path.</span>\n </div>\n <div class=\"form-field\">\n <label>Parent Scope</label>\n <kendo-dropdownlist [(ngModel)]=\"EditParentId\"\n [data]=\"getParentOptions()\"\n [textField]=\"'FullPath'\"\n [valueField]=\"'ID'\"\n [valuePrimitive]=\"true\"\n [defaultItem]=\"{ FullPath: '(No Parent - Root Level)', ID: null }\">\n </kendo-dropdownlist>\n @if (SelectedParentScope) {\n <span class=\"field-hint\">\n Full path will be: <code>{{SelectedParentScope.FullPath}}:{{EditName || '...'}}</code>\n </span>\n }\n </div>\n <div class=\"form-row\">\n <div class=\"form-field half\">\n <label>Category</label>\n <kendo-dropdownlist [(ngModel)]=\"EditCategory\"\n [data]=\"Categories\"\n [valuePrimitive]=\"true\">\n </kendo-dropdownlist>\n </div>\n <div class=\"form-field half\">\n <label>Resource Type</label>\n <kendo-dropdownlist [(ngModel)]=\"EditResourceType\"\n [data]=\"ResourceTypes\"\n [valuePrimitive]=\"true\"\n [defaultItem]=\"''\">\n </kendo-dropdownlist>\n </div>\n </div>\n <div class=\"form-field\">\n <label>Description</label>\n <textarea kendoTextArea [(ngModel)]=\"EditDescription\"\n placeholder=\"Describe what this scope allows...\"\n [rows]=\"3\"\n class=\"form-textarea\"></textarea>\n </div>\n <div class=\"form-field\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" kendoCheckBox [(ngModel)]=\"EditIsActive\" />\n <div>\n <span>Active</span>\n <span class=\"checkbox-hint\">Inactive scopes cannot be assigned to keys or applications</span>\n </div>\n </label>\n </div>\n <div class=\"dialog-actions\">\n <button kendoButton [themeColor]=\"'primary'\"\n [disabled]=\"!EditName.trim() || IsSaving\"\n (click)=\"saveScope()\">\n @if (IsSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n }\n @if (!IsSaving) {\n <span>\n <i class=\"fa-solid fa-save\"></i>\n {{EditingScope ? 'Update' : 'Create'}}\n </span>\n }\n </button>\n <button kendoButton (click)=\"closeDialogs()\">Cancel</button>\n </div>\n </div>\n </kendo-window>\n }\n</div>\n"]}
|
|
@@ -6,7 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
import { Component } from '@angular/core';
|
|
8
8
|
import { CompositeKey, RunView, LogError } from '@memberjunction/core';
|
|
9
|
-
import { RegisterClass } from '@memberjunction/global';
|
|
9
|
+
import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
|
|
10
10
|
import { BaseResourceComponent } from '@memberjunction/ng-shared';
|
|
11
11
|
import { Subject, BehaviorSubject, combineLatest } from 'rxjs';
|
|
12
12
|
import { debounceTime, takeUntil, distinctUntilChanged } from 'rxjs/operators';
|
|
@@ -339,8 +339,8 @@ let ActionsOverviewComponent = class ActionsOverviewComponent extends BaseResour
|
|
|
339
339
|
}
|
|
340
340
|
calculateCategoryStats(actions, categories, executions) {
|
|
341
341
|
this.categoryStats = categories.map(category => {
|
|
342
|
-
const categoryActions = actions.filter(a => a.CategoryID
|
|
343
|
-
const categoryExecutions = executions.filter(e => categoryActions.some(a => a.ID
|
|
342
|
+
const categoryActions = actions.filter(a => UUIDsEqual(a.CategoryID, category.ID));
|
|
343
|
+
const categoryExecutions = executions.filter(e => categoryActions.some(a => UUIDsEqual(a.ID, e.ActionID)));
|
|
344
344
|
return {
|
|
345
345
|
categoryId: category.ID,
|
|
346
346
|
categoryName: category.Name,
|