123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857 |
- 'use strict';
- define(['underscore', './VisRenderState', './VisRenderTrace', '../../DynamicFileLoader', '../../widgets/livewidget/util/VisUtil', '../../visualizations/vipr/VIPRLibraries', '../../lib/@waca/core-client/js/core-client/ui/core/Events', '../../lib/@waca/dashboard-common/dist/api/Error'], function (_, VisRenderState, VisRenderTrace, DynamicFileLoader, VisUtil, VIPRLibraries, Events, APIError) {
- 'use strict';
-
- var DEFAULT_SEQUENCE = [{
- id: 'visView',
- modulePath: './sequence/VisViewTask'
- }, {
- id: 'visControl',
- dependencies: ['visView'],
- modulePath: './sequence/VisControlTask'
- }, {
- id: 'visSpec',
- dependencies: ['visControl'],
- modulePath: './sequence/VisSpecTask'
- }, {
- id: 'data',
- dependencies: ['visSpec'],
- modulePath: './sequence/DataTask'
- }, {
- id: 'resultsdatareader',
- dependencies: ['data'],
- modulePath: './sequence/ResultsDataReaderTask'
- }, {
- id: 'highlighter',
- dependencies: ['resultsdatareader'],
- modulePath: './sequence/HighlighterTask'
- }, {
- id: 'setData',
- dependencies: ['resultsdatareader'],
- modulePath: './sequence/SetDataTask'
- }, {
- id: 'render',
- dependencies: ['highlighter'],
- modulePath: './sequence/RenderTask'
- }];
- var BASE_PATH = 'dashboard-analytics/visualizations/renderer/';
- var ERR_RENDER_ABORTED_MSG = 'widget render aborted';
- var VisRenderSequence = Events.extend({
- init: function init(attributes) {
- VisRenderSequence.inherited('init', this, [attributes]);
- this.logger = attributes.ownerWidget.logger;
- this.ownerWidget = attributes.ownerWidget;
- this.dashboardApi = attributes.ownerWidget.getDashboardApi();
- this.content = this.ownerWidget.content;
- this.visAPI = attributes.visModel;
-
- this._renderState = new VisRenderState();
- this._sequence = null;
- this._trace = new VisRenderTrace(this._renderState);
- this.widgetExtraStepsIdentifier = '';
- this._renderId = -1;
- },
- remove: function remove() {
- this._getRenderState().remove();
- this._renderState = null;
- },
-
- isActive: function isActive() {
- return !!this._renderState;
- },
-
- render: function render(options) {
- if (this.logger) {
- this.logger.debug('Data widget render start', this.visAPI);
- }
- options = options || { refreshAll: true, initial: true };
- return this.reRender(options);
- },
- _getRenderState: function _getRenderState() {
- if (this._renderState) {
- return this._renderState;
- } else {
- throw new Error(ERR_RENDER_ABORTED_MSG);
- }
- },
-
- _isRenderSequenceAPIReady: function _isRenderSequenceAPIReady() {
- var isReady = typeof this._renderAPI !== 'undefined';
- if (isReady === false) {
-
- this._renderAPI = this.content.getFeature('RenderSequence.internal');
- isReady = typeof this._renderAPI !== 'undefined';
- if (isReady) {
- this._renderAPI.registerRenderEngine(this);
- }
- }
- return isReady;
- },
-
- _getTaskProcessor: function _getTaskProcessor() {
- var taskProcessor = {};
- if (this._isRenderSequenceAPIReady() === true) {
- taskProcessor.startTaskExecution = function (task, renderContext) {
- if (task.id === 'data') {
- return this._renderAPI.startTaskExecution({ task: task, renderContext: renderContext });
- } else {
- return task.instance.process(renderContext);
- }
- }.bind(this);
- taskProcessor.resolveTaskExecution = function (taskExecution, task, renderContext) {
- if (task.id === 'data') {
- this._renderAPI.resolveTaskExecution({ taskExecution: taskExecution, task: task, renderContext: renderContext });
- } else {
- taskExecution.resolve();
- }
- }.bind(this);
- taskProcessor.rejectTaskExecution = function (taskExecution, error, task, renderContext) {
- if (task.id === 'data') {
- this._renderAPI.rejectTaskExecution({ taskExecution: taskExecution, task: task, renderContext: renderContext, error: error });
- } else {
- taskExecution.reject(error);
- }
- }.bind(this);
- } else {
- taskProcessor.startTaskExecution = function (task, renderContext) {
- return task.instance.process(renderContext);
- }.bind(this);
- taskProcessor.resolveTaskExecution = function (taskExecution) {
- taskExecution.resolve();
- }.bind(this);
- taskProcessor.rejectTaskExecution = function (taskExecution, error) {
- taskExecution.reject(error);
- }.bind(this);
- }
- return taskProcessor;
- },
-
- reRender: function reRender(options) {
- var _this = this,
- _arguments = arguments;
- return VisUtil.validateVisDefinition(this.content, this.dashboardApi, { visId: this.ownerWidget.model.visId }).then(function (isValid) {
- if (isValid || options && options.initial) {
- var runRenderId = ++_this._renderId;
- options = options || {
- refresh: {}
- };
- options.renderId = runRenderId;
- return _this._render(options).then(function (renderContext) {
-
- if (options.refreshAll || options.refresh && options.refresh.data) {
-
- _this.dashboardApi.triggerDashboardEvent('widget:rerendered', {
- sender: _this.ownerWidget.id,
- refreshAll: options.refreshAll
- });
- }
- _this._getRenderState().cleanRenderContextPool();
- return renderContext;
- }).catch(function (error) {
- if (_this.isActive()) {
-
-
-
- var errorMessage = error && (error.message || error.msg) || 'dwErrorRenderingVisualization';
- var state = _this.content.getFeature('state');
- var err = state.getError();
- var dataSourceName = _this.visAPI && _this.visAPI.getModule() && _this.visAPI.getModule().getSourceName();
- if (!dataSourceName) {
- if (errorMessage === 'dwErrorMissingDataset') {
- dataSourceName = err && err._params && err._params.datasetName;
- } else {
- dataSourceName = ' ';
- }
- }
- var isLastRun = _this.isLastRun({ id: runRenderId });
- var knownErrors = [ERR_RENDER_ABORTED_MSG,
-
-
- 'dwErrorStaleRequest', 'unSupportedPromptType', 'cancelPromptDialog'];
- var throwableErrors = [
-
- 'promptingIsDisabled'];
- if (throwableErrors.indexOf(errorMessage) > -1) {
- throw error;
- }
- if (knownErrors.indexOf(errorMessage) === -1) {
- var errorInfo = void 0;
- if (error && error.errorInfo) {
- errorInfo = error.errorInfo;
- } else if (err && err.getParams) {
- var params = err.getParams();
- errorInfo = params ? params.errorInfo : null;
- }
- if (isLastRun) {
- _this.showError(errorMessage, {
- 'datasetName': dataSourceName,
- errorInfo: errorInfo
- });
- }
-
- if (!errorInfo || errorInfo.errorCode !== VIPRLibraries.LOAD_DEFINITION_ERROR) {
- _this.logger.error('An error occurred while re-rendering test', _arguments, _this.visAPI, error);
- }
- } else {
- _this.logger.warn(errorMessage, { datasetName: dataSourceName });
- }
- } else {
-
-
- _this.logger.debug('An error occurred while re-rendering', _arguments, _this.visAPI);
- }
- });
- }
- });
- },
-
- onChangeRenderer: function onChangeRenderer(event) {
- var sender = event && event.sender;
- this._getRenderState().lastSizeRendered = null;
- this._getRenderState().reloadAllRenderSteps();
- if (sender !== 'UndoRedoController') {
- var undoRedoTransactionId = event && event.data && event.data.undoRedoTransactionId;
- var options = {
- undoRedoTransactionId: undoRedoTransactionId,
- transactionToken: event && event.data && event.data.transactionToken
- };
- this.ownerWidget.setPreferredSize(this.visAPI.getDefinition().preferredSize, options);
- }
- return this.render({ refreshAll: true, initial: false });
- },
-
- getLastSizeRendered: function getLastSizeRendered() {
- return this._renderState ? this._renderState.lastSizeRendered : null;
- },
-
- firstRenderComplete: function firstRenderComplete() {
- return this._getRenderState().firstRenderComplete;
- },
-
- _render: function _render(options) {
- var contentStateError = this.content && this.content.getFeature('state').getError();
- var isMissingDataSource = contentStateError && contentStateError.getMessage() === 'dwErrorMissingDataset';
- if (isMissingDataSource || !options.refresh && !options.refreshAll) {
- var widgetError = this.ownerWidget && this.ownerWidget.getAPI().getVisApi().getInvalidReason();
- var _contentStateError = this.content && this.content.getFeature('state').getError();
- if (widgetError || _contentStateError) {
-
- return Promise.reject(new Error(widgetError && widgetError.msg || _contentStateError && _contentStateError.getMessage()));
- }
- }
- this.ownerWidget.renderStart(options);
-
-
-
-
- if (this._isRenderSequenceAPIReady()) {
- return this._renderAPI.triggerRenderSequence(options);
- } else {
- return this.process(options);
- }
- },
- _initializeStep: function _initializeStep(step) {
- this._getRenderState().initCurrentContext(step);
- },
-
- _isStepComplete: function _isStepComplete(renderContext, stepName) {
- var contextForThisStep = this._getRenderState().getCurrentContext(stepName);
- var contextMatch = renderContext === contextForThisStep;
- return !contextMatch || contextMatch && renderContext[stepName];
- },
-
- _completeStep: function _completeStep(renderContext, step, value) {
- renderContext[step] = value;
- var currentStep = this._renderState ? this._renderState.getCurrentContext(step) : null;
- var stepMatch = currentStep && currentStep.id === renderContext.id;
- return !!currentStep && stepMatch;
- },
-
- getVisControl: function getVisControl() {
- return this._getRenderState().getCurrentContextData('visControl');
- },
- getVisSpec: function getVisSpec() {
- return this._getRenderState().getCurrentContextData('visSpec');
- },
-
- createRenderSequence: function createRenderSequence() {
- var _this2 = this;
- var sequence = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
-
- this._sequence = DEFAULT_SEQUENCE.concat([]);
- var newSequences = Array.isArray(sequence) ? sequence : [sequence];
- newSequences.forEach(function (newSequence) {
- var index = _this2._sequence.findIndex(function (defaultSequence) {
- return defaultSequence.id === newSequence.id;
- });
- if (index === -1) {
- _this2._sequence.push(newSequence);
- } else {
- _this2._sequence[index] = newSequence;
- }
- });
- this._createDependenciesFromBlockers();
-
- this._sequence.forEach(function (step) {
- _this2._validateDependencies(step.id);
- });
- return this._sequence;
- },
- _createDependenciesFromBlockers: function _createDependenciesFromBlockers() {
- var _this3 = this;
- this._sequence.forEach(function (step) {
- if (step.blocks) {
- step.blocks.forEach(function (id) {
- var blockedTask = _this3._getSequenceTask(id);
- if (blockedTask) {
- var dependencies = blockedTask.dependencies || [];
- if (dependencies.indexOf(step.id) === -1) {
- dependencies.push(step.id);
- }
- }
- });
- delete step.blocks;
- }
- });
- },
- _getSequenceTask: function _getSequenceTask(id) {
- return this._sequence.find(function (item) {
- return item.id === id;
- });
- },
- _validateDependencies: function _validateDependencies(taskId, currentDeps) {
- var _this4 = this;
- var dependencies = currentDeps || [];
- if (dependencies.indexOf(taskId) !== -1) {
- throw new Error('The task with id "' + taskId + '" has a a circular dependency: ' + currentDeps);
- }
- dependencies.push(taskId);
- var task = this._getSequenceTask(taskId);
- if (task.dependencies) {
- task.dependencies.forEach(function (depItem) {
- if (!_this4._getSequenceTask(depItem)) {
- throw new Error('The task with id "' + taskId + '" has a missing dependency "' + depItem + '"');
- }
- var clonedDepArray = dependencies.concat([]);
- _this4._validateDependencies(depItem, clonedDepArray);
- });
- }
- },
-
- _createExecutionState: function _createExecutionState(renderContext) {
- var _this5 = this;
-
-
-
-
-
- var previousExecutionStateMap = null;
- if (this._isExecuting) {
- previousExecutionStateMap = this.executionStateMap;
- }
- this.executionStateMap = {};
-
- this._sequence.forEach(function (step) {
- var execution = {
- renderId: renderContext.id,
- id: step.id
- };
- _this5.executionStateMap[step.id] = execution;
- execution.whenStepIsComplete = new Promise(function (resolve, reject) {
- execution.resolve = resolve;
- execution.reject = reject;
- });
-
- execution.whenStepIsComplete.catch(function (error) {
-
- });
- });
-
- this._sequence.forEach(function (step) {
- var dependentStepCompletePromises = [];
- if (step.dependencies) {
- step.dependencies.forEach(function (dep) {
- dependentStepCompletePromises.push(_this5.executionStateMap[dep].whenStepIsComplete);
- _this5._trace.taskDependency(step, renderContext, dep);
-
-
- var previousExecutionStepState = previousExecutionStateMap && previousExecutionStateMap[dep];
- if (previousExecutionStepState && !_this5._isPartOfTheCurrentRun(renderContext, dep)) {
- dependentStepCompletePromises.push(previousExecutionStepState.whenStepIsComplete);
- _this5._trace.taskDependency(step, renderContext, {
- renderId: previousExecutionStepState.renderId,
- id: dep
- });
- }
- });
- }
- _this5.executionStateMap[step.id].whenDepsAreComplete = Promise.all(dependentStepCompletePromises);
- });
- },
- getTaskExecutionState: function getTaskExecutionState(id) {
- return this.executionStateMap[id];
- },
-
- isLastRun: function isLastRun(renderContext) {
- return renderContext.id === this._renderId;
- },
-
- _isPartOfTheCurrentRun: function _isPartOfTheCurrentRun(renderContext, stepName) {
- var currentStepContext = this._getRenderState().getCurrentContext(stepName);
- return currentStepContext && currentStepContext.id === renderContext.id;
- },
-
- _getAllDependencies: function _getAllDependencies(id, sequence) {
- var _this6 = this;
- var dependencies = {};
- _.each(sequence, function (step) {
- if (step.dependencies && step.dependencies.indexOf(id) > -1) {
- dependencies[step.id] = step;
- _.extend(dependencies, _this6._getAllDependencies(step.id, sequence));
- }
- });
- return dependencies;
- },
-
- _applyRefreshDependencies: function _applyRefreshDependencies(sequence, options) {
- var _this7 = this;
- if (options.refresh) {
-
- _.each(options.refresh, function (refreshVal, id) {
- if (refreshVal) {
- _.each(_this7._getAllDependencies(id, sequence), function (step) {
- options.refresh[step.id] = true;
- });
- }
- });
- }
- return options;
- },
-
- _getWidgetStepsIdentifier: function _getWidgetStepsIdentifier(steps) {
- return steps.map(function (step) {
- return step.id;
- }).toString();
- },
-
- _ensureSequenceUpToDate: function _ensureSequenceUpToDate() {
-
-
-
-
- var widgetExtraSteps = this.ownerWidget.getExtraRenderSequenceSteps();
-
- if (this._isRenderSequenceAPIReady()) {
- widgetExtraSteps = widgetExtraSteps.concat(this._renderAPI.getProvidersRenderStepList());
- }
- if (this.widgetExtraStepsIdentifier !== this._getWidgetStepsIdentifier(widgetExtraSteps)) {
-
- this._sequence = null;
- }
- if (!this._sequence) {
- this.createRenderSequence(widgetExtraSteps);
-
- this.widgetExtraStepsIdentifier = this._getWidgetStepsIdentifier(widgetExtraSteps);
- }
- },
-
- process: function process(options) {
- var _this8 = this;
- this._ensureSequenceUpToDate();
- return this._loadTasks(this._sequence).then(function (tasks) {
- return _this8._preProcessDataOptions(options).then(function (options) {
- options = _this8._applyRefreshDependencies(_this8._sequence, options);
- var renderContext = _this8._renderState.addRenderContext(options);
- _this8._logRenderContext('_render', renderContext);
- _this8._trace.startRender(tasks, renderContext, options);
- return _this8._processTasks(tasks, renderContext);
- });
- });
- },
-
- _preProcessDataOptions: function _preProcessDataOptions(options) {
- if (options && options.refresh && options.refresh.dataIfQueryChanged) {
- delete options.refresh.dataIfQueryChanged;
- return this._queryChanged().then(function (changed) {
- if (changed.isRenderNeeded) {
- options.refresh.data = true;
- } else {
- delete options.refresh.data;
- }
- return options;
- });
- }
- return Promise.resolve(options);
- },
- _queryChanged: function _queryChanged() {
-
- if (this.ownerWidget.useNewQueryApi()) {
- var internalQueryExecution = this.content.getFeature('DataQueryExecution.internal');
- return Promise.resolve({
- isRenderNeeded: internalQueryExecution.queryChanged()
- });
- } else {
- return this.visAPI.queryChanged();
- }
- },
-
- _processTasks: function _processTasks(tasks, renderContext) {
- var _this9 = this;
- this._isExecuting = true;
-
- this._createExecutionState(renderContext);
- var taskProcessor = this._getTaskProcessor();
-
-
- renderContext.useAPI = this.ownerWidget.useNewQueryApi();
- var processTaskPromises = [];
-
- tasks.forEach(function (task) {
- var taskExecution = _this9.getTaskExecutionState(task.id);
- processTaskPromises.push(taskExecution.whenDepsAreComplete.then(function () {
- _this9._trace.startTask(task, renderContext);
- try {
- return taskProcessor.startTaskExecution(task, renderContext).then(function () {
- _this9._trace.endTask(task, renderContext, 'SUCCEEDED');
- taskProcessor.resolveTaskExecution(taskExecution, task, renderContext);
- }).catch(function (err) {
- _this9._trace.endTask(task, renderContext, 'FAILED', err);
- taskProcessor.rejectTaskExecution(taskExecution, err, task, renderContext);
- throw err;
- });
- } catch (err) {
- _this9._trace.endTask(task, renderContext, 'FAILED', err);
- taskProcessor.rejectTaskExecution(taskExecution, err, task, renderContext);
- throw err;
- }
- }, function (err) {
- _this9._trace.endTask(task, renderContext, 'DEPENDENCY_FAILED', err);
- taskExecution.reject(err);
- throw err;
- }));
- });
- return Promise.all(processTaskPromises).then(function () {
- _this9._isExecuting = false;
- return renderContext;
- });
- },
- _resolvePath: function _resolvePath(path) {
- if (!path || path.length === 0) {
- return null;
- }
- var resolved = path;
- var relativeIndex = path.indexOf('./');
- if (relativeIndex > -1) {
-
- resolved = BASE_PATH + path.substr(relativeIndex + 2);
- }
- return resolved;
- },
- _getSequenceModulePaths: function _getSequenceModulePaths(sequence) {
- var _this10 = this;
- return _.chain(sequence)
-
- .map(function (_ref) {
- var modulePath = _ref.modulePath;
- return _this10._resolvePath(modulePath);
- }).value();
- },
- _loadTasks: function _loadTasks(sequence) {
- var _this11 = this;
- var paths = this._getSequenceModulePaths(sequence);
- return DynamicFileLoader.load(paths).then(function (Modules) {
- return _.map(sequence, function (step, index) {
- var Module = step.module || Modules[index];
- return {
- instance: new Module({
- id: step.id,
- owner: _this11,
- ownerWidget: _this11.ownerWidget,
- logger: _this11.logger,
- visAPI: _this11.visAPI,
- dashboardApi: _this11.dashboardApi,
- content: _this11.content
- }, step.moduleOptions),
- id: step.id
- };
- });
- });
- },
- _logRenderContext: function _logRenderContext(stage, renderContext) {
- var renderTimeInfo = 'render sequence stage:' + stage + ' {rendering ' + this.visAPI.id + ':';
- _.each(_.keys(renderContext), function (key) {
- if (key !== 'id') {
- var c = this._getRenderState().getCurrentContext(key);
- renderTimeInfo += key + '(' + (c ? c.id : '<NULL>') + ')';
- }
- }.bind(this));
- var model = this.ownerWidget.model ? this.ownerWidget.model.toJSON() : 'NULL';
- this.logger.debug(renderTimeInfo + ', id=' + renderContext.id + '}', model);
- },
- showError: function showError(msg, params, type) {
- var state = this.content.getFeature('state.internal');
- if (state) {
- var error = new APIError({ 'msg': msg, 'params': params }, { 'type': type });
- state.setError(error);
- }
- },
- enableTrace: function enableTrace() {
- var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
- return this._trace.enable(enable);
- },
- clearTrace: function clearTrace() {
- return this._trace.clear();
- },
- getTrace: function getTrace() {
- return this._trace.getTrace();
- }
- });
- return VisRenderSequence;
- });
|