diff --git a/app/assets/javascripts/admin/menu.js b/app/assets/javascripts/admin/menu.js
new file mode 100644
index 000000000..f6d91978a
--- /dev/null
+++ b/app/assets/javascripts/admin/menu.js
@@ -0,0 +1,16 @@
+(function() {
+ "use strict";
+ App.AdminMenu = {
+ initialize: function() {
+ var toggle_buttons = $(".admin-sidebar [aria-expanded]");
+
+ toggle_buttons.removeAttr("disabled");
+ toggle_buttons.filter("[aria-expanded='false']").find("+ *").hide();
+
+ toggle_buttons.on("click", function() {
+ $(this).attr("aria-expanded", !JSON.parse($(this).attr("aria-expanded")));
+ $(this).next().slideToggle();
+ });
+ }
+ };
+}).call(this);
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 86a0f8243..9e6031dd4 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -174,6 +174,7 @@ var initialize_modules = function() {
App.AdminMachineLearningScripts.initialize();
App.AdminTenantsForm.initialize();
App.AdminVotationTypesFields.initialize();
+ App.AdminMenu.initialize();
App.BudgetEditAssociations.initialize();
App.BudgetHideMoney.initialize();
App.Datepicker.initialize();
diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss
index 70258353f..fd61560b3 100644
--- a/app/assets/stylesheets/admin.scss
+++ b/app/assets/stylesheets/admin.scss
@@ -214,10 +214,6 @@ $table-header: #ecf1f6;
padding-right: 0;
}
- .accordion-title {
- font-size: $base-font-size;
- }
-
.button.secondary {
margin-right: rem-calc(12);
}
diff --git a/app/assets/stylesheets/admin/menu.scss b/app/assets/stylesheets/admin/menu.scss
index 3a6cd7514..1993ff53a 100644
--- a/app/assets/stylesheets/admin/menu.scss
+++ b/app/assets/stylesheets/admin/menu.scss
@@ -10,7 +10,7 @@
padding: 0;
}
- > ul > li a {
+ > ul > li > :first-child {
display: flex;
font-weight: bold;
@@ -124,16 +124,9 @@
border-left: 2px solid $sidebar-active;
font-weight: bold;
}
-
- &[aria-expanded="true"] {
-
- > a::after {
- transform: rotate(180deg);
- }
- }
}
- li a {
+ li > :first-child {
color: inherit;
display: block;
padding: calc(#{$line-height} / 2);
@@ -146,19 +139,27 @@
}
}
- .is-accordion-submenu-parent {
+ [aria-expanded] {
+ @include has-fa-icon(chevron-down, solid, after);
+ line-height: inherit;
+ text-align: inherit;
+ width: 100%;
- > a {
- @include has-fa-icon(chevron-down, solid, after);
+ &::after {
+ margin-#{$global-left}: auto;
+ transition: 0.25s;
+ }
- &::after {
- margin-#{$global-left}: auto;
- transition: 0.25s;
- }
+ &:not([disabled]) {
+ cursor: pointer;
}
}
- .submenu {
+ [aria-expanded="true"]::after {
+ transform: rotate(180deg);
+ }
+
+ ul ul {
border-bottom: 0;
margin-left: $line-height;
diff --git a/app/components/admin/menu_component.html.erb b/app/components/admin/menu_component.html.erb
index 5b4a80597..0edc468b4 100644
--- a/app/components/admin/menu_component.html.erb
+++ b/app/components/admin/menu_component.html.erb
@@ -1 +1 @@
-<%= link_list(*links, id: "admin_menu", data: { "accordion-menu": true, "multi-open": true }) %>
+<%= link_list(*links, id: "admin_menu") %>
diff --git a/app/components/admin/menu_component.rb b/app/components/admin/menu_component.rb
index 8ec7df693..480be1b89 100644
--- a/app/components/admin/menu_component.rb
+++ b/app/components/admin/menu_component.rb
@@ -60,7 +60,9 @@ class Admin::MenuComponent < ApplicationComponent
def customization?
controllers_names = ["pages", "banners", "information_texts", "documents", "images", "content_blocks"]
- controllers_names.include?(controller_name) || homepage? || pages?
+
+ (controllers_names.include?(controller_name) || homepage? || pages?) &&
+ controller.class.module_parent != Admin::Poll::Questions::Answers
end
def homepage?
@@ -151,14 +153,15 @@ class Admin::MenuComponent < ApplicationComponent
end
def booths_links
- link_to(t("admin.menu.title_booths"), "#", class: "booths-link") +
+ section(t("admin.menu.title_booths"), active: booths?, class: "booths-link") do
link_list(
officers_link,
booths_link,
booth_assignments_link,
shifts_link,
- id: "booths_menu", class: ("is-active" if booths?)
+ id: "booths_menu"
)
+ end
end
def officers_link
@@ -204,14 +207,15 @@ class Admin::MenuComponent < ApplicationComponent
end
def messages_links
- link_to(t("admin.menu.messaging_users"), "#", class: "messages-link") +
+ section(t("admin.menu.messaging_users"), active: messages_menu_active?, class: "messages-link") do
link_list(
newsletters_link,
admin_notifications_link,
system_emails_link,
emails_download_link,
- id: "messaging_users_menu", class: ("is-active" if messages_menu_active?)
+ id: "messaging_users_menu"
)
+ end
end
def newsletters_link
@@ -247,7 +251,8 @@ class Admin::MenuComponent < ApplicationComponent
end
def site_customization_links
- link_to(t("admin.menu.title_site_customization"), "#", class: "site-customization-link") +
+ section(t("admin.menu.title_site_customization"),
+ active: customization?, class: "site-customization-link") do
link_list(
homepage_link,
pages_link,
@@ -255,10 +260,9 @@ class Admin::MenuComponent < ApplicationComponent
information_texts_link,
documents_link,
images_link,
- content_blocks_link,
- class: ("is-active" if customization? &&
- controller.class.module_parent != Admin::Poll::Questions::Answers)
+ content_blocks_link
)
+ end
end
def homepage_link
@@ -302,7 +306,8 @@ class Admin::MenuComponent < ApplicationComponent
end
def moderated_content_links
- link_to(t("admin.menu.title_moderated_content"), "#", class: "moderated-content-link") +
+ section(t("admin.menu.title_moderated_content"),
+ active: moderated_content?, class: "moderated-content-link") do
link_list(
(hidden_proposals_link if feature?(:proposals)),
(hidden_debates_link if feature?(:debates)),
@@ -310,9 +315,9 @@ class Admin::MenuComponent < ApplicationComponent
hidden_comments_link,
hidden_proposal_notifications_link,
hidden_users_link,
- activity_link,
- class: ("is-active" if moderated_content?)
+ activity_link
)
+ end
end
def hidden_proposals_link
@@ -372,7 +377,7 @@ class Admin::MenuComponent < ApplicationComponent
end
def profiles_links
- link_to(t("admin.menu.title_profiles"), "#", class: "profiles-link") +
+ section(t("admin.menu.title_profiles"), active: profiles?, class: "profiles-link") do
link_list(
administrators_link,
organizations_link,
@@ -381,9 +386,9 @@ class Admin::MenuComponent < ApplicationComponent
valuators_link,
managers_link,
(sdg_managers_link if feature?(:sdg)),
- users_link,
- class: ("is-active" if profiles?)
+ users_link
)
+ end
end
def administrators_link
@@ -452,15 +457,15 @@ class Admin::MenuComponent < ApplicationComponent
end
def settings_links
- link_to(t("admin.menu.title_settings"), "#", class: "settings-link") +
+ section(t("admin.menu.title_settings"), active: settings?, class: "settings-link") do
link_list(
settings_link,
tenants_link,
tags_link,
geozones_link,
- local_census_records_link,
- class: ("is-active" if settings?)
+ local_census_records_link
)
+ end
end
def settings_link
@@ -522,12 +527,12 @@ class Admin::MenuComponent < ApplicationComponent
end
def dashboard_links
- link_to(t("admin.menu.dashboard"), "#", class: "dashboard-link") +
+ section(t("admin.menu.dashboard"), active: dashboard?, class: "dashboard-link") do
link_list(
dashboard_actions_link,
- administrator_tasks_link,
- class: ("is-active" if dashboard?)
+ administrator_tasks_link
)
+ end
end
def machine_learning_link
@@ -562,4 +567,12 @@ class Admin::MenuComponent < ApplicationComponent
sdg_managers?
]
end
+
+ def section(title, **, &content)
+ section_opener(title, **) + content.call
+ end
+
+ def section_opener(title, active:, **options)
+ button_tag(title, { type: "button", disabled: "disabled", "aria-expanded": active }.merge(options))
+ end
end
diff --git a/app/components/management/menu_component.html.erb b/app/components/management/menu_component.html.erb
new file mode 100644
index 000000000..0edc468b4
--- /dev/null
+++ b/app/components/management/menu_component.html.erb
@@ -0,0 +1 @@
+<%= link_list(*links, id: "admin_menu") %>
diff --git a/app/components/management/menu_component.rb b/app/components/management/menu_component.rb
new file mode 100644
index 000000000..be11c0fd4
--- /dev/null
+++ b/app/components/management/menu_component.rb
@@ -0,0 +1,162 @@
+class Management::MenuComponent < ApplicationComponent
+ use_helpers :managed_user, :link_list
+
+ def links
+ [
+ user_links,
+ (print_investments_link if Setting["process.budgets"]),
+ print_proposals_link,
+ user_invites_link
+ ]
+ end
+
+ private
+
+ def user_links
+ section(t("management.menu.users"), active: true, class: "users-link") do
+ link_list(
+ select_user_link,
+ (reset_password_email_link if managed_user.email),
+ reset_password_manually_link,
+ create_proposal_link,
+ support_proposals_link,
+ (create_budget_investment_link if Setting["process.budgets"]),
+ (support_budget_investments_link if Setting["process.budgets"])
+ )
+ end
+ end
+
+ def select_user_link
+ [
+ t("management.menu.select_user"),
+ management_document_verifications_path,
+ users?
+ ]
+ end
+
+ def reset_password_email_link
+ [
+ t("management.account.menu.reset_password_email"),
+ edit_password_email_management_account_path,
+ edit_password_email?
+ ]
+ end
+
+ def reset_password_manually_link
+ [
+ t("management.account.menu.reset_password_manually"),
+ edit_password_manually_management_account_path,
+ edit_password_manually?
+ ]
+ end
+
+ def create_proposal_link
+ [
+ t("management.menu.create_proposal"),
+ new_management_proposal_path,
+ create_proposal?
+ ]
+ end
+
+ def support_proposals_link
+ [
+ t("management.menu.support_proposals"),
+ management_proposals_path,
+ support_proposal?
+ ]
+ end
+
+ def create_budget_investment_link
+ [
+ t("management.menu.create_budget_investment"),
+ create_investments_management_budgets_path,
+ create_investments?
+ ]
+ end
+
+ def support_budget_investments_link
+ [
+ t("management.menu.support_budget_investments"),
+ support_investments_management_budgets_path,
+ support_investments?
+ ]
+ end
+
+ def print_investments_link
+ [
+ t("management.menu.print_budget_investments"),
+ print_investments_management_budgets_path,
+ print_investments?,
+ class: "print-investments-link"
+ ]
+ end
+
+ def print_proposals_link
+ [
+ t("management.menu.print_proposals"),
+ print_management_proposals_path,
+ print_proposals?,
+ class: "print-proposals-link"
+ ]
+ end
+
+ def user_invites_link
+ [
+ t("management.menu.user_invites"),
+ new_management_user_invite_path,
+ user_invites?,
+ class: "invitations-link"
+ ]
+ end
+
+ def users?
+ ["users", "email_verifications", "document_verifications"].include?(controller_name)
+ end
+
+ def edit_password_email?
+ controller_name == "account" && action_name == "edit_password_email"
+ end
+
+ def edit_password_manually?
+ controller_name == "account" && action_name == "edit_password_manually"
+ end
+
+ def create_proposal?
+ controller_name == "proposals" && action_name == "new"
+ end
+
+ def support_proposal?
+ controller_name == "proposals" && action_name == "index"
+ end
+
+ def print_proposals?
+ controller_name == "proposals" && action_name == "print"
+ end
+
+ def create_investments?
+ (controller_name == "budget_investments" && action_name == "new") ||
+ (controller_name == "budgets" && action_name == "create_investments")
+ end
+
+ def support_investments?
+ (controller_name == "budget_investments" && action_name == "index") ||
+ (controller_name == "budgets" && action_name == "support_investments")
+ end
+
+ def print_investments?
+ (controller_name == "budget_investments" && action_name == "print") ||
+ (controller_name == "budgets" && action_name == "print_investments")
+ end
+
+ def user_invites?
+ controller_name == "user_invites"
+ end
+
+ def section(title, **, &content)
+ section_opener(title, **) + content.call
+ end
+
+ def section_opener(title, active:, **options)
+ button_tag(title, { type: "button", disabled: "disabled", "aria-expanded": active }.merge(options))
+ end
+end
diff --git a/app/helpers/management_helper.rb b/app/helpers/management_helper.rb
deleted file mode 100644
index 99bc18023..000000000
--- a/app/helpers/management_helper.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-module ManagementHelper
- def menu_users?
- ["users", "email_verifications", "document_verifications"].include?(controller_name)
- end
-
- def menu_edit_password_email?
- controller_name == "account" && action_name == "edit_password_email"
- end
-
- def menu_edit_password_manually?
- controller_name == "account" && action_name == "edit_password_manually"
- end
-
- def menu_create_proposal?
- controller_name == "proposals" && action_name == "new"
- end
-
- def menu_support_proposal?
- controller_name == "proposals" && action_name == "index"
- end
-
- def menu_print_proposals?
- controller_name == "proposals" && action_name == "print"
- end
-
- def menu_create_investments?
- (controller_name == "budget_investments" && action_name == "new") ||
- (controller_name == "budgets" && action_name == "create_investments")
- end
-
- def menu_support_investments?
- (controller_name == "budget_investments" && action_name == "index") ||
- (controller_name == "budgets" && action_name == "support_investments")
- end
-
- def menu_print_investments?
- (controller_name == "budget_investments" && action_name == "print") ||
- (controller_name == "budgets" && action_name == "print_investments")
- end
-
- def menu_user_invites?
- controller_name == "user_invites"
- end
-end
diff --git a/app/views/layouts/management.html.erb b/app/views/layouts/management.html.erb
index 4c01900d2..7f8f1ba60 100644
--- a/app/views/layouts/management.html.erb
+++ b/app/views/layouts/management.html.erb
@@ -14,7 +14,7 @@
<%= check_box_tag :show_menu, nil, false, role: "switch" %>
diff --git a/app/views/management/_menu.html.erb b/app/views/management/_menu.html.erb
deleted file mode 100644
index 42fa308a0..000000000
--- a/app/views/management/_menu.html.erb
+++ /dev/null
@@ -1,63 +0,0 @@
-
diff --git a/spec/components/admin/menu_component_spec.rb b/spec/components/admin/menu_component_spec.rb
new file mode 100644
index 000000000..0a7ccf82f
--- /dev/null
+++ b/spec/components/admin/menu_component_spec.rb
@@ -0,0 +1,22 @@
+require "rails_helper"
+
+describe Admin::MenuComponent, controller: Admin::NewslettersController do
+ it "disables all buttons when JavaScript isn't available" do
+ render_inline Admin::MenuComponent.new
+
+ expect(page).to have_button disabled: true
+ expect(page).not_to have_button disabled: false
+ end
+
+ it "expands the current section" do
+ render_inline Admin::MenuComponent.new
+
+ expect(page).to have_css "button[aria-expanded='true']", exact_text: "Messages to users"
+ end
+
+ it "does not expand other sections" do
+ render_inline Admin::MenuComponent.new
+
+ expect(page).to have_css "button[aria-expanded='false']", exact_text: "Settings"
+ end
+end
diff --git a/spec/system/admin/banners_spec.rb b/spec/system/admin/banners_spec.rb
index 0ac2a009e..c604f6d6e 100644
--- a/spec/system/admin/banners_spec.rb
+++ b/spec/system/admin/banners_spec.rb
@@ -64,7 +64,7 @@ describe "Admin banners magement", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Site content"
+ click_button "Site content"
click_link "Manage banners"
end
@@ -133,7 +133,7 @@ describe "Admin banners magement", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Site content"
+ click_button "Site content"
click_link "Manage banners"
end
diff --git a/spec/system/admin/geozones_spec.rb b/spec/system/admin/geozones_spec.rb
index 95c862baf..384cccc73 100644
--- a/spec/system/admin/geozones_spec.rb
+++ b/spec/system/admin/geozones_spec.rb
@@ -15,7 +15,7 @@ describe "Admin geozones", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Settings"
+ click_button "Settings"
click_link "Manage geozones"
end
diff --git a/spec/system/admin/poll/booths_spec.rb b/spec/system/admin/poll/booths_spec.rb
index 61b440bc0..392f01b62 100644
--- a/spec/system/admin/poll/booths_spec.rb
+++ b/spec/system/admin/poll/booths_spec.rb
@@ -5,7 +5,7 @@ describe "Admin booths", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Voting booths"
+ click_button "Voting booths"
click_link "Booths location"
end
@@ -18,7 +18,7 @@ describe "Admin booths", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Voting booths"
+ click_button "Voting booths"
click_link "Booths location"
end
@@ -38,7 +38,7 @@ describe "Admin booths", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Voting booths"
+ click_button "Voting booths"
click_link "Manage shifts"
end
diff --git a/spec/system/admin/site_customization/content_blocks_spec.rb b/spec/system/admin/site_customization/content_blocks_spec.rb
index 012fc28ee..6f77b1c31 100644
--- a/spec/system/admin/site_customization/content_blocks_spec.rb
+++ b/spec/system/admin/site_customization/content_blocks_spec.rb
@@ -23,7 +23,7 @@ describe "Admin custom content blocks", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Site content"
+ click_button "Site content"
click_link "Custom content blocks"
end
@@ -48,7 +48,7 @@ describe "Admin custom content blocks", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Site content"
+ click_button "Site content"
click_link "Custom content blocks"
end
@@ -75,7 +75,7 @@ describe "Admin custom content blocks", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Site content"
+ click_button "Site content"
click_link "Custom content blocks"
end
diff --git a/spec/system/admin/site_customization/documents_spec.rb b/spec/system/admin/site_customization/documents_spec.rb
index 76fff934b..3f4ec063c 100644
--- a/spec/system/admin/site_customization/documents_spec.rb
+++ b/spec/system/admin/site_customization/documents_spec.rb
@@ -5,7 +5,7 @@ describe "Documents", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Site content"
+ click_button "Site content"
click_link "Custom documents"
end
diff --git a/spec/system/admin/site_customization/images_spec.rb b/spec/system/admin/site_customization/images_spec.rb
index 11cf9fc0e..801e0576a 100644
--- a/spec/system/admin/site_customization/images_spec.rb
+++ b/spec/system/admin/site_customization/images_spec.rb
@@ -5,7 +5,7 @@ describe "Admin custom images", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Site content"
+ click_button "Site content"
click_link "Custom images"
end
diff --git a/spec/system/admin/site_customization/pages_spec.rb b/spec/system/admin/site_customization/pages_spec.rb
index 6192d5632..19a084ce6 100644
--- a/spec/system/admin/site_customization/pages_spec.rb
+++ b/spec/system/admin/site_customization/pages_spec.rb
@@ -33,7 +33,7 @@ describe "Admin custom pages", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Site content"
+ click_button "Site content"
click_link "Custom pages"
end
@@ -63,7 +63,7 @@ describe "Admin custom pages", :admin do
visit admin_root_path
within("#side_menu") do
- click_link "Site content"
+ click_button "Site content"
click_link "Custom pages"
end
diff --git a/spec/system/admin/tenants_spec.rb b/spec/system/admin/tenants_spec.rb
index acabe6464..0616eaa58 100644
--- a/spec/system/admin/tenants_spec.rb
+++ b/spec/system/admin/tenants_spec.rb
@@ -8,7 +8,7 @@ describe "Tenants", :admin, :seed_tenants do
visit admin_root_path
within("#side_menu") do
- click_link "Settings"
+ click_button "Settings"
click_link "Multitenancy"
end
diff --git a/spec/system/admin_spec.rb b/spec/system/admin_spec.rb
index a0f31c04d..d09d9bdeb 100644
--- a/spec/system/admin_spec.rb
+++ b/spec/system/admin_spec.rb
@@ -80,7 +80,7 @@ describe "Admin" do
within("#admin_menu") do
expect(page).to have_link "Participatory budgets"
- click_link "Site content"
+ click_button "Site content"
expect(page).to have_link "Participatory budgets"
end