/* * 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 = $('') $button.text($form.attr('data-lang-add-timestamps')); $toolbar.append($button) $button = $('') $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);