@ieeesa-npm/dashboard 0.0.0-stage → 0.0.2

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 (73) hide show
  1. package/README.md +75 -3
  2. package/esm2022/ieeesa-npm-dashboard.mjs +5 -0
  3. package/esm2022/lib/assets/constants.json +158 -0
  4. package/esm2022/lib/assets/dashboard-mock.mjs +221 -0
  5. package/esm2022/lib/assets/dashboard-route-paths.mock.mjs +14 -0
  6. package/esm2022/lib/assets/dashboard-user-permissions.mock.mjs +23 -0
  7. package/esm2022/lib/assets/date-formats.mjs +28 -0
  8. package/esm2022/lib/components/event-group-card/event-group-card.component.mjs +414 -0
  9. package/esm2022/lib/components/meeting-attendance-row/meeting-attendance-row.component.mjs +182 -0
  10. package/esm2022/lib/components/member-level-badge/member-level-badge.component.mjs +79 -0
  11. package/esm2022/lib/components/upcoming-meetings-events/upcoming-meetings-events.component.mjs +261 -0
  12. package/esm2022/lib/components/welcome-header/dashboard-welcome-header.component.mjs +151 -0
  13. package/esm2022/lib/components/your-groups/your-groups.component.mjs +243 -0
  14. package/esm2022/lib/dashboard.component.mjs +417 -0
  15. package/esm2022/lib/dashboard.module.mjs +16 -0
  16. package/esm2022/lib/dashboard.routes.mjs +7 -0
  17. package/esm2022/lib/models/attendance-action-permissions.model.mjs +2 -0
  18. package/esm2022/lib/models/attendance-state.model.mjs +7 -0
  19. package/esm2022/lib/models/dashboard-list-response.model.mjs +2 -0
  20. package/esm2022/lib/models/dashboard-route-config.model.mjs +2 -0
  21. package/esm2022/lib/models/dashboard-section-state.model.mjs +9 -0
  22. package/esm2022/lib/models/dashboard-user-info.model.mjs +2 -0
  23. package/esm2022/lib/models/event-meeting-list-item.model.mjs +2 -0
  24. package/esm2022/lib/models/event-meeting-list-payload.model.mjs +8 -0
  25. package/esm2022/lib/models/group-row.model.mjs +2 -0
  26. package/esm2022/lib/models/meeting-row.model.mjs +2 -0
  27. package/esm2022/lib/models/my-groups-view.model.mjs +2 -0
  28. package/esm2022/lib/models/page-change.model.mjs +2 -0
  29. package/esm2022/lib/models/upcoming-event.model.mjs +13 -0
  30. package/esm2022/lib/services/attendance-reducers.mjs +54 -0
  31. package/esm2022/lib/services/dashboard.service.mjs +402 -0
  32. package/esm2022/lib/services/user-permissions.service.mjs +50 -0
  33. package/esm2022/lib/utils/attendance-action.util.mjs +53 -0
  34. package/esm2022/lib/utils/date-format.util.mjs +110 -0
  35. package/esm2022/lib/utils/event-meeting-mapper.util.mjs +96 -0
  36. package/esm2022/public-api.mjs +36 -0
  37. package/fesm2022/ieeesa-npm-dashboard.mjs +2981 -0
  38. package/fesm2022/ieeesa-npm-dashboard.mjs.map +1 -0
  39. package/index.d.ts +5 -0
  40. package/lib/assets/dashboard-mock.d.ts +31 -0
  41. package/lib/assets/dashboard-route-paths.mock.d.ts +2 -0
  42. package/lib/assets/dashboard-user-permissions.mock.d.ts +2 -0
  43. package/lib/assets/date-formats.d.ts +27 -0
  44. package/lib/components/event-group-card/event-group-card.component.d.ts +268 -0
  45. package/lib/components/meeting-attendance-row/meeting-attendance-row.component.d.ts +115 -0
  46. package/lib/components/member-level-badge/member-level-badge.component.d.ts +177 -0
  47. package/lib/components/upcoming-meetings-events/upcoming-meetings-events.component.d.ts +175 -0
  48. package/lib/components/welcome-header/dashboard-welcome-header.component.d.ts +98 -0
  49. package/lib/components/your-groups/your-groups.component.d.ts +159 -0
  50. package/lib/dashboard.component.d.ts +414 -0
  51. package/lib/dashboard.module.d.ts +7 -0
  52. package/lib/dashboard.routes.d.ts +2 -0
  53. package/lib/models/attendance-action-permissions.model.d.ts +4 -0
  54. package/lib/models/attendance-state.model.d.ts +4 -0
  55. package/lib/models/dashboard-list-response.model.d.ts +5 -0
  56. package/lib/models/dashboard-route-config.model.d.ts +7 -0
  57. package/lib/models/dashboard-section-state.model.d.ts +6 -0
  58. package/lib/models/dashboard-user-info.model.d.ts +5 -0
  59. package/lib/models/event-meeting-list-item.model.d.ts +107 -0
  60. package/lib/models/event-meeting-list-payload.model.d.ts +40 -0
  61. package/lib/models/group-row.model.d.ts +33 -0
  62. package/lib/models/meeting-row.model.d.ts +28 -0
  63. package/lib/models/my-groups-view.model.d.ts +56 -0
  64. package/lib/models/page-change.model.d.ts +4 -0
  65. package/lib/models/upcoming-event.model.d.ts +51 -0
  66. package/lib/services/attendance-reducers.d.ts +43 -0
  67. package/lib/services/dashboard.service.d.ts +202 -0
  68. package/lib/services/user-permissions.service.d.ts +31 -0
  69. package/lib/utils/attendance-action.util.d.ts +38 -0
  70. package/lib/utils/date-format.util.d.ts +60 -0
  71. package/lib/utils/event-meeting-mapper.util.d.ts +50 -0
  72. package/package.json +30 -3
  73. package/public-api.d.ts +26 -0
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Request payloads for the dashboard "events & meetings" backend calls. These
3
+ * mirror the `events-and-meetings` library's `GetEventsAndMeetingsPayload` /
4
+ * `GetMeetingsByEventIdPayload` so the dashboard reuses the exact contract the
5
+ * existing `view-events-meetings-list` screen posts.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnQtbWVldGluZy1saXN0LXBheWxvYWQubW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXNoYm9hcmQvc3JjL2xpYi9tb2RlbHMvZXZlbnQtbWVldGluZy1saXN0LXBheWxvYWQubW9kZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0ciLCJzb3VyY2VzQ29udGVudCI6WyIvKipcclxuICogUmVxdWVzdCBwYXlsb2FkcyBmb3IgdGhlIGRhc2hib2FyZCBcImV2ZW50cyAmIG1lZXRpbmdzXCIgYmFja2VuZCBjYWxscy4gVGhlc2VcclxuICogbWlycm9yIHRoZSBgZXZlbnRzLWFuZC1tZWV0aW5nc2AgbGlicmFyeSdzIGBHZXRFdmVudHNBbmRNZWV0aW5nc1BheWxvYWRgIC9cclxuICogYEdldE1lZXRpbmdzQnlFdmVudElkUGF5bG9hZGAgc28gdGhlIGRhc2hib2FyZCByZXVzZXMgdGhlIGV4YWN0IGNvbnRyYWN0IHRoZVxyXG4gKiBleGlzdGluZyBgdmlldy1ldmVudHMtbWVldGluZ3MtbGlzdGAgc2NyZWVuIHBvc3RzLlxyXG4gKi9cclxuXHJcbi8qKiBGaWx0ZXIgYmxvY2sgc2hhcmVkIGJ5IHRoZSBsaXN0IGFuZCBleHBhbmQgcGF5bG9hZHMuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRXZlbnRNZWV0aW5nRmlsdGVyIHtcclxuICAvKiogTGlmZWN5Y2xlIHN0YXR1c2VzIHRvIGluY2x1ZGUsIGUuZy4gW1wiSW4gUHJvZ3Jlc3NcIiwgXCJVcGNvbWluZ1wiXS4gKi9cclxuICBzdGF0dXM6IHN0cmluZ1tdO1xyXG4gIC8qKiBXaGV0aGVyIGV2ZXJ5IG1lZXRpbmcgKHJlZ2FyZGxlc3Mgb2YgbWVtYmVyc2hpcCkgc2hvdWxkIGJlIHJldHVybmVkLiAqL1xyXG4gIGlzQWxsTWVldGluZ1NlbGVjdGVkOiBib29sZWFuO1xyXG4gIC8qKiBPcHRpb25hbCBncm91cC1pZCBzY29wZS4gKi9cclxuICBncm91cElkcz86IHN0cmluZ1tdO1xyXG59XHJcblxyXG4vKiogUGF5bG9hZCBmb3IgYFBPU1Qge2FwaUJhc2VVcmx9L21lZXRpbmdzL2V2ZW50c0FuZE1lZXRpbmdzYCAodGhlIHNlY3Rpb24gbGlzdCkuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRXZlbnRNZWV0aW5nTGlzdFBheWxvYWQge1xyXG4gIHBheWxvYWQ6IHtcclxuICAgIC8qKiBOdWxsIGZvciB0aGUgdG9wLWxldmVsIGxpc3Q7IGFuIGV2ZW50IGlkIHdoZW4gc2NvcGluZyB0byBvbmUgZXZlbnQuICovXHJcbiAgICBldmVudElkOiBzdHJpbmcgfCBudWxsO1xyXG4gICAgc29ydENvbHVtbjogc3RyaW5nO1xyXG4gICAgYXNjZW5kaW5nT3JkZXI6IGJvb2xlYW47XHJcbiAgICBwYWdlOiBudW1iZXI7XHJcbiAgICBzaXplOiBudW1iZXI7XHJcbiAgICBzZWFyY2hUZXJtPzogc3RyaW5nIHwgbnVsbDtcclxuICAgIGZpbHRlcjogRXZlbnRNZWV0aW5nRmlsdGVyO1xyXG4gIH07XHJcbn1cclxuXHJcbi8qKiBQYXlsb2FkIGZvciBgUE9TVCB7YXBpQmFzZVVybH0vbWVldGluZ3MvbWVldGluZ3NEZXRhaWxzYCAocGVyLWV2ZW50IGV4cGFuZCkuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRXZlbnRNZWV0aW5nRGV0YWlsUGF5bG9hZCB7XHJcbiAgcGF5bG9hZDoge1xyXG4gICAgZXZlbnRJZDogc3RyaW5nO1xyXG4gICAgc29ydENvbHVtbjogc3RyaW5nO1xyXG4gICAgYXNjZW5kaW5nT3JkZXI6IGJvb2xlYW47XHJcbiAgICBwYWdlOiBudW1iZXI7XHJcbiAgICBzaXplOiBudW1iZXI7XHJcbiAgICBzZWFyY2hUZXJtPzogc3RyaW5nIHwgbnVsbDtcclxuICAgIGZpbHRlcjogRXZlbnRNZWV0aW5nRmlsdGVyO1xyXG4gIH07XHJcbn1cclxuIl19
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JvdXAtcm93Lm1vZGVsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZGFzaGJvYXJkL3NyYy9saWIvbW9kZWxzL2dyb3VwLXJvdy5tb2RlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXHJcbiAqIEEgc2luZ2xlIG5vZGUgaW4gYSBncm91cCdzIGFuY2VzdG9yIGhpZXJhcmNoeSAocm9vdOKGkmxlYWYpLCBhcyByZXR1cm5lZCBieVxyXG4gKiBHRVQgL3YxL2dyb3Vwcy9teS1ncm91cHMuIFVzZWQgdG8gcmVuZGVyIHRoZSBleHBhbmRhYmxlIGhpZXJhcmNoeSByb3dzIGluIHRoZVxyXG4gKiBZb3VyIEdyb3VwcyB0YWJsZS5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgR3JvdXBIaWVyYXJjaHlOb2RlIHtcclxuICBncm91cElkOiBzdHJpbmc7XHJcbiAgZ3JvdXBOYW1lOiBzdHJpbmc7XHJcbiAgZ3JvdXBTaG9ydE5hbWU/OiBzdHJpbmc7XHJcbiAgZ3JvdXBBY3JvbnltPzogc3RyaW5nO1xyXG4gIGdyb3VwTGV2ZWw/OiBudW1iZXI7XHJcbiAgZ3JvdXBQYXJlbnRJZD86IHN0cmluZyB8IG51bGw7XHJcbiAgZ3JvdXBUeXBlPzogc3RyaW5nO1xyXG4gIGdyb3VwVHlwZU5hbWU/OiBzdHJpbmcgfCBudWxsO1xyXG4gIGdyb3VwRGVzYz86IHN0cmluZyB8IG51bGw7XHJcbiAgaGFzQ2hpbGRyZW4/OiBib29sZWFuIHwgbnVsbDtcclxufVxyXG5cclxuLyoqXHJcbiAqIFRhYmxlLWZhY2luZyB2aWV3IG9mIGEgZ3JvdXAgaW4gdGhlIFlvdXIgR3JvdXBzIHNlY3Rpb24uIFRoZSBkaXNwbGF5IGZpZWxkc1xyXG4gKiBhcmUgbWFwcGVkIGZyb20gdGhlIGJhY2tlbmQ7IGBoaWVyYXJjaHlgIGNhcnJpZXMgdGhlIGdyb3VwJ3MgYW5jZXN0b3IgcGF0aCBzb1xyXG4gKiB0aGUgcm93IGNhbiBleHBhbmQgdG8gc2hvdyB0aGUgaGllcmFyY2h5IChtYXRjaGluZyB0aGUgTXkgUHJvZmlsZSBGaW5kIEdyb3Vwc1xyXG4gKiB0cmVlKS5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgR3JvdXBSb3cge1xyXG4gIGdyb3VwSWQ6IHN0cmluZztcclxuICBncm91cDogc3RyaW5nO1xyXG4gIHR5cGU/OiBzdHJpbmc7XHJcbiAgb2ZmaWNlclJvbGU/OiBzdHJpbmc7XHJcbiAgYWZmaWxpYXRpb24/OiBzdHJpbmc7XHJcbiAgbWVtYmVyTGV2ZWw6IHN0cmluZztcclxuICAvKiogQW5jZXN0b3IgaGllcmFyY2h5IChyb2904oaSbGVhZikgZm9yIHRoZSBleHBhbmRhYmxlIGhpZXJhcmNoeSByb3dzLiAqL1xyXG4gIGhpZXJhcmNoeT86IEdyb3VwSGllcmFyY2h5Tm9kZVtdO1xyXG59XHJcbiJdfQ==
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVldGluZy1yb3cubW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXNoYm9hcmQvc3JjL2xpYi9tb2RlbHMvbWVldGluZy1yb3cubW9kZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEF0dGVuZGFuY2VTdGF0ZSB9IGZyb20gJy4vYXR0ZW5kYW5jZS1zdGF0ZS5tb2RlbCc7XHJcblxyXG4vKipcclxuICogVmlldyBtb2RlbCBmb3IgYSBzaW5nbGUgbWVldGluZyByb3csIHVzZWQgYm90aCBmb3IgYW4gZXZlbnQncyBleHBhbmRlZCBjaGlsZFxyXG4gKiBtZWV0aW5ncyBhbmQgKHZpYSB7QGxpbmsgVXBjb21pbmdFdmVudH0pIGZvciBzdGFuZGFsb25lIG1lZXRpbmcgY2FyZHMuXHJcbiAqXHJcbiAqIGBzdGFydEVwb2NoTXNgIC8gYGVuZEVwb2NoTXNgIGNhcnJ5IHRoZSByYXcgZXBvY2gtbWlsbGlzZWNvbmRzIHZhbHVlcyBmcm9tIHRoZVxyXG4gKiBiYWNrZW5kIGFuZCBhcmUgZm9ybWF0dGVkIHdpdGggbHV4b24gYERhdGVUaW1lLmZyb21NaWxsaXNgLiBUaGUgbGVnYWN5IElTT1xyXG4gKiBgbWVldGluZ0RhdGVgIC8gYG1lZXRpbmdUaW1lYCBmaWVsZHMgYXJlIHJldGFpbmVkIGZvciBleGlzdGluZyBmaXh0dXJlcy90ZXN0cy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgTWVldGluZ1JvdyB7XHJcbiAgbWVldGluZ0lkOiBzdHJpbmc7XHJcbiAgbWVldGluZ05hbWU6IHN0cmluZztcclxuICBncm91cE9yQ29tbWl0dGVlPzogc3RyaW5nO1xyXG4gIHJvb21PckxvY2F0aW9uPzogc3RyaW5nO1xyXG4gIC8qKiBTdGFydCBkYXRlLXRpbWUgYXMgYW4gSVNPLTg2MDEgc3RyaW5nIChvciBlcG9jaCBtcyBmb3IgZml4dHVyZXMpLiAqL1xyXG4gIHN0YXJ0RGF0ZVRpbWU/OiBzdHJpbmcgfCBudW1iZXI7XHJcbiAgLyoqIEVuZCBkYXRlLXRpbWUgYXMgYW4gSVNPLTg2MDEgc3RyaW5nIChvciBlcG9jaCBtcyBmb3IgZml4dHVyZXMpLiAqL1xyXG4gIGVuZERhdGVUaW1lPzogc3RyaW5nIHwgbnVtYmVyO1xyXG4gIC8qKiBMZWdhY3kgSVNPIG1lZXRpbmcgZGF0ZSwgcmV0YWluZWQgZm9yIGZpeHR1cmVzL3Rlc3RzLiAqL1xyXG4gIG1lZXRpbmdEYXRlPzogc3RyaW5nO1xyXG4gIC8qKiBMZWdhY3kgSVNPIG1lZXRpbmcgdGltZSwgcmV0YWluZWQgZm9yIGZpeHR1cmVzL3Rlc3RzLiAqL1xyXG4gIG1lZXRpbmdUaW1lPzogc3RyaW5nO1xyXG4gIHRpbWV6b25lOiBzdHJpbmc7XHJcbiAgc3RhdHVzPzogc3RyaW5nO1xyXG4gIGlzTWVtYmVyT2ZHcm91cD86IGJvb2xlYW47XHJcbiAgaXNPcGVuRm9yQXR0ZW5kYW5jZT86IGJvb2xlYW47XHJcbiAgYXR0ZW5kYW5jZVN0YXRlPzogQXR0ZW5kYW5jZVN0YXRlO1xyXG59XHJcbiJdfQ==
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXktZ3JvdXBzLXZpZXcubW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXNoYm9hcmQvc3JjL2xpYi9tb2RlbHMvbXktZ3JvdXBzLXZpZXcubW9kZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxyXG4gKiBSZWFkLW9ubHkgYWdncmVnYXRlIHZpZXcgcmV0dXJuZWQgYnkgR0VUIC92MS9ncm91cHMvbXktZ3JvdXBzLCBtaXJyb3JpbmcgdGhlXHJcbiAqIGdyb3Vwcy1hcGkgYE15R3JvdXBzVmlld2AgRFRPLiBUaGUgZGFzaGJvYXJkIFwiWW91ciBHcm91cHNcIiBzZWN0aW9uIGNvbnN1bWVzXHJcbiAqIHRoZSBgZ3JvdXBzYCBjb2xsZWN0aW9uOyBgaW50ZXJlc3RzYCBpcyBub3Qgc2hvd24gb24gdGhlIGRhc2hib2FyZC5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgTXlHcm91cHNWaWV3IHtcclxuICBncm91cHM6IE15R3JvdXBWaWV3W107XHJcbiAgaW50ZXJlc3RzPzogTXlJbnRlcmVzdFZpZXdbXTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEEgc2luZ2xlIG9mZmljZXIgcm9sZSB0aGUgdXNlciBob2xkcyBpbiBhIGdyb3VwLCBhcyByZXR1cm5lZCBpbiB0aGVcclxuICogYG9mZmljZXJgIGFycmF5IG9mIEdFVCAvdjEvZ3JvdXBzL215LWdyb3Vwcy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgR3JvdXBPZmZpY2VyIHtcclxuICBvZmZpY2VySWQ6IHN0cmluZztcclxuICBvZmZpY2VyTmFtZTogc3RyaW5nO1xyXG59XHJcblxyXG4vKipcclxuICogQSBzaW5nbGUgZ3JvdXAgdGhlIHVzZXIgaXMgYSByb3N0ZXIgbWVtYmVyIG9mLiBDYXJyaWVzIHRoZSBncm91cCdzIG5hbWUsXHJcbiAqIHR5cGUsIGFmZmlsaWF0aW9ucywgdGhlIHVzZXIncyBtZW1iZXIgbGV2ZWwsIGFuZCB0aGUgdXNlcidzIG9mZmljZXIgcm9sZShzKVxyXG4gKiBmb3IgdGhlIGdyb3VwICh0aGUgYG9mZmljZXJgIGFycmF5IOKAlCBlbXB0eSB3aGVuIHRoZSB1c2VyIGhvbGRzIG5vIG9mZmljZXJcclxuICogcm9sZSkuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIE15R3JvdXBWaWV3IHtcclxuICBncm91cElkOiBzdHJpbmc7XHJcbiAgZ3JvdXBOYW1lOiBzdHJpbmc7XHJcbiAgZ3JvdXBUeXBlPzogc3RyaW5nO1xyXG4gIGdyb3VwVHlwZU5hbWU/OiBzdHJpbmcgfCBudWxsO1xyXG4gIC8qKiBBbmNlc3RvciBoaWVyYXJjaHkgKHJvb3TihpJsZWFmKSBvZiB0aGUgZ3JvdXAsIGZvciB0aGUgZXhwYW5kYWJsZSByb3dzLiAqL1xyXG4gIGhpZXJhcmNoeT86IE15R3JvdXBIaWVyYXJjaHlJdGVtW107XHJcbiAgYWZmaWxpYXRpb25zPzogc3RyaW5nW107XHJcbiAgbWVtYmVyTGV2ZWxJZD86IHN0cmluZyB8IG51bGw7XHJcbiAgbWVtYmVyTGV2ZWw/OiBzdHJpbmcgfCBudWxsO1xyXG4gIC8qKiBPZmZpY2VyIHJvbGVzIHRoZSB1c2VyIGhvbGRzIGluIHRoaXMgZ3JvdXAgKGUuZy4gXCJDaGFpclwiKTsgZW1wdHkgaWYgbm9uZS4gKi9cclxuICBvZmZpY2VyPzogR3JvdXBPZmZpY2VyW107XHJcbn1cclxuXHJcbi8qKiBBIHNpbmdsZSBub2RlIGluIGEgZ3JvdXAncyBhbmNlc3RvciBoaWVyYXJjaHkgKHJvb3TihpJsZWFmKS4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBNeUdyb3VwSGllcmFyY2h5SXRlbSB7XHJcbiAgZ3JvdXBJZDogc3RyaW5nO1xyXG4gIGdyb3VwTmFtZTogc3RyaW5nO1xyXG4gIGdyb3VwU2hvcnROYW1lPzogc3RyaW5nO1xyXG4gIGdyb3VwQWNyb255bT86IHN0cmluZztcclxuICBncm91cExldmVsPzogbnVtYmVyO1xyXG4gIGdyb3VwUGFyZW50SWQ/OiBzdHJpbmcgfCBudWxsO1xyXG4gIGdyb3VwVHlwZT86IHN0cmluZztcclxuICBncm91cFR5cGVOYW1lPzogc3RyaW5nIHwgbnVsbDtcclxuICBncm91cERlc2M/OiBzdHJpbmcgfCBudWxsO1xyXG4gIGhhc0NoaWxkcmVuPzogYm9vbGVhbiB8IG51bGw7XHJcbn1cclxuXHJcbi8qKiBBIHNpbmdsZSBpbnRlcmVzdCB0aGUgdXNlciBoYXMgZXhwcmVzc2VkIChub3Qgc2hvd24gb24gdGhlIGRhc2hib2FyZCkuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgTXlJbnRlcmVzdFZpZXcge1xyXG4gIGludGVyZXN0SWQ6IHN0cmluZztcclxuICBncm91cElkOiBzdHJpbmc7XHJcbiAgZ3JvdXBOYW1lOiBzdHJpbmc7XHJcbiAgc3RhdHVzOiBzdHJpbmc7XHJcbn1cclxuIl19
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnZS1jaGFuZ2UubW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXNoYm9hcmQvc3JjL2xpYi9tb2RlbHMvcGFnZS1jaGFuZ2UubW9kZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBpbnRlcmZhY2UgUGFnZUNoYW5nZSB7XHJcbiAgcGFnZUluZGV4OiBudW1iZXI7XHJcbiAgcGFnZVNpemU6IG51bWJlcjtcclxufVxyXG4iXX0=
@@ -0,0 +1,13 @@
1
+ /* eslint-disable no-unused-vars */
2
+ /**
3
+ * Discriminates how a row in the "Upcoming Meetings & Events" list is rendered.
4
+ * EVENT rows render as an expandable event block that owns child meetings;
5
+ * STANDALONE_MEETING rows render as a single meeting card and always sort LAST
6
+ * within the list.
7
+ */
8
+ export var UpcomingItemKind;
9
+ (function (UpcomingItemKind) {
10
+ UpcomingItemKind["EVENT"] = "EVENT";
11
+ UpcomingItemKind["STANDALONE_MEETING"] = "STANDALONE_MEETING";
12
+ })(UpcomingItemKind || (UpcomingItemKind = {}));
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBjb21pbmctZXZlbnQubW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXNoYm9hcmQvc3JjL2xpYi9tb2RlbHMvdXBjb21pbmctZXZlbnQubW9kZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsbUNBQW1DO0FBQ25DOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFOLElBQVksZ0JBR1g7QUFIRCxXQUFZLGdCQUFnQjtJQUMxQixtQ0FBZSxDQUFBO0lBQ2YsNkRBQXlDLENBQUE7QUFDM0MsQ0FBQyxFQUhXLGdCQUFnQixLQUFoQixnQkFBZ0IsUUFHM0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNZWV0aW5nUm93IH0gZnJvbSAnLi9tZWV0aW5nLXJvdy5tb2RlbCc7XHJcblxyXG4vKiBlc2xpbnQtZGlzYWJsZSBuby11bnVzZWQtdmFycyAqL1xyXG4vKipcclxuICogRGlzY3JpbWluYXRlcyBob3cgYSByb3cgaW4gdGhlIFwiVXBjb21pbmcgTWVldGluZ3MgJiBFdmVudHNcIiBsaXN0IGlzIHJlbmRlcmVkLlxyXG4gKiBFVkVOVCByb3dzIHJlbmRlciBhcyBhbiBleHBhbmRhYmxlIGV2ZW50IGJsb2NrIHRoYXQgb3ducyBjaGlsZCBtZWV0aW5ncztcclxuICogU1RBTkRBTE9ORV9NRUVUSU5HIHJvd3MgcmVuZGVyIGFzIGEgc2luZ2xlIG1lZXRpbmcgY2FyZCBhbmQgYWx3YXlzIHNvcnQgTEFTVFxyXG4gKiB3aXRoaW4gdGhlIGxpc3QuXHJcbiAqL1xyXG5leHBvcnQgZW51bSBVcGNvbWluZ0l0ZW1LaW5kIHtcclxuICBFVkVOVCA9ICdFVkVOVCcsXHJcbiAgU1RBTkRBTE9ORV9NRUVUSU5HID0gJ1NUQU5EQUxPTkVfTUVFVElORycsXHJcbn1cclxuLyogZXNsaW50LWVuYWJsZSBuby11bnVzZWQtdmFycyAqL1xyXG5cclxuLyoqXHJcbiAqIFZpZXcgbW9kZWwgZm9yIGEgc2luZ2xlIGVudHJ5IGluIHRoZSBcIlVwY29taW5nIE1lZXRpbmdzICYgRXZlbnRzXCIgc2VjdGlvbi5cclxuICpcclxuICogV2hlbiB7QGxpbmsga2luZH0gaXMgYEVWRU5UYCB0aGUgZW50cnkgcmVuZGVycyBhcyB0aGUgZXhwYW5kYWJsZSBldmVudCBibG9ja1xyXG4gKiAoaGVhZGVyIGJhZGdlLCB0aXRsZSwgXCJEYXkgWCBvZiBZXCIsIG1lZXRpbmctY291bnQgc3ViLWxpbmUsIGRhdGVzL3RpbWV6b25lLFxyXG4gKiBWaWV3IGJ1dHRvbiwgYW5kIHRoZSBzaG93L2hpZGUgY2hpbGQtbWVldGluZyBsaXN0KS4gV2hlbiBga2luZGAgaXNcclxuICogYFNUQU5EQUxPTkVfTUVFVElOR2AgdGhlIGVudHJ5IHJlbmRlcnMgYXMgYSBzaW5nbGUgc3RhbmRhbG9uZSBtZWV0aW5nIGNhcmRcclxuICogKHJlbmRlcmVkIGFmdGVyIGFsbCBldmVudHMpLlxyXG4gKlxyXG4gKiBgc3RhcnRFcG9jaE1zYCAvIGBlbmRFcG9jaE1zYCBjYXJyeSB0aGUgcmF3IGVwb2NoLW1pbGxpc2Vjb25kcyB2YWx1ZXMgZnJvbSB0aGVcclxuICogYmFja2VuZCBhbmQgYXJlIGZvcm1hdHRlZCB3aXRoIGx1eG9uIGBEYXRlVGltZS5mcm9tTWlsbGlzYC4gVGhlIGxlZ2FjeSBJU09cclxuICogYHN0YXJ0RGF0ZWAgLyBgZW5kRGF0ZWAgZmllbGRzIGFyZSByZXRhaW5lZCBmb3IgZXhpc3RpbmcgZml4dHVyZXMvdGVzdHMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIFVwY29taW5nRXZlbnQge1xyXG4gIGV2ZW50SWQ6IHN0cmluZztcclxuICAvKiogRVZFTlQgdnMuIFNUQU5EQUxPTkVfTUVFVElORyByZW5kZXIgZGlzY3JpbWluYXRvci4gKi9cclxuICBraW5kOiBVcGNvbWluZ0l0ZW1LaW5kO1xyXG4gIHRpdGxlOiBzdHJpbmc7XHJcbiAgc3RhdHVzOiBzdHJpbmc7XHJcbiAgZGF5SW5kaWNhdG9yPzogc3RyaW5nO1xyXG4gIG1lZXRpbmdDb3VudDogbnVtYmVyO1xyXG4gIG9wZW5Gb3JBdHRlbmRhbmNlQ291bnQ6IG51bWJlcjtcclxuICAvKiogU3RhcnQgZGF0ZS10aW1lIGFzIGFuIElTTy04NjAxIHN0cmluZyAob3IgZXBvY2ggbXMgZm9yIGZpeHR1cmVzKS4gKi9cclxuICBzdGFydERhdGVUaW1lPzogc3RyaW5nIHwgbnVtYmVyO1xyXG4gIC8qKiBFbmQgZGF0ZS10aW1lIGFzIGFuIElTTy04NjAxIHN0cmluZyAob3IgZXBvY2ggbXMgZm9yIGZpeHR1cmVzKS4gKi9cclxuICBlbmREYXRlVGltZT86IHN0cmluZyB8IG51bWJlcjtcclxuICAvKiogTGVnYWN5IElTTyBzdGFydCBkYXRlLCByZXRhaW5lZCBmb3IgZml4dHVyZXMvdGVzdHMuICovXHJcbiAgc3RhcnREYXRlPzogc3RyaW5nO1xyXG4gIC8qKiBMZWdhY3kgSVNPIGVuZCBkYXRlLCByZXRhaW5lZCBmb3IgZml4dHVyZXMvdGVzdHMuICovXHJcbiAgZW5kRGF0ZT86IHN0cmluZztcclxuICB0aW1lem9uZTogc3RyaW5nO1xyXG4gIC8qKiBPd25pbmcgZ3JvdXAgbGFiZWwsIHNob3duIG9uIHN0YW5kYWxvbmUtbWVldGluZyBjYXJkcy4gKi9cclxuICBncm91cE9yQ29tbWl0dGVlPzogc3RyaW5nO1xyXG4gIC8qKiBSb29tIC8gbG9jYXRpb24sIHNob3duIG9uIHN0YW5kYWxvbmUtbWVldGluZyBjYXJkcy4gKi9cclxuICByb29tT3JMb2NhdGlvbj86IHN0cmluZztcclxuICAvKiogVHJ1ZSB3aGVuIHRoZSB1c2VyIGlzIGEgbWVtYmVyIG9mIHRoZSBvd25pbmcgZ3JvdXAuICovXHJcbiAgaXNNZW1iZXJPZkdyb3VwPzogYm9vbGVhbjtcclxuICAvKiogVGhlIGV2ZW50J3MgY2hpbGQgbWVldGluZ3MgKGVtcHR5IC8gbGF6aWx5IGxvYWRlZCBmb3IgRVZFTlQgcm93cykuICovXHJcbiAgbWVldGluZ3M6IE1lZXRpbmdSb3dbXTtcclxufVxyXG4iXX0=
@@ -0,0 +1,54 @@
1
+ import { AttendanceState } from '../models/attendance-state.model';
2
+ /**
3
+ * Pure reducers for the dashboard attendance state. These functions never
4
+ * mutate their inputs; each returns a new object/set so they can be exercised
5
+ * directly by property tests and composed by the DashboardService.
6
+ */
7
+ /**
8
+ * Produce a new attendance-state map with the target meeting set to
9
+ * CURRENTLY_ATTENDING. Every other entry is copied unchanged (frame property).
10
+ *
11
+ * @param {Record<string, AttendanceState>} map The current attendance-state map (not mutated).
12
+ * @param {string} meetingId The meeting whose state transitions to CURRENTLY_ATTENDING.
13
+ * @return {Record<string, AttendanceState>} A new map reflecting the successful log-attendance action.
14
+ */
15
+ export const applyLogAttendanceSuccess = (map, meetingId) => ({
16
+ ...map,
17
+ [meetingId]: AttendanceState.CURRENTLY_ATTENDING,
18
+ });
19
+ /**
20
+ * Produce a new attendance-state map with the target meeting set to
21
+ * NOT_ATTENDING. Every other entry is copied unchanged (frame property).
22
+ *
23
+ * @param {Record<string, AttendanceState>} map The current attendance-state map (not mutated).
24
+ * @param {string} meetingId The meeting whose state transitions to NOT_ATTENDING.
25
+ * @return {Record<string, AttendanceState>} A new map reflecting the successful leave-meeting action.
26
+ */
27
+ export const applyLeaveMeetingSuccess = (map, meetingId) => ({
28
+ ...map,
29
+ [meetingId]: AttendanceState.NOT_ATTENDING,
30
+ });
31
+ /**
32
+ * Add a meeting to the in-flight set, returning a new set. Prior membership is
33
+ * retained so the displayed attendance state is preserved while the request
34
+ * resolves.
35
+ *
36
+ * @param {ReadonlySet<string>} set The current in-flight meeting-id set (not mutated).
37
+ * @param {string} meetingId The meeting whose attendance action has started.
38
+ * @return {Set<string>} A new set that additionally contains the meeting id.
39
+ */
40
+ export const beginAttendanceAction = (set, meetingId) => new Set([...set, meetingId]);
41
+ /**
42
+ * Remove a meeting from the in-flight set, returning a new set. All other
43
+ * in-flight ids are retained.
44
+ *
45
+ * @param {ReadonlySet<string>} set The current in-flight meeting-id set (not mutated).
46
+ * @param {string} meetingId The meeting whose attendance action has resolved.
47
+ * @return {Set<string>} A new set that no longer contains the meeting id.
48
+ */
49
+ export const endAttendanceAction = (set, meetingId) => {
50
+ const next = new Set(set);
51
+ next.delete(meetingId);
52
+ return next;
53
+ };
54
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0ZW5kYW5jZS1yZWR1Y2Vycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Rhc2hib2FyZC9zcmMvbGliL3NlcnZpY2VzL2F0dGVuZGFuY2UtcmVkdWNlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBRW5FOzs7O0dBSUc7QUFFSDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsQ0FDdkMsR0FBb0MsRUFDcEMsU0FBaUIsRUFDZ0IsRUFBRSxDQUFDLENBQUM7SUFDckMsR0FBRyxHQUFHO0lBQ04sQ0FBQyxTQUFTLENBQUMsRUFBRSxlQUFlLENBQUMsbUJBQW1CO0NBQ2pELENBQUMsQ0FBQztBQUVIOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBRyxDQUN0QyxHQUFvQyxFQUNwQyxTQUFpQixFQUNnQixFQUFFLENBQUMsQ0FBQztJQUNyQyxHQUFHLEdBQUc7SUFDTixDQUFDLFNBQVMsQ0FBQyxFQUFFLGVBQWUsQ0FBQyxhQUFhO0NBQzNDLENBQUMsQ0FBQztBQUVIOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsQ0FDbkMsR0FBd0IsRUFDeEIsU0FBaUIsRUFDSixFQUFFLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBRS9DOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxDQUNqQyxHQUF3QixFQUN4QixTQUFpQixFQUNKLEVBQUU7SUFDZixNQUFNLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMxQixJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3ZCLE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQXR0ZW5kYW5jZVN0YXRlIH0gZnJvbSAnLi4vbW9kZWxzL2F0dGVuZGFuY2Utc3RhdGUubW9kZWwnO1xyXG5cclxuLyoqXHJcbiAqIFB1cmUgcmVkdWNlcnMgZm9yIHRoZSBkYXNoYm9hcmQgYXR0ZW5kYW5jZSBzdGF0ZS4gVGhlc2UgZnVuY3Rpb25zIG5ldmVyXHJcbiAqIG11dGF0ZSB0aGVpciBpbnB1dHM7IGVhY2ggcmV0dXJucyBhIG5ldyBvYmplY3Qvc2V0IHNvIHRoZXkgY2FuIGJlIGV4ZXJjaXNlZFxyXG4gKiBkaXJlY3RseSBieSBwcm9wZXJ0eSB0ZXN0cyBhbmQgY29tcG9zZWQgYnkgdGhlIERhc2hib2FyZFNlcnZpY2UuXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFByb2R1Y2UgYSBuZXcgYXR0ZW5kYW5jZS1zdGF0ZSBtYXAgd2l0aCB0aGUgdGFyZ2V0IG1lZXRpbmcgc2V0IHRvXHJcbiAqIENVUlJFTlRMWV9BVFRFTkRJTkcuIEV2ZXJ5IG90aGVyIGVudHJ5IGlzIGNvcGllZCB1bmNoYW5nZWQgKGZyYW1lIHByb3BlcnR5KS5cclxuICpcclxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBBdHRlbmRhbmNlU3RhdGU+fSBtYXAgVGhlIGN1cnJlbnQgYXR0ZW5kYW5jZS1zdGF0ZSBtYXAgKG5vdCBtdXRhdGVkKS5cclxuICogQHBhcmFtIHtzdHJpbmd9IG1lZXRpbmdJZCBUaGUgbWVldGluZyB3aG9zZSBzdGF0ZSB0cmFuc2l0aW9ucyB0byBDVVJSRU5UTFlfQVRURU5ESU5HLlxyXG4gKiBAcmV0dXJuIHtSZWNvcmQ8c3RyaW5nLCBBdHRlbmRhbmNlU3RhdGU+fSBBIG5ldyBtYXAgcmVmbGVjdGluZyB0aGUgc3VjY2Vzc2Z1bCBsb2ctYXR0ZW5kYW5jZSBhY3Rpb24uXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgYXBwbHlMb2dBdHRlbmRhbmNlU3VjY2VzcyA9IChcclxuICBtYXA6IFJlY29yZDxzdHJpbmcsIEF0dGVuZGFuY2VTdGF0ZT4sXHJcbiAgbWVldGluZ0lkOiBzdHJpbmdcclxuKTogUmVjb3JkPHN0cmluZywgQXR0ZW5kYW5jZVN0YXRlPiA9PiAoe1xyXG4gIC4uLm1hcCxcclxuICBbbWVldGluZ0lkXTogQXR0ZW5kYW5jZVN0YXRlLkNVUlJFTlRMWV9BVFRFTkRJTkcsXHJcbn0pO1xyXG5cclxuLyoqXHJcbiAqIFByb2R1Y2UgYSBuZXcgYXR0ZW5kYW5jZS1zdGF0ZSBtYXAgd2l0aCB0aGUgdGFyZ2V0IG1lZXRpbmcgc2V0IHRvXHJcbiAqIE5PVF9BVFRFTkRJTkcuIEV2ZXJ5IG90aGVyIGVudHJ5IGlzIGNvcGllZCB1bmNoYW5nZWQgKGZyYW1lIHByb3BlcnR5KS5cclxuICpcclxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBBdHRlbmRhbmNlU3RhdGU+fSBtYXAgVGhlIGN1cnJlbnQgYXR0ZW5kYW5jZS1zdGF0ZSBtYXAgKG5vdCBtdXRhdGVkKS5cclxuICogQHBhcmFtIHtzdHJpbmd9IG1lZXRpbmdJZCBUaGUgbWVldGluZyB3aG9zZSBzdGF0ZSB0cmFuc2l0aW9ucyB0byBOT1RfQVRURU5ESU5HLlxyXG4gKiBAcmV0dXJuIHtSZWNvcmQ8c3RyaW5nLCBBdHRlbmRhbmNlU3RhdGU+fSBBIG5ldyBtYXAgcmVmbGVjdGluZyB0aGUgc3VjY2Vzc2Z1bCBsZWF2ZS1tZWV0aW5nIGFjdGlvbi5cclxuICovXHJcbmV4cG9ydCBjb25zdCBhcHBseUxlYXZlTWVldGluZ1N1Y2Nlc3MgPSAoXHJcbiAgbWFwOiBSZWNvcmQ8c3RyaW5nLCBBdHRlbmRhbmNlU3RhdGU+LFxyXG4gIG1lZXRpbmdJZDogc3RyaW5nXHJcbik6IFJlY29yZDxzdHJpbmcsIEF0dGVuZGFuY2VTdGF0ZT4gPT4gKHtcclxuICAuLi5tYXAsXHJcbiAgW21lZXRpbmdJZF06IEF0dGVuZGFuY2VTdGF0ZS5OT1RfQVRURU5ESU5HLFxyXG59KTtcclxuXHJcbi8qKlxyXG4gKiBBZGQgYSBtZWV0aW5nIHRvIHRoZSBpbi1mbGlnaHQgc2V0LCByZXR1cm5pbmcgYSBuZXcgc2V0LiBQcmlvciBtZW1iZXJzaGlwIGlzXHJcbiAqIHJldGFpbmVkIHNvIHRoZSBkaXNwbGF5ZWQgYXR0ZW5kYW5jZSBzdGF0ZSBpcyBwcmVzZXJ2ZWQgd2hpbGUgdGhlIHJlcXVlc3RcclxuICogcmVzb2x2ZXMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7UmVhZG9ubHlTZXQ8c3RyaW5nPn0gc2V0IFRoZSBjdXJyZW50IGluLWZsaWdodCBtZWV0aW5nLWlkIHNldCAobm90IG11dGF0ZWQpLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVldGluZ0lkIFRoZSBtZWV0aW5nIHdob3NlIGF0dGVuZGFuY2UgYWN0aW9uIGhhcyBzdGFydGVkLlxyXG4gKiBAcmV0dXJuIHtTZXQ8c3RyaW5nPn0gQSBuZXcgc2V0IHRoYXQgYWRkaXRpb25hbGx5IGNvbnRhaW5zIHRoZSBtZWV0aW5nIGlkLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IGJlZ2luQXR0ZW5kYW5jZUFjdGlvbiA9IChcclxuICBzZXQ6IFJlYWRvbmx5U2V0PHN0cmluZz4sXHJcbiAgbWVldGluZ0lkOiBzdHJpbmdcclxuKTogU2V0PHN0cmluZz4gPT4gbmV3IFNldChbLi4uc2V0LCBtZWV0aW5nSWRdKTtcclxuXHJcbi8qKlxyXG4gKiBSZW1vdmUgYSBtZWV0aW5nIGZyb20gdGhlIGluLWZsaWdodCBzZXQsIHJldHVybmluZyBhIG5ldyBzZXQuIEFsbCBvdGhlclxyXG4gKiBpbi1mbGlnaHQgaWRzIGFyZSByZXRhaW5lZC5cclxuICpcclxuICogQHBhcmFtIHtSZWFkb25seVNldDxzdHJpbmc+fSBzZXQgVGhlIGN1cnJlbnQgaW4tZmxpZ2h0IG1lZXRpbmctaWQgc2V0IChub3QgbXV0YXRlZCkuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZWV0aW5nSWQgVGhlIG1lZXRpbmcgd2hvc2UgYXR0ZW5kYW5jZSBhY3Rpb24gaGFzIHJlc29sdmVkLlxyXG4gKiBAcmV0dXJuIHtTZXQ8c3RyaW5nPn0gQSBuZXcgc2V0IHRoYXQgbm8gbG9uZ2VyIGNvbnRhaW5zIHRoZSBtZWV0aW5nIGlkLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IGVuZEF0dGVuZGFuY2VBY3Rpb24gPSAoXHJcbiAgc2V0OiBSZWFkb25seVNldDxzdHJpbmc+LFxyXG4gIG1lZXRpbmdJZDogc3RyaW5nXHJcbik6IFNldDxzdHJpbmc+ID0+IHtcclxuICBjb25zdCBuZXh0ID0gbmV3IFNldChzZXQpO1xyXG4gIG5leHQuZGVsZXRlKG1lZXRpbmdJZCk7XHJcbiAgcmV0dXJuIG5leHQ7XHJcbn07XHJcbiJdfQ==
@@ -0,0 +1,402 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { BehaviorSubject, catchError, map, of, } from 'rxjs';
3
+ import { AttendanceState } from '../models/attendance-state.model';
4
+ import { DashboardSectionState } from '../models/dashboard-section-state.model';
5
+ import { UpcomingItemKind, } from '../models/upcoming-event.model';
6
+ import { mapEventMeetingDetails, mapEventMeetingList, } from '../utils/event-meeting-mapper.util';
7
+ import { applyLeaveMeetingSuccess, applyLogAttendanceSuccess, beginAttendanceAction, endAttendanceAction, } from './attendance-reducers';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "@ieeesa-npm/utility";
10
+ /** Fallback label for an empty group type / member level, matching the My Groups tab. */
11
+ const UNASSIGNED_LABEL = 'Unassigned';
12
+ /** Placeholder for an empty cell value. */
13
+ const EMPTY_VALUE = '-';
14
+ /** Statuses included in the upcoming section, matching the view-events-meetings-list screen. */
15
+ const UPCOMING_STATUSES = ['In Progress', 'Upcoming'];
16
+ /** Sort column used for the top-level events & meetings list. */
17
+ const UPCOMING_SORT_COLUMN = 'startDateTime';
18
+ /** Sort column used for an event's expanded child-meeting list (meetingsDetails). */
19
+ const EVENT_MEETINGS_SORT_COLUMN = 'meetingStDate';
20
+ /** Default page size for the top-level upcoming section list. */
21
+ const UPCOMING_PAGE_SIZE = 10;
22
+ /** Default page size for an event's expanded child-meeting list. */
23
+ const EVENT_MEETINGS_PAGE_SIZE = 5;
24
+ /** Large page size used by the eager count prefetch to capture the full set. */
25
+ const EVENT_COUNT_PAGE_SIZE = 200;
26
+ /**
27
+ * DashboardService is the single source of truth for the dashboard landing
28
+ * page's data and attendance state. It mirrors the `events-and-meetings`
29
+ * service conventions: it is a `providedIn: 'root'` singleton, holds the host
30
+ * `apiBaseUrl` / `userPermissions` set via {@link setAppConfig}, owns its state
31
+ * via `BehaviorSubject`s exposed as observables, and reaches the backend only
32
+ * through the shared `HttpService` from `@ieeesa-npm/utility` (never
33
+ * `HttpClient` directly).
34
+ *
35
+ * The upcoming-events load calls the real `POST /meetings/eventsAndMeetings`
36
+ * endpoint (child meetings are lazily loaded per-event via
37
+ * `POST /meetings/meetingsDetails`); the groups load calls `GET
38
+ * /groups/my-groups`. The attendance actions compose the pure reducers from
39
+ * `attendance-reducers.ts` so the displayed `AttendanceState` only advances on a
40
+ * successful resolution and the prior state is retained on failure.
41
+ * @export
42
+ * @class DashboardService
43
+ */
44
+ export class DashboardService {
45
+ constructor(
46
+ // eslint-disable-next-line no-unused-vars
47
+ httpService // eslint-disable-next-line no-empty-function
48
+ ) {
49
+ this.httpService = httpService;
50
+ this.upcomingEvents = new BehaviorSubject([]);
51
+ this.groups = new BehaviorSubject([]);
52
+ this.upcomingState = new BehaviorSubject(DashboardSectionState.LOADING);
53
+ this.groupsState = new BehaviorSubject(DashboardSectionState.LOADING);
54
+ this.attendanceStates = new BehaviorSubject({});
55
+ this.inFlightMeetingIds = new BehaviorSubject(new Set());
56
+ /** Emits the list of the user's upcoming events. */
57
+ this.upcomingEvents$ = this.upcomingEvents.asObservable();
58
+ /** Emits the list of the user's groups. */
59
+ this.groups$ = this.groups.asObservable();
60
+ /** Emits the load/empty/error state of the upcoming-events section. */
61
+ this.upcomingState$ = this.upcomingState.asObservable();
62
+ /** Emits the load/empty/error state of the groups section. */
63
+ this.groupsState$ = this.groupsState.asObservable();
64
+ /** Emits the per-meeting attendance-state map. */
65
+ this.attendanceStates$ = this.attendanceStates.asObservable();
66
+ /** Emits the set of meeting ids with an attendance action in flight. */
67
+ this.inFlightMeetingIds$ = this.inFlightMeetingIds.asObservable();
68
+ }
69
+ /**
70
+ * Stores the host-supplied API base URL and user permissions used to build
71
+ * request URLs and gate permission-controlled actions. Mirrors the
72
+ * `events-and-meetings` service `setAppConfig`.
73
+ * @param {string} apiBaseURL - The host application's API base URL.
74
+ * @param {UserPermission[]} userPermissions - The signed-in user's permissions.
75
+ * @return {void}
76
+ * @memberof DashboardService
77
+ */
78
+ setAppConfig(apiBaseURL, userPermissions) {
79
+ this.apiBaseUrl = apiBaseURL;
80
+ this.userPermissions = userPermissions;
81
+ }
82
+ /**
83
+ * Loads the user's upcoming events & meetings from the real backend via
84
+ * `POST {apiBaseUrl}/meetings/eventsAndMeetings`, the same endpoint the
85
+ * `view-events-meetings-list` screen uses. The response is mapped into the
86
+ * dashboard view models (with STANDALONE_MEETING rows ordered last), the
87
+ * per-meeting attendance-state map is seeded, and the section advances through
88
+ * LOADING → LOADED/EMPTY on success, leaving the caller to set ERROR on
89
+ * failure. Follows the shared `pipe(map, catchError(throw))` pattern.
90
+ * @return {Observable<EventMeetingListResponse>} The upcoming events & meetings response envelope.
91
+ * @memberof DashboardService
92
+ */
93
+ loadUpcomingEvents() {
94
+ this.upcomingState.next(DashboardSectionState.LOADING);
95
+ const payload = {
96
+ payload: {
97
+ eventId: null,
98
+ sortColumn: UPCOMING_SORT_COLUMN,
99
+ ascendingOrder: true,
100
+ page: 1,
101
+ size: UPCOMING_PAGE_SIZE,
102
+ filter: {
103
+ status: UPCOMING_STATUSES,
104
+ isAllMeetingSelected: false,
105
+ },
106
+ },
107
+ };
108
+ return this.httpService
109
+ .postData(`${this.apiBaseUrl}/meetings/eventsAndMeetings`, payload)
110
+ .pipe(map((response) => {
111
+ const events = mapEventMeetingList(response?.body?.eventMeetingList ?? []);
112
+ this.upcomingEvents.next(events);
113
+ this.seedAttendanceStates(events);
114
+ this.upcomingState.next(events.length > 0
115
+ ? DashboardSectionState.LOADED
116
+ : DashboardSectionState.EMPTY);
117
+ // Eagerly fetch each EVENT's meeting count so the "{n} meetings" and
118
+ // "{n} open for attendance" summaries are correct before expanding.
119
+ this.loadEventCounts(events);
120
+ return response;
121
+ }), catchError((error) => {
122
+ this.upcomingState.next(DashboardSectionState.ERROR);
123
+ throw error;
124
+ }));
125
+ }
126
+ /**
127
+ * Lazily loads (and paginates) the child meetings of an EVENT row via
128
+ * `POST {apiBaseUrl}/meetings/meetingsDetails` — the per-event expand endpoint
129
+ * used by the reference screen. On success the loaded meetings are mapped and
130
+ * merged onto the matching event in the `upcomingEvents` list (with its
131
+ * `meetingCount` / `openForAttendanceCount` refreshed), and the per-meeting
132
+ * attendance-state map is extended. Each event paginates independently.
133
+ * @param {string} eventId - The event whose meetings to load.
134
+ * @param {number} [page=1] - The one-based page to request.
135
+ * @param {number} [size=EVENT_MEETINGS_PAGE_SIZE] - The page size.
136
+ * @return {Observable<EventMeetingDetailResponse>} The child-meetings response envelope.
137
+ * @memberof DashboardService
138
+ */
139
+ loadEventMeetings(eventId, page = 1, size = EVENT_MEETINGS_PAGE_SIZE) {
140
+ return this.fetchEventMeetingsPage(eventId, page, size).pipe(map((response) => {
141
+ const meetings = mapEventMeetingDetails(response?.body?.meetings ?? []);
142
+ const total = response?.body?.totalRecords ?? meetings.length;
143
+ // Prefer the already-known full open count on the event; fall back to
144
+ // the current page's open count when it hasn't been prefetched.
145
+ const existing = this.upcomingEvents.value.find((event) => event.eventId === eventId);
146
+ const pageOpenCount = meetings.filter((meeting) => meeting.isOpenForAttendance).length;
147
+ const openForAttendanceCount = existing?.openForAttendanceCount || pageOpenCount;
148
+ this.mergeEventMeetings(eventId, meetings, total, openForAttendanceCount);
149
+ this.seedAttendanceStatesFromMeetings(meetings);
150
+ return response;
151
+ }), catchError((error) => {
152
+ throw error;
153
+ }));
154
+ }
155
+ /**
156
+ * Merges a freshly loaded page of child meetings onto the matching event in
157
+ * the `upcomingEvents` list, refreshing the event's `meetings`,
158
+ * `meetingCount` (from the backend `totalRecords`), and
159
+ * `openForAttendanceCount`. Leaves all other events untouched.
160
+ * @param {string} eventId - The event to merge meetings onto.
161
+ * @param {MeetingRow[]} meetings - The mapped child meetings for the page.
162
+ * @param {number} totalRecords - The event's total meeting count from the backend.
163
+ * @return {void}
164
+ * @memberof DashboardService
165
+ */
166
+ mergeEventMeetings(eventId, meetings, totalRecords, openForAttendanceCount) {
167
+ const next = this.upcomingEvents.value.map((event) => {
168
+ if (event.eventId !== eventId) {
169
+ return event;
170
+ }
171
+ return {
172
+ ...event,
173
+ meetings,
174
+ meetingCount: totalRecords,
175
+ openForAttendanceCount,
176
+ };
177
+ });
178
+ this.upcomingEvents.next(next);
179
+ }
180
+ /**
181
+ * Eagerly fetches each EVENT's total meeting count and open-for-attendance
182
+ * count by requesting a large first page of its child meetings, then merging
183
+ * only the counts (not the rows) so the collapsed card summaries are accurate
184
+ * before the user expands. Standalone meetings are skipped. Failures per event
185
+ * are swallowed so one failing count never breaks the list.
186
+ * @param {UpcomingEvent[]} events - The loaded events to fetch counts for.
187
+ * @return {void}
188
+ * @memberof DashboardService
189
+ */
190
+ loadEventCounts(events) {
191
+ events
192
+ .filter((event) => event.kind === UpcomingItemKind.EVENT && event.eventId)
193
+ .forEach((event) => {
194
+ this.fetchEventMeetingsPage(event.eventId, 1, EVENT_COUNT_PAGE_SIZE)
195
+ .pipe(catchError(() => of(null)))
196
+ .subscribe((response) => {
197
+ if (!response) {
198
+ return;
199
+ }
200
+ const meetings = mapEventMeetingDetails(response?.body?.meetings ?? []);
201
+ const total = response?.body?.totalRecords ?? meetings.length;
202
+ const openCount = meetings.filter((meeting) => meeting.isOpenForAttendance).length;
203
+ this.mergeEventCounts(event.eventId, total, openCount);
204
+ this.seedAttendanceStatesFromMeetings(meetings);
205
+ });
206
+ });
207
+ }
208
+ /**
209
+ * Merges only the meeting counts onto the matching event, leaving its
210
+ * `meetings` rows untouched (used by the eager count prefetch).
211
+ * @param {string} eventId - The event to update.
212
+ * @param {number} totalRecords - The event's total meeting count.
213
+ * @param {number} openForAttendanceCount - The open-for-attendance count.
214
+ * @return {void}
215
+ * @memberof DashboardService
216
+ */
217
+ mergeEventCounts(eventId, totalRecords, openForAttendanceCount) {
218
+ const next = this.upcomingEvents.value.map((event) => event.eventId === eventId
219
+ ? { ...event, meetingCount: totalRecords, openForAttendanceCount }
220
+ : event);
221
+ this.upcomingEvents.next(next);
222
+ }
223
+ /**
224
+ * Builds and posts the `meetingsDetails` request for a single event page,
225
+ * returning the raw response envelope. Shared by {@link loadEventMeetings} and
226
+ * the eager count prefetch.
227
+ * @param {string} eventId - The event whose meetings to fetch.
228
+ * @param {number} page - The one-based page to request.
229
+ * @param {number} size - The page size.
230
+ * @return {Observable<EventMeetingDetailResponse>} The child-meetings response.
231
+ * @memberof DashboardService
232
+ */
233
+ fetchEventMeetingsPage(eventId, page, size) {
234
+ const payload = {
235
+ payload: {
236
+ eventId,
237
+ sortColumn: EVENT_MEETINGS_SORT_COLUMN,
238
+ ascendingOrder: true,
239
+ page,
240
+ size,
241
+ filter: {
242
+ status: UPCOMING_STATUSES,
243
+ isAllMeetingSelected: false,
244
+ },
245
+ },
246
+ };
247
+ return this.httpService.postData(`${this.apiBaseUrl}/meetings/meetingsDetails`, payload);
248
+ }
249
+ /**
250
+ * Loads the user's groups, driving the groups section through
251
+ * LOADING → LOADED/EMPTY on success and leaving the caller to set ERROR on
252
+ * failure. Follows the `pipe(map, catchError(throw))` pattern.
253
+ *
254
+ * TODO: Replace mock with real API call when BE is ready
255
+ * @return {Observable<DashboardListResponse<GroupRow[]>>} The groups response envelope.
256
+ * @memberof DashboardService
257
+ */
258
+ loadGroups() {
259
+ this.groupsState.next(DashboardSectionState.LOADING);
260
+ return this.httpService
261
+ .getData(`${this.apiBaseUrl}/groups/my-groups`)
262
+ .pipe(map((response) => {
263
+ const groups = (response?.body?.groups ?? []).map((group) => this.mapGroup(group));
264
+ this.groups.next(groups);
265
+ this.groupsState.next(groups.length > 0
266
+ ? DashboardSectionState.LOADED
267
+ : DashboardSectionState.EMPTY);
268
+ return response;
269
+ }), catchError((error) => {
270
+ this.groupsState.next(DashboardSectionState.ERROR);
271
+ throw error;
272
+ }));
273
+ }
274
+ /**
275
+ * Maps a backend {@link MyGroupView} to the table-facing {@link GroupRow}.
276
+ * Mirrors the My Groups profile tab: the type falls back to "Unassigned" when
277
+ * `groupTypeName` is null, affiliations are comma-joined, empty officer role /
278
+ * affiliation render as a placeholder, and a blank member level becomes
279
+ * "Unassigned" (rendered as the warning pill by the Your Groups component).
280
+ * @param {MyGroupView} group - The backend group view.
281
+ * @return {GroupRow}
282
+ * @memberof DashboardService
283
+ */
284
+ mapGroup(group) {
285
+ // The backend returns officer roles as an `officer` array of
286
+ // { officerId, officerName }. Join the names for the Officer Role column
287
+ // (e.g. "Chair" or "Chair, Vice Chair"); show the placeholder when empty.
288
+ const officerRole = (group.officer ?? [])
289
+ .map((officer) => officer?.officerName?.trim())
290
+ .filter((name) => !!name)
291
+ .join(', ') || EMPTY_VALUE;
292
+ return {
293
+ groupId: group.groupId,
294
+ group: group.groupName,
295
+ type: group.groupTypeName || group.groupType || UNASSIGNED_LABEL,
296
+ officerRole,
297
+ affiliation: group.affiliations?.join(', ') || EMPTY_VALUE,
298
+ memberLevel: group.memberLevel?.trim() || UNASSIGNED_LABEL,
299
+ // Carry the ancestor hierarchy through for the expandable hierarchy rows.
300
+ hierarchy: group.hierarchy ?? [],
301
+ };
302
+ }
303
+ /**
304
+ * Logs attendance for a meeting. Marks the meeting in-flight (retaining the
305
+ * prior displayed state), posts through `HttpService`, applies the
306
+ * log-attendance-success reducer on success, clears the in-flight flag on
307
+ * completion, and rethrows while retaining prior state on failure.
308
+ * @param {string} meetingId - The meeting to log attendance for.
309
+ * @return {Observable<DashboardListResponse<unknown>>} The attendance response envelope.
310
+ * @memberof DashboardService
311
+ */
312
+ logAttendance(meetingId) {
313
+ this.inFlightMeetingIds.next(beginAttendanceAction(this.inFlightMeetingIds.value, meetingId));
314
+ return this.httpService
315
+ .postData(`${this.apiBaseUrl}/meetings/attendance/log`, { meetingId })
316
+ .pipe(map((response) => {
317
+ this.attendanceStates.next(applyLogAttendanceSuccess(this.attendanceStates.value, meetingId));
318
+ this.inFlightMeetingIds.next(endAttendanceAction(this.inFlightMeetingIds.value, meetingId));
319
+ return response;
320
+ }), catchError((error) => {
321
+ // Retain prior attendance state; only clear the in-flight flag.
322
+ this.inFlightMeetingIds.next(endAttendanceAction(this.inFlightMeetingIds.value, meetingId));
323
+ throw error;
324
+ }));
325
+ }
326
+ /**
327
+ * Leaves a meeting. Marks the meeting in-flight (retaining the prior
328
+ * displayed state), posts through `HttpService`, applies the
329
+ * leave-meeting-success reducer on success, clears the in-flight flag on
330
+ * completion, and rethrows while retaining prior state on failure.
331
+ * @param {string} meetingId - The meeting to leave.
332
+ * @return {Observable<DashboardListResponse<unknown>>} The attendance response envelope.
333
+ * @memberof DashboardService
334
+ */
335
+ leaveMeeting(meetingId) {
336
+ this.inFlightMeetingIds.next(beginAttendanceAction(this.inFlightMeetingIds.value, meetingId));
337
+ return this.httpService
338
+ .postData(`${this.apiBaseUrl}/meetings/attendance/leave`, { meetingId })
339
+ .pipe(map((response) => {
340
+ this.attendanceStates.next(applyLeaveMeetingSuccess(this.attendanceStates.value, meetingId));
341
+ this.inFlightMeetingIds.next(endAttendanceAction(this.inFlightMeetingIds.value, meetingId));
342
+ return response;
343
+ }), catchError((error) => {
344
+ // Retain prior attendance state; only clear the in-flight flag.
345
+ this.inFlightMeetingIds.next(endAttendanceAction(this.inFlightMeetingIds.value, meetingId));
346
+ throw error;
347
+ }));
348
+ }
349
+ /**
350
+ * Returns a synchronous snapshot of the per-meeting attendance-state map.
351
+ * @return {Record<string, AttendanceState>} The current attendance-state map.
352
+ * @memberof DashboardService
353
+ */
354
+ getAttendanceStatesSnapshot() {
355
+ return this.attendanceStates.value;
356
+ }
357
+ /**
358
+ * Seeds the attendance-state map from a freshly loaded list of events, using
359
+ * each meeting's `attendanceState` (defaulting to `NOT_ATTENDING`). Keeps the
360
+ * displayed state in sync with the data load without overwriting ids that are
361
+ * not present in the new list.
362
+ * @param {UpcomingEvent[]} events - The loaded upcoming events.
363
+ * @return {void}
364
+ * @memberof DashboardService
365
+ */
366
+ seedAttendanceStates(events) {
367
+ const meetings = events.flatMap((event) => event.meetings ?? []);
368
+ this.seedAttendanceStatesFromMeetings(meetings);
369
+ }
370
+ /**
371
+ * Seeds the attendance-state map from a list of meeting rows, using each
372
+ * meeting's `attendanceState` (defaulting to `NOT_ATTENDING`) without
373
+ * overwriting ids absent from the new list. Shared by the list load and the
374
+ * per-event expand so freshly loaded child meetings pick up their state.
375
+ * @param {MeetingRow[]} meetings - The meeting rows to seed from.
376
+ * @return {void}
377
+ * @memberof DashboardService
378
+ */
379
+ seedAttendanceStatesFromMeetings(meetings) {
380
+ const next = {
381
+ ...this.attendanceStates.value,
382
+ };
383
+ meetings.forEach((meeting) => {
384
+ if (meeting.meetingId) {
385
+ next[meeting.meetingId] =
386
+ meeting.attendanceState ??
387
+ next[meeting.meetingId] ??
388
+ AttendanceState.NOT_ATTENDING;
389
+ }
390
+ });
391
+ this.attendanceStates.next(next);
392
+ }
393
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DashboardService, deps: [{ token: i1.HttpService }], target: i0.ɵɵFactoryTarget.Injectable }); }
394
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DashboardService, providedIn: 'root' }); }
395
+ }
396
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DashboardService, decorators: [{
397
+ type: Injectable,
398
+ args: [{
399
+ providedIn: 'root',
400
+ }]
401
+ }], ctorParameters: function () { return [{ type: i1.HttpService }]; } });
402
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGFzaGJvYXJkLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXNoYm9hcmQvc3JjL2xpYi9zZXJ2aWNlcy9kYXNoYm9hcmQuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFDTCxlQUFlLEVBRWYsVUFBVSxFQUNWLEdBQUcsRUFDSCxFQUFFLEdBQ0gsTUFBTSxNQUFNLENBQUM7QUFHZCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFFbkUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFNaEYsT0FBTyxFQUVMLGdCQUFnQixHQUNqQixNQUFNLGdDQUFnQyxDQUFDO0FBU3hDLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsbUJBQW1CLEdBQ3BCLE1BQU0sb0NBQW9DLENBQUM7QUFtQjVDLE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIseUJBQXlCLEVBQ3pCLHFCQUFxQixFQUNyQixtQkFBbUIsR0FDcEIsTUFBTSx1QkFBdUIsQ0FBQzs7O0FBckIvQix5RkFBeUY7QUFDekYsTUFBTSxnQkFBZ0IsR0FBRyxZQUFZLENBQUM7QUFDdEMsMkNBQTJDO0FBQzNDLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQztBQUN4QixnR0FBZ0c7QUFDaEcsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLGFBQWEsRUFBRSxVQUFVLENBQUMsQ0FBQztBQUN0RCxpRUFBaUU7QUFDakUsTUFBTSxvQkFBb0IsR0FBRyxlQUFlLENBQUM7QUFDN0MscUZBQXFGO0FBQ3JGLE1BQU0sMEJBQTBCLEdBQUcsZUFBZSxDQUFDO0FBQ25ELGlFQUFpRTtBQUNqRSxNQUFNLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztBQUM5QixvRUFBb0U7QUFDcEUsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLENBQUM7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LENBQUMsS0FBSztTQUMvQixDQUFDO1FBQ0YsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQzNCLElBQUksT0FBTyxDQUFDLFNBQVMsRUFBRTtnQkFDckIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUM7b0JBQ3JCLE9BQU8sQ0FBQyxlQUFlO3dCQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQzt3QkFDdkIsZUFBZSxDQUFDLGFBQWEsQ0FBQzthQUNqQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuQyxDQUFDOytHQTFjVSxnQkFBZ0I7bUhBQWhCLGdCQUFnQixjQUZmLE1BQU07OzRGQUVQLGdCQUFnQjtrQkFINUIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7XHJcbiAgQmVoYXZpb3JTdWJqZWN0LFxyXG4gIE9ic2VydmFibGUsXHJcbiAgY2F0Y2hFcnJvcixcclxuICBtYXAsXHJcbiAgb2YsXHJcbn0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IEh0dHBTZXJ2aWNlIH0gZnJvbSAnQGllZWVzYS1ucG0vdXRpbGl0eSc7XHJcbmltcG9ydCB7IFVzZXJQZXJtaXNzaW9uIH0gZnJvbSAnQGllZWVzYS1ucG0vbW9kZWxzJztcclxuaW1wb3J0IHsgQXR0ZW5kYW5jZVN0YXRlIH0gZnJvbSAnLi4vbW9kZWxzL2F0dGVuZGFuY2Utc3RhdGUubW9kZWwnO1xyXG5pbXBvcnQgeyBEYXNoYm9hcmRMaXN0UmVzcG9uc2UgfSBmcm9tICcuLi9tb2RlbHMvZGFzaGJvYXJkLWxpc3QtcmVzcG9uc2UubW9kZWwnO1xyXG5pbXBvcnQgeyBEYXNoYm9hcmRTZWN0aW9uU3RhdGUgfSBmcm9tICcuLi9tb2RlbHMvZGFzaGJvYXJkLXNlY3Rpb24tc3RhdGUubW9kZWwnO1xyXG5pbXBvcnQgeyBHcm91cFJvdyB9IGZyb20gJy4uL21vZGVscy9ncm91cC1yb3cubW9kZWwnO1xyXG5pbXBvcnQge1xyXG4gIE15R3JvdXBzVmlldyxcclxuICBNeUdyb3VwVmlldyxcclxufSBmcm9tICcuLi9tb2RlbHMvbXktZ3JvdXBzLXZpZXcubW9kZWwnO1xyXG5pbXBvcnQge1xyXG4gIFVwY29taW5nRXZlbnQsXHJcbiAgVXBjb21pbmdJdGVtS2luZCxcclxufSBmcm9tICcuLi9tb2RlbHMvdXBjb21pbmctZXZlbnQubW9kZWwnO1xyXG5pbXBvcnQge1xyXG4gIEV2ZW50TWVldGluZ0RldGFpbFBheWxvYWQsXHJcbiAgRXZlbnRNZWV0aW5nTGlzdFBheWxvYWQsXHJcbn0gZnJvbSAnLi4vbW9kZWxzL2V2ZW50LW1lZXRpbmctbGlzdC1wYXlsb2FkLm1vZGVsJztcclxuaW1wb3J0IHtcclxuICBFdmVudE1lZXRpbmdEZXRhaWxSZXNwb25zZSxcclxuICBFdmVudE1lZXRpbmdMaXN0UmVzcG9uc2UsXHJcbn0gZnJvbSAnLi4vbW9kZWxzL2V2ZW50LW1lZXRpbmctbGlzdC1pdGVtLm1vZGVsJztcclxuaW1wb3J0IHtcclxuICBtYXBFdmVudE1lZXRpbmdEZXRhaWxzLFxyXG4gIG1hcEV2ZW50TWVldGluZ0xpc3QsXHJcbn0gZnJvbSAnLi4vdXRpbHMvZXZlbnQtbWVldGluZy1tYXBwZXIudXRpbCc7XHJcbmltcG9ydCB7IE1lZXRpbmdSb3cgfSBmcm9tICcuLi9tb2RlbHMvbWVldGluZy1yb3cubW9kZWwnO1xyXG5cclxuLyoqIEZhbGxiYWNrIGxhYmVsIGZvciBhbiBlbXB0eSBncm91cCB0eXBlIC8gbWVtYmVyIGxldmVsLCBtYXRjaGluZyB0aGUgTXkgR3JvdXBzIHRhYi4gKi9cclxuY29uc3QgVU5BU1NJR05FRF9MQUJFTCA9ICdVbmFzc2lnbmVkJztcclxuLyoqIFBsYWNlaG9sZGVyIGZvciBhbiBlbXB0eSBjZWxsIHZhbHVlLiAqL1xyXG5jb25zdCBFTVBUWV9WQUxVRSA9ICctJztcclxuLyoqIFN0YXR1c2VzIGluY2x1ZGVkIGluIHRoZSB1cGNvbWluZyBzZWN0aW9uLCBtYXRjaGluZyB0aGUgdmlldy1ldmVudHMtbWVldGluZ3MtbGlzdCBzY3JlZW4uICovXHJcbmNvbnN0IFVQQ09NSU5HX1NUQVRVU0VTID0gWydJbiBQcm9ncmVzcycsICdVcGNvbWluZyddO1xyXG4vKiogU29ydCBjb2x1bW4gdXNlZCBmb3IgdGhlIHRvcC1sZXZlbCBldmVudHMgJiBtZWV0aW5ncyBsaXN0LiAqL1xyXG5jb25zdCBVUENPTUlOR19TT1JUX0NPTFVNTiA9ICdzdGFydERhdGVUaW1lJztcclxuLyoqIFNvcnQgY29sdW1uIHVzZWQgZm9yIGFuIGV2ZW50J3MgZXhwYW5kZWQgY2hpbGQtbWVldGluZyBsaXN0IChtZWV0aW5nc0RldGFpbHMpLiAqL1xyXG5jb25zdCBFVkVOVF9NRUVUSU5HU19TT1JUX0NPTFVNTiA9ICdtZWV0aW5nU3REYXRlJztcclxuLyoqIERlZmF1bHQgcGFnZSBzaXplIGZvciB0aGUgdG9wLWxldmVsIHVwY29taW5nIHNlY3Rpb24gbGlzdC4gKi9cclxuY29uc3QgVVBDT01JTkdfUEFHRV9TSVpFID0gMTA7XHJcbi8qKiBEZWZhdWx0IHBhZ2Ugc2l6ZSBmb3IgYW4gZXZlbnQncyBleHBhbmRlZCBjaGlsZC1tZWV0aW5nIGxpc3QuICovXHJcbmNvbnN0IEVWRU5UX01FRVRJTkdTX1BBR0VfU0laRSA9IDU7XHJcbi8qKiBMYXJnZSBwYWdlIHNpemUgdXNlZCBieSB0aGUgZWFnZXIgY291bnQgcHJlZmV0Y2ggdG8gY2FwdHVyZSB0aGUgZnVsbCBzZXQuICovXHJcbmNvbnN0IEVWRU5UX0NPVU5UX1BBR0VfU0laRSA9IDIwMDtcclxuaW1wb3J0IHtcclxuICBhcHBseUxlYXZlTWVldGluZ1N1Y2Nlc3MsXHJcbiAgYXBwbHlMb2dBdHRlbmRhbmNlU3VjY2VzcyxcclxuICBiZWdpbkF0dGVuZGFuY2VBY3Rpb24sXHJcbiAgZW5kQXR0ZW5kYW5jZUFjdGlvbixcclxufSBmcm9tICcuL2F0dGVuZGFuY2UtcmVkdWNlcnMnO1xyXG5cclxuLyoqXHJcbiAqIERhc2hib2FyZFNlcnZpY2UgaXMgdGhlIHNpbmdsZSBzb3VyY2Ugb2YgdHJ1dGggZm9yIHRoZSBkYXNoYm9hcmQgbGFuZGluZ1xyXG4gKiBwYWdlJ3MgZGF0YSBhbmQgYXR0ZW5kYW5jZSBzdGF0ZS4gSXQgbWlycm9ycyB0aGUgYGV2ZW50cy1hbmQtbWVldGluZ3NgXHJcbiAqIHNlcnZpY2UgY29udmVudGlvbnM6IGl0IGlzIGEgYHByb3ZpZGVkSW46ICdyb290J2Agc2luZ2xldG9uLCBob2xkcyB0aGUgaG9zdFxyXG4gKiBgYXBpQmFzZVVybGAgLyBgdXNlclBlcm1pc3Npb25zYCBzZXQgdmlhIHtAbGluayBzZXRBcHBDb25maWd9LCBvd25zIGl0cyBzdGF0ZVxyXG4gKiB2aWEgYEJlaGF2aW9yU3ViamVjdGBzIGV4cG9zZWQgYXMgb2JzZXJ2YWJsZXMsIGFuZCByZWFjaGVzIHRoZSBiYWNrZW5kIG9ubHlcclxuICogdGhyb3VnaCB0aGUgc2hhcmVkIGBIdHRwU2VydmljZWAgZnJvbSBgQGllZWVzYS1ucG0vdXRpbGl0eWAgKG5ldmVyXHJcbiAqIGBIdHRwQ2xpZW50YCBkaXJlY3RseSkuXHJcbiAqXHJcbiAqIFRoZSB1cGNvbWluZy1ldmVudHMgbG9hZCBjYWxscyB0aGUgcmVhbCBgUE9TVCAvbWVldGluZ3MvZXZlbnRzQW5kTWVldGluZ3NgXHJcbiAqIGVuZHBvaW50IChjaGlsZCBtZWV0aW5ncyBhcmUgbGF6aWx5IGxvYWRlZCBwZXItZXZlbnQgdmlhXHJcbiAqIGBQT1NUIC9tZWV0aW5ncy9tZWV0aW5nc0RldGFpbHNgKTsgdGhlIGdyb3VwcyBsb2FkIGNhbGxzIGBHRVRcclxuICogL2dyb3Vwcy9teS1ncm91cHNgLiBUaGUgYXR0ZW5kYW5jZSBhY3Rpb25zIGNvbXBvc2UgdGhlIHB1cmUgcmVkdWNlcnMgZnJvbVxyXG4gKiBgYXR0ZW5kYW5jZS1yZWR1Y2Vycy50c2Agc28gdGhlIGRpc3BsYXllZCBgQXR0ZW5kYW5jZVN0YXRlYCBvbmx5IGFkdmFuY2VzIG9uIGFcclxuICogc3VjY2Vzc2Z1bCByZXNvbHV0aW9uIGFuZCB0aGUgcHJpb3Igc3RhdGUgaXMgcmV0YWluZWQgb24gZmFpbHVyZS5cclxuICogQGV4cG9ydFxyXG4gKiBAY2xhc3MgRGFzaGJvYXJkU2VydmljZVxyXG4gKi9cclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290JyxcclxufSlcclxuZXhwb3J0IGNsYXNzIERhc2hib2FyZFNlcnZpY2Uge1xyXG4gIGFwaUJhc2VVcmwhOiBzdHJpbmc7XHJcbiAgdXNlclBlcm1pc3Npb25zITogVXNlclBlcm1pc3Npb25bXTtcclxuXHJcbiAgcHJpdmF0ZSByZWFkb25seSB1cGNvbWluZ0V2ZW50cyA9IG5ldyBCZWhhdmlvclN1YmplY3Q8VXBjb21pbmdFdmVudFtdPihbXSk7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBncm91cHMgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PEdyb3VwUm93W10+KFtdKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IHVwY29taW5nU3RhdGUgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PERhc2hib2FyZFNlY3Rpb25TdGF0ZT4oXHJcbiAgICBEYXNoYm9hcmRTZWN0aW9uU3RhdGUuTE9BRElOR1xyXG4gICk7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBncm91cHNTdGF0ZSA9IG5ldyBCZWhhdmlvclN1YmplY3Q8RGFzaGJvYXJkU2VjdGlvblN0YXRlPihcclxuICAgIERhc2hib2FyZFNlY3Rpb25TdGF0ZS5MT0FESU5HXHJcbiAgKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IGF0dGVuZGFuY2VTdGF0ZXMgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFxyXG4gICAgUmVjb3JkPHN0cmluZywgQXR0ZW5kYW5jZVN0YXRlPlxyXG4gID4oe30pO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgaW5GbGlnaHRNZWV0aW5nSWRzID0gbmV3IEJlaGF2aW9yU3ViamVjdDxcclxuICAgIFJlYWRvbmx5U2V0PHN0cmluZz5cclxuICA+KG5ldyBTZXQ8c3RyaW5nPigpKTtcclxuXHJcbiAgLyoqIEVtaXRzIHRoZSBsaXN0IG9mIHRoZSB1c2VyJ3MgdXBjb21pbmcgZXZlbnRzLiAqL1xyXG4gIHVwY29taW5nRXZlbnRzJDogT2JzZXJ2YWJsZTxVcGNvbWluZ0V2ZW50W10+ID1cclxuICAgIHRoaXMudXBjb21pbmdFdmVudHMuYXNPYnNlcnZhYmxlKCk7XHJcbiAgLyoqIEVtaXRzIHRoZSBsaXN0IG9mIHRoZSB1c2VyJ3MgZ3JvdXBzLiAqL1xyXG4gIGdyb3VwcyQ6IE9ic2VydmFibGU8R3JvdXBSb3dbXT4gPSB0aGlzLmdyb3Vwcy5hc09ic2VydmFibGUoKTtcclxuICAvKiogRW1pdHMgdGhlIGxvYWQvZW1wdHkvZXJyb3Igc3RhdGUgb2YgdGhlIHVwY29taW5nLWV2ZW50cyBzZWN0aW9uLiAqL1xyXG4gIHVwY29taW5nU3RhdGUkOiBPYnNlcnZhYmxlPERhc2hib2FyZFNlY3Rpb25TdGF0ZT4gPVxyXG4gICAgdGhpcy51cGNvbWluZ1N0YXRlLmFzT2JzZXJ2YWJsZSgpO1xyXG4gIC8qKiBFbWl0cyB0aGUgbG9hZC9lbXB0eS9lcnJvciBzdGF0ZSBvZiB0aGUgZ3JvdXBzIHNlY3Rpb24uICovXHJcbiAgZ3JvdXBzU3RhdGUkOiBPYnNlcnZhYmxlPERhc2hib2FyZFNlY3Rpb25TdGF0ZT4gPVxyXG4gICAgdGhpcy5ncm91cHNTdGF0ZS5hc09ic2VydmFibGUoKTtcclxuICAvKiogRW1pdHMgdGhlIHBlci1tZWV0aW5nIGF0dGVuZGFuY2Utc3RhdGUgbWFwLiAqL1xyXG4gIGF0dGVuZGFuY2VTdGF0ZXMkOiBPYnNlcnZhYmxlPFJlY29yZDxzdHJpbmcsIEF0dGVuZGFuY2VTdGF0ZT4+ID1cclxuICAgIHRoaXMuYXR0ZW5kYW5jZVN0YXRlcy5hc09ic2VydmFibGUoKTtcclxuICAvKiogRW1pdHMgdGhlIHNldCBvZiBtZWV0aW5nIGlkcyB3aXRoIGFuIGF0dGVuZGFuY2UgYWN0aW9uIGluIGZsaWdodC4gKi9cclxuICBpbkZsaWdodE1lZXRpbmdJZHMkOiBPYnNlcnZhYmxlPFJlYWRvbmx5U2V0PHN0cmluZz4+ID1cclxuICAgIHRoaXMuaW5GbGlnaHRNZWV0aW5nSWRzLmFzT2JzZXJ2YWJsZSgpO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xyXG4gICAgcHJpdmF0ZSBodHRwU2VydmljZTogSHR0cFNlcnZpY2UgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWVtcHR5LWZ1bmN0aW9uXHJcbiAgKSB7fVxyXG5cclxuICAvKipcclxuICAgKiBTdG9yZXMgdGhlIGhvc3Qtc3VwcGxpZWQgQVBJIGJhc2UgVVJMIGFuZCB1c2VyIHBlcm1pc3Npb25zIHVzZWQgdG8gYnVpbGRcclxuICAgKiByZXF1ZXN0IFVSTHMgYW5kIGdhdGUgcGVybWlzc2lvbi1jb250cm9sbGVkIGFjdGlvbnMuIE1pcnJvcnMgdGhlXHJcbiAgICogYGV2ZW50cy1hbmQtbWVldGluZ3NgIHNlcnZpY2UgYHNldEFwcENvbmZpZ2AuXHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFwaUJhc2VVUkwgLSBUaGUgaG9zdCBhcHBsaWNhdGlvbidzIEFQSSBiYXNlIFVSTC5cclxuICAgKiBAcGFyYW0ge1VzZXJQZXJtaXNzaW9uW119IHVzZXJQZXJtaXNzaW9ucyAtIFRoZSBzaWduZWQtaW4gdXNlcidzIHBlcm1pc3Npb25zLlxyXG4gICAqIEByZXR1cm4ge3ZvaWR9XHJcbiAgICogQG1lbWJlcm9mIERhc2hib2FyZFNlcnZpY2VcclxuICAgKi9cclxuICBzZXRBcHBDb25maWcoYXBpQmFzZVVSTDogc3RyaW5nLCB1c2VyUGVybWlzc2lvbnM6IFVzZXJQZXJtaXNzaW9uW10pOiB2b2lkIHtcclxuICAgIHRoaXMuYXBpQmFzZVVybCA9IGFwaUJhc2VVUkw7XHJcbiAgICB0aGlzLnVzZXJQZXJtaXNzaW9ucyA9IHVzZXJQZXJtaXNzaW9ucztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIExvYWRzIHRoZSB1c2VyJ3MgdXBjb21pbmcgZXZlbnRzICYgbWVldGluZ3MgZnJvbSB0aGUgcmVhbCBiYWNrZW5kIHZpYVxyXG4gICAqIGBQT1NUIHthcGlCYXNlVXJsfS9tZWV0aW5ncy9ldmVudHNBbmRNZWV0aW5nc2AsIHRoZSBzYW1lIGVuZHBvaW50IHRoZVxyXG4gICAqIGB2aWV3LWV2ZW50cy1tZWV0aW5ncy1saXN0YCBzY3JlZW4gdXNlcy4gVGhlIHJlc3BvbnNlIGlzIG1hcHBlZCBpbnRvIHRoZVxyXG4gICAqIGRhc2hib2FyZCB2aWV3IG1vZGVscyAod2l0aCBTVEFOREFMT05FX01FRVRJTkcgcm93cyBvcmRlcmVkIGxhc3QpLCB0aGVcclxuICAgKiBwZXItbWVldGluZyBhdHRlbmRhbmNlLXN0YXRlIG1hcCBpcyBzZWVkZWQsIGFuZCB0aGUgc2VjdGlvbiBhZHZhbmNlcyB0aHJvdWdoXHJcbiAgICogTE9BRElORyDihpIgTE9BREVEL0VNUFRZIG9uIHN1Y2Nlc3MsIGxlYXZpbmcgdGhlIGNhbGxlciB0byBzZXQgRVJST1Igb25cclxuICAgKiBmYWlsdXJlLiBGb2xsb3dzIHRoZSBzaGFyZWQgYHBpcGUobWFwLCBjYXRjaEVycm9yKHRocm93KSlgIHBhdHRlcm4uXHJcbiAgICogQHJldHVybiB7T2JzZXJ2YWJsZTxFdmVudE1lZXRpbmdMaXN0UmVzcG9uc2U+fSBUaGUgdXBjb21pbmcgZXZlbnRzICYgbWVldGluZ3MgcmVzcG9uc2UgZW52ZWxvcGUuXHJcbiAgICogQG1lbWJlcm9mIERhc2hib2FyZFNlcnZpY2VcclxuICAgKi9cclxuICBsb2FkVXBjb21pbmdFdmVudHMoKTogT2JzZXJ2YWJsZTxFdmVudE1lZXRpbmdMaXN0UmVzcG9uc2U+IHtcclxuICAgIHRoaXMudXBjb21pbmdTdGF0ZS5uZXh0KERhc2hib2FyZFNlY3Rpb25TdGF0ZS5MT0FESU5HKTtcclxuICAgIGNvbnN0IHBheWxvYWQ6IEV2ZW50TWVldGluZ0xpc3RQYXlsb2FkID0ge1xyXG4gICAgICBwYXlsb2FkOiB7XHJcbiAgICAgICAgZXZlbnRJZDogbnVsbCxcclxuICAgICAgICBzb3J0Q29sdW1uOiBVUENPTUlOR19TT1JUX0NPTFVNTixcclxuICAgICAgICBhc2NlbmRpbmdPcmRlcjogdHJ1ZSxcclxuICAgICAgICBwYWdlOiAxLFxyXG4gICAgICAgIHNpemU6IFVQQ09NSU5HX1BBR0VfU0laRSxcclxuICAgICAgICBmaWx0ZXI6IHtcclxuICAgICAgICAgIHN0YXR1czogVVBDT01JTkdfU1RBVFVTRVMsXHJcbiAgICAgICAgICBpc0FsbE1lZXRpbmdTZWxlY3RlZDogZmFsc2UsXHJcbiAgICAgICAgfSxcclxuICAgICAgfSxcclxuICAgIH07XHJcbiAgICByZXR1cm4gdGhpcy5odHRwU2VydmljZVxyXG4gICAgICAucG9zdERhdGEoYCR7dGhpcy5hcGlCYXNlVXJsfS9tZWV0aW5ncy9ldmVudHNBbmRNZWV0aW5nc2AsIHBheWxvYWQpXHJcbiAgICAgIC5waXBlKFxyXG4gICAgICAgIG1hcCgocmVzcG9uc2U6IEV2ZW50TWVldGluZ0xpc3RSZXNwb25zZSkgPT4ge1xyXG4gICAgICAgICAgY29uc3QgZXZlbnRzID0gbWFwRXZlbnRNZWV0aW5nTGlzdChcclxuICAgICAgICAgICAgcmVzcG9uc2U/LmJvZHk/LmV2ZW50TWVldGluZ0xpc3QgPz8gW11cclxuICAgICAgICAgICk7XHJcbiAgICAgICAgICB0aGlzLnVwY29taW5nRXZlbnRzLm5leHQoZXZlbnRzKTtcclxuICAgICAgICAgIHRoaXMuc2VlZEF0dGVuZGFuY2VTdGF0ZXMoZXZlbnRzKTtcclxuICAgICAgICAgIHRoaXMudXBjb21pbmdTdGF0ZS5uZXh0KFxyXG4gICAgICAgICAgICBldmVudHMubGVuZ3RoID4gMFxyXG4gICAgICAgICAgICAgID8gRGFzaGJvYXJkU2VjdGlvblN0YXRlLkxPQURFRFxyXG4gICAgICAgICAgICAgIDogRGFzaGJvYXJkU2VjdGlvblN0YXRlLkVNUFRZXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgLy8gRWFnZXJseSBmZXRjaCBlYWNoIEVWRU5UJ3MgbWVldGluZyBjb3VudCBzbyB0aGUgXCJ7bn0gbWVldGluZ3NcIiBhbmRcclxuICAgICAgICAgIC8vIFwie259IG9wZW4gZm9yIGF0dGVuZGFuY2VcIiBzdW1tYXJpZXMgYXJlIGNvcnJlY3QgYmVmb3JlIGV4cGFuZGluZy5cclxuICAgICAgICAgIHRoaXMubG9hZEV2ZW50Q291bnRzKGV2ZW50cyk7XHJcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2U7XHJcbiAgICAgICAgfSksXHJcbiAgICAgICAgY2F0Y2hFcnJvcigoZXJyb3IpID0+IHtcclxuICAgICAgICAgIHRoaXMudXBjb21pbmdTdGF0ZS5uZXh0KERhc2hib2FyZFNlY3Rpb25TdGF0ZS5FUlJPUik7XHJcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcclxuICAgICAgICB9KVxyXG4gICAgICApO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTGF6aWx5IGxvYWRzIChhbmQgcGFnaW5hdGVzKSB0aGUgY2hpbGQgbWVldGluZ3Mgb2YgYW4gRVZFTlQgcm93IHZpYVxyXG4gICAqIGBQT1NUIHthcGlCYXNlVXJsfS9tZWV0aW5ncy9tZWV0aW5nc0RldGFpbHNgIOKAlCB0aGUgcGVyLWV2ZW50IGV4cGFuZCBlbmRwb2ludFxyXG4gICAqIHVzZWQgYnkgdGhlIHJlZmVyZW5jZSBzY3JlZW4uIE9uIHN1Y2Nlc3MgdGhlIGxvYWRlZCBtZWV0aW5ncyBhcmUgbWFwcGVkIGFuZFxyXG4gICAqIG1lcmdlZCBvbnRvIHRoZSBtYXRjaGluZyBldmVudCBpbiB0aGUgYHVwY29taW5nRXZlbnRzYCBsaXN0ICh3aXRoIGl0c1xyXG4gICAqIGBtZWV0aW5nQ291bnRgIC8gYG9wZW5Gb3JBdHRlbmRhbmNlQ291bnRgIHJlZnJlc2hlZCksIGFuZCB0aGUgcGVyLW1lZXRpbmdcclxuICAgKiBhdHRlbmRhbmNlLXN0YXRlIG1hcCBpcyBleHRlbmRlZC4gRWFjaCBldmVudCBwYWdpbmF0ZXMgaW5kZXBlbmRlbnRseS5cclxuICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRJZCAtIFRoZSBldmVudCB3aG9zZSBtZWV0aW5ncyB0byBsb2FkLlxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbcGFnZT0xXSAtIFRoZSBvbmUtYmFzZWQgcGFnZSB0byByZXF1ZXN0LlxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbc2l6ZT1FVkVOVF9NRUVUSU5HU19QQUdFX1NJWkVdIC0gVGhlIHBhZ2Ugc2l6ZS5cclxuICAgKiBAcmV0dXJuIHtPYnNlcnZhYmxlPEV2ZW50TWVldGluZ0RldGFpbFJlc3BvbnNlPn0gVGhlIGNoaWxkLW1lZXRpbmdzIHJlc3BvbnNlIGVudmVsb3BlLlxyXG4gICAqIEBtZW1iZXJvZiBEYXNoYm9hcmRTZXJ2aWNlXHJcbiAgICovXHJcbiAgbG9hZEV2ZW50TWVldGluZ3MoXHJcbiAgICBldmVudElkOiBzdHJpbmcsXHJcbiAgICBwYWdlID0gMSxcclxuICAgIHNpemUgPSBFVkVOVF9NRUVUSU5HU19QQUdFX1NJWkVcclxuICApOiBPYnNlcnZhYmxlPEV2ZW50TWVldGluZ0RldGFpbFJlc3BvbnNlPiB7XHJcbiAgICByZXR1cm4gdGhpcy5mZXRjaEV2ZW50TWVldGluZ3NQYWdlKGV2ZW50SWQsIHBhZ2UsIHNpemUpLnBpcGUoXHJcbiAgICAgIG1hcCgocmVzcG9uc2U6IEV2ZW50TWVldGluZ0RldGFpbFJlc3BvbnNlKSA9PiB7XHJcbiAgICAgICAgY29uc3QgbWVldGluZ3MgPSBtYXBFdmVudE1lZXRpbmdEZXRhaWxzKFxyXG4gICAgICAgICAgcmVzcG9uc2U/LmJvZHk/Lm1lZXRpbmdzID8/IFtdXHJcbiAgICAgICAgKTtcclxuICAgICAgICBjb25zdCB0b3RhbCA9IHJlc3BvbnNlPy5ib2R5Py50b3RhbFJlY29yZHMgPz8gbWVldGluZ3MubGVuZ3RoO1xyXG4gICAgICAgIC8vIFByZWZlciB0aGUgYWxyZWFkeS1rbm93biBmdWxsIG9wZW4gY291bnQgb24gdGhlIGV2ZW50OyBmYWxsIGJhY2sgdG9cclxuICAgICAgICAvLyB0aGUgY3VycmVudCBwYWdlJ3Mgb3BlbiBjb3VudCB3aGVuIGl0IGhhc24ndCBiZWVuIHByZWZldGNoZWQuXHJcbiAgICAgICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLnVwY29taW5nRXZlbnRzLnZhbHVlLmZpbmQoXHJcbiAgICAgICAgICAoZXZlbnQpID0+IGV2ZW50LmV2ZW50SWQgPT09IGV2ZW50SWRcclxuICAgICAgICApO1xyXG4gICAgICAgIGNvbnN0IHBhZ2VPcGVuQ291bnQgPSBtZWV0aW5ncy5maWx0ZXIoXHJcbiAgICAgICAgICAobWVldGluZykgPT4gbWVldGluZy5pc09wZW5Gb3JBdHRlbmRhbmNlXHJcbiAgICAgICAgKS5sZW5ndGg7XHJcbiAgICAgICAgY29uc3Qgb3BlbkZvckF0dGVuZGFuY2VDb3VudCA9XHJcbiAgICAgICAgICBleGlzdGluZz8ub3BlbkZvckF0dGVuZGFuY2VDb3VudCB8fCBwYWdlT3BlbkNvdW50O1xyXG4gICAgICAgIHRoaXMubWVyZ2VFdmVudE1lZXRpbmdzKGV2ZW50SWQsIG1lZXRpbmdzLCB0b3RhbCwgb3BlbkZvckF0dGVuZGFuY2VDb3VudCk7XHJcbiAgICAgICAgdGhpcy5zZWVkQXR0ZW5kYW5jZVN0YXRlc0Zyb21NZWV0aW5ncyhtZWV0aW5ncyk7XHJcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xyXG4gICAgICB9KSxcclxuICAgICAgY2F0Y2hFcnJvcigoZXJyb3IpID0+IHtcclxuICAgICAgICB0aHJvdyBlcnJvcjtcclxuICAgICAgfSlcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNZXJnZXMgYSBmcmVzaGx5IGxvYWRlZCBwYWdlIG9mIGNoaWxkIG1lZXRpbmdzIG9udG8gdGhlIG1hdGNoaW5nIGV2ZW50IGluXHJcbiAgICogdGhlIGB1cGNvbWluZ0V2ZW50c2AgbGlzdCwgcmVmcmVzaGluZyB0aGUgZXZlbnQncyBgbWVldGluZ3NgLFxyXG4gICAqIGBtZWV0aW5nQ291bnRgIChmcm9tIHRoZSBiYWNrZW5kIGB0b3RhbFJlY29yZHNgKSwgYW5kXHJcbiAgICogYG9wZW5Gb3JBdHRlbmRhbmNlQ291bnRgLiBMZWF2ZXMgYWxsIG90aGVyIGV2ZW50cyB1bnRvdWNoZWQuXHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50SWQgLSBUaGUgZXZlbnQgdG8gbWVyZ2UgbWVldGluZ3Mgb250by5cclxuICAgKiBAcGFyYW0ge01lZXRpbmdSb3dbXX0gbWVldGluZ3MgLSBUaGUgbWFwcGVkIGNoaWxkIG1lZXRpbmdzIGZvciB0aGUgcGFnZS5cclxuICAgKiBAcGFyYW0ge251bWJlcn0gdG90YWxSZWNvcmRzIC0gVGhlIGV2ZW50J3MgdG90YWwgbWVldGluZyBjb3VudCBmcm9tIHRoZSBiYWNrZW5kLlxyXG4gICAqIEByZXR1cm4ge3ZvaWR9XHJcbiAgICogQG1lbWJlcm9mIERhc2hib2FyZFNlcnZpY2VcclxuICAgKi9cclxuICBwcml2YXRlIG1lcmdlRXZlbnRNZWV0aW5ncyhcclxuICAgIGV2ZW50SWQ6IHN0cmluZyxcclxuICAgIG1lZXRpbmdzOiBNZWV0aW5nUm93W10sXHJcbiAgICB0b3RhbFJlY29yZHM6IG51bWJlcixcclxuICAgIG9wZW5Gb3JBdHRlbmRhbmNlQ291bnQ6IG51bWJlclxyXG4gICk6IHZvaWQge1xyXG4gICAgY29uc3QgbmV4dCA9IHRoaXMudXBjb21pbmdFdmVudHMudmFsdWUubWFwKChldmVudCkgPT4ge1xyXG4gICAgICBpZiAoZXZlbnQuZXZlbnRJZCAhPT0gZXZlbnRJZCkge1xyXG4gICAgICAgIHJldHVybiBldmVudDtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIC4uLmV2ZW50LFxyXG4gICAgICAgIG1lZXRpbmdzLFxyXG4gICAgICAgIG1lZXRpbmdDb3VudDogdG90YWxSZWNvcmRzLFxyXG4gICAgICAgIG9wZW5Gb3JBdHRlbmRhbmNlQ291bnQsXHJcbiAgICAgIH07XHJcbiAgICB9KTtcclxuICAgIHRoaXMudXBjb21pbmdFdmVudHMubmV4dChuZXh0KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEVhZ2VybHkgZmV0Y2hlcyBlYWNoIEVWRU5UJ3MgdG90YWwgbWVldGluZyBjb3VudCBhbmQgb3Blbi1mb3ItYXR0ZW5kYW5jZVxyXG4gICAqIGNvdW50IGJ5IHJlcXVlc3RpbmcgYSBsYXJnZSBmaXJzdCBwYWdlIG9mIGl0cyBjaGlsZCBtZWV0aW5ncywgdGhlbiBtZXJnaW5nXHJcbiAgICogb25seSB0aGUgY291bnRzIChub3QgdGhlIHJvd3MpIHNvIHRoZSBjb2xsYXBzZWQgY2FyZCBzdW1tYXJpZXMgYXJlIGFjY3VyYXRlXHJcbiAgICogYmVmb3JlIHRoZSB1c2VyIGV4cGFuZHMuIFN0YW5kYWxvbmUgbWVldGluZ3MgYXJlIHNraXBwZWQuIEZhaWx1cmVzIHBlciBldmVudFxyXG4gICAqIGFyZSBzd2FsbG93ZWQgc28gb25lIGZhaWxpbmcgY291bnQgbmV2ZXIgYnJlYWtzIHRoZSBsaXN0LlxyXG4gICAqIEBwYXJhbSB7VXBjb21pbmdFdmVudFtdfSBldmVudHMgLSBUaGUgbG9hZGVkIGV2ZW50cyB0byBmZXRjaCBjb3VudHMgZm9yLlxyXG4gICAqIEByZXR1cm4ge3ZvaWR9XHJcbiAgICogQG1lbWJlcm9mIERhc2hib2FyZFNlcnZpY2VcclxuICAgKi9cclxuICBwcml2YXRlIGxvYWRFdmVudENvdW50cyhldmVudHM6IFVwY29taW5nRXZlbnRbXSk6IHZvaWQge1xyXG4gICAgZXZlbnRzXHJcbiAgICAgIC5maWx0ZXIoKGV2ZW50KSA9PiBldmVudC5raW5kID09PSBVcGNvbWluZ0l0ZW1LaW5kLkVWRU5UICYmIGV2ZW50LmV2ZW50SWQpXHJcbiAgICAgIC5mb3JFYWNoKChldmVudCkgPT4ge1xyXG4gICAgICAgIHRoaXMuZmV0Y2hFdmVudE1lZXRpbmdzUGFnZShldmVudC5ldmVudElkLCAxLCBFVkVOVF9DT1VOVF9QQUdFX1NJWkUpXHJcbiAgICAgICAgICAucGlwZShcclxuICAgICAgICAgICAgY2F0Y2hFcnJvcigoKSA9PiBvZihudWxsKSlcclxuICAgICAgICAgIClcclxuICAgICAgICAgIC5zdWJzY3JpYmUoKHJlc3BvbnNlKSA9PiB7XHJcbiAgICAgICAgICAgIGlmICghcmVzcG9uc2UpIHtcclxuICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY29uc3QgbWVldGluZ3MgPSBtYXBFdmVudE1lZXRpbmdEZXRhaWxzKFxyXG4gICAgICAgICAgICAgIHJlc3BvbnNlPy5ib2R5Py5tZWV0aW5ncyA/PyBbXVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBjb25zdCB0b3RhbCA9IHJlc3BvbnNlPy5ib2R5Py50b3RhbFJlY29yZHMgPz8gbWVldGluZ3MubGVuZ3RoO1xyXG4gICAgICAgICAgICBjb25zdCBvcGVuQ291bnQgPSBtZWV0aW5ncy5maWx0ZXIoXHJcbiAgICAgICAgICAgICAgKG1lZXRpbmcpID0+IG1lZXRpbmcuaXNPcGVuRm9yQXR0ZW5kYW5jZVxyXG4gICAgICAgICAgICApLmxlbmd0aDtcclxuICAgICAgICAgICAgdGhpcy5tZXJnZUV2ZW50Q291bnRzKGV2ZW50LmV2ZW50SWQsIHRvdGFsLCBvcGVuQ291bnQpO1xyXG4gICAgICAgICAgICB0aGlzLnNlZWRBdHRlbmRhbmNlU3RhdGVzRnJvbU1lZXRpbmdzKG1lZXRpbmdzKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1lcmdlcyBvbmx5IHRoZSBtZWV0aW5nIGNvdW50cyBvbnRvIHRoZSBtYXRjaGluZyBldmVudCwgbGVhdmluZyBpdHNcclxuICAgKiBgbWVldGluZ3NgIHJvd3MgdW50b3VjaGVkICh1c2VkIGJ5IHRoZSBlYWdlciBjb3VudCBwcmVmZXRjaCkuXHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50SWQgLSBUaGUgZXZlbnQgdG8gdXBkYXRlLlxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB0b3RhbFJlY29yZHMgLSBUaGUgZXZlbnQncyB0b3RhbCBtZWV0aW5nIGNvdW50LlxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvcGVuRm9yQXR0ZW5kYW5jZUNvdW50IC0gVGhlIG9wZW4tZm9yLWF0dGVuZGFuY2UgY291bnQuXHJcbiAgICogQHJldHVybiB7dm9pZH1cclxuICAgKiBAbWVtYmVyb2YgRGFzaGJvYXJkU2VydmljZVxyXG4gICAqL1xyXG4gIHByaXZhdGUgbWVyZ2VFdmVudENvdW50cyhcclxuICAgIGV2ZW50SWQ6IHN0cmluZyxcclxuICAgIHRvdGFsUmVjb3JkczogbnVtYmVyLFxyXG4gICAgb3BlbkZvckF0dGVuZGFuY2VDb3VudDogbnVtYmVyXHJcbiAgKTogdm9pZCB7XHJcbiAgICBjb25zdCBuZXh0ID0gdGhpcy51cGNvbWluZ0V2ZW50cy52YWx1ZS5tYXAoKGV2ZW50KSA9PlxyXG4gICAgICBldmVudC5ldmVudElkID09PSBldmVudElkXHJcbiAgICAgICAgPyB7IC4uLmV2ZW50LCBtZWV0aW5nQ291bnQ6IHRvdGFsUmVjb3Jkcywgb3BlbkZvckF0dGVuZGFuY2VDb3VudCB9XHJcbiAgICAgICAgOiBldmVudFxyXG4gICAgKTtcclxuICAgIHRoaXMudXBjb21pbmdFdmVudHMubmV4dChuZXh0KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEJ1aWxkcyBhbmQgcG9zdHMgdGhlIGBtZWV0aW5nc0RldGFpbHNgIHJlcXVlc3QgZm9yIGEgc2luZ2xlIGV2ZW50IHBhZ2UsXHJcbiAgICogcmV0dXJuaW5nIHRoZSByYXcgcmVzcG9uc2UgZW52ZWxvcGUuIFNoYXJlZCBieSB7QGxpbmsgbG9hZEV2ZW50TWVldGluZ3N9IGFuZFxyXG4gICAqIHRoZSBlYWdlciBjb3VudCBwcmVmZXRjaC5cclxuICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRJZCAtIFRoZSBldmVudCB3aG9zZSBtZWV0aW5ncyB0byBmZXRjaC5cclxuICAgKiBAcGFyYW0ge251bWJlcn0gcGFnZSAtIFRoZSBvbmUtYmFzZWQgcGFnZSB0byByZXF1ZXN0LlxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIC0gVGhlIHBhZ2Ugc2l6ZS5cclxuICAgKiBAcmV0dXJuIHtPYnNlcnZhYmxlPEV2ZW50TWVldGluZ0RldGFpbFJlc3BvbnNlPn0gVGhlIGNoaWxkLW1lZXRpbmdzIHJlc3BvbnNlLlxyXG4gICAqIEBtZW1iZXJvZiBEYXNoYm9hcmRTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBmZXRjaEV2ZW50TWVldGluZ3NQYWdlKFxyXG4gICAgZXZlbnRJZDogc3RyaW5nLFxyXG4gICAgcGFnZTogbnVtYmVyLFxyXG4gICAgc2l6ZTogbnVtYmVyXHJcbiAgKTogT2JzZXJ2YWJsZTxFdmVudE1lZXRpbmdEZXRhaWxSZXNwb25zZT4ge1xyXG4gICAgY29uc3QgcGF5bG9hZDogRXZlbnRNZWV0aW5nRGV0YWlsUGF5bG9hZCA9IHtcclxuICAgICAgcGF5bG9hZDoge1xyXG4gICAgICAgIGV2ZW50SWQsXHJcbiAgICAgICAgc29ydENvbHVtbjogRVZFTlRfTUVFVElOR1NfU09SVF9DT0xVTU4sXHJcbiAgICAgICAgYXNjZW5kaW5nT3JkZXI6IHRydWUsXHJcbiAgICAgICAgcGFnZSxcclxuICAgICAgICBzaXplLFxyXG4gICAgICAgIGZpbHRlcjoge1xyXG4gICAgICAgICAgc3RhdHVzOiBVUENPTUlOR19TVEFUVVNFUyxcclxuICAgICAgICAgIGlzQWxsTWVldGluZ1NlbGVjdGVkOiBmYWxzZSxcclxuICAgICAgICB9LFxyXG4gICAgICB9LFxyXG4gICAgfTtcclxuICAgIHJldHVybiB0aGlzLmh0dHBTZXJ2aWNlLnBvc3REYXRhKFxyXG4gICAgICBgJHt0aGlzLmFwaUJhc2VVcmx9L21lZXRpbmdzL21lZXRpbmdzRGV0YWlsc2AsXHJcbiAgICAgIHBheWxvYWRcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBMb2FkcyB0aGUgdXNlcidzIGdyb3VwcywgZHJpdmluZyB0aGUgZ3JvdXBzIHNlY3Rpb24gdGhyb3VnaFxyXG4gICAqIExPQURJTkcg4oaSIExPQURFRC9FTVBUWSBvbiBzdWNjZXNzIGFuZCBsZWF2aW5nIHRoZSBjYWxsZXIgdG8gc2V0IEVSUk9SIG9uXHJcbiAgICogZmFpbHVyZS4gRm9sbG93cyB0aGUgYHBpcGUobWFwLCBjYXRjaEVycm9yKHRocm93KSlgIHBhdHRlcm4uXHJcbiAgICpcclxuICAgKiBUT0RPOiBSZXBsYWNlIG1vY2sgd2l0aCByZWFsIEFQSSBjYWxsIHdoZW4gQkUgaXMgcmVhZHlcclxuICAgKiBAcmV0dXJuIHtPYnNlcnZhYmxlPERhc2hib2FyZExpc3RSZXNwb25zZTxHcm91cFJvd1tdPj59IFRoZSBncm91cHMgcmVzcG9uc2UgZW52ZWxvcGUuXHJcbiAgICogQG1lbWJlcm9mIERhc2hib2FyZFNlcnZpY2VcclxuICAgKi9cclxuICBsb2FkR3JvdXBzKCk6IE9ic2VydmFibGU8RGFzaGJvYXJkTGlzdFJlc3BvbnNlPE15R3JvdXBzVmlldz4+IHtcclxuICAgIHRoaXMuZ3JvdXBzU3RhdGUubmV4dChEYXNoYm9hcmRTZWN0aW9uU3RhdGUuTE9BRElORyk7XHJcbiAgICByZXR1cm4gdGhpcy5odHRwU2VydmljZVxyXG4gICAgICAuZ2V0RGF0YShgJHt0aGlzLmFwaUJhc2VVcmx9L2dyb3Vwcy9teS1ncm91cHNgKVxyXG4gICAgICAucGlwZShcclxuICAgICAgICBtYXAoKHJlc3BvbnNlOiBEYXNoYm9hcmRMaXN0UmVzcG9uc2U8TXlHcm91cHNWaWV3PikgPT4ge1xyXG4gICAgICAgICAgY29uc3QgZ3JvdXBzID0gKHJlc3BvbnNlPy5ib2R5Py5ncm91cHMgPz8gW10pLm1hcCgoZ3JvdXApID0+XHJcbiAgICAgICAgICAgIHRoaXMubWFwR3JvdXAoZ3JvdXApXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgdGhpcy5ncm91cHMubmV4dChncm91cHMpO1xyXG4gICAgICAgICAgdGhpcy5ncm91cHNTdGF0ZS5uZXh0KFxyXG4gICAgICAgICAgICBncm91cHMubGVuZ3RoID4gMFxyXG4gICAgICAgICAgICAgID8gRGFzaGJvYXJkU2VjdGlvblN0YXRlLkxPQURFRFxyXG4gICAgICAgICAgICAgIDogRGFzaGJvYXJkU2VjdGlvblN0YXRlLkVNUFRZXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xyXG4gICAgICAgIH0pLFxyXG4gICAgICAgIGNhdGNoRXJyb3IoKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmdyb3Vwc1N0YXRlLm5leHQoRGFzaGJvYXJkU2VjdGlvblN0YXRlLkVSUk9SKTtcclxuICAgICAgICAgIHRocm93IGVycm9yO1xyXG4gICAgICAgIH0pXHJcbiAgICAgICk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNYXBzIGEgYmFja2VuZCB7QGxpbmsgTXlHcm91cFZpZXd9IHRvIHRoZSB0YWJsZS1mYWNpbmcge0BsaW5rIEdyb3VwUm93fS5cclxuICAgKiBNaXJyb3JzIHRoZSBNeSBHcm91cHMgcHJvZmlsZSB0YWI6IHRoZSB0eXBlIGZhbGxzIGJhY2sgdG8gXCJVbmFzc2lnbmVkXCIgd2hlblxyXG4gICAqIGBncm91cFR5cGVOYW1lYCBpcyBudWxsLCBhZmZpbGlhdGlvbnMgYXJlIGNvbW1hLWpvaW5lZCwgZW1wdHkgb2ZmaWNlciByb2xlIC9cclxuICAgKiBhZmZpbGlhdGlvbiByZW5kZXIgYXMgYSBwbGFjZWhvbGRlciwgYW5kIGEgYmxhbmsgbWVtYmVyIGxldmVsIGJlY29tZXNcclxuICAgKiBcIlVuYXNzaWduZWRcIiAocmVuZGVyZWQgYXMgdGhlIHdhcm5pbmcgcGlsbCBieSB0aGUgWW91ciBHcm91cHMgY29tcG9uZW50KS5cclxuICAgKiBAcGFyYW0ge015R3JvdXBWaWV3fSBncm91cCAtIFRoZSBiYWNrZW5kIGdyb3VwIHZpZXcuXHJcbiAgICogQHJldHVybiB7R3JvdXBSb3d9XHJcbiAgICogQG1lbWJlcm9mIERhc2hib2FyZFNlcnZpY2VcclxuICAgKi9cclxuICBwcml2YXRlIG1hcEdyb3VwKGdyb3VwOiBNeUdyb3VwVmlldyk6IEdyb3VwUm93IHtcclxuICAgIC8vIFRoZSBiYWNrZW5kIHJldHVybnMgb2ZmaWNlciByb2xlcyBhcyBhbiBgb2ZmaWNlcmAgYXJyYXkgb2ZcclxuICAgIC8vIHsgb2ZmaWNlcklkLCBvZmZpY2VyTmFtZSB9LiBKb2luIHRoZSBuYW1lcyBmb3IgdGhlIE9mZmljZXIgUm9sZSBjb2x1bW5cclxuICAgIC8vIChlLmcuIFwiQ2hhaXJcIiBvciBcIkNoYWlyLCBWaWNlIENoYWlyXCIpOyBzaG93IHRoZSBwbGFjZWhvbGRlciB3aGVuIGVtcHR5LlxyXG4gICAgY29uc3Qgb2ZmaWNlclJvbGUgPVxyXG4gICAgICAoZ3JvdXAub2ZmaWNlciA/PyBbXSlcclxuICAgICAgICAubWFwKChvZmZpY2VyKSA9PiBvZmZpY2VyPy5vZmZpY2VyTmFtZT8udHJpbSgpKVxyXG4gICAgICAgIC5maWx0ZXIoKG5hbWUpID0+ICEhbmFtZSlcclxuICAgICAgICAuam9pbignLCAnKSB8fCBFTVBUWV9WQUxVRTtcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBncm91cElkOiBncm91cC5ncm91cElkLFxyXG4gICAgICBncm91cDogZ3JvdXAuZ3JvdXBOYW1lLFxyXG4gICAgICB0eXBlOiBncm91cC5ncm91cFR5cGVOYW1lIHx8IGdyb3VwLmdyb3VwVHlwZSB8fCBVTkFTU0lHTkVEX0xBQkVMLFxyXG4gICAgICBvZmZpY2VyUm9sZSxcclxuICAgICAgYWZmaWxpYXRpb246IGdyb3VwLmFmZmlsaWF0aW9ucz8uam9pbignLCAnKSB8fCBFTVBUWV9WQUxVRSxcclxuICAgICAgbWVtYmVyTGV2ZWw6IGdyb3VwLm1lbWJlckxldmVsPy50cmltKCkgfHwgVU5BU1NJR05FRF9MQUJFTCxcclxuICAgICAgLy8gQ2FycnkgdGhlIGFuY2VzdG9yIGhpZXJhcmNoeSB0aHJvdWdoIGZvciB0aGUgZXhwYW5kYWJsZSBoaWVyYXJjaHkgcm93cy5cclxuICAgICAgaGllcmFyY2h5OiBncm91cC5oaWVyYXJjaHkgPz8gW10sXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTG9ncyBhdHRlbmRhbmNlIGZvciBhIG1lZXRpbmcuIE1hcmtzIHRoZSBtZWV0aW5nIGluLWZsaWdodCAocmV0YWluaW5nIHRoZVxyXG4gICAqIHByaW9yIGRpc3BsYXllZCBzdGF0ZSksIHBvc3RzIHRocm91Z2ggYEh0dHBTZXJ2aWNlYCwgYXBwbGllcyB0aGVcclxuICAgKiBsb2ctYXR0ZW5kYW5jZS1zdWNjZXNzIHJlZHVjZXIgb24gc3VjY2VzcywgY2xlYXJzIHRoZSBpbi1mbGlnaHQgZmxhZyBvblxyXG4gICAqIGNvbXBsZXRpb24sIGFuZCByZXRocm93cyB3aGlsZSByZXRhaW5pbmcgcHJpb3Igc3RhdGUgb24gZmFpbHVyZS5cclxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVldGluZ0lkIC0gVGhlIG1lZXRpbmcgdG8gbG9nIGF0dGVuZGFuY2UgZm9yLlxyXG4gICAqIEByZXR1cm4ge09ic2VydmFibGU8RGFzaGJvYXJkTGlzdFJlc3BvbnNlPHVua25vd24+Pn0gVGhlIGF0dGVuZGFuY2UgcmVzcG9uc2UgZW52ZWxvcGUuXHJcbiAgICogQG1lbWJlcm9mIERhc2hib2FyZFNlcnZpY2VcclxuICAgKi9cclxuICBsb2dBdHRlbmRhbmNlKFxyXG4gICAgbWVldGluZ0lkOiBzdHJpbmdcclxuICApOiBPYnNlcnZhYmxlPERhc2hib2FyZExpc3RSZXNwb25zZTx1bmtub3duPj4ge1xyXG4gICAgdGhpcy5pbkZsaWdodE1lZXRpbmdJZHMubmV4dChcclxuICAgICAgYmVnaW5BdHRlbmRhbmNlQWN0aW9uKHRoaXMuaW5GbGlnaHRNZWV0aW5nSWRzLnZhbHVlLCBtZWV0aW5nSWQpXHJcbiAgICApO1xyXG4gICAgcmV0dXJuIHRoaXMuaHR0cFNlcnZpY2VcclxuICAgICAgLnBvc3REYXRhKGAke3RoaXMuYXBpQmFzZVVybH0vbWVldGluZ3MvYXR0ZW5kYW5jZS9sb2dgLCB7IG1lZXRpbmdJZCB9KVxyXG4gICAgICAucGlwZShcclxuICAgICAgICBtYXAoKHJlc3BvbnNlKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmF0dGVuZGFuY2VTdGF0ZXMubmV4dChcclxuICAgICAgICAgICAgYXBwbHlMb2dBdHRlbmRhbmNlU3VjY2Vzcyh0aGlzLmF0dGVuZGFuY2VTdGF0ZXMudmFsdWUsIG1lZXRpbmdJZClcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgICB0aGlzLmluRmxpZ2h0TWVldGluZ0lkcy5uZXh0KFxyXG4gICAgICAgICAgICBlbmRBdHRlbmRhbmNlQWN0aW9uKHRoaXMuaW5GbGlnaHRNZWV0aW5nSWRzLnZhbHVlLCBtZWV0aW5nSWQpXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xyXG4gICAgICAgIH0pLFxyXG4gICAgICAgIGNhdGNoRXJyb3IoKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAvLyBSZXRhaW4gcHJpb3IgYXR0ZW5kYW5jZSBzdGF0ZTsgb25seSBjbGVhciB0aGUgaW4tZmxpZ2h0IGZsYWcuXHJcbiAgICAgICAgICB0aGlzLmluRmxpZ2h0TWVldGluZ0lkcy5uZXh0KFxyXG4gICAgICAgICAgICBlbmRBdHRlbmRhbmNlQWN0aW9uKHRoaXMuaW5GbGlnaHRNZWV0aW5nSWRzLnZhbHVlLCBtZWV0aW5nSWQpXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgdGhyb3cgZXJyb3I7XHJcbiAgICAgICAgfSlcclxuICAgICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIExlYXZlcyBhIG1lZXRpbmcuIE1hcmtzIHRoZSBtZWV0aW5nIGluLWZsaWdodCAocmV0YWluaW5nIHRoZSBwcmlvclxyXG4gICAqIGRpc3BsYXllZCBzdGF0ZSksIHBvc3RzIHRocm91Z2ggYEh0dHBTZXJ2aWNlYCwgYXBwbGllcyB0aGVcclxuICAgKiBsZWF2ZS1tZWV0aW5nLXN1Y2Nlc3MgcmVkdWNlciBvbiBzdWNjZXNzLCBjbGVhcnMgdGhlIGluLWZsaWdodCBmbGFnIG9uXHJcbiAgICogY29tcGxldGlvbiwgYW5kIHJldGhyb3dzIHdoaWxlIHJldGFpbmluZyBwcmlvciBzdGF0ZSBvbiBmYWlsdXJlLlxyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtZWV0aW5nSWQgLSBUaGUgbWVldGluZyB0byBsZWF2ZS5cclxuICAgKiBAcmV0dXJuIHtPYnNlcnZhYmxlPERhc2hib2FyZExpc3RSZXNwb25zZTx1bmtub3duPj59IFRoZSBhdHRlbmRhbmNlIHJlc3BvbnNlIGVudmVsb3BlLlxyXG4gICAqIEBtZW1iZXJvZiBEYXNoYm9hcmRTZXJ2aWNlXHJcbiAgICovXHJcbiAgbGVhdmVNZWV0aW5nKFxyXG4gICAgbWVldGluZ0lkOiBzdHJpbmdcclxuICApOiBPYnNlcnZhYmxlPERhc2hib2FyZExpc3RSZXNwb25zZTx1bmtub3duPj4ge1xyXG4gICAgdGhpcy5pbkZsaWdodE1lZXRpbmdJZHMubmV4dChcclxuICAgICAgYmVnaW5BdHRlbmRhbmNlQWN0aW9uKHRoaXMuaW5GbGlnaHRNZWV0aW5nSWRzLnZhbHVlLCBtZWV0aW5nSWQpXHJcbiAgICApO1xyXG4gICAgcmV0dXJuIHRoaXMuaHR0cFNlcnZpY2VcclxuICAgICAgLnBvc3REYXRhKGAke3RoaXMuYXBpQmFzZVVybH0vbWVldGluZ3MvYXR0ZW5kYW5jZS9sZWF2ZWAsIHsgbWVldGluZ0lkIH0pXHJcbiAgICAgIC5waXBlKFxyXG4gICAgICAgIG1hcCgocmVzcG9uc2UpID0+IHtcclxuICAgICAgICAgIHRoaXMuYXR0ZW5kYW5jZVN0YXRlcy5uZXh0KFxyXG4gICAgICAgICAgICBhcHBseUxlYXZlTWVldGluZ1N1Y2Nlc3ModGhpcy5hdHRlbmRhbmNlU3RhdGVzLnZhbHVlLCBtZWV0aW5nSWQpXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgdGhpcy5pbkZsaWdodE1lZXRpbmdJZHMubmV4dChcclxuICAgICAgICAgICAgZW5kQXR0ZW5kYW5jZUFjdGlvbih0aGlzLmluRmxpZ2h0TWVldGluZ0lkcy52YWx1ZSwgbWVldGluZ0lkKVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICAgIHJldHVybiByZXNwb25zZTtcclxuICAgICAgICB9KSxcclxuICAgICAgICBjYXRjaEVycm9yKChlcnJvcikgPT4ge1xyXG4gICAgICAgICAgLy8gUmV0YWluIHByaW9yIGF0dGVuZGFuY2Ugc3RhdGU7IG9ubHkgY2xlYXIgdGhlIGluLWZsaWdodCBmbGFnLlxyXG4gICAgICAgICAgdGhpcy5pbkZsaWdodE1lZXRpbmdJZHMubmV4dChcclxuICAgICAgICAgICAgZW5kQXR0ZW5kYW5jZUFjdGlvbih0aGlzLmluRmxpZ2h0TWVldGluZ0lkcy52YWx1ZSwgbWVldGluZ0lkKVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICAgIHRocm93IGVycm9yO1xyXG4gICAgICAgIH0pXHJcbiAgICAgICk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm5zIGEgc3luY2hyb25vdXMgc25hcHNob3Qgb2YgdGhlIHBlci1tZWV0aW5nIGF0dGVuZGFuY2Utc3RhdGUgbWFwLlxyXG4gICAqIEByZXR1cm4ge1JlY29yZDxzdHJpbmcsIEF0dGVuZGFuY2VTdGF0ZT59IFRoZSBjdXJyZW50IGF0dGVuZGFuY2Utc3RhdGUgbWFwLlxyXG4gICAqIEBtZW1iZXJvZiBEYXNoYm9hcmRTZXJ2aWNlXHJcbiAgICovXHJcbiAgZ2V0QXR0ZW5kYW5jZVN0YXRlc1NuYXBzaG90KCk6IFJlY29yZDxzdHJpbmcsIEF0dGVuZGFuY2VTdGF0ZT4ge1xyXG4gICAgcmV0dXJuIHRoaXMuYXR0ZW5kYW5jZVN0YXRlcy52YWx1ZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlZWRzIHRoZSBhdHRlbmRhbmNlLXN0YXRlIG1hcCBmcm9tIGEgZnJlc2hseSBsb2FkZWQgbGlzdCBvZiBldmVudHMsIHVzaW5nXHJcbiAgICogZWFjaCBtZWV0aW5nJ3MgYGF0dGVuZGFuY2VTdGF0ZWAgKGRlZmF1bHRpbmcgdG8gYE5PVF9BVFRFTkRJTkdgKS4gS2VlcHMgdGhlXHJcbiAgICogZGlzcGxheWVkIHN0YXRlIGluIHN5bmMgd2l0aCB0aGUgZGF0YSBsb2FkIHdpdGhvdXQgb3ZlcndyaXRpbmcgaWRzIHRoYXQgYXJlXHJcbiAgICogbm90IHByZXNlbnQgaW4gdGhlIG5ldyBsaXN0LlxyXG4gICAqIEBwYXJhbSB7VXBjb21pbmdFdmVudFtdfSBldmVudHMgLSBUaGUgbG9hZGVkIHVwY29taW5nIGV2ZW50cy5cclxuICAgKiBAcmV0dXJuIHt2b2lkfVxyXG4gICAqIEBtZW1iZXJvZiBEYXNoYm9hcmRTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBzZWVkQXR0ZW5kYW5jZVN0YXRlcyhldmVudHM6IFVwY29taW5nRXZlbnRbXSk6IHZvaWQge1xyXG4gICAgY29uc3QgbWVldGluZ3MgPSBldmVudHMuZmxhdE1hcCgoZXZlbnQpID0+IGV2ZW50Lm1lZXRpbmdzID8/IFtdKTtcclxuICAgIHRoaXMuc2VlZEF0dGVuZGFuY2VTdGF0ZXNGcm9tTWVldGluZ3MobWVldGluZ3MpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2VlZHMgdGhlIGF0dGVuZGFuY2Utc3RhdGUgbWFwIGZyb20gYSBsaXN0IG9mIG1lZXRpbmcgcm93cywgdXNpbmcgZWFjaFxyXG4gICAqIG1lZXRpbmcncyBgYXR0ZW5kYW5jZVN0YXRlYCAoZGVmYXVsdGluZyB0byBgTk9UX0FUVEVORElOR2ApIHdpdGhvdXRcclxuICAgKiBvdmVyd3JpdGluZyBpZHMgYWJzZW50IGZyb20gdGhlIG5ldyBsaXN0LiBTaGFyZWQgYnkgdGhlIGxpc3QgbG9hZCBhbmQgdGhlXHJcbiAgICogcGVyLWV2ZW50IGV4cGFuZCBzbyBmcmVzaGx5IGxvYWRlZCBjaGlsZCBtZWV0aW5ncyBwaWNrIHVwIHRoZWlyIHN0YXRlLlxyXG4gICAqIEBwYXJhbSB7TWVldGluZ1Jvd1tdfSBtZWV0aW5ncyAtIFRoZSBtZWV0aW5nIHJvd3MgdG8gc2VlZCBmcm9tLlxyXG4gICAqIEByZXR1cm4ge3ZvaWR9XHJcbiAgICogQG1lbWJlcm9mIERhc2hib2FyZFNlcnZpY2VcclxuICAgKi9cclxuICBwcml2YXRlIHNlZWRBdHRlbmRhbmNlU3RhdGVzRnJvbU1lZXRpbmdzKG1lZXRpbmdzOiBNZWV0aW5nUm93W10pOiB2b2lkIHtcclxuICAgIGNvbnN0IG5leHQ6IFJlY29yZDxzdHJpbmcsIEF0dGVuZGFuY2VTdGF0ZT4gPSB7XHJcbiAgICAgIC4uLnRoaXMuYXR0ZW5kYW5jZVN0YXRlcy52YWx1ZSxcclxuICAgIH07XHJcbiAgICBtZWV0aW5ncy5mb3JFYWNoKChtZWV0aW5nKSA9PiB7XHJcbiAgICAgIGlmIChtZWV0aW5nLm1lZXRpbmdJZCkge1xyXG4gICAgICAgIG5leHRbbWVldGluZy5tZWV0aW5nSWRdID1cclxuICAgICAgICAgIG1lZXRpbmcuYXR0ZW5kYW5jZVN0YXRlID8/XHJcbiAgICAgICAgICBuZXh0W21lZXRpbmcubWVldGluZ0lkXSA/P1xyXG4gICAgICAgICAgQXR0ZW5kYW5jZVN0YXRlLk5PVF9BVFRFTkRJTkc7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgdGhpcy5hdHRlbmRhbmNlU3RhdGVzLm5leHQobmV4dCk7XHJcbiAgfVxyXG59XHJcbiJdfQ==