@memberjunction/ng-explorer-core 6.2.0-edge.1 → 6.2.0-edge.3

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 (67) hide show
  1. package/dist/generated/lazy-feature-config.d.ts +1 -1
  2. package/dist/generated/lazy-feature-config.d.ts.map +1 -1
  3. package/dist/generated/lazy-feature-config.js +22 -2
  4. package/dist/generated/lazy-feature-config.js.map +1 -1
  5. package/dist/lib/resource-wrappers/artifact-resource.component.d.ts +7 -3
  6. package/dist/lib/resource-wrappers/artifact-resource.component.d.ts.map +1 -1
  7. package/dist/lib/resource-wrappers/artifact-resource.component.js +10 -5
  8. package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -1
  9. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +13 -2
  10. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
  11. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +35 -6
  12. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
  13. package/dist/lib/resource-wrappers/compose-email-fallback.d.ts +46 -0
  14. package/dist/lib/resource-wrappers/compose-email-fallback.d.ts.map +1 -0
  15. package/dist/lib/resource-wrappers/compose-email-fallback.js +62 -0
  16. package/dist/lib/resource-wrappers/compose-email-fallback.js.map +1 -0
  17. package/dist/lib/resource-wrappers/human-handoff-console-resource.component.d.ts +32 -0
  18. package/dist/lib/resource-wrappers/human-handoff-console-resource.component.d.ts.map +1 -0
  19. package/dist/lib/resource-wrappers/human-handoff-console-resource.component.js +114 -0
  20. package/dist/lib/resource-wrappers/human-handoff-console-resource.component.js.map +1 -0
  21. package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts +13 -0
  22. package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts.map +1 -1
  23. package/dist/lib/resource-wrappers/livekit-room-resource.component.js +210 -132
  24. package/dist/lib/resource-wrappers/livekit-room-resource.component.js.map +1 -1
  25. package/dist/lib/resource-wrappers/meetings-resource.component.d.ts +42 -0
  26. package/dist/lib/resource-wrappers/meetings-resource.component.d.ts.map +1 -0
  27. package/dist/lib/resource-wrappers/meetings-resource.component.js +225 -0
  28. package/dist/lib/resource-wrappers/meetings-resource.component.js.map +1 -0
  29. package/dist/lib/resource-wrappers/record-resource.component.d.ts +27 -2
  30. package/dist/lib/resource-wrappers/record-resource.component.d.ts.map +1 -1
  31. package/dist/lib/resource-wrappers/record-resource.component.js +58 -6
  32. package/dist/lib/resource-wrappers/record-resource.component.js.map +1 -1
  33. package/dist/lib/resource-wrappers/view-resource.component.d.ts +6 -1
  34. package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
  35. package/dist/lib/resource-wrappers/view-resource.component.js +37 -7
  36. package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
  37. package/dist/lib/services/server-connectivity.service.d.ts +9 -4
  38. package/dist/lib/services/server-connectivity.service.d.ts.map +1 -1
  39. package/dist/lib/services/server-connectivity.service.js +56 -12
  40. package/dist/lib/services/server-connectivity.service.js.map +1 -1
  41. package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
  42. package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
  43. package/dist/lib/shell/components/tabs/tab-container.component.d.ts +31 -0
  44. package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
  45. package/dist/lib/shell/components/tabs/tab-container.component.js +57 -2
  46. package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
  47. package/dist/lib/shell/shell.component.d.ts +2 -0
  48. package/dist/lib/shell/shell.component.d.ts.map +1 -1
  49. package/dist/lib/shell/shell.component.js +19 -9
  50. package/dist/lib/shell/shell.component.js.map +1 -1
  51. package/dist/lib/single-record/single-record.component.d.ts +29 -3
  52. package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
  53. package/dist/lib/single-record/single-record.component.js +44 -4
  54. package/dist/lib/single-record/single-record.component.js.map +1 -1
  55. package/dist/lib/user-notifications/user-notifications.component.d.ts +13 -0
  56. package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
  57. package/dist/lib/user-notifications/user-notifications.component.js +67 -0
  58. package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
  59. package/dist/module.d.ts +36 -33
  60. package/dist/module.d.ts.map +1 -1
  61. package/dist/module.js +25 -4
  62. package/dist/module.js.map +1 -1
  63. package/dist/public-api.d.ts +1 -0
  64. package/dist/public-api.d.ts.map +1 -1
  65. package/dist/public-api.js +1 -0
  66. package/dist/public-api.js.map +1 -1
  67. package/package.json +53 -52
