diff --git a/app/assets/javascripts/repositories/repository_datatable.js.erb b/app/assets/javascripts/repositories/repository_datatable.js.erb index 63a92ba63..3310146c0 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js.erb +++ b/app/assets/javascripts/repositories/repository_datatable.js.erb @@ -101,7 +101,7 @@ var RepositoryDatatable = (function(global) { $(row).addClass('selected'); } }, - // Next 2 options are shared with server-side default state + // Next 2 options are provided by server-side default state // (and get overriden once state load from server kicks in) order: <%= Constants::REPOSITORY_TABLE_DEFAULT_STATE[:order][0].to_s %>, columns: (function() { diff --git a/app/controllers/repository_columns_controller.rb b/app/controllers/repository_columns_controller.rb index 6d9910dcc..bd3018856 100644 --- a/app/controllers/repository_columns_controller.rb +++ b/app/controllers/repository_columns_controller.rb @@ -124,8 +124,9 @@ class RepositoryColumnsController < ApplicationController respond_to do |format| format.json do if @repository_column.destroy - RepositoryTableState.update_states_with_removed_column( - @del_repository_column, + service = RepositoryTableStateColumnUpdateService.new + service.update_states_with_removed_column( + @del_repository_column.repository, params[:repository_column][:column_index] ) render json: { diff --git a/app/controllers/user_repositories_controller.rb b/app/controllers/user_repositories_controller.rb index e416f9b25..2a6562c8f 100644 --- a/app/controllers/user_repositories_controller.rb +++ b/app/controllers/user_repositories_controller.rb @@ -2,7 +2,8 @@ class UserRepositoriesController < ApplicationController before_action :load_vars def save_table_state - RepositoryTableState.update_state(current_user, @repository, params[:state]) + service = RepositoryTableStateService.new(current_user, @repository) + service.update_state(params[:state]) respond_to do |format| format.json do render json: { @@ -13,14 +14,13 @@ class UserRepositoriesController < ApplicationController end def load_table_state - table_state = RepositoryTableState.load_state(current_user, - @repository) - .state + service = RepositoryTableStateService.new(current_user, @repository) + state = service.load_state.state respond_to do |format| - if table_state + if state format.json do render json: { - state: table_state + state: state } end end diff --git a/app/models/repository_column.rb b/app/models/repository_column.rb index 80c1fb440..9f92ec08d 100644 --- a/app/models/repository_column.rb +++ b/app/models/repository_column.rb @@ -24,7 +24,8 @@ class RepositoryColumn < ApplicationRecord scope :list_type, -> { where(data_type: 'RepositoryListValue') } def update_repository_table_states - RepositoryTableState.update_states_with_new_column(self) + service = RepositoryTableStateColumnUpdateService.new + service.update_states_with_new_column(self) end def importable? diff --git a/app/models/repository_table_state.rb b/app/models/repository_table_state.rb index d2f5e8ab4..0b83269e8 100644 --- a/app/models/repository_table_state.rb +++ b/app/models/repository_table_state.rb @@ -3,98 +3,4 @@ class RepositoryTableState < ApplicationRecord belongs_to :repository, inverse_of: :repository_table_states, optional: true validates :user, :repository, presence: true - - # We're using Constants::REPOSITORY_TABLE_DEFAULT_STATE as a reference for - # default table state; this Ruby Hash makes heavy use of Ruby symbols - # notation; HOWEVER, the state that is saved on the RepositoryTableState - # record, has EVERYTHING (booleans, symbols, keys, ...) saved as Strings. - - def self.load_state(user, repository) - state = where(user: user, repository: repository).take - if state.blank? - state = RepositoryTableState.create_default_state(user, repository) - end - state - end - - def self.update_state(user, repository, state) - RepositoryTableState.load_state(user, repository) - .update(state: state) - end - - def self.create_default_state(user, repository) - # Destroy any state object before recreating a new one - RepositoryTableState.where(user: user, repository: repository).destroy - - default_columns_num = - Constants::REPOSITORY_TABLE_DEFAULT_STATE[:length] - - # This state should be strings-only - state = HashUtil.deep_stringify_keys_and_values( - Constants::REPOSITORY_TABLE_DEFAULT_STATE - ) - repository.repository_columns.each_with_index do |_, index| - real_index = default_columns_num + index - state['columns'][real_index.to_s] = - HashUtil.deep_stringify_keys_and_values( - Constants::REPOSITORY_TABLE_STATE_CUSTOM_COLUMN_TEMPLATE - ) - state['ColReorder'] << real_index.to_s - end - state['length'] = state['columns'].length.to_s - state['time'] = Time.new.to_i.to_s - return RepositoryTableState.create(user: user, - repository: repository, - state: state) - end - - def self.update_states_with_new_column(new_column) - RepositoryTableState.where( - repository: new_column.repository - ).find_each do |table_state| - state = table_state.state - index = state['columns'].count - - # Add new columns, ColReorder, length entries - state['columns'][index.to_s] = - HashUtil.deep_stringify_keys_and_values( - Constants::REPOSITORY_TABLE_STATE_CUSTOM_COLUMN_TEMPLATE - ) - state['ColReorder'] << index.to_s - state['length'] = (index + 1).to_s - state['time'] = Time.new.to_i.to_s - table_state.save - end - end - - def self.update_states_with_removed_column(repository, old_column_index) - RepositoryTableState.where( - repository: repository - ).find_each do |table_state| - state = table_state.state - - # old_column_index is a String! - - # Remove column from ColReorder, columns, length entries - state['columns'].delete(old_column_index) - state['columns'].keys.each do |index| - if index.to_i > old_column_index.to_i - state['columns'][(index.to_i - 1).to_s] = - state['columns'].delete(index.to_s) - end - end - - state['ColReorder'].delete(old_column_index) - state['ColReorder'].map! do |index| - if index.to_i > old_column_index.to_i - (index.to_i - 1).to_s - else - index - end - end - state['length'] = (state['length'].to_i - 1).to_s - state['time'] = Time.new.to_i.to_s - table_state.save - end - end end diff --git a/app/services/repository_datatable_service.rb b/app/services/repository_datatable_service.rb index 705975eac..37af12f2f 100644 --- a/app/services/repository_datatable_service.rb +++ b/app/services/repository_datatable_service.rb @@ -95,8 +95,8 @@ class RepositoryDatatableService direction == column_obj[:dir].upcase end || 'ASC' column_index = column_obj[:column] - col_order = RepositoryTableState.load_state(@user, @repository) - .state['ColReorder'] + service = RepositoryTableStateService.new(@user, @repository) + col_order = service.load_state.state['ColReorder'] column_id = col_order[column_index].to_i if sortable_columns[column_id - 1] == 'assigned' diff --git a/app/services/repository_table_state_column_update_service.rb b/app/services/repository_table_state_column_update_service.rb new file mode 100644 index 000000000..0c7d853dd --- /dev/null +++ b/app/services/repository_table_state_column_update_service.rb @@ -0,0 +1,56 @@ +class RepositoryTableStateColumnUpdateService + # We're using Constants::REPOSITORY_TABLE_DEFAULT_STATE as a reference for + # default table state; this Ruby Hash makes heavy use of Ruby symbols + # notation; HOWEVER, the state that is saved on the RepositoryTableState + # record, has EVERYTHING (booleans, symbols, keys, ...) saved as Strings. + + def update_states_with_new_column(new_column) + RepositoryTableState.where( + repository: new_column.repository + ).find_each do |table_state| + state = table_state.state + index = state['columns'].count + + # Add new columns, ColReorder, length entries + state['columns'][index.to_s] = + HashUtil.deep_stringify_keys_and_values( + Constants::REPOSITORY_TABLE_STATE_CUSTOM_COLUMN_TEMPLATE + ) + state['ColReorder'] << index.to_s + state['length'] = (index + 1).to_s + state['time'] = Time.new.to_i.to_s + table_state.save + end + end + + def update_states_with_removed_column(repository, old_column_index) + RepositoryTableState.where( + repository: repository + ).find_each do |table_state| + state = table_state.state + + # old_column_index is a String! + + # Remove column from ColReorder, columns, length entries + state['columns'].delete(old_column_index) + state['columns'].keys.each do |index| + if index.to_i > old_column_index.to_i + state['columns'][(index.to_i - 1).to_s] = + state['columns'].delete(index.to_s) + end + end + + state['ColReorder'].delete(old_column_index) + state['ColReorder'].map! do |index| + if index.to_i > old_column_index.to_i + (index.to_i - 1).to_s + else + index + end + end + state['length'] = (state['length'].to_i - 1).to_s + state['time'] = Time.new.to_i.to_s + table_state.save + end + end +end \ No newline at end of file diff --git a/app/services/repository_table_state_service.rb b/app/services/repository_table_state_service.rb new file mode 100644 index 000000000..4fc78334c --- /dev/null +++ b/app/services/repository_table_state_service.rb @@ -0,0 +1,61 @@ +class RepositoryTableStateService + + attr_reader :user, :repository + + def initialize(user, repository) + @user = user + @repository = repository + end + + # We're using Constants::REPOSITORY_TABLE_DEFAULT_STATE as a reference for + # default table state; this Ruby Hash makes heavy use of Ruby symbols + # notation; HOWEVER, the state that is saved on the RepositoryTableState + # record, has EVERYTHING (booleans, symbols, keys, ...) saved as Strings. + + def load_state + state = RepositoryTableState.where(user: @user, repository: @repository).take + if state.blank? + state = self.create_default_state + end + state + end + + def update_state(state) + self.load_state + .update(state: state) + end + + def create_default_state + # Destroy any state object before recreating a new one + RepositoryTableState.where(user: @user, repository: @repository).destroy_all + + return RepositoryTableState.create( + user: @user, + repository: @repository, + state: generate_default_state + ) + end + + private + + def generate_default_state + default_columns_num = + Constants::REPOSITORY_TABLE_DEFAULT_STATE[:length] + + # This state should be strings-only + state = HashUtil.deep_stringify_keys_and_values( + Constants::REPOSITORY_TABLE_DEFAULT_STATE + ) + repository.repository_columns.each_with_index do |_, index| + real_index = default_columns_num + index + state['columns'][real_index.to_s] = + HashUtil.deep_stringify_keys_and_values( + Constants::REPOSITORY_TABLE_STATE_CUSTOM_COLUMN_TEMPLATE + ) + state['ColReorder'] << real_index.to_s + end + state['length'] = state['columns'].length.to_s + state['time'] = Time.new.to_i.to_s + state + end +end diff --git a/config/initializers/constants.rb b/config/initializers/constants.rb index e2f85e9e1..8019da32a 100644 --- a/config/initializers/constants.rb +++ b/config/initializers/constants.rb @@ -846,7 +846,7 @@ class Constants time: 0, start: 0, length: 6, - order: { 0 => [[2, 'asc']] }, # Default sorting by 'ID' column + order: { 0 => [2, 'asc'] }, # Default sorting by 'ID' column search: { search: '', smart: true, regex: false,