a lot of stuff added

from_scratch
Wojciech Todryk 2011-07-29 20:05:47 +02:00
parent 37f548ce46
commit 7967e6d5c8
35 changed files with 559 additions and 64 deletions

View File

@ -11,17 +11,28 @@ In _Rails 3_ all dependencies should be defined in file _Gemfile_. All needed ge
* Checkout the source code.
* Install all dependiences. Use _bundler_ for that.
* Install all dependiences. Check if proper gems (sqlite3/mysql/postgresql) are defined in _Gemfile_ and installed. Use _bundler_ for that:
```shell
bundle install
```
* Check _config/defaults.yml_ for proper values.
* Prepare config/database.yml file (see _config/database.yml.example_).
Check if proper gems (sqlite3/mysql/postgresql) are defined in _Gemfile_ and installed.
* Migrate database (rake db:migrate)
* Start rails server if applicable
* Point Your browser to application URL:
* Point your browser to application URL:
For local access: http://localhost:3000
For remote access: http://some_url/mailr
* Using browser do basic setup. If You make a mistake delete all data from DB using rake task:
```shell
rake db:clear_data
```
* Use it.

View File

@ -0,0 +1,22 @@
require 'imap_session'
require 'imap_mailbox'
class ContactsController < ApplicationController
include ImapMailboxModule
include ImapSessionModule
before_filter :check_current_user,:selected_folder
before_filter :open_imap_session
after_filter :close_imap_session
theme :theme_resolver
def index
@folders = @current_user.folders.order("name asc")
@current_folder = @current_user.folders.current(@selected_folder)
flash[:notice] = 'Not implemented yet'
end
end

View File

@ -0,0 +1,89 @@
class FoldersController < ApplicationController
include ImapMailboxModule
include ImapSessionModule
before_filter :check_current_user ,:selected_folder
before_filter :open_imap_session
after_filter :close_imap_session
before_filter :get_folders, :except => :manage
theme :theme_resolver
def index
end
def create
if params["folder"].empty?
flash[:warning] = t(:folder_to_create_empty)
render "index"
else
begin
if params["parent_folder"].empty?
@mailbox.create_folder(params[:folder])
else
parent_folder = Folder.find(params["parent_folder"])
if parent_folder.depth >= $defaults["mailbox_max_parent_folder_depth"].to_i
raise Exception, t(:folder_max_depth)
end
@mailbox.create_folder(parent_folder.full_name + parent_folder.delim + params[:folder])
end
rescue Exception => e
flash[:error] = t(:can_not_create_folder) + ' (' + e.to_s + ')'
render 'index'
return
end
redirect_to :action => 'manage', :flash => t(:folder_was_created), :type => :notice
end
end
# FIXME if you delete folder you should change current folder because if you go to messages/index you got nil
def delete
if params["folder"].empty?
flash[:warning] = t(:folder_to_delete_empty)
render "index"
else
begin
folder = Folder.find(params["folder"])
system_folders = Array.new
system_folders << $defaults["mailbox_inbox"]
system_folders << $defaults["mailbox_trash"]
system_folders << $defaults["mailbox_sent"]
system_folders << $defaults["mailbox_drafts"]
if system_folders.include?(folder.full_name.downcase)
raise Exception, t(:system_folder)
end
@mailbox.delete_folder(Folder.find(params["folder"]).full_name)
rescue Exception => e
flash[:error] = t(:can_not_delete_folder) + ' (' + e.to_s + ')'
render 'index'
return
end
redirect_to :action => 'manage', :flash => t(:folder_was_deleted), :type => :notice
end
end
def sub_un_scribe
redirect_to :action => 'manage'
end
def manage
@current_user.folders.destroy_all
folders=@mailbox.folders
Folder.createBulk(@current_user,folders)
if params[:flash]
flash[params[:type]] = params[:flash]
end
redirect_to :action => 'index'
end
protected
def get_folders
@folders = @current_user.folders.order("name asc")
@current_folder = @current_user.folders.current(@selected_folder)
end
end

View File

@ -13,7 +13,14 @@ class InternalController < ApplicationController
@title = t(:imap_error)
@error = params[:error] || t(:unspecified_error)
logger.error "!!! InternalControllerImapError: " + @error
render 'error'
render 'error'
end
def loginfailure
reset_session
flash[:error] = t(:login_failure)
@current_user = nil
redirect_to :controller=>'user', :action => 'login'
end
end

View File

