Skip to content

Commit

Permalink
Extend meeting#new form to allow creating "global" meetings
Browse files Browse the repository at this point in the history
Scoped and non-scoped actions and views are now split up to allow
for creating meetings in a "global" and scoped context.
  • Loading branch information
aaron-contreras committed Jun 8, 2023
1 parent 7833e1a commit 49e0ca8
Show file tree
Hide file tree
Showing 27 changed files with 838 additions and 217 deletions.
4 changes: 2 additions & 2 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -249,11 +249,11 @@ def authorize_global
# * a parameter-like Hash (eg. { controller: '/projects', action: 'edit' })
# * a permission Symbol (eg. :edit_project)
def do_authorize(action, global: false)
context = @project || @projects
context = @current_project || @project || @projects
is_authorized = User.current.allowed_to?(action, context, global:)

unless is_authorized
if @project&.archived?
if (@current_project || @project)&.archived?
render_403 message: :notice_not_authorized_archived_project
else
deny_access
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/global_styles/content/_forms.sass
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,10 @@ input[readonly].-clickable
line-height: normal
padding: 3px 24px 3px 3px

&.-prompt-visible
font-style: italic
color: $spot-color-basic-gray-3

&[multiple]
background-image: none
padding-right: $form-padding
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* -- copyright
* OpenProject is an open source project management software.
* Copyright (C) 2023 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 SelectFieldWithPromptController extends Controller<HTMLSelectElement> {
connect() {
this.togglePromptStyling();
}

togglePromptStyling() {
if (this.promptSelected()) {
this.element.classList.add('-prompt-visible');
} else {
this.element.classList.remove('-prompt-visible');
}
}

private promptSelected() {
const options = Array.from(this.element.options);

return options.find((option) => option.value === '' && option.selected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,42 @@ export default class RefreshOnFormChangesController extends ApplicationControlle

static values = {
refreshUrl: String,
preserveParams: Boolean,
};

declare readonly formTarget:HTMLFormElement;

declare refreshUrlValue:string;
declare preserveParamsValue:boolean;

triggerReload():void {
// without the cast to undefined, the URLSearchParams constructor will
// not accept the FormData object.
const formData = new FormData(this.formTarget) as unknown as undefined;
const serializedFormData = new URLSearchParams(formData).toString();
const formParams = new URLSearchParams(formData);
const currentParams = new URLSearchParams(window.location.search);
const mergedParams = this.mergeQueryParams(currentParams, formParams);

const serializedFormData = mergedParams.toString();

window.location.href = `${this.refreshUrlValue}?${serializedFormData}`;
}

// Merge the form's submitted params onto the currently present
// query string parameters on the URL.
//
// This preserves scope-dependent form data that would painfully
// get reset in some reload scenarios when calling triggerReload
// from a dependent form field.
private mergeQueryParams(currentParams:URLSearchParams, newParams:URLSearchParams) {
if (!this.preserveParamsValue) {
return newParams;
}

newParams.forEach((value, key) => {
currentParams.set(key, value);
});

return currentParams;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<li class="<%= li_css_class %>">
<a href="<%= dynamic_path %>"
id="<%= id %>"
title="<%= title %>"
arial-label="<%= aria_label %>"
class="<%= link_css_class %>">
<%= icon %>
<%= label %>
</a>
</li>
78 changes: 78 additions & 0 deletions modules/meeting/app/components/meetings/add_button_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# frozen_string_literal: true

# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2023 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
#

module Meetings
class AddButtonComponent < ::RailsComponent
options :current_project

def render?
if current_project
User.current.allowed_to?(:create_meetings, current_project)
else
User.current.allowed_to_globally?(:create_meetings)
end
end

def li_css_class
'toolbar-item'
end

def dynamic_path
polymorphic_path([:new, current_project, :meeting])
end

def id
'add-meeting-button'
end

def title
I18n.t(:label_meeting_new)
end

def aria_label
I18n.t(:label_meeting_new)
end

def link_css_class
'button -alt-highlight'
end

def label
content_tag(:span,
I18n.t(:label_meeting),
class: 'button--text')
end

def icon
helpers.op_icon('button--icon icon-add')
end
end
end
77 changes: 77 additions & 0 deletions modules/meeting/app/controllers/base_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# frozen_string_literal: true

# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2023 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 BaseController < ApplicationController
around_action :set_time_zone

helper :watchers
helper :meeting_contents
include WatchersHelper
include PaginationHelper
include SortHelper

private

def set_time_zone(&)
zone = User.current.time_zone
if zone.nil?
localzone = Time.current.utc_offset
localzone -= 3600 if Time.current.dst?
zone = ::ActiveSupport::TimeZone[localzone]
end

Time.use_zone(zone, &)
end

def convert_params
if params.key?(:meeting)
# We do some preprocessing of `meeting_params` that we will store in this
# instance variable.
@converted_params = meeting_params.to_h

@converted_params[:duration] = @converted_params[:duration].to_hours
# Force defaults on participants
@converted_params[:participants_attributes] ||= {}
@converted_params[:participants_attributes].each { |p| p.reverse_merge! attended: false, invited: false }
end
end

def populate_meeting_with_converted_params
@meeting.participants.clear # Start with a clean set of participants
@meeting.participants_attributes = @converted_params.delete(:participants_attributes)
@meeting.attributes = @converted_params
end

def meeting_params
params.require(:meeting).permit(:title, :location, :start_time, :duration, :start_date, :start_time_hour,
participants_attributes: %i[email name invited attended user user_id meeting id])
end
end
Loading

0 comments on commit 49e0ca8

Please sign in to comment.