mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Remove references to StructuredMeeting, Agenda and Minutes
This commit is contained in:
@@ -61,7 +61,6 @@ module Users
|
||||
)
|
||||
SQL
|
||||
},
|
||||
{ class: MeetingContent, column: :text },
|
||||
{ class: Journal::MeetingContentJournal, column: :text },
|
||||
{ class: Message, column: :content },
|
||||
{ class: Journal::MessageJournal, column: :content },
|
||||
|
||||
@@ -78,7 +78,7 @@ class BigintPrimaryAndForeignKeys < ActiveRecord::Migration[7.0]
|
||||
LdapGroups::SynchronizedGroup => %i[id group_id auth_source_id],
|
||||
MaterialBudgetItem => %i[id budget_id cost_type_id],
|
||||
Journal::MeetingContentJournal => %i[id meeting_id author_id],
|
||||
MeetingContent => %i[id meeting_id author_id],
|
||||
:meeting_contents => %i[id meeting_id author_id],
|
||||
Journal::MeetingJournal => %i[id project_id author_id],
|
||||
MeetingParticipant => %i[id user_id meeting_id],
|
||||
Meeting => %i[id author_id project_id],
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
//-- 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.
|
||||
//++
|
||||
|
||||
import { HalResource } from 'core-app/features/hal/resources/hal-resource';
|
||||
import { Attachable } from 'core-app/features/hal/resources/mixins/attachable-mixin';
|
||||
|
||||
export interface MeetingContentResourceLinks {
|
||||
addAttachment(attachment:HalResource):Promise<any>;
|
||||
}
|
||||
|
||||
class MeetingContentBaseResource extends HalResource {
|
||||
public $links:MeetingContentResourceLinks;
|
||||
|
||||
private attachmentsBackend = false;
|
||||
}
|
||||
|
||||
export const MeetingContentResource = Attachable(MeetingContentBaseResource);
|
||||
|
||||
export type MeetingContentResource = HalResource;
|
||||
@@ -33,7 +33,6 @@ import { QueryResource } from 'core-app/features/hal/resources/query-resource';
|
||||
import { CustomActionResource } from 'core-app/features/hal/resources/custom-action-resource';
|
||||
import { HalResource } from 'core-app/features/hal/resources/hal-resource';
|
||||
import { WikiPageResource } from 'core-app/features/hal/resources/wiki-page-resource';
|
||||
import { MeetingContentResource } from 'core-app/features/hal/resources/meeting-content-resource';
|
||||
import { PostResource } from 'core-app/features/hal/resources/post-resource';
|
||||
import { StatusResource } from 'core-app/features/hal/resources/status-resource';
|
||||
import { AttachmentCollectionResource } from 'core-app/features/hal/resources/attachment-collection-resource';
|
||||
@@ -185,9 +184,6 @@ const halResourceDefaultConfig:{ [typeName:string]:HalResourceFactoryConfigInter
|
||||
Meeting: {
|
||||
cls: MeetingResource,
|
||||
},
|
||||
MeetingContent: {
|
||||
cls: MeetingContentResource,
|
||||
},
|
||||
Post: {
|
||||
cls: PostResource,
|
||||
},
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* -- 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.
|
||||
* ++
|
||||
*/
|
||||
|
||||
import { Controller } from '@hotwired/stimulus';
|
||||
|
||||
export default class MeetingContentController extends Controller {
|
||||
static targets = [
|
||||
'renderedText',
|
||||
'editor',
|
||||
'attachments',
|
||||
'editButton',
|
||||
];
|
||||
|
||||
static values = {
|
||||
editState: { type: Boolean, default: false },
|
||||
};
|
||||
|
||||
declare editStateValue:boolean;
|
||||
|
||||
declare readonly renderedTextTarget:HTMLElement;
|
||||
|
||||
declare readonly editorTarget:HTMLElement;
|
||||
|
||||
declare readonly attachmentsTarget:HTMLElement;
|
||||
|
||||
declare readonly editButtonTarget:HTMLLinkElement;
|
||||
|
||||
enableEditState() {
|
||||
this.editStateValue = true;
|
||||
}
|
||||
|
||||
cancelEditState() {
|
||||
this.editStateValue = false;
|
||||
window.OpenProject.pageWasEdited = false;
|
||||
}
|
||||
|
||||
editStateValueChanged() {
|
||||
this.renderedTextTarget.hidden = this.editStateValue;
|
||||
this.attachmentsTarget.hidden = this.editStateValue;
|
||||
this.editorTarget.hidden = !this.editStateValue;
|
||||
this.editButtonTarget.classList.toggle('-active', this.editStateValue);
|
||||
}
|
||||
}
|
||||
@@ -36,10 +36,6 @@ export default class OpMeetingsFormController extends ApplicationController {
|
||||
private turboRequests:TurboRequestsService;
|
||||
private pathHelper:PathHelperService;
|
||||
|
||||
static values = { structured: Boolean };
|
||||
|
||||
declare structuredValue:boolean;
|
||||
|
||||
async connect() {
|
||||
const context = await window.OpenProject.getPluginContext();
|
||||
this.turboRequests = context.services.turboRequests;
|
||||
@@ -52,11 +48,7 @@ export default class OpMeetingsFormController extends ApplicationController {
|
||||
let key:string;
|
||||
|
||||
['start_date', 'start_time_hour'].forEach((name) => {
|
||||
if (this.structuredValue === true) {
|
||||
key = `structured_meeting[${name}]`;
|
||||
} else {
|
||||
key = `meeting[${name}]`;
|
||||
}
|
||||
key = `meeting[${name}]`;
|
||||
urlSearchParams.append(key, data.get(key) as string);
|
||||
});
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ RSpec.describe "Calendar Widget", :js, with_settings: { start_of_week: 1 } do
|
||||
due_date: Time.zone.today.beginning_of_week.next_occurring(:thursday))
|
||||
end
|
||||
shared_let(:meeting) do
|
||||
create(:structured_meeting, title: "Weekly", project:, start_time: Time.zone.tomorrow + 10.hours)
|
||||
create(:meeting, title: "Weekly", project:, start_time: Time.zone.tomorrow + 10.hours)
|
||||
end
|
||||
|
||||
let(:overview_page) do
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
menu.with_item(
|
||||
label: I18n.t("meeting.types.one_time"),
|
||||
tag: :a,
|
||||
href: polymorphic_path([:new_dialog, @project, :meetings], type: :structured),
|
||||
href: polymorphic_path([:new_dialog, @project, :meetings]),
|
||||
content_arguments: { data: { controller: "async-dialog" } }
|
||||
) do |item|
|
||||
item.with_description.with_content(t("meeting.types.structured_text"))
|
||||
@@ -45,14 +45,6 @@
|
||||
) do |item|
|
||||
item.with_description.with_content(t("meeting.types.recurring_text"))
|
||||
end
|
||||
|
||||
menu.with_item(
|
||||
label: I18n.t("meeting.types.classic"),
|
||||
tag: :a,
|
||||
href: dynamic_path
|
||||
) do |item|
|
||||
item.with_description.with_content(t("meeting.types.classic_text"))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -122,7 +122,6 @@ module Meetings
|
||||
href: copy_project_meeting_path(project, model),
|
||||
content_arguments: {
|
||||
data: {
|
||||
turbo: model.is_a?(StructuredMeeting),
|
||||
turbo_stream: true
|
||||
}
|
||||
}) do |item|
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
data: { turbo: true,
|
||||
turbo_stream: true,
|
||||
controller: "meetings--form",
|
||||
"application-target": "dynamic",
|
||||
"meetings--form-structured-value": true },
|
||||
"application-target": "dynamic" },
|
||||
url: update_details_project_meeting_path(@project, @meeting)
|
||||
) do |f|
|
||||
component_collection do |collection|
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -34,7 +35,7 @@ module MeetingAgendaItems
|
||||
validate :user_allowed_to_add, :validate_meeting_existence
|
||||
|
||||
def self.assignable_meetings(user)
|
||||
StructuredMeeting
|
||||
Meeting
|
||||
.open
|
||||
.not_templated
|
||||
.not_cancelled
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
# 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 MeetingContents
|
||||
class BaseContract < ::ModelContract
|
||||
include Attachments::ValidateReplacements
|
||||
|
||||
def self.model
|
||||
MeetingContent
|
||||
end
|
||||
|
||||
attribute :meeting
|
||||
attribute :text
|
||||
attribute :lock_version
|
||||
attribute :locked
|
||||
attribute :type
|
||||
|
||||
validate :type_in_allowed
|
||||
|
||||
private
|
||||
|
||||
def type_in_allowed
|
||||
unless [MeetingAgenda.name, MeetingMinutes.name].include?(model.type)
|
||||
errors.add(:type, :inclusion)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,42 +0,0 @@
|
||||
# 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 MeetingContents
|
||||
class UpdateContract < BaseContract
|
||||
validate :validate_editable
|
||||
|
||||
private
|
||||
|
||||
def validate_editable
|
||||
unless model.editable?
|
||||
errors.add :base, :error_readonly
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -40,7 +41,7 @@ module MeetingSections
|
||||
:validate_meeting_existence
|
||||
|
||||
def self.assignable_meetings(user)
|
||||
StructuredMeeting
|
||||
Meeting
|
||||
.open
|
||||
.visible(user)
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -29,21 +30,13 @@
|
||||
|
||||
module Meetings
|
||||
class CreateContract < BaseContract
|
||||
attribute :type
|
||||
attribute :recurring_meeting_id
|
||||
|
||||
validate :user_allowed_to_add
|
||||
validate :type_in_allowed
|
||||
validate :recurring_meeting_visible
|
||||
|
||||
private
|
||||
|
||||
def type_in_allowed
|
||||
unless [StructuredMeeting.name, Meeting.name].include?(model.type)
|
||||
errors.add(:type, :inclusion)
|
||||
end
|
||||
end
|
||||
|
||||
def user_allowed_to_add
|
||||
return if model.project.nil?
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
class MeetingAgendasController < MeetingContentsController
|
||||
menu_item :meetings
|
||||
|
||||
def close
|
||||
@meeting.close_agenda_and_copy_to_minutes!
|
||||
|
||||
redirect_back_or_default({ controller: "/meetings", action: "show", id: @meeting })
|
||||
end
|
||||
|
||||
def open
|
||||
@content.unlock!
|
||||
redirect_back_or_default({ controller: "/meetings", action: "show", id: @meeting })
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_content
|
||||
@content = @meeting.agenda || @meeting.build_agenda
|
||||
@content_type = "meeting_agenda"
|
||||
end
|
||||
end
|
||||
@@ -1,109 +0,0 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
class MeetingContentsController < ApplicationController
|
||||
include AttachableServiceCall
|
||||
include PaginationHelper
|
||||
|
||||
menu_item :meetings
|
||||
|
||||
helper :watchers
|
||||
helper :wiki
|
||||
helper :meetings
|
||||
helper :meeting_contents
|
||||
helper :watchers
|
||||
helper :meetings
|
||||
|
||||
before_action :load_and_authorize_in_optional_project
|
||||
before_action :find_meeting, :find_content
|
||||
|
||||
def show # rubocop:disable Metrics/AbcSize
|
||||
if params[:id].present? && @content.last_journal.version == params[:id].to_i
|
||||
# Redirect links to the last version
|
||||
redirect_to project_meeting_path(@project, @meeting, tab: @content_type.sub(/^meeting_/, ""))
|
||||
return
|
||||
end
|
||||
|
||||
# go to an old version if a version id is given
|
||||
@journaled_version = true
|
||||
@content = @content.at_version params[:id] if params[:id].present?
|
||||
render "meeting_contents/show"
|
||||
end
|
||||
|
||||
def update # rubocop:disable Metrics/AbcSize
|
||||
call = attachable_update_call ::MeetingContents::UpdateService,
|
||||
model: @content,
|
||||
args: content_params
|
||||
|
||||
if call.success?
|
||||
flash[:notice] = I18n.t(:notice_successful_update)
|
||||
redirect_back_or_default project_meeting_path(@project, @meeting)
|
||||
else
|
||||
flash.now[:error] = call.message
|
||||
params[:tab] ||= "minutes" if @meeting.agenda.present? && @meeting.agenda.locked?
|
||||
render "meetings/show", status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def history
|
||||
# don't load text
|
||||
@content_versions = @content.journals.select("id, user_id, notes, created_at, version")
|
||||
.order(Arel.sql("version DESC"))
|
||||
.page(page_param)
|
||||
.per_page(per_page_param)
|
||||
|
||||
render "meeting_contents/history", layout: !request.xhr?
|
||||
end
|
||||
|
||||
def diff
|
||||
@diff = @content.diff(params[:version_to], params[:version_from])
|
||||
render "meeting_contents/diff"
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
def default_breadcrumb
|
||||
MeetingsController.new.send(:default_breadcrumb)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_meeting
|
||||
@meeting = Meeting.includes(:project, :author, :participants, :agenda, :minutes)
|
||||
.find(params[:meeting_id])
|
||||
@project = @meeting.project
|
||||
@author = User.current
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
def content_params
|
||||
params.require(@content_type).permit(:text, :lock_version, :journal_notes)
|
||||
end
|
||||
end
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
class MeetingMinutesController < MeetingContentsController
|
||||
menu_item :meetings
|
||||
|
||||
private
|
||||
|
||||
def find_content
|
||||
@content = @meeting.minutes || @meeting.build_minutes
|
||||
@content_type = "meeting_minutes"
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -41,7 +42,6 @@ class MeetingsController < ApplicationController
|
||||
before_action :prevent_template_destruction, only: :destroy
|
||||
|
||||
helper :watchers
|
||||
helper :meeting_contents
|
||||
include MeetingsHelper
|
||||
include Layout
|
||||
include WatchersHelper
|
||||
@@ -67,18 +67,14 @@ class MeetingsController < ApplicationController
|
||||
:meetings
|
||||
end
|
||||
|
||||
def show # rubocop:disable Metrics/AbcSize
|
||||
def show
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
html_title "#{t(:label_meeting)}: #{@meeting.title}"
|
||||
if @meeting.is_a?(StructuredMeeting)
|
||||
if @meeting.state == "cancelled"
|
||||
render_404
|
||||
else
|
||||
render(Meetings::ShowComponent.new(meeting: @meeting), layout: true)
|
||||
end
|
||||
elsif @meeting.agenda.present? && @meeting.agenda.locked?
|
||||
params[:tab] ||= "minutes"
|
||||
if @meeting.state == "cancelled"
|
||||
render_404
|
||||
else
|
||||
render(Meetings::ShowComponent.new(meeting: @meeting), layout: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -256,7 +252,7 @@ class MeetingsController < ApplicationController
|
||||
end
|
||||
|
||||
def update_title
|
||||
@meeting.update(title: structured_meeting_params[:title])
|
||||
@meeting.update(title: meeting_params[:title])
|
||||
|
||||
if @meeting.errors.any?
|
||||
update_header_component_via_turbo_stream(state: :edit)
|
||||
@@ -270,7 +266,7 @@ class MeetingsController < ApplicationController
|
||||
def update_details
|
||||
call = ::Meetings::UpdateService
|
||||
.new(user: current_user, model: @meeting)
|
||||
.call(structured_meeting_params)
|
||||
.call(meeting_params)
|
||||
|
||||
if call.success?
|
||||
update_header_component_via_turbo_stream
|
||||
@@ -337,9 +333,7 @@ class MeetingsController < ApplicationController
|
||||
@text = friendly_timezone_name(User.current.time_zone, period: meeting.start_time)
|
||||
end
|
||||
|
||||
prefix = params[:structured_meeting] ? "structured_" : ""
|
||||
|
||||
add_caption_to_input_element_via_turbo_stream("input[name='#{prefix}meeting[start_time_hour]']",
|
||||
add_caption_to_input_element_via_turbo_stream("input[name='meeting[start_time_hour]']",
|
||||
caption: @text,
|
||||
clean_other_captions: true)
|
||||
|
||||
@@ -420,7 +414,12 @@ class MeetingsController < ApplicationController
|
||||
end
|
||||
|
||||
def build_meeting
|
||||
meeting = meeting_class.new
|
||||
meeting =
|
||||
if params[:type] == "recurring"
|
||||
RecurringMeeting.new
|
||||
else
|
||||
Meeting.new
|
||||
end
|
||||
|
||||
service = meeting.is_a?(RecurringMeeting) ? ::RecurringMeetings::SetAttributesService : ::Meetings::SetAttributesService
|
||||
call = service
|
||||
@@ -430,17 +429,6 @@ class MeetingsController < ApplicationController
|
||||
@meeting = call.result
|
||||
end
|
||||
|
||||
def meeting_class
|
||||
case params[:type]
|
||||
when "recurring"
|
||||
RecurringMeeting
|
||||
when "structured"
|
||||
StructuredMeeting
|
||||
else
|
||||
Meeting
|
||||
end
|
||||
end
|
||||
|
||||
def global_upcoming_meetings
|
||||
projects = Project.allowed_in_project(User.current, :view_meetings)
|
||||
|
||||
@@ -449,7 +437,7 @@ class MeetingsController < ApplicationController
|
||||
|
||||
def find_meeting
|
||||
@meeting = Meeting
|
||||
.includes([:project, :author, { participants: :user }, :agenda, :minutes])
|
||||
.includes([:project, :author, { participants: :user }, :sections, { agenda_items: :outcomes }])
|
||||
.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
@@ -466,7 +454,7 @@ class MeetingsController < ApplicationController
|
||||
|
||||
# Handle participants separately for each meeting type
|
||||
@converted_params[:participants_attributes] ||= {}
|
||||
if copy_structured_meeting_participants?
|
||||
if copy_meeting_participants?
|
||||
create_participants
|
||||
else
|
||||
force_defaults
|
||||
@@ -481,19 +469,11 @@ class MeetingsController < ApplicationController
|
||||
params
|
||||
.require(:meeting)
|
||||
.permit(:title, :location, :start_time, :project_id,
|
||||
:duration, :start_date, :start_time_hour, :type,
|
||||
:duration, :start_date, :start_time_hour,
|
||||
participants_attributes: %i[email name invited attended user user_id meeting id])
|
||||
end
|
||||
end
|
||||
|
||||
def structured_meeting_params
|
||||
if params[:structured_meeting].present?
|
||||
params
|
||||
.require(:structured_meeting)
|
||||
.permit(:title, :location, :start_time_hour, :duration, :start_date, :state, :lock_version)
|
||||
end
|
||||
end
|
||||
|
||||
def set_activity
|
||||
@activity = Activities::Fetcher.new(User.current,
|
||||
project: @project,
|
||||
@@ -559,12 +539,6 @@ class MeetingsController < ApplicationController
|
||||
end
|
||||
|
||||
def timezone_params
|
||||
meeting_params = if params[:meeting]
|
||||
params.require(:meeting)
|
||||
else
|
||||
params.require(:structured_meeting)
|
||||
end
|
||||
|
||||
@timezone_params ||= meeting_params.permit(:start_date, :start_time_hour).compact_blank
|
||||
@timezone_params ||= params.require(:meeting).permit(:start_date, :start_time_hour).compact_blank
|
||||
end
|
||||
end
|
||||
|
||||
@@ -346,9 +346,9 @@ class RecurringMeetingsController < ApplicationController
|
||||
end
|
||||
|
||||
def structured_meeting_params
|
||||
if params[:structured_meeting].present?
|
||||
if params[:meeting].present?
|
||||
params
|
||||
.require(:structured_meeting)
|
||||
.require(:meeting)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
# 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 MeetingContentsHelper
|
||||
def can_edit_meeting_content?(content, content_type)
|
||||
authorize_for(content_type.pluralize, "update") && content.editable?
|
||||
end
|
||||
|
||||
def saved_meeting_content_text_present?(content)
|
||||
!content.new_record? && content.text.present? && !content.text.empty?
|
||||
end
|
||||
|
||||
def show_meeting_content_editor?(content, content_type)
|
||||
can_edit_meeting_content?(content, content_type) && (!saved_meeting_content_text_present?(content) || content.changed?)
|
||||
end
|
||||
|
||||
def meeting_content_context_menu(content, content_type)
|
||||
menu = []
|
||||
menu << meeting_agenda_toggle_status_link(content, content_type)
|
||||
menu << meeting_content_edit_link(content_type) if can_edit_meeting_content?(content, content_type)
|
||||
menu << meeting_content_history_link(content_type, content.meeting)
|
||||
|
||||
menu.join(" ")
|
||||
end
|
||||
|
||||
def meeting_agenda_toggle_status_link(content, content_type)
|
||||
if content.meeting.agenda.present? && content.meeting.agenda.locked?
|
||||
open_meeting_agenda_link(content_type, content.meeting)
|
||||
else
|
||||
close_meeting_agenda_link(content_type, content.meeting)
|
||||
end
|
||||
end
|
||||
|
||||
def close_meeting_agenda_link(content_type, meeting)
|
||||
case content_type
|
||||
when "meeting_agenda"
|
||||
content_tag :li, "", class: "toolbar-item" do
|
||||
link_to_if_authorized({ controller: "/meeting_agendas",
|
||||
action: "close",
|
||||
meeting_id: meeting },
|
||||
method: :put,
|
||||
data: { confirm: I18n.t(:text_meeting_closing_are_you_sure) },
|
||||
class: "meetings--close-meeting-button button") do
|
||||
text_with_icon(I18n.t(:label_meeting_close), "icon-locked")
|
||||
end
|
||||
end
|
||||
when "meeting_minutes"
|
||||
content_tag :li, "", class: "toolbar-item" do
|
||||
link_to_if_authorized({ controller: "/meeting_agendas",
|
||||
action: "close",
|
||||
meeting_id: meeting },
|
||||
method: :put,
|
||||
class: "button") do
|
||||
text_with_icon(I18n.t(:label_meeting_agenda_close), "icon-locked")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def open_meeting_agenda_link(content_type, meeting)
|
||||
return unless content_type == "meeting_agenda"
|
||||
|
||||
content_tag :li, "", class: "toolbar-item" do
|
||||
link_to_if_authorized({ controller: "/meeting_agendas",
|
||||
action: "open",
|
||||
meeting_id: meeting },
|
||||
method: :put,
|
||||
class: "button",
|
||||
data: { confirm: I18n.t(:text_meeting_agenda_open_are_you_sure) }) do
|
||||
text_with_icon(I18n.t(:label_meeting_open), "icon-unlocked")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def meeting_content_edit_link(_content_type)
|
||||
content_tag :li, "", class: "toolbar-item" do
|
||||
link_to "",
|
||||
class: "button button--edit-agenda",
|
||||
data: {
|
||||
action: "meeting-content#enableEditState",
|
||||
"meeting-content-target": "editButton"
|
||||
},
|
||||
accesskey: accesskey(:edit) do
|
||||
text_with_icon(I18n.t(:label_edit), "icon-edit")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def meeting_content_history_link(content_type, meeting)
|
||||
content_tag :li, "", class: "toolbar-item" do
|
||||
link_to_if_authorized({ controller: "/" + content_type.pluralize,
|
||||
action: "history",
|
||||
meeting_id: meeting },
|
||||
aria: { label: t(:label_history) },
|
||||
title: t(:label_history),
|
||||
class: "button") do
|
||||
text_with_icon(I18n.t(:label_history), "icon-activity-history")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def text_with_icon(text, icon)
|
||||
op_icon("button--icon #{icon}") +
|
||||
" " +
|
||||
content_tag("span", text, class: "button--text")
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -86,8 +87,8 @@ module MeetingsHelper
|
||||
request.path == meetings_path && @project.nil?
|
||||
end
|
||||
|
||||
def copy_structured_meeting_participants?
|
||||
@copy_from.is_a?(StructuredMeeting) && params[:meeting][:copy_participants] == "1"
|
||||
def copy_meeting_participants?
|
||||
params[:meeting][:copy_participants] == "1"
|
||||
end
|
||||
|
||||
def create_participants
|
||||
|
||||
@@ -29,20 +29,9 @@
|
||||
|
||||
class Activities::MeetingActivityProvider < Activities::BaseActivityProvider
|
||||
activity_provider_for type: "meetings",
|
||||
activities: %i[meeting meeting_content],
|
||||
activities: %i[meeting],
|
||||
permission: :view_meetings
|
||||
|
||||
def extend_event_query(query)
|
||||
case activity
|
||||
when :meeting_content
|
||||
query.join(meetings_table).on(activity_journals_table[:meeting_id].eq(meetings_table[:id]))
|
||||
join_cond = journals_table[:journable_type].eq("MeetingContent")
|
||||
query.join(meeting_contents_table).on(journals_table[:journable_id].eq(meeting_contents_table[:id]).and(join_cond))
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def event_query_projection
|
||||
case activity
|
||||
when :meeting
|
||||
@@ -54,7 +43,6 @@ class Activities::MeetingActivityProvider < Activities::BaseActivityProvider
|
||||
]
|
||||
else
|
||||
[
|
||||
projection_statement(meeting_contents_table, :type, "meeting_content_type"),
|
||||
projection_statement(meetings_table, :id, "meeting_id"),
|
||||
projection_statement(meetings_table, :title, "meeting_title"),
|
||||
projection_statement(meetings_table, :project_id, "project_id")
|
||||
@@ -63,7 +51,7 @@ class Activities::MeetingActivityProvider < Activities::BaseActivityProvider
|
||||
end
|
||||
|
||||
def activitied_type
|
||||
activity == :meeting ? Meeting : MeetingContent
|
||||
Meeting
|
||||
end
|
||||
|
||||
def projects_reference_table
|
||||
@@ -76,56 +64,30 @@ class Activities::MeetingActivityProvider < Activities::BaseActivityProvider
|
||||
end
|
||||
|
||||
def activity_journals_table
|
||||
@activity_journals_table ||= case activity
|
||||
when :meeting
|
||||
Meeting.journal_class.arel_table
|
||||
else
|
||||
MeetingContent.journal_class.arel_table
|
||||
end
|
||||
@activity_journals_table ||= Meeting.journal_class.arel_table
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def event_name(event)
|
||||
case event["event_description"]
|
||||
when "Agenda closed"
|
||||
I18n.t("meeting_agenda_closed", scope: "events")
|
||||
when "Agenda opened"
|
||||
I18n.t("meeting_agenda_opened", scope: "events")
|
||||
when "Minutes created"
|
||||
I18n.t("meeting_minutes_created", scope: "events")
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def event_title(event)
|
||||
case activity
|
||||
when :meeting
|
||||
start_time = if event["meeting_start_time"].is_a?(String)
|
||||
DateTime.parse(event["meeting_start_time"])
|
||||
else
|
||||
event["meeting_start_time"]
|
||||
end
|
||||
end_time = start_time + event["meeting_duration"].to_f.hours
|
||||
start_time =
|
||||
if event["meeting_start_time"].is_a?(String)
|
||||
DateTime.parse(event["meeting_start_time"])
|
||||
else
|
||||
event["meeting_start_time"]
|
||||
end
|
||||
|
||||
fstart_with = format_date start_time
|
||||
fstart_without = format_time start_time, include_date: false
|
||||
fend_without = format_time end_time, include_date: false
|
||||
end_time = start_time + event["meeting_duration"].to_f.hours
|
||||
|
||||
"#{I18n.t(:label_meeting)}: #{event['meeting_title']} (#{fstart_with} #{fstart_without}-#{fend_without})"
|
||||
else
|
||||
"#{event['meeting_content_type'].constantize.model_name.human}: #{event['meeting_title']}"
|
||||
end
|
||||
fstart_with = format_date start_time
|
||||
fstart_without = format_time start_time, include_date: false
|
||||
fend_without = format_time end_time, include_date: false
|
||||
|
||||
"#{I18n.t(:label_meeting)}: #{event['meeting_title']} (#{fstart_with} #{fstart_without}-#{fend_without})"
|
||||
end
|
||||
|
||||
def event_type(event)
|
||||
case activity
|
||||
when :meeting
|
||||
"meeting"
|
||||
else
|
||||
event["meeting_content_type"].include?("Agenda") ? "meeting-agenda" : "meeting-minutes"
|
||||
end
|
||||
"meeting"
|
||||
end
|
||||
|
||||
def event_path(event)
|
||||
@@ -160,10 +122,6 @@ class Activities::MeetingActivityProvider < Activities::BaseActivityProvider
|
||||
@meetings_table ||= Meeting.arel_table
|
||||
end
|
||||
|
||||
def meeting_contents_table
|
||||
@meeting_contents_table ||= MeetingContent.arel_table
|
||||
end
|
||||
|
||||
def activity_id(event)
|
||||
activity == :meeting ? event["journable_id"] : event["meeting_id"]
|
||||
end
|
||||
|
||||
@@ -41,17 +41,17 @@ class Meeting < ApplicationRecord
|
||||
belongs_to :recurring_meeting, optional: true
|
||||
has_one :scheduled_meeting, inverse_of: :meeting
|
||||
|
||||
has_one :agenda, dependent: :destroy, class_name: "MeetingAgenda"
|
||||
has_one :minutes, dependent: :destroy, class_name: "MeetingMinutes"
|
||||
has_many :contents, -> { readonly }, class_name: "MeetingContent"
|
||||
|
||||
has_many :participants,
|
||||
dependent: :destroy,
|
||||
class_name: "MeetingParticipant",
|
||||
after_add: :send_participant_added_mail
|
||||
|
||||
has_many :sections, dependent: :destroy, class_name: "MeetingSection"
|
||||
has_many :agenda_items, dependent: :destroy, class_name: "MeetingAgendaItem"
|
||||
has_many :agenda_items,
|
||||
class_name: "MeetingAgendaItem",
|
||||
inverse_of: :meeting
|
||||
|
||||
accepts_nested_attributes_for :agenda_items
|
||||
|
||||
scope :templated, -> { where(template: true) }
|
||||
scope :not_templated, -> { where(template: false) }
|
||||
@@ -91,12 +91,12 @@ class Meeting < ApplicationRecord
|
||||
|
||||
acts_as_searchable columns: [
|
||||
"#{table_name}.title",
|
||||
"#{MeetingContent.table_name}.text",
|
||||
"#{MeetingAgendaItem.table_name}.title",
|
||||
"#{MeetingAgendaItem.table_name}.notes"
|
||||
"#{MeetingAgendaItem.table_name}.notes",
|
||||
"#{MeetingOutcome.table_name}.notes"
|
||||
],
|
||||
include: %i[contents project agenda_items],
|
||||
references: %i[meeting_contents agenda_items],
|
||||
include: [:project, { agenda_items: :outcomes }],
|
||||
references: %i[agenda_items outcomes],
|
||||
date_column: "#{table_name}.created_at"
|
||||
|
||||
include Meeting::Journalized
|
||||
@@ -157,10 +157,6 @@ class Meeting < ApplicationRecord
|
||||
title
|
||||
end
|
||||
|
||||
def text
|
||||
agenda.text if agenda.present?
|
||||
end
|
||||
|
||||
def templated?
|
||||
!!template
|
||||
end
|
||||
@@ -207,28 +203,6 @@ class Meeting < ApplicationRecord
|
||||
by_start_year_month_date
|
||||
end
|
||||
|
||||
def close_agenda_and_copy_to_minutes!
|
||||
Meeting.transaction do
|
||||
agenda.lock!
|
||||
|
||||
attachments = agenda.attachments.map { |a| [a, a.copy] }
|
||||
original_text = String(agenda.text)
|
||||
minutes = create_minutes(text: original_text,
|
||||
journal_notes: I18n.t("events.meeting_minutes_created"),
|
||||
attachments: attachments.map(&:last))
|
||||
|
||||
# substitute attachment references in text to use the respective copied attachments
|
||||
updated_text = original_text.gsub(/(?<=\(\/api\/v3\/attachments\/)\d+(?=\/content\))/) do |id|
|
||||
old_id = id.to_i
|
||||
new_id = attachments.select { |a, _| a.id == old_id }.map { |_, a| a.id }.first
|
||||
|
||||
new_id || -1
|
||||
end
|
||||
|
||||
minutes.update text: updated_text if updated_text != original_text
|
||||
end
|
||||
end
|
||||
|
||||
alias :original_participants_attributes= :participants_attributes=
|
||||
|
||||
def participants_attributes=(attrs)
|
||||
@@ -249,6 +223,55 @@ class Meeting < ApplicationRecord
|
||||
.where(user_id: available_members)
|
||||
end
|
||||
|
||||
# triggered by MeetingAgendaItem#after_create/after_destroy/after_save
|
||||
def calculate_agenda_item_time_slots
|
||||
current_time = start_time
|
||||
MeetingAgendaItem.transaction do
|
||||
changed_items = agenda_items.includes(:meeting_section).order("meeting_sections.position", :position).map do |top|
|
||||
start_time = current_time
|
||||
current_time += top.duration_in_minutes&.minutes || 0.minutes
|
||||
end_time = current_time
|
||||
top.assign_attributes(start_time:, end_time:)
|
||||
top
|
||||
end
|
||||
|
||||
# Disable optimistic locking in order to avoid causing `StaleObjectError`.
|
||||
MeetingAgendaItem.skip_optimistic_locking do
|
||||
MeetingAgendaItem.import(
|
||||
changed_items,
|
||||
on_duplicate_key_update: {
|
||||
conflict_target: [:id],
|
||||
columns: %i[meeting_id
|
||||
author_id
|
||||
title
|
||||
notes
|
||||
position
|
||||
duration_in_minutes
|
||||
start_time
|
||||
end_time
|
||||
created_at
|
||||
updated_at
|
||||
work_package_id
|
||||
item_type
|
||||
lock_version]
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def agenda_items_sum_duration_in_minutes
|
||||
agenda_items.sum(:duration_in_minutes)
|
||||
end
|
||||
|
||||
def duration_exceeded_by_agenda_items?
|
||||
agenda_items_sum_duration_in_minutes > (duration * 60)
|
||||
end
|
||||
|
||||
def duration_exceeded_by_agenda_items_in_minutes
|
||||
agenda_items_sum_duration_in_minutes - (duration * 60)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_new_participants_as_watcher
|
||||
|
||||
@@ -37,7 +37,7 @@ class MeetingAgendaItem < ApplicationRecord
|
||||
|
||||
enum :item_type, ITEM_TYPES
|
||||
|
||||
belongs_to :meeting, class_name: "StructuredMeeting"
|
||||
belongs_to :meeting
|
||||
belongs_to :meeting_section, optional: false
|
||||
belongs_to :work_package, class_name: "::WorkPackage"
|
||||
has_one :project, through: :meeting
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
class StructuredMeeting < Meeting
|
||||
has_many :agenda_items,
|
||||
dependent: :destroy,
|
||||
foreign_key: "meeting_id",
|
||||
class_name: "MeetingAgendaItem",
|
||||
inverse_of: :meeting
|
||||
accepts_nested_attributes_for :agenda_items
|
||||
|
||||
# triggered by MeetingAgendaItem#after_create/after_destroy/after_save
|
||||
def calculate_agenda_item_time_slots
|
||||
current_time = start_time
|
||||
MeetingAgendaItem.transaction do
|
||||
changed_items = agenda_items.includes(:meeting_section).order("meeting_sections.position", :position).map do |top|
|
||||
start_time = current_time
|
||||
current_time += top.duration_in_minutes&.minutes || 0.minutes
|
||||
end_time = current_time
|
||||
top.assign_attributes(start_time:, end_time:)
|
||||
top
|
||||
end
|
||||
|
||||
# Disable optimistic locking in order to avoid causing `StaleObjectError`.
|
||||
MeetingAgendaItem.skip_optimistic_locking do
|
||||
MeetingAgendaItem.import(
|
||||
changed_items,
|
||||
on_duplicate_key_update: {
|
||||
conflict_target: [:id],
|
||||
columns: %i[meeting_id
|
||||
author_id
|
||||
title
|
||||
notes
|
||||
position
|
||||
duration_in_minutes
|
||||
start_time
|
||||
end_time
|
||||
created_at
|
||||
updated_at
|
||||
work_package_id
|
||||
item_type
|
||||
lock_version]
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def agenda_items_sum_duration_in_minutes
|
||||
agenda_items.sum(:duration_in_minutes)
|
||||
end
|
||||
|
||||
def duration_exceeded_by_agenda_items?
|
||||
agenda_items_sum_duration_in_minutes > (duration * 60)
|
||||
end
|
||||
|
||||
def duration_exceeded_by_agenda_items_in_minutes
|
||||
agenda_items_sum_duration_in_minutes - (duration * 60)
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -51,7 +52,7 @@ module Meetings
|
||||
end
|
||||
|
||||
def create_meeting_template!(series, model_data)
|
||||
template = StructuredMeeting.new(template_attributes(model_data))
|
||||
template = Meeting.new(template_attributes(model_data))
|
||||
template.template = true
|
||||
template.recurring_meeting = series
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
# 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 MeetingContents
|
||||
class SetAttributesService < ::BaseServices::SetAttributes
|
||||
include Attachments::SetReplacements
|
||||
|
||||
def set_default_attributes(_params)
|
||||
model.change_by_system do
|
||||
model.author = user if model.author.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,46 +0,0 @@
|
||||
# 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 MeetingContents
|
||||
class UpdateService < ::BaseServices::Update
|
||||
include Attachments::ReplaceAttachments
|
||||
|
||||
def persist(call)
|
||||
content = call.result
|
||||
|
||||
if content.lock_version_changed?
|
||||
call.errors.add(:base, I18n.t(:notice_locking_conflict))
|
||||
call.success = false
|
||||
return call
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -114,31 +114,14 @@ module Meetings
|
||||
end
|
||||
|
||||
def copy_meeting_agenda(copy)
|
||||
if meeting.is_a?(StructuredMeeting)
|
||||
meeting.sections.each do |section|
|
||||
copy.sections << section.dup
|
||||
copied_section = copy.reload.sections.last
|
||||
section.agenda_items.each do |agenda_item|
|
||||
copied_agenda_item = agenda_item.dup
|
||||
copied_agenda_item.meeting_id = copy.id
|
||||
copied_section.agenda_items << copied_agenda_item
|
||||
end
|
||||
meeting.sections.each do |section|
|
||||
copy.sections << section.dup
|
||||
copied_section = copy.reload.sections.last
|
||||
section.agenda_items.each do |agenda_item|
|
||||
copied_agenda_item = agenda_item.dup
|
||||
copied_agenda_item.meeting_id = copy.id
|
||||
copied_section.agenda_items << copied_agenda_item
|
||||
end
|
||||
else
|
||||
MeetingAgenda.create!(
|
||||
meeting: copy,
|
||||
author: user,
|
||||
text: meeting.agenda&.text,
|
||||
journal_notes: I18n.t("meeting.copied", id: meeting.id)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def copy_structured_meeting_participants(copy)
|
||||
meeting.participants.each do |participant|
|
||||
copied_participant = participant.dup
|
||||
copied_participant.meeting_id = copy.id
|
||||
copy.participants << copied_participant
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -31,17 +32,6 @@ module Meetings
|
||||
class CreateService < ::BaseServices::Create
|
||||
protected
|
||||
|
||||
def instance(params)
|
||||
# Setting the #type as attributes will not work
|
||||
# as the STI instance is not changed without using e.g., +becomes!+
|
||||
case params.delete(:type)
|
||||
when "StructuredMeeting"
|
||||
StructuredMeeting.new
|
||||
else
|
||||
Meeting.new
|
||||
end
|
||||
end
|
||||
|
||||
def after_perform(call)
|
||||
if call.success? && Journal::NotificationConfiguration.active?
|
||||
meeting = call.result
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -44,7 +45,6 @@ module RecurringMeetings
|
||||
|
||||
def create_meeting_template(recurring_meeting)
|
||||
params = @template_params.merge(
|
||||
type: "StructuredMeeting",
|
||||
template: true,
|
||||
recurring_meeting:,
|
||||
project: recurring_meeting.project
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%= labelled_tabular_form_for content, :url => {:controller => '/' + content_type.pluralize, :action => 'update', :meeting_id => content.meeting}, :html => {:id => "#{content_type}_form", :method => :put} do |f| %>
|
||||
<%= error_messages_for content_type %>
|
||||
|
||||
<% resource = ::API::V3::MeetingContents::MeetingContentRepresenter.new(content, current_user: current_user, embed_links: true) %>
|
||||
|
||||
<div class="form--field -no-label -visible-overflow">
|
||||
<%=
|
||||
f.text_area(
|
||||
:text,
|
||||
class: 'wiki-edit wiki-toolbar',
|
||||
no_label: true,
|
||||
resource: resource,
|
||||
label_options: { class: 'hidden-for-sighted' },
|
||||
with_text_formatting: true
|
||||
)
|
||||
%>
|
||||
</div>
|
||||
<%= f.hidden_field :lock_version %>
|
||||
|
||||
<p><%= f.text_field :journal_notes, label: :comments %></p>
|
||||
<%= styled_button_tag t(:button_save),
|
||||
class: '-primary -with-icon icon-checkmark button--save-agenda',
|
||||
data: { disable_with: I18n.t(:label_loading) } %>
|
||||
<%= link_to t(:button_cancel),
|
||||
"#",
|
||||
data: {
|
||||
action: 'meeting-content#cancelEditState'
|
||||
},
|
||||
class: 'button -with-icon icon-cancel button--cancel-agenda' %>
|
||||
<% end %>
|
||||
@@ -1,76 +0,0 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%
|
||||
tab ||= locals[:tab_contents] if defined? locals
|
||||
if tab.present?
|
||||
content = tab[:content]
|
||||
content_type = tab[:content_type]
|
||||
end
|
||||
-%>
|
||||
|
||||
<div data-controller="meeting-content"
|
||||
data-application-target="dynamic"
|
||||
data-meeting-content-edit-state-value="<%= show_meeting_content_editor?(content, content_type) %>"
|
||||
data-test-selector="op-meeting--<%= content_type %>">
|
||||
<div>
|
||||
<%= toolbar title: t(:"label_#{content_type}") do %>
|
||||
<%= raw meeting_content_context_menu content, content_type %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if can_edit_meeting_content?(content, content_type) -%>
|
||||
<div data-meeting-content-target="editor"
|
||||
hidden>
|
||||
<%= render(partial: "meeting_contents/form", locals: { content: content, content_type: content_type }) %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<div data-meeting-content-target="renderedText"
|
||||
hidden>
|
||||
<% if saved_meeting_content_text_present?(content) -%>
|
||||
<div class="wiki op-uc-container">
|
||||
<%= format_text(content.text, object: @meeting) %>
|
||||
</div>
|
||||
<% else -%>
|
||||
<%= no_results_box %>
|
||||
<% end -%>
|
||||
</div>
|
||||
|
||||
<%# We cannot render attachments for journaled content %>
|
||||
<% unless local_assigns[:journaled_version] %>
|
||||
<% resource = ::API::V3::MeetingContents::MeetingContentRepresenter.new(content, current_user: current_user, embed_links: true) %>
|
||||
<%= list_attachments(
|
||||
resource,
|
||||
data: {
|
||||
"meeting-content-target": "attachments"
|
||||
}
|
||||
) %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -1,55 +0,0 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<% html_title "#{t(:label_meeting_diff)}: #{@meeting.title}" %>
|
||||
<%= toolbar title: t(:"label_#{@content_type}"),
|
||||
link_to: link_to(@meeting, @meeting) do %>
|
||||
<% if authorize_for(@content_type.pluralize, :history) %>
|
||||
<li class="toolbar-item">
|
||||
<%= link_to({ controller: "/#{@content_type.pluralize}", action: "history", meeting_id: @meeting }, class: "button") do %>
|
||||
<%= op_icon("button--icon icon-wiki") %>
|
||||
<span class="button--text"><%= t(:label_history) %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<p>
|
||||
<%= t(:label_version) %> <%= link_to @diff.content_from.version, send(:"#{@content_type}_version_path", @meeting, @diff.content_from.version) %>
|
||||
<em>(<%= link_to_user(@diff.content_from.user) %>, <%= format_time(@diff.content_from.created_at) %>)</em>
|
||||
→
|
||||
<%= t(:label_version) %> <%= link_to @diff.content_to.version, send(:"#{@content_type}_version_path", @meeting, @diff.content_to.version) %>/<%= @content.last_journal&.version || 0 %>
|
||||
<em>(<%= link_to_user(@diff.content_to.user) %>, <%= format_time(@diff.content_to.created_at) %>)</em>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="text-diff">
|
||||
<%= simple_format_without_paragraph @diff.to_html %>
|
||||
</div>
|
||||
@@ -1,148 +0,0 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<% html_title "#{t(:label_history)}: #{@meeting.title}" %>
|
||||
|
||||
<%= toolbar title: t(:"label_#{@content_type}"),
|
||||
link_to: link_to(@meeting, @meeting) %>
|
||||
|
||||
<h3><%= t(:label_history) %></h3>
|
||||
|
||||
<%= form_tag({ action: "diff" }, method: :get) do %>
|
||||
<div class="generic-table--container"
|
||||
data-application-target="dynamic"
|
||||
data-controller="journal-history">
|
||||
<div class="generic-table--results-container">
|
||||
<table class="generic-table" data-controller="table-highlighting">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="-short">
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<span id="history-version">#</span>
|
||||
<label class="hidden-for-sighted" for="history-version"><%= t(:label_version) %></label>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th class="-short">
|
||||
<div class="generic-table--empty-header"></div>
|
||||
</th>
|
||||
<th class="-short">
|
||||
<div class="generic-table--empty-header"></div>
|
||||
</th>
|
||||
<th>
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<span>
|
||||
<%= Meeting.human_attribute_name(:updated_at) %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th>
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<span>
|
||||
<%= Meeting.human_attribute_name(:author) %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th>
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<span>
|
||||
<%= Meeting.human_attribute_name(:comments) %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% show_diff = @content_versions.size > 1 %>
|
||||
<% @content_versions.each_with_index do |content_version,index| %>
|
||||
<tr>
|
||||
<td class="id -short">
|
||||
<%= if content_version.version == @content.last_journal.version
|
||||
link_to(content_version.version, tab_meeting_path(@meeting, tab: @content_type.sub(/^meeting_/, "")), id: "version-#{content_version.version}")
|
||||
else
|
||||
link_to(content_version.version, send(:"#{@content_type}_version_path", @meeting, content_version.version), id: "version-#{content_version.version}")
|
||||
end %>
|
||||
</td>
|
||||
<td class="checkbox -short">
|
||||
<% if show_diff && (index < @content_versions.size-1) %>
|
||||
<%= radio_button_tag(
|
||||
"version_from",
|
||||
content_version.version,
|
||||
(index == 0),
|
||||
class: "meetings--checkbox-version-to",
|
||||
data: {
|
||||
"journal-history-target": "fromVersion",
|
||||
action: "journal-history#selectToVersion"
|
||||
}
|
||||
) %>
|
||||
<label class="hidden-for-sighted" for="checkbox-from-<%= index %>"><%= t(:description_compare_from) %> <%= index %></label>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="checkbox -short">
|
||||
<% if show_diff && (index > 0) %>
|
||||
<%= radio_button_tag(
|
||||
"version_to",
|
||||
content_version.version,
|
||||
(index == 1),
|
||||
data: {
|
||||
"journal-history-target": "toVersion",
|
||||
action: "journal-history#selectFromVersion"
|
||||
}
|
||||
) %>
|
||||
<label class="hidden-for-sighted" for="checkbox-to-<%= index %>"><%= t(:description_compare_to) %> <%= index %></label>
|
||||
<% end %>
|
||||
</td>
|
||||
<td id="test"><%= format_time(content_version.created_at) %></td>
|
||||
<td><em><%= User.find content_version.user_id %></em></td>
|
||||
<td><%= h content_version.notes %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<%= styled_button_tag t(:label_view_diff), class: "-small -primary" if show_diff %>
|
||||
<%= pagination_links_full @content_versions %>
|
||||
<% end %>
|
||||
@@ -1,36 +0,0 @@
|
||||
<%#-- 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 partial: "meeting_contents/show",
|
||||
locals: {
|
||||
content: @content,
|
||||
journaled_version: @journaled_version,
|
||||
content_type: @content_type,
|
||||
title: "#{t(:"label_#{@content_type}")}: #{link_to @meeting, @meeting}"
|
||||
} %>
|
||||
@@ -1,156 +0,0 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%= error_messages_for "meeting" %>
|
||||
|
||||
<section class="form--section">
|
||||
|
||||
<div class="form--field -required">
|
||||
<%= f.text_field :title, required: true, size: 60, container_class: "-wide" %>
|
||||
</div>
|
||||
|
||||
<% copy_from = local_assigns[:copy_from] %>
|
||||
<% if copy_from.present? %>
|
||||
<%= f.hidden_field :type, value: copy_from.type %>
|
||||
<%= hidden_field_tag "copied_from_meeting_id", copy_from.id %>
|
||||
<div class="form--field">
|
||||
<%= styled_label_tag "copy_agenda", t("meeting.copy.agenda") %>
|
||||
<div class="form--field-container">
|
||||
<%= styled_check_box_tag "copy_agenda",
|
||||
1,
|
||||
true,
|
||||
no_label: true,
|
||||
class: "radio-button" %>
|
||||
</div>
|
||||
<div class="form--field-instructions">
|
||||
<%= t("meeting.copy.agenda_text") %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form--field">
|
||||
<%= styled_label_tag "copy_attachments", t("meeting.copy.attachments") %>
|
||||
<div class="form--field-container">
|
||||
<%= styled_check_box_tag "copy_attachments",
|
||||
1,
|
||||
false,
|
||||
no_label: true,
|
||||
class: "radio-button" %>
|
||||
</div>
|
||||
<div class="form--field-instructions">
|
||||
<%= t("meeting.copy.attachments_text") %>
|
||||
</div>
|
||||
</div>
|
||||
<% elsif @meeting.new_record? %>
|
||||
<%= f.hidden_field :type, value: "Meeting" %>
|
||||
<% end %>
|
||||
|
||||
<% if global_meeting_create_context? %>
|
||||
<div class="form--field -required">
|
||||
<label class="form--label" for="project_id"><%= Meeting.human_attribute_name(:project) %>:</label>
|
||||
<div class="form--field-container">
|
||||
<%= angular_component_tag "opce-project-autocompleter",
|
||||
inputs: {
|
||||
filters: [{ name: "user_action", operator: "=", values: ["meetings/create"] }],
|
||||
inputName: "project_id",
|
||||
inputValue: @project&.id,
|
||||
appendTo: "body",
|
||||
hiddenFieldAction: "change->refresh-on-form-changes#triggerTurboStream"
|
||||
},
|
||||
id: "project_id",
|
||||
class: "form--select-container -wide remote-field--input",
|
||||
data: {
|
||||
"test-selector": "project_id"
|
||||
} %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="form--field">
|
||||
<%= f.text_field :location, size: 60, container_class: "-wide" %>
|
||||
</div>
|
||||
|
||||
<div class="form--field -required">
|
||||
<label for="meeting_start_date" class="form--label"><%= Meeting.human_attribute_name(:start_date) %>
|
||||
<span class="hidden-for-sighted">
|
||||
<%= t(:label_start_date) %><%= t(:text_hint_date_format) %>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<div class="form--field-container -visible-overflow">
|
||||
<%= f.date_picker :start_date,
|
||||
id: "meeting-form-start-date",
|
||||
required: true,
|
||||
no_label: true %>
|
||||
<label for="meeting-form-start-time" class="hidden-for-sighted">
|
||||
<%= Meeting.human_attribute_name(:start_time) %>
|
||||
<label lang="en">
|
||||
<%= t(:label_time_zone) %>
|
||||
<%= formatted_time_zone_offset %>
|
||||
</label>
|
||||
</label>
|
||||
<%= f.text_field :start_time_hour,
|
||||
id: "meeting-form-start-time",
|
||||
required: true,
|
||||
type: "time",
|
||||
no_label: true,
|
||||
step: 5.minutes,
|
||||
suffix: formatted_time_zone_offset,
|
||||
container_class: "-xslim" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form--field -required">
|
||||
<label for="meeting-form-duration" class="form--label"><%= Meeting.human_attribute_name(:duration) %></label>
|
||||
<div class="form--field-container">
|
||||
<%= f.number_field :duration,
|
||||
id: "meeting-form-duration",
|
||||
required: true,
|
||||
size: 5,
|
||||
no_label: true,
|
||||
min: 0.00,
|
||||
step: 0.25,
|
||||
max: 168,
|
||||
suffix: t(:text_in_hours),
|
||||
container_class: "-xslim" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render partial: "meetings/participants_section" %>
|
||||
|
||||
<div class="form--field">
|
||||
<%= styled_label_tag "send_notfications", t(:"meeting.email.send_emails") %>
|
||||
<div class="form--field-container">
|
||||
<%= styled_check_box_tag "send_notifications",
|
||||
1,
|
||||
false %>
|
||||
</div>
|
||||
<div class="form--field-instructions">
|
||||
<%= t(:"meeting.email.send_invitation_emails") %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -1,38 +0,0 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<% html_title "#{t(:label_meeting_edit)}: #{@meeting.title}" %>
|
||||
|
||||
<%= toolbar title: "#{t(:label_meeting)} ##{@meeting.id}" %>
|
||||
<%= labelled_tabular_form_for @meeting, url: { controller: "/meetings", action: "update" }, html: { id: "meeting-form", method: :put } do |f| -%>
|
||||
<%= render partial: "form", locals: { f: f } %>
|
||||
<%= styled_button_tag t(:button_save), class: "-primary -with-icon icon-checkmark" %>
|
||||
<%= link_to t(:button_cancel), { action: "show", id: @meeting },
|
||||
class: "button -with-icon icon-cancel" %>
|
||||
<% end if @project %>
|
||||
@@ -1,73 +0,0 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
<% copy_from = local_assigns[:copy_from] %>
|
||||
<% if copy_from
|
||||
page_title = t("meeting.copy.title", title: copy_from.title)
|
||||
breadcrumb_element = t("meeting.copy.title", title: "<b>#{copy_from.title}</b>")
|
||||
else
|
||||
page_title = t(:label_meeting_new)
|
||||
breadcrumb_element = t(:label_meeting_new)
|
||||
end %>
|
||||
|
||||
<% html_title page_title %>
|
||||
|
||||
<%=
|
||||
render(Primer::OpenProject::PageHeader.new) do |header|
|
||||
header.with_title { page_title }
|
||||
header.with_breadcrumbs(
|
||||
[if @project.present?
|
||||
{ href: project_overview_path(@project.id), text: @project.name }
|
||||
else
|
||||
{ href: home_path, text: organization_name }
|
||||
end,
|
||||
{ href: @project.present? ? project_meetings_path(@project.id) : meetings_path,
|
||||
text: I18n.t(:label_meeting_plural) },
|
||||
breadcrumb_element.html_safe]
|
||||
)
|
||||
end
|
||||
%>
|
||||
|
||||
<%= labelled_tabular_form_for @meeting,
|
||||
as: :meeting,
|
||||
url: { controller: "/meetings", action: "create", project_id: @project },
|
||||
html: {
|
||||
id: "meeting-form",
|
||||
target: "_top",
|
||||
data: {
|
||||
turbo: false,
|
||||
controller: "refresh-on-form-changes",
|
||||
"refresh-on-form-changes-target": "form",
|
||||
"refresh-on-form-changes-turbo-stream-url-value": new_meeting_url
|
||||
}
|
||||
} do |f| -%>
|
||||
<%= render partial: "form", locals: { f:, copy_from: } %>
|
||||
<%= styled_button_tag t(:button_create), class: "-primary" %>
|
||||
<%= link_to t(:button_cancel), { action: "index", project_id: @project },
|
||||
class: "button" %>
|
||||
<% end %>
|
||||
@@ -1,154 +0,0 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%= toolbar title: t(:label_meeting),
|
||||
link_to: link_to(@meeting),
|
||||
html: { class: "meeting--main-toolbar -with-dropdown" } do %>
|
||||
<% unless User.current.anonymous? %>
|
||||
<li class="toolbar-item hidden-for-tablet">
|
||||
<div class="button">
|
||||
<%= watcher_link @meeting, User.current %>
|
||||
</div>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if authorize_for(:meetings, :edit) %>
|
||||
<li class="toolbar-item">
|
||||
<%= link_to(edit_project_meeting_path(@project, @meeting), class: "button", accesskey: accesskey(:edit)) do %>
|
||||
<%= op_icon("button--icon icon-edit") %>
|
||||
<span class="button--text"><%= t(:button_edit) %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<li class="toolbar-item drop-down">
|
||||
<a
|
||||
href="#"
|
||||
aria-haspopup="true"
|
||||
title="<%= t(:label_more) %>"
|
||||
class="button"
|
||||
data-test-selector="meetings-more-dropdown-menu">
|
||||
<%= op_icon("button--icon icon-show-more") %>
|
||||
</a>
|
||||
<ul style="display:none;" class="menu-drop-down-container">
|
||||
<% if authorize_for(:meetings, :notify) %>
|
||||
<li>
|
||||
<%= link_to t("meeting.label_mail_all_participants"),
|
||||
notify_project_meeting_path(@project, @meeting),
|
||||
class: "icon-context icon-mail1",
|
||||
method: :post %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if authorize_for(:meetings, :icalendar) %>
|
||||
<li>
|
||||
<%= link_to t(:label_icalendar_download),
|
||||
download_ics_project_meeting_path(@project, @meeting),
|
||||
class: "icon-context icon-calendar2" %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if authorize_for(:meetings, :copy) %>
|
||||
<li>
|
||||
<%= link_to(
|
||||
t(:button_copy),
|
||||
copy_project_meeting_path(@project, @meeting),
|
||||
class: "icon-context icon-copy"
|
||||
) %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if authorize_for(:meetings, :destroy) %>
|
||||
<li>
|
||||
<%= link_to(
|
||||
t(:button_delete),
|
||||
project_meeting_path(@project, @meeting),
|
||||
class: "icon-context icon-delete",
|
||||
method: :delete,
|
||||
data: { confirm: t(:text_are_you_sure) }
|
||||
) %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<div class="meeting details box">
|
||||
<div class="grid-block wrap">
|
||||
<div class="grid-content small-12 block--author">
|
||||
<%= avatar(@meeting.author) %>
|
||||
<p class="author"><%= authoring @meeting.created_at, @meeting.author %></p>
|
||||
</div>
|
||||
<div class="grid-content small-6">
|
||||
<p>
|
||||
<strong><%= Meeting.human_attribute_name(:start_time) %></strong>: <%= format_date @meeting.start_time %> <%= format_time @meeting.start_time, include_date: false %>
|
||||
- <%= format_time @meeting.end_time, include_date: false %> <%= formatted_time_zone_offset %></p>
|
||||
</div>
|
||||
<div class="grid-content small-6">
|
||||
<p>
|
||||
<strong><%= Meeting.human_attribute_name(:location) %></strong>: <%= auto_link(h(@meeting.location), link: :all, html: { target: "_blank" }) %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid-content small-12">
|
||||
<p>
|
||||
<strong><%= Meeting.human_attribute_name(:participants_invited) %></strong>: <%= format_participant_list @meeting.participants.invited %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid-content small-12">
|
||||
<p>
|
||||
<strong><%= Meeting.human_attribute_name(:participants_attended) %></strong>: <%= format_participant_list @meeting.participants.attended %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render_tabs(
|
||||
[
|
||||
{ name: "agenda",
|
||||
action: :create_meeting_agendas,
|
||||
partial: "meeting_contents/show",
|
||||
path: meeting_agenda_path(@meeting),
|
||||
label: :label_meeting_agenda,
|
||||
content: @meeting.agenda || @meeting.build_agenda,
|
||||
content_type: "meeting_agenda" },
|
||||
{
|
||||
name: "minutes",
|
||||
action: :create_meeting_minutes,
|
||||
partial: "meeting_contents/show",
|
||||
path: meeting_minutes_path(@meeting),
|
||||
label: :label_meeting_minutes, content: @meeting.minutes || @meeting.build_minutes,
|
||||
content_type: "meeting_minutes"
|
||||
}
|
||||
]
|
||||
) %>
|
||||
|
||||
<% if @meeting.journals.changing.present? %>
|
||||
<div id="history">
|
||||
<h3><%= t(:label_history) %></h3>
|
||||
<% @meeting.journals.each do |journal| %>
|
||||
<%= render_meeting_journal @meeting, journal %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -82,11 +82,9 @@ en:
|
||||
invalid_time_format: "is not a valid time. Required format: HH:MM"
|
||||
models:
|
||||
recurring_meeting: "Recurring meeting"
|
||||
structured_meeting: "One-time meeting"
|
||||
meeting: "Meeting"
|
||||
meeting: "One-time meeting"
|
||||
meeting_agenda_item: "Agenda item"
|
||||
meeting_agenda: "Agenda"
|
||||
meeting_minutes: "Minutes"
|
||||
meeting_section: "Section"
|
||||
|
||||
activity:
|
||||
@@ -234,9 +232,6 @@ en:
|
||||
new_date_time: "New date/time"
|
||||
label_mail_all_participants: "Send email to all participants"
|
||||
types:
|
||||
classic: "Classic (unsupported)"
|
||||
classic_text: "Note: Classic meetings will be removed in the next version of OpenProject."
|
||||
structured: "Structured"
|
||||
one_time: "One-time"
|
||||
recurring: "Recurring"
|
||||
recurring_text: "Create meeting series with dynamic template for each occurrence."
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CreateMeetingSections < ActiveRecord::Migration[7.1]
|
||||
def up
|
||||
create_table :meeting_sections do |t|
|
||||
@@ -24,7 +25,7 @@ class CreateMeetingSections < ActiveRecord::Migration[7.1]
|
||||
private
|
||||
|
||||
def create_and_assign_default_section
|
||||
StructuredMeeting.includes(:agenda_items).find_each do |meeting|
|
||||
Meeting.includes(:agenda_items).find_each do |meeting|
|
||||
section = MeetingSection.create!(
|
||||
meeting:,
|
||||
title: "Untitled"
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# 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 API
|
||||
module V3
|
||||
module MeetingAgendas
|
||||
class MeetingAgendaRepresenter < API::V3::MeetingContents::MeetingContentRepresenter
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,58 +0,0 @@
|
||||
# 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 API
|
||||
module V3
|
||||
module MeetingContents
|
||||
class MeetingContentRepresenter < ::API::Decorators::Single
|
||||
include API::Decorators::LinkedResource
|
||||
include API::Caching::CachedRepresenter
|
||||
include ::API::V3::Attachments::AttachableRepresenterMixin
|
||||
|
||||
self_link title_getter: ->(*) {}
|
||||
|
||||
property :id
|
||||
|
||||
associated_resource :project,
|
||||
link: ->(*) do
|
||||
next unless represented.project.present?
|
||||
|
||||
{
|
||||
href: api_v3_paths.project(represented.project.id),
|
||||
title: represented.project.name
|
||||
}
|
||||
end
|
||||
|
||||
def _type
|
||||
"MeetingContent"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,37 +0,0 @@
|
||||
# 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 API
|
||||
module V3
|
||||
module MeetingMinutes
|
||||
class MeetingMinutesRepresenter < API::V3::MeetingContents::MeetingContentRepresenter
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -48,10 +48,6 @@ module API
|
||||
lock_version.to_i
|
||||
}
|
||||
|
||||
property :type,
|
||||
as: :meeting_type,
|
||||
getter: ->(*) { type }
|
||||
|
||||
date_time_property :start_time
|
||||
date_time_property :end_time
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ RSpec.describe Meetings::DeleteDialogComponent, type: :component do
|
||||
|
||||
context "with an associated recurring/templated meeting" do
|
||||
let(:series) { build_stubbed(:recurring_meeting) }
|
||||
let(:meeting) { build_stubbed(:structured_meeting_template, recurring_meeting: series) }
|
||||
let(:meeting) { build_stubbed(:meeting_template, recurring_meeting: series) }
|
||||
|
||||
it "shows a heading" do
|
||||
expect(subject).to have_text "Cancel this meeting occurrence?"
|
||||
|
||||
@@ -61,7 +61,7 @@ RSpec.describe Meetings::RowComponent, type: :component do
|
||||
|
||||
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:) }
|
||||
let(:meeting) { build_stubbed(:meeting_template, recurring_meeting: series, project:) }
|
||||
|
||||
it "shows default menu items" do
|
||||
expect(subject).to have_link "View meeting series"
|
||||
@@ -99,7 +99,7 @@ RSpec.describe Meetings::RowComponent, type: :component do
|
||||
|
||||
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:) }
|
||||
let(:meeting) { build_stubbed(:meeting_template, recurring_meeting: series, project:) }
|
||||
|
||||
context "without a current project" do
|
||||
it "shows delete menu item with a back url" do
|
||||
|
||||
@@ -49,7 +49,7 @@ RSpec.describe Meetings::SidePanel::DetailsComponent, type: :component do
|
||||
frequency: "working_days")
|
||||
end
|
||||
let(:meeting) do
|
||||
build_stubbed(:structured_meeting_template,
|
||||
build_stubbed(:meeting_template,
|
||||
recurring_meeting: series)
|
||||
end
|
||||
|
||||
@@ -65,7 +65,7 @@ RSpec.describe Meetings::SidePanel::DetailsComponent, type: :component do
|
||||
frequency: "weekly")
|
||||
end
|
||||
let(:meeting) do
|
||||
build_stubbed(:structured_meeting_template,
|
||||
build_stubbed(:meeting_template,
|
||||
recurring_meeting: series)
|
||||
end
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe RecurringMeetings::DeleteDialogComponent, type: :component do
|
||||
|
||||
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(:meeting) { build_stubbed(:meeting_template, recurring_meeting:) }
|
||||
let(:user) { build_stubbed(:user) }
|
||||
|
||||
subject do
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ RSpec.describe RecurringMeetings::DeleteScheduledDialogComponent, type: :compone
|
||||
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(:meeting) { build_stubbed(:meeting_template, recurring_meeting:) }
|
||||
let(:user) { build_stubbed(:user) }
|
||||
|
||||
subject do
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe MeetingAgendaItems::CreateContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
let(:meeting) { create(:structured_meeting, project:) }
|
||||
let(:meeting) { create(:meeting, project:) }
|
||||
let(:item) { build(:meeting_agenda_item, meeting:) }
|
||||
let(:contract) { described_class.new(item, user) }
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe MeetingAgendaItems::DeleteContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
shared_let(:meeting) { create(:structured_meeting, project:) }
|
||||
shared_let(:meeting) { create(:meeting, project:) }
|
||||
shared_let(:item) { create(:meeting_agenda_item, meeting:) }
|
||||
let(:contract) { described_class.new(item, user) }
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe MeetingAgendaItems::UpdateContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
shared_let(:meeting) { create(:structured_meeting, project:) }
|
||||
shared_let(:meeting) { create(:meeting, project:) }
|
||||
shared_let(:item) { create(:meeting_agenda_item, meeting:) }
|
||||
let(:contract) { described_class.new(item, user) }
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
# 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 "contracts/shared/model_contract_shared_context"
|
||||
|
||||
RSpec.describe MeetingContents::UpdateContract do
|
||||
include_context "ModelContract shared context"
|
||||
let(:agenda) { build_stubbed(:meeting_agenda) }
|
||||
let(:current_user) { build_stubbed(:user) }
|
||||
let(:contract) { described_class.new(agenda, current_user) }
|
||||
|
||||
context "when not editable" do
|
||||
before do
|
||||
allow(agenda).to receive(:editable?).and_return false
|
||||
end
|
||||
|
||||
it_behaves_like "contract is invalid", base: :error_readonly
|
||||
end
|
||||
|
||||
context "when editable" do
|
||||
before do
|
||||
allow(agenda).to receive(:editable?).and_return true
|
||||
end
|
||||
|
||||
it_behaves_like "contract is valid"
|
||||
end
|
||||
|
||||
include_examples "contract reuses the model errors"
|
||||
end
|
||||
@@ -35,7 +35,7 @@ RSpec.describe MeetingOutcomes::CreateContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
let(:meeting) { create(:structured_meeting, project:) }
|
||||
let(:meeting) { create(:meeting, project:) }
|
||||
let(:meeting_agenda_item) { create(:meeting_agenda_item, meeting:) }
|
||||
let(:outcome) { build(:meeting_outcome, meeting_agenda_item:) }
|
||||
let(:contract) { described_class.new(outcome, user) }
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe MeetingOutcomes::DeleteContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
shared_let(:meeting) { create(:structured_meeting, project:) }
|
||||
shared_let(:meeting) { create(:meeting, project:) }
|
||||
let(:meeting_agenda_item) { create(:meeting_agenda_item, meeting:) }
|
||||
let(:outcome) { build_stubbed(:meeting_outcome, meeting_agenda_item:) }
|
||||
let(:contract) { described_class.new(outcome, user) }
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe MeetingOutcomes::UpdateContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
let(:meeting) { create(:structured_meeting, project:) }
|
||||
let(:meeting) { create(:meeting, project:) }
|
||||
let(:meeting_agenda_item) { create(:meeting_agenda_item, meeting:) }
|
||||
let(:outcome) { build(:meeting_outcome, meeting_agenda_item:) }
|
||||
let(:contract) { described_class.new(outcome, user) }
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe MeetingSections::CreateContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
let(:meeting) { create(:structured_meeting, project:) }
|
||||
let(:meeting) { create(:meeting, project:) }
|
||||
let(:section) { build(:meeting_section, meeting:) }
|
||||
let(:contract) { described_class.new(section, user) }
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe MeetingSections::DeleteContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
shared_let(:meeting) { create(:structured_meeting, project:) }
|
||||
shared_let(:meeting) { create(:meeting, project:) }
|
||||
let(:section) { create(:meeting_section, meeting:) }
|
||||
let(:contract) { described_class.new(section, user) }
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe MeetingSections::UpdateContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
shared_let(:meeting) { create(:structured_meeting, project:) }
|
||||
shared_let(:meeting) { create(:meeting, project:) }
|
||||
shared_let(:section) { create(:meeting_section, meeting:) }
|
||||
let(:contract) { described_class.new(section, user) }
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe Meetings::CreateContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
let(:meeting) { build(:structured_meeting, project:) }
|
||||
let(:meeting) { build(:meeting, project:) }
|
||||
let(:contract) { described_class.new(meeting, user) }
|
||||
|
||||
context "with permission" do
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe Meetings::UpdateContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
shared_let(:meeting) { create(:structured_meeting, project:) }
|
||||
shared_let(:meeting) { create(:meeting, project:) }
|
||||
let(:contract) { described_class.new(meeting, user) }
|
||||
|
||||
context "with permission" do
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
# 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 "#{File.dirname(__FILE__)}/../spec_helper"
|
||||
|
||||
RSpec.describe MeetingsController do
|
||||
shared_let(:user) { create(:admin) }
|
||||
shared_let(:project) { create(:project) }
|
||||
shared_let(:other_project) { create(:project) }
|
||||
|
||||
current_user { user }
|
||||
|
||||
describe "GET" do
|
||||
describe "index" do
|
||||
let(:meetings) do
|
||||
[
|
||||
create(:meeting, project:),
|
||||
create(:meeting, author: user, project:),
|
||||
create(:meeting, author: user, project: other_project)
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
describe "show" do
|
||||
let(:meeting) { create(:meeting, project:, agenda: nil) }
|
||||
|
||||
describe "html" do
|
||||
before do
|
||||
get "show", params: { id: meeting.id }
|
||||
end
|
||||
|
||||
it { expect(response).to redirect_to(project_meeting_path(project, meeting)) }
|
||||
it { expect(assigns(:meeting)).to eql meeting }
|
||||
end
|
||||
end
|
||||
|
||||
describe "new" do
|
||||
let(:meeting) { Meeting.new(project:) }
|
||||
|
||||
before do
|
||||
allow(Project).to receive(:find).and_return(project)
|
||||
allow(Meeting).to receive(:new).and_return(meeting)
|
||||
end
|
||||
|
||||
shared_examples_for "new action" do |response_type:|
|
||||
describe response_type do
|
||||
context "when requesting the page without a project id" do
|
||||
before do
|
||||
get "new"
|
||||
end
|
||||
|
||||
it { expect(response).to be_successful }
|
||||
it { expect(assigns(:meeting)).to eql meeting }
|
||||
it { expect(assigns(:project)).to be_nil }
|
||||
end
|
||||
|
||||
context "when requesting the page with a project id" do
|
||||
before do
|
||||
get "new", params: { project_id: project.id }
|
||||
end
|
||||
|
||||
it { expect(response).to be_successful }
|
||||
it { expect(assigns(:meeting)).to eql meeting }
|
||||
it { expect(assigns(:project)).to eql project }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like "new action", response_type: "html"
|
||||
it_behaves_like "new action", response_type: "turbo_stream"
|
||||
end
|
||||
|
||||
describe "edit" do
|
||||
let(:meeting) { create(:meeting, project:) }
|
||||
|
||||
describe "html" do
|
||||
before do
|
||||
get "edit", params: { project_id: meeting.project_id, id: meeting.id }
|
||||
end
|
||||
|
||||
it { expect(response).to be_successful }
|
||||
it { expect(assigns(:meeting)).to eql meeting }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST" do
|
||||
describe "create" do
|
||||
render_views
|
||||
|
||||
let(:base_params) do
|
||||
{
|
||||
project_id: project&.id,
|
||||
meeting: meeting_params
|
||||
}
|
||||
end
|
||||
|
||||
let(:base_meeting_params) do
|
||||
{
|
||||
title: "Foobar",
|
||||
duration: "1.0",
|
||||
start_date: "2015-06-01",
|
||||
start_time_hour: "10:00"
|
||||
}
|
||||
end
|
||||
|
||||
let(:params) { base_params }
|
||||
let(:meeting_params) { base_meeting_params }
|
||||
|
||||
before do
|
||||
post :create,
|
||||
params:
|
||||
end
|
||||
|
||||
context "with a project_id" do
|
||||
context "and an invalid start_date with start_time_hour" do
|
||||
let(:meeting_params) do
|
||||
base_meeting_params.merge(start_date: "-")
|
||||
end
|
||||
|
||||
it "renders an error" do
|
||||
expect(response).to have_http_status :unprocessable_entity
|
||||
expect(response).to render_template :new
|
||||
expect(response.body)
|
||||
.to have_text("Date #{I18n.t('activerecord.errors.messages.not_an_iso_date')}")
|
||||
end
|
||||
end
|
||||
|
||||
context "and an invalid start_time_hour with start_date" do
|
||||
let(:meeting_params) do
|
||||
base_meeting_params.merge(start_time_hour: "-")
|
||||
end
|
||||
|
||||
it "renders an error" do
|
||||
expect(response).to have_http_status :unprocessable_entity
|
||||
expect(response).to render_template :new
|
||||
expect(response.body)
|
||||
.to have_text("Start time #{I18n.t('activerecord.errors.messages.invalid_time_format')}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with a nil project_id" do
|
||||
let(:project) { nil }
|
||||
|
||||
it "renders an error" do
|
||||
expect(response).to have_http_status :unprocessable_entity
|
||||
expect(response).to render_template :new
|
||||
expect(response.body)
|
||||
.to have_text("Project #{I18n.t('activerecord.errors.messages.blank')}")
|
||||
end
|
||||
end
|
||||
|
||||
context "without a project_id" do
|
||||
let(:params) { base_params.except(:project_id) }
|
||||
let(:project) { nil }
|
||||
|
||||
it "renders an error" do
|
||||
expect(response).to have_http_status :unprocessable_entity
|
||||
expect(response).to render_template :new
|
||||
expect(response.body)
|
||||
.to have_text("Project #{I18n.t('activerecord.errors.messages.blank')}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "notify" do
|
||||
let!(:meeting) { create(:meeting) }
|
||||
let!(:participant) { create(:meeting_participant, meeting:, attended: true) }
|
||||
|
||||
it "produces a background job for notification" do
|
||||
post :notify, params: { project_id: meeting.project_id, id: meeting.id }
|
||||
|
||||
perform_enqueued_jobs
|
||||
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
||||
end
|
||||
|
||||
context "with an error during deliver" do
|
||||
before do
|
||||
allow(MeetingMailer).to receive(:invited).and_raise(Net::SMTPError)
|
||||
end
|
||||
|
||||
it "produces a flash message containing the mail addresses raising the error" do
|
||||
expect { post :notify, params: { project_id: meeting.project_id, id: meeting.id } }.not_to raise_error
|
||||
meeting.participants.each do |participant|
|
||||
expect(flash[:error]).to include(participant.name)
|
||||
end
|
||||
|
||||
perform_enqueued_jobs
|
||||
expect(ActionMailer::Base.deliveries.count).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,34 +0,0 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
FactoryBot.define do
|
||||
factory :meeting_agenda do |_a|
|
||||
meeting
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -29,7 +30,7 @@
|
||||
|
||||
FactoryBot.define do
|
||||
factory :meeting_agenda_item do |m|
|
||||
meeting factory: :structured_meeting
|
||||
meeting factory: :meeting
|
||||
work_package { nil }
|
||||
author factory: :user
|
||||
duration_in_minutes { 10 }
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
FactoryBot.define do
|
||||
factory :journal_meeting_content_journal, class: "Journal::MeetingContentJournal" do
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -47,12 +48,8 @@ FactoryBot.define do
|
||||
meeting.project = evaluator.project if evaluator.project
|
||||
end
|
||||
|
||||
factory :structured_meeting, class: "StructuredMeeting" do |structured_meeting|
|
||||
structured_meeting.sequence(:title) { |n| "Structured meeting #{n}" }
|
||||
end
|
||||
|
||||
factory :structured_meeting_template, class: "StructuredMeeting" do |structured_meeting|
|
||||
structured_meeting.sequence(:title) { |n| "Structured meeting template #{n}" }
|
||||
factory :meeting_template do |meeting|
|
||||
meeting.sequence(:title) { |n| "Meeting template #{n}" }
|
||||
template { true }
|
||||
recurring_meeting
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
FactoryBot.define do
|
||||
factory :meeting_minutes do |_m|
|
||||
meeting
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -29,7 +30,7 @@
|
||||
|
||||
FactoryBot.define do
|
||||
factory :meeting_section do |m|
|
||||
meeting factory: :structured_meeting
|
||||
meeting factory: :meeting
|
||||
|
||||
m.sequence(:title) { |n| "Section #{n}" }
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -48,7 +49,7 @@ FactoryBot.define do
|
||||
recurring_meeting.project = project
|
||||
|
||||
# create template
|
||||
template = create(:structured_meeting_template,
|
||||
template = create(:meeting_template,
|
||||
:author_participates,
|
||||
author: recurring_meeting.author,
|
||||
recurring_meeting:,
|
||||
|
||||
@@ -34,8 +34,6 @@ RSpec.describe "Meetings", :js do
|
||||
let(:user) { create(:admin) }
|
||||
|
||||
let!(:meeting) { create(:meeting, project:, title: "Awesome meeting!") }
|
||||
let!(:agenda) { create(:meeting_agenda, meeting:, text: "foo") }
|
||||
let!(:minutes) { create(:meeting_minutes, meeting:, text: "minutes") }
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
@@ -47,9 +45,6 @@ RSpec.describe "Meetings", :js do
|
||||
|
||||
check "Meetings"
|
||||
click_on "Apply"
|
||||
|
||||
expect(page).to have_css(".op-activity-list--item-title", text: "Minutes: Awesome meeting!")
|
||||
expect(page).to have_css(".op-activity-list--item-title", text: "Agenda: Awesome meeting!")
|
||||
expect(page).to have_css(".op-activity-list--item-title", text: "Meeting: Awesome meeting!")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
require "spec_helper"
|
||||
require "features/page_objects/notification"
|
||||
|
||||
RSpec.describe "Add an attachment to a meeting (agenda)", :js, :selenium do
|
||||
let(:role) do
|
||||
create(:project_role, permissions: %i[view_meetings edit_meetings create_meeting_agendas])
|
||||
end
|
||||
|
||||
let(:dev) do
|
||||
create(:user, member_with_roles: { project => role })
|
||||
end
|
||||
|
||||
let(:project) { create(:project) }
|
||||
|
||||
let(:meeting) do
|
||||
create(
|
||||
:meeting,
|
||||
project:,
|
||||
title: "Versammlung",
|
||||
agenda: create(:meeting_agenda, text: "Versammlung")
|
||||
)
|
||||
end
|
||||
|
||||
let(:attachments) { Components::Attachments.new }
|
||||
let(:image_fixture) { UploadedFile.load_from("spec/fixtures/files/image.png") }
|
||||
let(:editor) { Components::WysiwygEditor.new }
|
||||
let(:attachments_list) { Components::AttachmentsList.new }
|
||||
|
||||
before do
|
||||
login_as(dev)
|
||||
|
||||
visit "/meetings/#{meeting.id}"
|
||||
|
||||
within "#tab-content-agenda .toolbar" do
|
||||
click_on "Edit"
|
||||
end
|
||||
end
|
||||
|
||||
describe "wysiwyg editor" do
|
||||
context "if on an existing page" do
|
||||
it "can upload an image via drag & drop" do
|
||||
find(".ck-content")
|
||||
|
||||
editor.expect_button "Upload image from computer"
|
||||
|
||||
editor.drag_attachment image_fixture.path, "Some image caption"
|
||||
|
||||
click_on "Save"
|
||||
|
||||
content = find_test_selector("op-meeting--meeting_agenda")
|
||||
|
||||
expect(content).to have_css("img")
|
||||
expect(content).to have_content("Some image caption")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "attachment dropzone" do
|
||||
it "can upload an image via attaching and drag & drop" do
|
||||
editor.wait_until_loaded
|
||||
attachments_list.wait_until_visible
|
||||
|
||||
##
|
||||
# Attach file manually
|
||||
editor.attachments_list.expect_empty
|
||||
attachments.attach_file_on_input(image_fixture.path)
|
||||
editor.wait_until_upload_progress_toaster_cleared
|
||||
editor.attachments_list.expect_attached("image.png")
|
||||
|
||||
##
|
||||
# and via drag & drop
|
||||
editor.attachments_list.drag_enter
|
||||
editor.attachments_list.drop(image_fixture)
|
||||
editor.wait_until_upload_progress_toaster_cleared
|
||||
editor.attachments_list.expect_attached("image.png", count: 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,97 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe "Meetings close" do
|
||||
let(:project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
let(:user) do
|
||||
create(:user,
|
||||
member_with_permissions: { project => permissions })
|
||||
end
|
||||
let(:other_user) do
|
||||
create(:user,
|
||||
member_with_permissions: { project => permissions })
|
||||
end
|
||||
|
||||
let!(:meeting) { create(:meeting, :author_participates, project:, title: "Own awesome meeting!", author: user) }
|
||||
let!(:meeting_agenda) { create(:meeting_agenda, meeting:, text: "asdf") }
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
context "with permission to close meetings",
|
||||
:js do
|
||||
let(:permissions) { %i[view_meetings close_meeting_agendas] }
|
||||
|
||||
it "can delete own and other`s meetings" do
|
||||
visit project_meetings_path(project)
|
||||
|
||||
click_on meeting.title
|
||||
|
||||
# Go to minutes, expect uneditable
|
||||
find(".op-tab-row--link", text: "MINUTES").click
|
||||
wait_for_network_idle
|
||||
expect(page).to have_css(".button", text: "Close the agenda to begin the Minutes")
|
||||
|
||||
# Close the meeting
|
||||
find(".op-tab-row--link", text: "AGENDA").click
|
||||
wait_for_network_idle
|
||||
|
||||
accept_confirm do
|
||||
find(".button", text: "Close").click
|
||||
end
|
||||
|
||||
# Expect to be on minutes
|
||||
expect(page).to have_css(".op-tab-row--link_selected", text: "MINUTES")
|
||||
|
||||
# Copies the text
|
||||
expect(page).to have_css("#tab-content-minutes", text: "asdf")
|
||||
|
||||
# Go back to agenda, expect we can open it again
|
||||
find(".op-tab-row--link", text: "AGENDA").click
|
||||
accept_confirm do
|
||||
find(".button", text: "Open").click
|
||||
end
|
||||
expect(page).to have_css(".button", text: "Close")
|
||||
end
|
||||
end
|
||||
|
||||
context "without permission to close meetings" do
|
||||
let(:permissions) { %i[view_meetings] }
|
||||
|
||||
it "cannot delete own and other`s meetings" do
|
||||
visit project_meetings_path(project)
|
||||
|
||||
expect(page)
|
||||
.to have_no_link "Close"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,133 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe "Meetings copy", :js do
|
||||
shared_let(:project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
shared_let(:permissions) { %i[view_meetings create_meetings] }
|
||||
shared_let(:user) do
|
||||
create(:user,
|
||||
member_with_permissions: { project => permissions }).tap do |u|
|
||||
u.pref[:time_zone] = "Etc/UTC"
|
||||
|
||||
u.save!
|
||||
end
|
||||
end
|
||||
shared_let(:other_user) do
|
||||
create(:user,
|
||||
member_with_permissions: { project => permissions })
|
||||
end
|
||||
|
||||
shared_let(:start_time) { Time.current.next_day.at_noon }
|
||||
shared_let(:duration) { 1.5 }
|
||||
shared_let(:agenda_text) { "We will talk" }
|
||||
shared_let(:meeting) do
|
||||
create(:meeting,
|
||||
:author_participates,
|
||||
author: user,
|
||||
project:,
|
||||
title: "Awesome meeting!",
|
||||
location: "Meeting room",
|
||||
duration:,
|
||||
start_time:).tap do |m|
|
||||
create(:meeting_agenda, meeting: m, text: agenda_text)
|
||||
create(:meeting_participant, :attendee, meeting: m, user: other_user)
|
||||
end
|
||||
end
|
||||
|
||||
shared_let(:twelve_hour_format) { "%I:%M %p" }
|
||||
shared_let(:copied_meeting_time_heading) do
|
||||
date = (start_time + 1.day).strftime("%m/%d/%Y")
|
||||
start_of_meeting = start_time.strftime(twelve_hour_format)
|
||||
end_of_meeting = (start_time + meeting.duration.hours).strftime(twelve_hour_format)
|
||||
|
||||
"Start time: #{date} #{start_of_meeting} - #{end_of_meeting} UTC+00:00"
|
||||
end
|
||||
|
||||
before do
|
||||
login_as user
|
||||
end
|
||||
|
||||
it "copying a meeting" do
|
||||
visit project_meetings_path(project)
|
||||
|
||||
click_on meeting.title
|
||||
|
||||
find_test_selector("meetings-more-dropdown-menu").click
|
||||
page.within(".menu-drop-down-container") do
|
||||
click_on "Copy"
|
||||
end
|
||||
|
||||
expect(page)
|
||||
.to have_field "Title", with: meeting.title
|
||||
expect(page)
|
||||
.to have_field "Location", with: meeting.location
|
||||
expect(page)
|
||||
.to have_field "Duration", with: meeting.duration
|
||||
expect(page)
|
||||
.to have_field "Start date", with: (start_time + 1.day).strftime("%Y-%m-%d")
|
||||
expect(page)
|
||||
.to have_field "Time", with: start_time.strftime("%H:%M")
|
||||
|
||||
click_on "Create"
|
||||
|
||||
# Be on the new meeting's page with copied over attributes
|
||||
expect(page).to have_no_current_path meeting_path(meeting.id)
|
||||
|
||||
expect(page)
|
||||
.to have_content("Added by #{user.name}")
|
||||
expect(page)
|
||||
.to have_content("Meeting: #{meeting.title}")
|
||||
expect(page)
|
||||
.to have_content(copied_meeting_time_heading)
|
||||
expect(page)
|
||||
.to have_content("Location: #{meeting.location}")
|
||||
|
||||
# Copies the invitees
|
||||
expect(page)
|
||||
.to have_content "Invitees: #{other_user.name}"
|
||||
|
||||
# Does not copy the attendees
|
||||
expect(page)
|
||||
.to have_no_content "Attendees: #{other_user.name}"
|
||||
expect(page)
|
||||
.to have_content "Attendees:"
|
||||
|
||||
# Copies the agenda
|
||||
click_on "Agenda"
|
||||
expect(page)
|
||||
.to have_content agenda_text
|
||||
|
||||
# Adds an entry to the history
|
||||
click_on "History"
|
||||
expect(page)
|
||||
.to have_content("Copied from Meeting ##{meeting.id}")
|
||||
end
|
||||
end
|
||||
@@ -1,101 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe "Meetings deletion" do
|
||||
let(:project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
let(:user) do
|
||||
create(:user,
|
||||
member_with_permissions: { project => permissions })
|
||||
end
|
||||
let(:other_user) do
|
||||
create(:user,
|
||||
member_with_permissions: { project => permissions })
|
||||
end
|
||||
|
||||
let!(:meeting) { create(:meeting, project:, title: "Own awesome meeting!", author: user) }
|
||||
let!(:other_meeting) { create(:meeting, project:, title: "Other awesome meeting!", author: other_user) }
|
||||
|
||||
let(:index_path) { project_meetings_path(project) }
|
||||
|
||||
before do
|
||||
create(:meeting_participant, :invitee, user:, meeting:)
|
||||
create(:meeting_participant, :invitee, user:, meeting: other_meeting)
|
||||
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
context "with permission to delete meetings", :js do
|
||||
let(:permissions) { %i[view_meetings delete_meetings] }
|
||||
|
||||
it "can delete own and other's meetings" do
|
||||
visit index_path
|
||||
|
||||
click_on meeting.title
|
||||
accept_confirm do
|
||||
find_test_selector("meetings-more-dropdown-menu").click
|
||||
click_on "Delete"
|
||||
end
|
||||
|
||||
expect(page)
|
||||
.to have_current_path index_path
|
||||
|
||||
click_on other_meeting.title
|
||||
accept_confirm do
|
||||
find_test_selector("meetings-more-dropdown-menu").click
|
||||
click_on "Delete"
|
||||
end
|
||||
|
||||
expect(page)
|
||||
.to have_content(I18n.t("meeting.blankslate.title"))
|
||||
|
||||
expect(page)
|
||||
.to have_current_path index_path
|
||||
end
|
||||
end
|
||||
|
||||
context "without permission to delete meetings" do
|
||||
let(:permissions) { %i[view_meetings] }
|
||||
|
||||
it "cannot delete own and other's meetings" do
|
||||
visit index_path
|
||||
|
||||
click_on meeting.title
|
||||
expect(page)
|
||||
.to have_no_link "Delete"
|
||||
|
||||
visit index_path
|
||||
|
||||
click_on other_meeting.title
|
||||
expect(page)
|
||||
.to have_no_link "Delete"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,66 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe "Meetings locking", :js do
|
||||
let(:project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
let(:user) { create(:admin) }
|
||||
let!(:meeting) { create(:meeting, project:) }
|
||||
let!(:agenda) { create(:meeting_agenda, meeting:) }
|
||||
let(:agenda_field) do
|
||||
TextEditorField.new(page,
|
||||
"",
|
||||
selector: test_selector("op-meeting--meeting_agenda"))
|
||||
end
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
it "shows an error when trying to update a meeting update while editing" do
|
||||
visit meeting_path(meeting)
|
||||
|
||||
# Edit agenda
|
||||
within "#tab-content-agenda" do
|
||||
find(".button--edit-agenda").click
|
||||
|
||||
agenda_field.set_value("Some new text")
|
||||
|
||||
agenda.text = "blabla"
|
||||
agenda.save!
|
||||
|
||||
click_on "Save"
|
||||
end
|
||||
|
||||
expect(page).to have_text "Information has been updated by at least one other user in the meantime."
|
||||
|
||||
agenda_field.expect_value("Some new text")
|
||||
end
|
||||
end
|
||||
@@ -1,349 +0,0 @@
|
||||
# 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/index"
|
||||
|
||||
RSpec.describe "Meetings new", :js do
|
||||
shared_let(:project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
shared_let(:admin) { create(:admin) }
|
||||
let(:time_zone) { "Etc/UTC" }
|
||||
let(:user) do
|
||||
create(:user,
|
||||
lastname: "First",
|
||||
member_with_permissions: { project => permissions }).tap do |u|
|
||||
u.pref[:time_zone] = time_zone
|
||||
|
||||
u.save!
|
||||
end
|
||||
end
|
||||
let(:other_user) do
|
||||
create(:user,
|
||||
lastname: "Second",
|
||||
member_with_permissions: { project => permissions })
|
||||
end
|
||||
let(:permissions) { %i[view_meetings create_meetings] }
|
||||
let(:current_user) { user }
|
||||
|
||||
before do
|
||||
login_as current_user
|
||||
end
|
||||
|
||||
context "when creating a meeting from the global page" do
|
||||
before do
|
||||
other_user
|
||||
project
|
||||
end
|
||||
|
||||
let(:index_page) { Pages::Meetings::Index.new(project: nil) }
|
||||
let(:new_page) { Pages::Meetings::New.new(nil) }
|
||||
|
||||
context "with permission to create meetings" do
|
||||
it "does not render menus" do
|
||||
new_page.visit!
|
||||
new_page.expect_no_main_menu
|
||||
end
|
||||
|
||||
describe "clicking on the create new meeting button" do
|
||||
it "navigates to the global create form" do
|
||||
index_page.visit!
|
||||
index_page.click_create_new
|
||||
expect(page).to have_current_path(new_page.path)
|
||||
end
|
||||
end
|
||||
|
||||
["CET", "UTC", "", "Pacific Time (US & Canada)"].each do |zone|
|
||||
let(:time_zone) { zone }
|
||||
|
||||
it "allows creating a project and handles errors in time zone #{zone}" do
|
||||
new_page.visit!
|
||||
|
||||
expect_angular_frontend_initialized # Wait for project dropdown to be ready
|
||||
|
||||
new_page.set_title "Some title"
|
||||
new_page.set_project project
|
||||
|
||||
new_page.set_start_date "2013-03-28"
|
||||
new_page.set_start_time "13:30"
|
||||
new_page.set_duration "1.5"
|
||||
new_page.invite(other_user)
|
||||
|
||||
show_page = new_page.click_create
|
||||
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
show_page.expect_invited(user, other_user)
|
||||
|
||||
show_page.expect_date_time "03/28/2013 01:30 PM - 03:00 PM"
|
||||
end
|
||||
end
|
||||
|
||||
context "without a title set" do
|
||||
before do
|
||||
new_page.visit!
|
||||
|
||||
# Wait for project dropdown to be initialized
|
||||
expect_angular_frontend_initialized
|
||||
|
||||
new_page.set_project project
|
||||
|
||||
new_page.set_start_date "2013-03-28"
|
||||
new_page.set_start_time "13:30"
|
||||
new_page.set_duration "1.5"
|
||||
new_page.invite(other_user)
|
||||
end
|
||||
|
||||
it "renders a validation error" do
|
||||
expect do
|
||||
new_page.click_create
|
||||
end.not_to change(Query, :count)
|
||||
|
||||
# HTML required attribute validation error
|
||||
expect(page).to have_current_path(new_page.path)
|
||||
end
|
||||
end
|
||||
|
||||
context "without a project set" do
|
||||
before do
|
||||
new_page.visit!
|
||||
new_page.set_title "Some title"
|
||||
new_page.set_start_date "2013-03-28"
|
||||
new_page.set_start_time "13:30"
|
||||
new_page.set_duration "1.5"
|
||||
end
|
||||
|
||||
it "renders a validation error" do
|
||||
new_page.click_create
|
||||
|
||||
expect_flash(type: :error,
|
||||
message: "#{Project.model_name.human} #{I18n.t('activerecord.errors.messages.blank')}")
|
||||
|
||||
new_page.expect_project_dropdown
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "without permission to create meetings" do
|
||||
let(:permissions) { %i[view_meetings] }
|
||||
|
||||
it "shows no edit link" do
|
||||
index_page.visit!
|
||||
|
||||
index_page.expect_no_create_new_button
|
||||
end
|
||||
end
|
||||
|
||||
context "as an admin" do
|
||||
let(:current_user) { admin }
|
||||
|
||||
it "allows creating meeting in a project without members" do
|
||||
new_page.visit!
|
||||
|
||||
expect_angular_frontend_initialized # Wait for project dropdown to be ready
|
||||
|
||||
new_page.set_title "Some title"
|
||||
|
||||
new_page.set_project project
|
||||
|
||||
wait_for_network_idle # Wait for participant section to be fetched
|
||||
|
||||
show_page = new_page.click_create
|
||||
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
# Not sure if that is then intended behaviour but that is what is currently programmed
|
||||
show_page.expect_invited(admin)
|
||||
end
|
||||
|
||||
context "without a project set" do
|
||||
before do
|
||||
new_page.visit!
|
||||
new_page.set_title "Some title"
|
||||
end
|
||||
|
||||
it "renders a validation error" do
|
||||
new_page.click_create
|
||||
|
||||
expect(page).to have_text "#{Project.model_name.human} #{I18n.t('activerecord.errors.messages.blank')}"
|
||||
new_page.expect_project_dropdown
|
||||
end
|
||||
end
|
||||
|
||||
context "without a title set" do
|
||||
before do
|
||||
new_page.visit!
|
||||
|
||||
# Wait for project dropdown to be initialized
|
||||
expect_angular_frontend_initialized
|
||||
|
||||
new_page.set_project project
|
||||
end
|
||||
|
||||
it "renders a validation error" do
|
||||
expect do
|
||||
new_page.click_create
|
||||
end.not_to change(Query, :count)
|
||||
|
||||
# HTML required attribute validation error
|
||||
expect(page).to have_current_path(new_page.path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when creating a meeting from the project-specific page" do
|
||||
let(:index_page) { Pages::Meetings::Index.new(project:) }
|
||||
let(:new_page) { Pages::Meetings::New.new(project) }
|
||||
|
||||
context "with permission to create meetings" do
|
||||
before do
|
||||
other_user
|
||||
end
|
||||
|
||||
describe "clicking on the create new meeting button" do
|
||||
it "navigates to the project-specific create form" do
|
||||
index_page.visit!
|
||||
index_page.click_create_new
|
||||
expect(page).to have_current_path(new_page.path)
|
||||
end
|
||||
end
|
||||
|
||||
["CET", "UTC", "", "Pacific Time (US & Canada)"].each do |zone|
|
||||
let(:time_zone) { zone }
|
||||
|
||||
it "allows creating a project and handles errors in time zone #{zone}" do
|
||||
new_page.visit!
|
||||
|
||||
new_page.set_title "Some title"
|
||||
new_page.set_start_date "2013-03-28"
|
||||
new_page.set_start_time "13:30"
|
||||
new_page.set_duration "1.5"
|
||||
new_page.invite(other_user)
|
||||
|
||||
show_page = new_page.click_create
|
||||
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
show_page.expect_invited(user, other_user)
|
||||
|
||||
show_page.expect_date_time "03/28/2013 01:30 PM - 03:00 PM"
|
||||
end
|
||||
end
|
||||
|
||||
context "without a title set" do
|
||||
before do
|
||||
new_page.visit!
|
||||
new_page.set_start_date "2013-03-28"
|
||||
new_page.set_start_time "13:30"
|
||||
new_page.set_duration "1.5"
|
||||
new_page.invite(other_user)
|
||||
end
|
||||
|
||||
it "renders a validation error" do
|
||||
expect do
|
||||
new_page.click_create
|
||||
end.not_to change(Query, :count)
|
||||
|
||||
# HTML required attribute validation error
|
||||
expect(page).to have_current_path(new_page.path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "without permission to create meetings" do
|
||||
let(:permissions) { %i[view_meetings] }
|
||||
|
||||
it "shows no edit link" do
|
||||
index_page.visit!
|
||||
|
||||
index_page.expect_no_create_new_button
|
||||
end
|
||||
end
|
||||
|
||||
context "as an admin" do
|
||||
let(:current_user) { admin }
|
||||
let(:field) do
|
||||
TextEditorField.new(page,
|
||||
"",
|
||||
selector: test_selector("op-meeting--meeting_agenda"))
|
||||
end
|
||||
|
||||
it "allows creating meeting in a project without members" do
|
||||
new_page.visit!
|
||||
|
||||
new_page.set_title "Some title"
|
||||
|
||||
show_page = new_page.click_create
|
||||
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
# Not sure if that is then intended behaviour but that is what is currently programmed
|
||||
show_page.expect_invited(admin)
|
||||
end
|
||||
|
||||
context "without a title set" do
|
||||
before do
|
||||
new_page.visit!
|
||||
end
|
||||
|
||||
it "renders a validation error" do
|
||||
expect do
|
||||
new_page.click_create
|
||||
end.not_to change(Query, :count)
|
||||
|
||||
# HTML required attribute validation error
|
||||
expect(page).to have_current_path(new_page.path)
|
||||
end
|
||||
end
|
||||
|
||||
it "can save the meeting agenda via cmd+Enter" do
|
||||
new_page.visit!
|
||||
|
||||
new_page.set_title "Some title"
|
||||
|
||||
new_page.click_create
|
||||
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
meeting = Meeting.last
|
||||
|
||||
field.set_value("My new meeting text")
|
||||
|
||||
field.submit_by_enter
|
||||
|
||||
expect_flash(message: "Successful update")
|
||||
|
||||
meeting.reload
|
||||
|
||||
expect(meeting.agenda.text).to eq "My new meeting text"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,97 +0,0 @@
|
||||
# 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/edit"
|
||||
|
||||
RSpec.describe "Meetings participants" do
|
||||
let(:project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
let!(:user) do
|
||||
create(:user,
|
||||
firstname: "Current",
|
||||
member_with_permissions: { project => %i[view_meetings edit_meetings] })
|
||||
end
|
||||
let!(:viewer_user) do
|
||||
create(:user,
|
||||
firstname: "Viewer",
|
||||
member_with_permissions: { project => %i[view_meetings] })
|
||||
end
|
||||
let!(:non_viewer_user) do
|
||||
create(:user,
|
||||
firstname: "Nonviewer",
|
||||
member_with_permissions: { project => %i[] })
|
||||
end
|
||||
let(:edit_page) { Pages::Meetings::Edit.new(meeting) }
|
||||
let!(:meeting) { create(:meeting, project:, title: "Awesome meeting!") }
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
it "allows setting members to participants which are allowed to view the meeting" do
|
||||
edit_page.visit!
|
||||
|
||||
edit_page.expect_available_participant(user)
|
||||
edit_page.expect_available_participant(viewer_user)
|
||||
|
||||
edit_page.expect_not_available_participant(non_viewer_user)
|
||||
|
||||
edit_page.invite(viewer_user)
|
||||
show_page = edit_page.click_save
|
||||
expect_flash(message: "Successful update")
|
||||
|
||||
show_page.expect_invited(viewer_user)
|
||||
|
||||
show_page.click_edit
|
||||
|
||||
edit_page.uninvite(viewer_user)
|
||||
show_page = edit_page.click_save
|
||||
|
||||
expect_flash(message: "Successful update")
|
||||
|
||||
show_page.expect_uninvited(viewer_user)
|
||||
end
|
||||
|
||||
context "with an invalid user reference" do
|
||||
let(:show_page) { Pages::Meetings::Show.new(meeting) }
|
||||
let(:meeting_participant) { create(:meeting_participant, user: viewer_user, meeting:) }
|
||||
|
||||
before do
|
||||
meeting_participant.update_column(:user_id, 12341234)
|
||||
end
|
||||
|
||||
it "still allows to view the meeting" do
|
||||
show_page.visit!
|
||||
|
||||
show_page.expect_invited meeting.author
|
||||
show_page.expect_uninvited viewer_user
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -35,7 +36,7 @@ RSpec.describe "Meeting search", :js do
|
||||
let(:role) { create(:project_role, permissions: %i(view_meetings view_work_packages)) }
|
||||
let(:user) { create(:user, member_with_roles: { project => role }) }
|
||||
|
||||
let!(:meeting) { create(:structured_meeting, project:) }
|
||||
let!(:meeting) { create(:meeting, project:) }
|
||||
let!(:agenda_item) { create(:meeting_agenda_item, meeting:) }
|
||||
|
||||
before do
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
# 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/show"
|
||||
|
||||
RSpec.describe "Meetings", :js do
|
||||
let(:project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
let(:role) { create(:project_role, permissions:) }
|
||||
let(:user) do
|
||||
create(:user,
|
||||
member_with_roles: { project => role })
|
||||
end
|
||||
|
||||
let!(:meeting) { create(:meeting, project:, title: "Awesome meeting!") }
|
||||
let(:show_page) { Pages::Meetings::Show.new(meeting) }
|
||||
|
||||
current_user { user }
|
||||
|
||||
describe "navigate to meeting page" do
|
||||
before do
|
||||
create(:meeting_participant, :invitee, user:, meeting:)
|
||||
end
|
||||
|
||||
let(:permissions) { %i[view_meetings] }
|
||||
|
||||
it "can visit the meeting" do
|
||||
visit meetings_path(project)
|
||||
|
||||
find("div.title a", text: "Awesome meeting!", wait: 10).click
|
||||
expect(page).to have_css("h2", text: "Meeting: Awesome meeting!")
|
||||
|
||||
expect(page).to have_test_selector("op-meeting--meeting_agenda",
|
||||
text: "There is currently nothing to display")
|
||||
end
|
||||
|
||||
context "with a location" do
|
||||
context "as a valid url" do
|
||||
it "renders a link to the meeting location" do
|
||||
show_page.visit!
|
||||
|
||||
show_page.expect_link_to_location(meeting.location)
|
||||
end
|
||||
end
|
||||
|
||||
context "as an invalid url" do
|
||||
before do
|
||||
meeting.update!(location: "badurl")
|
||||
end
|
||||
|
||||
it "renders the meeting location as plaintext" do
|
||||
show_page.visit!
|
||||
|
||||
show_page.expect_plaintext_location(meeting.location)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with an open agenda" do
|
||||
let!(:agenda) { create(:meeting_agenda, meeting:, text: "foo") }
|
||||
let(:agenda_update) { create(:meeting_agenda, meeting:, text: "bla") }
|
||||
|
||||
it "shows the agenda" do
|
||||
visit meeting_path(meeting)
|
||||
expect(page).to have_test_selector("op-meeting--meeting_agenda",
|
||||
text: "foo")
|
||||
|
||||
# May not edit
|
||||
expect(page).to have_no_css(".button--edit-agenda")
|
||||
expect(page).not_to have_test_selector("op-meeting--meeting_agenda",
|
||||
text: "Edit")
|
||||
end
|
||||
|
||||
it "can view history" do
|
||||
agenda_update
|
||||
|
||||
visit meeting_path(meeting)
|
||||
|
||||
click_on "History"
|
||||
|
||||
find_by_id("version-1").click
|
||||
expect(page).to have_test_selector("op-meeting--meeting_agenda", text: "foo")
|
||||
end
|
||||
|
||||
context "and edit permissions" do
|
||||
let(:permissions) { %i[view_meetings create_meeting_agendas] }
|
||||
let(:field) do
|
||||
TextEditorField.new(page,
|
||||
"",
|
||||
selector: test_selector("op-meeting--meeting_agenda"))
|
||||
end
|
||||
|
||||
it "can edit the agenda" do
|
||||
visit meeting_path(meeting)
|
||||
|
||||
find(".toolbar-item", text: "Edit").click
|
||||
|
||||
field.expect_value("foo")
|
||||
|
||||
field.set_value("My new meeting text")
|
||||
|
||||
field.submit_by_enter
|
||||
|
||||
expect_and_dismiss_flash(message: "Successful update")
|
||||
|
||||
meeting.reload
|
||||
|
||||
expect(meeting.agenda.text).to eq "My new meeting text"
|
||||
end
|
||||
end
|
||||
|
||||
context "and edit minutes permissions" do
|
||||
let(:permissions) { %i[view_meetings create_meeting_minutes] }
|
||||
|
||||
it "can not edit the minutes" do
|
||||
visit meeting_path(meeting)
|
||||
click_on "Minutes"
|
||||
expect(page).not_to have_test_selector("op-meeting--meeting_minutes", text: "Edit")
|
||||
expect(page).to have_test_selector("op-meeting--meeting_minutes",
|
||||
text: "There is currently nothing to display")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with a locked agenda" do
|
||||
let!(:agenda) { create(:meeting_agenda, meeting:, text: "foo", locked: true) }
|
||||
|
||||
it "shows the minutes when visiting" do
|
||||
visit meeting_path(meeting)
|
||||
expect(page).to have_no_css("h2", text: "Agenda")
|
||||
expect(page).to have_no_css("#meeting_minutes_text")
|
||||
expect(page).to have_css("h2", text: "Minutes")
|
||||
end
|
||||
|
||||
context "and edit permissions" do
|
||||
let(:permissions) { %i[view_meetings create_meeting_minutes] }
|
||||
let(:field) do
|
||||
TextEditorField.new(page,
|
||||
"",
|
||||
selector: test_selector("op-meeting--meeting_minutes"))
|
||||
end
|
||||
|
||||
it "can edit the minutes" do
|
||||
visit meeting_path(meeting)
|
||||
|
||||
field.set_value("This is what we talked about")
|
||||
|
||||
click_on "Save"
|
||||
|
||||
expect(page)
|
||||
.to have_css(".op-uc-container",
|
||||
text: "This is what we talked about")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -29,8 +30,7 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
require_relative "../../support/pages/recurring_meeting/show"
|
||||
require_relative "../../support/pages/meetings/index"
|
||||
|
||||
@@ -61,7 +61,7 @@ RSpec.describe "Recurring meetings creation",
|
||||
let(:current_user) { user }
|
||||
let(:meeting) { RecurringMeeting.last }
|
||||
let(:show_page) { Pages::RecurringMeeting::Show.new(meeting) }
|
||||
let(:template_page) { Pages::StructuredMeeting::Show.new(meeting.template) }
|
||||
let(:template_page) { Pages::Meetings::Show.new(meeting.template) }
|
||||
let(:meetings_page) { Pages::Meetings::Index.new(project:) }
|
||||
|
||||
before do
|
||||
|
||||
@@ -30,8 +30,7 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
require_relative "../../support/pages/recurring_meeting/show"
|
||||
require_relative "../../support/pages/meetings/index"
|
||||
|
||||
|
||||
+1
-2
@@ -30,8 +30,7 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
require_relative "../../support/pages/recurring_meeting/show"
|
||||
require_relative "../../support/pages/meetings/index"
|
||||
|
||||
|
||||
+1
-2
@@ -29,8 +29,7 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
require_relative "../../support/pages/recurring_meeting/show"
|
||||
require_relative "../../support/pages/meetings/index"
|
||||
|
||||
|
||||
+1
-2
@@ -30,8 +30,7 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
require_relative "../../support/pages/recurring_meeting/show"
|
||||
require_relative "../../support/pages/meetings/index"
|
||||
|
||||
|
||||
+8
-14
@@ -30,8 +30,7 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
require_relative "../../support/pages/recurring_meeting/show"
|
||||
require_relative "../../support/pages/meetings/index"
|
||||
|
||||
@@ -60,8 +59,8 @@ RSpec.describe "Recurring meetings move to next meeting", :js do
|
||||
end_after: "never",
|
||||
author: user_with_manage_permissions
|
||||
end
|
||||
shared_let(:structured_meeting) do
|
||||
create :structured_meeting,
|
||||
shared_let(:meeting) do
|
||||
create :meeting,
|
||||
project:,
|
||||
start_time: DateTime.parse("2025-01-28T10:30:00Z"),
|
||||
duration: 1,
|
||||
@@ -75,10 +74,8 @@ RSpec.describe "Recurring meetings move to next meeting", :js do
|
||||
series.meetings.not_templated.first
|
||||
end
|
||||
|
||||
let!(:agenda_item) { create(:meeting_agenda_item, meeting: structured_meeting, title: "Test notes") }
|
||||
let!(:series_agenda_item) { create(:meeting_agenda_item, meeting: recurring_meeting, title: "Test notes") }
|
||||
|
||||
let(:meeting_page) { Pages::StructuredMeeting::Show.new(meeting) }
|
||||
let!(:agenda_item) { create(:meeting_agenda_item, meeting:, title: "Test notes") }
|
||||
let(:meeting_page) { Pages::Meetings::Show.new(meeting) }
|
||||
|
||||
before do
|
||||
login_as current_user
|
||||
@@ -94,10 +91,9 @@ RSpec.describe "Recurring meetings move to next meeting", :js do
|
||||
|
||||
it "shows the move to next meeting option" do
|
||||
meeting_page.expect_agenda_item(title: "Test notes")
|
||||
meeting_page.expect_agenda_action_menu(series_agenda_item)
|
||||
|
||||
accept_confirm do
|
||||
meeting_page.select_action(series_agenda_item, "Move to next meeting")
|
||||
meeting_page.select_action(agenda_item, "Move to next meeting")
|
||||
end
|
||||
|
||||
meeting_page.expect_no_agenda_item(title: "Test notes")
|
||||
@@ -115,10 +111,9 @@ RSpec.describe "Recurring meetings move to next meeting", :js do
|
||||
|
||||
it "shows the move to next meeting option" do
|
||||
meeting_page.expect_agenda_item(title: "Test notes")
|
||||
meeting_page.expect_agenda_action_menu(series_agenda_item)
|
||||
|
||||
accept_confirm do
|
||||
meeting_page.select_action(series_agenda_item, "Move to next meeting")
|
||||
meeting_page.select_action(agenda_item, "Move to next meeting")
|
||||
end
|
||||
|
||||
expect(page).to have_text "Unable to move to the next meeting since it has been cancelled."
|
||||
@@ -136,8 +131,7 @@ RSpec.describe "Recurring meetings move to next meeting", :js do
|
||||
end
|
||||
end
|
||||
|
||||
context "when viewing a structured meeting" do
|
||||
let(:meeting) { structured_meeting }
|
||||
context "when viewing a one-time meeting" do
|
||||
let(:current_user) { user_with_manage_permissions }
|
||||
|
||||
it "does not show the move to next meeting option" do
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -29,7 +30,7 @@
|
||||
|
||||
require "spec_helper"
|
||||
require "features/page_objects/notification"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
|
||||
RSpec.describe "Upload attachment to meetings", :js do
|
||||
let(:user) do
|
||||
@@ -43,8 +44,8 @@ RSpec.describe "Upload attachment to meetings", :js do
|
||||
let(:wiki_page_content) { project.wiki.pages.first.text }
|
||||
let(:attachment_list) { Components::AttachmentsList.new("#content") }
|
||||
|
||||
let(:meeting) { create(:structured_meeting, project:) }
|
||||
let(:show_page) { Pages::StructuredMeeting::Show.new(meeting) }
|
||||
let(:meeting) { create(:meeting, project:) }
|
||||
let(:show_page) { Pages::Meetings::Show.new(meeting) }
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -29,9 +30,8 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/structured_meeting/history"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
require_relative "../../support/pages/meetings/history"
|
||||
|
||||
RSpec.describe "history",
|
||||
:js do
|
||||
@@ -72,7 +72,7 @@ RSpec.describe "history",
|
||||
end
|
||||
shared_let(:meeting) do
|
||||
User.execute_as(user) do
|
||||
create(:structured_meeting,
|
||||
create(:meeting,
|
||||
project:,
|
||||
start_time: DateTime.parse("2024-03-28T13:30:00Z"),
|
||||
title: "Some title",
|
||||
@@ -82,8 +82,8 @@ RSpec.describe "history",
|
||||
end
|
||||
end
|
||||
|
||||
let(:show_page) { Pages::StructuredMeeting::Show.new(meeting) }
|
||||
let(:history_page) { Pages::StructuredMeeting::History.new(meeting) }
|
||||
let(:show_page) { Pages::Meetings::Show.new(meeting) }
|
||||
let(:history_page) { Pages::Meeting::History.new(meeting) }
|
||||
let(:editor) { Components::WysiwygEditor.new "#content", "opce-ckeditor-augmented-textarea" }
|
||||
|
||||
it "allows browsing the history", with_settings: { journal_aggregation_time_minutes: 0 } do
|
||||
|
||||
+3
-3
@@ -30,7 +30,7 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../../support/pages/structured_meeting/show"
|
||||
require_relative "../../../support/pages/meetings/show"
|
||||
|
||||
RSpec.describe "Meeting Outcomes CRUD", :js do
|
||||
shared_let(:project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
@@ -46,7 +46,7 @@ RSpec.describe "Meeting Outcomes CRUD", :js do
|
||||
member_with_permissions: { project => %i[view_meetings manage_agendas close_meeting_agendas] }
|
||||
end
|
||||
shared_let(:meeting) do
|
||||
create :structured_meeting,
|
||||
create :meeting,
|
||||
project:,
|
||||
start_time: "2024-12-31T13:30:00Z",
|
||||
duration: 1.5,
|
||||
@@ -59,7 +59,7 @@ RSpec.describe "Meeting Outcomes CRUD", :js do
|
||||
|
||||
let(:current_user) { user }
|
||||
let(:state) { :in_progress }
|
||||
let(:show_page) { Pages::StructuredMeeting::Show.new(meeting) }
|
||||
let(:show_page) { Pages::Meetings::Show.new(meeting) }
|
||||
let(:field) do
|
||||
TextEditorField.new(page, "Outcome", selector: test_selector("meeting-outcome-input"))
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -29,9 +30,9 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/structured_meeting//mobile/show"
|
||||
require_relative "../../support/pages/meetings/mobile/show"
|
||||
|
||||
RSpec.describe "Structured meetings CRUD",
|
||||
RSpec.describe "Meetings CRUD",
|
||||
:js do
|
||||
include Components::Autocompleter::NgSelectAutocompleteHelpers
|
||||
|
||||
@@ -57,14 +58,14 @@ RSpec.describe "Structured meetings CRUD",
|
||||
end
|
||||
|
||||
shared_let(:meeting) do
|
||||
create(:structured_meeting,
|
||||
create(:meeting,
|
||||
:author_participates,
|
||||
project:,
|
||||
author: user)
|
||||
end
|
||||
|
||||
let(:current_user) { user }
|
||||
let(:show_page) { Pages::StructuredMeeting::Mobile::Show.new(StructuredMeeting.last) }
|
||||
let(:show_page) { Pages::Meetings::Mobile::Show.new(Meeting.last) }
|
||||
|
||||
include_context "with mobile screen size"
|
||||
|
||||
@@ -73,7 +74,7 @@ RSpec.describe "Structured meetings CRUD",
|
||||
show_page.visit!
|
||||
end
|
||||
|
||||
it "can edit participants of a structured meeting" do
|
||||
it "can edit participants of a meeting" do
|
||||
expect(page).to have_current_path(show_page.path)
|
||||
show_page.expect_participants(count: 1)
|
||||
|
||||
|
||||
@@ -30,11 +30,10 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
require_relative "../../support/pages/meetings/index"
|
||||
|
||||
RSpec.describe "Structured meetings CRUD",
|
||||
RSpec.describe "Meetings CRUD",
|
||||
:js do
|
||||
include Components::Autocompleter::NgSelectAutocompleteHelpers
|
||||
|
||||
@@ -63,9 +62,8 @@ RSpec.describe "Structured meetings CRUD",
|
||||
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(:meeting) { Meeting.last }
|
||||
let(:show_page) { Pages::Meetings::Show.new(meeting) }
|
||||
let(:meetings_page) { Pages::Meetings::Index.new(project:) }
|
||||
|
||||
before do |test|
|
||||
@@ -88,7 +86,7 @@ RSpec.describe "Structured meetings CRUD",
|
||||
meetings_page.click_create
|
||||
end
|
||||
|
||||
it "can create a structured meeting and add agenda items" do
|
||||
it "can create a meeting and add agenda items" do
|
||||
expect_and_dismiss_flash(type: :success, message: "Successful creation")
|
||||
|
||||
# Does not send invitation mails by default
|
||||
@@ -312,7 +310,7 @@ RSpec.describe "Structured meetings CRUD",
|
||||
fill_in "Title", with: "Some title"
|
||||
click_on "Create meeting"
|
||||
|
||||
new_meeting = StructuredMeeting.last
|
||||
new_meeting = Meeting.last
|
||||
expect(page).to have_current_path "/projects/#{project.identifier}/meetings/#{new_meeting.id}"
|
||||
|
||||
# check for copied agenda items
|
||||
@@ -330,13 +328,13 @@ RSpec.describe "Structured meetings CRUD",
|
||||
end
|
||||
|
||||
context "with a work package reference to another" do
|
||||
let!(:meeting) { create(:structured_meeting, project:, author: current_user) }
|
||||
let!(:meeting) { create(:meeting, project:, author: current_user) }
|
||||
let!(:other_project) { create(:project) }
|
||||
let!(:other_wp) { create(:work_package, project: other_project, author: current_user, subject: "Private task") }
|
||||
let!(:role) { create(:project_role, permissions: %w[view_work_packages]) }
|
||||
let!(:membership) { create(:member, principal: user, project: other_project, roles: [role]) }
|
||||
let!(:agenda_item) { create(:wp_meeting_agenda_item, meeting:, author: current_user, work_package: other_wp) }
|
||||
let(:show_page) { Pages::StructuredMeeting::Show.new(meeting) }
|
||||
let(:show_page) { Pages::Meetings::Show.new(meeting) }
|
||||
|
||||
it "shows correctly for author, but returns an unresolved reference for the second user" do
|
||||
show_page.visit!
|
||||
@@ -352,8 +350,8 @@ RSpec.describe "Structured meetings CRUD",
|
||||
end
|
||||
|
||||
context "with sections" do
|
||||
let!(:meeting) { create(:structured_meeting, project:, author: current_user) }
|
||||
let(:show_page) { Pages::StructuredMeeting::Show.new(meeting) }
|
||||
let!(:meeting) { create(:meeting, project:, author: current_user) }
|
||||
let(:show_page) { Pages::Meetings::Show.new(meeting) }
|
||||
|
||||
context "when starting with empty sections" do
|
||||
it "can add, edit and delete sections" do
|
||||
|
||||
@@ -30,11 +30,10 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
require_relative "../../support/pages/meetings/index"
|
||||
|
||||
RSpec.describe "Structured meetings deletion",
|
||||
RSpec.describe "Meetings deletion",
|
||||
:js do
|
||||
include Components::Autocompleter::NgSelectAutocompleteHelpers
|
||||
|
||||
|
||||
+4
-6
@@ -30,11 +30,10 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
require_relative "../../support/pages/meetings/index"
|
||||
|
||||
RSpec.describe "Structured meetings global CRUD", :js do
|
||||
RSpec.describe "Meetings global CRUD", :js do
|
||||
include Components::Autocompleter::NgSelectAutocompleteHelpers
|
||||
|
||||
shared_let(:project) { create(:project, enabled_module_names: %w[meetings work_package_tracking]) }
|
||||
@@ -62,9 +61,8 @@ RSpec.describe "Structured meetings global CRUD", :js do
|
||||
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(:meeting) { Meeting.last }
|
||||
let(:show_page) { Pages::Meetings::Show.new(meeting) }
|
||||
let(:meetings_page) { Pages::Meetings::Index.new(project: nil) }
|
||||
|
||||
before do
|
||||
|
||||
+6
-5
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -29,9 +30,9 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/structured_meeting//mobile/show"
|
||||
require_relative "../../support/pages/meetings/mobile/show"
|
||||
|
||||
RSpec.describe "Structured meetings participants",
|
||||
RSpec.describe "Meetings participants",
|
||||
:js do
|
||||
include Components::Autocompleter::NgSelectAutocompleteHelpers
|
||||
|
||||
@@ -57,21 +58,21 @@ RSpec.describe "Structured meetings participants",
|
||||
end
|
||||
|
||||
shared_let(:meeting) do
|
||||
create(:structured_meeting,
|
||||
create(:meeting,
|
||||
:author_participates,
|
||||
project:,
|
||||
author: user)
|
||||
end
|
||||
|
||||
let(:current_user) { user }
|
||||
let(:show_page) { Pages::StructuredMeeting::Show.new(StructuredMeeting.last) }
|
||||
let(:show_page) { Pages::Meetings::Show.new(Meeting.last) }
|
||||
|
||||
before do
|
||||
login_as current_user
|
||||
show_page.visit!
|
||||
end
|
||||
|
||||
it "can edit participants of a structured meeting" do
|
||||
it "can edit participants of a meeting" do
|
||||
expect(page).to have_current_path(show_page.path)
|
||||
|
||||
show_page.open_participant_form
|
||||
|
||||
+6
-7
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -29,10 +30,9 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
|
||||
RSpec.describe "Structured meetings CRUD",
|
||||
RSpec.describe "Meetings CRUD",
|
||||
:js,
|
||||
:selenium do
|
||||
include Components::Autocompleter::NgSelectAutocompleteHelpers
|
||||
@@ -41,9 +41,8 @@ RSpec.describe "Structured meetings CRUD",
|
||||
shared_let(:user) { create(:admin) }
|
||||
|
||||
current_user { user }
|
||||
let(:new_page) { Pages::Meetings::New.new(project) }
|
||||
let(:meeting) { create(:structured_meeting, project:, author: current_user) }
|
||||
let(:show_page) { Pages::StructuredMeeting::Show.new(meeting) }
|
||||
let(:meeting) { create(:meeting, project:, author: current_user) }
|
||||
let(:show_page) { Pages::Meetings::Show.new(meeting) }
|
||||
|
||||
describe "meeting update flash" do
|
||||
before do
|
||||
@@ -134,7 +133,7 @@ RSpec.describe "Structured meetings CRUD",
|
||||
## Edit meeting details
|
||||
within_window(first_window) do
|
||||
find_test_selector("edit-meeting-details-button").click
|
||||
fill_in "structured_meeting_duration", with: "2.5"
|
||||
fill_in "meeting_duration", with: "2.5"
|
||||
click_link_or_button "Save"
|
||||
|
||||
# Expect updated duration
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -29,10 +30,9 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
require_relative "../../support/pages/meetings/new"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
|
||||
RSpec.describe "Structured meetings links caught by turbo",
|
||||
RSpec.describe "Meetings links caught by turbo",
|
||||
:js do
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
@@ -47,8 +47,8 @@ RSpec.describe "Structured meetings links caught by turbo",
|
||||
u.save!
|
||||
end
|
||||
end
|
||||
shared_let(:meeting1) { create(:structured_meeting, title: "First meeting", project:) }
|
||||
shared_let(:meeting2) { create(:structured_meeting, title: "Other meeting", project:) }
|
||||
shared_let(:meeting1) { create(:meeting, title: "First meeting", project:) }
|
||||
shared_let(:meeting2) { create(:meeting, title: "Other meeting", project:) }
|
||||
|
||||
let(:notes) do
|
||||
<<~NOTES
|
||||
@@ -56,7 +56,7 @@ RSpec.describe "Structured meetings links caught by turbo",
|
||||
NOTES
|
||||
end
|
||||
let!(:agenda_item) { create(:meeting_agenda_item, meeting: meeting1, notes:) }
|
||||
let(:show_page) { Pages::StructuredMeeting::Show.new(meeting1) }
|
||||
let(:show_page) { Pages::Meetings::Show.new(meeting1) }
|
||||
|
||||
before do
|
||||
login_as user
|
||||
|
||||
+15
-15
@@ -30,7 +30,7 @@
|
||||
|
||||
require "spec_helper"
|
||||
require_relative "../../support/pages/work_package_meetings_tab"
|
||||
require_relative "../../support/pages/structured_meeting/show"
|
||||
require_relative "../../support/pages/meetings/show"
|
||||
|
||||
RSpec.describe "Open the Meetings tab",
|
||||
:js do
|
||||
@@ -98,8 +98,8 @@ RSpec.describe "Open the Meetings tab",
|
||||
|
||||
context "when the user has the permission to see the tab, but the work package is linked in two projects" do
|
||||
let(:other_project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
let!(:visible_meeting) { create(:structured_meeting, project:) }
|
||||
let!(:invisible_meeting) { create(:structured_meeting, project: other_project) }
|
||||
let!(:visible_meeting) { create(:meeting, project:) }
|
||||
let!(:invisible_meeting) { create(:meeting, project: other_project) }
|
||||
|
||||
let!(:meeting_agenda_item_of_visible_meeting) do
|
||||
create(:meeting_agenda_item, meeting: visible_meeting, work_package:, notes: "Public note!")
|
||||
@@ -131,7 +131,7 @@ RSpec.describe "Open the Meetings tab",
|
||||
end
|
||||
|
||||
context "with another past meeting" do
|
||||
let!(:past_meeting) { create(:structured_meeting, project:, start_time: 1.week.ago) }
|
||||
let!(:past_meeting) { create(:meeting, project:, start_time: 1.week.ago) }
|
||||
|
||||
let!(:past_agenda_item) do
|
||||
create(:meeting_agenda_item, meeting: past_meeting, work_package:, notes: "Public note!")
|
||||
@@ -225,8 +225,8 @@ RSpec.describe "Open the Meetings tab",
|
||||
end
|
||||
|
||||
context "when the work_package is already referenced in upcoming meetings" do
|
||||
let!(:first_meeting) { create(:structured_meeting, project:) }
|
||||
let!(:second_meeting) { create(:structured_meeting, project:) }
|
||||
let!(:first_meeting) { create(:meeting, project:) }
|
||||
let!(:second_meeting) { create(:meeting, project:) }
|
||||
|
||||
let!(:first_meeting_agenda_item_of_first_meeting) do
|
||||
create(:meeting_agenda_item, meeting: first_meeting, work_package:, notes: "A very important note in first meeting!")
|
||||
@@ -267,7 +267,7 @@ RSpec.describe "Open the Meetings tab",
|
||||
end
|
||||
|
||||
context "when the work_package is referenced and has an outcome" do
|
||||
let!(:meeting) { create(:structured_meeting, project:) }
|
||||
let!(:meeting) { create(:meeting, project:) }
|
||||
|
||||
let!(:meeting_agenda_item) do
|
||||
create(:meeting_agenda_item, meeting:, work_package:, notes: "A very important note in first meeting!")
|
||||
@@ -291,8 +291,8 @@ RSpec.describe "Open the Meetings tab",
|
||||
end
|
||||
|
||||
context "when the work_package was already referenced in past meetings" do
|
||||
let!(:first_past_meeting) { create(:structured_meeting, project:, start_time: Date.yesterday - 11.hours) }
|
||||
let!(:second_past_meeting) { create(:structured_meeting, project:, start_time: Date.yesterday - 10.hours) }
|
||||
let!(:first_past_meeting) { create(:meeting, project:, start_time: Date.yesterday - 11.hours) }
|
||||
let!(:second_past_meeting) { create(:meeting, project:, start_time: Date.yesterday - 10.hours) }
|
||||
|
||||
let!(:first_meeting_agenda_item_of_first_past_meeting) do
|
||||
create(:meeting_agenda_item, meeting: first_past_meeting, work_package:, notes: "A very important note in first meeting!")
|
||||
@@ -347,15 +347,15 @@ RSpec.describe "Open the Meetings tab",
|
||||
end
|
||||
|
||||
context "when open, upcoming meetings are visible for the user" do
|
||||
shared_let(:past_meeting) { create(:structured_meeting, project:, start_time: Date.yesterday - 10.hours) }
|
||||
shared_let(:first_upcoming_meeting) { create(:structured_meeting, project:) }
|
||||
shared_let(:second_upcoming_meeting) { create(:structured_meeting, project:) }
|
||||
shared_let(:closed_upcoming_meeting) { create(:structured_meeting, project:, state: :closed) }
|
||||
shared_let(:past_meeting) { create(:meeting, project:, start_time: Date.yesterday - 10.hours) }
|
||||
shared_let(:first_upcoming_meeting) { create(:meeting, project:) }
|
||||
shared_let(:second_upcoming_meeting) { create(:meeting, project:) }
|
||||
shared_let(:closed_upcoming_meeting) { create(:meeting, project:, state: :closed) }
|
||||
shared_let(:ongoing_meeting) do
|
||||
create(:structured_meeting, title: "Ongoing", project:, start_time: 1.hour.ago, duration: 4.0)
|
||||
create(:meeting, title: "Ongoing", project:, start_time: 1.hour.ago, duration: 4.0)
|
||||
end
|
||||
|
||||
let(:meeting_page) { Pages::StructuredMeeting::Show.new(first_upcoming_meeting) }
|
||||
let(:meeting_page) { Pages::Meetings::Show.new(first_upcoming_meeting) }
|
||||
|
||||
it "enables the user to add the work package to multiple open, upcoming meetings" do
|
||||
work_package_page.visit!
|
||||
|
||||
@@ -45,9 +45,6 @@ RSpec.describe MeetingMailer do
|
||||
author:,
|
||||
project:)
|
||||
end
|
||||
let(:meeting_agenda) do
|
||||
create(:meeting_agenda, meeting:)
|
||||
end
|
||||
let(:tokyo_offset) { "UTC#{ActiveSupport::TimeZone['Asia/Tokyo'].now.formatted_offset}" }
|
||||
let(:berlin_offset) { "UTC#{ActiveSupport::TimeZone['Europe/Berlin'].now.formatted_offset}" }
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user