@ -16,6 +16,7 @@ class MessagesController < ApplicationController
def index
@folders = @current_user.folders.order("name asc")
@current_folder = @current_user.folders.current(@selected_folder)
flash[:notice] = 'Not implemented yet'
end
def refresh
@ -30,4 +31,10 @@ class MessagesController < ApplicationController
redirect_to :action => 'index'
end
def compose
@folders = @current_user.folders.order("name asc")
@current_folder = @current_user.folders.current(@selected_folder)
flash[:notice] = 'Not impelented yet'
end
end

View File

@ -0,0 +1,13 @@
class PrefsController < ApplicationController
before_filter :check_current_user,:selected_folder
theme :theme_resolver
def index
@folders = @current_user.folders.order("name asc")
@current_folder = @current_user.folders.current(@selected_folder)
flash[:notice] = 'Not implemented yet'
end
end

View File

@ -17,23 +17,16 @@ class UserController < ApplicationController
if user.nil?
redirect_to :action => 'unknown' ,:email=> params[:user][:email]
else
auten = true
if auten == true
session[:user_id] = user.id
user.set_cached_password(session,params[:user][:password])
if session["return_to"]
redirect_to(session["return_to"])
session["return_to"] = nil
else
redirect_to :controller=> 'messages', :action=> 'refresh'
end
session[:user_id] = user.id
user.set_cached_password(session,params[:user][:password])
if session["return_to"]
redirect_to(session["return_to"])
session["return_to"] = nil
else
flash[:error] = t(:login_failure)
redirect_to :action => 'login'
redirect_to :controller=> 'messages', :action=> 'refresh'
end
end
end

View File

@ -36,12 +36,12 @@ def form_field(object,field,flabel,example,val)
end
def form_button(text)
def form_button(text,image)
html = ""
html << "<div class=\"group navform wat-cf\">"
html << "<button class=\"button\" type=\"submit\">"
html << "<img src=\""
html << current_theme_image_path('tick.png')
html << current_theme_image_path(image)
html << "\" alt=\""
html << text
html << "\" />"
@ -49,4 +49,104 @@ def form_button(text)
html << "</button></div>"
end
def form_button_value(text,image,onclick)
html = ""
html << "<div class=\"group navform wat-cf\">"
html << "<button class=\"button\" type=\"submit\" onclick=\"window.location='"
html << onclick
html << "'\">"
html << "<img src=\""
html << current_theme_image_path(image)
html << "\" alt=\""
html << text
html << "\" />"
html << t(text.to_sym)
html << "</button></div>"
end
def simple_input_field(name,label,value)
html = ""
html << "<div class=\"group\">"
html << "<label class=\"label\">#{label}</label>"
html << "<input name=\"#{name}\" class=\"text_field\" type=\"text\" value=\"#{value}\">"
html << "</div>"
end
def select_field(name,object,label,blank)
html = ""
html << "<div class=\"group\">"
html << "<label class=\"label\">#{label}</label>"
html << select(name, name, object.all.collect {|p| [ p.name, p.id ] }, { :include_blank => (blank == true ? true : false)})
html << "</div>"
end
#def form_simle_field(name,label,value)
# html = ""
# html << "<div class=\"group\">"
# html << "<label class=\"label\">#{label}</label>"
# html << "<input class=\"text_field\" type=\"text\" value=\"#{value}\">"
# html << "</div>"
#end
def nav_to_folders
link_to( t(:folders), :controller=>:folders, :action=>:manage )
end
def nav_to_messages
link_to( t(:messages), :controller=>:messages, :action=>:index )
end
def nav_to_compose
link_to( t(:compose), :controller=>:messages, :action=>:compose )
end
def nav_to_contacts
link_to( t(:contacts), :controller=>:contacts, :action=>:index )
end
def nav_to_prefs
link_to( t(:preferences), :controller=>:prefs, :action=>:index )
end
def main_navigation(active)
s = ""
s += "<ul class=\"wat-cf\">"
active == :messages ? s += "<li class=\"first active\">#{nav_to_messages}</li>" : s += "<li class=\"first\">#{nav_to_messages}</li>"
active == :compose ? s += "<li class=\"active\">#{nav_to_compose}</li>" : s += "<li>#{nav_to_compose}</li>"
active == :folders ? s += "<li class=\" active\">#{nav_to_folders}</li>" : s += "<li class=\"first\">#{nav_to_folders}</li>"
active == :contacts ? s += "<li class=\"active\">#{nav_to_contacts}</li>" : s += "<li>#{nav_to_contacts}</li>"
active == :prefs ? s += "<li class=\"active\">#{nav_to_prefs}</li>" : s += "<li>#{nav_to_prefs}</li>"
# active == :filters ? s += "<li class=\"active\">#{link_mail_filters}</li>" : s += "<li>#{link_mail_filters}</li>"
s += "</ul>"
end
def multi_select(id, name, objects, selected_objects, label, value,joiner,content = {})
options = ""
objects.each do |o|
selected = selected_objects.include?(o) ? " selected=\"selected\"" : ""
option_value = escape_once(o.send(value))
text = [option_value]
unless content[:text].nil?
text = []
content[:text].each do |t|
text << o.send(t)
end
text = text.join(joiner)
end
text.gsub!(/^\./,'')
bracket = []
unless content[:bracket].nil?
content[:bracket].each do |b|
bracket << o.send(b)
end
bracket = bracket.join(joiner)
end
option_content = bracket.empty? ? "#{text}" : "#{text} (#{bracket})"
options << "<option value=\"#{option_value}\"#{selected}>&nbsp;&nbsp;#{option_content}&nbsp;&nbsp;</option>\n"
end
"<div class=\"group\"><label class=\"label\">#{label}</label><select multiple=\"multiple\" size=10 id=\"#{id}\" name=\"#{name}\">\n#{options}</select></div>"
end
end

