...
#
# If the user is authorized to update content then an edit link will be generated in
# conjunction with the content. For example:
#
# <%= tandem_content_tag(:test_text, :text) %>
#
# would produce the following HTML (assuming `can? :update, tandem_content` => true):
#
#
#
# If a user specifies link information for the corresponding Tandem::Content object,
# then an A HTML element will be generated surrounding the content. For example:
#
# <%= tandem_content_tag(:test_image, :image) %>
#
# produces (assuming that tandem_content.link? => true):
#
#
#
# tandem_content_tag accepts a hash of html_options, which will be converted to
# additional HTML attributes of the generated container div. If you specify a
value, it will be combined
# with the default class name for your object. For example:
#
# <%= tandem_content_tag(:test_image, :image, {}, :class => "bar", :style => 'display:none') %>...
#
# produces:
#
#
...
#
# tandem_content_tag also accepts a hash of options, which will be converted to
# additional HTML attributes of the internal asset type. If you specify a
:class value, it will be combined
# with the default class name for your object. For example:
#
# <%= tandem_content_tag(:test_image, :image, :class => "bar", :width => 80) %>...
#
# produces:
#
# ...
![]()
:editor option, which defaults to
:plain, but
# can also be changed to
:wysiwyg to enable a WYSIWYG editor, e.g.
#
# <%= tandem_content_tag(:main_body, :text, editor: :wysiwyg) %>
def tandem_content_tag(identifier, type, options = {}, html_options = {})
options[:editor] ||= :plain
using_tandem_abilities do
tandem_content = Content.scoped_type(type).constantize.find_or_create_by_request_key_and_tag(request_key, identifier)
content = case tandem_content
when Content::Text
content_tag(:div, tandem_content, options.merge(
id: "#{dom_class(tandem_content)}_#{identifier}",
class: "#{dom_class(tandem_content)} #{options[:class]}".strip
)) {
tandem_content.formatted_content.html_safe
}
when Content::Image
image_content_tag(tandem_content,options.merge(
id: "#{dom_class(tandem_content)}_#{identifier}",
class: "#{dom_class(tandem_content)} #{options[:class]}".strip
))
else
raise "Unable to create #{tandem_content.class.name}: #{tandem_content.errors.inspect}" if tandem_content.new_record?
raise "Rendering behavior not defined for: #{tandem_content.class.name}"
end
content = link_to(content,tandem_content.link_url,{
id: "tandem_content_link_#{identifier}",
class: "tandem_content_link",
target: tandem_content.link_target
}) if tandem_content.link?
content = content_tag(:div, tandem_content, {
id: "tandem_toolbar_#{identifier}",
class: "tandem_toolbar #{options[:class]}".strip
}) {
link_to("Edit", tandem.edit_content_path(tandem_content.id, editor: options[:editor]),{
id: "tandem_edit_link_#{identifier}",
class: "tandem_edit_link #{options[:class]}".strip,
title: "editing #{identifier}"
})
} + content if can? :update, tandem_content
html_options.merge! id: identifier
html_options[:class] ||= ''
html_options[:class] << ' tandem_content' if can? :update, tandem_content
html_options[:class].strip!
content_tag(:div, tandem_content, html_options) { content }
end
end
#todo... document this
def tandem_navigation_tag(active_page, pages_collection = nil, html_options = {})
html_options, pages_collection = pages_collection, nil if pages_collection.is_a?(Hash)
html_options[:class] ||= 'nav'
page_groups = (pages_collection || Page.all).inject({}) do |groups, page|
if groups[page.parent_id.to_s]
groups[page.parent_id.to_s] << page
else
groups[page.parent_id.to_s] = [page]
end
groups
end
# generate must be in scope for the iterate proc declaration, but must be defined below iterate, so that iterate is recursively in scope
generate = nil
iterate = Proc.new do |parent_id|
#very important to delete the group from the collection, or it is possible users can create looping relationships
(page_groups.delete(parent_id.to_s) || {}).inject(''.html_safe) do |buffer, page|
buffer + generate.call(page)
end
end
generate = Proc.new do |page|
content_tag_for(:li, page, :tandem, class: "#{page == active_page ? 'active' : ''}") do
link_to(page.link_label, tandem.page_path(page), class: "#{page == active_page ? 'active' : ''}") +
content_tag(:ul) do
iterate.call(page.id)
end
end
end
content_tag(:ul, html_options) do
iterate.call(page_groups.keys.first)
end
end
def tandem_page_links(options = {})
using_tandem_abilities do
return if cannot?(:create, @page) && cannot?(:update, @page) && cannot?(:destroy, @page) && cannot?(:index, ::Tandem::Page)
options[:id] ||= 'tandem_page_links'
content_tag(:ul, options) do
links = []
if can?(:create, ::Tandem::Page)
links << link_to('New Page', tandem.new_page_path(parent_id: @page.try(:id)), :class => :page_link, :id => :page_new_link)
end
if @page.present?
if @page.persisted? && can?(:update, @page)
links << link_to('Edit Page', tandem.edit_page_path(@page), :class => :page_link, :id => :page_edit_link)
end
if @page.persisted? && can?(:destroy, @page)
links << link_to('Destroy Page', tandem.page_path(@page), :confirm => 'Are you sure?', :method => :delete)
end
end
if can?(:index, ::Tandem::Page)
links << link_to('Page Listing', tandem.pages_path)
end
links.collect! do |link|
content_tag(:li, link)
end
raw(links.join)
end
end
end
def valid_layouts
@valid_layouts ||= Dir["#{::Rails.root}/app/views/layouts/**/*.html*"].collect do |layout|
name = layout.match(/layouts\/([\w\-\/]*)((\.\w*){2})$/)[1]
name unless name == 'application'
end.compact
end
def valid_templates
@valid_templates ||= Dir["#{::Rails.root}/app/views/tandem/pages/**/*.*.*"].collect do |template|
template_name = File.basename(template).split('.').first
template_name if valid_custom_template?(template_name)
end.compact
end
private
def invalid_templates
['show', 'edit', 'index', 'new']
end
def valid_custom_template?(template_name)
template_name[0] != '_' && !invalid_templates.include?(template_name)
end
def request_key
key = "#{controller_path}-#{action_name}".gsub(/[^\w]|_/, '-')
key += "-#{params[:id]}" if key == 'tandem-pages-show'
key
end
def using_tandem_abilities
controller.instance_variable_set :@current_ability, ::Tandem::Ability.new(::Tandem::Configuration.current_user.call(request))
yield.tap do
controller.instance_variable_set :@current_ability, nil
end
end
end
end