mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
Merge pull request #17569 from opf/feature/59885-cancellation-dialogs-recurring-meetings
[#59885] Cancellation dialogs for one-time and recurring meetings
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
<%#-- 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::OpenProject::DangerConfirmationDialog.new(
|
||||
id:,
|
||||
title:,
|
||||
form_arguments: {
|
||||
action: polymorphic_path([@project, @meeting.becomes(Meeting)]),
|
||||
method: :delete,
|
||||
data: { turbo: true }
|
||||
}
|
||||
)) do |dialog|
|
||||
dialog.with_confirmation_message do |message|
|
||||
message.with_heading(tag: :h2) { heading }
|
||||
message.with_description_content(confirmation_message)
|
||||
end
|
||||
dialog.with_confirmation_check_box_content(I18n.t("text_permanent_delete_confirmation_checkbox_label"))
|
||||
end
|
||||
%>
|
||||
@@ -0,0 +1,73 @@
|
||||
# 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 Meetings
|
||||
class DeleteDialogComponent < ApplicationComponent
|
||||
include ApplicationHelper
|
||||
include OpTurbo::Streamable
|
||||
|
||||
def initialize(meeting:, project:)
|
||||
super
|
||||
|
||||
@meeting = meeting
|
||||
@project = project
|
||||
end
|
||||
|
||||
delegate :recurring_meeting, to: :@meeting
|
||||
|
||||
private
|
||||
|
||||
def id = "delete-meeting-dialog"
|
||||
|
||||
def title
|
||||
if recurring_meeting.present?
|
||||
I18n.t("meeting.delete_dialog.occurrence.title")
|
||||
else
|
||||
I18n.t("meeting.delete_dialog.one_time.title")
|
||||
end
|
||||
end
|
||||
|
||||
def heading
|
||||
if recurring_meeting.present?
|
||||
I18n.t("meeting.delete_dialog.occurrence.heading")
|
||||
else
|
||||
I18n.t("meeting.delete_dialog.one_time.heading")
|
||||
end
|
||||
end
|
||||
|
||||
def confirmation_message
|
||||
if recurring_meeting.present?
|
||||
t("meeting.delete_dialog.occurrence.confirmation_message_html", title: recurring_meeting.title)
|
||||
else
|
||||
t("meeting.delete_dialog.one_time.confirmation_message_html")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -95,9 +95,10 @@
|
||||
|
||||
menu.with_item(label: delete_label,
|
||||
scheme: :danger,
|
||||
href: meeting_path(@meeting),
|
||||
form_arguments: {
|
||||
method: :delete, data: { confirm: t("text_are_you_sure"), turbo: 'false' }
|
||||
href: polymorphic_path([:delete_dialog, @project, @meeting.becomes(Meeting)]),
|
||||
tag: :a,
|
||||
content_arguments: {
|
||||
data: { controller: "async-dialog" }
|
||||
}) do |item|
|
||||
item.with_leading_visual_icon(icon: :trash)
|
||||
end if delete_enabled?
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
module Meetings
|
||||
class RowComponent < ::OpPrimer::BorderBoxRowComponent
|
||||
delegate :current_project, to: :table
|
||||
|
||||
def project_name
|
||||
helpers.link_to_project model.project, {}, {}, false
|
||||
end
|
||||
@@ -140,22 +142,15 @@ module Meetings
|
||||
|
||||
menu.with_item(label: recurring_meeting.present? ? I18n.t(:label_recurring_meeting_delete) : I18n.t(:label_meeting_delete),
|
||||
scheme: :danger,
|
||||
href: meeting_path(model),
|
||||
form_arguments: {
|
||||
method: :delete, data: { confirm: delete_confirm_message, turbo: false }
|
||||
href: polymorphic_path([:delete_dialog, current_project, model.becomes(Meeting)]),
|
||||
tag: :a,
|
||||
content_arguments: {
|
||||
data: { controller: "async-dialog" }
|
||||
}) do |item|
|
||||
item.with_leading_visual_icon(icon: :trash)
|
||||
end
|
||||
end
|
||||
|
||||
def delete_confirm_message
|
||||
if recurring_meeting.present?
|
||||
I18n.t(:label_recurring_meeting_delete_confirmation, name: recurring_meeting.title)
|
||||
else
|
||||
I18n.t("text_are_you_sure")
|
||||
end
|
||||
end
|
||||
|
||||
def recurring_label
|
||||
render(Primer::BaseComponent.new(tag: :span, color: :muted)) do
|
||||
concat render(Primer::Beta::Octicon.new(icon: :iterations, mr: 1, ml: 1))
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<%#-- 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::OpenProject::DangerConfirmationDialog.new(
|
||||
id:,
|
||||
title:,
|
||||
form_arguments: {
|
||||
action: polymorphic_path([@project, @recurring_meeting]),
|
||||
method: :delete,
|
||||
data: { turbo: true }
|
||||
}
|
||||
)) do |dialog|
|
||||
dialog.with_confirmation_message do |message|
|
||||
message.with_heading(tag: :h2) { I18n.t("recurring_meeting.delete_dialog.heading") }
|
||||
message.with_description_content(confirmation_message)
|
||||
end
|
||||
dialog.with_confirmation_check_box_content(I18n.t("text_permanent_delete_confirmation_checkbox_label"))
|
||||
end
|
||||
%>
|
||||
@@ -0,0 +1,55 @@
|
||||
# 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 RecurringMeetings
|
||||
class DeleteDialogComponent < ApplicationComponent
|
||||
include ApplicationHelper
|
||||
include OpTurbo::Streamable
|
||||
|
||||
def initialize(recurring_meeting:, project:)
|
||||
super
|
||||
|
||||
@recurring_meeting = recurring_meeting
|
||||
@project = project
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def id = "delete-recurring-meeting-dialog"
|
||||
|
||||
def title = I18n.t("recurring_meeting.delete_dialog.title")
|
||||
|
||||
def confirmation_message
|
||||
t("recurring_meeting.delete_dialog.confirmation_message_html",
|
||||
title: @recurring_meeting.title,
|
||||
count: @recurring_meeting.remaining_occurrences&.count || 0) # actually ♾️, but we show same message as for 0
|
||||
end
|
||||
end
|
||||
end
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<%#-- 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::OpenProject::DangerConfirmationDialog.new(
|
||||
id:,
|
||||
title:,
|
||||
confirm_button_text:,
|
||||
cancel_button_text:,
|
||||
form_arguments: {
|
||||
action: polymorphic_path(
|
||||
[:destroy_scheduled, @project, @scheduled_meeting.recurring_meeting],
|
||||
start_time: @scheduled_meeting.start_time.iso8601
|
||||
),
|
||||
method: :delete,
|
||||
data: { turbo: true }
|
||||
}
|
||||
)) do |dialog|
|
||||
dialog.with_confirmation_message do |message|
|
||||
message.with_heading(tag: :h2) { I18n.t("recurring_meeting.scheduled_delete_dialog.heading") }
|
||||
message.with_description_content(confirmation_message)
|
||||
end
|
||||
dialog.with_confirmation_check_box_content(I18n.t("text_permanent_delete_confirmation_checkbox_label"))
|
||||
end
|
||||
%>
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
# 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 RecurringMeetings
|
||||
class DeleteScheduledDialogComponent < ApplicationComponent
|
||||
include ApplicationHelper
|
||||
include OpTurbo::Streamable
|
||||
|
||||
def initialize(scheduled_meeting:, project:)
|
||||
super
|
||||
|
||||
@scheduled_meeting = scheduled_meeting
|
||||
@project = project
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def id = "delete-scheduled-recurring-meeting-dialog"
|
||||
|
||||
def title = I18n.t("recurring_meeting.scheduled_delete_dialog.title")
|
||||
|
||||
def confirmation_message = t("recurring_meeting.scheduled_delete_dialog.confirmation_message_html")
|
||||
|
||||
def confirm_button_text = I18n.t("recurring_meeting.scheduled_delete_dialog.confirm_button")
|
||||
|
||||
def cancel_button_text = I18n.t(:button_close)
|
||||
end
|
||||
end
|
||||
+1
-1
@@ -31,7 +31,7 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
render(Primer::OpenProject::DangerConfirmationDialog.new(
|
||||
id: "recurring-meetings-end-series-dialog",
|
||||
confirm_button_text: I18n.t(:label_recurring_meeting_series_end_now),
|
||||
title: I18n.t(:text_are_you_sure),
|
||||
title: I18n.t("recurring_meeting.end_series_dialog.title"),
|
||||
form_arguments: {
|
||||
action: end_series_recurring_meeting_path(@series),
|
||||
method: :post
|
||||
|
||||
@@ -177,9 +177,10 @@ module RecurringMeetings
|
||||
menu.with_item(
|
||||
label: past? ? I18n.t(:label_recurring_meeting_delete) : I18n.t(:label_recurring_meeting_cancel),
|
||||
scheme: :danger,
|
||||
href: current_project_meeting_path(meeting),
|
||||
form_arguments: {
|
||||
method: :delete, data: { confirm: I18n.t(:label_recurring_occurrence_delete_confirmation), turbo: false }
|
||||
href: polymorphic_path([:delete_dialog, current_project, meeting.becomes(Meeting)]),
|
||||
tag: :a,
|
||||
content_arguments: {
|
||||
data: { controller: "async-dialog" }
|
||||
}
|
||||
) do |item|
|
||||
item.with_leading_visual_icon(icon: :trash)
|
||||
@@ -192,9 +193,11 @@ module RecurringMeetings
|
||||
menu.with_item(
|
||||
label: I18n.t(:label_recurring_meeting_cancel),
|
||||
scheme: :danger,
|
||||
href: delete_scheduled_recurring_meeting_path(model.recurring_meeting.id, start_time: model.start_time.iso8601),
|
||||
form_arguments: {
|
||||
method: :post, data: { confirm: I18n.t("text_are_you_sure"), turbo: false }
|
||||
href: polymorphic_path([:delete_scheduled_dialog, current_project, model.recurring_meeting],
|
||||
start_time: model.start_time.iso8601),
|
||||
tag: :a,
|
||||
content_arguments: {
|
||||
data: { controller: "async-dialog" }
|
||||
}
|
||||
) do |item|
|
||||
item.with_leading_visual_icon(icon: :trash)
|
||||
|
||||
+4
-3
@@ -61,10 +61,11 @@
|
||||
|
||||
menu.with_item(
|
||||
label: I18n.t(:label_recurring_meeting_series_delete),
|
||||
href: polymorphic_path([@project, @meeting]),
|
||||
href: polymorphic_path([:delete_dialog, @project, @meeting]),
|
||||
scheme: :danger,
|
||||
form_arguments: {
|
||||
method: :delete, data: { confirm: t("text_are_you_sure"), turbo: 'false' }
|
||||
tag: :a,
|
||||
content_arguments: {
|
||||
data: { controller: 'async-dialog' }
|
||||
}
|
||||
) do |item|
|
||||
item.with_leading_visual_icon(icon: :trash)
|
||||
|
||||
@@ -27,12 +27,13 @@
|
||||
#++
|
||||
|
||||
class MeetingsController < ApplicationController
|
||||
before_action :load_and_authorize_in_optional_project, only: %i[index new new_dialog show create history]
|
||||
before_action :load_and_authorize_in_optional_project, only: %i[index new new_dialog show create delete_dialog destroy]
|
||||
before_action :verify_activities_module_activated, only: %i[history]
|
||||
before_action :determine_date_range, only: %i[history]
|
||||
before_action :determine_author, only: %i[history]
|
||||
before_action :build_meeting, only: %i[new new_dialog]
|
||||
before_action :find_meeting, except: %i[index new create new_dialog]
|
||||
before_action :set_project, only: %i[copy history update update_participants]
|
||||
before_action :set_activity, only: %i[history]
|
||||
before_action :find_copy_from_meeting, only: %i[create]
|
||||
before_action :convert_params, only: %i[create update update_participants]
|
||||
@@ -78,8 +79,9 @@ class MeetingsController < ApplicationController
|
||||
else
|
||||
render(Meetings::ShowComponent.new(meeting: @meeting, project: @project), layout: true)
|
||||
end
|
||||
elsif @meeting.agenda.present? && @meeting.agenda.locked?
|
||||
params[:tab] ||= "minutes"
|
||||
else
|
||||
@project = @meeting.project
|
||||
params[:tab] ||= "minutes" if @meeting.agenda.present? && @meeting.agenda.locked?
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -177,6 +179,13 @@ class MeetingsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def delete_dialog
|
||||
respond_with_dialog Meetings::DeleteDialogComponent.new(
|
||||
meeting: @meeting,
|
||||
project: @project
|
||||
)
|
||||
end
|
||||
|
||||
def destroy # rubocop:disable Metrics/AbcSize
|
||||
recurring = @meeting.recurring_meeting
|
||||
|
||||
@@ -203,6 +212,7 @@ class MeetingsController < ApplicationController
|
||||
render turbo_stream: @turbo_streams
|
||||
end
|
||||
format.html do
|
||||
@project = @meeting.project
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
@@ -418,11 +428,14 @@ class MeetingsController < ApplicationController
|
||||
@meeting = Meeting
|
||||
.includes([:project, :author, { participants: :user }, :agenda, :minutes])
|
||||
.find(params[:id])
|
||||
@project = @meeting.project
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
def set_project
|
||||
@project = @meeting.project
|
||||
end
|
||||
|
||||
def convert_params # rubocop:disable Metrics/AbcSize
|
||||
# We do some preprocessing of `meeting_params` that we will store in this
|
||||
# instance variable.
|
||||
|
||||
@@ -9,13 +9,15 @@ class RecurringMeetingsController < ApplicationController
|
||||
include OpTurbo::DialogStreamHelper
|
||||
|
||||
before_action :find_meeting,
|
||||
only: %i[show update details_dialog destroy edit init
|
||||
delete_scheduled template_completed download_ics notify end_series end_series_dialog]
|
||||
only: %i[show update details_dialog delete_dialog destroy edit init
|
||||
delete_scheduled_dialog destroy_scheduled template_completed download_ics notify end_series
|
||||
end_series_dialog]
|
||||
before_action :find_optional_project,
|
||||
only: %i[index show new create update details_dialog destroy edit delete_scheduled notify]
|
||||
only: %i[index show new create update details_dialog delete_dialog destroy edit delete_scheduled_dialog
|
||||
destroy_scheduled notify]
|
||||
before_action :authorize_global, only: %i[index new create]
|
||||
before_action :authorize, except: %i[index new create]
|
||||
before_action :get_scheduled_meeting, only: %i[delete_scheduled]
|
||||
before_action :get_scheduled_meeting, only: %i[delete_scheduled_dialog destroy_scheduled]
|
||||
|
||||
before_action :convert_params, only: %i[create update]
|
||||
before_action :check_template_completable, only: %i[template_completed]
|
||||
@@ -158,6 +160,13 @@ class RecurringMeetingsController < ApplicationController
|
||||
redirect_to action: :show
|
||||
end
|
||||
|
||||
def delete_dialog
|
||||
respond_with_dialog RecurringMeetings::DeleteDialogComponent.new(
|
||||
recurring_meeting: @recurring_meeting,
|
||||
project: @project
|
||||
)
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @recurring_meeting.destroy
|
||||
flash[:notice] = I18n.t(:notice_successful_delete)
|
||||
@@ -189,8 +198,15 @@ class RecurringMeetingsController < ApplicationController
|
||||
redirect_to action: :show, id: @recurring_meeting, status: :see_other
|
||||
end
|
||||
|
||||
def delete_scheduled
|
||||
if @scheduled.update(cancelled: true)
|
||||
def delete_scheduled_dialog
|
||||
respond_with_dialog RecurringMeetings::DeleteScheduledDialogComponent.new(
|
||||
scheduled_meeting: @scheduled_meeting,
|
||||
project: @project
|
||||
)
|
||||
end
|
||||
|
||||
def destroy_scheduled
|
||||
if @scheduled_meeting.update(cancelled: true)
|
||||
flash[:notice] = I18n.t(:notice_successful_cancel)
|
||||
else
|
||||
flash[:error] = I18n.t(:error_failed_to_delete_entry)
|
||||
@@ -274,9 +290,9 @@ class RecurringMeetingsController < ApplicationController
|
||||
end
|
||||
|
||||
def get_scheduled_meeting
|
||||
@scheduled = @recurring_meeting.scheduled_meetings.find_or_initialize_by(start_time: params[:start_time])
|
||||
@scheduled_meeting = @recurring_meeting.scheduled_meetings.find_or_initialize_by(start_time: params[:start_time])
|
||||
|
||||
render_400 unless @scheduled.meeting_id.nil?
|
||||
render_400 unless @scheduled_meeting.meeting_id.nil?
|
||||
end
|
||||
|
||||
def find_optional_project
|
||||
|
||||
@@ -33,9 +33,6 @@ class Meeting::ProjectAutocompleter < ApplicationForm
|
||||
id: "project_id",
|
||||
label: Project.model_name.human,
|
||||
required: true,
|
||||
data: {
|
||||
"test-selector": "project_id"
|
||||
},
|
||||
autocomplete_options: {
|
||||
with_search_icon: true,
|
||||
openDirectly: false,
|
||||
@@ -44,7 +41,10 @@ class Meeting::ProjectAutocompleter < ApplicationForm
|
||||
inputName: "project_id",
|
||||
inputValue: @project&.id,
|
||||
appendTo: "#new-meeting-dialog",
|
||||
filters: [{ name: "user_action", operator: "=", values: ["meetings/create"] }]
|
||||
filters: [{ name: "user_action", operator: "=", values: ["meetings/create"] }],
|
||||
data: {
|
||||
"test-selector": "project_id"
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
@@ -82,7 +82,7 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
<% if authorize_for(:meetings, :destroy) %>
|
||||
<li>
|
||||
<%= link_to(t(:button_delete),
|
||||
meeting_path(@meeting),
|
||||
polymorphic_path([@project, @meeting]),
|
||||
class: 'icon-context icon-delete',
|
||||
method: :delete,
|
||||
data: { confirm: t(:text_are_you_sure) }) %>
|
||||
|
||||
@@ -136,13 +136,6 @@ en:
|
||||
label_recurring_meeting_copy: "Copy as one-off"
|
||||
label_recurring_meeting_cancel: "Cancel this occurrence"
|
||||
label_recurring_meeting_delete: "Delete occurrence"
|
||||
label_recurring_meeting_delete_confirmation: >
|
||||
This meeting is part of a series called %{name}.
|
||||
This will only delete this particular occurrence and not the entire series.
|
||||
Do you want to continue?
|
||||
label_recurring_occurrence_delete_confirmation: >
|
||||
Any meeting information not in the template will be lost.
|
||||
Do you want to continue?
|
||||
label_recurring_meeting_restore: "Restore this occurrence"
|
||||
label_recurring_meeting_schedule: "Schedule"
|
||||
label_recurring_meeting_next_occurrence: "Next occurrence"
|
||||
@@ -225,6 +218,19 @@ en:
|
||||
structured_text: "Organize your meeting as a dynamic list of agenda items, optionally linking them to a work package."
|
||||
structured_text_copy: "Copying a meeting will currently not copy the associated meeting agenda items, just the details"
|
||||
copied: "Copied from Meeting #%{id}"
|
||||
delete_dialog:
|
||||
one_time:
|
||||
title: "Delete meeting"
|
||||
heading: "Delete this meeting?"
|
||||
confirmation_message_html: >
|
||||
This action is not reversible. Please proceed with caution.
|
||||
occurrence:
|
||||
title: "Delete meeting occurrence"
|
||||
heading: "Delete this meeting occurrence?"
|
||||
confirmation_message_html: >
|
||||
This meeting is part of a series called <strong>%{title}</strong>.
|
||||
This will only delete this particular occurrence and not the entire series.
|
||||
Do you want to continue?
|
||||
|
||||
meeting_section:
|
||||
untitled_title: "Untitled section"
|
||||
@@ -284,6 +290,30 @@ en:
|
||||
The following meetings are planned in the recurring meeting schedule but are not open yet.
|
||||
Every time a planned meeting starts, the next one will automatically be opened for you.
|
||||
You can also open planned meetings manually to import the template and start editing the agenda.
|
||||
delete_dialog:
|
||||
title: "Delete meeting series"
|
||||
heading: "Permanently delete this meeting series?"
|
||||
confirmation_message_html:
|
||||
zero: >
|
||||
Deleting <strong>%{title}</strong> will delete any meetings in this series.
|
||||
This action is not reversible. Please proceed with caution.
|
||||
one: >
|
||||
Deleting <strong>%{title}</strong> will also delete one meeting in this series.
|
||||
This action is not reversible. Please proceed with caution.
|
||||
other: >
|
||||
Deleting <strong>%{title}</strong> will delete all %{count} meetings in this series.
|
||||
This action is not reversible. Please proceed with caution.
|
||||
|
||||
scheduled_delete_dialog:
|
||||
title: "Cancel meeting occurrence"
|
||||
heading: "Cancel this meeting occurrence?"
|
||||
confirmation_message_html: >
|
||||
Any meeting information not in the template will be lost.
|
||||
|
||||
Do you want to continue?
|
||||
confirm_button: "Cancel occurrence"
|
||||
end_series_dialog:
|
||||
title: "End meeting series"
|
||||
|
||||
notice_successful_notification: "Notification sent successfully"
|
||||
notice_timezone_missing: No time zone is set and %{zone} is assumed. To choose your time zone, please click here.
|
||||
|
||||
@@ -28,12 +28,21 @@
|
||||
|
||||
Rails.application.routes.draw do
|
||||
resources :projects, only: %i[] do
|
||||
resources :meetings, only: %i[index new create show] do
|
||||
resources :meetings, only: %i[index new create show destroy] do
|
||||
collection do
|
||||
get "menu" => "meetings/menus#show"
|
||||
end
|
||||
member do
|
||||
get :delete_dialog
|
||||
end
|
||||
end
|
||||
resources :recurring_meetings, only: %i[index new create show destroy] do
|
||||
member do
|
||||
get :delete_dialog
|
||||
get :delete_scheduled_dialog
|
||||
delete :destroy_scheduled
|
||||
end
|
||||
end
|
||||
resources :recurring_meetings, only: %i[index new create show destroy]
|
||||
end
|
||||
|
||||
resources :work_packages, only: %i[] do
|
||||
@@ -60,8 +69,10 @@ Rails.application.routes.draw do
|
||||
member do
|
||||
get :details_dialog
|
||||
get :download_ics
|
||||
get :delete_dialog
|
||||
get :delete_scheduled_dialog
|
||||
post :init
|
||||
post :delete_scheduled
|
||||
delete :destroy_scheduled
|
||||
post :template_completed
|
||||
post :notify
|
||||
post :end_series
|
||||
@@ -86,6 +97,7 @@ Rails.application.routes.draw do
|
||||
put :change_state
|
||||
post :notify
|
||||
get :history
|
||||
get :delete_dialog
|
||||
end
|
||||
resources :agenda_items, controller: "meeting_agenda_items" do
|
||||
collection do
|
||||
|
||||
@@ -70,8 +70,8 @@ module OpenProject::Meeting
|
||||
require: :member
|
||||
permission :delete_meetings,
|
||||
{
|
||||
meetings: [:destroy],
|
||||
recurring_meetings: %i[destroy delete_scheduled]
|
||||
meetings: %i[delete_dialog destroy],
|
||||
recurring_meetings: %i[delete_dialog destroy delete_scheduled_dialog destroy_scheduled]
|
||||
},
|
||||
permissible_on: :project,
|
||||
require: :member
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# 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 Meetings::DeleteDialogComponent, type: :component do
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
let(:project) { build_stubbed(:project) }
|
||||
let(:user) { build_stubbed(:user) }
|
||||
|
||||
subject do
|
||||
render_inline(described_class.new(meeting:, project:))
|
||||
page
|
||||
end
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
describe "dialog form" do
|
||||
let(:meeting) { build_stubbed(:meeting, project:) }
|
||||
|
||||
context "without a current project" do
|
||||
let(:project) { nil }
|
||||
|
||||
it "renders the correct form action" do
|
||||
expect(subject).to have_element "form", action: meeting_path(meeting)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a current project" do
|
||||
let(:project) { build_stubbed(:project) }
|
||||
|
||||
it "renders the correct form action" do
|
||||
expect(subject).to have_element "form", action: project_meeting_path(project, meeting)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "with a one-off meeting" do
|
||||
let(:meeting) { build_stubbed(:meeting, project:) }
|
||||
|
||||
it "shows a heading" do
|
||||
expect(subject).to have_text "Delete this meeting?"
|
||||
end
|
||||
|
||||
it "shows a simple confirmation message" do
|
||||
expect(subject).to have_text "This action is not reversible. Please proceed with caution."
|
||||
end
|
||||
end
|
||||
|
||||
context "with an associated recurring/templated meeting" do
|
||||
let(:series) { build_stubbed(:recurring_meeting) }
|
||||
let(:meeting) { build_stubbed(:structured_meeting_template, recurring_meeting: series) }
|
||||
|
||||
it "shows a heading" do
|
||||
expect(subject).to have_text "Delete this meeting occurrence?"
|
||||
end
|
||||
|
||||
it "shows a message that the meeting is part of a series" do
|
||||
expect(subject).to have_text "meeting is part of a series"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,134 @@
|
||||
# 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 Meetings::RowComponent, type: :component do
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
let(:project) { build_stubbed(:project) }
|
||||
let(:table) do
|
||||
instance_double(Meetings::TableComponent, columns: [], grid_class: "test", has_actions?: true, current_project:)
|
||||
end
|
||||
let(:current_project) { nil }
|
||||
let(:user) { build_stubbed(:user) }
|
||||
|
||||
subject do
|
||||
render_inline(described_class.new(row: meeting, table:))
|
||||
page
|
||||
end
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
describe "actions" do
|
||||
context "with default permissions" do
|
||||
context "with a one-off meeting" do
|
||||
let(:meeting) { build_stubbed(:meeting, project:) }
|
||||
|
||||
it "shows default menu items" do
|
||||
expect(subject).to have_link "Download iCalendar event"
|
||||
end
|
||||
end
|
||||
|
||||
context "with an associated recurring/templated meeting" do
|
||||
let(:series) { build_stubbed(:recurring_meeting, project:) }
|
||||
let(:meeting) { build_stubbed(:structured_meeting_template, recurring_meeting: series, project:) }
|
||||
|
||||
it "shows default menu items" do
|
||||
expect(subject).to have_link "View meeting series"
|
||||
expect(subject).to have_link "Download iCalendar event"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with project delete meetings permissions" do
|
||||
before do
|
||||
mock_permissions_for(user) do |mock|
|
||||
mock.allow_in_project(:delete_meetings, project:)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a one-off meeting" do
|
||||
let(:meeting) { build_stubbed(:meeting, project:) }
|
||||
|
||||
context "without a current project" do
|
||||
it "shows delete menu item" do
|
||||
expect(subject).to have_link "Delete meeting", href: delete_dialog_meeting_path(meeting)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a current project" do
|
||||
let(:current_project) { project }
|
||||
|
||||
it "shows delete menu item" do
|
||||
expect(subject).to have_link "Delete meeting", href: delete_dialog_project_meeting_path(project, meeting)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with an associated recurring/templated meeting" do
|
||||
let(:series) { build_stubbed(:recurring_meeting, project:) }
|
||||
let(:meeting) { build_stubbed(:structured_meeting_template, recurring_meeting: series, project:) }
|
||||
|
||||
context "without a current project" do
|
||||
it "shows delete menu item" do
|
||||
expect(subject).to have_link "Delete occurrence", href: delete_dialog_meeting_path(meeting)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a current project" do
|
||||
let(:current_project) { project }
|
||||
|
||||
it "shows delete menu item" do
|
||||
expect(subject).to have_link "Delete occurrence", href: delete_dialog_project_meeting_path(project, meeting)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with project create meetings permissions" do
|
||||
before do
|
||||
mock_permissions_for(user) do |mock|
|
||||
mock.allow_in_project(:create_meetings, project:)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a one-off meeting" do
|
||||
let(:meeting) { build_stubbed(:meeting, project:) }
|
||||
|
||||
it "shows copy menu item" do
|
||||
expect(subject).to have_link "Copy meeting"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,93 @@
|
||||
# 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 RecurringMeetings::DeleteDialogComponent, type: :component do
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
let(:project) { build_stubbed(:project) }
|
||||
let(:recurring_meeting) { build_stubbed(:recurring_meeting, project:, end_after: :iterations, iterations: 6) }
|
||||
let(:meeting) { build_stubbed(:structured_meeting_template, recurring_meeting:) }
|
||||
let(:user) { build_stubbed(:user) }
|
||||
|
||||
subject do
|
||||
render_inline(described_class.new(recurring_meeting:, project:))
|
||||
page
|
||||
end
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
describe "dialog form" do
|
||||
context "without a current project" do
|
||||
let(:project) { nil }
|
||||
|
||||
it "renders the correct form action" do
|
||||
expect(subject).to have_element "form", action: recurring_meeting_path(recurring_meeting)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a current project" do
|
||||
let(:project) { build_stubbed(:project) }
|
||||
|
||||
it "renders the correct form action" do
|
||||
expect(subject).to have_element "form", action: project_recurring_meeting_path(project, recurring_meeting)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "shows a heading" do
|
||||
expect(subject).to have_text "Permanently delete this meeting series?"
|
||||
end
|
||||
|
||||
context "with a meeting series that ends - with several remaining meetings" do
|
||||
it "shows a confirmation message with a count of the remaining meetings" do
|
||||
expect(subject).to have_text "will delete all 6 meetings in this series"
|
||||
end
|
||||
end
|
||||
|
||||
context "with a meeting series that ends - with one remaining meeting" do
|
||||
let(:recurring_meeting) { build_stubbed(:recurring_meeting, project:, end_after: :iterations, iterations: 1) }
|
||||
|
||||
it "shows a confirmation message mentioning one remaining meeting" do
|
||||
expect(subject).to have_text "will also delete one meeting in this series"
|
||||
end
|
||||
end
|
||||
|
||||
context "with a meeting series that never ends" do
|
||||
let(:recurring_meeting) { build_stubbed(:recurring_meeting, project:, end_after: :never) }
|
||||
|
||||
it "shows a confirmation message without a count" do
|
||||
expect(subject).to have_text "will delete any meetings in this series"
|
||||
end
|
||||
end
|
||||
end
|
||||
+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 RecurringMeetings::DeleteScheduledDialogComponent, type: :component do
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
let(:project) { build_stubbed(:project) }
|
||||
let(:recurring_meeting) { build_stubbed(:recurring_meeting, project:, end_after: :iterations, iterations: 6) }
|
||||
let(:start_time) { 1.day.from_now }
|
||||
let(:scheduled_meeting) { recurring_meeting.scheduled_meetings.find_or_initialize_by(start_time: start_time) }
|
||||
let(:meeting) { build_stubbed(:structured_meeting_template, recurring_meeting:) }
|
||||
let(:user) { build_stubbed(:user) }
|
||||
|
||||
subject do
|
||||
render_inline(described_class.new(scheduled_meeting:, project:))
|
||||
page
|
||||
end
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
describe "dialog form" do
|
||||
context "without a current project" do
|
||||
let(:project) { nil }
|
||||
|
||||
it "renders the correct form action" do
|
||||
expect(subject).to have_element "form", action: destroy_scheduled_recurring_meeting_path(
|
||||
recurring_meeting, start_time: start_time.iso8601
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a current project" do
|
||||
let(:project) { build_stubbed(:project) }
|
||||
|
||||
it "renders the correct form action" do
|
||||
expect(subject).to have_element "form", action: destroy_scheduled_project_recurring_meeting_path(
|
||||
project, recurring_meeting, start_time: start_time.iso8601
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "shows a heading" do
|
||||
expect(subject).to have_text "Cancel this meeting occurrence?"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,108 @@
|
||||
# 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 RecurringMeetings::RowComponent, type: :component do
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
let(:project) { build_stubbed(:project) }
|
||||
let(:table) do
|
||||
instance_double(RecurringMeetings::TableComponent,
|
||||
columns: [], grid_class: "test", has_actions?: true, current_project:)
|
||||
end
|
||||
let(:recurring_meeting) { build_stubbed(:recurring_meeting, project:) }
|
||||
let(:current_project) { nil }
|
||||
let(:user) { build_stubbed(:user) }
|
||||
|
||||
subject do
|
||||
render_inline(described_class.new(row: scheduled_meeting, table:))
|
||||
page
|
||||
end
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
describe "actions" do
|
||||
context "with project delete meetings permissions" do
|
||||
before do
|
||||
mock_permissions_for(user) do |mock|
|
||||
mock.allow_in_project(:delete_meetings, project:)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a scheduled meeting" do
|
||||
let(:scheduled_meeting) { build_stubbed(:scheduled_meeting, :scheduled, recurring_meeting:) }
|
||||
|
||||
context "without a current project" do
|
||||
it "shows cancel menu item" do
|
||||
expect(subject).to have_link "Cancel this occurrence",
|
||||
href: delete_scheduled_dialog_recurring_meeting_path(
|
||||
recurring_meeting, start_time: scheduled_meeting.start_time.iso8601
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a current project" do
|
||||
let(:current_project) { project }
|
||||
|
||||
it "shows cancel menu item" do
|
||||
expect(subject).to have_link "Cancel this occurrence",
|
||||
href: delete_scheduled_dialog_project_recurring_meeting_path(
|
||||
project, recurring_meeting, start_time: scheduled_meeting.start_time.iso8601
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with an instantiated meeting" do
|
||||
let(:scheduled_meeting) { build_stubbed(:scheduled_meeting, recurring_meeting:, meeting:) }
|
||||
let(:meeting) { build_stubbed(:meeting) }
|
||||
|
||||
context "without a current project" do
|
||||
it "shows cancel menu item" do
|
||||
expect(subject).to have_link "Cancel this occurrence",
|
||||
href: delete_dialog_meeting_path(scheduled_meeting.meeting)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a current project" do
|
||||
let(:current_project) { project }
|
||||
|
||||
it "shows cancel menu item" do
|
||||
expect(subject).to have_link "Cancel this occurrence",
|
||||
href: delete_dialog_project_meeting_path(project, scheduled_meeting.meeting)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -73,7 +73,7 @@ RSpec.describe "Recurring meetings CRUD",
|
||||
end
|
||||
|
||||
let(:current_user) { user }
|
||||
let(:show_page) { Pages::RecurringMeeting::Show.new(meeting) }
|
||||
let(:show_page) { Pages::RecurringMeeting::Show.new(meeting, project:) }
|
||||
let(:meetings_page) { Pages::Meetings::Index.new(project:) }
|
||||
|
||||
before do
|
||||
@@ -87,13 +87,17 @@ RSpec.describe "Recurring meetings CRUD",
|
||||
it "can delete a recurring meeting from the show page and return to the index page" do
|
||||
show_page.visit!
|
||||
|
||||
click_on "recurring-meeting-action-menu"
|
||||
show_page.delete_meeting_series
|
||||
show_page.within_modal "Delete meeting series" do
|
||||
check "I understand that this deletion cannot be reversed", allow_label_click: true
|
||||
|
||||
accept_confirm(I18n.t("text_are_you_sure")) do
|
||||
click_on "Delete meeting series"
|
||||
click_on "Delete permanently"
|
||||
end
|
||||
|
||||
expect(page).to have_current_path meetings_path # check path
|
||||
expect(page).to have_current_path project_meetings_path(project)
|
||||
|
||||
expect_flash(type: :success, message: "Successful deletion.")
|
||||
show_page.expect_no_meeting date: "12/31/2024 01:30 PM"
|
||||
end
|
||||
|
||||
it "can use the 'Create from template' button" do
|
||||
@@ -110,28 +114,48 @@ RSpec.describe "Recurring meetings CRUD",
|
||||
show_page.expect_open_meeting date: "01/07/2025 01:30 PM"
|
||||
end
|
||||
|
||||
it "can cancel an occurrence" do
|
||||
it "can cancel an occurrence from the show page" do
|
||||
show_page.visit!
|
||||
|
||||
accept_confirm(I18n.t(:label_recurring_occurrence_delete_confirmation)) do
|
||||
show_page.cancel_occurrence date: "12/31/2024 01:30 PM"
|
||||
show_page.cancel_occurrence date: "12/31/2024 01:30 PM"
|
||||
show_page.within_modal "Delete meeting occurrence" do
|
||||
check "I understand that this deletion cannot be reversed", allow_label_click: true
|
||||
|
||||
click_on "Delete permanently"
|
||||
end
|
||||
|
||||
expect_flash(type: :success, message: "Successful cancellation.")
|
||||
|
||||
expect(page).to have_current_path(show_page.project_path)
|
||||
expect(page).to have_current_path(show_page.path)
|
||||
|
||||
show_page.expect_no_open_meeting date: "12/31/2024 01:30 PM"
|
||||
show_page.expect_cancelled_meeting date: "12/31/2024 01:30 PM"
|
||||
end
|
||||
|
||||
it "can cancel a scheduled occurrence from the show page" do
|
||||
show_page.visit!
|
||||
|
||||
show_page.cancel_scheduled_occurrence date: "01/07/2025 01:30 PM"
|
||||
show_page.within_modal "Cancel meeting occurrence" do
|
||||
check "I understand that this deletion cannot be reversed", allow_label_click: true
|
||||
|
||||
click_on "Cancel occurrence"
|
||||
end
|
||||
|
||||
expect_flash(type: :success, message: "Successful cancellation.")
|
||||
|
||||
expect(page).to have_current_path(show_page.path)
|
||||
|
||||
show_page.expect_cancelled_meeting date: "01/07/2025 01:30 PM"
|
||||
end
|
||||
|
||||
it "can edit the details of a recurring meeting" do
|
||||
show_page.visit!
|
||||
|
||||
show_page.expect_subtitle text: "Every week on Tuesday at 01:30 PM, ends on 01/14/2025"
|
||||
|
||||
show_page.edit_meeting_series
|
||||
show_page.in_edit_dialog do
|
||||
show_page.within_modal "Edit Meeting" do
|
||||
page.select("Daily", from: "Frequency")
|
||||
meetings_page.set_start_time "11:00"
|
||||
page.select("a number of occurrences", from: "Meeting series ends")
|
||||
@@ -153,11 +177,17 @@ RSpec.describe "Recurring meetings CRUD",
|
||||
show_page.expect_scheduled_meeting date: "01/07/2025 01:30 PM"
|
||||
show_page.expect_scheduled_actions date: "01/07/2025 01:30 PM"
|
||||
|
||||
accept_confirm(I18n.t(:label_recurring_occurrence_delete_confirmation)) do
|
||||
show_page.cancel_occurrence date: "12/31/2024 01:30 PM"
|
||||
show_page.cancel_occurrence date: "12/31/2024 01:30 PM"
|
||||
show_page.within_modal "Delete meeting occurrence" do
|
||||
check "I understand that this deletion cannot be reversed", allow_label_click: true
|
||||
|
||||
click_on "Delete permanently"
|
||||
end
|
||||
|
||||
wait_for_network_idle
|
||||
expect_flash(type: :success, message: "Successful cancellation.")
|
||||
|
||||
expect(page).to have_current_path(show_page.path)
|
||||
|
||||
show_page.expect_cancelled_meeting date: "12/31/2024 01:30 PM"
|
||||
show_page.expect_cancelled_actions date: "12/31/2024 01:30 PM"
|
||||
end
|
||||
|
||||
+9
-9
@@ -75,18 +75,18 @@ RSpec.describe "Recurring meetings end series", :js do
|
||||
it "can end the meeting early" do
|
||||
show_page.visit!
|
||||
|
||||
page.find_test_selector("recurring-meeting-action-menu").click
|
||||
click_on "End meeting series"
|
||||
expect(page).to have_css("#recurring-meetings-end-series-dialog")
|
||||
expect(page).to have_text("Ending the series will delete any future open or scheduled meeting occurrences")
|
||||
show_page.end_meeting_series
|
||||
show_page.within_modal "End meeting series" do
|
||||
expect(page).to have_text("Ending the series will delete any future open or scheduled meeting occurrences")
|
||||
|
||||
retry_block do
|
||||
check "I understand that this deletion cannot be reversed"
|
||||
expect(page).to have_checked_field("I understand that this deletion cannot be reversed")
|
||||
retry_block do
|
||||
check "I understand that this deletion cannot be reversed", allow_label_click: true
|
||||
expect(page).to have_checked_field("I understand that this deletion cannot be reversed")
|
||||
end
|
||||
|
||||
click_on "End series now"
|
||||
end
|
||||
|
||||
click_on "End series now"
|
||||
|
||||
expect(page).to have_current_path recurring_meeting_path(meeting)
|
||||
expect(page).to have_text("Nothing to display")
|
||||
end
|
||||
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
# 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"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/recurring_meeting/show"
|
||||
require_relative "../../support/pages/meetings/index"
|
||||
|
||||
RSpec.describe "Recurring meetings global CRUD", :js do
|
||||
include Components::Autocompleter::NgSelectAutocompleteHelpers
|
||||
|
||||
before_all do
|
||||
travel_to(Date.new(2024, 12, 1))
|
||||
end
|
||||
|
||||
after(:all) do # rubocop:disable RSpec/BeforeAfterAll
|
||||
travel_back
|
||||
end
|
||||
|
||||
shared_let(:project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
shared_let(:user) do
|
||||
create :user,
|
||||
lastname: "First",
|
||||
preferences: { time_zone: "Etc/UTC" },
|
||||
member_with_permissions: { project => %i[view_meetings create_meetings edit_meetings delete_meetings] }
|
||||
end
|
||||
shared_let(:other_user) do
|
||||
create(:user,
|
||||
lastname: "Second",
|
||||
member_with_permissions: { project => %i[view_meetings] })
|
||||
end
|
||||
shared_let(:no_member_user) do
|
||||
create(:user,
|
||||
lastname: "Third")
|
||||
end
|
||||
shared_let(:meeting) do
|
||||
create :recurring_meeting,
|
||||
project:,
|
||||
start_time: "2024-12-31T13:30:00Z",
|
||||
duration: 1.5,
|
||||
frequency: "weekly",
|
||||
end_after: "specific_date",
|
||||
end_date: "2025-01-15",
|
||||
author: user
|
||||
end
|
||||
|
||||
let(:current_user) { user }
|
||||
let(:show_page) { Pages::RecurringMeeting::Show.new(meeting, project: nil) }
|
||||
let(:meetings_page) { Pages::Meetings::Index.new(project: nil) }
|
||||
|
||||
before do
|
||||
travel_to(Date.new(2024, 12, 1))
|
||||
login_as current_user
|
||||
|
||||
# Assuming the first init job has run
|
||||
RecurringMeetings::InitNextOccurrenceJob.perform_now(meeting, meeting.first_occurrence.to_time)
|
||||
end
|
||||
|
||||
it "can delete a recurring meeting from the show page and return to the index page" do
|
||||
show_page.visit!
|
||||
|
||||
show_page.delete_meeting_series
|
||||
show_page.within_modal "Delete meeting series" do
|
||||
check "I understand that this deletion cannot be reversed", allow_label_click: true
|
||||
|
||||
click_on "Delete permanently"
|
||||
end
|
||||
|
||||
expect(page).to have_current_path meetings_path
|
||||
|
||||
expect_flash(type: :success, message: "Successful deletion.")
|
||||
show_page.expect_no_meeting date: "12/31/2024 01:30 PM"
|
||||
end
|
||||
|
||||
it "can cancel an occurrence from the show page" do
|
||||
show_page.visit!
|
||||
|
||||
show_page.cancel_occurrence date: "12/31/2024 01:30 PM"
|
||||
show_page.within_modal "Delete meeting occurrence" do
|
||||
check "I understand that this deletion cannot be reversed", allow_label_click: true
|
||||
|
||||
click_on "Delete permanently"
|
||||
end
|
||||
|
||||
expect_flash(type: :success, message: "Successful cancellation.")
|
||||
|
||||
expect(page).to have_current_path(show_page.path)
|
||||
|
||||
show_page.expect_no_open_meeting date: "12/31/2024 01:30 PM"
|
||||
show_page.expect_cancelled_meeting date: "12/31/2024 01:30 PM"
|
||||
end
|
||||
|
||||
it "can cancel a scheduled occurrence from the show page" do
|
||||
show_page.visit!
|
||||
|
||||
show_page.cancel_scheduled_occurrence date: "01/07/2025 01:30 PM"
|
||||
show_page.within_modal "Cancel meeting occurrence" do
|
||||
check "I understand that this deletion cannot be reversed", allow_label_click: true
|
||||
|
||||
click_on "Cancel occurrence"
|
||||
end
|
||||
|
||||
expect_flash(type: :success, message: "Successful cancellation.")
|
||||
|
||||
expect(page).to have_current_path(show_page.path)
|
||||
|
||||
show_page.expect_cancelled_meeting date: "01/07/2025 01:30 PM"
|
||||
end
|
||||
end
|
||||
@@ -209,13 +209,18 @@ RSpec.describe "Structured meetings CRUD",
|
||||
end
|
||||
|
||||
it "can delete a meeting and get back to the index page" do
|
||||
click_on("op-meetings-header-action-trigger")
|
||||
show_page.trigger_dropdown_menu_item "Delete meeting"
|
||||
show_page.expect_modal "Delete meeting"
|
||||
|
||||
accept_confirm(I18n.t("text_are_you_sure")) do
|
||||
click_on "Delete meeting"
|
||||
show_page.within_modal "Delete meeting" do
|
||||
check "I understand that this deletion cannot be reversed", allow_label_click: true
|
||||
|
||||
click_on "Delete permanently"
|
||||
end
|
||||
|
||||
expect(page).to have_current_path project_meetings_path(project)
|
||||
|
||||
expect_flash(type: :success, message: "Successful deletion.")
|
||||
end
|
||||
|
||||
context "when exporting as ICS" do
|
||||
@@ -315,7 +320,7 @@ RSpec.describe "Structured meetings CRUD",
|
||||
|
||||
# check for copied participants with attended status reset
|
||||
page.find_test_selector("manage-participants-button").click
|
||||
expect(page).to have_css("#edit-participants-dialog")
|
||||
expect(page).to have_modal("Participants")
|
||||
expect(page).to have_field(id: "checkbox_invited_#{other_user.id}", checked: true)
|
||||
expect(page).to have_field(id: "checkbox_attended_#{other_user.id}", checked: false)
|
||||
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
# 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"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/index"
|
||||
|
||||
RSpec.describe "Structured meetings global CRUD", :js do
|
||||
include Components::Autocompleter::NgSelectAutocompleteHelpers
|
||||
|
||||
shared_let(:project) { create(:project, enabled_module_names: %w[meetings work_package_tracking]) }
|
||||
shared_let(:user) do
|
||||
create(:user,
|
||||
lastname: "First",
|
||||
member_with_permissions: { project => %i[view_meetings create_meetings edit_meetings delete_meetings manage_agendas
|
||||
view_work_packages] }).tap do |u|
|
||||
u.pref[:time_zone] = "Etc/UTC"
|
||||
|
||||
u.save!
|
||||
end
|
||||
end
|
||||
shared_let(:other_user) do
|
||||
create(:user,
|
||||
lastname: "Second",
|
||||
member_with_permissions: { project => %i[view_meetings view_work_packages] })
|
||||
end
|
||||
shared_let(:no_member_user) do
|
||||
create(:user,
|
||||
lastname: "Third")
|
||||
end
|
||||
shared_let(:work_package) do
|
||||
create(:work_package, project:, subject: "Important task")
|
||||
end
|
||||
|
||||
let(:current_user) { user }
|
||||
let(:new_page) { Pages::Meetings::New.new(project) }
|
||||
let(:meeting) { StructuredMeeting.last }
|
||||
let(:show_page) { Pages::StructuredMeeting::Show.new(meeting) }
|
||||
let(:meetings_page) { Pages::Meetings::Index.new(project: nil) }
|
||||
|
||||
before do |test|
|
||||
login_as current_user
|
||||
meetings_page.visit!
|
||||
expect(page).to have_current_path(meetings_page.path) # rubocop:disable RSpec/ExpectInHook
|
||||
meetings_page.click_on "add-meeting-button"
|
||||
meetings_page.click_on "One-time"
|
||||
|
||||
meetings_page.set_project project
|
||||
|
||||
meetings_page.set_title "Some title"
|
||||
|
||||
meetings_page.set_start_date "2013-03-28"
|
||||
meetings_page.set_start_time "13:30"
|
||||
meetings_page.set_duration "1.5"
|
||||
|
||||
if test.metadata[:checked]
|
||||
expect(page).to have_unchecked_field "send_notifications" # rubocop:disable RSpec/ExpectInHook
|
||||
check "send_notifications"
|
||||
end
|
||||
|
||||
meetings_page.click_create
|
||||
end
|
||||
|
||||
it "can delete a meeting and get back to the index page" do
|
||||
show_page.trigger_dropdown_menu_item "Delete meeting"
|
||||
show_page.expect_modal "Delete meeting"
|
||||
|
||||
show_page.within_modal "Delete meeting" do
|
||||
check "I understand that this deletion cannot be reversed", allow_label_click: true
|
||||
|
||||
click_on "Delete permanently"
|
||||
end
|
||||
|
||||
expect(page).to have_current_path meetings_path
|
||||
|
||||
expect_flash(type: :success, message: "Successful deletion.")
|
||||
end
|
||||
end
|
||||
@@ -90,7 +90,7 @@ RSpec.describe "Recurring meetings show",
|
||||
|
||||
describe "upcoming tab" do
|
||||
let!(:upcoming_open_meeting) do
|
||||
create(:structured_meeting, recurring_meeting:, start_time: Time.zone.today + 10.hours, state: :open)
|
||||
create(:structured_meeting, recurring_meeting:, start_time: Time.zone.today + 1.day + 10.hours, state: :open)
|
||||
end
|
||||
let!(:open_meeting) do
|
||||
create :scheduled_meeting,
|
||||
|
||||
@@ -130,7 +130,7 @@ module Pages::Meetings
|
||||
|
||||
def expect_delete_action(meeting)
|
||||
within more_menu(meeting) do
|
||||
expect(page).to have_button("Delete meeting")
|
||||
expect(page).to have_link("Delete meeting")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -32,18 +32,18 @@ module Pages::RecurringMeeting
|
||||
class Show < ::Pages::Meetings::Base
|
||||
attr_accessor :meeting
|
||||
|
||||
def initialize(meeting)
|
||||
super
|
||||
def initialize(meeting, project: nil)
|
||||
super(project)
|
||||
|
||||
self.meeting = meeting
|
||||
end
|
||||
|
||||
def path
|
||||
recurring_meeting_path(meeting)
|
||||
end
|
||||
|
||||
def project_path
|
||||
project_recurring_meeting_path(meeting.project, meeting)
|
||||
if project
|
||||
project_recurring_meeting_path(project, meeting)
|
||||
else
|
||||
recurring_meeting_path(meeting)
|
||||
end
|
||||
end
|
||||
|
||||
def expect_scheduled_meeting(date:)
|
||||
@@ -100,6 +100,17 @@ module Pages::RecurringMeeting
|
||||
click_on "more-button"
|
||||
click_on "Cancel this occurrence"
|
||||
end
|
||||
|
||||
expect_modal("Delete meeting occurrence")
|
||||
end
|
||||
|
||||
def cancel_scheduled_occurrence(date:)
|
||||
within("li", text: date) do
|
||||
click_on "more-button"
|
||||
click_on "Cancel this occurrence"
|
||||
end
|
||||
|
||||
expect_modal("Cancel meeting occurrence")
|
||||
end
|
||||
|
||||
def expect_subtitle(text:)
|
||||
@@ -110,11 +121,25 @@ module Pages::RecurringMeeting
|
||||
page.find_test_selector("recurring-meeting-action-menu").click
|
||||
click_on "Edit meeting series"
|
||||
|
||||
expect(page).to have_css("#new-meeting-dialog")
|
||||
expect_modal("Edit Meeting")
|
||||
end
|
||||
|
||||
def in_edit_dialog(&)
|
||||
page.within("#new-meeting-dialog", &)
|
||||
def delete_meeting_series
|
||||
page.find_test_selector("recurring-meeting-action-menu").click
|
||||
click_on "Delete meeting series"
|
||||
|
||||
expect_modal("Delete meeting series")
|
||||
end
|
||||
|
||||
def end_meeting_series
|
||||
page.find_test_selector("recurring-meeting-action-menu").click
|
||||
click_on "End meeting series"
|
||||
|
||||
expect_modal("End meeting series")
|
||||
end
|
||||
|
||||
def expect_modal(...)
|
||||
expect(page).to have_modal(...)
|
||||
end
|
||||
|
||||
def expect_no_meeting(date:)
|
||||
|
||||
@@ -41,7 +41,7 @@ module Pages::StructuredMeeting::Mobile
|
||||
within(meeting_details_container) do
|
||||
click_link_or_button "Show all"
|
||||
end
|
||||
expect(page).to have_css("#edit-participants-dialog")
|
||||
expect(page).to have_modal("Participants")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -63,6 +63,10 @@ module Pages::StructuredMeeting
|
||||
end
|
||||
end
|
||||
|
||||
def expect_modal(...)
|
||||
expect(page).to have_modal(...)
|
||||
end
|
||||
|
||||
def expect_no_add_form
|
||||
expect(page).not_to have_test_selector("#meeting-agenda-items-form-component")
|
||||
end
|
||||
@@ -204,11 +208,11 @@ module Pages::StructuredMeeting
|
||||
|
||||
def open_participant_form
|
||||
page.find_test_selector("manage-participants-button").click
|
||||
expect(page).to have_css("#edit-participants-dialog")
|
||||
expect_modal("Participants")
|
||||
end
|
||||
|
||||
def in_participant_form(&)
|
||||
page.within("#edit-participants-dialog", &)
|
||||
page.within_modal("Participants", &)
|
||||
end
|
||||
|
||||
def expect_participant(participant, invited: false, attended: false, editable: true)
|
||||
|
||||
@@ -128,7 +128,7 @@ RSpec.describe "custom fields of type hierarchy", :js do
|
||||
hierarchy_page.open_action_menu_for("Phoenix Squad")
|
||||
click_on "Delete"
|
||||
expect(page).to have_test_selector("op-custom-fields--delete-item-dialog")
|
||||
check "I understand that this deletion cannot be reversed"
|
||||
check "I understand that this deletion cannot be reversed", allow_label_click: true
|
||||
click_on "Delete permanently"
|
||||
expect(page).not_to have_test_selector("op-custom-fields--delete-item-dialog")
|
||||
expect(page).to have_test_selector("op-custom-fields--hierarchy-item", count: 1)
|
||||
|
||||
Reference in New Issue
Block a user