diff --git a/app/controllers/org_admin/templates_controller.rb b/app/controllers/org_admin/templates_controller.rb index 07d99a4..ba6c281 100644 --- a/app/controllers/org_admin/templates_controller.rb +++ b/app/controllers/org_admin/templates_controller.rb @@ -7,31 +7,29 @@ # ----------------------------------------------------- def index authorize Template + # Apply scoping - orgs_hash = apply_scoping(params[:scope] || 'all') - funders_hash = apply_scoping(params[:scope] || 'all', true) + all_templates_hash = apply_scoping(params[:scope] || 'all', false, true) + own_hash = apply_scoping(params[:scope] || 'all', false, false) + customizable_hash = apply_scoping(params[:scope] || 'all', true, false) # Apply pagination - orgs_hash[:templates] = orgs_hash[:templates].page(1) - funders_hash[:templates] = funders_hash[:templates].page(1) + all_templates_hash[:templates] = all_templates_hash[:templates].page(1) + own_hash[:templates] = own_hash[:templates].page(1) + customizable_hash[:templates] = customizable_hash[:templates].page(1) # Gather up all of the publication dates for the live versions of each template. - published = {} - [funders_hash[:templates], orgs_hash[:templates]].each do |collection| - collection.each do |template| - live = Template.live(template.dmptemplate_id) - published[template.dmptemplate_id] = live.updated_at if live.present? - end - end + published = get_publication_dates(all_templates_hash[:scopes][:dmptemplate_ids]) render 'index', locals: { - funder_templates: funders_hash[:templates], - org_templates: orgs_hash[:templates], - customized_templates: funders_hash[:customizations], + all_templates: all_templates_hash[:templates], + customizable_templates: customizable_hash[:templates], + own_templates: own_hash[:templates], + customized_templates: customizable_hash[:customizations], published: published, current_org: current_user.org, orgs: Org.all, - scopes: { orgs: orgs_hash[:scopes], funders: funders_hash[:scopes] } + scopes: { all: all_templates_hash[:scopes], orgs: own_hash[:scopes], funders: customizable_hash[:scopes] } } end @@ -284,23 +282,40 @@ redirect_to edit_org_admin_template_path(new_customization) end + # GET /org_admin/templates/all/:page (AJAX) + # ----------------------------------------------------- + def all + authorize Template + # Apply scoping + hash = apply_scoping(params[:scope] || 'all', false, true) + + # Apply pagination + hash[:templates] = hash[:templates].page(params[:page]) if params[:page] != 'ALL' + + # Gather up all of the publication dates for the live versions of each template. + published = get_publication_dates(hash[:scopes][:dmptemplate_ids]) + + paginable_renderise partial: 'templates_list', + scope: hash[:templates], + locals: { current_org: current_user.org.id, + customizations: hash[:customizations], + published: published, + scopes: hash[:scopes], + hide_actions: true } + end # GET /org_admin/templates/funders/:page (AJAX) # ----------------------------------------------------- def funders authorize Template # Apply scoping - hash = apply_scoping(params[:scope] || 'all', true) + hash = apply_scoping(params[:scope] || 'all', true, false) # Apply pagination hash[:templates] = hash[:templates].page(params[:page]) if params[:page] != 'ALL' # Gather up all of the publication dates for the live versions of each template. - published = {} - hash[:templates].each do |template| - live = Template.live(template.dmptemplate_id) - published[template.dmptemplate_id] = live.updated_at if live.present? - end + published = get_publication_dates(hash[:scopes][:dmptemplate_ids]) paginable_renderise partial: 'funder_templates_list', scope: hash[:templates], @@ -315,24 +330,21 @@ def orgs authorize Template # Apply scoping - hash = apply_scoping(params[:scope] || 'all') + hash = apply_scoping(params[:scope] || 'all', false, false) # Apply pagination hash[:templates] = hash[:templates].page(params[:page]) if params[:page] != 'ALL' # Gather up all of the publication dates for the live versions of each template. - published = {} - hash[:templates].each do |template| - live = Template.live(template.dmptemplate_id) - published[template.dmptemplate_id] = live.updated_at if live.present? - end + published = get_publication_dates(hash[:scopes][:dmptemplate_ids]) paginable_renderise partial: 'templates_list', scope: hash[:templates], locals: { current_org: current_user.org.id, customizations: hash[:customizations], published: published, - scopes: hash[:scopes] } + scopes: hash[:scopes], + hide_actions: false } end # PUT /org_admin/templates/:id/copy (AJAX) @@ -362,30 +374,29 @@ # PUT /org_admin/templates/:id/publish (AJAX) # ----------------------------------------------------- def publish - @template = Template.find(params[:id]) - authorize @template + template = Template.find(params[:id]) + authorize template - current = Template.current(@template.dmptemplate_id) + current = Template.current(template.dmptemplate_id) # Only allow the current version to be updated - if current != @template + if current != template redirect_to org_admin_templates_path, alert: _('You can not publish a historical version of this template.') else # Unpublish the older published version if there is one - live = Template.live(@template.dmptemplate_id) + live = Template.live(template.dmptemplate_id) if !live.nil? and self != live live.published = false live.save! end # Set the dirty flag to false - @template.dirty = false - @template.published = true - @template.save + template.dirty = false + template.published = true + template.save flash[:notice] = _('Your template has been published and is now available to users.') - - redirect_to org_admin_templates_path + redirect_to "#{org_admin_templates_path}#{template.customization_of.present? ? '#funder-templates' : '#organisation-templates'}" end end @@ -395,18 +406,15 @@ template = Template.find(params[:id]) authorize template - # Unpublish the live version - @template = Template.live(template.dmptemplate_id) - - if @template.nil? + if template.nil? flash[:alert] = _('That template is not currently published.') else - @template.published = false - @template.save + template.published = false + template.save flash[:notice] = _('Your template is no longer published. Users will not be able to create new DMPs for this template until you re-publish it') end - redirect_to org_admin_templates_path + redirect_to "#{org_admin_templates_path}#{template.customization_of.present? ? '#funder-templates' : '#organisation-templates'}" end # PUT /org_admin/template_options (AJAX) @@ -464,13 +472,15 @@ end # Applies scoping to the template list - def apply_scoping(scope, funders = false) - if funders - templates = Template.get_latest_template_versions(Org.funder) - + def apply_scoping(scope, customizable = false, all = false) + if customizable + # Retrieve all of the publicly visible published funder templates + orgs = Org.funder.where.not(id: current_user.org.id) # Include the default template in the list of funder templates - templates << Template.default - + orgs << Template.default.org unless current_user.org == Template.default.org + + templates = Template.get_public_published_template_versions(orgs) + # If the user is an Org Admin look for customizations to funder templates customizations = {} if current_user.can_org_admin? @@ -495,10 +505,14 @@ templates = Template.where(id: scoped.collect(&:id)) end end - + else - valid_orgs = current_user.can_super_admin? ? Org.not_funder : Org.find(current_user.org) - templates = Template.get_latest_template_versions(valid_orgs) + # If we're collecting all templates + if all + templates = Template.get_latest_template_versions(Org.all) + else + templates = Template.get_latest_template_versions(Org.where(id: current_user.org.id)) + end scopes = calculate_table_scopes(templates, {}) @@ -507,7 +521,7 @@ templates = templates.where(published: false) if params[:scope] == 'unpublished' end end - + { templates: templates, customizations: customizations || {}, scopes: scopes } @@ -515,10 +529,10 @@ # Gets the nbr of templates and nbr of published/unpublished templates def calculate_table_scopes(templates, customizations) - scopes = { all: templates.length, published: 0, unpublished: 0 } + scopes = { all: templates.length, published: 0, unpublished: 0, dmptemplate_ids: templates.collect(&:dmptemplate_id).uniq } templates.each do |t| # If we have customizations use their status - if customizations.length > 0 + if customizations.respond_to?(:keys) c = customizations[t.dmptemplate_id] # If the template was not customized then its unpublished if c.nil? @@ -535,5 +549,14 @@ end scopes end + + def get_publication_dates(family_ids) + published = {} + lives = Template.live(family_ids) + lives.each do |live| + published[live.dmptemplate_id] = live.updated_at + end + published + end end end \ No newline at end of file diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 996a33d..598ded8 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -78,7 +78,7 @@ redirect_to "#{edit_user_registration_path}\#notification-preferences", notice: success_message(_('preferences'), _('saved')) end - # PUT /users/:id/org_swap (AJAX) + # PUT /users/:id/org_swap # ----------------------------------------------------- def org_swap # Allows the user to swap their org affiliation on the fly @@ -87,16 +87,12 @@ if org.present? current_user.org = org if current_user.save! - render json: { - msg: _('Your organisation affiliation has been changed. You may now edit templates for %{org_name}.') % {org_name: current_user.org.name} - }.to_json + redirect_to request.referer, notice: _('Your organisation affiliation has been changed. You may now edit templates for %{org_name}.') % {org_name: current_user.org.name} else - render json: { - err: _('Unable to change your organisation affiliation at this time.') - }.to_json + redirect_to request.referer, alert: _('Unable to change your organisation affiliation at this time.') end else - render json: {}.to_json + redirect_to request.referer, alert: _('Unknown organisation.') end end diff --git a/app/models/template.rb b/app/models/template.rb index 0ff158d..7f0d120 100644 --- a/app/models/template.rb +++ b/app/models/template.rb @@ -25,7 +25,7 @@ # -relies on protected_attributes gem as syntax depricated in rails 4.2 attr_accessible :id, :org_id, :description, :published, :title, :locale, :customization_of, :is_default, :guidance_group_ids, :org, :plans, :phases, :dmptemplate_id, - :migrated, :version, :visibility, :published, :as => [:default, :admin] + :migrated, :version, :visibility, :published, :links, :as => [:default, :admin] # A standard template should be organisationally visible. Funder templates that are # meant for external use will be publicly visible. This allows a funder to create 'funder' as @@ -67,12 +67,28 @@ select("MAX(version) AS version", :dmptemplate_id).group(:dmptemplate_id) end } + # Retrieves the maximum version for the array of customization_ofs passed. If customization_ofs is missing, every maximum + # version for each different customization_of will be retrieved + scope :customization_ofs_with_max_version, -> (customization_ofs=nil) { + if customization_ofs.is_a?(Array) + select("MAX(version) AS version", :customization_of).where(customization_of: customization_ofs).group(:customization_of) + else + select("MAX(version) AS version", :customization_of).group(:customization_of) + end + } # Retrieves the latest template version, i.e. the one with maximum version for each dmptemplate_id scope :latest_version, -> (dmptemplate_ids=nil) { from(dmptemplate_ids_with_max_version(dmptemplate_ids), :current) .joins("INNER JOIN templates ON current.version = templates.version"\ " AND current.dmptemplate_id = templates.dmptemplate_id") } + # Retrieves the latest customized version, i.e. the one with maximum version for each customization_of=dmptemplate_id + scope :latest_customization, -> (org_id, dmptemplate_ids=nil) { + from(customization_ofs_with_max_version(dmptemplate_ids), :current) + .joins("INNER JOIN templates ON current.version = templates.version"\ + " AND current.customization_of = templates.customization_of") + .where('templates.org_id = ?', org_id) + } # Retrieves the list of all dmptemplate_ids (template versioning families) for the specified Org def self.dmptemplate_ids Template.all.valid.distinct.pluck(:dmptemplate_id) @@ -85,7 +101,11 @@ # Retrieves the current published version of the template for the specified Org and dmptemplate_id def self.live(dmptemplate_id) - Template.where(dmptemplate_id: dmptemplate_id, published: true).valid.first + if dmptemplate_id.respond_to?(:each) + Template.where(dmptemplate_id: dmptemplate_id, published: true).valid + else + Template.where(dmptemplate_id: dmptemplate_id, published: true).valid.first + end end def self.default @@ -100,8 +120,9 @@ # @params dmptemplate_ids of the original template # @params [integer] org_id for the customizing organisation # @return [nil, Template] the customized template or nil - def self.org_customizations(dmptemplate_id, org_id) - Template.where(customization_of: dmptemplate_id, org_id: org_id).order(version: :desc).valid + def self.org_customizations(dmptemplate_ids, org_id) + template_ids = latest_customization(org_id, dmptemplate_ids).pluck(:id) + includes(:org).where(id: template_ids).order('orgs.name, templates.title') end # Retrieves current templates with their org associated for a set of valid orgs @@ -118,6 +139,19 @@ includes(:org).where(id: template_ids).order('orgs.name, templates.title') end + # Retrieves current templates with their org associated for a set of valid orgs + # TODO pass an array of org ids instead of Org instances + def self.get_public_published_template_versions(orgs) + if orgs.respond_to?(:each) + families_ids = families(orgs.map(&:id)).pluck(:dmptemplate_id) + elsif orgs.is_a?(Org) + families_ids = families([orgs.id]).pluck(:dmptemplate_id) + else + families_ids = [] + end + includes(:org).where(dmptemplate_id: families_ids, published: true, visibility: Template.visibilities[:publicly_visible]).order('orgs.name, templates.title') + end + ## # deep copy the given template and all of it's associations # diff --git a/app/policies/template_policy.rb b/app/policies/template_policy.rb index 64cf610..b4a62c3 100644 --- a/app/policies/template_policy.rb +++ b/app/policies/template_policy.rb @@ -44,6 +44,9 @@ end # Pagination + def all? + user.can_super_admin? + end def funders? user.can_super_admin? || user.can_modify_templates? end diff --git a/app/views/layouts/_branding.html.erb b/app/views/layouts/_branding.html.erb index 72e65ad..a746176 100644 --- a/app/views/layouts/_branding.html.erb +++ b/app/views/layouts/_branding.html.erb @@ -24,7 +24,7 @@