mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Implement fetching
This commit is contained in:
@@ -1,17 +1,32 @@
|
||||
import { ApplicationController } from 'stimulus-use';
|
||||
import { TurboRequestsService } from 'core-app/core/turbo/turbo-requests.service';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
|
||||
export default class OpRecurringMeetingsFormController extends ApplicationController {
|
||||
static targets = [
|
||||
'frequency',
|
||||
'interval',
|
||||
];
|
||||
private turboRequests:TurboRequestsService;
|
||||
private pathHelper:PathHelperService;
|
||||
|
||||
declare readonly frequencyTarget:HTMLSelectElement;
|
||||
declare readonly intervalTarget:HTMLInputElement;
|
||||
async connect() {
|
||||
const context = await window.OpenProject.getPluginContext();
|
||||
this.turboRequests = context.services.turboRequests;
|
||||
this.pathHelper = context.services.pathHelperService;
|
||||
}
|
||||
|
||||
updateFrequencyText():void {
|
||||
const frequency = this.frequencyTarget.value;
|
||||
const interval = this.intervalTarget.value;
|
||||
this.intervalTarget.placeholder = `Every ${frequency}`;
|
||||
const data = new FormData(this.element as HTMLFormElement);
|
||||
const urlSearchParams = new URLSearchParams();
|
||||
['start_date', 'start_time_hour', 'frequency', 'interval'].forEach((name) => {
|
||||
const key = `meeting[${name}]`;
|
||||
urlSearchParams.append(key, data.get(key) as string);
|
||||
});
|
||||
|
||||
void this
|
||||
.turboRequests
|
||||
.request(
|
||||
`${this.pathHelper.staticBase}/recurring_meetings/update_schedule?${urlSearchParams.toString()}`,
|
||||
{
|
||||
headers: { Accept: 'text/vnd.turbo-stream.html' },
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,11 @@
|
||||
end
|
||||
|
||||
modal_body.with_row(mt: 1) do
|
||||
render(Primer::Beta::Text.new(font_size: :small, color: :subtle)) { @meeting.human_frequency_schedule }
|
||||
render(Primer::Beta::Text.new(
|
||||
id: "recurring-meeting-frequency-schedule",
|
||||
font_size: :small,
|
||||
color: :subtle,
|
||||
)) { @meeting.human_frequency_schedule }
|
||||
end
|
||||
|
||||
modal_body.with_row(mt: 3) do
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
module RecurringMeetings
|
||||
class ScheduleController < ApplicationController
|
||||
before_action do
|
||||
do_authorize :create_meetings, global: true
|
||||
end
|
||||
authorization_checked! :update_text
|
||||
|
||||
around_action :with_user_time_zone
|
||||
before_action :build_meeting
|
||||
|
||||
def update_text
|
||||
text = @recurring_meeting.human_frequency_schedule
|
||||
respond_to do |format|
|
||||
format.html { render plain: text }
|
||||
format.turbo_stream do
|
||||
render turbo_stream: turbo_stream.update("recurring-meeting-frequency-schedule",
|
||||
plain: text)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_user_time_zone(&)
|
||||
User.execute_as(User.current, &)
|
||||
end
|
||||
|
||||
def build_meeting
|
||||
@recurring_meeting = RecurringMeeting.new(schedule_params.compact_blank)
|
||||
end
|
||||
|
||||
def schedule_params
|
||||
params
|
||||
.require(:meeting)
|
||||
.permit(:start_date, :start_time_hour, :frequency, :interval)
|
||||
end
|
||||
|
||||
def default_breadcrumb; end
|
||||
end
|
||||
end
|
||||
@@ -39,7 +39,10 @@ class Meeting::TimeGroup < ApplicationForm
|
||||
label: Meeting.human_attribute_name(:start_date),
|
||||
leading_visual: { icon: :calendar },
|
||||
required: true,
|
||||
autofocus: false
|
||||
autofocus: false,
|
||||
data: {
|
||||
action: "input->recurring-meetings--form#updateFrequencyText"
|
||||
}
|
||||
)
|
||||
|
||||
group.text_field(
|
||||
@@ -50,7 +53,10 @@ class Meeting::TimeGroup < ApplicationForm
|
||||
label: Meeting.human_attribute_name(:start_time),
|
||||
leading_visual: { icon: :clock },
|
||||
required: true,
|
||||
caption: formatted_time_zone_offset
|
||||
caption: formatted_time_zone_offset,
|
||||
data: {
|
||||
action: "input->recurring-meetings--form#updateFrequencyText"
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -33,7 +33,6 @@ class RecurringMeeting::Frequency < ApplicationForm
|
||||
label: I18n.t("activerecord.attributes.recurring_meeting.frequency"),
|
||||
data: {
|
||||
target_name: "frequency",
|
||||
"recurring-meetings--form-target": "frequency",
|
||||
"show-when-value-selected-target": "cause",
|
||||
action: "input->recurring-meetings--form#updateFrequencyText"
|
||||
}
|
||||
|
||||
@@ -31,9 +31,10 @@ class RecurringMeeting::Interval < ApplicationForm
|
||||
meeting_form.text_field(
|
||||
name: :interval,
|
||||
type: :number,
|
||||
step: 1,
|
||||
max: RecurringMeeting::MAX_INTERVAL,
|
||||
label: I18n.t("activerecord.attributes.recurring_meeting.interval"),
|
||||
data: {
|
||||
"recurring-meetings--form-target": "interval",
|
||||
action: "input->recurring-meetings--form#updateFrequencyText"
|
||||
}
|
||||
)
|
||||
|
||||
@@ -31,6 +31,8 @@ class RecurringMeeting::Iterations < ApplicationForm
|
||||
meeting_form.text_field(
|
||||
name: :iterations,
|
||||
type: :number,
|
||||
step: 1,
|
||||
max: RecurringMeeting::MAX_ITERATIONS,
|
||||
label: I18n.t("activerecord.attributes.recurring_meeting.iterations")
|
||||
)
|
||||
end
|
||||
|
||||
@@ -64,6 +64,9 @@ Rails.application.routes.draw do
|
||||
post :delete_scheduled
|
||||
post :template_completed
|
||||
end
|
||||
collection do
|
||||
get :update_schedule, controller: "recurring_meetings/schedule", action: :update_text
|
||||
end
|
||||
end
|
||||
|
||||
resources :meetings do
|
||||
|
||||
@@ -40,17 +40,20 @@ module OpenProject::Meeting
|
||||
bundled: true do
|
||||
project_module :meetings do
|
||||
permission :view_meetings,
|
||||
{ meetings: %i[index show check_for_updates download_ics participants_dialog history],
|
||||
{
|
||||
meetings: %i[index show check_for_updates download_ics participants_dialog history],
|
||||
meeting_agendas: %i[history show diff],
|
||||
meeting_minutes: %i[history show diff],
|
||||
"meetings/menus": %i[show],
|
||||
work_package_meetings_tab: %i[index count],
|
||||
recurring_meetings: %i[index show new create download_ics] },
|
||||
recurring_meetings: %i[index show new create download_ics]
|
||||
},
|
||||
permissible_on: :project
|
||||
permission :create_meetings,
|
||||
{
|
||||
meetings: %i[new create copy new_dialog],
|
||||
recurring_meetings: %i[new create copy init template_completed],
|
||||
"recurring_meetings/schedule": %i[update_text],
|
||||
"meetings/menus": %i[show]
|
||||
},
|
||||
permissible_on: :project,
|
||||
|
||||
@@ -81,6 +81,8 @@ RSpec.describe "Recurring meetings creation",
|
||||
meetings_page.set_duration "1.5"
|
||||
meetings_page.set_end_date "2025-01-15"
|
||||
|
||||
expect(page).to have_text "Every week on Tuesday at 01:30 PM"
|
||||
|
||||
click_on "Create meeting"
|
||||
wait_for_network_idle
|
||||
expect_and_dismiss_flash(type: :success, message: "Successful creation.")
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
#-- 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/recurring_meeting/show"
|
||||
|
||||
RSpec.describe "Recurring meetings schedule text",
|
||||
:skip_csrf,
|
||||
type: :rails_request do
|
||||
include Redmine::I18n
|
||||
|
||||
shared_let(:project) { create(:project, enabled_module_names: %i[meetings]) }
|
||||
shared_let(:user) do
|
||||
create(:user,
|
||||
preferences: { time_zone: "Europe/London" },
|
||||
member_with_permissions: { project => %i[view_meetings create_meetings] })
|
||||
end
|
||||
let(:current_user) { user }
|
||||
|
||||
let(:start_time_hour) { "10:00" }
|
||||
let(:start_date) { "2024-12-05" }
|
||||
let(:frequency) { "daily" }
|
||||
let(:interval) { "1" }
|
||||
let(:params) do
|
||||
{ meeting: { start_time_hour:, start_date:, frequency:, interval: } }
|
||||
end
|
||||
let(:format) { :html }
|
||||
|
||||
subject do
|
||||
get update_schedule_recurring_meetings_path(params:, format:)
|
||||
response
|
||||
end
|
||||
|
||||
before do
|
||||
login_as(current_user)
|
||||
end
|
||||
|
||||
describe "setting schedule" do
|
||||
it "returns the update text" do
|
||||
expect(subject).to have_http_status(:ok)
|
||||
expect(subject.body).to include("Daily at 10:00 AM")
|
||||
end
|
||||
|
||||
context "when changing the frequency and interval" do
|
||||
let(:frequency) { "weekly" }
|
||||
let(:interval) { "2" }
|
||||
|
||||
it "returns the update text" do
|
||||
expect(subject).to have_http_status(:ok)
|
||||
expect(subject.body).to include("Every 2nd week on Thursday at 10:00 AM")
|
||||
end
|
||||
end
|
||||
|
||||
context "when changing the interval" do
|
||||
let(:interval) { "2" }
|
||||
|
||||
it "returns the update text" do
|
||||
expect(subject).to have_http_status(:ok)
|
||||
expect(subject.body).to include("Every 2nd day at 10:00 AM")
|
||||
end
|
||||
end
|
||||
|
||||
context "when leaving the interval empty" do
|
||||
let(:interval) { "" }
|
||||
|
||||
it "falls back to the default" do
|
||||
expect(subject).to have_http_status(:ok)
|
||||
expect(subject.body).to include("Daily at 10:00 AM")
|
||||
end
|
||||
end
|
||||
|
||||
context "when requesting with turbo" do
|
||||
let(:format) { :turbo_stream }
|
||||
|
||||
it "returns an update turbo stream" do
|
||||
expect(subject).to have_http_status(:ok)
|
||||
expect(subject.body).to include("turbo-stream")
|
||||
expect(subject.body).to include("Daily at 10:00 AM")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when user has no permissions to access" do
|
||||
let(:current_user) { create(:user) }
|
||||
|
||||
it "does not allow to request it" do
|
||||
expect(subject).to have_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -58,6 +58,7 @@ module Pages::Meetings
|
||||
def set_start_time(time)
|
||||
input = page.find_by_id("meeting_start_time_hour")
|
||||
page.execute_script("arguments[0].value = arguments[1]", input.native, time)
|
||||
page.execute_script("arguments[0].dispatchEvent(new Event('input'))", input.native)
|
||||
end
|
||||
|
||||
def set_end_date(date)
|
||||
|
||||
Reference in New Issue
Block a user