Merge pull request #1851 from okriuchykhin/ok_SCI_3436

Implement saving of attachments ordering on steps [SCI-3436]
This commit is contained in:
Alex Kriuchykhin 2019-06-20 11:31:15 +02:00 committed by GitHub
commit db7c6435b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 94 additions and 21 deletions

View file

@ -667,13 +667,20 @@
}
// Reorder attachments
global.reorderAttachments = function reorderAtt(stepId, sortType) {
global.reorderAttachments = function reorderAtt(elem, stepId, sortType) {
var label_value = $("#dd-att-step-" + stepId + "> .dropdown-menu > li > a[data-order=" + sortType + "]").html();
$("#dd-att-step-" + stepId + "-label").html(label_value);
$('#att-' + stepId + ' a.file-preview-link').each(function(){
var elm = $(this)
elm.parent().css('order', elm.attr('data-order-' + sortType));
})
});
$.post(
$(elem).closest('.dropdown-menu').data('stateSavePath'),
{ assets: { order: sortType } },
null,
'json',
);
}
// On init

View file

@ -3,12 +3,11 @@ class StepsController < ApplicationController
include ApplicationHelper
include StepsActions
before_action :load_vars, only: %i(edit update destroy show toggle_step_state
checklistitem_state)
before_action :load_vars, only: %i(edit update destroy show toggle_step_state checklistitem_state update_view_state)
before_action :load_vars_nested, only: [:new, :create]
before_action :convert_table_contents_to_utf8, only: [:create, :update]
before_action :check_view_permissions, only: [:show]
before_action :check_view_permissions, only: %i(show update_view_state)
before_action :check_manage_permissions, only: %i(new create edit update
destroy)
before_action :check_complete_and_checkbox_permissions, only:
@ -190,6 +189,17 @@ class StepsController < ApplicationController
end
end
def update_view_state
view_state = @step.current_view_state(current_user)
view_state.state['assets']['sort'] = params.require(:assets).require(:order)
view_state.save! if view_state.changed?
respond_to do |format|
format.json do
render json: {}, status: :ok
end
end
end
def destroy
if @step.can_destroy?
# Update position on other steps of this module

View file

@ -8,11 +8,19 @@ module MyModulesHelper
end
def ordered_assets(step)
step.assets.order(:file_updated_at)
view_state = step.current_view_state(current_user)
sort = case view_state.state.dig('assets', 'sort')
when 'old' then { created_at: :asc }
when 'atoz' then { file_file_name: :asc }
when 'ztoa' then { file_file_name: :desc }
else { created_at: :desc }
end
step.assets.order(sort)
end
def az_ordered_assets_index(step, asset_id)
step.assets.order('LOWER(file_file_name)').pluck(:id).index(asset_id)
def az_ordered_assets_index(assets, asset_id)
assets.sort_by(&:file_file_name).map(&:id).index(asset_id)
end
def number_of_samples(my_module)

View file

@ -7,6 +7,18 @@ module ViewableModel
has_many :view_states, as: :viewable, dependent: :destroy
end
# This module requres that the class which includes it implements these methods:
# => default_view_state, returning hash with default state representation
# => validate_view_state(view_state), custom validator for the state hash
def default_view_state
raise NotImplementedError, 'default_view_state should be implemented!'
end
def validate_view_state(_view_state)
raise NotImplementedError, 'validate_view_state(view_state) should be implemented!'
end
def current_view_state(user)
state = view_states.where(user: user).take
state || view_states.create!(user: user, state: default_view_state)

View file

@ -2,6 +2,7 @@ class Step < ApplicationRecord
include SearchableModel
include SearchableByNameModel
include TinyMceImages
include ViewableModel
auto_strip_attributes :name, :description, nullify: false
validates :name,
@ -65,6 +66,16 @@ class Step < ApplicationRecord
end
end
def default_view_state
{ 'assets' => { 'sort' => 'new' } }
end
def validate_view_state(view_state)
unless %w(new old atoz ztoa).include?(view_state.state.dig('assets', 'sort'))
view_state.errors.add(:state, :wrong_state)
end
end
def destroy(current_user)
@current_user = current_user

View file

