UNPKG

@microsoft/sp-webpart-base

Version:

SharePoint Framework support for building web parts

913 lines 113 kB
"use strict"; /* eslint-disable max-lines */ // Copyright (c) Microsoft. All rights reserved. Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var sp_component_base_1 = require("@microsoft/sp-component-base"); var sp_core_library_1 = require("@microsoft/sp-core-library"); var sp_diagnostics_1 = require("@microsoft/sp-diagnostics"); var sp_http_1 = require("@microsoft/sp-http"); var sp_loader_1 = require("@microsoft/sp-loader"); var lodash = tslib_1.__importStar(require("@microsoft/sp-lodash-subset")); var sp_page_context_1 = require("@microsoft/sp-page-context"); var loadThemedStyles = tslib_1.__importStar(require("@microsoft/load-themed-styles")); var PropertyPaneLoader_1 = tslib_1.__importDefault(require("../PropertyPaneLoader")); var ExecuteWithoutFailing_1 = require("../utils/ExecuteWithoutFailing"); var KillSwitches_1 = require("../common/KillSwitches"); var Flights_1 = require("../common/Flights"); var BaseClientSideWebPart_1 = tslib_1.__importDefault(require("./BaseClientSideWebPart")); var ClassicPageUtils_1 = tslib_1.__importDefault(require("./classicPages/ClassicPageUtils")); var ClientSideWebPartStatusRenderer_1 = tslib_1.__importDefault(require("./ClientSideWebPartStatusRenderer")); var SPWebPartError_1 = require("./error/SPWebPartError"); var IWebPartData_1 = require("./IWebPartData"); var IframedWebPartControllerLoader_1 = tslib_1.__importDefault(require("./loaders/IframedWebPartControllerLoader")); var WebPartContext_1 = tslib_1.__importDefault(require("./WebPartContext")); var WebPartFormFactor_1 = require("./WebPartFormFactor"); var Strings_resx_1 = tslib_1.__importDefault(require("./loc/Strings.resx")); var WebPartWidthCacheManager_1 = tslib_1.__importDefault(require("./WebPartWidthCacheManager")); var Enums_1 = require("../common/Enums"); var constants_1 = require("../common/constants"); var getErrorAceLoadConfiguration_1 = require("../utils/getErrorAceLoadConfiguration"); var isWebPartData_1 = require("../utils/isWebPartData"); var WebPartIdleLoad_1 = require("./idleLoad/WebPartIdleLoad"); var THUMBNAIL_MAX_URL_LENGTH = 255; // All SharePoint URL field types have this limit var DOCVIZ_REGEX = /(\/_layouts\/15\/getpreview.ashx\/?(|(\?(.*?)))$)/i; // Flight name is 'SppplatIframedWebPartControllerLoadingFeature' var SPPPLAT_IFRAMED_WEBPART_CONTROLLER_FLIGHT_ID = 1147; var ISOLATED_ACE_WP_MANIFEST_ID = 'e6b93447-8007-4f1e-934f-754a0031a769'; var IMAGE_WEBPART_V1_MANIFEST_ID = 'd1d91016-032f-456d-98a4-721247c305e8'; var IMAGE_WEBPART_V2_MANIFEST_ID = 'fe2f2812-4df0-42c7-ae2e-2db57e092751'; var LIST_WEBPART_V1_MANIFEST_ID = 'f92bf067-bc19-489e-a556-7fe95f508720'; var LIST_WEBPART_V2_MANIFEST_ID = 'a572f711-58d9-473f-a827-ac3ffd529516'; var LIST_WEBPART_FILEBROWSER_MANIFEST_ID = 'da46359b-3267-4af8-9c8e-42c631ae31c0'; var LOAD_ISOLATED_WEBPART = 'LoadIsolatedWebPart'; var PREFAB_WEBPART_MANIFEST_ID = 'a0957e08-a450-4de0-b402-7db1bd92c4de'; /** * The ClientSideWebPartManager is expected to be the public interface to client-side web parts. Each * host is expected to create an instance of this class and manage loading of all web parts in that host * through that one instance. e.g. On one page, if there are multiple Canvas objects, each one could have * one instance of this class. If the page hosts web parts without the Canvas, then the page can have an * instance of this class. Overall this class is expected to provide the following purpose: * * - Orchestrates loading of one or more web parts in a host. * - It takes care of loading web part dependencies asynchronously. Each web part loads completely * independently of the other web parts in the host. * - Keep a reference to all the loaded web parts and help provide bulk operations on the web parts. * - Help manage memory leak type issues in one place. * - Integrate the web parts with the PropertyPane and other external entities. * - Help troubleshoot web parts during escalations. * * @internal */ var ClientSideWebPartManager = /** @class */ (function () { /** * Initialize the ClientSideWebPartManager. * * @param host - Reference to the host. A web part host is a component that is deemed capable of hosting a web * part. Any component that implements the IWebPartHost is allowed to host a web part. */ function ClientSideWebPartManager(host) { /** * Dictionary of all the active web parts in this instance of the manager. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any this._webParts = new Map(); /** * Web part status renderer instance scoped to this web part manager instance. */ this._statusRenderer = new ClientSideWebPartStatusRenderer_1.default(); /** * Dictionary of all the iframed web parts in this instance of the manager. */ this._iframedWebpartInstanceIds = new Set(); this._propertyPaneConsumerQueue = new Map(); this._displayMode = sp_core_library_1.DisplayMode.Read; sp_core_library_1.Validate.isNotNullOrUndefined(host, 'host'); this._host = host; this._pageContext = host.serviceScope.consume(sp_page_context_1.PageContext.serviceKey); this._onContainerResize = this._onContainerResize.bind(this); this._onPropertyPaneNotifications = this._onPropertyPaneNotifications.bind(this); this.requestPropertyPaneAction = this.requestPropertyPaneAction.bind(this); this.isPropertyPaneRenderedByWebPart = this.isPropertyPaneRenderedByWebPart.bind(this); this.isPropertyPaneOpen = this.isPropertyPaneOpen.bind(this); if (ClientSideWebPartManager._webPartManagerList.length === 0) { this._initialzeOnResizeEventHandler(); } ClientSideWebPartManager._webPartManagerList.push(this); } /** * Create the web part tag. Web part tag is a unique tag per web part instance and is used for logging and telemetry. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any ClientSideWebPartManager.createWebPartTag = function (manifest, instanceId) { return "WebPart.".concat(manifest.alias, ".").concat(manifest.isInternal ? 'internal' : 'external', ".").concat(instanceId); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any ClientSideWebPartManager._instanceOfBase = function (wp) { if (!wp) { return false; } else if (wp instanceof BaseClientSideWebPart_1.default) { return true; } else { var objectType = wp['__type']; return objectType === 'BaseClientSideWebPart' || objectType === 'BaseMRClientSideWebPart'; } }; // eslint-disable-next-line @typescript-eslint/no-explicit-any ClientSideWebPartManager._getWebPartTag = function (wp) { var errorReason; if (!ClientSideWebPartManager._instanceOfBase(wp)) { errorReason = 'WebpartTag requested for non-webpart'; } else if (!wp.context) { // wp not being defined is checked by _instanceOfBase errorReason = 'WebpartTag requested for instance that is missing context'; } if (errorReason) { sp_diagnostics_1._TraceLogger.logError(ClientSideWebPartManager._logSource, new Error(errorReason)); return undefined; } return wp.context.webPartTag; }; ClientSideWebPartManager._isLoadingIsolatedWebPart = function (context, siteUrl) { var manifest = context.manifest, pageLayoutType = context.pageLayoutType; if ((0, Flights_1.is1PIsolationEnabled)() && manifest.isInternal && manifest.isolationLevel === 'DomainIsolation') { var tenantName = siteUrl.match(ClientSideWebPartManager._1PIsolatedDomainRegex); if (tenantName) { // The special app domain is constant for each tenant // This code will need to be updated when we fix vanity domain issues with isolated domains manifest.isolatedDomain = new URL(siteUrl.replace(ClientSideWebPartManager._1PIsolatedDomainRegex, "".concat(tenantName[0], "-app3bc2296eaa224ed29e1e946d05afa6a2"))).hostname; } else if (pageLayoutType !== 'Isolated') { throw new Error("Cannot create isolated domain for: ".concat(siteUrl)); } } return (sp_core_library_1._SPFlight.isEnabled(SPPPLAT_IFRAMED_WEBPART_CONTROLLER_FLIGHT_ID) && // The next condition is neccessary because the same web part // will cross this path twice, once when determining if we should load in an // iframe and the second time is when we are loading the web part inside // the iframe. pageLayoutType !== 'Isolated' && (manifest.isolationLevel === IWebPartData_1.WebPartIsolationLevel.DomIsolation || // 'isolatedDomain' is a string and we want to check if 'isolatedDomain' has value, // instead of undefined or "". !!manifest.isolatedDomain)); }; ClientSideWebPartManager._getWebPartTitle = function (manifest, webPartData) { // If the web part has data, take the title from the data. var title = webPartData && webPartData.title; if (!title) { // If the web part has just been created from the Toolbox, use the title from the picked up entry. // eslint-disable-next-line @typescript-eslint/no-explicit-any title = manifest.title && manifest.title.default; } // If we still do not have a title use the title from the preconfigured entries return title || manifest.preconfiguredEntries[0].title.default; }; ClientSideWebPartManager._loadDynamicComponentDependencies = function (components, webPartData, webPartTag) { var componentDependencies = (webPartData.serverProcessedContent && webPartData.serverProcessedContent.componentDependencies) || {}; var dependencies = Object.keys(componentDependencies); for (var _i = 0, dependencies_1 = dependencies; _i < dependencies_1.length; _i++) { var dep = dependencies_1[_i]; var componentId = componentDependencies[dep]; if (sp_core_library_1.Guid.isValid(componentId)) { components.push(sp_loader_1.SPComponentLoader.loadComponentById(componentId)); } else { throw new Error("Failed to load web part's (".concat(webPartTag, ") dynamic dependency ").concat(dep, " with component id {").concat(componentId, "}")); } } }; Object.defineProperty(ClientSideWebPartManager, "isMaintenanceMode", { /** * Returns true if the maintenanceMode query string parameter is provided. */ get: function () { var urlParams = new sp_core_library_1.UrlQueryParameterCollection(window.location.href); return urlParams.getValue('maintenanceMode') === 'true'; }, enumerable: false, configurable: true }); /** * Enables prefetching for the specified set of web parts. * * @privateRemarks * This is a prerequiste for prefetching and it does not initiate prefetching. * You must call `prefetchWebParts` to start the prefetching process (see example below). * * Example: * ``` * ClientSideWebpartManager.webPartPrefetching?.then((prefetching) => * prefetching.prefetchWebParts() * ); * ``` * @param controls - The web parts to enable prefetching for. * @beta */ ClientSideWebPartManager.prototype.enablePrefetching = function (controls) { if (!(0, Flights_1.isLoadEditModeWebPartsInParallelEnabled)()) { return; } var prefetchingModule = this._loadWebPartPrefetching(); prefetchingModule === null || prefetchingModule === void 0 ? void 0 : prefetchingModule.enablePrefetching(controls); }; /** * Load a web part in the provided DOM element. Does the following steps * * 1. Validate params. * 2. Validate the web part manifest. * 3. Perform an async import of the web part modules from the provided manifest * - i.e ClientSideWebPartManager._loadComponentModules * 4. Instantiate and initialize the web part object * - i.e. ClientSideWebPartManager._initializeWebPart * 5. Render the web part in the provided DOM element * - i.e. ClientSideWebPartManager._renderWebPart * * If an error happens during any of the above steps, catch the error and log it. * * @param webPartManagerContext - web part manager context. */ ClientSideWebPartManager.prototype.loadWebPart = function (webPartManagerContext) { var _this = this; try { if ((0, KillSwitches_1.isRefactorLoadWebPartKSActivated)()) { return this._loadWebPartOld(webPartManagerContext); } var context_1 = webPartManagerContext; var isIsolated_1 = this._isIsolatedWebPart(context_1); var monitor_1 = new sp_diagnostics_1._QosMonitor('WebPart.Load', true); var loadError_1; // eslint-disable-next-line @typescript-eslint/no-explicit-any var webPartInstance_1; return (this._loadAndInitWebPart(context_1) // eslint-disable-next-line @typescript-eslint/no-explicit-any .then(function (response) { // if isolated webpart loaded successfully exit the promise chain if (response === LOAD_ISOLATED_WEBPART) { return Promise.reject(new Error(LOAD_ISOLATED_WEBPART)); } _this._validateIfWPIsNotDisposed(response); _this._host.onBeforeWebPartRender(context_1); loadThemedStyles.flush(); return response; }) // eslint-disable-next-line @typescript-eslint/no-explicit-any .then(function (webPart) { _this._validateIfWPIsNotDisposed(webPart); if (!(0, KillSwitches_1.isHandleDisposeRaceConditionKSActive)()) { webPartInstance_1 = webPart; } return _this._loadPropertyPaneModule(webPart); }) // eslint-disable-next-line @typescript-eslint/no-explicit-any .then(function (webPart) { _this._validateIfWPIsNotDisposed(webPart); return _this._renderWebPart(webPart); }) .then(function (_a) { var webPart = _a.webPart, renderCompleteTime = _a.renderCompleteTime; context_1.renderCompleteTime = renderCompleteTime; if (!(0, KillSwitches_1.isIsolatedAdaptiveCardExtensionIframedPropertyPaneKSActivated)() && isIsolated_1 && context_1.manifest.id === ISOLATED_ACE_WP_MANIFEST_ID) { if (_this._iframedWebPartController) { _this._iframedWebPartController.assignIsolatedACEWP(context_1.instanceId, webPart); } } _this._host.onAfterWebPartRender(context_1); ClassicPageUtils_1.default.removeFabricLinks(); return _this._loadLegacyFabricCssIfRequired(context_1); }) .catch(function (error) { if (error instanceof Error && error.message === LOAD_ISOLATED_WEBPART) { return LOAD_ISOLATED_WEBPART; } if ('isDisposed' in error) { // IWebPartDisposedError error.stage = 'Render'; throw error; } if (!loadError_1) { loadError_1 = { error: error, stage: 'Render' }; } throw loadError_1; }) .then(function (response) { if (response === LOAD_ISOLATED_WEBPART) { return; } var extraData = sp_component_base_1._WebPartLoadDataCollector.collect(context_1.manifest, context_1.webPartTag, _this._pageContext); monitor_1.writeSuccess(extraData); }) .catch(function (e) { var extraData = sp_component_base_1._WebPartLoadDataCollector.collect(context_1.manifest, context_1.webPartTag, _this._pageContext); if (!(0, KillSwitches_1.isLogWebPartLoadErrorKSActivated)() && !(e.error instanceof Error)) { // eslint-disable-next-line @typescript-eslint/no-explicit-any extraData.errorData = e.error; } if ('isDisposed' in e || (webPartInstance_1 === null || webPartInstance_1 === void 0 ? void 0 : webPartInstance_1.isDisposed)) { // IWebPartDisposedError monitor_1.writeExpectedFailure(e.stage, e.error, extraData); _this._statusRenderer.clearLoadingIndicator(context_1.domElement); } else { monitor_1.writeUnexpectedFailure(e.stage, e.error, extraData); var error = e.error, stage = e.stage; switch (stage) { case 'Load': _this._host.onAfterWebPartLoadFailed(context_1, error); break; case 'Initialize': _this._host.onAfterWebPartInitializeFailed(context_1, error); break; case 'Render': _this._host.onAfterWebPartRenderFailed(context_1, error); break; } var instanceId = context_1.instanceId; // eslint-disable-next-line @typescript-eslint/no-explicit-any var errorWebPart = _this._webParts.get(instanceId); if (errorWebPart) { errorWebPart.dispose(); _this._webParts.delete(instanceId); } var additionalMessage = ''; if (errorWebPart === null || errorWebPart === void 0 ? void 0 : errorWebPart.modifiedByGraph) { var date = new Date((errorWebPart === null || errorWebPart === void 0 ? void 0 : errorWebPart.modifiedByGraph.lastModified) * 1000); additionalMessage = sp_core_library_1.Text.format(Strings_resx_1.default.WebpartErrorPagesAPIRelated, errorWebPart === null || errorWebPart === void 0 ? void 0 : errorWebPart.modifiedByGraph.apiVersion, date.toLocaleDateString(), date.toLocaleTimeString()); } _this._statusRenderer.renderError(context_1.domElement, error, { message: additionalMessage }); throw e.error; } })); } catch (error) { return Promise.reject(error); } }; /** * Set a IPropertyPaneConsumer object into the set of the Client-side Web Part Manager's * managed web parts. * * @param id - A unique instance id. * @param control - A component which wants to use the property Pane. * * @internal */ ClientSideWebPartManager.prototype.setPropertyPaneConsumer = function (id, control) { sp_core_library_1.Validate.isNonemptyString(id, 'id'); sp_core_library_1.Validate.isNotNullOrUndefined(control, 'control'); // eslint-disable-next-line @typescript-eslint/no-explicit-any this._webParts.set(id, control); this._registerWebPartAsPropertyPaneConsumer(id); }; /** * Fetch web part manifests. This makes a REST call to load the current site's web parts into the module loader. * * Previously, this method only fetched WebPart manifests through a REST call to GetClientSideWebParts * Then, an extra call to fetch AdaptiveCardExtension manifests via GetAdaptiveCardExtensions was added when MEEDashboard is enabled * * To consolidate these calls into a single request, we use a new endpoint, GetClientSideComponentsByComponentType * * If the CallGetClientSideComponentsByComponentType flight is enabled * - call GetClientSideComponentsByComponentType(["WebPart", "AdaptiveCardExtension"]) if MEEDashboard flight enabled * - call GetClientSideWebParts, since GetClientSideComponentsByComponentType server endpoint checks for MEEDashboard flight: Workitem 1119156 * If the CallGetClientSideComponentsByComponentType flight is disabled * - call GetClientSideWebParts and GetAdaptiveCardExtensions if MEEDashboard flight is enabled * - call GetClientSideWebParts, only, if MEEDashboard flight is disabled * * This method will also initiate fetching of Teams-connected manifests from Teams App Catalog. */ ClientSideWebPartManager.prototype.fetchWebPartManifests = function () { var _this = this; var shouldFetchACEs = !(0, Flights_1.isOptionalSupportedHostsFilteringEnabled)(); if (shouldFetchACEs) { this._toolboxACEManifestsPromise = this._fetchAdaptiveCardExtensionManifests(); } if (!this._toolboxManifestsPromise && // If the webServerRelativeUrl is missing we don't have anything to do here. (!this._pageContext.web || !this._pageContext.web.serverRelativeUrl || sp_core_library_1.Environment.type === sp_core_library_1.EnvironmentType.Local || sp_core_library_1.Environment.type === sp_core_library_1.EnvironmentType.Test)) { this._toolboxManifestsPromise = Promise.resolve(); } // if web parts have already been fetched we don't have anything to do here. if (!this._toolboxManifestsPromise) { var requestCorrelationId_1; var fromServiceWorker_1; var qosMonitor_1 = new sp_diagnostics_1._QosMonitor('ClientSideWebPartManager.FetchWebParts'); var endpoint = void 0; if ((0, Flights_1.isOptionalSupportedHostsFilteringEnabled)()) { endpoint = "_api/web/GetClientSideComponentsByComponentType(componentTypesString='".concat(Enums_1.SPClientSideComponentType.WebPart, ",").concat(Enums_1.SPClientSideComponentType.AdaptiveCardExtension, "', includeManifestActivatedTime=true)"); } else { // ACEs will be fetched in another request endpoint = "_api/web/GetClientSideComponentsByComponentType(componentTypesString='".concat(Enums_1.SPClientSideComponentType.WebPart, "',supportedHostTypeValue=").concat(Enums_1.SupportedHostType.SharePointWebPart, ")"); } var requestUrl_1 = "".concat(sp_core_library_1.UrlUtilities.removeEndSlash(this._pageContext.web.serverRelativeUrl), "/").concat(endpoint); this._host.serviceScope.whenFinished(function () { var httpClient = _this._host.serviceScope.consume(sp_http_1.SPHttpClient.serviceKey); _this._toolboxManifestsPromise = _this._fetchManifestsWithCache(httpClient, requestUrl_1) .then(function (response) { requestCorrelationId_1 = response.correlationId ? response.correlationId.toString() : undefined; fromServiceWorker_1 = response.headers.get('X-From-Service-Worker') === 'true'; if (response.ok) { return (response.jsonCached || (response.jsonCached = Promise.resolve(response.json()))); } else { throw SPWebPartError_1.SPWebPartError.create(SPWebPartError_1.SPWebPartErrorCode.ManifestDownloadFailed); } }) .then(function (value) { var manifests = value.value.map(function (manifestObject) { var parsedManifest = JSON.parse(manifestObject.Manifest); if (manifestObject.ManifestActivatedTime) { parsedManifest.manifestActivatedTime = manifestObject.ManifestActivatedTime; } return parsedManifest; }); _this._disambiguateWebPartManifestLocales(manifests); // Ideally we always want to refresh manifests to get rid of stale manifests which might not be installed // in the current site (after cross-sites navigation). However, in debug mode, manifests are not marked as // "isInternal: true" which causes them being removed by refreshWebPartManifests if (!(0, KillSwitches_1.isWebPartManifestListCacheRefreshKSActivated)() && !_this._isDebugSession && !sp_core_library_1._BrowserUtilities.isWorkbenchHosted()) { sp_loader_1.SPComponentLoader.refreshWebPartManifests(manifests); } else { sp_loader_1.SPComponentLoader.registerManifests(manifests); } qosMonitor_1.writeSuccess(); }) .catch(function (error) { // Clear out the promise so we can try again if we enter edit mode again. _this._toolboxManifestsPromise = undefined; _this._clearManifestCacheItem(requestUrl_1); sp_diagnostics_1._TraceLogger.logErrorData({ source: ClientSideWebPartManager._logSource, error: error, serviceScope: _this._host.serviceScope }); qosMonitor_1.writeUnexpectedFailure('Rejected', error, { correlationId: requestCorrelationId_1, fromServiceWorker: fromServiceWorker_1 }); throw error; }); }); } var fetchTeamsAcePromise = this._fetchTeamsACEManifests(); // logic with all checks is included inside the method var resultPromise; if (shouldFetchACEs) { resultPromise = Promise.all([ this._toolboxACEManifestsPromise, this._toolboxManifestsPromise, fetchTeamsAcePromise ]).then(function () { return undefined; }); } else { if (!(0, KillSwitches_1.isUsePromiseAllForFetchWebPartsKSActivated)()) { // adding extra KS here as we're changing behavior to Promise.all - just for extra safety resultPromise = Promise.all([this._toolboxManifestsPromise, fetchTeamsAcePromise]).then(function () { return undefined; }); } else { resultPromise = this._toolboxManifestsPromise; } } return resultPromise; }; /** * Get list of active web part manifests. * * @param includeAdaptiveCardExtensions - Include ACE manifests (casted as webpart manifests) in the returned array. * * @returns - array of manifests. */ ClientSideWebPartManager.prototype.getWebPartManifests = function (includeAdaptiveCardExtensions) { var _a; if (includeAdaptiveCardExtensions === void 0) { includeAdaptiveCardExtensions = false; } var manifests = sp_loader_1.SPComponentLoader._getManifestReferences(); var result = []; for (var _i = 0, manifests_1 = manifests; _i < manifests_1.length; _i++) { var manifest = manifests_1[_i]; // Some 1P ACEs are currently using web part manifests // Remove this check after converting all the 1P manifests var isWebPartACE = (_a = manifest.experimentalData) === null || _a === void 0 ? void 0 : _a.ACE; if (manifest.componentType === 'WebPart' && !isWebPartACE) { result.push(manifest); } else if (includeAdaptiveCardExtensions && (manifest.componentType === 'AdaptiveCardExtension' || isWebPartACE)) { result.push(manifest); } } return result; }; /** * Get list of Adaptive Card Extension manifests. * * @returns - array of ACE manifests */ ClientSideWebPartManager.prototype.getAdaptiveCardExtensionManifests = function () { var _a, _b; var manifests = sp_loader_1.SPComponentLoader._getManifestReferences(); var result = []; // // Currently we treat Teams App Catalog as the point of truth if the same component is available in both catalogs. // So we need to add Teams ACEs first and then add missing ones from SharePoint. // This will change if/when we implement sync Timer Job // if ((0, Flights_1.isBotAcesFromTeamsEnabled)() && this._toolboxTeamsAppComponentsManifests) { result.push.apply(result, Array.from(this._toolboxTeamsAppComponentsManifests.values())); } for (var _i = 0, manifests_2 = manifests; _i < manifests_2.length; _i++) { var manifest = manifests_2[_i]; if ((manifest.componentType === 'AdaptiveCardExtension' || ((_a = manifest.experimentalData) === null || _a === void 0 ? void 0 : _a.ACE)) && !((_b = this._toolboxTeamsAppComponentsManifests) === null || _b === void 0 ? void 0 : _b.has(manifest.id)) && // we don't want to add items that have been already added (!this._toolboxTeamsAppComponentsManifests || !manifest.connectedTeamsAppId) // we also don't want to add any Teams-connected ACEs in the toolbox. If they were not added from Teams App Catalog, either they were deleted or a user doesn't have permissions to see them ) { result.push(manifest); } } return result; }; /** * Set the display mode of the specified web part. If no web part id is specified, switch mode of all web parts. * If the display mode passed is same as the current mode, no change is applied. * * @param displayMode - the new DisplayMode. * @param instanceId - instance id of the web part. */ ClientSideWebPartManager.prototype.setDisplayMode = function (displayMode, instanceId) { this._setDisplayMode(displayMode, instanceId).catch(function (e) { return sp_diagnostics_1._TraceLogger.logVerboseData({ source: ClientSideWebPartManager._logSource, message: e.message }); }); }; /** * @remarks * Only use this API if you need to immediately call property pane APIs after switching the mode. * * @internal */ ClientSideWebPartManager.prototype._setDisplayMode = function (displayMode, instanceId) { var _this = this; this._displayMode = displayMode; if (this._displayMode === sp_core_library_1.DisplayMode.Read) { this._closeIsolatedPropertyPaneIfRequired(); } // We only want to indicate we have loaded, if needed, the property pane var setDisplayModePromise = this._loadPropertyPaneModuleOld(); // Set the display mode for the requested or all web parts. this._executeForIdsOrAll(this._getArrayOrUndefined(instanceId), function (id, webPart) { if (webPart) { webPart._internalSetDisplayMode(displayMode); } else if (_this._iframedWebpartInstanceIds.has(id)) { var qosMonitor = new sp_diagnostics_1._QosMonitor('ClientSideWebPartManager._setDisplayMode'); if (_this._iframedWebPartController) { qosMonitor.writeSuccess(); _this._iframedWebPartController.setDisplayMode(displayMode, id); } else { qosMonitor.writeUnexpectedFailure('iFrame controller used before deferral loading is complete'); } } }); // Start the dirty bit timer if required this._startDirtyBitTimer(displayMode); return setDisplayModePromise; }; /** * Serialize the specified web part. If no web part is specified, serialize all web parts. * * @param instanceId - instance id of the web part. */ ClientSideWebPartManager.prototype.serialize = function (instanceId) { var _this = this; var sd = new Map(); this._executeForIdsOrAll(this._getArrayOrUndefined(instanceId), function (id, webPart) { if (webPart) { sd.set(id, webPart._internalSerialize()); } else if (_this._iframedWebpartInstanceIds.has(id)) { sp_core_library_1.Validate.isNotNullOrUndefined(_this._iframedWebPartController, 'IFramedWebPartController is undefined'); sd.set(id, _this._iframedWebPartController.serialize(id)); } }); return sd; }; ClientSideWebPartManager.prototype.setWebPartData = function (contextOrWebPartData, instanceId, shouldFallback) { if (shouldFallback === void 0) { shouldFallback = false; } sp_core_library_1.Validate.isNotNullOrUndefined(contextOrWebPartData, 'web part manager context'); sp_core_library_1.Validate.isNonemptyString(instanceId, 'web part instance id'); var wp = this._webParts.get(instanceId); var isWebPartDataUsed = !(0, KillSwitches_1.isClickToAddFromContentPaneKSActivated)() && (0, Flights_1.isConfigurationToolsEnabled)() && (0, isWebPartData_1.isWebPartData)(contextOrWebPartData); var context = isWebPartDataUsed ? undefined : contextOrWebPartData; var webPartData = isWebPartDataUsed ? contextOrWebPartData : context === null || context === void 0 ? void 0 : context.webPartData; sp_core_library_1.Validate.isNotNullOrUndefined(webPartData, 'web part data'); if (wp && webPartData) { if (shouldFallback && context) { this.disposeWebparts(instanceId); return this.loadWebPart(context); } else { var addedFromPersistedData = isWebPartDataUsed ? false : !!(context === null || context === void 0 ? void 0 : context.addedFromPersistedData); wp._internalSetWebPartData(webPartData, addedFromPersistedData); sp_core_library_1._SPEventManager.instance.raiseEvent(this._getDataUpdatedEventName(webPartData.instanceId), {}); } } return Promise.resolve(); }; /** * Dispose of the current webpart manager and all of the webparts it has loaded. */ ClientSideWebPartManager.prototype.dispose = function () { this.disposeWebparts(); var currentIdx = ClientSideWebPartManager._webPartManagerList.indexOf(this); if (currentIdx >= 0) { ClientSideWebPartManager._webPartManagerList.splice(currentIdx, 1); } }; /** * Dispose the specified web part. If no web part is specified, dispose all web parts. * * @param instanceId - instance id of the web part. */ ClientSideWebPartManager.prototype.disposeWebparts = function (instanceId) { var _this = this; this._executeForIdsOrAll(this._getArrayOrUndefined(instanceId), function (id, webPart) { if (webPart) { // Remove references to the web part from the manager before disposing it _this._deleteWebPart(id); // Actually dispose the web part (0, ExecuteWithoutFailing_1.executeWithoutFailing)(function () { webPart._internalDispose(); }, ClientSideWebPartManager._logSource); } else if (_this._iframedWebpartInstanceIds.has(id)) { sp_core_library_1.Validate.isNotNullOrUndefined(_this._iframedWebPartController, 'IFramedWebPartController is undefined'); _this._iframedWebPartController.deleteWebPart(id); } }); }; /* * Get the first web part with preview image url specified. If no web parts are specified, try to get the preview * image from all web parts. * * @param instanceIds - instance ids of the web parts. */ ClientSideWebPartManager.prototype.tryGeneratePreviewImageUrl = function (instanceIds) { var _this = this; var candidatePreviewImageUrl; var previewImageUrl = undefined; var previewFromAlias = undefined; var monitor = new sp_diagnostics_1._QosMonitor('ClientSideWebPartManager.tryGeneratePreviewImageUrl'); if (!(0, KillSwitches_1.isFixUnstableThumbnailKSActivated)()) { this._webParts.forEach(function (webPart, instanceId) { // Check the type because the dictionary can have web parts or property pane controls if (ClientSideWebPartManager._instanceOfBase(webPart) && _this._isTitleAreaBannerWebPart(webPart) && webPart.previewImageUrl) { previewImageUrl = webPart.previewImageUrl; } }); } this._executeForIdsOrAll(instanceIds, function (instanceId, webPart) { if (webPart) { // workaround for typescript targeting es5 only support for...of for array and string // also Map does not support some or every // @todo: Bug 222340 when switching to es6, use for...of and return after first match if (!previewImageUrl) { var webPartThumbnail = webPart.previewImageUrl; if (webPartThumbnail) { previewFromAlias = webPart.context.manifest.alias; if (webPartThumbnail.length < THUMBNAIL_MAX_URL_LENGTH) { candidatePreviewImageUrl = webPartThumbnail; // prefer non-canonical paths due to oAuth allowed end points var normalizedPath = candidatePreviewImageUrl.toUpperCase(); // https://onedrive.visualstudio.com/_search?action=contents&text=authEndpoints&type=code&lp=custom-Collection&filters=ProjectFilters%7BOneDrive%20Service%7DRepositoryFilters%7Bnotify-server%7D&pageSize=25&result=DefaultCollection%2FOneDrive%20Service%2Fnotify-server%2FGBmaster%2F%2FActivity%2FOneDrive.Activity.DataAccess%2Fsrc%2FIdentity%2FSpoUserProvider.cs var isSupportedByOAuth = DOCVIZ_REGEX.test(normalizedPath) || normalizedPath.indexOf('/_API/') >= 0; if (isSupportedByOAuth || ((0, KillSwitches_1.isFixUnstableThumbnailKSActivated)() && _this._isTitleAreaBannerWebPart(webPart))) { previewImageUrl = candidatePreviewImageUrl; } } else { var imageUrl = webPart.previewImageUrl; sp_diagnostics_1._TraceLogger.logVerboseData({ source: ClientSideWebPartManager._logSource, eventName: 'tryGeneratePreviewImageUrl', message: "".concat(previewFromAlias, " attempted preview URL of ").concat(imageUrl && imageUrl.length, " chars.") }); } } } } else if (_this._iframedWebpartInstanceIds.has(instanceId)) { // @todo: VSO#612911 - add support tryGeneratePreviewImageUrl for iframed webparts monitor.writeExpectedFailure('IframedPart'); return undefined; } }); var extraData = monitor && previewFromAlias ? { alias: previewFromAlias } : undefined; if (!previewImageUrl && candidatePreviewImageUrl) { previewImageUrl = candidatePreviewImageUrl; monitor.writeExpectedFailure('NonLayouts', undefined /* ex */, extraData); } if (!previewImageUrl && previewFromAlias) { monitor.writeUnexpectedFailure('PathTooLong', undefined /* ex */, extraData); // Ensure to adjust callers if changing this error message! throw new Error('tryGeneratePreviewImageUrl PathLengthError.'); } if (!monitor.hasEnded) { monitor.writeSuccess(extraData); } return previewImageUrl; }; /** * Gets the top action configuration for the webpart with the specified instanceId * @param instanceId - the specified instanceId * @returns undefined if the webpart isn't loaded yet or the webpart doesn't support top actions. */ ClientSideWebPartManager.prototype.getWebpartTopActions = function (instanceId) { var webPart = this._webParts.get(instanceId); return webPart === null || webPart === void 0 ? void 0 : webPart.getTopActionsConfiguration(); }; /** * Gets the accessibility results for the webpart with the specified instanceId * @param instanceId - the specified instanceId * @returns undefined if the webpart isn't loaded yet or the webpart doesn't support accessibility assistant. */ ClientSideWebPartManager.prototype.getWebpartA11yResult = function (instanceId) { return tslib_1.__awaiter(this, void 0, void 0, function () { var webPart, _i, _a, wpm; return tslib_1.__generator(this, function (_b) { for (_i = 0, _a = ClientSideWebPartManager._webPartManagerList; _i < _a.length; _i++) { wpm = _a[_i]; webPart = wpm._webParts.get(instanceId); if (webPart !== undefined) { break; } } if (webPart === undefined) { return [2 /*return*/, Promise.resolve([undefined])]; } return [2 /*return*/, webPart._checkA11y()]; }); }); }; /** * Calls the preOnClickA11yResult method for the webpart with the specified instanceId * to help users redirect to the specific item editing configuration pane to fix the accessibility issues. * @param result - the accessibility result to be passed to the webpart */ ClientSideWebPartManager.prototype.preOnClickA11yResult = function (result) { var webPart; // if the the webPartInstanceId is not found, then return directly if (!result.webPartInstanceId) { return; } for (var _i = 0, _a = ClientSideWebPartManager._webPartManagerList; _i < _a.length; _i++) { var wpm = _a[_i]; webPart = wpm._webParts.get(result.webPartInstanceId); if (webPart !== undefined) { break; } } webPart === null || webPart === void 0 ? void 0 : webPart._preOnClickA11yResult(result); }; /** * Request property pane or content panel to perform the given action. * * @param instanceId - web part instance id. * @param propertyPaneAction - indicates what action needs to be performed on the property pane. * @param renderedByWebPart - indicates whether the the property pane rendered by a web part or not. * @param context - pass additional context to property pane */ ClientSideWebPartManager.prototype.requestPropertyPaneAction = function (instanceId, propertyPaneAction, renderedByWebPart, // eslint-disable-next-line @typescript-eslint/no-explicit-any context) { var _this = this; var _a; if (propertyPaneAction === void 0) { propertyPaneAction = 'Default'; } if (this._iframedWebpartInstanceIds.has(instanceId)) { // Iframe controller scenario // Hiding the non-iframed property pane if open, before loading the iframed property pane. if ((_a = this._propertyPane) === null || _a === void 0 ? void 0 : _a.isOpen((0, Flights_1.isConfigurationToolsEnabled)() ? instanceId : undefined)) { this._propertyPane.requestAction(instanceId, 'Close', renderedByWebPart); } this._iframedWebPartController.requestPropertyPaneAction(propertyPaneAction, instanceId); } else { var isHandledByWPHost = false; if (this._host.requestPropertyPaneAction) { // Allow web part host to handle the property pane action. // For example, IFramedWebPartHost will post a message to the parent window to open the property pane. isHandledByWPHost = this._host.requestPropertyPaneAction(instanceId, propertyPaneAction, renderedByWebPart, context); } if (!isHandledByWPHost) { // Default scenario // Hide the Iframed property pane before opening non-iframe scenario. // if no iframed property pane is present then this is a no-op. if (this._iframedWebPartController) { this._iframedWebPartController.requestPropertyPaneAction('Close'); } if (this._propertyPane) { this._propertyPane.requestAction(instanceId, propertyPaneAction, renderedByWebPart, !(0, KillSwitches_1.isFixMissingContextKSActivated)() ? context : undefined); } else if (propertyPaneAction === 'OpenDetails') { // If the properyPane is not loaded for OpenDetails Action, // We have to load the property pane and then execute the action. this._loadPropertyPaneModuleOld(true) .then(function () { return _this._propertyPane.requestAction(instanceId, propertyPaneAction, renderedByWebPart, context); }) .catch(function (e) { return sp_diagnostics_1._TraceLogger.logVerboseData({ source: ClientSideWebPartManager._logSource, message: e.message }); }); } } } }; /** * Returns true if the current property pane or content panel source is a web part and not the Canvas or any other source. */ ClientSideWebPartManager.prototype.isPropertyPaneRenderedByWebPart = function () { return !!this._propertyPane && this._propertyPane.isRenderedByConsumer(); }; /** * Returns the state of the PropertyPane if it is open or not. * Also true if Property Pane is rendered by Content Panel. * * @param instanceId - optional param to check isopen based on the supported consumer (content panel or property pane). * see IConfigurableOptionsController.isOpen(instanceId) for more details */ ClientSideWebPartManager.prototype.isPropertyPaneOpen = function (instanceId) { return !!this._propertyPane && this._propertyPane.isOpen(instanceId); }; /** * Returns the state of the ContentPanel if it is open or not. * Returns true if the Content Panel is open, regardless if the Content Panel is rendering the property pane. */ ClientSideWebPartManager.prototype.isContentPanelOpen = function () { var _a, _b; return !!((_b = (_a = this._propertyPane) === null || _a === void 0 ? void 0 : _a.isContentPanelOpen) === null || _b === void 0 ? void 0 : _b.call(_a)); }; /** * Method to handle the web part delete action from the host. There is a key distinction between delete and dispose. * Delete implies that the web part has been deleted from the page and the web part should dispose all the server * side or other external resources attached to the web part. Dispose implies that an in-place navigation is * happening and the web part manager should delete the web part from its cache. * * @param instanceId - instance id of the webpart which is deleted. */ ClientSideWebPartManager.prototype.onWebPartDelete = function (instanceId) { var _a; this.disposeWebparts(instanceId); if ((0, Flights_1.isLoadEditModeWebPartsInParallelEnabled)() && instanceId) { (_a = this.webPartPrefetching) === null || _a === void 0 ? void 0 : _a.cancelPrefetching(instanceId); } }; /** * Render an error message in the web part container div. Also logs the error message to the IWebPartHost logger. */ ClientSideWebPartManager.prototype.renderError = function (domElement, error) { var _this = this; (0, ExecuteWithoutFailing_1.executeWithoutFailing)(function () { _this._statusRenderer.renderError(domElement, error); sp_diagnostics_1._TraceLogger.logErrorData({ source: ClientSideWebPartManager._logSource, error: error, serviceScope: _this._host.serviceScope }); }, ClientSideWebPartManager._logSource); }; /** * Notify webparts that their container has resized. * * @param instanceId -