Skip to content

Commit

Permalink
Merge pull request #1667 from tvdeyen/add-menus
Browse files Browse the repository at this point in the history
Add Menus
  • Loading branch information
tvdeyen authored Nov 8, 2019
2 parents 3e43e4b + 7ba30a3 commit 2cb573a
Show file tree
Hide file tree
Showing 45 changed files with 1,180 additions and 41 deletions.
2 changes: 1 addition & 1 deletion app/assets/javascripts/alchemy/alchemy.base.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ $.extend Alchemy,
Alchemy.setElementDirty $element
false

# Initializes all select tag with .alchemy_selectbox class as selectBoxIt instance
# Initializes all select tag with .alchemy_selectbox class as select2 instance
# Pass a jQuery scope to only init a subset of selectboxes.
SelectBox: (scope) ->
$("select.alchemy_selectbox", scope).select2
Expand Down
1 change: 1 addition & 0 deletions app/assets/stylesheets/alchemy/admin.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
@import "alchemy/icons";
@import "alchemy/image_library";
@import "alchemy/labels";
@import "alchemy/nodes";
@import "alchemy/notices";
@import "alchemy/pagination";
@import "alchemy/preview_window";
Expand Down
11 changes: 6 additions & 5 deletions app/assets/stylesheets/alchemy/forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ form {
float: right;
}

.input > .select2-container {
width: 100%;
}

