voluntary 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. data/app/assets/javascripts/voluntary/application.js +1 -1
  2. data/app/assets/javascripts/voluntary/base.js.coffee +30 -1
  3. data/app/assets/stylesheets/voluntary/application.css +1 -0
  4. data/app/assets/stylesheets/voluntary/base.css.sass +1 -1
  5. data/app/controllers/areas_controller.rb +6 -5
  6. data/app/controllers/candidatures_controller.rb +15 -10
  7. data/app/controllers/concerns/voluntary/v1/base_controller.rb +95 -0
  8. data/app/controllers/devise_extensions/registrations_controller.rb +2 -2
  9. data/app/controllers/organizations_controller.rb +7 -6
  10. data/app/controllers/professions_controller.rb +6 -5
  11. data/app/controllers/projects_controller.rb +11 -6
  12. data/app/controllers/users_controller.rb +2 -2
  13. data/app/controllers/vacancies_controller.rb +14 -5
  14. data/app/controllers/voluntary/api/v1/api_controller.rb +9 -0
  15. data/app/controllers/voluntary/application_controller.rb +2 -66
  16. data/app/controllers/workflow/candidatures_controller.rb +1 -1
  17. data/app/controllers/workflow/products_controller.rb +7 -7
  18. data/app/controllers/workflow/stories_controller.rb +1 -1
  19. data/app/controllers/workflow/tasks_controller.rb +2 -2
  20. data/app/controllers/workflow/user/product/areas_controller.rb +2 -2
  21. data/app/controllers/workflow/user/projects_controller.rb +10 -2
  22. data/app/helpers/voluntary/application_helper.rb +79 -0
  23. data/app/helpers/voluntary/collection_helper.rb +45 -0
  24. data/app/helpers/voluntary/comments_helper.rb +13 -0
  25. data/app/helpers/voluntary/form_helper.rb +46 -0
  26. data/app/helpers/voluntary/language_helper.rb +17 -0
  27. data/app/helpers/voluntary/layout_helper.rb +42 -0
  28. data/app/helpers/voluntary/product_helper.rb +36 -0
  29. data/app/helpers/voluntary/show_helper.rb +67 -0
  30. data/app/helpers/voluntary/wizard_helper.rb +29 -0
  31. data/app/models/ability.rb +20 -4
  32. data/app/models/candidature.rb +10 -7
  33. data/app/models/column.rb +1 -0
  34. data/app/models/concerns/user/extensions.rb +5 -0
  35. data/app/models/concerns/user/listable.rb +10 -0
  36. data/app/models/list.rb +30 -0
  37. data/app/models/list_item.rb +22 -0
  38. data/app/models/organization.rb +1 -0
  39. data/app/models/page.rb +2 -1
  40. data/app/models/product.rb +3 -2
  41. data/app/models/project.rb +2 -2
  42. data/app/models/result.rb +1 -0
  43. data/app/models/role.rb +1 -1
  44. data/app/models/state_machines/candidature.rb +17 -1
  45. data/app/models/state_machines/story.rb +15 -2
  46. data/app/models/state_machines/task.rb +33 -0
  47. data/app/models/story.rb +3 -2
  48. data/app/models/task.rb +44 -6
  49. data/app/models/thing.rb +3 -0
  50. data/app/models/user.rb +15 -4
  51. data/app/models/vacancy.rb +7 -5
  52. data/app/presenters/resources/general/wizards/story/steps/setup_tasks_presenter.rb +1 -1
  53. data/app/presenters/shared/collection/table_presenter.rb +1 -1
  54. data/app/views/candidatures/index.html.erb +1 -1
  55. data/app/views/candidatures/show.html.erb +1 -1
  56. data/app/views/columns/_collection.html.erb +0 -0
  57. data/app/views/comments/_resource.html.erb +1 -1
  58. data/app/views/layouts/application.html.erb +12 -0
  59. data/app/views/layouts/shared/_navigation.html.erb +3 -3
  60. data/app/views/organizations/show.html.erb +0 -1
  61. data/app/views/products/index.html.erb +53 -4
  62. data/app/views/projects/_form.html.erb +1 -0
  63. data/app/views/projects/show.html.erb +2 -1
  64. data/app/views/shared/collection/_list.html.erb +1 -1
  65. data/app/views/shared/resource/_actions.html.erb +2 -2
  66. data/app/views/stories/_column_fields.html.erb +0 -0
  67. data/app/views/stories/_form.html.erb +1 -1
  68. data/app/views/stories/steps/_activate.html.erb +1 -1
  69. data/app/views/workflow/products/show.html.erb +1 -1
  70. data/app/views/workflow/project_owner/_candidatures.html.erb +2 -1
  71. data/app/views/workflow/tasks/_work_head.html.erb +1 -1
  72. data/app/views/workflow/tasks/steps/_complete.html.erb +6 -2
  73. data/app/views/workflow/tasks/steps/_review.html.erb +6 -2
  74. data/app/views/workflow/tasks/steps/_work.html.erb +4 -2
  75. data/app/views/workflow/user/product/areas/show.html.erb +0 -0
  76. data/app/views/workflow/user/projects/show.html.erb +0 -0
  77. data/config/initializers/devise.rb +2 -5
  78. data/config/initializers/filter_parameters_logging.rb +1 -0
  79. data/config/initializers/friendly_id.rb +88 -0
  80. data/config/initializers/wrap_parameters.rb +15 -0
  81. data/config/locales/general/en.yml +15 -9
  82. data/config/locales/resources/story/en.yml +1 -0
  83. data/config/routes.rb +9 -0
  84. data/config/routes/workflow.rb +15 -15
  85. data/db/migrate/20120907144853_create_schema.rb +1 -1
  86. data/db/migrate/20120922201955_create_mongo_db_documents.rb +1 -1
  87. data/db/migrate/20121004132105_create_professions.rb +1 -1
  88. data/db/migrate/20121006162913_add_public_attribute_to_roles.rb +20 -1
  89. data/db/migrate/20130817090734_create_lists.rb +33 -0
  90. data/db/migrate/20131018143613_replace_user_by_polymorphic_resource_in_candidatures.rb +46 -0
  91. data/db/migrate/20140307113214_add_user_id_to_organizations.rb +5 -0
  92. data/lib/api_constraints.rb +10 -0
  93. data/lib/applicat/mvc/model/tree.rb +1 -1
  94. data/lib/concerns/model/base_list_item.rb +30 -0
  95. data/lib/concerns/model/base_thing.rb +50 -0
  96. data/lib/db_seed.rb +15 -4
  97. data/lib/generators/voluntary/install/install_generator.rb +17 -16
  98. data/lib/generators/voluntary/install/templates/app/views/layouts/application.html.erb +17 -1
  99. data/lib/generators/voluntary/install/templates/config/main_navigation.rb +1 -260
  100. data/lib/generators/voluntary/install/templates/features/support/integration_sessions_controller.rb +1 -2
  101. data/lib/generators/voluntary/install/templates/spec/factories.rb +19 -0
  102. data/lib/generators/voluntary/install/templates/spec/support/mongo_database_cleaner.rb +14 -4
  103. data/lib/generators/voluntary/product_dummy/product_dummy_generator.rb +23 -17
  104. data/lib/generators/voluntary/product_dummy/templates/config/database.example.yml +1 -1
  105. data/lib/generators/voluntary/product_dummy/templates/dummy/spec/factories.rb +19 -0
  106. data/lib/generators/voluntary/product_dummy/templates/dummy/spec/spec_helper.rb +75 -0
  107. data/lib/generators/voluntary/product_dummy/templates/features/support/integration_sessions_controller.rb +1 -2
  108. data/lib/generators/voluntary/product_dummy/templates/spec/factories.rb +19 -0
  109. data/lib/voluntary.rb +10 -22
  110. data/lib/voluntary/engine.rb +27 -3
  111. data/lib/voluntary/navigation.rb +358 -0
  112. data/lib/voluntary/test/rspec_helpers/factories.rb +123 -0
  113. data/lib/voluntary/version.rb +1 -1
  114. data/vendor_extensions/active_model/naming.rb +1 -1
  115. metadata +526 -308
  116. data/app/helpers/application_helper.rb +0 -65
  117. data/app/helpers/collection_helper.rb +0 -35
  118. data/app/helpers/comments_helper.rb +0 -11
  119. data/app/helpers/form_helper.rb +0 -43
  120. data/app/helpers/language_helper.rb +0 -15
  121. data/app/helpers/layout_helper.rb +0 -39
  122. data/app/helpers/product_helper.rb +0 -34
  123. data/app/helpers/show_helper.rb +0 -65
  124. data/app/helpers/wizard_helper.rb +0 -27
  125. data/app/observers/candidature_observer.rb +0 -29
  126. data/app/observers/story_observer.rb +0 -6
  127. data/app/observers/task_observer.rb +0 -34
  128. data/lib/voluntary/helpers/application.rb +0 -69
  129. data/lib/voluntary/helpers/collection.rb +0 -35
  130. data/lib/voluntary/helpers/comments.rb +0 -15
  131. data/lib/voluntary/helpers/form.rb +0 -43
  132. data/lib/voluntary/helpers/language.rb +0 -19
  133. data/lib/voluntary/helpers/layout.rb +0 -28
  134. data/lib/voluntary/helpers/product.rb +0 -36
  135. data/lib/voluntary/helpers/show.rb +0 -69
  136. data/lib/voluntary/helpers/wizard.rb +0 -31
