Initial commit
This commit is contained in:
+350
@@ -0,0 +1,350 @@
|
||||
var $ = require('jquery');
|
||||
var CoreView = require('backbone/core-view');
|
||||
var template = require('./table-head-item.tpl');
|
||||
var ContextMenuView = require('builder/components/context-menu/context-menu-view');
|
||||
var CustomListCollection = require('builder/components/custom-list/custom-list-collection');
|
||||
var TableHeadOptionsItemView = require('./table-head-options-item-view');
|
||||
var tableHeadOptionsItemTemplate = require('./table-head-options-item.tpl');
|
||||
var ConfirmationModalView = require('builder/components/modals/confirmation/modal-confirmation-view');
|
||||
var QueryColumnModel = require('builder/data/query-column-model');
|
||||
var addColumnOperation = require('builder/components/table/operations/table-add-column');
|
||||
var renameColumnOperation = require('builder/components/table/operations/table-rename-column');
|
||||
var changeColumnTypeOperation = require('builder/components/table/operations/table-change-column-type');
|
||||
var removeTableColumnOperation = require('builder/components/table/operations/table-remove-column');
|
||||
|
||||
var ENTER_KEY_CODE = 13;
|
||||
var ESC_KEY_CODE = 27;
|
||||
|
||||
/*
|
||||
* Main table view
|
||||
*/
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
className: 'Table-headItem',
|
||||
tagName: 'th',
|
||||
|
||||
events: {
|
||||
'dblclick .js-attribute': '_onAttributeDblClicked',
|
||||
'focusout .js-attribute': '_saveNewName',
|
||||
'click .js-columnOptions': '_showContextMenu'
|
||||
},
|
||||
|
||||
initialize: function (opts) {
|
||||
if (!opts.tableViewModel) throw new Error('tableViewModel is required');
|
||||
if (!opts.columnsCollection) throw new Error('columnsCollection is required');
|
||||
if (!opts.modals) throw new Error('modals is required');
|
||||
|
||||
this._tableViewModel = opts.tableViewModel;
|
||||
this._columnsCollection = opts.columnsCollection;
|
||||
this._modals = opts.modals;
|
||||
|
||||
this._hideContextMenu = this._hideContextMenu.bind(this);
|
||||
this._onKeyDown = this._onKeyDown.bind(this);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
var columnName = this.model.get('name');
|
||||
this.$el.html(
|
||||
template({
|
||||
name: columnName,
|
||||
type: this.model.get('type'),
|
||||
isOrderBy: this._tableViewModel.get('order_by') === columnName,
|
||||
sortBy: this._tableViewModel.get('sort_order'),
|
||||
geometry: this.options.simpleGeometry
|
||||
})
|
||||
);
|
||||
return this;
|
||||
},
|
||||
|
||||
_hasContextMenu: function () {
|
||||
return this._menuView;
|
||||
},
|
||||
|
||||
_hideContextMenu: function () {
|
||||
this._unhighlightHead();
|
||||
this._destroyScrollBinding();
|
||||
this._menuView.collection.unbind(null, null, this);
|
||||
this.removeView(this._menuView);
|
||||
this._menuView.clean();
|
||||
delete this._menuView;
|
||||
},
|
||||
|
||||
_highlightHead: function () {
|
||||
this.$el.addClass('is-highlighted');
|
||||
},
|
||||
|
||||
_unhighlightHead: function () {
|
||||
this.$el.removeClass('is-highlighted');
|
||||
},
|
||||
|
||||
_initScrollBinding: function () {
|
||||
$('.Table').scroll(this._hideContextMenu);
|
||||
},
|
||||
|
||||
_destroyScrollBinding: function () {
|
||||
$('.Table').off('scroll', this._hideContextMenu);
|
||||
},
|
||||
|
||||
_showContextMenu: function (ev) {
|
||||
var self = this;
|
||||
var position = { x: ev.clientX, y: ev.clientY };
|
||||
var elementIndex = this.$el.index();
|
||||
var modelCID = this.model.cid;
|
||||
var columnName = this.model.get('name');
|
||||
|
||||
this._highlightHead();
|
||||
|
||||
var menuItems = [{
|
||||
label: _t('components.table.columns.options.order'),
|
||||
val: 'order',
|
||||
isOrderBy: this._tableViewModel.get('order_by') === columnName,
|
||||
sortBy: this._tableViewModel.get('sort_order'),
|
||||
action: function (model) {
|
||||
self._tableViewModel.set({
|
||||
sort_order: model.get('sort'),
|
||||
order_by: columnName
|
||||
});
|
||||
}
|
||||
}];
|
||||
|
||||
if (!this._tableViewModel.isDisabled()) {
|
||||
if (!this.model.isCartoDBIDColumn() && !this.model.isGeometryColumn()) {
|
||||
menuItems = menuItems.concat([
|
||||
{
|
||||
label: _t('components.table.columns.options.rename'),
|
||||
val: 'rename',
|
||||
action: function () {
|
||||
self._startEditing();
|
||||
}
|
||||
}, {
|
||||
label: _t('components.table.columns.options.change'),
|
||||
type: this.model.get('type'),
|
||||
isLastColumns: (this._columnsCollection.size() - elementIndex) < 3,
|
||||
val: 'change',
|
||||
action: function (model) {
|
||||
self._changeColumnType(model.get('type'));
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
menuItems.push({
|
||||
label: _t('components.table.columns.options.create'),
|
||||
val: 'create',
|
||||
action: function () {
|
||||
self._addColumn();
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.model.isCartoDBIDColumn() && !this.model.isGeometryColumn()) {
|
||||
menuItems.push(
|
||||
{
|
||||
label: _t('components.table.columns.options.delete'),
|
||||
val: 'delete',
|
||||
destructive: true,
|
||||
action: function () {
|
||||
self._removeColumn();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var collection = new CustomListCollection(menuItems);
|
||||
|
||||
this._menuView = new ContextMenuView({
|
||||
className: ContextMenuView.prototype.className + ' Table-columnMenu',
|
||||
collection: collection,
|
||||
itemTemplate: tableHeadOptionsItemTemplate,
|
||||
itemView: TableHeadOptionsItemView,
|
||||
triggerElementID: modelCID,
|
||||
position: position
|
||||
});
|
||||
|
||||
collection.bind('change:selected', function (menuItem) {
|
||||
var action = menuItem.get('action');
|
||||
action && action(menuItem);
|
||||
}, this);
|
||||
|
||||
this._menuView.model.bind('change:visible', function (model, isContextMenuVisible) {
|
||||
if (this._hasContextMenu() && !isContextMenuVisible) {
|
||||
this._hideContextMenu();
|
||||
}
|
||||
}, this);
|
||||
|
||||
this._menuView.show();
|
||||
this.addView(this._menuView);
|
||||
|
||||
this._initScrollBinding();
|
||||
},
|
||||
|
||||
_addColumn: function () {
|
||||
addColumnOperation({
|
||||
columnsCollection: this._columnsCollection
|
||||
});
|
||||
},
|
||||
|
||||
_changeColumnType: function (newType) {
|
||||
var self = this;
|
||||
var oldType = this.model.get('type');
|
||||
var isTypeChangeDestructive = QueryColumnModel.isTypeChangeDestructive(oldType, newType);
|
||||
if (!isTypeChangeDestructive) {
|
||||
changeColumnTypeOperation({
|
||||
columnModel: this.model,
|
||||
newType: newType
|
||||
});
|
||||
} else {
|
||||
this._modals.create(
|
||||
function (modalModel) {
|
||||
return new ConfirmationModalView({
|
||||
modalModel: modalModel,
|
||||
template: require('./modals-templates/change-table-column-type.tpl'),
|
||||
renderOpts: {
|
||||
columnName: self.model.get('name'),
|
||||
newType: newType
|
||||
},
|
||||
loadingTitle: _t('components.table.columns.change-type.loading', {
|
||||
columnName: self.model.get('name')
|
||||
}),
|
||||
runAction: function () {
|
||||
changeColumnTypeOperation({
|
||||
columnModel: self.model,
|
||||
newType: newType,
|
||||
onSuccess: function () {
|
||||
modalModel.destroy();
|
||||
},
|
||||
onError: function (e) {
|
||||
modalModel.destroy();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
_removeColumn: function () {
|
||||
var self = this;
|
||||
this._modals.create(
|
||||
function (modalModel) {
|
||||
return new ConfirmationModalView({
|
||||
modalModel: modalModel,
|
||||
template: require('./modals-templates/remove-table-column.tpl'),
|
||||
renderOpts: {
|
||||
name: self.model.get('name')
|
||||
},
|
||||
loadingTitle: _t('components.table.columns.destroy.loading', {
|
||||
columnName: self.model.get('name')
|
||||
}),
|
||||
runAction: function () {
|
||||
removeTableColumnOperation({
|
||||
columnModel: self.model,
|
||||
onSuccess: function () {
|
||||
modalModel.destroy();
|
||||
},
|
||||
onError: function (e) {
|
||||
modalModel.destroy();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
_onAttributeDblClicked: function () {
|
||||
if (this.model.isEditable() && !this._tableViewModel.isDisabled()) {
|
||||
this._startEditing();
|
||||
}
|
||||
},
|
||||
|
||||
_initRenameBinds: function () {
|
||||
$(document).bind('keydown', this._onKeyDown);
|
||||
},
|
||||
|
||||
_destroyRenameBinds: function () {
|
||||
$(document).unbind('keydown', this._onKeyDown);
|
||||
},
|
||||
|
||||
_onKeyDown: function (ev) {
|
||||
var keyCode = ev.which;
|
||||
if (keyCode === ENTER_KEY_CODE) {
|
||||
this._saveNewName();
|
||||
} else if (keyCode === ESC_KEY_CODE) {
|
||||
this._finishEditing();
|
||||
}
|
||||
},
|
||||
|
||||
_startEditing: function () {
|
||||
this.$('.js-attribute')
|
||||
.addClass('is-active')
|
||||
.removeAttr('readonly');
|
||||
|
||||
this._initRenameBinds();
|
||||
},
|
||||
|
||||
_finishEditing: function () {
|
||||
this.$('.js-attribute')
|
||||
.val(this.model.get('name'))
|
||||
.removeClass('is-active')
|
||||
.attr('readonly', '');
|
||||
|
||||
this._destroyRenameBinds();
|
||||
},
|
||||
|
||||
_saveNewName: function () {
|
||||
if (this.model.isEditable()) {
|
||||
var newName = this.$('.js-attribute').val();
|
||||
var columnModel = this.model;
|
||||
var oldName = columnModel.get('name');
|
||||
|
||||
if (oldName !== newName && newName !== '') {
|
||||
this._modals.create(
|
||||
function (modalModel) {
|
||||
return new ConfirmationModalView({
|
||||
modalModel: modalModel,
|
||||
template: require('./modals-templates/rename-table-column.tpl'),
|
||||
renderOpts: {
|
||||
columnName: oldName,
|
||||
newName: newName
|
||||
},
|
||||
loadingTitle: _t('components.table.columns.rename.loading', {
|
||||
columnName: oldName,
|
||||
newName: newName
|
||||
}),
|
||||
runAction: function () {
|
||||
renameColumnOperation({
|
||||
columnModel: columnModel,
|
||||
newName: newName,
|
||||
onSuccess: function () {
|
||||
modalModel.destroy();
|
||||
},
|
||||
onError: function (e) {
|
||||
modalModel.destroy();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Setting old name just in case user cancel it
|
||||
this._finishEditing();
|
||||
},
|
||||
|
||||
focusInput: function () {
|
||||
this._startEditing();
|
||||
this.$('.js-attribute').select();
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
this._destroyRenameBinds();
|
||||
this._destroyScrollBinding();
|
||||
CoreView.prototype.clean.apply(this);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user