init import from old mailr project (http://svn.littlegreen.org/mailr/trunk)
This commit is contained in:
commit
51b79e7298
640 changed files with 34651 additions and 0 deletions
170
app/controllers/application.rb
Normal file
170
app/controllers/application.rb
Normal file
|
@ -0,0 +1,170 @@
|
|||
# The filters added to this controller will be run for all controllers in the application.
|
||||
# Likewise will all the methods added be available for all controllers.
|
||||
class ApplicationController < ActionController::Base
|
||||
before_filter :localize
|
||||
before_filter :user_login_filter
|
||||
before_filter :add_scripts
|
||||
|
||||
model :customer
|
||||
|
||||
protected
|
||||
def secure_user?() true end
|
||||
def secure_cust?() false end
|
||||
def additional_scripts() "" end
|
||||
def onload_function() "" end
|
||||
|
||||
private
|
||||
def add_scripts
|
||||
@additional_scripts = additional_scripts()
|
||||
@onload_function = onload_function()
|
||||
end
|
||||
|
||||
def user_login_filter
|
||||
if (secure_user? or secure_cust? )and logged_user.nil?
|
||||
@session["return_to"] = @request.request_uri
|
||||
redirect_to :controller=>"/login", :action => "index"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
alias login_required user_login_filter
|
||||
|
||||
def logged_user # returns customer id
|
||||
@session['user']
|
||||
end
|
||||
|
||||
def logged_customer
|
||||
@session['user']
|
||||
end
|
||||
|
||||
def localize
|
||||
# We will use instance vars for the locale so we can make use of them in
|
||||
# the templates.
|
||||
@charset = 'utf-8'
|
||||
@headers['Content-Type'] = "text/html; charset=#{@charset}"
|
||||
# Here is a very simplified approach to extract the prefered language
|
||||
# from the request. If all fails, just use 'en_EN' as the default.
|
||||
temp = if @request.env['HTTP_ACCEPT_LANGUAGE'].nil?
|
||||
[]
|
||||
else
|
||||
@request.env['HTTP_ACCEPT_LANGUAGE'].split(',').first.split('-') rescue []
|
||||
end
|
||||
language = temp.slice(0)
|
||||
dialect = temp.slice(1)
|
||||
@language = language.nil? ? 'en' : language.downcase # default is en
|
||||
# If there is no dialect use the language code ('en' becomes 'en_EN').
|
||||
@dialect = dialect.nil? ? @language.upcase : dialect
|
||||
# The complete locale string consists of
|
||||
# language_DIALECT (en_EN, en_GB, de_DE, ...)
|
||||
@locale = "#{@language}_#{@dialect.upcase}"
|
||||
@htmllang = @language == @dialect ? @language : "#{@language}-#{@dialect}"
|
||||
# Finally, bind the textdomain to the locale. From now on every used
|
||||
# _('String') will get translated into the right language. (Provided
|
||||
# that we have a corresponding mo file in the right place).
|
||||
bindtextdomain('messages', "#{RAILS_ROOT}/locale", @locale, @charset)
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
def include_tinymce(mode="textareas",elements="")
|
||||
tinymce=''
|
||||
tinymce << '
|
||||
<script language="javascript" type="text/javascript" src="/tiny_mce/tiny_mce.js"></script>
|
||||
<script language="javascript" type="text/javascript">
|
||||
tinyMCE.init({
|
||||
mode : "'
|
||||
tinymce << mode << '",'
|
||||
if mode == "exact"
|
||||
tinymce << 'elements : "' << elements << '",
|
||||
'
|
||||
end
|
||||
tinymce << '
|
||||
theme : "advanced",
|
||||
cleanup : true,
|
||||
width: "100%",
|
||||
remove_linebreaks : false,
|
||||
entity_encoding : "named",
|
||||
relative_urls : false,
|
||||
plugins : "table,save,advhr,advimage,advlink,iespell,preview,zoom,searchreplace,print,contextmenu,fullscreen,linkattach",
|
||||
theme_advanced_buttons1_add : "fontselect,fontsizeselect",
|
||||
theme_advanced_buttons2_add : "separator,preview,zoom",
|
||||
theme_advanced_buttons2_add_before: "cut,copy,paste,separator,search,replace,separator",
|
||||
theme_advanced_buttons3_add_before : "tablecontrols,separator",
|
||||
theme_advanced_buttons3_add : "iespell,forecolor,backcolor,fullscreen",
|
||||
theme_advanced_source_editor_width : "700",
|
||||
theme_advanced_source_editor_height : "500",
|
||||
theme_advanced_styles : "Header 1=header1",
|
||||
theme_advanced_toolbar_location : "top",
|
||||
theme_advanced_toolbar_align : "left",
|
||||
theme_advanced_path_location : "none",
|
||||
extended_valid_elements : ""
|
||||
+"a[accesskey|charset|class|coords|href|hreflang|id|lang|name"
|
||||
+"|onblur|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup"
|
||||
+"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|rel|rev"
|
||||
+"|shape|style|tabindex|title|target|type],"
|
||||
+"dd[class|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup"
|
||||
+"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title],"
|
||||
+"div[align|class|id|lang|onclick"
|
||||
+"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove"
|
||||
+"|onmouseout|onmouseover|onmouseup|style|title],"
|
||||
+"dl[class|compact|id|lang|onclick|ondblclick|onkeydown"
|
||||
+"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover"
|
||||
+"|onmouseup|style|title],"
|
||||
+"dt[class|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup"
|
||||
+"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title],"
|
||||
+"img[align|alt|border|class|height"
|
||||
+"|hspace|id|ismap|lang|longdesc|name|onclick|ondblclick|onkeydown"
|
||||
+"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover"
|
||||
+"|onmouseup|src|style|title|usemap|vspace|width],"
|
||||
+"script[charset|defer|language|src|type],"
|
||||
+"style[lang|media|title|type],"
|
||||
+"table[align|bgcolor|border|cellpadding|cellspacing|class"
|
||||
+"|frame|height|id|lang|onclick|ondblclick|onkeydown|onkeypress"
|
||||
+"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|rules"
|
||||
+"|style|summary|title|width],"
|
||||
+"td[abbr|align|axis|bgcolor|char|charoff|class"
|
||||
+"|colspan|headers|height|id|lang|nowrap|onclick"
|
||||
+"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove"
|
||||
+"|onmouseout|onmouseover|onmouseup|rowspan|scope"
|
||||
+"|style|title|valign|width],"
|
||||
+"hr[align|class|id|lang|noshade|onclick"
|
||||
+"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove"
|
||||
+"|onmouseout|onmouseover|onmouseup|size|style|title|width],"
|
||||
+"font[class|color|face|id|lang|size|style|title],"
|
||||
+"span[align|class|class|id|lang|onclick|ondblclick|onkeydown"
|
||||
+"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover"
|
||||
+"|onmouseup|style|title]",
|
||||
external_link_list_url : "/cms/urlchoose/choose_tinymce",
|
||||
external_attachments_list_url : "/attachments/attachments/choose_tinymce",
|
||||
external_image_list_url : "/gallery/imgchoose/choose_tinymce",
|
||||
flash_external_list_url : "example_data/example_flash_list.js"
|
||||
});
|
||||
</script>'
|
||||
tinymce
|
||||
end
|
||||
|
||||
helper_method :include_tinymce
|
||||
|
||||
def include_simple_tinymce(mode="textareas",elements="")
|
||||
tinymce = ''
|
||||
tinymce << '<script language="javascript" type="text/javascript" src="/tiny_mce/tiny_mce.js"></script>
|
||||
<script language="javascript" type="text/javascript">
|
||||
tinyMCE.init({
|
||||
mode : "'
|
||||
tinymce << mode << '",'
|
||||
if mode == "exact"
|
||||
tinymce << 'elements : "' << elements << '",
|
||||
'
|
||||
end
|
||||
tinymce << '
|
||||
theme : "default",
|
||||
width : "100%",
|
||||
auto_reset_designmode : true
|
||||
});
|
||||
</script>'
|
||||
tinymce
|
||||
end
|
||||
|
||||
helper_method :include_simple_tinymce
|
||||
|
||||
end
|
67
app/controllers/login_controller.rb
Normal file
67
app/controllers/login_controller.rb
Normal file
|
@ -0,0 +1,67 @@
|
|||
require 'ezcrypto'
|
||||
class LoginController < ApplicationController
|
||||
|
||||
model :customer
|
||||
|
||||
def index
|
||||
if not(logged_user.nil?)
|
||||
redirect_to :controller =>"webmail", :action=>"index"
|
||||
else
|
||||
@login_user = Customer.new
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate
|
||||
if user = auth(@params['login_user']["email"], @params['login_user']["password"])
|
||||
@session["user"] = user.id
|
||||
if CDF::CONFIG[:crypt_session_pass]
|
||||
@session["wmp"] = EzCrypto::Key.encrypt_with_password(CDF::CONFIG[:encryption_password], CDF::CONFIG[:encryption_salt], @params['login_user']["password"])
|
||||
else
|
||||
# dont use crypt
|
||||
@session["wmp"] = @params['login_user']["password"]
|
||||
end
|
||||
if @session["return_to"]
|
||||
redirect_to_path(@session["return_to"])
|
||||
@session["return_to"] = nil
|
||||
else
|
||||
redirect_to :action=>"index"
|
||||
end
|
||||
else
|
||||
@login_user = Customer.new
|
||||
flash["error"] = _('Wrong email or password specified.')
|
||||
redirect_to :action => "index"
|
||||
end
|
||||
end
|
||||
|
||||
def logout
|
||||
reset_session
|
||||
flash["status"] = _('User successfully logged out')
|
||||
redirect_to :action => "index"
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def need_subdomain?() true end
|
||||
def secure_user?() false end
|
||||
|
||||
private
|
||||
|
||||
def auth(email, password)
|
||||
mailbox = IMAPMailbox.new
|
||||
begin
|
||||
mailbox.connect(email, password)
|
||||
rescue
|
||||
return nil
|
||||
end
|
||||
mailbox.disconnect
|
||||
mailbox = nil
|
||||
if user = Customer.find_by_email(email)
|
||||
return user
|
||||
else
|
||||
# create record in database
|
||||
user = Customer.create("email"=>email)
|
||||
MailPref.create('customer_id' => user.id)
|
||||
return user
|
||||
end
|
||||
end
|
||||
end
|
137
app/helpers/application_helper.rb
Normal file
137
app/helpers/application_helper.rb
Normal file
|
@ -0,0 +1,137 @@
|
|||
# The methods added to this helper will be available to all templates in the application.
|
||||
module ApplicationHelper
|
||||
|
||||
protected
|
||||
|
||||
def format_datetime(datetime)
|
||||
datetime.strftime "%d.%m.%Y %H:%M"
|
||||
end
|
||||
|
||||
def errors_base(form_name)
|
||||
errors = instance_variable_get("@#{form_name}").errors.on_base()
|
||||
errors_out = ""
|
||||
if errors
|
||||
errors = [errors] unless errors.is_a? Array
|
||||
errors.each do |e|
|
||||
errors_out << "<span class=\"error\">#{e}</span>"
|
||||
end
|
||||
end
|
||||
errors_out
|
||||
end
|
||||
|
||||
# Useful abstraction for form input fields - combines an input field with error message (if any)
|
||||
# and writes an appropriate style (for errors)
|
||||
# Usage:
|
||||
# form_input :text_field, 'postform', 'subject'
|
||||
# form_input :text_area, 'postform', 'text', 'Please enter text:', 'cols' => 80
|
||||
# form_input :hidden_field, 'postform', 'topic_id'
|
||||
def form_input(helper_method, form_name, field_name, prompt = field_name.capitalize, options = {})
|
||||
case helper_method.to_s
|
||||
when 'hidden_field'
|
||||
self.hidden_field(form_name, field_name)
|
||||
when /^.*button$/
|
||||
<<-EOL
|
||||
<tr><td class="button" colspan="2">
|
||||
#{self.send(helper_method, form_name, prompt, options)}
|
||||
</td></tr>
|
||||
EOL
|
||||
else
|
||||
field = (
|
||||
if :select == helper_method
|
||||
self.send(helper_method, form_name, field_name, options.delete('values'), options)
|
||||
elsif :collection_select == helper_method
|
||||
self.send(helper_method, form_name, field_name, options.delete('collection'), options.delete('value_method'), options.delete('text_method'), options)
|
||||
else
|
||||
self.send(helper_method, form_name, field_name, options)
|
||||
end)
|
||||
errors = instance_variable_get("@#{form_name}").errors[field_name] unless instance_variable_get("@#{form_name}").nil?
|
||||
errors = Array.new if errors.nil?
|
||||
errors_out = ""
|
||||
if errors
|
||||
errors = [errors] unless errors.is_a? Array
|
||||
errors.each do |e|
|
||||
errors_out << "<span class=\"error\">#{e}</span>"
|
||||
end
|
||||
end
|
||||
if options['class'] == 'two_columns'
|
||||
<<-EOL
|
||||
<tr class="two_columns">
|
||||
<td class="prompt"><label>#{prompt}:</label></td>
|
||||
<td class="value">#{field}#{errors_out}</td>
|
||||
</tr>
|
||||
EOL
|
||||
else
|
||||
<<-EOL
|
||||
<tr><td class="prompt"><strong>#{prompt}:</strong></td></tr>
|
||||
<tr><td class="value">#{field}#{errors_out}</td></tr>
|
||||
EOL
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Helper method that has the same signature as real input field helpers, but simply displays
|
||||
# the value of a given field enclosed within <p> </p> tags.
|
||||
# Usage:
|
||||
# <%= form_input :read_only_field, 'new_user', 'name', _('user_name')) %>
|
||||
def read_only_field(form_name, field_name, html_options)
|
||||
"<span #{attributes(html_options)}>#{instance_variable_get('@' + form_name)[field_name]}</span>"
|
||||
end
|
||||
|
||||
def submit_button(form_name, prompt, html_options)
|
||||
%{<input name="submit" type="submit" value="#{prompt}" />}
|
||||
end
|
||||
|
||||
# Converts a hash to XML attributes string. E.g.:
|
||||
# to_attributes('a' => 'aaa', 'b' => 1)
|
||||
# => 'a="aaa" b="1" '
|
||||
def attributes(hash)
|
||||
hash.keys.inject("") { |attrs, key| attrs + %{#{key}="#{hash[key]}" } }
|
||||
end
|
||||
|
||||
def initListClass
|
||||
@itClass = 1
|
||||
end
|
||||
|
||||
def popListClass
|
||||
ret = getListClass
|
||||
@itClass = @itClass + 1
|
||||
return ret
|
||||
end
|
||||
|
||||
def getListClass
|
||||
return "even" if @itClass%2 == 0
|
||||
return "odd" if @itClass%2 == 1
|
||||
end
|
||||
|
||||
def get_meta_info
|
||||
'<meta name="rating" content="General">'
|
||||
'<meta name="robots" content="Index, ALL">'
|
||||
'<meta name="description" content="">'
|
||||
'<meta name="keywords" content="">'
|
||||
'<meta name content="">'
|
||||
end
|
||||
|
||||
def user
|
||||
@user = Customer.find(@session["user"]) if @user.nil?
|
||||
@user
|
||||
end
|
||||
|
||||
def link_main
|
||||
link_to(_('Contacts'), :controller => '/contacts/contact', :action => 'list')
|
||||
end
|
||||
|
||||
def alternator
|
||||
if @alternator.nil?
|
||||
@alternator = 1
|
||||
end
|
||||
|
||||
@alternator = -@alternator
|
||||
|
||||
if @alternator == -1
|
||||
return "even"
|
||||
else
|
||||
return "odd"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
487
app/helpers/pagination_helper.rb
Normal file
487
app/helpers/pagination_helper.rb
Normal file
|
@ -0,0 +1,487 @@
|
|||
# == Pagination Helper
|
||||
#
|
||||
# === Action Pack pagination for Active Record collections
|
||||
#
|
||||
# <em>Sam Stephenson <sstephenson at gmail dot com></em>
|
||||
#
|
||||
# Pagination Helper aids in the process of paging large collections of Active
|
||||
# Record objects. It offers macro-style automatic fetching of your model for
|
||||
# multiple views, or explicit fetching for single actions. And if the magic
|
||||
# isn't flexible enough for your needs, you can create your own paginators
|
||||
# with a minimal amount of code.
|
||||
#
|
||||
# Unlike most helpers, Pagination Helper is available to all of Action Pack:
|
||||
# it helps you query your models with Action Controller and render links in
|
||||
# Action View.
|
||||
#
|
||||
# ----
|
||||
#
|
||||
# === Controller examples
|
||||
#
|
||||
# Pagination Helper can handle as much or as little as you wish. In the
|
||||
# controller, have it automatically query your model for pagination; or,
|
||||
# if you prefer, create Paginator objects yourself.
|
||||
#
|
||||
# ==== Automatic pagination for every action in a controller
|
||||
#
|
||||
# class PersonController < ApplicationController
|
||||
# helper :pagination
|
||||
# model :person
|
||||
#
|
||||
# paginate :people, :order_by => 'last_name, first_name',
|
||||
# :per_page => 20
|
||||
#
|
||||
# # ...
|
||||
# end
|
||||
#
|
||||
# Each action in this controller now has access to a <tt>@people</tt> instance
|
||||
# variable, which is an ordered collection of model objects for the current
|
||||
# page (at most 20, sorted by last name and first name), and a
|
||||
# <tt>@person_pages</tt> Paginator instance. The current page is determined by
|
||||
# the <tt>@params['page']</tt> variable.
|
||||
#
|
||||
# ==== Pagination for a single action
|
||||
#
|
||||
# def list
|
||||
# @person_pages, @people =
|
||||
# paginate :people, :order_by => 'last_name, first_name'
|
||||
# end
|
||||
#
|
||||
# Like the previous example, but explicitly creates <tt>@person_pages</tt> and
|
||||
# <tt>@people</tt> for a single action, and uses the default of 10 items per
|
||||
# page.
|
||||
#
|
||||
# ==== Custom/"classic" pagination
|
||||
#
|
||||
# def list
|
||||
# @person_pages = Paginator.new self, Person.count, 10, @params['page']
|
||||
# @people = Person.find_all nil, 'last_name, first_name',
|
||||
# @person_pages.current.to_sql
|
||||
# end
|
||||
#
|
||||
# Explicitly creates the paginator from the previous example and uses
|
||||
# Paginator#to_sql to retrieve <tt>@people</tt> from the model.
|
||||
#
|
||||
# === View examples
|
||||
#
|
||||
# Paginator Helper includes various methods to help you display pagination
|
||||
# links in your views. (For information on displaying the paginated
|
||||
# collections you retrieve in the controller, see the documentation for
|
||||
# ActionView::Partials#render_collection_of_partials.)
|
||||
#
|
||||
# ==== Using Paginator#basic_html
|
||||
#
|
||||
# Use the +basic_html+ method to get a simple list of pages (always including
|
||||
# the first and last page) with a window around the current page. In your
|
||||
# view, using one of the controller examples above,
|
||||
#
|
||||
# <%= @person_pages.basic_html(self) %>
|
||||
#
|
||||
# will render a list of links. For a list of parameters, see the documentation
|
||||
# for Page#basic_html.
|
||||
#
|
||||
# ==== Using a paginator partial
|
||||
#
|
||||
# If you need more advanced control over pagination links and need to paginate
|
||||
# multiple actions and controllers, consider using a shared paginator partial.
|
||||
# For instance, _why suggests this partial, which you might place in
|
||||
# <tt>app/views/partial/_paginator.rhtml</tt>:
|
||||
#
|
||||
# <div class="counter">
|
||||
# Displaying <%= paginator.current.first_item %>
|
||||
# - <%= paginator.current.last_item %>
|
||||
# of <%= paginator.item_count %>
|
||||
#
|
||||
# <%= link_to(h('< Previous'), paginator.current.previous.to_link) +
|
||||
# " | " if paginator.current.previous %>
|
||||
# <%= paginator.basic_html(self, 4) %>
|
||||
# <%= " | " + link_to(h('Next >'), paginator.current.next.to_link) if
|
||||
# paginator.current.next %>
|
||||
# </div>
|
||||
#
|
||||
# Then in your views, simply call
|
||||
#
|
||||
# <%= render_partial "partial/paginator", @person_pages %>
|
||||
#
|
||||
# wherever you want your pagination links to appear.
|
||||
#
|
||||
# ----
|
||||
#
|
||||
# ==== Thanks
|
||||
#
|
||||
# Thanks to the following people for their contributions to Pagination Helper:
|
||||
# * Marcel Molina Jr (noradio), who provided the idea for and original
|
||||
# implementation of Paginator::Window, as well as endless mental support.
|
||||
# * evl, who pointed out that Page#link_to should take and merge in a hash of
|
||||
# additional parameters.
|
||||
# * why the lucky stiff, who wrote a lovely article on the original Pagination
|
||||
# Helper alongside the first implementation of Paginator#base_html, created
|
||||
# Page#first_item and Page#last_item, and who provided inspiration for
|
||||
# revising Pagination Helper to make it more "Rails-ish."
|
||||
# * xal, who saw the limitations of having only the macro-style paginate
|
||||
# method and suggested the single-action version, and who also suggested the
|
||||
# automatic inclusion into ActionController::Base.
|
||||
# * jbd for feedback and debugging help.
|
||||
# * ##rubyonrails on Freenode and the Rails mailing list.
|
||||
#
|
||||
module PaginationHelper
|
||||
# A hash holding options for controllers using macro-style pagination
|
||||
OPTIONS = Hash.new
|
||||
|
||||
# The default options for pagination
|
||||
DEFAULT_OPTIONS = {
|
||||
:class_name => nil,
|
||||
:per_page => 10,
|
||||
:parameter => 'page',
|
||||
:conditions => nil,
|
||||
:order_by => nil
|
||||
}
|
||||
|
||||
def self.included(base) #:nodoc:
|
||||
super
|
||||
base.extend(ClassMethods)
|
||||
end
|
||||
|
||||
def self.validate_options!(collection_id, options, in_action) #:nodoc:
|
||||
options.merge!(DEFAULT_OPTIONS) {|key, old, new| old}
|
||||
|
||||
valid_options = [:class_name, :per_page,
|
||||
:parameter, :conditions, :order_by]
|
||||
valid_options << :actions unless in_action
|
||||
|
||||
unknown_option_keys = options.keys - valid_options
|
||||
raise ActionController::ActionControllerError,
|
||||
"Unknown options: #{unknown_option_keys.join(', ')}" unless
|
||||
unknown_option_keys.empty?
|
||||
|
||||
options[:singular_name] = Inflector.singularize(collection_id.to_s)
|
||||
options[:class_name] ||= Inflector.camelize(options[:singular_name])
|
||||
end
|
||||
|
||||
# Returns a paginator and a collection of Active Record model instances for
|
||||
# the paginator's current page. This is designed to be used in a single
|
||||
# action; to automatically paginate multiple actions, consider
|
||||
# ClassMethods#paginate.
|
||||
#
|
||||
# +options+ are:
|
||||
# <tt>:class_name</tt>:: the class name to use, if it can't be inferred by
|
||||
# singularizing the collection name.
|
||||
# <tt>:per_page</tt>:: the maximum number of items to include in a
|
||||
# single page. Defaults to 10.
|
||||
# <tt>:parameter</tt>:: the CGI parameter from which the current page is
|
||||
# determined. Defaults to 'page'; i.e., the current
|
||||
# page is specified by <tt>@params['page']</tt>.
|
||||
# <tt>:conditions</tt>:: optional conditions passed to Model.find_all.
|
||||
# <tt>:order_by</tt>:: optional order parameter passed to Model.find_all
|
||||
# and Model.count.
|
||||
def paginate(collection_id, options={})
|
||||
PaginationHelper.validate_options!(collection_id, options, true)
|
||||
paginator_and_collection_for(collection_id, options)
|
||||
end
|
||||
|
||||
# These methods become class methods on any controller which includes
|
||||
# PaginationHelper.
|
||||
module ClassMethods
|
||||
# Creates a +before_filter+ which automatically paginates an Active Record
|
||||
# model for all actions in a controller (or certain actions if specified
|
||||
# with the <tt>:actions</tt> option).
|
||||
#
|
||||
# +options+ are the same as PaginationHelper#paginate, with the addition
|
||||
# of:
|
||||
# <tt>:actions</tt>:: an array of actions for which the pagination is
|
||||
# active. Defaults to +nil+ (i.e., every action).
|
||||
def paginate(collection_id, options={})
|
||||
PaginationHelper.validate_options!(collection_id, options, false)
|
||||
module_eval do
|
||||
before_filter :create_paginators_and_retrieve_collections
|
||||
OPTIONS[self] ||= Hash.new
|
||||
OPTIONS[self][collection_id] = options
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_paginators_and_retrieve_collections #:nodoc:
|
||||
PaginationHelper::OPTIONS[self.class].each do |collection_id, options|
|
||||
next unless options[:actions].include? action_name if options[:actions]
|
||||
|
||||
paginator, collection =
|
||||
paginator_and_collection_for(collection_id, options)
|
||||
|
||||
paginator_name = "@#{options[:singular_name]}_pages"
|
||||
self.instance_variable_set(paginator_name, paginator)
|
||||
|
||||
collection_name = "@#{collection_id.to_s}"
|
||||
self.instance_variable_set(collection_name, collection)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the total number of items in the collection to be paginated for
|
||||
# the +model+ and given +conditions+. Override this method to implement a
|
||||
# custom counter.
|
||||
def count_collection_for_pagination(model, conditions)
|
||||
model.count(conditions)
|
||||
end
|
||||
|
||||
# Returns a collection of items for the given +model+ and +conditions+,
|
||||
# ordered by +order_by+, for the current page in the given +paginator+.
|
||||
# Override this method to implement a custom finder.
|
||||
def find_collection_for_pagination(model, conditions, order_by, paginator)
|
||||
model.find_all(conditions, order_by, paginator.current.to_sql)
|
||||
end
|
||||
|
||||
protected :create_paginators_and_retrieve_collections,
|
||||
:count_collection_for_pagination, :find_collection_for_pagination
|
||||
|
||||
def paginator_and_collection_for(collection_id, options) #:nodoc:
|
||||
klass = eval options[:class_name]
|
||||
page = @params[options[:parameter]]
|
||||
count = count_collection_for_pagination(klass, options[:conditions])
|
||||
|
||||
paginator = Paginator.new(self, count,
|
||||
options[:per_page], page, options[:parameter])
|
||||
|
||||
collection = find_collection_for_pagination(klass,
|
||||
options[:conditions], options[:order_by], paginator)
|
||||
|
||||
return paginator, collection
|
||||
end
|
||||
|
||||
private :paginator_and_collection_for
|
||||
|
||||
# A class representing a paginator for an Active Record collection.
|
||||
class Paginator
|
||||
include Enumerable
|
||||
|
||||
# Creates a new Paginator on the given +controller+ for a set of items of
|
||||
# size +item_count+ and having +items_per_page+ items per page. Raises
|
||||
# ArgumentError if items_per_page is out of bounds (i.e., less than or
|
||||
# equal to zero). The page CGI parameter for links defaults to "page" and
|
||||
# can be overridden with +page_parameter+.
|
||||
def initialize(controller, item_count, items_per_page, current_page=1,
|
||||
page_parameter='page')
|
||||
raise ArgumentError, 'must have at least one item per page' if
|
||||
items_per_page <= 0
|
||||
|
||||
@controller = controller
|
||||
@item_count = item_count || 0
|
||||
@items_per_page = items_per_page
|
||||
@page_parameter = page_parameter
|
||||
|
||||
self.current_page = current_page
|
||||
end
|
||||
attr_reader :controller, :item_count, :items_per_page, :page_parameter
|
||||
|
||||
# Sets the current page number of this paginator. If +page+ is a Page
|
||||
# object, its +number+ attribute is used as the value; if the page does
|
||||
# not belong to this Paginator, an ArgumentError is raised.
|
||||
def current_page=(page)
|
||||
if page.is_a? Page
|
||||
raise ArgumentError, 'Page/Paginator mismatch' unless
|
||||
page.paginator == self
|
||||
end
|
||||
page = page.to_i
|
||||
@current_page = has_page_number?(page) ? page : 1
|
||||
end
|
||||
|
||||
# Returns a Page object representing this paginator's current page.
|
||||
def current_page
|
||||
self[@current_page]
|
||||
end
|
||||
alias current :current_page
|
||||
|
||||
# Returns a new Page representing the first page in this paginator.
|
||||
def first_page
|
||||
self[1]
|
||||
end
|
||||
alias first :first_page
|
||||
|
||||
# Returns a new Page representing the last page in this paginator.
|
||||
def last_page
|
||||
self[page_count]
|
||||
end
|
||||
alias last :last_page
|
||||
|
||||
# Returns the number of pages in this paginator.
|
||||
def page_count
|
||||
return 1 if @item_count.zero?
|
||||
(@item_count / @items_per_page.to_f).ceil
|
||||
end
|
||||
alias length :page_count
|
||||
|
||||
# Returns true if this paginator contains the page of index +number+.
|
||||
def has_page_number?(number)
|
||||
return false unless number.is_a? Fixnum
|
||||
number >= 1 and number <= page_count
|
||||
end
|
||||
|
||||
# Returns a new Page representing the page with the given index +number+.
|
||||
def [](number)
|
||||
Page.new(self, number)
|
||||
end
|
||||
|
||||
# Successively yields all the paginator's pages to the given block.
|
||||
def each(&block)
|
||||
page_count.times do |n|
|
||||
yield self[n+1]
|
||||
end
|
||||
end
|
||||
|
||||
# Creates a basic HTML link bar for the given +view+. The first and last
|
||||
# pages of the paginator are always shown, along with +window_size+ pages
|
||||
# around the current page. By default, the current page is displayed, but
|
||||
# not linked; to change this behavior, pass true to the
|
||||
# +link_to_current_page+ argument. Specify additional link_to parameters
|
||||
# with +params+.
|
||||
def basic_html(view, window_size=2, link_to_current_page=false, params={})
|
||||
window_pages = current.window(window_size).pages
|
||||
return if window_pages.length <= 1 unless link_to_current_page
|
||||
|
||||
html = ''
|
||||
unless window_pages[0].first?
|
||||
html << view.link_to(first.number, first.to_link(params))
|
||||
html << ' ... ' if window_pages[0].number - first.number > 1
|
||||
html << ' '
|
||||
end
|
||||
|
||||
window_pages.each do |page|
|
||||
if current == page and not link_to_current_page
|
||||
html << page.number.to_s
|
||||
else
|
||||
html << view.link_to(page.number, page.to_link(params))
|
||||
end
|
||||
html << ' '
|
||||
end
|
||||
|
||||
unless window_pages.last.last?
|
||||
html << ' ... ' if last.number - window_pages[-1].number > 1
|
||||
html << view.link_to(last.number, last.to_link(params))
|
||||
end
|
||||
|
||||
html
|
||||
end
|
||||
|
||||
# A class representing a single page in a paginator.
|
||||
class Page
|
||||
include Comparable
|
||||
|
||||
# Creates a new Page for the given +paginator+ with the index +number+.
|
||||
# If +number+ is not in the range of valid page numbers or is not a
|
||||
# number at all, it defaults to 1.
|
||||
def initialize(paginator, number)
|
||||
@paginator = paginator
|
||||
@number = number.to_i
|
||||
@number = 1 unless @paginator.has_page_number? @number
|
||||
end
|
||||
attr_reader :paginator, :number
|
||||
alias to_i :number
|
||||
|
||||
# Compares two Page objects and returns true when they represent the
|
||||
# same page (i.e., their paginators are the same and they have the same
|
||||
# page number).
|
||||
def ==(page)
|
||||
@paginator == page.paginator and
|
||||
@number == page.number
|
||||
end
|
||||
|
||||
# Compares two Page objects and returns -1 if the left-hand page comes
|
||||
# before the right-hand page, 0 if the pages are equal, and 1 if the
|
||||
# left-hand page comes after the right-hand page. Raises ArgumentError
|
||||
# if the pages do not belong to the same Paginator object.
|
||||
def <=>(page)
|
||||
raise ArgumentError unless @paginator == page.paginator
|
||||
@number <=> page.number
|
||||
end
|
||||
|
||||
# Returns the item offset for the first item in this page.
|
||||
def offset
|
||||
@paginator.items_per_page * (@number - 1)
|
||||
end
|
||||
|
||||
# Returns the number of the first item displayed.
|
||||
def first_item
|
||||
offset + 1
|
||||
end
|
||||
|
||||
# Returns the number of the last item displayed.
|
||||
def last_item
|
||||
[@paginator.items_per_page * @number, @paginator.item_count].min
|
||||
end
|
||||
|
||||
# Returns true if this page is the first page in the paginator.
|
||||
def first?
|
||||
self == @paginator.first
|
||||
end
|
||||
|
||||
# Returns true if this page is the last page in the paginator.
|
||||
def last?
|
||||
self == @paginator.last
|
||||
end
|
||||
|
||||
# Returns a new Page object representing the page just before this page,
|
||||
# or nil if this is the first page.
|
||||
def previous
|
||||
if first? then nil else Page.new(@paginator, @number - 1) end
|
||||
end
|
||||
|
||||
# Returns a new Page object representing the page just after this page,
|
||||
# or nil if this is the last page.
|
||||
def next
|
||||
if last? then nil else Page.new(@paginator, @number + 1) end
|
||||
end
|
||||
|
||||
# Returns a new Window object for this page with the specified
|
||||
# +padding+.
|
||||
def window(padding=2)
|
||||
Window.new(self, padding)
|
||||
end
|
||||
|
||||
# Returns a hash appropriate for using with link_to or url_for. Takes an
|
||||
# optional +params+ hash for specifying additional link parameters.
|
||||
def to_link(params={})
|
||||
{:params => {@paginator.page_parameter => @number.to_s}.merge(params)}
|
||||
end
|
||||
|
||||
# Returns the SQL "LIMIT ... OFFSET" clause for this page.
|
||||
def to_sql
|
||||
['? OFFSET ?', @paginator.items_per_page, offset]
|
||||
end
|
||||
end
|
||||
|
||||
# A class for representing ranges around a given page.
|
||||
class Window
|
||||
# Creates a new Window object for the given +page+ with the specified
|
||||
# +padding+.
|
||||
def initialize(page, padding=2)
|
||||
@paginator = page.paginator
|
||||
@page = page
|
||||
self.padding = padding
|
||||
end
|
||||
attr_reader :paginator, :page
|
||||
|
||||
# Sets the window's padding (the number of pages on either side of the
|
||||
# window page).
|
||||
def padding=(padding)
|
||||
@padding = padding < 0 ? 0 : padding
|
||||
# Find the beginning and end pages of the window
|
||||
@first = @paginator.has_page_number?(@page.number - @padding) ?
|
||||
@paginator[@page.number - @padding] : @paginator.first
|
||||
@last = @paginator.has_page_number?(@page.number + @padding) ?
|
||||
@paginator[@page.number + @padding] : @paginator.last
|
||||
end
|
||||
attr_reader :padding, :first, :last
|
||||
|
||||
# Returns an array of Page objects in the current window.
|
||||
def pages
|
||||
(@first.number..@last.number).to_a.map {|n| @paginator[n]}
|
||||
end
|
||||
alias to_a :pages
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module ActionController #:nodoc:
|
||||
class Base #:nodoc:
|
||||
# Automatically include PaginationHelper.
|
||||
include PaginationHelper
|
||||
end
|
||||
end
|
18
app/views/layouts/chooser.rhtml
Normal file
18
app/views/layouts/chooser.rhtml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= @htmllang %>" lang="<%= @htmllang %>">
|
||||
<head>
|
||||
<title><%=@title%></title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=<%= @charset %>" />
|
||||
<script type="text/javascript" src="/javascripts/global.js"></script>
|
||||
<link rel="stylesheet" href="/stylesheets/admin.css" type="text/css" media="screen" />
|
||||
<link rel="stylesheet" href="/stylesheets/tabs.css" type="text/css" media="screen" />
|
||||
<link rel="stylesheet" href="/stylesheets/mailr.css" type="text/css" media="screen" />
|
||||
<%=@additional_scripts%>
|
||||
</head>
|
||||
<body id="bodyID" onload="<%=@onload_function%>">
|
||||
<%= @content_for_layout %>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
25
app/views/layouts/public.rhtml
Normal file
25
app/views/layouts/public.rhtml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= @htmllang %>" lang="<%= @htmllang %>">
|
||||
<head>
|
||||
<title><%=_('Mailr')%></title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=<%= @charset %>" />
|
||||
<link rel="stylesheet" href="/stylesheets/admin.css" type="text/css" media="screen" />
|
||||
<link rel="stylesheet" href="/stylesheets/tabs.css" type="text/css" media="screen" />
|
||||
<link rel="stylesheet" href="/stylesheets/mailr.css" type="text/css" media="screen" />
|
||||
<script type="text/javascript" src="/javascripts/global.js"></script>
|
||||
<script type="text/javascript" src="/javascripts/prototype.js"></script>
|
||||
<%=(@content_for_scripts ? @content_for_scripts : @additional_scripts )%>
|
||||
</head>
|
||||
<body id="bodyID" onload="<%=@onload_function%>">
|
||||
<div id="wholepage">
|
||||
<div id="container">
|
||||
<div id="sidebar_outer">
|
||||
<div id="sidebar"><%= @content_for_sidebar %></div>
|
||||
</div>
|
||||
<div id="content"><%= @content_for_layout %></div>
|
||||
<br class="clear"/>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
41
app/views/login/index.rhtml
Normal file
41
app/views/login/index.rhtml
Normal file
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Mailr » Please Log In</title>
|
||||
<link rel="stylesheet" type="text/css" href="/stylesheets/admin.css" />
|
||||
<link rel="stylesheet" href="/stylesheets/mailr.css" type="text/css" media="screen" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="login" <%= 'class="login_error"' if @flash['error'] %>>
|
||||
<h1>Mailr</h1>
|
||||
<% if @flash['error'] %>
|
||||
<div id="SystemError"><%= @flash['error'] %></div>
|
||||
<% elsif @flash['status'] %>
|
||||
<div id="SystemStatus"><%= @flash['status'] %></div>
|
||||
<% end %>
|
||||
<form action="<%=url_for(:controller => 'login', :action => 'authenticate')%>" method="post">
|
||||
<table class="form_layout">
|
||||
<tr>
|
||||
<th><label for="<%=_('Email')%>"><%=_('Email')%>:</label></th>
|
||||
<td><%= text_field "login_user", "email" %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="<%=_('Password')%>"><%=_('Password')%>:</label></th>
|
||||
<td><%= password_field "login_user", "password" %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="form_actions">
|
||||
<input type="submit" name="submit" value="<%= _('Log In') %>"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<b class='cn tl'></b>
|
||||
<b class='cn tr'></b>
|
||||
<b class='cn bl'></b>
|
||||
<b class='cn br'></b>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue