volontariat/voluntary

View on GitHub
lib/voluntary/navigation.rb

Summary

Maintainability
F
1 wk
Test Coverage
module Voluntary
  module Navigation
    class Base
      @@products = {}
      @@core_menus = [:areas, :products, :organizations, :projects, :users, :workflow, :authentication]
      @@core_menu_codes = {}
      @@menu_options = {}
      
      def self.add_product(slug, text)
        @@products[slug] = text
      end
      
      def self.products
        @@products
      end
      
      def self.core_menus
        @@core_menus.uniq
      end
      
      def self.core_menu_codes
        @@core_menu_codes
      end
      
      def self.insert_before_core_menu_item(menu, other_menu)
        @@core_menus.insert(@@core_menus.index(other_menu), menu)
      end
      
      def self.add_core_menu_code(resource, code)
        @@core_menu_codes[resource] = code
      end
      
      def self.add_menu_option(resource, option, value)
        @@menu_options[resource] ||= {}
        @@menu_options[resource][option] = value
      end
      
      def self.menu_options(resource)
        @@menu_options[resource] ||= {}
        @@menu_options[resource]
      end
    end
    
    def self.code
      Proc.new do |navigation|
        navigation.items do |primary, options|
          primary.dom_class = 'nav'
          primary.item :root, I18n.t('general.index.title'), root_path
          
          ::Voluntary::Navigation::Base.core_menus.each do |resource|
            instance_exec primary, ::Voluntary::Navigation::Base.menu_options(resource), &::Voluntary::Navigation.menu_code(resource)
          end
        end
      end
    end
    
    def self.menu_code(resource)
      case resource
      when :areas
        Proc.new do |primary, options|
          primary.item :areas, I18n.t('areas.index.title'), areas_path do |areas|
            areas.item :new, I18n.t('general.new'), new_area_path
            
            unless (@area.new_record? rescue true)
              areas.item :show, @area.name, area_path(@area) do |area|
                if can? :destroy, @area
                  area.item :destroy, I18n.t('general.destroy'), area_path(@area), method: :delete, confirm: I18n.t('general.questions.are_you_sure')
                end
                
                area.item :show, I18n.t('general.details'), "#{area_path(@area)}#top"
                area.item :edit, I18n.t('general.edit'), edit_area_path(@area) if can? :edit, @area
                area.item :users, I18n.t('users.index.title'), area_users_path(@area)
                area.item :projects, I18n.t('projects.index.title'), area_projects_path(@area)  
                
                if options[:after_resource_has_many]
                  instance_exec area, {}, &options[:after_resource_has_many]
                end
              end
            end
          end
        end
      when :products 
        Proc.new do |primary, options|
          primary.item :products, I18n.t('products.index.title'), products_path do |products|
            products.item :new, I18n.t('general.new'), new_product_path
            
            unless (@product.new_record? rescue true)
              products.item :show, @product.name, product_path(@product) do |product|
                if can? :edit, @product
                  product.item :destroy, I18n.t('general.destroy'), product_path(@product), method: :delete, confirm: I18n.t('general.questions.are_you_sure')
                end
                
                product.item :show, I18n.t('general.details'), "#{product_path(@product)}#top"
                product.item :edit, I18n.t('general.edit'), edit_product_path(@product)  if can? :edit, @product
                  
                product.item :projects, I18n.t('projects.index.title'), product_projects_path(@product)   
                
                if options[:after_resource_has_many]
                  instance_exec product, {}, &options[:after_resource_has_many]
                end
              end
            end
          end
        end
      when :organizations
        Proc.new do |primary, options|
          primary.item :organizations, I18n.t('organizations.index.title'), organizations_path do |organizations|
            organizations.item :new, I18n.t('general.new'), new_organization_path
            
            unless (@organization.new_record? rescue true)
              organizations.item :show, @organization.name, organization_path(@organization) do |organization|
                if can? :destroy, @organization
                  organization.item :destroy, I18n.t('general.destroy'), organization_path(@organization), method: :delete, confirm: I18n.t('general.questions.are_you_sure')
                end
                
                organization.item :show, I18n.t('general.details'), "#{organization_path(@organization)}#top"
                organization.item :edit, I18n.t('general.edit'), edit_organization_path(@organization) if can? :edit, @organization
                organization.item :projects, I18n.t('projects.index.title'), organization_projects_path(@organization)  
                
                if options[:after_resource_has_many]
                  instance_exec organization, {}, &options[:after_resource_has_many]
                end
              end
            end
          end
        end
      when :projects
        Proc.new do |primary, options|
          primary.item :projects, I18n.t('projects.index.title'), projects_path do |projects|
            projects.item :new, I18n.t('general.new'), new_project_path
            
            unless (@project.new_record? rescue true)
              projects.item :show, @project.name, project_path(@project) do |project|
                if can? :destroy, @project
                  project.item :destroy, I18n.t('general.destroy'), project_path(@project), method: :delete, confirm: I18n.t('general.questions.are_you_sure')
                end
                
                project.item :show, I18n.t('general.details'), "#{project_path(@project)}#top"
                project.item :edit, I18n.t('general.edit'), edit_project_path(@project) if can? :edit, @project
                
                project.item :users, I18n.t('users.index.title'), project_users_path(@project)  
                
                project.item :stories, I18n.t('stories.index.title'), project_stories_path(@project) do |stories|
                  stories.item :new, I18n.t('general.new'), new_project_story_path(@project)
      
                  unless (@story.new_record? rescue true)
                    stories.item(:show, @story.name, story_path(@story)) do |story|
                      if can? :destroy, @story
                        story.item :destroy, I18n.t('general.destroy'), story_path(@story), method: :delete, confirm: I18n.t('general.questions.are_you_sure')
                      end
                      
                      story.item :show, I18n.t('general.details'), "#{story_path(@story)}#top"
                      story.item :edit, I18n.t('general.edit'), edit_story_path(@story) if can? :edit, @story
      
                      story.item :steps, I18n.t('general.steps'), setup_tasks_story_path(@story) do |steps|
                        steps.item :setup_tasks, I18n.t('stories.steps.setup_tasks.title'), setup_tasks_story_path(@story)
                        steps.item :activate, I18n.t('general.events.activate'), activate_story_path(@story)
                      end
                                      
                      story.item :tasks, I18n.t('tasks.index.title'), story_tasks_path(@story) do |tasks|
                        tasks.item :new, I18n.t('general.new'), new_story_task_path(@story)
            
                        unless (@task.new_record? rescue true)
                          tasks.item(:show, @task.name, task_path(@task)) do |task|
                            if can? :destroy, @task
                              task.item :destroy, I18n.t('general.destroy'), task_path(@task), method: :delete, confirm: I18n.t('general.questions.are_you_sure')
                            end
                            
                            task.item :show, I18n.t('general.details'), "#{task_path(@task)}#top"
                            task.item :edit, I18n.t('general.edit'), edit_task_path(@task) if can? :edit, @task
                            
                            task.item :results, I18n.t('results.index.title'), task_results_path(@task) do |results|
                              results.item :new, I18n.t('general.new'), new_task_result_path(@task)
                  
                              unless (@result.new_record? rescue true)
                                results.item(:show, @result.name, result_path(@result)) do |result|
                                  if can? :destroy, @result
                                    result.item :destroy, I18n.t('general.destroy'), result_path(@result), method: :delete, confirm: I18n.t('general.questions.are_you_sure')
                                  end
                                  
                                  result.item :show, I18n.t('general.details'), "#{result_path(@result)}#top"
                                  result.item :edit, I18n.t('general.edit'), edit_result_path(@result) if can? :edit, @result
                                  
                                  result.item :comments, I18n.t('comments.index.title'), "#{story_path(@story)}#comments" do |comments|
                                    comments.item(:new, I18n.t('general.new'), new_story_comment_path(@story)) if @comment
                                    
                                    if can? :edit, @comment
                                      comments.item(:edit, I18n.t('general.edit'), edit_comment_path(@comment)) if @comment.try(:id)
                                    end
                                  end 
                                end
                              end
                            end
                            
                            task.item :comments, I18n.t('comments.index.title'), "#{story_path(@story)}#comments" do |comments|
                              comments.item(:new, I18n.t('general.new'), new_story_comment_path(@story)) if @comment
                              
                              if @comment.try(:id) && can?(:edit, @comment)
                                comments.item(:edit, I18n.t('general.edit'), edit_comment_path(@comment))
                              end
                            end 
                          end
                        end
                      end
                      
                      story.item :comments, I18n.t('comments.index.title'), "#{story_path(@story)}#comments" do |comments|
                        comments.item(:new, I18n.t('general.new'), new_story_comment_path(@story)) if @comment
                        
                        if @comment.try(:id) && can?(:edit, @comment)
                          comments.item(:edit, I18n.t('general.edit'), edit_comment_path(@comment))
                        end
                      end 
                      
                      if options[:stories_after_resource_has_many]
                        instance_exec story, {}, &options[:stories_after_resource_has_many]
                      end
                    end
                  end
                end
                
                project.item :comments, I18n.t('comments.index.title'), "#{project_path(@project)}#comments" do |comments|
                  comments.item(:new, I18n.t('general.new'), new_project_comment_path(@project)) if @comment
                  
                  if @comment.try(:id) && can?(:edit, @comment)
                    comments.item(:edit, I18n.t('general.edit'), edit_comment_path(@comment))
                  end
                end
                
                if options[:after_resource_has_many]
                  instance_exec project, {}, &options[:after_resource_has_many]
                end
              end
            end  
          end
        end  
      when :users
        Proc.new do |primary, options|
          primary.item :users, I18n.t('users.index.title'), users_path do |users|
            unless (@user.new_record? rescue true) || current_user.try(:id) == @user.id
              users.item :show, I18n.t('general.details'), "#{user_path(@user)}#top"
              
              users.item :projects, I18n.t('projects.index.title'), user_projects_path(@user)
              
              if options[:after_resource_has_many]
                instance_exec users, {}, &options[:after_resource_has_many]
              end
            end
          end
        end
      when :workflow
        Proc.new do |primary, options|
          if user_signed_in?
            primary.item :workflow, I18n.t('workflow.index.title'), workflow_path do |workflow|
              workflow.item :project_owner, I18n.t('workflow.project_owner.index.title'), workflow_project_owner_index_path do |project_owner|
                if options[:project_owner_menu_items]
                  instance_exec project_owner, {}, &options[:project_owner_menu_items]
                end
              end
              
              workflow.item :user, I18n.t('workflow.user.index.title'), workflow_user_index_path do |user|
                ::Voluntary::Navigation::Base.products.each do |slug, key|
                  text = I18n.t(key)
                  
                  user.item slug.gsub('-', '_').to_sym, text, product_workflow_user_index_path(slug) do |product|
                    product_slug = @story ? (@story.product.try(:to_param) || 'no-name') : 'no-name'
                    
                    unless (@story.new_record? rescue true) || product_slug != slug
                      product.item(:show, @story.name, story_path(@story)) do |story|
                        story.item :show, I18n.t('general.details'), "#{story_path(@story)}#top"
                      
                        story.item :tasks, I18n.t('tasks.index.title'), tasks_workflow_user_index_path(@story) do |tasks|
                          unless (@task.new_record? rescue true)
                            tasks.item(:edit, @task.name, edit_task_workflow_user_index_path(@task))
                          end
                        end
                      end
                    end
                    
                    product.item :next_task, I18n.t('workflow.user.tasks.next.title'), next_task_workflow_user_index_path('text-creation')
                  end
                end
              end
            end
          end
        end
      when :authentication
        Proc.new do |primary, options|
          if user_signed_in?
            primary.item :profile, I18n.t('users.show.title'), user_path(current_user) do |profile|
              profile.item :show, I18n.t('users.show.title'), user_path(current_user) do |user|
                user.item :show, I18n.t('users.show.title'), "#{user_path(current_user)}#top"
                user.item :settings, I18n.t('users.edit.title'), edit_user_path(current_user)
                user.item :preferences, I18n.t('users.preferences.title'), preferences_user_path(current_user)
                user.item :projects, I18n.t('projects.index.title'), user_projects_path(current_user)
                
                if options[:profile_menu_items]
                  instance_exec user, {}, &options[:profile_menu_items]
                end
              end
            end
            
            primary.item :sign_out, I18n.t('authentication.sign_out'), destroy_user_session_path, method: :delete
          else
            primary.item :authentication, I18n.t('authentication.title'), new_user_session_path do |authentication|
              authentication.item :sign_in, I18n.t('authentication.sign_in'), new_user_session_path
              #authentication.item :rpx_sign_in, I18n.t('authentication.rpx_sign_in'), 'a' # link_to_rpx
              authentication.item :sign_up, I18n.t('authentication.sign_up'), new_user_registration_path
            end
          end
        end
      else
        Proc.new do |primary, options|
          ::Voluntary::Navigation::Base.core_menu_codes.each do |working_resource, code|
            next unless working_resource == resource
            
            instance_exec primary, ::Voluntary::Navigation::Base.menu_options(resource), &code
          end
        end
      end
    end
  end
end