@memberjunction/ng-explorer-settings 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.
Files changed (22) hide show
  1. package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts.map +1 -1
  2. package/dist/lib/application-management/application-dialog/application-dialog.component.js +6 -5
  3. package/dist/lib/application-management/application-dialog/application-dialog.component.js.map +1 -1
  4. package/dist/lib/application-management/application-management.component.js +2 -2
  5. package/dist/lib/application-management/application-management.component.js.map +1 -1
  6. package/dist/lib/application-settings/application-settings.component.d.ts.map +1 -1
  7. package/dist/lib/application-settings/application-settings.component.js +3 -2
  8. package/dist/lib/application-settings/application-settings.component.js.map +1 -1
  9. package/dist/lib/entity-permissions/entity-permissions.component.js +2 -2
  10. package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -1
  11. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts.map +1 -1
  12. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js +6 -5
  13. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js.map +1 -1
  14. package/dist/lib/notification-preferences/notification-preferences.component.d.ts.map +1 -1
  15. package/dist/lib/notification-preferences/notification-preferences.component.js +3 -2
  16. package/dist/lib/notification-preferences/notification-preferences.component.js.map +1 -1
  17. package/dist/lib/user-app-config/user-app-config.component.d.ts.map +1 -1
  18. package/dist/lib/user-app-config/user-app-config.component.js +3 -2
  19. package/dist/lib/user-app-config/user-app-config.component.js.map +1 -1
  20. package/dist/lib/user-management/user-management.component.js +2 -2
  21. package/dist/lib/user-management/user-management.component.js.map +1 -1
  22. package/package.json +17 -17
