mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Add methods to publish and unpublish a project list based on permission
This commit is contained in:
@@ -81,6 +81,28 @@
|
||||
end
|
||||
|
||||
if query.persisted?
|
||||
if can_publish?
|
||||
if query.public?
|
||||
menu.with_item(
|
||||
label: t(:button_unpublish),
|
||||
scheme: :danger,
|
||||
href: unpublish_projects_query_path(query),
|
||||
content_arguments: { data: { method: :post } }
|
||||
) do |item|
|
||||
item.with_leading_visual_icon(icon: 'eye-closed')
|
||||
end
|
||||
else
|
||||
menu.with_item(
|
||||
label: t(:button_publish),
|
||||
scheme: :default,
|
||||
href: publish_projects_query_path(query),
|
||||
content_arguments: { data: { method: :post } }
|
||||
) do |item|
|
||||
item.with_leading_visual_icon(icon: 'eye')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
menu.with_item(
|
||||
label: t(:button_delete),
|
||||
scheme: :danger,
|
||||
@@ -92,7 +114,6 @@
|
||||
end
|
||||
end
|
||||
%>
|
||||
|
||||
<%= render(Projects::ConfigureViewModalComponent.new(query:)) %>
|
||||
<%= render(Projects::DeleteListModalComponent.new(query:)) if query.persisted? %>
|
||||
<%= render(Projects::ExportListModalComponent.new(query:)) %>
|
||||
|
||||
@@ -74,6 +74,10 @@ class Projects::IndexPageHeaderComponent < ApplicationComponent
|
||||
|
||||
def can_rename? = may_save_as? && query.persisted? && query.user == current_user && !query.changed?
|
||||
|
||||
def can_publish?
|
||||
current_user.allowed_globally?(:manage_public_project_queries) && query.persisted?
|
||||
end
|
||||
|
||||
def show_state?
|
||||
state == :show
|
||||
end
|
||||
|
||||
@@ -46,19 +46,19 @@ module Projects
|
||||
|
||||
def favored
|
||||
render(Primer::Beta::IconButton.new(
|
||||
icon: currently_favored? ? "star-fill" : "star",
|
||||
scheme: :invisible,
|
||||
mobile_icon: currently_favored? ? "star-fill" : "star",
|
||||
size: :medium,
|
||||
tag: :a,
|
||||
tooltip_direction: :e,
|
||||
href: helpers.build_favorite_path(project, format: :html),
|
||||
data: { method: currently_favored? ? :delete : :post },
|
||||
classes: currently_favored? ? "op-primer--star-icon " : "op-project-row-component--favorite",
|
||||
label: currently_favored? ? I18n.t(:button_unfavorite) : I18n.t(:button_favorite),
|
||||
aria: { label: currently_favored? ? I18n.t(:button_unfavorite) : I18n.t(:button_favorite) },
|
||||
test_selector: 'project-list-favorite-button'
|
||||
))
|
||||
icon: currently_favored? ? "star-fill" : "star",
|
||||
scheme: :invisible,
|
||||
mobile_icon: currently_favored? ? "star-fill" : "star",
|
||||
size: :medium,
|
||||
tag: :a,
|
||||
tooltip_direction: :e,
|
||||
href: helpers.build_favorite_path(project, format: :html),
|
||||
data: { method: currently_favored? ? :delete : :post },
|
||||
classes: currently_favored? ? "op-primer--star-icon " : "op-project-row-component--favorite",
|
||||
label: currently_favored? ? I18n.t(:button_unfavorite) : I18n.t(:button_favorite),
|
||||
aria: { label: currently_favored? ? I18n.t(:button_unfavorite) : I18n.t(:button_favorite) },
|
||||
test_selector: "project-list-favorite-button"
|
||||
))
|
||||
end
|
||||
|
||||
def currently_favored?
|
||||
@@ -197,7 +197,7 @@ module Projects
|
||||
def additional_css_class(column)
|
||||
if column.attribute == :name
|
||||
"project--hierarchy #{project.archived? ? 'archived' : ''}"
|
||||
elsif [:status_explanation, :description].include?(column.attribute)
|
||||
elsif %i[status_explanation description].include?(column.attribute)
|
||||
"project-long-text-container"
|
||||
elsif custom_field_column?(column)
|
||||
cf = column.custom_field
|
||||
@@ -254,7 +254,7 @@ module Projects
|
||||
href: helpers.build_favorite_path(project, format: :html),
|
||||
data: { method: :post },
|
||||
label: I18n.t(:button_favorite),
|
||||
aria: { label: I18n.t(:button_favorite) },
|
||||
aria: { label: I18n.t(:button_favorite) }
|
||||
}
|
||||
end
|
||||
|
||||
@@ -269,7 +269,7 @@ module Projects
|
||||
data: { method: :delete },
|
||||
classes: "op-primer--star-icon",
|
||||
label: I18n.t(:button_unfavorite),
|
||||
aria: { label: I18n.t(:button_unfavorite) },
|
||||
aria: { label: I18n.t(:button_unfavorite) }
|
||||
}
|
||||
end
|
||||
|
||||
@@ -302,7 +302,7 @@ module Projects
|
||||
scheme: :default,
|
||||
icon: :check,
|
||||
label: I18n.t(:label_project_activity),
|
||||
href: project_activity_index_path(project, event_types: ["project_attributes"]),
|
||||
href: project_activity_index_path(project, event_types: ["project_attributes"])
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -317,7 +317,7 @@ module Projects
|
||||
data: {
|
||||
confirm: t("project.archive.are_you_sure", name: project.name),
|
||||
method: :post
|
||||
},
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -340,7 +340,7 @@ module Projects
|
||||
scheme: :default,
|
||||
icon: :copy,
|
||||
label: I18n.t(:button_copy),
|
||||
href: copy_project_path(project),
|
||||
href: copy_project_path(project)
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -351,7 +351,7 @@ module Projects
|
||||
scheme: :danger,
|
||||
icon: :trash,
|
||||
label: I18n.t(:button_delete),
|
||||
href: confirm_destroy_project_path(project),
|
||||
href: confirm_destroy_project_path(project)
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -361,7 +361,7 @@ module Projects
|
||||
end
|
||||
|
||||
def custom_field_column?(column)
|
||||
column.is_a?(Queries::Projects::Selects::CustomField)
|
||||
column.is_a?(::Queries::Projects::Selects::CustomField)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -64,11 +64,18 @@ module Projects
|
||||
# We don't return the project row
|
||||
# but the [project, level] array from the helper
|
||||
def rows
|
||||
<<<<<<< HEAD
|
||||
@rows ||=
|
||||
begin
|
||||
projects_enumerator = ->(model) { to_enum(:projects_with_levels_order_sensitive, model).to_a }
|
||||
instance_exec(model, &projects_enumerator)
|
||||
end
|
||||
=======
|
||||
@rows ||= begin
|
||||
projects_enumerator = ->(model) { to_enum(:projects_with_levels_order_sensitive, model).to_a }
|
||||
instance_exec(model, &projects_enumerator)
|
||||
end
|
||||
>>>>>>> 0e1a80b408 (Add methods to publish and unpublish a project list based on permission)
|
||||
end
|
||||
|
||||
def initialize_sorted_model
|
||||
@@ -113,12 +120,11 @@ module Projects
|
||||
end
|
||||
|
||||
def columns
|
||||
@columns ||=
|
||||
begin
|
||||
columns = query.selects.reject { |select| select.is_a?(Queries::Selects::NotExistingSelect) }
|
||||
@columns ||= begin
|
||||
columns = query.selects.reject { |select| select.is_a?(::Queries::Selects::NotExistingSelect) }
|
||||
|
||||
index = columns.index { |column| column.attribute == :name }
|
||||
columns.insert(index, Queries::Projects::Selects::Default.new(:hierarchy)) if index
|
||||
index = columns.index { |column| column.attribute == :name }
|
||||
columns.insert(index, ::Queries::Projects::Selects::Default.new(:hierarchy)) if index
|
||||
|
||||
columns
|
||||
end
|
||||
@@ -156,7 +162,7 @@ module Projects
|
||||
end
|
||||
|
||||
def favored_project_ids
|
||||
@favored_projects ||= Favorite.where(user: current_user, favored_type: 'Project').pluck(:favored_id)
|
||||
@favored_projects ||= Favorite.where(user: current_user, favored_type: "Project").pluck(:favored_id)
|
||||
end
|
||||
|
||||
def sorted_by_lft?
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) 2012-2024 the OpenProject GmbH
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
class Projects::Queries::PublishContract < BaseContract
|
||||
validate :allowed_to_modify_public_flag
|
||||
|
||||
protected
|
||||
|
||||
def allowed_to_modify_public_flag
|
||||
unless user.allowed_globally?(:manage_public_project_queries)
|
||||
errors.add :base, :error_unauthorized
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -31,7 +31,7 @@ class Projects::QueriesController < ApplicationController
|
||||
|
||||
# No need for a more specific authorization check. That is carried out in the contracts.
|
||||
before_action :require_login
|
||||
before_action :find_query, only: %i[rename update destroy]
|
||||
before_action :find_query, only: %i[rename update destroy publish unpublish]
|
||||
before_action :build_query_or_deny_access, only: %i[new create]
|
||||
|
||||
current_menu_item [:new, :rename, :create, :update] do
|
||||
@@ -55,17 +55,7 @@ class Projects::QueriesController < ApplicationController
|
||||
.new(from: @query, user: current_user)
|
||||
.call(permitted_query_params)
|
||||
|
||||
if call.success?
|
||||
flash[:notice] = I18n.t("lists.create.success")
|
||||
|
||||
redirect_to projects_path(query_id: call.result.id)
|
||||
else
|
||||
flash[:error] = I18n.t("lists.create.failure", errors: call.errors.full_messages.join("\n"))
|
||||
|
||||
render template: "/projects/index",
|
||||
layout: "global",
|
||||
locals: { query: call.result, state: :edit }
|
||||
end
|
||||
render_result(call, success_i18n_key: "lists.create.success", error_i18n_key: "lists.create.failure")
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -73,17 +63,23 @@ class Projects::QueriesController < ApplicationController
|
||||
.new(user: current_user, model: @query)
|
||||
.call(permitted_query_params)
|
||||
|
||||
if call.success?
|
||||
flash[:notice] = I18n.t("lists.update.success")
|
||||
render_result(call, success_i18n_key: "lists.update.success", error_i18n_key: "lists.update.failure")
|
||||
end
|
||||
|
||||
redirect_to projects_path(query_id: call.result.id)
|
||||
else
|
||||
flash[:error] = I18n.t("lists.update.failure", errors: call.errors.full_messages.join("\n"))
|
||||
def publish
|
||||
call = Queries::Projects::ProjectQueries::PublishService
|
||||
.new(user: current_user, model: @query)
|
||||
.call(public: true)
|
||||
|
||||
render template: "/projects/index",
|
||||
layout: "global",
|
||||
locals: { query: call.result, state: :edit }
|
||||
end
|
||||
render_result(call, success_i18n_key: "lists.publish.success", error_i18n_key: "lists.publish.failure")
|
||||
end
|
||||
|
||||
def unpublish
|
||||
call = Queries::Projects::ProjectQueries::PublishService
|
||||
.new(user: current_user, model: @query)
|
||||
.call(public: false)
|
||||
|
||||
render_result(call, success_i18n_key: "lists.unpublish.success", error_i18n_key: "lists.unpublish.failure")
|
||||
end
|
||||
|
||||
def destroy
|
||||
@@ -95,6 +91,20 @@ class Projects::QueriesController < ApplicationController
|
||||
|
||||
private
|
||||
|
||||
def render_result(service_call, success_i18n_key:, error_i18n_key:)
|
||||
if service_call.success?
|
||||
flash[:notice] = I18n.t(success_i18n_key)
|
||||
|
||||
redirect_to projects_path(query_id: service_call.result.id)
|
||||
else
|
||||
flash[:error] = I18n.t(error_i18n_key, errors: service_call.errors.full_messages.join("\n"))
|
||||
|
||||
render template: "/projects/index",
|
||||
layout: "global",
|
||||
locals: { query: service_call.result, state: :edit }
|
||||
end
|
||||
end
|
||||
|
||||
def find_query
|
||||
@query = Queries::Projects::ProjectQuery.find(params[:id])
|
||||
end
|
||||
|
||||
@@ -30,10 +30,10 @@ module Projects
|
||||
private
|
||||
|
||||
def load_query(duplicate:)
|
||||
Queries::Projects::Factory.find(params[:query_id],
|
||||
params: permitted_query_params,
|
||||
user: current_user,
|
||||
duplicate:)
|
||||
::Queries::Projects::Factory.find(params[:query_id],
|
||||
params: permitted_query_params,
|
||||
user: current_user,
|
||||
duplicate:)
|
||||
end
|
||||
|
||||
def load_query_or_deny_access
|
||||
@@ -55,7 +55,7 @@ module Projects
|
||||
query_params.merge!(params.require(:query).permit(:name))
|
||||
end
|
||||
|
||||
query_params.merge!(Queries::ParamsParser.parse(params))
|
||||
query_params.merge!(::Queries::ParamsParser.parse(params))
|
||||
|
||||
query_params.with_indifferent_access
|
||||
end
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) 2012-2024 the OpenProject GmbH
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
class Queries::Projects::ProjectQueries::PublishService < BaseServices::BaseContracted
|
||||
include Contracted
|
||||
|
||||
def initialize(user:, model:, contract_class: Projects::Queries::PublishContract)
|
||||
super(user:, contract_class:)
|
||||
self.model = model
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def after_validate(params, service_call)
|
||||
model.public = params[:public]
|
||||
|
||||
service_call
|
||||
end
|
||||
|
||||
def persist(service_call)
|
||||
model.save
|
||||
|
||||
service_call
|
||||
end
|
||||
end
|
||||
@@ -184,6 +184,9 @@ Rails.application.routes.draw do
|
||||
resources :queries, only: %i[new create update destroy] do
|
||||
member do
|
||||
get :rename
|
||||
|
||||
post :publish
|
||||
post :unpublish
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user