Split quota view in subviews.

Every subview is in charge of its own rendering now.
pull/12037/head
nobuti 8 years ago
parent b55a17e030
commit 0239724cd8

@ -5,5 +5,8 @@
"browser": true,
"jasmine": true
},
"extends": "semistandard"
"extends": "semistandard",
"globals": {
"_t": true
}
}

@ -0,0 +1,22 @@
var CoreView = require('backbone/core-view');
module.exports = CoreView.extend({
initialize: function (opts) {
this.template = opts.template;
this.model = opts.model;
this._initBinds();
},
render: function () {
var html = this.template(this.model.attributes);
this.clearSubViews();
this.$el.empty();
this.$el.append(html);
return this;
},
_initBinds: function () {
this.listenTo(this.model, 'change:isDisabled', this.render);
}
});

@ -2,7 +2,7 @@ var _ = require('underscore');
var Backbone = require('backbone');
var CoreView = require('backbone/core-view');
var template = require('./analysis-controls.tpl');
var InfoboxView = require('../../../../components/infobox/infobox-view');
// var InfoboxView = require('../../../../components/infobox/infobox-view');
var InfoboxFactory = require('../../../../components/infobox/infobox-factory');
var InfoboxModel = require('../../../../components/infobox/infobox-model');
var InfoboxCollection = require('../../../../components/infobox/infobox-collection');
@ -12,6 +12,8 @@ var AnalysesQuotaProvider = require('./analyses-quota/analyses-quota-provider');
var AnalysesQuotaEstimation = require('./analyses-quota/analyses-quota-estimation-input');
var AnalysesQuotaEnough = require('./analyses-quota/analyses-quota-enough');
var checkAndBuildOpts = require('../../../../helpers/required-opts');
var AnalysisButtonView = require('./analysis-button-view');
var AnalysisQuotaView = require('./analysis-quota-view');
var REQUIRED_OPTS = [
'formModel',
@ -43,7 +45,8 @@ module.exports = CoreView.extend({
this._viewModel = new Backbone.Model({
userFetchModelState: this._quotaInfo.getState(),
isNewAnalysis: !opts.analysisNode,
hasChanges: !opts.analysisNode
hasChanges: !opts.analysisNode,
type: this._formModel.get('type')
});
this._infoboxModel = new InfoboxModel({
@ -67,44 +70,50 @@ module.exports = CoreView.extend({
var fetchingState = this._viewModel.get('userFetchModelState');
// If no dataservice, requiresQuota returns false because the model doesn't exist and it's converted to boolean
var requiresQuota = AnalysesQuotaOptions.requiresQuota(type, this._quotaInfo);
var html;
var view;
if (this._isAnalysisDone() && !this._hasChanges()) {
html = this._html();
view = this._createButtonView();
} else {
// If the analysis doesn't require quota, let's not wait or check the fetching state
if (!requiresQuota) {
html = this._html();
view = this._createButtonView();
} else {
// If analysis requires quota info, we should wait for the quota info
if (fetchingState === 'fetching' || fetchingState === 'error') {
html = this._createQuotaView();
view = this._createQuotaView();
} else if (fetchingState === 'fetched') {
if (this._canSave() && requiresQuota) {
html = this._createQuotaView();
view = this._createQuotaView();
} else {
html = this._html();
view = this._createButtonView();
}
}
}
}
this.$el.html(html);
this.addView(view);
this.$el.append(view.render().el);
return this;
},
_initBinds: function () {
this._formModel.on('change', _.debounce(function () {
this._viewModel.set('hasChanges', true);
this._fetchQuotaIfNeeded(this.render.bind(this));
}, 100), this);
var isAnalysisDone = this._isAnalysisDone();
var isDone = this._viewModel.get('isNewAnalysis') || isAnalysisDone;
var canSave = this._formModel.isValid() && isDone;
this.add_related_model(this._formModel);
this._viewModel.set({
hasChanges: true,
type: this._formModel.get('type'),
isDisabled: !canSave
});
this._viewModel.on('change:userFetchModelState', function (model, userFetchModelState) {
this.render();
}, this);
this._fetchQuotaIfNeeded();
}, 100), this);
this.add_related_model(this._formModel);
this._viewModel.on('change:type', this.render, this);
this.add_related_model(this._viewModel);
if (this._analysisNode) {
@ -113,14 +122,12 @@ module.exports = CoreView.extend({
}
},
_fetchQuotaIfNeeded: function (notNeededCallback) {
_fetchQuotaIfNeeded: function () {
var type = this._formModel.get('type');
var isValid = this._formModel.isValid();
var quota = this._quotaInfo;
if ((quota.needsCheck() || AnalysesQuotaOptions.requiresQuota(type, quota)) && isValid) {
this._fetchQuota();
} else {
notNeededCallback();
}
},
@ -131,6 +138,7 @@ module.exports = CoreView.extend({
this._quotaInfo.fetch({
success: function () {
this._viewModel.set({userFetchModelState: 'fetched'});
this._infoboxModel.set('state', 'ready');
}.bind(this),
error: function (error) {
this._viewModel.set({userFetchModelState: 'error', error: error});
@ -139,13 +147,20 @@ module.exports = CoreView.extend({
});
},
_html: function () {
return template({
label: this._formModel.get('persisted')
_createButtonView: function () {
var label = this._formModel.get('persisted')
? _t('editor.layers.analysis-form.apply-btn')
: _t('editor.layers.analysis-form.create-btn'),
: _t('editor.layers.analysis-form.create-btn');
this._viewModel.set({
label: label,
isDisabled: !this._canSave()
});
return new AnalysisButtonView({
template: template,
model: this._viewModel
});
},
_createQuotaView: function () {
@ -161,30 +176,24 @@ module.exports = CoreView.extend({
var self = this;
this._payload = {};
this._payload.type = type;
var payload = {};
payload.type = type;
var errorCallback = function (error) {
this._viewModel.set('error', error);
this._infoboxModel.set('state', 'error');
}.bind(this);
var dsReady = quotaData.isReady();
// Only checks api if analysis belongs to a service with quota
if (service !== null && isFetched && formModel.isValid() && dsReady) {
// get the estimation for this analysis
AnalysesQuotaEstimation.fetch(query)
.then(function (data) {
var checkEnoughQuota = function (data) {
// Apply transformation to the input
// for example isolines takes tracts in in order to calculate estimation
var rows = AnalysesQuotaOptions.transformInput(type, data, formModel);
this._payload.estimation = rows;
payload.estimation = rows;
// with the input, we calculate wether the quota is enough
return AnalysesQuotaEnough.fetch(service, rows);
}.bind(this), errorCallback)
.then(function (enoughQuota) {
var payload = this._payload;
};
var buildPayload = function (enoughQuota) {
// then we can get the full set of data
payload.quotaInfo = AnalysesQuotaProvider(type, userModel, quotaData, enoughQuota);
payload.creditsLeft = payload.quotaInfo.totalQuota - payload.quotaInfo.usedQuota;
@ -195,26 +204,23 @@ module.exports = CoreView.extend({
if (viewModel.get('userFetchModelState') === 'fetched') {
infoboxModel.set('state', 'ready');
}
}.bind(self), errorCallback);
};
var dsReady = quotaData.isReady();
// Only checks api if analysis belongs to a service with quota
if (service !== null && isFetched && formModel.isValid() && dsReady) {
// get the estimation for this analysis
AnalysesQuotaEstimation.fetch(query)
.then(checkEnoughQuota, errorCallback)
.then(buildPayload, errorCallback);
} else if (!dsReady) {
errorCallback(_t('editor.layers.analysis-form.quota.quota-dataservice-down'));
}
var states = [
{
state: 'fetching',
createContentView: function () {
return InfoboxFactory.createLoading({
body: _t('editor.layers.analysis-form.quota.loading')
});
}
},
{
state: 'ready',
createContentView: function () {
var createQuotaContentView = (function (payload, context) {
var self = context;
var confirmLabel = _t('editor.layers.analysis-form.confirm-analysis');
var payload = this._payload;
var quotaMessage = '';
if (payload.creditsLeft > 0) {
@ -224,21 +230,34 @@ module.exports = CoreView.extend({
}
payload.quotaInfo.quotaMessage = quotaMessage;
var dataInfobox = _.extend(AnalysesQuotaPresenter.make(payload, this._configModel, this._userModel), {
var dataInfobox = _.extend(AnalysesQuotaPresenter.make(payload, self._configModel, self._userModel), {
title: _t('editor.layers.analysis-form.quota.title'),
mainAction: {
label: confirmLabel,
type: 'primary',
disabled: !this._canSave() || !payload.canRunAnalysis
disabled: !self._canSave() || !payload.canRunAnalysis
},
quota: payload.quotaInfo
});
return InfoboxFactory.createQuota(dataInfobox);
}.bind(this),
})(payload, this);
var states = [
{
state: 'fetching',
createContentView: function () {
return InfoboxFactory.createLoading({
body: _t('editor.layers.analysis-form.quota.loading')
});
}
},
{
state: 'ready',
createContentView: createQuotaContentView,
mainAction: function () {
var canRunAnalysis = this._payload.canRunAnalysis;
if (this._canSave() && canRunAnalysis) {
// var canRunAnalysis = this._payload.canRunAnalysis;
if (this._canSave() && payload.canRunAnalysis) {
this._saveAnalysis();
}
}.bind(this),
@ -266,14 +285,22 @@ module.exports = CoreView.extend({
}
];
this.view = new InfoboxView({
this.view = new AnalysisQuotaView({
className: 'Infobox-wrapper',
infoboxModel: this._infoboxModel,
infoboxCollection: new InfoboxCollection(states)
infoboxCollection: new InfoboxCollection(states),
model: this._viewModel
});
this.addView(this.view);
return this.view.render().el;
// this.view = new InfoboxView({
// className: 'Infobox-wrapper',
// infoboxModel: this._infoboxModel,
// infoboxCollection: new InfoboxCollection(states)
// });
return this.view;
// this.addView(this.view);
// return this.view.render().el;
},
_canSave: function () {

@ -246,6 +246,7 @@ module.exports = BaseAnalysisFormModel.extend({
this.clear({silent: true});
this.set('type', attrs.type, {silent: true}); // re-set type to avoid change:type event to trigger again
this.set(attrs);
this.trigger('change', this);
},
_typeDef: function (type) {

@ -0,0 +1,37 @@
var CoreView = require('backbone/core-view');
var InfoboxView = require('../../../../components/infobox/infobox-view');
var checkAndBuildOpts = require('../../../../helpers/required-opts');
var REQUIRED_OPTS = [
'infoboxModel',
'infoboxCollection',
'model'
];
module.exports = CoreView.extend({
initialize: function (opts) {
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
this._initBinds();
},
render: function () {
this.clearSubViews();
this.$el.empty();
this._initViews();
return this;
},
_initBinds: function () {
this.listenTo(this._model, 'change:userFetchModelState', this.render);
},
_initViews: function () {
var view = new InfoboxView({
infoboxModel: this._infoboxModel,
infoboxCollection: this._infoboxCollection
});
this.addView(view);
this.$el.append(view.render().$el);
}
});
Loading…
Cancel
Save