2
app/helpers/contacts_helper.rb Executable file
View File

@ -0,0 +1,2 @@
module ContactsHelper
end

25
app/helpers/folder_helper.rb Executable file
View File

@ -0,0 +1,25 @@
module FolderHelper
def folder_link(folder)
folder.parent.empty? ? name = folder.name : name = folder.parent.gsub(/\./,'#') + "#" + folder.name
s = link_to folder.name.capitalize, :controller => 'messages', :action => 'folder', :id => name
if !folder.unseen.zero?
s += ' (' + folder.unseen.to_s + ')'
end
s
end
def pretty_folder_name(folder)
#folder = folder.gsub(/#/,".")
folder.name.capitalize
end
def select_for_folders(name,id,object,label,blank)
html = ""
html << "<div class=\"group\">"
html << "<label class=\"label\">#{label}</label>"
html << select(name, id, object.all.collect {|p| [ p.parent.empty? ? p.name : p.parent+p.delim+p.name, p.id ] }, { :include_blank => (blank == true ? true : false)})
html << "</div>"
end
end

View File

@ -1,18 +1,4 @@
module MessagesHelper
def folder_link(folder)
folder.parent.empty? ? name = folder.name : name = folder.parent.gsub(/\./,'#') + "#" + folder.name
s = link_to folder.name.capitalize, :controller => 'messages', :action => 'folder', :id => name
if !folder.unseen.zero?
s += ' (' + folder.unseen.to_s + ')'
end
s
end
def pretty_folder_name(folder)
#folder = folder.gsub(/#/,".")
folder.name.capitalize
end
end

2
app/helpers/prefs_helper.rb Executable file
View File

@ -0,0 +1,2 @@
module PrefsHelper
end

View File

@ -4,6 +4,18 @@ class Folder < ActiveRecord::Base
validates_presence_of :name, :on => :create
before_save :check_fill_params, :on => :create
def full_name
if parent.empty?
name
else
parent + delim + name
end
end
def depth
parent.split('.').size
end
private
def check_fill_params
@ -25,6 +37,8 @@ class Folder < ActiveRecord::Base
parent = ""
end
logger.info "******************* #{name}, #{parent} "
user.folders.create(:name=>name,:parent=>parent,:haschildren=>has_children,:delim=>data.delim,:messages => data.messages,:unseen => data.unseen)
end
end
@ -38,4 +52,6 @@ class Folder < ActiveRecord::Base
end
end
end

View File

@ -1,15 +1,22 @@
theme: olive
locale: en
msgs_per_page: 20
msgs_refresh_time: 300
msg_send_type: html
imap_debug: true
imap_use_ssl: 'false'
imap_port: 143
imap_ssl_port: 993
imap_bye_timeout_retry_seconds: 2
imap_inbox_folder: inbox
session_encryption: true
session_password: asDD3s2@sAdc983#
mailbox_max_parent_folder_depth: 3
mailbox_inbox: inbox
mailbox_trash: inbox.trash
mailbox_sent: inbox.sent
mailbox_drafts: inbox.drafts

View File

@ -79,3 +79,16 @@ en:
general_error: General error
unspecified_error: Unspecified error occured
imap_error: Imap Error
folder_to_create: Folder to create
create: Create
subscribe_unsubscribe: (Un)Subscribe
folders_subscribed_selected: Folders subscribed
messages: Messages
folder_to_create_empty: Folder to create is empty
folder_was_created: Folder was created
can_not_create_folder: Can not create folder
folder_max_depth: Maximum folder depth reached
folder_to_delete_empty: Folder to delete empty
folder_was_deleted: Folder was deleted
can_not_delete_folder: Can not delete folder
system_folder: System folder