@@ -0,0 +1,225 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Component } from '@angular/core';
8
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
9
+ import { RegisterClass } from '@memberjunction/global';
10
+ import { GraphQLDataProvider, GraphQLMeetingClient, } from '@memberjunction/graphql-dataprovider';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "@memberjunction/ng-mj-livekit-room";
13
+ function MeetingsResource_Case_0_Template(rf, ctx) { if (rf & 1) {
14
+ const _r1 = i0.ɵɵgetCurrentView();
15
+ i0.ɵɵelementStart(0, "div", 0)(1, "mj-livekit-agent-room", 2);
16
+ i0.ɵɵlistener("Disconnected", function MeetingsResource_Case_0_Template_mj_livekit_agent_room_Disconnected_1_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnLiveRoomLeft()); });
17
+ i0.ɵɵelementEnd()();
18
+ } if (rf & 2) {
19
+ const ctx_r1 = i0.ɵɵnextContext();
20
+ i0.ɵɵadvance();
21
+ i0.ɵɵproperty("RoomName", ctx_r1.LiveRoomName)("Provider", ctx_r1.ProviderToUse)("StartWithMicrophone", ctx_r1.StartWithMic)("StartWithCamera", ctx_r1.StartWithCam)("ShowAgentState", true)("EnableLayoutSwitcher", true)("EnableLeaveControl", true);
22
+ } }
23
+ function MeetingsResource_Case_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
24
+ const _r3 = i0.ɵɵgetCurrentView();
25
+ i0.ɵɵelementStart(0, "div", 1)(1, "button", 3);
26
+ i0.ɵɵlistener("click", function MeetingsResource_Case_1_Conditional_0_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnLobbyCancelled()); });
27
+ i0.ɵɵelement(2, "i", 4);
28
+ i0.ɵɵtext(3, " Back to Meetings ");
29
+ i0.ɵɵelementEnd();
30
+ i0.ɵɵelementStart(4, "mj-meeting-lobby", 5);
31
+ i0.ɵɵlistener("JoinConfirmed", function MeetingsResource_Case_1_Conditional_0_Template_mj_meeting_lobby_JoinConfirmed_4_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnJoinConfirmed($event)); })("Cancelled", function MeetingsResource_Case_1_Conditional_0_Template_mj_meeting_lobby_Cancelled_4_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnLobbyCancelled()); });
32
+ i0.ɵɵelementEnd()();
33
+ } if (rf & 2) {
34
+ const ctx_r1 = i0.ɵɵnextContext(2);
35
+ i0.ɵɵadvance(4);
36
+ i0.ɵɵproperty("Meeting", ctx_r1.ActiveMeeting)("Provider", ctx_r1.ProviderToUse);
37
+ } }
38
+ function MeetingsResource_Case_1_Template(rf, ctx) { if (rf & 1) {
39
+ i0.ɵɵconditionalCreate(0, MeetingsResource_Case_1_Conditional_0_Template, 5, 2, "div", 1);
40
+ } if (rf & 2) {
41
+ const ctx_r1 = i0.ɵɵnextContext();
42
+ i0.ɵɵconditional(ctx_r1.ActiveMeeting ? 0 : -1);
43
+ } }
44
+ function MeetingsResource_Case_2_Template(rf, ctx) { if (rf & 1) {
45
+ const _r4 = i0.ɵɵgetCurrentView();
46
+ i0.ɵɵelementStart(0, "div", 1)(1, "button", 3);
47
+ i0.ɵɵlistener("click", function MeetingsResource_Case_2_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnScheduleCancelled()); });
48
+ i0.ɵɵelement(2, "i", 4);
49
+ i0.ɵɵtext(3, " Back to Meetings ");
50
+ i0.ɵɵelementEnd();
51
+ i0.ɵɵelementStart(4, "mj-meeting-schedule-form", 6);
52
+ i0.ɵɵlistener("MeetingSaved", function MeetingsResource_Case_2_Template_mj_meeting_schedule_form_MeetingSaved_4_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnMeetingSaved($event)); })("Cancelled", function MeetingsResource_Case_2_Template_mj_meeting_schedule_form_Cancelled_4_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnScheduleCancelled()); });
53
+ i0.ɵɵelementEnd()();
54
+ } if (rf & 2) {
55
+ const ctx_r1 = i0.ɵɵnextContext();
56
+ i0.ɵɵadvance(4);
57
+ i0.ɵɵproperty("Provider", ctx_r1.ProviderToUse)("Meeting", ctx_r1.EditingMeeting || undefined);
58
+ } }
59
+ function MeetingsResource_Case_3_Template(rf, ctx) { if (rf & 1) {
60
+ const _r5 = i0.ɵɵgetCurrentView();
61
+ i0.ɵɵelementStart(0, "div", 1)(1, "mj-meeting-list", 7);
62
+ i0.ɵɵlistener("JoinMeeting", function MeetingsResource_Case_3_Template_mj_meeting_list_JoinMeeting_1_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnJoinMeetingFromList($event)); })("ScheduleRequested", function MeetingsResource_Case_3_Template_mj_meeting_list_ScheduleRequested_1_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnScheduleRequested()); })("EditMeetingRequested", function MeetingsResource_Case_3_Template_mj_meeting_list_EditMeetingRequested_1_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnEditMeetingRequested($event)); });
63
+ i0.ɵɵelementEnd()();
64
+ } if (rf & 2) {
65
+ const ctx_r1 = i0.ɵɵnextContext();
66
+ i0.ɵɵadvance();
67
+ i0.ɵɵproperty("Provider", ctx_r1.ProviderToUse);
68
+ } }
69
+ /**
70
+ * Meetings Resource — multi-party scheduled and ad-hoc meeting hub in Explorer (the Meet app's "Meetings").
71
+ *
72
+ * Coordinates:
73
+ * - Meeting list view (`mj-meeting-list`)
74
+ * - Scheduling / editing form (`mj-meeting-schedule-form`)
75
+ * - Pre-join lobby with AV checks & dial-in info (`mj-meeting-lobby`)
76
+ * - Active multi-party call (`mj-livekit-agent-room` in join mode)
77
+ *
78
+ * Registered via `@RegisterClass(BaseResourceComponent, 'MeetingsResource')`.
79
+ */
80
+ let MeetingsResource = class MeetingsResource extends BaseResourceComponent {
81
+ Phase = 'list';
82
+ ActiveMeeting = null;
83
+ EditingMeeting = null;
84
+ LiveRoomName = '';
85
+ StartWithMic = true;
86
+ StartWithCam = false;
87
+ ngOnInit() {
88
+ super.ngOnInit();
89
+ void this.initialize();
90
+ }
91
+ async initialize() {
92
+ const config = this.Data?.Configuration;
93
+ const initialMeetingId = config?.MeetingID || this.Data?.ResourceRecordID;
94
+ if (initialMeetingId) {
95
+ try {
96
+ const client = new GraphQLMeetingClient(this.ProviderToUse || GraphQLDataProvider.Instance);
97
+ const meeting = await client.GetMeeting(initialMeetingId);
98
+ if (meeting) {
99
+ this.ActiveMeeting = meeting;
100
+ this.Phase = 'lobby';
101
+ }
102
+ }
103
+ catch (err) {
104
+ console.warn('MeetingsResource: unable to resolve initial meeting deep-link', err);
105
+ }
106
+ }
107
+ this.NotifyLoadComplete();
108
+ }
109
+ OnScheduleRequested() {
110
+ this.EditingMeeting = null;
111
+ this.Phase = 'schedule';
112
+ }
113
+ OnEditMeetingRequested(meeting) {
114
+ this.EditingMeeting = meeting;
115
+ this.Phase = 'schedule';
116
+ }
117
+ OnMeetingSaved(meeting) {
118
+ this.ActiveMeeting = meeting;
119
+ this.EditingMeeting = null;
120
+ this.Phase = 'lobby';
121
+ }
122
+ OnScheduleCancelled() {
123
+ this.EditingMeeting = null;
124
+ this.Phase = 'list';
125
+ }
126
+ OnJoinMeetingFromList(meeting) {
127
+ this.ActiveMeeting = meeting;
128
+ this.Phase = 'lobby';
129
+ }
130
+ OnJoinConfirmed(prefs) {
131
+ this.StartWithMic = prefs.startWithAudio;
132
+ this.StartWithCam = prefs.startWithVideo;
133
+ this.LiveRoomName = this.ActiveMeeting?.RoomName || '';
134
+ this.Phase = 'live';
135
+ }
136
+ OnLobbyCancelled() {
137
+ this.ActiveMeeting = null;
138
+ this.Phase = 'list';
139
+ }
140
+ OnLiveRoomLeft() {
141
+ this.LiveRoomName = '';
142
+ this.ActiveMeeting = null;
143
+ this.Phase = 'list';
144
+ }
145
+ async GetResourceDisplayName(_data) {
146
+ return this.ActiveMeeting?.Title || 'Meetings';
147
+ }
148
+ async GetResourceIconClass(_data) {
149
+ return 'fa-solid fa-calendar-users';
150
+ }
151
+ static ɵfac = /*@__PURE__*/ (() => { let ɵMeetingsResource_BaseFactory; return function MeetingsResource_Factory(__ngFactoryType__) { return (ɵMeetingsResource_BaseFactory || (ɵMeetingsResource_BaseFactory = i0.ɵɵgetInheritedFactory(MeetingsResource)))(__ngFactoryType__ || MeetingsResource); }; })();
152
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MeetingsResource, selectors: [["mj-meetings-resource"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 1, consts: [[1, "mj-mtg-live-container"], [1, "mj-mtg-resource-wrapper"], ["Mode", "join", 1, "mj-mtg-room", 3, "Disconnected", "RoomName", "Provider", "StartWithMicrophone", "StartWithCamera", "ShowAgentState", "EnableLayoutSwitcher", "EnableLeaveControl"], ["type", "button", 1, "mj-mtg-back-btn", 3, "click"], [1, "fa-solid", "fa-arrow-left"], [3, "JoinConfirmed", "Cancelled", "Meeting", "Provider"], [3, "MeetingSaved", "Cancelled", "Provider", "Meeting"], [3, "JoinMeeting", "ScheduleRequested", "EditMeetingRequested", "Provider"]], template: function MeetingsResource_Template(rf, ctx) { if (rf & 1) {
153
+ i0.ɵɵconditionalCreate(0, MeetingsResource_Case_0_Template, 2, 7, "div", 0)(1, MeetingsResource_Case_1_Template, 1, 1)(2, MeetingsResource_Case_2_Template, 5, 2, "div", 1)(3, MeetingsResource_Case_3_Template, 2, 1, "div", 1);
154
+ } if (rf & 2) {
155
+ let tmp_0_0;
156
+ i0.ɵɵconditional((tmp_0_0 = ctx.Phase) === "live" ? 0 : tmp_0_0 === "lobby" ? 1 : tmp_0_0 === "schedule" ? 2 : 3);
157
+ } }, dependencies: [i1.MJLiveKitRoomComponent, i1.MJMeetingListComponent, i1.MJMeetingScheduleFormComponent, i1.MJMeetingLobbyComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n overflow-y: auto;\n background: var(--mj-bg-page, #f8fafc);\n }\n .mj-mtg-resource-wrapper[_ngcontent-%COMP%] {\n padding: var(--mj-space-4, 16px);\n }\n .mj-mtg-live-container[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n .mj-mtg-room[_ngcontent-%COMP%] {\n display: block;\n height: 100%;\n }\n .mj-mtg-back-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n border: none;\n background: none;\n color: var(--mj-brand-primary, #0076b6);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n padding: 8px 12px;\n margin-bottom: 12px;\n border-radius: 6px;\n }\n .mj-mtg-back-btn[_ngcontent-%COMP%]:hover {\n background: rgba(0, 118, 182, 0.08);\n }"] });
158
+ };
159
+ MeetingsResource = __decorate([
160
+ RegisterClass(BaseResourceComponent, 'MeetingsResource')
161
+ ], MeetingsResource);
162
+ export { MeetingsResource };
163
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MeetingsResource, [{
164
+ type: Component,
165
+ args: [{ standalone: false, selector: 'mj-meetings-resource', template: `
166
+ @switch (Phase) {
167
+ @case ('live') {
168
+ <div class="mj-mtg-live-container">
169
+ <mj-livekit-agent-room
170
+ class="mj-mtg-room"
171
+ Mode="join"
172
+ [RoomName]="LiveRoomName"
173
+ [Provider]="ProviderToUse"
174
+ [StartWithMicrophone]="StartWithMic"
175
+ [StartWithCamera]="StartWithCam"
176
+ [ShowAgentState]="true"
177
+ [EnableLayoutSwitcher]="true"
178
+ [EnableLeaveControl]="true"
179
+ (Disconnected)="OnLiveRoomLeft()"
180
+ ></mj-livekit-agent-room>
181
+ </div>
182
+ }
183
+ @case ('lobby') {
184
+ @if (ActiveMeeting) {
185
+ <div class="mj-mtg-resource-wrapper">
186
+ <button type="button" class="mj-mtg-back-btn" (click)="OnLobbyCancelled()">
187
+ <i class="fa-solid fa-arrow-left"></i> Back to Meetings
188
+ </button>
189
+ <mj-meeting-lobby
190
+ [Meeting]="ActiveMeeting"
191
+ [Provider]="ProviderToUse"
192
+ (JoinConfirmed)="OnJoinConfirmed($event)"
193
+ (Cancelled)="OnLobbyCancelled()"
194
+ ></mj-meeting-lobby>
195
+ </div>
196
+ }
197
+ }
198
+ @case ('schedule') {
199
+ <div class="mj-mtg-resource-wrapper">
200
+ <button type="button" class="mj-mtg-back-btn" (click)="OnScheduleCancelled()">
201
+ <i class="fa-solid fa-arrow-left"></i> Back to Meetings
202
+ </button>
203
+ <mj-meeting-schedule-form
204
+ [Provider]="ProviderToUse"
205
+ [Meeting]="EditingMeeting || undefined"
206
+ (MeetingSaved)="OnMeetingSaved($event)"
207
+ (Cancelled)="OnScheduleCancelled()"
208
+ ></mj-meeting-schedule-form>
209
+ </div>
210
+ }
211
+ @default {
212
+ <div class="mj-mtg-resource-wrapper">
213
+ <mj-meeting-list
214
+ [Provider]="ProviderToUse"
215
+ (JoinMeeting)="OnJoinMeetingFromList($event)"
216
+ (ScheduleRequested)="OnScheduleRequested()"
217
+ (EditMeetingRequested)="OnEditMeetingRequested($event)"
218
+ ></mj-meeting-list>
219
+ </div>
220
+ }
221
+ }
222
+ `, styles: ["\n :host {\n display: block;\n height: 100%;\n overflow-y: auto;\n background: var(--mj-bg-page, #f8fafc);\n }\n .mj-mtg-resource-wrapper {\n padding: var(--mj-space-4, 16px);\n }\n .mj-mtg-live-container {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n .mj-mtg-room {\n display: block;\n height: 100%;\n }\n .mj-mtg-back-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n border: none;\n background: none;\n color: var(--mj-brand-primary, #0076b6);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n padding: 8px 12px;\n margin-bottom: 12px;\n border-radius: 6px;\n }\n .mj-mtg-back-btn:hover {\n background: rgba(0, 118, 182, 0.08);\n }\n "] }]
223
+ }], null, null); })();
224
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MeetingsResource, { className: "MeetingsResource", filePath: "src/lib/resource-wrappers/meetings-resource.component.ts", lineNumber: 124 }); })();
225
+ //# sourceMappingURL=meetings-resource.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meetings-resource.component.js","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/meetings-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit } from '@angular/core';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { ResourceData } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport {\n GraphQLDataProvider,\n GraphQLMeetingClient,\n type MeetingInfo,\n} from '@memberjunction/graphql-dataprovider';\n\n/**\n * Meetings Resource — multi-party scheduled and ad-hoc meeting hub in Explorer (the Meet app's \"Meetings\").\n *\n * Coordinates:\n * - Meeting list view (`mj-meeting-list`)\n * - Scheduling / editing form (`mj-meeting-schedule-form`)\n * - Pre-join lobby with AV checks & dial-in info (`mj-meeting-lobby`)\n * - Active multi-party call (`mj-livekit-agent-room` in join mode)\n *\n * Registered via `@RegisterClass(BaseResourceComponent, 'MeetingsResource')`.\n */\n@RegisterClass(BaseResourceComponent, 'MeetingsResource')\n@Component({\n standalone: false,\n selector: 'mj-meetings-resource',\n template: `\n @switch (Phase) {\n @case ('live') {\n <div class=\"mj-mtg-live-container\">\n <mj-livekit-agent-room\n class=\"mj-mtg-room\"\n Mode=\"join\"\n [RoomName]=\"LiveRoomName\"\n [Provider]=\"ProviderToUse\"\n [StartWithMicrophone]=\"StartWithMic\"\n [StartWithCamera]=\"StartWithCam\"\n [ShowAgentState]=\"true\"\n [EnableLayoutSwitcher]=\"true\"\n [EnableLeaveControl]=\"true\"\n (Disconnected)=\"OnLiveRoomLeft()\"\n ></mj-livekit-agent-room>\n </div>\n }\n @case ('lobby') {\n @if (ActiveMeeting) {\n <div class=\"mj-mtg-resource-wrapper\">\n <button type=\"button\" class=\"mj-mtg-back-btn\" (click)=\"OnLobbyCancelled()\">\n <i class=\"fa-solid fa-arrow-left\"></i> Back to Meetings\n </button>\n <mj-meeting-lobby\n [Meeting]=\"ActiveMeeting\"\n [Provider]=\"ProviderToUse\"\n (JoinConfirmed)=\"OnJoinConfirmed($event)\"\n (Cancelled)=\"OnLobbyCancelled()\"\n ></mj-meeting-lobby>\n </div>\n }\n }\n @case ('schedule') {\n <div class=\"mj-mtg-resource-wrapper\">\n <button type=\"button\" class=\"mj-mtg-back-btn\" (click)=\"OnScheduleCancelled()\">\n <i class=\"fa-solid fa-arrow-left\"></i> Back to Meetings\n </button>\n <mj-meeting-schedule-form\n [Provider]=\"ProviderToUse\"\n [Meeting]=\"EditingMeeting || undefined\"\n (MeetingSaved)=\"OnMeetingSaved($event)\"\n (Cancelled)=\"OnScheduleCancelled()\"\n ></mj-meeting-schedule-form>\n </div>\n }\n @default {\n <div class=\"mj-mtg-resource-wrapper\">\n <mj-meeting-list\n [Provider]=\"ProviderToUse\"\n (JoinMeeting)=\"OnJoinMeetingFromList($event)\"\n (ScheduleRequested)=\"OnScheduleRequested()\"\n (EditMeetingRequested)=\"OnEditMeetingRequested($event)\"\n ></mj-meeting-list>\n </div>\n }\n }\n `,\n styles: [\n `\n :host {\n display: block;\n height: 100%;\n overflow-y: auto;\n background: var(--mj-bg-page, #f8fafc);\n }\n .mj-mtg-resource-wrapper {\n padding: var(--mj-space-4, 16px);\n }\n .mj-mtg-live-container {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n .mj-mtg-room {\n display: block;\n height: 100%;\n }\n .mj-mtg-back-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n border: none;\n background: none;\n color: var(--mj-brand-primary, #0076b6);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n padding: 8px 12px;\n margin-bottom: 12px;\n border-radius: 6px;\n }\n .mj-mtg-back-btn:hover {\n background: rgba(0, 118, 182, 0.08);\n }\n `,\n ],\n})\nexport class MeetingsResource extends BaseResourceComponent implements OnInit {\n public Phase: 'list' | 'schedule' | 'lobby' | 'live' = 'list';\n public ActiveMeeting: MeetingInfo | null = null;\n public EditingMeeting: MeetingInfo | null = null;\n public LiveRoomName: string = '';\n public StartWithMic: boolean = true;\n public StartWithCam: boolean = false;\n\n override ngOnInit(): void {\n super.ngOnInit();\n void this.initialize();\n }\n\n private async initialize(): Promise<void> {\n const config = this.Data?.Configuration as { MeetingID?: string } | undefined;\n const initialMeetingId = config?.MeetingID || this.Data?.ResourceRecordID;\n if (initialMeetingId) {\n try {\n const client = new GraphQLMeetingClient(this.ProviderToUse || GraphQLDataProvider.Instance);\n const meeting = await client.GetMeeting(initialMeetingId);\n if (meeting) {\n this.ActiveMeeting = meeting;\n this.Phase = 'lobby';\n }\n } catch (err) {\n console.warn('MeetingsResource: unable to resolve initial meeting deep-link', err);\n }\n }\n this.NotifyLoadComplete();\n }\n\n public OnScheduleRequested(): void {\n this.EditingMeeting = null;\n this.Phase = 'schedule';\n }\n\n public OnEditMeetingRequested(meeting: MeetingInfo): void {\n this.EditingMeeting = meeting;\n this.Phase = 'schedule';\n }\n\n public OnMeetingSaved(meeting: MeetingInfo): void {\n this.ActiveMeeting = meeting;\n this.EditingMeeting = null;\n this.Phase = 'lobby';\n }\n\n public OnScheduleCancelled(): void {\n this.EditingMeeting = null;\n this.Phase = 'list';\n }\n\n public OnJoinMeetingFromList(meeting: MeetingInfo): void {\n this.ActiveMeeting = meeting;\n this.Phase = 'lobby';\n }\n\n public OnJoinConfirmed(prefs: { startWithAudio: boolean; startWithVideo: boolean }): void {\n this.StartWithMic = prefs.startWithAudio;\n this.StartWithCam = prefs.startWithVideo;\n this.LiveRoomName = this.ActiveMeeting?.RoomName || '';\n this.Phase = 'live';\n }\n\n public OnLobbyCancelled(): void {\n this.ActiveMeeting = null;\n this.Phase = 'list';\n }\n\n public OnLiveRoomLeft(): void {\n this.LiveRoomName = '';\n this.ActiveMeeting = null;\n this.Phase = 'list';\n }\n\n async GetResourceDisplayName(_data: ResourceData): Promise<string> {\n return this.ActiveMeeting?.Title || 'Meetings';\n }\n\n async GetResourceIconClass(_data: ResourceData): Promise<string> {\n return 'fa-solid fa-calendar-users';\n }\n}\n"]}
@@ -1,11 +1,36 @@
1
+ import { OnInit } from '@angular/core';
1
2
  import { BaseResourceComponent } from '@memberjunction/ng-shared';
