Skip to content

Commit 596e22e

Browse files
committed
Show template selector from global meeting create form as well
1 parent cdcb191 commit 596e22e

File tree

12 files changed

+294
-30
lines changed

12 files changed

+294
-30
lines changed

modules/meeting/app/components/meetings/index/form_component.html.erb

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,6 @@
11
<%=
22
component_wrapper do
3-
primer_form_with(
4-
scope: :meeting,
5-
model: @meeting,
6-
method: form_method,
7-
data: {
8-
turbo: true,
9-
controller: [
10-
"show-when-value-selected",
11-
"show-when-checked",
12-
@meeting.is_a?(RecurringMeeting) ? "recurring-meetings--form" : nil
13-
].compact.join(" "),
14-
"recurring-meetings--form-persisted-value": @meeting.persisted?
15-
},
16-
html: {
17-
id: "meeting-form"
18-
},
19-
url: {
20-
controller: form_controller,
21-
action: form_action,
22-
project_id: @project
23-
}
24-
) do |f|
3+
primer_form_with(**form_options) do |f|
254
flex_layout(mb: 3) do |modal_body|
265
if @meeting.errors[:base].present?
276
modal_body.with_row do
@@ -35,9 +14,9 @@
3514
end
3615
end
3716

38-
if creating_onetime_meeting? && no_preselection? && available_templates.any?
17+
if show_template_selector?
3918
modal_body.with_row(mb: 3) do
40-
render(Meeting::TemplateAutocompleter.new(f, project: @project))
19+
render(Meeting::TemplateAutocompleter.new(f, project: effective_project, disabled: template_selector_disabled?, placeholder: template_selector_placeholder))
4120
end
4221
end
4322

modules/meeting/app/components/meetings/index/form_component.rb

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,29 @@ def form_action
7070
end
7171
end
7272

73+
def form_options
74+
{
75+
scope: :meeting,
76+
model: @meeting,
77+
method: form_method,
78+
data: {
79+
turbo: true,
80+
controller: [
81+
"show-when-value-selected",
82+
"show-when-checked",
83+
@meeting.is_a?(RecurringMeeting) ? "recurring-meetings--form" : nil,
84+
"meetings--form",
85+
use_refresh_on_form_changes? ? "refresh-on-form-changes" : nil
86+
].compact.join(" "),
87+
"recurring-meetings--form-persisted-value": @meeting.persisted?,
88+
"refresh-on-form-changes-target": "form",
89+
"refresh-on-form-changes-turbo-stream-url-value": fetch_templates_url
90+
},
91+
html: { id: "meeting-form" },
92+
url: { controller: form_controller, action: form_action, project_id: @project }
93+
}
94+
end
95+
7396
def creating_onetime_meeting?
7497
return false unless EnterpriseToken.allows_to?(:meeting_templates)
7598

@@ -80,10 +103,56 @@ def no_preselection?
80103
!@copy_from
81104
end
82105

106+
def show_template_selector?
107+
return false unless creating_onetime_meeting? && no_preselection?
108+
109+
if @project.nil?
110+
# Global context - show if user can see any templates
111+
globally_visible_templates.any?
112+
else
113+
# Project context - only show if the project actually has templates
114+
available_templates.any?
115+
end
116+
end
117+
118+
def template_selector_disabled?
119+
effective_project.nil? || available_templates.empty?
120+
end
121+
122+
def template_selector_placeholder
123+
if effective_project.nil?
124+
I18n.t(:placeholder_meeting_template_select_project_first)
125+
elsif available_templates.empty?
126+
I18n.t(:placeholder_meeting_template_no_templates_for_project)
127+
end
128+
end
129+
130+
def use_refresh_on_form_changes?
131+
creating_onetime_meeting? && no_preselection? && @project.nil?
132+
end
133+
134+
def fetch_templates_url
135+
if @project
136+
fetch_templates_project_meetings_path(@project)
137+
else
138+
fetch_templates_meetings_path
139+
end
140+
end
141+
83142
def available_templates
84-
return [] unless @project
143+
@available_templates ||= if effective_project
144+
Meeting.templates_visible_in_project(effective_project)
145+
else
146+
Meeting.templates_visible_globally
147+
end
148+
end
149+
150+
def globally_visible_templates
151+
@globally_visible_templates ||= Meeting.templates_visible_globally
152+
end
85153