@@ -46,7 +46,7 @@ class UsersController < ApplicationController
46
46
  private
47
47
 
48
48
  def find_resource
49
- @user = User.find(params[:id])
49
+ @user = User.friendly.find(params[:id])
50
50
  @presenter = Resources::User::FormPresenter.new(self.view_context, resource: resource)
51
51
  end
52
- end
52
+ end
@@ -1,6 +1,8 @@
1
1
  class VacanciesController < ApplicationController
2
2
  include Applicat::Mvc::Controller::Resource
3
3
 
4
+ before_filter :find_vacancy
5
+
4
6
  load_and_authorize_resource
5
7
 
6
8
  before_filter :find_project, only: [:index, :new, :edit]
@@ -12,7 +14,6 @@ class VacanciesController < ApplicationController
12
14
  end
13
15
 
14
16
  def show
15
- @vacancy = Vacancy.includes(:project, :candidatures, :comments).find(params[:id])
16
17
  @comments = @vacancy.comments
17
18
  end
18
19
 
@@ -40,11 +41,11 @@ class VacanciesController < ApplicationController
40
41
  end
41
42
 
42
43
  def edit
43
- @vacancy = Vacancy.find(params[:id])
44
+ @vacancy = Vacancy.friendly.find(params[:id])
44
45
  end
