@microsoft/sp-component-base 1.23.1 → 1.24.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/467dc675-7cc5-4709-8aac-78e3b71bd2f6.manifest.json +136 -141
- package/dist/{chunk.legacy-third-party-fabric-core-localfont_none_9e84ea19c68fdc8b9094.js → chunk.legacy-third-party-fabric-core-localfont_none_b7f7978a3e90166c361b.js} +1 -1
- package/dist/chunk.teams-apps-client_none_27d3c7c1d01080e4f131.js +2 -0
- package/dist/index-internal-beta.d.ts +30 -8
- package/dist/index-internal-public.d.ts +30 -8
- package/dist/index-internal.d.ts +30 -8
- package/dist/sp-component-base_default_8d535b51fa18aa47002b.js +22 -0
- package/dist/sp-component-base_en-us_8ce25dfb69a7786caece.js +22 -0
- package/dist/sp-component-base_qps-ploc_4fec831895d90df8aa7a.js +22 -0
- package/dist/sp-component-base_qps-ploca_b80610c8dff04dcec755.js +22 -0
- package/dist/tsdoc-metadata.json +1 -1
- package/lib-commonjs/BaseComponent.js +110 -145
- package/lib-commonjs/BaseComponentContext.js +126 -183
- package/lib-commonjs/DynamicDataProvider.js +251 -268
- package/lib-commonjs/DynamicDataSourceManager.js +218 -241
- package/lib-commonjs/DynamicProperty.js +232 -280
- package/lib-commonjs/EnsureIsolatedDomainUrl.js +14 -14
- package/lib-commonjs/IComponentPosition.js +8 -3
- package/lib-commonjs/IComponentPropertyMetadata.js +10 -3
- package/lib-commonjs/ISerializedServerProcessedData.js +24 -21
- package/lib-commonjs/LegacyThirdPartyFabricCoreLoader.js +53 -87
- package/lib-commonjs/PropertyMetadataProcessor.js +117 -150
- package/lib-commonjs/RenderableComponentContext.js +37 -0
- package/lib-commonjs/ShimmerFactory.js +66 -51
- package/lib-commonjs/chunks/legacy-third-party-fabric-core/FabricLocalFont.js +6 -4
- package/lib-commonjs/common/Flights.js +22 -10
- package/lib-commonjs/common/KillSwitches.js +13 -6
- package/lib-commonjs/dataCollector/IWebPartLoadData.js +35 -30
- package/lib-commonjs/dataCollector/WebPartLoadDataCollector.js +82 -91
- package/lib-commonjs/index.js +78 -38
- package/lib-commonjs/teams/DeferredTeamsAppsClient.js +30 -52
- package/lib-commonjs/teams/ITeamsAppCatalog.js +10 -3
- package/lib-commonjs/teams/TeamsAppsClient.js +189 -231
- package/lib-commonjs/test-api/MockComponent.js +38 -23
- package/lib-commonjs/test-api/MockComponentContext.js +21 -14
- package/lib-commonjs/test-api/index.js +21 -7
- package/lib-commonjs/themeProvider/ThemeProvider.js +68 -82
- package/lib-commonjs/themeProvider/themeInterfaces/IFontStyles.js +5 -2
- package/lib-commonjs/themeProvider/themeInterfaces/IPalette.js +10 -3
- package/lib-commonjs/themeProvider/themeInterfaces/ISemanticColors.js +59 -3
- package/lib-commonjs/themeProvider/themeInterfaces/ISemanticTextColors.js +10 -3
- package/lib-commonjs/themeProvider/themeInterfaces/ITheme.js +5 -2
- package/{lib → lib-dts}/BaseComponent.d.ts +8 -8
- package/{lib → lib-dts}/BaseComponentContext.d.ts +5 -5
- package/lib-dts/RenderableComponentContext.d.ts +35 -0
- package/{lib → lib-dts}/index.d.ts +1 -0
- package/lib-esm/BaseComponent.js +123 -0
- package/lib-esm/BaseComponentContext.js +157 -0
- package/lib-esm/DynamicDataProvider.js +401 -0
- package/lib-esm/DynamicDataSourceManager.js +358 -0
- package/lib-esm/DynamicProperty.js +344 -0
- package/{lib → lib-esm}/EnsureIsolatedDomainUrl.js +6 -6
- package/lib-esm/IComponentPosition.js +5 -0
- package/lib-esm/IComponentPropertyMetadata.js +7 -0
- package/lib-esm/ISerializedServerProcessedData.js +24 -0
- package/lib-esm/LegacyThirdPartyFabricCoreLoader.js +76 -0
- package/{lib → lib-esm}/PropertyMetadataProcessor.js +92 -127
- package/lib-esm/RenderableComponentContext.js +26 -0
- package/lib-esm/ShimmerFactory.js +74 -0
- package/{lib → lib-esm}/chunks/legacy-third-party-fabric-core/FabricLocalFont.js +3 -3
- package/{lib → lib-esm}/common/Flights.js +4 -3
- package/{lib → lib-esm}/common/KillSwitches.js +3 -2
- package/lib-esm/dataCollector/IWebPartLoadData.js +33 -0
- package/lib-esm/dataCollector/WebPartLoadDataCollector.js +125 -0
- package/{lib → lib-esm}/index.js +4 -3
- package/lib-esm/teams/DeferredTeamsAppsClient.js +32 -0
- package/lib-esm/teams/ITeamsAppCatalog.js +9 -0
- package/lib-esm/teams/TeamsAppsClient.js +395 -0
- package/lib-esm/test-api/MockComponent.js +38 -0
- package/{lib → lib-esm}/test-api/MockComponentContext.js +10 -11
- package/{lib → lib-esm}/test-api/index.js +2 -1
- package/lib-esm/themeProvider/ThemeProvider.js +79 -0
- package/lib-esm/themeProvider/themeInterfaces/IFontStyles.js +7 -0
- package/lib-esm/themeProvider/themeInterfaces/IPalette.js +7 -0
- package/lib-esm/themeProvider/themeInterfaces/ISemanticColors.js +56 -0
- package/lib-esm/themeProvider/themeInterfaces/ISemanticTextColors.js +7 -0
- package/lib-esm/themeProvider/themeInterfaces/ITheme.js +7 -0
- package/package.json +41 -14
- package/dist/chunk.teams-apps-client_none_f9872389cb6ea9ad28e2.js +0 -2
- package/dist/sp-component-base_default_5ba07be39b0dc8968f7b.js +0 -2
- package/dist/sp-component-base_en-us_eb9bebb3acce0ae83f1c.js +0 -2
- package/dist/sp-component-base_qps-ploc_45f37623d87c3d848f2a.js +0 -2
- package/dist/sp-component-base_qps-ploca_b3f3b7bf97c4185b0fd6.js +0 -2
- package/lib/BaseComponent.d.ts.map +0 -1
- package/lib/BaseComponent.js +0 -161
- package/lib/BaseComponentContext.d.ts.map +0 -1
- package/lib/BaseComponentContext.js +0 -222
- package/lib/DynamicDataProvider.d.ts.map +0 -1
- package/lib/DynamicDataProvider.js +0 -420
- package/lib/DynamicDataSourceManager.d.ts.map +0 -1
- package/lib/DynamicDataSourceManager.js +0 -382
- package/lib/DynamicProperty.d.ts.map +0 -1
- package/lib/DynamicProperty.js +0 -390
- package/lib/EnsureIsolatedDomainUrl.d.ts.map +0 -1
- package/lib/IComponentPosition.d.ts.map +0 -1
- package/lib/IComponentPosition.js +0 -2
- package/lib/IComponentPropertyMetadata.d.ts.map +0 -1
- package/lib/IComponentPropertyMetadata.js +0 -2
- package/lib/ISerializedServerProcessedData.d.ts.map +0 -1
- package/lib/ISerializedServerProcessedData.js +0 -28
- package/lib/LegacyThirdPartyFabricCoreLoader.d.ts.map +0 -1
- package/lib/LegacyThirdPartyFabricCoreLoader.js +0 -90
- package/lib/PropertyMetadataProcessor.d.ts.map +0 -1
- package/lib/ShimmerFactory.d.ts.map +0 -1
- package/lib/ShimmerFactory.js +0 -62
- package/lib/chunks/legacy-third-party-fabric-core/FabricLocalFont.d.ts.map +0 -1
- package/lib/common/Flights.d.ts.map +0 -1
- package/lib/common/KillSwitches.d.ts.map +0 -1
- package/lib/dataCollector/IWebPartLoadData.d.ts.map +0 -1
- package/lib/dataCollector/IWebPartLoadData.js +0 -40
- package/lib/dataCollector/WebPartLoadDataCollector.d.ts.map +0 -1
- package/lib/dataCollector/WebPartLoadDataCollector.js +0 -137
- package/lib/index.d.ts.map +0 -1
- package/lib/teams/DeferredTeamsAppsClient.d.ts.map +0 -1
- package/lib/teams/DeferredTeamsAppsClient.js +0 -39
- package/lib/teams/ITeamsAppCatalog.d.ts.map +0 -1
- package/lib/teams/ITeamsAppCatalog.js +0 -2
- package/lib/teams/TeamsAppsClient.d.ts.map +0 -1
- package/lib/teams/TeamsAppsClient.js +0 -440
- package/lib/test-api/MockComponent.d.ts.map +0 -1
- package/lib/test-api/MockComponent.js +0 -31
- package/lib/test-api/MockComponentContext.d.ts.map +0 -1
- package/lib/test-api/index.d.ts.map +0 -1
- package/lib/themeProvider/ThemeProvider.d.ts.map +0 -1
- package/lib/themeProvider/ThemeProvider.js +0 -99
- package/lib/themeProvider/themeInterfaces/IFontStyles.d.ts.map +0 -1
- package/lib/themeProvider/themeInterfaces/IFontStyles.js +0 -2
- package/lib/themeProvider/themeInterfaces/IPalette.d.ts.map +0 -1
- package/lib/themeProvider/themeInterfaces/IPalette.js +0 -2
- package/lib/themeProvider/themeInterfaces/ISemanticColors.d.ts.map +0 -1
- package/lib/themeProvider/themeInterfaces/ISemanticColors.js +0 -2
- package/lib/themeProvider/themeInterfaces/ISemanticTextColors.d.ts.map +0 -1
- package/lib/themeProvider/themeInterfaces/ISemanticTextColors.js +0 -2
- package/lib/themeProvider/themeInterfaces/ITheme.d.ts.map +0 -1
- package/lib/themeProvider/themeInterfaces/ITheme.js +0 -2
- /package/{lib → lib-dts}/DynamicDataProvider.d.ts +0 -0
- /package/{lib → lib-dts}/DynamicDataSourceManager.d.ts +0 -0
- /package/{lib → lib-dts}/DynamicProperty.d.ts +0 -0
- /package/{lib → lib-dts}/EnsureIsolatedDomainUrl.d.ts +0 -0
- /package/{lib → lib-dts}/IComponentPosition.d.ts +0 -0
- /package/{lib → lib-dts}/IComponentPropertyMetadata.d.ts +0 -0
- /package/{lib → lib-dts}/ISerializedServerProcessedData.d.ts +0 -0
- /package/{lib → lib-dts}/LegacyThirdPartyFabricCoreLoader.d.ts +0 -0
- /package/{lib → lib-dts}/PropertyMetadataProcessor.d.ts +0 -0
- /package/{lib → lib-dts}/ShimmerFactory.d.ts +0 -0
- /package/{lib → lib-dts}/chunks/legacy-third-party-fabric-core/FabricLocalFont.d.ts +0 -0
- /package/{lib → lib-dts}/common/Flights.d.ts +0 -0
- /package/{lib → lib-dts}/common/KillSwitches.d.ts +0 -0
- /package/{lib → lib-dts}/dataCollector/IWebPartLoadData.d.ts +0 -0
- /package/{lib → lib-dts}/dataCollector/WebPartLoadDataCollector.d.ts +0 -0
- /package/{lib → lib-dts}/loc/Strings.resx.d.ts +0 -0
- /package/{lib → lib-dts}/teams/DeferredTeamsAppsClient.d.ts +0 -0
- /package/{lib → lib-dts}/teams/ITeamsAppCatalog.d.ts +0 -0
- /package/{lib → lib-dts}/teams/TeamsAppsClient.d.ts +0 -0
- /package/{lib → lib-dts}/test-api/MockComponent.d.ts +0 -0
- /package/{lib → lib-dts}/test-api/MockComponentContext.d.ts +0 -0
- /package/{lib → lib-dts}/test-api/index.d.ts +0 -0
- /package/{lib → lib-dts}/themeProvider/ThemeProvider.d.ts +0 -0
- /package/{lib → lib-dts}/themeProvider/themeInterfaces/IFontStyles.d.ts +0 -0
- /package/{lib → lib-dts}/themeProvider/themeInterfaces/IPalette.d.ts +0 -0
- /package/{lib → lib-dts}/themeProvider/themeInterfaces/ISemanticColors.d.ts +0 -0
- /package/{lib → lib-dts}/themeProvider/themeInterfaces/ISemanticTextColors.d.ts +0 -0
- /package/{lib → lib-dts}/themeProvider/themeInterfaces/ITheme.d.ts +0 -0
- /package/{lib → lib-esm}/chunks/legacy-third-party-fabric-core/fabric-core-sass/Fabric.LocalFont.global.scss.css +0 -0
- /package/{lib → lib-esm}/chunks/legacy-third-party-fabric-core/fabric-core-sass/Fabric.LocalFontKillSwitchActivated.scss.css +0 -0
- /package/{lib → lib-esm}/chunks/legacy-third-party-fabric-core/fabric-core-shim.global.scss.css +0 -0
- /package/{lib → lib-esm}/chunks/legacy-third-party-fabric-core/fabric-core-shimKillSwitchActivated.scss.css +0 -0
- /package/{lib → lib-esm}/chunks/legacy-third-party-fabric-core/iconDefinitions.css +0 -0
- /package/{lib → lib-esm}/loc/Strings.resx.json +0 -0
- /package/{lib → lib-esm}/sp-component-base.manifest.json +0 -0
- /package/{lib → lib-esm}/styles/shimmer.module.scss.css +0 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
// This file contains code for the WebPartLoadDataCollector. This class will collect webpart data on load
|
|
3
|
+
// and upload it for monitoring purposes.
|
|
4
|
+
import { _PerformanceLogger, _PerformanceDataDimensions } from '@msinternal/sp-telemetry';
|
|
5
|
+
import { _CacheMissReason as CacheMissReason, CacheStatus } from './IWebPartLoadData';
|
|
6
|
+
import { _BrowserUtilities } from '@microsoft/sp-core-library';
|
|
7
|
+
const NOT_AVAILABLE = 'N/A';
|
|
8
|
+
/**
|
|
9
|
+
* This is used internally to collect web part and adaptive card extension's module load, init, and render performances.
|
|
10
|
+
* This file moved from sp-webpart-base to not additional dependency to sp-adaptive-card-extension-base.
|
|
11
|
+
* @internal
|
|
12
|
+
*/ export class WebPartLoadDataCollector {
|
|
13
|
+
static collect(manifest, webPartTag, pageContext) {
|
|
14
|
+
const getTime = (key)=>{
|
|
15
|
+
return _PerformanceLogger.readComponentBreakdown(webPartTag, key) || _PerformanceLogger.readTempData(`${webPartTag}.${key}`);
|
|
16
|
+
};
|
|
17
|
+
const start = getTime('start');
|
|
18
|
+
const moduleLoaded = getTime('modulesLoaded');
|
|
19
|
+
const initialized = getTime('init');
|
|
20
|
+
const end = getTime('end');
|
|
21
|
+
const isSpinnyShown = !!getTime('displaySpinner');
|
|
22
|
+
const isMultiGeo = Boolean(pageContext && pageContext.legacyPageContext && pageContext.legacyPageContext.isMultiGeoTenant);
|
|
23
|
+
let dataProvider = NOT_AVAILABLE;
|
|
24
|
+
let layoutID = NOT_AVAILABLE;
|
|
25
|
+
let webPartCacheHit = CacheStatus.NotAvailable;
|
|
26
|
+
let cacheMissReason = CacheMissReason.NotApplicable;
|
|
27
|
+
// Collect data for first-party web parts only. This ideally should be done outside of spfx.
|
|
28
|
+
// VSO#855246 Refactor WebPartLoadDataCollector to move out first-party only logging logic.
|
|
29
|
+
if (manifest.isInternal) {
|
|
30
|
+
const cacheHit = getTime('CacheHit');
|
|
31
|
+
const cacheMiss = getTime('CacheMiss');
|
|
32
|
+
const prefetechedData = getTime('prefetchedData');
|
|
33
|
+
const isCacheApplicable = Boolean(cacheHit || cacheMiss);
|
|
34
|
+
webPartCacheHit = isCacheApplicable ? cacheHit ? CacheStatus.True : CacheStatus.False : CacheStatus.NotAvailable;
|
|
35
|
+
cacheMissReason = WebPartLoadDataCollector._getCacheMissReason(cacheHit, getTime);
|
|
36
|
+
let dataProviderTime = _PerformanceLogger.now();
|
|
37
|
+
const layoutKey = _PerformanceDataDimensions.Layout;
|
|
38
|
+
const dataProviderKey = _PerformanceDataDimensions.DataProvider;
|
|
39
|
+
const perfBreakDown = _PerformanceLogger.readFullEUPLBreakDown();
|
|
40
|
+
// WebParts which have different layouts and dataproviders, will have perf marks such as
|
|
41
|
+
// webPartTag.dataProvider: [dataProviderName]
|
|
42
|
+
// webPartTag.Layout: [Layout]
|
|
43
|
+
// The logic below will extract the data provider and layout, and log them for perf measurements.
|
|
44
|
+
Object.keys(perfBreakDown).forEach((key)=>{
|
|
45
|
+
if (key.indexOf(webPartTag) > -1) {
|
|
46
|
+
// We only have 1 layout
|
|
47
|
+
if (layoutID === NOT_AVAILABLE && key.indexOf(layoutKey) > -1) {
|
|
48
|
+
layoutID = key.split(layoutKey)[1];
|
|
49
|
+
// Focus on primary data provider
|
|
50
|
+
} else if (key.indexOf(dataProviderKey) > -1) {
|
|
51
|
+
// Pick earliest data provider, in case there are multiple
|
|
52
|
+
if (dataProvider === NOT_AVAILABLE || perfBreakDown[key] < dataProviderTime) {
|
|
53
|
+
dataProvider = key.split(dataProviderKey)[1];
|
|
54
|
+
dataProviderTime = perfBreakDown[key];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
dataProvider = prefetechedData ? 'Prefetch' : dataProvider;
|
|
60
|
+
}
|
|
61
|
+
const webpartPerfFlights = _PerformanceLogger.getWebpartFlightsAndExperiments(webPartTag);
|
|
62
|
+
const syncRenderTime = this._getSyncRenderTime(layoutID, getTime);
|
|
63
|
+
const retVal = {
|
|
64
|
+
alias: manifest.alias,
|
|
65
|
+
isMultiGeo: isMultiGeo,
|
|
66
|
+
isInternal: manifest.isInternal,
|
|
67
|
+
isSpinnyShown: isSpinnyShown,
|
|
68
|
+
manifestId: manifest.id,
|
|
69
|
+
moduleLoadTime: Math.floor(moduleLoaded - start),
|
|
70
|
+
initTime: Math.floor(initialized - moduleLoaded),
|
|
71
|
+
renderTime: Math.floor(end - initialized),
|
|
72
|
+
syncRenderTime,
|
|
73
|
+
scenarioId: _PerformanceLogger.getScenarioId(),
|
|
74
|
+
isFullPage: _PerformanceLogger.fullPageLoad,
|
|
75
|
+
dataProvider,
|
|
76
|
+
layout: layoutID,
|
|
77
|
+
mySiteCacheHit: webPartCacheHit,
|
|
78
|
+
cacheMissReason,
|
|
79
|
+
flights: webpartPerfFlights,
|
|
80
|
+
storeAppId: manifest.storeAppId,
|
|
81
|
+
mpnId: manifest.mpnId,
|
|
82
|
+
componentDeveloperName: manifest.componentDeveloperName
|
|
83
|
+
};
|
|
84
|
+
retVal.teamsHosted = _BrowserUtilities.isTeamsHosted();
|
|
85
|
+
return retVal;
|
|
86
|
+
}
|
|
87
|
+
static _getSyncRenderTime(layoutID, getTime) {
|
|
88
|
+
let syncRenderTime = undefined;
|
|
89
|
+
syncRenderTime = Math.floor(getTime('syncRender') - getTime('getDataComplete'));
|
|
90
|
+
const postRenderCompleteTime = getTime('postRenderComplete');
|
|
91
|
+
const loadLayoutEnd = getTime('loadLayoutEnd');
|
|
92
|
+
const syncLayoutRenderComplete = getTime('syncLayoutRenderComplete');
|
|
93
|
+
if (loadLayoutEnd && syncLayoutRenderComplete) {
|
|
94
|
+
// render layout and items inside it
|
|
95
|
+
syncRenderTime = Math.floor(syncRenderTime + (syncLayoutRenderComplete - loadLayoutEnd));
|
|
96
|
+
}
|
|
97
|
+
if (postRenderCompleteTime) {
|
|
98
|
+
syncRenderTime = Math.floor(// transposeRow + transposeItems + render + syncPostRender
|
|
99
|
+
syncRenderTime + (postRenderCompleteTime - getTime(_PerformanceDataDimensions.Layout + layoutID)));
|
|
100
|
+
}
|
|
101
|
+
return syncRenderTime;
|
|
102
|
+
}
|
|
103
|
+
static _getCacheMissReason(cacheHit, getTime) {
|
|
104
|
+
if (cacheHit) {
|
|
105
|
+
return CacheMissReason.NotApplicable;
|
|
106
|
+
}
|
|
107
|
+
const mySiteCacheMissOnConfgMismatch = !!getTime('CacheMissConfigMismatch');
|
|
108
|
+
const mySiteCacheMissOnLateFlush = !!getTime('LateFlush');
|
|
109
|
+
const cachedWebPartNotFound = !!getTime('CachedWebPartNotFound');
|
|
110
|
+
const cacheExpired = !!getTime('CacheExpired');
|
|
111
|
+
let cacheMissReason = CacheMissReason.NotSpecified;
|
|
112
|
+
if (mySiteCacheMissOnConfgMismatch) {
|
|
113
|
+
cacheMissReason = CacheMissReason.CacheConfigMissmatch;
|
|
114
|
+
} else if (mySiteCacheMissOnLateFlush) {
|
|
115
|
+
cacheMissReason = CacheMissReason.LateFlush;
|
|
116
|
+
} else if (cachedWebPartNotFound) {
|
|
117
|
+
cacheMissReason = CacheMissReason.CachedItemNotFound;
|
|
118
|
+
} else if (cacheExpired) {
|
|
119
|
+
cacheMissReason = CacheMissReason.CacheExpired;
|
|
120
|
+
}
|
|
121
|
+
return cacheMissReason;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=./WebPartLoadDataCollector.js.map
|
package/{lib → lib-esm}/index.js
RENAMED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* common across all client-side component types.
|
|
9
9
|
*
|
|
10
10
|
* @packagedocumentation
|
|
11
|
-
*/
|
|
12
|
-
export { default as BaseComponent } from './BaseComponent';
|
|
11
|
+
*/ export { default as BaseComponent } from './BaseComponent';
|
|
13
12
|
export { default as BaseComponentContext } from './BaseComponentContext';
|
|
13
|
+
export { default as RenderableComponentContext } from './RenderableComponentContext';
|
|
14
14
|
export { default as DynamicDataProvider } from './DynamicDataProvider';
|
|
15
15
|
export { default as DynamicDataSourceManager } from './DynamicDataSourceManager';
|
|
16
16
|
export { default as DynamicProperty } from './DynamicProperty';
|
|
@@ -24,4 +24,5 @@ export { ensureIsolatedDomainUrl as _ensureIsolatedDomainUrl } from './EnsureIso
|
|
|
24
24
|
export { WebPartLoadDataCollector as _WebPartLoadDataCollector } from './dataCollector/WebPartLoadDataCollector';
|
|
25
25
|
export { _CacheMissReason } from './dataCollector/IWebPartLoadData';
|
|
26
26
|
export { DeferredTeamsAppsClient as _DeferredTeamsAppsClient } from './teams/DeferredTeamsAppsClient';
|
|
27
|
-
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=./index.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ServiceKey } from '@microsoft/sp-core-library';
|
|
2
|
+
import { _QosMonitor } from '@microsoft/sp-diagnostics';
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/ export class DeferredTeamsAppsClient {
|
|
6
|
+
getClient() {
|
|
7
|
+
if (this._teamsAppsClient) {
|
|
8
|
+
return Promise.resolve(this._teamsAppsClient);
|
|
9
|
+
}
|
|
10
|
+
if (!this._teamsAppsClientPromise) {
|
|
11
|
+
const loadMonitor = new _QosMonitor('DeferredTeamsAppsClient.LoadTeamsAppClient');
|
|
12
|
+
this._teamsAppsClientPromise = import(/* webpackChunkName: 'teams-apps-client' */ './TeamsAppsClient')// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
13
|
+
.then(({ TeamsAppsClient })=>{
|
|
14
|
+
this._teamsAppsClient = new TeamsAppsClient(this._serviceScope);
|
|
15
|
+
loadMonitor.writeSuccess();
|
|
16
|
+
return this._teamsAppsClient;
|
|
17
|
+
}).catch((error)=>{
|
|
18
|
+
loadMonitor.writeUnexpectedFailure(undefined, error);
|
|
19
|
+
throw error;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return this._teamsAppsClientPromise;
|
|
23
|
+
}
|
|
24
|
+
constructor(serviceScope){
|
|
25
|
+
this._serviceScope = serviceScope;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The service key for DeferredTeamsAppsClient.
|
|
30
|
+
*/ DeferredTeamsAppsClient.serviceKey = ServiceKey.create('sp-teams-apps-client', DeferredTeamsAppsClient);
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=./DeferredTeamsAppsClient.js.map
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import { _QosMonitor } from '@microsoft/sp-diagnostics';
|
|
2
|
+
import { MSGraphClientFactory, SPHttpClient } from '@microsoft/sp-http';
|
|
3
|
+
import { PageContext } from '@microsoft/sp-page-context';
|
|
4
|
+
import { isBotAcesFromTeamsEnabled } from '../common/Flights';
|
|
5
|
+
import { uniq } from '@microsoft/sp-lodash-subset';
|
|
6
|
+
// base teams apps endpoint
|
|
7
|
+
const MS_GRAPH_TEAMS_APPS_ENDPOINT = '/appCatalogs/teamsApps';
|
|
8
|
+
// QSP to fetch all teams apps with dashboard cards
|
|
9
|
+
const MS_GRAPH_FETCH_TEAMS_APPS_QSP = `$expand=appDefinitions($expand=outlineIcon,colorIcon,dashboardCards)&$filter=appDefinitions/any(a:a/dashboardCards/$count ne 0)`;
|
|
10
|
+
// QSP to check permissions for the list of app ids
|
|
11
|
+
const MS_GRAPH_CHECK_PERMISSIONS_QSP = `$expand=appDefinitions($expand=dashboardCards)&$filter=appDefinitions/any(a:a/dashboardCards/$count ne 0) and id in ('{appIds}')`;
|
|
12
|
+
const MS_GRAPH_API_VERSION = 'beta';
|
|
13
|
+
// the number of app ids we can process without batching the request to avoid the URL length limit
|
|
14
|
+
const MAX_IDS_WITHOUT_BATCHING = 30;
|
|
15
|
+
const MAX_REQUESTS_PER_BATCH = 10;
|
|
16
|
+
const MANIFEST_VERSION = 2;
|
|
17
|
+
const ADVANCED_TOOLBOX_GROUP_ID = '5c03119e-3074-46fd-976b-c60198311f70';
|
|
18
|
+
/**
|
|
19
|
+
* The client for the Teams Apps sync.
|
|
20
|
+
*
|
|
21
|
+
* @internal
|
|
22
|
+
*/ export class TeamsAppsClient {
|
|
23
|
+
/**
|
|
24
|
+
* Gets the list of Teams App components from Teams App Catalog.
|
|
25
|
+
* @returns Promise that resolves to the list of Teams App components.
|
|
26
|
+
*/ getTeamsAppComponentManifests() {
|
|
27
|
+
if (!TeamsAppsClient._getTeamsAppComponentManifestsPromise) {
|
|
28
|
+
if (!isBotAcesFromTeamsEnabled()) {
|
|
29
|
+
TeamsAppsClient._getTeamsAppComponentManifestsPromise = Promise.resolve([]);
|
|
30
|
+
} else {
|
|
31
|
+
const monitor = new _QosMonitor('TeamsAppsClient.FetchTeamsApp');
|
|
32
|
+
TeamsAppsClient._getTeamsAppComponentManifestsPromise = this._msGraphClient.then((client)=>{
|
|
33
|
+
return client.api(`${MS_GRAPH_TEAMS_APPS_ENDPOINT}?${MS_GRAPH_FETCH_TEAMS_APPS_QSP}`).version(MS_GRAPH_API_VERSION).get();
|
|
34
|
+
}).then((response)=>{
|
|
35
|
+
const manifestsPromises = response.value.map((item)=>{
|
|
36
|
+
return this._teamsAppCatalogItemToAceManifests(item);
|
|
37
|
+
});
|
|
38
|
+
return Promise.all(manifestsPromises).then((manifests)=>{
|
|
39
|
+
const flatManifests = [];
|
|
40
|
+
manifests.forEach((item)=>{
|
|
41
|
+
flatManifests.push(...item);
|
|
42
|
+
});
|
|
43
|
+
monitor.writeSuccess();
|
|
44
|
+
return flatManifests;
|
|
45
|
+
});
|
|
46
|
+
}).catch((error)=>{
|
|
47
|
+
monitor.writeUnexpectedFailure(undefined, error);
|
|
48
|
+
// removing reference to the promise to allow retry
|
|
49
|
+
TeamsAppsClient._getTeamsAppComponentManifestsPromise = undefined;
|
|
50
|
+
return [];
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return TeamsAppsClient._getTeamsAppComponentManifestsPromise;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Syncs the Teams App component into SharePoint App Catalog.
|
|
58
|
+
*/ syncComponent(teamsAppComponentManifest) {
|
|
59
|
+
const manifest = teamsAppComponentManifest;
|
|
60
|
+
if (!isBotAcesFromTeamsEnabled() || !manifest.isPendingTeamsAppSync) {
|
|
61
|
+
return Promise.resolve(teamsAppComponentManifest);
|
|
62
|
+
}
|
|
63
|
+
const monitor = new _QosMonitor('TeamsAppsClient.SyncComponent');
|
|
64
|
+
if (!teamsAppComponentManifest.properties?.teamsAppComponent) {
|
|
65
|
+
monitor.writeExpectedFailure('TeamsAppComponentMissing');
|
|
66
|
+
return new Promise(()=>{
|
|
67
|
+
throw new Error('Teams App component manifest is missing teamsAppComponent property');
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const spHttpClient = this._serviceScope.consume(SPHttpClient.serviceKey);
|
|
71
|
+
const pageContext = this._serviceScope.consume(PageContext.serviceKey);
|
|
72
|
+
const baseRequestUrl = pageContext.web.absoluteUrl;
|
|
73
|
+
let monitorFailureTagNameSuffix = undefined;
|
|
74
|
+
let ensureAppCatalogPromise = TeamsAppsClient._ensureAppCatalogPromise;
|
|
75
|
+
if (!TeamsAppsClient._ensureAppCatalogPromise) {
|
|
76
|
+
// first step is to ensure app catalog
|
|
77
|
+
const ensureAppCatalogRequestUrl = `${baseRequestUrl}/_api/web/EnsureTenantAppCatalog(callerId='TeamsAppsClient')`;
|
|
78
|
+
ensureAppCatalogPromise = TeamsAppsClient._ensureAppCatalogPromise = spHttpClient.post(ensureAppCatalogRequestUrl, SPHttpClient.configurations.v1, {}).then((response)=>{
|
|
79
|
+
return response.json();
|
|
80
|
+
}).then((response)=>{
|
|
81
|
+
if (response.error) {
|
|
82
|
+
throw new Error(response.error.message);
|
|
83
|
+
}
|
|
84
|
+
}).catch((error)=>{
|
|
85
|
+
// app catalog error
|
|
86
|
+
monitorFailureTagNameSuffix = 'EnsureAppCatalogFailed';
|
|
87
|
+
// we want to retry if needed
|
|
88
|
+
TeamsAppsClient._ensureAppCatalogPromise = undefined;
|
|
89
|
+
throw error;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return ensureAppCatalogPromise.then(()=>{
|
|
93
|
+
const syncRequestUrl = `${baseRequestUrl}/_api/web/SyncTeamsComponent`;
|
|
94
|
+
const teamsAppComponent = teamsAppComponentManifest.properties.teamsAppComponent;
|
|
95
|
+
return spHttpClient.post(syncRequestUrl, SPHttpClient.configurations.v1, {
|
|
96
|
+
body: JSON.stringify({
|
|
97
|
+
teamsComponent: teamsAppComponent
|
|
98
|
+
})
|
|
99
|
+
}).catch((error)=>{
|
|
100
|
+
// sync error
|
|
101
|
+
monitorFailureTagNameSuffix = 'SyncComponentFailed';
|
|
102
|
+
throw error;
|
|
103
|
+
});
|
|
104
|
+
}).then((response)=>{
|
|
105
|
+
return response.json();
|
|
106
|
+
}).then((syncedManifest)=>{
|
|
107
|
+
if (syncedManifest.error) {
|
|
108
|
+
monitorFailureTagNameSuffix = 'SyncComponentFailed';
|
|
109
|
+
throw new Error(syncedManifest.error.message);
|
|
110
|
+
}
|
|
111
|
+
const manifestResponse = syncedManifest;
|
|
112
|
+
const parsedManifest = JSON.parse(manifestResponse.Manifest);
|
|
113
|
+
if (manifestResponse.ManifestActivatedTime) {
|
|
114
|
+
parsedManifest.manifestActivatedTime = manifestResponse.ManifestActivatedTime;
|
|
115
|
+
}
|
|
116
|
+
monitor.writeSuccess();
|
|
117
|
+
const { appId } = teamsAppComponentManifest.properties.teamsAppComponent;
|
|
118
|
+
// we know for sure the component is allowed
|
|
119
|
+
this._appComponentsPermissionsPromises.set(appId, Promise.resolve(new Set([
|
|
120
|
+
appId
|
|
121
|
+
])));
|
|
122
|
+
return parsedManifest;
|
|
123
|
+
}).catch((error)=>{
|
|
124
|
+
monitor.writeUnexpectedFailure(monitorFailureTagNameSuffix, error);
|
|
125
|
+
throw error;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Requests permissions for the Teams App components (apps) for the current user.
|
|
130
|
+
*/ requestPermissions(teamsAppComponentIds) {
|
|
131
|
+
if (!isBotAcesFromTeamsEnabled() || !teamsAppComponentIds.length) {
|
|
132
|
+
return Promise.resolve();
|
|
133
|
+
}
|
|
134
|
+
return this._requestAppsPermissions(teamsAppComponentIds).then(()=>{});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Checks if the component is enabled for the current user based on requested Teams permissions.
|
|
138
|
+
*/ isComponentEnabled(teamsAppId) {
|
|
139
|
+
if (!isBotAcesFromTeamsEnabled()) {
|
|
140
|
+
return Promise.resolve(true);
|
|
141
|
+
}
|
|
142
|
+
if (this._appComponentsPermissionsPromises.has(teamsAppId)) {
|
|
143
|
+
return this._appComponentsPermissionsPromises.get(teamsAppId).then((allowedApps)=>{
|
|
144
|
+
return allowedApps.has(teamsAppId) || false;
|
|
145
|
+
});
|
|
146
|
+
} else {
|
|
147
|
+
return this._requestAppsPermissions([
|
|
148
|
+
{
|
|
149
|
+
appId: teamsAppId,
|
|
150
|
+
componentId: ''
|
|
151
|
+
}
|
|
152
|
+
]).then((allowedComponents)=>{
|
|
153
|
+
return allowedComponents.has(teamsAppId) || false;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
_requestAppsPermissions(teamsAppComponentIds) {
|
|
158
|
+
// getting app ids for which we don't have a promise yet
|
|
159
|
+
const uniqueAppIds = uniq(teamsAppComponentIds.map((item)=>item.appId)).filter((appId)=>!this._appComponentsPermissionsPromises.has(appId));
|
|
160
|
+
let requestPermissionsPromise;
|
|
161
|
+
if (uniqueAppIds.length > MAX_IDS_WITHOUT_BATCHING) {
|
|
162
|
+
requestPermissionsPromise = this._requestAppsPermissionsBatched(uniqueAppIds);
|
|
163
|
+
}
|
|
164
|
+
if (!requestPermissionsPromise) {
|
|
165
|
+
const monitor = new _QosMonitor('TeamsAppsClient.RequestAppsPermissions');
|
|
166
|
+
requestPermissionsPromise = this._msGraphClient.then((client)=>{
|
|
167
|
+
return client.api(this._getCheckPermissionsUrl(uniqueAppIds)).version(MS_GRAPH_API_VERSION).get();
|
|
168
|
+
}).then((response)=>{
|
|
169
|
+
if (response.error) {
|
|
170
|
+
monitor.writeUnexpectedFailure('RequestFailed', new Error(response.error.message));
|
|
171
|
+
return new Set();
|
|
172
|
+
}
|
|
173
|
+
const allowedApps = new Set();
|
|
174
|
+
response.value.map((item)=>{
|
|
175
|
+
allowedApps.add(item.id);
|
|
176
|
+
});
|
|
177
|
+
monitor.writeSuccess();
|
|
178
|
+
return allowedApps;
|
|
179
|
+
}).catch((error)=>{
|
|
180
|
+
monitor.writeUnexpectedFailure(undefined, error);
|
|
181
|
+
return new Set();
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
// store the promise to avoid multiple requests to the API for the same teamsAppId
|
|
185
|
+
uniqueAppIds.forEach((teamsAppId)=>{
|
|
186
|
+
this._appComponentsPermissionsPromises.set(teamsAppId, requestPermissionsPromise);
|
|
187
|
+
});
|
|
188
|
+
return requestPermissionsPromise;
|
|
189
|
+
}
|
|
190
|
+
_requestAppsPermissionsBatched(appIds) {
|
|
191
|
+
const monitor = new _QosMonitor('TeamsAppsClient.RequestAppsPermissionsBatched');
|
|
192
|
+
const allowedApps = new Set();
|
|
193
|
+
//
|
|
194
|
+
// MS Graph batch body is like that:
|
|
195
|
+
// {
|
|
196
|
+
// "requests": [
|
|
197
|
+
// {
|
|
198
|
+
// "id": "1",
|
|
199
|
+
// "method": "GET",
|
|
200
|
+
// "url": "our-permissions-url"
|
|
201
|
+
// },
|
|
202
|
+
// {
|
|
203
|
+
// etc.
|
|
204
|
+
// }
|
|
205
|
+
// ]
|
|
206
|
+
// }
|
|
207
|
+
// We need to split the list of app ids to have no more than 10 requests per batch and no more than 30 ids per request
|
|
208
|
+
//
|
|
209
|
+
// we can have MAX_IDS_WITHOUT_BATCHING per one request in batch. And up to MAX_REQUESTS_PER_BATCH requests in batch.
|
|
210
|
+
const maxIdsPerBatch = MAX_IDS_WITHOUT_BATCHING * MAX_REQUESTS_PER_BATCH;
|
|
211
|
+
const batchesCount = Math.ceil(appIds.length / maxIdsPerBatch);
|
|
212
|
+
let batchIndex = 0;
|
|
213
|
+
const batchRequests = [];
|
|
214
|
+
try {
|
|
215
|
+
while(batchIndex < batchesCount){
|
|
216
|
+
const batchBody = {
|
|
217
|
+
requests: []
|
|
218
|
+
};
|
|
219
|
+
const batchStartIndex = batchIndex * maxIdsPerBatch;
|
|
220
|
+
const batchEndIndex = Math.min(batchStartIndex + maxIdsPerBatch, appIds.length);
|
|
221
|
+
let batchIdStartIndex = batchStartIndex;
|
|
222
|
+
while(batchIdStartIndex < batchEndIndex){
|
|
223
|
+
const batchIdEndIndex = batchIdStartIndex + MAX_IDS_WITHOUT_BATCHING;
|
|
224
|
+
const batchIds = appIds.slice(batchIdStartIndex, batchIdEndIndex);
|
|
225
|
+
batchBody.requests.push({
|
|
226
|
+
id: batchIdStartIndex.toString(),
|
|
227
|
+
method: 'GET',
|
|
228
|
+
url: this._getCheckPermissionsUrl(batchIds)
|
|
229
|
+
});
|
|
230
|
+
batchIdStartIndex = batchIdEndIndex;
|
|
231
|
+
}
|
|
232
|
+
batchRequests.push(batchBody);
|
|
233
|
+
batchIndex++;
|
|
234
|
+
}
|
|
235
|
+
} catch (error) {
|
|
236
|
+
monitor.writeUnexpectedFailure('BatchSplitLogicError', error);
|
|
237
|
+
// Early return to avoid the request
|
|
238
|
+
return Promise.resolve(allowedApps);
|
|
239
|
+
}
|
|
240
|
+
const errors = [];
|
|
241
|
+
return this._msGraphClient.then((client)=>{
|
|
242
|
+
const batchPromises = batchRequests.map((batchBody)=>{
|
|
243
|
+
return client.api('$batch').version(MS_GRAPH_API_VERSION).post(batchBody).then((response)=>{
|
|
244
|
+
response.responses.forEach((responseItem)=>{
|
|
245
|
+
if (responseItem.status !== 200) {
|
|
246
|
+
errors.push(new Error(responseItem.body.error.message));
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
responseItem.body.value.map((app)=>{
|
|
250
|
+
allowedApps.add(app.id);
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
}).catch((error)=>{
|
|
254
|
+
errors.push(error);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
return Promise.all(batchPromises);
|
|
258
|
+
}).then(()=>{
|
|
259
|
+
// some batches failed
|
|
260
|
+
if (errors.length) {
|
|
261
|
+
monitor.writeUnexpectedFailure('SomeBatchRequestsError', undefined, {
|
|
262
|
+
errors: errors
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
return allowedApps;
|
|
266
|
+
}).catch((error)=>{
|
|
267
|
+
// all batches failed
|
|
268
|
+
monitor.writeUnexpectedFailure('BatchRequestError', error);
|
|
269
|
+
return new Set();
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
_getCheckPermissionsUrl(appIds) {
|
|
273
|
+
return `${MS_GRAPH_TEAMS_APPS_ENDPOINT}?${MS_GRAPH_CHECK_PERMISSIONS_QSP.replace('{appIds}', appIds.join(`','`))}`;
|
|
274
|
+
}
|
|
275
|
+
get _msGraphClient() {
|
|
276
|
+
if (!this._msGraphClientFactory) {
|
|
277
|
+
this._msGraphClientFactory = this._serviceScope.consume(MSGraphClientFactory.serviceKey);
|
|
278
|
+
}
|
|
279
|
+
if (!this._msGraphClientDeferred) {
|
|
280
|
+
this._msGraphClientDeferred = this._msGraphClientFactory.getClientInternal('3');
|
|
281
|
+
}
|
|
282
|
+
return this._msGraphClientDeferred;
|
|
283
|
+
}
|
|
284
|
+
_teamsAppCatalogItemToAceManifests(item) {
|
|
285
|
+
//
|
|
286
|
+
// collect components that use Teams App icon instead of having its own
|
|
287
|
+
// if there are such components, we will need to fetch the app icon
|
|
288
|
+
//
|
|
289
|
+
let iconPromise;
|
|
290
|
+
const colorIconWebUrl = item.appDefinitions[0].colorIcon?.webUrl;
|
|
291
|
+
const manifestsWithoutIcon = [];
|
|
292
|
+
const dashboardCards = item.appDefinitions[0].dashboardCards || [];
|
|
293
|
+
const manifests = [];
|
|
294
|
+
dashboardCards.forEach((dashboardCard)=>{
|
|
295
|
+
const component = {
|
|
296
|
+
appId: item.id,
|
|
297
|
+
externalAppId: item.externalId || undefined,
|
|
298
|
+
componentId: dashboardCard.id,
|
|
299
|
+
groupId: ADVANCED_TOOLBOX_GROUP_ID,
|
|
300
|
+
iconUrl: dashboardCard.icon?.iconUrl,
|
|
301
|
+
officeUIFabricIconName: dashboardCard.icon?.officeUIFabricIconName,
|
|
302
|
+
description: dashboardCard.description,
|
|
303
|
+
name: dashboardCard.displayName,
|
|
304
|
+
botId: dashboardCard.contentSource.botConfiguration.botId,
|
|
305
|
+
appName: item.displayName,
|
|
306
|
+
appDescription: item.appDefinitions[0].description,
|
|
307
|
+
version: item.appDefinitions[0].version,
|
|
308
|
+
// size is lower case in the manifest
|
|
309
|
+
defaultSize: `${dashboardCard.defaultSize.charAt(0).toUpperCase()}${dashboardCard.defaultSize.slice(1)}`
|
|
310
|
+
};
|
|
311
|
+
const manifest = this._teamsAppComponentToAceManifest(component);
|
|
312
|
+
manifests.push(manifest);
|
|
313
|
+
if (!component.iconUrl && !component.officeUIFabricIconName) {
|
|
314
|
+
manifestsWithoutIcon.push(manifest);
|
|
315
|
+
if (!iconPromise && colorIconWebUrl) iconPromise = this._msGraphClient.then((client)=>{
|
|
316
|
+
return client.api(colorIconWebUrl).responseType('blob').get();
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
let resultPromise = Promise.resolve(manifests);
|
|
321
|
+
if (manifestsWithoutIcon.length && iconPromise) {
|
|
322
|
+
resultPromise = iconPromise.then((response)=>{
|
|
323
|
+
return this._convertBlobToBase64(response);
|
|
324
|
+
}).then((iconUrl)=>{
|
|
325
|
+
manifestsWithoutIcon.forEach((manifest)=>{
|
|
326
|
+
manifest.preconfiguredEntries[0].iconImageUrl = iconUrl;
|
|
327
|
+
manifest.properties.teamsAppComponent.iconUrl = iconUrl;
|
|
328
|
+
});
|
|
329
|
+
return manifests;
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
return resultPromise;
|
|
333
|
+
}
|
|
334
|
+
_convertBlobToBase64(blob) {
|
|
335
|
+
return new Promise((resolve, reject)=>{
|
|
336
|
+
const reader = new FileReader();
|
|
337
|
+
reader.onerror = reject;
|
|
338
|
+
reader.onload = ()=>{
|
|
339
|
+
const base64String = reader.result;
|
|
340
|
+
if (!base64String) {
|
|
341
|
+
reject('');
|
|
342
|
+
}
|
|
343
|
+
resolve(base64String.substr(base64String.indexOf(', ') + 1));
|
|
344
|
+
};
|
|
345
|
+
reader.readAsDataURL(blob);
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
_teamsAppComponentToAceManifest(component) {
|
|
349
|
+
return {
|
|
350
|
+
id: component.componentId,
|
|
351
|
+
manifestVersion: MANIFEST_VERSION,
|
|
352
|
+
version: component.version,
|
|
353
|
+
componentType: 'AdaptiveCardExtension',
|
|
354
|
+
alias: component.componentId,
|
|
355
|
+
properties: {
|
|
356
|
+
teamsAppComponent: component
|
|
357
|
+
},
|
|
358
|
+
loaderConfig: {
|
|
359
|
+
entryModuleId: component.componentId,
|
|
360
|
+
internalModuleBaseUrls: [
|
|
361
|
+
'HTTPS://CLIENTSIDEASSETSLIBRARY/'
|
|
362
|
+
],
|
|
363
|
+
scriptResources: {}
|
|
364
|
+
},
|
|
365
|
+
preconfiguredEntries: [
|
|
366
|
+
{
|
|
367
|
+
cardSize: component.defaultSize,
|
|
368
|
+
title: {
|
|
369
|
+
default: component.name
|
|
370
|
+
},
|
|
371
|
+
description: {
|
|
372
|
+
default: component.description
|
|
373
|
+
},
|
|
374
|
+
iconImageUrl: component.iconUrl,
|
|
375
|
+
officeFabricIconFontName: component.officeUIFabricIconName,
|
|
376
|
+
groupId: component.groupId,
|
|
377
|
+
properties: {}
|
|
378
|
+
}
|
|
379
|
+
],
|
|
380
|
+
connectedTeamsAppId: component.appId,
|
|
381
|
+
isPendingTeamsAppSync: true
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
constructor(serviceScope){
|
|
385
|
+
/**
|
|
386
|
+
* Map[teamsAppId, Promise[Set[teamsAppId]]]
|
|
387
|
+
*
|
|
388
|
+
* We store a map where the same promise can be used for multiple entries.
|
|
389
|
+
* In that case we can avoid multiple requests to the API for the same teamsAppId as well as avoid race conditions and allow to make extra requests if needed.
|
|
390
|
+
*/ this._appComponentsPermissionsPromises = new Map();
|
|
391
|
+
this._serviceScope = serviceScope;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
//# sourceMappingURL=./TeamsAppsClient.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import BaseComponent from '../BaseComponent';
|
|
2
|
+
import { MockComponentContext } from './MockComponentContext';
|
|
3
|
+
export class MockComponent extends BaseComponent {
|
|
4
|
+
constructor(mockScope){
|
|
5
|
+
super();
|
|
6
|
+
this.mockIDynamicData = {
|
|
7
|
+
getPropertyDefinitions: ()=>{
|
|
8
|
+
return [
|
|
9
|
+
{
|
|
10
|
+
id: 'test1',
|
|
11
|
+
title: 'Test One'
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 'test2',
|
|
15
|
+
title: 'Test Two'
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'test3',
|
|
19
|
+
title: 'Test Three'
|
|
20
|
+
}
|
|
21
|
+
];
|
|
22
|
+
},
|
|
23
|
+
getPropertyValue: ()=>{
|
|
24
|
+
return {
|
|
25
|
+
'mock-key': 'mock-value'
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
getAnnotatedPropertyValue: ()=>{
|
|
29
|
+
return {
|
|
30
|
+
sampleValue: {}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
this._initializeContext(new MockComponentContext(mockScope));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=./MockComponent.js.map
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { __extends } from "tslib";
|
|
2
1
|
import BaseComponentContext from '../BaseComponentContext';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return _super.call(this, {
|
|
2
|
+
export class MockComponentContext extends BaseComponentContext {
|
|
3
|
+
constructor(mockRootScope){
|
|
4
|
+
super({
|
|
7
5
|
parentServiceScope: mockRootScope,
|
|
8
6
|
manifest: {
|
|
9
7
|
componentType: 'Application',
|
|
10
8
|
alias: 'alias',
|
|
11
9
|
version: '1.0',
|
|
12
10
|
loaderConfig: {
|
|
13
|
-
internalModuleBaseUrls: [
|
|
11
|
+
internalModuleBaseUrls: [
|
|
12
|
+
'mock info'
|
|
13
|
+
],
|
|
14
14
|
entryModuleId: 'eId',
|
|
15
15
|
scriptResources: {}
|
|
16
16
|
},
|
|
@@ -19,9 +19,8 @@ var MockComponentContext = /** @class */ (function (_super) {
|
|
|
19
19
|
},
|
|
20
20
|
loggingTag: 'logtag',
|
|
21
21
|
instanceId: 'iId'
|
|
22
|
-
})
|
|
22
|
+
});
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
//# sourceMappingURL=MockComponentContext.js.map
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=./MockComponentContext.js.map
|