86-
@available_templates ||= Meeting.templates_visible_in_project(@project)
154+
def effective_project
155+
@project || @meeting.project
87156
end
88157
end
89158
end

modules/meeting/app/controllers/meetings_controller.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ class MeetingsController < ApplicationController
3434
before_action :determine_date_range, only: %i[history]
3535
before_action :determine_author, only: %i[history]
3636
before_action :build_meeting, only: %i[new new_dialog fetch_timezone]
37-
before_action :find_meeting, except: %i[index new create new_dialog fetch_timezone]
37+
before_action :find_meeting, except: %i[index new create new_dialog fetch_timezone fetch_templates]
3838
before_action :redirect_to_project, only: %i[show]
3939
before_action :set_activity, only: %i[history]
4040
before_action :find_copy_from_meeting, only: %i[create]
4141
before_action :convert_params, only: %i[create update]
4242
before_action :prevent_series_template_destruction, only: :destroy
43-
before_action :check_for_enterprise_token, only: %i[create new_dialog]
43+
before_action :check_for_enterprise_token, only: %i[create new_dialog fetch_templates]
4444

4545
helper :watchers
4646
include MeetingsHelper
@@ -342,6 +342,17 @@ def fetch_timezone
342342
respond_with_turbo_streams
343343
end
344344

