@memberjunction/ng-dashboards 6.2.0-edge.3 → 6.2.0-edge.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AI/components/analytics/realtime/realtime-transcripts-data.d.ts +4 -3
- package/dist/AI/components/analytics/realtime/realtime-transcripts-data.d.ts.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-transcripts-data.js +8 -5
- package/dist/AI/components/analytics/realtime/realtime-transcripts-data.js.map +1 -1
- package/dist/AI/components/duplicates/compare-value.component.d.ts +67 -0
- package/dist/AI/components/duplicates/compare-value.component.d.ts.map +1 -0
- package/dist/AI/components/duplicates/compare-value.component.js +168 -0
- package/dist/AI/components/duplicates/compare-value.component.js.map +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +49 -3
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +287 -169
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts +77 -0
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts.map +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.js +116 -0
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.js.map +1 -0
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts +1 -0
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +16 -4
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts +2 -0
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +12 -6
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-index-auto.d.ts +29 -0
- package/dist/AI/components/vectors/vector-index-auto.d.ts.map +1 -0
- package/dist/AI/components/vectors/vector-index-auto.js +59 -0
- package/dist/AI/components/vectors/vector-index-auto.js.map +1 -0
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +9 -0
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +65 -20
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.d.ts.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +7 -3
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js +3 -2
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +1 -0
- package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts +0 -3
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js +5 -14
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +1 -0
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +1 -0
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.d.ts +2 -0
- package/dist/Credentials/components/credentials-list-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +12 -10
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-agent-context.d.ts +14 -43
- package/dist/DashboardBrowser/dashboard-browser-agent-context.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-agent-context.js +6 -29
- package/dist/DashboardBrowser/dashboard-browser-agent-context.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts +174 -321
- package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts.map +1 -1
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js +522 -1195
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboard-library-filter.d.ts +116 -0
- package/dist/DashboardBrowser/dashboard-library-filter.d.ts.map +1 -0
- package/dist/DashboardBrowser/dashboard-library-filter.js +277 -0
- package/dist/DashboardBrowser/dashboard-library-filter.js.map +1 -0
- package/dist/DashboardBrowser/dashboard-share-dialog.component.d.ts +1 -1
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
- package/dist/DashboardBrowser/dashboards-agent-tools.d.ts +26 -0
- package/dist/DashboardBrowser/dashboards-agent-tools.d.ts.map +1 -0
- package/dist/DashboardBrowser/dashboards-agent-tools.js +32 -0
- package/dist/DashboardBrowser/dashboards-agent-tools.js.map +1 -0
- package/dist/DashboardBrowser/dashboards-categories-resource.component.d.ts +58 -0
- package/dist/DashboardBrowser/dashboards-categories-resource.component.d.ts.map +1 -0
- package/dist/DashboardBrowser/dashboards-categories-resource.component.js +391 -0
- package/dist/DashboardBrowser/dashboards-categories-resource.component.js.map +1 -0
- package/dist/DashboardBrowser/dashboards-categories.helpers.d.ts +37 -0
- package/dist/DashboardBrowser/dashboards-categories.helpers.d.ts.map +1 -0
- package/dist/DashboardBrowser/dashboards-categories.helpers.js +68 -0
- package/dist/DashboardBrowser/dashboards-categories.helpers.js.map +1 -0
- package/dist/DashboardEditor/dashboard-editor.component.d.ts +295 -0
- package/dist/DashboardEditor/dashboard-editor.component.d.ts.map +1 -0
- package/dist/DashboardEditor/dashboard-editor.component.js +1022 -0
- package/dist/DashboardEditor/dashboard-editor.component.js.map +1 -0
- package/dist/DashboardEditor/dashboard-editor.types.d.ts +23 -0
- package/dist/DashboardEditor/dashboard-editor.types.d.ts.map +1 -0
- package/dist/DashboardEditor/dashboard-editor.types.js +3 -0
- package/dist/DashboardEditor/dashboard-editor.types.js.map +1 -0
- package/dist/DashboardEditor/dashboard-viewer-factory.d.ts +11 -0
- package/dist/DashboardEditor/dashboard-viewer-factory.d.ts.map +1 -0
- package/dist/DashboardEditor/dashboard-viewer-factory.js +17 -0
- package/dist/DashboardEditor/dashboard-viewer-factory.js.map +1 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +26 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +302 -219
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/services/explorer-state.service.d.ts +1 -1
- package/dist/DataExplorer/services/explorer-state.service.js +2 -5
- package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
- package/dist/FormBuilder/form-builder-resource.component.d.ts +0 -14
- package/dist/FormBuilder/form-builder-resource.component.d.ts.map +1 -1
- package/dist/FormBuilder/form-builder-resource.component.js +7 -29
- package/dist/FormBuilder/form-builder-resource.component.js.map +1 -1
- package/dist/Home/home-agent-context.d.ts +29 -10
- package/dist/Home/home-agent-context.d.ts.map +1 -1
- package/dist/Home/home-agent-context.js +50 -24
- package/dist/Home/home-agent-context.js.map +1 -1
- package/dist/Home/home-dashboard-switcher.component.d.ts +95 -0
- package/dist/Home/home-dashboard-switcher.component.d.ts.map +1 -0
- package/dist/Home/home-dashboard-switcher.component.js +442 -0
- package/dist/Home/home-dashboard-switcher.component.js.map +1 -0
- package/dist/Home/home-dashboard.component.d.ts +330 -17
- package/dist/Home/home-dashboard.component.d.ts.map +1 -1
- package/dist/Home/home-dashboard.component.js +1702 -1014
- package/dist/Home/home-dashboard.component.js.map +1 -1
- package/dist/Home/home-menus.d.ts +38 -0
- package/dist/Home/home-menus.d.ts.map +1 -0
- package/dist/Home/home-menus.js +53 -0
- package/dist/Home/home-menus.js.map +1 -0
- package/dist/Home/home-pinned-dashboards.d.ts +33 -0
- package/dist/Home/home-pinned-dashboards.d.ts.map +1 -0
- package/dist/Home/home-pinned-dashboards.js +76 -0
- package/dist/Home/home-pinned-dashboards.js.map +1 -0
- package/dist/PredictiveStudio/components/ps-production.component.d.ts +5 -1
- package/dist/PredictiveStudio/components/ps-production.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-production.component.js +64 -41
- package/dist/PredictiveStudio/components/ps-production.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +3 -2
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/RealtimeRecordings/realtime-recordings-dashboard.component.js +2 -2
- package/dist/RealtimeRecordings/realtime-recordings-dashboard.component.js.map +1 -1
- package/dist/TelephonyOperations/telephony-operations-dashboard.component.d.ts +1 -0
- package/dist/TelephonyOperations/telephony-operations-dashboard.component.d.ts.map +1 -1
- package/dist/TelephonyOperations/telephony-operations-dashboard.component.js +7 -0
- package/dist/TelephonyOperations/telephony-operations-dashboard.component.js.map +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +7 -7
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +21 -20
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +4 -1
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/core-dashboards.module.d.ts +69 -62
- package/dist/core-dashboards.module.d.ts.map +1 -1
- package/dist/core-dashboards.module.js +22 -2
- package/dist/core-dashboards.module.js.map +1 -1
- package/dist/data-explorer-dashboards.module.d.ts +1 -1
- package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
- package/dist/data-explorer-dashboards.module.js +3 -1
- package/dist/data-explorer-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +3 -0
- package/dist/public-api.js.map +1 -1
- package/dist/shared/dashboard-library-changes.d.ts +23 -0
- package/dist/shared/dashboard-library-changes.d.ts.map +1 -0
- package/dist/shared/dashboard-library-changes.js +26 -0
- package/dist/shared/dashboard-library-changes.js.map +1 -0
- package/dist/shared/dashboard-owner-names.d.ts +17 -0
- package/dist/shared/dashboard-owner-names.d.ts.map +1 -0
- package/dist/shared/dashboard-owner-names.js +65 -0
- package/dist/shared/dashboard-owner-names.js.map +1 -0
- package/dist/shared/dashboard-recents.d.ts +34 -0
- package/dist/shared/dashboard-recents.d.ts.map +1 -0
- package/dist/shared/dashboard-recents.js +87 -0
- package/dist/shared/dashboard-recents.js.map +1 -0
- package/dist/shared/dashboards-app-install.d.ts +59 -0
- package/dist/shared/dashboards-app-install.d.ts.map +1 -0
- package/dist/shared/dashboards-app-install.js +97 -0
- package/dist/shared/dashboards-app-install.js.map +1 -0
- package/dist/shared/dashboards-app.helpers.d.ts +42 -0
- package/dist/shared/dashboards-app.helpers.d.ts.map +1 -0
- package/dist/shared/dashboards-app.helpers.js +143 -0
- package/dist/shared/dashboards-app.helpers.js.map +1 -0
- package/package.json +69 -68
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-recents.js","sourceRoot":"","sources":["../../src/shared/dashboard-recents.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview The user's recently opened dashboards, for the Library (its order and Recently\n * opened).\n *\n * The list comes from a query of the user's MJ: User Record Logs for the MJ: Dashboards entity, so it\n * lists every dashboard the user opened, not only the dashboards among the latest records of any\n * entity. Record logs are not cached, so the list is read again each time it can have changed.\n *\n * Opening a dashboard saves a record log (RecentAccessService.LogAccess). The service then reloads its\n * recent items and emits RecentItems, after the log is saved. ObserveRecentDashboardIds reads the list\n * again each time its trigger emits, so a caller that passes RecentItems shows the new open.\n */\nimport { LogError, RunView } from '@memberjunction/core';\nimport type { IMetadataProvider } from '@memberjunction/core';\nimport { EscapeSQLString, UUIDsEqual } from '@memberjunction/global';\nimport { from, Observable } from 'rxjs';\nimport { switchMap } from 'rxjs/operators';\n\n/** The entity whose record logs are dashboard opens. */\nexport const DASHBOARDS_ENTITY_NAME = 'MJ: Dashboards';\n\nconst USER_RECORD_LOGS_ENTITY_NAME = 'MJ: User Record Logs';\n\n/** A record log, as far as dashboard recents need it. A simple RunView row can carry `LatestAt` as text. */\nexport interface DashboardRecordLog {\n RecordID: string;\n LatestAt: Date | string;\n}\n\n/**\n * The record ids of `logs`, most recently opened first, each id once (compared with UUIDsEqual,\n * keeping the newest), at most `maxItems` of them. Logs without a record id are skipped.\n */\nexport function OrderRecentDashboardIds(logs: ReadonlyArray<DashboardRecordLog>, maxItems: number = Number.POSITIVE_INFINITY): string[] {\n const newestFirst = [...logs].sort((a, b) => timeOf(b.LatestAt) - timeOf(a.LatestAt));\n const ids: string[] = [];\n for (const log of newestFirst) {\n if (ids.length >= maxItems) {\n break;\n }\n if (log.RecordID && !ids.some(id => UUIDsEqual(id, log.RecordID))) {\n ids.push(log.RecordID);\n }\n }\n return ids;\n}\n\n/**\n * Loads the ids of the dashboards the current user of `provider` opened, most recent first, at most\n * `maxItems` (all of them when omitted), with one query of the user's MJ: User Record Logs for the\n * MJ: Dashboards entity. Returns an empty list when the metadata has no MJ: Dashboards entity, there\n * is no current user, or the query fails or throws (for example when the user cannot read the record\n * logs, or the server cannot be reached). A failed or thrown read is logged; it never rejects.\n */\nexport async function LoadRecentDashboardIds(provider: IMetadataProvider, maxItems?: number): Promise<string[]> {\n const dashboardsEntity = provider.EntityByName(DASHBOARDS_ENTITY_NAME);\n const user = provider.CurrentUser;\n if (!dashboardsEntity || !user) {\n return [];\n }\n try {\n const result = await RunView.FromMetadataProvider(provider).RunView<DashboardRecordLog>({\n EntityName: USER_RECORD_LOGS_ENTITY_NAME,\n ExtraFilter: `UserID='${EscapeSQLString(user.ID)}' AND EntityID='${EscapeSQLString(dashboardsEntity.ID)}'`,\n OrderBy: 'LatestAt DESC',\n Fields: ['RecordID', 'LatestAt'],\n ResultType: 'simple',\n });\n if (!result.Success) {\n LogError(`Recently opened dashboards could not be read: ${result.ErrorMessage}`);\n return [];\n }\n return OrderRecentDashboardIds(result.Results, maxItems);\n } catch (error) {\n LogError(`Recently opened dashboards could not be read: ${error instanceof Error ? error.message : String(error)}`);\n return [];\n }\n}\n\n/**\n * Emits the ids of the dashboards the current user opened (see {@link LoadRecentDashboardIds}) each\n * time `trigger` emits, read again each time. A read that a newer emission overtakes is dropped.\n * With the default `load`, a read that fails or throws gives an empty list, so the stream keeps running.\n *\n * @param provider The provider whose metadata and current user the read uses.\n * @param trigger Emits when the list can have changed, for example RecentAccessService.RecentItems,\n * which emits after a dashboard open is logged.\n * @param load Reads the ids. The default is {@link LoadRecentDashboardIds}.\n */\nexport function ObserveRecentDashboardIds(\n provider: IMetadataProvider,\n trigger: Observable<unknown>,\n load: (provider: IMetadataProvider) => Promise<string[]> = LoadRecentDashboardIds\n): Observable<string[]> {\n return trigger.pipe(switchMap(() => from(load(provider))));\n}\n\n/** Milliseconds since the epoch, or 0 for a missing or invalid date. */\nfunction timeOf(value: Date | string): number {\n const time = new Date(value).getTime();\n return Number.isNaN(time) ? 0 : time;\n}\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { UserApplicationAccessStatus } from '@memberjunction/core-entities';
|
|
2
|
+
/**
|
|
3
|
+
* UserInfoEngine setting that records the one-time automatic install of the Dashboards app.
|
|
4
|
+
* The value is 'true' when set.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY = "Dashboards.AppAutoInstalled";
|
|
7
|
+
/**
|
|
8
|
+
* How long one install step (the install, or the marker save) may take. A step that takes longer
|
|
9
|
+
* counts as failed, so the install queue moves on and its callers are not held.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS = 5000;
|
|
12
|
+
/** What the install paths know about the Dashboards app and the current user. */
|
|
13
|
+
export interface DashboardsAppInstallState {
|
|
14
|
+
/** An Active application named Dashboards exists in metadata. */
|
|
15
|
+
AppExists: boolean;
|
|
16
|
+
/** The user's access to the app: role authorization, then the UserApplication row. Ignored when AppExists is false. */
|
|
17
|
+
Access: UserApplicationAccessStatus;
|
|
18
|
+
/** The one-time automatic install is recorded for the user. */
|
|
19
|
+
AutoInstallRecorded: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** The operations the install paths call. `dashboards-app.helpers.ts` builds them from ApplicationManager and UserInfoEngine. */
|
|
22
|
+
export interface DashboardsAppInstallOperations {
|
|
23
|
+
/** The current state, or null when the user's app data cannot be read. */
|
|
24
|
+
ReadState(): DashboardsAppInstallState | null;
|
|
25
|
+
/** Installs or re-enables the app for the user and refreshes the user's app list. Resolves true on success. */
|
|
26
|
+
Install(): Promise<boolean>;
|
|
27
|
+
/** Saves the one-time automatic-install marker. Resolves true on success. */
|
|
28
|
+
RecordAutoInstall(): Promise<boolean>;
|
|
29
|
+
}
|
|
30
|
+
/** What a Home load does about the Dashboards app. */
|
|
31
|
+
export type DashboardsAppAutoInstallAction = 'install' | 'skip';
|
|
32
|
+
/** What a user click that goes to the Dashboards app does before it navigates. */
|
|
33
|
+
export type DashboardsAppExplicitInstallAction = 'open' | 'install' | 'unavailable';
|
|
34
|
+
/**
|
|
35
|
+
* The automatic path installs only for a user with no UserApplication row for the app and no
|
|
36
|
+
* recorded install. An inactive row means the user removed the app, so it is left alone.
|
|
37
|
+
*/
|
|
38
|
+
export declare function DecideDashboardsAppAutoInstall(state: DashboardsAppInstallState): DashboardsAppAutoInstallAction;
|
|
39
|
+
/**
|
|
40
|
+
* The explicit path ignores the marker: a missing or removed app is installed, an active one
|
|
41
|
+
* opens, and a missing or unauthorized app is unavailable.
|
|
42
|
+
*/
|
|
43
|
+
export declare function DecideDashboardsAppExplicitInstall(state: DashboardsAppInstallState): DashboardsAppExplicitInstallAction;
|
|
44
|
+
/**
|
|
45
|
+
* Automatic path (Home load). Installs the app when {@link DecideDashboardsAppAutoInstall} says so,
|
|
46
|
+
* then records the marker. The marker is written only after a successful install, so a failed or
|
|
47
|
+
* timed-out install is retried on the next load. Each step waits at most
|
|
48
|
+
* {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.
|
|
49
|
+
* @returns true when this call installed the app.
|
|
50
|
+
*/
|
|
51
|
+
export declare function RunDashboardsAppAutoInstall(operations: DashboardsAppInstallOperations): Promise<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* Explicit path (a user click that goes to the app). Installs the app when it is missing or
|
|
54
|
+
* removed, and records the marker if it is not set yet. Each step waits at most
|
|
55
|
+
* {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.
|
|
56
|
+
* @returns true when the user has the app active afterwards, so the caller can navigate.
|
|
57
|
+
*/
|
|
58
|
+
export declare function RunDashboardsAppExplicitInstall(operations: DashboardsAppInstallOperations): Promise<boolean>;
|
|
59
|
+
//# sourceMappingURL=dashboards-app-install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboards-app-install.d.ts","sourceRoot":"","sources":["../../src/shared/dashboards-app-install.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAEjF;;;GAGG;AACH,eAAO,MAAM,uCAAuC,gCAAgC,CAAC;AAErF;;;GAGG;AACH,eAAO,MAAM,sCAAsC,OAAO,CAAC;AAE3D,iFAAiF;AACjF,MAAM,WAAW,yBAAyB;IACxC,iEAAiE;IACjE,SAAS,EAAE,OAAO,CAAC;IACnB,uHAAuH;IACvH,MAAM,EAAE,2BAA2B,CAAC;IACpC,+DAA+D;IAC/D,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,iIAAiI;AACjI,MAAM,WAAW,8BAA8B;IAC7C,0EAA0E;IAC1E,SAAS,IAAI,yBAAyB,GAAG,IAAI,CAAC;IAC9C,+GAA+G;IAC/G,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,6EAA6E;IAC7E,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CACvC;AAED,sDAAsD;AACtD,MAAM,MAAM,8BAA8B,GAAG,SAAS,GAAG,MAAM,CAAC;AAEhE,kFAAkF;AAClF,MAAM,MAAM,kCAAkC,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;AAEpF;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,yBAAyB,GAAG,8BAA8B,CAG/G;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,yBAAyB,GAAG,kCAAkC,CAKvH;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,8BAA8B,GAAG,OAAO,CAAC,OAAO,CAAC,CAYxG;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,UAAU,EAAE,8BAA8B,GAAG,OAAO,CAAC,OAAO,CAAC,CAkB5G"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { LogError } from '@memberjunction/core';
|
|
2
|
+
/**
|
|
3
|
+
* UserInfoEngine setting that records the one-time automatic install of the Dashboards app.
|
|
4
|
+
* The value is 'true' when set.
|
|
5
|
+
*/
|
|
6
|
+
export const DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY = 'Dashboards.AppAutoInstalled';
|
|
7
|
+
/**
|
|
8
|
+
* How long one install step (the install, or the marker save) may take. A step that takes longer
|
|
9
|
+
* counts as failed, so the install queue moves on and its callers are not held.
|
|
10
|
+
*/
|
|
11
|
+
export const DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS = 5000;
|
|
12
|
+
/**
|
|
13
|
+
* The automatic path installs only for a user with no UserApplication row for the app and no
|
|
14
|
+
* recorded install. An inactive row means the user removed the app, so it is left alone.
|
|
15
|
+
*/
|
|
16
|
+
export function DecideDashboardsAppAutoInstall(state) {
|
|
17
|
+
const install = state.AppExists && state.Access === 'not_installed' && !state.AutoInstallRecorded;
|
|
18
|
+
return install ? 'install' : 'skip';
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The explicit path ignores the marker: a missing or removed app is installed, an active one
|
|
22
|
+
* opens, and a missing or unauthorized app is unavailable.
|
|
23
|
+
*/
|
|
24
|
+
export function DecideDashboardsAppExplicitInstall(state) {
|
|
25
|
+
if (!state.AppExists || state.Access === 'not_authorized') {
|
|
26
|
+
return 'unavailable';
|
|
27
|
+
}
|
|
28
|
+
return state.Access === 'installed_active' ? 'open' : 'install';
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Automatic path (Home load). Installs the app when {@link DecideDashboardsAppAutoInstall} says so,
|
|
32
|
+
* then records the marker. The marker is written only after a successful install, so a failed or
|
|
33
|
+
* timed-out install is retried on the next load. Each step waits at most
|
|
34
|
+
* {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.
|
|
35
|
+
* @returns true when this call installed the app.
|
|
36
|
+
*/
|
|
37
|
+
export function RunDashboardsAppAutoInstall(operations) {
|
|
38
|
+
return runOneAtATime(async () => {
|
|
39
|
+
const state = operations.ReadState();
|
|
40
|
+
if (!state || DecideDashboardsAppAutoInstall(state) === 'skip') {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
if (!(await withStepTimeout(operations.Install(), 'the install'))) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
await withStepTimeout(operations.RecordAutoInstall(), 'the marker save');
|
|
47
|
+
return true;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Explicit path (a user click that goes to the app). Installs the app when it is missing or
|
|
52
|
+
* removed, and records the marker if it is not set yet. Each step waits at most
|
|
53
|
+
* {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.
|
|
54
|
+
* @returns true when the user has the app active afterwards, so the caller can navigate.
|
|
55
|
+
*/
|
|
56
|
+
export function RunDashboardsAppExplicitInstall(operations) {
|
|
57
|
+
return runOneAtATime(async () => {
|
|
58
|
+
const state = operations.ReadState();
|
|
59
|
+
if (!state) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const action = DecideDashboardsAppExplicitInstall(state);
|
|
63
|
+
if (action !== 'install') {
|
|
64
|
+
return action === 'open';
|
|
65
|
+
}
|
|
66
|
+
if (!(await withStepTimeout(operations.Install(), 'the install'))) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
if (!state.AutoInstallRecorded) {
|
|
70
|
+
await withStepTimeout(operations.RecordAutoInstall(), 'the marker save');
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Resolves with the step's result, or with false when the step does not settle within
|
|
77
|
+
* {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}. A timed-out step is logged and keeps running in
|
|
78
|
+
* the background, but nothing waits for it. The timer is cleared when the step settles first.
|
|
79
|
+
*/
|
|
80
|
+
function withStepTimeout(step, stepName) {
|
|
81
|
+
let timer;
|
|
82
|
+
const timedOut = new Promise((resolve) => {
|
|
83
|
+
timer = setTimeout(() => {
|
|
84
|
+
LogError(`Dashboards app install: ${stepName} did not finish within ${DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS} ms, so it counts as failed`);
|
|
85
|
+
resolve(false);
|
|
86
|
+
}, DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS);
|
|
87
|
+
});
|
|
88
|
+
return Promise.race([step, timedOut]).finally(() => clearTimeout(timer));
|
|
89
|
+
}
|
|
90
|
+
let installQueue = Promise.resolve();
|
|
91
|
+
/** Runs install work one call at a time, so each call reads the state the previous call left. */
|
|
92
|
+
function runOneAtATime(work) {
|
|
93
|
+
const run = installQueue.then(work);
|
|
94
|
+
installQueue = run.catch(() => undefined);
|
|
95
|
+
return run;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=dashboards-app-install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboards-app-install.js","sourceRoot":"","sources":["../../src/shared/dashboards-app-install.ts"],"names":[],"mappings":"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","sourcesContent":["import { LogError } from '@memberjunction/core';\nimport type { UserApplicationAccessStatus } from '@memberjunction/core-entities';\n\n/**\n * UserInfoEngine setting that records the one-time automatic install of the Dashboards app.\n * The value is 'true' when set.\n */\nexport const DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY = 'Dashboards.AppAutoInstalled';\n\n/**\n * How long one install step (the install, or the marker save) may take. A step that takes longer\n * counts as failed, so the install queue moves on and its callers are not held.\n */\nexport const DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS = 5000;\n\n/** What the install paths know about the Dashboards app and the current user. */\nexport interface DashboardsAppInstallState {\n /** An Active application named Dashboards exists in metadata. */\n AppExists: boolean;\n /** The user's access to the app: role authorization, then the UserApplication row. Ignored when AppExists is false. */\n Access: UserApplicationAccessStatus;\n /** The one-time automatic install is recorded for the user. */\n AutoInstallRecorded: boolean;\n}\n\n/** The operations the install paths call. `dashboards-app.helpers.ts` builds them from ApplicationManager and UserInfoEngine. */\nexport interface DashboardsAppInstallOperations {\n /** The current state, or null when the user's app data cannot be read. */\n ReadState(): DashboardsAppInstallState | null;\n /** Installs or re-enables the app for the user and refreshes the user's app list. Resolves true on success. */\n Install(): Promise<boolean>;\n /** Saves the one-time automatic-install marker. Resolves true on success. */\n RecordAutoInstall(): Promise<boolean>;\n}\n\n/** What a Home load does about the Dashboards app. */\nexport type DashboardsAppAutoInstallAction = 'install' | 'skip';\n\n/** What a user click that goes to the Dashboards app does before it navigates. */\nexport type DashboardsAppExplicitInstallAction = 'open' | 'install' | 'unavailable';\n\n/**\n * The automatic path installs only for a user with no UserApplication row for the app and no\n * recorded install. An inactive row means the user removed the app, so it is left alone.\n */\nexport function DecideDashboardsAppAutoInstall(state: DashboardsAppInstallState): DashboardsAppAutoInstallAction {\n const install = state.AppExists && state.Access === 'not_installed' && !state.AutoInstallRecorded;\n return install ? 'install' : 'skip';\n}\n\n/**\n * The explicit path ignores the marker: a missing or removed app is installed, an active one\n * opens, and a missing or unauthorized app is unavailable.\n */\nexport function DecideDashboardsAppExplicitInstall(state: DashboardsAppInstallState): DashboardsAppExplicitInstallAction {\n if (!state.AppExists || state.Access === 'not_authorized') {\n return 'unavailable';\n }\n return state.Access === 'installed_active' ? 'open' : 'install';\n}\n\n/**\n * Automatic path (Home load). Installs the app when {@link DecideDashboardsAppAutoInstall} says so,\n * then records the marker. The marker is written only after a successful install, so a failed or\n * timed-out install is retried on the next load. Each step waits at most\n * {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.\n * @returns true when this call installed the app.\n */\nexport function RunDashboardsAppAutoInstall(operations: DashboardsAppInstallOperations): Promise<boolean> {\n return runOneAtATime(async () => {\n const state = operations.ReadState();\n if (!state || DecideDashboardsAppAutoInstall(state) === 'skip') {\n return false;\n }\n if (!(await withStepTimeout(operations.Install(), 'the install'))) {\n return false;\n }\n await withStepTimeout(operations.RecordAutoInstall(), 'the marker save');\n return true;\n });\n}\n\n/**\n * Explicit path (a user click that goes to the app). Installs the app when it is missing or\n * removed, and records the marker if it is not set yet. Each step waits at most\n * {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}.\n * @returns true when the user has the app active afterwards, so the caller can navigate.\n */\nexport function RunDashboardsAppExplicitInstall(operations: DashboardsAppInstallOperations): Promise<boolean> {\n return runOneAtATime(async () => {\n const state = operations.ReadState();\n if (!state) {\n return false;\n }\n const action = DecideDashboardsAppExplicitInstall(state);\n if (action !== 'install') {\n return action === 'open';\n }\n if (!(await withStepTimeout(operations.Install(), 'the install'))) {\n return false;\n }\n if (!state.AutoInstallRecorded) {\n await withStepTimeout(operations.RecordAutoInstall(), 'the marker save');\n }\n return true;\n });\n}\n\n/**\n * Resolves with the step's result, or with false when the step does not settle within\n * {@link DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS}. A timed-out step is logged and keeps running in\n * the background, but nothing waits for it. The timer is cleared when the step settles first.\n */\nfunction withStepTimeout(step: Promise<boolean>, stepName: string): Promise<boolean> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timedOut = new Promise<boolean>((resolve) => {\n timer = setTimeout(() => {\n LogError(`Dashboards app install: ${stepName} did not finish within ${DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS} ms, so it counts as failed`);\n resolve(false);\n }, DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS);\n });\n return Promise.race([step, timedOut]).finally(() => clearTimeout(timer));\n}\n\nlet installQueue: Promise<unknown> = Promise.resolve();\n\n/** Runs install work one call at a time, so each call reads the state the previous call left. */\nfunction runOneAtATime<T>(work: () => Promise<T>): Promise<T> {\n const run = installQueue.then(work);\n installQueue = run.catch(() => undefined);\n return run;\n}\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { IMetadataProvider } from '@memberjunction/core';
|
|
2
|
+
import type { MJDashboardEntity } from '@memberjunction/core-entities';
|
|
3
|
+
import type { ApplicationManager, BaseApplication } from '@memberjunction/ng-base-application';
|
|
4
|
+
import type { DashboardNavigationOptions } from '@memberjunction/ng-shared';
|
|
5
|
+
export declare const DASHBOARDS_APP_NAME = "Dashboards";
|
|
6
|
+
/** Label of the Dashboards app's Library nav item. */
|
|
7
|
+
export declare const DASHBOARDS_LIBRARY_NAV_ITEM = "Library";
|
|
8
|
+
/** The Dashboards application, if the user has it enabled. */
|
|
9
|
+
export declare function FindDashboardsApp(appManager: ApplicationManager): BaseApplication | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* The NavigationService.OpenDashboard options for a dashboard opened from a page of the Dashboards
|
|
12
|
+
* app: a tab of the Dashboards app. Like any open, the dashboard replaces the current preview tab,
|
|
13
|
+
* so Back returns to the page, and a Shift-click opens a separate tab. When the user does not have
|
|
14
|
+
* the app, no application is named and the tab opens in NavigationService's default application.
|
|
15
|
+
* `openInEditMode` asks the tab to enter edit mode (a new dashboard, or a card's Edit action).
|
|
16
|
+
* `openInNewTab` forces a separate tab, for a click the dashboard browser reports as one
|
|
17
|
+
* (`DashboardOpenEvent.OpenInNewTab`: Shift, Ctrl or Cmd).
|
|
18
|
+
*/
|
|
19
|
+
export declare function DashboardsAppOpenOptions(appManager: ApplicationManager, openInEditMode?: boolean, openInNewTab?: boolean): DashboardNavigationOptions;
|
|
20
|
+
/** The longest name MJ: Dashboards stores: the MaxLength of its Name field, or DASHBOARD_NAME_MAX_LENGTH when the metadata gives none. */
|
|
21
|
+
export declare function DashboardNameMaxLength(md: IMetadataProvider): number;
|
|
22
|
+
/**
|
|
23
|
+
* Creates and saves an empty Config dashboard with the trimmed `name`, owned by the current user, in
|
|
24
|
+
* `categoryId` when one is given. Returns null for a blank name or a failed save.
|
|
25
|
+
*/
|
|
26
|
+
export declare function CreateBlankDashboard(md: IMetadataProvider, name: string, categoryId?: string | null): Promise<MJDashboardEntity | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Automatic install path, for Home load. Installs the Dashboards app for a user who has no
|
|
29
|
+
* UserApplication row for it, at most once per user (tracked by a UserInfoEngine setting), so a
|
|
30
|
+
* user who removes the app keeps it removed. Never rejects.
|
|
31
|
+
* @returns true when this call installed the app.
|
|
32
|
+
*/
|
|
33
|
+
export declare function AutoInstallDashboardsApp(appManager: ApplicationManager): Promise<boolean>;
|
|
34
|
+
/**
|
|
35
|
+
* Explicit install path, for a user click that goes to the Dashboards app (for example Open
|
|
36
|
+
* Dashboards on the Data Explorer banner). Installs the app when it is missing or removed. Never rejects.
|
|
37
|
+
* @returns the app to pass to `NavigationService.SwitchToApp`, or undefined when no Active
|
|
38
|
+
* Dashboards app exists, the user is not authorized for it, or the install failed or did not
|
|
39
|
+
* finish within DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS.
|
|
40
|
+
*/
|
|
41
|
+
export declare function EnsureDashboardsApp(appManager: ApplicationManager): Promise<BaseApplication | undefined>;
|
|
42
|
+
//# sourceMappingURL=dashboards-app.helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboards-app.helpers.d.ts","sourceRoot":"","sources":["../../src/shared/dashboards-app.helpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC/F,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAU5E,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAEhD,sDAAsD;AACtD,eAAO,MAAM,2BAA2B,YAAY,CAAC;AAErD,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,kBAAkB,GAAG,eAAe,GAAG,SAAS,CAE7F;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,kBAAkB,EAAE,cAAc,UAAQ,EAAE,YAAY,UAAQ,GAAG,0BAA0B,CAOjJ;AAKD,0IAA0I;AAC1I,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,iBAAiB,GAAG,MAAM,CAGpE;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAwB7I;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAAC,UAAU,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ/F;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,kBAAkB,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAgB9G"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { LogError } from '@memberjunction/core';
|
|
2
|
+
import { UserInfoEngine } from '@memberjunction/core-entities';
|
|
3
|
+
import { CreateDefaultDashboardConfig, DASHBOARD_NAME_MAX_LENGTH } from '@memberjunction/ng-dashboard-viewer';
|
|
4
|
+
import { DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY, RunDashboardsAppAutoInstall, RunDashboardsAppExplicitInstall, } from './dashboards-app-install';
|
|
5
|
+
export const DASHBOARDS_APP_NAME = 'Dashboards';
|
|
6
|
+
/** Label of the Dashboards app's Library nav item. */
|
|
7
|
+
export const DASHBOARDS_LIBRARY_NAV_ITEM = 'Library';
|
|
8
|
+
/** The Dashboards application, if the user has it enabled. */
|
|
9
|
+
export function FindDashboardsApp(appManager) {
|
|
10
|
+
return appManager.GetAllApps().find((a) => a.Name === DASHBOARDS_APP_NAME);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The NavigationService.OpenDashboard options for a dashboard opened from a page of the Dashboards
|
|
14
|
+
* app: a tab of the Dashboards app. Like any open, the dashboard replaces the current preview tab,
|
|
15
|
+
* so Back returns to the page, and a Shift-click opens a separate tab. When the user does not have
|
|
16
|
+
* the app, no application is named and the tab opens in NavigationService's default application.
|
|
17
|
+
* `openInEditMode` asks the tab to enter edit mode (a new dashboard, or a card's Edit action).
|
|
18
|
+
* `openInNewTab` forces a separate tab, for a click the dashboard browser reports as one
|
|
19
|
+
* (`DashboardOpenEvent.OpenInNewTab`: Shift, Ctrl or Cmd).
|
|
20
|
+
*/
|
|
21
|
+
export function DashboardsAppOpenOptions(appManager, openInEditMode = false, openInNewTab = false) {
|
|
22
|
+
const app = FindDashboardsApp(appManager);
|
|
23
|
+
return {
|
|
24
|
+
...(app ? { applicationId: app.ID } : {}),
|
|
25
|
+
...(openInEditMode ? { openInEditMode: true } : {}),
|
|
26
|
+
...(openInNewTab ? { forceNewTab: true } : {}),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** The entity of dashboard records. */
|
|
30
|
+
const DASHBOARDS_ENTITY = 'MJ: Dashboards';
|
|
31
|
+
/** The longest name MJ: Dashboards stores: the MaxLength of its Name field, or DASHBOARD_NAME_MAX_LENGTH when the metadata gives none. */
|
|
32
|
+
export function DashboardNameMaxLength(md) {
|
|
33
|
+
const maxLength = md.EntityByName(DASHBOARDS_ENTITY)?.FieldByName('Name')?.MaxLength ?? 0;
|
|
34
|
+
return maxLength > 0 ? maxLength : DASHBOARD_NAME_MAX_LENGTH;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Creates and saves an empty Config dashboard with the trimmed `name`, owned by the current user, in
|
|
38
|
+
* `categoryId` when one is given. Returns null for a blank name or a failed save.
|
|
39
|
+
*/
|
|
40
|
+
export async function CreateBlankDashboard(md, name, categoryId) {
|
|
41
|
+
const trimmed = name.trim();
|
|
42
|
+
if (!trimmed) {
|
|
43
|
+
LogError('CreateBlankDashboard: the dashboard needs a name');
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const dashboard = await md.GetEntityObject(DASHBOARDS_ENTITY, md.CurrentUser);
|
|
48
|
+
dashboard.Name = trimmed;
|
|
49
|
+
dashboard.Description = '';
|
|
50
|
+
dashboard.UserID = md.CurrentUser.ID;
|
|
51
|
+
dashboard.UIConfigDetails = JSON.stringify(CreateDefaultDashboardConfig());
|
|
52
|
+
if (categoryId) {
|
|
53
|
+
dashboard.CategoryID = categoryId;
|
|
54
|
+
}
|
|
55
|
+
if (await dashboard.Save()) {
|
|
56
|
+
return dashboard;
|
|
57
|
+
}
|
|
58
|
+
LogError(`CreateBlankDashboard: ${dashboard.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
LogError(`CreateBlankDashboard: ${errorMessage(error)}`);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Automatic install path, for Home load. Installs the Dashboards app for a user who has no
|
|
68
|
+
* UserApplication row for it, at most once per user (tracked by a UserInfoEngine setting), so a
|
|
69
|
+
* user who removes the app keeps it removed. Never rejects.
|
|
70
|
+
* @returns true when this call installed the app.
|
|
71
|
+
*/
|
|
72
|
+
export async function AutoInstallDashboardsApp(appManager) {
|
|
73
|
+
try {
|
|
74
|
+
await appManager.WhenReady();
|
|
75
|
+
return await RunDashboardsAppAutoInstall(buildInstallOperations(appManager));
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
LogError(`AutoInstallDashboardsApp: ${errorMessage(error)}`);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Explicit install path, for a user click that goes to the Dashboards app (for example Open
|
|
84
|
+
* Dashboards on the Data Explorer banner). Installs the app when it is missing or removed. Never rejects.
|
|
85
|
+
* @returns the app to pass to `NavigationService.SwitchToApp`, or undefined when no Active
|
|
86
|
+
* Dashboards app exists, the user is not authorized for it, or the install failed or did not
|
|
87
|
+
* finish within DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS.
|
|
88
|
+
*/
|
|
89
|
+
export async function EnsureDashboardsApp(appManager) {
|
|
90
|
+
try {
|
|
91
|
+
await appManager.WhenReady();
|
|
92
|
+
if (!(await RunDashboardsAppExplicitInstall(buildInstallOperations(appManager)))) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
const app = FindDashboardsApp(appManager);
|
|
96
|
+
if (app) {
|
|
97
|
+
return app;
|
|
98
|
+
}
|
|
99
|
+
await appManager.ReloadUserApplications();
|
|
100
|
+
return FindDashboardsApp(appManager);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
LogError(`EnsureDashboardsApp: ${errorMessage(error)}`);
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/** Install operations over ApplicationManager and UserInfoEngine.Instance, the engine ApplicationManager reads and installs through. */
|
|
108
|
+
function buildInstallOperations(appManager) {
|
|
109
|
+
const engine = UserInfoEngine.Instance;
|
|
110
|
+
return {
|
|
111
|
+
ReadState: () => readInstallState(appManager, engine),
|
|
112
|
+
Install: () => installForUser(appManager),
|
|
113
|
+
RecordAutoInstall: () => engine.SetSetting(DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY, 'true'),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function readInstallState(appManager, engine) {
|
|
117
|
+
if (engine.IsPermissionConstrained) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const app = findSystemDashboardsApp(appManager);
|
|
121
|
+
return {
|
|
122
|
+
AppExists: app != null,
|
|
123
|
+
Access: app ? engine.CheckUserApplicationAccess(app.ID) : 'not_installed',
|
|
124
|
+
AutoInstallRecorded: engine.GetSetting(DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY) === 'true',
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/** Installs or re-enables the app, then rebuilds the user's app list so navigation can find it. */
|
|
128
|
+
async function installForUser(appManager) {
|
|
129
|
+
const app = findSystemDashboardsApp(appManager);
|
|
130
|
+
if (!app || !(await appManager.InstallAppForUser(app.ID))) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
await appManager.ReloadUserApplications();
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
/** The Dashboards app among all Active applications, whether or not the user has it. */
|
|
137
|
+
function findSystemDashboardsApp(appManager) {
|
|
138
|
+
return appManager.GetAllSystemApps().find((a) => a.Name === DASHBOARDS_APP_NAME);
|
|
139
|
+
}
|
|
140
|
+
function errorMessage(error) {
|
|
141
|
+
return error instanceof Error ? error.message : String(error);
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=dashboards-app.helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboards-app.helpers.js","sourceRoot":"","sources":["../../src/shared/dashboards-app.helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { LogError } from '@memberjunction/core';\nimport type { IMetadataProvider } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport type { MJDashboardEntity } from '@memberjunction/core-entities';\nimport type { ApplicationManager, BaseApplication } from '@memberjunction/ng-base-application';\nimport type { DashboardNavigationOptions } from '@memberjunction/ng-shared';\nimport { CreateDefaultDashboardConfig, DASHBOARD_NAME_MAX_LENGTH } from '@memberjunction/ng-dashboard-viewer';\nimport {\n DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY,\n DashboardsAppInstallOperations,\n DashboardsAppInstallState,\n RunDashboardsAppAutoInstall,\n RunDashboardsAppExplicitInstall,\n} from './dashboards-app-install';\n\nexport const DASHBOARDS_APP_NAME = 'Dashboards';\n\n/** Label of the Dashboards app's Library nav item. */\nexport const DASHBOARDS_LIBRARY_NAV_ITEM = 'Library';\n\n/** The Dashboards application, if the user has it enabled. */\nexport function FindDashboardsApp(appManager: ApplicationManager): BaseApplication | undefined {\n return appManager.GetAllApps().find((a) => a.Name === DASHBOARDS_APP_NAME);\n}\n\n/**\n * The NavigationService.OpenDashboard options for a dashboard opened from a page of the Dashboards\n * app: a tab of the Dashboards app. Like any open, the dashboard replaces the current preview tab,\n * so Back returns to the page, and a Shift-click opens a separate tab. When the user does not have\n * the app, no application is named and the tab opens in NavigationService's default application.\n * `openInEditMode` asks the tab to enter edit mode (a new dashboard, or a card's Edit action).\n * `openInNewTab` forces a separate tab, for a click the dashboard browser reports as one\n * (`DashboardOpenEvent.OpenInNewTab`: Shift, Ctrl or Cmd).\n */\nexport function DashboardsAppOpenOptions(appManager: ApplicationManager, openInEditMode = false, openInNewTab = false): DashboardNavigationOptions {\n const app = FindDashboardsApp(appManager);\n return {\n ...(app ? { applicationId: app.ID } : {}),\n ...(openInEditMode ? { openInEditMode: true } : {}),\n ...(openInNewTab ? { forceNewTab: true } : {}),\n };\n}\n\n/** The entity of dashboard records. */\nconst DASHBOARDS_ENTITY = 'MJ: Dashboards';\n\n/** The longest name MJ: Dashboards stores: the MaxLength of its Name field, or DASHBOARD_NAME_MAX_LENGTH when the metadata gives none. */\nexport function DashboardNameMaxLength(md: IMetadataProvider): number {\n const maxLength = md.EntityByName(DASHBOARDS_ENTITY)?.FieldByName('Name')?.MaxLength ?? 0;\n return maxLength > 0 ? maxLength : DASHBOARD_NAME_MAX_LENGTH;\n}\n\n/**\n * Creates and saves an empty Config dashboard with the trimmed `name`, owned by the current user, in\n * `categoryId` when one is given. Returns null for a blank name or a failed save.\n */\nexport async function CreateBlankDashboard(md: IMetadataProvider, name: string, categoryId?: string | null): Promise<MJDashboardEntity | null> {\n const trimmed = name.trim();\n if (!trimmed) {\n LogError('CreateBlankDashboard: the dashboard needs a name');\n return null;\n }\n try {\n const dashboard = await md.GetEntityObject<MJDashboardEntity>(DASHBOARDS_ENTITY, md.CurrentUser);\n dashboard.Name = trimmed;\n dashboard.Description = '';\n dashboard.UserID = md.CurrentUser.ID;\n dashboard.UIConfigDetails = JSON.stringify(CreateDefaultDashboardConfig());\n if (categoryId) {\n dashboard.CategoryID = categoryId;\n }\n if (await dashboard.Save()) {\n return dashboard;\n }\n LogError(`CreateBlankDashboard: ${dashboard.LatestResult?.CompleteMessage ?? 'unknown error'}`);\n return null;\n } catch (error) {\n LogError(`CreateBlankDashboard: ${errorMessage(error)}`);\n return null;\n }\n}\n\n/**\n * Automatic install path, for Home load. Installs the Dashboards app for a user who has no\n * UserApplication row for it, at most once per user (tracked by a UserInfoEngine setting), so a\n * user who removes the app keeps it removed. Never rejects.\n * @returns true when this call installed the app.\n */\nexport async function AutoInstallDashboardsApp(appManager: ApplicationManager): Promise<boolean> {\n try {\n await appManager.WhenReady();\n return await RunDashboardsAppAutoInstall(buildInstallOperations(appManager));\n } catch (error) {\n LogError(`AutoInstallDashboardsApp: ${errorMessage(error)}`);\n return false;\n }\n}\n\n/**\n * Explicit install path, for a user click that goes to the Dashboards app (for example Open\n * Dashboards on the Data Explorer banner). Installs the app when it is missing or removed. Never rejects.\n * @returns the app to pass to `NavigationService.SwitchToApp`, or undefined when no Active\n * Dashboards app exists, the user is not authorized for it, or the install failed or did not\n * finish within DASHBOARDS_APP_INSTALL_STEP_TIMEOUT_MS.\n */\nexport async function EnsureDashboardsApp(appManager: ApplicationManager): Promise<BaseApplication | undefined> {\n try {\n await appManager.WhenReady();\n if (!(await RunDashboardsAppExplicitInstall(buildInstallOperations(appManager)))) {\n return undefined;\n }\n const app = FindDashboardsApp(appManager);\n if (app) {\n return app;\n }\n await appManager.ReloadUserApplications();\n return FindDashboardsApp(appManager);\n } catch (error) {\n LogError(`EnsureDashboardsApp: ${errorMessage(error)}`);\n return undefined;\n }\n}\n\n/** Install operations over ApplicationManager and UserInfoEngine.Instance, the engine ApplicationManager reads and installs through. */\nfunction buildInstallOperations(appManager: ApplicationManager): DashboardsAppInstallOperations {\n const engine = UserInfoEngine.Instance;\n return {\n ReadState: () => readInstallState(appManager, engine),\n Install: () => installForUser(appManager),\n RecordAutoInstall: () => engine.SetSetting(DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY, 'true'),\n };\n}\n\nfunction readInstallState(appManager: ApplicationManager, engine: UserInfoEngine): DashboardsAppInstallState | null {\n if (engine.IsPermissionConstrained) {\n return null;\n }\n const app = findSystemDashboardsApp(appManager);\n return {\n AppExists: app != null,\n Access: app ? engine.CheckUserApplicationAccess(app.ID) : 'not_installed',\n AutoInstallRecorded: engine.GetSetting(DASHBOARDS_APP_AUTO_INSTALL_SETTING_KEY) === 'true',\n };\n}\n\n/** Installs or re-enables the app, then rebuilds the user's app list so navigation can find it. */\nasync function installForUser(appManager: ApplicationManager): Promise<boolean> {\n const app = findSystemDashboardsApp(appManager);\n if (!app || !(await appManager.InstallAppForUser(app.ID))) {\n return false;\n }\n await appManager.ReloadUserApplications();\n return true;\n}\n\n/** The Dashboards app among all Active applications, whether or not the user has it. */\nfunction findSystemDashboardsApp(appManager: ApplicationManager): BaseApplication | undefined {\n return appManager.GetAllSystemApps().find((a) => a.Name === DASHBOARDS_APP_NAME);\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-dashboards",
|
|
3
|
-
"version": "6.2.0-edge.
|
|
3
|
+
"version": "6.2.0-edge.4",
|
|
4
4
|
"description": "MemberJunction Dashboards",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -95,9 +95,10 @@
|
|
|
95
95
|
"devDependencies": {
|
|
96
96
|
"@angular/compiler": "21.2.22",
|
|
97
97
|
"@angular/compiler-cli": "21.2.22",
|
|
98
|
+
"@fortawesome/fontawesome-free": "6.7.2",
|
|
98
99
|
"@types/d3": "^7.4.0",
|
|
99
100
|
"sass": "^1.97.3",
|
|
100
|
-
"@memberjunction/ng-test-utils": "6.2.0-edge.
|
|
101
|
+
"@memberjunction/ng-test-utils": "6.2.0-edge.4"
|
|
101
102
|
},
|
|
102
103
|
"peerDependencies": {
|
|
103
104
|
"@angular/animations": "^21.2.22",
|
|
@@ -114,72 +115,72 @@
|
|
|
114
115
|
"@codemirror/merge": "^6.11.2",
|
|
115
116
|
"@codemirror/state": "^6.5.4",
|
|
116
117
|
"@codemirror/view": "^6.39.12",
|
|
117
|
-
"@memberjunction/actions-base": "6.2.0-edge.
|
|
118
|
-
"@memberjunction/ai-core-plus": "6.2.0-edge.
|
|
119
|
-
"@memberjunction/ai-engine-base": "6.2.0-edge.
|
|
120
|
-
"@memberjunction/api-keys-base": "6.2.0-edge.
|
|
121
|
-
"@memberjunction/core": "6.2.0-edge.
|
|
122
|
-
"@memberjunction/core-entities": "6.2.0-edge.
|
|
123
|
-
"@memberjunction/credentials": "6.2.0-edge.
|
|
124
|
-
"@memberjunction/export-engine": "6.2.0-edge.
|
|
125
|
-
"@memberjunction/global": "6.2.0-edge.
|
|
126
|
-
"@memberjunction/graphql-dataprovider": "6.2.0-edge.
|
|
127
|
-
"@memberjunction/integration-engine-base": "6.2.0-edge.
|
|
128
|
-
"@memberjunction/interactive-component-types": "6.2.0-edge.
|
|
129
|
-
"@memberjunction/lists-base": "6.2.0-edge.
|
|
130
|
-
"@memberjunction/ng-action-gallery": "6.2.0-edge.
|
|
131
|
-
"@memberjunction/ng-actions": "6.2.0-edge.
|
|
132
|
-
"@memberjunction/ng-agent-requests": "6.2.0-edge.
|
|
133
|
-
"@memberjunction/ng-agents": "6.2.0-edge.
|
|
134
|
-
"@memberjunction/ng-rubrics": "6.2.0-edge.
|
|
135
|
-
"@memberjunction/rubrics-base": "6.2.0-edge.
|
|
136
|
-
"@memberjunction/ng-ai-test-harness": "6.2.0-edge.
|
|
137
|
-
"@memberjunction/ng-archive-manager": "6.2.0-edge.
|
|
138
|
-
"@memberjunction/ng-artifacts": "6.2.0-edge.
|
|
139
|
-
"@memberjunction/ng-base-application": "6.2.0-edge.
|
|
140
|
-
"@memberjunction/ng-base-forms": "6.2.0-edge.
|
|
141
|
-
"@memberjunction/ng-base-types": "6.2.0-edge.
|
|
142
|
-
"@memberjunction/ng-clustering": "6.2.0-edge.
|
|
143
|
-
"@memberjunction/ng-code-editor": "6.2.0-edge.
|
|
144
|
-
"@memberjunction/ng-composer": "6.2.0-edge.
|
|
145
|
-
"@memberjunction/ng-container-directives": "6.2.0-edge.
|
|
146
|
-
"@memberjunction/ng-conversations": "6.2.0-edge.
|
|
147
|
-
"@memberjunction/ng-core-entity-forms": "6.2.0-edge.
|
|
148
|
-
"@memberjunction/ng-credentials": "6.2.0-edge.
|
|
149
|
-
"@memberjunction/ng-dashboard-viewer": "6.2.0-edge.
|
|
150
|
-
"@memberjunction/ng-entity-relationship-diagram": "6.2.0-edge.
|
|
151
|
-
"@memberjunction/ng-entity-viewer": "6.2.0-edge.
|
|
152
|
-
"@memberjunction/ng-explorer-settings": "6.2.0-edge.
|
|
153
|
-
"@memberjunction/ng-export-service": "6.2.0-edge.
|
|
154
|
-
"@memberjunction/ng-filter-builder": "6.2.0-edge.
|
|
155
|
-
"@memberjunction/ng-list-management": "6.2.0-edge.
|
|
156
|
-
"@memberjunction/ng-map-view": "6.2.0-edge.
|
|
157
|
-
"@memberjunction/ng-markdown": "6.2.0-edge.
|
|
158
|
-
"@memberjunction/ng-media-player": "6.2.0-edge.
|
|
159
|
-
"@memberjunction/ng-notifications": "6.2.0-edge.
|
|
160
|
-
"@memberjunction/ng-query-viewer": "6.2.0-edge.
|
|
161
|
-
"@memberjunction/ng-react": "6.2.0-edge.
|
|
162
|
-
"@memberjunction/ng-record-process-studio": "6.2.0-edge.
|
|
163
|
-
"@memberjunction/ng-resource-permissions": "6.2.0-edge.
|
|
164
|
-
"@memberjunction/ng-scheduling": "6.2.0-edge.
|
|
165
|
-
"@memberjunction/ng-search": "6.2.0-edge.
|
|
166
|
-
"@memberjunction/ng-shared": "6.2.0-edge.
|
|
167
|
-
"@memberjunction/ng-shared-generic": "6.2.0-edge.
|
|
168
|
-
"@memberjunction/ng-task-graph-editor": "6.2.0-edge.
|
|
169
|
-
"@memberjunction/ng-tabstrip": "6.2.0-edge.
|
|
170
|
-
"@memberjunction/ng-testing": "6.2.0-edge.
|
|
171
|
-
"@memberjunction/ng-trees": "6.2.0-edge.
|
|
172
|
-
"@memberjunction/ng-ui-components": "6.2.0-edge.
|
|
173
|
-
"@memberjunction/ng-user-routines": "6.2.0-edge.
|
|
174
|
-
"@memberjunction/ng-versions": "6.2.0-edge.
|
|
175
|
-
"@memberjunction/ng-word-cloud": "6.2.0-edge.
|
|
176
|
-
"@memberjunction/predictive-studio-core": "6.2.0-edge.
|
|
177
|
-
"@memberjunction/tag-engine-base": "6.2.0-edge.
|
|
178
|
-
"@memberjunction/templates-base-types": "6.2.0-edge.
|
|
179
|
-
"@memberjunction/testing-engine-base": "6.2.0-edge.
|
|
180
|
-
"@memberjunction/theme-engine": "6.2.0-edge.
|
|
181
|
-
"@memberjunction/work-queue-base": "6.2.0-edge.
|
|
182
|
-
"@memberjunction/work-queue-core": "6.2.0-edge.
|
|
118
|
+
"@memberjunction/actions-base": "6.2.0-edge.4",
|
|
119
|
+
"@memberjunction/ai-core-plus": "6.2.0-edge.4",
|
|
120
|
+
"@memberjunction/ai-engine-base": "6.2.0-edge.4",
|
|
121
|
+
"@memberjunction/api-keys-base": "6.2.0-edge.4",
|
|
122
|
+
"@memberjunction/core": "6.2.0-edge.4",
|
|
123
|
+
"@memberjunction/core-entities": "6.2.0-edge.4",
|
|
124
|
+
"@memberjunction/credentials": "6.2.0-edge.4",
|
|
125
|
+
"@memberjunction/export-engine": "6.2.0-edge.4",
|
|
126
|
+
"@memberjunction/global": "6.2.0-edge.4",
|
|
127
|
+
"@memberjunction/graphql-dataprovider": "6.2.0-edge.4",
|
|
128
|
+
"@memberjunction/integration-engine-base": "6.2.0-edge.4",
|
|
129
|
+
"@memberjunction/interactive-component-types": "6.2.0-edge.4",
|
|
130
|
+
"@memberjunction/lists-base": "6.2.0-edge.4",
|
|
131
|
+
"@memberjunction/ng-action-gallery": "6.2.0-edge.4",
|
|
132
|
+
"@memberjunction/ng-actions": "6.2.0-edge.4",
|
|
133
|
+
"@memberjunction/ng-agent-requests": "6.2.0-edge.4",
|
|
134
|
+
"@memberjunction/ng-agents": "6.2.0-edge.4",
|
|
135
|
+
"@memberjunction/ng-rubrics": "6.2.0-edge.4",
|
|
136
|
+
"@memberjunction/rubrics-base": "6.2.0-edge.4",
|
|
137
|
+
"@memberjunction/ng-ai-test-harness": "6.2.0-edge.4",
|
|
138
|
+
"@memberjunction/ng-archive-manager": "6.2.0-edge.4",
|
|
139
|
+
"@memberjunction/ng-artifacts": "6.2.0-edge.4",
|
|
140
|
+
"@memberjunction/ng-base-application": "6.2.0-edge.4",
|
|
141
|
+
"@memberjunction/ng-base-forms": "6.2.0-edge.4",
|
|
142
|
+
"@memberjunction/ng-base-types": "6.2.0-edge.4",
|
|
143
|
+
"@memberjunction/ng-clustering": "6.2.0-edge.4",
|
|
144
|
+
"@memberjunction/ng-code-editor": "6.2.0-edge.4",
|
|
145
|
+
"@memberjunction/ng-composer": "6.2.0-edge.4",
|
|
146
|
+
"@memberjunction/ng-container-directives": "6.2.0-edge.4",
|
|
147
|
+
"@memberjunction/ng-conversations": "6.2.0-edge.4",
|
|
148
|
+
"@memberjunction/ng-core-entity-forms": "6.2.0-edge.4",
|
|
149
|
+
"@memberjunction/ng-credentials": "6.2.0-edge.4",
|
|
150
|
+
"@memberjunction/ng-dashboard-viewer": "6.2.0-edge.4",
|
|
151
|
+
"@memberjunction/ng-entity-relationship-diagram": "6.2.0-edge.4",
|
|
152
|
+
"@memberjunction/ng-entity-viewer": "6.2.0-edge.4",
|
|
153
|
+
"@memberjunction/ng-explorer-settings": "6.2.0-edge.4",
|
|
154
|
+
"@memberjunction/ng-export-service": "6.2.0-edge.4",
|
|
155
|
+
"@memberjunction/ng-filter-builder": "6.2.0-edge.4",
|
|
156
|
+
"@memberjunction/ng-list-management": "6.2.0-edge.4",
|
|
157
|
+
"@memberjunction/ng-map-view": "6.2.0-edge.4",
|
|
158
|
+
"@memberjunction/ng-markdown": "6.2.0-edge.4",
|
|
159
|
+
"@memberjunction/ng-media-player": "6.2.0-edge.4",
|
|
160
|
+
"@memberjunction/ng-notifications": "6.2.0-edge.4",
|
|
161
|
+
"@memberjunction/ng-query-viewer": "6.2.0-edge.4",
|
|
162
|
+
"@memberjunction/ng-react": "6.2.0-edge.4",
|
|
163
|
+
"@memberjunction/ng-record-process-studio": "6.2.0-edge.4",
|
|
164
|
+
"@memberjunction/ng-resource-permissions": "6.2.0-edge.4",
|
|
165
|
+
"@memberjunction/ng-scheduling": "6.2.0-edge.4",
|
|
166
|
+
"@memberjunction/ng-search": "6.2.0-edge.4",
|
|
167
|
+
"@memberjunction/ng-shared": "6.2.0-edge.4",
|
|
168
|
+
"@memberjunction/ng-shared-generic": "6.2.0-edge.4",
|
|
169
|
+
"@memberjunction/ng-task-graph-editor": "6.2.0-edge.4",
|
|
170
|
+
"@memberjunction/ng-tabstrip": "6.2.0-edge.4",
|
|
171
|
+
"@memberjunction/ng-testing": "6.2.0-edge.4",
|
|
172
|
+
"@memberjunction/ng-trees": "6.2.0-edge.4",
|
|
173
|
+
"@memberjunction/ng-ui-components": "6.2.0-edge.4",
|
|
174
|
+
"@memberjunction/ng-user-routines": "6.2.0-edge.4",
|
|
175
|
+
"@memberjunction/ng-versions": "6.2.0-edge.4",
|
|
176
|
+
"@memberjunction/ng-word-cloud": "6.2.0-edge.4",
|
|
177
|
+
"@memberjunction/predictive-studio-core": "6.2.0-edge.4",
|
|
178
|
+
"@memberjunction/tag-engine-base": "6.2.0-edge.4",
|
|
179
|
+
"@memberjunction/templates-base-types": "6.2.0-edge.4",
|
|
180
|
+
"@memberjunction/testing-engine-base": "6.2.0-edge.4",
|
|
181
|
+
"@memberjunction/theme-engine": "6.2.0-edge.4",
|
|
182
|
+
"@memberjunction/work-queue-base": "6.2.0-edge.4",
|
|
183
|
+
"@memberjunction/work-queue-core": "6.2.0-edge.4",
|
|
183
184
|
"ag-grid-angular": "^35.0.1",
|
|
184
185
|
"ag-grid-community": "^35.0.1",
|
|
185
186
|
"angular-split": "^20.0.0",
|