Compare commits
1 commit
master
...
master-old
Author | SHA1 | Date | |
---|---|---|---|
8cc24cb8cf |
22
.gitignore
vendored
Executable file → Normal file
22
.gitignore
vendored
Executable file → Normal file
|
@ -1,15 +1,7 @@
|
||||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
log
|
||||||
#
|
config/database.yml
|
||||||
# If you find yourself ignoring temporary files generated by your text editor
|
.*.sw?
|
||||||
# or operating system, you probably want to add a global ignore instead:
|
config/site.rb
|
||||||
# git config --global core.excludesfile ~/.gitignore_global
|
tmp
|
||||||
|
mail_temp
|
||||||
# Ignore bundler config
|
config/site.rb
|
||||||
/.bundle
|
|
||||||
|
|
||||||
# Ignore the default SQLite database.
|
|
||||||
/db/*.sqlite3
|
|
||||||
|
|
||||||
# Ignore all logfiles and tempfiles.
|
|
||||||
/log/*.log
|
|
||||||
/tmp
|
|
||||||
|
|
4
AUTHORS.markdown → AUTHORS
Executable file → Normal file
4
AUTHORS.markdown → AUTHORS
Executable file → Normal file
|
@ -1,7 +1,5 @@
|
||||||
## Authors
|
|
||||||
|
|
||||||
* Luben Manolov <luben.manolov@gmail.com>
|
* Luben Manolov <luben.manolov@gmail.com>
|
||||||
* Nick Penkov <nick.penkov@gmail.com>
|
* Nick Penkov <nick.penkov@gmail.com>
|
||||||
* Eugene Korbut
|
* Eugene Korbut
|
||||||
* Emilio Blanco
|
* Emilio Blanco
|
||||||
* Wojciech Todryk <wojciech(at)todryk(dot).pl>
|
* Wojciech Todryk
|
|
@ -1,47 +0,0 @@
|
||||||
## Changes
|
|
||||||
|
|
||||||
#### 0.9.5
|
|
||||||
|
|
||||||
* favicon added
|
|
||||||
|
|
||||||
#### 0.9.4
|
|
||||||
|
|
||||||
* bump gems
|
|
||||||
|
|
||||||
#### 0.9.3
|
|
||||||
|
|
||||||
* handle Cc & Bcc adresses fix
|
|
||||||
|
|
||||||
#### 0.9.2
|
|
||||||
|
|
||||||
* fixes in handling draft folder
|
|
||||||
|
|
||||||
#### 0.9.1
|
|
||||||
|
|
||||||
* nowrap to edit column in contacts & links
|
|
||||||
* decoded changed in mail gem
|
|
||||||
* fixes in pl locale
|
|
||||||
|
|
||||||
#### 0.9.0
|
|
||||||
|
|
||||||
* switch to Rails 3.2.x
|
|
||||||
* Tweeter Bootstrap as default theme
|
|
||||||
* many fixes
|
|
||||||
|
|
||||||
#### 0.8.6
|
|
||||||
|
|
||||||
* new calendar view
|
|
||||||
|
|
||||||
#### 0.8.5
|
|
||||||
|
|
||||||
* servers view
|
|
||||||
* identity modification
|
|
||||||
|
|
||||||
#### 0.8.4
|
|
||||||
|
|
||||||
* calendar view as separate gem
|
|
||||||
* adding bluecloth for rendering markdown text
|
|
||||||
|
|
||||||
#### 0.8.3
|
|
||||||
|
|
||||||
* export, imports of contact
|
|
47
Gemfile
47
Gemfile
|
@ -1,47 +0,0 @@
|
||||||
source 'https://rubygems.org'
|
|
||||||
|
|
||||||
gem 'rails', '>= 3.2.11'
|
|
||||||
|
|
||||||
# Bundle edge Rails instead:
|
|
||||||
# gem 'rails', :git => 'git://github.com/rails/rails.git'
|
|
||||||
|
|
||||||
gem 'mysql2'
|
|
||||||
|
|
||||||
gem 'json', '>= 1.7.6'
|
|
||||||
|
|
||||||
# Gems used only for assets and not required
|
|
||||||
# in production environments by default.
|
|
||||||
group :assets do
|
|
||||||
gem 'sass-rails'
|
|
||||||
gem 'coffee-rails'
|
|
||||||
|
|
||||||
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
|
|
||||||
# gem 'therubyracer'
|
|
||||||
|
|
||||||
gem 'uglifier'
|
|
||||||
end
|
|
||||||
|
|
||||||
gem 'jquery-rails'
|
|
||||||
|
|
||||||
# To use ActiveModel has_secure_password
|
|
||||||
# gem 'bcrypt-ruby', '~> 3.0.0'
|
|
||||||
|
|
||||||
# To use Jbuilder templates for JSON
|
|
||||||
# gem 'jbuilder'
|
|
||||||
|
|
||||||
# Use unicorn as the app server
|
|
||||||
# gem 'unicorn'
|
|
||||||
|
|
||||||
# Deploy with Capistrano
|
|
||||||
# gem 'capistrano'
|
|
||||||
|
|
||||||
# To use debugger
|
|
||||||
# gem 'ruby-debug'
|
|
||||||
|
|
||||||
gem 'will_paginate'
|
|
||||||
gem "ezcrypto"
|
|
||||||
gem 'calendar_view'
|
|
||||||
gem 'bluecloth'
|
|
||||||
gem 'sass'
|
|
||||||
gem 'haml'
|
|
||||||
#gem 'twitter_bootstrap_form_for'
|
|
125
Gemfile.lock
125
Gemfile.lock
|
@ -1,125 +0,0 @@
|
||||||
GEM
|
|
||||||
remote: https://rubygems.org/
|
|
||||||
specs:
|
|
||||||
actionmailer (3.2.11)
|
|
||||||
actionpack (= 3.2.11)
|
|
||||||
mail (~> 2.4.4)
|
|
||||||
actionpack (3.2.11)
|
|
||||||
activemodel (= 3.2.11)
|
|
||||||
activesupport (= 3.2.11)
|
|
||||||
builder (~> 3.0.0)
|
|
||||||
erubis (~> 2.7.0)
|
|
||||||
journey (~> 1.0.4)
|
|
||||||
rack (~> 1.4.0)
|
|
||||||
rack-cache (~> 1.2)
|
|
||||||
rack-test (~> 0.6.1)
|
|
||||||
sprockets (~> 2.2.1)
|
|
||||||
activemodel (3.2.11)
|
|
||||||
activesupport (= 3.2.11)
|
|
||||||
builder (~> 3.0.0)
|
|
||||||
activerecord (3.2.11)
|
|
||||||
activemodel (= 3.2.11)
|
|
||||||
activesupport (= 3.2.11)
|
|
||||||
arel (~> 3.0.2)
|
|
||||||
tzinfo (~> 0.3.29)
|
|
||||||
activeresource (3.2.11)
|
|
||||||
activemodel (= 3.2.11)
|
|
||||||
activesupport (= 3.2.11)
|
|
||||||
activesupport (3.2.11)
|
|
||||||
i18n (~> 0.6)
|
|
||||||
multi_json (~> 1.0)
|
|
||||||
arel (3.0.2)
|
|
||||||
bluecloth (2.2.0)
|
|
||||||
builder (3.0.4)
|
|
||||||
calendar_view (0.0.7)
|
|
||||||
rails (>= 3.0.0)
|
|
||||||
coffee-rails (3.2.2)
|
|
||||||
coffee-script (>= 2.2.0)
|
|
||||||
railties (~> 3.2.0)
|
|
||||||
coffee-script (2.2.0)
|
|
||||||
coffee-script-source
|
|
||||||
execjs
|
|
||||||
coffee-script-source (1.4.0)
|
|
||||||
erubis (2.7.0)
|
|
||||||
execjs (1.4.0)
|
|
||||||
multi_json (~> 1.0)
|
|
||||||
ezcrypto (0.7.2)
|
|
||||||
haml (3.1.7)
|
|
||||||
hike (1.2.1)
|
|
||||||
i18n (0.6.1)
|
|
||||||
journey (1.0.4)
|
|
||||||
jquery-rails (2.2.0)
|
|
||||||
railties (>= 3.0, < 5.0)
|
|
||||||
thor (>= 0.14, < 2.0)
|
|
||||||
json (1.7.6)
|
|
||||||
mail (2.4.4)
|
|
||||||
i18n (>= 0.4.0)
|
|
||||||
mime-types (~> 1.16)
|
|
||||||
treetop (~> 1.4.8)
|
|
||||||
mime-types (1.19)
|
|
||||||
multi_json (1.5.0)
|
|
||||||
mysql2 (0.3.11)
|
|
||||||
polyglot (0.3.3)
|
|
||||||
rack (1.4.4)
|
|
||||||
rack-cache (1.2)
|
|
||||||
rack (>= 0.4)
|
|
||||||
rack-ssl (1.3.3)
|
|
||||||
rack
|
|
||||||
rack-test (0.6.2)
|
|
||||||
rack (>= 1.0)
|
|
||||||
rails (3.2.11)
|
|
||||||
actionmailer (= 3.2.11)
|
|
||||||
actionpack (= 3.2.11)
|
|
||||||
activerecord (= 3.2.11)
|
|
||||||
activeresource (= 3.2.11)
|
|
||||||
activesupport (= 3.2.11)
|
|
||||||
bundler (~> 1.0)
|
|
||||||
railties (= 3.2.11)
|
|
||||||
railties (3.2.11)
|
|
||||||
actionpack (= 3.2.11)
|
|
||||||
activesupport (= 3.2.11)
|
|
||||||
rack-ssl (~> 1.3.2)
|
|
||||||
rake (>= 0.8.7)
|
|
||||||
rdoc (~> 3.4)
|
|
||||||
thor (>= 0.14.6, < 2.0)
|
|
||||||
rake (10.0.3)
|
|
||||||
rdoc (3.12)
|
|
||||||
json (~> 1.4)
|
|
||||||
sass (3.2.5)
|
|
||||||
sass-rails (3.2.6)
|
|
||||||
railties (~> 3.2.0)
|
|
||||||
sass (>= 3.1.10)
|
|
||||||
tilt (~> 1.3)
|
|
||||||
sprockets (2.2.2)
|
|
||||||
hike (~> 1.2)
|
|
||||||
multi_json (~> 1.0)
|
|
||||||
rack (~> 1.0)
|
|
||||||
tilt (~> 1.1, != 1.3.0)
|
|
||||||
thor (0.17.0)
|
|
||||||
tilt (1.3.3)
|
|
||||||
treetop (1.4.12)
|
|
||||||
polyglot
|
|
||||||
polyglot (>= 0.3.1)
|
|
||||||
tzinfo (0.3.35)
|
|
||||||
uglifier (1.3.0)
|
|
||||||
execjs (>= 0.3.0)
|
|
||||||
multi_json (~> 1.0, >= 1.0.2)
|
|
||||||
will_paginate (3.0.4)
|
|
||||||
|
|
||||||
PLATFORMS
|
|
||||||
ruby
|
|
||||||
|
|
||||||
DEPENDENCIES
|
|
||||||
bluecloth
|
|
||||||
calendar_view
|
|
||||||
coffee-rails
|
|
||||||
ezcrypto
|
|
||||||
haml
|
|
||||||
jquery-rails
|
|
||||||
json (>= 1.7.6)
|
|
||||||
mysql2
|
|
||||||
rails (>= 3.2.11)
|
|
||||||
sass
|
|
||||||
sass-rails
|
|
||||||
uglifier
|
|
||||||
will_paginate
|
|
31
README
Normal file
31
README
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
Installation Guide
|
||||||
|
Requirements
|
||||||
|
|
||||||
|
* Ruby 1.8.7
|
||||||
|
* Rails 2.3.2
|
||||||
|
|
||||||
|
Installation
|
||||||
|
|
||||||
|
1. Checkout the source code
|
||||||
|
2. If you need to override some of the default constants used in the application take a look at config/default_site.rb. Then create config/site.rb that contains only the keys which you want to override. Example content of config/site.rb is:
|
||||||
|
|
||||||
|
module CDF
|
||||||
|
|
||||||
|
LOCALCONFIG = {
|
||||||
|
:imap_server => 'your.imap.server'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
3. Configure SMTP settings
|
||||||
|
# initializers/smtp_settings.rb
|
||||||
|
ActionMailer::Base.smtp_settings = {
|
||||||
|
:address => "mail.example.com.py",
|
||||||
|
:port => 26,
|
||||||
|
:authentication => :plain,
|
||||||
|
:enable_starttls_auto => true,
|
||||||
|
:user_name => "emilio@example.com.py",
|
||||||
|
:password => "yourpass"
|
||||||
|
}
|
||||||
|
|
||||||
|
4 Use it
|
|
@ -1,38 +0,0 @@
|
||||||
[![Dependency Status](https://gemnasium.com/musashimm/mailr.png)](https://gemnasium.com/musashimm/mailr)
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
_MailR_ is a IMAP mail client based on _Ruby on Rails_ platform.
|
|
||||||
|
|
||||||
**NOTE** All path and filenames are based on _Rails.root_ directory.
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
In _Rails 3_ and above all dependencies should be defined in file _Gemfile_. All needed gems can be installed using bundler.
|
|
||||||
|
|
||||||
## Installation procedure
|
|
||||||
|
|
||||||
* Checkout the source code.
|
|
||||||
* 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/settings.yml_ for proper values. (see _config/settings.yml.example_).
|
|
||||||
* Prepare config/database.yml file (see _config/database.yml.example_).
|
|
||||||
* Migrate database (rake db:migrate)
|
|
||||||
* Start rails server if applicable
|
|
||||||
* 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.
|
|
||||||
|
|
||||||
## Specific configuration
|
|
||||||
|
|
||||||
None
|
|
11
Rakefile
Executable file → Normal file
11
Rakefile
Executable file → Normal file
|
@ -1,7 +1,10 @@
|
||||||
#!/usr/bin/env rake
|
|
||||||
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
||||||
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
# for example lib/tasks/switchtower.rake, and they will automatically be available to Rake.
|
||||||
|
|
||||||
require File.expand_path('../config/application', __FILE__)
|
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
|
||||||
|
|
||||||
Mailr::Application.load_tasks
|
require 'rake'
|
||||||
|
require 'rake/testtask'
|
||||||
|
require 'rake/rdoctask'
|
||||||
|
|
||||||
|
require 'tasks/rails'
|
|
@ -1,21 +0,0 @@
|
||||||
## Todo
|
|
||||||
|
|
||||||
* add themes
|
|
||||||
|
|
||||||
app/controllers/folders_controller.rb:
|
|
||||||
|
|
||||||
* [ 29] [TODO] recreate local copy of folders
|
|
||||||
* [ 98] [TODO] save system folders
|
|
||||||
|
|
||||||
app/controllers/messages_controller.rb:
|
|
||||||
|
|
||||||
* [101] [FIXME] missing fields and support arrays
|
|
||||||
|
|
||||||
app/controllers/messages_ops_controller.rb:
|
|
||||||
|
|
||||||
* [261] [FIXME] edit does not support attachments
|
|
||||||
* [325] [TODO] check if email address is valid if not get address from contacts
|
|
||||||
|
|
||||||
app/models/prefs.rb:
|
|
||||||
|
|
||||||
* [ 21] [TODO] move refresh to prefs and make refresh page with messages
|
|
2
UNLICENSE.markdown → UNLICENSE
Executable file → Normal file
2
UNLICENSE.markdown → UNLICENSE
Executable file → Normal file
|
@ -1,5 +1,3 @@
|
||||||
## License
|
|
||||||
|
|
||||||
This is free and unencumbered software released into the public domain.
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
Binary file not shown.
Before Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 18 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.5 KiB |
|
@ -1,15 +0,0 @@
|
||||||
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
||||||
// listed below.
|
|
||||||
//
|
|
||||||
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
||||||
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
|
||||||
//
|
|
||||||
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
||||||
// the compiled file.
|
|
||||||
//
|
|
||||||
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
|
||||||
// GO AFTER THE REQUIRES BELOW.
|
|
||||||
//
|
|
||||||
//= require jquery
|
|
||||||
//= require jquery_ujs
|
|
||||||
//= require_tree .
|
|
1
app/assets/javascripts/bootstrap.min.js
vendored
1
app/assets/javascripts/bootstrap.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,498 +0,0 @@
|
||||||
/*!
|
|
||||||
* jQuery Migrate - v1.0.0 - 2013-01-14
|
|
||||||
* https://github.com/jquery/jquery-migrate
|
|
||||||
* Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; Licensed MIT
|
|
||||||
*/
|
|
||||||
(function( jQuery, window, undefined ) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
|
|
||||||
var warnedAbout = {};
|
|
||||||
|
|
||||||
// List of warnings already given; public read only
|
|
||||||
jQuery.migrateWarnings = [];
|
|
||||||
|
|
||||||
// Set to true to prevent console output; migrateWarnings still maintained
|
|
||||||
// jQuery.migrateMute = false;
|
|
||||||
|
|
||||||
// Forget any warnings we've already given; public
|
|
||||||
jQuery.migrateReset = function() {
|
|
||||||
warnedAbout = {};
|
|
||||||
jQuery.migrateWarnings.length = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
function migrateWarn( msg) {
|
|
||||||
if ( !warnedAbout[ msg ] ) {
|
|
||||||
warnedAbout[ msg ] = true;
|
|
||||||
jQuery.migrateWarnings.push( msg );
|
|
||||||
if ( window.console && console.warn && !jQuery.migrateMute ) {
|
|
||||||
console.warn( "JQMIGRATE: " + msg );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function migrateWarnProp( obj, prop, value, msg ) {
|
|
||||||
if ( Object.defineProperty ) {
|
|
||||||
// On ES5 browsers (non-oldIE), warn if the code tries to get prop;
|
|
||||||
// allow property to be overwritten in case some other plugin wants it
|
|
||||||
try {
|
|
||||||
Object.defineProperty( obj, prop, {
|
|
||||||
configurable: true,
|
|
||||||
enumerable: true,
|
|
||||||
get: function() {
|
|
||||||
migrateWarn( msg );
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
set: function( newValue ) {
|
|
||||||
migrateWarn( msg );
|
|
||||||
value = newValue;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
} catch( err ) {
|
|
||||||
// IE8 is a dope about Object.defineProperty, can't warn there
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non-ES5 (or broken) browser; just set the property
|
|
||||||
jQuery._definePropertyBroken = true;
|
|
||||||
obj[ prop ] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( document.compatMode === "BackCompat" ) {
|
|
||||||
// jQuery has never supported or tested Quirks Mode
|
|
||||||
migrateWarn( "jQuery is not compatible with Quirks Mode" );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var attrFn = {},
|
|
||||||
attr = jQuery.attr,
|
|
||||||
valueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get ||
|
|
||||||
function() { return null; },
|
|
||||||
valueAttrSet = jQuery.attrHooks.value && jQuery.attrHooks.value.set ||
|
|
||||||
function() { return undefined; },
|
|
||||||
rnoType = /^(?:input|button)$/i,
|
|
||||||
rnoAttrNodeType = /^[238]$/,
|
|
||||||
rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
|
|
||||||
ruseDefault = /^(?:checked|selected)$/i;
|
|
||||||
|
|
||||||
// jQuery.attrFn
|
|
||||||
migrateWarnProp( jQuery, "attrFn", attrFn, "jQuery.attrFn is deprecated" );
|
|
||||||
|
|
||||||
jQuery.attr = function( elem, name, value, pass ) {
|
|
||||||
var lowerName = name.toLowerCase(),
|
|
||||||
nType = elem && elem.nodeType;
|
|
||||||
|
|
||||||
if ( pass ) {
|
|
||||||
migrateWarn("jQuery.fn.attr( props, pass ) is deprecated");
|
|
||||||
if ( elem && !rnoAttrNodeType.test( nType ) && jQuery.isFunction( jQuery.fn[ name ] ) ) {
|
|
||||||
return jQuery( elem )[ name ]( value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warn if user tries to set `type` since it breaks on IE 6/7/8
|
|
||||||
if ( name === "type" && value !== undefined && rnoType.test( elem.nodeName ) ) {
|
|
||||||
migrateWarn("Can't change the 'type' of an input or button in IE 6/7/8");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore boolHook for boolean property/attribute synchronization
|
|
||||||
if ( !jQuery.attrHooks[ lowerName ] && rboolean.test( lowerName ) ) {
|
|
||||||
jQuery.attrHooks[ lowerName ] = {
|
|
||||||
get: function( elem, name ) {
|
|
||||||
// Align boolean attributes with corresponding properties
|
|
||||||
// Fall back to attribute presence where some booleans are not supported
|
|
||||||
var attrNode,
|
|
||||||
property = jQuery.prop( elem, name );
|
|
||||||
return property === true || typeof property !== "boolean" &&
|
|
||||||
( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
|
|
||||||
|
|
||||||
name.toLowerCase() :
|
|
||||||
undefined;
|
|
||||||
},
|
|
||||||
set: function( elem, value, name ) {
|
|
||||||
var propName;
|
|
||||||
if ( value === false ) {
|
|
||||||
// Remove boolean attributes when set to false
|
|
||||||
jQuery.removeAttr( elem, name );
|
|
||||||
} else {
|
|
||||||
// value is true since we know at this point it's type boolean and not false
|
|
||||||
// Set boolean attributes to the same name and set the DOM property
|
|
||||||
propName = jQuery.propFix[ name ] || name;
|
|
||||||
if ( propName in elem ) {
|
|
||||||
// Only set the IDL specifically if it already exists on the element
|
|
||||||
elem[ propName ] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
elem.setAttribute( name, name.toLowerCase() );
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Warn only for attributes that can remain distinct from their properties post-1.9
|
|
||||||
if ( ruseDefault.test( lowerName ) ) {
|
|
||||||
migrateWarn( "jQuery.fn.attr(" + lowerName + ") may use property instead of attribute" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return attr.call( jQuery, elem, name, value );
|
|
||||||
};
|
|
||||||
|
|
||||||
// attrHooks: value
|
|
||||||
jQuery.attrHooks.value = {
|
|
||||||
get: function( elem, name ) {
|
|
||||||
var nodeName = ( elem.nodeName || "" ).toLowerCase();
|
|
||||||
if ( nodeName === "button" ) {
|
|
||||||
return valueAttrGet.apply( this, arguments );
|
|
||||||
}
|
|
||||||
if ( nodeName !== "input" && nodeName !== "option" ) {
|
|
||||||
migrateWarn("property-based jQuery.fn.attr('value') is deprecated");
|
|
||||||
}
|
|
||||||
return name in elem ?
|
|
||||||
elem.value :
|
|
||||||
null;
|
|
||||||
},
|
|
||||||
set: function( elem, value ) {
|
|
||||||
var nodeName = ( elem.nodeName || "" ).toLowerCase();
|
|
||||||
if ( nodeName === "button" ) {
|
|
||||||
return valueAttrSet.apply( this, arguments );
|
|
||||||
}
|
|
||||||
if ( nodeName !== "input" && nodeName !== "option" ) {
|
|
||||||
migrateWarn("property-based jQuery.fn.attr('value', val) is deprecated");
|
|
||||||
}
|
|
||||||
// Does not return so that setAttribute is also used
|
|
||||||
elem.value = value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var matched, browser,
|
|
||||||
oldInit = jQuery.fn.init,
|
|
||||||
// Note this does NOT include the # XSS fix from 1.7!
|
|
||||||
rquickExpr = /^(?:.*(<[\w\W]+>)[^>]*|#([\w\-]*))$/;
|
|
||||||
|
|
||||||
// $(html) "looks like html" rule change
|
|
||||||
jQuery.fn.init = function( selector, context, rootjQuery ) {
|
|
||||||
var match;
|
|
||||||
|
|
||||||
if ( selector && typeof selector === "string" && !jQuery.isPlainObject( context ) &&
|
|
||||||
(match = rquickExpr.exec( selector )) && match[1] ) {
|
|
||||||
// This is an HTML string according to the "old" rules; is it still?
|
|
||||||
if ( selector.charAt( 0 ) !== "<" ) {
|
|
||||||
migrateWarn("$(html) HTML strings must start with '<' character");
|
|
||||||
}
|
|
||||||
// Now process using loose rules; let pre-1.8 play too
|
|
||||||
if ( context && context.context ) {
|
|
||||||
// jQuery object as context; parseHTML expects a DOM object
|
|
||||||
context = context.context;
|
|
||||||
}
|
|
||||||
if ( jQuery.parseHTML ) {
|
|
||||||
return oldInit.call( this, jQuery.parseHTML( jQuery.trim(selector), context, true ),
|
|
||||||
context, rootjQuery );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return oldInit.apply( this, arguments );
|
|
||||||
};
|
|
||||||
jQuery.fn.init.prototype = jQuery.fn;
|
|
||||||
|
|
||||||
jQuery.uaMatch = function( ua ) {
|
|
||||||
ua = ua.toLowerCase();
|
|
||||||
|
|
||||||
var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
|
|
||||||
/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
|
|
||||||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
|
|
||||||
/(msie) ([\w.]+)/.exec( ua ) ||
|
|
||||||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
|
|
||||||
[];
|
|
||||||
|
|
||||||
return {
|
|
||||||
browser: match[ 1 ] || "",
|
|
||||||
version: match[ 2 ] || "0"
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
matched = jQuery.uaMatch( navigator.userAgent );
|
|
||||||
browser = {};
|
|
||||||
|
|
||||||
if ( matched.browser ) {
|
|
||||||
browser[ matched.browser ] = true;
|
|
||||||
browser.version = matched.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chrome is Webkit, but Webkit is also Safari.
|
|
||||||
if ( browser.chrome ) {
|
|
||||||
browser.webkit = true;
|
|
||||||
} else if ( browser.webkit ) {
|
|
||||||
browser.safari = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
jQuery.browser = browser;
|
|
||||||
|
|
||||||
// Warn if the code tries to get jQuery.browser
|
|
||||||
migrateWarnProp( jQuery, "browser", browser, "jQuery.browser is deprecated" );
|
|
||||||
|
|
||||||
jQuery.sub = function() {
|
|
||||||
function jQuerySub( selector, context ) {
|
|
||||||
return new jQuerySub.fn.init( selector, context );
|
|
||||||
}
|
|
||||||
jQuery.extend( true, jQuerySub, this );
|
|
||||||
jQuerySub.superclass = this;
|
|
||||||
jQuerySub.fn = jQuerySub.prototype = this();
|
|
||||||
jQuerySub.fn.constructor = jQuerySub;
|
|
||||||
jQuerySub.sub = this.sub;
|
|
||||||
jQuerySub.fn.init = function init( selector, context ) {
|
|
||||||
if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
|
|
||||||
context = jQuerySub( context );
|
|
||||||
}
|
|
||||||
|
|
||||||
return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
|
|
||||||
};
|
|
||||||
jQuerySub.fn.init.prototype = jQuerySub.fn;
|
|
||||||
var rootjQuerySub = jQuerySub(document);
|
|
||||||
migrateWarn( "jQuery.sub() is deprecated" );
|
|
||||||
return jQuerySub;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var oldFnData = jQuery.fn.data;
|
|
||||||
|
|
||||||
jQuery.fn.data = function( name ) {
|
|
||||||
var ret, evt,
|
|
||||||
elem = this[0];
|
|
||||||
|
|
||||||
// Handles 1.7 which has this behavior and 1.8 which doesn't
|
|
||||||
if ( elem && name === "events" && arguments.length === 1 ) {
|
|
||||||
ret = jQuery.data( elem, name );
|
|
||||||
evt = jQuery._data( elem, name );
|
|
||||||
if ( ( ret === undefined || ret === evt ) && evt !== undefined ) {
|
|
||||||
migrateWarn("Use of jQuery.fn.data('events') is deprecated");
|
|
||||||
return evt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return oldFnData.apply( this, arguments );
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var rscriptType = /\/(java|ecma)script/i,
|
|
||||||
oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack,
|
|
||||||
oldFragment = jQuery.buildFragment;
|
|
||||||
|
|
||||||
jQuery.fn.andSelf = function() {
|
|
||||||
migrateWarn("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()");
|
|
||||||
return oldSelf.apply( this, arguments );
|
|
||||||
};
|
|
||||||
|
|
||||||
// Since jQuery.clean is used internally on older versions, we only shim if it's missing
|
|
||||||
if ( !jQuery.clean ) {
|
|
||||||
jQuery.clean = function( elems, context, fragment, scripts ) {
|
|
||||||
// Set context per 1.8 logic
|
|
||||||
context = context || document;
|
|
||||||
context = !context.nodeType && context[0] || context;
|
|
||||||
context = context.ownerDocument || context;
|
|
||||||
|
|
||||||
migrateWarn("jQuery.clean() is deprecated");
|
|
||||||
|
|
||||||
var i, elem, handleScript, jsTags,
|
|
||||||
ret = [];
|
|
||||||
|
|
||||||
jQuery.merge( ret, jQuery.buildFragment( elems, context ).childNodes );
|
|
||||||
|
|
||||||
// Complex logic lifted directly from jQuery 1.8
|
|
||||||
if ( fragment ) {
|
|
||||||
// Special handling of each script element
|
|
||||||
handleScript = function( elem ) {
|
|
||||||
// Check if we consider it executable
|
|
||||||
if ( !elem.type || rscriptType.test( elem.type ) ) {
|
|
||||||
// Detach the script and store it in the scripts array (if provided) or the fragment
|
|
||||||
// Return truthy to indicate that it has been handled
|
|
||||||
return scripts ?
|
|
||||||
scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
|
|
||||||
fragment.appendChild( elem );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for ( i = 0; (elem = ret[i]) != null; i++ ) {
|
|
||||||
// Check if we're done after handling an executable script
|
|
||||||
if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
|
|
||||||
// Append to fragment and handle embedded scripts
|
|
||||||
fragment.appendChild( elem );
|
|
||||||
if ( typeof elem.getElementsByTagName !== "undefined" ) {
|
|
||||||
// handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
|
|
||||||
jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
|
|
||||||
|
|
||||||
// Splice the scripts into ret after their former ancestor and advance our index beyond them
|
|
||||||
ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
|
|
||||||
i += jsTags.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
jQuery.buildFragment = function( elems, context, scripts, selection ) {
|
|
||||||
var ret,
|
|
||||||
warning = "jQuery.buildFragment() is deprecated";
|
|
||||||
|
|
||||||
// Set context per 1.8 logic
|
|
||||||
context = context || document;
|
|
||||||
context = !context.nodeType && context[0] || context;
|
|
||||||
context = context.ownerDocument || context;
|
|
||||||
|
|
||||||
try {
|
|
||||||
ret = oldFragment.call( jQuery, elems, context, scripts, selection );
|
|
||||||
|
|
||||||
// jQuery < 1.8 required arrayish context; jQuery 1.9 fails on it
|
|
||||||
} catch( x ) {
|
|
||||||
ret = oldFragment.call( jQuery, elems, context.nodeType ? [ context ] : context[ 0 ], scripts, selection );
|
|
||||||
|
|
||||||
// Success from tweaking context means buildFragment was called by the user
|
|
||||||
migrateWarn( warning );
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery < 1.9 returned an object instead of the fragment itself
|
|
||||||
if ( !ret.fragment ) {
|
|
||||||
migrateWarnProp( ret, "fragment", ret, warning );
|
|
||||||
migrateWarnProp( ret, "cacheable", false, warning );
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
var eventAdd = jQuery.event.add,
|
|
||||||
eventRemove = jQuery.event.remove,
|
|
||||||
eventTrigger = jQuery.event.trigger,
|
|
||||||
oldToggle = jQuery.fn.toggle,
|
|
||||||
oldLive = jQuery.fn.live,
|
|
||||||
oldDie = jQuery.fn.die,
|
|
||||||
ajaxEvents = "ajaxStart|ajaxStop|ajaxSend|ajaxComplete|ajaxError|ajaxSuccess",
|
|
||||||
rajaxEvent = new RegExp( "\\b(?:" + ajaxEvents + ")\\b" ),
|
|
||||||
rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
|
|
||||||
hoverHack = function( events ) {
|
|
||||||
if ( typeof( events ) != "string" || jQuery.event.special.hover ) {
|
|
||||||
return events;
|
|
||||||
}
|
|
||||||
if ( rhoverHack.test( events ) ) {
|
|
||||||
migrateWarn("'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'");
|
|
||||||
}
|
|
||||||
return events && events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
|
|
||||||
};
|
|
||||||
|
|
||||||
// Event props removed in 1.9, put them back if needed; no practical way to warn them
|
|
||||||
if ( jQuery.event.props && jQuery.event.props[ 0 ] !== "attrChange" ) {
|
|
||||||
jQuery.event.props.unshift( "attrChange", "attrName", "relatedNode", "srcElement" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Undocumented jQuery.event.handle was "deprecated" in jQuery 1.7
|
|
||||||
migrateWarnProp( jQuery.event, "handle", jQuery.event.dispatch, "jQuery.event.handle is undocumented and deprecated" );
|
|
||||||
|
|
||||||
// Support for 'hover' pseudo-event and ajax event warnings
|
|
||||||
jQuery.event.add = function( elem, types, handler, data, selector ){
|
|
||||||
if ( elem !== document && rajaxEvent.test( types ) ) {
|
|
||||||
migrateWarn( "AJAX events should be attached to document: " + types );
|
|
||||||
}
|
|
||||||
eventAdd.call( this, elem, hoverHack( types || "" ), handler, data, selector );
|
|
||||||
};
|
|
||||||
jQuery.event.remove = function( elem, types, handler, selector, mappedTypes ){
|
|
||||||
eventRemove.call( this, elem, hoverHack( types ) || "", handler, selector, mappedTypes );
|
|
||||||
};
|
|
||||||
|
|
||||||
jQuery.fn.error = function() {
|
|
||||||
var args = Array.prototype.slice.call( arguments, 0);
|
|
||||||
migrateWarn("jQuery.fn.error() is deprecated");
|
|
||||||
args.splice( 0, 0, "error" );
|
|
||||||
if ( arguments.length ) {
|
|
||||||
return this.bind.apply( this, args );
|
|
||||||
}
|
|
||||||
// error event should not bubble to window, although it does pre-1.7
|
|
||||||
this.triggerHandler.apply( this, args );
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
jQuery.fn.toggle = function( fn, fn2 ) {
|
|
||||||
|
|
||||||
// Don't mess with animation or css toggles
|
|
||||||
if ( !jQuery.isFunction( fn ) || !jQuery.isFunction( fn2 ) ) {
|
|
||||||
return oldToggle.apply( this, arguments );
|
|
||||||
}
|
|
||||||
migrateWarn("jQuery.fn.toggle(handler, handler...) is deprecated");
|
|
||||||
|
|
||||||
// Save reference to arguments for access in closure
|
|
||||||
var args = arguments,
|
|
||||||
guid = fn.guid || jQuery.guid++,
|
|
||||||
i = 0,
|
|
||||||
toggler = function( event ) {
|
|
||||||
// Figure out which function to execute
|
|
||||||
var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
|
|
||||||
jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
|
|
||||||
|
|
||||||
// Make sure that clicks stop
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
// and execute the function
|
|
||||||
return args[ lastToggle ].apply( this, arguments ) || false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// link all the functions, so any of them can unbind this click handler
|
|
||||||
toggler.guid = guid;
|
|
||||||
while ( i < args.length ) {
|
|
||||||
args[ i++ ].guid = guid;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.click( toggler );
|
|
||||||
};
|
|
||||||
|
|
||||||
jQuery.fn.live = function( types, data, fn ) {
|
|
||||||
migrateWarn("jQuery.fn.live() is deprecated");
|
|
||||||
if ( oldLive ) {
|
|
||||||
return oldLive.apply( this, arguments );
|
|
||||||
}
|
|
||||||
jQuery( this.context ).on( types, this.selector, data, fn );
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
jQuery.fn.die = function( types, fn ) {
|
|
||||||
migrateWarn("jQuery.fn.die() is deprecated");
|
|
||||||
if ( oldDie ) {
|
|
||||||
return oldDie.apply( this, arguments );
|
|
||||||
}
|
|
||||||
jQuery( this.context ).off( types, this.selector || "**", fn );
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Turn global events into document-triggered events
|
|
||||||
jQuery.event.trigger = function( event, data, elem, onlyHandlers ){
|
|
||||||
if ( !elem & !rajaxEvent.test( event ) ) {
|
|
||||||
migrateWarn( "Global events are undocumented and deprecated" );
|
|
||||||
}
|
|
||||||
return eventTrigger.call( this, event, data, elem || document, onlyHandlers );
|
|
||||||
};
|
|
||||||
jQuery.each( ajaxEvents.split("|"),
|
|
||||||
function( _, name ) {
|
|
||||||
jQuery.event.special[ name ] = {
|
|
||||||
setup: function() {
|
|
||||||
var elem = this;
|
|
||||||
|
|
||||||
// The document needs no shimming; must be !== for oldIE
|
|
||||||
if ( elem !== document ) {
|
|
||||||
jQuery.event.add( document, name + "." + jQuery.guid, function() {
|
|
||||||
jQuery.event.trigger( name, null, elem, true );
|
|
||||||
});
|
|
||||||
jQuery._data( this, name, jQuery.guid++ );
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
teardown: function() {
|
|
||||||
if ( this !== document ) {
|
|
||||||
jQuery.event.remove( document, name + "." + jQuery._data( this, name ) );
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
})( jQuery, window );
|
|
|
@ -1,9 +0,0 @@
|
||||||
$(function() {
|
|
||||||
$("#toggleall").click(function() {
|
|
||||||
var checked_status = this.checked;
|
|
||||||
jQuery("input[type='checkbox']").each(function() {
|
|
||||||
this.checked = checked_status;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,13 +0,0 @@
|
||||||
/*
|
|
||||||
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
||||||
* listed below.
|
|
||||||
*
|
|
||||||
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
||||||
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
|
||||||
*
|
|
||||||
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
|
||||||
* compiled file, but it's generally better to create a new file per style scope.
|
|
||||||
*
|
|
||||||
*= require_self
|
|
||||||
*= require_tree .
|
|
||||||
*/
|
|
File diff suppressed because one or more lines are too long
632
app/assets/stylesheets/bootstrap.min.css
vendored
632
app/assets/stylesheets/bootstrap.min.css
vendored
|
@ -1,632 +0,0 @@
|
||||||
article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}
|
|
||||||
audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}
|
|
||||||
audio:not([controls]){display:none;}
|
|
||||||
html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}
|
|
||||||
a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
|
|
||||||
a:hover,a:active{outline:0;}
|
|
||||||
sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}
|
|
||||||
sup{top:-0.5em;}
|
|
||||||
sub{bottom:-0.25em;}
|
|
||||||
img{max-width:100%;height:auto;border:0;-ms-interpolation-mode:bicubic;}
|
|
||||||
button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;}
|
|
||||||
button,input{*overflow:visible;line-height:normal;}
|
|
||||||
button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}
|
|
||||||
button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;}
|
|
||||||
input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;}
|
|
||||||
input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;}
|
|
||||||
textarea{overflow:auto;vertical-align:top;}
|
|
||||||
.clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";}
|
|
||||||
.clearfix:after{clear:both;}
|
|
||||||
body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333333;background-color:#ffffff;}
|
|
||||||
a{color:#0088cc;text-decoration:none;}
|
|
||||||
a:hover{color:#005580;text-decoration:underline;}
|
|
||||||
.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";}
|
|
||||||
.row:after{clear:both;}
|
|
||||||
[class*="span"]{float:left;margin-left:20px;}
|
|
||||||
.span1{width:60px;}
|
|
||||||
.span2{width:140px;}
|
|
||||||
.span3{width:220px;}
|
|
||||||
.span4{width:300px;}
|
|
||||||
.span5{width:380px;}
|
|
||||||
.span6{width:460px;}
|
|
||||||
.span7{width:540px;}
|
|
||||||
.span8{width:620px;}
|
|
||||||
.span9{width:700px;}
|
|
||||||
.span10{width:780px;}
|
|
||||||
.span11{width:860px;}
|
|
||||||
.span12,.container{width:940px;}
|
|
||||||
.offset1{margin-left:100px;}
|
|
||||||
.offset2{margin-left:180px;}
|
|
||||||
.offset3{margin-left:260px;}
|
|
||||||
.offset4{margin-left:340px;}
|
|
||||||
.offset5{margin-left:420px;}
|
|
||||||
.offset6{margin-left:500px;}
|
|
||||||
.offset7{margin-left:580px;}
|
|
||||||
.offset8{margin-left:660px;}
|
|
||||||
.offset9{margin-left:740px;}
|
|
||||||
.offset10{margin-left:820px;}
|
|
||||||
.offset11{margin-left:900px;}
|
|
||||||
.row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";}
|
|
||||||
.row-fluid:after{clear:both;}
|
|
||||||
.row-fluid>[class*="span"]{float:left;margin-left:2.127659574%;}
|
|
||||||
.row-fluid>[class*="span"]:first-child{margin-left:0;}
|
|
||||||
.row-fluid>.span1{width:6.382978723%;}
|
|
||||||
.row-fluid>.span2{width:14.89361702%;}
|
|
||||||
.row-fluid>.span3{width:23.404255317%;}
|
|
||||||
.row-fluid>.span4{width:31.914893614%;}
|
|
||||||
.row-fluid>.span5{width:40.425531911%;}
|
|
||||||
.row-fluid>.span6{width:48.93617020799999%;}
|
|
||||||
.row-fluid>.span7{width:57.446808505%;}
|
|
||||||
.row-fluid>.span8{width:65.95744680199999%;}
|
|
||||||
.row-fluid>.span9{width:74.468085099%;}
|
|
||||||
.row-fluid>.span10{width:82.97872339599999%;}
|
|
||||||
.row-fluid>.span11{width:91.489361693%;}
|
|
||||||
.row-fluid>.span12{width:99.99999998999999%;}
|
|
||||||
.container{width:940px;margin-left:auto;margin-right:auto;*zoom:1;}.container:before,.container:after{display:table;content:"";}
|
|
||||||
.container:after{clear:both;}
|
|
||||||
.container-fluid{padding-left:20px;padding-right:20px;*zoom:1;}.container-fluid:before,.container-fluid:after{display:table;content:"";}
|
|
||||||
.container-fluid:after{clear:both;}
|
|
||||||
p{margin:0 0 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;}p small{font-size:11px;color:#999999;}
|
|
||||||
.lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px;}
|
|
||||||
h1,h2,h3,h4,h5,h6{margin:0;font-weight:bold;color:#333333;text-rendering:optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;color:#999999;}
|
|
||||||
h1{font-size:30px;line-height:36px;}h1 small{font-size:18px;}
|
|
||||||
h2{font-size:24px;line-height:36px;}h2 small{font-size:18px;}
|
|
||||||
h3{line-height:27px;font-size:18px;}h3 small{font-size:14px;}
|
|
||||||
h4,h5,h6{line-height:18px;}
|
|
||||||
h4{font-size:14px;}h4 small{font-size:12px;}
|
|
||||||
h5{font-size:12px;}
|
|
||||||
h6{font-size:11px;color:#999999;text-transform:uppercase;}
|
|
||||||
.page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eeeeee;}
|
|
||||||
.page-header h1{line-height:1;}
|
|
||||||
ul,ol{padding:0;margin:0 0 9px 25px;}
|
|
||||||
ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}
|
|
||||||
ul{list-style:disc;}
|
|
||||||
ol{list-style:decimal;}
|
|
||||||
li{line-height:18px;}
|
|
||||||
ul.unstyled,ol.unstyled{margin-left:0;list-style:none;}
|
|
||||||
dl{margin-bottom:18px;}
|
|
||||||
dt,dd{line-height:18px;}
|
|
||||||
dt{font-weight:bold;}
|
|
||||||
dd{margin-left:9px;}
|
|
||||||
hr{margin:18px 0;border:0;border-top:1px solid #eeeeee;border-bottom:1px solid #ffffff;}
|
|
||||||
strong{font-weight:bold;}
|
|
||||||
em{font-style:italic;}
|
|
||||||
.muted{color:#999999;}
|
|
||||||
abbr{font-size:90%;text-transform:uppercase;border-bottom:1px dotted #ddd;cursor:help;}
|
|
||||||
blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eeeeee;}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px;}
|
|
||||||
blockquote small{display:block;line-height:18px;color:#999999;}blockquote small:before{content:'\2014 \00A0';}
|
|
||||||
blockquote.pull-right{float:right;padding-left:0;padding-right:15px;border-left:0;border-right:5px solid #eeeeee;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;}
|
|
||||||
q:before,q:after,blockquote:before,blockquote:after{content:"";}
|
|
||||||
address{display:block;margin-bottom:18px;line-height:18px;font-style:normal;}
|
|
||||||
small{font-size:100%;}
|
|
||||||
cite{font-style:normal;}
|
|
||||||
code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,"Courier New",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
|
|
||||||
code{padding:3px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;}
|
|
||||||
pre{display:block;padding:8.5px;margin:0 0 9px;font-size:12px;line-height:18px;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;white-space:pre;white-space:pre-wrap;word-break:break-all;word-wrap:break-word;}pre.prettyprint{margin-bottom:18px;}
|
|
||||||
pre code{padding:0;color:inherit;background-color:transparent;border:0;}
|
|
||||||
.pre-scrollable{max-height:340px;overflow-y:scroll;}
|
|
||||||
form{margin:0 0 18px;}
|
|
||||||
fieldset{padding:0;margin:0;border:0;}
|
|
||||||
legend{display:block;width:100%;padding:0;margin-bottom:27px;font-size:19.5px;line-height:36px;color:#333333;border:0;border-bottom:1px solid #eee;}legend small{font-size:13.5px;color:#999999;}
|
|
||||||
label,input,button,select,textarea{font-size:13px;font-weight:normal;line-height:18px;}
|
|
||||||
input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;}
|
|
||||||
label{display:block;margin-bottom:5px;color:#333333;}
|
|
||||||
input,textarea,select,.uneditable-input{display:inline-block;width:210px;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555555;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
|
|
||||||
.uneditable-textarea{width:auto;height:auto;}
|
|
||||||
label input,label textarea,label select{display:block;}
|
|
||||||
input[type="image"],input[type="checkbox"],input[type="radio"]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;cursor:pointer;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;border:0 \9;}
|
|
||||||
input[type="image"]{border:0;}
|
|
||||||
input[type="file"]{width:auto;padding:initial;line-height:initial;border:initial;background-color:#ffffff;background-color:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
|
||||||
input[type="button"],input[type="reset"],input[type="submit"]{width:auto;height:auto;}
|
|
||||||
select,input[type="file"]{height:28px;*margin-top:4px;line-height:28px;}
|
|
||||||
input[type="file"]{line-height:18px \9;}
|
|
||||||
select{width:220px;background-color:#ffffff;}
|
|
||||||
select[multiple],select[size]{height:auto;}
|
|
||||||
input[type="image"]{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
|
||||||
textarea{height:auto;}
|
|
||||||
input[type="hidden"]{display:none;}
|
|
||||||
.radio,.checkbox{padding-left:18px;}
|
|
||||||
.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px;}
|
|
||||||
.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px;}
|
|
||||||
.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle;}
|
|
||||||
.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px;}
|
|
||||||
input,textarea{-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border linear 0.2s,box-shadow linear 0.2s;-moz-transition:border linear 0.2s,box-shadow linear 0.2s;-ms-transition:border linear 0.2s,box-shadow linear 0.2s;-o-transition:border linear 0.2s,box-shadow linear 0.2s;transition:border linear 0.2s,box-shadow linear 0.2s;}
|
|
||||||
input:focus,textarea:focus{border-color:rgba(82, 168, 236, 0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);outline:0;outline:thin dotted \9;}
|
|
||||||
input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
|
|
||||||
.input-mini{width:60px;}
|
|
||||||
.input-small{width:90px;}
|
|
||||||
.input-medium{width:150px;}
|
|
||||||
.input-large{width:210px;}
|
|
||||||
.input-xlarge{width:270px;}
|
|
||||||
.input-xxlarge{width:530px;}
|
|
||||||
input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{float:none;margin-left:0;}
|
|
||||||
input.span1,textarea.span1,.uneditable-input.span1{width:50px;}
|
|
||||||
input.span2,textarea.span2,.uneditable-input.span2{width:130px;}
|
|
||||||
input.span3,textarea.span3,.uneditable-input.span3{width:210px;}
|
|
||||||
input.span4,textarea.span4,.uneditable-input.span4{width:290px;}
|
|
||||||
input.span5,textarea.span5,.uneditable-input.span5{width:370px;}
|
|
||||||
input.span6,textarea.span6,.uneditable-input.span6{width:450px;}
|
|
||||||
input.span7,textarea.span7,.uneditable-input.span7{width:530px;}
|
|
||||||
input.span8,textarea.span8,.uneditable-input.span8{width:610px;}
|
|
||||||
input.span9,textarea.span9,.uneditable-input.span9{width:690px;}
|
|
||||||
input.span10,textarea.span10,.uneditable-input.span10{width:770px;}
|
|
||||||
input.span11,textarea.span11,.uneditable-input.span11{width:850px;}
|
|
||||||
input.span12,textarea.span12,.uneditable-input.span12{width:930px;}
|
|
||||||
input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{background-color:#f5f5f5;border-color:#ddd;cursor:not-allowed;}
|
|
||||||
.control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853;}
|
|
||||||
.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;border-color:#c09853;}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:0 0 6px #dbc59e;-moz-box-shadow:0 0 6px #dbc59e;box-shadow:0 0 6px #dbc59e;}
|
|
||||||
.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853;}
|
|
||||||
.control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48;}
|
|
||||||
.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;border-color:#b94a48;}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:0 0 6px #d59392;-moz-box-shadow:0 0 6px #d59392;box-shadow:0 0 6px #d59392;}
|
|
||||||
.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48;}
|
|
||||||
.control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847;}
|
|
||||||
.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;border-color:#468847;}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:0 0 6px #7aba7b;-moz-box-shadow:0 0 6px #7aba7b;box-shadow:0 0 6px #7aba7b;}
|
|
||||||
.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847;}
|
|
||||||
input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b;}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;}
|
|
||||||
.form-actions{padding:17px 20px 18px;margin-top:18px;margin-bottom:18px;background-color:#f5f5f5;border-top:1px solid #ddd;}
|
|
||||||
.uneditable-input{display:block;background-color:#ffffff;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;}
|
|
||||||
:-moz-placeholder{color:#999999;}
|
|
||||||
::-webkit-input-placeholder{color:#999999;}
|
|
||||||
.help-block{display:block;margin-top:5px;margin-bottom:0;color:#999999;}
|
|
||||||
.help-inline{display:inline-block;*display:inline;*zoom:1;margin-bottom:9px;vertical-align:middle;padding-left:5px;}
|
|
||||||
.input-prepend,.input-append{margin-bottom:5px;*zoom:1;}.input-prepend:before,.input-append:before,.input-prepend:after,.input-append:after{display:table;content:"";}
|
|
||||||
.input-prepend:after,.input-append:after{clear:both;}
|
|
||||||
.input-prepend input,.input-append input,.input-prepend .uneditable-input,.input-append .uneditable-input{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}.input-prepend input:focus,.input-append input:focus,.input-prepend .uneditable-input:focus,.input-append .uneditable-input:focus{position:relative;z-index:2;}
|
|
||||||
.input-prepend .uneditable-input,.input-append .uneditable-input{border-left-color:#ccc;}
|
|
||||||
.input-prepend .add-on,.input-append .add-on{float:left;display:block;width:auto;min-width:16px;height:18px;margin-right:-1px;padding:4px 5px;font-weight:normal;line-height:18px;color:#999999;text-align:center;text-shadow:0 1px 0 #ffffff;background-color:#f5f5f5;border:1px solid #ccc;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
|
|
||||||
.input-prepend .active,.input-append .active{background-color:#a9dba9;border-color:#46a546;}
|
|
||||||
.input-prepend .add-on{*margin-top:1px;}
|
|
||||||
.input-append input,.input-append .uneditable-input{float:left;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
|
|
||||||
.input-append .uneditable-input{border-left-color:#eee;border-right-color:#ccc;}
|
|
||||||
.input-append .add-on{margin-right:0;margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
|
|
||||||
.input-append input:first-child{*margin-left:-160px;}.input-append input:first-child+.add-on{*margin-left:-21px;}
|
|
||||||
.search-query{padding-left:14px;padding-right:14px;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px;}
|
|
||||||
.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input{display:inline-block;margin-bottom:0;}
|
|
||||||
.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none;}
|
|
||||||
.form-search label,.form-inline label,.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{display:inline-block;}
|
|
||||||
.form-search .input-append .add-on,.form-inline .input-prepend .add-on,.form-search .input-append .add-on,.form-inline .input-prepend .add-on{vertical-align:middle;}
|
|
||||||
.form-search .radio,.form-inline .radio,.form-search .checkbox,.form-inline .checkbox{margin-bottom:0;vertical-align:middle;}
|
|
||||||
.control-group{margin-bottom:9px;}
|
|
||||||
legend+.control-group{margin-top:18px;-webkit-margin-top-collapse:separate;}
|
|
||||||
.form-horizontal .control-group{margin-bottom:18px;*zoom:1;}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:"";}
|
|
||||||
.form-horizontal .control-group:after{clear:both;}
|
|
||||||
.form-horizontal .control-label{float:left;width:140px;padding-top:5px;text-align:right;}
|
|
||||||
.form-horizontal .controls{margin-left:160px;}
|
|
||||||
.form-horizontal .form-actions{padding-left:160px;}
|
|
||||||
table{max-width:100%;border-collapse:collapse;border-spacing:0;}
|
|
||||||
.table{width:100%;margin-bottom:18px;}.table th,.table td{padding:8px;line-height:18px;text-align:left;vertical-align:top;border-top:1px solid #ddd;}
|
|
||||||
.table th{font-weight:bold;}
|
|
||||||
.table thead th{vertical-align:bottom;}
|
|
||||||
.table thead:first-child tr th,.table thead:first-child tr td{border-top:0;}
|
|
||||||
.table tbody+tbody{border-top:2px solid #ddd;}
|
|
||||||
.table-condensed th,.table-condensed td{padding:4px 5px;}
|
|
||||||
.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapsed;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th+th,.table-bordered td+td,.table-bordered th+td,.table-bordered td+th{border-left:1px solid #ddd;}
|
|
||||||
.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0;}
|
|
||||||
.table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-radius:4px 0 0 0;-moz-border-radius:4px 0 0 0;border-radius:4px 0 0 0;}
|
|
||||||
.table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0;}
|
|
||||||
.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;}
|
|
||||||
.table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0;}
|
|
||||||
.table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9;}
|
|
||||||
.table tbody tr:hover td,.table tbody tr:hover th{background-color:#f5f5f5;}
|
|
||||||
table .span1{float:none;width:44px;margin-left:0;}
|
|
||||||
table .span2{float:none;width:124px;margin-left:0;}
|
|
||||||
table .span3{float:none;width:204px;margin-left:0;}
|
|
||||||
table .span4{float:none;width:284px;margin-left:0;}
|
|
||||||
table .span5{float:none;width:364px;margin-left:0;}
|
|
||||||
table .span6{float:none;width:444px;margin-left:0;}
|
|
||||||
table .span7{float:none;width:524px;margin-left:0;}
|
|
||||||
table .span8{float:none;width:604px;margin-left:0;}
|
|
||||||
table .span9{float:none;width:684px;margin-left:0;}
|
|
||||||
table .span10{float:none;width:764px;margin-left:0;}
|
|
||||||
table .span11{float:none;width:844px;margin-left:0;}
|
|
||||||
table .span12{float:none;width:924px;margin-left:0;}
|
|
||||||
[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;line-height:14px;vertical-align:text-top;background-image:url("/assets/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat;*margin-right:.3em;}[class^="icon-"]:last-child,[class*=" icon-"]:last-child{*margin-left:0;}
|
|
||||||
.icon-white{background-image:url("/assets/glyphicons-halflings-white.png");}
|
|
||||||
.icon-glass{background-position:0 0;}
|
|
||||||
.icon-music{background-position:-24px 0;}
|
|
||||||
.icon-search{background-position:-48px 0;}
|
|
||||||
.icon-envelope{background-position:-72px 0;}
|
|
||||||
.icon-heart{background-position:-96px 0;}
|
|
||||||
.icon-star{background-position:-120px 0;}
|
|
||||||
.icon-star-empty{background-position:-144px 0;}
|
|
||||||
.icon-user{background-position:-168px 0;}
|
|
||||||
.icon-film{background-position:-192px 0;}
|
|
||||||
.icon-th-large{background-position:-216px 0;}
|
|
||||||
.icon-th{background-position:-240px 0;}
|
|
||||||
.icon-th-list{background-position:-264px 0;}
|
|
||||||
.icon-ok{background-position:-288px 0;}
|
|
||||||
.icon-remove{background-position:-312px 0;}
|
|
||||||
.icon-zoom-in{background-position:-336px 0;}
|
|
||||||
.icon-zoom-out{background-position:-360px 0;}
|
|
||||||
.icon-off{background-position:-384px 0;}
|
|
||||||
.icon-signal{background-position:-408px 0;}
|
|
||||||
.icon-cog{background-position:-432px 0;}
|
|
||||||
.icon-trash{background-position:-456px 0;}
|
|
||||||
.icon-home{background-position:0 -24px;}
|
|
||||||
.icon-file{background-position:-24px -24px;}
|
|
||||||
.icon-time{background-position:-48px -24px;}
|
|
||||||
.icon-road{background-position:-72px -24px;}
|
|
||||||
.icon-download-alt{background-position:-96px -24px;}
|
|
||||||
.icon-download{background-position:-120px -24px;}
|
|
||||||
.icon-upload{background-position:-144px -24px;}
|
|
||||||
.icon-inbox{background-position:-168px -24px;}
|
|
||||||
.icon-play-circle{background-position:-192px -24px;}
|
|
||||||
.icon-repeat{background-position:-216px -24px;}
|
|
||||||
.icon-refresh{background-position:-240px -24px;}
|
|
||||||
.icon-list-alt{background-position:-264px -24px;}
|
|
||||||
.icon-lock{background-position:-287px -24px;}
|
|
||||||
.icon-flag{background-position:-312px -24px;}
|
|
||||||
.icon-headphones{background-position:-336px -24px;}
|
|
||||||
.icon-volume-off{background-position:-360px -24px;}
|
|
||||||
.icon-volume-down{background-position:-384px -24px;}
|
|
||||||
.icon-volume-up{background-position:-408px -24px;}
|
|
||||||
.icon-qrcode{background-position:-432px -24px;}
|
|
||||||
.icon-barcode{background-position:-456px -24px;}
|
|
||||||
.icon-tag{background-position:0 -48px;}
|
|
||||||
.icon-tags{background-position:-25px -48px;}
|
|
||||||
.icon-book{background-position:-48px -48px;}
|
|
||||||
.icon-bookmark{background-position:-72px -48px;}
|
|
||||||
.icon-print{background-position:-96px -48px;}
|
|
||||||
.icon-camera{background-position:-120px -48px;}
|
|
||||||
.icon-font{background-position:-144px -48px;}
|
|
||||||
.icon-bold{background-position:-167px -48px;}
|
|
||||||
.icon-italic{background-position:-192px -48px;}
|
|
||||||
.icon-text-height{background-position:-216px -48px;}
|
|
||||||
.icon-text-width{background-position:-240px -48px;}
|
|
||||||
.icon-align-left{background-position:-264px -48px;}
|
|
||||||
.icon-align-center{background-position:-288px -48px;}
|
|
||||||
.icon-align-right{background-position:-312px -48px;}
|
|
||||||
.icon-align-justify{background-position:-336px -48px;}
|
|
||||||
.icon-list{background-position:-360px -48px;}
|
|
||||||
.icon-indent-left{background-position:-384px -48px;}
|
|
||||||
.icon-indent-right{background-position:-408px -48px;}
|
|
||||||
.icon-facetime-video{background-position:-432px -48px;}
|
|
||||||
.icon-picture{background-position:-456px -48px;}
|
|
||||||
.icon-pencil{background-position:0 -72px;}
|
|
||||||
.icon-map-marker{background-position:-24px -72px;}
|
|
||||||
.icon-adjust{background-position:-48px -72px;}
|
|
||||||
.icon-tint{background-position:-72px -72px;}
|
|
||||||
.icon-edit{background-position:-96px -72px;}
|
|
||||||
.icon-share{background-position:-120px -72px;}
|
|
||||||
.icon-check{background-position:-144px -72px;}
|
|
||||||
.icon-move{background-position:-168px -72px;}
|
|
||||||
.icon-step-backward{background-position:-192px -72px;}
|
|
||||||
.icon-fast-backward{background-position:-216px -72px;}
|
|
||||||
.icon-backward{background-position:-240px -72px;}
|
|
||||||
.icon-play{background-position:-264px -72px;}
|
|
||||||
.icon-pause{background-position:-288px -72px;}
|
|
||||||
.icon-stop{background-position:-312px -72px;}
|
|
||||||
.icon-forward{background-position:-336px -72px;}
|
|
||||||
.icon-fast-forward{background-position:-360px -72px;}
|
|
||||||
.icon-step-forward{background-position:-384px -72px;}
|
|
||||||
.icon-eject{background-position:-408px -72px;}
|
|
||||||
.icon-chevron-left{background-position:-432px -72px;}
|
|
||||||
.icon-chevron-right{background-position:-456px -72px;}
|
|
||||||
.icon-plus-sign{background-position:0 -96px;}
|
|
||||||
.icon-minus-sign{background-position:-24px -96px;}
|
|
||||||
.icon-remove-sign{background-position:-48px -96px;}
|
|
||||||
.icon-ok-sign{background-position:-72px -96px;}
|
|
||||||
.icon-question-sign{background-position:-96px -96px;}
|
|
||||||
.icon-info-sign{background-position:-120px -96px;}
|
|
||||||
.icon-screenshot{background-position:-144px -96px;}
|
|
||||||
.icon-remove-circle{background-position:-168px -96px;}
|
|
||||||
.icon-ok-circle{background-position:-192px -96px;}
|
|
||||||
.icon-ban-circle{background-position:-216px -96px;}
|
|
||||||
.icon-arrow-left{background-position:-240px -96px;}
|
|
||||||
.icon-arrow-right{background-position:-264px -96px;}
|
|
||||||
.icon-arrow-up{background-position:-289px -96px;}
|
|
||||||
.icon-arrow-down{background-position:-312px -96px;}
|
|
||||||
.icon-share-alt{background-position:-336px -96px;}
|
|
||||||
.icon-resize-full{background-position:-360px -96px;}
|
|
||||||
.icon-resize-small{background-position:-384px -96px;}
|
|
||||||
.icon-plus{background-position:-408px -96px;}
|
|
||||||
.icon-minus{background-position:-433px -96px;}
|
|
||||||
.icon-asterisk{background-position:-456px -96px;}
|
|
||||||
.icon-exclamation-sign{background-position:0 -120px;}
|
|
||||||
.icon-gift{background-position:-24px -120px;}
|
|
||||||
.icon-leaf{background-position:-48px -120px;}
|
|
||||||
.icon-fire{background-position:-72px -120px;}
|
|
||||||
.icon-eye-open{background-position:-96px -120px;}
|
|
||||||
.icon-eye-close{background-position:-120px -120px;}
|
|
||||||
.icon-warning-sign{background-position:-144px -120px;}
|
|
||||||
.icon-plane{background-position:-168px -120px;}
|
|
||||||
.icon-calendar{background-position:-192px -120px;}
|
|
||||||
.icon-random{background-position:-216px -120px;}
|
|
||||||
.icon-comment{background-position:-240px -120px;}
|
|
||||||
.icon-magnet{background-position:-264px -120px;}
|
|
||||||
.icon-chevron-up{background-position:-288px -120px;}
|
|
||||||
.icon-chevron-down{background-position:-313px -119px;}
|
|
||||||
.icon-retweet{background-position:-336px -120px;}
|
|
||||||
.icon-shopping-cart{background-position:-360px -120px;}
|
|
||||||
.icon-folder-close{background-position:-384px -120px;}
|
|
||||||
.icon-folder-open{background-position:-408px -120px;}
|
|
||||||
.icon-resize-vertical{background-position:-432px -119px;}
|
|
||||||
.icon-resize-horizontal{background-position:-456px -118px;}
|
|
||||||
.dropdown{position:relative;}
|
|
||||||
.dropdown-toggle{*margin-bottom:-3px;}
|
|
||||||
.dropdown-toggle:active,.open .dropdown-toggle{outline:0;}
|
|
||||||
.caret{display:inline-block;width:0;height:0;text-indent:-99999px;*text-indent:0;vertical-align:top;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #000000;opacity:0.3;filter:alpha(opacity=30);content:"\2193";}
|
|
||||||
.dropdown .caret{margin-top:8px;margin-left:2px;}
|
|
||||||
.dropdown:hover .caret,.open.dropdown .caret{opacity:1;filter:alpha(opacity=100);}
|
|
||||||
.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;float:left;display:none;min-width:160px;_width:160px;padding:4px 0;margin:0;list-style:none;background-color:#ffffff;border-color:#ccc;border-color:rgba(0, 0, 0, 0.2);border-style:solid;border-width:1px;-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;*border-right-width:2px;*border-bottom-width:2px;}.dropdown-menu.bottom-up{top:auto;bottom:100%;margin-bottom:2px;}
|
|
||||||
.dropdown-menu .divider{height:1px;margin:5px 1px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff;*width:100%;*margin:-5px 0 5px;}
|
|
||||||
.dropdown-menu a{display:block;padding:3px 15px;clear:both;font-weight:normal;line-height:18px;color:#555555;white-space:nowrap;}
|
|
||||||
.dropdown-menu li>a:hover,.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#ffffff;text-decoration:none;background-color:#0088cc;}
|
|
||||||
.dropdown.open{*z-index:1000;}.dropdown.open .dropdown-toggle{color:#ffffff;background:#ccc;background:rgba(0, 0, 0, 0.3);}
|
|
||||||
.dropdown.open .dropdown-menu{display:block;}
|
|
||||||
.typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
|
||||||
.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #eee;border:1px solid rgba(0, 0, 0, 0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);}
|
|
||||||
.fade{-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-ms-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;opacity:0;}.fade.in{opacity:1;}
|
|
||||||
.collapse{-webkit-transition:height 0.35s ease;-moz-transition:height 0.35s ease;-ms-transition:height 0.35s ease;-o-transition:height 0.35s ease;transition:height 0.35s ease;position:relative;overflow:hidden;height:0;}.collapse.in{height:auto;}
|
|
||||||
.close{float:right;font-size:20px;font-weight:bold;line-height:18px;color:#000000;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20);}.close:hover{color:#000000;text-decoration:none;opacity:0.4;filter:alpha(opacity=40);cursor:pointer;}
|
|
||||||
.btn{display:inline-block;padding:4px 10px 4px;margin-bottom:0;font-size:13px;line-height:18px;color:#333333;text-align:center;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);vertical-align:middle;background-color:#f5f5f5;background-image:-moz-linear-gradient(top, #ffffff, #e6e6e6);background-image:-ms-linear-gradient(top, #ffffff, #e6e6e6);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(top, #ffffff, #e6e6e6);background-image:-o-linear-gradient(top, #ffffff, #e6e6e6);background-image:linear-gradient(top, #ffffff, #e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid #ccc;border-bottom-color:#bbb;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);cursor:pointer;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);*margin-left:.3em;}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{background-color:#e6e6e6;}
|
|
||||||
.btn:active,.btn.active{background-color:#cccccc \9;}
|
|
||||||
.btn:first-child{*margin-left:0;}
|
|
||||||
.btn:hover{color:#333333;text-decoration:none;background-color:#e6e6e6;background-position:0 -15px;-webkit-transition:background-position 0.1s linear;-moz-transition:background-position 0.1s linear;-ms-transition:background-position 0.1s linear;-o-transition:background-position 0.1s linear;transition:background-position 0.1s linear;}
|
|
||||||
.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
|
|
||||||
.btn.active,.btn:active{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);background-color:#e6e6e6;background-color:#d9d9d9 \9;outline:0;}
|
|
||||||
.btn.disabled,.btn[disabled]{cursor:default;background-image:none;background-color:#e6e6e6;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
|
||||||
.btn-large{padding:9px 14px;font-size:15px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
|
|
||||||
.btn-large [class^="icon-"]{margin-top:1px;}
|
|
||||||
.btn-small{padding:5px 9px;font-size:11px;line-height:16px;}
|
|
||||||
.btn-small [class^="icon-"]{margin-top:-1px;}
|
|
||||||
.btn-mini{padding:2px 6px;font-size:11px;line-height:14px;}
|
|
||||||
.btn-primary,.btn-primary:hover,.btn-warning,.btn-warning:hover,.btn-danger,.btn-danger:hover,.btn-success,.btn-success:hover,.btn-info,.btn-info:hover,.btn-inverse,.btn-inverse:hover{text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);color:#ffffff;}
|
|
||||||
.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-dark.active{color:rgba(255, 255, 255, 0.75);}
|
|
||||||
.btn-primary{background-color:#006dcc;background-image:-moz-linear-gradient(top, #0088cc, #0044cc);background-image:-ms-linear-gradient(top, #0088cc, #0044cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));background-image:-webkit-linear-gradient(top, #0088cc, #0044cc);background-image:-o-linear-gradient(top, #0088cc, #0044cc);background-image:linear-gradient(top, #0088cc, #0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{background-color:#0044cc;}
|
|
||||||
.btn-primary:active,.btn-primary.active{background-color:#003399 \9;}
|
|
||||||
.btn-warning{background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-ms-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(top, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{background-color:#f89406;}
|
|
||||||
.btn-warning:active,.btn-warning.active{background-color:#c67605 \9;}
|
|
||||||
.btn-danger{background-color:#da4f49;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-ms-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(top, #ee5f5b, #bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{background-color:#bd362f;}
|
|
||||||
.btn-danger:active,.btn-danger.active{background-color:#942a25 \9;}
|
|
||||||
.btn-success{background-color:#5bb75b;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-ms-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(top, #62c462, #51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{background-color:#51a351;}
|
|
||||||
.btn-success:active,.btn-success.active{background-color:#408140 \9;}
|
|
||||||
.btn-info{background-color:#49afcd;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-ms-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(top, #5bc0de, #2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{background-color:#2f96b4;}
|
|
||||||
.btn-info:active,.btn-info.active{background-color:#24748c \9;}
|
|
||||||
.btn-inverse{background-color:#393939;background-image:-moz-linear-gradient(top, #454545, #262626);background-image:-ms-linear-gradient(top, #454545, #262626);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#454545), to(#262626));background-image:-webkit-linear-gradient(top, #454545, #262626);background-image:-o-linear-gradient(top, #454545, #262626);background-image:linear-gradient(top, #454545, #262626);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#454545', endColorstr='#262626', GradientType=0);border-color:#262626 #262626 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{background-color:#262626;}
|
|
||||||
.btn-inverse:active,.btn-inverse.active{background-color:#0c0c0c \9;}
|
|
||||||
button.btn,input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;}
|
|
||||||
button.btn.large,input[type="submit"].btn.large{*padding-top:7px;*padding-bottom:7px;}
|
|
||||||
button.btn.small,input[type="submit"].btn.small{*padding-top:3px;*padding-bottom:3px;}
|
|
||||||
.btn-group{position:relative;*zoom:1;*margin-left:.3em;}.btn-group:before,.btn-group:after{display:table;content:"";}
|
|
||||||
.btn-group:after{clear:both;}
|
|
||||||
.btn-group:first-child{*margin-left:0;}
|
|
||||||
.btn-group+.btn-group{margin-left:5px;}
|
|
||||||
.btn-toolbar{margin-top:9px;margin-bottom:9px;}.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1;}
|
|
||||||
.btn-group .btn{position:relative;float:left;margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.btn-group .btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
|
|
||||||
.btn-group .btn:last-child,.btn-group .dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;}
|
|
||||||
.btn-group .btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;}
|
|
||||||
.btn-group .btn.large:last-child,.btn-group .large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;}
|
|
||||||
.btn-group .btn:hover,.btn-group .btn:focus,.btn-group .btn:active,.btn-group .btn.active{z-index:2;}
|
|
||||||
.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;}
|
|
||||||
.btn-group .dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);*padding-top:5px;*padding-bottom:5px;}
|
|
||||||
.btn-group.open{*z-index:1000;}.btn-group.open .dropdown-menu{display:block;margin-top:1px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
|
|
||||||
.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);}
|
|
||||||
.btn .caret{margin-top:7px;margin-left:0;}
|
|
||||||
.btn:hover .caret,.open.btn-group .caret{opacity:1;filter:alpha(opacity=100);}
|
|
||||||
.btn-primary .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#ffffff;opacity:0.75;filter:alpha(opacity=75);}
|
|
||||||
.btn-small .caret{margin-top:4px;}
|
|
||||||
.alert{padding:8px 35px 8px 14px;margin-bottom:18px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
|
||||||
.alert,.alert-heading{color:#c09853;}
|
|
||||||
.alert .close{position:relative;top:-2px;right:-21px;line-height:18px;}
|
|
||||||
.alert-success{background-color:#dff0d8;border-color:#d6e9c6;}
|
|
||||||
.alert-success,.alert-success .alert-heading{color:#468847;}
|
|
||||||
.alert-danger,.alert-error{background-color:#f2dede;border-color:#eed3d7;}
|
|
||||||
.alert-danger,.alert-error,.alert-danger .alert-heading,.alert-error .alert-heading{color:#b94a48;}
|
|
||||||
.alert-info{background-color:#d9edf7;border-color:#bce8f1;}
|
|
||||||
.alert-info,.alert-info .alert-heading{color:#3a87ad;}
|
|
||||||
.alert-block{padding-top:14px;padding-bottom:14px;}
|
|
||||||
.alert-block>p,.alert-block>ul{margin-bottom:0;}
|
|
||||||
.alert-block p+p{margin-top:5px;}
|
|
||||||
.nav{margin-left:0;margin-bottom:18px;list-style:none;}
|
|
||||||
.nav>li>a{display:block;}
|
|
||||||
.nav>li>a:hover{text-decoration:none;background-color:#eeeeee;}
|
|
||||||
.nav .nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:18px;color:#999999;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);text-transform:uppercase;}
|
|
||||||
.nav li+.nav-header{margin-top:9px;}
|
|
||||||
.nav-list{padding-left:14px;padding-right:14px;margin-bottom:0;}
|
|
||||||
.nav-list>li>a,.nav-list .nav-header{margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);}
|
|
||||||
.nav-list>li>a{padding:3px 15px;}
|
|
||||||
.nav-list .active>a,.nav-list .active>a:hover{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.2);background-color:#0088cc;}
|
|
||||||
.nav-list [class^="icon-"]{margin-right:2px;}
|
|
||||||
.nav-tabs,.nav-pills{*zoom:1;}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:"";}
|
|
||||||
.nav-tabs:after,.nav-pills:after{clear:both;}
|
|
||||||
.nav-tabs>li,.nav-pills>li{float:left;}
|
|
||||||
.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px;}
|
|
||||||
.nav-tabs{border-bottom:1px solid #ddd;}
|
|
||||||
.nav-tabs>li{margin-bottom:-1px;}
|
|
||||||
.nav-tabs>li>a{padding-top:9px;padding-bottom:9px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd;}
|
|
||||||
.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555555;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;}
|
|
||||||
.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
|
|
||||||
.nav-pills .active>a,.nav-pills .active>a:hover{color:#ffffff;background-color:#0088cc;}
|
|
||||||
.nav-stacked>li{float:none;}
|
|
||||||
.nav-stacked>li>a{margin-right:0;}
|
|
||||||
.nav-tabs.nav-stacked{border-bottom:0;}
|
|
||||||
.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}
|
|
||||||
.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}
|
|
||||||
.nav-tabs.nav-stacked>li>a:hover{border-color:#ddd;z-index:2;}
|
|
||||||
.nav-pills.nav-stacked>li>a{margin-bottom:3px;}
|
|
||||||
.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px;}
|
|
||||||
.nav-tabs .dropdown-menu,.nav-pills .dropdown-menu{margin-top:1px;border-width:1px;}
|
|
||||||
.nav-pills .dropdown-menu{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
|
||||||
.nav-tabs .dropdown-toggle .caret,.nav-pills .dropdown-toggle .caret{border-top-color:#0088cc;margin-top:6px;}
|
|
||||||
.nav-tabs .dropdown-toggle:hover .caret,.nav-pills .dropdown-toggle:hover .caret{border-top-color:#005580;}
|
|
||||||
.nav-tabs .active .dropdown-toggle .caret,.nav-pills .active .dropdown-toggle .caret{border-top-color:#333333;}
|
|
||||||
.nav>.dropdown.active>a:hover{color:#000000;cursor:pointer;}
|
|
||||||
.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>.open.active>a:hover{color:#ffffff;background-color:#999999;border-color:#999999;}
|
|
||||||
.nav .open .caret,.nav .open.active .caret,.nav .open a:hover .caret{border-top-color:#ffffff;opacity:1;filter:alpha(opacity=100);}
|
|
||||||
.tabs-stacked .open>a:hover{border-color:#999999;}
|
|
||||||
.tabbable{*zoom:1;}.tabbable:before,.tabbable:after{display:table;content:"";}
|
|
||||||
.tabbable:after{clear:both;}
|
|
||||||
.tab-content{overflow:hidden;}
|
|
||||||
.tabs-below .nav-tabs,.tabs-right .nav-tabs,.tabs-left .nav-tabs{border-bottom:0;}
|
|
||||||
.tab-content>.tab-pane,.pill-content>.pill-pane{display:none;}
|
|
||||||
.tab-content>.active,.pill-content>.active{display:block;}
|
|
||||||
.tabs-below .nav-tabs{border-top:1px solid #ddd;}
|
|
||||||
.tabs-below .nav-tabs>li{margin-top:-1px;margin-bottom:0;}
|
|
||||||
.tabs-below .nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.tabs-below .nav-tabs>li>a:hover{border-bottom-color:transparent;border-top-color:#ddd;}
|
|
||||||
.tabs-below .nav-tabs .active>a,.tabs-below .nav-tabs .active>a:hover{border-color:transparent #ddd #ddd #ddd;}
|
|
||||||
.tabs-left .nav-tabs>li,.tabs-right .nav-tabs>li{float:none;}
|
|
||||||
.tabs-left .nav-tabs>li>a,.tabs-right .nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px;}
|
|
||||||
.tabs-left .nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd;}
|
|
||||||
.tabs-left .nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;}
|
|
||||||
.tabs-left .nav-tabs>li>a:hover{border-color:#eeeeee #dddddd #eeeeee #eeeeee;}
|
|
||||||
.tabs-left .nav-tabs .active>a,.tabs-left .nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#ffffff;}
|
|
||||||
.tabs-right .nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd;}
|
|
||||||
.tabs-right .nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}
|
|
||||||
.tabs-right .nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #eeeeee #dddddd;}
|
|
||||||
.tabs-right .nav-tabs .active>a,.tabs-right .nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#ffffff;}
|
|
||||||
.navbar{overflow:visible;margin-bottom:18px;}
|
|
||||||
.navbar-inner{padding-left:20px;padding-right:20px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);}
|
|
||||||
.btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);border-color:#222222 #222222 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);}.btn-navbar:hover,.btn-navbar:active,.btn-navbar.active,.btn-navbar.disabled,.btn-navbar[disabled]{background-color:#222222;}
|
|
||||||
.btn-navbar:active,.btn-navbar.active{background-color:#080808 \9;}
|
|
||||||
.btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);-moz-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);}
|
|
||||||
.btn-navbar .icon-bar+.icon-bar{margin-top:3px;}
|
|
||||||
.nav-collapse.collapse{height:auto;}
|
|
||||||
.navbar .brand:hover{text-decoration:none;}
|
|
||||||
.navbar .brand{float:left;display:block;padding:8px 20px 12px;margin-left:-20px;font-size:20px;font-weight:200;line-height:1;color:#ffffff;}
|
|
||||||
.navbar .navbar-text{margin-bottom:0;line-height:40px;color:#999999;}.navbar .navbar-text a:hover{color:#ffffff;background-color:transparent;}
|
|
||||||
.navbar .btn,.navbar .btn-group{margin-top:5px;}
|
|
||||||
.navbar .btn-group .btn{margin-top:0;}
|
|
||||||
.navbar-form{margin-bottom:0;*zoom:1;}.navbar-form:before,.navbar-form:after{display:table;content:"";}
|
|
||||||
.navbar-form:after{clear:both;}
|
|
||||||
.navbar-form input,.navbar-form select{display:inline-block;margin-top:5px;margin-bottom:0;}
|
|
||||||
.navbar-form .radio,.navbar-form .checkbox{margin-top:5px;}
|
|
||||||
.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px;}
|
|
||||||
.navbar-form .input-append,.navbar-form .input-prepend{margin-top:6px;white-space:nowrap;}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0;}
|
|
||||||
.navbar-search{position:relative;float:left;margin-top:6px;margin-bottom:0;}.navbar-search .search-query{padding:4px 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;color:#ffffff;color:rgba(255, 255, 255, 0.75);background:#666;background:rgba(255, 255, 255, 0.3);border:1px solid #111;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none;}.navbar-search .search-query :-moz-placeholder{color:#eeeeee;}
|
|
||||||
.navbar-search .search-query::-webkit-input-placeholder{color:#eeeeee;}
|
|
||||||
.navbar-search .search-query:hover{color:#ffffff;background-color:#999999;background-color:rgba(255, 255, 255, 0.5);}
|
|
||||||
.navbar-search .search-query:focus,.navbar-search .search-query.focused{padding:5px 10px;color:#333333;text-shadow:0 1px 0 #ffffff;background-color:#ffffff;border:0;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);outline:0;}
|
|
||||||
.navbar-fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030;}
|
|
||||||
.navbar-fixed-top .navbar-inner{padding-left:0;padding-right:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0;}
|
|
||||||
.navbar .nav.pull-right{float:right;}
|
|
||||||
.navbar .nav>li{display:block;float:left;}
|
|
||||||
.navbar .nav>li>a{float:none;padding:10px 10px 11px;line-height:19px;color:#999999;text-decoration:none;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);}
|
|
||||||
.navbar .nav>li>a:hover{background-color:transparent;color:#ffffff;text-decoration:none;}
|
|
||||||
.navbar .nav .active>a,.navbar .nav .active>a:hover{color:#ffffff;text-decoration:none;background-color:#222222;}
|
|
||||||
.navbar .divider-vertical{height:40px;width:1px;margin:0 9px;overflow:hidden;background-color:#222222;border-right:1px solid #333333;}
|
|
||||||
.navbar .nav.pull-right{margin-left:10px;margin-right:0;}
|
|
||||||
.navbar .dropdown-menu{margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.navbar .dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0, 0, 0, 0.2);position:absolute;top:-7px;left:9px;}
|
|
||||||
.navbar .dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:10px;}
|
|
||||||
.navbar .nav .dropdown-toggle .caret,.navbar .nav .open.dropdown .caret{border-top-color:#ffffff;}
|
|
||||||
.navbar .nav .active .caret{opacity:1;filter:alpha(opacity=100);}
|
|
||||||
.navbar .nav .open>.dropdown-toggle,.navbar .nav .active>.dropdown-toggle,.navbar .nav .open.active>.dropdown-toggle{background-color:transparent;}
|
|
||||||
.navbar .nav .active>.dropdown-toggle:hover{color:#ffffff;}
|
|
||||||
.navbar .nav.pull-right .dropdown-menu{left:auto;right:0;}.navbar .nav.pull-right .dropdown-menu:before{left:auto;right:12px;}
|
|
||||||
.navbar .nav.pull-right .dropdown-menu:after{left:auto;right:13px;}
|
|
||||||
.breadcrumb{padding:7px 14px;margin:0 0 18px;background-color:#fbfbfb;background-image:-moz-linear-gradient(top, #ffffff, #f5f5f5);background-image:-ms-linear-gradient(top, #ffffff, #f5f5f5);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5));background-image:-webkit-linear-gradient(top, #ffffff, #f5f5f5);background-image:-o-linear-gradient(top, #ffffff, #f5f5f5);background-image:linear-gradient(top, #ffffff, #f5f5f5);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;}.breadcrumb li{display:inline-block;text-shadow:0 1px 0 #ffffff;}
|
|
||||||
.breadcrumb .divider{padding:0 5px;color:#999999;}
|
|
||||||
.breadcrumb .active a{color:#333333;}
|
|
||||||
.pagination{height:36px;margin:18px 0;}
|
|
||||||
.pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);}
|
|
||||||
.pagination li{display:inline;}
|
|
||||||
.pagination a{float:left;padding:0 14px;line-height:34px;text-decoration:none;border:1px solid #ddd;border-left-width:0;}
|
|
||||||
.pagination a:hover,.pagination .active a{background-color:#f5f5f5;}
|
|
||||||
.pagination .active a{color:#999999;cursor:default;}
|
|
||||||
.pagination .disabled a,.pagination .disabled a:hover{color:#999999;background-color:transparent;cursor:default;}
|
|
||||||
.pagination li:first-child a{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
|
|
||||||
.pagination li:last-child a{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
|
|
||||||
.pagination-centered{text-align:center;}
|
|
||||||
.pagination-right{text-align:right;}
|
|
||||||
.pager{margin-left:0;margin-bottom:18px;list-style:none;text-align:center;*zoom:1;}.pager:before,.pager:after{display:table;content:"";}
|
|
||||||
.pager:after{clear:both;}
|
|
||||||
.pager li{display:inline;}
|
|
||||||
.pager a{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
|
|
||||||
.pager a:hover{text-decoration:none;background-color:#f5f5f5;}
|
|
||||||
.pager .next a{float:right;}
|
|
||||||
.pager .previous a{float:left;}
|
|
||||||
.modal-open .dropdown-menu{z-index:2050;}
|
|
||||||
.modal-open .dropdown.open{*z-index:2050;}
|
|
||||||
.modal-open .popover{z-index:2060;}
|
|
||||||
.modal-open .tooltip{z-index:2070;}
|
|
||||||
.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000;}.modal-backdrop.fade{opacity:0;}
|
|
||||||
.modal-backdrop,.modal-backdrop.fade.in{opacity:0.8;filter:alpha(opacity=80);}
|
|
||||||
.modal{position:fixed;top:50%;left:50%;z-index:1050;max-height:500px;overflow:auto;width:560px;margin:-250px 0 0 -280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-ms-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;}
|
|
||||||
.modal.fade.in{top:50%;}
|
|
||||||
.modal-header{padding:9px 15px;border-bottom:1px solid #eee;}.modal-header .close{margin-top:2px;}
|
|
||||||
.modal-body{padding:15px;}
|
|
||||||
.modal-body .modal-form{margin-bottom:0;}
|
|
||||||
.modal-footer{padding:14px 15px 15px;margin-bottom:0;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;*zoom:1;}.modal-footer:before,.modal-footer:after{display:table;content:"";}
|
|
||||||
.modal-footer:after{clear:both;}
|
|
||||||
.modal-footer .btn{float:right;margin-left:5px;margin-bottom:0;}
|
|
||||||
.tooltip{position:absolute;z-index:1020;display:block;visibility:visible;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:0.8;filter:alpha(opacity=80);}
|
|
||||||
.tooltip.top{margin-top:-2px;}
|
|
||||||
.tooltip.right{margin-left:2px;}
|
|
||||||
.tooltip.bottom{margin-top:2px;}
|
|
||||||
.tooltip.left{margin-left:-2px;}
|
|
||||||
.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
|
|
||||||
.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
|
|
||||||
.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
|
|
||||||
.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
|
|
||||||
.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
|
||||||
.tooltip-arrow{position:absolute;width:0;height:0;}
|
|
||||||
.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px;}.popover.top{margin-top:-5px;}
|
|
||||||
.popover.right{margin-left:5px;}
|
|
||||||
.popover.bottom{margin-top:5px;}
|
|
||||||
.popover.left{margin-left:-5px;}
|
|
||||||
.popover.top .arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
|
|
||||||
.popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
|
|
||||||
.popover.bottom .arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
|
|
||||||
.popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
|
|
||||||
.popover .arrow{position:absolute;width:0;height:0;}
|
|
||||||
.popover-inner{padding:3px;width:280px;overflow:hidden;background:#000000;background:rgba(0, 0, 0, 0.8);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);}
|
|
||||||
.popover-title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;}
|
|
||||||
.popover-content{padding:14px;background-color:#ffffff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0;}
|
|
||||||
.thumbnails{margin-left:-20px;list-style:none;*zoom:1;}.thumbnails:before,.thumbnails:after{display:table;content:"";}
|
|
||||||
.thumbnails:after{clear:both;}
|
|
||||||
.thumbnails>li{float:left;margin:0 0 18px 20px;}
|
|
||||||
.thumbnail{display:block;padding:4px;line-height:1;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);}
|
|
||||||
a.thumbnail:hover{border-color:#0088cc;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);}
|
|
||||||
.thumbnail>img{display:block;max-width:100%;margin-left:auto;margin-right:auto;}
|
|
||||||
.thumbnail .caption{padding:9px;}
|
|
||||||
.label{padding:2px 4px 3px;font-size:11.049999999999999px;font-weight:bold;color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
|
|
||||||
.label:hover{color:#ffffff;text-decoration:none;}
|
|
||||||
.label-important{background-color:#b94a48;}
|
|
||||||
.label-important:hover{background-color:#953b39;}
|
|
||||||
.label-warning{background-color:#f89406;}
|
|
||||||
.label-warning:hover{background-color:#c67605;}
|
|
||||||
.label-success{background-color:#468847;}
|
|
||||||
.label-success:hover{background-color:#356635;}
|
|
||||||
.label-info{background-color:#3a87ad;}
|
|
||||||
.label-info:hover{background-color:#2d6987;}
|
|
||||||
@-webkit-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@-moz-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}.progress{overflow:hidden;height:18px;margin-bottom:18px;background-color:#f7f7f7;background-image:-moz-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-ms-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));background-image:-webkit-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-o-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:linear-gradient(top, #f5f5f5, #f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
|
||||||
.progress .bar{width:0%;height:18px;color:#ffffff;font-size:12px;text-align:center;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top, #149bdf, #0480be);background-image:-ms-linear-gradient(top, #149bdf, #0480be);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));background-image:-webkit-linear-gradient(top, #149bdf, #0480be);background-image:-o-linear-gradient(top, #149bdf, #0480be);background-image:linear-gradient(top, #149bdf, #0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width 0.6s ease;-moz-transition:width 0.6s ease;-ms-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease;}
|
|
||||||
.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px;}
|
|
||||||
.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite;}
|
|
||||||
.progress-danger .bar{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-ms-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(top, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);}
|
|
||||||
.progress-danger.progress-striped .bar{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
|
|
||||||
.progress-success .bar{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-ms-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(top, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);}
|
|
||||||
.progress-success.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
|
|
||||||
.progress-info .bar{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-ms-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(top, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);}
|
|
||||||
.progress-info.progress-striped .bar{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
|
|
||||||
.accordion{margin-bottom:18px;}
|
|
||||||
.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
|
||||||
.accordion-heading{border-bottom:0;}
|
|
||||||
.accordion-heading .accordion-toggle{display:block;padding:8px 15px;}
|
|
||||||
.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5;}
|
|
||||||
.carousel{position:relative;margin-bottom:18px;line-height:1;}
|
|
||||||
.carousel-inner{overflow:hidden;width:100%;position:relative;}
|
|
||||||
.carousel .item{display:none;position:relative;-webkit-transition:0.6s ease-in-out left;-moz-transition:0.6s ease-in-out left;-ms-transition:0.6s ease-in-out left;-o-transition:0.6s ease-in-out left;transition:0.6s ease-in-out left;}
|
|
||||||
.carousel .item>img{display:block;line-height:1;}
|
|
||||||
.carousel .active,.carousel .next,.carousel .prev{display:block;}
|
|
||||||
.carousel .active{left:0;}
|
|
||||||
.carousel .next,.carousel .prev{position:absolute;top:0;width:100%;}
|
|
||||||
.carousel .next{left:100%;}
|
|
||||||
.carousel .prev{left:-100%;}
|
|
||||||
.carousel .next.left,.carousel .prev.right{left:0;}
|
|
||||||
.carousel .active.left{left:-100%;}
|
|
||||||
.carousel .active.right{left:100%;}
|
|
||||||
.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#ffffff;text-align:center;background:#222222;border:3px solid #ffffff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:0.5;filter:alpha(opacity=50);}.carousel-control.right{left:auto;right:15px;}
|
|
||||||
.carousel-control:hover{color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90);}
|
|
||||||
.carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:10px 15px 5px;background:#333333;background:rgba(0, 0, 0, 0.75);}
|
|
||||||
.carousel-caption h4,.carousel-caption p{color:#ffffff;}
|
|
||||||
.hero-unit{padding:60px;margin-bottom:30px;background-color:#f5f5f5;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;}
|
|
||||||
.hero-unit p{font-size:18px;font-weight:200;line-height:27px;}
|
|
||||||
.pull-right{float:right;}
|
|
||||||
.pull-left{float:left;}
|
|
||||||
.hide{display:none;}
|
|
||||||
.show{display:block;}
|
|
||||||
.invisible{visibility:hidden;}
|
|
|
@ -1,55 +0,0 @@
|
||||||
body.simple
|
|
||||||
margin-top: 20px
|
|
||||||
margin-bottom: 20px
|
|
||||||
|
|
||||||
#footer-simple
|
|
||||||
text-align: center
|
|
||||||
|
|
||||||
.top-pix18
|
|
||||||
margin-top: 18px
|
|
||||||
|
|
||||||
body.application
|
|
||||||
margin-top: 10px
|
|
||||||
margin-bottom: 10px
|
|
||||||
|
|
||||||
#sidebar
|
|
||||||
.logo
|
|
||||||
img
|
|
||||||
margin-bottom: 10px
|
|
||||||
|
|
||||||
p.version
|
|
||||||
text-align: center
|
|
||||||
|
|
||||||
tr.unseen
|
|
||||||
font-weight: bold
|
|
||||||
|
|
||||||
.bottom-pix18
|
|
||||||
margin-bottom: 18px
|
|
||||||
|
|
||||||
table.header
|
|
||||||
td.field_name
|
|
||||||
text-align: right
|
|
||||||
font-weight: bold
|
|
||||||
padding-right: 10px
|
|
||||||
|
|
||||||
p.help-block
|
|
||||||
font-size: 10px
|
|
||||||
|
|
||||||
.custom_pagination
|
|
||||||
text-align: right
|
|
||||||
a,span,em
|
|
||||||
line-height: 18px
|
|
||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05)
|
|
||||||
margin-bottom: 0
|
|
||||||
margin-left: 0
|
|
||||||
border: 1px solid #DDDDDD
|
|
||||||
padding: 3px
|
|
||||||
|
|
||||||
table.records
|
|
||||||
font-size: 12px
|
|
||||||
td
|
|
||||||
padding: 4px
|
|
||||||
|
|
||||||
iframe
|
|
||||||
width: 700px
|
|
||||||
height: 800px
|
|
|
@ -1,53 +0,0 @@
|
||||||
$blue: #0088CC
|
|
||||||
$outline: #DDDDDD
|
|
||||||
$month: #0044CC
|
|
||||||
$outside: #DDDDDD
|
|
||||||
$today: #DA4F49
|
|
||||||
|
|
||||||
.calendar
|
|
||||||
margin-bottom: 18px
|
|
||||||
h3
|
|
||||||
color: $month
|
|
||||||
table
|
|
||||||
width: 100%
|
|
||||||
border: 1px solid $outline
|
|
||||||
border-collapse: separate
|
|
||||||
border-radius: 4px 4px 4px 4px
|
|
||||||
td
|
|
||||||
text-align: right
|
|
||||||
margin: 2px
|
|
||||||
padding: 2px
|
|
||||||
border-top: 1px solid $outline
|
|
||||||
border-left: 1px solid $outline
|
|
||||||
td.wday
|
|
||||||
color: $blue
|
|
||||||
font-weight: bold
|
|
||||||
text-align: center
|
|
||||||
td.corner
|
|
||||||
border-top: 0 none
|
|
||||||
border-left: 0 none
|
|
||||||
td.weekend
|
|
||||||
background-color: $outline
|
|
||||||
td.outside
|
|
||||||
background-color: white
|
|
||||||
color: $outside
|
|
||||||
td.today
|
|
||||||
background-color: $today
|
|
||||||
color: white
|
|
||||||
font-weight: bold
|
|
||||||
td.weeknum
|
|
||||||
color: $blue
|
|
||||||
font-weight: bold
|
|
||||||
text-align: center
|
|
||||||
|
|
||||||
.calendar.square
|
|
||||||
td.wday
|
|
||||||
border-top: 0 none
|
|
||||||
td.weeknum
|
|
||||||
border-left: 0 none
|
|
||||||
|
|
||||||
.calendar.window
|
|
||||||
td.monthnum
|
|
||||||
border-top: 0 none
|
|
||||||
tr > td:first-child
|
|
||||||
border-left: 0 none
|
|
248
app/controllers/application_controller.rb
Executable file → Normal file
248
app/controllers/application_controller.rb
Executable file → Normal file
|
@ -1,95 +1,175 @@
|
||||||
require 'yaml'
|
# 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
|
class ApplicationController < ActionController::Base
|
||||||
|
before_filter :user_login_filter
|
||||||
|
before_filter :add_scripts
|
||||||
|
#before_filter :localize
|
||||||
|
|
||||||
|
|
||||||
#logger.custom("session",session.inspect)
|
filter_parameter_logging :password
|
||||||
#protect_from_forgery
|
protected
|
||||||
|
def secure_user?() true end
|
||||||
before_filter :load_settings,:current_user,:set_locale
|
def secure_cust?() false end
|
||||||
#before_filter :plugins_configuration
|
def additional_scripts() "" end
|
||||||
|
def onload_function() "" end
|
||||||
def load_settings
|
|
||||||
$defaults ||= YAML::load(File.open(Rails.root.join('config','settings.yml')))
|
private
|
||||||
end
|
def add_scripts
|
||||||
|
@additional_scripts = additional_scripts()
|
||||||
################################# protected section ###########################################
|
@onload_function = onload_function()
|
||||||
|
end
|
||||||
protected
|
|
||||||
|
def user_login_filter
|
||||||
def theme_resolver
|
if (secure_user? or secure_cust? )and logged_user.nil?
|
||||||
if @current_user.nil?
|
session["return_to"] = request.request_uri
|
||||||
$defaults['theme']
|
redirect_to :controller=>"/login", :action => "index"
|
||||||
else
|
return false
|
||||||
@current_user.prefs.theme || $defaults['theme']
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
alias login_required user_login_filter
|
||||||
def set_locale
|
|
||||||
if @current_user.nil?
|
def logged_user # returns customer id
|
||||||
I18n.locale = $defaults['locale'] || I18n.default_locale
|
session['user']
|
||||||
else
|
|
||||||
I18n.locale = @current_user.prefs.locale.to_sym || I18n.default_locale
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def current_user
|
|
||||||
@current_user ||= User.find(session[:user_id]) if session[:user_id]
|
|
||||||
logger.custom("current_user",@current_user.inspect)
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_current_user
|
|
||||||
if @current_user.nil?
|
|
||||||
session["return_to"] = request.fullpath
|
|
||||||
redirect_to :controller => 'user', :action => 'login'
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def selected_folder
|
|
||||||
if session[:selected_folder]
|
|
||||||
@selected_folder = session[:selected_folder]
|
|
||||||
else
|
|
||||||
folder = @current_user.folders.inbox.first
|
|
||||||
if not folder.nil?
|
|
||||||
@selected_folder = folder.full_name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_current_folders
|
|
||||||
@folders_shown = @current_user.folders.shown.order("name asc")
|
|
||||||
if not @selected_folder.nil?
|
|
||||||
@current_folder = @current_user.folders.find_by_full_name(@selected_folder)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def prepare_compose_buttons
|
|
||||||
@buttons = []
|
|
||||||
@buttons << {:text => 'sendout',:scope=>:compose,:image => 'email.png'}
|
|
||||||
@buttons << {:text => 'save',:scope=>:compose,:image => 'save.png'}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_message_with_params
|
def logged_customer
|
||||||
@message = Message.new(params[:message])
|
session['user']
|
||||||
# if params[:message]
|
end
|
||||||
# @message.update_attributes(params[:message])
|
|
||||||
# end
|
def localize
|
||||||
files = Dir.glob(File.join($defaults["msg_upload_dir"],@current_user.username + "*"))
|
# We will use instance vars for the locale so we can make use of them in
|
||||||
@attachments = []
|
# the templates.
|
||||||
files.each do |f|
|
@charset = 'utf-8'
|
||||||
@attachments << {:name => File.basename(f).gsub!(/#{@current_user.username}_/,"") , :size => File.stat(f).size }
|
headers['Content-Type'] = "text/html; charset=#{@charset}"
|
||||||
end
|
# 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
|
end
|
||||||
|
|
||||||
def get_system_folders
|
public
|
||||||
@drafts_folder = @current_user.folders.drafts.first
|
|
||||||
@sent_folder = @current_user.folders.sent.first
|
def include_tinymce(mode="textareas",elements="")
|
||||||
@inbox_folder = @current_user.folders.inbox.first
|
tinymce=''
|
||||||
@trash_folder = @current_user.folders.trash.first
|
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
|
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
|
||||||
|
|
||||||
##################################### private section ##########################################
|
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
|
||||||
|
|
||||||
|
def _(text)
|
||||||
|
t text
|
||||||
|
end
|
||||||
|
|
||||||
|
helper_method :include_simple_tinymce, :_
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
52
app/controllers/contact_groups_controller.rb
Normal file
52
app/controllers/contact_groups_controller.rb
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
class ContactGroupsController < ApplicationController
|
||||||
|
layout 'public'
|
||||||
|
|
||||||
|
def index
|
||||||
|
@contact_group = ContactGroup.new
|
||||||
|
@contact_group.customer_id = logged_user
|
||||||
|
@contactgroups = ContactGroup.find_by_user(logged_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add
|
||||||
|
@contactgroup = ContactGroup.new
|
||||||
|
@contactgroup.customer_id = logged_user
|
||||||
|
render("/contact_group/edit")
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete
|
||||||
|
contactgroup = ContactGroup.find(@params["id"])
|
||||||
|
contactgroup.destroy
|
||||||
|
redirect_to(:action=>"list")
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@contactgroup = ContactGroup.find(@params["id"])
|
||||||
|
end
|
||||||
|
|
||||||
|
def save
|
||||||
|
begin
|
||||||
|
if @params["contactgroup"]["id"].nil? or @params["contactgroup"]["id"] == ""
|
||||||
|
# New contactgroup
|
||||||
|
@contactgroup = ContactGroup.create(@params["contactgroup"])
|
||||||
|
else
|
||||||
|
# Edit existing
|
||||||
|
@contactgroup = ContactGroup.find(@params["contactgroup"]["id"])
|
||||||
|
@contactgroup.attributes = @params["contactgroup"]
|
||||||
|
end
|
||||||
|
|
||||||
|
if @contactgroup.save
|
||||||
|
redirect_to(:action=>"list")
|
||||||
|
else
|
||||||
|
render "/contact_group/edit"
|
||||||
|
end
|
||||||
|
rescue CDF::ValidationError => e
|
||||||
|
logger.info("RESCUE")
|
||||||
|
@contactgroup = e.entity
|
||||||
|
render("/contact_group/edit")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
def secure_user?() true end
|
||||||
|
|
||||||
|
end
|
484
app/controllers/contacts_controller.rb
Executable file → Normal file
484
app/controllers/contacts_controller.rb
Executable file → Normal file
|
@ -1,109 +1,375 @@
|
||||||
require 'tempfile'
|
class ContactsController < ApplicationController
|
||||||
|
layout :select_layout
|
||||||
class ContactsController < ApplicationController
|
|
||||||
|
def index
|
||||||
before_filter :check_current_user,:selected_folder, :get_current_folders
|
if params[:letter] && params[:letter].any?
|
||||||
|
@contacts = Contact.for_customer(logged_user).letter(params[:letter]).paginate :page => params[:page],
|
||||||
before_filter :get_contacts, :only => [:index]
|
:per_page => CDF::CONFIG[:contacts_per_page]
|
||||||
|
else
|
||||||
def index
|
@contacts = Contact.for_customer(logged_user).paginate :page => params[:page], :per_page => CDF::CONFIG[:contacts_per_page]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#problem http://binary10ve.blogspot.com/2011/05/migrating-to-rails-3-got-stuck-with.html
|
def listLetter
|
||||||
#def destroy
|
letters = CDF::CONFIG[:contact_letters]
|
||||||
# @current_user.contacts.find(params[:id]).destroy
|
@contact_pages = Paginator.new(self, Contact.count(
|
||||||
# redirect_to(contacts_path)
|
["customer_id = %s and substr(UPPER(fname),1,1) = '%s'", logged_user, letters[params['id'].to_i]]), CDF::CONFIG[:contacts_per_page], params['page'])
|
||||||
#end
|
@contacts = Contact.find(:all, :conditions=>["customer_id = %s and substr(UPPER(fname),1,1) = '%s'", logged_user, letters[params['id'].to_i]],
|
||||||
|
:order=>['fname'], :limit=>CDF::CONFIG[:contacts_per_page], :offset=>@contact_pages.current.offset)
|
||||||
def new
|
|
||||||
@contact = Contact.new
|
if params["mode"] == "groups"
|
||||||
end
|
if params["group_id"] and not params["group_id"].nil? and not params["group_id"] == ''
|
||||||
|
@group_id = params["group_id"].to_i
|
||||||
def edit
|
@contacts_for_group = Hash.new
|
||||||
@contact = @current_user.contacts.find(params[:id])
|
for contact in @contacts
|
||||||
render 'edit'
|
@contacts_for_group[contact.id] = 0 # initialize
|
||||||
end
|
for gr in contact.groups
|
||||||
|
if gr.contact_group_id.to_i == @group_id
|
||||||
def create
|
@contacts_for_group[contact.id] = 1 # checked
|
||||||
if params["compose_to_selected"]
|
end
|
||||||
if params["items_ids"]
|
end
|
||||||
redirect_to compose_path(:cids => params["items_ids"])
|
end
|
||||||
return
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
if params["delete_selected"]
|
render :action => "list"
|
||||||
if params["items_ids"]
|
end
|
||||||
params["items_ids"].each do |id|
|
|
||||||
@current_user.contacts.find_by_id(id).destroy
|
def new
|
||||||
end
|
@contact = Contact.new
|
||||||
end
|
@contact.customer_id = logged_user
|
||||||
redirect_to(contacts_path)
|
|
||||||
return
|
# load related lists
|
||||||
end
|
loadLists
|
||||||
@contact = @current_user.contacts.build(params[:contact])
|
|
||||||
if @contact.valid?
|
# Init groups: because of checkbox
|
||||||
@contact.save
|
# Set all to 0 => unchecked
|
||||||
flash[:success] = t(:was_created,:scope=>:contact)
|
@groups = Hash.new
|
||||||
redirect_to(contacts_path)
|
@contactgroups.each {|g|
|
||||||
else
|
@groups[g.id] = 0
|
||||||
render 'new'
|
}
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
def add_multiple
|
||||||
def update
|
@contact = Contact.new
|
||||||
@contact = @current_user.contacts.find(params[:id])
|
@contact["file_type"] = "1"
|
||||||
if @contact.update_attributes(params[:contact])
|
end
|
||||||
redirect_to(contacts_path)
|
|
||||||
else
|
def add_from_mail
|
||||||
render 'edit'
|
cstr = params['cstr']
|
||||||
end
|
retmsg = params['retmsg']
|
||||||
end
|
session["return_to"] = url_for(:controller=>'/webmail/webmail',
|
||||||
|
:action=>'folders',
|
||||||
def import_export
|
:msg_id=>retmsg)
|
||||||
if params["export"]
|
# parse string
|
||||||
contacts = @current_user.contacts
|
if i = cstr.index("<")
|
||||||
s = ""
|
name, email = cstr.slice(0, i), cstr.slice((i+1)..(cstr.strip().index(">")-1))
|
||||||
contacts.each do |c|
|
fname = name.split().first
|
||||||
s += c.export + "\r\n"
|
lname = name.split().last if name.split().size() > 1
|
||||||
end
|
else
|
||||||
headers['Content-type'] = "text/csv"
|
fname, lname, email = "", "", cstr
|
||||||
headers['Content-Disposition'] = %(attachment; filename="contacts.csv")
|
end
|
||||||
render :text => s
|
|
||||||
return
|
if @contact = Contact.find_by_user_email(logged_user, email)
|
||||||
elsif params["import"]
|
# load related lists
|
||||||
begin
|
loadLists
|
||||||
raise t(:no_file_chosen,:scope=>:common) if not params[:upload]
|
|
||||||
raise t(:no_tmp_dir,:scope=>:common) if not File.exists?($defaults["msg_upload_dir"])
|
@contact.fname, @contact.lname = fname, lname
|
||||||
tmp_file = Tempfile.new($defaults["contact_tmp_filename"],$defaults["msg_upload_dir"])
|
|
||||||
tmp_file.write(params[:upload][:datafile].read)
|
# groups = @contact.groups
|
||||||
tmp_file.flush
|
@groups = Hash.new
|
||||||
tmp_file.rewind
|
@contactgroups.each {|g|
|
||||||
tmp_file.readlines.each do |line|
|
groupSelected = false
|
||||||
next if line =~ /^#/
|
@contact.groups.each {|gr|
|
||||||
Contact.import(@current_user,line)
|
if gr.contact_group_id.to_i == g.id.to_i
|
||||||
end
|
groupSelected = true
|
||||||
rescue ActiveRecord::RecordInvalid => e
|
break
|
||||||
flash[:error] = {:title => e.to_s,:info => e.record.inspect + e.record.errors.inspect}
|
end
|
||||||
rescue Exception => e
|
}
|
||||||
flash[:error] = e.to_s
|
if groupSelected
|
||||||
else
|
@groups[g.id] = 1 # checked
|
||||||
flash[:success] = t(:were_imported,:scope=>:contact)
|
else
|
||||||
end
|
@groups[g.id] = 0 # unchecked
|
||||||
end
|
end
|
||||||
redirect_to :action => 'index'
|
}
|
||||||
end
|
else
|
||||||
|
@contact = Contact.new("fname"=>fname, "lname" => lname, "email" => email)
|
||||||
####################################### protected section ################################
|
@contact.customer_id = logged_user
|
||||||
|
|
||||||
protected
|
# load related lists
|
||||||
|
loadLists
|
||||||
####################################### private section ##################################
|
|
||||||
|
# Init groups: because of checkbox
|
||||||
private
|
# Set all to 0 => unchecked
|
||||||
|
@groups = Hash.new
|
||||||
def get_contacts
|
@contactgroups.each {|g|
|
||||||
@contacts = Contact.getPageForUser(@current_user,params[:page],params[:sort_field],params[:sort_dir])
|
@groups[g.id] = 0
|
||||||
end
|
}
|
||||||
|
end
|
||||||
end
|
render :action => "new"
|
||||||
|
end
|
||||||
|
|
||||||
|
def import_preview
|
||||||
|
file = params["contact"]["data"]
|
||||||
|
|
||||||
|
flash["errors"] = Array.new
|
||||||
|
|
||||||
|
if file.size == 0
|
||||||
|
flash["errors"] << _('You haven\'t selected file or the file is empty')
|
||||||
|
@contact = Contact.new
|
||||||
|
@contact["file_type"] = params["contact"]["file_type"]
|
||||||
|
render :action => "add_multiple"
|
||||||
|
end
|
||||||
|
|
||||||
|
file_type = params["contact"]["file_type"]
|
||||||
|
if file_type.nil? or file_type == '1'
|
||||||
|
separator = ','
|
||||||
|
else
|
||||||
|
separator = /\t/
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
@contacts = Array.new
|
||||||
|
emails = Array.new
|
||||||
|
|
||||||
|
file.each {|line|
|
||||||
|
cdata = line.strip.chomp.split(separator)
|
||||||
|
cont = Contact.new
|
||||||
|
cont.fname = cdata[0].to_s.strip.chomp
|
||||||
|
cont.lname = cdata[1].to_s.strip.chomp
|
||||||
|
cont.email = cdata[2].to_s.strip.chomp
|
||||||
|
|
||||||
|
# Check for duplicate emails in the file
|
||||||
|
if emails.include?(cont.email)
|
||||||
|
flash["errors"] << sprintf(_('Contact %'), file.lineno.to_s) + ": " + _('The e-mail duplicates the e-mail of another record!')
|
||||||
|
else
|
||||||
|
emails << cont.email
|
||||||
|
end
|
||||||
|
|
||||||
|
@contacts << cont
|
||||||
|
}
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def import
|
||||||
|
contacts_count = params["contact"].length
|
||||||
|
contacts_to_import = params["contact"]
|
||||||
|
@contacts = Array.new
|
||||||
|
emails = Array.new
|
||||||
|
|
||||||
|
flash["errors"] = Array.new
|
||||||
|
|
||||||
|
for i in 0...contacts_count
|
||||||
|
contact = Contact.new
|
||||||
|
contact.customer_id = logged_user
|
||||||
|
contact.fname = contacts_to_import[i.to_s]["fname"]
|
||||||
|
contact.lname = contacts_to_import[i.to_s]["lname"]
|
||||||
|
contact.email = contacts_to_import[i.to_s]["email"]
|
||||||
|
|
||||||
|
begin
|
||||||
|
# Check for duplicate emails in the submitted data
|
||||||
|
if emails.include?(contact.email)
|
||||||
|
flash["errors"] << sprintf(_('Contact %'), (i+1).to_s) + ": " + _('The e-mail duplicates the e-mail of another record!')
|
||||||
|
else
|
||||||
|
emails << contact.email
|
||||||
|
end
|
||||||
|
# Check if contact is valid
|
||||||
|
contact.valid?
|
||||||
|
rescue CDF::ValidationError => e
|
||||||
|
if not contact.errors.empty?
|
||||||
|
["fname", "lname", "email"].each do |attr|
|
||||||
|
attr_errors = contact.errors.on(attr)
|
||||||
|
attr_errors = [attr_errors] unless attr_errors.nil? or attr_errors.is_a? Array
|
||||||
|
|
||||||
|
if not attr_errors.nil?
|
||||||
|
attr_errors.each do |msg|
|
||||||
|
flash["errors"] << l(:contact_addmultiple_errorforcontact, (i+1).to_s) + ": " + l(msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end # rescue
|
||||||
|
|
||||||
|
@contacts << contact
|
||||||
|
end # for
|
||||||
|
|
||||||
|
# If there are validation errors - display them
|
||||||
|
if not flash["errors"].nil? and not flash["errors"].empty?
|
||||||
|
render :action => "import_preview"
|
||||||
|
else
|
||||||
|
# save
|
||||||
|
begin
|
||||||
|
for contact in @contacts
|
||||||
|
Contact.create(contact.attributes)
|
||||||
|
end
|
||||||
|
# Set message for successful import
|
||||||
|
flash["alert"] = Array.new
|
||||||
|
flash["alert"] << l(:contact_addmultiple_success, @contacts.length.to_s)
|
||||||
|
keep_flash()
|
||||||
|
redirect_to(:action=>"list")
|
||||||
|
rescue Exception => exc
|
||||||
|
flash["errors"] << exc
|
||||||
|
render :action => "import_preview"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def choose
|
||||||
|
if params["mode"] == "groups"
|
||||||
|
save_groups
|
||||||
|
end
|
||||||
|
|
||||||
|
@tos, @ccs, @bccs = Array.new, Array.new, Array.new
|
||||||
|
|
||||||
|
params["contacts_to"].each{ |id,value| @tos << Contact.find(id) if value == "1" } if params["contacts_to"]
|
||||||
|
params["contacts_cc"].each{ |id,value| @ccs << Contact.find(id) if value == "1" } if params["contacts_cc"]
|
||||||
|
params["contacts_bcc"].each{ |id,value| @bccs << Contact.find(id) if value == "1" } if params["contacts_bcc"]
|
||||||
|
|
||||||
|
params["groups_to"].each{ |id,value|
|
||||||
|
ContactGroup.find(id).contacts.each {|c| @tos << c} if value == "1" } if params["groups_to"]
|
||||||
|
params["groups_cc"].each{ |id,value|
|
||||||
|
ContactGroup.find(id).contacts.each {|c| @ccs << c} if value == "1" } if params["groups_cc"]
|
||||||
|
params["groups_bcc"].each{ |id,value|
|
||||||
|
ContactGroup.find(id).contacts.each {|c| @bccs << c} if value == "1" } if params["groups_bcc"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def save_groups
|
||||||
|
contacts_for_group = params["contacts_for_group"]
|
||||||
|
group_id = params["group_id"]
|
||||||
|
contact_group = ContactGroup.find(group_id)
|
||||||
|
|
||||||
|
|
||||||
|
contacts_for_group.each { |contact_id,value|
|
||||||
|
contact = Contact.find(contact_id)
|
||||||
|
if value == "1" and not contact_group.contacts.include?(contact)
|
||||||
|
contact_group.contacts << contact
|
||||||
|
end
|
||||||
|
if value == "0" and contact_group.contacts.include?(contact)
|
||||||
|
contact_group.contacts.delete(contact)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
redirect_to(:action=>"index", :id=>group_id, :params=>{"mode"=>params["mode"]})
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@contact = Contact.find(params["id"])
|
||||||
|
# load related lists
|
||||||
|
loadLists
|
||||||
|
|
||||||
|
# groups = @contact.groups
|
||||||
|
@groups = Hash.new
|
||||||
|
@contactgroups.each {|g|
|
||||||
|
groupSelected = false
|
||||||
|
@contact.groups.each {|gr|
|
||||||
|
if gr.contact_group_id.to_i == g.id.to_i
|
||||||
|
groupSelected = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
}
|
||||||
|
if groupSelected
|
||||||
|
@groups[g.id] = 1 # checked
|
||||||
|
else
|
||||||
|
@groups[g.id] = 0 # unchecked
|
||||||
|
end
|
||||||
|
}
|
||||||
|
render :action => "new"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Insert or update
|
||||||
|
def create
|
||||||
|
if params["contact"]["id"] == ""
|
||||||
|
# New contact
|
||||||
|
@contact = Contact.create(params["contact"])
|
||||||
|
else
|
||||||
|
# Edit existing
|
||||||
|
@contact = Contact.find(params["contact"]["id"])
|
||||||
|
@contact.attributes = params["contact"]
|
||||||
|
end
|
||||||
|
|
||||||
|
@contactgroups = ContactGroup.find_by_user(logged_user)
|
||||||
|
# Groups displayed
|
||||||
|
groups = params['groups']
|
||||||
|
tempGroups = Array.new
|
||||||
|
tempGroups.concat(@contact.groups)
|
||||||
|
|
||||||
|
@contactgroups.each { |cgroup|
|
||||||
|
includesCGroup = false
|
||||||
|
tempGroups.each {|gr|
|
||||||
|
if gr.contact_group_id.to_i == cgroup.id.to_i
|
||||||
|
includesCGroup = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
}
|
||||||
|
if groups["#{cgroup.id}"] == "1" and not includesCGroup
|
||||||
|
@contact.groups << cgroup
|
||||||
|
end
|
||||||
|
|
||||||
|
if groups["#{cgroup.id}"] == "0" and includesCGroup
|
||||||
|
@contact.groups.delete(cgroup)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
if @contact.save
|
||||||
|
if params["paction"] == t(:save)
|
||||||
|
redirect_to :action =>:index
|
||||||
|
else
|
||||||
|
redirect_to :action => :new
|
||||||
|
end
|
||||||
|
else
|
||||||
|
loadLists
|
||||||
|
@groups = Hash.new
|
||||||
|
@contactgroups.each {|g|
|
||||||
|
if @contact.groups.include?(g)
|
||||||
|
@groups[g.id] = 1
|
||||||
|
else
|
||||||
|
@groups[g.id] = 0
|
||||||
|
end
|
||||||
|
}
|
||||||
|
render :action => :new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete
|
||||||
|
Contact.destroy(params['id'])
|
||||||
|
redirect_to(:action=>'index')
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
def secure_user?() true end
|
||||||
|
def additional_scripts()
|
||||||
|
add_s = ''
|
||||||
|
if action_name == "choose"
|
||||||
|
add_s<<'<script type="text/javascript" src="/javascripts/global.js"></script>'
|
||||||
|
add_s<<'<script type="text/javascript" src="/javascripts/contact_choose.js"></script>'
|
||||||
|
end
|
||||||
|
add_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def onload_function()
|
||||||
|
if action_name == "choose"
|
||||||
|
"javascript:respondToCaller();"
|
||||||
|
else
|
||||||
|
""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
private
|
||||||
|
def select_layout
|
||||||
|
if params["mode"] == "choose"
|
||||||
|
@mode = "choose"
|
||||||
|
@contactgroups = ContactGroup.find_by_user(logged_user)
|
||||||
|
'chooser'
|
||||||
|
elsif params["mode"] == "groups"
|
||||||
|
@mode = "groups"
|
||||||
|
'public'
|
||||||
|
else
|
||||||
|
@mode = "normal"
|
||||||
|
'public'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def loadLists
|
||||||
|
if @contactgroups.nil?
|
||||||
|
@contactgroups = ContactGroup.find_by_user(logged_user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
182
app/controllers/folders_controller.rb
Executable file → Normal file
182
app/controllers/folders_controller.rb
Executable file → Normal file
|
@ -1,172 +1,24 @@
|
||||||
require 'imap_mailbox'
|
require 'ezcrypto'
|
||||||
require 'imap_session'
|
|
||||||
|
|
||||||
class FoldersController < ApplicationController
|
class FoldersController < ApplicationController
|
||||||
|
include ImapUtils
|
||||||
|
|
||||||
include ImapMailboxModule
|
before_filter :login_required
|
||||||
include ImapSessionModule
|
before_filter :load_imap_session
|
||||||
|
after_filter :close_imap_session
|
||||||
|
|
||||||
before_filter :check_current_user,:selected_folder, :get_current_folders
|
layout 'public'
|
||||||
|
|
||||||
before_filter :open_imap_session, :except => [:index,:show_hide,:system]
|
def index
|
||||||
after_filter :close_imap_session, :except => [:index,:show_hide,:system]
|
@folders = @mailbox.folders
|
||||||
|
end
|
||||||
|
|
||||||
before_filter :get_folders
|
def create
|
||||||
#before_filter :prepare_buttons_to_folders
|
@mailbox.create_folder(CDF::CONFIG[:mail_inbox] + '.' + params[:folder])
|
||||||
|
redirect_to folders_path
|
||||||
#theme :theme_resolver
|
end
|
||||||
|
|
||||||
def index
|
|
||||||
#before_filter
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
if params[:folder][:target].empty?
|
|
||||||
flash[:warning] = t(:to_create_empty,:scope=>:folder)
|
|
||||||
render "index"
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
#TODO recreate local copy of folders
|
|
||||||
if params[:folder][:parent].empty?
|
|
||||||
@mailbox.create_folder(params[:folder][:target])
|
|
||||||
else
|
|
||||||
parent_folder = @current_user.folders.find(params[:folder][:parent])
|
|
||||||
if parent_folder.depth >= $defaults["mailbox_max_parent_folder_depth"].to_i
|
|
||||||
raise Exception, t(:max_depth,:scope=>:folder)
|
|
||||||
end
|
|
||||||
@mailbox.create_folder(parent_folder.full_name + parent_folder.delim + params[:folder][:target])
|
|
||||||
end
|
|
||||||
rescue Exception => e
|
|
||||||
flash[:error] = t(:can_not_create,:scope=>:folder) + ' (' + e.to_s + ')'
|
|
||||||
render 'index'
|
|
||||||
return
|
|
||||||
end
|
|
||||||
flash[:success] = t(:was_created,:scope=>:folder)
|
|
||||||
redirect_to :action => 'index'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def delete
|
|
||||||
if params[:folder][:delete].empty?
|
|
||||||
flash[:warning] = t(:to_delete_empty,:scope=>:folder)
|
|
||||||
render "index"
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
folder = @current_user.folders.find(params[:folder][:delete])
|
|
||||||
if @folders_system.include?(folder)
|
|
||||||
raise Exception, t(:system,:scope=>:folder)
|
|
||||||
end
|
|
||||||
@mailbox.delete_folder(folder.full_name)
|
|
||||||
if @current_folder.eql? folder
|
|
||||||
session[:selected_folder] = nil
|
|
||||||
end
|
|
||||||
folder.destroy
|
|
||||||
rescue Exception => e
|
|
||||||
flash[:error] = t(:can_not_delete,:scope=>:folder) + ' (' + e.to_s + ')'
|
|
||||||
render 'index'
|
|
||||||
return
|
|
||||||
end
|
|
||||||
flash[:success] = t(:was_deleted,:scope=>:folder)
|
|
||||||
redirect_to :action => 'index'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def system
|
|
||||||
logger.custom('sss',params[:folder].inspect)
|
|
||||||
@folders.each do |f|
|
|
||||||
logger.custom('s',f.inspect)
|
|
||||||
if f.isSystem?
|
|
||||||
f.setNone
|
|
||||||
end
|
|
||||||
if f.id == params[:folder][:mailbox_inbox].to_i
|
|
||||||
f.setInbox
|
|
||||||
end
|
|
||||||
if f.id == params[:folder][:mailbox_sent].to_i
|
|
||||||
f.setSent
|
|
||||||
end
|
|
||||||
if f.id == params[:folder][:mailbox_trash].to_i
|
|
||||||
f.setTrash
|
|
||||||
end
|
|
||||||
if f.id == params[:folder][:mailbox_drafts].to_i
|
|
||||||
f.setDrafts
|
|
||||||
end
|
|
||||||
end
|
|
||||||
redirect_to :action => 'index'
|
|
||||||
end
|
|
||||||
|
|
||||||
def refresh
|
|
||||||
# TODO save system folders
|
|
||||||
if params[:refresh]
|
|
||||||
Folder.refresh(@mailbox,@current_user)
|
|
||||||
flash.keep
|
|
||||||
elsif params[:show_hide]
|
|
||||||
if !params["folders_to_show"].nil?
|
|
||||||
@folders.each do |f|
|
|
||||||
if params["folders_to_show"].include?(f.id.to_s)
|
|
||||||
f.shown = true
|
|
||||||
f.save
|
|
||||||
else
|
|
||||||
f.shown = false
|
|
||||||
f.save
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
redirect_to :action => 'index'
|
|
||||||
end
|
|
||||||
|
|
||||||
def select
|
|
||||||
session[:selected_folder] = params[:id]
|
|
||||||
redirect_to :controller => 'messages', :action => 'index'
|
|
||||||
end
|
|
||||||
|
|
||||||
def refresh_status
|
|
||||||
@folders_shown.each do |f|
|
|
||||||
@mailbox.set_folder(f.full_name)
|
|
||||||
folder_status = @mailbox.status
|
|
||||||
f.update_attributes(:total => folder_status['MESSAGES'], :unseen => folder_status['UNSEEN'])
|
|
||||||
end
|
|
||||||
redirect_to :controller=> 'messages', :action => 'index'
|
|
||||||
end
|
|
||||||
|
|
||||||
def emptybin
|
|
||||||
begin
|
|
||||||
trash_folder = @current_user.folders.trash.first
|
|
||||||
if trash_folder.nil?
|
|
||||||
raise Exception, t(:not_configured_trash,:scope=>:folder)
|
|
||||||
end
|
|
||||||
@mailbox.set_folder(trash_folder.full_name)
|
|
||||||
trash_folder.messages.each do |m|
|
|
||||||
@mailbox.delete_message(m.uid)
|
|
||||||
end
|
|
||||||
@mailbox.expunge
|
|
||||||
trash_folder.messages.destroy_all
|
|
||||||
trash_folder.update_attributes(:unseen => 0, :total => 0)
|
|
||||||
rescue Exception => e
|
|
||||||
flash[:error] = "#{t(:imap_error,:scope=>:common)} (#{e.to_s})"
|
|
||||||
end
|
|
||||||
redirect_to :controller => 'messages', :action => 'index'
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
############################################# protected section #######################################
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
#def prepare_buttons_to_folders
|
|
||||||
#@buttons = []
|
|
||||||
#@buttons << {:text => 'show_hide',:scope=>'folder',:image => 'flag.png'}
|
|
||||||
#@buttons << {:text => 'refresh',:scope=>'folder',:image => 'refresh.png'}
|
|
||||||
#end
|
|
||||||
|
|
||||||
def get_folders
|
|
||||||
@folders = @current_user.folders
|
|
||||||
@folders_shown = @current_user.folders.shown
|
|
||||||
@folders_system = @current_user.folders.sys
|
|
||||||
@current_user.folders.inbox.first.nil? ? @folder_inbox = "" : @folder_inbox = @current_user.folders.inbox.first.id
|
|
||||||
@current_user.folders.drafts.first.nil? ? @folder_drafts = "" : @folder_drafts = @current_user.folders.drafts.first.id
|
|
||||||
@current_user.folders.sent.first.nil? ? @folder_sent = "" : @folder_sent = @current_user.folders.sent.first.id
|
|
||||||
@current_user.folders.trash.first.nil? ? @folder_trash = "" : @folder_trash = @current_user.folders.trash.first.id
|
|
||||||
end
|
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@mailbox.delete_folder params[:id]
|
||||||
|
redirect_to folders_path
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
class InternalController < ApplicationController
|
|
||||||
|
|
||||||
before_filter :check_current_user ,:selected_folder, :get_current_folders, :only => [:about]
|
|
||||||
|
|
||||||
#theme :theme_resolver
|
|
||||||
layout "simple"
|
|
||||||
|
|
||||||
|
|
||||||
ERRORS = [
|
|
||||||
:internal_server_error,
|
|
||||||
:not_found,
|
|
||||||
:unprocessable_entity,
|
|
||||||
:allready_configured
|
|
||||||
].freeze
|
|
||||||
|
|
||||||
ERRORS.each do |e|
|
|
||||||
define_method e do
|
|
||||||
@title = t(e,:scope=>:internal)
|
|
||||||
flash[:error] = t(e,:scope=>:internal)
|
|
||||||
render 'error'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def error
|
|
||||||
@title = t(:unspecified_error,:scope=>:internal)
|
|
||||||
@error = params[:error] || t(:unspecified_error,:scope=>:internal)
|
|
||||||
end
|
|
||||||
|
|
||||||
def imaperror
|
|
||||||
@title = t(:imap_error,:scope => :internal)
|
|
||||||
@error = params[:error] || t(:unspecified_error, :scope => :internal)
|
|
||||||
logger.error "!!! InternalControllerImapError: " + @error
|
|
||||||
render 'error'
|
|
||||||
end
|
|
||||||
|
|
||||||
def loginfailure
|
|
||||||
reset_session
|
|
||||||
flash[:error] = t(:login_failure,:scope=>:user)
|
|
||||||
@current_user = nil
|
|
||||||
redirect_to :controller=>'user', :action => 'login'
|
|
||||||
end
|
|
||||||
|
|
||||||
#def onlycanlogins
|
|
||||||
#reset_session
|
|
||||||
#flash[:error] = t(:only_can_logins,:scope=>:user)
|
|
||||||
#@current_user = nil
|
|
||||||
#redirect_to :controller=>'user', :action => 'login'
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def onlycanlogins
|
|
||||||
#reset_session
|
|
||||||
#flash[:error] = t(:allready_configured,:scope=>:user)
|
|
||||||
#@current_user = nil
|
|
||||||
#redirect_to :controller=>'user', :action => 'login'
|
|
||||||
#end
|
|
||||||
|
|
||||||
def about
|
|
||||||
render 'internal/about', :layout => 'application'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,97 +0,0 @@
|
||||||
require 'tempfile'
|
|
||||||
|
|
||||||
class LinksController < ApplicationController
|
|
||||||
|
|
||||||
before_filter :check_current_user,:selected_folder, :get_current_folders
|
|
||||||
|
|
||||||
before_filter :get_links, :only => [:index]
|
|
||||||
|
|
||||||
def index
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def new
|
|
||||||
@link = Link.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def edit
|
|
||||||
@link = @current_user.links.find(params[:id])
|
|
||||||
render 'edit'
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
if params["delete_selected"]
|
|
||||||
if params["items_ids"]
|
|
||||||
params["items_ids"].each do |id|
|
|
||||||
@current_user.links.find_by_id(id).destroy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
redirect_to(links_path)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
@link = @current_user.links.build(params[:link])
|
|
||||||
if @link.valid?
|
|
||||||
@link.save
|
|
||||||
flash[:success] = t(:was_created,:scope=>:link)
|
|
||||||
redirect_to(links_path)
|
|
||||||
else
|
|
||||||
render 'new'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
|
||||||
@link = @current_user.links.find(params[:id])
|
|
||||||
if @link.update_attributes(params[:link])
|
|
||||||
redirect_to(links_path)
|
|
||||||
else
|
|
||||||
render 'edit'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def import_export
|
|
||||||
if params["export"]
|
|
||||||
links = @current_user.links
|
|
||||||
s = ""
|
|
||||||
links.each do |l|
|
|
||||||
s += l.export + "\r\n"
|
|
||||||
end
|
|
||||||
headers['Content-type'] = "text/csv"
|
|
||||||
headers['Content-Disposition'] = %(attachment; filename="links.csv")
|
|
||||||
render :text => s
|
|
||||||
return
|
|
||||||
elsif params["import"]
|
|
||||||
begin
|
|
||||||
raise t(:no_file_chosen,:scope=>:common) if not params[:upload]
|
|
||||||
raise t(:no_tmp_dir,:scope=>:common) if not File.exists?($defaults["msg_upload_dir"])
|
|
||||||
tmp_file = Tempfile.new($defaults["contact_tmp_filename"],$defaults["msg_upload_dir"])
|
|
||||||
tmp_file.write(params[:upload][:datafile].read)
|
|
||||||
tmp_file.flush
|
|
||||||
tmp_file.rewind
|
|
||||||
tmp_file.readlines.each do |line|
|
|
||||||
next if line =~ /^#/
|
|
||||||
Link.import(@current_user,line)
|
|
||||||
end
|
|
||||||
rescue ActiveRecord::RecordInvalid => e
|
|
||||||
flash[:error] = {:title => e.to_s,:info => e.record.inspect + e.record.errors.inspect}
|
|
||||||
rescue Exception => e
|
|
||||||
flash[:error] = e.to_s
|
|
||||||
else
|
|
||||||
flash[:success] = t(:were_imported,:scope=>:link)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
redirect_to :action => 'index'
|
|
||||||
end
|
|
||||||
|
|
||||||
####################################### protected section ################################
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
####################################### private section ##################################
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def get_links
|
|
||||||
@links = Link.getPageForUser(@current_user,params[:page],params[:sort_field],params[:sort_dir])
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
65
app/controllers/login_controller.rb
Normal file
65
app/controllers/login_controller.rb
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
require 'ezcrypto'
|
||||||
|
class LoginController < ApplicationController
|
||||||
|
|
||||||
|
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(session["return_to"])
|
||||||
|
session["return_to"] = nil
|
||||||
|
else
|
||||||
|
redirect_to :action=>"index"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@login_user = Customer.new
|
||||||
|
flash["error"] = t :wrong_email_or_password
|
||||||
|
redirect_to :action => "index"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def logout
|
||||||
|
reset_session
|
||||||
|
flash["status"] = t(:user_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
|
|
@ -1,214 +0,0 @@
|
||||||
require 'imap_session'
|
|
||||||
require 'imap_mailbox'
|
|
||||||
require 'imap_message'
|
|
||||||
require 'mail'
|
|
||||||
require 'mail_plugin_extension'
|
|
||||||
|
|
||||||
class MessagesController < ApplicationController
|
|
||||||
|
|
||||||
include ImapMailboxModule
|
|
||||||
include ImapSessionModule
|
|
||||||
include ImapMessageModule
|
|
||||||
include MessagesHelper
|
|
||||||
|
|
||||||
before_filter :check_current_user ,:selected_folder,:get_current_folders
|
|
||||||
before_filter :open_imap_session, :select_imap_folder
|
|
||||||
before_filter :prepare_compose_buttons, :only => [:compose]
|
|
||||||
before_filter :get_system_folders, :only => [:index]
|
|
||||||
before_filter :create_message_with_params, :only => [:compose]
|
|
||||||
#before_filter :prepare_multi1_buttons, :only => [:index,:show]
|
|
||||||
#before_filter :prepare_multi2_buttons, :only => [:index]
|
|
||||||
#before_filter :prepare_multi3_buttons, :only => [:show]
|
|
||||||
after_filter :close_imap_session
|
|
||||||
|
|
||||||
#theme :theme_resolver
|
|
||||||
|
|
||||||
def index
|
|
||||||
|
|
||||||
if @sent_folder.nil? || @drafts_folder.nil? || @inbox_folder.nil? || @trash_folder.nil?
|
|
||||||
flash[:warning] = t(:not_all_configured,:scope => :folder)
|
|
||||||
end
|
|
||||||
|
|
||||||
if @current_folder.nil?
|
|
||||||
flash[:warning] = t(:no_selected,:scope => :folder)
|
|
||||||
redirect_to :controller => 'folders', :action => 'index'
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
@messages = []
|
|
||||||
|
|
||||||
folder_status = @mailbox.status
|
|
||||||
@current_folder.update_attributes(:total => folder_status['MESSAGES'], :unseen => folder_status['UNSEEN'])
|
|
||||||
|
|
||||||
folder_status['MESSAGES'].zero? ? uids_remote = [] : uids_remote = @mailbox.fetch_uids
|
|
||||||
uids_local = @current_user.messages.where(:folder_id => @current_folder).collect(&:uid)
|
|
||||||
|
|
||||||
logger.custom('current_folder',@current_folder.inspect)
|
|
||||||
logger.custom('uids_local',uids_local.join(","))
|
|
||||||
logger.custom('uids_remote',uids_remote.join(","))
|
|
||||||
logger.custom('to_delete',(uids_local-uids_remote).join(","))
|
|
||||||
logger.custom('to_fetch',(uids_remote-uids_local).join(","))
|
|
||||||
|
|
||||||
(uids_local-uids_remote).each do |uid|
|
|
||||||
@current_folder.messages.find_by_uid(uid).destroy
|
|
||||||
end
|
|
||||||
|
|
||||||
(uids_remote-uids_local).each_slice($defaults["imap_fetch_slice"].to_i) do |slice|
|
|
||||||
messages = @mailbox.uid_fetch(slice, ImapMessageModule::IMAPMessage.fetch_attr)
|
|
||||||
messages.each do |m|
|
|
||||||
Message.createForUser(@current_user,@current_folder,m)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@messages = Message.getPageForUser(@current_user,@current_folder,params[:page],params[:sort_field],params[:sort_dir])
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def compose
|
|
||||||
#before filter :prepare_compose_buttons, :create_message_with_params
|
|
||||||
@operation = :new
|
|
||||||
if params["cid"].present?
|
|
||||||
contact = @current_user.contacts.find_by_id(params["cid"])
|
|
||||||
if not contact.nil?
|
|
||||||
@message.to_addr = contact.email
|
|
||||||
end
|
|
||||||
elsif params["cids"].present?
|
|
||||||
contacts = []
|
|
||||||
params["cids"].each do |c|
|
|
||||||
contact = @current_user.contacts.find_by_id(c)
|
|
||||||
if not contact.nil?
|
|
||||||
contacts << contact.email
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@message.to_addr = contacts.join(';')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def show
|
|
||||||
@images = []
|
|
||||||
@attachments = []
|
|
||||||
@text_part = nil
|
|
||||||
@html_part = nil
|
|
||||||
|
|
||||||
@message = @current_user.messages.where('folder_id = ? and uid = ?',@current_folder,params[:id]).first
|
|
||||||
@message.update_attributes(:unseen => false)
|
|
||||||
imap_message = @mailbox.fetch_body(@message.uid)
|
|
||||||
|
|
||||||
mail = Mail.new(imap_message)
|
|
||||||
@mail = Mail.new(imap_message)
|
|
||||||
@plain_header = mail.header.to_s
|
|
||||||
|
|
||||||
|
|
||||||
# FIXME missing fields and support arrays
|
|
||||||
#@from = mail.From.addrs.presence
|
|
||||||
#@to = mail.To.addrs.presence
|
|
||||||
@from = @message.from_addr
|
|
||||||
@to = @message.to_addr
|
|
||||||
#@cc = mail.cc
|
|
||||||
#@bcc = mail.bcc
|
|
||||||
#@subject = mail.Subject
|
|
||||||
@date = mail.date.presence
|
|
||||||
|
|
||||||
if mail.multipart? == true
|
|
||||||
if not mail.text_part.nil?
|
|
||||||
@text_part = mail.text_part.decoded_and_charseted
|
|
||||||
end
|
|
||||||
if not mail.html_part.nil?
|
|
||||||
@html_part = mail.html_part.decoded_and_charseted
|
|
||||||
end
|
|
||||||
attachments = mail.attachments
|
|
||||||
if not attachments.size.zero?
|
|
||||||
for idx in 0..attachments.size - 1
|
|
||||||
a = attachments[idx]
|
|
||||||
a.idx = idx
|
|
||||||
a.parent_id = @message.uid
|
|
||||||
if a.isImage? and @current_user.prefs.msg_image_view_as.to_sym.eql?(:thumbnail)
|
|
||||||
@images << a
|
|
||||||
else
|
|
||||||
@attachments << a
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
logger.custom('mail',mail.inspect)
|
|
||||||
part = mail
|
|
||||||
#part = Mail::Part.new(mail)
|
|
||||||
part.idx = 0
|
|
||||||
part.parent_id = @message.uid
|
|
||||||
if part.isText?
|
|
||||||
@text_part = part.decoded_and_charseted
|
|
||||||
elsif part.isImage? and @current_user.prefs.msg_image_view_as.to_sym.eql?(:thumbnail)
|
|
||||||
@images << part
|
|
||||||
elsif part.isHtml?
|
|
||||||
@html_part = part.decoded_and_charseted
|
|
||||||
else
|
|
||||||
@attachments << part
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def html_body
|
|
||||||
message = @current_user.messages.where('folder_id = ? and uid = ?',@current_folder,params[:id]).first
|
|
||||||
mail = Mail.new(@mailbox.fetch_body(message.uid))
|
|
||||||
if mail.multipart?
|
|
||||||
@body = mail.html_part.decoded_and_charseted
|
|
||||||
else
|
|
||||||
@body = mail.decoded_and_charseted
|
|
||||||
end
|
|
||||||
|
|
||||||
if @body.nil?
|
|
||||||
@body = t(:no_body,:scope=>:message)
|
|
||||||
else
|
|
||||||
if @body=~/cid:([\w@\.]+)/
|
|
||||||
attachments = mail.attachments
|
|
||||||
if not attachments.size.zero?
|
|
||||||
for idx in 0..attachments.size - 1
|
|
||||||
@body.gsub!(/cid:#{attachments[idx].cid}/,attachment_download_path(message.uid,idx))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
render 'html_body',:layout => 'html_body'
|
|
||||||
end
|
|
||||||
|
|
||||||
def attachment
|
|
||||||
attachments = []
|
|
||||||
message = @current_user.messages.where('folder_id = ? and uid = ?',@current_folder,params[:id]).first
|
|
||||||
mail = Mail.new(@mailbox.fetch_body(message.uid))
|
|
||||||
if mail.multipart? == true
|
|
||||||
attachments = mail.attachments
|
|
||||||
else
|
|
||||||
#attachments << Mail::Part.new(mail)
|
|
||||||
attachments << mail
|
|
||||||
end
|
|
||||||
a = attachments[params[:idx].to_i]
|
|
||||||
headers['Content-type'] = a.main_type + "/" + a.sub_type
|
|
||||||
headers['Content-Disposition'] = %(attachment; filename="#{a.filename}")
|
|
||||||
render :text => a.decoded
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
############################################# protected section ##########################################
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
#def prepare_multi2_buttons
|
|
||||||
#@multi2_buttons = []
|
|
||||||
#@multi2_buttons << {:text => 'trash',:scope=>:message,:image => 'trash.png'}
|
|
||||||
#@multi2_buttons << {:text => 'set_unread',:scope=>:message,:image => 'unseen.png'}
|
|
||||||
#@multi2_buttons << {:text => 'set_read',:scope=>:message,:image => 'seen.png'}
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def prepare_multi1_buttons
|
|
||||||
#@multi1_buttons = []
|
|
||||||
#@multi1_buttons << {:text => 'copy',:scope=>:message,:image => 'copy.png'}
|
|
||||||
#@multi1_buttons << {:text => 'move',:scope=>:message,:image => 'move.png'}
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def prepare_multi3_buttons
|
|
||||||
#@multi3_buttons = []
|
|
||||||
#@multi3_buttons << {:text => 'show_header',:scope=>:show,:image => 'zoom.png'}
|
|
||||||
#@multi3_buttons << {:text => 'trash',:scope=>:show,:image => 'trash.png'}
|
|
||||||
#@multi3_buttons << {:text => 'reply',:scope=>:show,:image => 'reply.png'}
|
|
||||||
#end
|
|
||||||
end
|
|
|
@ -1,367 +0,0 @@
|
||||||
require 'imap_session'
|
|
||||||
require 'imap_mailbox'
|
|
||||||
require 'imap_message'
|
|
||||||
require 'mail'
|
|
||||||
require 'mail_plugin_extension'
|
|
||||||
require 'net/smtp'
|
|
||||||
|
|
||||||
class MessagesOpsController < ApplicationController
|
|
||||||
|
|
||||||
include ImapMailboxModule
|
|
||||||
include ImapSessionModule
|
|
||||||
include ImapMessageModule
|
|
||||||
include MessagesHelper
|
|
||||||
|
|
||||||
before_filter :check_current_user ,:selected_folder,:get_current_folders
|
|
||||||
before_filter :open_imap_session, :select_imap_folder
|
|
||||||
before_filter :prepare_compose_buttons
|
|
||||||
before_filter :get_system_folders, :only => [:composed,:single,:multi]
|
|
||||||
before_filter :prepare_composed , :only => [:composed]
|
|
||||||
before_filter :create_message_with_params, :only=> [:composed,:single,:multi]
|
|
||||||
after_filter :close_imap_session
|
|
||||||
#theme :theme_resolver
|
|
||||||
|
|
||||||
|
|
||||||
############################################### single #####################################
|
|
||||||
|
|
||||||
def single
|
|
||||||
if params[:reply] or params[:reply_all]
|
|
||||||
reply
|
|
||||||
return
|
|
||||||
elsif params[:trash]
|
|
||||||
trash
|
|
||||||
elsif params[:move]
|
|
||||||
move
|
|
||||||
elsif params[:copy]
|
|
||||||
copy
|
|
||||||
end
|
|
||||||
redirect_to :controller => 'messages', :action => 'index'
|
|
||||||
end
|
|
||||||
|
|
||||||
############################################### multi ######################################
|
|
||||||
|
|
||||||
def multi
|
|
||||||
begin
|
|
||||||
if !params[:uids]
|
|
||||||
flash[:warning] = t(:no_selected,:scope=>:message)
|
|
||||||
elsif params[:set_unread]
|
|
||||||
set_unread
|
|
||||||
elsif params[:set_read]
|
|
||||||
set_read
|
|
||||||
elsif params[:trash]
|
|
||||||
trash
|
|
||||||
elsif params[:copy]
|
|
||||||
copy
|
|
||||||
elsif params[:move]
|
|
||||||
move
|
|
||||||
end
|
|
||||||
rescue Exception => e
|
|
||||||
flash[:error] = "#{t(:imap_error,:scope=>:internal)} (#{e.to_s})"
|
|
||||||
end
|
|
||||||
redirect_to :controller => 'messages', :action => 'index'
|
|
||||||
end
|
|
||||||
|
|
||||||
############################################### ################################################
|
|
||||||
|
|
||||||
|
|
||||||
def set_unread
|
|
||||||
params["uids"].each do |uid|
|
|
||||||
@mailbox.set_unread(uid)
|
|
||||||
@current_user.messages.where('folder_id = ? and uid = ?',@current_folder,uid).first.update_attributes(:unseen => 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_read
|
|
||||||
params["uids"].each do |uid|
|
|
||||||
@mailbox.set_read(uid)
|
|
||||||
@current_user.messages.where('folder_id = ? and uid = ?',@current_folder,uid).first.update_attributes(:unseen => 0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def trash
|
|
||||||
if @trash_folder.nil?
|
|
||||||
flash[:warning] = t(:not_configured_trash, :scope=>:folder)
|
|
||||||
else
|
|
||||||
params["uids"].each do |uid|
|
|
||||||
@mailbox.move_message(uid,@trash_folder.full_name)
|
|
||||||
message = @current_folder.messages.find_by_uid(uid)
|
|
||||||
message.change_folder(@trash_folder)
|
|
||||||
end
|
|
||||||
@mailbox.expunge
|
|
||||||
@trash_folder.update_stats
|
|
||||||
@current_folder.update_stats
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def copy
|
|
||||||
if params[:folder][:target].empty?
|
|
||||||
flash[:warning] = t(:no_selected,:scope=>:folder)
|
|
||||||
else
|
|
||||||
dest_folder = @current_user.folders.find(params[:folder][:target])
|
|
||||||
params["uids"].each do |uid|
|
|
||||||
@mailbox.copy_message(uid,dest_folder.full_name)
|
|
||||||
message = @current_folder.messages.find_by_uid(uid)
|
|
||||||
new_message = message.clone
|
|
||||||
new_message.folder_id = dest_folder.id
|
|
||||||
new_message.save
|
|
||||||
end
|
|
||||||
dest_folder.update_stats
|
|
||||||
@current_folder.update_stats
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def move
|
|
||||||
if params[:folder][:target].empty?
|
|
||||||
flash[:warning] = t(:no_selected,:scope=>:folder)
|
|
||||||
else
|
|
||||||
dest_folder = @current_user.folders.find(params[:folder][:target])
|
|
||||||
logger.info "DEST: "+dest_folder.inspect
|
|
||||||
params["uids"].each do |uid|
|
|
||||||
logger.info "UID: "+uid
|
|
||||||
logger.info "DEST_FULL: "+dest_folder.full_name
|
|
||||||
@mailbox.move_message(uid,dest_folder.full_name)
|
|
||||||
message = @current_folder.messages.find_by_uid(uid)
|
|
||||||
logger.info "M: "+message.inspect
|
|
||||||
logger.info "UPDATE_DEST_BEFORE1: "+dest_folder.inspect
|
|
||||||
message.change_folder(dest_folder)
|
|
||||||
logger.info "UPDATE_DEST_BEFORE2: "+dest_folder.inspect
|
|
||||||
end
|
|
||||||
logger.info "UPDATE_DEST_BEFORE: "+dest_folder.inspect
|
|
||||||
@mailbox.expunge
|
|
||||||
dest_folder.update_stats
|
|
||||||
logger.info "UPDATE_DEST: "+dest_folder.inspect
|
|
||||||
@current_folder.update_stats
|
|
||||||
logger.info "UPDATE_CUT: "+@current_folder.inspect
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def upload
|
|
||||||
begin
|
|
||||||
raise MailrException.new :cause=>:no_tmp_dir,:scope=>:common if not File.exists?($defaults["msg_upload_dir"])
|
|
||||||
raise MailrException.new :cause=>:no_file_chosen,:scope=>:common if not params[:upload]
|
|
||||||
@operation = :upload
|
|
||||||
name = params[:file][:data].original_filename
|
|
||||||
upload_dir = $defaults["msg_upload_dir"]
|
|
||||||
path = File.join(upload_dir, @current_user.username + "_" + name)
|
|
||||||
File.open(path, "wb") { |f| f.write(params[:file][:data].read) }
|
|
||||||
rescue MailrException => e
|
|
||||||
flash[:error] = t(e.message[:cause],:scope => e.message[:scope])
|
|
||||||
rescue Exception => e
|
|
||||||
flash[:error] = t(:general_error,:scope=>:internal) + " (" + e.class.name + " " + e.to_s + ")"
|
|
||||||
end
|
|
||||||
create_message_with_params
|
|
||||||
render 'messages/compose'
|
|
||||||
end
|
|
||||||
|
|
||||||
# Files uploaded from Internet Explorer:
|
|
||||||
#
|
|
||||||
#Internet Explorer includes the entire path of a file in the filename sent, so the original_filename routine will return something like:
|
|
||||||
#
|
|
||||||
#C:\Documents and Files\user_name\Pictures\My File.jpg
|
|
||||||
#
|
|
||||||
#instead of just:
|
|
||||||
#
|
|
||||||
#My File.jpg
|
|
||||||
#
|
|
||||||
#This is easily handled by File.basename, which strips out everything before the filename.
|
|
||||||
#
|
|
||||||
#def sanitize_filename(file_name)
|
|
||||||
# # get only the filename, not the whole path (from IE)
|
|
||||||
# just_filename = File.basename(file_name)
|
|
||||||
# # replace all none alphanumeric, underscore or perioids
|
|
||||||
# # with underscore
|
|
||||||
# just_filename.sub(/[^\w\.\-]/,'_')
|
|
||||||
#end
|
|
||||||
#
|
|
||||||
#Deleting an existing File:
|
|
||||||
#
|
|
||||||
#If you want to delete any existing file then its simple and need to write following code:
|
|
||||||
#
|
|
||||||
# def cleanup
|
|
||||||
# File.delete("#{RAILS_ROOT}/dirname/#{@filename}")
|
|
||||||
# if File.exist?("#{RAILS_ROOT}/dirname/#{@filename}")
|
|
||||||
# end
|
|
||||||
|
|
||||||
def composed
|
|
||||||
if params[:delete_marked] and params[:files]
|
|
||||||
params[:files].each do |filename|
|
|
||||||
path = File.join(Rails.root,$defaults["msg_upload_dir"],@current_user.username + "_" +filename)
|
|
||||||
File.delete(path) if File.exist?(path)
|
|
||||||
end
|
|
||||||
create_message_with_params
|
|
||||||
@operation = :new
|
|
||||||
render 'messages/compose'
|
|
||||||
return
|
|
||||||
elsif params[:upload]
|
|
||||||
upload
|
|
||||||
elsif params[:save]
|
|
||||||
save
|
|
||||||
elsif params[:sendout]
|
|
||||||
sendout
|
|
||||||
else
|
|
||||||
redirect_to :controller => 'messages', :action => 'index'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def sendout
|
|
||||||
begin
|
|
||||||
smtp_server = @current_user.servers.primary_for_smtp
|
|
||||||
raise MailrException.new :cause=>:not_configured_smtp,:scope => :compose if smtp_server.nil?
|
|
||||||
raise MailrException.new :cause=>:has_no_domain,:scope=>:user if @current_user.has_domain?.nil?
|
|
||||||
raise MailrException.new :cause=>:not_configured_sent,:scope=>:compose if @sent_folder.nil?
|
|
||||||
send_mail_message( smtp_server,
|
|
||||||
@current_user.has_domain?,
|
|
||||||
@current_user.login,
|
|
||||||
@current_user.get_cached_password(session),
|
|
||||||
@mail.to_s,
|
|
||||||
@current_user.email,
|
|
||||||
params[:message][:to_addr]
|
|
||||||
)
|
|
||||||
@mailbox.append(@sent_folder.full_name,@mail.to_s,[:Seen])
|
|
||||||
upload_dir = $defaults["msg_upload_dir"]
|
|
||||||
@attachments.each do |file|
|
|
||||||
path = File.join(upload_dir, @current_user.username + "_" + file[:name])
|
|
||||||
File.delete(path) if File.exist?(path)
|
|
||||||
end
|
|
||||||
rescue MailrException => e
|
|
||||||
flash[:error] = t(e.message[:cause],:scope => e.message[:scope])
|
|
||||||
rescue Exception => e
|
|
||||||
flash[:error] = t(:general_error,:scope=>:internal) + " (" + e.class.name + " " + e.to_s + ")"
|
|
||||||
else
|
|
||||||
flash[:success] = t(:was_sent,:scope => :compose)
|
|
||||||
redirect_to :controller => 'messages', :action => 'index'
|
|
||||||
return
|
|
||||||
end
|
|
||||||
@operation = :new
|
|
||||||
render 'messages/compose'
|
|
||||||
end
|
|
||||||
|
|
||||||
def save
|
|
||||||
begin
|
|
||||||
raise MailrException.new :cause=>:not_configured_drafts,:scope=>:folder if @drafts_folder.nil?
|
|
||||||
@mailbox.append(@drafts_folder.full_name,@mail.to_s,[:Seen])
|
|
||||||
if params[:olduid].present?
|
|
||||||
@mailbox.move_message(params[:olduid],@trash_folder.full_name)
|
|
||||||
@mailbox.expunge
|
|
||||||
end
|
|
||||||
rescue MailrException => e
|
|
||||||
flash[:error] = t(e.message[:cause],:scope => e.message[:scope])
|
|
||||||
rescue Exception => e
|
|
||||||
flash[:error] = t(:general_error,:scope=>:internal) + " (" + e.class.name + " " + e.to_s + ")"
|
|
||||||
else
|
|
||||||
@attachments.each do |filename|
|
|
||||||
path = File.join(Rails.root,filename[:name])
|
|
||||||
File.delete(path) if File.exist?(path)
|
|
||||||
end
|
|
||||||
flash[:success] = t(:was_saved,:scope => :compose)
|
|
||||||
end
|
|
||||||
redirect_to :controller => 'messages', :action => 'index'
|
|
||||||
end
|
|
||||||
|
|
||||||
#FIXME edit does not support attachments
|
|
||||||
def edit
|
|
||||||
#logger.info @current_folder.inspect
|
|
||||||
#logger.info params.inspect
|
|
||||||
|
|
||||||
old_message = @current_user.messages.where('folder_id = ? and uid = ?',@current_folder,params[:id]).first
|
|
||||||
@message = Message.new
|
|
||||||
@message.to_addr = old_message.to_addr
|
|
||||||
@message.subject = old_message.subject
|
|
||||||
|
|
||||||
imap_message = @mailbox.fetch_body(old_message.uid)
|
|
||||||
mail = Mail.new(imap_message)
|
|
||||||
if mail.multipart?
|
|
||||||
@message.body = mail.text_part.nil? ? "" : mail.text_part.decoded_and_charseted.gsub(/<\/?[^>]*>/, "")
|
|
||||||
else
|
|
||||||
@message.body = mail.decoded_and_charseted.gsub(/<\/?[^>]*>/, "")
|
|
||||||
end
|
|
||||||
@attachments = []
|
|
||||||
@operation = :edit
|
|
||||||
@olduid = old_message.uid
|
|
||||||
render 'messages/compose'
|
|
||||||
end
|
|
||||||
|
|
||||||
def reply
|
|
||||||
old_message = @current_user.messages.where('folder_id = ? and uid = ?',@current_folder,params[:uids].first).first
|
|
||||||
@message = Message.new
|
|
||||||
#@message.to_addr = old_message.from_addr
|
|
||||||
#@message.to_addr = old_message.from.first
|
|
||||||
#@message.subject = old_message.subject
|
|
||||||
|
|
||||||
imap_message = @mailbox.fetch_body(old_message.uid)
|
|
||||||
mail = Mail.new(imap_message)
|
|
||||||
@message.to_addr = mail.from.first
|
|
||||||
@message.subject = mail.subject
|
|
||||||
|
|
||||||
if params[:reply_all]
|
|
||||||
@message.cc_addr = mail.cc.join('; ')
|
|
||||||
end
|
|
||||||
|
|
||||||
if mail.multipart?
|
|
||||||
@message.body = mail.text_part.nil? ? "" : mail.text_part.decoded_and_charseted.gsub(/<\/?[^>]*>/, "")
|
|
||||||
else
|
|
||||||
@message.body = mail.decoded_and_charseted.gsub(/<\/?[^>]*>/, "")
|
|
||||||
end
|
|
||||||
@attachments = []
|
|
||||||
@operation = :reply
|
|
||||||
render 'messages/compose'
|
|
||||||
end
|
|
||||||
|
|
||||||
###################################### protected section #######################################
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def send_mail_message(smtp_server,domain,username,password,msgstr,from,to)
|
|
||||||
if smtp_server.auth.nil?
|
|
||||||
smtp = Net::SMTP.start(smtp_server.name, smtp_server.port, domain)
|
|
||||||
else
|
|
||||||
smtp = Net::SMTP.start(smtp_server.name, smtp_server.port, domain, username, password, smtp_server.auth)
|
|
||||||
end
|
|
||||||
smtp.send_message msgstr, from, to
|
|
||||||
smtp.finish
|
|
||||||
end
|
|
||||||
|
|
||||||
def prepare_composed
|
|
||||||
@mail = Mail.new
|
|
||||||
@mail.subject = params[:message][:subject]
|
|
||||||
@mail.from = @current_user.full_id
|
|
||||||
#TODO check if email address is valid if not get address from contacts
|
|
||||||
@mail.to = params[:message][:to_addr]
|
|
||||||
@mail.cc = params[:message][:cc_addr]
|
|
||||||
@mail.body = params[:message][:body]
|
|
||||||
@attachments = Dir.glob(File.join($defaults["msg_upload_dir"],@current_user.username + "*"))
|
|
||||||
@attachments.each do |a|
|
|
||||||
@mail.add_file :filename => File.basename(a.gsub(/#{@current_user.username}_/,"")), :content => File.read(a)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
############################################ set_mail_defaults ####################################
|
|
||||||
|
|
||||||
def set_mail_defaults(user,server,session)
|
|
||||||
if server.auth.nil? or server.auth == 'none'
|
|
||||||
password = nil
|
|
||||||
authentication = nil
|
|
||||||
enable_starttls_auto = nil
|
|
||||||
openssl_verify_mode = nil
|
|
||||||
user_name = nil
|
|
||||||
else
|
|
||||||
password = user.get_cached_password(session)
|
|
||||||
authentication = server.auth
|
|
||||||
enable_starttls_auto = server.use_tls
|
|
||||||
openssl_verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
||||||
user_name = user.login
|
|
||||||
end
|
|
||||||
Mail.defaults do
|
|
||||||
delivery_method :smtp, {:address => server.name,
|
|
||||||
:port => server.port,
|
|
||||||
:domain => user.domain,
|
|
||||||
:user_name => user_name,
|
|
||||||
:password => password,
|
|
||||||
:authentication => authentication,
|
|
||||||
:enable_starttls_auto => enable_starttls_auto,
|
|
||||||
:openssl_verify_mode => openssl_verify_mode
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,55 +0,0 @@
|
||||||
class PrefsController < ApplicationController
|
|
||||||
|
|
||||||
before_filter :check_current_user,:selected_folder
|
|
||||||
|
|
||||||
before_filter :get_current_folders
|
|
||||||
|
|
||||||
before_filter :get_prefs, :only => [:look,:update_look]
|
|
||||||
|
|
||||||
#theme :theme_resolver
|
|
||||||
|
|
||||||
def update_look
|
|
||||||
if params[:prefs]
|
|
||||||
@prefs.update_attributes(params[:prefs])
|
|
||||||
end
|
|
||||||
flash[:success] = t(:were_saved,:scope=>:prefs)
|
|
||||||
redirect_to :action => 'look'
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_servers
|
|
||||||
|
|
||||||
redirect_to :action => 'servers'
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_identity
|
|
||||||
if params[:user]
|
|
||||||
@current_user.first_name = params[:user][:first_name]
|
|
||||||
@current_user.last_name = params[:user][:last_name]
|
|
||||||
@current_user.domain = params[:user][:domain]
|
|
||||||
if @current_user.valid?
|
|
||||||
@current_user.save
|
|
||||||
flash[:success] = t(:were_saved,:scope=>:prefs)
|
|
||||||
redirect_to :action => 'identity'
|
|
||||||
else
|
|
||||||
render 'prefs/identity'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def look
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def identity
|
|
||||||
end
|
|
||||||
|
|
||||||
def servers
|
|
||||||
@servers = @current_user.servers
|
|
||||||
end
|
|
||||||
|
|
||||||
############################# protected section ##################################
|
|
||||||
|
|
||||||
def get_prefs
|
|
||||||
@prefs = @current_user.prefs
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,91 +0,0 @@
|
||||||
class UserController < ApplicationController
|
|
||||||
|
|
||||||
#theme :theme_resolver
|
|
||||||
layout "simple"
|
|
||||||
|
|
||||||
def login
|
|
||||||
# database empty redirect to setup screen
|
|
||||||
users = User.all
|
|
||||||
if users.count.zero?
|
|
||||||
redirect_to :controller => 'user', :action => 'setup'
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def logout
|
|
||||||
reset_session
|
|
||||||
flash[:success] = t(:logged_out,:scope=>:user)
|
|
||||||
redirect_to :action => "login"
|
|
||||||
end
|
|
||||||
|
|
||||||
def authenticate
|
|
||||||
|
|
||||||
# check if user can use application
|
|
||||||
if not $defaults["only_can_logins"].nil?
|
|
||||||
if not $defaults["only_can_logins"].include?(params[:user][:login])
|
|
||||||
flash[:error] = t(:only_can_logins,:scope=>:user)
|
|
||||||
redirect_to :action => 'login'
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
user = User.find_by_login(params[:user][:login])
|
|
||||||
if user.nil?
|
|
||||||
|
|
||||||
flash[:error] = t(:login_failure,:scope=>:user)
|
|
||||||
redirect_to :action => 'login'
|
|
||||||
return false
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
session[:user_id] = user.id
|
|
||||||
user.set_cached_password(session,params[:user][:password])
|
|
||||||
|
|
||||||
if session["return_to"]
|
|
||||||
redirect = session["return_to"]
|
|
||||||
session["return_to"] = nil
|
|
||||||
redirect_to(redirect)
|
|
||||||
else
|
|
||||||
redirect_to :controller=> 'messages', :action=> 'index'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
#def loginfailure
|
|
||||||
#end
|
|
||||||
|
|
||||||
def setup
|
|
||||||
users = User.all
|
|
||||||
if !users.count.zero?
|
|
||||||
redirect_to :controller => 'internal', :action => 'allready_configured'
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
@user = User.new
|
|
||||||
@server = Server.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
|
|
||||||
@user = User.new
|
|
||||||
@user.login = params[:user][:login]
|
|
||||||
@user.first_name = params[:user][:first_name]
|
|
||||||
@user.last_name = params[:user][:last_name]
|
|
||||||
|
|
||||||
@server = Server.new
|
|
||||||
@server.name = params[:server][:name]
|
|
||||||
|
|
||||||
if @user.valid? and @server.valid?
|
|
||||||
@user.save
|
|
||||||
#@server.user_id = @user.id
|
|
||||||
#@server.save
|
|
||||||
Prefs.create_default(@user)
|
|
||||||
Server.create_server(@user,@server.name)
|
|
||||||
flash[:success] = t(:setup_done,:scope=>:user)
|
|
||||||
redirect_to :action => 'login'
|
|
||||||
else
|
|
||||||
render "setup"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
417
app/controllers/webmail_controller.rb
Normal file
417
app/controllers/webmail_controller.rb
Normal file
|
@ -0,0 +1,417 @@
|
||||||
|
require 'cdfmail'
|
||||||
|
require 'net/smtp'
|
||||||
|
require 'net/imap'
|
||||||
|
require 'mail2screen'
|
||||||
|
require 'ezcrypto'
|
||||||
|
|
||||||
|
class WebmailController < ApplicationController
|
||||||
|
include ImapUtils
|
||||||
|
|
||||||
|
# Administrative functions
|
||||||
|
before_filter :login_required
|
||||||
|
before_filter :obtain_cookies_for_search_and_nav, :only=>[:messages]
|
||||||
|
before_filter :load_imap_session
|
||||||
|
after_filter :close_imap_session
|
||||||
|
|
||||||
|
layout "public", :except => [:view_source, :download]
|
||||||
|
|
||||||
|
# model :filter, :expression, :mail_pref, :customer
|
||||||
|
|
||||||
|
BOOL_ON = "on"
|
||||||
|
|
||||||
|
def index
|
||||||
|
redirect_to(:action=>"messages")
|
||||||
|
end
|
||||||
|
|
||||||
|
def error_connection
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh
|
||||||
|
@mailbox.reload
|
||||||
|
@folders = @mailbox.folders
|
||||||
|
redirect_to(:action=>'messages')
|
||||||
|
end
|
||||||
|
|
||||||
|
def messages
|
||||||
|
session["return_to"] = nil
|
||||||
|
@search_field = params['search_field']
|
||||||
|
@search_value = params['search_value']
|
||||||
|
|
||||||
|
# handle sorting - tsort session field contains last reverse or no for field
|
||||||
|
# and lsort - last sort field
|
||||||
|
if session['tsort'].nil? or session['lsort'].nil?
|
||||||
|
session['lsort'] = "DATE"
|
||||||
|
session['tsort'] = {"DATE" => true, "FROM" => true, "SUBJECT" => true, "TO" => false}
|
||||||
|
end
|
||||||
|
|
||||||
|
case operation_param
|
||||||
|
when t(:copy) # copy
|
||||||
|
msg_ids = []
|
||||||
|
messages_param.each { |msg_id, bool|
|
||||||
|
msg_ids << msg_id.to_i if bool == BOOL_ON and dst_folder != @folder_name } if messages_param
|
||||||
|
folder.copy_multiple(msg_ids, dst_folder) if msg_ids.size > 0
|
||||||
|
when t(:move) # move
|
||||||
|
msg_ids = []
|
||||||
|
messages_param.each { |msg_id, bool|
|
||||||
|
msg_ids << msg_id.to_i if bool == BOOL_ON and dst_folder != @folder_name } if messages_param
|
||||||
|
folder.move_multiple(msg_ids, dst_folder) if msg_ids.size > 0
|
||||||
|
when t(:delete) # delete
|
||||||
|
msg_ids = []
|
||||||
|
messages_param.each { |msg_id, bool| msg_ids << msg_id.to_i if bool == BOOL_ON } if messages_param
|
||||||
|
folder.delete_multiple(msg_ids) if msg_ids.size > 0
|
||||||
|
when t(:mark_read) # mark as read
|
||||||
|
messages_param.each { |msg_id, bool| msg = folder.mark_read(msg_id.to_i) if bool == BOOL_ON } if messages_param
|
||||||
|
when t(:mark_unread) # mark as unread
|
||||||
|
messages_param.each { |msg_id, bool| msg = folder.mark_unread(msg_id.to_i) if bool == BOOL_ON } if messages_param
|
||||||
|
when "SORT"
|
||||||
|
session['lsort'] = sort_query = params["scc"]
|
||||||
|
session['tsort'][sort_query] = (session['tsort'][sort_query]? false : true)
|
||||||
|
@search_field, @search_value = session['search_field'], session['search_value']
|
||||||
|
when t(:search) # search
|
||||||
|
session['search_field'] = @search_field
|
||||||
|
session['search_value'] = @search_value
|
||||||
|
when t(:show_all) # search
|
||||||
|
session['search_field'] = @search_field = nil
|
||||||
|
session['search_value'] = @search_value = nil
|
||||||
|
else
|
||||||
|
# get search criteria from session
|
||||||
|
@search_field = session['search_field']
|
||||||
|
@search_value = session['search_value']
|
||||||
|
end
|
||||||
|
|
||||||
|
sort_query = session['lsort']
|
||||||
|
reverse_sort = session['tsort'][sort_query]
|
||||||
|
query = ["ALL"]
|
||||||
|
@page = params["page"]
|
||||||
|
@page ||= session['page']
|
||||||
|
session['page'] = @page
|
||||||
|
if @search_field and @search_value and not(@search_field.strip() == "") and not(@search_value.strip() == "")
|
||||||
|
@pages = Paginator.new self, 0, get_mail_prefs.wm_rows, @page
|
||||||
|
@messages = folder.messages_search([@search_field, @search_value], sort_query + (reverse_sort ? ' desc' : ' asc'))
|
||||||
|
else
|
||||||
|
@pages = Paginator.new self, folder.total, get_mail_prefs.wm_rows, @page
|
||||||
|
@messages = folder.messages(@pages.current.first_item - 1, get_mail_prefs.wm_rows, sort_query + (reverse_sort ? ' desc' : ' asc'))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete
|
||||||
|
@msg_id = msg_id_param.to_i
|
||||||
|
folder.delete(@msg_id)
|
||||||
|
redirect_to(:action=>"messages")
|
||||||
|
end
|
||||||
|
|
||||||
|
def reply # not ready at all
|
||||||
|
@msg_id = msg_id_param.to_i
|
||||||
|
@imapmail = folder.message(@msg_id)
|
||||||
|
fb = @imapmail.full_body
|
||||||
|
@tmail = TMail::Mail.parse(fb)
|
||||||
|
|
||||||
|
@mail = prepare_mail
|
||||||
|
@mail.reply(@tmail, fb, get_mail_prefs.mail_type)
|
||||||
|
|
||||||
|
render :action => 'compose'
|
||||||
|
end
|
||||||
|
|
||||||
|
def forward
|
||||||
|
@msg_id = msg_id_param.to_i
|
||||||
|
@imapmail = folder.message(@msg_id)
|
||||||
|
fb = @imapmail.full_body
|
||||||
|
@tmail = TMail::Mail.parse(fb)
|
||||||
|
|
||||||
|
@mail = prepare_mail
|
||||||
|
@mail.forward(@tmail, fb)
|
||||||
|
|
||||||
|
render :action => 'compose'
|
||||||
|
end
|
||||||
|
|
||||||
|
def compose
|
||||||
|
if @mail.nil?
|
||||||
|
operation = operation_param
|
||||||
|
if operation == t(:send)
|
||||||
|
@mail = create_mail
|
||||||
|
encmail = @mail.send_mail
|
||||||
|
get_imap_session
|
||||||
|
@mailbox.message_sent(encmail)
|
||||||
|
|
||||||
|
# delete temporary files (attachments)
|
||||||
|
@mail.delete_attachments()
|
||||||
|
render :action => :mailsent
|
||||||
|
elsif operation == t(:add)
|
||||||
|
@mail = create_mail
|
||||||
|
if params['attachment']
|
||||||
|
attachment = CDF::Attachment.new(@mail)
|
||||||
|
attachment.file = params['attachment']
|
||||||
|
end
|
||||||
|
else
|
||||||
|
# default - new email create
|
||||||
|
@mail = create_mail
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def empty # empty trash folder (works for any one else :-))
|
||||||
|
folder.messages(0, -1).each{ |message|
|
||||||
|
folder.delete(message)
|
||||||
|
}
|
||||||
|
folder.expunge
|
||||||
|
redirect_to(:action=>"messages")
|
||||||
|
end
|
||||||
|
|
||||||
|
def message
|
||||||
|
@msg_id = msg_id_param
|
||||||
|
@imapmail = folder.message(@msg_id)
|
||||||
|
folder.mark_read(@imapmail.uid) if @imapmail.unread
|
||||||
|
@mail = TMail::Mail.parse(@imapmail.full_body)
|
||||||
|
end
|
||||||
|
|
||||||
|
def download
|
||||||
|
msg_id = msg_id_param
|
||||||
|
imapmail = folder.message(msg_id)
|
||||||
|
mail = TMail::Mail.parse(imapmail.full_body)
|
||||||
|
|
||||||
|
if mail.multipart?
|
||||||
|
get_parts(mail).each { |part|
|
||||||
|
return send_part(part) if part.header and part.header['content-type']['name'] == params['ctype']
|
||||||
|
}
|
||||||
|
render("webmail/noattachment")
|
||||||
|
else
|
||||||
|
render("webmail/noattachment")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prefs
|
||||||
|
@customer = Customer.find(logged_customer)
|
||||||
|
@mailpref = MailPref.find_or_create_by_customer_id logged_customer
|
||||||
|
|
||||||
|
if params['op'] == _('Save')
|
||||||
|
if params['customer']
|
||||||
|
@customer.fname = params['customer']['fname']
|
||||||
|
@customer.lname = params['customer']['lname']
|
||||||
|
@customer.save
|
||||||
|
end
|
||||||
|
@mailpref.attributes = params["mailpref"]
|
||||||
|
@mailpref.save
|
||||||
|
session["wmimapseskey"] = nil
|
||||||
|
redirect_to(:action=>"messages")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Message filters management
|
||||||
|
def filters
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter
|
||||||
|
if params['op']
|
||||||
|
@filter = Filter.new(params['filter'])
|
||||||
|
@filter.customer_id = logged_customer
|
||||||
|
params['expression'].each { |index, expr| @filter.expressions << Expression.new(expr) unless expr["expr_value"].nil? or expr["expr_value"].strip == "" }
|
||||||
|
case params['op']
|
||||||
|
when _('Add')
|
||||||
|
@filter.expressions << Expression.new
|
||||||
|
when _('Save')
|
||||||
|
if params['filter']['id'] and params['filter']['id'] != ""
|
||||||
|
@sf = Filter.find(params['filter']['id'])
|
||||||
|
@sf.name, @sf.destination_folder = @filter.name, @filter.destination_folder
|
||||||
|
@sf.expressions.each{|expr| Expression.delete(expr.id) }
|
||||||
|
@filter.expressions.each {|expr| @sf.expressions << Expression.create(expr.attributes) }
|
||||||
|
else
|
||||||
|
@sf = Filter.create(@filter.attributes)
|
||||||
|
@sf.order_num = @user.filters.size
|
||||||
|
@filter.expressions.each {|expr| @sf.expressions << Expression.create(expr.attributes) }
|
||||||
|
end
|
||||||
|
# may be some validation will be needed
|
||||||
|
@sf.save
|
||||||
|
@user.serialize_to_file
|
||||||
|
return redirect_to(:action=>"filters")
|
||||||
|
end
|
||||||
|
@expressions = @filter.expressions
|
||||||
|
else
|
||||||
|
@filter = Filter.find(params["id"]) if params["id"]
|
||||||
|
@expressions = @filter.expressions
|
||||||
|
end
|
||||||
|
@destfolders = get_to_folders
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_delete
|
||||||
|
Filter.delete(params["id"])
|
||||||
|
# reindex other filters
|
||||||
|
@user = Customer.find(logged_customer)
|
||||||
|
findex = 0
|
||||||
|
@user.filters.each { |filter|
|
||||||
|
findex = findex + 1
|
||||||
|
filter.order_num = findex
|
||||||
|
filter.save
|
||||||
|
}
|
||||||
|
@user.serialize_to_file
|
||||||
|
redirect_to :action=>"filters"
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_up
|
||||||
|
filt = @user.filters.find(params['id'])
|
||||||
|
ufilt = @user.filters.find_all("order_num = #{filt.order_num - 1}").first
|
||||||
|
ufilt.order_num = ufilt.order_num + 1
|
||||||
|
filt.order_num = filt.order_num - 1
|
||||||
|
ufilt.save
|
||||||
|
filt.save
|
||||||
|
@user.serialize_to_file
|
||||||
|
redirect_to :action=>"filters"
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_down
|
||||||
|
filt = Filter.find(params["id"])
|
||||||
|
dfilt = @user.filters[filt.order_num]
|
||||||
|
dfilt.order_num = dfilt.order_num - 1
|
||||||
|
filt.order_num = filt.order_num + 1
|
||||||
|
dfilt.save
|
||||||
|
filt.save
|
||||||
|
@user.serialize_to_file
|
||||||
|
redirect_to :action=>"filters"
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_add
|
||||||
|
@filter = Filter.new
|
||||||
|
@filter.expressions << Expression.new
|
||||||
|
@expressions = @filter.expressions
|
||||||
|
@destfolders = get_to_folders
|
||||||
|
render "filter"
|
||||||
|
end
|
||||||
|
# end of filters
|
||||||
|
|
||||||
|
def view_source
|
||||||
|
@msg_id = msg_id_param.to_i
|
||||||
|
@imapmail = folder.message(@msg_id)
|
||||||
|
@msg_source = CGI.escapeHTML(@imapmail.full_body).gsub("\n", "<br/>")
|
||||||
|
end
|
||||||
|
|
||||||
|
def auto_complete_for_mail_to
|
||||||
|
auto_complete_responder_for_contacts params[:mail][:to]
|
||||||
|
end
|
||||||
|
|
||||||
|
def auto_complete_for_mail_cc
|
||||||
|
auto_complete_responder_for_contacts params[:mail][:cc]
|
||||||
|
end
|
||||||
|
|
||||||
|
def auto_complete_for_mail_bcc
|
||||||
|
auto_complete_responder_for_contacts params[:mail][:bcc]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def auto_complete_responder_for_contacts(value)
|
||||||
|
# first split by "," and take last name
|
||||||
|
searchName = value.split(',').last.strip
|
||||||
|
|
||||||
|
# if there are 2 names search by them
|
||||||
|
if searchName.split.size > 1
|
||||||
|
fname, lname = searchName.split.first, searchName.split.last
|
||||||
|
conditions = ['customer_id = ? and LOWER(fname) LIKE ? and LOWER(lname) like ?', logged_customer, fname.downcase + '%', lname.downcase + '%']
|
||||||
|
else
|
||||||
|
conditions = ['customer_id = ? and LOWER(fname) LIKE ?', logged_customer, searchName.downcase + '%']
|
||||||
|
end
|
||||||
|
@contacts = Contact.find(:all, :conditions => conditions, :order => 'fname ASC',:limit => 8)
|
||||||
|
render :partial => 'contacts'
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def additional_scripts()
|
||||||
|
@additional_css = ["webmail/webmail"]
|
||||||
|
@additional_js = ["webmail"]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def get_to_folders
|
||||||
|
res = Array.new
|
||||||
|
@folders.each{|f| res << f unless f.name == CDF::CONFIG[:mail_sent] or f.name == CDF::CONFIG[:mail_inbox] }
|
||||||
|
res
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def create_mail
|
||||||
|
m = CDF::Mail.new(user.mail_temporary_path)
|
||||||
|
if params["mail"]
|
||||||
|
ma = params["mail"]
|
||||||
|
m.body, m.content_type, m.from, m.to, m.cc, m.bcc, m.subject = ma["body"], ma["content_type"], ma["from"], ma["to"], ma["cc"], ma["bcc"], ma["subject"]
|
||||||
|
if params["att_files"]
|
||||||
|
att_files, att_tfiles, att_ctypes = params["att_files"], params["att_tfiles"], params["att_ctypes"]
|
||||||
|
att_files.each {|i, value|
|
||||||
|
att = CDF::Attachment.new(m)
|
||||||
|
att.filename, att.temp_filename, att.content_type = value, att_tfiles[i], att_ctypes[i]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
m.from, m.content_type = user.friendlly_local_email, get_mail_prefs.mail_type
|
||||||
|
end
|
||||||
|
m.customer_id = logged_customer
|
||||||
|
m
|
||||||
|
end
|
||||||
|
|
||||||
|
def prepare_mail
|
||||||
|
m = CDF::Mail.new(user.mail_temporary_path)
|
||||||
|
m.from, m.content_type = user.friendlly_local_email, get_mail_prefs.mail_type
|
||||||
|
m
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def send_part(part)
|
||||||
|
if part.content_type == "text/html"
|
||||||
|
disposition = "inline"
|
||||||
|
elsif part.content_type.include?("image/")
|
||||||
|
disposition = "inline"
|
||||||
|
else
|
||||||
|
disposition = "attachment"
|
||||||
|
end
|
||||||
|
headers['Content-Length'] = part.body.size
|
||||||
|
response.headers['Accept-Ranges'] = 'bytes'
|
||||||
|
headers['Content-type'] = part.content_type.strip
|
||||||
|
headers['Content-Disposition'] = disposition << %(; filename="#{part.header['content-type']['name']}")
|
||||||
|
render :text => part.body
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_parts(mail)
|
||||||
|
parts = Array.new
|
||||||
|
parts << mail
|
||||||
|
mail.parts.each { |part|
|
||||||
|
if part.multipart?
|
||||||
|
parts = parts.concat(get_parts(part))
|
||||||
|
elsif part.content_type and part.content_type.include?("rfc822")
|
||||||
|
parts = parts.concat(get_parts(TMail::Mail.parse(part.body))) << part
|
||||||
|
else
|
||||||
|
parts << part
|
||||||
|
end
|
||||||
|
}
|
||||||
|
parts
|
||||||
|
end
|
||||||
|
|
||||||
|
def obtain_cookies_for_search_and_nav
|
||||||
|
@srch_class = ((cookies['_wmlms'] and cookies['_wmlms'] == 'closed') ? 'closed' : 'open')
|
||||||
|
@srch_img_src = ((cookies['_wmlms'] and cookies['_wmlms'] == 'closed') ? 'closed' : 'opened')
|
||||||
|
@ops_class = ((cookies['_wmlmo'] and cookies['_wmlmo'] == 'closed') ? 'closed' : 'open')
|
||||||
|
@ops_img_src = ((cookies['_wmlmo'] and cookies['_wmlmo'] == 'closed') ? 'closed' : 'opened')
|
||||||
|
end
|
||||||
|
|
||||||
|
###################################################################
|
||||||
|
### Some fixed parameters and session variables
|
||||||
|
###################################################################
|
||||||
|
def folder
|
||||||
|
@folders[@folder_name]
|
||||||
|
end
|
||||||
|
|
||||||
|
def msg_id_param
|
||||||
|
params["msg_id"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def messages_param
|
||||||
|
params["messages"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def dst_folder
|
||||||
|
params["cpdest"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def operation_param
|
||||||
|
params["op"]
|
||||||
|
end
|
||||||
|
end
|
450
app/helpers/application_helper.rb
Executable file → Normal file
450
app/helpers/application_helper.rb
Executable file → Normal file
|
@ -1,334 +1,138 @@
|
||||||
require 'iconv'
|
# The methods added to this helper will be available to all templates in the application.
|
||||||
|
|
||||||
module ApplicationHelper
|
module ApplicationHelper
|
||||||
|
include NavigationHelper
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
#def form_field(object,field,flabel,example,val)
|
def format_datetime(datetime)
|
||||||
#model_name = eval(object.class.model_name)
|
datetime.strftime "%d.%m.%Y %H:%M"
|
||||||
#html = ""
|
end
|
||||||
#html << "<div class=\"param_group\">"
|
|
||||||
#if not object.errors[field.to_sym].empty?
|
|
||||||
#html << "<div class=\"fieldWithErrors\">"
|
|
||||||
|
|
||||||
#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
|
||||||
|
|
||||||
#html << "<label class=\"label\">"
|
# Useful abstraction for form input fields - combines an input field with error message (if any)
|
||||||
#flabel.nil? ? html << model_name.human_attribute_name(field) : html << t(flabel.to_sym)
|
# and writes an appropriate style (for errors)
|
||||||
#html << "</label>"
|
# 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
|
||||||
|
|
||||||
#if not object.errors[field.to_sym].empty?
|
# Helper method that has the same signature as real input field helpers, but simply displays
|
||||||
#html << "<span class=\"error\"> "
|
# the value of a given field enclosed within <p> </p> tags.
|
||||||
#html << object.errors[field.to_sym].to_s
|
# Usage:
|
||||||
#html << "</span>"
|
# <%= form_input :read_only_field, 'new_user', 'name', _('user_name')) %>
|
||||||
#html << "</div>"
|
def read_only_field(form_name, field_name, html_options)
|
||||||
#end
|
"<span #{attributes(html_options)}>#{instance_variable_get('@' + form_name)[field_name]}</span>"
|
||||||
#html << "<input id=\""
|
end
|
||||||
#html << object.class.name.downcase+"_"+field
|
|
||||||
#html << "\""
|
|
||||||
#html << " name=\"#{object.class.name.downcase}[#{field}]\""
|
|
||||||
#html << " type=\"text\" class=\"text_field\" value=\""
|
|
||||||
#value = val || object.instance_eval(field) || ""
|
|
||||||
#html << value
|
|
||||||
#html << "\"/>"
|
|
||||||
#html << "<span class=\"description\">"
|
|
||||||
#html << t(:example,:scope=>:common)
|
|
||||||
#html << ": "
|
|
||||||
#html << example
|
|
||||||
#html << "</span>"
|
|
||||||
#html << "</div>"
|
|
||||||
|
|
||||||
#end
|
def submit_button(form_name, prompt, html_options)
|
||||||
|
%{<input name="submit" type="submit" value="#{prompt}" />}
|
||||||
|
end
|
||||||
|
|
||||||
#def show_param_view(object,field,value)
|
# Converts a hash to XML attributes string. E.g.:
|
||||||
#model_name = eval(object.class.model_name)
|
# to_attributes('a' => 'aaa', 'b' => 1)
|
||||||
#html = ""
|
# => 'a="aaa" b="1" '
|
||||||
#html << "<div class=\"group clearfix\">"
|
def attributes(hash)
|
||||||
#html << "<label class=\"label\">#{model_name.human_attribute_name(field)}: </label>"
|
hash.keys.inject("") { |attrs, key| attrs + %{#{key}="#{hash[key]}" } }
|
||||||
#html << value
|
end
|
||||||
#html << "</div>"
|
|
||||||
#html
|
def initListClass
|
||||||
#end
|
@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 area_field(object,field,flabel,example,val,cols,rows)
|
def link_main
|
||||||
#model_name = eval(object.class.model_name)
|
link_to( t(:contacts), contacts_path)
|
||||||
#html = ""
|
end
|
||||||
#html << "<div class=\"group\">"
|
|
||||||
|
|
||||||
#if not object.errors[field.to_sym].empty?
|
def alternator
|
||||||
#html << "<div class=\"fieldWithErrors\">"
|
if @alternator.nil?
|
||||||
#end
|
@alternator = 1
|
||||||
|
end
|
||||||
#html << "<label class=\"label\">"
|
|
||||||
#flabel.nil? ? html << model_name.human_attribute_name(field) : html << t(flabel.to_sym)
|
@alternator = -@alternator
|
||||||
#html << "</label>"
|
|
||||||
|
if @alternator == -1
|
||||||
#if not object.errors[field.to_sym].empty?
|
return "even"
|
||||||
#html << "<span class=\"error\">"
|
else
|
||||||
#html << object.errors[field.to_sym].to_s
|
return "odd"
|
||||||
#html << "</span>"
|
end
|
||||||
#html << "</div>"
|
end
|
||||||
#end
|
|
||||||
|
|
||||||
#name = object.class.name.downcase + '[' + field + ']'
|
|
||||||
#id = object.class.name.downcase+"_"+field
|
|
||||||
#value = val || object.instance_eval(field) || ""
|
|
||||||
#html << "<textarea id=\"#{id}\" name=\"#{name}\" class=\"text_area\" cols=\"#{cols}\" rows=\"#{rows}\">#{value}</textarea>"
|
|
||||||
|
|
||||||
#desc = t(:example,:scope=>:common) + ": " + example
|
|
||||||
#html << "<span class=\"description\">#{desc}</span>"
|
|
||||||
|
|
||||||
#html << "</div>"
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def form_button(text,image)
|
|
||||||
#html = ""
|
|
||||||
#html << "<div class=\"group\">"
|
|
||||||
#html << "<button class=\"button\" type=\"submit\">"
|
|
||||||
#html << "<img src=\""
|
|
||||||
#html << current_theme_image_path(image)
|
|
||||||
#html << "\" alt=\""
|
|
||||||
#html << t(text.to_sym)
|
|
||||||
#html << "\" />"
|
|
||||||
#html << t(text.to_sym)
|
|
||||||
#html << "</button></div>"
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def single_action(text,scope,image)
|
|
||||||
#html = ""
|
|
||||||
#html << "<div class=\"actiongroup clearfix\">"
|
|
||||||
#html << "<button class=\"button\" name=\"#{text}\" type=\"submit\">"
|
|
||||||
#html << "<img src=\""
|
|
||||||
#html << current_theme_image_path(image)
|
|
||||||
#html << "\" alt=\""
|
|
||||||
#html << t(text.to_sym, :scope => scope.to_sym)
|
|
||||||
#html << "\" />"
|
|
||||||
#html << t(text.to_sym, :scope => scope.to_sym)
|
|
||||||
#html << "</button></div>"
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def single_action_onclick(text,scope,image,onclick)
|
|
||||||
#html = ""
|
|
||||||
#html << "<div class=\"actiongroup clearfix\">"
|
|
||||||
#html << "<button class=\"button\" type=\"submit\" onclick=\"window.location='"
|
|
||||||
#html << onclick
|
|
||||||
#html << "'\">"
|
|
||||||
#html << "<img src=\""
|
|
||||||
#html << current_theme_image_path(image)
|
|
||||||
#html << "\" alt=\""
|
|
||||||
#html << t(text.to_sym, :scope => scope.to_sym)
|
|
||||||
#html << "\" />"
|
|
||||||
#html << t(text.to_sym, :scope => scope.to_sym)
|
|
||||||
#html << "</button>"
|
|
||||||
#html << "</div>"
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def group_action(buttons)
|
|
||||||
#html = ""
|
|
||||||
#html << "<div class=\"actiongroup clearfix\">"
|
|
||||||
#buttons.each do |b|
|
|
||||||
#html << "<button class=\"button\" type=\"submit\" name=\"#{b[:text]}\">"
|
|
||||||
#html << "<img src=\""
|
|
||||||
#html << current_theme_image_path(b[:image])
|
|
||||||
#html << "\" alt=\""
|
|
||||||
#html << t(b[:text].to_sym,:scope=>b[:scope].to_sym)
|
|
||||||
#html << "\" />"
|
|
||||||
#html << t(b[:text].to_sym,:scope=>b[:scope].to_sym)
|
|
||||||
#html << "</button> "
|
|
||||||
#end
|
|
||||||
#html << "</div>"
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def group_action_text(buttons,text)
|
|
||||||
#html = ""
|
|
||||||
#html << "<div class=\"group\">"
|
|
||||||
#buttons.each do |b|
|
|
||||||
#html << "<button class=\"button\" type=\"submit\" name=\"#{b[:text]}\">"
|
|
||||||
#html << "<img src=\""
|
|
||||||
#html << current_theme_image_path(b[:image])
|
|
||||||
#html << "\" alt=\""
|
|
||||||
#html << t(b[:text].to_sym,:scope=>b[:scope].to_sym)
|
|
||||||
#html << "\" />"
|
|
||||||
#html << t(b[:text].to_sym,:scope=>b[:scope].to_sym)
|
|
||||||
#html << "</button> "
|
|
||||||
#end
|
|
||||||
#html << text
|
|
||||||
#html << "</div>"
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def form_buttons(buttons)
|
|
||||||
#html = ""
|
|
||||||
#html << "<div class=\"group\">"
|
|
||||||
|
|
||||||
#buttons.each do |b|
|
|
||||||
#html << "<button class=\"button\" type=\"submit\" name=\"#{b[:text]}\">"
|
|
||||||
#html << "<img src=\""
|
|
||||||
#html << current_theme_image_path(b[:image])
|
|
||||||
#html << "\" alt=\""
|
|
||||||
#html << t(b[:text].to_sym)
|
|
||||||
#html << "\" />"
|
|
||||||
#html << t(b[:text].to_sym)
|
|
||||||
#html << "</button> "
|
|
||||||
#end
|
|
||||||
|
|
||||||
#html << "</div>"
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def form_button_value(text,image,onclick)
|
|
||||||
#html = ""
|
|
||||||
#html << "<div class=\"group\">"
|
|
||||||
#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,id,label,value)
|
|
||||||
#html = ""
|
|
||||||
#html << "<div class=\"param_group\">"
|
|
||||||
#html << "<label class=\"label\">#{label}</label>"
|
|
||||||
#html << "<input name=\"#{name}[#{id}]\" id=\"#{name}_#{id} 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 select_field_table(object,field,table_choices,choice,blank)
|
|
||||||
#model_name = eval(object.class.model_name)
|
|
||||||
#html = ""
|
|
||||||
#html << "<div class=\"param_group\">"
|
|
||||||
#html << "<label class=\"label\">#{model_name.human_attribute_name(field)}</label>"
|
|
||||||
#html << select(object.class.to_s.downcase, field, options_for_select(table_choices,choice), {:include_blank => blank})
|
|
||||||
#html << "</div>"
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def select_field_table_t(object,field,table_choices,choice,blank)
|
|
||||||
#model_name = eval(object.class.model_name)
|
|
||||||
#html = ""
|
|
||||||
#html << "<div class=\"param_group\">"
|
|
||||||
#html << "<label class=\"label\">#{model_name.human_attribute_name(field)}</label>"
|
|
||||||
#t = []
|
|
||||||
#table_choices.each do |c|
|
|
||||||
#t << [t(c.to_sym,:scope=>:prefs),c.to_s]
|
|
||||||
#end
|
|
||||||
#html << select(object.class.to_s.downcase, field, options_for_select(t,choice), {:include_blank => blank})
|
|
||||||
#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,:scope=>:folder), :controller=>:folders, :action=>:index )
|
|
||||||
##end
|
|
||||||
##
|
|
||||||
##def nav_to_messages
|
|
||||||
## link_to( t(:messages,:scope=>:message), :controller=>:messages, :action=>:index )
|
|
||||||
##end
|
|
||||||
##
|
|
||||||
##def nav_to_compose
|
|
||||||
## link_to( t(:compose,:scope=>:compose), :controller=>:messages, :action=>:compose )
|
|
||||||
##end
|
|
||||||
##
|
|
||||||
##def nav_to_contacts
|
|
||||||
## link_to( t(:contacts,:scope=>:contact), contacts_path )
|
|
||||||
##end
|
|
||||||
##
|
|
||||||
##def nav_to_prefs
|
|
||||||
## link_to( t(:prefs,:scope=>:prefs), prefs_look_path )
|
|
||||||
##end
|
|
||||||
|
|
||||||
#def single_navigation(label,scope)
|
|
||||||
#s = ""
|
|
||||||
#s += "<ul>"
|
|
||||||
#s += "<li class=\"first active\">#{link_to(t(label,:scope=>scope),'#')}</li>"
|
|
||||||
#s += "<li class=\"last\"> </li>"
|
|
||||||
#s += "</ul>"
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def main_navigation(active)
|
|
||||||
#instance_variable_set("@#{active}", "active")
|
|
||||||
#s = ""
|
|
||||||
#s += "<ul>"
|
|
||||||
#s += "<li class=\"first #{@messages_tab}\">#{link_to( t(:messages,:scope=>:message), messages_path )}</li>"
|
|
||||||
#s += "<li class=\"#{@compose_tab}\">#{link_to( t(:compose,:scope=>:compose), compose_path )}</li>"
|
|
||||||
#s += "<li class=\"#{@folders_tab}\">#{link_to( t(:folders,:scope=>:folder), folders_path )}</li>"
|
|
||||||
#s += "<li class=\"#{@contacts_tab}\">#{link_to( t(:contacts,:scope=>:contact), contacts_path )}</li>"
|
|
||||||
#s += "<li class=\"#{@prefs_tab}\">#{link_to( t(:prefs,:scope=>:prefs), prefs_look_path )}</li>"
|
|
||||||
#s += "<li class=\"last #{@links_tab}\">#{link_to( t(:links,:scope=>:link), links_path )}</li>"
|
|
||||||
#s += "</ul>"
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def prefs_navigation(active)
|
|
||||||
#instance_variable_set("@#{active}", "active")
|
|
||||||
#s = ""
|
|
||||||
#s += "<ul>"
|
|
||||||
#s += "<li class=\"first #{@look_tab}\">#{link_to( t(:look,:scope=>:prefs), prefs_look_path )}</li>"
|
|
||||||
#s += "<li class=\"#{@identity_tab}\">#{link_to( t(:identity,:scope=>:prefs), prefs_identity_path )}</li>"
|
|
||||||
#s += "<li class=\"last #{@servers_tab}\">#{link_to( t(:servers,:scope=>:prefs), prefs_servers_path )}</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}> #{option_content} </option>\n"
|
|
||||||
#end
|
|
||||||
#"<div class=\"param_group\"><label class=\"label\">#{label}</label><select multiple=\"multiple\" size=10 id=\"#{id}\" name=\"#{name}\">\n#{options}</select></div>"
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def force_charset(text)
|
|
||||||
#begin
|
|
||||||
#Iconv.iconv("UTF-8",$defaults["msg_unknown_charset"],text)
|
|
||||||
#rescue
|
|
||||||
#text
|
|
||||||
#end
|
|
||||||
#end
|
|
||||||
|
|
||||||
#def content_for_sidebar
|
|
||||||
#s = render :partial => 'sidebar/logo'
|
|
||||||
#s += render :partial => 'folders/list'
|
|
||||||
#s += render :partial => 'sidebar/calendar_view'
|
|
||||||
#s += render :partial => 'internal/version'
|
|
||||||
#s
|
|
||||||
#end
|
|
||||||
|
|
||||||
def boolean_answer(answer)
|
|
||||||
answer == true ? t(:true_answer,:scope=>:common) : t(:false_answer,:scope=>:common)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
4
app/helpers/contact_group_helper.rb
Normal file
4
app/helpers/contact_group_helper.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module ContactGroupHelper
|
||||||
|
def link_save() "/contact_group/save" end
|
||||||
|
def link_list() "/contact_group/list" end
|
||||||
|
end
|
20
app/helpers/contacts_helper.rb
Executable file → Normal file
20
app/helpers/contacts_helper.rb
Executable file → Normal file
|
@ -1,17 +1,3 @@
|
||||||
module ContactsHelper
|
module ContactsHelper
|
||||||
|
|
||||||
def contacts_table_header
|
end
|
||||||
html = ""
|
|
||||||
$defaults["contacts_table_fields"].each do |f|
|
|
||||||
html << "<th>"
|
|
||||||
if params[:sort_field] == f
|
|
||||||
params[:sort_dir].nil? ? dir = 'desc' : dir = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
html << link_to(Contact.human_attribute_name(f), {:controller => 'contacts',:action => 'index',:sort_field => f,:sort_dir => dir}, {:class=>"header"})
|
|
||||||
html << "</th>"
|
|
||||||
end
|
|
||||||
html
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
module FolderHelper
|
|
||||||
|
|
||||||
def folder_link(options={})
|
|
||||||
|
|
||||||
folder = options[:folder]
|
|
||||||
active = ""
|
|
||||||
if options[:active]
|
|
||||||
active = "icon-white"
|
|
||||||
end
|
|
||||||
|
|
||||||
folder.parent.empty? ? name = folder.name : name = folder.parent.gsub(/\./,'#') + "#" + folder.name
|
|
||||||
|
|
||||||
if folder.isInbox?
|
|
||||||
name_shown = "<i class=\"icon-inbox #{active}\"></i>" + t(:inbox_name,:scope => :folder)
|
|
||||||
elsif folder.isSent?
|
|
||||||
name_shown = "<i class=\"icon-plane #{active}\"></i>" + t(:sent_name,:scope => :folder)
|
|
||||||
elsif folder.isDrafts?
|
|
||||||
name_shown = "<i class=\"icon-book #{active}\"></i>" + t(:drafts_name,:scope => :folder)
|
|
||||||
elsif folder.isTrash?
|
|
||||||
name_shown = "<i class=\"icon-trash #{active}\"></i>" +t(:trash_name,:scope => :folder)
|
|
||||||
else
|
|
||||||
name_shown = "<i class=\"icon-none\"></i>" + folder.name.capitalize
|
|
||||||
end
|
|
||||||
|
|
||||||
if folder.isTrash?
|
|
||||||
if not folder.total.zero?
|
|
||||||
name_shown += " <button class=\"btn btn-mini btn-danger\" onclick=\"window.location='#{folders_emptybin_path}'\" href=\"#\">#{t(:emptybin,:scope=>:folder)}</button>"
|
|
||||||
#name_shown += raw link_to(t(:emptybin,:scope=>:folder),folders_emptybin_path)
|
|
||||||
#name_shown += ')'
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if !folder.unseen.zero?
|
|
||||||
name_shown += ' (' + folder.unseen.to_s + ')'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
link_to name_shown.html_safe, folders_select_path(:id => name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pretty_folder_name(folder)
|
|
||||||
if folder.nil?
|
|
||||||
t(:no_selected,:scope=>:folder)
|
|
||||||
else
|
|
||||||
if folder.isInbox?
|
|
||||||
t(:inbox_name,:scope => :folder)
|
|
||||||
elsif folder.isSent?
|
|
||||||
t(:sent_name,:scope => :folder)
|
|
||||||
elsif folder.isDrafts?
|
|
||||||
t(:drafts_name,:scope => :folder)
|
|
||||||
elsif folder.isTrash?
|
|
||||||
t(:trash_name,:scope => :folder)
|
|
||||||
else
|
|
||||||
folder.name.capitalize
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def select_for_folders(name,id,collection,label,choice,blank)
|
|
||||||
html = ""
|
|
||||||
html << "<div class=\"param_group\">"
|
|
||||||
html << "<label class=\"label\">#{label}</label>"
|
|
||||||
html << simple_select_for_folders(name,id,collection,choice,blank)
|
|
||||||
html << "</div>"
|
|
||||||
end
|
|
||||||
|
|
||||||
def simple_select_for_folders(name,id,collection,choice,blank)
|
|
||||||
html = ""
|
|
||||||
html << select(name , id, options_from_collection_for_select(collection, 'id', 'full_name', choice),{ :include_blank => (blank == true ? true : false)})
|
|
||||||
html
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
2
app/helpers/folders_helper.rb
Normal file
2
app/helpers/folders_helper.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
module FoldersHelper
|
||||||
|
end
|
|
@ -1,2 +0,0 @@
|
||||||
module InternalHelper
|
|
||||||
end
|
|
|
@ -1,17 +0,0 @@
|
||||||
module LinksHelper
|
|
||||||
|
|
||||||
def links_table_header
|
|
||||||
html = ""
|
|
||||||
$defaults["links_table_fields"].each do |f|
|
|
||||||
html << "<th>"
|
|
||||||
if params[:sort_field] == f
|
|
||||||
params[:sort_dir].nil? ? dir = 'desc' : dir = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
html << link_to(Link.human_attribute_name(f), {:controller => 'links',:action => 'index',:sort_field => f,:sort_dir => dir}, {:class=>"header"})
|
|
||||||
html << "</th>"
|
|
||||||
end
|
|
||||||
html
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,130 +0,0 @@
|
||||||
module MessagesHelper
|
|
||||||
|
|
||||||
def size_formatter(size)
|
|
||||||
if size <= 2**10
|
|
||||||
"#{size} #{t(:bytes,:scope=>:common)}"
|
|
||||||
elsif size <= 2**20
|
|
||||||
sprintf("%.1f #{t(:kbytes,:scope=>:common)}",size.to_f/2**10)
|
|
||||||
else
|
|
||||||
sprintf("%.1f #{t(:mbytes,:scope=>:common)}",size.to_f/2**20)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def date_formatter(date)
|
|
||||||
date.nil? ? t(:no_date,:scope=>:message) : date.strftime("%Y-%m-%d %H:%M")
|
|
||||||
end
|
|
||||||
|
|
||||||
def address_formatter(addr,op)
|
|
||||||
return "" if addr.nil?
|
|
||||||
s = ""
|
|
||||||
return t(:no_address,:scope=>:message) if addr.empty?
|
|
||||||
length = $defaults["msg_address_length"].to_i
|
|
||||||
|
|
||||||
case op
|
|
||||||
when :index
|
|
||||||
logger.custom('addr',addr)
|
|
||||||
fs = addr.gsub(/\"/,"").split(/</)
|
|
||||||
fs[0].size.zero? ? s = fs[1] : s = fs[0]
|
|
||||||
s.length >= length ? s = s[0,length]+"..." : s
|
|
||||||
return h(s)
|
|
||||||
when :show
|
|
||||||
#addr = addr[0].charseted.gsub(/\"/,"")
|
|
||||||
return h(addr.gsub(/\"/,""))
|
|
||||||
when :raw
|
|
||||||
#fs = addr.gsub(/\"/,"").split(/</)
|
|
||||||
#fs[0].size.zero? ? s = fs[1] : s << fs[0] + " <" + fs[1] + ">"
|
|
||||||
s = h(addr)
|
|
||||||
return s
|
|
||||||
when :reply
|
|
||||||
return addr
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def body_formatter(body,op)
|
|
||||||
case op
|
|
||||||
when :reply
|
|
||||||
s = "\n\n\n"
|
|
||||||
body.split(/\n/).each do |line|
|
|
||||||
s += '>' + line.strip + "\n"
|
|
||||||
end
|
|
||||||
s
|
|
||||||
when :edit
|
|
||||||
return body
|
|
||||||
when :plain
|
|
||||||
safe_body = h(body)
|
|
||||||
s = ""
|
|
||||||
safe_body.split(/\n/).each do |line|
|
|
||||||
s += line.gsub(/^\s+/,"") + "<br/>"
|
|
||||||
end
|
|
||||||
s.html_safe
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def subject_formatter(message,op)
|
|
||||||
case op
|
|
||||||
when :index
|
|
||||||
if message.subject.nil? or message.subject.size.zero?
|
|
||||||
s = t(:no_subject,:scope=>:message)
|
|
||||||
else
|
|
||||||
length = $defaults["msg_subject_length"].to_i
|
|
||||||
message.subject.length >= length ? s = message.subject[0,length]+"..." : s = message.subject
|
|
||||||
end
|
|
||||||
link_to s,{:controller => 'messages', :action => 'show', :id => message.uid} , :title => message.subject
|
|
||||||
when :show
|
|
||||||
if message.subject.nil? or message.subject.size.zero?
|
|
||||||
t(:no_subject,:scope=>:message)
|
|
||||||
else
|
|
||||||
message.subject
|
|
||||||
end
|
|
||||||
when :reply
|
|
||||||
if message.nil? or message.size.zero?
|
|
||||||
t(:reply_string,:scope=>:show)
|
|
||||||
else
|
|
||||||
t(:reply_string,:scope=>:show) + " " + message
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def attachment_formatter(message)
|
|
||||||
message.content_type =~ /^text\/plain/ ? "" : "<i class=\"icon-file\"></i>"
|
|
||||||
end
|
|
||||||
|
|
||||||
def headers_links
|
|
||||||
#if @current_folder.hasFullName?(@folder_sent_name) || @current_folder.hasFullName?(@folder_drafts_name)
|
|
||||||
if @current_folder == @sent_folder || @current_folder == @drafts_folder
|
|
||||||
fields = $defaults["msgs_sent_view_fields"]
|
|
||||||
else
|
|
||||||
fields = $defaults["msgs_inbox_view_fields"]
|
|
||||||
end
|
|
||||||
|
|
||||||
html = ""
|
|
||||||
fields.each do |f|
|
|
||||||
html << "<th>"
|
|
||||||
if params[:sort_field] == f
|
|
||||||
params[:sort_dir].nil? ? dir = 'desc' : dir = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
html << link_to(Message.human_attribute_name(f), {:controller => 'messages',:action => 'index',:sort_field => f,:sort_dir => dir}, {:class=>"header"})
|
|
||||||
html << "</th>"
|
|
||||||
end
|
|
||||||
if @current_folder == @drafts_folder
|
|
||||||
html << "<th> </th>"
|
|
||||||
end
|
|
||||||
html
|
|
||||||
end
|
|
||||||
|
|
||||||
#def content_text_plain_for_render(text)
|
|
||||||
#html = "<pre class=\"clearfix\">"
|
|
||||||
##html << text.gsub!(/\r\n/,"\n")
|
|
||||||
#html << h(text)
|
|
||||||
#html << "</pre>"
|
|
||||||
#html
|
|
||||||
#end
|
|
||||||
|
|
||||||
def humanize_attr(object,attr)
|
|
||||||
model_name = eval(object.class.model_name)
|
|
||||||
return model_name.human_attribute_name(attr)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
module MessagesOpsHelper
|
|
||||||
end
|
|
60
app/helpers/navigation_helper.rb
Normal file
60
app/helpers/navigation_helper.rb
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
module NavigationHelper
|
||||||
|
def link_back_to_messages
|
||||||
|
link_to("«" << t(:back_to_message), :controller=>"webmail", :action=>"messages")
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_send_mail
|
||||||
|
link_to( t(:compose), :controller=>"webmail", :action=>"compose")
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_mail_prefs
|
||||||
|
link_to( t(:preferences), :controller=>"webmail", :action=>"prefs")
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_mail_filters
|
||||||
|
link_to( t(:filters), :controller=>"webmail", :action=>"filters")
|
||||||
|
end
|
||||||
|
|
||||||
|
def folder_manage_link(folder)
|
||||||
|
if folder.name == CDF::CONFIG[:mail_trash] or folder.name == CDF::CONFIG[:mail_inbox] or folder.name == CDF::CONFIG[:mail_sent]
|
||||||
|
short_fn(folder)
|
||||||
|
else
|
||||||
|
short_fn(folder) + ' ' + link_to(t(:delete), folder_path(folder.name), :method => :delete)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_import_preview() "/contacts/import_preview" end
|
||||||
|
def link_main_index() root_url end
|
||||||
|
def link_contact_import() url_for(:controller => :contacts, :action => :import) end
|
||||||
|
def link_contact_choose() url_for(:controller => :contacts, :action => :choose) end
|
||||||
|
|
||||||
|
def link_contact_list
|
||||||
|
link_to(t(:list), :controller => :contacts, :action => :index)
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_contact_add_one
|
||||||
|
link_to(t(:add_one_contact), new_contact_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_contact_add_multiple
|
||||||
|
link_to(t(:add_multiple), :controller => :contacts, :action => "add_multiple")
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_contact_group_list
|
||||||
|
link_to(t(:groups), :controller => :contact_group, :action => :index)
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_folders
|
||||||
|
link_to( t(:folders), :controller=>:webmail, :action=>:messages)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def short_fn(folder)
|
||||||
|
if folder.name.include? folder.delim
|
||||||
|
folder.name.split(folder.delim).last
|
||||||
|
else
|
||||||
|
folder.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,16 +0,0 @@
|
||||||
module PrefsHelper
|
|
||||||
def servers_table_header
|
|
||||||
html = ""
|
|
||||||
$defaults["servers_table_fields"].each do |f|
|
|
||||||
html << "<th>"
|
|
||||||
if params[:sort_field] == f
|
|
||||||
params[:sort_dir].nil? ? dir = 'desc' : dir = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
html << link_to(Server.human_attribute_name(f), {:controller => 'prefs',:action => 'servers',:sort_field => f,:sort_dir => dir}, {:class=>"header"})
|
|
||||||
html << "</th>"
|
|
||||||
end
|
|
||||||
html
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,2 +0,0 @@
|
||||||
module UserHelper
|
|
||||||
end
|
|
166
app/helpers/webmail_helper.rb
Normal file
166
app/helpers/webmail_helper.rb
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
require 'cdfutils'
|
||||||
|
require 'mail2screen'
|
||||||
|
|
||||||
|
module WebmailHelper
|
||||||
|
include Mail2Screen
|
||||||
|
def link_compose_new
|
||||||
|
link_to(t(:compose_txt), :controller=>"webmail", :action=>"compose")
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_refresh
|
||||||
|
link_to(t(:refresh), :controller=>"webmail", :action=>"refresh")
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_message_list
|
||||||
|
link_to(_('Message list'), :controller=>"webmail", :action=>"messages")
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_reply_to_sender(msg_id)
|
||||||
|
link_to(t(:reply), :controller=>"webmail", :action=>"reply", :params=>{"msg_id"=>msg_id})
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_forward_message(msg_id)
|
||||||
|
link_to(t(:forward), :controller=>"webmail", :action=>"forward", :params=>{"msg_id"=>msg_id})
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_flag_for_deletion(msg_id)
|
||||||
|
link_to(t(:delete), :controller=>"webmail", :action=>"delete", :params=>{"msg_id"=>msg_id})
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_view_source(msg_id)
|
||||||
|
link_to(t(:view_source), {:controller=>"webmail", :action=>"view_source", :params=>{"msg_id"=>msg_id}}, {'target'=>"_blank"})
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_filter_add
|
||||||
|
link_to(t(:add_filter), :controller=>'webmail', :action=>'filter_add')
|
||||||
|
end
|
||||||
|
|
||||||
|
def folder_link(folder)
|
||||||
|
return folder.name if folder.attribs.include?(:Noselect)
|
||||||
|
folder_name = short_fn(folder)
|
||||||
|
folder_name = t(folder_name.downcase.to_sym, :default => folder_name)
|
||||||
|
title = folder.unseen > 0 ? "#{folder_name} (#{folder.unseen})" : "#{folder_name}"
|
||||||
|
link = link_to title, :controller => 'webmail', :action => 'messages', :folder_name => folder.name
|
||||||
|
link = content_tag('b', link) if folder.name == @folder_name
|
||||||
|
link += ' ' + empty_trash_link(folder.name) if folder.trash?
|
||||||
|
link
|
||||||
|
end
|
||||||
|
|
||||||
|
def message_date(datestr)
|
||||||
|
t = Time.now
|
||||||
|
begin
|
||||||
|
if datestr.kind_of?(String)
|
||||||
|
d = (Time.rfc2822(datestr) rescue Time.parse(value)).localtime
|
||||||
|
else
|
||||||
|
d = datestr
|
||||||
|
end
|
||||||
|
if d.day == t.day and d.month == t.month and d.year == t.year
|
||||||
|
d.strftime("%H:%M")
|
||||||
|
else
|
||||||
|
d.strftime("%Y-%m-%d")
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
begin
|
||||||
|
d = imap2time(datestr)
|
||||||
|
if d.day == t.day and d.month == t.month and d.year == t.year
|
||||||
|
d.strftime("%H:%M")
|
||||||
|
else
|
||||||
|
d.strftime("%Y-%m-%d")
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
datestr
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def attachment(att, index)
|
||||||
|
ret = "#{att.filename}"
|
||||||
|
# todo: add link to delete attachment
|
||||||
|
#ret <<
|
||||||
|
ret << "<input type='hidden' name='att_files[#{index}]' value='#{att.filename}'/>"
|
||||||
|
ret << "<input type='hidden' name='att_tfiles[#{index}]' value='#{att.temp_filename}'/>"
|
||||||
|
ret << "<input type='hidden' name='att_ctypes[#{index}]' value='#{att.content_type}'/>"
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_filter_up(filter_id)
|
||||||
|
link_to(_('Up'), :controller=>"webmail", :action=>"filter_up", :id=>filter_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_filter_down(filter_id)
|
||||||
|
link_to(_('Down'), :controller=>"webmail", :action=>"filter_down", :id=>filter_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_filter_edit(filter_id)
|
||||||
|
link_to(_('Edit'), :controller=>"webmail", :action=>"filter", :id=>filter_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_filter_delete(filter_id)
|
||||||
|
link_to(_('Delete'), :controller=>"webmail", :action=>"filter_delete", :id=>filter_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def page_navigation_webmail(pages)
|
||||||
|
nav = "<p class='paginator'><small>"
|
||||||
|
|
||||||
|
nav << "(#{pages.length} #{t :pages}) "
|
||||||
|
|
||||||
|
window_pages = pages.current.window.pages
|
||||||
|
nav << "..." unless window_pages[0].first?
|
||||||
|
for page in window_pages
|
||||||
|
if pages.current == page
|
||||||
|
nav << page.number.to_s << " "
|
||||||
|
else
|
||||||
|
nav << link_to(page.number, :controller=>"webmail", :action=>'messages', :page=>page.number) << " "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
nav << "..." unless window_pages[-1].last?
|
||||||
|
nav << " "
|
||||||
|
|
||||||
|
nav << link_to(t(:first), :controller=>"webmail", :action=>'messages', :page=>@pages.first.number) << " | " unless @pages.current.first?
|
||||||
|
nav << link_to(t(:prev), :controller=>"webmail", :action=>'messages', :page=>@pages.current.previous.number) << " | " if @pages.current.previous
|
||||||
|
nav << link_to(t(:next), :controller=>"webmail", :action=>'messages', :page=>@pages.current.next.number) << " | " if @pages.current.next
|
||||||
|
nav << link_to(t(:last), :controller=>"webmail", :action=>'messages', :page=>@pages.last.number) << " | " unless @pages.current.last?
|
||||||
|
|
||||||
|
nav << "</small></p>"
|
||||||
|
|
||||||
|
return nav
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_subject(subject)
|
||||||
|
begin
|
||||||
|
if mime_encoded?(subject)
|
||||||
|
if mime_decode(subject) == ''
|
||||||
|
_('(No subject)')
|
||||||
|
else
|
||||||
|
mime_decode(subject)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if from_qp(subject) == ''
|
||||||
|
_('(No subject)')
|
||||||
|
else
|
||||||
|
from_qp(subject)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue Exception => ex
|
||||||
|
RAILS_DEFAULT_LOGGER.debug('Exception occured - #{ex}')
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def message_size(size)
|
||||||
|
if size / (1024*1024) > 0
|
||||||
|
return "#{(size / (1024*1024)).round} MB"
|
||||||
|
elsif size / 1024 > 0
|
||||||
|
return "#{(size / (1024)).round} KB"
|
||||||
|
else
|
||||||
|
return "#{size} B"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def empty_trash_link(folder_name)
|
||||||
|
link_to( "(#{t :empty})",
|
||||||
|
{ :controller => "webmail", :action => "empty", :params=>{"folder_name"=>folder_name}},
|
||||||
|
:confirm => t(:want_to_empty_trash_message))
|
||||||
|
end
|
||||||
|
end
|
116
app/models/contact.rb
Executable file → Normal file
116
app/models/contact.rb
Executable file → Normal file
|
@ -1,45 +1,71 @@
|
||||||
class Contact < ActiveRecord::Base
|
require 'cdfutils'
|
||||||
|
require_association 'contact_group'
|
||||||
validates_length_of :name, :within => 3..20
|
|
||||||
validates_length_of :email, :within => 5..50
|
class Contact < ActiveRecord::Base
|
||||||
validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
|
|
||||||
validates_length_of :info, :maximum => 100
|
has_and_belongs_to_many :groups, :class_name => "ContactGroup", :join_table => "contact_contact_groups", :association_foreign_key => "contact_group_id", :foreign_key => "contact_id"
|
||||||
validate :check_unique_name, :on => :create
|
|
||||||
default_scope :order => 'name ASC'
|
# Finder methods follow
|
||||||
|
def Contact.find_by_user(user_id)
|
||||||
belongs_to :user
|
find(:all, :conditions => ["customer_id = ?", user_id], :order => "fname asc", :limit => 10)
|
||||||
|
end
|
||||||
def self.getPageForUser(user,page,sort_field,sort_dir)
|
|
||||||
|
def Contact.find_by_user_email(user_id, email)
|
||||||
if sort_field
|
find(:first, :conditions => ["customer_id = #{user_id} and email = ?", email])
|
||||||
if Contact.attribute_method?(sort_field) == true
|
end
|
||||||
order = sort_field
|
|
||||||
sort_dir == 'desc' ? order += ' desc' : sort_dir
|
def Contact.find_by_group_user(user_id, grp_id)
|
||||||
end
|
result = Array.new
|
||||||
end
|
find(:all, :conditions => ["customer_id = ?", user_id], :order => "fname asc").each { |c|
|
||||||
|
begin
|
||||||
Contact.paginate :page => page , :per_page => $defaults["contacts_per_page"], :conditions=> ['user_id = ?', user.id],:order => order
|
c.groups.find(grp_id)
|
||||||
end
|
result << c
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
def check_unique_name
|
end
|
||||||
if !Contact.where('upper(name) = ? and user_id = ?',name.upcase,user_id).size.zero?
|
}
|
||||||
errors.add(:name, :not_unique)
|
result
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
named_scope :for_customer, lambda{ |customer_id| {:conditions => {:customer_id => customer_id}} }
|
||||||
def export
|
named_scope :letter, lambda{ |letter| {:conditions => ["contacts.fname LIKE ?", "#{letter}%"]} }
|
||||||
fields = []
|
|
||||||
fields << name || ""
|
def Contact.find_by_user_letter(user_id, letter)
|
||||||
fields << email || ""
|
find_by_sql("select * from contacts where customer_id=#{user_id} and substr(UPPER(fname),1,1) = '#{letter}' order by fname")
|
||||||
fields << info || ""
|
end
|
||||||
fields.join(';')
|
|
||||||
end
|
def full_name
|
||||||
|
"#{fname} #{lname}"
|
||||||
def self.import(user,line)
|
end
|
||||||
fields = line.split(/;/)
|
|
||||||
contact = user.contacts.build( :name => fields[0].strip,
|
def show_name
|
||||||
:email => fields[1].strip,
|
"#{fname} #{lname}"
|
||||||
:info => fields[2].strip)
|
end
|
||||||
contact.save!
|
|
||||||
end
|
def full_address
|
||||||
end
|
"#{fname} #{lname}<#{email}>"
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
def validate
|
||||||
|
errors.add 'fname', I18n.t(:validate_fname_error) unless self.fname =~ /^.{2,20}$/i
|
||||||
|
errors.add 'lname', I18n.t(:validate_lname_error) unless self.lname =~ /^.{2,20}$/i
|
||||||
|
|
||||||
|
# Contact e-mail cannot be changed
|
||||||
|
unless self.new_record?
|
||||||
|
old_record = Contact.find(self.id)
|
||||||
|
errors.add 'email', I18n.t(:contacto_cannot_be_changed) unless old_record.email == self.email
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_on_create
|
||||||
|
# Contact e-mail cannot be changed, so we only need to validate it on create
|
||||||
|
errors.add 'email', I18n.t(:validate_email_error) unless valid_email?(self.email)
|
||||||
|
# Already existing e-mail in contacts for this user is not allowed
|
||||||
|
if self.new_record?
|
||||||
|
if Contact.find :first, :conditions => {:email => email, :customer_id => customer_id}
|
||||||
|
errors.add('email', I18n.t(:email_exists))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
25
app/models/contact_group.rb
Normal file
25
app/models/contact_group.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
class ContactGroup < ActiveRecord::Base
|
||||||
|
has_and_belongs_to_many :contacts, :class_name => "Contact", :join_table => "contact_contact_groups", :association_foreign_key => "contact_id", :foreign_key => "contact_group_id"
|
||||||
|
|
||||||
|
def ContactGroup.find_by_user(user_id)
|
||||||
|
find_by_sql("select * from contact_groups where customer_id = #{user_id} order by name asc")
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
def validate
|
||||||
|
errors.add('name', :contactgroup_name_invalid) unless self.name =~ /^.{1,50}$/i
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_on_create
|
||||||
|
if ContactGroup.find_first(["name = '#{name}' and customer_id = #{user_id}"])
|
||||||
|
errors.add("name", _('Please enter group name (1 to 50 characters)'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_on_update
|
||||||
|
if ContactGroup.find_first(["name = '#{name}' and customer_id = #{user_id} and id <> #{id}"])
|
||||||
|
errors.add("name", _('You already have contact group with this name'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
32
app/models/customer.rb
Normal file
32
app/models/customer.rb
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
require_dependency 'maildropserializator'
|
||||||
|
class Customer < ActiveRecord::Base
|
||||||
|
include MaildropSerializator
|
||||||
|
|
||||||
|
has_many :filters, :order => "order_num"
|
||||||
|
has_one :mail_pref
|
||||||
|
attr_accessor :password
|
||||||
|
|
||||||
|
def mail_temporary_path
|
||||||
|
"#{CDF::CONFIG[:mail_temp_path]}/#{self.email}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def friendlly_local_email
|
||||||
|
encode_email("#{self.fname} #{self.lname}", check_for_domain(email))
|
||||||
|
end
|
||||||
|
|
||||||
|
def mail_filter_path
|
||||||
|
"#{CDF::CONFIG[:mail_filters_path]}/#{self.email}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def local_email
|
||||||
|
self.email
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_for_domain(email)
|
||||||
|
if email && !email.nil? && !email.include?("@") && CDF::CONFIG[:send_from_domain]
|
||||||
|
email + "@" + CDF::CONFIG[:send_from_domain]
|
||||||
|
else
|
||||||
|
email
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,146 +0,0 @@
|
||||||
class Folder < ActiveRecord::Base
|
|
||||||
|
|
||||||
belongs_to :user
|
|
||||||
validates_presence_of :name, :on => :create
|
|
||||||
before_save :check_fill_params, :on => :create
|
|
||||||
has_many :messages, :dependent => :destroy
|
|
||||||
|
|
||||||
SYS_NONE = 0
|
|
||||||
SYS_TRASH = 1
|
|
||||||
SYS_INBOX = 2
|
|
||||||
SYS_SENT = 3
|
|
||||||
SYS_DRAFTS = 4
|
|
||||||
|
|
||||||
default_scope :order => 'name asc'
|
|
||||||
scope :shown, where(['shown = ?',true])
|
|
||||||
scope :inbox, where(['sys = ?',SYS_INBOX])
|
|
||||||
scope :sent, where(['sys = ?',SYS_SENT])
|
|
||||||
scope :drafts, where(['sys = ?',SYS_DRAFTS])
|
|
||||||
scope :trash, where(['sys = ?',SYS_TRASH])
|
|
||||||
scope :sys, where(['sys > ?',SYS_NONE])
|
|
||||||
|
|
||||||
def full_name
|
|
||||||
if parent.empty?
|
|
||||||
name
|
|
||||||
else
|
|
||||||
parent + delim + name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def depth
|
|
||||||
parent.split('.').size
|
|
||||||
end
|
|
||||||
|
|
||||||
def selected?(session_folder)
|
|
||||||
fields = session_folder.split("#")
|
|
||||||
fields[1].nil? ? fields.insert(0,"") : fields
|
|
||||||
(fields[1].downcase == name.downcase) && (fields[0].downcase == parent.downcase)
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_stats
|
|
||||||
logger.info "MESS_BEFORE: "+messages.inspect
|
|
||||||
unseen = messages.where(:unseen => true).count
|
|
||||||
total = messages.count
|
|
||||||
logger.info "MESS: "+messages.inspect
|
|
||||||
logger.info "MESS: #{unseen} #{total}"
|
|
||||||
update_attributes(:unseen => unseen, :total => total)
|
|
||||||
end
|
|
||||||
|
|
||||||
def hasFullName?(folder_name)
|
|
||||||
full_name.downcase == folder_name.downcase
|
|
||||||
end
|
|
||||||
|
|
||||||
def isSystem?
|
|
||||||
sys > SYS_NONE
|
|
||||||
end
|
|
||||||
|
|
||||||
def isTrash?
|
|
||||||
sys == SYS_TRASH
|
|
||||||
end
|
|
||||||
|
|
||||||
def isSent?
|
|
||||||
sys == SYS_SENT
|
|
||||||
end
|
|
||||||
|
|
||||||
def isInbox?
|
|
||||||
sys == SYS_INBOX
|
|
||||||
end
|
|
||||||
|
|
||||||
def isDrafts?
|
|
||||||
sys == SYS_DRAFTS
|
|
||||||
end
|
|
||||||
|
|
||||||
def setNone
|
|
||||||
update_attributes(:sys => SYS_NONE)
|
|
||||||
end
|
|
||||||
|
|
||||||
def setTrash
|
|
||||||
update_attributes(:sys => SYS_TRASH)
|
|
||||||
end
|
|
||||||
|
|
||||||
def setSent
|
|
||||||
update_attributes(:sys => SYS_SENT)
|
|
||||||
end
|
|
||||||
|
|
||||||
def setInbox
|
|
||||||
update_attributes(:sys => SYS_INBOX)
|
|
||||||
end
|
|
||||||
|
|
||||||
def setDrafts
|
|
||||||
update_attributes(:sys => SYS_DRAFTS)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
############################################## private section #####################################
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def check_fill_params
|
|
||||||
self.total.nil? ? self.total = 0 : self.total
|
|
||||||
self.unseen.nil? ? self.unseen = 0 : self.unseen
|
|
||||||
self.parent.nil? ? self.parent = "" : self.parent
|
|
||||||
self.haschildren.nil? ? self.haschildren = false : self.haschildren
|
|
||||||
self.delim.nil? ? self.delim = "." : self.delim
|
|
||||||
self.sys.nil? ? self.sys = SYS_NONE : self.sys
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.createBulk(user,imapFolders)
|
|
||||||
imapFolders.each do |name,data|
|
|
||||||
data.attribs.find_index(:Haschildren).nil? ? has_children = 0 : has_children = 1
|
|
||||||
name_fields = name.split(data.delim)
|
|
||||||
|
|
||||||
if name_fields.count > 1
|
|
||||||
name = name_fields.delete_at(name_fields.size - 1)
|
|
||||||
parent = name_fields.join(data.delim)
|
|
||||||
else
|
|
||||||
name = name_fields[0]
|
|
||||||
parent = ""
|
|
||||||
end
|
|
||||||
|
|
||||||
user.folders.create(
|
|
||||||
:name => name,
|
|
||||||
:parent => parent,
|
|
||||||
:haschildren => has_children,
|
|
||||||
:delim => data.delim,
|
|
||||||
:total => data.messages,
|
|
||||||
:unseen => data.unseen,
|
|
||||||
:sys => SYS_NONE)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.find_by_full_name(data)
|
|
||||||
folder = data.gsub(/\./,'#')
|
|
||||||
fields = folder.split("#")
|
|
||||||
nam = fields.delete_at(fields.size - 1)
|
|
||||||
fields.size.zero? == true ? par = "" : par = fields.join(".")
|
|
||||||
where(['name = ? and parent = ?',nam,par]).first
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.refresh(mailbox,user)
|
|
||||||
user.folders.destroy_all
|
|
||||||
folders=mailbox.folders
|
|
||||||
Folder.createBulk(user,folders)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,33 +0,0 @@
|
||||||
class Link < ActiveRecord::Base
|
|
||||||
validates_length_of :url, :within => 5..150
|
|
||||||
validates_length_of :info, :maximum => 50
|
|
||||||
belongs_to :user
|
|
||||||
default_scope :order => 'url asc'
|
|
||||||
|
|
||||||
def self.getPageForUser(user,page,sort_field,sort_dir)
|
|
||||||
|
|
||||||
if sort_field
|
|
||||||
if Link.attribute_method?(sort_field) == true
|
|
||||||
order = sort_field
|
|
||||||
sort_dir == 'desc' ? order += ' desc' : sort_dir
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Link.paginate :page => page , :per_page => $defaults["links_per_page"], :conditions=> ['user_id = ?', user.id],:order => order
|
|
||||||
end
|
|
||||||
|
|
||||||
def export
|
|
||||||
fields = []
|
|
||||||
fields << url || ""
|
|
||||||
fields << info || ""
|
|
||||||
fields.join(';')
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.import(user,line)
|
|
||||||
fields = line.split(/;/)
|
|
||||||
contact = user.links.build( :url => fields[0].strip,
|
|
||||||
:info => fields[1].strip)
|
|
||||||
contact.save!
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
9
app/models/mail_pref.rb
Normal file
9
app/models/mail_pref.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# require_association 'customer'
|
||||||
|
|
||||||
|
class MailPref < ActiveRecord::Base
|
||||||
|
belongs_to :customer
|
||||||
|
|
||||||
|
# def MailPref.find_by_customer(customer_id)
|
||||||
|
# find :first, :conditions => (["customer_id = #{customer_id}"])
|
||||||
|
# end
|
||||||
|
end
|
|
@ -1,73 +0,0 @@
|
||||||
require 'iconv'
|
|
||||||
require 'mail'
|
|
||||||
|
|
||||||
class Message < ActiveRecord::Base
|
|
||||||
|
|
||||||
belongs_to :user
|
|
||||||
belongs_to :folder
|
|
||||||
|
|
||||||
#set_primary_key :uid
|
|
||||||
self.primary_key = :uid
|
|
||||||
attr_accessible :unseen, :to_addr, :size, :content_type, :folder_id, :subject, :date, :uid, :from_addr, :user_id, :msg_id, :body, :cc_addr, :bcc_addr
|
|
||||||
attr_accessor :body
|
|
||||||
|
|
||||||
def self.addr_to_db(addr)
|
|
||||||
ret = ""
|
|
||||||
name = addr.name
|
|
||||||
name.nil? ? ret : ret << ApplicationController.decode_quoted(name)
|
|
||||||
ret << "<" + addr.mailbox + "@" + addr.host
|
|
||||||
ret
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.getPageForUser(user,folder,page,sort_field,sort_dir)
|
|
||||||
|
|
||||||
order = 'date desc'
|
|
||||||
if sort_field
|
|
||||||
if Message.attribute_method?(sort_field) == true
|
|
||||||
order = sort_field
|
|
||||||
sort_dir == 'desc' ? order += ' desc' : sort_dir
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Message.paginate :page => page , :per_page => user.prefs.msgs_per_page.to_i, :conditions=> ['user_id = ? and folder_id = ?', user.id,folder.id],:order => order
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.createForUser(user,folder,message)
|
|
||||||
|
|
||||||
# envelope = imap_message.attr['ENVELOPE']
|
|
||||||
#
|
|
||||||
# envelope.from.nil? ? from = "" : from = addr_to_db(envelope.from[0])
|
|
||||||
# envelope.to.nil? ? to = "" : to = addr_to_db(envelope.to[0])
|
|
||||||
# envelope.subject.nil? ? subject = "" : subject = ApplicationController.decode_quoted(envelope.subject)
|
|
||||||
|
|
||||||
mail = Mail.new(message.attr['RFC822.HEADER'])
|
|
||||||
|
|
||||||
mail.date.nil? ? date = nil : date = mail.date.to_s
|
|
||||||
mail.From.nil? ? from = nil : from = mail.From.charseted
|
|
||||||
mail.To.nil? ? to = nil : to = mail.To.charseted
|
|
||||||
mail.Subject.nil? ? subject = nil : subject = mail.Subject.charseted
|
|
||||||
|
|
||||||
#logger.custom('subject',mail.Subject.encoded)
|
|
||||||
#logger.custom('subject',subject)
|
|
||||||
#logger.custom('mail',mail.inspect)
|
|
||||||
|
|
||||||
create(
|
|
||||||
:user_id => user.id,
|
|
||||||
:folder_id => folder.id,
|
|
||||||
:msg_id => mail.message_id,
|
|
||||||
:uid => message.attr['UID'].to_i,
|
|
||||||
:from_addr => from,
|
|
||||||
:to_addr => to,
|
|
||||||
:subject => subject,
|
|
||||||
:content_type => mail.content_type,
|
|
||||||
:date => date,
|
|
||||||
:unseen => !(message.attr['FLAGS'].member? :Seen),
|
|
||||||
:size => message.attr['RFC822.SIZE']
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def change_folder(folder)
|
|
||||||
update_attributes(:folder_id => folder.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,21 +0,0 @@
|
||||||
class Prefs < ActiveRecord::Base
|
|
||||||
|
|
||||||
validates_presence_of :theme,:locale
|
|
||||||
|
|
||||||
has_one :user
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def self.create_default(user)
|
|
||||||
Prefs.create(:user_id => user.id,
|
|
||||||
:theme => $defaults['theme'],
|
|
||||||
:locale => $defaults['locale'],
|
|
||||||
:msgs_per_page => $defaults['msgs_per_page'],
|
|
||||||
:msg_send_type => $defaults['msg_send_type'],
|
|
||||||
:msg_image_view_as => 'attachment',
|
|
||||||
:msg_image_thumbnail_size => '192x144'
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# TODO move refresh to prefs and make refresh page with messages
|
|
|
@ -1,45 +0,0 @@
|
||||||
class Server < ActiveRecord::Base
|
|
||||||
|
|
||||||
validates_presence_of :name
|
|
||||||
belongs_to :user
|
|
||||||
#before_save :fill_params
|
|
||||||
|
|
||||||
def self.primary_for_imap
|
|
||||||
where(:for_imap=>true).first
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.primary_for_smtp
|
|
||||||
where(:for_smtp=>true).first
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.create_default(user)
|
|
||||||
create_server(user,"localhost")
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.create_server(user,server)
|
|
||||||
create( :user_id=>user.id,
|
|
||||||
:name=>server,
|
|
||||||
:port=>$defaults['imap_port'],
|
|
||||||
:use_ssl=>false,
|
|
||||||
:use_tls=>false,
|
|
||||||
:for_smtp=>false,
|
|
||||||
:for_imap=>true
|
|
||||||
)
|
|
||||||
create( :user_id=>user.id,
|
|
||||||
:name=>server,
|
|
||||||
:port=>$defaults['smtp_port'],
|
|
||||||
:use_ssl=>false,
|
|
||||||
:use_tls=>false,
|
|
||||||
:for_smtp=>true,
|
|
||||||
:for_imap=>false
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
# private
|
|
||||||
|
|
||||||
# def fill_params
|
|
||||||
# port.nil? ? port = $defaults['imap_port'] : port
|
|
||||||
# $defaults['imap_use_ssl'] == true ? self.use_ssl = 1 : self.use_ssl = 0
|
|
||||||
# end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,64 +0,0 @@
|
||||||
require 'ezcrypto'
|
|
||||||
|
|
||||||
class User < ActiveRecord::Base
|
|
||||||
|
|
||||||
#acts_as_notes_owner
|
|
||||||
|
|
||||||
validates_presence_of :first_name,:last_name,:login
|
|
||||||
validates_uniqueness_of :login
|
|
||||||
has_many :servers, :dependent => :destroy
|
|
||||||
has_one :prefs, :dependent => :destroy
|
|
||||||
has_many :folders, :dependent => :destroy
|
|
||||||
has_many :messages, :dependent => :destroy
|
|
||||||
has_many :contacts, :dependent => :destroy
|
|
||||||
has_many :links, :dependent => :destroy
|
|
||||||
|
|
||||||
def set_cached_password(session,password)
|
|
||||||
if $defaults['session_encryption']
|
|
||||||
session[:session_salt] = generate_salt
|
|
||||||
session[:user_password] = EzCrypto::Key.encrypt_with_password($defaults['session_password'], session[:session_salt], password)
|
|
||||||
else
|
|
||||||
session[:user_password] = password
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_cached_password(session)
|
|
||||||
if $defaults['session_encryption']
|
|
||||||
EzCrypto::Key.decrypt_with_password($defaults['session_password'], session[:session_salt], session[:user_password])
|
|
||||||
else
|
|
||||||
session[:user_password]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def generate_salt
|
|
||||||
(0...8).map{65.+(rand(25)).chr}.join
|
|
||||||
end
|
|
||||||
|
|
||||||
def name
|
|
||||||
first_name + " " + last_name
|
|
||||||
end
|
|
||||||
|
|
||||||
def full_id
|
|
||||||
(name + " <" + email + ">") if email
|
|
||||||
end
|
|
||||||
|
|
||||||
def email
|
|
||||||
if login =~ /\@/
|
|
||||||
login
|
|
||||||
else
|
|
||||||
(login + "@" + domain) if domain.presence
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def username
|
|
||||||
login.gsub(/\@/,"_").gsub(/\./,"_")
|
|
||||||
end
|
|
||||||
|
|
||||||
def has_domain?
|
|
||||||
return domain if domain.presence
|
|
||||||
if login =~ /\@/
|
|
||||||
login.split(/\@/)[1]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
- size ||= "btn-small"
|
|
||||||
- type ||= "btn-primary"
|
|
||||||
- icon ||= ""
|
|
||||||
|
|
||||||
%a{:class=>"btn #{size} #{type}",:href=>"#{href}"}
|
|
||||||
- if !icon.empty?
|
|
||||||
%i{:class=>"#{icon}"}
|
|
||||||
= caption
|
|
|
@ -1,27 +0,0 @@
|
||||||
- model = eval(object.class.model_name)
|
|
||||||
- model_string = object.class.model_name.downcase
|
|
||||||
- label.nil? ? model_label = model.human_attribute_name(attr) : model_label = t(label.to_sym)
|
|
||||||
- val = value || object.instance_eval(attr) || ""
|
|
||||||
- if object.errors[attr.to_sym].empty?
|
|
||||||
- to_class ||= ""
|
|
||||||
- rows ||= 5
|
|
||||||
.control-group
|
|
||||||
%label{:class=>"control-label",:for=>"#{attr}"}
|
|
||||||
= model_label
|
|
||||||
.controls
|
|
||||||
%textarea{:rows=>"#{rows}",:class=>"#{to_class}",:id=>"#{model_string}_#{attr}",:name=>"#{model_string}[#{attr}]"}
|
|
||||||
= val
|
|
||||||
%p{:class=>"help-block"}
|
|
||||||
= t(:example,:scope=>:common)
|
|
||||||
= example
|
|
||||||
- else
|
|
||||||
.control-group.error
|
|
||||||
%label{:class=>"control-label",:for=>"#{attr}"}
|
|
||||||
= model_label
|
|
||||||
.controls
|
|
||||||
%input{:id=>"#{model_string}_#{attr}",:name=>"#{model_string}[#{attr}]",:value=>"#{val}"}
|
|
||||||
%span{:class=>"help-inline"}
|
|
||||||
= object.errors[attr.to_sym].to_s
|
|
||||||
%p{:class=>"help-block"}
|
|
||||||
= t(:example,:scope=>:common)
|
|
||||||
= example
|
|
|
@ -1,19 +0,0 @@
|
||||||
|
|
||||||
- size ||= "btn-small"
|
|
||||||
- type ||= "btn-primary"
|
|
||||||
- icon ||= ""
|
|
||||||
- onclick ||= 'empty'
|
|
||||||
|
|
||||||
- def isOnclick(value)
|
|
||||||
- if value != 'empty'
|
|
||||||
- {:onclick => "#{value}"}
|
|
||||||
- else
|
|
||||||
- {}
|
|
||||||
|
|
||||||
%button{isOnclick(onclick),:class=>"btn #{size} #{type}",
|
|
||||||
:type=>"submit",
|
|
||||||
:name=>"#{name}"}
|
|
||||||
- if !icon.empty?
|
|
||||||
%i{:class=>"#{icon}"}
|
|
||||||
= caption
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
.control-group
|
|
||||||
%label{:class=>"control-label",:for=>"#{attr}"}
|
|
||||||
= model_label
|
|
||||||
.controls
|
|
||||||
%input{:id=>"#{model_string}_#{attr}",:name=>"#{model_string}[#{attr}]",:type=>"file"}
|
|
|
@ -1,12 +0,0 @@
|
||||||
%form{:enctype=>"multipart/form-data", :class=>"form-horizontal top-pix18",:action=>"#{im_ex_path}",:method=>"post"}
|
|
||||||
= render :partial => "common/file_select", :locals => { :model_label => "#{im_ex_label}",
|
|
||||||
:model_string => "upload",
|
|
||||||
:attr => "datafile"}
|
|
||||||
%p
|
|
||||||
= render :partial => "common/button", :locals => {:name=>'import',
|
|
||||||
:caption=>t('import',:scope=>'contact'),
|
|
||||||
:icon=>'icon-upload icon-white'}
|
|
||||||
- if !im_ex_size.zero?
|
|
||||||
= render :partial => "common/button", :locals => {:name=>'export',
|
|
||||||
:caption=>t('export',:scope=>'contact'),
|
|
||||||
:icon=>'icon-download icon-white'}
|
|
|
@ -1,27 +0,0 @@
|
||||||
- model = eval(object.class.model_name)
|
|
||||||
- model_string = object.class.model_name.downcase
|
|
||||||
- label.nil? ? model_label = model.human_attribute_name(attr) : model_label = t(label.to_sym)
|
|
||||||
- val = value || object.instance_eval(attr) || ""
|
|
||||||
- if object.errors[attr.to_sym].empty?
|
|
||||||
- to_class ||= ""
|
|
||||||
.control-group
|
|
||||||
%label{:class=>"control-label",:for=>"#{attr}"}
|
|
||||||
= model_label
|
|
||||||
.controls
|
|
||||||
%input{:class=>"#{to_class}",:id=>"#{model_string}_#{attr}",:name=>"#{model_string}[#{attr}]",:value=>"#{val}"}
|
|
||||||
%p{:class=>"help-block"}
|
|
||||||
= t(:example,:scope=>:common)
|
|
||||||
= example
|
|
||||||
- else
|
|
||||||
.control-group.error
|
|
||||||
%label{:class=>"control-label",:for=>"#{attr}"}
|
|
||||||
= model_label
|
|
||||||
.controls
|
|
||||||
%input{:id=>"#{model_string}_#{attr}",:name=>"#{model_string}[#{attr}]",:value=>"#{val}"}
|
|
||||||
%span{:class=>"help-inline"}
|
|
||||||
= object.errors[attr.to_sym].to_s
|
|
||||||
%p{:class=>"help-block"}
|
|
||||||
= t(:example,:scope=>:common)
|
|
||||||
= example
|
|
||||||
|
|
||||||
-#= render :partial => "common/input_form_desc_field",:locals => {:object => @user,:attr => 'login',:label => nil,:example => 'joe.doe',:value => params[:user] ? params[:user][:login] : "" }
|
|
|
@ -1,8 +0,0 @@
|
||||||
.control-group
|
|
||||||
%label{:class=>"control-label",:for=>"#{attr}"}
|
|
||||||
= model.capitalize.constantize.human_attribute_name(attr)
|
|
||||||
.controls
|
|
||||||
%input{:type=>"text",:id=>"#{model}_#{attr}",:name=>"#{model}[#{attr}]"}
|
|
||||||
|
|
||||||
|
|
||||||
-#= render :partial => "common/input_form_field",:locals => { :model => 'user',:attr => 'login'}
|
|
|
@ -1,5 +0,0 @@
|
||||||
.control-group
|
|
||||||
%label{:class=>"control-label",:for=>"#{attr}"}
|
|
||||||
= model.capitalize.constantize.human_attribute_name(attr)
|
|
||||||
.controls
|
|
||||||
%input{:type=>"password",:id=>"#{model}_#{attr}",:name=>"#{model}[#{attr}]"}
|
|
|
@ -1,2 +0,0 @@
|
||||||
.logo
|
|
||||||
= link_to image_tag("logo.png",:alt=> t(:mailr,:scope=>:common)), root_path
|
|
|
@ -1 +0,0 @@
|
||||||
= calendar_window(:title=>t(:calendar,:scope=>:common))
|
|
|
@ -1,21 +0,0 @@
|
||||||
- messages ||= ""
|
|
||||||
- compose ||= ""
|
|
||||||
- folders ||= ""
|
|
||||||
- contacts ||= ""
|
|
||||||
- prefs ||= ""
|
|
||||||
- links ||= ""
|
|
||||||
|
|
||||||
%ul{:class=>"nav nav-pills"}
|
|
||||||
%li{:class=>"#{messages}"}
|
|
||||||
= link_to( t(:messages,:scope=>:message), messages_path )
|
|
||||||
%li{:class=>"#{compose}"}
|
|
||||||
= link_to( t(:compose,:scope=>:compose), compose_path )
|
|
||||||
%li{:class=>"#{folders}"}
|
|
||||||
= link_to( t(:folders,:scope=>:folder), folders_path )
|
|
||||||
%li{:class=>"#{contacts}"}
|
|
||||||
= link_to( t(:contacts,:scope=>:contact), contacts_path )
|
|
||||||
%li{:class=>"#{links}"}
|
|
||||||
= link_to( t(:links,:scope=>:link), links_path )
|
|
||||||
%li{:class=>"#{prefs}"}
|
|
||||||
= link_to( t(:prefs,:scope=>:prefs), prefs_look_path )
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
%select{:multiple=>"multiple",:class=>"#{style}",:id=>"#{id}",:name=>"#{name}"}
|
|
||||||
- objects.each do |o|
|
|
||||||
- option_value = escape_once(o.send(value))
|
|
||||||
- option_text = [option_value]
|
|
||||||
|
|
||||||
- unless text.nil?
|
|
||||||
- option_text = []
|
|
||||||
- text.each do |t|
|
|
||||||
- option_text << o.send(t)
|
|
||||||
- option_text = option_text.join(joiner)
|
|
||||||
- option_text.gsub!(/^\./,'')
|
|
||||||
|
|
||||||
|
|
||||||
- if selected_objects.include?(o)
|
|
||||||
%option{:value=>"#{option_value}",:selected=>"selected"}
|
|
||||||
= option_text
|
|
||||||
- else
|
|
||||||
%option{:value=>"#{option_value}"}
|
|
||||||
= option_text
|
|
||||||
|
|
||||||
-#<%= raw multi_select("", 'folders_to_show[]', @folders, @folders_shown,t(:shown,:scope=>:folder),:id,"",{:text => [:parent,:delim,:name]}) %>
|
|
||||||
-#def multi_select(id, name, objects, selected_objects, label, value,joiner,content = {})
|
|
|
@ -1,11 +0,0 @@
|
||||||
- look ||= ""
|
|
||||||
- identity ||= ""
|
|
||||||
- servers ||= ""
|
|
||||||
|
|
||||||
%ul{:class=>"nav nav-pills"}
|
|
||||||
%li{:class=>"#{look}"}
|
|
||||||
= link_to( t(:look,:scope=>:prefs), prefs_look_path )
|
|
||||||
%li{:class=>"#{identity}"}
|
|
||||||
= link_to( t(:identity,:scope=>:prefs), prefs_identity_path )
|
|
||||||
%li{:class=>"#{servers}"}
|
|
||||||
= link_to( t(:servers,:scope=>:prefs), prefs_servers_path )
|
|
|
@ -1,22 +0,0 @@
|
||||||
- model = eval(object.class.model_name)
|
|
||||||
- model_string = object.class.model_name.downcase
|
|
||||||
- model_label = model.human_attribute_name(attr)
|
|
||||||
- translation_scope ||= false
|
|
||||||
|
|
||||||
.control-group
|
|
||||||
%label{:class=>"control-label",:for=>"#{attr}"}
|
|
||||||
= model_label
|
|
||||||
.controls
|
|
||||||
- if translation_scope
|
|
||||||
- t = []
|
|
||||||
- choices.each do |c|
|
|
||||||
- t << [t(c.to_sym,:scope=>translation_scope),c.to_s]
|
|
||||||
= select(model_string, attr, options_for_select(t,choice), {:include_blank => blank})
|
|
||||||
- else
|
|
||||||
= select(model_string, attr, options_for_select(choices,choice), {:include_blank => blank})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-# select(model.downcase, attr, options_for_select(choices,choice), {:include_blank => blank})
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
.control-group
|
|
||||||
%label{:class=>"control-label"}
|
|
||||||
= label
|
|
||||||
.controls
|
|
||||||
= raw simple_select_for_folders(name,id,collection,choice,blank)
|
|
|
@ -1,2 +0,0 @@
|
||||||
%p{:class=>"version"}
|
|
||||||
= link_to (t(:version,:scope=>:common) + " " + $defaults["version"]),about_path
|
|
24
app/views/contact_groups/edit.rhtml
Normal file
24
app/views/contact_groups/edit.rhtml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<h1><%=_('Edit/Create Contact Group')%></h1>
|
||||||
|
<%=
|
||||||
|
form_tag(
|
||||||
|
link_save,
|
||||||
|
'method' => 'post',
|
||||||
|
'class' => 'two_columns'
|
||||||
|
)
|
||||||
|
%>
|
||||||
|
<%= form_input(:hidden_field, 'contactgroup', 'id') %>
|
||||||
|
<%= form_input(:hidden_field, 'contactgroup', 'customer_id') %>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<%= form_input(:text_field, 'contactgroup', 'name', _('Name'), 'class'=>'two_columns') %>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td colspan=2 class="buttonBar">
|
||||||
|
<input type="submit" name="Save" value="<%=_('Save')%>"/>
|
||||||
|
<input type="button" value="<%=_('Back to groups')%>" onclick="window.location='<%=link_list%>'"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<%= end_form_tag %>
|
26
app/views/contact_groups/index.html.erb
Normal file
26
app/views/contact_groups/index.html.erb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<h1><%=_('Contact Groups')%></h1>
|
||||||
|
|
||||||
|
<%- form_for @contact_group do |f| %>
|
||||||
|
<%= hidden_field "contactgroup", "user_id" %>
|
||||||
|
<table class="list">
|
||||||
|
<tr>
|
||||||
|
<th><%=_('Name')%></th>
|
||||||
|
<th colspan=3> </th>
|
||||||
|
</tr>
|
||||||
|
<%
|
||||||
|
for contactgroup in @contactgroups %>
|
||||||
|
<tr class="even">
|
||||||
|
<td><%= contactgroup.name %></td>
|
||||||
|
<td><%= link_to(_('members'), :controller=>'contact', :action=>'list', :id=>contactgroup.id, :params=>{"mode"=>"groups"}) %></td>
|
||||||
|
<td><%= link_to(_('edit'), :controller=>'/contacts/contact_group', :action=>'edit', :id=>contactgroup.id) %></td>
|
||||||
|
<td><%= link_to(_('delete'), {:controller=>'/contacts/contact_group', :action=>'delete', :id=>contactgroup.id}, {:confirm=>sprintf(_('DELETE CONTACT GROUP \'%s\'?'), contactgroup.name)})%></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<tr>
|
||||||
|
<td colspan=2 class="buttonBar">
|
||||||
|
<input type="submit" value="<%=_('Add Contact Group')%>"/>
|
||||||
|
<input type="button" value="<%=_('Back to folders')%>" onclick="window.location='/webmail/folders'">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<%- end %>
|
|
@ -1,18 +0,0 @@
|
||||||
= render :partial => "common/input_form_desc_field",:locals => {:object => @contact,
|
|
||||||
:attr => 'name',
|
|
||||||
:label => nil,
|
|
||||||
:example => 'Joe Doe',
|
|
||||||
:value => @contact.name,
|
|
||||||
:to_class=>"span6" }
|
|
||||||
= render :partial => "common/input_form_desc_field",:locals => {:object => @contact,
|
|
||||||
:attr => 'email',
|
|
||||||
:label => nil,
|
|
||||||
:example => 'joe.doe@domain.com',
|
|
||||||
:value => @contact.email,
|
|
||||||
:to_class=>"span6" }
|
|
||||||
= render :partial => "common/input_form_desc_field",:locals => {:object => @contact,
|
|
||||||
:attr => 'info',
|
|
||||||
:label => nil,
|
|
||||||
:example => t(:some_add_info,:scope=>:common),
|
|
||||||
:value => @contact.info,
|
|
||||||
:to_class=>"span6" }
|
|
|
@ -1,11 +0,0 @@
|
||||||
%tr
|
|
||||||
%td{:nowrap=>"nowrap"}
|
|
||||||
= check_box_tag "items_ids[]", contact.id
|
|
||||||
\/
|
|
||||||
= link_to "<i class=\"icon-edit\"></i>".html_safe,edit_contact_path(contact)
|
|
||||||
%td{:nowrap=>"nowrap"}
|
|
||||||
= link_to contact.name,compose_contact_path(contact.id)
|
|
||||||
%td{:nowrap=>"nowrap"}
|
|
||||||
= link_to contact.email, compose_contact_path(contact.id)
|
|
||||||
%td{:nowrap=>"nowrap"}
|
|
||||||
= contact.info
|
|
|
@ -1,13 +0,0 @@
|
||||||
= will_paginate @contacts
|
|
||||||
|
|
||||||
%table{:class=>"table table-bordered records"}
|
|
||||||
%thead
|
|
||||||
%tr
|
|
||||||
%th
|
|
||||||
%input{:id=>"toggleall",:type=>"checkbox",:name=>"allbox"}
|
|
||||||
= raw contacts_table_header
|
|
||||||
%tbody
|
|
||||||
- @contacts.each do |c|
|
|
||||||
= render :partial => 'contact', :locals => {:contact => c}
|
|
||||||
|
|
||||||
= will_paginate @contacts
|
|
26
app/views/contacts/add_multiple.rhtml
Normal file
26
app/views/contacts/add_multiple.rhtml
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<h1><%=t :add_multiple_contacts %></h1>
|
||||||
|
<% if flash["errors"] and not flash["errors"].empty?%>
|
||||||
|
<%= t(:errors)%>
|
||||||
|
<ul>
|
||||||
|
<% flash["errors"].each do |message| %>
|
||||||
|
<li><%= message %>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
<% end %>
|
||||||
|
<form action="<%=link_import_preview%>" enctype="multipart/form-data" method="post">
|
||||||
|
<%= radio_button("contact", "file_type", "1")%> <%= t(:csv_file)%>
|
||||||
|
<%= radio_button("contact", "file_type", "2")%> <%= t(:tab_file)%>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th><label for="contact[data]"><%=t(:select_file)%></label></th>
|
||||||
|
<td><input type="file" name="contact[data]"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan=2>
|
||||||
|
<input type="submit" value="<%= t(:import)%>"/>
|
||||||
|
<input type="button" value="<%= t(:back_to_contacts)%>" onclick="window.location='<%=contacts_url%>'">
|
||||||
|
<input type="button" value="<%= t(:back_to_folders)%>" onclick="window.location='<%=url_for(:controller => :webmail)%>'">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
11
app/views/contacts/choose.rhtml
Normal file
11
app/views/contacts/choose.rhtml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<script language="javascript">
|
||||||
|
<% for to in @tos %>
|
||||||
|
respondTo("<%=to.full_address%>", "<%=to.id%>");
|
||||||
|
<% end %>
|
||||||
|
<% for cc in @ccs %>
|
||||||
|
respondCC("<%=cc.full_address%>");
|
||||||
|
<% end %>
|
||||||
|
<% for bcc in @bccs %>
|
||||||
|
respondBCC("<%=bcc.full_address%>");
|
||||||
|
<% end %>
|
||||||
|
</script>
|
|
@ -1,20 +0,0 @@
|
||||||
= content_for :sidebar do
|
|
||||||
= render :partial => "sidebar/sidebar"
|
|
||||||
|
|
||||||
= content_for :title do
|
|
||||||
\-
|
|
||||||
= t(:contacts,:scope=>:contact)
|
|
||||||
|
|
||||||
= render :partial => 'common/main_navigation', :locals => { :contacts => :active }
|
|
||||||
|
|
||||||
.well{:style=>"padding: 5px 3pt;"}
|
|
||||||
%h3
|
|
||||||
= t(:modifying,:scope=>:contact)
|
|
||||||
|
|
||||||
%form{:class=>"form-horizontal",:action=>url_for(@contact),:method=>"post"}
|
|
||||||
%input{:name=>"_method",:type=>"hidden",:value=>"put"}
|
|
||||||
%fieldset
|
|
||||||
= render :partial => "attrs"
|
|
||||||
.control-group
|
|
||||||
.controls
|
|
||||||
= render :partial => "common/button",:locals => { :name=>:save, :caption => t(:save,:scope=>:common), :icon =>'icon-cog icon-white'}
|
|
43
app/views/contacts/import_preview.rhtml
Normal file
43
app/views/contacts/import_preview.rhtml
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<h1><%= _('Contacts You Are About To Import')%></h1>
|
||||||
|
|
||||||
|
<% if flash["errors"] and not flash["errors"].empty?%>
|
||||||
|
<%= _('Errors')%>
|
||||||
|
<ul>
|
||||||
|
<% flash["errors"].each do |message| %>
|
||||||
|
<li><%= message %>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<form action="<%=link_contact_import%>" method="post">
|
||||||
|
|
||||||
|
<table class="list">
|
||||||
|
<tr>
|
||||||
|
<th> </th>
|
||||||
|
<th width="100px"><%= _('First name')%></th>
|
||||||
|
<th width="100px"><%= _('Last name')%></th>
|
||||||
|
<th><%= _('E-mail')%></th>
|
||||||
|
</tr>
|
||||||
|
<%
|
||||||
|
for i in 0...@contacts.length
|
||||||
|
contact = @contacts[i]
|
||||||
|
%>
|
||||||
|
<tr class="<%= alternator %>">
|
||||||
|
<td><%=i+1%></td>
|
||||||
|
<td><input type="text" name="contact[<%=i%>][fname]" value="<%=contact.fname%>" size="15" /></td>
|
||||||
|
<td><input type="text" name="contact[<%=i%>][lname]" value="<%=contact.lname%>" size="15" /></td>
|
||||||
|
<td><input type="text" name="contact[<%=i%>][email]" value="<%=contact.email%>" size="45" /></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan=4 class="buttonBar">
|
||||||
|
<input type="submit" value="<%= _('Import')%>">
|
||||||
|
<input type="button" value="<%= _('Choose another file')%>" onclick="window.location='<%=link_contact_add_multiple%>'">
|
||||||
|
<input type="button" value="<%= _('Back to contacts')%>" onclick="window.location='<%=link_contact_list%>'">
|
||||||
|
<input type="button" value="<%= _('Back to folders')%>" onclick="window.location='<%=link_main_index%>'">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
115
app/views/contacts/index.html.erb
Normal file
115
app/views/contacts/index.html.erb
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
<h1><%= t :contacts %></h1>
|
||||||
|
<% unless @mode == "choose" %>
|
||||||
|
<div id="header">
|
||||||
|
<ul id="primary">
|
||||||
|
<li><%=link_folders%></li>
|
||||||
|
<li><%=link_send_mail%></li>
|
||||||
|
<li><%=link_mail_prefs%></li>
|
||||||
|
<li><%=link_mail_filters%></li>
|
||||||
|
<li><span><%= t :contacts %></span>
|
||||||
|
<ul id="secondary">
|
||||||
|
<li><%=link_contact_add_one%></li>
|
||||||
|
<li><%=link_to t(:add_multiple), add_multiple_contacts_path %></li>
|
||||||
|
<% if ret = session["return_to"] %>
|
||||||
|
<li><%=link_to(t(:back_to_message), ret) %></li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<% end -%>
|
||||||
|
<div id="tab_main">
|
||||||
|
<div id="tab_content">
|
||||||
|
|
||||||
|
<% if flash["alert"] %><ul><li><%= flash["alert"] %></li></ul><% end %>
|
||||||
|
<form action="<%=link_contact_choose%>?mode=<%=@mode%>" method="post">
|
||||||
|
<input type="hidden" name="mode" value="<%=@mode%>"/>
|
||||||
|
<% if @group_id and not @group_id.nil? %>
|
||||||
|
<input type="hidden" name="group_id" value="<%=@group_id%>"/>
|
||||||
|
<% end %>
|
||||||
|
<table class="list">
|
||||||
|
<tr>
|
||||||
|
<td colspan="4" id="alphaListHeader">
|
||||||
|
<% CDF::CONFIG[:contact_letters].each do |letter| %>
|
||||||
|
<%= link_to letter, contacts_path(:letter => letter) %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= link_to t(:show_all), contacts_path %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3"><%= will_paginate @contacts %></td>
|
||||||
|
</tr>
|
||||||
|
<% if @mode == "choose" %>
|
||||||
|
<tr>
|
||||||
|
<th><%= "#{t :to} #{t :cc} #{t :bcc}" %></th>
|
||||||
|
<th><%= t :name %></th>
|
||||||
|
<th><%= t :email %></th>
|
||||||
|
</tr>
|
||||||
|
<% for contact in @contacts %>
|
||||||
|
<tr class="<%= alternator %>">
|
||||||
|
<td><input type="checkbox" name="contacts_to[<%=contact.id%>]" value="1"/>
|
||||||
|
<input type="checkbox" name="contacts_cc[<%=contact.id%>]" value="1"/>
|
||||||
|
<input type="checkbox" name="contacts_bcc[<%=contact.id%>]" value="1"/></td>
|
||||||
|
<td><%=contact.full_name%></td>
|
||||||
|
<td><%=contact.email%></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<tr class="rowsep"><td colspan="3"><%=t(:groups)%>:</td></tr>
|
||||||
|
<% for group in @contactgroups %>
|
||||||
|
<tr class="<%= alternator %>">
|
||||||
|
<td><input type="checkbox" name="groups_to[<%=group.id%>]" value="1"/>
|
||||||
|
<input type="checkbox" name="groups_cc[<%=group.id%>]" value="1"/>
|
||||||
|
<input type="checkbox" name="groups_bcc[<%=group.id%>]" value="1"/></td>
|
||||||
|
<td><%=group.name%></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<tr>
|
||||||
|
<td colspan=3 class="buttonBar">
|
||||||
|
<input type="submit" value="<%= t(:choose)%>">
|
||||||
|
<input type="button" value="<%= t(:cancel)%>" onclick="javascript:window.close();">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% elsif @mode == "groups"%>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th width="200px"><%= t(:name)%></th>
|
||||||
|
<th><%= t(:email)%></th>
|
||||||
|
</tr>
|
||||||
|
<% for contact in @contacts %>
|
||||||
|
<input type="hidden" id="contacts_for_group[<%=contact.id%>]" name="contacts_for_group[<%=contact.id%>]" value="<%=@contacts_for_group[contact.id]%>" >
|
||||||
|
<tr class="<%= alternator %>">
|
||||||
|
<td><input type="checkbox" id="contacts_for_group[<%=contact.id%>]" name="contacts_for_group[<%=contact.id%>]"
|
||||||
|
value="<%=@contacts_for_group[contact.id]%>" onclick="toggleCheckbox(this)"
|
||||||
|
<%=@contacts_for_group[contact.id] == 1 ? " checked " : " " %> ></td>
|
||||||
|
<td><%=contact.full_name%></td>
|
||||||
|
<td><%=contact.email%></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<tr>
|
||||||
|
<td colspan=2 class="buttonBar">
|
||||||
|
<input type="submit" value="<%= t(:save)%>">
|
||||||
|
<input type="button" value="<%= t(:back_to_groups)%>" onclick="window.location='<%=link_contact_group_list%>'">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% else %>
|
||||||
|
<tr>
|
||||||
|
<th width="200px"><%= t(:name)%></th>
|
||||||
|
<th><%= t(:email)%></th>
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
<% for contact in @contacts %>
|
||||||
|
<tr class="<%= alternator %>">
|
||||||
|
<td><%= link_to(contact.full_name, :controller=>:contacts, :action => "edit", :id => contact.id ) %></td>
|
||||||
|
<td><%= link_to( contact.email, :controller => :webmail, :action => "compose", :params => { "mail[to]" => contact.email } ) %></td>
|
||||||
|
<td><%= link_to(t(:delete), {:controller=>:contacts, :action=>'delete', :id=>contact.id},
|
||||||
|
{:confirm=>t(:delete_contact_question, :name => contact.show_name, :email => contact.email)})%>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,38 +0,0 @@
|
||||||
= content_for :sidebar do
|
|
||||||
= render :partial => "sidebar/sidebar"
|
|
||||||
|
|
||||||
= content_for :title do
|
|
||||||
\-
|
|
||||||
= t(:contacts,:scope=>:contact)
|
|
||||||
|
|
||||||
= render :partial => 'common/main_navigation', :locals => { :contacts => :active }
|
|
||||||
|
|
||||||
%form{:class=>"form-horizontal top-pix18",:action=>url_for(@contact),:method=>"post"}
|
|
||||||
- if @contacts.size.zero?
|
|
||||||
.alert
|
|
||||||
= t(:no_entries,:scope=>:contact)
|
|
||||||
%p{:class=>"bottom-pix18"}
|
|
||||||
= render :partial => "common/anchor", :locals => {:caption=>t('create_new',:scope=>'contact'),
|
|
||||||
:icon=>'icon-plus icon-white',
|
|
||||||
:href=>new_contact_path}
|
|
||||||
- else
|
|
||||||
.well{:style=>"padding: 5px 3pt;"}
|
|
||||||
%h5
|
|
||||||
= t(:total_entries,:scope=>:contact)
|
|
||||||
\:
|
|
||||||
= @contacts.total_entries
|
|
||||||
%p{:class=>"bottom-pix18"}
|
|
||||||
= render :partial => "common/anchor", :locals => {:caption=>t('create_new',:scope=>'contact'),
|
|
||||||
:icon=>'icon-plus icon-white',
|
|
||||||
:href=>new_contact_path}
|
|
||||||
= render :partial => "common/button", :locals => {:name=>'delete_selected',
|
|
||||||
:caption=>t('delete_selected',:scope=>'contact'),
|
|
||||||
:icon=>'icon-minus icon-white'}
|
|
||||||
= render :partial => "common/button", :locals => {:name=>'compose_to_selected',
|
|
||||||
:caption=>t('compose_to_selected',:scope=>'contact'),
|
|
||||||
:icon=>'icon-envelope icon-white'}
|
|
||||||
= render :partial => 'list'
|
|
||||||
|
|
||||||
= render :partial => 'common/import_export',:locals=>{:im_ex_path => contacts_import_export_path,
|
|
||||||
:im_ex_label => t(:select_file,:scope=>:contact),
|
|
||||||
:im_ex_size => @contacts.total_entries }
|
|
73
app/views/contacts/new.html.erb
Normal file
73
app/views/contacts/new.html.erb
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
<h1><%=t(:edit_create_contact)%></h1>
|
||||||
|
<div id="header">
|
||||||
|
<ul id="primary">
|
||||||
|
<li><%=link_folders%></li>
|
||||||
|
<li><%=link_send_mail%></li>
|
||||||
|
<li><%=link_mail_prefs%></li>
|
||||||
|
<li><%=link_mail_filters%></li>
|
||||||
|
<li><span><%= t :contacts %></span>
|
||||||
|
<ul id="secondary">
|
||||||
|
<li><%=link_to t(:back_to_contacts), contacts_url%></li>
|
||||||
|
<% if ret = session["return_to"] %>
|
||||||
|
<li><%=link_to(t(:back_to_message), ret) %></li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="tab_main">
|
||||||
|
<div id="tab_content">
|
||||||
|
|
||||||
|
|
||||||
|
<% form_tag( contacts_path, 'method' => 'post', 'class' => 'two_columns') do %>
|
||||||
|
<%= form_input(:hidden_field, 'contact', 'id') %>
|
||||||
|
<%= form_input(:hidden_field, 'contact', 'customer_id') %>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<%= form_input(:text_field, 'contact', 'fname', t(:first_name), 'class'=>'two_columns') %>
|
||||||
|
<%= form_input(:text_field, 'contact', 'lname', t(:last_name), 'class'=>'two_columns') %>
|
||||||
|
<%= form_input((@contact.new_record? ? :text_field : :read_only_field), 'contact', 'email', t(:email), 'class'=>'two_columns')%>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<% for group in @contactgroups %>
|
||||||
|
<input id="groups[<%=group.id%>]" type="hidden" name="groups[<%=group.id%>]" value="<%=@groups[group.id]%>">
|
||||||
|
<% end %>
|
||||||
|
<% if not(@contactgroups.empty?) %>
|
||||||
|
<%=_('Contact belong to these groups')%>:
|
||||||
|
<table class="list">
|
||||||
|
<tr>
|
||||||
|
<%
|
||||||
|
end
|
||||||
|
col = 1
|
||||||
|
for group in @contactgroups %>
|
||||||
|
<th>
|
||||||
|
<input id="groups[<%=group.id%>]" type="checkbox" name="groups[<%=group.id%>]" value="<%=@groups[group.id]%>" onclick="toggleCheckbox(this)"
|
||||||
|
<%=@groups[group.id] == 1 ? " checked " : " " %> >
|
||||||
|
<%=group.name %>
|
||||||
|
</th>
|
||||||
|
<% if col%2 == 0 %>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<% end
|
||||||
|
col = col + 1 %>
|
||||||
|
<% end %>
|
||||||
|
<% if col%2 == 0 and not(@contactgroups.empty?) %>
|
||||||
|
<th> </th>
|
||||||
|
<% end %>
|
||||||
|
<% if not(@contactgroups.empty?) %>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<table class="edit">
|
||||||
|
<tr>
|
||||||
|
<td colspan=2 class="buttonBar">
|
||||||
|
<input type="submit" name="paction" value="<%=t(:save)%>"/>
|
||||||
|
<input type="submit" name="paction" value="<%=t(:save_and_add_another)%>"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,19 +0,0 @@
|
||||||
= content_for :sidebar do
|
|
||||||
= render :partial => "sidebar/sidebar"
|
|
||||||
|
|
||||||
= content_for :title do
|
|
||||||
\-
|
|
||||||
= t(:contacts,:scope=>:contact)
|
|
||||||
|
|
||||||
= render :partial => 'common/main_navigation', :locals => { :contacts => :active }
|
|
||||||
|
|
||||||
.well{:style=>"padding: 5px 3pt;"}
|
|
||||||
%h3
|
|
||||||
= t(:creating_new,:scope=>:contact)
|
|
||||||
|
|
||||||
%form{:class=>"form-horizontal",:action=>url_for(@contact),:method=>"post"}
|
|
||||||
%fieldset
|
|
||||||
= render :partial => "attrs"
|
|
||||||
.control-group
|
|
||||||
.controls
|
|
||||||
= render :partial => "common/button",:locals => { :name=>:save, :caption => t(:save,:scope=>:common), :icon =>'icon-cog icon-white'}
|
|
|
@ -1,8 +0,0 @@
|
||||||
%form{:class=>"form-horizontal",:action=>folders_create_path,:method=>"post"}
|
|
||||||
%fieldset
|
|
||||||
= render :partial => "common/select_for_folders",:locals => { :label=> t(:parent,:scope=>:folder), :name => "folder", :id => "parent", :collection => @folders, :choice => "", :blank => true}
|
|
||||||
= render :partial => "common/input_form_field",:locals => { :model => 'folder',:attr => 'target'}
|
|
||||||
.control-group
|
|
||||||
.controls
|
|
||||||
= render :partial => "common/button",:locals => { :name=>:create, :caption => t(:create,:scope=>:common), :icon =>'icon-plus icon-white'}
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
%form{:class=>"form-horizontal",:action=>folders_delete_path,:method=>"post"}
|
|
||||||
%fieldset
|
|
||||||
= render :partial => "common/select_for_folders",:locals => { :label=> t(:to_delete,:scope=>:folder), :name => "folder", :id => "delete", :collection => @folders, :choice => "", :blank => true}
|
|
||||||
.control-group
|
|
||||||
.controls
|
|
||||||
= render :partial => "common/button",:locals => { :name=>:delete, :caption => t(:delete,:scope=>:common), :icon =>'icon-minus icon-white'}
|
|
|
@ -1,16 +0,0 @@
|
||||||
.well{:style=>"padding: 8px 3pt;"}
|
|
||||||
- if @folders_shown.nil? or @folders_shown.size.zero?
|
|
||||||
%p
|
|
||||||
= t(:no_shown,:scope=>:folder)
|
|
||||||
= link_to t(:folders,:scope=>:folder), folders_path
|
|
||||||
- else
|
|
||||||
%ul{:class=>"nav nav-list"}
|
|
||||||
%li{:class=>"nav-header"}
|
|
||||||
=t(:folders,:scope=>:folder)
|
|
||||||
- @folders_shown.each do |folder|
|
|
||||||
- if folder == @current_folder
|
|
||||||
%li{:class=>"active"}
|
|
||||||
= folder_link(:folder=>folder,:active=>true)
|
|
||||||
- else
|
|
||||||
%li
|
|
||||||
= folder_link(:folder=>folder,:active=>false)
|
|
|
@ -1,11 +0,0 @@
|
||||||
%form{:class=>"form-horizontal",:action=>folders_refresh_path,:method=>"post"}
|
|
||||||
%fieldset
|
|
||||||
.control-group
|
|
||||||
%label{:class=>"control-label"}
|
|
||||||
= t(:presentation,:scope=>:folder)
|
|
||||||
.controls
|
|
||||||
= render :partial=>"common/multiselect",:locals => {:objects => @folders, :selected_objects => @folders_shown,:style=>"",:id=>"multiselect_form",:name=>"folders_to_show[]",:value=>:id,:joiner=>"",:text=>[:parent,:delim,:name]}
|
|
||||||
.control-group
|
|
||||||
.controls
|
|
||||||
= render :partial => "common/button",:locals => { :name=>:show_hide, :caption => t(:show_hide,:scope=>:folder), :icon =>'icon-eye-open icon-white'}
|
|
||||||
= render :partial => "common/button",:locals => { :name=>:refresh, :caption => t(:refresh,:scope=>:folder), :icon =>'icon-refresh icon-white'}
|
|
|
@ -1,9 +0,0 @@
|
||||||
%form{:class=>"form-horizontal",:action=>folders_system_path,:method=>"post"}
|
|
||||||
%fieldset
|
|
||||||
= render :partial => "common/select_for_folders",:locals => { :label=> t(:folder,:scope => :folder) + " " + t(:inbox_name,:scope=>:folder), :name => "folder", :id => "mailbox_inbox", :collection => @folders, :choice => @folder_inbox, :blank => true}
|
|
||||||
= render :partial => "common/select_for_folders",:locals => { :label=> t(:folder,:scope => :folder) + " " + t(:trash_name,:scope=>:folder), :name => "folder", :id => "mailbox_trash", :collection => @folders, :choice => @folder_trash, :blank => true}
|
|
||||||
= render :partial => "common/select_for_folders",:locals => { :label=> t(:folder,:scope => :folder) + " " + t(:sent_name,:scope=>:folder), :name => "folder", :id => "mailbox_sent", :collection => @folders, :choice => @folder_sent, :blank => true}
|
|
||||||
= render :partial => "common/select_for_folders",:locals => { :label=> t(:folder,:scope => :folder) + " " + t(:drafts_name,:scope=>:folder), :name => "folder", :id => "mailbox_drafts", :collection => @folders, :choice => @folder_drafts, :blank => true}
|
|
||||||
.control-group
|
|
||||||
.controls
|
|
||||||
= render :partial => "common/button",:locals => { :name=>:set, :caption => t(:set,:scope=>:common), :icon =>'icon-cog icon-white'}
|
|
48
app/views/folders/index.html.erb
Normal file
48
app/views/folders/index.html.erb
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<h1><%=t :mailbox %></h1>
|
||||||
|
<div id="header">
|
||||||
|
<ul id="primary">
|
||||||
|
<li><span><%= t :folders %></span>
|
||||||
|
<ul id="secondary">
|
||||||
|
<li><%=link_back_to_messages%></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><%=link_send_mail%></li>
|
||||||
|
<li><%=link_mail_prefs%></li>
|
||||||
|
<li><%=link_mail_filters%></li>
|
||||||
|
<li><%=link_main%></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="tab_main">
|
||||||
|
<div id="tab_content">
|
||||||
|
|
||||||
|
<% content_for('sidebar') { %>
|
||||||
|
<div id="folders">
|
||||||
|
<h4><%= t :add_folder %></h4>
|
||||||
|
<hr/>
|
||||||
|
<% form_tag folders_path, :id => 'new_folder' do %>
|
||||||
|
<ul>
|
||||||
|
<li><label for='folder'><%= t :name %>:</label></li>
|
||||||
|
<li><%= text_field_tag 'folder', '', :size => 18 %></li>
|
||||||
|
<li><%= submit_tag t(:add_folder) %></li>
|
||||||
|
</ul>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<div id="messages">
|
||||||
|
<div id='msg-fl-list'>
|
||||||
|
<table>
|
||||||
|
<thead><tr><th><%= t :folder %></th><th><%= t :total_messages %></th><th><%= t :unseen%></th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<% for folder in @folders %>
|
||||||
|
<tr>
|
||||||
|
<td><%=folder_manage_link(folder)%></td>
|
||||||
|
<td><%= folder.total %></td>
|
||||||
|
<td><%= folder.unseen > 0 ? "<b>#{folder.unseen}</b>" : "#{folder.unseen}" %></td></tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,16 +0,0 @@
|
||||||
= content_for :sidebar do
|
|
||||||
= render :partial => "sidebar/sidebar"
|
|
||||||
|
|
||||||
= content_for :title do
|
|
||||||
\-
|
|
||||||
= t(:folders,:scope=>:folder)
|
|
||||||
|
|
||||||
= render :partial => 'common/main_navigation', :locals => { :folders => :active }
|
|
||||||
|
|
||||||
.row
|
|
||||||
.span9
|
|
||||||
= render :partial => "refresh"
|
|
||||||
= render :partial => "create"
|
|
||||||
= render :partial => "delete"
|
|
||||||
= render :partial => "system"
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
= content_for :sidebar do
|
|
||||||
= render :partial => "sidebar/sidebar"
|
|
||||||
|
|
||||||
= content_for :title do
|
|
||||||
\-
|
|
||||||
= t(:about,:scope=>:internal)
|
|
||||||
|
|
||||||
= render :partial => 'common/main_navigation', :locals => { :about => :active }
|
|
||||||
|
|
||||||
.well{:style=>"padding: 5px 3pt;"}
|
|
||||||
%h3
|
|
||||||
= t(:current_version,:scope=>:internal) + ": " + $defaults["version"]
|
|
||||||
.well
|
|
||||||
= raw BlueCloth::new(render :file => 'README.markdown').to_html
|
|
||||||
.well
|
|
||||||
= raw BlueCloth::new(render :file => 'CHANGES.markdown').to_html
|
|
||||||
.well
|
|
||||||
= raw BlueCloth::new(render :file => 'TODO.markdown').to_html
|
|
||||||
.well
|
|
||||||
= raw BlueCloth::new(render :file => 'AUTHORS.markdown').to_html
|
|
||||||
.well
|
|
||||||
= raw BlueCloth::new(render :file => 'UNLICENSE.markdown').to_html
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
!!!
|
|
||||||
%html
|
|
||||||
%head
|
|
||||||
%title
|
|
||||||
=t(:mailr,:scope=>:common)
|
|
||||||
= yield :title
|
|
||||||
%li{:rel=>"shortcut icon", :href=>"/favicon.ico"}/
|
|
||||||
= stylesheet_link_tag "application", :media => "all"
|
|
||||||
= javascript_include_tag "application"
|
|
||||||
= csrf_meta_tags
|
|
||||||
%body{:class=>"application"}
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.span3#sidebar
|
|
||||||
= yield :sidebar
|
|
||||||
.span9#main
|
|
||||||
- if flash[:error]
|
|
||||||
.alert.alert-error
|
|
||||||
= flash[:error]
|
|
||||||
- elsif flash[:info]
|
|
||||||
.alert.alert-info
|
|
||||||
= flash[:info]
|
|
||||||
- elsif flash[:success]
|
|
||||||
.alert.alert-success
|
|
||||||
= flash[:success]
|
|
||||||
= render :partial => "common/main_header"
|
|
||||||
= yield
|
|
||||||
%hr/
|
|
||||||
.row
|
|
||||||
#footer-simple
|
|
||||||
%a{:href=>"https://github.com/musashimm/mailr"} MailR
|
|
||||||
\- open source web mail client
|
|
16
app/views/layouts/chooser.html.erb
Normal file
16
app/views/layouts/chooser.html.erb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<!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=utf-8" />
|
||||||
|
<%=javascript_include_tag "global" %>
|
||||||
|
<%=stylesheet_link_tag "admin", "tabs", "mailr" %>
|
||||||
|
<%=@additional_scripts%>
|
||||||
|
</head>
|
||||||
|
<body id="bodyID" onload="<%=@onload_function%>">
|
||||||
|
<%= @content_for_layout %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue