mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
Resource Allocation info dialog
This commit is contained in:
+69
@@ -0,0 +1,69 @@
|
||||
<%#-- copyright
|
||||
OpenProject is an open source project management software.
|
||||
Copyright (C) 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%=
|
||||
render(Primer::Alpha::Dialog.new(id: DIALOG_ID, title:, size: :medium_portrait, position: :right)) do |dialog|
|
||||
dialog.with_header(variant: :large)
|
||||
|
||||
dialog.with_body do
|
||||
flex_layout do |body|
|
||||
body.with_row(mb: 3) do
|
||||
render(ResourcePlannerViews::WorkPackageList::AllocationProgressComponent.new(work_package:, allocations:))
|
||||
end
|
||||
|
||||
allocations.each do |allocation|
|
||||
body.with_row(border: :bottom, py: 2) do
|
||||
render(ResourceAllocations::ListItemComponent.new(allocation:, visible: visible_principal?(allocation)))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
dialog.with_footer(show_divider: true) do
|
||||
flex_layout(justify_content: :space_between, align_items: :center) do |footer|
|
||||
footer.with_column do
|
||||
render Primer::Beta::Button.new(
|
||||
scheme: :link,
|
||||
tag: :a,
|
||||
href: allocate_resource_path,
|
||||
data: { controller: "async-dialog" }
|
||||
) do |button|
|
||||
button.with_leading_visual_icon(icon: :plus)
|
||||
t("resource_management.work_package_allocations_dialog.allocate_resource")
|
||||
end
|
||||
end
|
||||
footer.with_column do
|
||||
render(Primer::Beta::Button.new(data: { "close-dialog-id": DIALOG_ID })) do
|
||||
t(:button_close)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
%>
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) 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.
|
||||
#++
|
||||
|
||||
module ResourceAllocations
|
||||
# Lists a work package's allocations: the allocation progress summary, one row
|
||||
# per allocation, and a footer to add another. Allocations whose principal is
|
||||
# not visible to the current user are still listed, but anonymised.
|
||||
class ListDialogComponent < ApplicationComponent
|
||||
include OpTurbo::Streamable
|
||||
include OpPrimer::ComponentHelpers
|
||||
|
||||
DIALOG_ID = "work-package-allocations-dialog"
|
||||
|
||||
def initialize(project:, work_package:, allocations:, visible_principal_ids:)
|
||||
super
|
||||
|
||||
@project = project
|
||||
@work_package = work_package
|
||||
@allocations = allocations
|
||||
@visible_principal_ids = visible_principal_ids
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :project, :work_package, :allocations, :visible_principal_ids
|
||||
|
||||
def title
|
||||
I18n.t("resource_management.work_package_allocations_dialog.title")
|
||||
end
|
||||
|
||||
def visible_principal?(allocation)
|
||||
allocation.principal_id.nil? || visible_principal_ids.include?(allocation.principal_id)
|
||||
end
|
||||
|
||||
def allocate_resource_path
|
||||
new_project_resource_allocation_path(project, work_package_id: work_package.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
<%#-- copyright
|
||||
OpenProject is an open source project management software.
|
||||
Copyright (C) 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%= flex_layout(align_items: :center) do |row| %>
|
||||
<%= row.with_column(mr: 2) do %>
|
||||
<%= render(avatar) %>
|
||||
<% end %>
|
||||
<%= row.with_column(flex: 1) do %>
|
||||
<%= render(Primer::Beta::Text.new(font_size: :small)) { name } %>
|
||||
<% end %>
|
||||
<%= row.with_column do %>
|
||||
<%= render(Primer::Beta::Text.new(font_size: :small, color: :muted)) { hours } %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) 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.
|
||||
#++
|
||||
|
||||
module ResourceAllocations
|
||||
# A single allocation row in the work package allocations dialog: the member's
|
||||
# avatar and name (or an anonymous placeholder when the principal is not
|
||||
# visible to the current user) and the allocated hours.
|
||||
class ListItemComponent < ApplicationComponent
|
||||
include OpPrimer::ComponentHelpers
|
||||
include AvatarHelper
|
||||
|
||||
AVATAR_SIZE = 24
|
||||
|
||||
def initialize(allocation:, visible:)
|
||||
super
|
||||
|
||||
@allocation = allocation
|
||||
@visible = visible
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :allocation
|
||||
|
||||
def visible?
|
||||
@visible
|
||||
end
|
||||
|
||||
def name
|
||||
if allocation.principal
|
||||
visible? ? allocation.principal.name : hidden_label
|
||||
else
|
||||
allocation.filter_name.presence || unassigned_label
|
||||
end
|
||||
end
|
||||
|
||||
# Only a visible principal exposes a real avatar (and an identity-revealing
|
||||
# initials/colour seed). Everything else falls back to a generated avatar
|
||||
# keyed to the allocation, so a hidden user cannot be correlated.
|
||||
def avatar
|
||||
Primer::OpenProject::AvatarWithFallback.new(size: AVATAR_SIZE, **avatar_options)
|
||||
end
|
||||
|
||||
def avatar_options
|
||||
if allocation.principal && visible?
|
||||
{
|
||||
src: avatar_url(allocation.principal),
|
||||
alt: allocation.principal.name,
|
||||
unique_id: allocation.principal.id
|
||||
}
|
||||
else
|
||||
{
|
||||
alt: name,
|
||||
unique_id: "resource-allocation-#{allocation.id}"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def hours
|
||||
t("resource_management.work_package_list.allocation.hours",
|
||||
value: helpers.number_with_precision(allocation.allocated_hours, precision: 1, strip_insignificant_zeros: true))
|
||||
end
|
||||
|
||||
def hidden_label
|
||||
t("resource_management.work_package_allocations_dialog.hidden_user")
|
||||
end
|
||||
|
||||
def unassigned_label
|
||||
t("resource_management.work_package_list.allocated_members.unassigned")
|
||||
end
|
||||
end
|
||||
end
|
||||
+6
-2
@@ -142,8 +142,12 @@ module ResourcePlannerViews::WorkPackageList
|
||||
end
|
||||
|
||||
def see_allocation_item(menu)
|
||||
menu.with_item(label: t("resource_management.work_package_list.context_menu.see_allocation"),
|
||||
disabled: true) do |item|
|
||||
menu.with_item(
|
||||
label: t("resource_management.work_package_list.context_menu.see_allocation"),
|
||||
tag: :a,
|
||||
href: helpers.project_work_package_resource_allocations_path(table.project, work_package),
|
||||
content_arguments: { data: { controller: "async-dialog" } }
|
||||
) do |item|
|
||||
item.with_leading_visual_icon(icon: :hourglass)
|
||||
end
|
||||
end
|
||||
|
||||
+1
-11
@@ -206,20 +206,10 @@ module ::ResourceManagement
|
||||
resource_planner: @resource_planner,
|
||||
work_packages:,
|
||||
allocations:,
|
||||
visible_principal_ids: visible_principal_ids(allocations)
|
||||
visible_principal_ids: ResourceAllocation.visible_principal_ids(allocations.values.flatten, current_user)
|
||||
)
|
||||
end
|
||||
|
||||
# The principals among the allocations that the current user may see. The
|
||||
# members column keeps the rest as an anonymous count rather than revealing
|
||||
# who they are.
|
||||
def visible_principal_ids(allocations)
|
||||
principal_ids = allocations.values.flatten.filter_map(&:principal_id).uniq
|
||||
return Set.new if principal_ids.empty?
|
||||
|
||||
Principal.visible(current_user).where(id: principal_ids).pluck(:id).to_set
|
||||
end
|
||||
|
||||
def render_configure_step(view, status: :ok)
|
||||
update_dialog_title_via_turbo_stream(
|
||||
ResourcePlannerViews::NewDialogComponent::DIALOG_ID,
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) 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.
|
||||
#++
|
||||
|
||||
module ::ResourceManagement
|
||||
# Lists the allocations of a single work package in a dialog. Visible to users
|
||||
# who may view the work package and hold the `view_resource_planners`
|
||||
# permission in its project.
|
||||
class WorkPackageResourceAllocationsController < BaseController
|
||||
include OpTurbo::ComponentStream
|
||||
|
||||
menu_item :resource_management
|
||||
|
||||
before_action :find_project_by_project_id
|
||||
before_action :find_work_package
|
||||
before_action :authorize
|
||||
|
||||
def index
|
||||
respond_with_dialog ResourceAllocations::ListDialogComponent.new(
|
||||
project: @project,
|
||||
work_package: @work_package,
|
||||
allocations:,
|
||||
visible_principal_ids: ResourceAllocation.visible_principal_ids(allocations, current_user)
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def allocations
|
||||
@allocations ||=
|
||||
ResourceAllocation.allocated_for_work_packages([@work_package])[@work_package.id] || []
|
||||
end
|
||||
|
||||
# `WorkPackage.visible` enforces the view-work-package permission; a
|
||||
# non-visible (or out-of-project) id therefore 404s. The
|
||||
# `view_resource_planners` permission is enforced by `authorize`.
|
||||
def find_work_package
|
||||
@work_package = WorkPackage
|
||||
.visible(current_user)
|
||||
.where(project: @project)
|
||||
.find(params.expect(:work_package_id))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -69,6 +69,15 @@ class ResourceAllocation < ApplicationRecord
|
||||
.group_by(&:entity_id)
|
||||
end
|
||||
|
||||
# The subset of the given allocations' principal ids that `user` may see.
|
||||
# Used to anonymise members the current user is not allowed to know about.
|
||||
def self.visible_principal_ids(allocations, user)
|
||||
principal_ids = allocations.filter_map(&:principal_id).uniq
|
||||
return Set.new if principal_ids.empty?
|
||||
|
||||
Principal.visible(user).where(id: principal_ids).pluck(:id).to_set
|
||||
end
|
||||
|
||||
validates :state, :start_date, :end_date, presence: true
|
||||
validates :allocated_time,
|
||||
presence: true,
|
||||
|
||||
@@ -129,6 +129,10 @@ en:
|
||||
caption: >-
|
||||
Create a view based on users and see their details and allocation in a list of user cards
|
||||
label: Users card list
|
||||
work_package_allocations_dialog:
|
||||
allocate_resource: Allocate resource
|
||||
hidden_user: Hidden user
|
||||
title: Allocation
|
||||
work_package_list:
|
||||
add_work_package_dialog:
|
||||
title: Add work package
|
||||
|
||||
@@ -69,5 +69,11 @@ Rails.application.routes.draw do
|
||||
get :refresh_form
|
||||
end
|
||||
end
|
||||
|
||||
resources :work_packages, only: [] do
|
||||
resources :resource_allocations,
|
||||
controller: "resource_management/work_package_resource_allocations",
|
||||
only: :index
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -60,6 +60,7 @@ module OpenProject::ResourceManagement
|
||||
new_work_package add_work_package
|
||||
remove_work_package move_work_package
|
||||
reorder_work_package],
|
||||
"resource_management/work_package_resource_allocations": %i[index],
|
||||
"resource_management/menus": %i[show]
|
||||
},
|
||||
permissible_on: :project
|
||||
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) 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.
|
||||
#++
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe ResourceAllocations::ListItemComponent, type: :component do
|
||||
shared_let(:work_package) { create(:work_package) }
|
||||
shared_let(:member) { create(:user, firstname: "Sarah", lastname: "Smith") }
|
||||
|
||||
let(:visible) { true }
|
||||
|
||||
subject(:rendered) do
|
||||
render_inline(described_class.new(allocation:, visible:))
|
||||
page
|
||||
end
|
||||
|
||||
before { login_as(create(:admin)) }
|
||||
|
||||
context "with a visible assigned member" do
|
||||
let(:allocation) { create(:resource_allocation, entity: work_package, principal: member, allocated_time: 720) }
|
||||
|
||||
it "shows the member's name, avatar and allocated hours" do
|
||||
expect(rendered).to have_text("Sarah Smith")
|
||||
expect(rendered).to have_text("12h")
|
||||
expect(rendered).to have_css("avatar-fallback[data-unique-id='#{member.id}']")
|
||||
end
|
||||
end
|
||||
|
||||
context "with an assigned member the user may not see" do
|
||||
let(:allocation) { create(:resource_allocation, entity: work_package, principal: member, allocated_time: 720) }
|
||||
let(:visible) { false }
|
||||
|
||||
it "anonymises the member without revealing the name" do
|
||||
expect(rendered).to have_no_text("Sarah Smith")
|
||||
expect(rendered).to have_no_css("avatar-fallback[data-unique-id='#{member.id}']")
|
||||
expect(rendered).to have_text(I18n.t("resource_management.work_package_allocations_dialog.hidden_user"))
|
||||
end
|
||||
end
|
||||
|
||||
context "with a filter-based allocation" do
|
||||
let(:allocation) do
|
||||
create(:resource_allocation,
|
||||
entity: work_package, principal_explicit: false, principal: nil, filter_name: "Full stack developer")
|
||||
end
|
||||
|
||||
it "shows the filter name" do
|
||||
expect(rendered).to have_text("Full stack developer")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,106 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) 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.
|
||||
#++
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe "WorkPackage resource allocations requests", type: :rails_request do
|
||||
shared_let(:project) { create(:project, enabled_module_names: %w[resource_management work_package_tracking]) }
|
||||
shared_let(:user) do
|
||||
create(:user, member_with_permissions: { project => %i[view_resource_planners view_work_packages] })
|
||||
end
|
||||
# A project member the current user can see.
|
||||
shared_let(:assignee) do
|
||||
create(:user, firstname: "Sarah", lastname: "Smith", member_with_permissions: { project => %i[view_work_packages] })
|
||||
end
|
||||
# No shared project or group, so invisible to the (non-admin) current user.
|
||||
shared_let(:hidden_user) { create(:user, firstname: "Secret", lastname: "Agent") }
|
||||
shared_let(:work_package) { create(:work_package, project:) }
|
||||
|
||||
let(:path) { project_work_package_resource_allocations_path(project, work_package) }
|
||||
|
||||
before { login_as(user) }
|
||||
|
||||
describe "GET index" do
|
||||
before do
|
||||
create(:resource_allocation, entity: work_package, principal: assignee, allocated_time: 720)
|
||||
create(:resource_allocation, entity: work_package, principal: hidden_user, allocated_time: 300)
|
||||
create(:resource_allocation,
|
||||
entity: work_package, principal_explicit: false, principal: nil, filter_name: "Full stack developer")
|
||||
end
|
||||
|
||||
it "renders the allocations dialog" do
|
||||
get path, as: :turbo_stream
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.body).to include(I18n.t("resource_management.work_package_allocations_dialog.title"))
|
||||
end
|
||||
|
||||
it "names the visible member and the filter allocation" do
|
||||
get path, as: :turbo_stream
|
||||
|
||||
expect(response.body).to include("Sarah Smith")
|
||||
expect(response.body).to include("Full stack developer")
|
||||
end
|
||||
|
||||
it "lists the invisible member anonymously, never revealing the name" do
|
||||
get path, as: :turbo_stream
|
||||
|
||||
expect(response.body).not_to include("Secret Agent")
|
||||
expect(response.body).to include(I18n.t("resource_management.work_package_allocations_dialog.hidden_user"))
|
||||
end
|
||||
end
|
||||
|
||||
describe "authorization" do
|
||||
context "without the view_resource_planners permission" do
|
||||
shared_let(:other_user) do
|
||||
create(:user, member_with_permissions: { project => %i[view_work_packages] })
|
||||
end
|
||||
|
||||
before { login_as(other_user) }
|
||||
|
||||
it "is forbidden" do
|
||||
get path, as: :turbo_stream
|
||||
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
context "when the work package is not visible to the user" do
|
||||
let(:other_project) { create(:project, enabled_module_names: %w[resource_management]) }
|
||||
let(:invisible_work_package) { create(:work_package, project: other_project) }
|
||||
|
||||
it "returns not found" do
|
||||
get project_work_package_resource_allocations_path(project, invisible_work_package), as: :turbo_stream
|
||||
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user