45
46
 
46
47
  def update
47
- @vacancy = Vacancy.find(params[:id])
48
+ @vacancy = Vacancy.friendly.find(params[:id])
48
49
 
49
50
  if @vacancy.update_attributes(params[:vacancy])
50
51
  redirect_to @vacancy, notice: t('general.form.successfully_updated')
@@ -54,7 +55,7 @@ class VacanciesController < ApplicationController
54
55
  end
55
56
 
56
57
  def destroy
57
- @vacancy = Vacancy.find(params[:id])
58
+ @vacancy = Vacancy.friendly.find(params[:id])
58
59
  @vacancy.destroy
59
60
  redirect_to vacancies_url, notice: t('general.form.destroyed')
60
61
  end
@@ -73,7 +74,15 @@ class VacanciesController < ApplicationController
73
74
 
74
75
  private
75
76
 
77
+ def find_vacancy
78
+ return unless params[:id].present?
79
+
80
+ @vacancy = Vacancy
81
+ @vacancy = @vacancy.includes(:project, :candidatures, :comments) if action_name == 'show'
82
+ @vacancy = @vacancy.friendly.find(params[:id])
83
+ end
84
+
76
85
  def find_project
77
- @project = params[:project_id].present? ? Project.find(params[:project_id]) : nil
86
+ @project = params[:project_id].present? ? Project.friendly.find(params[:project_id]) : nil
78
87
  end
79
88
  end
@@ -0,0 +1,9 @@
1
+ module Voluntary
2
+ module Api
3
+ module V1
4
+ class BaseController < ActionController::API
5
+ include Voluntary::V1::BaseController
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,6 @@
1
1
  class Voluntary::ApplicationController < ActionController::Base
2
2
  include Applicat::Mvc::Controller
3
+ include Voluntary::V1::BaseController
3
4
 
4
5
  protect_from_forgery
5
6
 
@@ -7,24 +8,10 @@ class Voluntary::ApplicationController < ActionController::Base
7
8
 
8
9
  layout Proc.new { |controller| controller.request.xhr? ? 'facebox' : 'application' }
9
10
 
