Initial commit
This commit is contained in:
33
lib/assets/javascripts/builder/components/notifier/notifier-action-view.js
Executable file
33
lib/assets/javascripts/builder/components/notifier/notifier-action-view.js
Executable file
@@ -0,0 +1,33 @@
|
||||
var CoreView = require('backbone/core-view');
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
tagName: 'button',
|
||||
|
||||
initialize: function (opts) {
|
||||
if (!opts.template) throw new Error('template is required');
|
||||
if (!opts.editorModel) throw new Error('editorModel is required');
|
||||
this.template = opts.template;
|
||||
this._editorModel = opts.editorModel;
|
||||
this._data = {};
|
||||
if (opts.model) {
|
||||
this._data = opts.model.toJSON();
|
||||
}
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this._editorModel, 'change:edition', this._changeStyle);
|
||||
this.add_related_model(this._editorModel);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
this.$el.empty();
|
||||
this.$el.append(this.template(this._data));
|
||||
return this;
|
||||
},
|
||||
|
||||
_changeStyle: function () {
|
||||
this.$('.js-theme').toggleClass('is-white', this._editorModel.isEditing());
|
||||
}
|
||||
});
|
||||
1
lib/assets/javascripts/builder/components/notifier/notifier-action.tpl
Executable file
1
lib/assets/javascripts/builder/components/notifier/notifier-action.tpl
Executable file
@@ -0,0 +1 @@
|
||||
<span data-action="<%- button %>" class="CDB-Text is-semibold u-lSpace u-actionTextColor u-upperCase"><%- button %></span>
|
||||
1
lib/assets/javascripts/builder/components/notifier/notifier-close.tpl
Executable file
1
lib/assets/javascripts/builder/components/notifier/notifier-close.tpl
Executable file
@@ -0,0 +1 @@
|
||||
<div class="CDB-Shape-close is-blue is-large js-theme"></div>
|
||||
22
lib/assets/javascripts/builder/components/notifier/notifier-collection.js
Executable file
22
lib/assets/javascripts/builder/components/notifier/notifier-collection.js
Executable file
@@ -0,0 +1,22 @@
|
||||
var Backbone = require('backbone');
|
||||
var NotifierModel = require('./notifier-model');
|
||||
|
||||
module.exports = Backbone.Collection.extend({
|
||||
model: function (attrs, opts) {
|
||||
return new NotifierModel(attrs, opts);
|
||||
},
|
||||
|
||||
findById: function (id) {
|
||||
return this.findWhere({id: id});
|
||||
},
|
||||
|
||||
addNotification: function (attrs, options) {
|
||||
var notification = this._findNotificationByAttrs(attrs);
|
||||
|
||||
return notification ? notification.update(attrs) : this.add(attrs, options);
|
||||
},
|
||||
|
||||
_findNotificationByAttrs: function (attrs) {
|
||||
return this.findWhere({ info: attrs.info });
|
||||
}
|
||||
});
|
||||
126
lib/assets/javascripts/builder/components/notifier/notifier-item-view.js
Executable file
126
lib/assets/javascripts/builder/components/notifier/notifier-item-view.js
Executable file
@@ -0,0 +1,126 @@
|
||||
var CoreView = require('backbone/core-view');
|
||||
var Template = require('./notifier-item.tpl');
|
||||
var ActionView = require('./notifier-action-view');
|
||||
var closeTemplate = require('./notifier-close.tpl');
|
||||
var actionTemplate = require('./notifier-action.tpl');
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
className: 'Notifier-inner',
|
||||
tagName: 'li',
|
||||
events: {
|
||||
'click .js-close': '_closeHandler',
|
||||
'click .js-action': '_actionHandler'
|
||||
},
|
||||
|
||||
initialize: function (opts) {
|
||||
if (!opts.notifierModel) throw new Error('notifierModel is required');
|
||||
if (!opts.editorModel) throw new Error('editorModel is required');
|
||||
|
||||
this._editorModel = opts.editorModel;
|
||||
this.template = this.options.template || Template;
|
||||
this._notifierModel = opts.notifierModel;
|
||||
this.$el.attr('id', this._notifierModel.get('id'));
|
||||
|
||||
this._delay = this._notifierModel.get('delay') || this._notifierModel.get('defaultDelay');
|
||||
|
||||
if (this._notifierModel.get('delay') && this._notifierModel.get('closable') !== false) {
|
||||
this._timeout = setTimeout(this._autoClose.bind(this), this._delay);
|
||||
}
|
||||
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
this.$el.empty();
|
||||
this._initViews();
|
||||
this._changeStyle();
|
||||
return this;
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this._notifierModel, 'change', this.render);
|
||||
this.listenTo(this._notifierModel, 'change:status', this._onChangeStatus);
|
||||
this.add_related_model(this._notifierModel);
|
||||
|
||||
this.listenTo(this._editorModel, 'change:edition', this._changeStyle);
|
||||
this.add_related_model(this._editorModel);
|
||||
},
|
||||
|
||||
_initViews: function () {
|
||||
var actionable = this._notifierModel.getButton();
|
||||
var closable = this._notifierModel.isClosable();
|
||||
var view = this.template({
|
||||
status: this._notifierModel.getStatus(),
|
||||
info: this._notifierModel.getInfo(),
|
||||
isActionable: actionable,
|
||||
isClosable: closable
|
||||
});
|
||||
|
||||
this.$el.append(view);
|
||||
|
||||
if (actionable) {
|
||||
this._createActionView(actionable);
|
||||
}
|
||||
|
||||
if (closable) {
|
||||
this._createCloseView();
|
||||
}
|
||||
},
|
||||
|
||||
_createActionView: function (action) {
|
||||
var actionView = new ActionView({
|
||||
template: actionTemplate,
|
||||
className: 'js-action',
|
||||
model: this._notifierModel,
|
||||
editorModel: this._editorModel
|
||||
});
|
||||
|
||||
this.$('.js-actionButton').append(actionView.render().el);
|
||||
this.addView(actionView);
|
||||
},
|
||||
|
||||
_createCloseView: function () {
|
||||
var actionView = new ActionView({
|
||||
template: closeTemplate,
|
||||
className: 'CDB-Shape js-close',
|
||||
editorModel: this._editorModel
|
||||
});
|
||||
|
||||
this.$('.js-closeButton').append(actionView.render().el);
|
||||
this.addView(actionView);
|
||||
},
|
||||
|
||||
_closeHandler: function () {
|
||||
var status = this._notifierModel.getStatus();
|
||||
var action = this._notifierModel.getAction();
|
||||
this._notifierModel.trigger('notification:close', action || status);
|
||||
clearTimeout(this._timeout);
|
||||
if (this._notifierModel && this._notifierModel.collection) {
|
||||
this._notifierModel.collection.remove(this._notifierModel);
|
||||
}
|
||||
},
|
||||
|
||||
_actionHandler: function () {
|
||||
var status = this._notifierModel.getStatus();
|
||||
var action = this._notifierModel.getAction();
|
||||
this._notifierModel.trigger('notification:action', action || status);
|
||||
},
|
||||
|
||||
_changeStyle: function () {
|
||||
this.$('.Notifier-info').toggleClass('u-whiteTextColor', this._editorModel.isEditing());
|
||||
this.$('.Notifier-actions .CDB-Shape-close').toggleClass('is-blue', !this._editorModel.isEditing());
|
||||
this.$('.Notifier-actions .CDB-Shape-close').toggleClass('is-white', this._editorModel.isEditing());
|
||||
},
|
||||
|
||||
_autoClose: function () {
|
||||
this._notifierModel.set({action: 'autoclose'}, {silent: true});
|
||||
this._closeHandler();
|
||||
},
|
||||
|
||||
_onChangeStatus: function (model, status) {
|
||||
if ((status === 'success' || status === 'error') && this._notifierModel.get('closable') !== false && this._notifierModel.get('autoclosable') !== false) {
|
||||
this._timeout = setTimeout(this._autoClose.bind(this), this._delay);
|
||||
}
|
||||
}
|
||||
});
|
||||
34
lib/assets/javascripts/builder/components/notifier/notifier-item.tpl
Executable file
34
lib/assets/javascripts/builder/components/notifier/notifier-item.tpl
Executable file
@@ -0,0 +1,34 @@
|
||||
<div class="Notifier-item Notifier-item--<%- status %>">
|
||||
|
||||
<% if (status === 'loading') { %>
|
||||
<div class="Notifier-icon CDB-LoaderIcon is-blue js-theme u-rSpace--m">
|
||||
<svg class="CDB-LoaderIcon-spinner" viewBox="0 0 50 50">
|
||||
<circle class="CDB-LoaderIcon-path" cx="25" cy="25" r="20" fill="none"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<% if (status === 'success') { %>
|
||||
<div class="Notifier-icon CDB-Shape u-rSpace--m">
|
||||
<div class="CDB-Shape-CircleItem CDB-Shape-CircleItem--fill is-green">
|
||||
<div class="CDB-Shape-tick is-medium is-white"></div>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<% if (status === 'error' || status === 'warning') { %>
|
||||
<div class="Notifier-icon CDB-Shape u-rSpace--m">
|
||||
<div class="CDB-Shape-CircleItem CDB-Shape-CircleItem--fill is-red">
|
||||
<div class="CDB-Shape-close is-medium is-white"></div>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<div class="Notifier-info">
|
||||
<p class="CDB-Text CDB-Size-medium"><%= info %> <% if (isActionable) { %> <span class="js-actionButton"></span> <% } %></p>
|
||||
</div>
|
||||
|
||||
<% if (isClosable) { %>
|
||||
<div class="Notifier-actions js-closeButton"></div>
|
||||
<% } %>
|
||||
</div>
|
||||
72
lib/assets/javascripts/builder/components/notifier/notifier-model.js
Executable file
72
lib/assets/javascripts/builder/components/notifier/notifier-model.js
Executable file
@@ -0,0 +1,72 @@
|
||||
var Backbone = require('backbone');
|
||||
|
||||
module.exports = Backbone.Model.extend({
|
||||
defaults: {
|
||||
status: 'idle',
|
||||
info: '',
|
||||
closable: true
|
||||
},
|
||||
|
||||
initialize: function (attrs, opts) {
|
||||
if (attrs.id === undefined) {
|
||||
this.set('id', 'notifier' + this.cid);
|
||||
}
|
||||
|
||||
this.set('defaultDelay', opts.delay);
|
||||
|
||||
if (opts.visDefinitionModel) {
|
||||
this._retriggerEvent(opts.visDefinitionModel, 'vis:reload');
|
||||
this._retriggerEvent(opts.visDefinitionModel, 'vis:error');
|
||||
}
|
||||
},
|
||||
|
||||
isClosable: function () {
|
||||
return this.get('closable') === true;
|
||||
},
|
||||
|
||||
updateClosable: function (val) {
|
||||
this.set({closable: val});
|
||||
},
|
||||
|
||||
getButton: function () {
|
||||
return this.get('button');
|
||||
},
|
||||
|
||||
updateButton: function (val) {
|
||||
this.set({button: val});
|
||||
},
|
||||
|
||||
getStatus: function () {
|
||||
return this.get('status');
|
||||
},
|
||||
|
||||
updateStatus: function (val) {
|
||||
this.set({status: val});
|
||||
},
|
||||
|
||||
getInfo: function () {
|
||||
return this.get('info');
|
||||
},
|
||||
|
||||
getAction: function () {
|
||||
return this.get('action');
|
||||
},
|
||||
|
||||
setAction: function (val) {
|
||||
this.set({action: val});
|
||||
},
|
||||
|
||||
updateInfo: function (val) {
|
||||
this.set({info: val});
|
||||
},
|
||||
|
||||
update: function (state) {
|
||||
this.set(state);
|
||||
},
|
||||
|
||||
_retriggerEvent: function (model, event) {
|
||||
model.on(event, function () {
|
||||
this.trigger(event, arguments);
|
||||
}, this);
|
||||
}
|
||||
});
|
||||
96
lib/assets/javascripts/builder/components/notifier/notifier-view.js
Executable file
96
lib/assets/javascripts/builder/components/notifier/notifier-view.js
Executable file
@@ -0,0 +1,96 @@
|
||||
var CoreView = require('backbone/core-view');
|
||||
var _ = require('underscore');
|
||||
var NotifierItemView = require('./notifier-item-view');
|
||||
var template = require('./notifier.tpl');
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
className: 'Notifier',
|
||||
|
||||
initialize: function (opts) {
|
||||
if (!opts.collection) throw new Error('collection is mandatory');
|
||||
if (!opts.editorModel) throw new Error('editorModel is mandatory');
|
||||
|
||||
this._editorModel = opts.editorModel;
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
this.$el.html(template());
|
||||
this._renderAllSubviews();
|
||||
this._renderLoading();
|
||||
return this;
|
||||
},
|
||||
|
||||
rebindEvents: function () {
|
||||
// Just in case
|
||||
this.stopListening(this.collection);
|
||||
this.stopListening(this._editorModel);
|
||||
this._initBinds();
|
||||
return this;
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this.collection, 'reset update change:status', this.render);
|
||||
this.add_related_model(this.collection);
|
||||
|
||||
this.listenTo(this._editorModel, 'change:edition', this._changeStyle);
|
||||
this.add_related_model(this._editorModel);
|
||||
},
|
||||
|
||||
_renderAllSubviews: function () {
|
||||
this.collection.each(this._renderSubview, this);
|
||||
},
|
||||
|
||||
_renderSubview: function (model) {
|
||||
var view = new NotifierItemView({
|
||||
notifierModel: model,
|
||||
editorModel: this._editorModel
|
||||
});
|
||||
|
||||
var status = model.get('status');
|
||||
var container = (status === 'success' || status === 'error')
|
||||
? this._getDoneContainer()
|
||||
: this._getLoadingContainer();
|
||||
container.append(view.render().el);
|
||||
this.addView(view);
|
||||
},
|
||||
|
||||
_removeSubview: function (model) {
|
||||
var id = model.get('id');
|
||||
var view = _.first(_.filter(this._subviews, function (subview) {
|
||||
return subview._notifierModel.get('id') === id;
|
||||
}));
|
||||
|
||||
if (view) {
|
||||
this.removeView(view);
|
||||
view.remove();
|
||||
}
|
||||
},
|
||||
|
||||
_renderLoading: function () {
|
||||
this._getLoader().toggleClass('is-visible', this._anyNotificationLoading());
|
||||
},
|
||||
|
||||
_anyNotificationLoading: function () {
|
||||
return this.collection.any(function (model) {
|
||||
return !_.contains(['success', 'error', 'warning'], model.get('status'));
|
||||
});
|
||||
},
|
||||
|
||||
_changeStyle: function () {
|
||||
this.$el.toggleClass('is-dark', this._editorModel.isEditing());
|
||||
},
|
||||
|
||||
_getDoneContainer: function () {
|
||||
return this.$('.js-status-done');
|
||||
},
|
||||
|
||||
_getLoadingContainer: function () {
|
||||
return this.$('.js-status-loading');
|
||||
},
|
||||
|
||||
_getLoader: function () {
|
||||
return this.$('.js-loader');
|
||||
}
|
||||
});
|
||||
81
lib/assets/javascripts/builder/components/notifier/notifier.js
Executable file
81
lib/assets/javascripts/builder/components/notifier/notifier.js
Executable file
@@ -0,0 +1,81 @@
|
||||
var NotifierView = require('./notifier-view');
|
||||
var NotifierCollection = require('./notifier-collection');
|
||||
|
||||
var manager = (function () {
|
||||
var initialized = false;
|
||||
var notifierView;
|
||||
var collection = new NotifierCollection();
|
||||
var editorModel;
|
||||
|
||||
function init (opts) {
|
||||
if (!editorModel && !opts) {
|
||||
throw new Error('editorModel is required');
|
||||
}
|
||||
|
||||
if (!editorModel && opts && opts.editorModel) {
|
||||
editorModel = opts.editorModel;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
notifierView = new NotifierView({
|
||||
collection: collection,
|
||||
editorModel: editorModel
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
DEFAULT_DELAY: 5000,
|
||||
init: function (opts) {
|
||||
if (opts.visDefinitionModel) {
|
||||
this._visDefinitionModel = opts.visDefinitionModel;
|
||||
}
|
||||
init(opts);
|
||||
},
|
||||
|
||||
// For testing porposes only
|
||||
off: function () {
|
||||
if (__ENV__ === 'test') {
|
||||
collection.reset();
|
||||
initialized = false;
|
||||
notifierView.remove();
|
||||
notifierView = null;
|
||||
}
|
||||
},
|
||||
|
||||
getView: function () {
|
||||
if (!initialized) init();
|
||||
return notifierView.rebindEvents();
|
||||
},
|
||||
|
||||
getCollection: function () {
|
||||
return collection;
|
||||
},
|
||||
|
||||
getCount: function () {
|
||||
return collection.size();
|
||||
},
|
||||
|
||||
getNotification: function (model) {
|
||||
return typeof model === 'string'
|
||||
? collection.findById(model)
|
||||
: collection.findById(model.id);
|
||||
},
|
||||
|
||||
addNotification: function (attrs) {
|
||||
return collection.addNotification(attrs, {
|
||||
visDefinitionModel: this._visDefinitionModel,
|
||||
delay: this.DEFAULT_DELAY
|
||||
});
|
||||
},
|
||||
|
||||
removeNotification: function (model) {
|
||||
var notification = typeof model === 'string'
|
||||
? collection.findById(model)
|
||||
: collection.findById(model.id);
|
||||
|
||||
return collection.remove(notification);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
module.exports = manager;
|
||||
3
lib/assets/javascripts/builder/components/notifier/notifier.tpl
Executable file
3
lib/assets/javascripts/builder/components/notifier/notifier.tpl
Executable file
@@ -0,0 +1,3 @@
|
||||
<div class="CDB-Loader js-loader"></div>
|
||||
<ul class="Notifier-list js-status-loading"></ul>
|
||||
<ul class="Notifier-list js-status-done"></ul>
|
||||
Reference in New Issue
Block a user