303 lines
9.5 KiB
JavaScript
303 lines
9.5 KiB
JavaScript
|
/*
|
||
|
* Builder Index controller Database Table entity controller
|
||
|
*/
|
||
|
+function ($) { "use strict";
|
||
|
|
||
|
if ($.oc.builder === undefined)
|
||
|
$.oc.builder = {}
|
||
|
|
||
|
if ($.oc.builder.entityControllers === undefined)
|
||
|
$.oc.builder.entityControllers = {}
|
||
|
|
||
|
var Base = $.oc.builder.entityControllers.base,
|
||
|
BaseProto = Base.prototype
|
||
|
|
||
|
var DatabaseTable = function(indexController) {
|
||
|
Base.call(this, 'databaseTable', indexController)
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype = Object.create(BaseProto)
|
||
|
DatabaseTable.prototype.constructor = DatabaseTable
|
||
|
|
||
|
// PUBLIC METHODS
|
||
|
// ============================
|
||
|
|
||
|
DatabaseTable.prototype.cmdCreateTable = function(ev) {
|
||
|
var result = this.indexController.openOrLoadMasterTab($(ev.target), 'onDatabaseTableCreateOrOpen', this.newTabId())
|
||
|
|
||
|
if (result !== false) {
|
||
|
result.done(this.proxy(this.onTableLoaded, this))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.cmdOpenTable = function(ev) {
|
||
|
var table = $(ev.currentTarget).data('id'),
|
||
|
result = this.indexController.openOrLoadMasterTab($(ev.target), 'onDatabaseTableCreateOrOpen', this.makeTabId(table), {
|
||
|
table_name: table
|
||
|
})
|
||
|
|
||
|
if (result !== false) {
|
||
|
result.done(this.proxy(this.onTableLoaded, this))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.cmdSaveTable = function(ev) {
|
||
|
var $target = $(ev.currentTarget)
|
||
|
|
||
|
// The process of saving a database table:
|
||
|
// - validate client-side
|
||
|
// - validate columns on the server
|
||
|
// - display a popup asking to enter the migration text
|
||
|
// - generate the migration on the server and execute it
|
||
|
// - drop the form modified flag
|
||
|
|
||
|
if (!this.validateTable($target)) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var data = {
|
||
|
'columns': this.getTableData($target)
|
||
|
}
|
||
|
|
||
|
$target.popup({
|
||
|
extraData: data,
|
||
|
handler: 'onDatabaseTableValidateAndShowPopup'
|
||
|
})
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.cmdSaveMigration = function(ev) {
|
||
|
var $target = $(ev.currentTarget)
|
||
|
|
||
|
$.oc.stripeLoadIndicator.show()
|
||
|
$target.request('onDatabaseTableMigrationApply').always(
|
||
|
$.oc.builder.indexController.hideStripeIndicatorProxy
|
||
|
).done(
|
||
|
this.proxy(this.saveMigrationDone)
|
||
|
)
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.cmdDeleteTable = function(ev) {
|
||
|
var $target = $(ev.currentTarget)
|
||
|
$.oc.confirm($target.data('confirm'), this.proxy(this.deleteConfirmed))
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.cmdUnModifyForm = function() {
|
||
|
var $masterTabPane = this.getMasterTabsActivePane()
|
||
|
this.unmodifyTab($masterTabPane)
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.cmdAddTimestamps = function(ev) {
|
||
|
var $target = $(ev.currentTarget),
|
||
|
added = this.addTimeStampColumns($target, ['created_at', 'updated_at'])
|
||
|
|
||
|
if (!added) {
|
||
|
alert($target.closest('form').attr('data-lang-timestamps-exist'))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.cmdAddSoftDelete = function(ev) {
|
||
|
var $target = $(ev.currentTarget),
|
||
|
added = this.addTimeStampColumns($target, ['deleted_at'])
|
||
|
|
||
|
if (!added) {
|
||
|
alert($target.closest('form').attr('data-lang-soft-deleting-exist'))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// EVENT HANDLERS
|
||
|
// ============================
|
||
|
|
||
|
DatabaseTable.prototype.onTableCellChanged = function(ev, column, value, rowIndex) {
|
||
|
var $target = $(ev.target)
|
||
|
|
||
|
if ($target.data('alias') != 'columns') {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if ($target.closest('form').data('entity') != 'database') {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Some migration-related rules are enforced here:
|
||
|
//
|
||
|
// 1. Checking Autoincrement checkbox automatically checks the Unsigned checkbox (this corresponds to the
|
||
|
// logic internally implemented in Laravel schema builder) and PK
|
||
|
// 2. Unchecking Unsigned unchecks Autoincrement
|
||
|
// 3. Checking the PK column unchecks Nullable
|
||
|
// 4. Checking Nullable unchecks PK
|
||
|
// 6. Unchecking the PK unchecks Autoincrement
|
||
|
|
||
|
var updatedRow = {}
|
||
|
|
||
|
if (column == 'auto_increment' && value) {
|
||
|
updatedRow.unsigned = 1
|
||
|
updatedRow.primary_key = 1
|
||
|
}
|
||
|
|
||
|
if (column == 'unsigned' && !value) {
|
||
|
updatedRow.auto_increment = 0
|
||
|
}
|
||
|
|
||
|
if (column == 'primary_key' && value) {
|
||
|
updatedRow.allow_null = 0
|
||
|
}
|
||
|
|
||
|
if (column == 'allow_null' && value) {
|
||
|
updatedRow.primary_key = 0
|
||
|
}
|
||
|
|
||
|
if (column == 'primary_key' && !value) {
|
||
|
updatedRow.auto_increment = 0
|
||
|
}
|
||
|
|
||
|
$target.table('setRowValues', rowIndex, updatedRow)
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.onTableLoaded = function() {
|
||
|
$(document).trigger('render')
|
||
|
|
||
|
var $masterTabPane = this.getMasterTabsActivePane(),
|
||
|
$form = $masterTabPane.find('form'),
|
||
|
$toolbar = $masterTabPane.find('div[data-control=table] div.toolbar'),
|
||
|
$button = $('<a class="btn oc-icon-clock-o builder-custom-table-button" data-builder-command="databaseTable:cmdAddTimestamps"></a>')
|
||
|
|
||
|
$button.text($form.attr('data-lang-add-timestamps'));
|
||
|
$toolbar.append($button)
|
||
|
|
||
|
$button = $('<a class="btn oc-icon-refresh builder-custom-table-button" data-builder-command="databaseTable:cmdAddSoftDelete"></a>')
|
||
|
$button.text($form.attr('data-lang-add-soft-delete'));
|
||
|
$toolbar.append($button)
|
||
|
}
|
||
|
|
||
|
// INTERNAL METHODS
|
||
|
// ============================
|
||
|
|
||
|
DatabaseTable.prototype.registerHandlers = function() {
|
||
|
this.indexController.$masterTabs.on('oc.tableCellChanged', this.proxy(this.onTableCellChanged))
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.validateTable = function($target) {
|
||
|
var tableObj = this.getTableControlObject($target)
|
||
|
|
||
|
tableObj.unfocusTable()
|
||
|
return tableObj.validate()
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.getTableData = function($target) {
|
||
|
var tableObj = this.getTableControlObject($target)
|
||
|
|
||
|
return tableObj.dataSource.getAllData()
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.getTableControlObject = function($target) {
|
||
|
var $form = $target.closest('form'),
|
||
|
$table = $form.find('[data-control=table]'),
|
||
|
tableObj = $table.data('oc.table')
|
||
|
|
||
|
if (!tableObj) {
|
||
|
throw new Error('Table object is not found on the database table tab')
|
||
|
}
|
||
|
|
||
|
return tableObj
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.saveMigrationDone = function(data) {
|
||
|
if (data['builderResponseData'] === undefined) {
|
||
|
throw new Error('Invalid response data')
|
||
|
}
|
||
|
|
||
|
$('#builderTableMigrationPopup').trigger('close.oc.popup')
|
||
|
|
||
|
var $masterTabPane = this.getMasterTabsActivePane(),
|
||
|
tabsObject = this.getMasterTabsObject()
|
||
|
|
||
|
if (data.builderResponseData.operation != 'delete') {
|
||
|
$masterTabPane.find('input[name=table_name]').val(data.builderResponseData.builderObjectName)
|
||
|
this.updateMasterTabIdAndTitle($masterTabPane, data.builderResponseData)
|
||
|
this.unhideFormDeleteButton($masterTabPane)
|
||
|
|
||
|
this.getTableList().fileList('markActive', data.builderResponseData.tabId)
|
||
|
this.getIndexController().unchangeTab($masterTabPane)
|
||
|
}
|
||
|
else {
|
||
|
this.forceCloseTab($masterTabPane)
|
||
|
}
|
||
|
|
||
|
$.oc.builder.dataRegistry.clearCache(data.builderResponseData.pluginCode, 'model-columns')
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.getTableList = function() {
|
||
|
return $('#layout-side-panel form[data-content-id=database] [data-control=filelist]')
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.deleteConfirmed = function() {
|
||
|
var $masterTabPane = this.getMasterTabsActivePane()
|
||
|
|
||
|
$masterTabPane.find('form').popup({
|
||
|
handler: 'onDatabaseTableShowDeletePopup'
|
||
|
})
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.getColumnNames = function($target) {
|
||
|
var tableObj = this.getTableControlObject($target)
|
||
|
|
||
|
tableObj.unfocusTable()
|
||
|
|
||
|
var data = this.getTableData($target),
|
||
|
result = []
|
||
|
|
||
|
for (var index in data) {
|
||
|
if (data[index].name !== undefined) {
|
||
|
result.push($.trim(data[index].name))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.addTimeStampColumns = function($target, columns)
|
||
|
{
|
||
|
var existingColumns = this.getColumnNames($target),
|
||
|
added = false
|
||
|
|
||
|
for (var index in columns) {
|
||
|
var column = columns[index]
|
||
|
|
||
|
if ($.inArray(column, existingColumns) == -1) {
|
||
|
this.addTimeStampColumn($target, column)
|
||
|
added = true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (added) {
|
||
|
$target.trigger('change')
|
||
|
}
|
||
|
|
||
|
return added
|
||
|
}
|
||
|
|
||
|
DatabaseTable.prototype.addTimeStampColumn = function($target, column) {
|
||
|
var tableObj = this.getTableControlObject($target),
|
||
|
currentData = this.getTableData($target),
|
||
|
rowData = {
|
||
|
name: column,
|
||
|
type: 'timestamp',
|
||
|
'default': null,
|
||
|
allow_null: true // Simplifies the case when a timestamp is added to a table with data
|
||
|
}
|
||
|
|
||
|
tableObj.addRecord('bottom', true)
|
||
|
tableObj.setRowValues(currentData.length-1, rowData)
|
||
|
|
||
|
// Forces the table to apply values
|
||
|
// from the data source
|
||
|
tableObj.addRecord('bottom', false)
|
||
|
tableObj.deleteRecord()
|
||
|
}
|
||
|
|
||
|
// REGISTRATION
|
||
|
// ============================
|
||
|
|
||
|
$.oc.builder.entityControllers.databaseTable = DatabaseTable;
|
||
|
|
||
|
}(window.jQuery);
|