@@ -1 +1 @@
1
- {"version":3,"file":"permission-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/entity-permissions/permission-dialog/permission-dialog.component.ts","../../../../src/lib/entity-permissions/permission-dialog/permission-dialog.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAA+C,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAExL,OAAO,EAAoC,WAAW,EAAa,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAW,MAAM,sBAAsB,CAAC;;;;;;;;ICqB3C,AADF,+BAA6B,cACI;IAC7B,wBAAgD;IAChD,2BAAK;IAAA,YAAW;IAEpB,AADE,AADkB,iBAAM,EAClB,EACF;;;IAFG,eAAW;IAAX,kCAAW;;;IAkFF,gCAAwB;IAAA,mBAAG;IAAA,iBAAO;;;IAGlC,gCAA4B;IAAA,wBAAQ;IAAA,iBAAO;;;;IAP/C,AADF,AADF,8BAAwH,aAChG,cACG;IACrB,wBAAyC;IACzC,4BAAM;IAAA,YAA6B;IAAA,iBAAO;IAC1C,kHAA4B;IAG5B,kHAAiE;IAIrE,AADE,iBAAM,EACH;IAGD,AADF,AADF,8BAA4B,cACK,iBAOzB;IAHF,oXAAuD;IAHzD,iBAMI;IACJ,kCAA0E;IACxE,2BAAsC;IAG5C,AADE,AADE,iBAAQ,EACJ,EACH;IAGD,AADF,AADF,+BAA4B,eACK,iBAOzB;IAHF,gXAAqD;IAHvD,iBAMI;IACJ,kCAAwE;IACtE,2BAAsC;IAG5C,AADE,AADE,iBAAQ,EACJ,EACH;IAGD,AADF,AADF,+BAA4B,eACK,iBAOzB;IAHF,oXAAuD;IAHzD,iBAMI;IACJ,kCAA0E;IACxE,2BAAsC;IAG5C,AADE,AADE,iBAAQ,EACJ,EACH;IAGD,AADF,AADF,+BAA4B,eACK,iBAOzB;IAHF,oXAAuD;IAHzD,iBAMI;IACJ,kCAA0E;IACxE,2BAAsC;IAG5C,AADE,AADE,iBAAQ,EACJ,EACH;IAEH,AADF,+BAAyB,kBAOpB;IAHD,0OAAS,8CAAoC,KAAC;IAI9C,wBAAiC;IAGvC,AADE,AADE,iBAAS,EACN,EACF;;;;IAhF6E,AAAvD,yEAAsD,mCAAsC;IAI3G,eAA6B;IAA7B,gDAA6B;IACnC,cAEC;IAFD,kDAEC;IACD,cAEC;IAFD,iGAEC;IAOC,eAAwC;IAAxC,yDAAwC;IACxC,4EAAuD;IACvD,4DAAqC;IAGhC,cAAyC;IAAzC,0DAAyC;IAS9C,eAAsC;IAAtC,uDAAsC;IACtC,0EAAqD;IACrD,4DAAqC;IAGhC,cAAuC;IAAvC,wDAAuC;IAS5C,eAAwC;IAAxC,yDAAwC;IACxC,4EAAuD;IACvD,4DAAqC;IAGhC,cAAyC;IAAzC,0DAAyC;IAS9C,eAAwC;IAAxC,yDAAwC;IACxC,4EAAuD;IACvD,4DAAqC;IAGhC,cAAyC;IAAzC,0DAAyC;IAWhD,eAAsE;iCAAtE,wEAAsE;;;IAUhF,+BAA+B;IAC7B,wBAAyC;IACzC,yBAAG;IAAA,8CAA8B;IAAA,iBAAI;IACrC,6BAAyB;IAAA,mFAAmE;IAC9F,AAD8F,iBAAI,EAC5F;;;;IAWJ,kCAMG;IAHD,+NAAS,iCAAuB,KAAC;IAIjC,wBAAgC;IAChC,YACF;IAAA,iBAAS;;;iCAJP,uDAAqD;IADrD,uBAAA,uDAA2C,CAAA;IAI3C,eACF;IADE,6CACF;;;IAGA,6BAA8B;IAAA,8CAA8B;IAAA,iBAAI;;;IAUpE,gCAAgC;IAC9B,wBAAgD;IAChD,0CACF;IAAA,iBAAO;;;IAUL,wBAA2C;IAC3C,2BACF;;;IACE,wBAAgC;IAChC,kCACF;;;;IAhPd,8BAAiD;IAArB,0LAAS,iBAAU,KAAC;IAC9C,8BAA6D;IAAnC,6JAAS,wBAAwB,KAAC;IAItD,AADF,AADF,8BAA0B,aACG,YACA;IACvB,uBAA+B;IAC/B,yCACF;IAAA,iBAAK;IACL,4BAA2B;IACzB,YACF;IACF,AADE,iBAAI,EACA;IACN,iCAAyF;IAA/C,6LAAS,iBAAU,KAAC;IAC5D,wBAAiC;IAErC,AADE,iBAAS,EACL;IAGJ,AADF,gCAAwB,gBACqC;IAAxB,kMAAY,iBAAU,KAAC;IACxD,4GAAa;IAYP,AADF,AADF,AADF,gCAA6B,eACD,eACI,cACA;IACxB,yBAAoC;IACpC,qCACF;IAAA,iBAAK;IACL,8BAA+B;IAAA,aAAqE;IACtG,AADsG,iBAAI,EACpG;IAGF,AADF,AADF,gCAA8B,eACH,eACA;IACrB,yBAAiC;IACjC,iCAAyB;IAAA,wBAAO;IAAA,iBAAO;IACvC,iCAAyB;IAAA,aAAwB;IACnD,AADmD,iBAAO,EACpD;IACN,gCAAuB;IACrB,yBAAyC;IACzC,iCAAyB;IAAA,6BAAY;IAAA,iBAAO;IAC5C,iCAAyB;IAAA,aAAuC;IAClE,AADkE,iBAAO,EACnE;IACN,gCAAuB;IACrB,wBAA+B;IAC/B,iCAAyB;IAAA,mCAAkB;IAAA,iBAAO;IAClD,iCAAyB;IAAA,aAA4B;IACvD,AADuD,iBAAO,EACxD;IACN,gCAAuB;IACrB,yBAAiC;IACjC,iCAAyB;IAAA,8BAAa;IAAA,iBAAO;IAC7C,iCAAyB;IAAA,aAAkD;;IAKrF,AADE,AADE,AADE,AADE,AAD6E,iBAAO,EAC9E,EACF,EACF,EACF,EACF;IAKA,AADF,AADF,AADF,gCAA6B,eACD,eACI,cACA;IACxB,yBAAqC;IACrC,mCACF;IAAA,iBAAK;IACL,8BAA+B;IAAA,yDAAwC;IACzE,AADyE,iBAAI,EACvE;IAKE,AADF,AADF,AADF,AADF,gCAAyC,iBACN,aACxB,UACD,cACsB;IAAA,qBAAI;IAAA,iBAAK;IACjC,+BAA8B;IAC5B,yBAAgC;IAChC,yBACF;IAAA,iBAAK;IACL,+BAA8B;IAC5B,yBAA+B;IAC/B,uBACF;IAAA,iBAAK;IACL,+BAA8B;IAC5B,yBAAgC;IAChC,yBACF;IAAA,iBAAK;IACL,+BAA8B;IAC5B,yBAAiC;IACjC,yBACF;IAAA,iBAAK;IACL,+BAA2B;IAAA,wBAAO;IAEtC,AADE,AADoC,iBAAK,EACpC,EACC;IACR,8BAAO;IACL,8GAkFC;IAEL,AADE,iBAAQ,EACF;IACR,4GAAoC;IAOtC,iBAAM;IAIF,AADF,AADF,gCAA8B,eACC,UACvB;IAAA,qCAAoB;IAAA,iBAAK;IAC7B,0BAAG;IAAA,sEAAqD;IAC1D,AAD0D,iBAAI,EACxD;IACN,gCAA6B;IAC3B,gHAWC;IACD,0GAAmC;IAM3C,AADE,AADE,AADE,iBAAM,EACF,EACF,EACF;IAGJ,AADF,gCAA0B,eACC;IACvB,6GAAkB;IAMpB,iBAAM;IAEJ,AADF,gCAA4B,kBAKvB;IAIC,AAHF,iGAAiB,2EAGR;IAIX,iBAAS;IACT,mCAAqE;IAArB,8LAAS,iBAAU,KAAC;IAClE,wBAAiC;IACjC,0BACF;IAMZ,AADE,AADE,AADE,AADE,AADE,AADE,iBAAS,EACL,EACF,EACD,EACH,EACF,EACF;;;IAjPI,eACF;IADE,8JACF;IAQI,eAA4B;IAA5B,iDAA4B;IAChC,cAOC;IAPD,wCAOC;IASoC,eAAqE;IAArE,6JAAqE;IAOvE,eAAwB;IAAxB,8GAAwB;IAKxB,eAAuC;IAAvC,+HAAuC;IAKvC,eAA4B;IAA5B,mDAA4B;IAK5B,eAAkD;IAAlD,0JAAkD;IAyC3E,gBAkFC;IAlFD,qCAkFC;IAGL,eAMC;IAND,+DAMC;IASC,eAWC;IAXD,oCAWC;IACD,eAEC;IAFD,8DAEC;IAQL,eAKC;IALD,6CAKC;IAMC,eAAqC;IAArC,iEAAqC;IAErC,cAMC;IAND,4CAMC;;ADnNjB,MAAM,OAAO,yBAAyB;IAC3B,IAAI,GAAgC,IAAI,CAAC;IACzC,OAAO,GAAG,KAAK,CAAC;IACf,MAAM,GAAG,IAAI,YAAY,EAA0B,CAAC;IAEtD,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACzB,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAChC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACxB,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAE3B,cAAc,CAAY;IAC1B,SAAS,GAAG,KAAK,CAAC;IAClB,KAAK,GAAkB,IAAI,CAAC;IAC5B,eAAe,GAAsB,EAAE,CAAC;IACxC,cAAc,GAAmB,EAAE,CAAC;IAE3C;QACE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,QAAQ;QACN,gBAAgB;IAClB,CAAC;IAED,WAAW,CAAC,OAAsB;QAChC,OAAO,CAAC,GAAG,CAAC,uCAAuC,EAAE,OAAO,CAAC,CAAC;QAE9D,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,yDAAyD;YACzD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;gBAC9D,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjD,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;YAC/E,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,WAAW;QACT,oBAAoB;IACtB,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;IAGD,WAAW,CAAC,KAAY;QACtB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,IAAW,UAAU;QACnB,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAChF,CAAC;IAEM,gBAAgB,CAAC,cAA+B;QACrD,OAAO,cAAc,CAAC,KAAK,IAAI,cAAc,CAAC,gBAAgB,CAAC,KAAK,CAAC;IACvE,CAAC;IAEO,kBAAkB;QACxB,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO;QAEvB,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEjD,iDAAiD;QACjD,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;QAE1C,+BAA+B;QAC/B,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACvD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,MAAM,CAAC,CAAC;YACnE,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,CAAC,GAAG,CAAC,kCAAkC,IAAI,CAAC,IAAI,GAAG,EAAE;oBAC1D,SAAS,EAAE,UAAU,CAAC,SAAS;oBAC/B,OAAO,EAAE,UAAU,CAAC,OAAO;oBAC3B,SAAS,EAAE,UAAU,CAAC,SAAS;oBAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;iBAChC,CAAC,CAAC;gBAEH,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;oBACxB,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;oBACzB,gBAAgB,EAAE,UAAU;oBAC5B,KAAK,EAAE,KAAK;iBACb,CAAC,CAAC;gBACH,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAE9D,qDAAqD;QACrD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAEpF,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAEjF,4CAA4C;QAC5C,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,IAAkB;QAC/C,qCAAqC;QACrC,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAA2B,wBAAwB,CAAC,CAAC;QACjH,gBAAgB,CAAC,SAAS,EAAE,CAAC;QAC7B,gBAAgB,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACjD,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;QAClC,gBAAgB,CAAC,SAAS,GAAG,KAAK,CAAC;QACnC,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,yBAAyB;QAC1D,gBAAgB,CAAC,SAAS,GAAG,KAAK,CAAC;QACnC,gBAAgB,CAAC,SAAS,GAAG,KAAK,CAAC;QAEnC,0BAA0B;QAC1B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;YACxB,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;YACzB,gBAAgB,EAAE,gBAAgB;YAClC,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,8BAA8B;QAC9B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAEM,oBAAoB,CAAC,cAA+B;QACzD,yCAAyC;QACzC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,cAAc,CAAC,MAAM,CAAC,CAAC;YACxE,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;aAAM,CAAC;YACN,8BAA8B;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,cAAc,CAAC,MAAM,CAAC,CAAC;YACxE,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9F,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,QAAQ;QACnB,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAE3C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAElB,IAAI,CAAC;YACH,+BAA+B;YAC/B,KAAK,MAAM,cAAc,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBAClD,IAAI,cAAc,CAAC,KAAK,IAAI,cAAc,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;oBAClE,MAAM,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAEjE,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;gBACnB,IAAI,CAAC,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uDAAuD,CAAC;gBAC9G,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC1B,CAAC,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;gBACnB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;gBACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC1B,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,cAA+B;QAC9D,iEAAiE;QACjE,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAChE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,YAAY,EAAE,OAAO,IAAI,uCAAuC,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC7I,CAAC;IACH,CAAC;IAEM,QAAQ;QACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzC,CAAC;mHAnMU,yBAAyB;6DAAzB,yBAAyB;YAAzB,sHAAA,uBAAmB,0BAAM;;YC9BtC,8FAAe;;YAAf,sCA6PC;;;iFD/NY,yBAAyB;cAPrC,SAAS;6BACI,KAAK,YACP,sBAAsB,iBACjB,iBAAiB,CAAC,IAAI;;kBAKpC,KAAK;;kBACL,KAAK;;kBACL,MAAM;;kBAgDN,YAAY;mBAAC,yBAAyB,EAAE,CAAC,QAAQ,CAAC;;kFAnDxC,yBAAyB","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges, SimpleChanges, inject, HostListener, ChangeDetectorRef, NgZone, ViewEncapsulation } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule, ReactiveFormsModule, FormBuilder, FormGroup } from '@angular/forms';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJEntityPermissionEntity, MJEntityEntity, MJRoleEntity } from '@memberjunction/core-entities';\n\nexport interface PermissionDialogData {\n entity: MJEntityEntity;\n roles: MJRoleEntity[];\n existingPermissions: MJEntityPermissionEntity[];\n}\n\nexport interface PermissionDialogResult {\n action: 'save' | 'cancel';\n entity?: MJEntityEntity;\n}\n\ninterface RolePermissions {\n roleId: string;\n roleName: string;\n entityPermission: MJEntityPermissionEntity;\n isNew: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-permission-dialog',\n encapsulation: ViewEncapsulation.None,\n templateUrl: './permission-dialog.component.html',\n styleUrls: ['./permission-dialog.component.css']\n})\nexport class PermissionDialogComponent implements OnInit, OnDestroy, OnChanges {\n @Input() data: PermissionDialogData | null = null;\n @Input() visible = false;\n @Output() result = new EventEmitter<PermissionDialogResult>();\n\n private fb = inject(FormBuilder);\n private cdr = inject(ChangeDetectorRef);\n private ngZone = inject(NgZone);\n private metadata = new Metadata();\n\n public permissionForm: FormGroup;\n public isLoading = false;\n public error: string | null = null;\n public rolePermissions: RolePermissions[] = [];\n public availableRoles: MJRoleEntity[] = [];\n\n constructor() {\n this.permissionForm = this.fb.group({});\n }\n\n ngOnInit(): void {\n // Initial setup\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n console.log('Permission dialog ngOnChanges called:', changes);\n \n if (changes['visible'] && this.visible) {\n this.resetDialog();\n // Load data when dialog becomes visible and we have data\n if (this.data) {\n console.log('Dialog became visible, loading permission data');\n this.loadPermissionData();\n }\n }\n \n if (changes['data'] && this.data && this.visible) {\n console.log('Data changed while dialog is visible, reloading permission data');\n this.loadPermissionData();\n }\n }\n\n ngOnDestroy(): void {\n // Cleanup if needed\n }\n\n private resetDialog(): void {\n this.error = null;\n this.isLoading = false;\n }\n\n @HostListener('document:keydown.escape', ['$event'])\n onEscapeKey(event: Event): void {\n if (this.visible) {\n this.onCancel();\n }\n }\n\n public get hasChanges(): boolean {\n return this.rolePermissions.some(rp => rp.isNew || rp.entityPermission.Dirty);\n }\n\n public hasEntityChanges(rolePermission: RolePermissions): boolean {\n return rolePermission.isNew || rolePermission.entityPermission.Dirty;\n }\n\n private loadPermissionData(): void {\n if (!this.data) return;\n\n console.log('Loading permission data for entity:', this.data.entity.Name);\n console.log('Existing permissions:', this.data.existingPermissions);\n console.log('Available roles:', this.data.roles);\n\n // Initialize role permissions from existing data\n this.rolePermissions = [];\n const existingRoleIds = new Set<string>();\n\n // Process existing permissions\n for (const permission of this.data.existingPermissions) {\n const role = this.data.roles.find(r => r.ID === permission.RoleID);\n if (role) {\n console.log(`Processing permission for role ${role.Name}:`, {\n canCreate: permission.CanCreate,\n canRead: permission.CanRead,\n canUpdate: permission.CanUpdate,\n canDelete: permission.CanDelete\n });\n \n this.rolePermissions.push({\n roleId: role.ID,\n roleName: role.Name || '',\n entityPermission: permission,\n isNew: false\n });\n existingRoleIds.add(role.ID);\n }\n }\n\n console.log('Loaded role permissions:', this.rolePermissions);\n\n // Set available roles (those not already configured)\n this.availableRoles = this.data.roles.filter(role => !existingRoleIds.has(role.ID));\n \n console.log('Available roles for adding:', this.availableRoles.map(r => r.Name));\n \n // Trigger change detection to update the UI\n this.cdr.detectChanges();\n }\n\n public async addRolePermission(role: MJRoleEntity): Promise<void> {\n // Create new EntityPermission entity\n const entityPermission = await this.metadata.GetEntityObject<MJEntityPermissionEntity>('MJ: Entity Permissions');\n entityPermission.NewRecord();\n entityPermission.EntityID = this.data!.entity.ID;\n entityPermission.RoleID = role.ID;\n entityPermission.CanCreate = false;\n entityPermission.CanRead = true; // Default to read access\n entityPermission.CanUpdate = false;\n entityPermission.CanDelete = false;\n\n // Add new role permission\n this.rolePermissions.push({\n roleId: role.ID,\n roleName: role.Name || '',\n entityPermission: entityPermission,\n isNew: true\n });\n\n // Remove from available roles\n this.availableRoles = this.availableRoles.filter(r => r.ID !== role.ID);\n this.cdr.detectChanges();\n }\n\n public removeRolePermission(rolePermission: RolePermissions): void {\n // Add back to available roles if not new\n if (!rolePermission.isNew) {\n const role = this.data?.roles.find(r => r.ID === rolePermission.roleId);\n if (role) {\n this.availableRoles.push(role);\n this.availableRoles.sort((a, b) => (a.Name || '').localeCompare(b.Name || ''));\n }\n } else {\n // Add back to available roles\n const role = this.data?.roles.find(r => r.ID === rolePermission.roleId);\n if (role) {\n this.availableRoles.push(role);\n this.availableRoles.sort((a, b) => (a.Name || '').localeCompare(b.Name || ''));\n }\n }\n\n // Remove from role permissions\n this.rolePermissions = this.rolePermissions.filter(rp => rp.roleId !== rolePermission.roleId);\n this.cdr.detectChanges();\n }\n\n public async onSubmit(): Promise<void> {\n if (!this.data || !this.hasChanges) return;\n\n this.isLoading = true;\n this.error = null;\n\n try {\n // Process each role permission\n for (const rolePermission of this.rolePermissions) {\n if (rolePermission.isNew || rolePermission.entityPermission.Dirty) {\n await this.saveRolePermission(rolePermission);\n }\n }\n\n this.result.emit({ action: 'save', entity: this.data.entity });\n\n } catch (error: unknown) {\n console.error('Error saving permissions:', error);\n this.ngZone.run(() => {\n this.error = error instanceof Error ? error.message : 'An unexpected error occurred while saving permissions';\n this.cdr.markForCheck();\n });\n } finally {\n this.ngZone.run(() => {\n this.isLoading = false;\n this.cdr.markForCheck();\n });\n }\n }\n\n private async saveRolePermission(rolePermission: RolePermissions): Promise<void> {\n // Save the entity directly - it already has all the values bound\n const saveResult = await rolePermission.entityPermission.Save();\n if (!saveResult) {\n throw new Error(rolePermission.entityPermission.LatestResult?.Message || `Failed to save permissions for role ${rolePermission.roleName}`);\n }\n }\n\n public onCancel(): void {\n this.result.emit({ action: 'cancel' });\n }\n}","<!-- MD3 Modal Dialog -->\n@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <!-- Modal Header -->\n <div class=\"modal-header\">\n <div class=\"dialog-header\">\n <h2 class=\"dialog-title\">\n <i class=\"fa-solid fa-key\"></i>\n Edit Entity Permissions\n </h2>\n <p class=\"dialog-subtitle\">\n Configure role-based permissions for {{ data?.entity?.Name }}\n </p>\n </div>\n <button type=\"button\" class=\"modal-close\" (click)=\"onCancel()\" aria-label=\"Close dialog\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"permissionForm\" (ngSubmit)=\"onSubmit()\">\n @if (error) {\n <div class=\"content-section\">\n <div class=\"alert alert-error\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <div>{{ error }}</div>\n </div>\n </div>\n }\n <!-- Entity Information Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-database\"></i>\n Entity Information\n </h3>\n <p class=\"section-description\">{{ data?.entity?.Description || 'Entity permissions configuration' }}</p>\n </div>\n <div class=\"entity-info-card\">\n <div class=\"entity-meta\">\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-table\"></i>\n <span class=\"meta-label\">Entity:</span>\n <span class=\"meta-value\">{{ data?.entity?.Name }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span class=\"meta-label\">Schema Name:</span>\n <span class=\"meta-value\">{{ data?.entity?.SchemaName || 'N/A' }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-key\"></i>\n <span class=\"meta-label\">Total Permissions:</span>\n <span class=\"meta-value\">{{ rolePermissions.length }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-clock\"></i>\n <span class=\"meta-label\">Last Updated:</span>\n <span class=\"meta-value\">{{ data?.entity?.__mj_UpdatedAt | date:'medium' }}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n <!-- Permissions Configuration Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-users-cog\"></i>\n Role Permissions\n </h3>\n <p class=\"section-description\">Configure CRUD permissions for each role</p>\n </div>\n <div class=\"permissions-table-container\">\n <table class=\"permissions-table\">\n <thead>\n <tr>\n <th class=\"role-column\">Role</th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-plus\"></i>\n Create\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-eye\"></i>\n Read\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-edit\"></i>\n Update\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-trash\"></i>\n Delete\n </th>\n <th class=\"actions-column\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (rolePermission of rolePermissions; track rolePermission.roleId) {\n <tr class=\"permission-row\" [class.has-changes]=\"hasEntityChanges(rolePermission)\" [class.is-new]=\"rolePermission.isNew\">\n <td class=\"role-name\">\n <div class=\"role-info\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>{{ rolePermission.roleName }}</span>\n @if (rolePermission.isNew) {\n <span class=\"new-badge\">New</span>\n }\n @if (hasEntityChanges(rolePermission) && !rolePermission.isNew) {\n <span class=\"changed-badge\">Modified</span>\n }\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'create-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanCreate\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'create-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'read-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanRead\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'read-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'update-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanUpdate\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'update-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'delete-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanDelete\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'delete-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"actions-cell\">\n <button\n type=\"button\"\n class=\"btn-icon btn-danger\"\n (click)=\"removeRolePermission(rolePermission)\"\n title=\"Remove permissions for this role\"\n attr.aria-label=\"Remove permissions for {{ rolePermission.roleName }}\"\n >\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n @if (rolePermissions.length === 0) {\n <div class=\"empty-permissions\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <p>No role permissions configured</p>\n <p class=\"empty-subtext\">Add permissions for specific roles to control access to this entity</p>\n </div>\n }\n </div>\n <!-- Add Role Permissions -->\n <div class=\"add-role-section\">\n <div class=\"add-role-header\">\n <h4>Add Role Permissions</h4>\n <p>Select roles to configure permissions for this entity</p>\n </div>\n <div class=\"available-roles\">\n @for (role of availableRoles; track role.ID) {\n <button\n type=\"button\"\n class=\"role-chip\"\n (click)=\"addRolePermission(role)\"\n title=\"Add permissions for {{ role.Name }}\"\n attr.aria-label=\"Add permissions for {{ role.Name }}\"\n >\n <i class=\"fa-solid fa-plus\"></i>\n {{ role.Name }}\n </button>\n }\n @if (availableRoles.length === 0) {\n <p class=\"no-available-roles\">All roles have been configured</p>\n }\n </div>\n </div>\n </div>\n </div>\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n <div class=\"footer-info\">\n @if (hasChanges) {\n <span class=\"changes-indicator\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n You have unsaved changes\n </span>\n }\n </div>\n <div class=\"footer-actions\">\n <button\n type=\"submit\"\n class=\"btn btn-primary\"\n [disabled]=\"!hasChanges || isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n Save Permissions\n }\n </button>\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"onCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n Cancel\n </button>\n </div>\n </div>\n </form>\n </div>\n </div>\n </div>\n}\n"]}
1
+ {"version":3,"file":"permission-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/entity-permissions/permission-dialog/permission-dialog.component.ts","../../../../src/lib/entity-permissions/permission-dialog/permission-dialog.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAA+C,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAExL,OAAO,EAAoC,WAAW,EAAa,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAW,MAAM,sBAAsB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;;;;;;;;ICmBtC,AADF,+BAA6B,cACI;IAC7B,wBAAgD;IAChD,2BAAK;IAAA,YAAW;IAEpB,AADE,AADkB,iBAAM,EAClB,EACF;;;IAFG,eAAW;IAAX,kCAAW;;;IAkFF,gCAAwB;IAAA,mBAAG;IAAA,iBAAO;;;IAGlC,gCAA4B;IAAA,wBAAQ;IAAA,iBAAO;;;;IAP/C,AADF,AADF,8BAAwH,aAChG,cACG;IACrB,wBAAyC;IACzC,4BAAM;IAAA,YAA6B;IAAA,iBAAO;IAC1C,kHAA4B;IAG5B,kHAAiE;IAIrE,AADE,iBAAM,EACH;IAGD,AADF,AADF,8BAA4B,cACK,iBAOzB;IAHF,oXAAuD;IAHzD,iBAMI;IACJ,kCAA0E;IACxE,2BAAsC;IAG5C,AADE,AADE,iBAAQ,EACJ,EACH;IAGD,AADF,AADF,+BAA4B,eACK,iBAOzB;IAHF,gXAAqD;IAHvD,iBAMI;IACJ,kCAAwE;IACtE,2BAAsC;IAG5C,AADE,AADE,iBAAQ,EACJ,EACH;IAGD,AADF,AADF,+BAA4B,eACK,iBAOzB;IAHF,oXAAuD;IAHzD,iBAMI;IACJ,kCAA0E;IACxE,2BAAsC;IAG5C,AADE,AADE,iBAAQ,EACJ,EACH;IAGD,AADF,AADF,+BAA4B,eACK,iBAOzB;IAHF,oXAAuD;IAHzD,iBAMI;IACJ,kCAA0E;IACxE,2BAAsC;IAG5C,AADE,AADE,iBAAQ,EACJ,EACH;IAEH,AADF,+BAAyB,kBAOpB;IAHD,0OAAS,8CAAoC,KAAC;IAI9C,wBAAiC;IAGvC,AADE,AADE,iBAAS,EACN,EACF;;;;IAhF6E,AAAvD,yEAAsD,mCAAsC;IAI3G,eAA6B;IAA7B,gDAA6B;IACnC,cAEC;IAFD,kDAEC;IACD,cAEC;IAFD,iGAEC;IAOC,eAAwC;IAAxC,yDAAwC;IACxC,4EAAuD;IACvD,4DAAqC;IAGhC,cAAyC;IAAzC,0DAAyC;IAS9C,eAAsC;IAAtC,uDAAsC;IACtC,0EAAqD;IACrD,4DAAqC;IAGhC,cAAuC;IAAvC,wDAAuC;IAS5C,eAAwC;IAAxC,yDAAwC;IACxC,4EAAuD;IACvD,4DAAqC;IAGhC,cAAyC;IAAzC,0DAAyC;IAS9C,eAAwC;IAAxC,yDAAwC;IACxC,4EAAuD;IACvD,4DAAqC;IAGhC,cAAyC;IAAzC,0DAAyC;IAWhD,eAAsE;iCAAtE,wEAAsE;;;IAUhF,+BAA+B;IAC7B,wBAAyC;IACzC,yBAAG;IAAA,8CAA8B;IAAA,iBAAI;IACrC,6BAAyB;IAAA,mFAAmE;IAC9F,AAD8F,iBAAI,EAC5F;;;;IAWJ,kCAMG;IAHD,+NAAS,iCAAuB,KAAC;IAIjC,wBAAgC;IAChC,YACF;IAAA,iBAAS;;;iCAJP,uDAAqD;IADrD,uBAAA,uDAA2C,CAAA;IAI3C,eACF;IADE,6CACF;;;IAGA,6BAA8B;IAAA,8CAA8B;IAAA,iBAAI;;;IAUpE,gCAAgC;IAC9B,wBAAgD;IAChD,0CACF;IAAA,iBAAO;;;IAUL,wBAA2C;IAC3C,2BACF;;;IACE,wBAAgC;IAChC,kCACF;;;;IAhPd,8BAAiD;IAArB,0LAAS,iBAAU,KAAC;IAC9C,8BAA6D;IAAnC,6JAAS,wBAAwB,KAAC;IAItD,AADF,AADF,8BAA0B,aACG,YACA;IACvB,uBAA+B;IAC/B,yCACF;IAAA,iBAAK;IACL,4BAA2B;IACzB,YACF;IACF,AADE,iBAAI,EACA;IACN,iCAAyF;IAA/C,6LAAS,iBAAU,KAAC;IAC5D,wBAAiC;IAErC,AADE,iBAAS,EACL;IAGJ,AADF,gCAAwB,gBACqC;IAAxB,kMAAY,iBAAU,KAAC;IACxD,4GAAa;IAYP,AADF,AADF,AADF,gCAA6B,eACD,eACI,cACA;IACxB,yBAAoC;IACpC,qCACF;IAAA,iBAAK;IACL,8BAA+B;IAAA,aAAqE;IACtG,AADsG,iBAAI,EACpG;IAGF,AADF,AADF,gCAA8B,eACH,eACA;IACrB,yBAAiC;IACjC,iCAAyB;IAAA,wBAAO;IAAA,iBAAO;IACvC,iCAAyB;IAAA,aAAwB;IACnD,AADmD,iBAAO,EACpD;IACN,gCAAuB;IACrB,yBAAyC;IACzC,iCAAyB;IAAA,6BAAY;IAAA,iBAAO;IAC5C,iCAAyB;IAAA,aAAuC;IAClE,AADkE,iBAAO,EACnE;IACN,gCAAuB;IACrB,wBAA+B;IAC/B,iCAAyB;IAAA,mCAAkB;IAAA,iBAAO;IAClD,iCAAyB;IAAA,aAA4B;IACvD,AADuD,iBAAO,EACxD;IACN,gCAAuB;IACrB,yBAAiC;IACjC,iCAAyB;IAAA,8BAAa;IAAA,iBAAO;IAC7C,iCAAyB;IAAA,aAAkD;;IAKrF,AADE,AADE,AADE,AADE,AAD6E,iBAAO,EAC9E,EACF,EACF,EACF,EACF;IAKA,AADF,AADF,AADF,gCAA6B,eACD,eACI,cACA;IACxB,yBAAqC;IACrC,mCACF;IAAA,iBAAK;IACL,8BAA+B;IAAA,yDAAwC;IACzE,AADyE,iBAAI,EACvE;IAKE,AADF,AADF,AADF,AADF,gCAAyC,iBACN,aACxB,UACD,cACsB;IAAA,qBAAI;IAAA,iBAAK;IACjC,+BAA8B;IAC5B,yBAAgC;IAChC,yBACF;IAAA,iBAAK;IACL,+BAA8B;IAC5B,yBAA+B;IAC/B,uBACF;IAAA,iBAAK;IACL,+BAA8B;IAC5B,yBAAgC;IAChC,yBACF;IAAA,iBAAK;IACL,+BAA8B;IAC5B,yBAAiC;IACjC,yBACF;IAAA,iBAAK;IACL,+BAA2B;IAAA,wBAAO;IAEtC,AADE,AADoC,iBAAK,EACpC,EACC;IACR,8BAAO;IACL,8GAkFC;IAEL,AADE,iBAAQ,EACF;IACR,4GAAoC;IAOtC,iBAAM;IAIF,AADF,AADF,gCAA8B,eACC,UACvB;IAAA,qCAAoB;IAAA,iBAAK;IAC7B,0BAAG;IAAA,sEAAqD;IAC1D,AAD0D,iBAAI,EACxD;IACN,gCAA6B;IAC3B,gHAWC;IACD,0GAAmC;IAM3C,AADE,AADE,AADE,iBAAM,EACF,EACF,EACF;IAGJ,AADF,gCAA0B,eACC;IACvB,6GAAkB;IAMpB,iBAAM;IAEJ,AADF,gCAA4B,kBAKvB;IAIC,AAHF,iGAAiB,2EAGR;IAIX,iBAAS;IACT,mCAAqE;IAArB,8LAAS,iBAAU,KAAC;IAClE,wBAAiC;IACjC,0BACF;IAMZ,AADE,AADE,AADE,AADE,AADE,AADE,iBAAS,EACL,EACF,EACD,EACH,EACF,EACF;;;IAjPI,eACF;IADE,8JACF;IAQI,eAA4B;IAA5B,iDAA4B;IAChC,cAOC;IAPD,wCAOC;IASoC,eAAqE;IAArE,6JAAqE;IAOvE,eAAwB;IAAxB,8GAAwB;IAKxB,eAAuC;IAAvC,+HAAuC;IAKvC,eAA4B;IAA5B,mDAA4B;IAK5B,eAAkD;IAAlD,0JAAkD;IAyC3E,gBAkFC;IAlFD,qCAkFC;IAGL,eAMC;IAND,+DAMC;IASC,eAWC;IAXD,oCAWC;IACD,eAEC;IAFD,8DAEC;IAQL,eAKC;IALD,6CAKC;IAMC,eAAqC;IAArC,iEAAqC;IAErC,cAMC;IAND,4CAMC;;ADlNjB,MAAM,OAAO,yBAAyB;IAC3B,IAAI,GAAgC,IAAI,CAAC;IACzC,OAAO,GAAG,KAAK,CAAC;IACf,MAAM,GAAG,IAAI,YAAY,EAA0B,CAAC;IAEtD,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACzB,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAChC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACxB,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAE3B,cAAc,CAAY;IAC1B,SAAS,GAAG,KAAK,CAAC;IAClB,KAAK,GAAkB,IAAI,CAAC;IAC5B,eAAe,GAAsB,EAAE,CAAC;IACxC,cAAc,GAAmB,EAAE,CAAC;IAE3C;QACE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,QAAQ;QACN,gBAAgB;IAClB,CAAC;IAED,WAAW,CAAC,OAAsB;QAChC,OAAO,CAAC,GAAG,CAAC,uCAAuC,EAAE,OAAO,CAAC,CAAC;QAE9D,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,yDAAyD;YACzD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;gBAC9D,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjD,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;YAC/E,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,WAAW;QACT,oBAAoB;IACtB,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;IAGD,WAAW,CAAC,KAAY;QACtB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,IAAW,UAAU;QACnB,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAChF,CAAC;IAEM,gBAAgB,CAAC,cAA+B;QACrD,OAAO,cAAc,CAAC,KAAK,IAAI,cAAc,CAAC,gBAAgB,CAAC,KAAK,CAAC;IACvE,CAAC;IAEO,kBAAkB;QACxB,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO;QAEvB,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEjD,iDAAiD;QACjD,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;QAE1C,+BAA+B;QAC/B,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACvD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;YAC5E,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,CAAC,GAAG,CAAC,kCAAkC,IAAI,CAAC,IAAI,GAAG,EAAE;oBAC1D,SAAS,EAAE,UAAU,CAAC,SAAS;oBAC/B,OAAO,EAAE,UAAU,CAAC,OAAO;oBAC3B,SAAS,EAAE,UAAU,CAAC,SAAS;oBAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;iBAChC,CAAC,CAAC;gBAEH,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;oBACxB,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;oBACzB,gBAAgB,EAAE,UAAU;oBAC5B,KAAK,EAAE,KAAK;iBACb,CAAC,CAAC;gBACH,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAE9D,qDAAqD;QACrD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAEpF,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAEjF,4CAA4C;QAC5C,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,IAAkB;QAC/C,qCAAqC;QACrC,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAA2B,wBAAwB,CAAC,CAAC;QACjH,gBAAgB,CAAC,SAAS,EAAE,CAAC;QAC7B,gBAAgB,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACjD,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;QAClC,gBAAgB,CAAC,SAAS,GAAG,KAAK,CAAC;QACnC,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,yBAAyB;QAC1D,gBAAgB,CAAC,SAAS,GAAG,KAAK,CAAC;QACnC,gBAAgB,CAAC,SAAS,GAAG,KAAK,CAAC;QAEnC,0BAA0B;QAC1B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;YACxB,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;YACzB,gBAAgB,EAAE,gBAAgB;YAClC,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,8BAA8B;QAC9B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAClF,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAEM,oBAAoB,CAAC,cAA+B;QACzD,yCAAyC;QACzC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;YACjF,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;aAAM,CAAC;YACN,8BAA8B;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;YACjF,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9F,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,QAAQ;QACnB,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAE3C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAElB,IAAI,CAAC;YACH,+BAA+B;YAC/B,KAAK,MAAM,cAAc,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBAClD,IAAI,cAAc,CAAC,KAAK,IAAI,cAAc,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;oBAClE,MAAM,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAEjE,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;gBACnB,IAAI,CAAC,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uDAAuD,CAAC;gBAC9G,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC1B,CAAC,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;gBACnB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;gBACvB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC1B,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,cAA+B;QAC9D,iEAAiE;QACjE,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAChE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,YAAY,EAAE,OAAO,IAAI,uCAAuC,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC7I,CAAC;IACH,CAAC;IAEM,QAAQ;QACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzC,CAAC;mHAnMU,yBAAyB;6DAAzB,yBAAyB;YAAzB,sHAAA,uBAAmB,0BAAM;;YC/BtC,8FAAe;;YAAf,sCA6PC;;;iFD9NY,yBAAyB;cAPrC,SAAS;6BACI,KAAK,YACP,sBAAsB,iBACjB,iBAAiB,CAAC,IAAI;;kBAKpC,KAAK;;kBACL,KAAK;;kBACL,MAAM;;kBAgDN,YAAY;mBAAC,yBAAyB,EAAE,CAAC,QAAQ,CAAC;;kFAnDxC,yBAAyB","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges, SimpleChanges, inject, HostListener, ChangeDetectorRef, NgZone, ViewEncapsulation } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule, ReactiveFormsModule, FormBuilder, FormGroup } from '@angular/forms';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJEntityPermissionEntity, MJEntityEntity, MJRoleEntity } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\n\nexport interface PermissionDialogData {\n entity: MJEntityEntity;\n roles: MJRoleEntity[];\n existingPermissions: MJEntityPermissionEntity[];\n}\n\nexport interface PermissionDialogResult {\n action: 'save' | 'cancel';\n entity?: MJEntityEntity;\n}\n\ninterface RolePermissions {\n roleId: string;\n roleName: string;\n entityPermission: MJEntityPermissionEntity;\n isNew: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-permission-dialog',\n encapsulation: ViewEncapsulation.None,\n templateUrl: './permission-dialog.component.html',\n styleUrls: ['./permission-dialog.component.css']\n})\nexport class PermissionDialogComponent implements OnInit, OnDestroy, OnChanges {\n @Input() data: PermissionDialogData | null = null;\n @Input() visible = false;\n @Output() result = new EventEmitter<PermissionDialogResult>();\n\n private fb = inject(FormBuilder);\n private cdr = inject(ChangeDetectorRef);\n private ngZone = inject(NgZone);\n private metadata = new Metadata();\n\n public permissionForm: FormGroup;\n public isLoading = false;\n public error: string | null = null;\n public rolePermissions: RolePermissions[] = [];\n public availableRoles: MJRoleEntity[] = [];\n\n constructor() {\n this.permissionForm = this.fb.group({});\n }\n\n ngOnInit(): void {\n // Initial setup\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n console.log('Permission dialog ngOnChanges called:', changes);\n \n if (changes['visible'] && this.visible) {\n this.resetDialog();\n // Load data when dialog becomes visible and we have data\n if (this.data) {\n console.log('Dialog became visible, loading permission data');\n this.loadPermissionData();\n }\n }\n \n if (changes['data'] && this.data && this.visible) {\n console.log('Data changed while dialog is visible, reloading permission data');\n this.loadPermissionData();\n }\n }\n\n ngOnDestroy(): void {\n // Cleanup if needed\n }\n\n private resetDialog(): void {\n this.error = null;\n this.isLoading = false;\n }\n\n @HostListener('document:keydown.escape', ['$event'])\n onEscapeKey(event: Event): void {\n if (this.visible) {\n this.onCancel();\n }\n }\n\n public get hasChanges(): boolean {\n return this.rolePermissions.some(rp => rp.isNew || rp.entityPermission.Dirty);\n }\n\n public hasEntityChanges(rolePermission: RolePermissions): boolean {\n return rolePermission.isNew || rolePermission.entityPermission.Dirty;\n }\n\n private loadPermissionData(): void {\n if (!this.data) return;\n\n console.log('Loading permission data for entity:', this.data.entity.Name);\n console.log('Existing permissions:', this.data.existingPermissions);\n console.log('Available roles:', this.data.roles);\n\n // Initialize role permissions from existing data\n this.rolePermissions = [];\n const existingRoleIds = new Set<string>();\n\n // Process existing permissions\n for (const permission of this.data.existingPermissions) {\n const role = this.data.roles.find(r => UUIDsEqual(r.ID, permission.RoleID));\n if (role) {\n console.log(`Processing permission for role ${role.Name}:`, {\n canCreate: permission.CanCreate,\n canRead: permission.CanRead,\n canUpdate: permission.CanUpdate,\n canDelete: permission.CanDelete\n });\n \n this.rolePermissions.push({\n roleId: role.ID,\n roleName: role.Name || '',\n entityPermission: permission,\n isNew: false\n });\n existingRoleIds.add(role.ID);\n }\n }\n\n console.log('Loaded role permissions:', this.rolePermissions);\n\n // Set available roles (those not already configured)\n this.availableRoles = this.data.roles.filter(role => !existingRoleIds.has(role.ID));\n \n console.log('Available roles for adding:', this.availableRoles.map(r => r.Name));\n \n // Trigger change detection to update the UI\n this.cdr.detectChanges();\n }\n\n public async addRolePermission(role: MJRoleEntity): Promise<void> {\n // Create new EntityPermission entity\n const entityPermission = await this.metadata.GetEntityObject<MJEntityPermissionEntity>('MJ: Entity Permissions');\n entityPermission.NewRecord();\n entityPermission.EntityID = this.data!.entity.ID;\n entityPermission.RoleID = role.ID;\n entityPermission.CanCreate = false;\n entityPermission.CanRead = true; // Default to read access\n entityPermission.CanUpdate = false;\n entityPermission.CanDelete = false;\n\n // Add new role permission\n this.rolePermissions.push({\n roleId: role.ID,\n roleName: role.Name || '',\n entityPermission: entityPermission,\n isNew: true\n });\n\n // Remove from available roles\n this.availableRoles = this.availableRoles.filter(r => !UUIDsEqual(r.ID, role.ID));\n this.cdr.detectChanges();\n }\n\n public removeRolePermission(rolePermission: RolePermissions): void {\n // Add back to available roles if not new\n if (!rolePermission.isNew) {\n const role = this.data?.roles.find(r => UUIDsEqual(r.ID, rolePermission.roleId));\n if (role) {\n this.availableRoles.push(role);\n this.availableRoles.sort((a, b) => (a.Name || '').localeCompare(b.Name || ''));\n }\n } else {\n // Add back to available roles\n const role = this.data?.roles.find(r => UUIDsEqual(r.ID, rolePermission.roleId));\n if (role) {\n this.availableRoles.push(role);\n this.availableRoles.sort((a, b) => (a.Name || '').localeCompare(b.Name || ''));\n }\n }\n\n // Remove from role permissions\n this.rolePermissions = this.rolePermissions.filter(rp => rp.roleId !== rolePermission.roleId);\n this.cdr.detectChanges();\n }\n\n public async onSubmit(): Promise<void> {\n if (!this.data || !this.hasChanges) return;\n\n this.isLoading = true;\n this.error = null;\n\n try {\n // Process each role permission\n for (const rolePermission of this.rolePermissions) {\n if (rolePermission.isNew || rolePermission.entityPermission.Dirty) {\n await this.saveRolePermission(rolePermission);\n }\n }\n\n this.result.emit({ action: 'save', entity: this.data.entity });\n\n } catch (error: unknown) {\n console.error('Error saving permissions:', error);\n this.ngZone.run(() => {\n this.error = error instanceof Error ? error.message : 'An unexpected error occurred while saving permissions';\n this.cdr.markForCheck();\n });\n } finally {\n this.ngZone.run(() => {\n this.isLoading = false;\n this.cdr.markForCheck();\n });\n }\n }\n\n private async saveRolePermission(rolePermission: RolePermissions): Promise<void> {\n // Save the entity directly - it already has all the values bound\n const saveResult = await rolePermission.entityPermission.Save();\n if (!saveResult) {\n throw new Error(rolePermission.entityPermission.LatestResult?.Message || `Failed to save permissions for role ${rolePermission.roleName}`);\n }\n }\n\n public onCancel(): void {\n this.result.emit({ action: 'cancel' });\n }\n}","<!-- MD3 Modal Dialog -->\n@if (visible) {\n <div class=\"modal-backdrop\" (click)=\"onCancel()\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <!-- Modal Header -->\n <div class=\"modal-header\">\n <div class=\"dialog-header\">\n <h2 class=\"dialog-title\">\n <i class=\"fa-solid fa-key\"></i>\n Edit Entity Permissions\n </h2>\n <p class=\"dialog-subtitle\">\n Configure role-based permissions for {{ data?.entity?.Name }}\n </p>\n </div>\n <button type=\"button\" class=\"modal-close\" (click)=\"onCancel()\" aria-label=\"Close dialog\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <form [formGroup]=\"permissionForm\" (ngSubmit)=\"onSubmit()\">\n @if (error) {\n <div class=\"content-section\">\n <div class=\"alert alert-error\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <div>{{ error }}</div>\n </div>\n </div>\n }\n <!-- Entity Information Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-database\"></i>\n Entity Information\n </h3>\n <p class=\"section-description\">{{ data?.entity?.Description || 'Entity permissions configuration' }}</p>\n </div>\n <div class=\"entity-info-card\">\n <div class=\"entity-meta\">\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-table\"></i>\n <span class=\"meta-label\">Entity:</span>\n <span class=\"meta-value\">{{ data?.entity?.Name }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span class=\"meta-label\">Schema Name:</span>\n <span class=\"meta-value\">{{ data?.entity?.SchemaName || 'N/A' }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-key\"></i>\n <span class=\"meta-label\">Total Permissions:</span>\n <span class=\"meta-value\">{{ rolePermissions.length }}</span>\n </div>\n <div class=\"meta-item\">\n <i class=\"fa-solid fa-clock\"></i>\n <span class=\"meta-label\">Last Updated:</span>\n <span class=\"meta-value\">{{ data?.entity?.__mj_UpdatedAt | date:'medium' }}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n <!-- Permissions Configuration Section -->\n <div class=\"content-section\">\n <div class=\"form-section\">\n <div class=\"section-header\">\n <h3 class=\"section-title\">\n <i class=\"fa-solid fa-users-cog\"></i>\n Role Permissions\n </h3>\n <p class=\"section-description\">Configure CRUD permissions for each role</p>\n </div>\n <div class=\"permissions-table-container\">\n <table class=\"permissions-table\">\n <thead>\n <tr>\n <th class=\"role-column\">Role</th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-plus\"></i>\n Create\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-eye\"></i>\n Read\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-edit\"></i>\n Update\n </th>\n <th class=\"permission-column\">\n <i class=\"fa-solid fa-trash\"></i>\n Delete\n </th>\n <th class=\"actions-column\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (rolePermission of rolePermissions; track rolePermission.roleId) {\n <tr class=\"permission-row\" [class.has-changes]=\"hasEntityChanges(rolePermission)\" [class.is-new]=\"rolePermission.isNew\">\n <td class=\"role-name\">\n <div class=\"role-info\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>{{ rolePermission.roleName }}</span>\n @if (rolePermission.isNew) {\n <span class=\"new-badge\">New</span>\n }\n @if (hasEntityChanges(rolePermission) && !rolePermission.isNew) {\n <span class=\"changed-badge\">Modified</span>\n }\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'create-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanCreate\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'create-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'read-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanRead\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'read-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'update-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanUpdate\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'update-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"permission-cell\">\n <div class=\"permission-toggle\">\n <input\n type=\"checkbox\"\n [id]=\"'delete-' + rolePermission.roleId\"\n [(ngModel)]=\"rolePermission.entityPermission.CanDelete\"\n [ngModelOptions]=\"{standalone: true}\"\n class=\"permission-checkbox\"\n />\n <label [for]=\"'delete-' + rolePermission.roleId\" class=\"permission-label\">\n <div class=\"checkbox-indicator\"></div>\n </label>\n </div>\n </td>\n <td class=\"actions-cell\">\n <button\n type=\"button\"\n class=\"btn-icon btn-danger\"\n (click)=\"removeRolePermission(rolePermission)\"\n title=\"Remove permissions for this role\"\n attr.aria-label=\"Remove permissions for {{ rolePermission.roleName }}\"\n >\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n @if (rolePermissions.length === 0) {\n <div class=\"empty-permissions\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <p>No role permissions configured</p>\n <p class=\"empty-subtext\">Add permissions for specific roles to control access to this entity</p>\n </div>\n }\n </div>\n <!-- Add Role Permissions -->\n <div class=\"add-role-section\">\n <div class=\"add-role-header\">\n <h4>Add Role Permissions</h4>\n <p>Select roles to configure permissions for this entity</p>\n </div>\n <div class=\"available-roles\">\n @for (role of availableRoles; track role.ID) {\n <button\n type=\"button\"\n class=\"role-chip\"\n (click)=\"addRolePermission(role)\"\n title=\"Add permissions for {{ role.Name }}\"\n attr.aria-label=\"Add permissions for {{ role.Name }}\"\n >\n <i class=\"fa-solid fa-plus\"></i>\n {{ role.Name }}\n </button>\n }\n @if (availableRoles.length === 0) {\n <p class=\"no-available-roles\">All roles have been configured</p>\n }\n </div>\n </div>\n </div>\n </div>\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n <div class=\"footer-info\">\n @if (hasChanges) {\n <span class=\"changes-indicator\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n You have unsaved changes\n </span>\n }\n </div>\n <div class=\"footer-actions\">\n <button\n type=\"submit\"\n class=\"btn btn-primary\"\n [disabled]=\"!hasChanges || isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Saving...\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n Save Permissions\n }\n </button>\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"onCancel()\">\n <i class=\"fa-solid fa-times\"></i>\n Cancel\n </button>\n </div>\n </div>\n </form>\n </div>\n </div>\n </div>\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"notification-preferences.component.d.ts","sourceRoot":"","sources":["../../../src/lib/notification-preferences/notification-preferences.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,4BAA4B,EAAE,kCAAkC,EAAkB,MAAM,+BAA+B,CAAC;AACjI,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;;AAE1D;;;GAGG;AACH,UAAU,+BAA+B;IACvC,mDAAmD;IACnD,IAAI,EAAE,4BAA4B,CAAC;IACnC,gEAAgE;IAChE,UAAU,EAAE,kCAAkC,GAAG,IAAI,CAAC;IACtD,kDAAkD;IAClD,YAAY,EAAE,OAAO,CAAC;IACtB,iDAAiD;IACjD,YAAY,EAAE,OAAO,CAAC;IACtB,+CAA+C;IAC/C,UAAU,EAAE,OAAO,CAAC;IACpB,4DAA4D;IAC5D,OAAO,EAAE,OAAO,CAAC;IACjB,wDAAwD;IACxD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,uDAAuD;IACvD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,qDAAqD;IACrD,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,qBAMa,gCAAiC,YAAW,MAAM;IAMjD,OAAO,CAAC,aAAa;IALjC,OAAO,UAAQ;IACf,MAAM,UAAS;IACf,UAAU,EAAE,+BAA+B,EAAE,CAAM;IACnD,UAAU,UAAS;gBAEC,aAAa,EAAE,aAAa;IAEhD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/B;;;;;OAKG;YACW,QAAQ;IAmDtB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,EAAE,+BAA+B,GAAG,IAAI;IAK1D;;;;;;OAMG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA4D3B;;;OAGG;IACH,MAAM,IAAI,IAAI;IAWd;;;;;OAKG;IACH,WAAW,CAAC,IAAI,EAAE,4BAA4B,GAAG,MAAM;IAIvD;;;;;OAKG;IACH,YAAY,CAAC,IAAI,EAAE,4BAA4B,GAAG,MAAM;IAIxD;;;;;OAKG;IACH,qBAAqB,CAAC,IAAI,EAAE,4BAA4B,GAAG,MAAM,GAAG,IAAI;IAIxE;;;;;OAKG;IACH,sBAAsB,CAAC,IAAI,EAAE,4BAA4B,GAAG,OAAO;yCAzMxD,gCAAgC;2CAAhC,gCAAgC;CA4M5C"}
1
+ {"version":3,"file":"notification-preferences.component.d.ts","sourceRoot":"","sources":["../../../src/lib/notification-preferences/notification-preferences.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,4BAA4B,EAAE,kCAAkC,EAAkB,MAAM,+BAA+B,CAAC;AACjI,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;;AAG1D;;;GAGG;AACH,UAAU,+BAA+B;IACvC,mDAAmD;IACnD,IAAI,EAAE,4BAA4B,CAAC;IACnC,gEAAgE;IAChE,UAAU,EAAE,kCAAkC,GAAG,IAAI,CAAC;IACtD,kDAAkD;IAClD,YAAY,EAAE,OAAO,CAAC;IACtB,iDAAiD;IACjD,YAAY,EAAE,OAAO,CAAC;IACtB,+CAA+C;IAC/C,UAAU,EAAE,OAAO,CAAC;IACpB,4DAA4D;IAC5D,OAAO,EAAE,OAAO,CAAC;IACjB,wDAAwD;IACxD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,uDAAuD;IACvD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,qDAAqD;IACrD,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,qBAMa,gCAAiC,YAAW,MAAM;IAMjD,OAAO,CAAC,aAAa;IALjC,OAAO,UAAQ;IACf,MAAM,UAAS;IACf,UAAU,EAAE,+BAA+B,EAAE,CAAM;IACnD,UAAU,UAAS;gBAEC,aAAa,EAAE,aAAa;IAEhD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/B;;;;;OAKG;YACW,QAAQ;IAmDtB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,EAAE,+BAA+B,GAAG,IAAI;IAK1D;;;;;;OAMG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA4D3B;;;OAGG;IACH,MAAM,IAAI,IAAI;IAWd;;;;;OAKG;IACH,WAAW,CAAC,IAAI,EAAE,4BAA4B,GAAG,MAAM;IAIvD;;;;;OAKG;IACH,YAAY,CAAC,IAAI,EAAE,4BAA4B,GAAG,MAAM;IAIxD;;;;;OAKG;IACH,qBAAqB,CAAC,IAAI,EAAE,4BAA4B,GAAG,MAAM,GAAG,IAAI;IAIxE;;;;;OAKG;IACH,sBAAsB,CAAC,IAAI,EAAE,4BAA4B,GAAG,OAAO;yCAzMxD,gCAAgC;2CAAhC,gCAAgC;CA4M5C"}
@@ -1,6 +1,7 @@
1
1
  import { Component } from '@angular/core';
2
2
  import { Metadata } from '@memberjunction/core';
3
3
  import { UserInfoEngine } from '@memberjunction/core-entities';
4
+ import { UUIDsEqual } from '@memberjunction/global';
4
5
  import * as i0 from "@angular/core";
5
6
  import * as i1 from "@memberjunction/ng-shared";
6
7
  import * as i2 from "@angular/forms";
@@ -221,7 +222,7 @@ export class NotificationPreferencesComponent {
221
222
  const prefs = UserInfoEngine.Instance.NotificationPreferences;
222
223
  // Build view models from cached data
223
224
  this.viewModels = types.map((type) => {
224
- const existingPref = prefs.find((p) => p.NotificationTypeID === type.ID);
225
+ const existingPref = prefs.find((p) => UUIDsEqual(p.NotificationTypeID, type.ID));
225
226
  // Get channel values: user preference > type default
226
227
  const inAppEnabled = existingPref?.InAppEnabled ?? type.DefaultInApp ?? true;
227
228
  const emailEnabled = existingPref?.EmailEnabled ?? type.DefaultEmail ?? false;
@@ -379,5 +380,5 @@ export class NotificationPreferencesComponent {
379
380
  type: Component,
380
381
  args: [{ standalone: false, selector: 'mj-notification-preferences', template: "<div class=\"notification-preferences-container\">\n @if (loading) {\n <mj-loading text=\"Loading notification preferences...\"></mj-loading>\n } @else {\n <div class=\"content\">\n @if (viewModels.length === 0) {\n <!-- Empty state -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-bell-slash\"></i>\n <p>No notification types configured yet.</p>\n </div>\n } @else {\n <!-- Notification type cards -->\n <div class=\"notification-types-grid\">\n @for (vm of viewModels; track vm.type.ID) {\n <article class=\"notification-type-card\"\n [class.changed]=\"vm.changed\"\n role=\"region\"\n [attr.aria-label]=\"'Notification settings for ' + vm.type.Name\">\n\n <div class=\"card-header\" [style.border-left-color]=\"getTypeColor(vm.type)\">\n <div class=\"icon-wrapper\" [style.background-color]=\"getTypeColor(vm.type) + '20'\">\n <i [class]=\"'fa-solid ' + getTypeIcon(vm.type)\" [style.color]=\"getTypeColor(vm.type)\" [attr.aria-hidden]=\"true\"></i>\n </div>\n <div class=\"header-text\">\n <h4>{{ vm.type.Name }}</h4>\n <p class=\"type-description\">{{ vm.type.Description }}</p>\n </div>\n </div>\n\n <div class=\"card-body\">\n <!-- Delivery channel checkboxes -->\n <div class=\"preference-row\">\n <label class=\"delivery-label\" [attr.id]=\"'delivery-label-' + vm.type.ID\">Delivery Channels</label>\n\n <div class=\"delivery-checkboxes\" role=\"group\" [attr.aria-labelledby]=\"'delivery-label-' + vm.type.ID\">\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.inAppEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable in-app notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-bell\" aria-hidden=\"true\"></i>\n <span>In-App</span>\n </label>\n\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.emailEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable email notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span>Email</span>\n </label>\n\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.smsEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable SMS notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-mobile\" aria-hidden=\"true\"></i>\n <span>SMS</span>\n </label>\n </div>\n\n @if (!getAllowUserPreference(vm.type)) {\n <div class=\"info-message\" role=\"alert\" aria-live=\"polite\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n <span>This notification type's delivery channels cannot be customized.</span>\n </div>\n }\n </div>\n\n <!-- Auto-expire info -->\n @if (getTypeAutoExpireDays(vm.type)) {\n <div class=\"metadata-row\">\n <i class=\"fa-solid fa-clock\" aria-hidden=\"true\"></i>\n <span class=\"metadata-text\">\n Auto-marks as read after {{ getTypeAutoExpireDays(vm.type) }} day(s)\n </span>\n </div>\n }\n </div>\n </article>\n }\n </div>\n }\n\n <!-- Action buttons -->\n @if (hasChanges) {\n <div class=\"actions\" role=\"group\" aria-label=\"Save or cancel changes\">\n <button class=\"btn btn-secondary\"\n type=\"button\"\n (click)=\"cancel()\"\n [disabled]=\"saving\"\n [attr.aria-busy]=\"saving\">\n Cancel\n </button>\n <button class=\"btn btn-primary\"\n type=\"button\"\n (click)=\"save()\"\n [disabled]=\"saving\"\n [attr.aria-busy]=\"saving\">\n @if (saving) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n } @else {\n <i class=\"fa-solid fa-save\" aria-hidden=\"true\"></i>\n }\n <span>{{ saving ? 'Saving...' : 'Save Preferences' }}</span>\n </button>\n </div>\n }\n </div>\n }\n</div>\n", styles: ["/* =============================================================================\n Notification Preferences Component - Material Design 3\n Following MD3 Design System Guidelines\n ============================================================================= */\n\n/* MD3 Color Tokens */\n:host {\n /* Primary - Deep Blue */\n --md-primary: #0076B6;\n --md-on-primary: #FFFFFF;\n --md-primary-container: #AAE7FD;\n --md-on-primary-container: #001F2A;\n\n /* Secondary - Light Orange */\n --md-secondary: #F5A623;\n --md-on-secondary: #FFFFFF;\n --md-secondary-container: #FFECD6;\n --md-on-secondary-container: #2D1600;\n\n /* Tertiary - Light Green */\n --md-tertiary: #4CAF50;\n --md-on-tertiary: #FFFFFF;\n --md-tertiary-container: #C8E6C9;\n --md-on-tertiary-container: #002204;\n\n /* Error - Red */\n --md-error: #D32F2F;\n --md-on-error: #FFFFFF;\n --md-error-container: #FFCDD2;\n --md-on-error-container: #410002;\n\n /* Warning - Amber */\n --md-warning: #FFC107;\n --md-on-warning: #2D1600;\n --md-warning-container: #FFF3CD;\n --md-on-warning-container: #856404;\n\n /* Surface Colors */\n --md-surface: #FAFCFF;\n --md-surface-container-lowest: #FFFFFF;\n --md-surface-container-low: #F3F5F9;\n --md-surface-container: #EDF0F4;\n --md-surface-container-high: #E7EAEE;\n --md-surface-container-highest: #E1E3E8;\n --md-on-surface: #191C20;\n --md-on-surface-variant: #43474E;\n --md-outline: #74777F;\n --md-outline-variant: #C4C6D0;\n\n /* Elevation (Box Shadows) */\n --md-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n --md-elevation-2: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n --md-elevation-3: 0 4px 8px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.08);\n --md-elevation-4: 0 6px 12px rgba(0, 0, 0, 0.1), 0 12px 24px rgba(0, 0, 0, 0.08);\n --md-elevation-5: 0 8px 16px rgba(0, 0, 0, 0.12), 0 16px 32px rgba(0, 0, 0, 0.1);\n\n /* Corner Radii */\n --md-corner-extra-small: 4px;\n --md-corner-small: 8px;\n --md-corner-medium: 12px;\n --md-corner-large: 16px;\n --md-corner-extra-large: 28px;\n --md-corner-full: 9999px;\n\n /* Host element configuration */\n display: block;\n width: 100%;\n}\n\n/* -----------------------------------------------------------------------------\n Container & Layout\n ----------------------------------------------------------------------------- */\n.notification-preferences-container {\n padding: 1.5rem;\n max-width: 1200px;\n margin: 0 auto;\n background: var(--md-surface);\n}\n\n/* -----------------------------------------------------------------------------\n Loading State\n ----------------------------------------------------------------------------- */\n.content {\n animation: fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* -----------------------------------------------------------------------------\n Empty State\n ----------------------------------------------------------------------------- */\n.empty-state {\n text-align: center;\n padding: 3rem 1.5rem;\n}\n\n.empty-state i {\n font-size: 4rem;\n color: var(--md-outline-variant);\n margin-bottom: 1.5rem;\n display: block;\n}\n\n.empty-state p {\n font-size: 1.125rem;\n font-weight: 500;\n color: var(--md-on-surface-variant);\n margin: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Notification Types Grid\n ----------------------------------------------------------------------------- */\n.notification-types-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));\n gap: 1.25rem;\n margin-bottom: 1.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Notification Type Card\n ----------------------------------------------------------------------------- */\n.notification-type-card {\n background: var(--md-surface-container-lowest);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n border-left: 4px solid var(--md-outline-variant);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--md-elevation-1);\n}\n\n.notification-type-card:hover {\n box-shadow: var(--md-elevation-2);\n border-color: var(--md-primary);\n}\n\n.notification-type-card.changed {\n border-left-color: var(--md-primary) !important;\n border-color: var(--md-primary);\n box-shadow: var(--md-elevation-3);\n background: var(--md-primary-container);\n}\n\n/* -----------------------------------------------------------------------------\n Card Header\n ----------------------------------------------------------------------------- */\n.card-header {\n display: flex;\n gap: 1rem;\n padding: 1.25rem;\n border-bottom: 1px solid var(--md-outline-variant);\n align-items: flex-start;\n}\n\n.icon-wrapper {\n width: 48px;\n height: 48px;\n border-radius: var(--md-corner-small);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: transform 0.2s;\n}\n\n.notification-type-card:hover .icon-wrapper {\n transform: scale(1.05);\n}\n\n.icon-wrapper i {\n font-size: 1.5rem;\n}\n\n.header-text {\n flex: 1;\n min-width: 0;\n}\n\n.header-text h4 {\n margin: 0 0 0.375rem 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--md-on-surface);\n}\n\n.type-description {\n margin: 0;\n font-size: 0.875rem;\n color: var(--md-on-surface-variant);\n line-height: 1.4;\n}\n\n/* -----------------------------------------------------------------------------\n Card Body\n ----------------------------------------------------------------------------- */\n.card-body {\n padding: 1.25rem;\n}\n\n.preference-row {\n margin-bottom: 1rem;\n}\n\n.preference-row:last-child {\n margin-bottom: 0;\n}\n\n.delivery-label {\n display: block;\n font-weight: 600;\n margin-bottom: 0.75rem;\n font-size: 0.875rem;\n color: var(--md-on-surface);\n letter-spacing: 0.01em;\n}\n\n/* -----------------------------------------------------------------------------\n Delivery Channel Checkboxes\n ----------------------------------------------------------------------------- */\n.delivery-checkboxes {\n display: flex;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.channel-checkbox {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 0.75rem 1rem;\n border: 2px solid var(--md-outline-variant);\n border-radius: var(--md-corner-small);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n user-select: none;\n background: var(--md-surface);\n min-height: 44px;\n}\n\n.channel-checkbox input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--md-primary);\n margin: 0;\n}\n\n.channel-checkbox input[type=\"checkbox\"]:disabled {\n cursor: not-allowed;\n}\n\n.channel-checkbox i {\n color: var(--md-on-surface-variant);\n font-size: 1rem;\n transition: color 0.2s;\n}\n\n.channel-checkbox span {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--md-on-surface);\n}\n\n.channel-checkbox:hover:not(:has(input:disabled)) {\n border-color: var(--md-primary);\n background: var(--md-primary-container);\n}\n\n.channel-checkbox:hover:not(:has(input:disabled)) i {\n color: var(--md-primary);\n}\n\n.channel-checkbox:has(input:checked) {\n border-color: var(--md-primary);\n background: var(--md-primary-container);\n}\n\n.channel-checkbox:has(input:checked) i {\n color: var(--md-primary);\n}\n\n.channel-checkbox:has(input:disabled) {\n opacity: 0.5;\n cursor: not-allowed;\n background: var(--md-surface-container-low);\n}\n\n.channel-checkbox:focus-within {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Info Message\n ----------------------------------------------------------------------------- */\n.info-message {\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: var(--md-warning-container);\n border-left: 3px solid var(--md-warning);\n border-radius: var(--md-corner-small);\n font-size: 0.8125rem;\n display: flex;\n gap: 0.75rem;\n align-items: flex-start;\n line-height: 1.4;\n color: var(--md-on-warning-container);\n}\n\n.info-message i {\n color: var(--md-on-warning-container);\n font-size: 1rem;\n margin-top: 0.1rem;\n flex-shrink: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Metadata Row\n ----------------------------------------------------------------------------- */\n.metadata-row {\n display: flex;\n gap: 0.625rem;\n align-items: center;\n font-size: 0.8125rem;\n color: var(--md-on-surface-variant);\n padding-top: 0.75rem;\n margin-top: 0.75rem;\n border-top: 1px solid var(--md-outline-variant);\n}\n\n.metadata-row i {\n color: var(--md-on-surface-variant);\n font-size: 0.875rem;\n flex-shrink: 0;\n}\n\n.metadata-text {\n line-height: 1.4;\n}\n\n/* -----------------------------------------------------------------------------\n Action Buttons Section\n ----------------------------------------------------------------------------- */\n.actions {\n display: flex;\n justify-content: flex-start;\n gap: 0.75rem;\n padding: 1.25rem;\n background: var(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n border: 1px solid var(--md-outline-variant);\n margin-top: 1.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Button System - MD3 Patterns\n ----------------------------------------------------------------------------- */\n.btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n border: none;\n border-radius: var(--md-corner-full);\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n min-height: 44px;\n}\n\n.btn:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.btn i {\n font-size: 1rem;\n}\n\n.btn-secondary {\n background: var(--md-surface);\n color: var(--md-primary);\n border: 1px solid var(--md-outline);\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n}\n\n.btn-secondary:active:not(:disabled) {\n background: #005A8C;\n border-color: #005A8C;\n transform: scale(0.98);\n}\n\n.btn-primary {\n background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n.btn-primary:hover:not(:disabled) {\n background: #3395C8;\n box-shadow: var(--md-elevation-2);\n}\n\n.btn-primary:active:not(:disabled) {\n background: #4BA5D4;\n transform: scale(0.98);\n}\n\n.btn-ghost {\n background: transparent;\n color: var(--md-on-surface-variant);\n border: none;\n}\n\n.btn-ghost:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.btn-ghost:active:not(:disabled) {\n background: #005A8C;\n transform: scale(0.98);\n}\n\n.btn-danger {\n background: var(--md-error);\n color: var(--md-on-error);\n box-shadow: var(--md-elevation-1);\n}\n\n.btn-danger:hover:not(:disabled) {\n background: #E57373;\n box-shadow: var(--md-elevation-2);\n}\n\n.btn-danger:active:not(:disabled) {\n background: #EF9A9A;\n transform: scale(0.98);\n}\n\n.btn-sm {\n padding: 0.5rem 0.875rem;\n font-size: 0.8125rem;\n min-height: 36px;\n}\n\n/* -----------------------------------------------------------------------------\n Badge System - MD3 Patterns\n ----------------------------------------------------------------------------- */\n.badge-system {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--md-corner-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n background: var(--md-secondary-container);\n color: #7A4D0C;\n border: 1px solid var(--md-secondary);\n}\n\n.badge-custom {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--md-corner-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n background: var(--md-tertiary-container);\n color: #1B5E20;\n border: 1px solid var(--md-tertiary);\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Focus Indicators\n ----------------------------------------------------------------------------- */\nbutton:focus-visible,\ninput:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Reduced Motion\n ----------------------------------------------------------------------------- */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Animations\n ----------------------------------------------------------------------------- */\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* -----------------------------------------------------------------------------\n Responsive Design - Mobile First\n ----------------------------------------------------------------------------- */\n@media (max-width: 639px) {\n .notification-preferences-container {\n padding: 1rem;\n }\n\n .notification-types-grid {\n grid-template-columns: 1fr;\n gap: 1rem;\n }\n\n .card-header {\n padding: 1rem;\n }\n\n .card-body {\n padding: 1rem;\n }\n\n .delivery-checkboxes {\n flex-direction: column;\n }\n\n .channel-checkbox {\n width: 100%;\n }\n\n .actions {\n flex-direction: column;\n padding: 1rem;\n }\n\n .actions .btn {\n width: 100%;\n justify-content: center;\n }\n}\n\n@media (min-width: 640px) and (max-width: 767px) {\n .notification-types-grid {\n grid-template-columns: 1fr;\n }\n}\n\n@media (min-width: 768px) {\n .notification-preferences-container {\n padding: 2rem;\n }\n\n .notification-types-grid {\n grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));\n }\n}\n\n@media (min-width: 1024px) {\n .notification-types-grid {\n grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));\n gap: 1.5rem;\n }\n}\n"] }]
381
382
  }], () => [{ type: i1.SharedService }], null); })();
382
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(NotificationPreferencesComponent, { className: "NotificationPreferencesComponent", filePath: "src/lib/notification-preferences/notification-preferences.component.ts", lineNumber: 51 }); })();
383
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(NotificationPreferencesComponent, { className: "NotificationPreferencesComponent", filePath: "src/lib/notification-preferences/notification-preferences.component.ts", lineNumber: 52 }); })();
383
384
  //# sourceMappingURL=notification-preferences.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"notification-preferences.component.js","sourceRoot":"","sources":["../../../src/lib/notification-preferences/notification-preferences.component.ts","../../../src/lib/notification-preferences/notification-preferences.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit } from '@angular/core';\nimport { Metadata } from '@memberjunction/core';\nimport { MJUserNotificationTypeEntity, MJUserNotificationPreferenceEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { SharedService } from '@memberjunction/ng-shared';\n\n/**\n * View model for managing notification preferences in the UI.\n * Combines notification type definition with user's current preferences and change tracking.\n */\ninterface NotificationPreferenceViewModel {\n /** The notification type definition (read-only) */\n type: MJUserNotificationTypeEntity;\n /** User's existing preference record, or null if not yet set */\n preference: MJUserNotificationPreferenceEntity | null;\n /** Current state: In-app notifications enabled */\n inAppEnabled: boolean;\n /** Current state: Email notifications enabled */\n emailEnabled: boolean;\n /** Current state: SMS notifications enabled */\n smsEnabled: boolean;\n /** Whether this preference has been modified by the user */\n changed: boolean;\n /** Original value for rollback: In-app enabled state */\n originalInAppEnabled: boolean;\n /** Original value for rollback: Email enabled state */\n originalEmailEnabled: boolean;\n /** Original value for rollback: SMS enabled state */\n originalSmsEnabled: boolean;\n}\n\n/**\n * Component for managing user notification preferences.\n *\n * Displays notification types with configurable delivery channels (in-app, email, SMS).\n * Users can customize which channels they want to receive notifications through,\n * unless the notification type restricts user customization.\n *\n * Uses Material Design 3 (MD3) styling principles for consistent, accessible UI.\n *\n * Data flow:\n * - Loads notification types from UserInfoEngine (global cache)\n * - Loads user preferences from UserInfoEngine (per-user cache)\n * - Saves preferences using transaction groups for batch updates\n */\n@Component({\n standalone: false,\n selector: 'mj-notification-preferences',\n templateUrl: './notification-preferences.component.html',\n styleUrls: ['./notification-preferences.component.css'],\n})\nexport class NotificationPreferencesComponent implements OnInit {\n loading = true;\n saving = false;\n viewModels: NotificationPreferenceViewModel[] = [];\n hasChanges = false;\n\n constructor(private sharedService: SharedService) {}\n\n /**\n * Angular lifecycle hook - initializes the component by loading notification preferences.\n */\n async ngOnInit(): Promise<void> {\n await this.loadData();\n }\n\n /**\n * Loads notification types and user preferences from UserInfoEngine.\n * Builds view models by merging type defaults with user preferences.\n * Sorts types by Priority (ascending), then Name (alphabetical).\n * @private\n */\n private async loadData(): Promise<void> {\n try {\n this.loading = true;\n\n // UserInfoEngine is auto-configured via @RegisterForStartup()\n // NotificationEngine (server-side) loads notification types into global cache\n // UserInfoEngine provides a getter to access them from both client and server\n\n // Get notification types from UserInfoEngine, sorted client-side\n const types = [...UserInfoEngine.Instance.NotificationTypes].sort((a, b) => {\n const priorityA = a.Priority ?? 999;\n const priorityB = b.Priority ?? 999;\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n return a.Name.localeCompare(b.Name);\n });\n\n // Get preferences from UserInfoEngine (entity objects - can be mutated)\n const prefs = UserInfoEngine.Instance.NotificationPreferences;\n\n // Build view models from cached data\n this.viewModels = types.map((type) => {\n const existingPref = prefs.find((p) => p.NotificationTypeID === type.ID);\n\n // Get channel values: user preference > type default\n const inAppEnabled = existingPref?.InAppEnabled ?? type.DefaultInApp ?? true;\n const emailEnabled = existingPref?.EmailEnabled ?? type.DefaultEmail ?? false;\n const smsEnabled = existingPref?.SMSEnabled ?? type.DefaultSMS ?? false;\n\n return {\n type,\n preference: existingPref || null,\n inAppEnabled,\n emailEnabled,\n smsEnabled,\n changed: false,\n originalInAppEnabled: inAppEnabled,\n originalEmailEnabled: emailEnabled,\n originalSmsEnabled: smsEnabled,\n };\n });\n\n this.loading = false;\n } catch (error: unknown) {\n this.loading = false;\n const message = error instanceof Error ? error.message : 'Unknown error';\n this.sharedService.CreateSimpleNotification(`Failed to load notification preferences: ${message}`, 'error', 3000);\n }\n }\n\n /**\n * Called when a user toggles any delivery channel checkbox.\n * Updates the view model's changed flag by comparing current state to original values.\n * Sets the global hasChanges flag to show/hide the save/cancel buttons.\n * @param vm The view model for the notification type being modified\n */\n onChannelChange(vm: NotificationPreferenceViewModel): void {\n vm.changed = vm.inAppEnabled !== vm.originalInAppEnabled || vm.emailEnabled !== vm.originalEmailEnabled || vm.smsEnabled !== vm.originalSmsEnabled;\n this.hasChanges = this.viewModels.some((v) => v.changed);\n }\n\n /**\n * Saves all changed notification preferences using a transaction group for batch updates.\n * Creates new preference records for types that don't have existing preferences.\n * Updates the Enabled field based on whether any channel is enabled.\n * Shows success/error notification on completion.\n * @returns Promise that resolves when save is complete\n */\n async save(): Promise<void> {\n try {\n this.saving = true;\n const md = new Metadata();\n const currentUser = md.CurrentUser;\n const transGroup = await md.CreateTransactionGroup();\n\n // Queue all saves in transaction group - no need to await individual saves\n // Transaction group queues them and submits all in one batch\n for (const vm of this.viewModels.filter((v) => v.changed)) {\n let pref = vm.preference;\n\n if (!pref) {\n // Create new preference record\n pref = await md.GetEntityObject<MJUserNotificationPreferenceEntity>('MJ: User Notification Preferences');\n pref.UserID = currentUser.ID;\n pref.NotificationTypeID = vm.type.ID;\n vm.preference = pref;\n }\n\n // Set Enabled based on whether any channel is enabled\n pref.Enabled = vm.inAppEnabled || vm.emailEnabled || vm.smsEnabled;\n\n // Set the boolean channel fields\n pref.InAppEnabled = vm.inAppEnabled;\n pref.EmailEnabled = vm.emailEnabled;\n pref.SMSEnabled = vm.smsEnabled;\n pref.TransactionGroup = transGroup;\n // Don't await - Save() with transaction group queues immediately\n pref.Save();\n }\n\n // Submit transaction group - this is where the actual network call happens\n const success = await transGroup.Submit();\n\n if (success) {\n // Cache refresh happens automatically in MJUserNotificationPreferenceEntityExtended.Save()\n\n // Update original values\n this.viewModels.forEach((vm) => {\n vm.originalInAppEnabled = vm.inAppEnabled;\n vm.originalEmailEnabled = vm.emailEnabled;\n vm.originalSmsEnabled = vm.smsEnabled;\n vm.changed = false;\n });\n\n this.hasChanges = false;\n this.sharedService.CreateSimpleNotification('Notification preferences saved successfully', 'success', 2500);\n } else {\n throw new Error('Failed to save preferences');\n }\n\n this.saving = false;\n } catch (error: unknown) {\n this.saving = false;\n const message = error instanceof Error ? error.message : 'Unknown error';\n this.sharedService.CreateSimpleNotification(`Failed to save preferences: ${message}`, 'error', 3000);\n }\n }\n\n /**\n * Cancels all unsaved changes and reverts to original values.\n * Resets the changed flag on all view models and hides the action buttons.\n */\n cancel(): void {\n // Revert changes\n this.viewModels.forEach((vm) => {\n vm.inAppEnabled = vm.originalInAppEnabled;\n vm.emailEnabled = vm.originalEmailEnabled;\n vm.smsEnabled = vm.originalSmsEnabled;\n vm.changed = false;\n });\n this.hasChanges = false;\n }\n\n /**\n * Gets the Font Awesome icon class for a notification type.\n * Used for MD3 dynamic icon styling in the card header.\n * @param type The notification type entity\n * @returns Font Awesome icon class (e.g., 'fa-bell'), defaults to 'fa-bell' if not specified\n */\n getTypeIcon(type: MJUserNotificationTypeEntity): string {\n return type.Icon || 'fa-bell';\n }\n\n /**\n * Gets the color hex code for a notification type.\n * Used for MD3 dynamic color styling (icon background, border accent).\n * @param type The notification type entity\n * @returns Hex color code (e.g., '#0076B6'), defaults to '#999' if not specified\n */\n getTypeColor(type: MJUserNotificationTypeEntity): string {\n return type.Color || '#999';\n }\n\n /**\n * Gets the auto-expire duration in days for a notification type.\n * Displayed in the metadata row to inform users about automatic read marking.\n * @param type The notification type entity\n * @returns Number of days until auto-expire, or null if not configured\n */\n getTypeAutoExpireDays(type: MJUserNotificationTypeEntity): number | null {\n return type.AutoExpireDays || null;\n }\n\n /**\n * Checks if users are allowed to customize preferences for this notification type.\n * When false, the delivery channel checkboxes are disabled and an info message is shown.\n * @param type The notification type entity\n * @returns True if user customization is allowed (default), false otherwise\n */\n getAllowUserPreference(type: MJUserNotificationTypeEntity): boolean {\n return type.AllowUserPreference !== false;\n }\n}\n","<div class=\"notification-preferences-container\">\n @if (loading) {\n <mj-loading text=\"Loading notification preferences...\"></mj-loading>\n } @else {\n <div class=\"content\">\n @if (viewModels.length === 0) {\n <!-- Empty state -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-bell-slash\"></i>\n <p>No notification types configured yet.</p>\n </div>\n } @else {\n <!-- Notification type cards -->\n <div class=\"notification-types-grid\">\n @for (vm of viewModels; track vm.type.ID) {\n <article class=\"notification-type-card\"\n [class.changed]=\"vm.changed\"\n role=\"region\"\n [attr.aria-label]=\"'Notification settings for ' + vm.type.Name\">\n\n <div class=\"card-header\" [style.border-left-color]=\"getTypeColor(vm.type)\">\n <div class=\"icon-wrapper\" [style.background-color]=\"getTypeColor(vm.type) + '20'\">\n <i [class]=\"'fa-solid ' + getTypeIcon(vm.type)\" [style.color]=\"getTypeColor(vm.type)\" [attr.aria-hidden]=\"true\"></i>\n </div>\n <div class=\"header-text\">\n <h4>{{ vm.type.Name }}</h4>\n <p class=\"type-description\">{{ vm.type.Description }}</p>\n </div>\n </div>\n\n <div class=\"card-body\">\n <!-- Delivery channel checkboxes -->\n <div class=\"preference-row\">\n <label class=\"delivery-label\" [attr.id]=\"'delivery-label-' + vm.type.ID\">Delivery Channels</label>\n\n <div class=\"delivery-checkboxes\" role=\"group\" [attr.aria-labelledby]=\"'delivery-label-' + vm.type.ID\">\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.inAppEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable in-app notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-bell\" aria-hidden=\"true\"></i>\n <span>In-App</span>\n </label>\n\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.emailEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable email notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span>Email</span>\n </label>\n\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.smsEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable SMS notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-mobile\" aria-hidden=\"true\"></i>\n <span>SMS</span>\n </label>\n </div>\n\n @if (!getAllowUserPreference(vm.type)) {\n <div class=\"info-message\" role=\"alert\" aria-live=\"polite\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n <span>This notification type's delivery channels cannot be customized.</span>\n </div>\n }\n </div>\n\n <!-- Auto-expire info -->\n @if (getTypeAutoExpireDays(vm.type)) {\n <div class=\"metadata-row\">\n <i class=\"fa-solid fa-clock\" aria-hidden=\"true\"></i>\n <span class=\"metadata-text\">\n Auto-marks as read after {{ getTypeAutoExpireDays(vm.type) }} day(s)\n </span>\n </div>\n }\n </div>\n </article>\n }\n </div>\n }\n\n <!-- Action buttons -->\n @if (hasChanges) {\n <div class=\"actions\" role=\"group\" aria-label=\"Save or cancel changes\">\n <button class=\"btn btn-secondary\"\n type=\"button\"\n (click)=\"cancel()\"\n [disabled]=\"saving\"\n [attr.aria-busy]=\"saving\">\n Cancel\n </button>\n <button class=\"btn btn-primary\"\n type=\"button\"\n (click)=\"save()\"\n [disabled]=\"saving\"\n [attr.aria-busy]=\"saving\">\n @if (saving) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n } @else {\n <i class=\"fa-solid fa-save\" aria-hidden=\"true\"></i>\n }\n <span>{{ saving ? 'Saving...' : 'Save Preferences' }}</span>\n </button>\n </div>\n }\n </div>\n }\n</div>\n"]}