View File

@ -1,12 +1,27 @@
Mailr::Application.routes.draw do
get "prefs/index"
get "contacts/index"
get "folders/index"
post "folders/create"
post "folders/delete"
post "folders/sub_un_scribe"
get "folders/manage"
get "internal/error"
get "internal/imaperror"
get "internal/loginfailure"
root :to => "messages#index"
get "messages/index"
get "messages/refresh"
match 'messages/folder/:id' => 'messages#folder'
post "messages/ops"
get "messages/compose"
get "user/logout"
post "user/authenticate"

View File

@ -72,6 +72,21 @@ class IMAPMailbox
@folders
end
def create_folder(name)
begin
@imap.create(Net::IMAP.encode_utf7(name))
rescue Exception => e
raise e
end
end
def delete_folder(name)
begin
@imap.delete(Net::IMAP.decode_utf7(name))
rescue Exception => e
raise e
end
end
end
end

View File

@ -8,7 +8,7 @@ def open_imap_session
@mailbox = ImapMailboxModule::IMAPMailbox.new(logger)
@mailbox.connect(@current_user.servers.primary,@current_user.email, @current_user.get_cached_password(session))
rescue Exception => ex
redirect_to :controller => 'internal', :action => 'imaperror' , :error => ex.inspect
redirect_to :controller => 'internal', :action => 'loginfailure'
end
end

10
lib/tasks/clear_db.rake Normal file
View File

@ -0,0 +1,10 @@
namespace :db do
desc "Clears all date in db"
task :clear_data => :environment do
users = User.all
puts "Number of users in db: #{users.size}"
puts "Deleting data....."
User.destroy_all
puts "Done"
end
end

View File

@ -0,0 +1,9 @@
require 'test_helper'
class ContactsControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
end
end

View File

@ -0,0 +1,19 @@
require 'test_helper'
class FolderControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
end
test "should get create" do
get :create
assert_response :success
end
test "should get delete" do
get :delete
assert_response :success
end
end

View File

@ -0,0 +1,9 @@
require 'test_helper'
class PrefsControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
end
end

View File

@ -0,0 +1,4 @@
require 'test_helper'
class ContactsHelperTest < ActionView::TestCase
end

View File

@ -0,0 +1,4 @@
require 'test_helper'
class FolderHelperTest < ActionView::TestCase
end

View File

@ -0,0 +1,4 @@
require 'test_helper'
class PrefsHelperTest < ActionView::TestCase
end

BIN
themes/olive/images/cross.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

View File