@ -57,6 +57,13 @@ class Team < ApplicationRecord
'filter' => 'active' } }
end
def validate_view_state(view_state)
unless %w(new old atoz ztoa).include?(view_state.state.dig('projects', 'cards', 'sort')) &&
%w(active archived).include?(view_state.state.dig('projects', 'filter'))
view_state.errors.add(:state, :wrong_state)
end
end
def search_users(query = nil)
a_query = "%#{query}%"
users.where.not(confirmed_at: nil)

View file

@ -8,4 +8,13 @@ class ViewState < ApplicationRecord
scope: %i(viewable_type user_id),
message: :not_unique
}
validate :validate_state_content
private
def validate_state_content
return unless state.present?
viewable.validate_view_state(self)
end
end

View file

@ -15,8 +15,8 @@
status: asset_status,
'present-url': present_url,
'preview-url': asset_file_preview_path(asset),
'order-atoz': az_ordered_assets_index(step, asset.id),
'order-ztoa': assets_count - az_ordered_assets_index(step, asset.id),
'order-atoz': order_atoz,
'order-ztoa': order_ztoa,
'order-old': i,
'order-new': assets_count - i,
} do %>

View file

@ -1,4 +1,4 @@
<% assets = ordered_assets step %>
<% assets = ordered_assets(step) %>
<div class="col-xs-12">
<hr>
</div>
@ -6,7 +6,7 @@
<div class="title">
<h4>
<%= t('protocols.steps.files', count: assets.count) %>
<%= t('protocols.steps.files', count: assets.length) %>
</h4>
</div>
<div>
@ -18,14 +18,17 @@
<% end %>
<div class="dropdown attachments-order" id="dd-att-step-<%= step.id %>">
<button class="btn btn-default dropdown-toggle" type="button" id="sortMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span id="dd-att-step-<%= step.id %>-label"><%= t('protocols.steps.attachments.sort_new').html_safe %></span>
<span id="dd-att-step-<%= step.id %>-label">
<%= t("protocols.steps.attachments.sort.#{step.current_view_state(current_user).state.dig('assets', 'sort')}_html") %>
</span>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="sortMenu">
<ul class="dropdown-menu" aria-labelledby="sortMenu" data-state-save-path="<%= update_view_state_step_path(step.id) %>">
<% ['new', 'old', 'atoz', 'ztoa'].each do |sort| %>
<li>
<a data-order="<%= sort %>" onClick="reorderAttachments('<%= step.id %>', '<%= sort %>')">
<%= t('protocols.steps.attachments.sort_' + sort ).html_safe %></a>
<a data-order="<%= sort %>" onClick="reorderAttachments(this, '<%= step.id %>', '<%= sort %>')">
<%= t("protocols.steps.attachments.sort.#{sort}_html") %>
</a>
</li>
<% end %>
</ul>
@ -36,8 +39,10 @@
<div class="col-xs-12 attachments" id="att-<%= step.id %>">
<% assets.each_with_index do |asset, i| %>
<% order_atoz = az_ordered_assets_index(assets, asset.id) %>
<% order_ztoa = assets.length - az_ordered_assets_index(assets, asset.id) %>
<%= render partial: 'steps/attachments/item.html.erb',
locals: { asset: asset, i: i, assets_count: assets.count, step: step } %>
locals: { asset: asset, i: i, assets_count: assets.length, step: step, order_atoz: order_atoz, order_ztoa: order_ztoa } %>
<% end %>
</div>
<hr>

View file

@ -75,6 +75,8 @@ en:
attributes:
viewable_id:
not_unique: "State already exists for this user and parent object"
state:
wrong_state: "Wrong parameters"
helpers:
label:
@ -1761,10 +1763,11 @@ en:
complete_title: "Complete Step"
uncomplete_title: "Uncomplete Step"
attachments:
sort_new: "Newest first &#8595;"
sort_old: "Oldest first &#8593;"
sort_atoz: "Name &#8595;"
sort_ztoa: "Name &#8593;"
sort:
new_html: "Newest first &#8595;"
old_html: "Oldest first &#8593;"
atoz_html: "Name &#8595;"
ztoa_html: "Name &#8593;"
modified_label: "Modified:"
new:
add_step_title: "Add new step"

View file

@ -435,6 +435,7 @@ Rails.application.routes.draw do
post 'toggle_step_state'
get 'move_down'
get 'move_up'
post 'update_view_state'
end
end