1
+ {"version":3,"file":"notification-preferences.component.js","sourceRoot":"","sources":["../../../src/lib/notification-preferences/notification-preferences.component.ts","../../../src/lib/notification-preferences/notification-preferences.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit } from '@angular/core';\nimport { Metadata } from '@memberjunction/core';\nimport { MJUserNotificationTypeEntity, MJUserNotificationPreferenceEntity, UserInfoEngine } from '@memberjunction/core-entities';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * View model for managing notification preferences in the UI.\n * Combines notification type definition with user's current preferences and change tracking.\n */\ninterface NotificationPreferenceViewModel {\n /** The notification type definition (read-only) */\n type: MJUserNotificationTypeEntity;\n /** User's existing preference record, or null if not yet set */\n preference: MJUserNotificationPreferenceEntity | null;\n /** Current state: In-app notifications enabled */\n inAppEnabled: boolean;\n /** Current state: Email notifications enabled */\n emailEnabled: boolean;\n /** Current state: SMS notifications enabled */\n smsEnabled: boolean;\n /** Whether this preference has been modified by the user */\n changed: boolean;\n /** Original value for rollback: In-app enabled state */\n originalInAppEnabled: boolean;\n /** Original value for rollback: Email enabled state */\n originalEmailEnabled: boolean;\n /** Original value for rollback: SMS enabled state */\n originalSmsEnabled: boolean;\n}\n\n/**\n * Component for managing user notification preferences.\n *\n * Displays notification types with configurable delivery channels (in-app, email, SMS).\n * Users can customize which channels they want to receive notifications through,\n * unless the notification type restricts user customization.\n *\n * Uses Material Design 3 (MD3) styling principles for consistent, accessible UI.\n *\n * Data flow:\n * - Loads notification types from UserInfoEngine (global cache)\n * - Loads user preferences from UserInfoEngine (per-user cache)\n * - Saves preferences using transaction groups for batch updates\n */\n@Component({\n standalone: false,\n selector: 'mj-notification-preferences',\n templateUrl: './notification-preferences.component.html',\n styleUrls: ['./notification-preferences.component.css'],\n})\nexport class NotificationPreferencesComponent implements OnInit {\n loading = true;\n saving = false;\n viewModels: NotificationPreferenceViewModel[] = [];\n hasChanges = false;\n\n constructor(private sharedService: SharedService) {}\n\n /**\n * Angular lifecycle hook - initializes the component by loading notification preferences.\n */\n async ngOnInit(): Promise<void> {\n await this.loadData();\n }\n\n /**\n * Loads notification types and user preferences from UserInfoEngine.\n * Builds view models by merging type defaults with user preferences.\n * Sorts types by Priority (ascending), then Name (alphabetical).\n * @private\n */\n private async loadData(): Promise<void> {\n try {\n this.loading = true;\n\n // UserInfoEngine is auto-configured via @RegisterForStartup()\n // NotificationEngine (server-side) loads notification types into global cache\n // UserInfoEngine provides a getter to access them from both client and server\n\n // Get notification types from UserInfoEngine, sorted client-side\n const types = [...UserInfoEngine.Instance.NotificationTypes].sort((a, b) => {\n const priorityA = a.Priority ?? 999;\n const priorityB = b.Priority ?? 999;\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n return a.Name.localeCompare(b.Name);\n });\n\n // Get preferences from UserInfoEngine (entity objects - can be mutated)\n const prefs = UserInfoEngine.Instance.NotificationPreferences;\n\n // Build view models from cached data\n this.viewModels = types.map((type) => {\n const existingPref = prefs.find((p) => UUIDsEqual(p.NotificationTypeID, type.ID));\n\n // Get channel values: user preference > type default\n const inAppEnabled = existingPref?.InAppEnabled ?? type.DefaultInApp ?? true;\n const emailEnabled = existingPref?.EmailEnabled ?? type.DefaultEmail ?? false;\n const smsEnabled = existingPref?.SMSEnabled ?? type.DefaultSMS ?? false;\n\n return {\n type,\n preference: existingPref || null,\n inAppEnabled,\n emailEnabled,\n smsEnabled,\n changed: false,\n originalInAppEnabled: inAppEnabled,\n originalEmailEnabled: emailEnabled,\n originalSmsEnabled: smsEnabled,\n };\n });\n\n this.loading = false;\n } catch (error: unknown) {\n this.loading = false;\n const message = error instanceof Error ? error.message : 'Unknown error';\n this.sharedService.CreateSimpleNotification(`Failed to load notification preferences: ${message}`, 'error', 3000);\n }\n }\n\n /**\n * Called when a user toggles any delivery channel checkbox.\n * Updates the view model's changed flag by comparing current state to original values.\n * Sets the global hasChanges flag to show/hide the save/cancel buttons.\n * @param vm The view model for the notification type being modified\n */\n onChannelChange(vm: NotificationPreferenceViewModel): void {\n vm.changed = vm.inAppEnabled !== vm.originalInAppEnabled || vm.emailEnabled !== vm.originalEmailEnabled || vm.smsEnabled !== vm.originalSmsEnabled;\n this.hasChanges = this.viewModels.some((v) => v.changed);\n }\n\n /**\n * Saves all changed notification preferences using a transaction group for batch updates.\n * Creates new preference records for types that don't have existing preferences.\n * Updates the Enabled field based on whether any channel is enabled.\n * Shows success/error notification on completion.\n * @returns Promise that resolves when save is complete\n */\n async save(): Promise<void> {\n try {\n this.saving = true;\n const md = new Metadata();\n const currentUser = md.CurrentUser;\n const transGroup = await md.CreateTransactionGroup();\n\n // Queue all saves in transaction group - no need to await individual saves\n // Transaction group queues them and submits all in one batch\n for (const vm of this.viewModels.filter((v) => v.changed)) {\n let pref = vm.preference;\n\n if (!pref) {\n // Create new preference record\n pref = await md.GetEntityObject<MJUserNotificationPreferenceEntity>('MJ: User Notification Preferences');\n pref.UserID = currentUser.ID;\n pref.NotificationTypeID = vm.type.ID;\n vm.preference = pref;\n }\n\n // Set Enabled based on whether any channel is enabled\n pref.Enabled = vm.inAppEnabled || vm.emailEnabled || vm.smsEnabled;\n\n // Set the boolean channel fields\n pref.InAppEnabled = vm.inAppEnabled;\n pref.EmailEnabled = vm.emailEnabled;\n pref.SMSEnabled = vm.smsEnabled;\n pref.TransactionGroup = transGroup;\n // Don't await - Save() with transaction group queues immediately\n pref.Save();\n }\n\n // Submit transaction group - this is where the actual network call happens\n const success = await transGroup.Submit();\n\n if (success) {\n // Cache refresh happens automatically in MJUserNotificationPreferenceEntityExtended.Save()\n\n // Update original values\n this.viewModels.forEach((vm) => {\n vm.originalInAppEnabled = vm.inAppEnabled;\n vm.originalEmailEnabled = vm.emailEnabled;\n vm.originalSmsEnabled = vm.smsEnabled;\n vm.changed = false;\n });\n\n this.hasChanges = false;\n this.sharedService.CreateSimpleNotification('Notification preferences saved successfully', 'success', 2500);\n } else {\n throw new Error('Failed to save preferences');\n }\n\n this.saving = false;\n } catch (error: unknown) {\n this.saving = false;\n const message = error instanceof Error ? error.message : 'Unknown error';\n this.sharedService.CreateSimpleNotification(`Failed to save preferences: ${message}`, 'error', 3000);\n }\n }\n\n /**\n * Cancels all unsaved changes and reverts to original values.\n * Resets the changed flag on all view models and hides the action buttons.\n */\n cancel(): void {\n // Revert changes\n this.viewModels.forEach((vm) => {\n vm.inAppEnabled = vm.originalInAppEnabled;\n vm.emailEnabled = vm.originalEmailEnabled;\n vm.smsEnabled = vm.originalSmsEnabled;\n vm.changed = false;\n });\n this.hasChanges = false;\n }\n\n /**\n * Gets the Font Awesome icon class for a notification type.\n * Used for MD3 dynamic icon styling in the card header.\n * @param type The notification type entity\n * @returns Font Awesome icon class (e.g., 'fa-bell'), defaults to 'fa-bell' if not specified\n */\n getTypeIcon(type: MJUserNotificationTypeEntity): string {\n return type.Icon || 'fa-bell';\n }\n\n /**\n * Gets the color hex code for a notification type.\n * Used for MD3 dynamic color styling (icon background, border accent).\n * @param type The notification type entity\n * @returns Hex color code (e.g., '#0076B6'), defaults to '#999' if not specified\n */\n getTypeColor(type: MJUserNotificationTypeEntity): string {\n return type.Color || '#999';\n }\n\n /**\n * Gets the auto-expire duration in days for a notification type.\n * Displayed in the metadata row to inform users about automatic read marking.\n * @param type The notification type entity\n * @returns Number of days until auto-expire, or null if not configured\n */\n getTypeAutoExpireDays(type: MJUserNotificationTypeEntity): number | null {\n return type.AutoExpireDays || null;\n }\n\n /**\n * Checks if users are allowed to customize preferences for this notification type.\n * When false, the delivery channel checkboxes are disabled and an info message is shown.\n * @param type The notification type entity\n * @returns True if user customization is allowed (default), false otherwise\n */\n getAllowUserPreference(type: MJUserNotificationTypeEntity): boolean {\n return type.AllowUserPreference !== false;\n }\n}\n","<div class=\"notification-preferences-container\">\n @if (loading) {\n <mj-loading text=\"Loading notification preferences...\"></mj-loading>\n } @else {\n <div class=\"content\">\n @if (viewModels.length === 0) {\n <!-- Empty state -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-bell-slash\"></i>\n <p>No notification types configured yet.</p>\n </div>\n } @else {\n <!-- Notification type cards -->\n <div class=\"notification-types-grid\">\n @for (vm of viewModels; track vm.type.ID) {\n <article class=\"notification-type-card\"\n [class.changed]=\"vm.changed\"\n role=\"region\"\n [attr.aria-label]=\"'Notification settings for ' + vm.type.Name\">\n\n <div class=\"card-header\" [style.border-left-color]=\"getTypeColor(vm.type)\">\n <div class=\"icon-wrapper\" [style.background-color]=\"getTypeColor(vm.type) + '20'\">\n <i [class]=\"'fa-solid ' + getTypeIcon(vm.type)\" [style.color]=\"getTypeColor(vm.type)\" [attr.aria-hidden]=\"true\"></i>\n </div>\n <div class=\"header-text\">\n <h4>{{ vm.type.Name }}</h4>\n <p class=\"type-description\">{{ vm.type.Description }}</p>\n </div>\n </div>\n\n <div class=\"card-body\">\n <!-- Delivery channel checkboxes -->\n <div class=\"preference-row\">\n <label class=\"delivery-label\" [attr.id]=\"'delivery-label-' + vm.type.ID\">Delivery Channels</label>\n\n <div class=\"delivery-checkboxes\" role=\"group\" [attr.aria-labelledby]=\"'delivery-label-' + vm.type.ID\">\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.inAppEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable in-app notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-bell\" aria-hidden=\"true\"></i>\n <span>In-App</span>\n </label>\n\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.emailEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable email notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-envelope\" aria-hidden=\"true\"></i>\n <span>Email</span>\n </label>\n\n <label class=\"channel-checkbox\">\n <input type=\"checkbox\"\n [(ngModel)]=\"vm.smsEnabled\"\n (change)=\"onChannelChange(vm)\"\n [disabled]=\"!getAllowUserPreference(vm.type)\"\n [attr.aria-label]=\"'Enable SMS notifications for ' + vm.type.Name\">\n <i class=\"fa-solid fa-mobile\" aria-hidden=\"true\"></i>\n <span>SMS</span>\n </label>\n </div>\n\n @if (!getAllowUserPreference(vm.type)) {\n <div class=\"info-message\" role=\"alert\" aria-live=\"polite\">\n <i class=\"fa-solid fa-info-circle\" aria-hidden=\"true\"></i>\n <span>This notification type's delivery channels cannot be customized.</span>\n </div>\n }\n </div>\n\n <!-- Auto-expire info -->\n @if (getTypeAutoExpireDays(vm.type)) {\n <div class=\"metadata-row\">\n <i class=\"fa-solid fa-clock\" aria-hidden=\"true\"></i>\n <span class=\"metadata-text\">\n Auto-marks as read after {{ getTypeAutoExpireDays(vm.type) }} day(s)\n </span>\n </div>\n }\n </div>\n </article>\n }\n </div>\n }\n\n <!-- Action buttons -->\n @if (hasChanges) {\n <div class=\"actions\" role=\"group\" aria-label=\"Save or cancel changes\">\n <button class=\"btn btn-secondary\"\n type=\"button\"\n (click)=\"cancel()\"\n [disabled]=\"saving\"\n [attr.aria-busy]=\"saving\">\n Cancel\n </button>\n <button class=\"btn btn-primary\"\n type=\"button\"\n (click)=\"save()\"\n [disabled]=\"saving\"\n [attr.aria-busy]=\"saving\">\n @if (saving) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n } @else {\n <i class=\"fa-solid fa-save\" aria-hidden=\"true\"></i>\n }\n <span>{{ saving ? 'Saving...' : 'Save Preferences' }}</span>\n </button>\n </div>\n }\n </div>\n }\n</div>\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"user-app-config.component.d.ts","sourceRoot":"","sources":["../../../src/lib/user-app-config/user-app-config.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAiD,MAAM,eAAe,CAAC;AAGtH,OAAO,EAAsB,eAAe,EAAE,MAAM,qCAAqC,CAAC;;AAG1F;;GAEG;AACH,UAAU,aAAa;IACrB,GAAG,EAAE,eAAe,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAYD;;;;;;GAMG;AACH,qBAMa,sBAAsB;IACjC,OAAO,CAAC,UAAU,CAA8B;IAChD,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,GAAG,CAA6B;IACxC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,EAAE,CAAsB;IAEhC,OAAO,CAAC,WAAW,CAAS;IAE5B,IACI,UAAU,CAAC,KAAK,EAAE,OAAO,EAI5B;IACD,IAAI,UAAU,IAAI,OAAO,CAExB;IAES,gBAAgB,wBAA+B;IAC/C,WAAW,qBAA4B;IAEjD,OAAO,EAAE,aAAa,EAAE,CAAM;IAC9B,UAAU,EAAE,aAAa,EAAE,CAAM;IACjC,aAAa,EAAE,aAAa,EAAE,CAAM;IAEpC,SAAS,UAAS;IAClB,QAAQ,UAAS;IACjB,YAAY,SAAM;IAElB,uBAAuB,UAAS;IAChC,sBAAsB,UAAS;IAE/B,WAAW,EAAE,aAAa,GAAG,IAAI,CAAQ;IACzC,YAAY,SAAM;IAClB,eAAe,SAAM;IAErB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAOjC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IASpC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAQpC;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAQjC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAQnC;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwC3B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAUvE,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAOlC,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKlD,SAAS,IAAI,IAAI;IAMjB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAiB9B,cAAc,SAAM;IACpB,cAAc,SAAM;IACpB,eAAe,UAAS;IAExB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,oBAAoB,CAA4B;IAExD,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAkBxD,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAexC,cAAc,IAAI,IAAI;IAmBtB,OAAO,CAAC,qBAAqB;IAM7B,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,mBAAmB;YAYb,iBAAiB;IAmC/B,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,aAAa;YAQP,qBAAqB;YAgBrB,qBAAqB;yCAhZxB,sBAAsB;2CAAtB,sBAAsB;CAkalC"}
1
+ {"version":3,"file":"user-app-config.component.d.ts","sourceRoot":"","sources":["../../../src/lib/user-app-config/user-app-config.component.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { Component, Input, Output, EventEmitter, ChangeDetectorRef, NgZone, Elem
2
2
  import { Metadata, RunView, LogError, LogStatus } from '@memberjunction/core';
3
3
  import { ApplicationManager } from '@memberjunction/ng-base-application';
4
4
  import { SharedService } from '@memberjunction/ng-shared';
5
+ import { UUIDsEqual } from '@memberjunction/global';
5
6
  import * as i0 from "@angular/core";
6
7
  import * as i1 from "@memberjunction/ng-shared-generic";
7
8
  const _forTrack0 = ($index, $item) => $item.app.ID;
@@ -674,7 +675,7 @@ export class UserAppConfigComponent {
674
675
  }
675
676
  buildAppConfigItems(systemApps, userApps) {
676
677
  return systemApps.map(app => {
677
- const userApp = userApps.find(ua => ua.ApplicationID === app.ID);
678
+ const userApp = userApps.find(ua => UUIDsEqual(ua.ApplicationID, app.ID));
678
679
  return {
679
680
  app,
680
681
  userAppId: userApp?.ID ?? null,
@@ -751,5 +752,5 @@ export class UserAppConfigComponent {
751
752
  }], ConfigSaved: [{
752
753
  type: Output
753
754
  }] }); })();
754
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserAppConfigComponent, { className: "UserAppConfigComponent", filePath: "src/lib/user-app-config/user-app-config.component.ts", lineNumber: 41 }); })();
755
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserAppConfigComponent, { className: "UserAppConfigComponent", filePath: "src/lib/user-app-config/user-app-config.component.ts", lineNumber: 42 }); })();
755
756
  //# sourceMappingURL=user-app-config.component.js.map