2
3
  import { ResourceData } from '@memberjunction/core-entities';
3
4
  import { CompositeKey, IMetadataProvider } from '@memberjunction/core';
5
+ import { type FormCompositionSnapshot } from '@memberjunction/ng-base-forms';
4
6
  import * as i0 from "@angular/core";
5
- export declare class EntityRecordResource extends BaseResourceComponent {
7
+ export declare class EntityRecordResource extends BaseResourceComponent implements OnInit {
6
8
  private singleRecord?;
7
- /** A record being edited must never be consumed as the region's temp tab. */
9
+ private readonly workspace;
10
+ /** The form context this tab last reported, kept so it can be published again. */
11
+ private agentContext;
12
+ /** Fallback read for the pool predicate; promotion via ResourceEditModeChanged is the primary guard. */
8
13
  IsEditing(): boolean;
14
+ /** The hosted form entered or left edit mode; the shell promotes the tab on `true`. */
15
+ ResourceEditModeChanged(editing: boolean): void;
16
+ ngOnInit(): void;
17
+ /**
18
+ * Report the form to the agent context, so an agent asked to build a panel for this record
19
+ * knows what the form shows. The agent gets the compact form ({@link BuildFormAgentContext}):
20
+ * entity, record, which form, and the sections. The full snapshot stays in the browser, in
21
+ * the `FormCompositionRegistry` the apply flow reads.
22
+ *
23
+ * The shell folds this into `AppContextSnapshot.AdditionalContext` and assigns that wholesale,
24
+ * so the last publisher wins app-wide, and it rebuilds the app context without it on every tab
25
+ * switch. So the context is kept here and published only while this tab is the one on screen
26
+ * (attached and the active tab): a background tab's late resolve cannot replace the context of
27
+ * the surface the user sees, and returning to this tab publishes it again.
28
+ */
29
+ OnCompositionChanged(snapshot: FormCompositionSnapshot): void;
30
+ /** Publishes the kept context while this tab is on screen and the shell's context lacks it. */
31
+ private publishAgentContext;
32
+ /** True while the cache has this tab attached and it is the workspace's active tab. */
33
+ private isOnScreen;
9
34
  get PrimaryKey(): CompositeKey;
10
35
  static GetPrimaryKey(data: ResourceData, provider?: IMetadataProvider): CompositeKey;
11
36
  GetResourceDisplayName(data: ResourceData): Promise<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"record-resource.component.d.ts","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/record-resource.component.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EAAY,YAAY,EAAc,iBAAiB,EAA0B,MAAM,sBAAsB,CAAC;;AAErH,qBAOa,oBAAqB,SAAQ,qBAAqB;IACzB,OAAO,CAAC,YAAY,CAAC,CAAwB;IAE/E,6EAA6E;IAC7D,SAAS,IAAI,OAAO;IAIpC,IAAW,UAAU,IAAI,YAAY,CAEpC;WAEa,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,YAAY;IA4BrF,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA2B3D,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;yCAnEtD,oBAAoB;2CAApB,oBAAoB;CAgFhC"}
1
+ {"version":3,"file":"record-resource.component.d.ts","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/record-resource.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAqB,MAAM,eAAe,CAAC;AAGrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EAAY,YAAY,EAAc,iBAAiB,EAA0B,MAAM,sBAAsB,CAAC;AAErH,OAAO,EAAgD,KAAK,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;;AAC3H,qBAOa,oBAAqB,SAAQ,qBAAsB,YAAW,MAAM;IAC3C,OAAO,CAAC,YAAY,CAAC,CAAwB;IAE/E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAE3D,kFAAkF;IAClF,OAAO,CAAC,YAAY,CAA2C;IAE/D,wGAAwG;IACxF,SAAS,IAAI,OAAO;IAIpC,uFAAuF;IAChF,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAItC,QAAQ,IAAI,IAAI;IAahC;;;;;;;;;;;OAWG;IACI,oBAAoB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,IAAI;IAKpE,+FAA+F;IAC/F,OAAO,CAAC,mBAAmB;IAO3B,uFAAuF;IACvF,OAAO,CAAC,UAAU;IAMlB,IAAW,UAAU,IAAI,YAAY,CAEpC;WAEa,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,YAAY;IA4BrF,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA2B3D,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;yCA1HtD,oBAAoB;2CAApB,oBAAoB;CAuIhC"}
@@ -5,20 +5,72 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  var EntityRecordResource_1;
8
- import { Component, ViewChild } from '@angular/core';
8
+ import { Component, ViewChild, inject } from '@angular/core';
9
+ import { asapScheduler, merge } from 'rxjs';
10
+ import { filter, observeOn, takeUntil } from 'rxjs/operators';
9
11
  import { BaseResourceComponent } from '@memberjunction/ng-shared';
12
+ import { WorkspaceStateManager } from '@memberjunction/ng-base-application';
10
13
  import { RegisterClass } from '@memberjunction/global';
11
14
  import { Metadata, CompositeKey, IsNewEntityRecordUrlId } from '@memberjunction/core';
12
15
  import { SingleRecordComponent } from '../single-record/single-record.component';
16
+ import { BuildFormAgentContext } from '@memberjunction/ng-base-forms';
13
17
  import * as i0 from "@angular/core";
14
18
  import * as i1 from "../single-record/single-record.component";
15
19
  let EntityRecordResource = class EntityRecordResource extends BaseResourceComponent {
16
20
  static { EntityRecordResource_1 = this; }
17
21
  singleRecord;
18
- /** A record being edited must never be consumed as the region's temp tab. */
22
+ workspace = inject(WorkspaceStateManager);
23
+ /** The form context this tab last reported, kept so it can be published again. */
24
+ agentContext = null;
25
+ /** Fallback read for the pool predicate; promotion via ResourceEditModeChanged is the primary guard. */
19
26
  IsEditing() {
20
27
  return this.singleRecord?.IsEditing() === true;
21
28
  }
29
+ /** The hosted form entered or left edit mode; the shell promotes the tab on `true`. */
30
+ ResourceEditModeChanged(editing) {
31
+ this.NotifyEditModeChanged(editing);
32
+ }
33
+ ngOnInit() {
34
+ super.ngOnInit();
35
+ // Publish the kept context again when the shell's app context lacks it, or when the cache
36
+ // reattaches this tab. Deferred, so a publish never runs inside another subscriber's
37
+ // AppContextSnapshot$ delivery.
38
+ merge(this.navigationService.AppContextSnapshot$, this.navigationService.ResourceReattached$.pipe(filter((resource) => resource === this)))
39
+ .pipe(observeOn(asapScheduler), takeUntil(this.destroy$))
40
+ .subscribe(() => this.publishAgentContext());
41
+ }
42
+ /**
43
+ * Report the form to the agent context, so an agent asked to build a panel for this record
44
+ * knows what the form shows. The agent gets the compact form ({@link BuildFormAgentContext}):
45
+ * entity, record, which form, and the sections. The full snapshot stays in the browser, in
46
+ * the `FormCompositionRegistry` the apply flow reads.
47
+ *
48
+ * The shell folds this into `AppContextSnapshot.AdditionalContext` and assigns that wholesale,
49
+ * so the last publisher wins app-wide, and it rebuilds the app context without it on every tab
50
+ * switch. So the context is kept here and published only while this tab is the one on screen
51
+ * (attached and the active tab): a background tab's late resolve cannot replace the context of
52
+ * the surface the user sees, and returning to this tab publishes it again.
53
+ */
54
+ OnCompositionChanged(snapshot) {
55
+ this.agentContext = { Form: BuildFormAgentContext(snapshot) };
56
+ this.publishAgentContext();
57
+ }
58
+ /** Publishes the kept context while this tab is on screen and the shell's context lacks it. */
59
+ publishAgentContext() {
60
+ const context = this.agentContext;
61
+ if (!context || !this.isOnScreen())
62
+ return;
63
+ if (this.navigationService.AppContextSnapshot$.value?.AdditionalContext === context)
64
+ return;
65
+ this.navigationService.SetAgentContext(this, context);
66
+ }
67
+ /** True while the cache has this tab attached and it is the workspace's active tab. */
68
+ isOnScreen() {
69
+ if (this.navigationService.IsResourceDetached(this))
70
+ return false;
71
+ const tabId = this.getTabId();
72
+ return !!tabId && this.workspace.GetActiveTabId() === tabId;
73
+ }
22
74
  get PrimaryKey() {
23
75
  return EntityRecordResource_1.GetPrimaryKey(this.Data, this.ProviderToUse);
24
76
  }
@@ -89,9 +141,9 @@ let EntityRecordResource = class EntityRecordResource extends BaseResourceCompon
89
141
  } if (rf & 2) {
90
142
  let _t;
91
143
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.singleRecord = _t.first);
92
- } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 3, consts: [[3, "loadComplete", "recordSaved", "recordDismissed", "PrimaryKey", "entityName", "newRecordValues"]], template: function EntityRecordResource_Template(rf, ctx) { if (rf & 1) {
144
+ } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 3, consts: [[3, "loadComplete", "recordSaved", "recordDismissed", "EditModeChanged", "CompositionChanged", "PrimaryKey", "entityName", "newRecordValues"]], template: function EntityRecordResource_Template(rf, ctx) { if (rf & 1) {
93
145
  i0.ɵɵelementStart(0, "mj-single-record", 0);
94
- i0.ɵɵlistener("loadComplete", function EntityRecordResource_Template_mj_single_record_loadComplete_0_listener() { return ctx.NotifyLoadComplete(); })("recordSaved", function EntityRecordResource_Template_mj_single_record_recordSaved_0_listener($event) { return ctx.ResourceRecordSaved($event); })("recordDismissed", function EntityRecordResource_Template_mj_single_record_recordDismissed_0_listener() { return ctx.NotifyCloseRequested(); });
146
+ i0.ɵɵlistener("loadComplete", function EntityRecordResource_Template_mj_single_record_loadComplete_0_listener() { return ctx.NotifyLoadComplete(); })("recordSaved", function EntityRecordResource_Template_mj_single_record_recordSaved_0_listener($event) { return ctx.ResourceRecordSaved($event); })("recordDismissed", function EntityRecordResource_Template_mj_single_record_recordDismissed_0_listener() { return ctx.NotifyCloseRequested(); })("EditModeChanged", function EntityRecordResource_Template_mj_single_record_EditModeChanged_0_listener($event) { return ctx.ResourceEditModeChanged($event); })("CompositionChanged", function EntityRecordResource_Template_mj_single_record_CompositionChanged_0_listener($event) { return ctx.OnCompositionChanged($event); });
95
147
  i0.ɵɵelementEnd();
96
148
  } if (rf & 2) {
97
149
  i0.ɵɵproperty("PrimaryKey", ctx.PrimaryKey)("entityName", ctx.Data.Configuration.Entity)("newRecordValues", ctx.Data.Configuration.NewRecordValues);
@@ -103,10 +155,10 @@ EntityRecordResource = EntityRecordResource_1 = __decorate([
103
155
  export { EntityRecordResource };
104
156
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(EntityRecordResource, [{
105
157
  type: Component,
106
- args: [{ standalone: false, selector: 'mj-record-resource', template: `<mj-single-record [PrimaryKey]="this.PrimaryKey" [entityName]="Data.Configuration.Entity" [newRecordValues]="Data.Configuration.NewRecordValues" (loadComplete)="NotifyLoadComplete()" (recordSaved)="ResourceRecordSaved($event)" (recordDismissed)="NotifyCloseRequested()"></mj-single-record>`, styles: [":host { display: block; height: 100%; width: 100%; }"] }]
158
+ args: [{ standalone: false, selector: 'mj-record-resource', template: `<mj-single-record [PrimaryKey]="this.PrimaryKey" [entityName]="Data.Configuration.Entity" [newRecordValues]="Data.Configuration.NewRecordValues" (loadComplete)="NotifyLoadComplete()" (recordSaved)="ResourceRecordSaved($event)" (recordDismissed)="NotifyCloseRequested()" (EditModeChanged)="ResourceEditModeChanged($event)" (CompositionChanged)="OnCompositionChanged($event)"></mj-single-record>`, styles: [":host { display: block; height: 100%; width: 100%; }"] }]
107
159
  }], null, { singleRecord: [{
108
160
  type: ViewChild,
109
161
  args: [SingleRecordComponent]
110
162
  }] }); })();
111
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EntityRecordResource, { className: "EntityRecordResource", filePath: "src/lib/resource-wrappers/record-resource.component.ts", lineNumber: 14 }); })();
163
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EntityRecordResource, { className: "EntityRecordResource", filePath: "src/lib/resource-wrappers/record-resource.component.ts", lineNumber: 18 }); })();
112
164
  //# sourceMappingURL=record-resource.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"record-resource.component.js","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/record-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ViewChild } from '@angular/core';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { ResourceData } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport { Metadata, CompositeKey, EntityInfo, IMetadataProvider, IsNewEntityRecordUrlId } from '@memberjunction/core';\nimport { SingleRecordComponent } from '../single-record/single-record.component';\n@RegisterClass(BaseResourceComponent, 'RecordResource')\n@Component({\n standalone: false,\n selector: 'mj-record-resource',\n styles: [`:host { display: block; height: 100%; width: 100%; }`],\n template: `<mj-single-record [PrimaryKey]=\"this.PrimaryKey\" [entityName]=\"Data.Configuration.Entity\" [newRecordValues]=\"Data.Configuration.NewRecordValues\" (loadComplete)=\"NotifyLoadComplete()\" (recordSaved)=\"ResourceRecordSaved($event)\" (recordDismissed)=\"NotifyCloseRequested()\"></mj-single-record>`\n})\nexport class EntityRecordResource extends BaseResourceComponent {\n @ViewChild(SingleRecordComponent) private singleRecord?: SingleRecordComponent;\n\n /** A record being edited must never be consumed as the region's temp tab. */\n public override IsEditing(): boolean {\n return this.singleRecord?.IsEditing() === true;\n }\n\n public get PrimaryKey(): CompositeKey {\n return EntityRecordResource.GetPrimaryKey(this.Data, this.ProviderToUse);\n }\n\n public static GetPrimaryKey(data: ResourceData, provider?: IMetadataProvider): CompositeKey {\n // global-provider-ok: static helper has no component instance scope; falls back to default provider\n const md = (provider ?? Metadata.Provider) as IMetadataProvider;\n const requested = (data.Configuration.Entity ?? '').trim();\n // Prefer EntityByName (project rule: never use Entities.find for\n // single-entity lookups — case/whitespace tolerant + O(1) map). Fall\n // back to DisplayName match for callers (AI agents, hand-typed URLs,\n // external CTAs) that pass the human-readable display name instead\n // of the canonical Name (e.g. \"Users\" for \"MJ: Users\").\n let e: EntityInfo | undefined = md.EntityByName(requested);\n if (!e) {\n const lowered = requested.toLowerCase();\n e = md.Entities.find((x: EntityInfo) =>\n (x.DisplayName ?? '').trim().toLowerCase() === lowered);\n }\n if (!e){\n throw new Error(`Entity ${data.Configuration.Entity} not found in metadata (tried Name and DisplayName)`);\n }\n\n if (IsNewEntityRecordUrlId(data.ResourceRecordID)) {\n return new CompositeKey();\n }\n\n let compositeKey: CompositeKey = new CompositeKey();\n compositeKey.LoadFromURLSegment(e, data.ResourceRecordID);\n return compositeKey;\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n if (!data.Configuration.Entity) {\n return '';\n }\n\n const md = this.ProviderToUse;\n let e = md.EntityByName(data.Configuration.Entity);\n if (!e) {\n // Same DisplayName fallback as GetPrimaryKey — keeps the\n // breadcrumb/title in sync when a CTA used the display name.\n const lowered = (data.Configuration.Entity ?? '').trim().toLowerCase();\n e = md.Entities.find((x: EntityInfo) =>\n (x.DisplayName ?? '').trim().toLowerCase() === lowered);\n }\n if (!e) {\n return '';\n }\n\n const pk: CompositeKey = EntityRecordResource.GetPrimaryKey(data, this.ProviderToUse);\n if (pk.HasValue) {\n const name = await md.GetEntityRecordName(data.Configuration.Entity, pk);\n return name ? name : e.DisplayNameOrName;\n } else {\n return `New ${e.DisplayNameOrName} Record`;\n }\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n if (!data.Configuration.Entity){\n return ''\n }\n else {\n const md = this.ProviderToUse;\n const e = md.Entities.find(e => e.Name.trim().toLowerCase() === data.Configuration.Entity.trim().toLowerCase());\n if (e)\n return e?.Icon;\n else\n return '';\n }\n }\n}\n"]}
