UNPKG

@microsoft/sp-webpart-base

Version:

SharePoint Framework support for building web parts

746 lines 35.7 kB
"use strict"; // Copyright (c) Microsoft. All rights reserved. Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var sp_telemetry_1 = require("@msinternal/sp-telemetry"); var sp_diagnostics_1 = require("@microsoft/sp-diagnostics"); var sp_core_library_1 = require("@microsoft/sp-core-library"); var sp_component_base_1 = require("@microsoft/sp-component-base"); var sp_edit_customer_promise_1 = require("@msinternal/sp-edit-customer-promise"); var BaseWebPart_1 = tslib_1.__importDefault(require("./BaseWebPart")); var ClassicPageUtils_1 = tslib_1.__importDefault(require("./classicPages/ClassicPageUtils")); var SPWebPartError_1 = require("./error/SPWebPartError"); var WebPartWidthCacheManager_1 = tslib_1.__importDefault(require("./WebPartWidthCacheManager")); var cswp_base_module_scss_1 = tslib_1.__importDefault(require("./styles/cswp-base.module.scss")); var KillSwitches_1 = require("../common/KillSwitches"); var Flights_1 = require("../common/Flights"); /** * This abstract class implements the the base functionality for a client-side web part. Every client-side web part * needs to inherit from this class. * * @remarks * Along with the base functionality, this class provides some APIs that can be * used by the web part. These APIs fall in two catagories. * * The first category of APIs provide data and functionality. Example, the web part context (i.e. this.context). This * API should be used to access contextual data relevant to this web part instance. * * The second category of APIs provide a base implementation for the web part lifecycle and can be overridden for an * updated implementation. The render() API is the only API that is mandatory to be implemented/overridden by a web * part. All other life cycle APIs have a base implementation and can be overridden based on the needs of the web part. * Please refer to the documentation of the individual APIs to make the right decision. * * @public */ var BaseClientSideWebPart = /** @class */ (function (_super) { tslib_1.__extends(BaseClientSideWebPart, _super); /** * Constructor for the BaseClientSideWebPart class. * * @remarks * It is highly recommended that the web part use the `onInit()` API to perform any web part specific * initialization. Most of the web part features like this.context and `this.properties` are not * available to be used before the the `onInit()` part of the web part loading lifecycle. */ function BaseClientSideWebPart() { var _this = _super.call(this) || this; _this._logSource = sp_diagnostics_1._LogSource.create('BaseClientSideWebPart'); _this._asyncRenderQosMonitor = new sp_diagnostics_1._QosMonitor("WebPartAsyncRender"); _this._asyncRenderCompleteCalled = false; /** * Whether the web part is visible. */ _this._isVisible = true; _this._internalIsDisposing = false; // Disallow instantiation of the base class by itself // eslint-disable-next-line @typescript-eslint/no-explicit-any if (_this.constructor.name === 'BaseClientSideWebPart') { throw SPWebPartError_1.SPWebPartError.create(SPWebPartError_1.SPWebPartErrorCode.BaseConstructError); } _this._firstTimeRenderPromises = []; return _this; } Object.defineProperty(BaseClientSideWebPart.prototype, "domElement", { // Readonly protected properties. To change these to readonly once TypeScript supports that feature. /** * This property is a pointer to the root DOM element of the web part. This is a DIV element and contains the whole * DOM subtree of the web part. * * @readonly */ get: function () { return this.context.domElement; }, enumerable: false, configurable: true }); Object.defineProperty(BaseClientSideWebPart.prototype, "width", { /** * This property returns the width of the container for the web part. * @returns Width (in pixels) of the container for the web part. * * @remarks * Web parts should utilize this property to perform operations such as any conditional styling of components * based on the initial available width for the web part. * @readonly */ get: function () { // This function retrieves web part's key to get stored section width from cache. // If cache key does not exist in cache it will calculate and store the width before returning. // // In the case where getWebPartCacheKey is not passed down, it will go through the original // workflow to calculate web part width. if (this.displayMode === sp_core_library_1.DisplayMode.Read) { this._width = WebPartWidthCacheManager_1.default.getOrCalculateWidth(this.domElement, this._getExtendedWidthCacheKey()); } else { if (this._width === undefined) { this._width = WebPartWidthCacheManager_1.default.calculateWebPartWidth(this.domElement); } } return this._width; }, enumerable: false, configurable: true }); Object.defineProperty(BaseClientSideWebPart.prototype, "renderedOnce", { /** * This property indicates whether the web part has been rendered once or not. After the first time rendering, * the value of this property is always true until a full re-render of the web part happens. * * @readonly */ get: function () { return !!this._renderedOnce; }, enumerable: false, configurable: true }); Object.defineProperty(BaseClientSideWebPart.prototype, "renderedFromPersistedData", { /** * This property indicates whether the web part was rendered from the persisted data (serialized state from the * last time that the web part was saved) or not. * * @remarks * Example: When web part is added for the first time using toolbox then the value is false. * * @readonly */ get: function () { return !!this._renderedFromPersistedData; }, enumerable: false, configurable: true }); Object.defineProperty(BaseClientSideWebPart.prototype, "canOpenPopupOnRender", { /** * This property indicates whether a web part can open a popup on initial render. * * @remarks * In some environments the host * re-renders the web parts frequently, and therefore opening popups during render will cause popups to open * repeatedly, which is a poor user experience. As an example, the classic SharePoint pages perform postbacks * causing the page to re-render on all button clicks. * * If a web part needs to open a popup on render, it should use this API before opening the popup. If this API * returns false, the web part should not open popup on initial render. Some web parts that open popups during * render are the document embed web part that pops up the file picker on initial render, embedded video web part * that pops up the PropertyPane on initial render. * * @readonly */ get: function () { // @todo (SPPPLAT VSO#243602): if the classic page experience is usable, we should remove this API. return true; }, enumerable: false, configurable: true }); Object.defineProperty(BaseClientSideWebPart.prototype, "isRenderAsync", { /** * Indicates whether the web part is rendering in Async mode. * * @remarks * If the web part overrides this field to return true, then it needs to call renderCompleted API * after the web part rendering is complete. * * The default value is false. * * @virtual */ get: function () { return false; }, enumerable: false, configurable: true }); Object.defineProperty(BaseClientSideWebPart.prototype, "isVisible", { /** * API to hide or show the web part. It tells the host whether the web part is supposed to be hidden. * The host might decide to remove or recover the side effects that are not rendered by web part implementation. * @remarks * This does NOT work in edit mode. * * @alpha */ get: function () { return this.displayMode === sp_core_library_1.DisplayMode.Edit || this._isVisible; }, set: function (value) { var _a, _b; if (this.displayMode !== sp_core_library_1.DisplayMode.Edit && value !== this._isVisible) { this._isVisible = value; (_b = (_a = this.context.host).onAfterWebPartVisibilityChanged) === null || _b === void 0 ? void 0 : _b.call(_a, this.context.instanceId, value); } }, enumerable: false, configurable: true }); Object.defineProperty(BaseClientSideWebPart.prototype, "_isDisposing", { /** * If the web part is being disposed * @internal */ get: function () { return this._internalIsDisposing; }, enumerable: false, configurable: true }); /** * Internal API to update the webpart upon a resize of the DOM window's viewport * * See onAfterResize for more details. * * @internal */ BaseClientSideWebPart.prototype._internalOnAfterResize = function () { this._width = undefined; this.onAfterResize(this.width); }; /** * Internal API for the first time render of the web part. The purpose of this API is to enforce initialization steps * before the actual render is called. This API is called only once during the web part loading lifecycle. * * @returns The promise indicates the render loop is finished (success or fail). * * @internal */ BaseClientSideWebPart.prototype._internalFirstTimeRender = function () { var _this = this; if (this._renderPromiseResolver) { throw SPWebPartError_1.SPWebPartError.create(SPWebPartError_1.SPWebPartErrorCode.FirstTimeRenderCalledMoreThanOnce, this.context.webPartTag); } return new Promise(function (resolve, reject) { _this._renderPromiseResolver = resolve; _this._renderPromiseRejecter = reject; _this._onInViewport(); }); }; /** * @internal */ BaseClientSideWebPart.prototype._internalSetDisplayMode = function (newDisplayMode) { if (this.displayMode !== newDisplayMode) { // Switch display mode will change the canvas width of web part. Clear the cache of width here. this._width = undefined; this._renderedFromPersistedData = true; } _super.prototype._internalSetDisplayMode.call(this, newDisplayMode); }; /** * Internal API for the web part transpile invoke * * @returns Transpile result * * @internal */ BaseClientSideWebPart.prototype._internalTranspile = function (context) { return this.onTranspile(context); }; /** * @internal * {@inheritDoc BaseWebPart._internalInitialize} */ BaseClientSideWebPart.prototype._internalInitialize = function (webPartContext, addedFromPersistedData, mode) { _super.prototype._internalInitialize.call(this, webPartContext, addedFromPersistedData, mode); this._renderedOnce = false; // eslint-disable-next-line @typescript-eslint/no-explicit-any this['__type'] = 'BaseClientSideWebPart'; // Bind the callbacks this.render = this.render.bind(this); this.onDispose = this.onDispose.bind(this); this.onTranspile = this.onTranspile.bind(this); this.renderError = this.renderError.bind(this); this.clearError = this.clearError.bind(this); this.renderCompleted = this.renderCompleted.bind(this); this._asyncRenderTimeout = this._asyncRenderTimeout.bind(this); this._internalHandleThemeChangedEvent = this._internalHandleThemeChangedEvent.bind(this); // Consume the new ThemeProvider service this._internalThemeProvider = this.context.serviceScope.consume(sp_component_base_1.ThemeProvider.serviceKey); // If it exists, get the theme variant this._internalThemeVariant = this._internalThemeProvider.tryGetTheme(); this.onThemeChanged(this._internalThemeVariant); // Register a handler to be notified if the theme variant changes this._internalThemeProvider.themeChangedEvent.add(this, this._internalHandleThemeChangedEvent); }; /** * Internal API to dispose the web part. * * See onDispose for more details. * * @internal */ BaseClientSideWebPart.prototype._internalDispose = function () { var _a; // this function will eventually call super.dispose(); this._disposeAfterRenderPromises(); (_a = this._internalThemeProvider) === null || _a === void 0 ? void 0 : _a.themeChangedEvent.remove(this, this._internalHandleThemeChangedEvent); }; /** * This API should be called to find the render props used to transpile the webpart * @param context - transpile context * * @internal */ BaseClientSideWebPart.prototype.onTranspile = function (context) { // Override in web part to provide transpiled render props. throw SPWebPartError_1.SPWebPartError.create(SPWebPartError_1.SPWebPartErrorCode.TranspileNotImplemented); }; /** * This API should be called by web parts that perform Async rendering. Those web part are required to override * the isRenderAsync API and return true. One such example is web parts that render content in an IFrame. The * web part initiates the IFrame rendering in the `render()` API but the actual rendering is complete only after * the iframe loading completes. * * @param error - error object indicating async render has completed with an error * @param didUpdate - used to override end performance time with sync render time */ BaseClientSideWebPart.prototype.renderCompleted = function (error, didUpdate) { if (error) { this._handleAsyncRenderFailed(error); } else { this._renderCompleted(didUpdate); } }; /** * This event method is called when the display mode of a web part is changed. * * @remarks * The default implementation of this API calls * the web part render method to re-render the web part with the new display mode. If a web part developer does not * want a full re-render to happen on display mode change, they can override this API and perform specific updates * to the web part DOM to switch its display mode. * * If the web part is initialized or re-initialized when switching to a different display mode then this * lifecycle method is not called. Example: SharePoint Site Page. * * @param oldDisplayMode - The old display mode. * * @virtual */ BaseClientSideWebPart.prototype.onDisplayModeChanged = function (oldDisplayMode) { var _this = this; _super.prototype.onDisplayModeChanged.call(this, oldDisplayMode); if (oldDisplayMode === this.displayMode) { return; } // Note: this quirk has existed for a very long time now. Long enough that it can be considered // a part of the design :(. Consider the scenario when the page is loaded with "&Mode=Edit" query // string parameter. As per the original design, the host, say, the ModernPage in this case, should call // the ClientSideWebPartManager.loadWebPart API with "displayMode == Edit" value. But that is not // the case. The ModernPage calls loadWebPart with "displayMode == Read" and then calls // ClientSideWebPartManager.setDisplayMode(displayMode == Edit). This opens the door for race condition // bugs to occur. Especially as the web part loading lifecycle is becoming more complex. To avoid these // race conditions from happening we need to to make sure all the first time rendering promises are // resolved before this._renderWithAccessibleTitle can be called. Promise.all(this._firstTimeRenderPromises) .then(function () { return _this._renderWithAccessibleTitle(); }) .catch(function (e) { return sp_diagnostics_1._TraceLogger.logVerboseData({ source: _this._logSource, message: e.message }); }); }; /** * This API should be used to refresh the contents of the PropertyPane. * * @remarks * This API is called at the end of the web part lifecycle on a page. It should be used to dispose any local * resources (i.e. DOM elements) that the web part is holding onto. This API is expected to be called in scenarios * like page navigation i.e. the host is transitioning from one page to another and disposes the page that is being * transitioned out. * * @virtual */ BaseClientSideWebPart.prototype.onDispose = function () { /* EMPTY BLOCK */ }; /** * This API is invoked when the web part container dom element width is changed, e.g. when the browser * browser window is resized and when the property pane is toggled open/closed. * * @param newWidth - Width (in pixels) of the container for the web part after the resize event. * @remarks * Web parts should utilize this method to perform operations such as potentially re-rendering components * based on the new available width for the web part. * * @virtual */ BaseClientSideWebPart.prototype.onAfterResize = function (newWidth) { /* EMPTY BLOCK */ }; /** * This API is called when a theme is initialized or changed on the page or for the current section. * @param theme - New theme for the page or section * @remarks * Developers sould not call render in overridden method. It can lead to unpredicted re-flow of the web part. * render will be called from the base class when needed. * * @virtual */ BaseClientSideWebPart.prototype.onThemeChanged = function (theme) { /* EMPTY BLOCK */ }; /** * This API should be used to render an error message in the web part display area. Also logs the error message * using the trace logger. * * @param error - An error object containing the error message to render. */ BaseClientSideWebPart.prototype.renderError = function (error) { this.context.statusRenderer.clearLoadingIndicator(this.domElement); this.context.statusRenderer.renderError(this.domElement, error); if (this.displayMode === sp_core_library_1.DisplayMode.Edit && !!this.context.manifest.isInternal && !!this.context.serviceScope && ((0, KillSwitches_1.isHandleDisposeRaceConditionKSActive)() || !this.isDisposed)) { var err = ''; if (!(0, KillSwitches_1.isAddMoreRenderErrorInfoKSActivated)()) { if (error.name) { err += 'name:' + error.name + ';'; } if (error.message) { err += 'msg:' + error.message + ';'; } if (this.context && this.context.webPartTag) { err += 'webPT:' + this.context.webPartTag + ';'; } if (this.iconImageUrl) { err += 'iconImageUrl:' + this.iconImageUrl + ';'; } if (this.title) { err += 'title:' + this.title + ';'; } if (this.previewImageUrl) { err += 'previewImageUrl:' + this.previewImageUrl + ';'; } if (this.context && this.context.pageContext && this.context.pageContext.web && this.context.pageContext.web.absoluteUrl) { err += 'absUrl:' + this.context.pageContext.web.absoluteUrl + ';'; } } else { err = error.message; } var errorDetails = { errorCode: "WebPartBase ".concat(this.context.manifest.alias, " Failure"), errorMessage: err, errorScenario: 'Render', errorStack: error === null || error === void 0 ? void 0 : error.stack, veto: 'WebPart Render Failure' }; (0, sp_edit_customer_promise_1._logFailuresForEditCustomerPromise)(errorDetails, this.context.serviceScope); } sp_diagnostics_1._TraceLogger.logError(this._logSource, error); }; /** * This API should be used to clear the error message from the web part display area. */ BaseClientSideWebPart.prototype.clearError = function () { this.context.statusRenderer.clearError(this.domElement); }; /** * Internal API to trigger a refresh to the WebPart's visual rendition. * In this implementation of the BaseWebPart class we call the render API. * * @internal */ BaseClientSideWebPart.prototype._refresh = function () { this._renderWithAccessibleTitle(); }; /** * Internal API triggered by a dynamic property's callback. * In this implementation of the BaseWebPart class we call the render API, only if rendered once. * * @internal */ BaseClientSideWebPart.prototype._dynamicPropertyRefresh = function () { if (this.renderedOnce) { this.render(); } }; /** * Waits for all render promises to resolve before disposing. */ BaseClientSideWebPart.prototype._disposeAfterRenderPromises = function () { var _this = this; if (!this.isDisposed && !(0, KillSwitches_1.isChainDisposeCallsAfterOninitKSActivated)() && (0, Flights_1.isWEXWebPartOnDisposePromiseChainEnabled)()) { this._internalIsDisposing = true; // VSO: 1268748 // wait for rendering to complete before disposing this component as this would put the application // in a bad state since (this.context) is deleted in the super.dispose method. // Note: this logic mirrors what we do in onDisplayModeChanged with more safe guards Promise.all(this._firstTimeRenderPromises).then(function () { _this._internalIsDisposing = false; _super.prototype._internalDispose.call(_this); }, function (_a) { var message = _a.message; sp_diagnostics_1._TraceLogger.logVerboseData({ source: _this._logSource, message: message }); // if the render promises fails then bail and just dispose _this._internalIsDisposing = false; _super.prototype._internalDispose.call(_this); }); } else { _super.prototype._internalDispose.call(this); } }; /** * @returns extends base width cache key with additional info to minimize reflows. * Otherwise if base cache key does not exist return undefined. * @internal */ BaseClientSideWebPart.prototype._getExtendedWidthCacheKey = function () { var baseKey = this.context.widthCacheKey; return baseKey ? "".concat(this.displayMode, "-").concat(baseKey) : undefined; }; /** * The actual initialization and rendering of the Web part starts when it is close enough * to the Viewport */ BaseClientSideWebPart.prototype._onInViewport = function () { var _this = this; // Render promise callback should be defined at this time. if (!this._renderPromiseResolver || !this._renderPromiseRejecter) { throw SPWebPartError_1.SPWebPartError.create(SPWebPartError_1.SPWebPartErrorCode.RenderPromiseUndefined, this.context.webPartTag); } // Perform web part initialization and then render the web part. var initPromise = this.onInit(); if (!initPromise) { var error = SPWebPartError_1.SPWebPartError.create(SPWebPartError_1.SPWebPartErrorCode.OnInitReturnedNullPromise, this.context.webPartTag); this._renderPromiseRejecter(error); this._clearRenderPromises(); return; } this._firstTimeRenderPromises.push(initPromise); initPromise .then(function () { sp_telemetry_1._PerformanceLogger.markComponent(_this.context.webPartTag, 'init'); var getDataPromise = Promise.resolve(); // Perform web part initialization and then render the web part. getDataPromise = _this._internalGetData(); if (!getDataPromise) { throw SPWebPartError_1.SPWebPartError.create(SPWebPartError_1.SPWebPartErrorCode.GetDataReturnedNullPromise, _this.context.webPartTag); } _this._firstTimeRenderPromises.push(getDataPromise); var renderPromise = getDataPromise.then(function () { sp_telemetry_1._PerformanceLogger.markComponent(_this.context.webPartTag, 'getDataComplete'); // Clear the loading indicator _this.context.statusRenderer.clearLoadingIndicator(_this.domElement); if (_this.isRenderAsync) { _this._startAsyncRenderGuardTimer(); } _this._renderWithAccessibleTitle(); // Record the time framework has finished calling render(). By this time framework is accountable // for loading web part module through fasted CDN and loading web part data through appropriate // techniques like Web part cache and synchronous time to execute web part's render() method. sp_telemetry_1._PerformanceLogger.markComponent(_this.context.webPartTag, 'syncRender'); if (!(0, KillSwitches_1.isIsolatedACEWPRenderAsyncKSActivated)() && _this.isRenderAsync) { _this._syncRenderTime = sp_telemetry_1._PerformanceLogger.now(); } else { // If rendering happened synchronously, simply complete the rendering cycle. // Else, create a new promise and wait for it to be resolved. The resolution // can happen when the web part completes the promise or when the timeout fires. _this._resolveOrRejectOnRenderPromise(); } }); return renderPromise; }) .catch(function (e) { if (_this._renderPromiseRejecter) { _this._renderPromiseRejecter(e); _this._clearRenderPromises(); } }); }; /** * Wraps render to ensure any type of rendering has access to the latest context * to provide the most accurate accessible info to screen readers. */ BaseClientSideWebPart.prototype._renderWithAccessibleTitle = function () { sp_telemetry_1._PerformanceLogger.devMark("webpart(".concat(this.context.webPartTag, ")._renderWithAccessibleTitle")); var accessibleRoot = (0, KillSwitches_1.isAccessibleRootKSActivated)() ? this.domElement : this.domElement.parentElement; this.render(); // The accessible label is only required in edit mode. It is also not required for mobile devices // which only provide view mode if (this.displayMode === sp_core_library_1.DisplayMode.Edit) { // Render the accessible description after and associate by ID to avoid re-rendering the whole zone // when webpart updates contextual info. var accessibleContext = this.accessibleTitle || this._getDefaultAccessibleTitle(); if (accessibleContext) { // Keep ID in sync with ControlZone.render var contextualLabelId = "cswpAccessibleLabelContextual_".concat(this.context.instanceId); var accessibleDiv = accessibleRoot.querySelector("#".concat(contextualLabelId)); var isNewLabelElement = !accessibleDiv; if (isNewLabelElement) { accessibleDiv = document.createElement('div'); accessibleDiv.id = contextualLabelId; accessibleDiv.className = cswp_base_module_scss_1.default.screenReaderOnly; accessibleDiv.setAttribute('aria-hidden', 'true'); } accessibleDiv.textContent = accessibleContext; if (isNewLabelElement) { accessibleRoot.appendChild(accessibleDiv); } } // Perform classic page fixup. It should only be called in edit mode otherwise it will // make anchor elements not working in view mode. ClassicPageUtils_1.default.disableAutomaticPostbacks(this.domElement, sp_core_library_1.Environment.type); } }; /** * Start async guard timer. This timer is to help avoid losing performance markers for a web part * that renders asynchronously but does not call the `renderCompleted` API; */ BaseClientSideWebPart.prototype._startAsyncRenderGuardTimer = function () { var _this = this; // Note: the timer is 25 seconds because after 30 seconds, the PerformanceLogger will auto expire // the log timer and we will lose data. This value needs to be smaller than that. this._clearAsyncRenderGuardTimer(); this._asyncRenderGuardTimer = window.setTimeout(function () { _this._asyncRenderTimeout(); }, 25000); if (!(0, KillSwitches_1.isAsyncCompleteKSActivated)() && this._asyncRenderCompleteCalled === true) { // Now we can process this render complete. this._renderCompleted(this._asyncRenderCompleteDidUpdate); this._asyncRenderCompleteCalled = false; this._asyncRenderCompleteDidUpdate = undefined; } }; /** * Render completed. * * @param didUpdate - used to override end performance time with sync render time. */ BaseClientSideWebPart.prototype._renderCompleted = function (didUpdate) { if (this._asyncRenderGuardTimer) { this._clearAsyncRenderGuardTimer(); this._asyncRenderQosMonitor.writeSuccess({ alias: this.context.manifest.alias, isInternal: this.context.manifest.isInternal, webPartId: this.context.manifest.id }); if (!(0, KillSwitches_1.isIsolatedACEWPRenderAsyncKSActivated)()) { this._resolveOrRejectOnRenderPromise(undefined, didUpdate); } else { this._resolveOrRejectOnRenderPromise(); } } else { if (!(0, KillSwitches_1.isAsyncCompleteKSActivated)()) { // We aren't quite ready to handle an async-render-complete, so note that // it is done, and we will trigger it when we are ready. this._asyncRenderCompleteCalled = true; this._asyncRenderCompleteDidUpdate = didUpdate; } } }; BaseClientSideWebPart.prototype._handleAsyncRenderFailed = function (error) { if (this._asyncRenderGuardTimer) { this._clearAsyncRenderGuardTimer(); this._logAsyncRenderError(error, 'Failed'); this._resolveOrRejectOnRenderPromise(error); } }; /** * Async render timed out. Log error information and */ BaseClientSideWebPart.prototype._asyncRenderTimeout = function () { // There is a potential race condition when the async guard timer gets queued into the javascript // task queue right at the time when renderCompleted API gets called. Protect against that. if (this._asyncRenderGuardTimer) { this._clearAsyncRenderGuardTimer(); // At this time we only log an error and fail the QOS monitor when the async guard timer fires. var error = SPWebPartError_1.SPWebPartError.create(SPWebPartError_1.SPWebPartErrorCode.RenderCompletedCallNotCalled, this.context.webPartTag); this._logAsyncRenderError(error, 'Timeout'); this._resolveOrRejectOnRenderPromise(); } }; BaseClientSideWebPart.prototype._logAsyncRenderError = function (error, qosFailureTag) { sp_diagnostics_1._TraceLogger.logErrorData({ source: this._logSource, error: error, serviceScope: this.context.serviceScope }); this._asyncRenderQosMonitor.writeUnexpectedFailure(qosFailureTag, error, { alias: this.context.manifest.alias, isInternal: this.context.manifest.isInternal, webPartId: this.context.manifest.id, instanceId: this.instanceId }); }; BaseClientSideWebPart.prototype._clearAsyncRenderGuardTimer = function () { if (this._asyncRenderGuardTimer) { window.clearTimeout(this._asyncRenderGuardTimer); this._asyncRenderGuardTimer = undefined; } }; /** * This is called for every web part whether sync or async once rendering is completed. * * @param error - error object indicating asycn render has completed with an error * @param didUpdate - used to override end performance time with sync render time. */ BaseClientSideWebPart.prototype._resolveOrRejectOnRenderPromise = function (error, didUpdate) { this._renderedOnce = true; sp_telemetry_1._PerformanceLogger.devMark("webpart(".concat(this.context.webPartTag, ").complete")); if (error) { if (this._renderPromiseRejecter) { this._renderPromiseRejecter(error); } } else { if (this._renderPromiseResolver) { this._renderPromiseResolver((0, KillSwitches_1.isIsolatedACEWPRenderAsyncKSActivated)() || didUpdate ? sp_telemetry_1._PerformanceLogger.now() : this._syncRenderTime); } } this._clearRenderPromises(); }; BaseClientSideWebPart.prototype._clearRenderPromises = function () { this._renderPromiseResolver = undefined; this._renderPromiseRejecter = undefined; // Reset minHeight this.domElement.style.minHeight = null; }; BaseClientSideWebPart.prototype._internalHandleThemeChangedEvent = function (args) { this._internalThemeVariant = args.theme; this.onThemeChanged(this._internalThemeVariant); // // we call render only if the onThemeChanged was overridden in a child class // if (this.onThemeChanged !== BaseClientSideWebPart.prototype.onThemeChanged) { this.render(); } }; return BaseClientSideWebPart; }(BaseWebPart_1.default)); exports.default = BaseClientSideWebPart; //# sourceMappingURL=BaseClientSideWebPart.js.map