From 754384a15af2060fc0e6b7b3a7b25dc1346f6d31 Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Fri, 14 Jul 2023 11:29:09 +0100 Subject: [PATCH 01/47] Refactored options for publishing - more compact and collapsible. --- app/assets/javascripts/checkbox.js | 42 +++++++++ .../_options_for_publishing.html.erb | 87 ++++++++++++------- .../publishing/batch_publishing_test.rb | 2 +- .../publishing/single_publishing_test.rb | 10 +-- 4 files changed, 104 insertions(+), 37 deletions(-) diff --git a/app/assets/javascripts/checkbox.js b/app/assets/javascripts/checkbox.js index d5751b2fa2..9c060735a9 100644 --- a/app/assets/javascripts/checkbox.js +++ b/app/assets/javascripts/checkbox.js @@ -15,6 +15,15 @@ $j(document).ready(function () { event.preventDefault(); deselectChildren(this,$j(this).data("cb_parent_selector")) }) + $j("a.managed_by_toggle").click(function () { + toggleManagers(this,$j(this).data("managed_by_selector")) + }) + $j("div.isa-tree-toggle-open").click(function () { + isaTreeShow(this,$j(this).data("cb_parent_selector")) + }) + $j("div.isa-tree-toggle-close").click(function () { + isaTreeHide(this,$j(this).data("cb_parent_selector")) + }) }) function selectChildren(select_all_element,cb_parent_selector){ @@ -39,4 +48,37 @@ function checkRepeatedItems(checkbox_element) { for(let element of repeated_elements){ element.checked = check } +} + +function toggleManagers(item,managed_by_selector) { + $j(managed_by_selector).toggle() +} + +function isaTreeShow(item,cb_parent_selector) { + let children_assets = $j('.isa-tree', $j(item).parents(cb_parent_selector)) + children_assets.splice(0, 1); + let keep_closed = [] + for (let asset of children_assets) { + $j(asset).show() + for (let caret of $j('.isa-tree-toggle-close', $j(asset))){ + if (caret.style.display == "none"){ + keep_closed.push(caret) + } + } + } + $j($j('.isa-tree-toggle-open', $j(item).parents(cb_parent_selector))[0]).hide() + $j($j('.isa-tree-toggle-close', $j(item).parents(cb_parent_selector))[0]).show() + + for (let caret of keep_closed){ + isaTreeHide(caret,$j(caret).data("cb_parent_selector")) + } +} +function isaTreeHide(item,cb_parent_selector){ + let children_assets = $j('.isa-tree', $j(item).parents(cb_parent_selector)) + children_assets.splice(0, 1); + for (let asset of children_assets) { + $j(asset).hide() + } + $j($j('.isa-tree-toggle-open', $j(item).parents(cb_parent_selector))[0]).show() + $j($j('.isa-tree-toggle-close', $j(item).parents(cb_parent_selector))[0]).hide() } \ No newline at end of file diff --git a/app/views/assets/publishing/_options_for_publishing.html.erb b/app/views/assets/publishing/_options_for_publishing.html.erb index 403fe471ea..3bf01616e9 100644 --- a/app/views/assets/publishing/_options_for_publishing.html.erb +++ b/app/views/assets/publishing/_options_for_publishing.html.erb @@ -8,44 +8,69 @@ toggle ||=false cb_parent_selector ||="div\##{item.class.name}_#{item.id}.split_button_parent" + show_managers=true + managed_by_selector ||="div\##{item.class.name}_#{item.id}.managed_by_toggle" -%>
- <% if item.can_view? %> -
- <%= text_for_resource item -%>: <%= link_to item.title, item, :target => "_blank" -%> - <%=list_item_visibility(item)-%> -
-
Manageable by <%= item.managers.empty? ? "None".html_safe : item.managers.collect { |m| link_to(h(m.title), m) }.join(", ").html_safe -%>
- <% else %> -
<%= text_for_resource item -%>: This item is hidden to you
- <% if current_user.try(:person) && item.can_see_hidden_item?(current_user.person) %> -
Manageable by <%= item.managers.empty? ? "
None
".html_safe : item.managers.collect { |m| link_to(h(m.title), m) }.join(", ").html_safe -%>
- <% end %> + <% if toggle %> +
+ +
+
+ +
<% end %> - -
- <% if item.is_published? %> - <%= render :partial => 'general/split_button_checkbox', - locals: { checkbox_id: publishing_item_param(item), - checkbox_class: "#{item.class.name}_#{item.id}", - published: true, - toggle: toggle, - cb_parent_selector: cb_parent_selector} -%> - <% elsif item.can_publish? %> - <%= render :partial => 'general/split_button_checkbox', - locals: { checkbox_id: publishing_item_param(item), - checkbox_class: "#{item.class.name}_#{item.id}", - checkbox_text: "Publish?", - checked: checked, - toggle: toggle, - cb_parent_selector: cb_parent_selector} -%> - <% else %> + <% if item.can_view? %> +
+ <% if item.is_published? %> + <%= render :partial => 'general/split_button_checkbox', + locals: { checkbox_id: publishing_item_param(item), + checkbox_class: "#{item.class.name}_#{item.id}", + published: true, + toggle: toggle, + cb_parent_selector: cb_parent_selector} -%> + <% elsif item.can_publish? %> + <%= render :partial => 'general/split_button_checkbox', + locals: { checkbox_id: publishing_item_param(item), + checkbox_class: "#{item.class.name}_#{item.id}", + checkbox_text: "", + checked: checked, + toggle: toggle, + cb_parent_selector: cb_parent_selector} -%> + <% else %> - Can't publish + <% end %> +
+
+ <%= text_for_resource item -%>: <%= link_to item.title, item, :target => "_blank" -%> + <%=list_item_visibility(item)-%> +
+ <% else %> +
+ + + +
+
<%= text_for_resource item -%>: This item is hidden to you
+ <% unless current_user.try(:person) && item.can_see_hidden_item?(current_user.person) %> + <% show_managers=false%> <% end %> -
+ <% end %> + <% if show_managers %> +
+ +
style="display:none;margin-left:5em"> + Manageable by <%= item.managers.empty? ? "None".html_safe : item.managers.collect { |m| link_to(h(m.title), m) }.join(", ").html_safe -%> +
+
+ <% end %>
+ diff --git a/test/functional/publishing/batch_publishing_test.rb b/test/functional/publishing/batch_publishing_test.rb index b90cdd2993..aeac3eb6ab 100644 --- a/test/functional/publishing/batch_publishing_test.rb +++ b/test/functional/publishing/batch_publishing_test.rb @@ -59,7 +59,7 @@ def setup assert_select '.type_and_title img[src*=?][title=?]', 'lock.png', 'Private', count: total_asset_count end - assert_select '.parent-btn-checkbox', text: /Publish/, count: total_asset_count do + assert_select '.parent-btn-checkbox', count: total_asset_count do publish_immediately_assets.each do |a| assert_select "input[type='checkbox'][id=?]", "publish_#{a.class.name}_#{a.id}" end diff --git a/test/functional/publishing/single_publishing_test.rb b/test/functional/publishing/single_publishing_test.rb index 8f77468a73..4638c54f76 100644 --- a/test/functional/publishing/single_publishing_test.rb +++ b/test/functional/publishing/single_publishing_test.rb @@ -109,21 +109,21 @@ def setup assert_select '.type_and_title', text: /Investigation/, count: 1 do assert_select 'a[href=?]', investigation_path(investigation), text: /#{investigation.title}/ end - assert_select '.parent-btn-checkbox', text: /Publish/ do + assert_select '.parent-btn-checkbox' do assert_select "input[type='checkbox'][id=?]", "publish_Investigation_#{investigation.id}" end assert_select '.type_and_title', text: /Study/, count: 1 do assert_select 'a[href=?]', study_path(study), text: /#{study.title}/ end - assert_select '.parent-btn-checkbox', text: /Publish/ do + assert_select '.parent-btn-checkbox' do assert_select "input[type='checkbox'][id=?]", "publish_Study_#{study.id}" end assert_select '.type_and_title', text: /Assay/, count: 1 do assert_select 'a[href=?]', assay_path(assay), text: /#{assay.title}/ end - assert_select '.parent-btn-checkbox', text: /Publish/ do + assert_select '.parent-btn-checkbox' do assert_select "input[type='checkbox'][id=?]", "publish_Assay_#{assay.id}" end @@ -133,12 +133,12 @@ def setup assert_select 'a[href=?]', data_file_path(request_publishing_df), text: /#{request_publishing_df.title}/ assert_select 'a[href=?]', data_file_path(notifying_df), text: /#{notifying_df.title}/ end - assert_select '.parent-btn-checkbox', text: /Publish/ do + assert_select '.parent-btn-checkbox' do assert_select "input[type='checkbox'][id=?]", "publish_DataFile_#{publishing_df.id}" assert_select "input[type='checkbox'][id=?]", "publish_DataFile_#{request_publishing_df.id}" end - assert_select 'span.label-warning', text: "Can't publish", count: 1 + assert_select 'span.label-warning[data-tooltip=?]', 'You do not have permission to publish this item.', count: 1 end test 'split-button recursive selection' do From 8741deae0f554bf257b501bc8dda9e7eb460c7aa Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Wed, 19 Jul 2023 17:26:39 +0100 Subject: [PATCH 02/47] Refactored batch publishing preview - options for sorting and js --- app/assets/javascripts/checkbox.js | 54 ++++++- .../_isa_publishing_preview.html.erb | 1 + .../batch_publishing_preview.html.erb | 148 +++++++++++++++--- lib/seek/publishing/publishing_common.rb | 19 ++- 4 files changed, 194 insertions(+), 28 deletions(-) diff --git a/app/assets/javascripts/checkbox.js b/app/assets/javascripts/checkbox.js index 9c060735a9..cfaecfd5d3 100644 --- a/app/assets/javascripts/checkbox.js +++ b/app/assets/javascripts/checkbox.js @@ -24,6 +24,22 @@ $j(document).ready(function () { $j("div.isa-tree-toggle-close").click(function () { isaTreeHide(this,$j(this).data("cb_parent_selector")) }) + $j("a.collapseChildren").click(function (event) { + event.preventDefault(); + collapseRecursively($j(this).data("cb_parent_selector")) + }) + $j("a.expandChildren").click(function (event) { + event.preventDefault(); + expandRecursively($j(this).data("cb_parent_selector")) + }) + $j(".hideBlocked").click(function (event) { + event.preventDefault(); + hideBlocked($j(this).data("cb_parent_selector"),$j(this).data("blocked_selector")) + }) + $j(".showBlocked").click(function (event) { + event.preventDefault(); + showBlocked($j(this).data("cb_parent_selector"),$j(this).data("blocked_selector")) + }) }) function selectChildren(select_all_element,cb_parent_selector){ @@ -56,7 +72,9 @@ function toggleManagers(item,managed_by_selector) { function isaTreeShow(item,cb_parent_selector) { let children_assets = $j('.isa-tree', $j(item).parents(cb_parent_selector)) - children_assets.splice(0, 1); + if(cb_parent_selector.includes('split_button_parent')){ + children_assets.splice(0, 1); + } let keep_closed = [] for (let asset of children_assets) { $j(asset).show() @@ -75,10 +93,40 @@ function isaTreeShow(item,cb_parent_selector) { } function isaTreeHide(item,cb_parent_selector){ let children_assets = $j('.isa-tree', $j(item).parents(cb_parent_selector)) - children_assets.splice(0, 1); + if(cb_parent_selector.includes('split_button_parent')){ + children_assets.splice(0, 1); + } for (let asset of children_assets) { $j(asset).hide() } $j($j('.isa-tree-toggle-open', $j(item).parents(cb_parent_selector))[0]).show() $j($j('.isa-tree-toggle-close', $j(item).parents(cb_parent_selector))[0]).hide() -} \ No newline at end of file +} + +function collapseRecursively(cb_parent_selector){ + let children_assets = $j('[class^=isa-tree-toggle]', $j(cb_parent_selector)) + for (let asset of children_assets) { + isaTreeHide(asset,$j(asset).data("cb_parent_selector")) + } +} + +function expandRecursively(cb_parent_selector){ + let children_assets = $j('[class^=isa-tree-toggle]', $j(cb_parent_selector)) + for (let asset of children_assets) { + isaTreeShow(asset,$j(asset).data("cb_parent_selector")) + } +} + +function hideBlocked(cb_parent_selector,blocked_selector){ + let children_assets = $j(blocked_selector, $j(cb_parent_selector)) + for (let asset of children_assets) { + $j($j(asset).parents('div.split_button_parent')[0]).hide() + } +} + +function showBlocked(cb_parent_selector,blocked_selector){ + let children_assets = $j(blocked_selector, $j(cb_parent_selector)) + for (let asset of children_assets) { + $j($j(asset).parents('div.split_button_parent')[0]).show() + } +} diff --git a/app/views/assets/publishing/_isa_publishing_preview.html.erb b/app/views/assets/publishing/_isa_publishing_preview.html.erb index 53779ae75a..5e22c36ac8 100644 --- a/app/views/assets/publishing/_isa_publishing_preview.html.erb +++ b/app/views/assets/publishing/_isa_publishing_preview.html.erb @@ -1,5 +1,6 @@ <% item = isa_publishing_preview + preselected ||=[] case item when Investigation diff --git a/app/views/assets/publishing/batch_publishing_preview.html.erb b/app/views/assets/publishing/batch_publishing_preview.html.erb index 625fca6bae..cc9055d779 100644 --- a/app/views/assets/publishing/batch_publishing_preview.html.erb +++ b/app/views/assets/publishing/batch_publishing_preview.html.erb @@ -11,17 +11,10 @@

- You can select an item to be published by checking the Publish - checkbox beside that item. + You can select an item to be published by checking the checkbox beside that item.

-
- - | - <%= form_tag({:action => :check_related_items},:method=>:post) do -%> <% if @assets.empty? %> @@ -30,23 +23,124 @@
<%= link_to "Back to profile", person_path(params[:id].to_i) -%> <% else %> - <% @assets.sort_by { |k, v| v.first.class.name }.each do |type, items| %> -
-

<%= text_for_resource items.first %>(s)

- | - - <% items.each do |item| %> - <%= render :partial => "assets/publishing/options_for_publishing", - :object => item, - :locals => { :html_classes => "publishing_options" } -%> -
+ +
+ + +
+

+
+ | + | + | + +
+ +
+ <% @assets.sort_by { |k, v| v.first.class.name }.each do |type, items| %> +
+
+ +
+
+ +
+

<%= text_for_resource items.first %>(s)

+ +
+ <% end %> +
+
+ +
+ <% unless @assets_not_in_isa.empty? %> +
+
+ +
+
+ +
+

Items not in ISA

+ + <% @assets_not_in_isa.each do |item| %> + <%= render :partial => "assets/publishing/options_for_publishing", + :object => item, + :locals => { :html_classes => "publishing_options" } -%> + <% end %> +
+
<% end %> -
- <% end %> + +
+ + <% unless @investigations.empty? %> +
+
+ +
+
+ +
+

Items in ISA

+ +
+ <% @investigations.each do |inv| %> + <%= render :partial => "assets/publishing/isa_publishing_preview", + :collection => inv.assays.map(&:study).map(&:investigation).flatten.uniq %> + <% end %> +
+
+
+ <% end %> +
+
<%= submit_tag "Next",data: { disable_with: 'Next' }, :class => 'btn btn-primary' -%> @@ -54,3 +148,9 @@ <%= cancel_button person_path(params[:id].to_i)-%> <% end -%> <% end -%> + + diff --git a/lib/seek/publishing/publishing_common.rb b/lib/seek/publishing/publishing_common.rb index f8410d2515..1979158ba8 100644 --- a/lib/seek/publishing/publishing_common.rb +++ b/lib/seek/publishing/publishing_common.rb @@ -3,7 +3,7 @@ module Publishing module PublishingCommon def self.included(base) base.before_action :set_asset, only: [:check_related_items, :publish_related_items, :check_gatekeeper_required, :publish, :published] - base.before_action :set_assets, only: [:batch_publishing_preview] + base.before_action :set_assets, :set_investigations, only: [:batch_publishing_preview] base.before_action :set_items_for_publishing, only: [:check_gatekeeper_required, :publish] base.before_action :set_items_for_potential_publishing, only: [:check_related_items, :publish_related_items] base.before_action :publish_auth, only: [:batch_publishing_preview, :check_related_items, :publish_related_items, :check_gatekeeper_required, :publish, :waiting_approval_assets, :cancel_publishing_request] @@ -145,6 +145,23 @@ def set_assets end end + def set_investigations + @investigations = [] + @assets_not_in_isa = [] + @assets.each do |type, klass| + klass.each do |asset| + if asset.investigations.empty? + @assets_not_in_isa.push(asset) + else + asset.investigations.each do |inv| + next if @investigations.include?(inv) + @investigations.push(inv) + end + end + end + end + end + # sets the @items_for_publishing based on the :publish param, and filtered by whether than can_publish? def set_items_for_publishing @items_for_publishing = resolve_publish_params(params[:publish]).select(&:can_publish?) From 8b42a159ccbc18f17589a5cd0b4f14372c3fa925 Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Fri, 21 Jul 2023 16:05:16 +0100 Subject: [PATCH 03/47] Created batch_asset_selection and isa_tree_toggle partials --- .../assets/_batch_asset_selection.html.erb | 119 ++++++++++++++++ app/views/assets/_isa-tree-toggle.html.erb | 16 +++ .../_isa_publishing_preview.html.erb | 2 + .../_options_for_publishing.html.erb | 14 +- .../batch_publishing_preview.html.erb | 131 +----------------- .../publishing/publish_related_items.html.erb | 4 +- 6 files changed, 147 insertions(+), 139 deletions(-) create mode 100644 app/views/assets/_batch_asset_selection.html.erb create mode 100644 app/views/assets/_isa-tree-toggle.html.erb diff --git a/app/views/assets/_batch_asset_selection.html.erb b/app/views/assets/_batch_asset_selection.html.erb new file mode 100644 index 0000000000..866b42c46d --- /dev/null +++ b/app/views/assets/_batch_asset_selection.html.erb @@ -0,0 +1,119 @@ +<% + publishing ||= true + show_hide_blocked ||= false + blocked_selector ||= '' +-%> + + +
+ + +
+

+
+ | + | + | + +
+ +
+ <% @assets.sort_by { |k, v| v.first.class.name }.each do |type, items| %> +
+ <%= render :partial => 'assets/isa-tree-toggle', locals: { cb_parent_selector: "div##{items.first.class.table_name}" } -%> +

<%= text_for_resource items.first %>(s)

+
+ | + + <% items.each do |item| %> + <%= render :partial => "assets/publishing/options_for_publishing", + :object => item, + :block_published => publishing, + :locals => { :html_classes => "publishing_options" } -%> + <% end %> +
+
+ <% end %> +
+
+ +
+ <% unless @assets_not_in_isa.empty? %> +
+ <%= render :partial => 'assets/isa-tree-toggle', locals: { cb_parent_selector: "div#items_not_in_isa" } -%> +

Items not in ISA

+ + <% @assets_not_in_isa.each do |item| %> + <%= render :partial => "assets/publishing/options_for_publishing", + :object => item, + :block_published => publishing, + :locals => { :html_classes => "publishing_options" } -%> + <% end %> +
+
+ <% end %> + +
+ + <% unless @investigations.empty? %> +
+ <%= render :partial => 'assets/isa-tree-toggle', locals: { cb_parent_selector: "div#items_in_isa" } -%> +

Items in ISA

+ +
+ <% @investigations.each do |inv| %> + <%= render :partial => "assets/publishing/isa_publishing_preview", + :locals => { :publishing => publishing }, + :collection => inv.assays.map(&:study).map(&:investigation).flatten.uniq %> + <% end %> +
+
+
+ <% end %> +
+ + \ No newline at end of file diff --git a/app/views/assets/_isa-tree-toggle.html.erb b/app/views/assets/_isa-tree-toggle.html.erb new file mode 100644 index 0000000000..985efd7d17 --- /dev/null +++ b/app/views/assets/_isa-tree-toggle.html.erb @@ -0,0 +1,16 @@ +<% + cb_parent_selector ||="" +-%> + +
+ +
+
+ +
+ + diff --git a/app/views/assets/publishing/_isa_publishing_preview.html.erb b/app/views/assets/publishing/_isa_publishing_preview.html.erb index 5e22c36ac8..ca8e354963 100644 --- a/app/views/assets/publishing/_isa_publishing_preview.html.erb +++ b/app/views/assets/publishing/_isa_publishing_preview.html.erb @@ -1,6 +1,7 @@ <% item = isa_publishing_preview preselected ||=[] + publishing ||= false case item when Investigation @@ -19,6 +20,7 @@ :locals => { :html_classes => "publishing_options", :toggle => children.any?, :cb_parent_selector => "div\##{item.class.name}_#{item.id}.split_button_parent", + :block_published => publishing, :checked => (item == preselected) } -%> <% if children.any? %> diff --git a/app/views/assets/publishing/_options_for_publishing.html.erb b/app/views/assets/publishing/_options_for_publishing.html.erb index 3bf01616e9..d8bc91eae1 100644 --- a/app/views/assets/publishing/_options_for_publishing.html.erb +++ b/app/views/assets/publishing/_options_for_publishing.html.erb @@ -1,6 +1,7 @@ <% item = options_for_publishing checked ||= false + block_published ||= false tree_class = 'not-publishable' tree_class = 'publishable' if item.can_publish? @@ -14,12 +15,7 @@ -%>
<% if toggle %> -
- -
-
- -
+ <%= render :partial => 'assets/isa-tree-toggle', locals: { cb_parent_selector: cb_parent_selector } -%> <% end %> <% if item.can_view? %>
@@ -68,9 +64,3 @@
<% end %>
- - diff --git a/app/views/assets/publishing/batch_publishing_preview.html.erb b/app/views/assets/publishing/batch_publishing_preview.html.erb index cc9055d779..56b9145061 100644 --- a/app/views/assets/publishing/batch_publishing_preview.html.erb +++ b/app/views/assets/publishing/batch_publishing_preview.html.erb @@ -23,134 +23,15 @@
<%= link_to "Back to profile", person_path(params[:id].to_i) -%> <% else %> - -
- - -
-

-
- | - | - | - -
- -
- <% @assets.sort_by { |k, v| v.first.class.name }.each do |type, items| %> -
-
- -
-
- -
-

<%= text_for_resource items.first %>(s)

- -
- <% end %> -
-
- -
- <% unless @assets_not_in_isa.empty? %> -
-
- -
-
- -
-

Items not in ISA

- - <% @assets_not_in_isa.each do |item| %> - <%= render :partial => "assets/publishing/options_for_publishing", - :object => item, - :locals => { :html_classes => "publishing_options" } -%> - <% end %> -
-
- <% end %> - -
- - <% unless @investigations.empty? %> -
-
- -
-
- -
-

Items in ISA

- -
- <% @investigations.each do |inv| %> - <%= render :partial => "assets/publishing/isa_publishing_preview", - :collection => inv.assays.map(&:study).map(&:investigation).flatten.uniq %> - <% end %> -
-
-
- <% end %> -
- + <%= render :partial => "assets/batch_asset_selection", + :locals => { :publishing => true, + :show_hide_blocked => true, + :blocked_selector => '.not-visible,.not-publishable,.already-published' + } + -%>
- <%= submit_tag "Next",data: { disable_with: 'Next' }, :class => 'btn btn-primary' -%> Or <%= cancel_button person_path(params[:id].to_i)-%> <% end -%> <% end -%> - - diff --git a/app/views/assets/publishing/publish_related_items.html.erb b/app/views/assets/publishing/publish_related_items.html.erb index 7bb8cdc55e..8e368393e4 100644 --- a/app/views/assets/publishing/publish_related_items.html.erb +++ b/app/views/assets/publishing/publish_related_items.html.erb @@ -18,10 +18,10 @@ <% if item.is_asset? %> <%= render :partial => "assets/publishing/isa_publishing_preview", :collection => item.assays.map(&:study).map(&:investigation).flatten.uniq, - :locals => { :preselected => item } %> + :locals => { :preselected => item, :publishing => true } %> <% else %> <%= render :partial => "assets/publishing/isa_publishing_preview", :object => item, - :locals => { :preselected => item } %> + :locals => { :preselected => item, :publishing => true } %> <% end %> <% else %> <%= check_box_tag publishing_item_param(item), 1, true, {:style => 'display:none;'} %> From 39630f1d4fec1e45ef8f67788ad3b5c097a3de4e Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Fri, 21 Jul 2023 16:09:06 +0100 Subject: [PATCH 04/47] Homogenised parent-btn-checkbox appearance and fixed hideBlocked. --- app/assets/javascripts/checkbox.js | 5 ++- app/assets/stylesheets/publishing.scss | 4 ++ app/assets/stylesheets/sharing.scss | 1 + .../_options_for_publishing.html.erb | 39 ++++++++----------- .../general/_split_button_checkbox.html.erb | 34 ++++++++++++---- .../publishing/batch_publishing_test.rb | 36 +++++++++-------- .../publishing/single_publishing_test.rb | 4 +- 7 files changed, 75 insertions(+), 48 deletions(-) diff --git a/app/assets/javascripts/checkbox.js b/app/assets/javascripts/checkbox.js index cfaecfd5d3..6aad9d7537 100644 --- a/app/assets/javascripts/checkbox.js +++ b/app/assets/javascripts/checkbox.js @@ -120,7 +120,10 @@ function expandRecursively(cb_parent_selector){ function hideBlocked(cb_parent_selector,blocked_selector){ let children_assets = $j(blocked_selector, $j(cb_parent_selector)) for (let asset of children_assets) { - $j($j(asset).parents('div.split_button_parent')[0]).hide() + // Don't hide "parents" of non-blocked items + if(!$j('input[type=checkbox]',$j(asset).parent()).length>0) { + $j($j(asset).parents('div.split_button_parent')[0]).hide() + } } } diff --git a/app/assets/stylesheets/publishing.scss b/app/assets/stylesheets/publishing.scss index 1de7aec917..6e47fdcdd7 100644 --- a/app/assets/stylesheets/publishing.scss +++ b/app/assets/stylesheets/publishing.scss @@ -73,6 +73,10 @@ ul.item_for_decision { border-left-color: $btn-warning-bg; } + &.not-visible { + border-left-color: $btn-danger-bg; + } + &.already-published { border-left-color: $gray-light; } diff --git a/app/assets/stylesheets/sharing.scss b/app/assets/stylesheets/sharing.scss index d396101a0c..9a4ce89df3 100644 --- a/app/assets/stylesheets/sharing.scss +++ b/app/assets/stylesheets/sharing.scss @@ -216,6 +216,7 @@ border-radius: 5px; display: inline-block; height: 25px; + cursor: default; } .parent-btn-dropdown { padding: 2px 6px 10px 0px; diff --git a/app/views/assets/publishing/_options_for_publishing.html.erb b/app/views/assets/publishing/_options_for_publishing.html.erb index d8bc91eae1..87831e6b81 100644 --- a/app/views/assets/publishing/_options_for_publishing.html.erb +++ b/app/views/assets/publishing/_options_for_publishing.html.erb @@ -6,6 +6,7 @@ tree_class = 'not-publishable' tree_class = 'publishable' if item.can_publish? tree_class = 'already-published' if item.is_published? + tree_class = 'not-visible' unless item.can_view? toggle ||=false cb_parent_selector ||="div\##{item.class.name}_#{item.id}.split_button_parent" @@ -19,26 +20,15 @@ <% end %> <% if item.can_view? %>
- <% if item.is_published? %> - <%= render :partial => 'general/split_button_checkbox', - locals: { checkbox_id: publishing_item_param(item), - checkbox_class: "#{item.class.name}_#{item.id}", - published: true, - toggle: toggle, - cb_parent_selector: cb_parent_selector} -%> - <% elsif item.can_publish? %> - <%= render :partial => 'general/split_button_checkbox', - locals: { checkbox_id: publishing_item_param(item), - checkbox_class: "#{item.class.name}_#{item.id}", - checkbox_text: "", - checked: checked, - toggle: toggle, - cb_parent_selector: cb_parent_selector} -%> - <% else %> - - - - <% end %> + <%= render :partial => 'general/split_button_checkbox', + locals: { checkbox_id: publishing_item_param(item), + checkbox_class: "#{item.class.name}_#{item.id}", + checked: checked, + checkbox_text: "", + published: (item.is_published? && block_published), + cant_manage: !(item.can_manage?), + toggle: toggle, + cb_parent_selector: cb_parent_selector} -%>
<%= text_for_resource item -%>: <%= link_to item.title, item, :target => "_blank" -%> @@ -46,9 +36,12 @@
<% else %>
- - - + <%= render :partial => 'general/split_button_checkbox', + locals: { checkbox_id: publishing_item_param(item), + checkbox_class: "#{item.class.name}_#{item.id}", + not_visible: true, + toggle: toggle, + cb_parent_selector: cb_parent_selector} -%>
<%= text_for_resource item -%>: This item is hidden to you
<% unless current_user.try(:person) && item.can_see_hidden_item?(current_user.person) %> diff --git a/app/views/general/_split_button_checkbox.html.erb b/app/views/general/_split_button_checkbox.html.erb index fbf98b52f3..9bdd827f5e 100644 --- a/app/views/general/_split_button_checkbox.html.erb +++ b/app/views/general/_split_button_checkbox.html.erb @@ -2,7 +2,9 @@ #<%= render :partial => 'general/split_button_checkbox', #locals: { checkbox_id: publishing_item_param(item), # checkbox_class: "#{item.class.name}_#{item.id}", - # published: true, + # published: false, + # cant_manage: false + # not_visible: false # checkbox_text: "Publish?", # checked: checked, # toggle: children.any?, @@ -11,27 +13,45 @@ checkbox_class ||= "no_name" # <- Needed! checkbox_id ||= checkbox_class published ||= false + cant_manage ||= false + not_visible ||= false checkbox_text ||= "" checked ||= false toggle ||= false cb_parent_selector ||= "div\##{checkbox_class}.split_button_parent" -%>
- + <% elsif cant_manage %> + + <% elsif not_visible %> + + <% else %> + + + <% end %> + <% if toggle %>
<% @investigations.each do |inv| %> - <%= render :partial => "assets/publishing/isa_publishing_preview", + <%= render :partial => "assets/isa_tree_preview", :locals => { :publishing => publishing }, :collection => inv.assays.map(&:study).map(&:investigation).flatten.uniq %> <% end %> diff --git a/app/views/assets/_isa_tree_preview.html.erb b/app/views/assets/_isa_tree_preview.html.erb new file mode 100644 index 0000000000..f0c827885a --- /dev/null +++ b/app/views/assets/_isa_tree_preview.html.erb @@ -0,0 +1,37 @@ +<% + item = isa_tree_preview + preselected ||=[] + publishing ||= false + + case item + when Investigation + children = item.studies + when Study + children = item.assays + when Assay + children = item.assets + else + children = [] + end +-%> +
"> + <%= render :partial => "assets/asset_checkbox_row", + :object => item, + :locals => { :html_classes => "publishing_options", + :toggle => children.any?, + :cb_parent_selector => "div\##{item.class.name}_#{item.id}.split_button_parent", + :block_published => publishing, + :checked => (item == preselected) } -%> + + <% if children.any? %> +
+ <% children.each do |child| %> + <%= render :partial => "assets/isa_tree_preview", + :object => child, + :locals => { :preselected => preselected, + :publishing => publishing, + :html_classes => "publishing_options"} -%> + <% end %> +
+ <% end %> +
\ No newline at end of file diff --git a/app/views/assets/publishing/_isa_publishing_preview.html.erb b/app/views/assets/publishing/_isa_publishing_preview.html.erb deleted file mode 100644 index ca8e354963..0000000000 --- a/app/views/assets/publishing/_isa_publishing_preview.html.erb +++ /dev/null @@ -1,36 +0,0 @@ -<% - item = isa_publishing_preview - preselected ||=[] - publishing ||= false - - case item - when Investigation - children = item.studies - when Study - children = item.assays - when Assay - children = item.assets - else - children = [] - end --%> -
"> - <%= render :partial => "assets/publishing/options_for_publishing", - :object => item, - :locals => { :html_classes => "publishing_options", - :toggle => children.any?, - :cb_parent_selector => "div\##{item.class.name}_#{item.id}.split_button_parent", - :block_published => publishing, - :checked => (item == preselected) } -%> - - <% if children.any? %> -
- <% children.each do |child| %> - <%= render :partial => "assets/publishing/isa_publishing_preview", - :object => child, - :locals => { :preselected => preselected, - :html_classes => "publishing_options"} -%> - <% end %> -
- <% end %> -
\ No newline at end of file diff --git a/app/views/assets/publishing/batch_publishing_preview.html.erb b/app/views/assets/publishing/batch_publishing_preview.html.erb index 56b9145061..bab2590b4b 100644 --- a/app/views/assets/publishing/batch_publishing_preview.html.erb +++ b/app/views/assets/publishing/batch_publishing_preview.html.erb @@ -26,7 +26,7 @@ <%= render :partial => "assets/batch_asset_selection", :locals => { :publishing => true, :show_hide_blocked => true, - :blocked_selector => '.not-visible,.not-publishable,.already-published' + :blocked_selector => '.not-visible,.not-manageable,.already-published' } -%>
diff --git a/app/views/assets/publishing/publish_related_items.html.erb b/app/views/assets/publishing/publish_related_items.html.erb index 8e368393e4..ac7ea874a1 100644 --- a/app/views/assets/publishing/publish_related_items.html.erb +++ b/app/views/assets/publishing/publish_related_items.html.erb @@ -16,11 +16,11 @@ <% @items_for_publishing.each do |item| %> <% if item.contains_publishable_items? %> <% if item.is_asset? %> - <%= render :partial => "assets/publishing/isa_publishing_preview", + <%= render :partial => "assets/isa_tree_preview", :collection => item.assays.map(&:study).map(&:investigation).flatten.uniq, :locals => { :preselected => item, :publishing => true } %> <% else %> - <%= render :partial => "assets/publishing/isa_publishing_preview", :object => item, + <%= render :partial => "assets/isa_tree_preview", :object => item, :locals => { :preselected => item, :publishing => true } %> <% end %> <% else %> From 0b386762130ce700d2e6e07a8140c5a9ae76e483 Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Tue, 25 Jul 2023 10:48:38 +0100 Subject: [PATCH 06/47] Fixes issues with published and blocked items, and hides blocked by default --- app/assets/javascripts/checkbox.js | 18 ++++++++++++++---- app/views/assets/_asset_checkbox_row.html.erb | 2 +- .../assets/_batch_asset_selection.html.erb | 17 +++++++++++++---- lib/seek/publishing/publishing_common.rb | 3 +-- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/checkbox.js b/app/assets/javascripts/checkbox.js index 6aad9d7537..1245bd5675 100644 --- a/app/assets/javascripts/checkbox.js +++ b/app/assets/javascripts/checkbox.js @@ -120,9 +120,15 @@ function expandRecursively(cb_parent_selector){ function hideBlocked(cb_parent_selector,blocked_selector){ let children_assets = $j(blocked_selector, $j(cb_parent_selector)) for (let asset of children_assets) { - // Don't hide "parents" of non-blocked items - if(!$j('input[type=checkbox]',$j(asset).parent()).length>0) { - $j($j(asset).parents('div.split_button_parent')[0]).hide() + //Items in isa tree + if($j($j(asset).parents('div.split_button_parent')).length>0) { + // Don't hide "parents" of non-blocked items + if (!$j('input[type=checkbox]', $j(asset).parent()).length > 0) { + $j($j(asset).parents('div.split_button_parent')[0]).hide() + } + //Items not in isa tree + } else { + $j(asset).hide() } } } @@ -130,6 +136,10 @@ function hideBlocked(cb_parent_selector,blocked_selector){ function showBlocked(cb_parent_selector,blocked_selector){ let children_assets = $j(blocked_selector, $j(cb_parent_selector)) for (let asset of children_assets) { - $j($j(asset).parents('div.split_button_parent')[0]).show() + if($j($j(asset).parents('div.split_button_parent')).length>0) { + $j($j(asset).parents('div.split_button_parent')[0]).show() + } else{ + $j(asset).show() + } } } diff --git a/app/views/assets/_asset_checkbox_row.html.erb b/app/views/assets/_asset_checkbox_row.html.erb index f83be55ac1..5e7dbe6b59 100644 --- a/app/views/assets/_asset_checkbox_row.html.erb +++ b/app/views/assets/_asset_checkbox_row.html.erb @@ -5,7 +5,7 @@ tree_class = 'not-manageable' tree_class = 'publishable' if item.can_publish? && item.can_manage? - tree_class = 'already-published' if item.is_published? && block_published + tree_class = 'already-published' if item.is_published? tree_class = 'not-visible' unless item.can_view? toggle ||=false diff --git a/app/views/assets/_batch_asset_selection.html.erb b/app/views/assets/_batch_asset_selection.html.erb index a3f383219d..d441bbd234 100644 --- a/app/views/assets/_batch_asset_selection.html.erb +++ b/app/views/assets/_batch_asset_selection.html.erb @@ -27,6 +27,12 @@ Collapse all | + <% if show_hide_blocked %> + | + | + <% end %>
@@ -44,8 +50,8 @@ <% items.each do |item| %> <%= render :partial => "assets/asset_checkbox_row", :object => item, - :block_published => publishing, - :locals => { :html_classes => "publishing_options" } -%> + :locals => { :html_classes => "publishing_options", + :block_published => publishing } -%> <% end %>
@@ -69,8 +75,8 @@ <% @assets_not_in_isa.each do |item| %> <%= render :partial => "assets/asset_checkbox_row", :object => item, - :block_published => publishing, - :locals => { :html_classes => "publishing_options" } -%> + :locals => { :html_classes => "publishing_options", + :block_published => publishing } -%> <% end %>
@@ -116,4 +122,7 @@ $j(document).ready(function () { $j('div#sorted_by_isa').hide() }) + $j(document).ready(function () { + hideBlocked(document,"<%="#{blocked_selector}"%>") + }) \ No newline at end of file diff --git a/lib/seek/publishing/publishing_common.rb b/lib/seek/publishing/publishing_common.rb index 1979158ba8..80aacac50b 100644 --- a/lib/seek/publishing/publishing_common.rb +++ b/lib/seek/publishing/publishing_common.rb @@ -133,12 +133,11 @@ def set_asset end def set_assets - # get the assets that current_user can manage, then take the one that can_publish? + # get the assets that current_user can manage @assets = {} publishable_types = Seek::Util.authorized_types.select { |authorized_type| authorized_type.first.try(:is_in_isa_publishable?) } publishable_types.each do |klass| can_manage_assets = klass.authorized_for 'manage', current_user - can_manage_assets = can_manage_assets.select(&:can_publish?) unless can_manage_assets.empty? @assets[klass.name] = can_manage_assets end From db40534c180689189b3b05b186c8d7103fee253c Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Thu, 27 Jul 2023 16:50:33 +0100 Subject: [PATCH 07/47] Uses batch_asset_selection for batch_sharing_permission_preview --- app/helpers/assets_helper.rb | 12 - .../batch_sharing_permission_preview.html.erb | 322 ++---------------- .../sharing_bulk_change_preview.html.erb | 2 +- ...ample_sharing_bulk_change_preview.html.erb | 2 +- lib/seek/publishing/publishing_common.rb | 2 +- lib/seek/sharing/sharing_common.rb | 11 +- 6 files changed, 27 insertions(+), 324 deletions(-) diff --git a/app/helpers/assets_helper.rb b/app/helpers/assets_helper.rb index b3b74a9228..9e79a75ce5 100644 --- a/app/helpers/assets_helper.rb +++ b/app/helpers/assets_helper.rb @@ -94,18 +94,6 @@ def publishing_item_param(item) "publish[#{item.class.name}][#{item.id}]" end - def sharing_item_param(item) - if item.try(:is_isa?) - "share_isa[#{item.class.name}][#{item.id}]" - elsif (item.respond_to? (:investigations)) && (!item.investigations.any?) - "share_not_isa[#{item.class.name}][#{item.id}]" - elsif !item.respond_to? (:investigations) - "share_not_isa[#{item.class.name}][#{item.id}]" - else - "share_isa[#{item.class.name}][#{item.id}]" - end - end - def include_downloadable_item?(items) has_downloadable_item = false items.each do |item| diff --git a/app/views/assets/sharing/batch_sharing_permission_preview.html.erb b/app/views/assets/sharing/batch_sharing_permission_preview.html.erb index 14f8355a67..6c1ebd757e 100644 --- a/app/views/assets/sharing/batch_sharing_permission_preview.html.erb +++ b/app/views/assets/sharing/batch_sharing_permission_preview.html.erb @@ -1,14 +1,4 @@ <% - items_not_in_isa_hash = SharingPermissionsHelper::ITEMS_NOT_IN_ISA_HASH - items_not_in_isa_hash[:children] =[] - - all_investigations_hash = SharingPermissionsHelper::ALL_INVESTIGATIONS_HASH - all_investigations_hash[:children] = [] - - #include items which can change sharing permissions, the 'publication' is intendedly excluded. - all_related_items_hash = get_related_resources(current_user.person).slice(*Seek::Util.authorized_types.map(&:name)).except!('Publication') - - items_not_in_isa = filter_items_not_in_ISA(all_related_items_hash) @policy_params = params[:policy_attributes] @@ -26,296 +16,24 @@
-<%= form_tag({:action => :batch_change_permission_for_selected_items}, :method => :post) do -%> - - <%= folding_panel("Items not in ISA", false, :id => 'not_isa_item', :body_options => {:id => 'items_fold_content'}, - :help_text => nil) do %> - - | - | - | - - - - <% items_not_in_isa.each do |resource_type, resource_items| %> - <% asset_node= asset_node_json(resource_type, resource_items) %> - <% items_not_in_isa_hash[:children].append(asset_node) %> - <% end %> - -
- - <% end %> - - - <% all_related_items_hash.each do |resource_type, resource_items| %> - <% if resource_type == "Investigation" %> - <% resource_items[:items].each do |item| %> - <% options ||= { depth: 4, parent_depth: nil, sibling_depth: nil, include_self: true } %> - <% hash = Seek::IsaGraphGenerator.new(item).generate(**options) %> - <% tree = JSON.parse(build_tree_json(hash, item)) %> - <% tree = add_permissions_to_tree_json(tree) %> - <% all_investigations_hash[:children].append(tree.first) %> - <% end %> - <% end %> - <% end %> - - <%= folding_panel("Items in ISA: ", false, :id => 'isa_item', :body_options => {:id => 'items_fold_content'}, - :help_text => nil) do %> - - | - | - | - - -
- + <%= form_tag({:action => :batch_change_permission_for_selected_items}, :method => :post) do -%> + + <% if @assets.empty? %> + You have no manageable assets in <%= Seek::Config.instance_name %> +
+
+ <%= link_to "Back to profile", person_path(params[:id].to_i) -%> + <% else %> + <%= render :partial => "assets/batch_asset_selection", + :locals => { :publishing => false, + :show_hide_blocked => true, + :blocked_selector => '.not-visible,.not-manageable' + } + -%> +
+ <%= submit_tag "Next",data: { disable_with: 'Next' }, :class => 'btn btn-primary' -%> + Or + <%= cancel_button person_path(params[:id].to_i)-%> + <% end -%> <% end -%> - - <% resource = (controller_name == 'people') ? current_user.person : @asset %> - - <%= submit_tag "Next", data: {disable_with: 'Next'}, :class => 'btn btn-primary', :onclick => 'show_all_checkboxes()' -%> - - or - <%= cancel_button(resource, button_text: "Back to profile") %> - -<% end -%> -
- - - + \ No newline at end of file diff --git a/app/views/assets/sharing/sharing_bulk_change_preview.html.erb b/app/views/assets/sharing/sharing_bulk_change_preview.html.erb index 2e78eadd38..1bbb6f93b5 100644 --- a/app/views/assets/sharing/sharing_bulk_change_preview.html.erb +++ b/app/views/assets/sharing/sharing_bulk_change_preview.html.erb @@ -13,7 +13,7 @@ ").html_safe - respond_to do |format| - if params[:single_page] - format.html { render 'single_pages/sample_batch_sharing_permission_preview', { layout: false } } - else + if params[:single_page] + render 'single_pages/sample_batch_sharing_permissions_changed', { layout: false } + else + respond_to do |format| format.html { render 'assets/sharing/batch_sharing_permission_preview' } end end From b38a156219a6e4215e7777b77eb7fb4d9dca351c Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Mon, 21 Aug 2023 12:46:56 +0100 Subject: [PATCH 12/47] Styling fixes --- app/views/assets/_asset_checkbox_row.html.erb | 4 +-- .../assets/_batch_asset_selection.html.erb | 28 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/views/assets/_asset_checkbox_row.html.erb b/app/views/assets/_asset_checkbox_row.html.erb index 0468549435..9280585bf1 100644 --- a/app/views/assets/_asset_checkbox_row.html.erb +++ b/app/views/assets/_asset_checkbox_row.html.erb @@ -60,12 +60,12 @@ data-managed_by_selector='<%= managed_by_selector %>'> -
style="display:none;margin-left:5em"> +
" style="display:none;margin-left:5em"> Manageable by: <%= item.managers.empty? ? "None".html_safe : item.managers.collect { |m| link_to(h(m.title), m) }.join(", ").html_safe -%>
<% end %> <% if show_permissions %> -
style="display:none;margin-left:5em" > +
" style="display:none;margin-left:5em" > <%= get_permission_list item -%>
<% end %> diff --git a/app/views/assets/_batch_asset_selection.html.erb b/app/views/assets/_batch_asset_selection.html.erb index bac0934e5c..6a7867e2c6 100644 --- a/app/views/assets/_batch_asset_selection.html.erb +++ b/app/views/assets/_batch_asset_selection.html.erb @@ -45,7 +45,7 @@
<% @assets.sort_by { |k, v| v.first.class.name }.each do |type, items| %>
- <%= render :partial => 'assets/isa-tree-toggle', locals: { cb_parent_selector: "div##{items.first.class.table_name}" } -%> + <%= render partial: 'assets/isa-tree-toggle', locals: { cb_parent_selector: "div##{items.first.class.table_name}" } -%>

<%= text_for_resource items.first %>(s)

<% items.each do |item| %> - <%= render :partial => "assets/asset_checkbox_row", - :object => item, - :locals => { :html_classes => "publishing_options", - :block_published => publishing } -%> + <%= render partial: 'assets/asset_checkbox_row', + object: item, + locals: { html_classes: 'publishing_options', + block_published: publishing } -%> <% end %>
@@ -69,7 +69,7 @@
<% unless @assets_not_in_isa.empty? %> @@ -93,7 +93,7 @@ <% unless @investigations.empty? %>
- <%= render :partial => 'assets/isa-tree-toggle', locals: { cb_parent_selector: "div#items_in_isa" } -%> + <%= render partial: 'assets/isa-tree-toggle', locals: { cb_parent_selector: "div#items_in_isa" } -%>

Items in ISA

<% @investigations.each do |inv| %> - <%= render :partial => "assets/isa_tree_preview", - :locals => { :publishing => publishing }, - :collection => inv.assays.map(&:study).map(&:investigation).flatten.uniq %> + <%= render partial: 'assets/isa_tree_preview', + locals: { publishing: publishing }, + collection: inv.assays.map(&:study).map(&:investigation).flatten.uniq %> <% end %>

From ea2e182157ee7b7c7306dae42fc14dafd349d85a Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Mon, 21 Aug 2023 14:08:15 +0100 Subject: [PATCH 13/47] Improves switch statement in get_permission_list --- app/helpers/sharing_permissions_helper.rb | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/app/helpers/sharing_permissions_helper.rb b/app/helpers/sharing_permissions_helper.rb index 07d35de0b4..b98c7c82a6 100644 --- a/app/helpers/sharing_permissions_helper.rb +++ b/app/helpers/sharing_permissions_helper.rb @@ -17,30 +17,16 @@ def get_permission_list (item) option = { target: :_blank } item.policy.permissions.map do |permission| sharing_policy_changed = @batch_sharing_permission_changed && (@items_for_sharing.include? item) ? PolicyHelper::permission_changed_item_class(permission, @policy_params) : "" - div_id = 'case-not-found' + m = permission.contributor + div_id = "#{item_id}-Permission-#{permission.contributor_type}-#{m.id}:" + policy_text = "#{permission.contributor_type} #{link_to(h(m.title), m, option)}:" case permission.contributor_type - when Permission::PROJECT - m = Project.find(permission.contributor_id) - policy_text = "Project #{link_to(h(m.title), m, option)}:" - div_id = "#{item_id}-Permission-Project-#{m.id}:" when Permission::WORKGROUP - m = WorkGroup.find(permission.contributor_id) institution = Institution.find(m.institution_id) project = Project.find(m.project_id) policy_text = " #{link_to(h(project.title), project, option)} @ #{link_to(h(institution.title), institution, option)}:" - div_id = "#{item_id}-Permission-Workgroup-#{m.id}" - when Permission::INSTITUTION - m = Institution.find(permission.contributor_id) - policy_text = "Institution #{link_to(h(m.title), m, option)}:" - div_id = "#{item_id}-Permission-Institution-#{m.id}" when Permission::PERSON - m = Person.find(permission.contributor_id) policy_text = "#{link_to(h(m.title), m, option)}:" - div_id = "#{item_id}-Permission-Person-#{m.id}" - when Permission::PROGRAMME - m = Programme.find(permission.contributor_id) - policy_text = "Programme #{link_to(h(m.title), m, option)}:" - div_id = "#{item_id}-Permission-Programme-#{m.id}" end policy_text += " #{Policy.get_access_type_wording(permission.access_type, downloadable)}." policy.append("
#{policy_text}
".html_safe) From 8c79844630b63c4bda68fb657d2c855f62919260 Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Tue, 22 Aug 2023 09:24:50 +0100 Subject: [PATCH 14/47] Moved most html rendering from SharingPermissionsHelper to partial --- app/helpers/sharing_permissions_helper.rb | 42 ++++++------------- app/views/assets/_asset_checkbox_row.html.erb | 4 +- app/views/assets/_permission_list.html.erb | 19 +++++++++ 3 files changed, 32 insertions(+), 33 deletions(-) create mode 100644 app/views/assets/_permission_list.html.erb diff --git a/app/helpers/sharing_permissions_helper.rb b/app/helpers/sharing_permissions_helper.rb index b98c7c82a6..4657adcb1e 100644 --- a/app/helpers/sharing_permissions_helper.rb +++ b/app/helpers/sharing_permissions_helper.rb @@ -1,37 +1,19 @@ module SharingPermissionsHelper - def get_permission_list (item) - - item_id = "#{item.class.name}_#{item.id}" - - policy = [] - - # policy - downloadable = item.try(:is_downloadable?) - policy_text = "Public: #{Policy.get_access_type_wording(item.policy.access_type, downloadable)}." - sharing_policy_changed = (@batch_sharing_permission_changed && (@items_for_sharing.include? item) && !@policy_params[:access_type].nil?)? "sharing_permission_changed" : "" - - policy.append("
#{policy_text}
".html_safe) - - #permission + def get_permission_type (permission) option = { target: :_blank } - item.policy.permissions.map do |permission| - sharing_policy_changed = @batch_sharing_permission_changed && (@items_for_sharing.include? item) ? PolicyHelper::permission_changed_item_class(permission, @policy_params) : "" - m = permission.contributor - div_id = "#{item_id}-Permission-#{permission.contributor_type}-#{m.id}:" - policy_text = "#{permission.contributor_type} #{link_to(h(m.title), m, option)}:" - case permission.contributor_type - when Permission::WORKGROUP - institution = Institution.find(m.institution_id) - project = Project.find(m.project_id) - policy_text = " #{link_to(h(project.title), project, option)} @ #{link_to(h(institution.title), institution, option)}:" - when Permission::PERSON - policy_text = "#{link_to(h(m.title), m, option)}:" - end - policy_text += " #{Policy.get_access_type_wording(permission.access_type, downloadable)}." - policy.append("
#{policy_text}
".html_safe) + m = permission.contributor + case permission.contributor_type + when Permission::WORKGROUP + institution = Institution.find(m.institution_id) + project = Project.find(m.project_id) + p_type = "#{link_to(h(project.title), project, option)} @ #{link_to(h(institution.title), institution, option)}" + when Permission::PERSON + p_type = "#{link_to(h(m.title), m, option)}" + else + p_type = "#{permission.contributor_type} #{link_to(h(m.title), m, option)}" end - safe_join(policy) + p_type.html_safe end end diff --git a/app/views/assets/_asset_checkbox_row.html.erb b/app/views/assets/_asset_checkbox_row.html.erb index 9280585bf1..7411d8e3b3 100644 --- a/app/views/assets/_asset_checkbox_row.html.erb +++ b/app/views/assets/_asset_checkbox_row.html.erb @@ -65,8 +65,6 @@
<% end %> <% if show_permissions %> -
" style="display:none;margin-left:5em" > - <%= get_permission_list item -%> -
+ <%= render :partial => 'assets/permission_list', locals: { item: item} -%> <% end %>
diff --git a/app/views/assets/_permission_list.html.erb b/app/views/assets/_permission_list.html.erb new file mode 100644 index 0000000000..c1428373e3 --- /dev/null +++ b/app/views/assets/_permission_list.html.erb @@ -0,0 +1,19 @@ +<% + item ||= permission_list + item_id = "#{item.class.name}_#{item.id}" + downloadable = item.try(:is_downloadable?) +-%> +
" style="display:none;margin-left:5em" > + <% sharing_policy_changed = (@batch_sharing_permission_changed && (@items_for_sharing.include? item) && !@policy_params[:access_type].nil?)? "sharing_permission_changed" : "" %> + + <% item.policy.permissions.map do |permission| %> + <% sharing_permission_changed = @batch_sharing_permission_changed && (@items_for_sharing.include? item) ? PolicyHelper::permission_changed_item_class(permission, @policy_params) : "" %> + + <% end %> +
From 5f6e2ba154dbfed93461fd12db050e8f03245ee4 Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Tue, 22 Aug 2023 15:58:51 +0100 Subject: [PATCH 15/47] Moved batch_asset_selection links to partial --- .../assets/_batch_asset_selection.html.erb | 79 ++++++++----------- .../_batch_asset_selection_buttons.html.erb | 38 +++++++++ 2 files changed, 69 insertions(+), 48 deletions(-) create mode 100644 app/views/assets/_batch_asset_selection_buttons.html.erb diff --git a/app/views/assets/_batch_asset_selection.html.erb b/app/views/assets/_batch_asset_selection.html.erb index 6a7867e2c6..d7d6b60ac6 100644 --- a/app/views/assets/_batch_asset_selection.html.erb +++ b/app/views/assets/_batch_asset_selection.html.erb @@ -20,26 +20,15 @@


- - Select all your items - | - || - | - <% if show_hide_blocked %> - || - | - <% end %> - <% if show_hide_permissions %> - || - | - <% end %> + <%= render partial: 'assets/batch_asset_selection_buttons', locals: { + id: "items", + text: "your items", + cb_parent_selector: "body", + show_hide_selector: "div#sorted_by_type,#sorted_by_isa", + select_deselect_all: true, + collapse_expand: true, + show_hide_permissions: show_hide_permissions + } %>
@@ -48,12 +37,12 @@ <%= render partial: 'assets/isa-tree-toggle', locals: { cb_parent_selector: "div##{items.first.class.table_name}" } -%>

<%= text_for_resource items.first %>(s)

- | - + <%= render partial: 'assets/batch_asset_selection_buttons', locals: { + id: items.first.class.table_name, + text: (text_for_resource items.first).downcase.pluralize, + cb_parent_selector: 'div#'+items.first.class.table_name, + select_deselect_all: true + } %> <% items.each do |item| %> <%= render partial: 'assets/asset_checkbox_row', object: item, @@ -72,12 +61,12 @@ <%= render partial: 'assets/isa-tree-toggle', locals: { cb_parent_selector: "div#items_not_in_isa" } -%>

Items not in ISA

- | - + <%= render partial: 'assets/batch_asset_selection_buttons', locals: { + id: "items_not_in_isa", + text: "items not in ISA", + cb_parent_selector: 'div#items_not_in_isa', + select_deselect_all: true + } %>
<% @assets_not_in_isa.each do |item| %> <%= render partial: 'assets/asset_checkbox_row', @@ -96,22 +85,16 @@ <%= render partial: 'assets/isa-tree-toggle', locals: { cb_parent_selector: "div#items_in_isa" } -%>

Items in ISA

- - | - || - | - <% if show_hide_blocked %> - || - | - <% end %> + <%= render partial: 'assets/batch_asset_selection_buttons', locals: { + id: "items_in_isa", + text: "items in ISA", + cb_parent_selector: "div#items_in_isa", + collapse_selector: "div#investigation_list", + blocked_selector: blocked_selector, + select_deselect_all: true, + collapse_expand: true, + show_hide_blocked: show_hide_blocked + } %>
<% @investigations.each do |inv| %> diff --git a/app/views/assets/_batch_asset_selection_buttons.html.erb b/app/views/assets/_batch_asset_selection_buttons.html.erb new file mode 100644 index 0000000000..176555be62 --- /dev/null +++ b/app/views/assets/_batch_asset_selection_buttons.html.erb @@ -0,0 +1,38 @@ +<% + id ||= "items" + text ||= "your items" + cb_parent_selector ||= 'body' + collapse_selector ||= cb_parent_selector + show_hide_selector ||= cb_parent_selector + blocked_selector ||= '' + + select_deselect_all ||= false + collapse_expand ||= false + show_hide_blocked ||= false + show_hide_permissions ||= false +%> + +<% if select_deselect_all %> + + | +<% end %> +<% if collapse_expand %> + || + | +<% end %> +<% if show_hide_blocked %> + || + | +<% end %> +<% if show_hide_permissions %> + || + | +<% end %> From 9b8185eb473f4fdf47cdeb54742b017a3ba5d96e Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Tue, 22 Aug 2023 17:39:41 +0100 Subject: [PATCH 16/47] Replaced batch_asset_selection links with buttons --- .../_batch_asset_selection_buttons.html.erb | 57 +++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/app/views/assets/_batch_asset_selection_buttons.html.erb b/app/views/assets/_batch_asset_selection_buttons.html.erb index 176555be62..8f66097fb8 100644 --- a/app/views/assets/_batch_asset_selection_buttons.html.erb +++ b/app/views/assets/_batch_asset_selection_buttons.html.erb @@ -13,26 +13,51 @@ %> <% if select_deselect_all %> - - | + + <% end %> <% if collapse_expand %> - || - | + <% end %> <% if show_hide_blocked %> - || - | + <% end %> <% if show_hide_permissions %> - || - | + <% end %> From 7a48b362205461c278575c70fd19e702c898f2b4 Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Thu, 31 Aug 2023 12:07:58 +0100 Subject: [PATCH 17/47] Fixes hidden files in batch sharing --- lib/seek/publishing/publishing_common.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/seek/publishing/publishing_common.rb b/lib/seek/publishing/publishing_common.rb index f277afe369..150c67dbce 100644 --- a/lib/seek/publishing/publishing_common.rb +++ b/lib/seek/publishing/publishing_common.rb @@ -135,8 +135,7 @@ def set_asset def set_assets # get the assets that current_user can manage @assets = {} - publishable_types = Seek::Util.authorized_types.select { |authorized_type| authorized_type.first.try(:is_in_isa_publishable?) } - publishable_types.each do |klass| + Seek::Util.asset_types.each do |klass| can_manage_assets = klass.authorized_for 'manage', current_user unless can_manage_assets.empty? @assets[klass.name] = can_manage_assets From aac7dc95de9e3ba79639d476c46be5d980d51426 Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Thu, 31 Aug 2023 13:41:24 +0100 Subject: [PATCH 18/47] Improved batch sharing permissions instructions --- .../batch_sharing_permission_preview.html.erb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/views/assets/sharing/batch_sharing_permission_preview.html.erb b/app/views/assets/sharing/batch_sharing_permission_preview.html.erb index e0be7b67eb..4e37d0fe17 100644 --- a/app/views/assets/sharing/batch_sharing_permission_preview.html.erb +++ b/app/views/assets/sharing/batch_sharing_permission_preview.html.erb @@ -4,11 +4,19 @@ %> -<%= show_title "Change permissions of items related to #{link_to(h(current_user.person.name),current_user.person)} in batch".html_safe -%> +<%= show_title "Change permissions of assets related to #{link_to(h(current_user.person.name),current_user.person)} in batch".html_safe -%>
    -
  • You can view the details of current permissions for each item by clicking the item's policy icon.
  • +
  • You can view the details of current permissions for each item by clicking the item's policy icon ( + <%= image('world', title: 'Was published', class: 'visibility_icon') %> + <%= image('partial_world', title: 'Visible to everyone, but not accessible', class: 'visibility_icon') %> + <%= image('manage', title: 'Custom policy', class: 'visibility_icon') %> + <%= image('lock', title: 'Private', class: 'visibility_icon') %> + ).
  • +
  • You can view the managers for each item by clicking the + + icon.
  • After your confirmation, the newly modified permissions will be highlighted with .
From 3336fbf1bef2add125b7da127d63bc5cc458e96c Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Thu, 31 Aug 2023 14:48:13 +0100 Subject: [PATCH 19/47] Replaced get_permission_type with permission_title; added link option. --- app/helpers/policy_helper.rb | 25 ++++++++++++++++------ app/helpers/sharing_permissions_helper.rb | 19 ---------------- app/views/assets/_permission_list.html.erb | 2 +- 3 files changed, 20 insertions(+), 26 deletions(-) delete mode 100644 app/helpers/sharing_permissions_helper.rb diff --git a/app/helpers/policy_helper.rb b/app/helpers/policy_helper.rb index 1a70d38ff7..7c431caa93 100644 --- a/app/helpers/policy_helper.rb +++ b/app/helpers/policy_helper.rb @@ -159,7 +159,7 @@ def project_policy_json(project) hash.to_json.html_safe end - def permission_title(permission, member_prefix: false, icon: false) + def permission_title(permission, member_prefix: false, icon: false, link: false) if permission.is_a?(Permission) type = permission.contributor_type contributor = permission.contributor @@ -168,18 +168,31 @@ def permission_title(permission, member_prefix: false, icon: false) contributor = permission end - if type == 'Person' + option = { target: :_blank } + case type + when 'Person' text = "#{contributor.first_name} #{contributor.last_name}" - elsif type == 'WorkGroup' - text = "#{member_prefix ? 'Members of ' : ''}#{contributor.project.title} @ #{contributor.institution.title}" + text = link_to(h(text), contributor, option).html_safe if link + when 'WorkGroup' + institution = contributor.institution + project = contributor.project + if link + text = "#{member_prefix ? 'Members of ' : ''}#{link_to(h(project.title), project, option)} @ #{link_to(h(institution.title), institution, option)}".html_safe + else + text = "#{member_prefix ? 'Members of ' : ''}#{project.title} @ #{institution.title}" + end else - text = "#{member_prefix ? 'Members of ' : ''}#{contributor.title}" + if link + text = "#{member_prefix ? 'Members of ' : ''}#{link_to(h(contributor.title), contributor, option)}".html_safe + else + text = "#{member_prefix ? 'Members of ' : ''}#{contributor.title}" + end end if icon content_tag(:span, class: 'type-icon-wrapper') do image_tag(asset_path(icon_filename_for_key(type.underscore)), class: 'type-icon') - end.html_safe + " #{text}" + end.html_safe + " #{text}".html_safe else text end diff --git a/app/helpers/sharing_permissions_helper.rb b/app/helpers/sharing_permissions_helper.rb deleted file mode 100644 index 4657adcb1e..0000000000 --- a/app/helpers/sharing_permissions_helper.rb +++ /dev/null @@ -1,19 +0,0 @@ -module SharingPermissionsHelper - - def get_permission_type (permission) - option = { target: :_blank } - m = permission.contributor - case permission.contributor_type - when Permission::WORKGROUP - institution = Institution.find(m.institution_id) - project = Project.find(m.project_id) - p_type = "#{link_to(h(project.title), project, option)} @ #{link_to(h(institution.title), institution, option)}" - when Permission::PERSON - p_type = "#{link_to(h(m.title), m, option)}" - else - p_type = "#{permission.contributor_type} #{link_to(h(m.title), m, option)}" - end - p_type.html_safe - end - -end diff --git a/app/views/assets/_permission_list.html.erb b/app/views/assets/_permission_list.html.erb index c1428373e3..094d22a222 100644 --- a/app/views/assets/_permission_list.html.erb +++ b/app/views/assets/_permission_list.html.erb @@ -12,7 +12,7 @@ <% item.policy.permissions.map do |permission| %> <% sharing_permission_changed = @batch_sharing_permission_changed && (@items_for_sharing.include? item) ? PolicyHelper::permission_changed_item_class(permission, @policy_params) : "" %> <% end %> From f4211fc942590e532d93d008bceae2026973959e Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Thu, 31 Aug 2023 16:31:12 +0100 Subject: [PATCH 20/47] Updated list of items shown in batch sharing to all manageable items. --- app/views/assets/_batch_asset_selection.html.erb | 5 ++++- .../sharing/batch_sharing_permission_preview.html.erb | 2 +- app/views/people/_buttons.html.erb | 6 +++--- lib/seek/publishing/publishing_common.rb | 8 +++++++- test/functional/publishing/batch_publishing_test.rb | 8 ++++---- test/functional/sharing/batch_sharing_change_test.rb | 8 ++++---- 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/app/views/assets/_batch_asset_selection.html.erb b/app/views/assets/_batch_asset_selection.html.erb index d7d6b60ac6..0d0d42697a 100644 --- a/app/views/assets/_batch_asset_selection.html.erb +++ b/app/views/assets/_batch_asset_selection.html.erb @@ -98,9 +98,12 @@
<% @investigations.each do |inv| %> + <% collection = inv.assays.map(&:study).map(&:investigation).flatten.uniq %> + <% collection = inv.studies.map(&:investigation).flatten.uniq if collection.empty? %> + <% collection = [inv] if collection.empty?%> <%= render partial: 'assets/isa_tree_preview', locals: { publishing: publishing }, - collection: inv.assays.map(&:study).map(&:investigation).flatten.uniq %> + collection: collection %> <% end %>

diff --git a/app/views/assets/sharing/batch_sharing_permission_preview.html.erb b/app/views/assets/sharing/batch_sharing_permission_preview.html.erb index 4e37d0fe17..28d6ed083e 100644 --- a/app/views/assets/sharing/batch_sharing_permission_preview.html.erb +++ b/app/views/assets/sharing/batch_sharing_permission_preview.html.erb @@ -4,7 +4,7 @@ %> -<%= show_title "Change permissions of assets related to #{link_to(h(current_user.person.name),current_user.person)} in batch".html_safe -%> +<%= show_title "Change permissions of items related to #{link_to(h(current_user.person.name),current_user.person)} in batch".html_safe -%>
@@ -72,7 +76,10 @@ <%= render partial: 'assets/asset_checkbox_row', object: item, locals: { html_classes: "publishing_options", - block_published: publishing } -%> + block_published: publishing, + show_permissions: show_permissions, + show_managers: show_managers + } -%> <% end %>
@@ -102,7 +109,10 @@ <% collection = inv.studies.map(&:investigation).flatten.uniq if collection.empty? %> <% collection = [inv] if collection.empty?%> <%= render partial: 'assets/isa_tree_preview', - locals: { publishing: publishing }, + locals: { publishing: publishing, + show_permissions: show_permissions, + show_managers: show_managers + }, collection: collection %> <% end %>
diff --git a/app/views/assets/_isa_tree_preview.html.erb b/app/views/assets/_isa_tree_preview.html.erb index 80f885e917..84b62c90a6 100644 --- a/app/views/assets/_isa_tree_preview.html.erb +++ b/app/views/assets/_isa_tree_preview.html.erb @@ -13,6 +13,9 @@ else children = [] end + + show_permissions ||= false + show_managers ||= false -%>
"> <%= render partial: "assets/asset_checkbox_row", @@ -21,7 +24,10 @@ toggle: children.any?, cb_parent_selector: "div\##{item.class.name}_#{item.id}.split_button_parent", block_published: publishing, - checked: (item == preselected) } -%> + checked: (item == preselected), + show_permissions: show_permissions, + show_managers: show_managers + } -%> <% if children.any? %>
@@ -30,7 +36,10 @@ object: child, locals: { preselected: preselected, publishing: publishing, - html_classes: "publishing_options"} -%> + html_classes: "publishing_options", + show_permissions: show_permissions, + show_managers: show_managers + } -%> <% end %>
<% end %> diff --git a/app/views/assets/publishing/batch_publishing_preview.html.erb b/app/views/assets/publishing/batch_publishing_preview.html.erb index 4a5fbc77ee..43988077d2 100644 --- a/app/views/assets/publishing/batch_publishing_preview.html.erb +++ b/app/views/assets/publishing/batch_publishing_preview.html.erb @@ -26,7 +26,8 @@ <%= render partial: "assets/batch_asset_selection", locals: { publishing: true, show_hide_blocked: true, - show_hide_permissions: true, + show_permissions: true, + show_managers: false, blocked_selector: '.not-visible,.not-manageable,.already-published' } -%> diff --git a/app/views/assets/publishing/publish_related_items.html.erb b/app/views/assets/publishing/publish_related_items.html.erb index cf0c244c3f..5eb386b1ae 100644 --- a/app/views/assets/publishing/publish_related_items.html.erb +++ b/app/views/assets/publishing/publish_related_items.html.erb @@ -18,10 +18,10 @@ <% if item.is_asset? %> <%= render partial: "assets/isa_tree_preview", collection: item.assays.map(&:study).map(&:investigation).flatten.uniq, - locals: { preselected: item, publishing: true } %> + locals: { preselected: item, publishing: true, show_permissions: true } %> <% else %> <%= render partial: "assets/isa_tree_preview", object: item, - locals: { preselected: item, publishing: true } %> + locals: { preselected: item, publishing: true, show_permissions: true } %> <% end %> <% else %> <%= check_box_tag publishing_item_param(item), 1, true, {style: 'display:none;'} %> diff --git a/app/views/assets/sharing/batch_sharing_permission_preview.html.erb b/app/views/assets/sharing/batch_sharing_permission_preview.html.erb index 30d8807f0b..16508c8223 100644 --- a/app/views/assets/sharing/batch_sharing_permission_preview.html.erb +++ b/app/views/assets/sharing/batch_sharing_permission_preview.html.erb @@ -23,7 +23,7 @@
- <%= form_tag({:action => :batch_change_permission_for_selected_items}, :method => :post) do -%> + <%= form_tag({action: :batch_change_permission_for_selected_items}, method: :post) do -%> <% if @assets.empty? %> You have no manageable assets in <%= Seek::Config.instance_name %> @@ -31,15 +31,16 @@
<%= link_to "Back to profile", person_path(params[:id].to_i) -%> <% else %> - <%= render :partial => "assets/batch_asset_selection", - :locals => { :publishing => false, - :show_hide_blocked => true, - :show_hide_permissions => true, - :blocked_selector => '.not-visible,.not-manageable' + <%= render partial: "assets/batch_asset_selection", + locals: { publishing: false, + show_hide_blocked: true, + show_permissions: true, + show_managers: false, + blocked_selector: '.not-visible,.not-manageable' } -%>
- <%= submit_tag "Next",data: { disable_with: 'Next' }, :class => 'btn btn-primary' -%> + <%= submit_tag "Next",data: { disable_with: 'Next' }, class: 'btn btn-primary' -%> Or <%= cancel_button person_path(params[:id].to_i)-%> <% end -%> From 9d9e7003cb4fec7006bc76f0b984385768272cb4 Mon Sep 17 00:00:00 2001 From: fherreazcue Date: Thu, 21 Sep 2023 14:11:46 +0100 Subject: [PATCH 29/47] Button ticks checkbox --- app/assets/javascripts/checkbox.js | 8 ++++++++ app/views/general/_split_button_checkbox.html.erb | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/checkbox.js b/app/assets/javascripts/checkbox.js index be56c22be0..579970ae74 100644 --- a/app/assets/javascripts/checkbox.js +++ b/app/assets/javascripts/checkbox.js @@ -75,6 +75,14 @@ function checkRepeatedItems(checkbox_element) { } } +function button_checkRepeatedItems(button_element) { + if(this.event.target.nodeName.includes("BUTTON")){ + let checkbox_element = $j(button_element).find('input')[0] + checkbox_element.checked = !(checkbox_element.checked) + checkRepeatedItems(checkbox_element) + } +} + function toggleManagers(item,managed_by_selector) { $j(managed_by_selector).toggle() } diff --git a/app/views/general/_split_button_checkbox.html.erb b/app/views/general/_split_button_checkbox.html.erb index 0cf7207d3d..ed573bfcf7 100644 --- a/app/views/general/_split_button_checkbox.html.erb +++ b/app/views/general/_split_button_checkbox.html.erb @@ -31,7 +31,7 @@ <% else %> - From 56b5ff6cb035d9ae3017f938b6018889ec0b50aa Mon Sep 17 00:00:00 2001 From: Finn Bacall Date: Tue, 26 Sep 2023 13:07:06 +0100 Subject: [PATCH 31/47] Namespace JavaScript functions and avoid `onclick` --- app/assets/javascripts/checkbox.js | 246 +++++++++--------- .../assets/_batch_asset_selection.html.erb | 2 +- .../general/_split_button_checkbox.html.erb | 6 +- 3 files changed, 128 insertions(+), 126 deletions(-) diff --git a/app/assets/javascripts/checkbox.js b/app/assets/javascripts/checkbox.js index 7b2f8e09d9..9b9b5b7ee7 100644 --- a/app/assets/javascripts/checkbox.js +++ b/app/assets/javascripts/checkbox.js @@ -1,153 +1,157 @@ $j(document).ready(function () { - $j("a.selectChildren").click(selectChildren); - $j("a.deselectChildren").click(deselectChildren); - $j("a.managed_by_toggle").click(toggleManagers); + $j("a.selectChildren").click(BatchAssetSelection.selectChildren); + $j("a.deselectChildren").click(BatchAssetSelection.deselectChildren); + $j("a.managed_by_toggle").click(BatchAssetSelection.toggleManagers); $j("a.permissions_toggle").click(function () { - togglePermissions($j(this).closest('.isa-tree')); + BatchAssetSelection.togglePermissions($j(this).closest('.isa-tree')); return false; }); $j("a.showPermissions").click(function () { - togglePermissions($j(this).closest('.batch-selection-scope'), 'show'); + BatchAssetSelection.togglePermissions($j(this).closest('.batch-selection-scope'), 'show'); return false; }) $j("a.hidePermissions").click(function () { - togglePermissions($j(this).closest('.batch-selection-scope'), 'hide'); + BatchAssetSelection.togglePermissions($j(this).closest('.batch-selection-scope'), 'hide'); return false; }) - $j(".isa-tree-toggle-open").click(isaTreeShow); - $j(".isa-tree-toggle-close").click(isaTreeHide); - $j("a.collapseChildren").click(collapseRecursively); - $j("a.expandChildren").click(expandRecursively); - $j(".hideBlocked").click(hideBlocked); - $j(".showBlocked").click(showBlocked); -}) - -function selectChildren() { - let children_checkboxes = $j(':checkbox', $j(this).closest('.batch-selection-scope')); - for(let checkbox of children_checkboxes){ - let checkbox_element = { className: checkbox.className, checked: true } - checkRepeatedItems(checkbox_element) - } - - return false; -} - -function deselectChildren() { - let children_checkboxes = $j(':checkbox', $j(this).closest('.batch-selection-scope')); - for(let checkbox of children_checkboxes){ - let checkbox_element = { className: checkbox.className, checked: false } - checkRepeatedItems(checkbox_element) - } - - return false; -} - -function checkRepeatedItems(checkbox_element) { - let repeated_elements = document.getElementsByClassName(checkbox_element.className) - let check = checkbox_element.checked - for(let element of repeated_elements){ - element.checked = check - } -} + $j(".isa-tree-toggle-open").click(BatchAssetSelection.isaTreeShow); + $j(".isa-tree-toggle-close").click(BatchAssetSelection.isaTreeHide); + $j("a.collapseChildren").click(BatchAssetSelection.collapseRecursively); + $j("a.expandChildren").click(BatchAssetSelection.expandRecursively); + $j(".hideBlocked").click(BatchAssetSelection.hideBlocked); + $j(".showBlocked").click(BatchAssetSelection.showBlocked); + $j(".batch-asset-select-btn").click(BatchAssetSelection.button_checkRepeatedItems); + $j('.batch-asset-select-btn input[type="checkbox"]').click(BatchAssetSelection.checkRepeatedItems); +}); + +const BatchAssetSelection = { + selectChildren: function () { + let children_checkboxes = $j(':checkbox', $j(this).closest('.batch-selection-scope')); + for(let checkbox of children_checkboxes){ + let checkbox_element = { className: checkbox.className, checked: true } + BatchAssetSelection.checkRepeatedItems(checkbox_element) + } -function button_checkRepeatedItems(button_element) { - if(this.event.target.nodeName.includes("BUTTON")){ - let checkbox_element = $j(button_element).find('input')[0] - checkbox_element.checked = !(checkbox_element.checked) - checkRepeatedItems(checkbox_element) - } -} + return false; + }, -function toggleManagers() { - $j(this).siblings('.managed_by_list').toggle(); + deselectChildren: function () { + let children_checkboxes = $j(':checkbox', $j(this).closest('.batch-selection-scope')); + for(let checkbox of children_checkboxes){ + let checkbox_element = { className: checkbox.className, checked: false } + BatchAssetSelection.checkRepeatedItems(checkbox_element) + } - return false; -} + return false; + }, -function togglePermissions(scope, state) { - const permissions = $j('.permission_list', scope); - switch(state){ - case 'show': - permissions.show() - break - case 'hide': - permissions.hide() - break - default: - permissions.toggle() - } -} + checkRepeatedItems: function () { + let repeated_elements = document.getElementsByClassName(this.className) + let check = this.checked + for(let element of repeated_elements){ + element.checked = check + } + }, -function isaTreeShow() { - $j(this).closest('.batch-selection-scope').children('.collapse-scope').show(); - $j(this).siblings('.isa-tree-toggle-close').show(); - $j(this).hide(); + button_checkRepeatedItems: function (event) { + if (event.target.nodeName.includes("BUTTON")){ + let checkbox_element = $j(this).find('input')[0] + checkbox_element.checked = !(checkbox_element.checked) + BatchAssetSelection.checkRepeatedItems(checkbox_element) + } + }, - return false; -} + toggleManagers: function () { + $j(this).siblings('.managed_by_list').toggle(); -function isaTreeHide(){ - $j(this).closest('.batch-selection-scope').children('.collapse-scope').hide(); - $j(this).siblings('.isa-tree-toggle-open').show(); - $j(this).hide(); + return false; + }, + + togglePermissions: function (scope, state) { + const permissions = $j('.permission_list', scope); + switch(state){ + case 'show': + permissions.show() + break + case 'hide': + permissions.hide() + break + default: + permissions.toggle() + } + }, - return false; -} + isaTreeShow: function () { + $j(this).closest('.batch-selection-scope').children('.collapse-scope').show(); + $j(this).siblings('.isa-tree-toggle-close').show(); + $j(this).hide(); -function collapseRecursively() { - const scope = $j(this).closest('.batch-selection-scope').children('.collapse-scope'); - const toggles = $j('.isa-tree-toggle-close', scope); - for (let toggle of toggles) { - if (toggle.style.display === 'none') // Skip those that are already closed - continue; - isaTreeHide.apply(toggle); - } + return false; + }, - return false; -} + isaTreeHide: function (){ + $j(this).closest('.batch-selection-scope').children('.collapse-scope').hide(); + $j(this).siblings('.isa-tree-toggle-open').show(); + $j(this).hide(); -function expandRecursively() { - const scope = $j(this).closest('.batch-selection-scope').children('.collapse-scope'); - const toggles = $j('.isa-tree-toggle-open', scope); - for (let toggle of toggles) { - if (toggle.style.display === 'none') - continue; - isaTreeShow.apply(toggle); - } + return false; + }, + + collapseRecursively: function () { + const scope = $j(this).closest('.batch-selection-scope').children('.collapse-scope'); + const toggles = $j('.isa-tree-toggle-close', scope); + for (let toggle of toggles) { + if (toggle.style.display === 'none') // Skip those that are already closed + continue; + BatchAssetSelection.isaTreeHide.apply(toggle); + } - return false; -} + return false; + }, + + expandRecursively: function () { + const scope = $j(this).closest('.batch-selection-scope').children('.collapse-scope'); + const toggles = $j('.isa-tree-toggle-open', scope); + for (let toggle of toggles) { + if (toggle.style.display === 'none') + continue; + BatchAssetSelection.isaTreeShow.apply(toggle); + } -function hideBlocked(){ - let children_assets = $j($j(this).data('blocked_selector'), $j(this).closest('.batch-selection-scope')); - for (let asset of children_assets) { - //Items in isa tree - if($j($j(asset).parents('div.split_button_parent')).length>0) { - // Don't hide "parents" of non-blocked items - if (!$j('input[type=checkbox]', $j(asset).parent()).length > 0) { - $j($j(asset).parents('div.split_button_parent')[0]).hide() + return false; + }, + + hideBlocked: function (){ + let children_assets = $j($j(this).data('blocked_selector'), $j(this).closest('.batch-selection-scope')); + for (let asset of children_assets) { + //Items in isa tree + if($j($j(asset).parents('div.split_button_parent')).length>0) { + // Don't hide "parents" of non-blocked items + if (!$j('input[type=checkbox]', $j(asset).parent()).length > 0) { + $j($j(asset).parents('div.split_button_parent')[0]).hide() + } + //Items not in isa tree + } else { + $j(asset).hide() } - //Items not in isa tree - } else { - $j(asset).hide() } - } - - return false; -} -function showBlocked(){ - let children_assets = $j($j(this).data('blocked_selector'), $j(this).closest('.batch-selection-scope')); - for (let asset of children_assets) { - if($j($j(asset).parents('div.split_button_parent')).length>0) { - $j($j(asset).parents('div.split_button_parent')[0]).show() - } else{ - $j(asset).show() + return false; + }, + + showBlocked: function (){ + let children_assets = $j($j(this).data('blocked_selector'), $j(this).closest('.batch-selection-scope')); + for (let asset of children_assets) { + if($j($j(asset).parents('div.split_button_parent')).length>0) { + $j($j(asset).parents('div.split_button_parent')[0]).show() + } else{ + $j(asset).show() + } } - } - return false; + return false; + } } diff --git a/app/views/assets/_batch_asset_selection.html.erb b/app/views/assets/_batch_asset_selection.html.erb index 0b1e1c0224..2d0789246b 100644 --- a/app/views/assets/_batch_asset_selection.html.erb +++ b/app/views/assets/_batch_asset_selection.html.erb @@ -117,6 +117,6 @@ $j('div#sorted_by_isa').hide() }) $j(document).ready(function () { - hideBlocked(document,"<%="#{blocked_selector}"%>") + BatchAssetSelection.hideBlocked('<%= blocked_selector -%>'); }) \ No newline at end of file diff --git a/app/views/general/_split_button_checkbox.html.erb b/app/views/general/_split_button_checkbox.html.erb index e3d1457365..4e2fcc75d0 100644 --- a/app/views/general/_split_button_checkbox.html.erb +++ b/app/views/general/_split_button_checkbox.html.erb @@ -30,11 +30,9 @@ <% else %> - From 722f36569dcf66b5166ad03f296c08e639444aae Mon Sep 17 00:00:00 2001 From: Finn Bacall Date: Tue, 26 Sep 2023 13:23:39 +0100 Subject: [PATCH 32/47] Fix checkRepeatedItems regression --- app/assets/javascripts/checkbox.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/checkbox.js b/app/assets/javascripts/checkbox.js index 9b9b5b7ee7..ad2542903c 100644 --- a/app/assets/javascripts/checkbox.js +++ b/app/assets/javascripts/checkbox.js @@ -30,9 +30,9 @@ $j(document).ready(function () { const BatchAssetSelection = { selectChildren: function () { let children_checkboxes = $j(':checkbox', $j(this).closest('.batch-selection-scope')); - for(let checkbox of children_checkboxes){ + for (let checkbox of children_checkboxes){ let checkbox_element = { className: checkbox.className, checked: true } - BatchAssetSelection.checkRepeatedItems(checkbox_element) + BatchAssetSelection.checkRepeatedItems.apply(checkbox_element); } return false; @@ -40,9 +40,9 @@ const BatchAssetSelection = { deselectChildren: function () { let children_checkboxes = $j(':checkbox', $j(this).closest('.batch-selection-scope')); - for(let checkbox of children_checkboxes){ + for (let checkbox of children_checkboxes){ let checkbox_element = { className: checkbox.className, checked: false } - BatchAssetSelection.checkRepeatedItems(checkbox_element) + BatchAssetSelection.checkRepeatedItems.apply(checkbox_element) } return false; @@ -60,7 +60,7 @@ const BatchAssetSelection = { if (event.target.nodeName.includes("BUTTON")){ let checkbox_element = $j(this).find('input')[0] checkbox_element.checked = !(checkbox_element.checked) - BatchAssetSelection.checkRepeatedItems(checkbox_element) + BatchAssetSelection.checkRepeatedItems.apply(checkbox_element) } }, From d7009434ca2d99d5d5de11e8ce83a341bce55f0d Mon Sep 17 00:00:00 2001 From: Finn Bacall Date: Tue, 26 Sep 2023 13:27:05 +0100 Subject: [PATCH 33/47] Use tabs to separate type/ISA views Avoids need for custom JS to show/hide --- .../assets/_batch_asset_selection.html.erb | 43 ++++----- .../_batch_asset_selection_buttons.html.erb | 92 +++++++++---------- 2 files changed, 62 insertions(+), 73 deletions(-) diff --git a/app/views/assets/_batch_asset_selection.html.erb b/app/views/assets/_batch_asset_selection.html.erb index 2d0789246b..02860aa997 100644 --- a/app/views/assets/_batch_asset_selection.html.erb +++ b/app/views/assets/_batch_asset_selection.html.erb @@ -6,36 +6,34 @@ blocked_selector ||= '' -%> -
- - -
-

-
+
<%= render partial: 'assets/batch_asset_selection_buttons', locals: { - id: "items", text: "your items", select_deselect_all: true, collapse_expand: true, show_hide_permissions: show_permissions } %> -
-
+ + +
+
<% @assets.sort_by { |k, v| v.first.class.name }.each do |type, items| %>

<%= render partial: 'assets/isa-tree-toggle' -%> <%= text_for_resource items.first %>(s)

<%= render partial: 'assets/batch_asset_selection_buttons', locals: { - id: items.first.class.table_name, text: (text_for_resource items.first).downcase.pluralize, select_deselect_all: true } %> @@ -53,13 +51,12 @@ <% end %>
-
+
<% unless @assets_not_in_isa.empty? %>

<%= render partial: 'assets/isa-tree-toggle' -%> Items not in ISA

<%= render partial: 'assets/batch_asset_selection_buttons', locals: { - id: "items_not_in_isa", text: "items not in ISA", select_deselect_all: true } %> @@ -84,7 +81,6 @@

<%= render partial: 'assets/isa-tree-toggle'-%> Items in ISA

<%= render partial: 'assets/batch_asset_selection_buttons', locals: { - id: "items_in_isa", text: "items in ISA", blocked_selector: blocked_selector, select_deselect_all: true, @@ -113,10 +109,7 @@
\ No newline at end of file + diff --git a/app/views/assets/_batch_asset_selection_buttons.html.erb b/app/views/assets/_batch_asset_selection_buttons.html.erb index 61b1357dca..a0ba4b80d6 100644 --- a/app/views/assets/_batch_asset_selection_buttons.html.erb +++ b/app/views/assets/_batch_asset_selection_buttons.html.erb @@ -1,5 +1,4 @@ <% - id ||= "items" text ||= "your items" blocked_selector ||= '' @@ -9,50 +8,47 @@ show_hide_permissions ||= false %> -<% if select_deselect_all %> - - -<% end %> -<% if collapse_expand %> - -<% end %> -<% if show_hide_blocked %> - -<% end %> -<% if show_hide_permissions %> - -<% end %> +
+ <% if select_deselect_all %> + + <% end %> + <% if collapse_expand %> + + <% end %> + <% if show_hide_blocked %> + + <% end %> + <% if show_hide_permissions %> + + <% end %> +
From 81f8e704cf28178a4baae89179441679b6500bdf Mon Sep 17 00:00:00 2001 From: Finn Bacall Date: Tue, 26 Sep 2023 16:38:11 +0100 Subject: [PATCH 34/47] Restructure some views, replace inline styles Re-use bootstrap classes where possible for consistency --- app/assets/javascripts/checkbox.js | 10 +-- app/assets/stylesheets/publishing.scss | 49 ++++++----- app/assets/stylesheets/sharing.scss | 15 ---- app/views/assets/_asset_checkbox_row.html.erb | 87 ++++++++++--------- .../_batch_asset_selection_buttons.html.erb | 26 +++--- app/views/assets/_isa_tree_preview.html.erb | 4 +- app/views/assets/_permission_list.html.erb | 7 +- .../publishing/publish_related_items.html.erb | 3 +- .../general/_split_button_checkbox.html.erb | 39 +++------ 9 files changed, 113 insertions(+), 127 deletions(-) diff --git a/app/assets/javascripts/checkbox.js b/app/assets/javascripts/checkbox.js index ad2542903c..59cb770d85 100644 --- a/app/assets/javascripts/checkbox.js +++ b/app/assets/javascripts/checkbox.js @@ -65,7 +65,7 @@ const BatchAssetSelection = { }, toggleManagers: function () { - $j(this).siblings('.managed_by_list').toggle(); + $j('.managed_by_list', $j(this).closest('.isa-tree')).toggle(); return false; }, @@ -128,10 +128,10 @@ const BatchAssetSelection = { let children_assets = $j($j(this).data('blocked_selector'), $j(this).closest('.batch-selection-scope')); for (let asset of children_assets) { //Items in isa tree - if($j($j(asset).parents('div.split_button_parent')).length>0) { + if($j($j(asset).parents('div.batch-asset-selection-isa')).length>0) { // Don't hide "parents" of non-blocked items if (!$j('input[type=checkbox]', $j(asset).parent()).length > 0) { - $j($j(asset).parents('div.split_button_parent')[0]).hide() + $j($j(asset).parents('div.batch-asset-selection-isa')[0]).hide() } //Items not in isa tree } else { @@ -145,8 +145,8 @@ const BatchAssetSelection = { showBlocked: function (){ let children_assets = $j($j(this).data('blocked_selector'), $j(this).closest('.batch-selection-scope')); for (let asset of children_assets) { - if($j($j(asset).parents('div.split_button_parent')).length>0) { - $j($j(asset).parents('div.split_button_parent')[0]).show() + if($j($j(asset).parents('div.batch-asset-selection-isa')).length>0) { + $j($j(asset).parents('div.batch-asset-selection-isa')[0]).show() } else{ $j(asset).show() } diff --git a/app/assets/stylesheets/publishing.scss b/app/assets/stylesheets/publishing.scss index 9af8d7a905..776e408101 100644 --- a/app/assets/stylesheets/publishing.scss +++ b/app/assets/stylesheets/publishing.scss @@ -17,14 +17,6 @@ ul.publishing_options li.secondary { } -.published { - color: limegreen; -} - -span.published { - color: green; -} - span.approve { color: limegreen; font-weight: bolder; @@ -77,18 +69,6 @@ ul.item_for_decision { } } -.publish-colour { - color: $btn-success-bg; -} - -.publish-checkbox { - background-color: $btn-success-bg; - color: $btn-success-color; - padding: 0px 10px; - border-radius: 5px; - display: inline-block; -} - ul.decided_item { padding-left: 1em; } @@ -107,3 +87,32 @@ ul.decided_item li.type_and_title { padding: 0.5em 15px; margin: 0.3em 0em; } + +.batch-asset-selection-buttons { + margin-bottom: 1em; + display: flex; + gap: 1em; +} + +.batch-asset-selection-row { + display: flex; + gap: 1em; + align-items: center; + .visibility_icon { + margin: 0; + } +} + +.permission_list, .managed_by_list { + margin-left: 3em; +} + +.batch-asset-selection-isa-children { + margin-left: 3em; +} + +.batch-asset-select-btn { + input { + margin: 0; + } +} diff --git a/app/assets/stylesheets/sharing.scss b/app/assets/stylesheets/sharing.scss index 9a4ce89df3..6f56e31c5f 100644 --- a/app/assets/stylesheets/sharing.scss +++ b/app/assets/stylesheets/sharing.scss @@ -210,18 +210,3 @@ padding-left: 16px; } } - -.parent-btn-checkbox { - padding: 1px 6px 0px 6px; - border-radius: 5px; - display: inline-block; - height: 25px; - cursor: default; -} -.parent-btn-dropdown { - padding: 2px 6px 10px 0px; - border-radius: 5px; - display: inline-block; - height: 25px; -} - diff --git a/app/views/assets/_asset_checkbox_row.html.erb b/app/views/assets/_asset_checkbox_row.html.erb index bc1191f9c5..c3588019bd 100644 --- a/app/views/assets/_asset_checkbox_row.html.erb +++ b/app/views/assets/_asset_checkbox_row.html.erb @@ -18,58 +18,63 @@ itemid="#{item.class.name}_#{item.id}" - toggle ||=false + toggle ||= false show_managers ||= false show_permissions ||= false + show_managers = show_managers && (can_view || item.can_see_hidden_item?(current_user.person)) -%>
- <% if toggle %> - <%= render partial: 'assets/isa-tree-toggle' -%> - <% end %> - <% if can_view %> -
- <%= render partial: 'general/split_button_checkbox', - locals: { checkbox_id: publishing_item_param(item), - checkbox_class: itemid, - checked: checked, - checkbox_text: "", - published: published, - cant_manage: !(can_manage), - toggle: toggle } -%> -
+
+ <% if toggle %> + <%= render partial: 'assets/isa-tree-toggle' -%> + <% end %> + + <%= render partial: 'general/split_button_checkbox', + locals: { checkbox_id: publishing_item_param(item), + checkbox_class: itemid, + checked: can_view && checked, + not_visible: !can_view, + published: can_view && published, + cant_manage: !(can_manage), + toggle: toggle } -%> +
- <%= text_for_resource item -%>: <%= link_to item.title, item, target: "_blank" -%> - <% if show_permissions %> - + <%= text_for_resource item -%>: + <% if can_view %> + <%= link_to item.title, item, target: "_blank" -%> + <% else %> + This item is hidden to you + <% end %> +
+ + <% if show_permissions %> + <% if can_view %> + <%= list_item_visibility(item)-%> + <% else %> + <%= list_item_visibility(item)-%> <% end %> - - <% else %> -
- <%= render partial: 'general/split_button_checkbox', - locals: { checkbox_id: publishing_item_param(item), - checkbox_class: itemid, - not_visible: true, - toggle: toggle, - cb_parent_selector: cb_parent_selector} -%> -
-
<%= text_for_resource item -%>: This item is hidden to you
- <%=list_item_visibility(item)-%> - <% show_permissions=false%> - <% unless current_user.try(:person) && item.can_see_hidden_item?(current_user.person) %> - <% show_managers=false%> <% end %> - <% end %> + + <% if show_managers %> + + + + <% end %> +
+ <% if show_managers %> - - - - diff --git a/app/views/assets/_batch_asset_selection_buttons.html.erb b/app/views/assets/_batch_asset_selection_buttons.html.erb index a0ba4b80d6..bf2a1f9ae2 100644 --- a/app/views/assets/_batch_asset_selection_buttons.html.erb +++ b/app/views/assets/_batch_asset_selection_buttons.html.erb @@ -8,45 +8,45 @@ show_hide_permissions ||= false %> -
+
<% if select_deselect_all %> -
- + <% end %> <% if collapse_expand %> -
- + <% end %> <% if show_hide_blocked %> - <% end %> <% if show_hide_permissions %> -
- + diff --git a/app/views/assets/_isa_tree_preview.html.erb b/app/views/assets/_isa_tree_preview.html.erb index 673ff4dcdf..53bbc3363c 100644 --- a/app/views/assets/_isa_tree_preview.html.erb +++ b/app/views/assets/_isa_tree_preview.html.erb @@ -17,7 +17,7 @@ show_permissions ||= false show_managers ||= false -%> -
+
<%= render partial: "assets/asset_checkbox_row", object: item, locals: { html_classes: "publishing_options", @@ -29,7 +29,7 @@ } -%> <% if children.any? %> -
+
<% children.each do |child| %> <%= render partial: "assets/isa_tree_preview", object: child, diff --git a/app/views/assets/_permission_list.html.erb b/app/views/assets/_permission_list.html.erb index 094d22a222..d5fb3fed95 100644 --- a/app/views/assets/_permission_list.html.erb +++ b/app/views/assets/_permission_list.html.erb @@ -1,17 +1,16 @@ <% item ||= permission_list - item_id = "#{item.class.name}_#{item.id}" downloadable = item.try(:is_downloadable?) -%> -
" style="display:none;margin-left:5em" > +