1
+ {"version":3,"file":"record-resource.component.js","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/record-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, ViewChild, inject } from '@angular/core';\nimport { asapScheduler, merge } from 'rxjs';\nimport { filter, observeOn, takeUntil } from 'rxjs/operators';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { WorkspaceStateManager } from '@memberjunction/ng-base-application';\nimport { ResourceData } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport { Metadata, CompositeKey, EntityInfo, IMetadataProvider, IsNewEntityRecordUrlId } from '@memberjunction/core';\nimport { SingleRecordComponent } from '../single-record/single-record.component';\nimport { BuildFormAgentContext, type FormAgentContext, type FormCompositionSnapshot } from '@memberjunction/ng-base-forms';\n@RegisterClass(BaseResourceComponent, 'RecordResource')\n@Component({\n standalone: false,\n selector: 'mj-record-resource',\n styles: [`:host { display: block; height: 100%; width: 100%; }`],\n template: `<mj-single-record [PrimaryKey]=\"this.PrimaryKey\" [entityName]=\"Data.Configuration.Entity\" [newRecordValues]=\"Data.Configuration.NewRecordValues\" (loadComplete)=\"NotifyLoadComplete()\" (recordSaved)=\"ResourceRecordSaved($event)\" (recordDismissed)=\"NotifyCloseRequested()\" (EditModeChanged)=\"ResourceEditModeChanged($event)\" (CompositionChanged)=\"OnCompositionChanged($event)\"></mj-single-record>`\n})\nexport class EntityRecordResource extends BaseResourceComponent implements OnInit {\n @ViewChild(SingleRecordComponent) private singleRecord?: SingleRecordComponent;\n\n private readonly workspace = inject(WorkspaceStateManager);\n\n /** The form context this tab last reported, kept so it can be published again. */\n private agentContext: { Form: FormAgentContext } | null = null;\n\n /** Fallback read for the pool predicate; promotion via ResourceEditModeChanged is the primary guard. */\n public override IsEditing(): boolean {\n return this.singleRecord?.IsEditing() === true;\n }\n\n /** The hosted form entered or left edit mode; the shell promotes the tab on `true`. */\n public ResourceEditModeChanged(editing: boolean): void {\n this.NotifyEditModeChanged(editing);\n }\n\n public override ngOnInit(): void {\n super.ngOnInit();\n // Publish the kept context again when the shell's app context lacks it, or when the cache\n // reattaches this tab. Deferred, so a publish never runs inside another subscriber's\n // AppContextSnapshot$ delivery.\n merge(\n this.navigationService.AppContextSnapshot$,\n this.navigationService.ResourceReattached$.pipe(filter((resource) => resource === this)),\n )\n .pipe(observeOn(asapScheduler), takeUntil(this.destroy$))\n .subscribe(() => this.publishAgentContext());\n }\n\n /**\n * Report the form to the agent context, so an agent asked to build a panel for this record\n * knows what the form shows. The agent gets the compact form ({@link BuildFormAgentContext}):\n * entity, record, which form, and the sections. The full snapshot stays in the browser, in\n * the `FormCompositionRegistry` the apply flow reads.\n *\n * The shell folds this into `AppContextSnapshot.AdditionalContext` and assigns that wholesale,\n * so the last publisher wins app-wide, and it rebuilds the app context without it on every tab\n * switch. So the context is kept here and published only while this tab is the one on screen\n * (attached and the active tab): a background tab's late resolve cannot replace the context of\n * the surface the user sees, and returning to this tab publishes it again.\n */\n public OnCompositionChanged(snapshot: FormCompositionSnapshot): void {\n this.agentContext = { Form: BuildFormAgentContext(snapshot) };\n this.publishAgentContext();\n }\n\n /** Publishes the kept context while this tab is on screen and the shell's context lacks it. */\n private publishAgentContext(): void {\n const context = this.agentContext;\n if (!context || !this.isOnScreen()) return;\n if (this.navigationService.AppContextSnapshot$.value?.AdditionalContext === context) return;\n this.navigationService.SetAgentContext(this, context);\n }\n\n /** True while the cache has this tab attached and it is the workspace's active tab. */\n private isOnScreen(): boolean {\n if (this.navigationService.IsResourceDetached(this)) return false;\n const tabId = this.getTabId();\n return !!tabId && this.workspace.GetActiveTabId() === tabId;\n }\n\n public get PrimaryKey(): CompositeKey {\n return EntityRecordResource.GetPrimaryKey(this.Data, this.ProviderToUse);\n }\n\n public static GetPrimaryKey(data: ResourceData, provider?: IMetadataProvider): CompositeKey {\n // global-provider-ok: static helper has no component instance scope; falls back to default provider\n const md = (provider ?? Metadata.Provider) as IMetadataProvider;\n const requested = (data.Configuration.Entity ?? '').trim();\n // Prefer EntityByName (project rule: never use Entities.find for\n // single-entity lookups — case/whitespace tolerant + O(1) map). Fall\n // back to DisplayName match for callers (AI agents, hand-typed URLs,\n // external CTAs) that pass the human-readable display name instead\n // of the canonical Name (e.g. \"Users\" for \"MJ: Users\").\n let e: EntityInfo | undefined = md.EntityByName(requested);\n if (!e) {\n const lowered = requested.toLowerCase();\n e = md.Entities.find((x: EntityInfo) =>\n (x.DisplayName ?? '').trim().toLowerCase() === lowered);\n }\n if (!e){\n throw new Error(`Entity ${data.Configuration.Entity} not found in metadata (tried Name and DisplayName)`);\n }\n\n if (IsNewEntityRecordUrlId(data.ResourceRecordID)) {\n return new CompositeKey();\n }\n\n let compositeKey: CompositeKey = new CompositeKey();\n compositeKey.LoadFromURLSegment(e, data.ResourceRecordID);\n return compositeKey;\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n if (!data.Configuration.Entity) {\n return '';\n }\n\n const md = this.ProviderToUse;\n let e = md.EntityByName(data.Configuration.Entity);\n if (!e) {\n // Same DisplayName fallback as GetPrimaryKey — keeps the\n // breadcrumb/title in sync when a CTA used the display name.\n const lowered = (data.Configuration.Entity ?? '').trim().toLowerCase();\n e = md.Entities.find((x: EntityInfo) =>\n (x.DisplayName ?? '').trim().toLowerCase() === lowered);\n }\n if (!e) {\n return '';\n }\n\n const pk: CompositeKey = EntityRecordResource.GetPrimaryKey(data, this.ProviderToUse);\n if (pk.HasValue) {\n const name = await md.GetEntityRecordName(data.Configuration.Entity, pk);\n return name ? name : e.DisplayNameOrName;\n } else {\n return `New ${e.DisplayNameOrName} Record`;\n }\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n if (!data.Configuration.Entity){\n return ''\n }\n else {\n const md = this.ProviderToUse;\n const e = md.Entities.find(e => e.Name.trim().toLowerCase() === data.Configuration.Entity.trim().toLowerCase());\n if (e)\n return e?.Icon;\n else\n return '';\n }\n }\n}\n"]}
@@ -76,6 +76,7 @@ export declare class UserViewResource extends BaseResourceComponent {
76
76
  private dataLoaded;
77
77
  private get metadata();
78
78
  constructor(cdr: ChangeDetectorRef, exportService: ExportService);
79
+ ngOnInit(): void;
79
80
  set Data(value: ResourceData);
80
81
  get Data(): ResourceData;
81
82
  /**
@@ -128,7 +129,11 @@ export declare class UserViewResource extends BaseResourceComponent {
128
129
  OnExport(): Promise<void>;
129
130
  /** @deprecated Use {@link OnExport}. */
130
131
  onExport(): Promise<void>;
131
- /** Columns to export — from grid state, else the view's columns, else the entity's real fields. */
132
+ /**
133
+ * Columns to export — from grid state, else the view's columns, else the entity's real fields. Each
134
+ * column carries its field's export type, as the grid's export does, so a date-only field writes
135
+ * a date cell on its stored day rather than a timestamp.
136
+ */
132
137
  private buildExportColumns;
133
138
  private buildExportFileName;
134
139
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"view-resource.component.d.ts","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/view-resource.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"view-resource.component.d.ts","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/view-resource.component.ts"],"names":[],"mappings":"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"}
@@ -8,8 +8,10 @@ import { Component, ViewChild } from '@angular/core';
8
8
  import { BaseResourceComponent } from '@memberjunction/ng-shared';
9
9
  import { ViewInfo } from '@memberjunction/core-entities';
10
10
  import { RegisterClass, MJGlobal, MJEventType, UUIDsEqual } from '@memberjunction/global';
11
- import { CompositeKey } from '@memberjunction/core';
11
+ import { CompositeKey, BaseEntity } from '@memberjunction/core';
12
+ import { ExportColumnTypeForSQLType } from '@memberjunction/ng-entity-viewer';
12
13
  import { GraphQLListsClient } from '@memberjunction/graphql-dataprovider';
14
+ import { debounceTime, filter, takeUntil } from 'rxjs/operators';
13
15
  import * as i0 from "@angular/core";
14
16
  import * as i1 from "@memberjunction/ng-export-service";
15
17
  import * as i2 from "@memberjunction/ng-shared-generic";
@@ -244,6 +246,25 @@ let UserViewResource = class UserViewResource extends BaseResourceComponent {
244
246
  this.cdr = cdr;
245
247
  this.exportService = exportService;
246
248
  }
249
+ ngOnInit() {
250
+ super.ngOnInit();
251
+ // Refresh when rows of this view's entity change: a local save/delete, or a server-side
252
+ // write announced as remote-invalidate (a clone, or another server). Debounced, so a burst
253
+ // of writes (a clone creating many rows) reloads the view once.
254
+ MJGlobal.Instance.GetEventListener()
255
+ .pipe(filter((event) => {
256
+ if (event.event !== MJEventType.ComponentEvent || event.eventCode !== BaseEntity.BaseEventCode)
257
+ return false;
258
+ const entityEvent = event.args;
259
+ const type = entityEvent?.type;
260
+ if (type !== 'save' && type !== 'delete' && type !== 'remote-invalidate')
261
+ return false;
262
+ const affectedName = (entityEvent.baseEntity?.EntityInfo?.Name ?? entityEvent.entityName)?.trim().toLowerCase();
263
+ return !!affectedName && affectedName === this.entityInfo?.Name?.trim().toLowerCase();
264
+ }), debounceTime(300), takeUntil(this.destroy$))
265
+ // In place: a change made elsewhere shouldn't move the user off their page or sort.
266
+ .subscribe(() => this.entityViewerRef?.RefreshInPlace());
267
+ }
247
268
  set Data(value) {
248
269
  const previousRecordId = super.Data?.ResourceRecordID;
249
270
  const previousEntity = super.Data?.Configuration?.Entity;
@@ -469,23 +490,32 @@ let UserViewResource = class UserViewResource extends BaseResourceComponent {
469
490
  async onExport() {
470
491
  return this.OnExport();
471
492
  }
472
- /** Columns to export — from grid state, else the view's columns, else the entity's real fields. */
493
+ /**
494
+ * Columns to export — from grid state, else the view's columns, else the entity's real fields. Each
495
+ * column carries its field's export type, as the grid's export does, so a date-only field writes
496
+ * a date cell on its stored day rather than a timestamp.
497
+ */
473
498
  buildExportColumns() {
474
499
  if (!this.EntityInfo)
475
500
  return [];
501
+ const entity = this.EntityInfo;
502
+ const typed = (name, displayName) => {
503
+ const field = entity.Fields.find(f => f.Name.toLowerCase() === name.toLowerCase());
504
+ return { name, displayName, dataType: ExportColumnTypeForSQLType(field?.Type) };
505
+ };
476
506
  if (this.GridState?.columnSettings && this.GridState.columnSettings.length > 0) {
477
507
  return this.GridState.columnSettings
478
508
  .filter(col => col.hidden !== true)
479
- .map(col => ({ name: col.Name, displayName: col.DisplayName || col.Name }));
509
+ .map(col => typed(col.Name, col.DisplayName || col.Name));
480
510
  }
481
511
  if (this.ViewEntity?.Columns) {
482
512
  return this.ViewEntity.Columns
483
513
  .filter(col => !col.hidden)
484
- .map(col => ({ name: col.Name, displayName: col.DisplayName || col.Name }));
514
+ .map(col => typed(col.Name, col.DisplayName || col.Name));
485
515
  }
486
- return this.EntityInfo.Fields
516
+ return entity.Fields
487
517
  .filter(f => !f.IsVirtual)
488
- .map(f => ({ name: f.Name, displayName: f.DisplayNameOrName }));
518
+ .map(f => typed(f.Name, f.DisplayNameOrName));
489
519
  }
490
520
  buildExportFileName() {
491
521
  const viewName = this.ViewEntity?.Name || 'Data';
@@ -639,5 +669,5 @@ export { UserViewResource };
639
669
  type: ViewChild,
640
670
  args: ['entityViewer']
641
671
  }] }); })();
642
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserViewResource, { className: "UserViewResource", filePath: "src/lib/resource-wrappers/view-resource.component.ts", lineNumber: 138 }); })();
672
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserViewResource, { className: "UserViewResource", filePath: "src/lib/resource-wrappers/view-resource.component.ts", lineNumber: 139 }); })();
643
673
  //# sourceMappingURL=view-resource.component.js.map