10
- rescue_from CanCan::AccessDenied, with: :access_denied
11
- rescue_from ActiveRecord::RecordNotFound, with: :not_found
12
- rescue_from Mongoid::Errors::DocumentNotFound, with: :not_found
13
-
14
11
  respond_to :html, :js, :json
15
12
 
16
- def parent
17
- @parent
18
- end
19
-
20
- helper_method :parent
21
-
22
13
  protected
23
-
24
- def current_ability
25
- Ability.new(current_user, controller_namespace: current_namespace)
26
- end
27
-
14
+
28
15
  def after_sign_in_path_for(resource_or_scope)
29
16
  if resource_or_scope.main_role.is_a? Role::ProjectOwner
30
17
  workflow_project_owner_index_path
@@ -39,58 +26,7 @@ class Voluntary::ApplicationController < ActionController::Base
39
26
  @twitter_sidenav_level = 3
40
27
  end
41
28
 
42
- def find_parent(types, parent_key = nil)
43
- parent_type, id = nil, nil
44
-
45
- if parent_type = types.select{|p| params.keys.include?("#{p}_id") }.first
46
- id = params["#{parent_type}_id"]
47
- elsif parent_type = types.select{|p| params[parent_key] && params[parent_key].keys.include?("#{p}_id") }.first
48
- id = params[parent_key]["#{parent_type}_id"]
49
- end
50
-
51
- return if parent_type.blank?
52
-
53
- parent = parent_type.classify.constantize.find(id)
54
- root_model_class_name = Voluntary::Helpers::Application.root_model_class_name_helper(parent)
55
- eval("@#{root_model_class_name.tableize.singularize} = parent")
56
-
57
- parent
58
- end
59
-
60
29
  def response_with_standard(format = nil, error = nil)
61
30
  render status: error ? 500 : 200, json: { success: error ? false : true, error: error} and return true
62
31
  end
63
-
64
- private
65
-
66
- def current_namespace
67
- controller_name_segments = params[:controller].split('/')
68
- controller_name_segments.pop
69
- controller_namespace = controller_name_segments.join('/').downcase
70
- end
71
-
72
- def access_denied
73
- message = I18n.t('general.exceptions.access_denied')
74
-
75
- if request.format.try('json?')
76
- render status: 403, json: { error: message } and return
77
- else
78
- flash[:alert] = message
79
-
80
- if request.env["HTTP_REFERER"]
81
- redirect_to :back
82
- else
83
- redirect_to root_path
84
- end
85
- end
86
- end
87
-
88
- def not_found(e)
89
- if Rails.env.development?
90
- raise e
91
- else
92
- logger.info "not found (#{e.inspect})"
93
- redirect_to root_path, notice: t('general.exceptions.not_found')
94
- end
95
- end
96
32
  end
@@ -14,7 +14,7 @@ class Workflow::CandidaturesController < ApplicationController
14
14
  private
15
15
 
16
16
  def state_action
17
- @candidatures = current_user.offeror_candidatures.where(state: action_name).includes(:vacancy, :user)
17
+ @candidatures = current_user.offeror_candidatures.where(state: action_name).includes(:vacancy, :resource)
18
18
  render 'candidatures/index'
19
19
  end
20
20
  end
@@ -1,7 +1,7 @@
1
- class Workflow::ProductsController < ApplicationController
2
- def show
3
- @stories = Product.stories(params[:id], current_user)
4
- @areas = Area.find_by_product_id(params[:id])
5
- @product = Product.find(params[:id]) unless params[:id] == 'no-name'
6
- end
7
- end
1
+ class Workflow::ProductsController < ApplicationController
2
+ def show
3
+ @stories = Product.stories(params[:id], current_user)
4
+ @areas = Area.find_by_product_id(params[:id])
5
+ @product = Product.find(params[:id]) unless params[:id] == 'no-name'
6
+ end
7
+ end
@@ -1,6 +1,6 @@
1
1
  class Workflow::StoriesController < ApplicationController
2
2
  def index
3
- @product = Product.find(params[:product_id])
3
+ @product = Product.friendly.find(params[:product_id])
4
4
  @stories = @product.stories
5
5
  end
6
6
  end
@@ -78,7 +78,7 @@ class Workflow::TasksController < ApplicationController
78
78
  method = params[:event] ? params[:event].keys.first : 'save'
79
79
  success = false
80
80
 
81
- if @result.valid?
81
+ if (@task.with_result? && @result.valid?) || (!@task.with_result? && @task.valid?)
82
82
  success = if params[:next_step] == '1' || (params[:event] && params[:event][:next])