345+
def fetch_templates
346+
selected_project = Project.visible.find_by(id: params.dig(:meeting, :project_id))
347+
meeting = Meeting.new(project: selected_project)
348+
349+
update_via_turbo_stream(
350+
component: Meetings::Index::FormComponent.new(meeting: meeting, project: nil)
351+
)
352+
353+
respond_with_turbo_streams
354+
end
355+
345356
def generate_pdf_dialog
346357
respond_with_dialog Meetings::Exports::ModalDialogComponent.new(
347358
meeting: @meeting,

modules/meeting/app/forms/meeting/project_autocompleter.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class Meeting::ProjectAutocompleter < ApplicationForm
4242
dropdownPosition: "bottom",
4343
appendTo: "#new-meeting-dialog",
4444
filters: [{ name: "user_action", operator: "=", values: ["meetings/create"] }],
45+
hiddenFieldAction: "change->refresh-on-form-changes#triggerTurboStream",
4546
data: {
4647
"test-selector": "project_id"
4748
}

modules/meeting/app/forms/meeting/template_autocompleter.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class Meeting::TemplateAutocompleter < ApplicationForm
3838
decorated: true,
3939
defaultData: false,
4040
multiple: false,
41+
disabled: @disabled,
42+
placeholder: @placeholder,
4143
appendTo: "#new-meeting-dialog",
4244
data: {
4345
"test-selector": "template_id"
@@ -53,14 +55,18 @@ class Meeting::TemplateAutocompleter < ApplicationForm
5355
end
5456
end
5557

56-
def initialize(project:)
58+
def initialize(project:, disabled: false, placeholder: nil)
5759
super()
5860
@project = project
61+
@disabled = disabled
62+
@placeholder = placeholder
5963
end
6064

6165
private
6266

6367
def templates
68+
return [] if @disabled
69+
6470
Meeting.templates_visible_in_project(@project).order(:title)
6571
end
6672
end

modules/meeting/app/models/meeting.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,16 @@ def self.templates_visible_in_project(project, user = User.current)
155155
.or(available_onetime_templates.where(sharing: :system))
156156
end
157157

158+
def self.templates_visible_globally(user = User.current)
159+
accessible = Project.allowed_to(user, :view_meetings).to_a
160+
ancestor_ids = accessible.flat_map(&:ancestors).pluck(:id).uniq
161+
162+
available_onetime_templates
163+
.where(project_id: accessible.map(&:id))
164+
.or(available_onetime_templates.where(sharing: :descendants, project_id: ancestor_ids))
165+
.or(available_onetime_templates.where(sharing: :system))
166+
end
167+
158168
def recurring?
159169
recurring_meeting_id.present?
160170
end

modules/meeting/config/locales/en.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ en:
215215

216216
caption_meeting_template_select: "Select a template to automatically copy its agenda items"
217217
caption_template_project_select: "Please select the project in which to create this meeting template"
218+
placeholder_meeting_template_select_project_first: "Select a project first"
219+
placeholder_meeting_template_no_templates_for_project: "No templates available for this project"
218220

219221
meeting:
220222
participants:

modules/meeting/config/routes.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
get :new_dialog
4343
get "menu" => "meetings/menus#show"
4444
get :fetch_timezone
45+
get :fetch_templates
4546

4647
get "ical/:token", controller: "meetings/ical", action: :index, as: "ical_feed"
4748

@@ -58,6 +59,7 @@
5859
get :new_dialog
5960
get "menu" => "meetings/menus#show"
6061
get :fetch_timezone
62+
get :fetch_templates
6163

6264
get "templates", action: :index, controller: "meeting_templates", as: "templates"
6365
get "templates/new_dialog", action: :new_dialog, controller: "meeting_templates", as: "new_dialog_template"

modules/meeting/lib/open_project/meeting/engine.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class Engine < ::Rails::Engine
5353
permissible_on: :project
5454
permission :create_meetings,
5555
{
56-
meetings: %i[new create copy new_dialog fetch_timezone],
56+
meetings: %i[new create copy new_dialog fetch_timezone fetch_templates],
5757
recurring_meetings: %i[new create copy init template_completed],
5858
"recurring_meetings/schedule": %i[update_text],
5959
"meetings/menus": %i[show],

modules/meeting/spec/features/meeting_templates/create_meeting_from_template_spec.rb

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,57 @@
199199
end
200200
end
201201

202+
describe "creating meeting from template using template selector from global index", with_ee: [:meeting_templates] do
203+
let(:global_meetings_page) { Pages::Meetings::Index.new(project: nil) }
204+
let(:template) { create(:onetime_template, project:, title: "Template") }
205+
206+
before do
207+
global_meetings_page.visit!
208+
end
209+
210+
it "shows a template selector when user has access to templates" do
211+
template
212+
213+
global_meetings_page.click_on "add-meeting-button"
214+
global_meetings_page.click_on "One-time"
215+
216+
expect(page).to have_dialog("New one-time meeting")
217+
218+
# Initially disabled
219+
within_dialog "New one-time meeting" do
220+
expect(page).to have_css('[data-test-selector="template_id"]', text: "Select a project first")
221+
end
222+
223+
# Disabled when a project with no accessible templates is selected
224+
global_meetings_page.set_project(other_project)
225+
wait_for_network_idle
226+
227+
within_dialog "New one-time meeting" do
228+
expect(page).to have_css('[data-test-selector="template_id"]', text: "Select a project first")
229+
end
230+
231+
# Enabled when a project with accessible templates is selected
232+
global_meetings_page.set_project(project)
233+
wait_for_network_idle
234+
235+
within_dialog "New one-time meeting" do
236+
find('[data-test-selector="template_id"]').click
237+
expect(page).to have_text(template.title)
238+
end
239+
end
240+
241+
it "shows no template selector when user has access to no templates" do
242+
global_meetings_page.click_on "add-meeting-button"
243+
global_meetings_page.click_on "One-time"
244+
245+
expect(page).to have_dialog("New one-time meeting")
246+
247+
within_dialog "New one-time meeting" do
248+
expect(page).to have_no_css('[data-test-selector="template_id"]')
249+
end
250+
end
251+
end
252+
202253
describe "creating meeting from template using 'Create from template' button" do
203254
context "without enterprise token" do
204255
let!(:template) { create(:onetime_template, project:, title: "Planning template") }

0 commit comments

Comments
 (0)