Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Allow for customised templates based on current organisation's class.

Adds a new ActionView resolver, OrganisationResolver, which looks for a
template in a subdirectory named after the current organisation's class, in
preference to the default template in the default location.
  • Loading branch information...
commit a165f4095f81e7e5fa3efce02db5dc2fe01d6f65 1 parent 1d74ee7
@chrismear chrismear authored
View
30 app/controllers/application_controller.rb
@@ -1,6 +1,7 @@
require 'lib/one_click_orgs/setup'
require 'lib/unauthenticated'
require 'lib/not_found'
+require 'lib/one_click_orgs/organisation_resolver'
class ApplicationController < ActionController::Base
protect_from_forgery
@@ -18,15 +19,18 @@ class ApplicationController < ActionController::Base
# Returns the organisation corresponding to the subdomain that the current
# request has been made on (or just returns the organisation if the app
# is running in single organisation mode).
- helper_method :current_organisation
def current_organisation
- @current_organisation ||= (
+ unless @current_organisation
if Setting[:single_organisation_mode]
- Organisation.first
+ @current_organisation = Organisation.first
else
- Organisation.find_by_host(request.host_with_port)
+ @current_organisation = Organisation.find_by_host(
+ request.host_with_port
+ )
end
- )
+ install_organisation_resolver(@current_organisation)
+ end
+ @current_organisation
end
alias :co :current_organisation
@@ -225,4 +229,20 @@ def handle_unauthenticated
flash[:error] = exception.message
redirect_to root_path
end
+
+ # ORGANISATION RESOLVER
+
+ # Configures the controller's view context to use an
+ # OrganisationResolver based on the given organisation's class when
+ # resolving (looking up) template paths.
+ def install_organisation_resolver(organisation)
+ view_paths.dup.each do |view_path|
+ prepend_view_path(
+ OneClickOrgs::OrganisationResolver.new(
+ view_path.to_path,
+ organisation.class
+ )
+ )
+ end
+ end
end
View
57 app/views/one_click/association/dashboard.html.haml
@@ -0,0 +1,57 @@
+%h2 Voting & proposals
+
+- if current_organisation.active? || current_organisation.proposed?
+ .section.open-proposals
+ %h3 Votes in progress
+ %p.explanation
+ - if @proposals.count == 0
+ No proposals are currently undergoing voting by
+ = @current_organisation.name
+ members.
+ - else
+ These proposals are currently undergoing voting by
+ = @current_organisation.name
+ members.
+ - @proposals.each do |proposal|
+ = content_tag_for(:div, proposal) do
+ %h4
+ = proposal.title
+ %span.time-ends
+ (voting ends
+ = proposal.end_date.to_s(:long)
+ )
+ = render 'proposals/description', :proposal => proposal
+ %p.votes
+ = proposal.votes_for
+ votes for,
+ = proposal.votes_against
+ against
+ = render 'proposals/vote', :proposal => proposal
+ %br.clear
+
+- if current_organisation.active?
+ .section
+ %input{:type => 'button', :value => 'Propose a vote', :id => 'button-proposal', :class => 'button-form-show'}
+ %input{:type => 'button', :value => 'Propose a new member', :id => 'button-member-invite', :class => 'button-form-show'}
+ %input{:type => 'button', :value => 'Propose an amendment to the constitution', :id => 'button-constitution-change', :class => 'button-form-show'}
+ %br.clear
+
+ %div#propose_freeform_form.form-to-hide
+ = render :partial => 'shared/propose_freeform_form'
+
+ %div#propose_new_member_form.form-to-hide
+ %h3 Propose a new member
+ = form_for(@add_member_proposal) do |form|
+ = render :partial => 'add_member_proposals/form', :locals => {:form => form}
+
+- if current_organisation.active?
+ %div.section
+ %h3 Timeline
+ %table.timeline
+ %tr
+ %th Event
+ %th Date
+ - for event in @timeline
+ %tr{:class => cycle('odd', 'even')}
+ = render :partial => event[:kind].to_s, :locals => {:event => event}
+ %td.timestamp= event[:timestamp].to_s(:long)
View
57 app/views/one_click/company/dashboard.html.haml
@@ -0,0 +1,57 @@
+%h2 Voting & proposals
+
+- if current_organisation.active? || current_organisation.proposed?
+ .section.open-proposals
+ %h3 Votes in progress
+ %p.explanation
+ - if @proposals.count == 0
+ No proposals are currently undergoing voting by
+ = @current_organisation.name
+ members.
+ - else
+ These proposals are currently undergoing voting by
+ = @current_organisation.name
+ members.
+ - @proposals.each do |proposal|
+ = content_tag_for(:div, proposal) do
+ %h4
+ = proposal.title
+ %span.time-ends
+ (voting ends
+ = proposal.end_date.to_s(:long)
+ )
+ = render 'proposals/description', :proposal => proposal
+ %p.votes
+ = proposal.votes_for
+ votes for,
+ = proposal.votes_against
+ against
+ = render 'proposals/vote', :proposal => proposal
+ %br.clear
+
+- if current_organisation.active?
+ .section
+ %input{:type => 'button', :value => 'Propose a vote', :id => 'button-proposal', :class => 'button-form-show'}
+ %input{:type => 'button', :value => 'Propose a new member', :id => 'button-member-invite', :class => 'button-form-show'}
+ %input{:type => 'button', :value => 'Propose an amendment to the constitution', :id => 'button-constitution-change', :class => 'button-form-show'}
+ %br.clear
+
+ %div#propose_freeform_form.form-to-hide
+ = render :partial => 'shared/propose_freeform_form'
+
+ %div#propose_new_member_form.form-to-hide
+ %h3 Propose a new member
+ = form_for(@add_member_proposal) do |form|
+ = render :partial => 'add_member_proposals/form', :locals => {:form => form}
+
+- if current_organisation.active?
+ %div.section
+ %h3 Timeline
+ %table.timeline
+ %tr
+ %th Event
+ %th Date
+ - for event in @timeline
+ %tr{:class => cycle('odd', 'even')}
+ = render :partial => event[:kind].to_s, :locals => {:event => event}
+ %td.timestamp= event[:timestamp].to_s(:long)
View
44 lib/one_click_orgs/organisation_resolver.rb
@@ -0,0 +1,44 @@
+require 'action_view/template/resolver'
+
+module OneClickOrgs
+ # OrganisationResolver is a custom template resolver that provides for
+ # customisation of an entire template based on the kind of organisation
+ # we are dealing with.
+ #
+ # The resolver looks for customised templates in a subdirectory named after
+ # the name of the class you specify at initialisation time. If a customised
+ # template cannot be found, it falls back to using the default template.
+ #
+ # For instance, if you create a new OrganisationResolver like this:
+ #
+ # OrganisationResolver.new(Rails.root + '/app/views', Company)
+ #
+ # and prepend the new resolver to your view paths, then an attempt to
+ # render the +index+ action of the +people+ controller will try the
+ # follwing templates in order until it finds one that exists:
+ #
+ # * <tt>app/views/people/index</tt>
+ # * <tt>app/views/people/company/index</tt>
+ class OrganisationResolver < ActionView::FileSystemResolver
+ # +path+ is a root template path on the file system
+ # (e.g. <tt>Rails.root + '/app/views'</tt>).
+ #
+ # +organisation_class+ is the Class for which you want to search for
+ # customised templates.
+ def initialize(path, organisation_class)
+ super(path)
+ @organisation_class_name = organisation_class.name.underscore
+ end
+
+ private
+
+ def find_templates(name, prefix, partial, details)
+ name_expansions = ["#{@organisation_class_name}/#{name}", name]
+ templates = []
+ name_expansions.each do |expanded_name|
+ templates += super(expanded_name, prefix, partial, details)
+ end
+ templates
+ end
+ end
+end
View
28 spec/requests/template_resolution_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe "template resolution" do
+
+ describe "scoped by organisation class" do
+ it "picks an association subtemplate when the organisation is an association" do
+ default_association
+ login
+ get '/'
+ response.should render_template 'one_click/association/dashboard'
+ end
+
+ it "picks a company subtemplate when the organisation is a company" do
+ default_company
+ login
+ get '/'
+ response.should render_template 'one_click/company/dashboard'
+ end
+
+ it "picks the default template when no subtemplate is available" do
+ default_association
+ login
+ get '/proposals'
+ response.should render_template 'proposals/index'
+ end
+ end
+
+end
View
6 spec/support/blueprints.rb
@@ -90,3 +90,9 @@
objectives
subdomain
end
+
+Association.blueprint do
+end
+
+Company.blueprint do
+end
View
20 spec/support/helpers.rb
@@ -13,6 +13,26 @@ def default_organisation(attributes={})
@organisation
end
+def default_association(attributes={})
+ set_up_app
+
+ unless @organisation
+ @organisation = Association.make({:state => 'active'}.merge(attributes))
+ Organisation.stub!(:find_by_host).and_return(@organisation)
+ end
+ @organisation
+end
+
+def default_company(attributes={})
+ set_up_app
+
+ unless @organisation
+ @organisation = Company.make({:state => 'active'}.merge(attributes))
+ Organisation.stub!(:find_by_host).and_return(@organisation)
+ end
+ @organisation
+end
+
def default_constitution
default_organisation
@organisation.clauses.set_integer!(:voting_period, 3 * 86400)
Please sign in to comment.
Something went wrong with that request. Please try again.