@memberjunction/ng-explorer-core 6.2.0-edge.0 → 6.2.0-edge.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-routing.module.d.ts +23 -1
- package/dist/app-routing.module.d.ts.map +1 -1
- package/dist/app-routing.module.js +50 -14
- package/dist/app-routing.module.js.map +1 -1
- package/dist/lib/command-palette/command-palette.component.d.ts +7 -1
- package/dist/lib/command-palette/command-palette.component.d.ts.map +1 -1
- package/dist/lib/command-palette/command-palette.component.js +28 -14
- package/dist/lib/command-palette/command-palette.component.js.map +1 -1
- package/dist/lib/conversation-feedback/conversation-feedback.d.ts +103 -13
- package/dist/lib/conversation-feedback/conversation-feedback.d.ts.map +1 -1
- package/dist/lib/conversation-feedback/conversation-feedback.js +219 -67
- package/dist/lib/conversation-feedback/conversation-feedback.js.map +1 -1
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.d.ts +64 -10
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.d.ts.map +1 -1
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +172 -66
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -1
- package/dist/lib/generic/resource-container-component.d.ts +19 -5
- package/dist/lib/generic/resource-container-component.d.ts.map +1 -1
- package/dist/lib/generic/resource-container-component.js +43 -13
- package/dist/lib/generic/resource-container-component.js.map +1 -1
- package/dist/lib/guards/entities.guard.d.ts +4 -0
- package/dist/lib/guards/entities.guard.d.ts.map +1 -1
- package/dist/lib/guards/entities.guard.js +10 -2
- package/dist/lib/guards/entities.guard.js.map +1 -1
- package/dist/lib/identity-claims/claim-redeem.component.d.ts +4 -0
- package/dist/lib/identity-claims/claim-redeem.component.d.ts.map +1 -1
- package/dist/lib/identity-claims/claim-redeem.component.js +10 -2
- package/dist/lib/identity-claims/claim-redeem.component.js.map +1 -1
- package/dist/lib/oauth/oauth-callback.component.d.ts +4 -0
- package/dist/lib/oauth/oauth-callback.component.d.ts.map +1 -1
- package/dist/lib/oauth/oauth-callback.component.js +10 -2
- package/dist/lib/oauth/oauth-callback.component.js.map +1 -1
- package/dist/lib/profile/profile-dialog.component.d.ts.map +1 -1
- package/dist/lib/profile/profile-dialog.component.js +194 -191
- package/dist/lib/profile/profile-dialog.component.js.map +1 -1
- package/dist/lib/resource-wrappers/artifact-resource.component.d.ts +20 -2
- package/dist/lib/resource-wrappers/artifact-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/artifact-resource.component.js +33 -9
- package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts +80 -10
- package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-collections-resource.component.js +168 -56
- package/dist/lib/resource-wrappers/chat-collections-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +186 -23
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +500 -177
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-deeplink-params.d.ts +2 -0
- package/dist/lib/resource-wrappers/chat-deeplink-params.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-deeplink-params.js +5 -1
- package/dist/lib/resource-wrappers/chat-deeplink-params.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-search-routing.d.ts +25 -0
- package/dist/lib/resource-wrappers/chat-search-routing.d.ts.map +1 -0
- package/dist/lib/resource-wrappers/chat-search-routing.js +24 -0
- package/dist/lib/resource-wrappers/chat-search-routing.js.map +1 -0
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts +14 -2
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.js +32 -8
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts +54 -8
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js +138 -46
- package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts +223 -30
- package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/livekit-room-resource.component.js +438 -118
- package/dist/lib/resource-wrappers/livekit-room-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.d.ts +7 -3
- package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.js +23 -15
- package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/view-resource.component.d.ts +68 -10
- package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/view-resource.component.js +178 -62
- package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
- package/dist/lib/services/startup-validation.service.d.ts +4 -0
- package/dist/lib/services/startup-validation.service.d.ts.map +1 -1
- package/dist/lib/services/startup-validation.service.js +10 -2
- package/dist/lib/services/startup-validation.service.js.map +1 -1
- package/dist/lib/services/system-validation.service.d.ts +13 -1
- package/dist/lib/services/system-validation.service.d.ts.map +1 -1
- package/dist/lib/services/system-validation.service.js +29 -5
- package/dist/lib/services/system-validation.service.js.map +1 -1
- package/dist/lib/shell/components/dialogs/app-access-dialog.component.d.ts +54 -4
- package/dist/lib/shell/components/dialogs/app-access-dialog.component.d.ts.map +1 -1
- package/dist/lib/shell/components/dialogs/app-access-dialog.component.js +130 -40
- package/dist/lib/shell/components/dialogs/app-access-dialog.component.js.map +1 -1
- package/dist/lib/shell/components/header/app-nav.component.d.ts +29 -1
- package/dist/lib/shell/components/header/app-nav.component.d.ts.map +1 -1
- package/dist/lib/shell/components/header/app-nav.component.js +56 -12
- package/dist/lib/shell/components/header/app-nav.component.js.map +1 -1
- package/dist/lib/shell/components/header/app-switcher.component.d.ts +33 -5
- package/dist/lib/shell/components/header/app-switcher.component.d.ts.map +1 -1
- package/dist/lib/shell/components/header/app-switcher.component.js +85 -29
- package/dist/lib/shell/components/header/app-switcher.component.js.map +1 -1
- package/dist/lib/shell/components/record-open/record-origin-crumb.component.js +1 -1
- package/dist/lib/shell/components/record-open/record-origin-crumb.component.js.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts +50 -6
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.js +95 -22
- package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts +91 -9
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.js +257 -101
- package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
- package/dist/lib/shell/loading-themes.d.ts +16 -12
- package/dist/lib/shell/loading-themes.d.ts.map +1 -1
- package/dist/lib/shell/loading-themes.js +145 -137
- package/dist/lib/shell/loading-themes.js.map +1 -1
- package/dist/lib/shell/readiness-beacon.d.ts +2 -0
- package/dist/lib/shell/readiness-beacon.d.ts.map +1 -1
- package/dist/lib/shell/readiness-beacon.js +5 -1
- package/dist/lib/shell/readiness-beacon.js.map +1 -1
- package/dist/lib/shell/services/about-dialog.service.d.ts +6 -0
- package/dist/lib/shell/services/about-dialog.service.d.ts.map +1 -1
- package/dist/lib/shell/services/about-dialog.service.js +16 -4
- package/dist/lib/shell/services/about-dialog.service.js.map +1 -1
- package/dist/lib/shell/services/profile-dialog.service.d.ts +6 -0
- package/dist/lib/shell/services/profile-dialog.service.d.ts.map +1 -1
- package/dist/lib/shell/services/profile-dialog.service.js +16 -4
- package/dist/lib/shell/services/profile-dialog.service.js.map +1 -1
- package/dist/lib/shell/services/user-sharing-center-dialog.service.d.ts +6 -0
- package/dist/lib/shell/services/user-sharing-center-dialog.service.d.ts.map +1 -1
- package/dist/lib/shell/services/user-sharing-center-dialog.service.js +15 -3
- package/dist/lib/shell/services/user-sharing-center-dialog.service.js.map +1 -1
- package/dist/lib/shell/shell.component.d.ts +262 -39
- package/dist/lib/shell/shell.component.d.ts.map +1 -1
- package/dist/lib/shell/shell.component.js +688 -292
- package/dist/lib/shell/shell.component.js.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts +64 -8
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +129 -37
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
- package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.d.ts +26 -2
- package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js +48 -10
- package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js.map +1 -1
- package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.d.ts +84 -6
- package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js +133 -29
- package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.d.ts +173 -23
- package/dist/lib/single-dashboard/single-dashboard.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js +383 -109
- package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts +383 -55
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.js +962 -326
- package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
- package/dist/lib/single-query/single-query.component.d.ts +22 -2
- package/dist/lib/single-query/single-query.component.d.ts.map +1 -1
- package/dist/lib/single-query/single-query.component.js +40 -10
- package/dist/lib/single-query/single-query.component.js.map +1 -1
- package/dist/lib/single-record/single-record.component.d.ts +41 -3
- package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
- package/dist/lib/single-record/single-record.component.js +71 -11
- package/dist/lib/single-record/single-record.component.js.map +1 -1
- package/dist/lib/single-search-result/single-search-result.component.d.ts +23 -3
- package/dist/lib/single-search-result/single-search-result.component.d.ts.map +1 -1
- package/dist/lib/single-search-result/single-search-result.component.js +42 -12
- package/dist/lib/single-search-result/single-search-result.component.js.map +1 -1
- package/dist/lib/system-validation/system-validation-banner.component.d.ts +12 -2
- package/dist/lib/system-validation/system-validation-banner.component.d.ts.map +1 -1
- package/dist/lib/system-validation/system-validation-banner.component.js +25 -5
- package/dist/lib/system-validation/system-validation-banner.component.js.map +1 -1
- package/dist/lib/user-menu/user-menu.types.d.ts +4 -0
- package/dist/lib/user-menu/user-menu.types.d.ts.map +1 -1
- package/dist/lib/user-menu/user-menu.types.js +10 -2
- package/dist/lib/user-menu/user-menu.types.js.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.d.ts +59 -7
- package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.js +151 -47
- package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
- package/dist/lib/user-profile/user-profile.component.d.ts +3 -2
- package/dist/lib/user-profile/user-profile.component.d.ts.map +1 -1
- package/dist/lib/user-profile/user-profile.component.js +5 -4
- package/dist/lib/user-profile/user-profile.component.js.map +1 -1
- package/package.json +52 -52
|
@@ -158,20 +158,60 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
158
158
|
appRef;
|
|
159
159
|
environmentInjector;
|
|
160
160
|
cdr;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
GlContainer;
|
|
162
|
+
/** @deprecated Use {@link GlContainer}. */
|
|
163
|
+
get glContainer() {
|
|
164
|
+
return this.GlContainer;
|
|
165
|
+
}
|
|
166
|
+
/** @deprecated Use {@link GlContainer}. */
|
|
167
|
+
set glContainer(value) {
|
|
168
|
+
this.GlContainer = value;
|
|
169
|
+
}
|
|
170
|
+
DirectContentContainer;
|
|
171
|
+
/** @deprecated Use {@link DirectContentContainer}. */
|
|
172
|
+
get directContentContainer() {
|
|
173
|
+
return this.DirectContentContainer;
|
|
174
|
+
}
|
|
175
|
+
/** @deprecated Use {@link DirectContentContainer}. */
|
|
176
|
+
set directContentContainer(value) {
|
|
177
|
+
this.DirectContentContainer = value;
|
|
178
|
+
}
|
|
179
|
+
RecordsGlContainer;
|
|
180
|
+
/** @deprecated Use {@link RecordsGlContainer}. */
|
|
181
|
+
get recordsGlContainer() {
|
|
182
|
+
return this.RecordsGlContainer;
|
|
183
|
+
}
|
|
184
|
+
/** @deprecated Use {@link RecordsGlContainer}. */
|
|
185
|
+
set recordsGlContainer(value) {
|
|
186
|
+
this.RecordsGlContainer = value;
|
|
187
|
+
}
|
|
164
188
|
/**
|
|
165
189
|
* Emitted when the first resource component finishes loading.
|
|
166
190
|
* This allows the shell to keep showing its loading indicator until the first
|
|
167
191
|
* resource is ready, eliminating the visual gap between shell loading and resource loading.
|
|
168
192
|
*/
|
|
169
|
-
|
|
193
|
+
FirstResourceLoadComplete = new EventEmitter();
|
|
194
|
+
/**
|
|
195
|
+
* @deprecated Use {@link FirstResourceLoadComplete}.
|
|
196
|
+
*
|
|
197
|
+
* The same emitter under the old binding name, so a template still binding
|
|
198
|
+
* (firstResourceLoadComplete) keeps working. Must stay AFTER FirstResourceLoadComplete: class fields
|
|
199
|
+
* initialise in order, and the other way round this captures undefined.
|
|
200
|
+
*/
|
|
201
|
+
firstResourceLoadComplete = this.FirstResourceLoadComplete;
|
|
170
202
|
/**
|
|
171
203
|
* Emitted when Golden Layout fails to initialize after multiple retries.
|
|
172
204
|
* The shell can use this to show an error dialog and redirect.
|
|
173
205
|
*/
|
|
174
|
-
|
|
206
|
+
LayoutInitError = new EventEmitter();
|
|
207
|
+
/**
|
|
208
|
+
* @deprecated Use {@link LayoutInitError}.
|
|
209
|
+
*
|
|
210
|
+
* The same emitter under the old binding name, so a template still binding
|
|
211
|
+
* (layoutInitError) keeps working. Must stay AFTER LayoutInitError: class fields
|
|
212
|
+
* initialise in order, and the other way round this captures undefined.
|
|
213
|
+
*/
|
|
214
|
+
layoutInitError = this.LayoutInitError;
|
|
175
215
|
pinService = inject(HomeAppPinService);
|
|
176
216
|
navigationService = inject(NavigationService);
|
|
177
217
|
recordSwitcher = inject(RecordSwitcherService);
|
|
@@ -201,7 +241,15 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
201
241
|
cacheManager;
|
|
202
242
|
// Single-resource mode: render component directly without Golden Layout
|
|
203
243
|
// This avoids the 20px height issue when GL header is hidden
|
|
204
|
-
|
|
244
|
+
UseSingleResourceMode = false;
|
|
245
|
+
/** @deprecated Use {@link UseSingleResourceMode}. */
|
|
246
|
+
get useSingleResourceMode() {
|
|
247
|
+
return this.UseSingleResourceMode;
|
|
248
|
+
}
|
|
249
|
+
/** @deprecated Use {@link UseSingleResourceMode}. */
|
|
250
|
+
set useSingleResourceMode(value) {
|
|
251
|
+
this.UseSingleResourceMode = value;
|
|
252
|
+
}
|
|
205
253
|
singleResourceComponentRef = null;
|
|
206
254
|
/** Cache identity of the current single-resource component for detachment */
|
|
207
255
|
singleResourceCacheIdentity = null;
|
|
@@ -209,10 +257,42 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
209
257
|
currentSingleResourceSignature = null; // Track loaded content signature to avoid unnecessary reloads
|
|
210
258
|
isCreatingInitialTabs = false; // Flag to prevent syncTabsWithConfiguration during initial tab creation
|
|
211
259
|
// Context menu state
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
260
|
+
ContextMenuVisible = false;
|
|
261
|
+
/** @deprecated Use {@link ContextMenuVisible}. */
|
|
262
|
+
get contextMenuVisible() {
|
|
263
|
+
return this.ContextMenuVisible;
|
|
264
|
+
}
|
|
265
|
+
/** @deprecated Use {@link ContextMenuVisible}. */
|
|
266
|
+
set contextMenuVisible(value) {
|
|
267
|
+
this.ContextMenuVisible = value;
|
|
268
|
+
}
|
|
269
|
+
ContextMenuX = 0;
|
|
270
|
+
/** @deprecated Use {@link ContextMenuX}. */
|
|
271
|
+
get contextMenuX() {
|
|
272
|
+
return this.ContextMenuX;
|
|
273
|
+
}
|
|
274
|
+
/** @deprecated Use {@link ContextMenuX}. */
|
|
275
|
+
set contextMenuX(value) {
|
|
276
|
+
this.ContextMenuX = value;
|
|
277
|
+
}
|
|
278
|
+
ContextMenuY = 0;
|
|
279
|
+
/** @deprecated Use {@link ContextMenuY}. */
|
|
280
|
+
get contextMenuY() {
|
|
281
|
+
return this.ContextMenuY;
|
|
282
|
+
}
|
|
283
|
+
/** @deprecated Use {@link ContextMenuY}. */
|
|
284
|
+
set contextMenuY(value) {
|
|
285
|
+
this.ContextMenuY = value;
|
|
286
|
+
}
|
|
287
|
+
ContextMenuTabId = null;
|
|
288
|
+
/** @deprecated Use {@link ContextMenuTabId}. */
|
|
289
|
+
get contextMenuTabId() {
|
|
290
|
+
return this.ContextMenuTabId;
|
|
291
|
+
}
|
|
292
|
+
/** @deprecated Use {@link ContextMenuTabId}. */
|
|
293
|
+
set contextMenuTabId(value) {
|
|
294
|
+
this.ContextMenuTabId = value;
|
|
295
|
+
}
|
|
216
296
|
/** The control that opened the context menu — focus returns here on close */
|
|
217
297
|
contextMenuAnchor = null;
|
|
218
298
|
// ---- RECORDS region (records-style record opens) ----
|
|
@@ -606,7 +686,7 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
606
686
|
if (this.recordsLayoutInitialized) {
|
|
607
687
|
return;
|
|
608
688
|
}
|
|
609
|
-
const container = this.
|
|
689
|
+
const container = this.RecordsGlContainer?.nativeElement;
|
|
610
690
|
if (!container) {
|
|
611
691
|
return; // Template not settled yet — the next sync pass retries
|
|
612
692
|
}
|
|
@@ -742,7 +822,7 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
742
822
|
}), this.layoutManager.TabDoubleClicked.subscribe(tabId => {
|
|
743
823
|
this.workspaceManager.TogglePin(tabId);
|
|
744
824
|
}), this.layoutManager.TabRightClicked.subscribe(event => {
|
|
745
|
-
this.
|
|
825
|
+
this.ShowContextMenu(event.x, event.y, event.tabId, event.anchorEl);
|
|
746
826
|
}));
|
|
747
827
|
this.wireRecordsLayoutEvents();
|
|
748
828
|
// Breakpoint crossings rebuild the records GL in the other chrome mode
|
|
@@ -780,7 +860,7 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
780
860
|
// the region is the visible surface for this configuration.
|
|
781
861
|
this.syncRecordsRegion(config);
|
|
782
862
|
this.updateRecordSurfaceState(config);
|
|
783
|
-
if (this.
|
|
863
|
+
if (this.UseSingleResourceMode) {
|
|
784
864
|
// In single-resource mode, reload content if the tab content changed
|
|
785
865
|
// The same tab ID can have different content (tab gets reused)
|
|
786
866
|
const activeTab = config.tabs.find(t => t.id === config.activeTabId) || config.tabs[0];
|
|
@@ -903,12 +983,12 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
903
983
|
}), this.recordsLayoutManager.TabDoubleClicked.subscribe(tabId => {
|
|
904
984
|
this.workspaceManager.TogglePin(tabId);
|
|
905
985
|
}), this.recordsLayoutManager.TabRightClicked.subscribe(event => {
|
|
906
|
-
this.
|
|
986
|
+
this.ShowContextMenu(event.x, event.y, event.tabId, event.anchorEl);
|
|
907
987
|
}));
|
|
908
988
|
}
|
|
909
989
|
ngAfterViewInit() {
|
|
910
990
|
// Initialize Golden Layout only if we're not in single-resource mode
|
|
911
|
-
if (!this.
|
|
991
|
+
if (!this.UseSingleResourceMode) {
|
|
912
992
|
this.initializeGoldenLayout();
|
|
913
993
|
}
|
|
914
994
|
else {
|
|
@@ -922,13 +1002,13 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
922
1002
|
*/
|
|
923
1003
|
initializeGoldenLayout(forceCreateTabs = false) {
|
|
924
1004
|
// If we are in single resource mode we do NOT need to do this work as golden layout should not exist in that state
|
|
925
|
-
if (this.
|
|
1005
|
+
if (this.UseSingleResourceMode)
|
|
926
1006
|
return;
|
|
927
|
-
if (!this.
|
|
1007
|
+
if (!this.GlContainer?.nativeElement) {
|
|
928
1008
|
this.layoutInitRetryCount++;
|
|
929
1009
|
if (this.layoutInitRetryCount > this.MAX_LAYOUT_INIT_RETRIES) {
|
|
930
1010
|
console.error(`Golden Layout container not available after ${this.MAX_LAYOUT_INIT_RETRIES} retries, emitting error`);
|
|
931
|
-
this.
|
|
1011
|
+
this.LayoutInitError.emit();
|
|
932
1012
|
return;
|
|
933
1013
|
}
|
|
934
1014
|
console.warn(`Golden Layout container not available, retry ${this.layoutInitRetryCount}/${this.MAX_LAYOUT_INIT_RETRIES}...`);
|
|
@@ -962,7 +1042,7 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
962
1042
|
return;
|
|
963
1043
|
}
|
|
964
1044
|
// Initialize Golden Layout (we have config now)
|
|
965
|
-
this.layoutManager.Initialize(this.
|
|
1045
|
+
this.layoutManager.Initialize(this.GlContainer.nativeElement);
|
|
966
1046
|
// Mark layout as initialized
|
|
967
1047
|
this.layoutInitialized = true;
|
|
968
1048
|
// The MAIN layout hosts only non-record tabs — record tabs live in the
|
|
@@ -1062,7 +1142,7 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
1062
1142
|
async ReloadAllTabs() {
|
|
1063
1143
|
// Destroy all cached component instances
|
|
1064
1144
|
this.cacheManager.clearCache();
|
|
1065
|
-
if (this.
|
|
1145
|
+
if (this.UseSingleResourceMode) {
|
|
1066
1146
|
// Force reload by clearing the signature check
|
|
1067
1147
|
this.currentSingleResourceSignature = null;
|
|
1068
1148
|
this.singleResourceComponentRef = null;
|
|
@@ -1155,7 +1235,7 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
1155
1235
|
* ensures the layout is properly sized after browser window changes.
|
|
1156
1236
|
*/
|
|
1157
1237
|
onWindowResize() {
|
|
1158
|
-
if (this.layoutInitialized && !this.
|
|
1238
|
+
if (this.layoutInitialized && !this.UseSingleResourceMode) {
|
|
1159
1239
|
this.layoutManager.updateSize();
|
|
1160
1240
|
}
|
|
1161
1241
|
}
|
|
@@ -1170,12 +1250,12 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
1170
1250
|
this.previousTabBarVisible = tabBarVisible;
|
|
1171
1251
|
// Determine if we should use single-resource mode
|
|
1172
1252
|
const shouldUseSingleResourceMode = !tabBarVisible;
|
|
1173
|
-
if (shouldUseSingleResourceMode !== this.
|
|
1174
|
-
this.
|
|
1253
|
+
if (shouldUseSingleResourceMode !== this.UseSingleResourceMode) {
|
|
1254
|
+
this.UseSingleResourceMode = shouldUseSingleResourceMode;
|
|
1175
1255
|
// Defer detectChanges to next microtask to avoid ExpressionChangedAfterItHasBeenCheckedError
|
|
1176
1256
|
// when this handler fires during an already-running change detection cycle.
|
|
1177
1257
|
Promise.resolve().then(() => this.cdr.detectChanges());
|
|
1178
|
-
if (this.
|
|
1258
|
+
if (this.UseSingleResourceMode) {
|
|
1179
1259
|
// Transitioning to single-resource mode
|
|
1180
1260
|
// **CRITICAL FIX**: Wait for the template to render directContentContainer
|
|
1181
1261
|
// before trying to load content. detectChanges() only marks dirty, doesn't render immediately.
|
|
@@ -1277,7 +1357,7 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
1277
1357
|
}
|
|
1278
1358
|
this.currentSingleResourceSignature = newSignature;
|
|
1279
1359
|
// Get the container element
|
|
1280
|
-
const container = this.
|
|
1360
|
+
const container = this.DirectContentContainer?.nativeElement;
|
|
1281
1361
|
if (!container) {
|
|
1282
1362
|
// Retry after view is updated
|
|
1283
1363
|
setTimeout(() => this.loadSingleResourceContent(), 50);
|
|
@@ -1475,7 +1555,7 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
1475
1555
|
// Remove children from the container. This detaches the wrapper DOM element
|
|
1476
1556
|
// without destroying the Angular component — it lives on in the cache.
|
|
1477
1557
|
// Using removeChild (not innerHTML='') to avoid aggressive DOM cleanup.
|
|
1478
|
-
const container = this.
|
|
1558
|
+
const container = this.DirectContentContainer?.nativeElement;
|
|
1479
1559
|
if (container) {
|
|
1480
1560
|
while (container.firstChild) {
|
|
1481
1561
|
container.removeChild(container.firstChild);
|
|
@@ -1529,7 +1609,7 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
1529
1609
|
// Pre-compute and stamp the new signature so the configuration-subscription path
|
|
1530
1610
|
// in single-resource mode doesn't see a "content changed" delta and trigger a
|
|
1531
1611
|
// needless reload cycle (which would destroy the currently attached component).
|
|
1532
|
-
if (this.
|
|
1612
|
+
if (this.UseSingleResourceMode && this.currentSingleResourceSignature !== null) {
|
|
1533
1613
|
const updatedTab = {
|
|
1534
1614
|
...tab,
|
|
1535
1615
|
resourceRecordId: newRecordId,
|
|
@@ -1612,7 +1692,7 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
1612
1692
|
this.singleResourceCacheIdentity = null;
|
|
1613
1693
|
// Clear the host container's DOM so the user isn't briefly looking at the
|
|
1614
1694
|
// destroyed component's wrapper between CloseTab and the default-tab load.
|
|
1615
|
-
const directContainer = this.
|
|
1695
|
+
const directContainer = this.DirectContentContainer?.nativeElement;
|
|
1616
1696
|
if (directContainer) {
|
|
1617
1697
|
while (directContainer.firstChild)
|
|
1618
1698
|
directContainer.removeChild(directContainer.firstChild);
|
|
@@ -2028,11 +2108,19 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2028
2108
|
*/
|
|
2029
2109
|
static findResourceTypeTolerant(rows, resourceType) {
|
|
2030
2110
|
const wanted = resourceType.trim().toLowerCase();
|
|
2031
|
-
const normalize = (name) => name.trim().toLowerCase().replace(/^mj:\s*/, '');
|
|
2032
2111
|
return rows.find(r => r.Name.trim().toLowerCase() === wanted)
|
|
2033
|
-
?? rows.find(r =>
|
|
2112
|
+
?? rows.find(r => TabContainerComponent.IsSameResourceType(r.Name, resourceType))
|
|
2034
2113
|
?? null;
|
|
2035
2114
|
}
|
|
2115
|
+
/**
|
|
2116
|
+
* Whether two resource type names refer to the same type, ignoring case and the 'MJ: '
|
|
2117
|
+
* prefix. A loaded component's ResourceType is the stored row name ('User Views'), while
|
|
2118
|
+
* its tab's configuration keeps whatever the caller passed ('MJ: User Views').
|
|
2119
|
+
*/
|
|
2120
|
+
static IsSameResourceType(a, b) {
|
|
2121
|
+
const normalize = (name) => (name ?? '').trim().toLowerCase().replace(/^mj:\s*/, '');
|
|
2122
|
+
return normalize(a) === normalize(b);
|
|
2123
|
+
}
|
|
2036
2124
|
async getResourceTypeId(resourceType) {
|
|
2037
2125
|
const rt = await this.getResourceTypeEntity(resourceType);
|
|
2038
2126
|
if (rt) {
|
|
@@ -2236,9 +2324,17 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2236
2324
|
// because for nav items, the recordId is stored in configuration, not resourceRecordId
|
|
2237
2325
|
const existingRecordId = existingResourceData?.ResourceRecordID || '';
|
|
2238
2326
|
const newRecordId = tab.resourceRecordId || tab.configuration['recordId'] || '';
|
|
2239
|
-
|
|
2327
|
+
// Entity tells dynamic views apart: every one carries recordId 'dynamic', so without it
|
|
2328
|
+
// opening #Contacts into a tab showing #Accounts retitles the tab and keeps the Accounts
|
|
2329
|
+
// grid. Saved-view configs never carry Entity, so both sides are undefined there. It is
|
|
2330
|
+
// also part of ComponentCacheManager's key for 'dynamic', which is what stops this
|
|
2331
|
+
// reload from being handed back the component it just detached.
|
|
2332
|
+
const existingEntity = existingResourceData?.Configuration?.Entity;
|
|
2333
|
+
const newEntity = tab.configuration['Entity'];
|
|
2334
|
+
const needsReload = !TabContainerComponent.IsSameResourceType(existingResourceData?.ResourceType, tab.configuration['resourceType']) ||
|
|
2240
2335
|
existingResourceData?.Configuration?.applicationId !== tab.applicationId ||
|
|
2241
2336
|
existingRecordId !== newRecordId ||
|
|
2337
|
+
existingEntity !== newEntity ||
|
|
2242
2338
|
(tab.configuration['resourceType'] === 'Custom' && existingDriverClass !== newDriverClass);
|
|
2243
2339
|
if (needsReload) {
|
|
2244
2340
|
// Clean up old component
|
|
@@ -2286,11 +2382,11 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2286
2382
|
/**
|
|
2287
2383
|
* Show context menu
|
|
2288
2384
|
*/
|
|
2289
|
-
|
|
2290
|
-
this.
|
|
2291
|
-
this.
|
|
2292
|
-
this.
|
|
2293
|
-
this.
|
|
2385
|
+
ShowContextMenu(x, y, tabId, anchorEl) {
|
|
2386
|
+
this.ContextMenuX = x;
|
|
2387
|
+
this.ContextMenuY = y;
|
|
2388
|
+
this.ContextMenuTabId = tabId;
|
|
2389
|
+
this.ContextMenuVisible = true;
|
|
2294
2390
|
// Remember the invoking control so closing can hand focus back (the
|
|
2295
2391
|
// slot button passes itself; right-click falls back to whatever was
|
|
2296
2392
|
// focused). aria-expanded reflects the open menu on the anchor.
|
|
@@ -2317,14 +2413,14 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2317
2413
|
const clickHandler = (event) => {
|
|
2318
2414
|
const target = event.target;
|
|
2319
2415
|
if (!target.closest('.context-menu')) {
|
|
2320
|
-
this.
|
|
2416
|
+
this.HideContextMenu();
|
|
2321
2417
|
document.removeEventListener('click', clickHandler, true);
|
|
2322
2418
|
document.removeEventListener('keydown', keyHandler, true);
|
|
2323
2419
|
}
|
|
2324
2420
|
};
|
|
2325
2421
|
const keyHandler = (event) => {
|
|
2326
2422
|
if (event.key === 'Escape') {
|
|
2327
|
-
this.
|
|
2423
|
+
this.HideContextMenu();
|
|
2328
2424
|
document.removeEventListener('click', clickHandler, true);
|
|
2329
2425
|
document.removeEventListener('keydown', keyHandler, true);
|
|
2330
2426
|
}
|
|
@@ -2333,12 +2429,16 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2333
2429
|
document.addEventListener('keydown', keyHandler, true);
|
|
2334
2430
|
}, 0);
|
|
2335
2431
|
}
|
|
2432
|
+
/** @deprecated Use {@link ShowContextMenu}. */
|
|
2433
|
+
showContextMenu(x, y, tabId, anchorEl) {
|
|
2434
|
+
return this.ShowContextMenu(x, y, tabId, anchorEl);
|
|
2435
|
+
}
|
|
2336
2436
|
/**
|
|
2337
2437
|
* Hide context menu
|
|
2338
2438
|
*/
|
|
2339
|
-
|
|
2340
|
-
this.
|
|
2341
|
-
this.
|
|
2439
|
+
HideContextMenu(restoreFocus = true) {
|
|
2440
|
+
this.ContextMenuVisible = false;
|
|
2441
|
+
this.ContextMenuTabId = null;
|
|
2342
2442
|
const anchor = this.contextMenuAnchor;
|
|
2343
2443
|
this.contextMenuAnchor = null;
|
|
2344
2444
|
if (anchor?.classList.contains('mj-tab-type-slot')) {
|
|
@@ -2354,12 +2454,16 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2354
2454
|
requestAnimationFrame(() => anchor.focus());
|
|
2355
2455
|
}
|
|
2356
2456
|
}
|
|
2457
|
+
/** @deprecated Use {@link HideContextMenu}. */
|
|
2458
|
+
hideContextMenu(restoreFocus = true) {
|
|
2459
|
+
return this.HideContextMenu(restoreFocus);
|
|
2460
|
+
}
|
|
2357
2461
|
/**
|
|
2358
2462
|
* role="menu" keyboard model: ArrowUp/Down rove (wrapping) over enabled
|
|
2359
2463
|
* items, Home/End jump, Escape closes with focus return, Tab dismisses
|
|
2360
2464
|
* (native menus don't trap Tab).
|
|
2361
2465
|
*/
|
|
2362
|
-
|
|
2466
|
+
OnMenuKeydown(event) {
|
|
2363
2467
|
const items = Array.from(document.querySelectorAll('.context-menu [role="menuitem"]:not([disabled])'));
|
|
2364
2468
|
if (items.length === 0) {
|
|
2365
2469
|
return;
|
|
@@ -2387,37 +2491,53 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2387
2491
|
// deferred document-level teardown listener attaches.
|
|
2388
2492
|
event.preventDefault();
|
|
2389
2493
|
event.stopPropagation();
|
|
2390
|
-
this.
|
|
2494
|
+
this.HideContextMenu();
|
|
2391
2495
|
break;
|
|
2392
2496
|
case 'Tab':
|
|
2393
|
-
this.
|
|
2497
|
+
this.HideContextMenu(false);
|
|
2394
2498
|
break;
|
|
2395
2499
|
}
|
|
2396
2500
|
}
|
|
2501
|
+
/** @deprecated Use {@link OnMenuKeydown}. */
|
|
2502
|
+
onMenuKeydown(event) {
|
|
2503
|
+
return this.OnMenuKeydown(event);
|
|
2504
|
+
}
|
|
2397
2505
|
/**
|
|
2398
2506
|
* Check if context menu tab is pinned
|
|
2399
2507
|
*/
|
|
2400
|
-
get
|
|
2401
|
-
if (!this.
|
|
2508
|
+
get IsContextTabPinned() {
|
|
2509
|
+
if (!this.ContextMenuTabId)
|
|
2402
2510
|
return false;
|
|
2403
|
-
const tab = this.workspaceManager.GetTab(this.
|
|
2511
|
+
const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
|
|
2404
2512
|
return tab?.isPinned || false;
|
|
2405
2513
|
}
|
|
2514
|
+
/** @deprecated Use {@link IsContextTabPinned}. */
|
|
2515
|
+
get isContextTabPinned() {
|
|
2516
|
+
return this.IsContextTabPinned;
|
|
2517
|
+
}
|
|
2406
2518
|
/** Context tab is a records-REGION record — eligible for "Move to Workspace" */
|
|
2407
|
-
get
|
|
2519
|
+
get CanContextMoveToWorkspace() {
|
|
2408
2520
|
// Docked/region composition is a DESKTOP concept — no move actions on mobile
|
|
2409
|
-
if (!this.
|
|
2521
|
+
if (!this.ContextMenuTabId || !this.RecordsStyleActive || this.mobileRecordsActive)
|
|
2410
2522
|
return false;
|
|
2411
|
-
const tab = this.workspaceManager.GetTab(this.
|
|
2523
|
+
const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
|
|
2412
2524
|
return !!tab && IsRecordsRegionTab(tab.configuration);
|
|
2413
2525
|
}
|
|
2526
|
+
/** @deprecated Use {@link CanContextMoveToWorkspace}. */
|
|
2527
|
+
get canContextMoveToWorkspace() {
|
|
2528
|
+
return this.CanContextMoveToWorkspace;
|
|
2529
|
+
}
|
|
2414
2530
|
/** Context tab is a DOCKED record — eligible for "Move to Records" */
|
|
2415
|
-
get
|
|
2416
|
-
if (!this.
|
|
2531
|
+
get CanContextMoveToRecords() {
|
|
2532
|
+
if (!this.ContextMenuTabId || !this.RecordsStyleActive || this.mobileRecordsActive)
|
|
2417
2533
|
return false;
|
|
2418
|
-
const tab = this.workspaceManager.GetTab(this.
|
|
2534
|
+
const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
|
|
2419
2535
|
return !!tab && IsRecordsTabConfiguration(tab.configuration) && IsRecordDockedToWorkspace(tab.configuration);
|
|
2420
2536
|
}
|
|
2537
|
+
/** @deprecated Use {@link CanContextMoveToRecords}. */
|
|
2538
|
+
get canContextMoveToRecords() {
|
|
2539
|
+
return this.CanContextMoveToRecords;
|
|
2540
|
+
}
|
|
2421
2541
|
/**
|
|
2422
2542
|
* Promote: records region → main workspace layout ("Move to Workspace").
|
|
2423
2543
|
* ORDER MATTERS: activate FIRST, then flip the flag. With the tab already
|
|
@@ -2426,15 +2546,19 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2426
2546
|
* (b) a single-resource→multi-tab transition triggered by the flip exempts
|
|
2427
2547
|
* it from the force-pin sweep (it IS the activeTabId).
|
|
2428
2548
|
*/
|
|
2429
|
-
|
|
2430
|
-
const tabId = this.
|
|
2431
|
-
this.
|
|
2549
|
+
OnContextMoveToWorkspace() {
|
|
2550
|
+
const tabId = this.ContextMenuTabId;
|
|
2551
|
+
this.HideContextMenu(false);
|
|
2432
2552
|
if (!tabId)
|
|
2433
2553
|
return;
|
|
2434
2554
|
this.workspaceManager.SetActiveTab(tabId);
|
|
2435
2555
|
this.workspaceManager.UpdateTabConfiguration(tabId, { [RECORD_DOCKED_TO_WORKSPACE_KEY]: true });
|
|
2436
2556
|
this.assertMovedTabActivation(tabId);
|
|
2437
2557
|
}
|
|
2558
|
+
/** @deprecated Use {@link OnContextMoveToWorkspace}. */
|
|
2559
|
+
onContextMoveToWorkspace() {
|
|
2560
|
+
return this.OnContextMoveToWorkspace();
|
|
2561
|
+
}
|
|
2438
2562
|
/**
|
|
2439
2563
|
* Demote: main workspace layout → records region ("Move to Records").
|
|
2440
2564
|
* Same activate-first ordering: the flip's emission then computes
|
|
@@ -2442,15 +2566,19 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2442
2566
|
* the returned tab. `false` (not undefined) so the choice is explicit in
|
|
2443
2567
|
* the persisted configuration.
|
|
2444
2568
|
*/
|
|
2445
|
-
|
|
2446
|
-
const tabId = this.
|
|
2447
|
-
this.
|
|
2569
|
+
OnContextMoveToRecords() {
|
|
2570
|
+
const tabId = this.ContextMenuTabId;
|
|
2571
|
+
this.HideContextMenu(false);
|
|
2448
2572
|
if (!tabId)
|
|
2449
2573
|
return;
|
|
2450
2574
|
this.workspaceManager.SetActiveTab(tabId);
|
|
2451
2575
|
this.workspaceManager.UpdateTabConfiguration(tabId, { [RECORD_DOCKED_TO_WORKSPACE_KEY]: false });
|
|
2452
2576
|
this.assertMovedTabActivation(tabId);
|
|
2453
2577
|
}
|
|
2578
|
+
/** @deprecated Use {@link OnContextMoveToRecords}. */
|
|
2579
|
+
onContextMoveToRecords() {
|
|
2580
|
+
return this.OnContextMoveToRecords();
|
|
2581
|
+
}
|
|
2454
2582
|
/**
|
|
2455
2583
|
* A move's SOURCE layout auto-activates its next tab when the moved tab is
|
|
2456
2584
|
* removed, and that GL activation WRITES BACK into the workspace — stomping
|
|
@@ -2469,69 +2597,89 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2469
2597
|
/**
|
|
2470
2598
|
* Toggle pin from context menu
|
|
2471
2599
|
*/
|
|
2472
|
-
|
|
2473
|
-
if (this.
|
|
2474
|
-
this.workspaceManager.TogglePin(this.
|
|
2600
|
+
OnContextPin() {
|
|
2601
|
+
if (this.ContextMenuTabId) {
|
|
2602
|
+
this.workspaceManager.TogglePin(this.ContextMenuTabId);
|
|
2475
2603
|
}
|
|
2476
|
-
this.
|
|
2604
|
+
this.HideContextMenu();
|
|
2605
|
+
}
|
|
2606
|
+
/** @deprecated Use {@link OnContextPin}. */
|
|
2607
|
+
onContextPin() {
|
|
2608
|
+
return this.OnContextPin();
|
|
2477
2609
|
}
|
|
2478
2610
|
/**
|
|
2479
2611
|
* Close tab from context menu
|
|
2480
2612
|
*/
|
|
2481
|
-
|
|
2482
|
-
if (this.
|
|
2483
|
-
const tab = this.workspaceManager.GetTab(this.
|
|
2613
|
+
OnContextClose() {
|
|
2614
|
+
if (this.ContextMenuTabId) {
|
|
2615
|
+
const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
|
|
2484
2616
|
const manager = tab && this.isRecordTab(tab) ? this.recordsLayoutManager : this.layoutManager;
|
|
2485
|
-
manager.RemoveTab(this.
|
|
2617
|
+
manager.RemoveTab(this.ContextMenuTabId);
|
|
2486
2618
|
}
|
|
2487
2619
|
// The anchor lives on the closed tab — nothing to return focus to.
|
|
2488
|
-
this.
|
|
2620
|
+
this.HideContextMenu(false);
|
|
2621
|
+
}
|
|
2622
|
+
/** @deprecated Use {@link OnContextClose}. */
|
|
2623
|
+
onContextClose() {
|
|
2624
|
+
return this.OnContextClose();
|
|
2489
2625
|
}
|
|
2490
2626
|
/**
|
|
2491
2627
|
* Close all other tabs from context menu
|
|
2492
2628
|
*/
|
|
2493
|
-
|
|
2494
|
-
if (this.
|
|
2495
|
-
this.workspaceManager.CloseOtherTabs(this.
|
|
2629
|
+
OnContextCloseOthers() {
|
|
2630
|
+
if (this.ContextMenuTabId) {
|
|
2631
|
+
this.workspaceManager.CloseOtherTabs(this.ContextMenuTabId);
|
|
2496
2632
|
}
|
|
2497
|
-
this.
|
|
2633
|
+
this.HideContextMenu();
|
|
2634
|
+
}
|
|
2635
|
+
/** @deprecated Use {@link OnContextCloseOthers}. */
|
|
2636
|
+
onContextCloseOthers() {
|
|
2637
|
+
return this.OnContextCloseOthers();
|
|
2498
2638
|
}
|
|
2499
2639
|
/**
|
|
2500
2640
|
* Close tabs to the right from context menu
|
|
2501
2641
|
*/
|
|
2502
|
-
|
|
2503
|
-
if (this.
|
|
2504
|
-
this.workspaceManager.CloseTabsToRight(this.
|
|
2642
|
+
OnContextCloseToRight() {
|
|
2643
|
+
if (this.ContextMenuTabId) {
|
|
2644
|
+
this.workspaceManager.CloseTabsToRight(this.ContextMenuTabId);
|
|
2505
2645
|
}
|
|
2506
|
-
this.
|
|
2646
|
+
this.HideContextMenu();
|
|
2647
|
+
}
|
|
2648
|
+
/** @deprecated Use {@link OnContextCloseToRight}. */
|
|
2649
|
+
onContextCloseToRight() {
|
|
2650
|
+
return this.OnContextCloseToRight();
|
|
2507
2651
|
}
|
|
2508
2652
|
/**
|
|
2509
2653
|
* Check if context menu tab is pinned to Home dashboard
|
|
2510
2654
|
*/
|
|
2511
|
-
get
|
|
2512
|
-
if (!this.
|
|
2655
|
+
get IsContextTabPinnedToHome() {
|
|
2656
|
+
if (!this.ContextMenuTabId)
|
|
2513
2657
|
return false;
|
|
2514
|
-
const tab = this.workspaceManager.GetTab(this.
|
|
2658
|
+
const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
|
|
2515
2659
|
if (!tab)
|
|
2516
2660
|
return false;
|
|
2517
2661
|
const resourceType = this.resolveResourceType(tab);
|
|
2518
2662
|
return this.pinService.IsPinned(resourceType, tab.configuration);
|
|
2519
2663
|
}
|
|
2664
|
+
/** @deprecated Use {@link IsContextTabPinnedToHome}. */
|
|
2665
|
+
get isContextTabPinnedToHome() {
|
|
2666
|
+
return this.IsContextTabPinnedToHome;
|
|
2667
|
+
}
|
|
2520
2668
|
/**
|
|
2521
2669
|
* Pin current context menu tab to Home dashboard
|
|
2522
2670
|
*/
|
|
2523
|
-
async
|
|
2524
|
-
if (this.
|
|
2525
|
-
this.
|
|
2671
|
+
async OnContextPinToHome() {
|
|
2672
|
+
if (this.IsContextTabPinnedToHome) {
|
|
2673
|
+
this.HideContextMenu();
|
|
2526
2674
|
return;
|
|
2527
2675
|
}
|
|
2528
|
-
if (!this.
|
|
2529
|
-
this.
|
|
2676
|
+
if (!this.ContextMenuTabId) {
|
|
2677
|
+
this.HideContextMenu();
|
|
2530
2678
|
return;
|
|
2531
2679
|
}
|
|
2532
|
-
const tab = this.workspaceManager.GetTab(this.
|
|
2680
|
+
const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
|
|
2533
2681
|
if (!tab) {
|
|
2534
|
-
this.
|
|
2682
|
+
this.HideContextMenu();
|
|
2535
2683
|
return;
|
|
2536
2684
|
}
|
|
2537
2685
|
const resourceType = this.resolveResourceType(tab);
|
|
@@ -2562,7 +2710,11 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2562
2710
|
else {
|
|
2563
2711
|
MJNotificationService.Instance.CreateSimpleNotification(`"${tab.title}" is already pinned to Home`, 'info', 3000);
|
|
2564
2712
|
}
|
|
2565
|
-
this.
|
|
2713
|
+
this.HideContextMenu();
|
|
2714
|
+
}
|
|
2715
|
+
/** @deprecated Use {@link OnContextPinToHome}. */
|
|
2716
|
+
async onContextPinToHome() {
|
|
2717
|
+
return this.OnContextPinToHome();
|
|
2566
2718
|
}
|
|
2567
2719
|
/**
|
|
2568
2720
|
* Resolve a WorkspaceTab's resource type string for pin matching
|
|
@@ -2589,12 +2741,12 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2589
2741
|
try {
|
|
2590
2742
|
// Find the active content element — differs by mode
|
|
2591
2743
|
let contentEl = null;
|
|
2592
|
-
if (this.
|
|
2593
|
-
contentEl = this.
|
|
2744
|
+
if (this.UseSingleResourceMode) {
|
|
2745
|
+
contentEl = this.DirectContentContainer?.nativeElement ?? null;
|
|
2594
2746
|
}
|
|
2595
2747
|
else {
|
|
2596
2748
|
// In Golden Layout mode, find the active tab's content pane
|
|
2597
|
-
contentEl = this.
|
|
2749
|
+
contentEl = this.GlContainer?.nativeElement?.querySelector('.lm_item_container .lm_content');
|
|
2598
2750
|
}
|
|
2599
2751
|
if (!contentEl)
|
|
2600
2752
|
return;
|
|
@@ -2618,11 +2770,11 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2618
2770
|
async CaptureActiveThumbnail() {
|
|
2619
2771
|
try {
|
|
2620
2772
|
let contentEl = null;
|
|
2621
|
-
if (this.
|
|
2622
|
-
contentEl = this.
|
|
2773
|
+
if (this.UseSingleResourceMode) {
|
|
2774
|
+
contentEl = this.DirectContentContainer?.nativeElement ?? null;
|
|
2623
2775
|
}
|
|
2624
2776
|
else {
|
|
2625
|
-
contentEl = this.
|
|
2777
|
+
contentEl = this.GlContainer?.nativeElement?.querySelector('.lm_item_container .lm_content');
|
|
2626
2778
|
}
|
|
2627
2779
|
if (!contentEl)
|
|
2628
2780
|
return undefined;
|
|
@@ -2638,7 +2790,7 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2638
2790
|
* forever we emit all events upstream
|
|
2639
2791
|
*/
|
|
2640
2792
|
emitFirstLoadCompleteOnce() {
|
|
2641
|
-
this.
|
|
2793
|
+
this.FirstResourceLoadComplete.emit(); // do this each time to be sure we don't suppress messages
|
|
2642
2794
|
}
|
|
2643
2795
|
/**
|
|
2644
2796
|
* Render an inline "missing resource component" error into a host element when
|
|
@@ -2699,12 +2851,12 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2699
2851
|
i0.ɵɵviewQuery(_c0, 5)(_c1, 5)(_c2, 5);
|
|
2700
2852
|
} if (rf & 2) {
|
|
2701
2853
|
let _t;
|
|
2702
|
-
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.
|
|
2703
|
-
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.
|
|
2704
|
-
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.
|
|
2854
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.GlContainer = _t.first);
|
|
2855
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.DirectContentContainer = _t.first);
|
|
2856
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.RecordsGlContainer = _t.first);
|
|
2705
2857
|
} }, hostBindings: function TabContainerComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
2706
2858
|
i0.ɵɵlistener("resize", function TabContainerComponent_resize_HostBindingHandler() { return ctx.onWindowResize(); }, i0.ɵɵresolveWindow);
|
|
2707
|
-
} }, outputs: { firstResourceLoadComplete: "firstResourceLoadComplete", layoutInitError: "layoutInitError" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 6, vars: 5, consts: [["directContentContainer", ""], ["glContainer", ""], ["recordsGlContainer", ""], [1, "tab-container"], [1, "main-region"], [1, "direct-content-container"], [1, "gl-container"], ["role", "menu", "aria-label", "Tab actions", 1, "context-menu", 3, "left", "top"], [1, "records-region"], [3, "Title", "Icon", "Color", "Count"], [1, "records-gl-container"], [3, "VisibleChange", "ActivateRequested", "CloseRequested", "Entries", "Visible"], [3, "SwitcherRequested", "Title", "Icon", "Color", "Count"], ["role", "menu", "aria-label", "Tab actions", 1, "context-menu", 3, "keydown"], ["type", "button", "role", "menuitem", 1, "context-menu-item", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-thumbtack"], [1, "context-menu-divider"], ["type", "button", "role", "menuitem", 1, "context-menu-item", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-house-chimney"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["aria-hidden", "true", 1, "fa-solid", "fa-layer-group"], ["aria-hidden", "true", 1, "fa-solid", "fa-angles-right"], [1, "check"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"], ["type", "button", "role", "menuitem", 1, "context-menu-item"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-up-right-from-square"], ["aria-hidden", "true", 1, "fa-solid", "fa-file-lines"]], template: function TabContainerComponent_Template(rf, ctx) { if (rf & 1) {
|
|
2859
|
+
} }, outputs: { FirstResourceLoadComplete: "FirstResourceLoadComplete", firstResourceLoadComplete: "firstResourceLoadComplete", LayoutInitError: "LayoutInitError", layoutInitError: "layoutInitError" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 6, vars: 5, consts: [["directContentContainer", ""], ["glContainer", ""], ["recordsGlContainer", ""], [1, "tab-container"], [1, "main-region"], [1, "direct-content-container"], [1, "gl-container"], ["role", "menu", "aria-label", "Tab actions", 1, "context-menu", 3, "left", "top"], [1, "records-region"], [3, "Title", "Icon", "Color", "Count"], [1, "records-gl-container"], [3, "VisibleChange", "ActivateRequested", "CloseRequested", "Entries", "Visible"], [3, "SwitcherRequested", "Title", "Icon", "Color", "Count"], ["role", "menu", "aria-label", "Tab actions", 1, "context-menu", 3, "keydown"], ["type", "button", "role", "menuitem", 1, "context-menu-item", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-thumbtack"], [1, "context-menu-divider"], ["type", "button", "role", "menuitem", 1, "context-menu-item", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-house-chimney"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["aria-hidden", "true", 1, "fa-solid", "fa-layer-group"], ["aria-hidden", "true", 1, "fa-solid", "fa-angles-right"], [1, "check"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"], ["type", "button", "role", "menuitem", 1, "context-menu-item"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-up-right-from-square"], ["aria-hidden", "true", 1, "fa-solid", "fa-file-lines"]], template: function TabContainerComponent_Template(rf, ctx) { if (rf & 1) {
|
|
2708
2860
|
i0.ɵɵelementStart(0, "div", 3)(1, "div", 4);
|
|
2709
2861
|
i0.ɵɵconditionalCreate(2, TabContainerComponent_Conditional_2_Template, 2, 0, "div", 5)(3, TabContainerComponent_Conditional_3_Template, 2, 0, "div", 6);
|
|
2710
2862
|
i0.ɵɵelementEnd();
|
|
@@ -2725,17 +2877,21 @@ export class TabContainerComponent extends BaseAngularComponent {
|
|
|
2725
2877
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TabContainerComponent, [{
|
|
2726
2878
|
type: Component,
|
|
2727
2879
|
args: [{ standalone: false, selector: 'mj-tab-container', encapsulation: ViewEncapsulation.None, template: "<div class=\"tab-container\">\n\n <!-- Main region: nav pages (single-resource or main Golden Layout).\n Hidden (not destroyed) while the RECORDS region is showing, so nav\n content keeps its state and reappears instantly. -->\n <div class=\"main-region\" [class.region-hidden]=\"ShowRecordsRegion\">\n <!-- Single-Resource Mode: Direct component rendering without Golden Layout -->\n <!-- This avoids the 20px height issue when GL header is hidden -->\n @if (useSingleResourceMode) {\n <div #directContentContainer class=\"direct-content-container\"></div>\n } @else {\n <!-- Multi-Tab Mode: Golden Layout Container -->\n <div #glContainer class=\"gl-container\"></div>\n }\n </div>\n\n <!-- RECORDS region: a SEPARATE Golden Layout hosting only record tabs\n (records-style record opens). Always in the DOM once created so the\n layout survives visibility flips; shown only while the active tab is\n a record. Native GL tab bar = record tabs, drag-to-split included. -->\n @if (RecordsStyleActive) {\n <!-- Origin crumbs are PANE-LEVEL now (first element inside each record\n pane \u2014 see RecordOriginCrumbComponent); the region needs no bar. -->\n <div class=\"records-region\" [class.region-hidden]=\"!ShowRecordsRegion\">\n <!-- MOBILE: the GL tab strip is unusable at phone widths (one tab\n fits, no overflow UI) \u2014 the record bar replaces it and opens the\n record switcher sheet. The GL itself runs headerless (HideHeaders). -->\n @if (IsMobileRecords) {\n <mj-record-bar\n [Title]=\"RecordBarTitle\"\n [Icon]=\"RecordBarIcon\"\n [Color]=\"RecordBarColor\"\n [Count]=\"OpenRecordCount\"\n (SwitcherRequested)=\"OpenRecordSwitcher()\">\n </mj-record-bar>\n }\n <div #recordsGlContainer class=\"records-gl-container\"></div>\n </div>\n\n <!-- MOBILE record switcher: bottom sheet listing ALL open records\n (region + docked). Fixed-position \u2014 DOM location here is\n visual-neutral; living in tab-container keeps close routing on the\n same path as the tab context menu. -->\n <mj-record-switcher-sheet\n [Entries]=\"SwitcherEntries\"\n [Visible]=\"RecordSwitcherVisible\"\n (VisibleChange)=\"OnSwitcherVisibleChange($event)\"\n (ActivateRequested)=\"OnSwitcherActivate($event)\"\n (CloseRequested)=\"OnSwitcherClose($event)\">\n </mj-record-switcher-sheet>\n }\n\n <!-- Context Menu (only relevant in multi-tab mode). Real buttons with\n menu semantics: arrow keys rove, Escape closes with focus return to\n the invoking control (see onMenuKeydown / hideContextMenu). -->\n @if (contextMenuVisible) {\n <div\n class=\"context-menu\"\n role=\"menu\"\n aria-label=\"Tab actions\"\n (keydown)=\"onMenuKeydown($event)\"\n [style.left.px]=\"contextMenuX\"\n [style.top.px]=\"contextMenuY\">\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextPin()\">\n <i class=\"fa-solid fa-thumbtack\" aria-hidden=\"true\"></i>\n <span>{{ isContextTabPinned ? 'Unpin Tab' : 'Pin Tab' }}</span>\n </button>\n <div class=\"context-menu-divider\"></div>\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" [class.new-item]=\"!isContextTabPinnedToHome\" [class.disabled]=\"isContextTabPinnedToHome\" [disabled]=\"isContextTabPinnedToHome\" (click)=\"onContextPinToHome()\">\n <i class=\"fa-solid fa-house-chimney\" aria-hidden=\"true\"></i>\n @if (isContextTabPinnedToHome) {\n <span>Pinned to Home</span>\n <span class=\"check\"><i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i></span>\n } @else {\n <span>Pin to Home</span>\n }\n </button>\n @if (canContextMoveToWorkspace || canContextMoveToRecords) {\n <div class=\"context-menu-divider\"></div>\n @if (canContextMoveToWorkspace) {\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextMoveToWorkspace()\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i>\n <span>Move to Workspace</span>\n </button>\n }\n @if (canContextMoveToRecords) {\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextMoveToRecords()\">\n <i class=\"fa-solid fa-file-lines\" aria-hidden=\"true\"></i>\n <span>Move to Records</span>\n </button>\n }\n }\n <div class=\"context-menu-divider\"></div>\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextClose()\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n <span>Close Tab</span>\n </button>\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextCloseOthers()\">\n <i class=\"fa-solid fa-layer-group\" aria-hidden=\"true\"></i>\n <span>Close Others</span>\n </button>\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextCloseToRight()\">\n <i class=\"fa-solid fa-angles-right\" aria-hidden=\"true\"></i>\n <span>Close to Right</span>\n </button>\n </div>\n }\n</div>\n", styles: [":host {\n display: flex;\n flex: 1;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n.tab-container {\n display: flex;\n flex-direction: column;\n flex: 1;\n width: 100%;\n overflow: hidden;\n}\n\n.gl-container {\n flex: 1;\n width: 100%;\n height: 100%;\n position: relative;\n background: var(--mj-bg-page);\n}\n\n/* Main region (nav pages) and the separate RECORDS region \u2014 exactly one is\n visible at a time. CRITICAL: the hidden region keeps its FULL LAYOUT BOX\n (visibility, not display:none). Golden Layout instances live in both;\n display:none would feed GL 0-size resizes and let it initialize/restore\n against a zero baseline \u2014 the root cause of clipped tab headers, stale\n strips, and the collapsed-sliver layout. */\n.tab-container {\n position: relative;\n}\n\n.main-region,\n.records-region {\n position: absolute;\n inset: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n}\n\n/* The records GL host fills the region below the origin bar. Must keep a\n real layout box at all times (see the region comment above) \u2014 it's a flex\n child of an always-sized absolute region, so it does. */\n.records-gl-container {\n flex: 1;\n min-height: 0;\n position: relative;\n background: var(--mj-bg-page);\n}\n\n/* Pane layout with an origin crumb as the FIRST element: the crumb keeps\n its fixed 32px (component host); the content sibling flex-fills. The\n height override neutralizes inline height:100% that cached wrapper\n elements carry from earlier renders (CSS !important beats inline). */\nmj-tab-container .lm_items > div > mj-record-origin-crumb,\n.direct-content-container > mj-record-origin-crumb {\n flex-shrink: 0;\n}\n\nmj-tab-container .lm_items > div > *:not(mj-record-origin-crumb),\n.direct-content-container > *:not(mj-record-origin-crumb) {\n flex: 1 1 auto;\n min-height: 0;\n height: auto !important;\n}\n\n/* Defense against visibility punch-through: `visibility: visible` on a\n DESCENDANT defeats an ancestor's visibility:hidden (unlike display:none).\n Real case: explorer-app's global `.visible { visibility: visible\n !important }` utility collides with components whose show-state class is\n named `visible` (several bespoke detail panels did this), leaving their\n overlays painted on top of the records region. The two-class specificity\n here outranks the single-class utility even with both !important. */\n.region-hidden,\n.region-hidden * {\n visibility: hidden !important;\n pointer-events: none !important;\n /* Region swaps must be INSTANT: `transition: all` rules on GL internals\n (e.g. .lm_stack) would otherwise transition `visibility` \u2014 which\n interpolates discretely, keeping the outgoing region painted on top for\n the full transition duration (a ~200ms flash of the record form over\n the destination page). */\n transition: none !important;\n}\n\n/* Direct content container for single-resource mode */\n/* Renders components directly without Golden Layout overhead */\n.direct-content-container {\n flex: 1;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n overflow: hidden;\n}\n\n.tab-content-container {\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n padding: 20px;\n}\n\n/* Context Menu */\n.context-menu {\n position: fixed;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n min-width: 150px;\n z-index: 10001;\n overflow: hidden;\n}\n\n.context-menu .context-menu-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n /* Real <button role=\"menuitem\"> now \u2014 neutralize UA chrome */\n width: 100%;\n text-align: left;\n background: transparent;\n border: none;\n font-family: inherit;\n}\n\n/* Keyboard roving highlights like hover; ring omitted on purpose \u2014 the\n moving highlight IS the focus indicator inside a menu. */\n.context-menu .context-menu-item:focus-visible {\n outline: none;\n background: var(--mj-bg-surface-hover);\n}\n\n.context-menu .context-menu-item i {\n width: 16px;\n text-align: center;\n color: var(--mj-text-secondary);\n}\n\n.context-menu .context-menu-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.context-menu .context-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n/* Context menu item variants */\n.context-menu-item.new-item i { color: var(--mj-brand-primary); }\n.context-menu-item.new-item { font-weight: 500; }\n.context-menu-item.disabled { color: var(--mj-text-disabled); cursor: default; }\n.context-menu-item.disabled:hover { background: transparent; }\n.context-menu-item.disabled i { color: var(--mj-text-disabled); }\n.context-menu-item .check { margin-left: auto; color: var(--mj-status-success); font-size: 12px; }\n\n/* Override Golden Layout styles */\n/* Global overrides */\n\n/* Ensure GL root container fills available space */\nmj-tab-container .lm_goldenlayout {\n width: 100% !important;\n height: 100% !important;\n}\n\n/* Ensure the root layout item fills space */\nmj-tab-container .lm_root {\n width: 100% !important;\n height: 100% !important;\n}\n\n/* Ensure proper box-sizing for all GL layout elements */\nmj-tab-container .lm_item,\nmj-tab-container .lm_content,\nmj-tab-container .lm_stack,\nmj-tab-container .lm_row,\nmj-tab-container .lm_column {\n box-sizing: border-box !important;\n}\n\n/* Ensure layout items don't overflow */\nmj-tab-container .lm_item {\n overflow: hidden !important;\n}\n\n/* SPLIT panes get a subtle frame so side-by-side content doesn't bleed\n together (single-pane layouts stay frameless). \"Adjacent to a splitter\"\n is exactly and only the split case \u2014 any orientation, any nesting. */\nmj-tab-container .lm_stack:has(+ .lm_splitter),\nmj-tab-container .lm_splitter + .lm_stack {\n border: 1px solid var(--mj-border-default) !important;\n}\n\n/* Fix for .lm_items - the content container inside stacks */\n/* This is separate from .lm_item - it holds the actual tab content */\nmj-tab-container .lm_items {\n width: 100% !important;\n height: calc(100% - 38px) !important; /* Account for header height (38px) */\n box-sizing: border-box !important;\n position: relative !important;\n}\n\n/* When tabs are maximized, no header visible */\nmj-tab-container .lm_stack.lm_maximised > .lm_items {\n height: 100% !important;\n}\n\n/* Target the anonymous ComponentItem div inside lm_items (has no class) */\n/* Created in golden-layout/src/ts/items/component-item.ts:51 without a class */\n/* NOTE: Do NOT set display here - GL uses display:none to hide inactive tabs */\nmj-tab-container .lm_items > div {\n width: 100% !important;\n height: 100% !important;\n box-sizing: border-box !important;\n flex-direction: column !important;\n}\n\n/* Only apply flex display to the active/visible tab content div */\nmj-tab-container .lm_items > div:not([style*=\"display: none\"]) {\n display: flex !important;\n}\n\n/* Clearfix for float-based row layout - GL uses float:left for horizontal panes */\nmj-tab-container .lm_row::after {\n content: \"\" !important;\n display: table !important;\n clear: both !important;\n}\n\n/* Force content children to respect parent bounds (GL sets pixel widths inline) */\nmj-tab-container .lm_content > * {\n max-width: 100% !important;\n width: 100% !important;\n}\n\nmj-tab-container .lm_content {\n background: var(--mj-bg-page) !important;\n display: flex !important;\n flex-direction: column !important;\n height: 100% !important;\n width: 100% !important;\n}\n\nmj-tab-container .lm_item_container {\n background: var(--mj-bg-page) !important;\n}\n\n/* Tab content wrapper - allow scrolling */\n.tab-content-wrapper {\n overflow: auto !important;\n}\n\n/* Make tabs larger and easier to click */\nmj-tab-container .lm_header {\n height: 38px !important;\n padding-top: 2px !important;\n padding-left: 4px !important;\n background: var(--mj-bg-surface-sunken) !important;\n border-bottom: 1px solid var(--mj-border-default) !important;\n overflow: visible !important;\n box-sizing: border-box !important;\n}\n\n/* SCROLLING TAB STRIP (browser-tab pattern, Matt's call over GL's overflow\n dropdown): tabs keep natural width and the strip scrolls horizontally.\n Works with settingsConfig()'s effectively-infinite tabOverlapAllowance \u2014\n GL then never re-homes tabs to its dropdown, only writes inline zIndex +\n negative marginLeft, both neutralized here. Scrollbar hidden per the\n browser-tab convention; wheel input is translated to horizontal scroll by\n GoldenLayoutManager.onStripWheel, and activation scrolls the tab into view. */\nmj-tab-container .lm_tabs {\n height: 36px !important;\n left: 0;\n right: 0;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n}\n\nmj-tab-container .lm_tabs::-webkit-scrollbar {\n display: none;\n}\n\n/* Strip nudge arrows \u2014 the VISIBLE overflow affordance (created by\n GoldenLayoutManager.updateStripNudges, one pair per header, [hidden]\n unless that direction has more tabs). The gradient doubles as the\n \"content continues\" edge fade. */\nmj-tab-container .mj-strip-nudge {\n position: absolute;\n top: 0;\n height: 36px;\n width: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n padding: 0;\n margin: 0;\n z-index: 3; /* above tabs (z 1/2) within the header context */\n font-size: 11px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\nmj-tab-container .mj-strip-nudge[hidden] {\n display: none;\n}\n\nmj-tab-container .mj-strip-nudge--left {\n left: 0;\n background: linear-gradient(to right, var(--mj-bg-surface-sunken) 55%, transparent);\n justify-content: flex-start;\n padding-left: 6px;\n}\n\nmj-tab-container .mj-strip-nudge--right {\n right: 0;\n background: linear-gradient(to left, var(--mj-bg-surface-sunken) 55%, transparent);\n justify-content: flex-end;\n padding-right: 6px;\n}\n\nmj-tab-container .mj-strip-nudge:hover {\n color: var(--mj-text-primary);\n}\n\nmj-tab-container .mj-strip-nudge:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: -2px;\n}\n\n/* Hide Golden Layout WINDOW controls (popout/maximise/stack-close). The\n scrolling strip replaces GL's lm_tabdropdown overflow menu entirely (it\n never activates with the infinite overlap allowance). */\nmj-tab-container .lm_controls .lm_popout,\nmj-tab-container .lm_controls .lm_maximise,\nmj-tab-container .lm_controls .lm_close {\n display: none !important;\n}\n\nmj-tab-container .lm_header .lm_tab {\n /* Flex centering: the type-icon slot (and any future adornment) must sit\n on the tab's vertical center \u2014 inline baseline alignment inside the\n 35px line-height text line pushed it ~15px low. */\n /* FULL FLEX FLOW (Matt's refactor): [type icon] [title] [pin] [close] are\n ordinary flex siblings \u2014 no absolute anchoring, no padding reservations,\n no vertical transforms. gap owns horizontal rhythm; align-items owns\n vertical centering for every child. */\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n padding: 0 9px !important;\n font-size: 13px !important;\n height: 35px !important;\n /* Scrolling strip: tabs are flex items of .lm_tabs \u2014 never let them\n shrink to \"fit\" (that's what the strip's scroll is for), and zero out\n the negative overlap margins GL writes inline when tabs overflow. */\n flex: 0 0 auto !important;\n margin-left: 0 !important;\n line-height: 35px !important;\n box-sizing: border-box !important;\n cursor: pointer !important;\n user-select: none !important;\n background: transparent !important;\n border: none !important;\n border-bottom: 1px solid var(--mj-border-default) !important;\n transition: all 0.15s ease !important;\n position: relative !important;\n z-index: 1 !important;\n margin-right: 1px !important;\n}\n\n/* Pipe separators between INACTIVE tabs (browser-tab pattern): a short\n centered divider on each tab's right edge establishes separation without\n boxing every tab. Suppressed around the ACTIVE tab (its raised card has\n real edges), around the hovered tab, and after the last tab. */\nmj-tab-container .lm_header .lm_tab::after {\n content: '' !important;\n position: absolute !important;\n right: -1px !important;\n top: 50% !important;\n transform: translateY(-50%) !important;\n width: 1px !important;\n height: 16px !important;\n background: var(--mj-border-strong) !important;\n}\n\nmj-tab-container .lm_header .lm_tab.lm_active::after,\nmj-tab-container .lm_header .lm_tab:has(+ .lm_tab.lm_active)::after,\nmj-tab-container .lm_header .lm_tab:hover::after,\nmj-tab-container .lm_header .lm_tab:has(+ .lm_tab:hover)::after,\nmj-tab-container .lm_header .lm_tab:last-child::after {\n content: none !important;\n}\n\n/* Type-icon slot (Matt's tab design, 2026-07-29): every tab leads with its\n TYPE icon tinted in the app color \u2014 entity icon for records, nav-item/app\n icon for pages. The old 3px app-color left-edge bar is GONE; the icon\n tint carries app identity now. Hovering the TAB swaps the icon to an\n ellipsis: the slot is the visible \"this tab has actions\" affordance \u2014\n clicking it opens the tab-actions menu (same menu as right-click). */\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot {\n display: inline-flex !important;\n align-items: center !important;\n justify-content: center !important;\n /* 24px = WCAG 2.2 AA minimum pointer target (SC 2.5.8); glyph stays 12px */\n width: 24px !important;\n height: 24px !important;\n border-radius: 5px !important;\n flex-shrink: 0 !important;\n cursor: pointer !important;\n /* The slot is a real <button> now \u2014 neutralize UA button chrome */\n background: transparent !important;\n border: none !important;\n padding: 0 !important;\n font: inherit !important;\n color: inherit !important;\n}\n\n/* Keyboard parity with hover: focused slot shows the dots + house focus\n ring (outline idiom \u2014 GL headers clip box-shadows). */\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot:focus-visible {\n outline: 2px solid var(--mj-border-focus) !important;\n outline-offset: -2px !important;\n}\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot:focus-visible .mj-tab-type-ico {\n display: none !important;\n}\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot:focus-visible .mj-tab-dots {\n display: inline-block !important;\n}\n/* GL's base stylesheet styles EVERY `i` inside a tab as its legacy 2x19px\n absolutely-positioned corner decoration (.lm_header .lm_tab i) \u2014 which\n turns our icon elements into slivers the glyph overflows. Restore normal\n flow for the slot's icons. */\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot i {\n position: static !important;\n width: auto !important;\n height: auto !important;\n}\n\nmj-tab-container .lm_header .lm_tab .mj-tab-type-ico {\n color: var(--app-color, var(--mj-text-muted)) !important;\n font-size: 12px !important;\n line-height: 1 !important;\n}\nmj-tab-container .lm_header .lm_tab .mj-tab-dots {\n display: none !important;\n color: var(--mj-text-secondary) !important;\n font-size: 12px !important;\n line-height: 1 !important;\n}\nmj-tab-container .lm_header .lm_tab:hover .mj-tab-type-ico {\n display: none !important;\n}\nmj-tab-container .lm_header .lm_tab:hover .mj-tab-dots {\n display: inline-block !important;\n}\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot:hover {\n background: var(--mj-bg-surface-hover) !important;\n}\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot:hover .mj-tab-dots {\n color: var(--mj-text-primary) !important;\n}\n\nmj-tab-container .lm_header .lm_tab:hover {\n background: var(--mj-bg-surface-hover) !important;\n}\n\n\nmj-tab-container .lm_header .lm_tab.lm_active {\n background: var(--mj-bg-surface) !important;\n height: 36px !important;\n margin-bottom: -1px !important;\n margin-right: 0 !important;\n border: 1px solid var(--mj-border-default) !important;\n border-bottom-color: var(--mj-bg-surface) !important;\n border-radius: 4px 4px 0 0 !important;\n z-index: 2 !important;\n}\n\n\nmj-tab-container .lm_title {\n cursor: pointer !important;\n user-select: none !important;\n /* In-flow flex child: normalize the inherited 35px line-height so the\n text box is glyph-height and centers identically to its siblings;\n truncate instead of colliding when GL constrains tab width. */\n line-height: normal !important;\n flex: 0 1 auto !important;\n min-width: 0 !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n white-space: nowrap !important;\n /* Glyph-overhang room: italics (unpinned tabs) paint past the last\n glyph's advance width, and overflow:hidden clips at the padding edge \u2014\n without this the final letter loses its slant. */\n padding-right: 3px !important;\n}\n\nmj-tab-container .lm_close_tab {\n position: static !important;\n order: 10 !important;\n transform: none !important;\n margin: 0 !important;\n /* 24px WCAG target; glyph stays 10px */\n width: 24px !important;\n height: 24px !important;\n border-radius: 5px !important;\n cursor: pointer !important;\n /* ALWAYS visible (Matt's call): quiet at rest, full on its own hover/focus.\n Discoverability shouldn't depend on hovering. */\n opacity: 0.55 !important;\n transition: opacity 0.15s ease !important;\n flex-shrink: 0 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n font-size: 10px !important;\n color: var(--mj-text-secondary) !important;\n}\n\nmj-tab-container .lm_close_tab:focus-visible {\n outline: 2px solid var(--mj-border-focus) !important;\n outline-offset: -2px !important;\n opacity: 1 !important;\n}\n\nmj-tab-container .lm_close_tab:hover {\n opacity: 1 !important;\n color: var(--mj-status-error) !important;\n /* background-COLOR, never the shorthand: GL's stock close was a\n background-image PNG and the shorthand silently wiped it (now it's an\n FA ::before glyph, but the discipline stands). */\n background-color: var(--mj-bg-surface-hover) !important;\n}\n\n/* Pinned tabs never show close button (the pin control replaces it) */\nmj-tab-container .lm_header .lm_tab.pinned .lm_close_tab {\n display: none !important;\n}\n\n\n"] }]
|
|
2728
|
-
}], () => [{ type: i1.GoldenLayoutManager }, { type: i1.WorkspaceStateManager }, { type: i1.ApplicationManager }, { type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }, { type: i0.ChangeDetectorRef }], {
|
|
2880
|
+
}], () => [{ type: i1.GoldenLayoutManager }, { type: i1.WorkspaceStateManager }, { type: i1.ApplicationManager }, { type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }, { type: i0.ChangeDetectorRef }], { GlContainer: [{
|
|
2729
2881
|
type: ViewChild,
|
|
2730
2882
|
args: ['glContainer', { static: false }]
|
|
2731
|
-
}],
|
|
2883
|
+
}], DirectContentContainer: [{
|
|
2732
2884
|
type: ViewChild,
|
|
2733
2885
|
args: ['directContentContainer', { static: false }]
|
|
2734
|
-
}],
|
|
2886
|
+
}], RecordsGlContainer: [{
|
|
2735
2887
|
type: ViewChild,
|
|
2736
2888
|
args: ['recordsGlContainer', { static: false }]
|
|
2889
|
+
}], FirstResourceLoadComplete: [{
|
|
2890
|
+
type: Output
|
|
2737
2891
|
}], firstResourceLoadComplete: [{
|
|
2738
2892
|
type: Output
|
|
2893
|
+
}], LayoutInitError: [{
|
|
2894
|
+
type: Output
|
|
2739
2895
|
}], layoutInitError: [{
|
|
2740
2896
|
type: Output
|
|
2741
2897
|
}], onWindowResize: [{
|