Skip to content

Commit

Permalink
Merge pull request #16860 from opf/feature/57854-primerised-meeting-i…
Browse files Browse the repository at this point in the history
…ndex-pages

[#57854] Primerised Meeting index pages
  • Loading branch information
oliverguenther authored Nov 11, 2024
2 parents c5f66db + ed5dce9 commit 88859fe
Show file tree
Hide file tree
Showing 38 changed files with 941 additions and 356 deletions.
4 changes: 4 additions & 0 deletions app/components/op_primer/border_box_table_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,7 @@ See COPYRIGHT and LICENSE files for more details.
end
end
%>
<% if paginated? %>
<%= helpers.pagination_links_full rows %>
<% end %>
6 changes: 0 additions & 6 deletions app/components/op_primer/border_box_table_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,6 @@ module OpPrimer
class BorderBoxTableComponent < TableComponent
include ComponentHelpers

def before_render
raise ArgumentError, "BorderBoxTableComponent cannot be #sortable?" if sortable?

super
end

def header_args(_column)
{}
end
Expand Down
6 changes: 3 additions & 3 deletions lookbook/docs/patterns/05-dialogs.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ attributes to it:

- `tag: :a` so that the component is rendered as a link
- `href: link_to_dialog_path` to specify where to request the dialog stream from
- `data: { controller: "async-dialog" }` to attach the async-dialog controller to the button.
- `data: { controller: "async-dialog" }` to attach the async-dialog controller to the button (In some cases, depending on the underlying html structure, `content_arguments: { data: { controller: "async-dialog" }}` might be needed instead)

```erb
<%%= render(Primer::Beta::Button.new(
Expand Down Expand Up @@ -39,7 +39,7 @@ class TestController < ApplicationControler
end
```

For this to work, the `OpTurbo::Streamable` module needs to be included in the modal component:
For this to work, the `OpTurbo::Streamable` module needs to be included in the modal component, along with the `OpTurbo::DialogStreamHelper` module in the corresponding controller:

```ruby
class MyDialogComponent < ApplicationControler
Expand All @@ -66,7 +66,7 @@ Assuming the MyDialogComponent template looks like this:
%>
```

You can also render the dialog in a manual turbo_stream template
You can also render the dialog in a manual turbo_stream template:

```ruby
class TestController < ApplicationControler
Expand Down
1 change: 1 addition & 0 deletions lookbook/docs/patterns/11-sub-header.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ This component is an own implementation for OpenProject requirements of contextu

- Restrict SubHeader actions to the page's content-specific actions (e.g. filtering or creating a new object).
- Use IconButtons instead of Buttons for actions only when the icon is clear enough to describe the action.
- When more actions are necessary, or if a menu is needed, use an ActionMenu instead of the ActionButtons.

**Don't**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
menu.with_item(label: t(:button_copy),
href: copy_meeting_path(@meeting),
content_arguments: {
data: { turbo: false }
data: { turbo_stream: true }
}) do |item|
item.with_leading_visual_icon(icon: :copy)
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<%=
render(Primer::Alpha::Dialog.new(
id: "new-meeting-dialog", title: title,
size: :medium_portrait,
data: { 'keep-open-on-submit': true }
)) do |dialog|
dialog.with_header(variant: :large)
render(Meetings::Index::FormComponent.new(meeting: @meeting, project: @project, type: @type))
end
%>
58 changes: 58 additions & 0 deletions modules/meeting/app/components/meetings/index/dialog_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++

module Meetings
class Index::DialogComponent < ApplicationComponent
include ApplicationHelper
include OpenProject::FormTagHelper
include OpTurbo::Streamable
include OpPrimer::ComponentHelpers

def initialize(meeting:, project:, type:)
super

@meeting = meeting
@project = project
@type = type
end

private

def render?
if @project
User.current.allowed_in_project?(:create_meetings, @project)
else
User.current.allowed_in_any_project?(:create_meetings)
end
end

def title
@type == :new ? I18n.t("label_meeting_new_one_time") : "Copy meeting"
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<%=
component_wrapper do
primer_form_with(
scope: :meeting,
model: @meeting,
method: :post,
data: { turbo: true },
html: { :id => 'meeting-form' },
url: {:controller => '/meetings', :action => 'create', :project_id => @project}
) do |f|
component_collection do |collection|
collection.with_component(Primer::Alpha::Dialog::Body.new) do
flex_layout(mb: 3) do |modal_body|
if @project.nil?
modal_body.with_row(mt: 3) do
render(Meeting::ProjectAutocompleter.new(f))
end
end

modal_body.with_row(mt: 3) do
render(Meeting::Title.new(f))
end

modal_body.with_row(mt: 3) do
render(Meeting::StartDate.new(f, initial_value: start_date_initial_value))
end

modal_body.with_row(mt: 3) do
render(Meeting::StartTime.new(f, initial_value: start_time_initial_value))
end

modal_body.with_row(mt: 3) do
render(Meeting::Duration.new(f))
end

modal_body.with_row(mt: 3) do
render(Meeting::Location.new(f))
end

modal_body.with_row do
render(Meeting::Type.new(f))
end

unless @type == :new
modal_body.with_row do
render(Meeting::CopiedFrom.new(f, id: @type.id))
end

modal_body.with_row(mt: 3) do
render(Meeting::CopyItems.new(f))
end

modal_body.with_row(mt: 3) do
render(Meeting::CopyParticipants.new(f))
end

modal_body.with_row(mt: 3) do
render(Meeting::CopyAttachments.new(f))
end

modal_body.with_row(mt: 3) do
render(Meeting::EmailParticipants.new(f))
end
end
end
end

collection.with_component(Primer::Alpha::Dialog::Footer.new) do
component_collection do |modal_footer|
modal_footer.with_component(Primer::ButtonComponent.new(data: { 'close-dialog-id': "new-meeting-dialog" })) do
I18n.t("button_cancel")
end

modal_footer.with_component(Primer::ButtonComponent.new(scheme: :primary, type: :submit)) do
I18n.t("label_meeting_create")
end
end
end
end
end
end
%>
53 changes: 53 additions & 0 deletions modules/meeting/app/components/meetings/index/form_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++

module Meetings
class Index::FormComponent < ApplicationComponent
include ApplicationHelper
include OpTurbo::Streamable
include OpPrimer::ComponentHelpers

def initialize(meeting:, project:, type:)
super

@meeting = meeting
@project = project
@type = type
end

private

def start_date_initial_value
format_time_as_date(@meeting.start_time, format: "%Y-%m-%d")
end

def start_time_initial_value
format_time(@meeting.start_time, include_date: false, format: "%H:%M")
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,35 @@
render(Meetings::MeetingFilterButtonComponent.new(query: @query, project: @project))
end

subheader.with_action_button(tag: :a,
href: dynamic_path,
scheme: :primary,
mobile_icon: :plus,
mobile_label: label_text,
aria: { label: accessibility_label_text },
title: accessibility_label_text,
id: id,
test_selector: "add-meeting-button") do |button|
button.with_leading_visual_icon(icon: :plus)
label_text
end if render_create_button?
if render_create_button?
subheader.with_action_component do

render Primer::Alpha::ActionMenu.new(anchor_align: :end) do |menu|
menu.with_show_button(scheme: :primary,
test_selector: "add-meeting-button",
mobile_icon: :plus,
mobile_label: label_text,
id: id,
title: accessibility_label_text,
aria: { label: accessibility_label_text }) do |button|
button.with_leading_visual_icon(icon: :plus)
button.with_trailing_action_icon(icon: :"triangle-down")
I18n.t(:label_meeting)
end

menu.with_item(label: I18n.t("meeting.types.classic"),
tag: :a,
href: dynamic_path
)

menu.with_item(label: I18n.t("meeting.types.structured"),
tag: :a,
href: new_dialog_meetings_path(project_id: @project&.id),
content_arguments: { data: { controller: "async-dialog" }}
)
end
end
end

subheader.with_bottom_pane_component(mt: 0) do
render(Meetings::MeetingFiltersComponent.new(query: @query, project: @project))
Expand Down
Loading

0 comments on commit 88859fe

Please sign in to comment.