> .autocomplete_tag_list {

.select2-container, .select2-choices {
Expand All @@ -49,11 +53,8 @@ form {
line-height: 16px;
}

&.select, &.grouped_select {

.select2-container {
margin: 4px 0;
}
.select2-container {
margin: 4px 0;
}

&.boolean {
Expand Down
154 changes: 154 additions & 0 deletions app/assets/stylesheets/alchemy/nodes.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
.nodes_tree.list {
margin: 2em 0;

&.sorting {
padding-top: 100px;

.page_icon {
cursor: move
}
}

.sitemap_node-level_0 {

> .node_name {
font-weight: bold;
}
}

.node_page,
.node_url {
width: 200px;
max-width: 45%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;

> a {
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;

.external & {
max-width: 90%;
}
}
}

.node_page {
padding: 0 8px;
margin-left: auto;
}

.node_url {
display: flex;
align-items: center;
padding: 0 2*$default-padding;
white-space: nowrap;
background-color: $sitemap-info-background-color;
line-height: $sitemap-line-height;
font-size: $small-font-size;
@include border-right-radius($default-border-radius);

> i {
margin-left: auto;
padding-left: $default-padding;
}
}

.node_folder {
cursor: pointer;
}

ul {
margin: 0;
padding: 0;
}

li {
line-height: $sitemap-line-height;
padding-left: $default-padding;

li {
padding-left: $sitemap-line-height;
}
}
}

#node_filter_result {
display: none;
margin-left: 2*$default-margin;
}

.sitemap_node {
margin: 3*$default-margin 0;
transition: background-color $transition-duration;

&.highlight {
background-color: $sitemap-highlight-color;
}

&.no-match .sitemap_pagename_link {
color: $medium-gray;
}

&:hover {
background-color: $sitemap-page-hover-color;
border-radius: $default-border-radius;
}

.node_name {
display: flex;
justify-content: space-between;
@include border-left-radius($default-border-radius);
padding: 0 0 0 10px;
margin: 2px;
text-decoration: none;
overflow: hidden;
background-color: $sitemap-page-background-color;

&.without-status {
@include border-right-radius($default-border-radius);
}

&.inactive {
color: #656565;
}
}
}

.nodes_tree-left_images {
position: relative;
width: 32px;
line-height: $sitemap-line-height;
float: left;
padding: 0 2*$default-padding;
text-align: center;
}

.nodes_tree-right_tools {
height: $sitemap-line-height;
padding: 0 2*$default-padding;
float: right;

> a {
float: left;
width: $sitemap-line-height;
height: $sitemap-line-height;
line-height: $sitemap-line-height;
text-align: center;
margin: 0;

&.disabled .icon {
opacity: 0.25;
filter: grayscale(100%);
}
}

.icon.blank {
margin-left: 2px;
float: left;
margin-top: 3px;
margin-right: 3px;
}
}
4 changes: 4 additions & 0 deletions app/assets/stylesheets/alchemy/selects.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ select {
font-weight: normal;
text-align: left;

.select2-chosen {
overflow: visible;
}

.select2-arrow {
top: 0;
width: $form-field-height;
Expand Down
43 changes: 43 additions & 0 deletions app/controllers/alchemy/admin/nodes_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

module Alchemy
module Admin
class NodesController < Admin::ResourcesController
def index
@root_nodes = Node.language_root_nodes
end

def new
@node = Node.new(
parent_id: params[:parent_id],
language: Language.current
)
end

def toggle
node = Node.find(params[:id])
node.update(folded: !node.folded)
if node.folded?
head :ok
else
render partial: 'node', collection: node.children.includes(:page, :children)
end
end

private

def resource_params
params.require(:node).permit(
:parent_id,
:language_id,
:page_id,
:name,
:url,
:title,
:nofollow,
:external
)
end
end
end
end
29 changes: 29 additions & 0 deletions app/helpers/alchemy/pages_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def render_site_layout
end

# Renders the navigation.
# @deprecated
#
# It produces a html <ul><li></li></ul> structure with all necessary classes so you can produce every navigation the web uses today.
# I.E. dropdown-navigations, simple mainnavigations or even complex nested ones.
Expand Down Expand Up @@ -177,6 +178,33 @@ def render_navigation(options = {}, html_options = {})
pages: pages,
html_options: html_options
end
deprecate render_navigation: 'Create a menu and use render_menu instead', deprecator: Alchemy::Deprecation

# Renders a menu partial
#
# Menu partials are placed in the `app/views/alchemy/menus` folder
# Use the `rails g alchemy:menus` generator to create the partials
#
# @param [String] - Name of the menu
# @param [Hash] - A set of options available in your menu partials
def render_menu(name, options = {})
root_node = Alchemy::Node.roots.find_by(name: name)
if root_node.nil?
warning("Menu with name #{name} not found!")
return
end

options = {
node_partial_name: "#{root_node.view_folder_name}/node"
}.merge(options)

render(root_node, node: root_node, options: options)
rescue ActionView::MissingTemplate => e
warning <<~WARN
Menu partial not found for #{name}.
#{e}
WARN
end

# Renders navigation the children and all siblings of the given page (standard is the current page).
#
Expand Down Expand Up @@ -206,6 +234,7 @@ def render_subnavigation(options = {}, html_options = {})
return nil
end
end
deprecate :render_subnavigation, deprecator: Alchemy::Deprecation

# Returns true if page is in the active branch
def page_active?(page)
Expand Down
47 changes: 47 additions & 0 deletions app/models/alchemy/node.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

module Alchemy
class Node < BaseRecord
VALID_URL_REGEX = /\A(\/|\D[a-z\+\d\.\-]+:)/

acts_as_nested_set scope: 'language_id', touch: true
stampable stamper_class_name: Alchemy.user_class_name

belongs_to :language, class_name: 'Alchemy::Language'
belongs_to :page, class_name: 'Alchemy::Page', optional: true, inverse_of: :nodes

validates :url, format: { with: VALID_URL_REGEX }, unless: -> { url.nil? }

# Returns the name
#
# Either the value is stored in the database
# or, if attached, the values comes from a page.
def name
read_attribute(:name).presence || page&.name
end

class << self
# Returns all root nodes for current language
def language_root_nodes
raise 'No language found' if Language.current.nil?
roots.where(language_id: Language.current.id)
end
end

# Returns the url
#
# Either the value is stored in the database, aka. an external url.
# Or, if attached, the values comes from a page.
def url
page && "/#{page.urlname}" || read_attribute(:url).presence
end

def to_partial_path
"#{view_folder_name}/wrapper"
end

def view_folder_name
"alchemy/menus/#{name.parameterize.underscore}"
end
end
end
Loading

0 comments on commit 2cb573a

Please sign in to comment.