This menu item will show up once you have added the `:limit_post_creation_to_admins` feature flag (regardless of whether it is enabled or not). If you wish to add the menu item: ```console rails console runner "FeatureFlag.add(:limit_post_creation_to_admins)" ``` In "adding" the item, it will default to disabled. However, as an administrator you should now be able to toggle on and off the authorization enforcement. If you wish to remove the menu item: ```console rails console runner "FeatureFlag.remove(:limit_post_creation_to_admins)" ``` Future plans for this will be to remove the `FeatureFlag.exist?` conditional so that the menu item shows up. A major consideration is that we'll assume that all Forem's have a "default space" in which folks (by default) can post. Builds on forem/forem#16897 Closes forem/forem#16842
119 lines
4.8 KiB
Ruby
119 lines
4.8 KiB
Ruby
# This "model" is not backed by the database. Its main purpose is to
|
|
# setup and provide methods to interact with the admin sidebar and tabbed menu
|
|
class AdminMenu
|
|
# On second level navigation with more children, we reference the default tabs controller. i.e look at developer_tools
|
|
# rubocop:disable Metrics/BlockLength
|
|
ITEMS = Menu.define do
|
|
scope :people, "group-2-line", [
|
|
item(name: "people", controller: "users", parent: "users"),
|
|
]
|
|
|
|
scope :content_manager, "dashboard-line", [
|
|
item(name: "spaces", controller: "spaces", visible: -> { FeatureFlag.exist?(:limit_post_creation_to_admins) }),
|
|
item(name: "posts", controller: "articles"),
|
|
item(name: "comments", controller: "comments"),
|
|
item(name: "badges", children: [
|
|
item(name: "library", controller: "badges"),
|
|
item(name: "achievements", controller: "badge_achievements"),
|
|
]),
|
|
item(name: "organizations"),
|
|
item(name: "podcasts"),
|
|
item(name: "tags"),
|
|
]
|
|
|
|
scope :customization, "tools-line", [
|
|
item(name: "config"),
|
|
item(name: "html variants", controller: "html_variants"),
|
|
item(name: "display ads"),
|
|
item(name: "navigation links"),
|
|
item(name: "pages"),
|
|
item(name: "profile fields", visible: -> { FeatureFlag.enabled?(:profile_admin) }),
|
|
]
|
|
|
|
scope :admin_team, "user-line", [
|
|
item(name: "admin team", controller: "permissions", parent: "permissions"),
|
|
]
|
|
|
|
scope :moderation, "mod", [
|
|
item(name: "reports"),
|
|
item(name: "mods"),
|
|
item(name: "moderator actions ads", controller: "moderator_actions"),
|
|
item(name: "privileged reactions"),
|
|
]
|
|
|
|
scope :advanced, "flashlight-line", [
|
|
item(name: "broadcasts"),
|
|
item(name: "response templates"),
|
|
item(name: "sponsorships"),
|
|
item(name: "developer tools", controller: "tools", children: [
|
|
item(name: "tools"),
|
|
item(name: "vault secrets", controller: "secrets"),
|
|
item(name: "data update scripts", visible: -> { FeatureFlag.enabled?(:data_update_scripts) }),
|
|
item(name: "extensions", controller: "extensions"),
|
|
]),
|
|
]
|
|
|
|
scope :apps, "palette-line", [
|
|
item(name: "consumer apps", controller: "consumer_apps"),
|
|
item(name: "listings"),
|
|
item(name: "welcome"),
|
|
]
|
|
end.freeze
|
|
# rubocop:enable Metrics/BlockLength
|
|
|
|
def self.navigation_items
|
|
ITEMS
|
|
end
|
|
|
|
# Return the Menu item that corresponds to the nav_item within the given named scope.
|
|
#
|
|
# @param scope_name [String] a slug from the request.path, which, by convention maps to the scope
|
|
# declarations in {ITEMS}.
|
|
# @param nav_item [String] a slug from the request.path, which, by convention maps to the item
|
|
# declarations that are one level below the scope declarations of {ITEMS}.
|
|
#
|
|
# @return [NilClass] when we don't have a menu representation of the nav_item
|
|
# @return [Menu::Item] the representation of the nav_item
|
|
#
|
|
# @todo This method returns the nav_item, but we really only operate on that item's children.
|
|
# Consider replacing with a method that is "children of nav_item within scope".
|
|
#
|
|
# @see AdminMenu.nested_menu_items_from_request
|
|
# @see AdminMenu::ITEMS
|
|
def self.nested_menu_items(scope_name, nav_item)
|
|
children = navigation_items[scope_name.to_sym]&.children
|
|
return unless children
|
|
|
|
children.each do |items|
|
|
return items if items.controller == nav_item
|
|
|
|
next unless items.children&.any?
|
|
|
|
items.children.each do |child|
|
|
# NOTE: [@jeremyf] trying to puzzle this one out. My read is that if the "grandchild" of the
|
|
# scope matches the controller, return the parent node (e.g. the item).
|
|
return items if child.controller == nav_item
|
|
end
|
|
end
|
|
|
|
# Because we're using each loops, with short-circuiting returns, we need to make sure we don't
|
|
# return the results of `items[:children].each`, which will be `items[:children]`.
|
|
nil
|
|
end
|
|
|
|
# @param request [#path] the request object (which must respond to `#path`)
|
|
# @return [NilClass] when we don't have a menu representation of the nav_item
|
|
# @return [MenuItem] the representation of the nav_item
|
|
#
|
|
# @see {.nested_menu_items} for implementation details
|
|
#
|
|
# @note This method assumes that the last two slugs of the request's path are the relevant
|
|
# information for determining which menu item to return. In other words, strongly consider
|
|
# the impact of having admin routes whose paths are comprised of more than 3 slugs (.e.g. we
|
|
# assume /admin/:scope_name/:nav_item but be wary of /admin/something/:scope_name/:nav_item
|
|
# or /admin/:scope_name/something/:nav_item).
|
|
def self.nested_menu_items_from_request(request)
|
|
scope, nav_item = request.path.split("/").last(2)
|
|
nested_menu_items(scope, nav_item)
|
|
end
|
|
end
|