@ -246,15 +246,15 @@ input.checkbox {
float: right;
}
.form .columns .column {
.columns .column {
width: 48%;
}
.form .columns .left {
.columns .left {
float: left;
}
.form .columns .right {
.columns .right {
float: right;
}

View File

@ -0,0 +1,18 @@
<% content_for :sidebar do %>
<%= render :partial => 'folders/list' %>
<% end %>
<% content_for :title do %>
- <%= t(:contacts) %>
<% end %>
<div class="block" id="block-tables">
<div class="secondary-navigation">
<%= raw main_navigation(:contacts) %>
</div>
<div class="content">
<%= form_tag({:controller=>'messages', :action=>'ops'})%>
</form>
</div>
</div>

View File

@ -0,0 +1,12 @@
<div class="block">
<h3><%=t (:folders) %> <%= link_to t(:refresh), {:controller => 'messages', :action => 'refresh'}, :class=>'minor' %></h3>
<div class="content">
<ul class="navigation">
<% @folders.each do |folder| -%>
<li><%= raw folder_link(folder) %></li>
<% end -%>
</ul>
<br/>
<%= raw form_button_value(t(:logout),'tick.png',url_for(:controller => :user, :action => :logout)) %>
</div>
</div>

View File

@ -0,0 +1,36 @@
<% content_for :sidebar do %>
<%= render :partial => 'folders/list' %>
<% end %>
<% content_for :title do %>
- <%= t(:folders) %>
<% end %>
<div class="block" id="block-tables">
<div class="secondary-navigation">
<%= raw main_navigation(:folders) %>
</div>
<div class="content">
<div class="inner">
<div class="columns wat-cf">
<div class="column left">
<%= form_tag({:controller=>'folders',:action=>'create'},:class=>'form') %>
<%= raw select_for_folders("","parent_folder",@folders,t(:parent_folder),true) %>
<%= raw simple_input_field("folder",t(:folder_to_create),"") %>
<%= raw form_button(t(:create),'tick.png') %>
</form>
<%= form_tag({:controller=>'folders',:action=>'delete'},:class=>'form') %>
<%= raw select_for_folders("","folder",@folders,t(:folder_to_delete),true) %>
<%= raw form_button(t(:delete),'cross.png') %>
</form>
</div>
<div class="column right">
<%= form_tag({:controller=>'folders',:action=>'sub_un_scribe'},:class=>'form') %>
<%= raw multi_select("", 'folders_to_subscribe[]', @folders, @folders,t(:folders_subscribed),:id,"",{:text => [:parent,:delim,:name]}) %>
<%= raw form_button(t(:subscribe_unsubscribe),'tick.png') %>
</form>
</div>
</div>
</div>
</div>

View File

@ -3,7 +3,10 @@ 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><%= t(:mailr) %></title>
<title>
<%= t(:mailr) %>
<%= yield :title %>
</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<%=stylesheet_link_tag current_theme_stylesheet_path('base') %>
@ -12,14 +15,24 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
<%=javascript_include_tag :defaults %>
</head>
<body id="bodyID" onload="<%=@onload_function%>">
<body>
<div id="container">
<div id="wrapper" class="wat-cf">
<div id="sidebar">
<div id="logo"><%= yield :logo %></div>
<div id="logo"><img src="<%= current_theme_image_path('logo_small.png')%>" alt="Mailr"/></div>
<div id="sidebar"><%= yield :sidebar %></div>
</div>
<div id="main"><%= yield %></div>
<div id="main">
<div class="flash">
<% flash.each do |key, msg| %>
<% unless msg.blank? %>
<%= content_tag(:div,(content_tag :p, msg), :class => "message #{key.to_s}" )%>
<%= flash[key.to_sym]='' %>
<% end %>
<% end %>
</div>
<%= yield %>
</div>
<br class="clear"/>
</div>
</div>

View File

@ -0,0 +1,19 @@
<% content_for :sidebar do %>
<%= render :partial => 'folders/list' %>
<% end %>
<% content_for :title do %>
- <%= t(:compose) %>
<% end %>
<div class="block" id="block-tables">
<div class="secondary-navigation">
<%= raw main_navigation(:compose) %>
</div>
<div class="content">
<%= form_tag({:controller=>'messages', :action=>'ops'})%>
</form>
</div>
</div>

View File

@ -1,26 +1,23 @@
<% content_for :sidebar do %>
<%= render :partial => 'folders/list' %>
<% end %>
<%= link_to t(:refresh), :controller => 'messages', :action => 'refresh' %>
<% content_for :title do %>
- <%= t(:messages) %>
<% end %>
<div class="block" id="block-tables">
<div class="secondary-navigation">
<%= raw main_navigation(:messages) %>
</div>
<div class="content">
<%= form_tag({:controller=>'messages', :action=>'ops'})%>
</form>
</div>
</div>
<h1>Current: <%= pretty_folder_name(@current_folder) %></h1>
<%= @current_folder.inspect %>
<%= Time.now - @current_folder.msgs_updated_at %>
<h1>Folders</h1>
<% if @folders.size.zero? %>
No folders.
<% else %>
<ul class="folders">
<% @folders.each do |f|%>
<% if @selected_folder.upcase == f.name.upcase %>
<li class="selected"><%= folder_link(f) %></li>
<% else %>
<li><%= folder_link(f) %></li>
<% end %>
<% end %>
</ul>
<% end %>
<%= link_to t(:logout), :controller => 'user', :action => 'logout' %>

View File

@ -0,0 +1,18 @@
<% content_for :sidebar do %>
<%= render :partial => 'folders/list' %>
<% end %>
<% content_for :title do %>
- <%= t(:preferences) %>
<% end %>
<div class="block" id="block-tables">
<div class="secondary-navigation">
<%= raw main_navigation(:prefs) %>
</div>
<div class="content">
<%= form_tag({:controller=>'messages', :action=>'ops'})%>
</form>
</div>
</div>

View File

@ -13,7 +13,7 @@
<%= raw form_field(@user,"first_name",nil,"Joe","") %>
<%= raw form_field(@user,"last_name",nil,"Doe","") %>
<%= raw form_field(@server,"name","server_name","domain.domain","") %>
<%= raw form_button("send") %>
<%= raw form_button(t(:send),"tick.png") %>
</form>
</div>
</div>