mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
consolidate lazy loading and filter components
This commit is contained in:
@@ -1,113 +1,152 @@
|
||||
<%= form_tag({},
|
||||
method: :get,
|
||||
data: {
|
||||
action: 'submit->filter--filters-form#sendForm:prevent'
|
||||
}) do %>
|
||||
<fieldset class="advanced-filters--container">
|
||||
<a title="<%= t('js.close_form_title') %>"
|
||||
class="advanced-filters--close icon-context icon-close"
|
||||
data-action="filter--filters-form#toggleDisplayFilters"></a>
|
||||
<legend><%= t(:label_filter_plural) %></legend>
|
||||
<ul class="advanced-filters--filters">
|
||||
<% each_filter do |filter, filter_active, additional_options| %>
|
||||
<% filter_boolean = filter.is_a?(Queries::Filters::Shared::BooleanFilter) %>
|
||||
<% autocomplete_filter = additional_options.key?(:autocomplete_options) %>
|
||||
<%=
|
||||
helpers.content_tag :div,
|
||||
class: filter_classes,
|
||||
data: {
|
||||
"filter--filters-form-target": "filterForm"
|
||||
} do
|
||||
%>
|
||||
|
||||
<li class="advanced-filters--filter <%= filter_active ? '' : 'hidden' %>"
|
||||
data-filter-name="<%= filter.name %>"
|
||||
data-filter-type="<%= filter.type %>"
|
||||
data-filter--filters-form-target="filter">
|
||||
<label class='advanced-filters--filter-name' for="<%= filter.name %>">
|
||||
<%= filter.human_name %>
|
||||
</label>
|
||||
<% selected_operator = filter.operator || filter.default_operator.symbol %>
|
||||
<%= content_tag :div, class: "advanced-filters--filter-operator", style: filter_boolean ? 'display:none' : '' do %>
|
||||
<%= select_tag :operator,
|
||||
options_from_collection_for_select(
|
||||
filter.available_operators,
|
||||
:symbol,
|
||||
:human_name,
|
||||
selected_operator),
|
||||
class: 'advanced-filters--select',
|
||||
data: {
|
||||
action: 'change->filter--filters-form#setValueVisibility',
|
||||
'filter--filters-form-filter-name-param': filter.name,
|
||||
'filter--filters-form-target': 'operator',
|
||||
'filter-name': filter.name
|
||||
} %>
|
||||
<% end %>
|
||||
<% if autocomplete_filter %>
|
||||
<%= render partial: 'filters/autocomplete',
|
||||
locals: { value_visibility: value_hidden_class(selected_operator),
|
||||
filter: filter,
|
||||
autocomplete_options: additional_options[:autocomplete_options] } %>
|
||||
<% elsif filter_boolean %>
|
||||
<%= render partial: 'filters/boolean',
|
||||
locals: { value_visibility: value_hidden_class(selected_operator),
|
||||
filter: filter } %>
|
||||
<% elsif %i(list list_optional list_all).include? filter.type %>
|
||||
<%= render partial: 'filters/list/input_options',
|
||||
locals: { value_visibility: value_hidden_class(selected_operator),
|
||||
filter: filter } %>
|
||||
<% elsif [:datetime_past, :date].include? filter.type %>
|
||||
<%= render partial: 'filters/date/input_options',
|
||||
locals: { value_visibility: value_hidden_class(selected_operator),
|
||||
filter: filter,
|
||||
selected_operator: selected_operator } %>
|
||||
<% else %>
|
||||
<%# All other simple types %>
|
||||
<%= render partial: 'filters/text',
|
||||
locals: { value_visibility: value_hidden_class(selected_operator),
|
||||
filter: filter } %>
|
||||
<% end %>
|
||||
<% if lazy_loaded? %>
|
||||
|
||||
<div class="advanced-filters--remove-filter">
|
||||
<a href="#"
|
||||
class="filter_rem"
|
||||
data-action="click->filter--filters-form#removeFilter"
|
||||
data-filter--filters-form-filter-name-param="<%= filter.name %>">
|
||||
<%= helpers.op_icon("icon-close advanced-filters--remove-filter-icon", title: I18n.t('js.button_delete')) %>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<%=
|
||||
helpers.turbo_frame_tag(
|
||||
TURBO_FRAME_ID,
|
||||
src: lazy_turbo_frame_src,
|
||||
target: "_top",
|
||||
loading: "lazy",
|
||||
data: { turbo: false }
|
||||
) do
|
||||
render Primer::Alpha::SkeletonBox.new(
|
||||
width: "100%",
|
||||
height: skeleton_height
|
||||
)
|
||||
end
|
||||
%>
|
||||
|
||||
<% else %>
|
||||
|
||||
<%= helpers.turbo_frame_tag TURBO_FRAME_ID do %>
|
||||
<%= form_tag(
|
||||
{},
|
||||
method: :get,
|
||||
data: {
|
||||
action: "submit->filter--filters-form#sendForm:prevent"
|
||||
}
|
||||
) do %>
|
||||
<fieldset class="advanced-filters--container">
|
||||
<a title="<%= t("js.close_form_title") %>"
|
||||
href=""
|
||||
class="advanced-filters--close icon-context icon-close"
|
||||
data-action="filter--filters-form#toggleDisplayFilters"></a>
|
||||
<legend><%= t(:label_filter_plural) %></legend>
|
||||
<ul class="advanced-filters--filters">
|
||||
<% each_filter do |filter, filter_active, additional_options| %>
|
||||
<% filter_boolean = filter.is_a?(Queries::Filters::Shared::BooleanFilter) %>
|
||||
<% autocomplete_filter = additional_options.key?(:autocomplete_options) %>
|
||||
|
||||
<li class="advanced-filters--filter <%= filter_active ? "" : "hidden" %>"
|
||||
data-filter-name="<%= filter.name %>"
|
||||
data-filter-type="<%= filter.type %>"
|
||||
data-filter--filters-form-target="filter">
|
||||
<label class="advanced-filters--filter-name" for="<%= filter.name %>">
|
||||
<%= filter.human_name %>
|
||||
</label>
|
||||
<% selected_operator = filter.operator || filter.default_operator.symbol %>
|
||||
<%= content_tag :div, class: "advanced-filters--filter-operator", style: filter_boolean ? "display:none" : "" do %>
|
||||
<%= select_tag :operator,
|
||||
options_from_collection_for_select(
|
||||
filter.available_operators,
|
||||
:symbol,
|
||||
:human_name,
|
||||
selected_operator
|
||||
),
|
||||
class: "advanced-filters--select",
|
||||
data: {
|
||||
action: "change->filter--filters-form#setValueVisibility",
|
||||
"filter--filters-form-filter-name-param": filter.name,
|
||||
"filter--filters-form-target": "operator",
|
||||
"filter-name": filter.name
|
||||
} %>
|
||||
<% end %>
|
||||
<% if autocomplete_filter %>
|
||||
<%= render partial: "filters/autocomplete",
|
||||
locals: { value_visibility: value_hidden_class(selected_operator),
|
||||
filter: filter,
|
||||
autocomplete_options: additional_options[:autocomplete_options] } %>
|
||||
<% elsif filter_boolean %>
|
||||
<%= render partial: "filters/boolean",
|
||||
locals: { value_visibility: value_hidden_class(selected_operator),
|
||||
filter: filter } %>
|
||||
<% elsif %i(list list_optional list_all).include? filter.type %>
|
||||
<%= render partial: "filters/list/input_options",
|
||||
locals: { value_visibility: value_hidden_class(selected_operator),
|
||||
filter: filter } %>
|
||||
<% elsif [:datetime_past, :date].include? filter.type %>
|
||||
<%= render partial: "filters/date/input_options",
|
||||
locals: { value_visibility: value_hidden_class(selected_operator),
|
||||
filter: filter,
|
||||
selected_operator: selected_operator } %>
|
||||
<% else %>
|
||||
<%# All other simple types %>
|
||||
<%= render partial: "filters/text",
|
||||
locals: { value_visibility: value_hidden_class(selected_operator),
|
||||
filter: filter } %>
|
||||
<% end %>
|
||||
|
||||
<div class="advanced-filters--remove-filter">
|
||||
<a href=""
|
||||
class="filter_rem"
|
||||
data-action="click->filter--filters-form#removeFilter"
|
||||
data-filter--filters-form-filter-name-param="<%= filter.name %>">
|
||||
<%= helpers.op_icon("icon-close advanced-filters--remove-filter-icon", title: I18n.t("js.button_delete")) %>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<li class="advanced-filters--spacer <%= query.filters.blank? ? "hidden" : "" %>"
|
||||
data-filter--filters-form-target="spacer"></li>
|
||||
|
||||
<li class="advanced-filters--add-filter">
|
||||
<!-- Add filters -->
|
||||
<label for="add_filter_select" aria-hidden="true" class="advanced-filters--add-filter-label ng-binding">
|
||||
<%= helpers.op_icon("icon-add icon4") %>
|
||||
<%= t(:label_filter_add) %>:
|
||||
</label>
|
||||
<label for="add_filter_select" class="sr-only ng-binding">
|
||||
<%= t(:label_filter_add) %>
|
||||
<%= t("js.filter.description.text_open_filter") %>
|
||||
<%= t("js.filter.description.text_close_filter") %>
|
||||
</label>
|
||||
|
||||
<div class="advanced-filters--add-filter-value">
|
||||
<%= select_tag "add_filter_select",
|
||||
options_from_collection_for_select(
|
||||
allowed_filters,
|
||||
:name,
|
||||
:human_name,
|
||||
disabled: query.filters.map(&:name)
|
||||
),
|
||||
prompt: t(:actionview_instancetag_blank_option),
|
||||
class: "advanced-filters--select",
|
||||
focus: "false",
|
||||
"aria-invalid": "false",
|
||||
data: {
|
||||
"filter--filters-form-target": "addFilterSelect",
|
||||
action: "change->filter--filters-form#addFilter:prevent"
|
||||
} %>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<% unless turbo_requests? %>
|
||||
<li class="advanced-filters--controls">
|
||||
<%= submit_tag t("button_apply"), class: "button -small -primary", name: nil %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
</ul>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<li class="advanced-filters--spacer <%= query.filters.blank? ? 'hidden' : '' %>"
|
||||
data-filter--filters-form-target="spacer"></li>
|
||||
|
||||
<li class="advanced-filters--add-filter">
|
||||
<!-- Add filters -->
|
||||
<label for="add_filter_select" aria-hidden="true" class="advanced-filters--add-filter-label ng-binding">
|
||||
<%= helpers.op_icon("icon-add icon4") %>
|
||||
<%= t(:label_filter_add) %>:
|
||||
</label>
|
||||
<label for="add_filter_select" class="sr-only ng-binding">
|
||||
<%= t(:label_filter_add) %>
|
||||
<%= t('js.filter.description.text_open_filter') %>
|
||||
<%= t('js.filter.description.text_close_filter') %>
|
||||
</label>
|
||||
|
||||
<div class="advanced-filters--add-filter-value">
|
||||
<%= select_tag 'add_filter_select',
|
||||
options_from_collection_for_select(
|
||||
allowed_filters,
|
||||
:name,
|
||||
:human_name,
|
||||
disabled: query.filters.map(&:name)
|
||||
),
|
||||
prompt: t(:actionview_instancetag_blank_option),
|
||||
class: 'advanced-filters--select',
|
||||
focus: "false",
|
||||
'aria-invalid': "false",
|
||||
data: {
|
||||
'filter--filters-form-target': 'addFilterSelect',
|
||||
action: 'change->filter--filters-form#addFilter:prevent'
|
||||
} %>
|
||||
</div>
|
||||
</li>
|
||||
<li class="advanced-filters--controls">
|
||||
<%= submit_tag t('button_apply'), class: 'button -small -primary', name: nil %>
|
||||
</li>
|
||||
</ul>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -31,9 +31,12 @@ module Filter
|
||||
# rubocop:disable OpenProject/AddPreviewForViewComponent
|
||||
class FilterComponent < ApplicationComponent
|
||||
OPERATORS_WITHOUT_VALUES = %w[* !* t w].freeze
|
||||
TURBO_FRAME_ID = "filter_component"
|
||||
|
||||
# rubocop:enable OpenProject/AddPreviewForViewComponent
|
||||
options :query
|
||||
options :lazy_loaded_path
|
||||
options :initially_expanded
|
||||
|
||||
# Returns filters, active and inactive.
|
||||
# In case a filter is active, the active one will be preferred over the inactive one.
|
||||
@@ -58,6 +61,27 @@ module Filter
|
||||
OPERATORS_WITHOUT_VALUES.include?(operator)
|
||||
end
|
||||
|
||||
def lazy_loaded? = !!lazy_loaded_path
|
||||
|
||||
def initially_expanded? = initially_expanded || false
|
||||
|
||||
def turbo_requests? = false
|
||||
|
||||
def skeleton_height
|
||||
# This is an approximation.
|
||||
# * 100 for the padding and the filter selection
|
||||
# * 40 per filter and their bottom margin. But the height of the filters vary unfortunately.
|
||||
"#{100 + (query.filters.count * 40)}px"
|
||||
end
|
||||
|
||||
def filter_classes
|
||||
"op-filters-form op-filters-form_top-margin #{'-expanded' if initially_expanded?}"
|
||||
end
|
||||
|
||||
def lazy_turbo_frame_src
|
||||
public_send(lazy_loaded_path, **params.permit(:filters, :columns, :sortBy, :id, :query_id))
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# With this method we can pass additional options for each type of filter into the frontend. This is especially
|
||||
|
||||
@@ -33,25 +33,14 @@
|
||||
end
|
||||
end
|
||||
|
||||
subheader.with_bottom_pane_component classes: filter_classes,
|
||||
data: {
|
||||
"filter--filters-form-target": "filterForm"
|
||||
} do
|
||||
helpers.turbo_frame_tag(
|
||||
"portfolios_filters",
|
||||
src: portfolios_filters_path(
|
||||
**params.permit(:filters, :columns, :sortBy, :id, :query_id)
|
||||
),
|
||||
target: "_top",
|
||||
loading: "lazy",
|
||||
data: { turbo: false }
|
||||
) do
|
||||
render Primer::Alpha::SkeletonBox.new(
|
||||
width: "100%",
|
||||
height: skeleton_height,
|
||||
mt: 3
|
||||
subheader.with_bottom_pane_component do
|
||||
render(
|
||||
Projects::ProjectsFiltersComponent.new(
|
||||
query: @query,
|
||||
lazy_loaded_path: :portfolios_filters_path,
|
||||
initially_expanded: filters_expanded?
|
||||
)
|
||||
end
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -74,19 +74,8 @@ module Portfolios
|
||||
@current_user.allowed_globally?(:add_portfolios)
|
||||
end
|
||||
|
||||
def skeleton_height
|
||||
# This is an approximation.
|
||||
# * 100 for the padding and the filter selection
|
||||
# * 40 per filter and their bottom margin. But the height of the filters vary unfortunately.
|
||||
"#{100 + (@query.filters.count * 40)}px"
|
||||
end
|
||||
|
||||
def filters_expanded?
|
||||
params[:filters].present?
|
||||
end
|
||||
|
||||
def filter_classes
|
||||
"op-filters-form op-filters-form_top-margin #{'-expanded' if filters_expanded?}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -59,25 +59,14 @@
|
||||
end
|
||||
end
|
||||
|
||||
subheader.with_bottom_pane_component classes: filter_classes,
|
||||
data: {
|
||||
"filter--filters-form-target": "filterForm"
|
||||
} do
|
||||
helpers.turbo_frame_tag(
|
||||
"projects_filters",
|
||||
src: projects_filters_path(
|
||||
**params.permit(:filters, :columns, :sortBy, :id, :query_id)
|
||||
),
|
||||
target: "_top",
|
||||
loading: "lazy",
|
||||
data: { turbo: false }
|
||||
) do
|
||||
render Primer::Alpha::SkeletonBox.new(
|
||||
width: "100%",
|
||||
height: skeleton_height,
|
||||
mt: 3
|
||||
subheader.with_bottom_pane_component do
|
||||
render(
|
||||
Projects::ProjectsFiltersComponent.new(
|
||||
query: @query,
|
||||
lazy_loaded_path: :projects_filters_path,
|
||||
initially_expanded: filters_expanded?
|
||||
)
|
||||
end
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -110,19 +110,8 @@ module Projects
|
||||
true
|
||||
end
|
||||
|
||||
def skeleton_height
|
||||
# This is an approximation.
|
||||
# * 100 for the padding and the filter selection
|
||||
# * 40 per filter and their bottom margin. But the height of the filters vary unfortunately.
|
||||
"#{100 + (@query.filters.count * 40)}px"
|
||||
end
|
||||
|
||||
def filters_expanded?
|
||||
params[:filters].present?
|
||||
end
|
||||
|
||||
def filter_classes
|
||||
"op-filters-form op-filters-form_top-margin #{'-expanded' if filters_expanded?}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
<%= form_tag(
|
||||
{},
|
||||
method: :get,
|
||||
data: {
|
||||
action: "submit->filter--filters-form#sendForm:prevent"
|
||||
}
|
||||
) do %>
|
||||
<% operators_without_values = %w[* !* t w] %>
|
||||
<fieldset class="advanced-filters--container">
|
||||
<a title="<%= t("js.close_form_title") %>"
|
||||
href=""
|
||||
class="advanced-filters--close icon-context icon-close"
|
||||
data-action="filter--filters-form#toggleDisplayFilters"></a>
|
||||
<legend><%= t(:label_filter_plural) %></legend>
|
||||
<ul class="advanced-filters--filters">
|
||||
<% each_filter do |filter, filter_active, additional_options| %>
|
||||
<% filter_boolean = filter.is_a?(Queries::Filters::Shared::BooleanFilter) %>
|
||||
<% autocomplete_filter = additional_options.key?(:autocomplete_options) %>
|
||||
<li class="advanced-filters--filter <%= filter_active ? "" : "hidden" %>"
|
||||
data-filter-name="<%= filter.name %>"
|
||||
data-filter-type="<%= filter.type %>"
|
||||
data-filter--filters-form-target="filter">
|
||||
<label class="advanced-filters--filter-name" for="<%= filter.name %>">
|
||||
<%= filter.human_name %>
|
||||
</label>
|
||||
<% selected_operator = filter.operator || filter.default_operator.symbol %>
|
||||
<%= content_tag :div, class: "advanced-filters--filter-operator", style: filter_boolean ? "display:none" : "" do %>
|
||||
<%= select_tag :operator,
|
||||
options_from_collection_for_select(
|
||||
filter.available_operators,
|
||||
:symbol,
|
||||
:human_name,
|
||||
selected_operator
|
||||
),
|
||||
class: "advanced-filters--select",
|
||||
data: {
|
||||
action: "change->filter--filters-form#setValueVisibility",
|
||||
"filter--filters-form-filter-name-param": filter.name,
|
||||
"filter--filters-form-target": "operator",
|
||||
"filter-name": filter.name
|
||||
} %>
|
||||
<% end %>
|
||||
<% value_visibility = operators_without_values.include?(selected_operator) ? "hidden" : "" %>
|
||||
<% if autocomplete_filter %>
|
||||
<%= render partial: "filters/autocomplete",
|
||||
locals: { value_visibility: value_visibility,
|
||||
filter: filter,
|
||||
autocomplete_options: additional_options[:autocomplete_options] } %>
|
||||
<% elsif filter_boolean %>
|
||||
<%= render partial: "filters/boolean",
|
||||
locals: { value_visibility: value_visibility,
|
||||
filter: filter } %>
|
||||
<% elsif %i(list list_optional list_all).include? filter.type %>
|
||||
<%= render partial: "filters/list/input_options",
|
||||
locals: { value_visibility: value_visibility,
|
||||
filter: filter } %>
|
||||
<% elsif [:datetime_past, :date].include? filter.type %>
|
||||
<%= render partial: "filters/date/input_options",
|
||||
locals: { value_visibility: value_visibility,
|
||||
filter: filter,
|
||||
selected_operator: selected_operator } %>
|
||||
<% else %>
|
||||
<%# All other simple types %>
|
||||
<%= render partial: "filters/text",
|
||||
locals: { value_visibility: value_visibility,
|
||||
filter: filter } %>
|
||||
<% end %>
|
||||
<div class="advanced-filters--remove-filter">
|
||||
<a href=""
|
||||
class="filter_rem"
|
||||
data-action="click->filter--filters-form#removeFilter"
|
||||
data-filter--filters-form-filter-name-param="<%= filter.name %>">
|
||||
<%= helpers.op_icon("icon-close advanced-filters--remove-filter-icon", title: I18n.t("js.button_delete")) %>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<% end %>
|
||||
<li class="advanced-filters--spacer <%= query.filters.blank? ? "hidden" : "" %>"
|
||||
data-filter--filters-form-target="spacer"></li>
|
||||
<li class="advanced-filters--add-filter">
|
||||
<!-- Add filters -->
|
||||
<label for="add_filter_select" aria-hidden="true" class="advanced-filters--add-filter-label ng-binding">
|
||||
<%= helpers.op_icon("icon-add icon4") %>
|
||||
<%= t(:label_filter_add) %>:
|
||||
</label>
|
||||
<label for="add_filter_select" class="sr-only ng-binding">
|
||||
<%= t(:label_filter_add) %>
|
||||
<%= t("js.filter.description.text_open_filter") %>
|
||||
<%= t("js.filter.description.text_close_filter") %>
|
||||
</label>
|
||||
<div class="advanced-filters--add-filter-value">
|
||||
<%= select_tag "add_filter_select",
|
||||
options_from_collection_for_select(
|
||||
allowed_filters,
|
||||
:name,
|
||||
:human_name,
|
||||
disabled: query.filters.map(&:name)
|
||||
),
|
||||
prompt: t(:actionview_instancetag_blank_option),
|
||||
class: "advanced-filters--select",
|
||||
focus: "false",
|
||||
"aria-invalid": "false",
|
||||
data: {
|
||||
"filter--filters-form-target": "addFilterSelect",
|
||||
action: "change->filter--filters-form#addFilter:prevent"
|
||||
} %>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
@@ -28,19 +28,13 @@
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
# ++
|
||||
|
||||
# rubocop:disable OpenProject/AddPreviewForViewComponent
|
||||
class Projects::ProjectsFiltersComponent < Filter::FilterComponent
|
||||
# rubocop:enable OpenProject/AddPreviewForViewComponent
|
||||
def allowed_filters
|
||||
super
|
||||
.select { |f| allowed_filter?(f) }
|
||||
.sort_by(&:human_name)
|
||||
end
|
||||
|
||||
def turbo_requests?
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def allowed_filter?(filter)
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
<%=
|
||||
turbo_frame_tag "portfolios_filters" do
|
||||
render(Projects::ProjectsFiltersComponent.new(query: @query))
|
||||
end
|
||||
%>
|
||||
<%= render(Projects::ProjectsFiltersComponent.new(query: @query)) %>
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
<%=
|
||||
turbo_frame_tag "projects_filters" do
|
||||
render(Projects::ProjectsFiltersComponent.new(query: @query))
|
||||
end
|
||||
%>
|
||||
<%= render(Projects::ProjectsFiltersComponent.new(query: @query)) %>
|
||||
|
||||
@@ -1,71 +1,78 @@
|
||||
<%= render(
|
||||
Primer::OpenProject::SubHeader.new(
|
||||
data: {
|
||||
controller: "filter--filters-form",
|
||||
"filter--filters-form-output-format-value": "json",
|
||||
"filter--filters-form-display-filters-value": filters_expanded?
|
||||
}
|
||||
<%=
|
||||
render(
|
||||
Primer::OpenProject::SubHeader.new(
|
||||
data: {
|
||||
controller: "filter--filters-form",
|
||||
"filter--filters-form-output-format-value": "json",
|
||||
"filter--filters-form-display-filters-value": filters_expanded?
|
||||
}
|
||||
)
|
||||
) do |subheader|
|
||||
subheader.with_filter_component do
|
||||
render(Meetings::MeetingFilterButtonComponent.new(query: @query, project: @project))
|
||||
end
|
||||
|
||||
subheader.with_segmented_control("aria-label": I18n.t(:label_meeting_date_time)) do |control|
|
||||
control.with_item(
|
||||
tag: :a,
|
||||
icon: :"arrow-right",
|
||||
href: dynamic_path,
|
||||
label: t(:label_upcoming_meetings_short),
|
||||
title: t(:label_upcoming_meetings),
|
||||
selected: upcoming_query?
|
||||
)
|
||||
) do |subheader|
|
||||
subheader.with_filter_component do
|
||||
render(Meetings::MeetingFilterButtonComponent.new(query: @query, project: @project))
|
||||
end
|
||||
control.with_item(
|
||||
tag: :a,
|
||||
icon: :history,
|
||||
href: dynamic_path(upcoming: false),
|
||||
label: t(:label_past_meetings_short),
|
||||
title: t(:label_past_meetings),
|
||||
selected: !upcoming_query?
|
||||
)
|
||||
end
|
||||
|
||||
subheader.with_segmented_control("aria-label": I18n.t(:label_meeting_date_time)) do |control|
|
||||
control.with_item(
|
||||
if render_create_button?
|
||||
subheader.with_action_menu(
|
||||
leading_icon: :plus,
|
||||
trailing_icon: :"triangle-down",
|
||||
label: label_text,
|
||||
anchor_align: :end,
|
||||
size: :small,
|
||||
button_arguments: {
|
||||
scheme: :primary,
|
||||
id: id,
|
||||
aria: { label: accessibility_label_text },
|
||||
test_selector: "add-meeting-button"
|
||||
}
|
||||
) do |menu|
|
||||
menu.with_item(
|
||||
label: I18n.t("meeting.types.one_time"),
|
||||
tag: :a,
|
||||
icon: :"arrow-right",
|
||||
href: dynamic_path,
|
||||
label: t(:label_upcoming_meetings_short),
|
||||
title: t(:label_upcoming_meetings),
|
||||
selected: upcoming_query?
|
||||
)
|
||||
control.with_item(
|
||||
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"))
|
||||
end
|
||||
|
||||
menu.with_item(
|
||||
label: I18n.t("meeting.types.recurring"),
|
||||
tag: :a,
|
||||
icon: :history,
|
||||
href: dynamic_path(upcoming: false),
|
||||
label: t(:label_past_meetings_short),
|
||||
title: t(:label_past_meetings),
|
||||
selected: !upcoming_query?
|
||||
)
|
||||
end
|
||||
|
||||
if render_create_button?
|
||||
subheader.with_action_menu(leading_icon: :plus,
|
||||
trailing_icon: :"triangle-down",
|
||||
label: label_text,
|
||||
anchor_align: :end,
|
||||
size: :small,
|
||||
button_arguments: { scheme: :primary,
|
||||
id: id,
|
||||
aria: { label: accessibility_label_text },
|
||||
test_selector: "add-meeting-button" }) do |menu|
|
||||
menu.with_item(
|
||||
label: I18n.t("meeting.types.one_time"),
|
||||
tag: :a,
|
||||
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"))
|
||||
end
|
||||
|
||||
menu.with_item(
|
||||
label: I18n.t("meeting.types.recurring"),
|
||||
tag: :a,
|
||||
href: polymorphic_path([:new_dialog, @project, :meetings], type: :recurring),
|
||||
content_arguments: { data: { controller: "async-dialog" } }
|
||||
) do |item|
|
||||
item.with_description.with_content(t("meeting.types.recurring_text"))
|
||||
end
|
||||
href: polymorphic_path([:new_dialog, @project, :meetings], type: :recurring),
|
||||
content_arguments: { data: { controller: "async-dialog" } }
|
||||
) do |item|
|
||||
item.with_description.with_content(t("meeting.types.recurring_text"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
subheader.with_bottom_pane_component(
|
||||
classes: "op-filters-form op-filters-form_top-margin #{"-expanded" if filters_expanded?}",
|
||||
data: {
|
||||
'filter--filters-form-target': 'filterForm',
|
||||
}
|
||||
) do
|
||||
render(Meetings::MeetingFiltersComponent.new(query: @query, project: @project))
|
||||
end
|
||||
end %>
|
||||
subheader.with_bottom_pane_component do
|
||||
render(
|
||||
Meetings::MeetingFiltersComponent.new(
|
||||
query: @query,
|
||||
project: @project,
|
||||
initially_expanded: filters_expanded?
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
%>
|
||||
|
||||
Reference in New Issue
Block a user