class TeamsDatatable < CustomDatatable include InputSanitizeHelper def_delegator :@view, :link_to def_delegator :@view, :team_path def_delegator :@view, :leave_user_team_html_path MEMEBERS_SORT_COL = 'members'.freeze def initialize(view, user) super(view) @user = user end def sortable_columns @sortable_columns ||= [ 'Team.name', 'UserRole.name', MEMEBERS_SORT_COL ] end private # Returns json of current items (already paginated) def data records.map do |record| { 'DT_RowId': record.id, '0': if current_user_team_role(record)&.owner? link_to(escape_input(record.name), team_path(record)) else escape_input(record.name) end, '1': escape_input(current_user_team_role(record)&.name), '2': if current_user_team_role(record)&.viewer? I18n.t('users.settings.teams.index.na') else record.users.count end, '3': leave_team_button(record) } end end # Overwrite default pagination method as here # we need to be able work also with arrays def paginate_records(records) records.to_a.drop(offset).first(per_page) end def load_paginator self end # Overwrite default sort method to handle custom members column # which is calculated in code and not present in DB def sort_records(records) if sort_column(order_params) == MEMEBERS_SORT_COL records = records.sort_by(&proc { |team| team.users.count }) if order_params['dir'] == 'asc' records elsif order_params['dir'] == 'desc' records.reverse end elsif sort_column(order_params) == 'user_roles.name' records_with_role = records.joins(user_assignments: :user) .where(user_assignments: { user: @user }) .sort_by(&proc { |team| current_user_team_role(team)&.name }) records_with_no_role = records.joins("LEFT OUTER JOIN user_assignments AS current_user_assignments "\ "ON current_user_assignments.assignable_type = 'Team' "\ "AND current_user_assignments.assignable_id = teams.id "\ "AND current_user_assignments.user_id = #{@user.id}") .where(current_user_assignments: { id: nil }) records = records_with_no_role + records_with_role if order_params['dir'] == 'asc' records else records.reverse end else super(records) end end # If user is last admin of team, don't allow # him/her to leave team def leave_team_button(record) button = " #{I18n.t('users.settings.teams.index.leave')} " owner_role = UserRole.find_by(name: UserRole.public_send('owner_role').name) if current_user_team_role(record)&.owner? && record.user_assignments.where(user_role: owner_role).none? button.prepend('
') button << '
' else button = link_to( button.html_safe, leave_user_team_html_path(current_user_team_assignment(record), format: :json, leave: true), remote: true, class: 'btn btn-secondary btn-xs', type: 'button', data: { action: 'leave-user-team' } ) end button end # Query database for records (this will be later paginated and filtered) # after that "data" function will return json def get_raw_records @user.teams .preload(user_assignments: %i(user user_role)) .distinct end def current_user_team_assignment(team) team.user_assignments.find { |ua| ua.user == @user } end def current_user_team_role(team) current_user_team_assignment(team)&.user_role end end