83
83
  @task.send(step)
84
84
  elsif (method == 'save' && can?(:update, @task)) || can?(method.to_sym, @task)
@@ -90,7 +90,7 @@ class Workflow::TasksController < ApplicationController
90
90
 
91
91
  render 'edit' and return unless success
92
92
 
93
- @result.save
93
+ @result.save if @task.with_result?
94
94
 
95
95
  if params[:event] && params[:event][:next]
96
96
  redirect_to(
@@ -1,8 +1,8 @@
1
1
  class Workflow::User::Product::AreasController < ApplicationController
2
2
  def show
3
- @area = Area.find(params[:id])
3
+ @area = Area.friendly.find(params[:id])
4
4
  @areas = @area.children_for_product_id(params[:product_id])
5
5
  @projects = @area.projects.for_product_id(params[:product_id])
6
- @product = Product.find(params[:product_id]) unless params[:product_id] == 'no-name'
6
+ @product = ::Product.find(params[:product_id]) unless params[:product_id] == 'no-name'
7
7
  end
8
8
  end
@@ -1,8 +1,16 @@
1
1
  class Workflow::User::ProjectsController < ApplicationController
2
2
  def show
3
- @project = Project.find(params[:id])
3
+ @project = Project.friendly.find(params[:id])
4
4
 
5
- @stories = @project.product.stories_for_user(current_user).
5
+ product = if @project.product
6
+ @project.product
7
+ else
8
+ value = ::Product.new
9
+ value.id = 'no-name'
10
+ value
11
+ end
12
+
13
+ @stories = product.stories_for_user(current_user).
6
14
  where(project_id: @project.try(:id)).paginate(page: params[:page])
7
15
  end
8
16
  end
@@ -0,0 +1,79 @@
1
+ module Voluntary
2
+ module ApplicationHelper
3
+ include AutoHtml
4
+
5
+ def self.root_model_class_name_helper(resource)
6
+ if resource.class.superclass.name == 'ActiveRecord::Base'
7
+ resource.class.name
8
+ elsif resource.class.superclass.name == 'Object'
9
+ # classes like mongo db models without a specific superclass
10
+ resource.class.name
11
+ else
12
+ resource.class.superclass.name
13
+ end
14
+ end
15
+
16
+ def markdown(text)
17
+ text = Redcarpet::Markdown.new(Redcarpet::Render::XHTML.new(filter_html: true)).render(text)
18
+
19
+ auto_html(text) do
20
+ youtube(width: 515, height: 300)
21
+ dailymotion(width: 515, height: 300)
22
+ vimeo(width: 515, height: 300)
23
+ google_video(width: 515, height: 300)
24
+ image
25
+
26
+ redcarpet(
27
+ renderer: Redcarpet::Render::XHTML.new(
28
+ no_images: true, no_styles: true, hard_wrap: true, with_toc_data: true
29
+ ),
30
+ markdown_options: { no_intra_emphasis: true, autolink: true, fenced_code_blocks: true }
31
+ )
32
+ link :target => "_blank", :rel => "nofollow"
33
+ end.gsub(/(>https?:\/\/[^\<\\]+)/) do |match|
34
+ truncate(match)
35
+ end.html_safe
36
+ end
37
+
38
+ def root_model_class_name(resource)
39
+ ::Voluntary::ApplicationHelper.root_model_class_name_helper(resource)
40
+ end
41
+
42
+ def directory_for_resource(resource)
43
+ resource.class.name.split('::').last.underscore
44
+ end
45
+
46
+ def link_list(collection)
47
+ raw collection.map{|a| link_to a.name, a}.join(', ')
48
+ end
49
+
50
+ def general_attribute?(attribute)
51
+ begin
52
+ I18n.t("attributes.#{attribute}", raise: true)
53
+ true
54
+ rescue
55
+ false
56
+ end
57
+ end
58
+
59
+ def attribute_translation(attribute, current_resource = nil)
60
+ current_resource = current_resource || resource
61
+ t("activerecord.attributes.#{root_model_class_name(current_resource).underscore}.#{attribute}",
62
+ default: t("attributes.#{attribute}")
63
+ )
64
+ end
65
+
66
+ def polymorphic_or_resource_path(record)
67
+ begin
68
+ polymorphic_path(record)
69
+ rescue NoMethodError
70
+ resource_path(record)
71
+ end
72
+ end
73
+
74
+ def resource_path(record)
75
+ klass = ::Voluntary::ApplicationHelper.root_model_class_name_helper(record)
76
+ eval("#{klass.tableize.singularize}_path(record)")
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,45 @@
1
+ module Voluntary
2
+ module CollectionHelper
3
+ def table_cell column, resource, alternative_value = nil
4
+ value = '-'
5
+
6
+ if column == 'name'
7
+ value = resource.send(column)
8
+
9
+ if alternative_value.is_a?(Proc)
10
+ return alternative_value.call(resource)
11
+ elsif value.blank? && alternative_value.present?
12
+ value = eval("resource.#{alternative_value}")
13
+ elsif value.blank?
14
+ value = '-'
15
+ end
16
+
17
+ begin
18
+ link_to value, eval("#{root_model_class_name(resource).tableize.singularize}_path(resource)")
19
+ rescue
20
+ link_to value, eval("#{root_model_class_name(resource).constantize.table_name.singularize}_path(resource)")
21
+ end
22
+ elsif column.match('_id')
23
+ association = nil
24
+
25
+ begin
26
+ association = resource.send(column.gsub('_id', ''))
27
+ rescue
28
+ association = eval("resource.#{alternative_value}") if alternative_value.present?
29
+ end
30
+
31
+ if association
32
+ begin
33
+ link_to(association.name, association)
34
+ rescue NoMethodError
35
+ link_to(association.name, resource_path(association))
36
+ end
37
+ else
38
+ value
39
+ end
40
+ else
41
+ resource.send(column)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,13 @@
1
+ module Voluntary
2
+ module CommentsHelper
3
+ def nested_comments(comments)
4
+ comments.map do |comment, sub_comments|
5
+ next if comment.id.blank?
6
+
7
+ content = render(partial: 'comments/resource', locals: { resource: comment })
8
+ content += content_tag(:div, nested_comments(sub_comments), class: 'nested_comments')
9
+ content
10
+ end.join.html_safe
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,46 @@
1
+ module Voluntary
2
+ module FormHelper
3
+ def link_to_add_fields(name, f, association, options = {})
4
+ attributes = {
5
+ "#{root_model_class_name(f.object).tableize.singularize}".to_sym => f.object
6
+ }
7
+
8
+ new_object = if f.object.respond_to? "#{association.to_s.singularize}_class"
9
+ f.object.send("#{association.to_s.singularize}_class").new(attributes)
10
+ else
11
+ f.object.send(association).new(attributes)
12
+ end
13
+
14
+ id = new_object.object_id
15
+
16
+ #fields = f.fields_for(association, new_object, child_index: id) do |builder|
17
+ fields = f.simple_fields_for(association) do |builder|
18
+ render_product_specific_partial_if_available(
19
+ new_object, "#{controller_name}/#{association.to_s.singularize}_fields",
20
+ f: builder
21
+ )
22
+ end
23
+
24
+ data = {id: id, fields: fields.gsub("\n", '')}
25
+ data[:target] = options[:target] if options.has_key?(:target)
26
+
27
+ link_to(name, '#', class: 'add_fields', data: data)
28
+ end
29
+
30
+ def remove_fields(f)
31
+ if f.object.try(:new_record?)
32
+ link_to t('general.remove'), '#', class: 'remove_fields'
33
+ else
34
+ f.check_box(:_destroy) + f.label(:_destroy, t('general.destroy'))
35
+ end
36
+ end
37
+
38
+ def autocomplete_input(f, field, namespace = nil)
39
+ if namespace
40
+ f.input "#{field}_name", input_html: { data: {autocomplete: eval("autocomplete_#{namespace}_#{field.to_s.tableize}_path")} }
41
+ else
42
+ f.input "#{field}_name", input_html: { data: {autocomplete: eval("autocomplete_#{field.to_s.tableize}_path")} }
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ module Voluntary
2
+ module LanguageHelper
3
+ def available_language_options
4
+ options = []
5
+
6
+ AVAILABLE_LANGUAGES.each do |locale, language|
7
+ options << [language, locale]
8
+ end
9
+
10
+ options.sort_by { |o| o[0] }
11
+ end
12
+
13
+ def all_language_options
14
+ User.languages.sort_by { |o| o[0] }
15
+ end
16
+ end
17
+ end