Compare commits

...

31 Commits

Author SHA1 Message Date
Denis Knauf fe63f11068 header-anchor-test 2012-08-11 17:57:01 +02:00
Denis Knauf 309adafd48 README -> README.md: markdown 2012-08-11 17:55:26 +02:00
Alexander Negoda 0af713b765 update gems 2012-08-05 21:33:01 +04:00
Alexander Negoda b05879afdc visible true for all photos after create 2012-07-30 23:56:01 +04:00
Alexander Negoda c526882f27 bootstrap to forms 2012-07-30 23:08:48 +04:00
Alexander Negoda ef55c642d0 added new files to precompile list 2012-07-30 21:29:25 +04:00
Alexander Negoda b185c08481 fix default_url_options for production mode 2012-07-30 03:13:51 +04:00
Alexander Negoda 68cd47abba fix default_url_options for production mode 2012-07-30 03:11:42 +04:00
Alexander Negoda 5f5b2eca86 fix default_url_options for production mode 2012-07-30 03:10:12 +04:00
Alexander Negoda a7722cf8d5 try fix assets precompile error 2012-07-30 02:56:45 +04:00
Alexander Negoda bf80a200f0 comment all favicon_tag 2012-07-30 02:46:05 +04:00
Alexander Negoda 5c131394aa fix bug for production mode 2012-07-30 02:42:26 +04:00
Alexander Negoda 2469225cda fix username 2012-07-29 20:49:53 +04:00
Alexander Negoda 7caba3f464 fix translate 2012-07-29 20:37:56 +04:00
Alexander Negoda 2042f17a3d update gems 2012-07-29 20:32:22 +04:00
Alexander Negoda 7e9754714a added unicorn cinfig 2012-07-29 03:19:53 +04:00
Alexander Negoda 954e3b68ae upd 2012-07-29 02:33:03 +04:00
Alexander Negoda 0ab5ab468f added theme metallic for slider 2012-07-27 03:08:25 +04:00
Alexander Negoda b1ad108123 ratings, home slider etc. 2012-07-27 00:26:23 +04:00
Alexander Negoda e59d11e1c9 big update 2012-07-25 01:26:16 +04:00
Alexander Negoda ac9a8886de to rails assets pipeline style 2012-07-21 00:57:53 +04:00
Alexander Negoda d996de1514 fix validation for photo title if russian locale 2012-07-21 00:50:30 +04:00
Alexander Negoda aedc18f834 comment for pg gem 2012-07-21 00:05:12 +04:00
Alexander Negoda 0b7628dc95 move princaly & dynamic_form to gems 2012-07-21 00:04:15 +04:00
Alexander Negoda 3ae36b6689 ignore for .idea + update gems 2012-07-20 23:57:24 +04:00
Espen Antonsen b8a14725ee sqlite as default for dev env 2012-06-21 13:54:48 +02:00
Espen Antonsen 9c0ef432d0 carrierwave 0.6.1 2012-04-24 14:56:42 +08:00
Espen Antonsen 1a2cbff99e no encoding 2012-04-24 14:53:14 +08:00
Espen Antonsen 25c8c3b5cb bundle update 2012-04-24 12:53:27 +08:00
Espen Antonsen bd431ab2e3 plupload 1.5.4 2012-04-24 12:51:32 +08:00
Espen Antonsen 0ed49f3021 Version 1.2.3 2012-04-04 16:36:45 +07:00
281 changed files with 11878 additions and 21033 deletions

5
.gitignore vendored
View File

@ -13,4 +13,7 @@ config/deploy
Capfile
public/thumbs
public/uploads
vendor/cache
public/assets
vendor/cache
.idea
.sass-cache

51
Gemfile
View File

@ -1,23 +1,46 @@
source 'http://rubygems.org'
gem 'rails', '3.2.3'
gem 'authlogic'
gem 'rails', '3.2.7'
gem 'sqlite3'
gem 'mime-types', :require => 'mime/types'
gem 'carrierwave'
gem 'dynamic_form'
gem 'kaminari', :git => 'git://github.com/amatsuda/kaminari.git'
gem 'princely'
gem 'unicorn'
gem 'jquery-rails'
gem 'jquery-ui-rails'
gem 'twitter-bootstrap-rails', :git => 'git://github.com/seyhunak/twitter-bootstrap-rails.git'
gem 'ajaxful_rating_jquery', :git => 'git://github.com/greendog/ajaxful_rating_jquery.git'#, :branch => 'rails3'
gem 'configatron', :git => 'git://github.com/markbates/configatron.git'
gem 'plupload-rails', :git => 'git://github.com/bryanmig/plupload-rails.git'
#gem 'sequel', :git => 'git://github.com/jeremyevans/sequel.git'
gem 'breadcrumbs_on_rails', :git => 'git://github.com/lloydk/breadcrumbs_on_rails.git'
gem 'russian', :git => 'git://github.com/yaroslav/russian.git'
# -- Heroku
#gem 'heroku'
#gem 'pg'
gem "devise_omniauth_engine", :git=>"git://github.com/greendog/devise_omniauth_engine.git"
gem 'omniauth-twitter'
gem 'omniauth-facebook'
gem 'omniauth-openid'
gem 'omniauth-google-apps'
gem 'omniauth-vkontakte', :git => 'git://github.com/mamantoha/omniauth-vkontakte.git'
gem 'cancan'
# -- Database
# SQLite:
#gem 'sqlite3-ruby'
# MySQL:
#gem 'mysql2'
# PostgreSQL:
gem 'pg'
group :assets do
gem 'sass-rails'
gem 'coffee-rails'
gem 'uglifier'
end
group :development do
gem 'ffaker'
gem 'machinist'
gem 'action_mailer_tls', :git => 'git://github.com/openrain/action_mailer_tls.git'
gem 'capistrano', :git => 'git://github.com/capistrano/capistrano.git'
gem 'capistrano-unicorn', :git => 'git://github.com/sosedoff/capistrano-unicorn.git'
gem 'rvm-capistrano'
gem 'capistrano_colors'
end
# -- Cloud storage
# AWS S3 support. Can be disabled if using local file system instead of cloud storage.

View File

@ -1,46 +1,158 @@
GIT
remote: git://github.com/amatsuda/kaminari.git
revision: 82a38e07db1ca1598c8daf073a8f6be22ae714d6
specs:
kaminari (0.13.0)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
GIT
remote: git://github.com/bryanmig/plupload-rails.git
revision: 6d07d0f7e05d0b3fdc9b03b49d3a7c3aa1cd703b
specs:
plupload-rails (1.0.6)
rails (~> 3.1)
GIT
remote: git://github.com/capistrano/capistrano.git
revision: 62a6cb723dc583468943fc642847791fb4ad2686
specs:
capistrano (2.12.0)
highline
net-scp (>= 1.0.0)
net-sftp (>= 2.0.0)
net-ssh (>= 2.0.14)
net-ssh-gateway (>= 1.1.0)
GIT
remote: git://github.com/greendog/ajaxful_rating_jquery.git
revision: ae3314d3067d9f13a62675fa08afa4ecd31a7828
specs:
ajaxful_rating_jquery (3.0.0.beta3)
GIT
remote: git://github.com/greendog/devise_omniauth_engine.git
revision: c46d449222133f709b5f0cafc31a57f1ae208f06
specs:
devise_omniauth_engine (1.0.0)
devise
omniauth
yettings
GIT
remote: git://github.com/lloydk/breadcrumbs_on_rails.git
revision: 310c40186b97dc816e22e9be7aac3b43dcef040b
specs:
breadcrumbs_on_rails (2.2.0)
GIT
remote: git://github.com/mamantoha/omniauth-vkontakte.git
revision: b2b9f62972911ba328538368d13407b01bc9f297
specs:
omniauth-vkontakte (1.0.9)
multi_json
omniauth (~> 1.1.0)
omniauth-oauth2 (~> 1.0)
GIT
remote: git://github.com/markbates/configatron.git
revision: 7a81defa5e1fb032b5ed62754d7e6d7bfecf07a2
specs:
configatron (2.9.1)
yamler (>= 0.1.0)
GIT
remote: git://github.com/openrain/action_mailer_tls.git
revision: 4c4db7e098d54b2239c1ce7c195417552718418c
specs:
action_mailer_tls (1.1.3)
GIT
remote: git://github.com/seyhunak/twitter-bootstrap-rails.git
revision: 908e150800610138e2b48738f842afb85b3a832e
specs:
twitter-bootstrap-rails (2.1.1)
actionpack (>= 3.1)
less-rails (~> 2.2.3)
railties (>= 3.1)
therubyracer (= 0.10.1)
GIT
remote: git://github.com/sosedoff/capistrano-unicorn.git
revision: bafc12cd8235307d30b5c85259914d17c5ece2d3
specs:
capistrano-unicorn (0.1.6)
capistrano
GIT
remote: git://github.com/yaroslav/russian.git
revision: e2dde13672bcee176f8b0be364a55ac256913231
specs:
russian (0.6.0)
i18n (>= 0.5.0)
GEM
remote: http://rubygems.org/
specs:
actionmailer (3.2.3)
actionpack (= 3.2.3)
actionmailer (3.2.7)
actionpack (= 3.2.7)
mail (~> 2.4.4)
actionpack (3.2.3)
activemodel (= 3.2.3)
activesupport (= 3.2.3)
actionpack (3.2.7)
activemodel (= 3.2.7)
activesupport (= 3.2.7)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.1)
journey (~> 1.0.4)
rack (~> 1.4.0)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.1.2)
activemodel (3.2.3)
activesupport (= 3.2.3)
sprockets (~> 2.1.3)
activemodel (3.2.7)
activesupport (= 3.2.7)
builder (~> 3.0.0)
activerecord (3.2.3)
activemodel (= 3.2.3)
activesupport (= 3.2.3)
activerecord (3.2.7)
activemodel (= 3.2.7)
activesupport (= 3.2.7)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.3)
activemodel (= 3.2.3)
activesupport (= 3.2.3)
activesupport (3.2.3)
activeresource (3.2.7)
activemodel (= 3.2.7)
activesupport (= 3.2.7)
activesupport (3.2.7)
i18n (~> 0.6)
multi_json (~> 1.0)
arel (3.0.2)
authlogic (3.1.0)
activerecord (>= 3.0.7)
activerecord (>= 3.0.7)
bcrypt-ruby (3.0.1)
builder (3.0.0)
carrierwave (0.6.1)
cancan (1.6.8)
capistrano_colors (0.5.5)
carrierwave (0.6.2)
activemodel (>= 3.2.0)
activesupport (>= 3.2.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.3.3)
commonjs (0.2.6)
devise (2.1.2)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.1)
railties (~> 3.1)
warden (~> 1.2.1)
dynamic_form (1.1.4)
erubis (2.7.0)
excon (0.13.2)
fog (1.3.1)
excon (0.15.5)
execjs (1.4.0)
multi_json (~> 1.0)
faraday (0.8.1)
multipart-post (~> 1.1)
ffaker (1.15.0)
fog (1.5.0)
builder
excon (~> 0.13.0)
excon (~> 0.14)
formatador (~> 0.2.0)
mime-types
multi_json (~> 1.0)
@ -48,73 +160,182 @@ GEM
net-ssh (>= 2.1.3)
nokogiri (~> 1.5.0)
ruby-hmac
formatador (0.2.1)
formatador (0.2.3)
hashie (1.2.0)
highline (1.6.13)
hike (1.2.1)
httpauth (0.1)
i18n (0.6.0)
journey (1.0.3)
json (1.6.6)
journey (1.0.4)
jquery-rails (2.0.2)
railties (>= 3.2.0, < 5.0)
thor (~> 0.14)
jquery-ui-rails (1.1.0)
jquery-rails
railties (>= 3.1.0)
json (1.7.4)
jwt (0.1.5)
multi_json (>= 1.0)
kgio (2.7.4)
less (2.2.1)
commonjs (~> 0.2.6)
less-rails (2.2.3)
actionpack (>= 3.1)
less (~> 2.2.0)
libv8 (3.3.10.4)
machinist (2.0)
mail (2.4.4)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.18)
mini_exiftool (1.3.1)
mime-types (1.19)
mini_exiftool (1.6.0)
mini_magick (3.4)
subexec (~> 0.2.1)
multi_json (1.2.0)
multi_json (1.3.6)
multipart-post (1.1.5)
net-scp (1.0.4)
net-ssh (>= 1.99.1)
net-ssh (2.3.0)
nokogiri (1.5.2)
pg (0.13.2)
net-sftp (2.0.5)
net-ssh (>= 2.0.9)
net-ssh (2.5.2)
net-ssh-gateway (1.1.0)
net-ssh (>= 1.99.1)
nokogiri (1.5.5)
oauth (0.4.6)
oauth2 (0.8.0)
faraday (~> 0.8)
httpauth (~> 0.1)
jwt (~> 0.1.4)
multi_json (~> 1.0)
rack (~> 1.2)
omniauth (1.1.0)
hashie (~> 1.2)
rack
omniauth-facebook (1.4.1)
omniauth-oauth2 (~> 1.1.0)
omniauth-google-apps (0.0.2)
omniauth (~> 1.0)
omniauth-openid (~> 1.0)
ruby-openid-apps-discovery (~> 1.2.0)
omniauth-oauth (1.0.1)
oauth
omniauth (~> 1.0)
omniauth-oauth2 (1.1.0)
oauth2 (~> 0.8.0)
omniauth (~> 1.0)
omniauth-openid (1.0.1)
omniauth (~> 1.0)
rack-openid (~> 1.3.1)
omniauth-twitter (0.0.12)
multi_json (~> 1.3)
omniauth-oauth (~> 1.0)
orm_adapter (0.4.0)
polyglot (0.3.3)
princely (1.2.5)
rack (1.4.1)
rack-cache (1.2)
rack (>= 0.4)
rack-openid (1.3.1)
rack (>= 1.1.0)
ruby-openid (>= 2.1.8)
rack-ssl (1.3.2)
rack
rack-test (0.6.1)
rack (>= 1.0)
rails (3.2.3)
actionmailer (= 3.2.3)
actionpack (= 3.2.3)
activerecord (= 3.2.3)
activeresource (= 3.2.3)
activesupport (= 3.2.3)
rails (3.2.7)
actionmailer (= 3.2.7)
actionpack (= 3.2.7)
activerecord (= 3.2.7)
activeresource (= 3.2.7)
activesupport (= 3.2.7)
bundler (~> 1.0)
railties (= 3.2.3)
railties (3.2.3)
actionpack (= 3.2.3)
activesupport (= 3.2.3)
railties (= 3.2.7)
railties (3.2.7)
actionpack (= 3.2.7)
activesupport (= 3.2.7)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (~> 0.14.6)
thor (>= 0.14.6, < 2.0)
raindrops (0.10.0)
rake (0.9.2.2)
rdoc (3.12)
json (~> 1.4)
ruby-hmac (0.4.0)
sprockets (2.1.2)
ruby-openid (2.2.0)
ruby-openid-apps-discovery (1.2.0)
ruby-openid (>= 2.1.7)
rvm-capistrano (1.2.5)
capistrano (>= 2.0.0)
sass (3.1.20)
sass-rails (3.2.5)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
sprockets (2.1.3)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
subexec (0.2.1)
thor (0.14.6)
sqlite3 (1.3.6)
subexec (0.2.2)
therubyracer (0.10.1)
libv8 (~> 3.3.10)
thor (0.15.4)
tilt (1.3.3)
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.32)
tzinfo (0.3.33)
uglifier (1.2.7)
execjs (>= 0.3.0)
multi_json (~> 1.3)
unicorn (4.3.1)
kgio (~> 2.6)
rack
raindrops (~> 0.7)
warden (1.2.1)
rack (>= 1.0)
yamler (0.1.0)
yettings (0.1.1)
PLATFORMS
ruby
DEPENDENCIES
authlogic
action_mailer_tls!
ajaxful_rating_jquery!
breadcrumbs_on_rails!
cancan
capistrano!
capistrano-unicorn!
capistrano_colors
carrierwave
coffee-rails
configatron!
devise_omniauth_engine!
dynamic_form
ffaker
fog
jquery-rails
jquery-ui-rails
kaminari!
machinist
mime-types
mini_exiftool
mini_magick
pg
rails (= 3.2.3)
omniauth-facebook
omniauth-google-apps
omniauth-openid
omniauth-twitter
omniauth-vkontakte!
plupload-rails!
princely
rails (= 3.2.7)
russian!
rvm-capistrano
sass-rails
sqlite3
twitter-bootstrap-rails!
uglifier
unicorn

109
README
View File

@ -1,109 +0,0 @@
== Welcome to Balder photo gallery
Made by Espen Antonsen.
Version 1.2.2 for Rails 3.1. See the rails2 branch for previous version.
http://balderapp.com
== Features
* Stores photos to disk in folders or on S3 (can run from Heroku...yay)
* Create multiple thumbnails of custom sizes
* Read and writes EXIF/IPTC title, description and keywords
* Organize in albums (as events in iPhoto)
* Combine albums in collections (as albums in iPhoto)
* Upload multiple photos
* Tag photos. Can also tag albums (actually all photos in album is tagged)
* User management with roles and permissions
* Geo-location of albums & photos with Google Maps integration.
== Requirements
Rails 3.1
Software
Default:
- ExifTool (required for Mini_EfixTool). Can be disabled. Default is to read EXIF tags but not write them to the file when database is updated as writing EXIF is slow. To enable just uncomment exif_write in photo.rb
Can be installed from: http://www.sno.phy.queensu.ca/~phil/exiftool/
- ImageMagicK. Carrierwave can use either RMagicK or MiniMagicK (default). To change resize option the correct gem must be used (specified in Gemfile) and change included setting for Carrierwave in file_uploader.rb
Can be installed from: http://www.imagemagick.org
Optional:
- ImageScience which requires FreeImage. Can be installed from: http://sourceforge.net/projects/freeimage/
Ruby Gems: See Gemfile
== Configuration
config/balder.rb has the following adjustable settings:
STORAGE_PATH Relative path to where the photos are stored. Default: uploads
Under the specified path two folders are used. "files" for original files and "thumbs" for generated thumbnails.
This can be adjusted in app/uploaders/file_uploader.rb
PRIVATE Require visitors to have a user and authenticate before viewing photos.
TITLE Title of site
HEROKU To be used on heroku.com. This will adjust carrierwave to save to Heroku's tmp area.
S3_KEY For saving files to Amazon S3 (required for Heroku)
S3_SECRET For saving files to Amazon S3 (required for Heroku)
S3_BUCKET For saving files to Amazon S3 (required for Heroku)
As these are environment variables you can easily add them to Heroku:
http://devcenter.heroku.com/articles/config-vars#rack_env_rails_env_merb_env
For a brief introduction to how to set up Balder on Heroku see:
http://blog.inspired.no/rails-photo-gallery-balder-on-heroku-and-s3-726
== Installation
1. Clone the project from GitHub or Gitorious:
GitHub: git clone git://github.com/espen/balder.git
2. Install required software listed above
3. 'bundle install' to install required gems.
4. Adjust the settings in balder.rb or as Heroku config variables (See configuration above)
5. Copy database file (not needed when hosting on Heroku):
cp config/database.example.yml config/database.yml
6. Create database user and edit database file. (unless on Heroku or using SQLite3)
7. rake db:create
8. rake db:migrate
9. Start up the project with your preferred web-server
=== Optional: add photos directly to disk
The gallery has a web-based upload tool. Alternatively you can upload files directly to the upload folder. This means you can import an existing folder based photo collection to Balder.
Put photos in containing folders(albums) in the specified gallery folder.
Hierarchy of folders is not fully supported.
This format is recommended:
./ski weekend in hemsedal/snow.jpg
./ski weekend in hemsedal/afterski.jpg
./trip to iran/beautiful girls in tehran.jpg
./trip to iran/mosque in yazd.jpg
./trip to iran/powder snow in dizin.jpg
Every time you manually add photos to disk you must scan by visiting /photos/scan or run ScanFiles.Scan(false) from the console.
== Version history
1.2.2
- Rails 3.1
1.2.1
- Using plupupload instead of uploadify for non-flash upload options. Can now use html5, normal form, silverlight, gears and browserplus for photo upload.
1.2.0
- New storage path: "/uploads/files/" instead of "/uploads/". Make sure you move your photos or adjust the storage path.
== TODO
- Testing...
== IDEAS
- Themes
- Improved UX
- Mobile/Tablet friendly display using CSS media queries
Patches welcome!
== Copyright and license info
This code is copyrighted by Espen Antonsen. The source code is available free under the MIT License.

157
README.md Normal file
View File

@ -0,0 +1,157 @@
Welcome to Balder photo gallery
===============================
Made by Espen Antonsen.
Version 1.2.3 for Rails 3.2. See the rails2 branch for previous version.
[http://balderapp.com](http://balderapp.com)
Features
========
* Stores photos to disk in folders or on S3 (can run from Heroku...yay)
* Create multiple thumbnails of custom sizes
* Read and writes EXIF/IPTC title, description and keywords
* Organize in albums (as events in iPhoto)
* Combine albums in collections (as albums in iPhoto)
* Upload multiple photos
* Tag photos. Can also tag albums (actually all photos in album is tagged)
* User management with roles and permissions
* Geo-location of albums & photos with Google Maps integration.
Requirements
============
Rails 3.2
Software
Default:
- **[ExifTool]** (required for *Mini_EfixTool*). Can be disabled. Default is to read EXIF tags but not write them to the file when database is updated as writing EXIF is slow. To enable just uncomment `exif_write in photo.rb`
- **[ImageMagicK]**. *Carrierwave* can use either *RMagicK* or *MiniMagicK* (default). To change resize option the correct gem must be used (specified in Gemfile) and change included setting for Carrierwave in `file_uploader.rb`
Optional:
- *ImageScience* which requires **[FreeImage]**.
Ruby Gems: See `Gemfile`
Configuration
=============
{#configuration}
`config/balder.rb` has the following adjustable settings:
STORAGE_PATH
: Relative path to where the photos are stored. Default: uploads
Under the specified path two folders are used. "files" for original files and "thumbs" for generated thumbnails.
This can be adjusted in app/uploaders/file_uploader.rb
PRIVATE
: Require visitors to have a user and authenticate before viewing photos.
TITLE
: Title of site
HEROKU
: To be used on heroku.com. This will adjust carrierwave to save to Heroku's tmp area.
S3_KEY
: For saving files to Amazon S3 (required for Heroku)
S3_SECRET
: For saving files to Amazon S3 (required for Heroku)
S3_BUCKET
: For saving files to Amazon S3 (required for Heroku)
As these are environment variables you can easily add them to Heroku:
http://devcenter.heroku.com/articles/config-vars#rack_env_rails_env_merb_env
For a brief introduction to how to set up Balder on Heroku see:
http://blog.inspired.no/rails-photo-gallery-balder-on-heroku-and-s3-726
Installation
============
1. Clone the project from GitHub or Gitorious:
git clone git://github.com/espen/balder.git # GitHup
2. Install required software listed above
3. `bundle install` to install required gems.
4. Adjust the settings in `balder.rb` or as Heroku config variables (See [configuration above](#configuration))
5. Copy database file (not needed when hosting on Heroku):
cp config/database.example.yml config/database.yml
6. Create database user and edit database file. (unless on Heroku or using SQLite3)
7. Create database:
rake db:create
8. Migrate database schema:
rake db:migrate
9. Start up the project with your preferred web-server
For example:
rails start # or:
passenger start
Optional: add photos directly to disk
-------------------------------------
The gallery has a web-based upload tool. Alternatively you can upload files directly to the upload folder. This means you can import an existing folder based photo collection to Balder.
Put photos in containing folders(albums) in the specified gallery folder.
Hierarchy of folders is not fully supported.
This format is recommended:
./ski weekend in hemsedal/snow.jpg
./ski weekend in hemsedal/afterski.jpg
./trip to iran/beautiful girls in tehran.jpg
./trip to iran/mosque in yazd.jpg
./trip to iran/powder snow in dizin.jpg
Every time you manually add photos to disk you must scan by visiting `/photos/scan` or run `ScanFiles.Scan(false)` from the console.
Version history
===============
v1.2.3
: Rails 1.2.3
v1.2.2
: Rails 3.1
v1.2.1
: Using plupupload instead of uploadify for non-flash upload options. Can now use html5, normal form, silverlight, gears and browserplus for photo upload.
v1.2.0
: New storage path: `/uploads/files/` instead of `/uploads/`. Make sure you move your photos or adjust the storage path.
TODO
====
- Testing...
IDEAS
=====
- Themes
- Improved UX
- Mobile/Tablet friendly display using CSS media queries
Patches welcome!
Copyright and license info
==========================
This code is copyrighted by Espen Antonsen.
The source code is available free under the MIT License.
[ImageMagicK]: http://www.imagemagick.org
[ExifTool]: http://www.sno.phy.queensu.ca/~phil/exiftool/
[FreeImage]: http://sourceforge.net/projects/freeimage/

View File

@ -4,4 +4,4 @@
require File.expand_path('../config/application', __FILE__)
require 'rake'
Balder::Application.load_tasks
Photomix::Application.load_tasks

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,59 @@
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
//= require jquery
//= require jquery_ujs
//= require jquery.easing.1.3
//= require jquery.noisy.min
//= require jquery.mousewheel
//= require fancybox/jquery.fancybox.pack
//= require fancybox/helpers/jquery.fancybox-buttons
//= require fancybox/helpers/jquery.fancybox-media
//= require fancybox/helpers/jquery.fancybox-thumbs
//= require twitter/bootstrap
//= require plupload
//= require jquery.plupload.queue
//= require plupload.flash
//= require plupload.silverlight
//= require plupload.html4
//= require plupload.html5
//= require plupload.gears
//= require plupload.browserplus
//= require_tree .
$(document).ready(function () {
$('body').noisy({
'intensity':10,
'size':200,
'opacity':0.120,
'fallback':'',
'monochrome':false
}).css('background-color', '#fefefe');
$('.icon-popover').popover()
$(".fancybox-thumb").fancybox({
prevEffect : 'none',
nextEffect : 'none',
helpers : {
title : {
type: 'outside'
},
overlay : {
opacity : 0.8,
css : {
'background-color' : '#000'
}
},
thumbs : {
width : 50,
height : 50
}
}
});
});

View File

@ -0,0 +1,4 @@
jQuery ->
$("a[rel=popover]").popover()
$(".tooltip").tooltip()
$("a[rel=tooltip]").tooltip()

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -0,0 +1,91 @@
/*
* Style by Rogie http://www.komodomedia.com/blog/2007/01/css-star-rating-redux/
*/
.ajaxful-rating,
.ajaxful-rating a:hover,
.ajaxful-rating a:active,
.ajaxful-rating a:focus,
.ajaxful-rating .show-value {
background: url("/assets/ajaxful_rating/star.png") left -1000px repeat-x;
}
.ajaxful-rating {
position: relative;
/*width: 125px; this is setted dynamically */
height: 25px;
overflow: hidden;
list-style: none;
margin: 0;
padding: 0;
background-position: left top;
}
.ajaxful-rating li {
display: inline;
}
.ajaxful-rating a,
.ajaxful-rating span,
.ajaxful-rating .show-value {
position: absolute;
top: 0;
left: 0;
text-indent: -1000em;
height: 25px;
line-height: 25px;
outline: none;
overflow: hidden;
border: none;
}
.ajaxful-rating a:hover,
.ajaxful-rating a:active,
.ajaxful-rating a:focus {
background-position: left bottom;
}
/* This section is generated dynamically.
Just add a call to the helper method 'ajaxful_rating_style' within
the head tags in your main layout
.ajaxful-rating .stars-1{
width: 20%;
z-index: 6;
}
.ajaxful-rating .stars-2{
width: 40%;
z-index: 5;
}
.ajaxful-rating .stars-3{
width: 60%;
z-index: 4;
}
.ajaxful-rating .stars-4{
width: 80%;
z-index: 3;
}
.ajaxful-rating .stars-5{
width: 100%;
z-index: 2;
}
*/
.ajaxful-rating .show-value {
z-index: 1;
background-position: left center;
}
/* smaller star */
.ajaxful-rating.small {
/*width: 50px; this is setted dynamically */
height: 10px;
}
.ajaxful-rating.small,
.ajaxful-rating.small a:hover,
.ajaxful-rating.small a:active,
.ajaxful-rating.small a:focus,
.ajaxful-rating.small .show-value {
background-image: url("/assets/ajaxful_rating/star_small.png");
line-height: 10px;
height: 10px;
}

View File

@ -0,0 +1,191 @@
/*
*= require_tree .
*= require jquery.plupload.queue
*= require bootstrap_and_overrides
*= require fancybox/jquery.fancybox
*= require fancybox/helpers/jquery.fancybox-buttons
*= require fancybox/helpers/jquery.fancybox-thumbs
*= require_self
*/
* {
text-shadow: 1px 1px 1px #999;
/*text-shadow: 0 1px 0 rgba(255, 255, 255, 0.1), 0 0 30px rgba(255, 255, 255, 0.125);*/
font-family: 'Nunito', 'Istok Web', sans-serif;
color: #333;
}
body {
padding-top: 90px;
padding-bottom: 40px;
}
h1, h2, h3, h4, h5, h6 {
color: #666;
}
.navbar-inner {
background-color: #FAFAFA !important;
background-image: -moz-linear-gradient(center top, #FAFAFA, #EAEAEA) !important;
background-image: -ms-linear-gradient(center top, #FAFAFA, #EAEAEA) !important;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#FAFAFA), to(#EAEAEA)) !important;
background-image: -webkit-linear-gradient(center top, #FAFAFA, #EAEAEA) !important;
background-image: -o-linear-gradient(center top, #FAFAFA, #EAEAEA) !important;
background-image: linear-gradient(top, #FAFAFA, #EAEAEA) !important;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#FAFAFA', endColorstr = '#EAEAEA', GradientType = 0) !important;
}
.navbar .brand {
color: #000 !important;
font-weight: bold !important;
padding-bottom: 5px !important;
padding: 10px 20px 12px;
/*text-shadow: 0 1px 0 rgba(255, 255, 255, 0.1), 0 0 30px rgba(255, 255, 255, 0.125);*/
}
.navbar .nav .dropdown-toggle .caret, .navbar .nav .open.dropdown .caret {
border-top-color: #000000;
}
.navbar .nav {
margin-top: 5px;
margin-bottom: 10px;
}
.navbar .nav > li {
padding-right: 5px;
}
.navbar .nav .divider-vertical {
padding: 0;
}
.navbar .nav > li > a {
color: #333333;
font-size: 18px;
}
.navbar .nav > li > a:hover {
background-color: #FAFAFA;
color: #7B7B7B;
border: 0px solid #C9C9C9;
border-radius: 5px 5px 5px 5px;
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 0px rgba(255, 255, 255, 0.75);
-moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 0px rgba(255, 255, 255, 0.75);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 0px rgba(255, 255, 255, 0.75);
transition: none;
}
.navbar .nav .active > a, .navbar .nav .active > a:hover {
background-color: #FAFAFA;
color: #7B7B7B;
border: 0;
border-radius: 5px 5px 5px 5px;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 0px rgba(255, 255, 255, 0.75);
transition: none;
}
.navbar .nav .open > .dropdown-toggle, .navbar .nav .active > .dropdown-toggle, .navbar .nav .open.active > .dropdown-toggle {
background-color: #FAFAFA;
color: #7B7B7B;
}
.navbar .nav .active > .dropdown-toggle:hover {
color: #7B7B7B;
}
.navbar-search {
margin-top: 15px;
}
.navbar-search .search-query {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 15px;
font-weight: normal;
line-height: 1.2;
color: #333;
background: #666;
background: rgba(255, 255, 255, 0.3);
border: 0;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 0px rgba(255, 255, 255, 0.75);
transition: none;
}
.navbar-search .search-query :-moz-placeholder {
color: #666;
}
.navbar-search .search-query::-webkit-input-placeholder {
color: #666;
}
.navbar-search .search-query:hover {
color: #333;
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;
box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
outline: 0;
}
.ajaxful-rating-wrapper {
float: right;
}
.view-btn {
display: inline;
padding: 5px;
float: left;
}
.anythingSlider {
padding: 0 0 28px 0;
}
.thumbnail {
background: none repeat scroll 0 0 #FFFFFF;
border: 0 none;
border-radius: 7px 7px 7px 7px;
box-shadow: 1px 1px 3px #D9D9D9;
display: block;
height: 340px;
}
.caption {
position: relative;
bottom: 0px;
height: 150px;
}
.caption .title {
padding: 5px 0 5px 0;
font-size: 13px;
text-align: center;
}
.caption .descr {
display: block;
padding: 10px 0 0 0;
}
.caption .controls {
position: absolute;
bottom: 5px;
width: 250px;
}
.caption .controls .tooltips{
float: left;
width: 15px;
padding: 5px;
}
.icon-popover{
cursor: pointer;
}

View File

@ -0,0 +1,32 @@
@import "twitter/bootstrap/bootstrap";
body {
padding-top: 60px;
}
@import "twitter/bootstrap/responsive";
// Set the correct sprite paths
@iconSpritePath: asset-path('twitter/bootstrap/glyphicons-halflings.png');
@iconWhiteSpritePath: asset-path('twitter/bootstrap/glyphicons-halflings-white.png');
// Set the Font Awesome (Font Awesome is default. You can disable by commenting below lines)
// Note: If you use asset_path() here, your compiled boostrap_and_overrides.css will not
// have the proper paths. So for now we use the absolute path.
@fontAwesomeEotPath: '/assets/fontawesome-webfont.eot';
@fontAwesomeWoffPath: '/assets/fontawesome-webfont.woff';
@fontAwesomeTtfPath: '/assets/fontawesome-webfont.ttf';
@fontAwesomeSvgPath: '/assets/fontawesome-webfont.svg';
// Font Awesome
@import "fontawesome";
// Your custom LESS stylesheets goes here
//
// Since bootstrap was imported above you have access to its mixins which
// you may use and inherit here
//
// If you'd like to override bootstrap's own variables, you can do so here as well
// See http://twitter.github.com/bootstrap/less.html for their names and documentation
//
// Example:
// @linkColor: #ff0000;

View File

@ -0,0 +1,3 @@
// Place all the styles related to the home controller here.
// They will automatically be included in application.css.
// You can use Less here: http://lesscss.org/

View File

@ -11,7 +11,7 @@
border: 1px solid #bababa;
padding: 2px 8px 3px 20px;
margin-right: 4px;
background: #f3f3f3 url('../img/buttons.png') no-repeat 0 center;
background: #f3f3f3 url(asset_path("buttons.png")) no-repeat 0 center;
outline: 0;
/* Optional rounded corners for browsers that support it */
@ -29,7 +29,7 @@
.plupload_disabled, a.plupload_disabled:hover {
color: #737373;
border-color: #c5c5c5;
background: #ededed url('../img/buttons-disabled.png') no-repeat 0 center;
background: #ededed url(asset_path('buttons-disabled.png')) no-repeat 0 center;
cursor: default;
}
@ -44,7 +44,7 @@
.plupload_container {
padding: 8px;
background: url('../img/transp50.png');
background: url(asset_path('transp50.png'));
/*-moz-border-radius: 5px;*/
}
@ -54,9 +54,9 @@
width: 98%;
}
.plupload_header {background: #2A2C2E url('../img/backgrounds.gif') repeat-x;}
.plupload_header {background: #2A2C2E url(asset_path('backgrounds.gif')) repeat-x;}
.plupload_header_content {
background: url('../img/backgrounds.gif') no-repeat 0 -317px;
background: url(asset_path('backgrounds.gif')) no-repeat 0 -317px;
min-height: 56px;
padding-left: 60px;
color: #FFF;
@ -83,7 +83,7 @@
.plupload_filelist li {
padding: 10px 8px;
background: #F5F5F5 url('../img/backgrounds.gif') repeat-x 0 -156px;
background: #F5F5F5 url(asset_path('backgrounds.gif')) repeat-x 0 -156px;
border-bottom: 1px solid #DDD;
}
@ -122,20 +122,20 @@
height: 16px;
}
li.plupload_uploading {background: #ECF3DC url('../img/backgrounds.gif') repeat-x 0 -238px;}
li.plupload_uploading {background: #ECF3DC url(asset_path('backgrounds.gif')) repeat-x 0 -238px;}
li.plupload_done {color:#AAA}
li.plupload_delete a {
background: url('../img/delete.gif');
background: url(asset_path('delete.gif'));
}
li.plupload_failed a {
background: url('../img/error.gif');
background: url(asset_path('error.gif'));
cursor: default;
}
li.plupload_done a {
background: url('../img/done.gif');
background: url(asset_path('done.gif'));
cursor: default;
}

View File

@ -20,14 +20,14 @@ div.plupload div.plupload_header {border-width: 0 0 1px 0; position: relative;}
}
.plupload_header_content {
background-image: url('../img/plupload.png');
background-image: url(asset_path('plupload.png'));
background-repeat: no-repeat;
background-position: 8px center;
min-height: 56px;
padding-left: 60px;
position:relative;
}
.plupload_header_content_bw {background-image: url('../img/plupload-bw.png');}
.plupload_header_content_bw {background-image: url(asset_path('plupload-bw.png'));}
.plupload_header_title {
font: normal 18px sans-serif;
padding: 6px 0 3px;
@ -61,7 +61,6 @@ div.plupload div.plupload_header {border-width: 0 0 1px 0; position: relative;}
max-height: 180px;
min-height: 168px;
_height: 168px;
overflow-y: auto;
}
.plupload_file_size, .plupload_file_status {text-align: right;}

View File

@ -1,5 +0,0 @@
class Admin::ApplicationController < ApplicationController
before_filter :require_role_admin
end

View File

@ -1,47 +0,0 @@
class Admin::UsersController < Admin::ApplicationController
def index
@users = User.find(:all, :order => "Name, email")
end
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(params[:user])
if @user.save
flash[:notice] = "Account registered!"
redirect_to @user
else
render :action => :new
end
end
def edit
@user = User.find(params[:id])
end
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
flash[:notice] = "Account updated!"
redirect_to @user
else
render :action => :edit
end
end
def destroy
@user = User.find(params[:id])
if @user.destroy
redirect_to users_path
else
redirect_to @user
end
end
end

View File

@ -1,10 +1,15 @@
class AlbumsController < ApplicationController
before_filter :check_public_access
before_filter :require_role_admin, :only => [:untouched, :new, :create, :edit, :update, :destroy]
skip_before_filter :authenticate_user!, :only => [:index, :show]
def index
add_breadcrumb t('activerecord.models.album.popular'), collections_path, :title => t('activerecord.models.album.popular')
add_breadcrumb t('activerecord.actions.create', :model => I18n.t('activerecord.models.album.single')), new_album_path,
:title => t('activerecord.actions.create', :model => I18n.t('activerecord.models.album.single')),
:li_icon => 'icon-plus-sign'
if params[:tag_id]
@albums = Album.find(:all, :conditions => [ "id IN ( SELECT DISTINCT photos.album_id FROM photos WHERE photos.id IN ( SELECT photo_id FROM photo_tags WHERE photo_tags.tag_id = :q) )", { :q => Tag.find( params[:tag_id] ).id } ], :order => 'title')
@albums = Album.where(:conditions => [ "id IN ( SELECT DISTINCT photos.album_id FROM photos WHERE photos.id IN ( SELECT photo_id FROM photo_tags WHERE photo_tags.tag_id = :q) )", { :q => Tag.find( params[:tag_id] ).id } ]).order('title')
elsif params[:q]
#search = params[:q]
#search = search.split("AND").map{|q|q.strip}
@ -20,7 +25,7 @@ class AlbumsController < ApplicationController
end
}
else
@albums = Album.find(:all, :order => 'title')
@albums = Album.popular.page(@page).per(@per_page)
end
respond_to do |format|
format.html
@ -40,6 +45,8 @@ class AlbumsController < ApplicationController
def show
@album = Album.find( params[:id])
@photos = @album.photos.popular
respond_to do |format|
format.html
format.json { render :json => @album }
@ -98,5 +105,11 @@ class AlbumsController < ApplicationController
redirect_to @album
end
end
def rate
@album = Album.find(params[:id])
@album.rate(params[:stars], current_user, params[:dimension])
render :json => {:id => @album.wrapper_dom_id(params), :width => 125}
end
end

View File

@ -2,86 +2,50 @@
# Likewise, all the methods added will be available for all controllers.
class ApplicationController < ActionController::Base
layout 'bootstrap'
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details
helper_method :current_user, :current_user_session
before_filter :setup
before_filter :set_locale
before_filter :authenticate_user!, :set_current_user
before_filter :setup, :set_pagination_params
private
def setup
redirect_to new_account_path if User.all.length == 0
end
def check_public_access
require_user if ENV['PRIVATE'] == 'true'
end
# This hack is needed to access the current user in models. See http://rails-bestpractices.com/posts/47-fetch-current-user-in-models
def set_current_user
User.current = current_user
end
def current_user_session
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
def setup
redirect_to new_account_path if User.all.size == 0
end
def current_user
return @current_user if defined?(@current_user)
@current_user = current_user_session && current_user_session.user
end
def check_public_access
require_user if ENV['PRIVATE'] == 'true'
end
def require_role(roles = [])
unless current_user && current_user.in_role?(*roles)
store_location
flash[:notice] = "You must have permission to access this page"
redirect_to account_path
return false
end
return true
end
def store_location
session[:return_to] = request.fullpath
end
def require_role_admin
return false if !require_user
return require_role("admin")
end
def require_permission(permissions = [])
return false if !require_user
unless current_user && current_user.has_permission?(*permissions)
store_location
flash[:notice] = "You must have permission to access this page"
redirect_to account_path
return false
end
return true
end
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
def require_user
unless current_user
store_location
flash[:notice] = "You must be logged in to access this page"
redirect_to login_path
return false
end
return true
private
def set_pagination_params
@page = params[:page]
@per_page = params[:per_page]
end
def set_locale
I18n.locale = session[:locale]
if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym)
session[:locale] = I18n.locale = params[:locale].to_sym
end
def require_no_user
if current_user
store_location
flash[:notice] = "Already logged in. Please logout"
redirect_to account_path
return false
end
return true
end
def store_location
session[:return_to] = request.fullpath
end
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
end
end

View File

@ -1,9 +1,14 @@
class CollectionsController < ApplicationController
before_filter :check_public_access
before_filter :require_role_admin, :only => [:new, :create, :edit, :update, :destroy]
skip_before_filter :authenticate_user!, :only => [:index, :show]
add_breadcrumb I18n.t('home_page'), :root_path, :title => I18n.t('home_page')
def index
@collections = Collection.find(:all, :order => 'title')
add_breadcrumb t('activerecord.models.collection.popular'), collections_path, :title => t('activerecord.models.collection.popular')
add_breadcrumb t('activerecord.actions.create', :model => I18n.t('activerecord.models.collection.single')), new_collection_path,
:title => t('activerecord.actions.create'), :li_icon => 'icon-plus-sign'
@collections = Collection.popular.page(@page).per(@per_page)
respond_to do |format|
format.html
format.json { render :json => @collections }
@ -13,7 +18,14 @@ class CollectionsController < ApplicationController
def show
@collection = Collection.find( params[:id] )
@albums = @collection.albums.find(:all, :order => 'title')
add_breadcrumb t('activerecord.models.collection.popular'), collections_path, :title => t('activerecord.models.collection.popular')
add_breadcrumb @collection.title, collection_path(@collection), :title => @collection.title
add_breadcrumb t('activerecord.actions.update', :model => I18n.t('activerecord.models.collection.single')), edit_collection_path,
:title => t('activerecord.actions.update', :model => I18n.t('activerecord.models.collection.single'))
add_breadcrumb t('activerecord.actions.destroy', :model => I18n.t('activerecord.models.collection.single')),collection_path(@collection),
:title => t('activerecord.actions.destroy', :model => I18n.t('activerecord.models.collection.single'))
@albums = @collection.albums.includes(:photos).where("photos.id NOT NULL").order('albums.rating_average desc').page(@page).per(@per_page)
respond_to do |format|
format.html
format.json { render :json => @collection }
@ -24,6 +36,10 @@ class CollectionsController < ApplicationController
def new
@collection = Collection.new
add_breadcrumb t('activerecord.models.collection.other').mb_chars.capitalize.to_s, collections_path,
:title => t('activerecord.models.collection.other')
add_breadcrumb t('activerecord.actions.new', :model => I18n.t('activerecord.models.collection.one')), new_collection_path,
:title => t('activerecord.actions.new', :model => I18n.t('activerecord.models.collection.one'))
end
def create
@ -42,6 +58,8 @@ class CollectionsController < ApplicationController
def update
@collection = Collection.find( params[:id])
add_breadcrumb t('activerecord.models.collection.popular'), collections_path, :title => t('activerecord.models.collection.popular')
add_breadcrumb t('activerecord.actions.create', :model => I18n.t('activerecord.models.collection.single')), new_collection_path, :title => t('activerecord.actions.create')
if @collection.update_attributes(params[:collection])
flash[:notice] = "Collection updated!"
redirect_to @collection
@ -58,5 +76,11 @@ class CollectionsController < ApplicationController
redirect_to @collection
end
end
def rate
@collection = Collection.find(params[:id])
@collection.rate(params[:stars], current_user, params[:dimension])
render :json => {:id => @collection.wrapper_dom_id(params), :width => 125}
end
end

View File

@ -0,0 +1,16 @@
class HomeController < ApplicationController
skip_before_filter :authenticate_user!, :only => [:index]
add_breadcrumb I18n.t(:home_page), :root_path
def index
@collections = Collection.popular.limit(12)
@popular_photos = Photo.popular.limit(10)
respond_to do |format|
format.html
format.json { render :json => @collections }
format.xml { render :xml => @collections }
end
end
end

View File

@ -0,0 +1,16 @@
class LocaleController < ApplicationController
skip_before_filter :authenticate_user!, :only => [:set]
def set
if request.referer && request.referer.starts_with?('http://' + request.host)
session['return_to'] = request.referer
end
if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym)
session[:locale] = I18n.locale = params[:locale].to_sym
flash.notice = t(:locale_changed)
else
flash[:error] = t(:locale_not_changed)
end
redirect_back_or_default(root_path)
end
end

View File

@ -1,17 +1,17 @@
class PhotosController < ApplicationController
before_filter :check_public_access
before_filter :require_role_admin, :only => [:untouched, :upload, :new, :create, :edit, :update, :destroy, :scan]
skip_before_filter :authenticate_user!, :only => [:index, :show]
def index
if params[:tag_id] && params[:album_id]
@tag = Tag.find_by_title!( params[:tag_id] )
@photos = @tag.photos.find(:all, :conditions => ['photos.album_id = :album', {:album => Album.find(params[:album_id] ) } ], :order => "photos.id ASC")
@photos = @tag.photos.where(:conditions => ['photos.album_id = :album', {:album => Album.find(params[:album_id] ) } ]).order("photos.id ASC")
elsif params[:tag_id]
@tag = Tag.find_by_title!( params[:tag_id] )
@photos = @tag.photos.find(:all, :order => "photos.id ASC")
@photos = @tag.photos.order("photos.id ASC")
elsif params[:album_id]
@album = Album.find( params[:album_id])
@photos = @album.photos.find(:all, :order => "photos.id ASC")
@photos = @album.photos.order("photos.id ASC")
elsif params[:q]
#search = params[:q]
#search = search.split("AND").map{|q|q.strip}
@ -25,7 +25,7 @@ class PhotosController < ApplicationController
end
}
else
@photos = Photo.find(:all, :order => "photos.id ASC")
@photos = Photo.popular.page(@page).per(@per_page)
end
respond_to do |format|
format.html
@ -37,9 +37,9 @@ class PhotosController < ApplicationController
def untouched
if params[:album_id]
@album = Album.find( params[:album_id])
@photos = @album.photos.untouched
@photos = @album.photos.untouched.page(@page).per(@per_page)
else
@photos = Photo.untouched()
@photos = Photo.untouched().page(@page).per(@per_page)
end
respond_to do |format|
format.html
@ -77,10 +77,10 @@ class PhotosController < ApplicationController
def create
@photo = Photo.new(params[:photo])
@photo.file = params[:file]
@photo.attachment = params[:file]
respond_to do |format|
if @photo.save
format.html { render :text => "FILEID:" + @photo.file.album.url }
format.html { render :text => "FILEID:" + @photo.attachment.album.url }
format.xml { render :nothing => true }
else
format.html { render :text => "ERRORS:" + @photo.errors.full_messages.join(" "), :status => 500 }
@ -91,7 +91,7 @@ class PhotosController < ApplicationController
def edit
@photo = Photo.find( params[:id])
@tags = Tag.find(:all).map { |tag| tag.title }.join('\',\'')
@tags = Tag.all.map { |tag| tag.title }.join('\',\'')
end
def edit_multiple
@ -148,4 +148,10 @@ class PhotosController < ApplicationController
redirect_to @photo
end
end
def rate
@photo = Photo.find(params[:id])
@photo.rate(params[:stars], current_user, params[:dimension])
render :json => {:id => @photo.wrapper_dom_id(params), :width => 125}
end
end

View File

@ -1,24 +0,0 @@
class UserSessionsController < ApplicationController
before_filter :require_no_user, :only => [:new, :create]
before_filter :require_user, :only => :destroy
def new
@user_session = UserSession.new
end
def create
@user_session = UserSession.new(params[:user_session])
if @user_session.save
flash[:notice] = "Login successful!"
redirect_back_or_default account_path
else
render :new
end
end
def destroy
current_user_session.destroy
flash[:notice] = "Logout successful!"
redirect_to root_path
end
end

View File

@ -1,7 +1,6 @@
class UsersController < ApplicationController
before_filter :check_public_access
before_filter :require_no_user, :only => [:new, :create]
before_filter :require_user, :only => [:show, :edit, :update, :destroy]
skip_before_filter :authenticate_user!, :only => [:new, :create]
skip_filter :setup
def new

View File

@ -1,12 +1,13 @@
# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper
=begin
def breadcrumbs(sep = "/", include_home = true)
levels = request.path.split('?')[0].split('/')
levels.delete_at(0)
#links = "You are here: "
links = content_tag('a', "HOME", :href => root_path ) if include_home
links = content_tag('li', (content_tag('a', t(:home_page), :href => root_path ) if include_home))
nocrumb = ["collections", "albums", "photos", "tags", "new", "edit", "tags"]
@ -15,12 +16,19 @@ module ApplicationHelper
level = level.gsub("-", " ")
if index+1 == levels.length
#links += " #{sep} #{level.upcase}" unless nocrumb.include?(level)
elsif !nocrumb.include?(level)
#elsif !nocrumb.include?(level)
links += " " + sep + " "
links += content_tag('a', level.upcase, :href => '/'+levels[0..index].join('/'))
links += content_tag('li', content_tag('a', level, :href => '/'+levels[0..index].join('/')))
end
end
content_tag("div", links, :id => "breadcrumb")
end
content_tag("ul", links, :class => "breadcrumb")
end
=end
def pluralize(string, count=nil, variants=nil)
# example variants for russian: # Russian.pluralize(3.14, "вещь", "вещи", "вещей", "вещи")
a,b,c,d=*variants
I18n.locale.eql?(:ru) ? Russian.pluralize(count, a,b,c,d) : string.pluralize
end
end

View File

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

View File

@ -1,9 +1,3 @@
module UsersHelper
def has_permission?(permissions = [])
return current_user && current_user.has_permission?(permissions)
end
def has_role?(roles = [])
return current_user && current_user.in_role?(roles)
end
end

63
app/models/ability.rb Normal file
View File

@ -0,0 +1,63 @@
class Ability
include CanCan::Ability
def initialize(user)
self.clear_aliased_actions
alias_action :edit, :to => :update
alias_action :new, :to => :create
alias_action :new_action, :to => :create
alias_action :show, :to => :read
if user.has_role? 'admin'
can :manage, :all
else
#############################
can :read, User do |resource|
resource == user
end
can :update, User do |resource|
resource == user
end
can :create, User
##############################
can :read, Profile do |resource|
resource == user
end
can :update, Profile do |resource|
resource == user
end
can :create, Profile
###############################
can :read, Link do |resource|
resource == user
end
can :update, Link do |resource|
resource == user
end
can :create, Link
end
# Define abilities for the passed in user here. For example:
#
# user ||= User.new # guest user (not logged in)
# if user.admin?
# can :manage, :all
# else
# can :read, :all
# end
#
# The first argument to `can` is the action you are giving the user permission to do.
# If you pass :manage it will apply to every action. Other common actions here are
# :read, :create, :update and :destroy.
#
# The second argument is the resource the user can perform the action on. If you pass
# :all it will apply to every resource. Otherwise pass a Ruby class of the resource.
#
# The third argument is an optional hash of conditions to further filter the objects.
# For example, here the user can only update published articles.
#
# can :update, Article, :published => true
#
# See the wiki for details: https://github.com/ryanb/cancan/wiki/Defining-Abilities
end
end

View File

@ -1,99 +1,104 @@
class Album < ActiveRecord::Base
extend Ext::GroupFor
ajaxful_rateable :stars => 5, :cache_column => :rating_average
has_many :photos, :dependent => :destroy
has_many :collection_albums
has_many :collections, :through => :collection_albums
validates :path, :presence => true, :uniqueness => true #, :message => "Album already exsists on disc"
validates :title, :presence => true #, :message => "can't be blank"
before_validation :ensure_path, :set_title
after_create :create_folders
after_destroy :destroy_folders
attr_accessor :tags
#attr_protected :path
scope :untouched, where("albums.id IN ( SELECT DISTINCT photos.album_id FROM photos WHERE photos.description IS NULL AND photos.id NOT IN ( SELECT photo_id FROM photo_tags) )").order('title')
scope :unused, where("albums.id NOT IN (SELECT album_id FROM collection_albums)")
scope :used, where("albums.id IN (SELECT album_id FROM collection_albums)")
scope :visible, lambda { where(:public => true) }
scope :popular, lambda{visible.includes(:photos).where("photos.id NOT NULL").order('albums.rating_average desc')}
scope :untouched, lambda{where("albums.id IN ( SELECT DISTINCT photos.album_id FROM photos WHERE photos.description IS NULL AND photos.id NOT IN ( SELECT photo_id FROM photo_tags) )").order('title')}
scope :unused, lambda{where("albums.id NOT IN (SELECT album_id FROM collection_albums)")}
scope :used, lambda{where("albums.id IN (SELECT album_id FROM collection_albums)")}
def to_param
"#{id}-#{title.parameterize}"
end
def ensure_path
self.path = self.title.parameterize unless self.path
end
def set_title
self.title = File.basename(self.path).titleize unless self.title || !self.path
end
def tags
# should maybe cache this to database?
# should maybe return array instead?
tags = Array.new
self.photos.map{ |photo|
if photo.tags.empty?
# photo has no tags => no unversial tags for this album
return
else
photo.tags
end
}.each_with_index{ |photo_tags,i|
# returns tag collection for each photo
if i == 0
tags = photo_tags
else
# combine arrays if they have identical tags.
# Will remove tags that are only tagged to one photo
#tags = tags & photo_tags
tags = tags & photo_tags
end
self.photos.map { |photo|
if photo.tags.empty?
# photo has no tags => no unversial tags for this album
return
else
photo.tags
end
}.each_with_index { |photo_tags, i|
# returns tag collection for each photo
if i == 0
tags = photo_tags
else
# combine arrays if they have identical tags.
# Will remove tags that are only tagged to one photo
#tags = tags & photo_tags
tags = tags & photo_tags
end
}
return tags
end
def tags=(tags)
tags = tags.split(" ").sort
current_tags = ( self.tags.nil? ? [] : self.tags.map{|tag|tag.title} )
current_tags = (self.tags.nil? ? [] : self.tags.map { |tag| tag.title })
return if tags == self.tags
# find tags that should be removed from this album - thus remove from all photos in album
# i.e. tags listed in self.tag_list but no in parameter tags
#current_tags.map {|tag|tag if !tags.include?(tag) }.compact
(current_tags - tags).each { |tag|
self.photos.each {|photo|
photo.untag( tag )
self.photos.each { |photo|
photo.untag(tag)
}
}
# add universial tags to all photos in album
(tags - current_tags).each do |tag|
self.photos.each { |photo|
photo.tag( tag )
photo.tag(tag)
}
end
end
def photo_tags
tags = Array.new
self.photos.each{ |photo|
self.photos.each { |photo|
tags = tags | photo.tags
}
return tags
end
end
protected
private
def create_folders
#Dir.mkdir( APP_CONFIG[:photos_path] + self.path ) unless File.exists?( APP_CONFIG[:photos_path] + self.path )
#Dir.mkdir( APP_CONFIG[:thumbs_path] + self.path ) unless File.exists?( APP_CONFIG[:thumbs_path] + self.path )
end
def destroy_folders
#puts "DELETE DIRECTORY " + APP_CONFIG[:photos_path] + self.path
#Dir.delete( APP_CONFIG[:photos_path] + self.path ) if File.exists?( APP_CONFIG[:photos_path] + self.path )

View File

@ -1,10 +1,21 @@
class Collection < ActiveRecord::Base
extend Ext::GroupFor
ajaxful_rateable :stars => 5, :cache_column => :rating_average
has_many :collection_albums
has_many :albums, :through => :collection_albums
attr_accessor :album_list
validates :title, :presence => true
scope :visible, where(:public => true)
scope :popular, lambda{visible.includes(:albums => :photos).where("photos.id NOT NULL").order('collections.rating_average desc')}
def photos_count
self.albums.includes(:photos).size
end
def to_param
"#{id}-#{title.parameterize}"
end

View File

@ -1,19 +0,0 @@
class Permission < ActiveRecord::Base
# uncomment any of the following lines which is relevant to your application,
# or create your own with the name of the model which acts_as_permissible.
belongs_to :user
belongs_to :role
belongs_to :permissible, :polymorphic => true, :dependent => :destroy
validates_presence_of :permissible_id, :permissible_type, :action
validates_format_of :action, :with => /^[a-z_]+$/
validates_numericality_of :permissible_id
validates_uniqueness_of :action, :scope => [:permissible_id,:permissible_type]
def to_hash
self.new_record? ? {} : {self.action => self.granted}
end
end

View File

@ -1,20 +1,22 @@
class Photo < ActiveRecord::Base
# TODO: path not used? it should be removed from the DB
extend Ext::GroupFor
ajaxful_rateable :stars => 5, :cache_column => :rating_average
belongs_to :album
has_many :photo_tags, :dependent => :destroy
has_many :tags, :through => :photo_tags
mount_uploader :file, FileUploader
validates :title, :presence => true
before_validation :set_title
mount_uploader :attachment, FileUploader
before_create :exif_read
#before_update :exif_write
before_update :exif_write
after_create :set_title, :set_visible
attr_accessor :tag_list
scope :visible, where(:public => true)
scope :popular, visible.order('rating_average desc')
scope :untouched, :conditions => "photos.description IS NULL AND photos.id NOT IN ( SELECT photo_id FROM photo_tags)", :include => :album
scope :previous, lambda { |p,a| { :conditions => ["id < :id AND album_Id = :album ", { :id => p, :album => a } ], :limit => 1, :order => "id DESC"} }
scope :next, lambda { |p,a| { :conditions => ["id > :id AND album_Id = :album ", { :id => p, :album => a } ], :limit => 1, :order => "id ASC"} }
@ -39,7 +41,7 @@ class Photo < ActiveRecord::Base
end
def tag_list
return self.tags.find(:all, :order => 'title').map{ |t| t.title }.sort.join(" ")
return self.tags.order('title').map{ |t| t.title }.sort.join(" ")
end
def tag_list=(tags)
@ -57,12 +59,16 @@ class Photo < ActiveRecord::Base
private
def set_visible
update_attribute(:public, true) unless self.public
end
def set_title
self.title = self.file.file.basename.titleize unless self.title
update_attribute(:title, self.attachment.file.basename.titleize) unless self.title
end
def exif_read
photo = MiniExiftool.new(self.file.file.file)
photo = MiniExiftool.new(self.attachment.file.file)
self.longitude = photo.GPSLongitude if self.longitude.nil?
self.latitude = photo.GPSLatitude if self.latitude.nil?
self.title = photo.DocumentName if self.title.nil?
@ -72,7 +78,7 @@ class Photo < ActiveRecord::Base
def exif_write
# should only write if tags are changed as images can be large and thus ExifTool will take a while to write to the file
photo = MiniExiftool.new(self.file.file.file)
photo = MiniExiftool.new(self.attachment.file.file)
photo.GPSLongitude = self.longitude
photo.GPSLatitude = self.latitude
photo.DocumentName = self.title

7
app/models/rate.rb Normal file
View File

@ -0,0 +1,7 @@
class Rate < ActiveRecord::Base
belongs_to :rater, :class_name => "User"
belongs_to :rateable, :polymorphic => true
validates_numericality_of :stars, :minimum => 1
attr_accessible :rate, :dimension
end

View File

@ -1,12 +1,5 @@
class Role < ActiveRecord::Base
has_many :role_memberships, :as => :roleable, :dependent => :destroy
has_many :roles, :through => :role_memberships, :source => :role
has_many :roleables, :class_name => "RoleMembership", :foreign_key => "role_id", :dependent => :destroy
has_many :subroles, :through => :roleables, :source => :roleable, :source_type => 'Role'
has_many :users, :through => :roleables, :source => :roleable, :source_type => 'User'
validates :name, :presence => true, :uniqueness => true
acts_as_permissible
end
attr_accessible :name
has_and_belongs_to_many :users
end

View File

@ -1,36 +0,0 @@
class RoleMembership < ActiveRecord::Base
belongs_to :user
belongs_to :role
belongs_to :roleable, :polymorphic => true
validates_presence_of :roleable_id, :roleable_type, :role_id
validates_uniqueness_of :role_id, :scope => [:roleable_id, :roleable_type]
validates_numericality_of :roleable_id, :role_id
validates_format_of :roleable_type, :with => /^[A-Z]{1}[a-z0-9]+([A-Z]{1}[a-z0-9]+)*$/
validate :role_does_not_belong_to_itself_in_a_loop
protected
def role_does_not_belong_to_itself_in_a_loop
if roleable_type == "Role"
if role_id == roleable_id
errors.add_to_base("A role cannot belong to itself.")
else
if belongs_to_itself_through_other?(roleable_id, role_id)
errors.add_to_base("A role cannot belong to a role which belongs to it.")
end
end
end
end
def belongs_to_itself_through_other?(original_roleable_id, current_role_id)
if self.class.find(:first, :select => "id", :conditions => ["roleable_id=? AND roleable_type='Role' AND role_id=?",current_role_id,original_roleable_id])
return true
else
memberships = self.class.find(:all, :select => "role_id", :conditions => ["roleable_id=? AND roleable_type='Role'",current_role_id])
if memberships.any? {|membership| belongs_to_itself_through_other?(original_roleable_id,membership.role_id)}
return true
end
end
return false
end
end

View File

@ -0,0 +1,7 @@
class SecretLinkObserver < ActiveRecord::Observer
observe :collection, :album, :photo
def before_create(record)
record.url = ::SecureRandom.hex(16)
end
end

View File

@ -1,4 +1,45 @@
class User < ActiveRecord::Base
acts_as_authentic
acts_as_permissible
devise :database_authenticatable, :registerable, :confirmable, :token_authenticatable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :lockable
attr_accessible :id, :name, :second_name, :surname, :email, :password, :password_confirmation, :remember_me, :userpic
ajaxful_rater
mount_uploader :userpic, UserpicUploader
has_and_belongs_to_many :roles
def small_url
userpic.url(:small)
end
alias_method :avatar, :small_url
def thumb_url
userpic.url(:thumb)
end
def original_url
userpic.url(:original)
end
##########################################################
# This hack is needed to access the current user in models.
#See http://rails-bestpractices.com/posts/47-fetch-current-user-in-models
def self.current
Thread.current[:user]
end
def self.current=(user)
Thread.current[:user] = user
end
def self.admin_created?
User.admin.count > 0
end
def has_role?(role_in_question)
roles.any? { |role| role.name == role_in_question.to_s }
end
end

View File

@ -1,6 +0,0 @@
class UserSession < Authlogic::Session::Base
# configuration here, see documentation for sub modules of Authlogic::Session
def to_key
new_record? ? nil : [ self.send(self.class.primary_key) ]
end
end

View File

@ -2,14 +2,18 @@
class FileUploader < CarrierWave::Uploader::Base
@@generate_file_name = ''
@@original_filename = ''
# Include RMagick or ImageScience support
# include CarrierWave::RMagick
# include CarrierWave::ImageScience
include CarrierWave::MiniMagick
include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader
if ENV['S3_KEY']
storage :fog
def cache_dir
"#{Rails.root.to_s}/tmp/uploads" if ENV['HEROKU'] == 'true'
end
@ -21,7 +25,15 @@ class FileUploader < CarrierWave::Uploader::Base
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
#{}"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
ENV['STORAGE_PATH'] + "/files/#{model.album.path}"
ENV['STORAGE_PATH'] + "/files/#{model.album.path}/#{model.id}"
end
def filename
unless @@original_filename == original_filename
@@original_filename = original_filename
@@generate_file_name = "#{::SecureRandom.hex(8)}#{File.extname(original_filename).downcase}" if original_filename
end
@@generate_file_name
end
# Provide a default URL as a default if there hasn't been a file uploaded
@ -37,40 +49,50 @@ class FileUploader < CarrierWave::Uploader::Base
# end
# Create different versions of your uploaded files
version :collection do
process :resize_to_fill => [200, 200]
def store_dir
ENV['STORAGE_PATH'] + "/thumbs/#{model.album.path}"
end
end
version :album do
process :resize_to_fill => [100, 100]
def store_dir
ENV['STORAGE_PATH'] + "/thumbs/#{model.album.path}"
end
end
version :preview do
process :resize_to_fit => [210, 210]
def store_dir
ENV['STORAGE_PATH'] + "/thumbs/#{model.album.path}"
end
end
version :single do
process :resize_to_limit => [950, 950]
def store_dir
ENV['STORAGE_PATH'] + "/thumbs/#{model.album.path}"
end
end
version :thumb do
process :resize_to_fill => [260, 180]
def store_dir
ENV['STORAGE_PATH'] + "/thumbs/#{model.album.path}/#{model.id}"
end
end
######################################################################################################################
# Note
# The default grid system provided in Bootstrap utilizes 12 columns that
# render out at widths of 724px, 940px (default without responsive CSS included), and 1170px.
# Below 767px viewports, the columns become fluid and stack vertically.
version :middle do
process :resize_to_fill => [742, 500]
def store_dir
ENV['STORAGE_PATH'] + "/thumbs/#{model.album.path}/#{model.id}"
end
end
version :large do
process :resize_to_fill => [940, 600]
def store_dir
ENV['STORAGE_PATH'] + "/thumbs/#{model.album.path}/#{model.id}"
end
end
version :largest do
process :resize_to_fill => [1170, 600]
def store_dir
ENV['STORAGE_PATH'] + "/thumbs/#{model.album.path}/#{model.id}"
end
end
######################################################################################################################
# Add a white list of extensions which are allowed to be uploaded,
# for images you might use something like this:
def extension_white_list
%w(jpg jpeg gif png bmp tiff)
end
# Override the filename of the uploaded files
# def filename
# "something.jpg" if original_filename
# end
def extension_white_list
%w(jpg jpeg gif png bmp tiff)
end
end

View File

@ -0,0 +1,28 @@
class UserpicUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
def store_dir
"#{ENV['STORAGE_PATH']}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}/original"
end
def filename
"#{::SecureRandom.hex(8)}#{File.extname(original_filename).downcase}" if original_filename
end
version :mini do
process :resize_to_fit => [50, 50]
def store_dir
"#{ENV['STORAGE_PATH']}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}/mini"
end
end
version :small do
process :resize_to_fit => [100, 100]
def store_dir
"#{ENV['STORAGE_PATH']}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}/small"
end
end
end

View File

@ -1,12 +0,0 @@
<%= form.label :name, 'Display name' %><br />
<%= form.text_field :name %><br />
<br />
<%= form.label :email %><br />
<%= form.text_field :email %><br />
<br/>
<%= form.label :password %><br />
<%= form.password_field :password %><br />
<br/>
<%= form.label :password_confirmation %><br />
<%= form.password_field :password_confirmation %><br />
<br/>

View File

@ -1,15 +0,0 @@
<h1>Edit Account</h1>
<%= form_for @user do |f| %>
<%= f.error_messages %>
<%= render :partial => "form", :object => f %>
<%= f.submit "Update" %>
<% end %>
<%= content_for :action_links do %>
<%= link_to("Delete user", { :action => "destroy", :id => @user },
:confirm => "Are you sure you want to delete this user?",
:method => :delete) %>
<% end %>

View File

@ -1,7 +0,0 @@
<% for user in @users %>
<h2><%= link_to user.name || user.email , user %></h2>
<% end %>
<%= content_for :action_links do %>
<%= link_to "New user", new_user_path %>
<% end %>

View File

@ -1,7 +0,0 @@
<h1>Register</h1>
<%= form_for @user do |f| %>
<%= f.error_messages %>
<%= render :partial => "form", :object => f %>
<%= f.submit "Register" %>
<% end %>

View File

@ -1,45 +0,0 @@
<p>
<b>Name:</b>
<%=h @user.name %>
</p>
<p>
<b>Email:</b>
<%=h @user.email %>
</p>
<p>
<b>Login count:</b>
<%=h @user.login_count %>
</p>
<p>
<b>Last request at:</b>
<%=h @user.last_request_at %>
</p>
<p>
<b>Last login at:</b>
<%=h @user.last_login_at %>
</p>
<p>
<b>Current login at:</b>
<%=h @user.current_login_at %>
</p>
<p>
<b>Last login ip:</b>
<%=h @user.last_login_ip %>
</p>
<p>
<b>Current login ip:</b>
<%=h @user.current_login_ip %>
</p>
<%= content_for :action_links do %>
<%= link_to 'Edit', edit_user_path(@user) %>
<% end %>

View File

@ -5,26 +5,59 @@
<div id="map_canvas"></div>
<%= hidden_field_tag :all_tags, "'#{Tag.find(:all).map { |tag| tag.title }.join('\',\'')}'" %>
<%= hidden_field_tag :collection_id, params[:collection_id] %>
<%= form.hidden_field :id %>
<%= form.hidden_field :latitude %>
<%= form.hidden_field :longitude %>
<fieldset>
<%= hidden_field_tag :all_tags, "'#{Tag.all.map { |tag| tag.title }.join('\',\'')}'" %>
<%= hidden_field_tag :collection_id, params[:collection_id] %>
<%= form.hidden_field :id %>
<%= form.hidden_field :latitude %>
<%= form.hidden_field :longitude %>
<%= form.label :title, :Title, {:class => 'big'} %><br />
<%= form.text_field :title, {:class => 'big'} %><br />
<div class="control-group">
<%= form.label :title, t('activerecord.models.album.attributes.title'), {:class => 'control-label'} %>
<div class="controls">
<%= form.text_field :title, {:class => 'input-xlarge'} %>
</div>
</div>
<%= form.label :description %><br />
<%= form.text_area :description %><br />
<div class="control-group">
<%= form.label :description, t('activerecord.models.album.attributes.description'), {:class => 'control-label'} %>
<div class="controls">
<%= form.text_area :description, {:class => 'input-xlarge', :rows => 5} %>
</div>
</div>
<%= form.label :address %><br />
<%= form.text_area :address, { :rows => 3} %><br />
<div class="control-group">
<%= form.label :public, t('activerecord.models.album.attributes.visible'), {:class => 'control-label'} %>
<div class="controls">
<label class="checkbox">
<%= check_box 'collection', :public %> <%= t(:make_visible_for_all) %>
</label>
</div>
</div>
<%= form.label :note %><br />
<%= form.text_area :note %><br />
<div class="control-group">
<%= form.label :address, t('activerecord.models.album.attributes.address'), {:class => 'control-label'} %>
<div class="controls">
<%= form.text_area :address, {:class => 'input-xlarge', :rows => 5} %>
</div>
</div>
<%= form.label :tags %><br />
<%= form.text_field :tags, { :autocomplete => "off", :class => 'tag_list', :value => (@album.tags.map{|tag|tag.title}.join(" ") unless @album.tags.nil?) } %><br />
<div class="control-group">
<%= form.label :note, t('activerecord.models.album.attributes.note'), {:class => 'control-label'} %>
<div class="controls">
<%= form.text_area :note, {:class => 'input-xlarge', :rows => 5} %>
</div>
</div>
<br />
Contains: <%= @album.photos.count %> photos<br/>
<div class="control-group">
<%= form.label :tags, t('activerecord.models.album.attributes.tags'), {:class => 'control-label'} %>
<div class="controls">
<%= form.text_field :tags, {:class => 'input-xlarge', :autocomplete => "off", :class => 'tag_list', :value => (@album.tags.map{|tag|tag.title}.join(" ") unless @album.tags.nil?) } %>
</div>
</div>
<br />
Contains: <%= @album.photos.count %> photos<br/>
</fieldset>

View File

@ -0,0 +1,28 @@
<div class="row">
<div class="span12">
<% @albums.in_groups_of(4).each do |group| %>
<% unless group.empty? %>
<ul class="thumbnails">
<% group.compact.each_with_index do |album, index| %>
<li class="span3">
<div class="thumbnail">
<%= image_tag album.photos.first.attachment.thumb.url %>
<div class="caption">
<h5 class="title"><%= album.title %></h5>
<em class="descr"><%= album.description %></em>
<div class="controls">
<p class="view-btn"><%= link_to 'View', (album_path(album) unless album.photos.empty?), {:class => 'btn btn-primary'} %></p>
<div class="tooltips">
<span rel="popover" class="icon-th icon-popover" data-content="<%= t(:photos_counter, :count => album.photos.count) %>"></span>
</div>
<%= ratings_for album %>
</div>
</div>
</div>
</li>
<% end %>
</ul>
<% end %>
<% end %>
</div>
</div>

View File

@ -1,19 +1,11 @@
<% for album in @albums %>
<div class="row">
<div class="title">
<%= render :partial => "photos/thumb", :locals => {:photo => album.photos.first } unless album.photos.empty? %>
<p><%= link_to album.title, album %></p>
</div>
<div class="image">
<%= render :partial => "photos/thumb", :collection => album.photos.find(:all, :limit => 5, :offset => 1), :as => :photo %>
</div>
</div>
<% end %>
<%= paginate @albums %>
<%= render 'row_collections' %>
<%= paginate @albums %>
<%= content_for :action_links do %>
<%= link_to "Show just the photos tagged with #{params[:q]}", photos_path(:q => params[:q]) if params[:q] %>
<% if has_role?("admin") %>
<%= " |&nbsp;" if params[:q] %>
<%= link_to "New album", new_album_path() %>
<% end %>
<%= link_to "Show just the photos tagged with #{params[:q]}", photos_path(:q => params[:q]) if params[:q] %>
<% if current_user and current_user.has_role?("admin") %>
<%= " |&nbsp;" if params[:q] %>
<%= link_to "New album", new_album_path() %>
<% end %>
<% end %>

View File

@ -1,8 +1,9 @@
<h1>New Album</h1>
<%= form_for @album do |f| %>
<%= f.error_messages %>
<%= render :partial => "form", :object => f %>
<%= f.submit "Create" %>
<%= form_for @album, :html => {:class => 'form-horizontal'} do |f| %>
<legend><%= t('activerecord.actions.new', :model => I18n.t('activerecord.models.album.one')) %></legend>
<%= f.error_messages %>
<%= render :partial => "form", :object => f %>
<div class="form-actions">
<%= f.button "Create", :class => 'btn btn-primary btn-large' %>
</div>
<% end %>

View File

@ -1,60 +1,47 @@
<h2><%= @album.title %></h2>
<div id="multipleimages">
<table>
<% count = 0.0 %>
<% for photo in @album.photos.find(:all, :order => "Id ASC") %>
<% count += 1%>
<% if count == 1 || ( (count-1) / 4.0 == ( (count-1) / 4.0).to_i ) %><tr><% end %>
<td><%= link_to image_tag( photo.file.preview.url ), [@album.collections.first, @album, photo] %></td>
<% if count / 4.0 == (count / 4.0).to_i %></tr><% end %>
<% end %>
</table>
</div>
<%= render :partial => 'photos/row_collections' %>
<p><%= @album.description %></p>
<% unless @album.photo_tags.empty? %>
<p>Tagged with:
<% for tag in @album.photo_tags.map{|tag|tag.title}.sort %>
<%= link_to tag, album_tag_photos_path(@album, tag) %>
<% end %>
</p>
<p>Tagged with:
<% for tag in @album.photo_tags.map { |tag| tag.title }.sort %>
<%= link_to tag, album_tag_photos_path(@album, tag) %>
<% end %>
</p>
<% end %>
<% unless @album.collections.empty? %>
<p>Part of:
<% for collection in @album.collections.find(:all, :order => 'title') %>
<%= link_to collection.title, collection_path(collection) %>
<% end %>
</p>
<p>Part of:
<% for collection in @album.collections.order('title') %>
<%= link_to collection.title, collection_path(collection) %>
<% end %>
</p>
<% end %>
<% if has_role?("admin") %>
<p><%= @album.address %></p>
<% end %>
<% if has_role?("admin") %>
<p><%= @album.note %></p>
<% if current_user and current_user.has_role?("admin") %>
<p><%= @album.address %></p>
<p><%= @album.note %></p>
<% end %>
<%= content_for :action_links do %>
<% if has_role?("admin") %>
<% if params[:collection_id] %>
<%= link_to "PDF", collection_album_path(params[:collection_id],@album, :format => 'pdf') %> |&nbsp;
<%= link_to "Edit album", edit_collection_album_path(params[:collection_id],@album) %> |&nbsp;
<%= link_to "Edit all photos", edit_multiple_collection_album_photos_path(params[:collection_id],@album) %> |&nbsp;
<%= link_to "Edit untouched photos", untouched_collection_album_photos_path(params[:collection_id], @album) %> |&nbsp;
<%= link_to "Add photos", upload_collection_album_photos_path(params[:collection_id], @album) %>
<% else %>
<%= link_to "PDF", album_path(@album, :format => 'pdf') %> |&nbsp;
<%= link_to "Edit album", edit_album_path(@album) %> |&nbsp;
<%= link_to "Edit all photos", edit_multiple_album_photos_path(@album) %> |&nbsp;
<%= link_to "Edit untouched photos", untouched_album_photos_path(@album) %> |&nbsp;
<%= link_to "Add photos", upload_album_photos_path(@album) %>
<% end %>
<% if current_user and current_user.has_role?("admin") %>
<% if params[:collection_id] %>
<li><%= link_to "PDF", collection_album_path(params[:collection_id], @album, :format => 'pdf') %></li>
<li><%= link_to "Edit album", edit_collection_album_path(params[:collection_id], @album) %></li>
<li><%= link_to "Edit all photos", edit_multiple_collection_album_photos_path(params[:collection_id], @album) %></li>
<li><%= link_to "Edit untouched photos", untouched_collection_album_photos_path(params[:collection_id], @album) %></li>
<li><%= link_to "Add photos", upload_collection_album_photos_path(params[:collection_id], @album) %></li>
<% else %>
<li><%= link_to "PDF", album_path(@album, :format => 'pdf') %></li>
<li><%= link_to "Edit album", edit_album_path(@album) %></li>
<li><%= link_to "Edit all photos", edit_multiple_album_photos_path(@album) %></li>
<li><%= link_to "Edit untouched photos", untouched_album_photos_path(@album) %></li>
<li><%= link_to "Add photos", upload_album_photos_path(@album) %></li>
<% end %>
<% end %>
<% end %>
<% end %>

View File

@ -1,38 +1,49 @@
<%= form.label :title, :Title, {:class => 'big'} %><br />
<%= form.text_field :title, {:class => 'big'} %><br />
<fieldset>
<div class="control-group">
<%= form.label :title, t('activerecord.models.collection.attributes.title'), {:class => 'control-label'} %>
<div class="controls">
<%= form.text_field :title, {:class => 'input-xlarge'} %>
</div>
</div>
<%= form.label :description %><br />
<%= form.text_area :description %><br />
<div class="control-group">
<%= form.label :description, t('activerecord.models.collection.attributes.description'), {:class => 'control-label'} %>
<div class="controls">
<%= form.text_area :description, {:class => 'input-xlarge', :rows => 5} %>
</div>
</div>
<% unless @collection.albums.empty? %>
<%= form.label :albums %><br />
<div id="collection_albums">
<% for album in @collection.albums %>
<%= form.fields_for :album_list do |album_fields| %>
<span>
<%= image_tag "delete-24x24.png", :class => "delete", :alt => "Delete" -%>
<div class="control-group">
<%= form.label :public, t('activerecord.models.collection.attributes.visible'), {:class => 'control-label'} %>
<div class="controls">
<label class="checkbox">
<%= check_box 'collection', :public %> <%= t(:make_visible_for_all) %>
</label>
</div>
</div>
<% if album.photos.empty? %>
<%= album.title %>
<% else %>
<%= image_tag album.photos.first.file.album.url, :alt => album.title %>
<% end %>
<%= album_fields.hidden_field album.id %>
</span>
<% end %>
<% end %>
</div>
<% unless @collection.albums.empty? %>
<%= form.label :albums %>
<% @collection.albums.each do |album| %>
<%= form.fields_for :album_list do |album_fields| %>
<%= image_tag "delete-24x24.png", :class => "delete", :alt => "Delete" -%>
<% if album.photos.empty? %>
<%= album.title %>
<% else %>
<%= image_tag album.photos.first.attachment.thumb.url, :alt => album.title %>
<% end %>
<%= album_fields.hidden_field album.id %>
<% end %>
<% end %>
<p class="clear">
<%
grouped_options = [
['Available albums',[['Choose album to add','']]],
['Not used', Album.unused.map{|album|[album.title, album.id]} ],
['In use', Album.used.map{|album|[album.title, album.id]} ]
]
grouped_options_for_select(grouped_options)
%>
<%= select_tag 'available_albums', grouped_options_for_select(grouped_options) %>
</p>
<% end %>
<%
grouped_options = [
['Available albums', [['Choose album to add', '']]],
['Not used', Album.unused.map { |album| [album.title, album.id] }],
['In use', Album.used.map { |album| [album.title, album.id] }]
]
grouped_options_for_select(grouped_options)
%>
<%= select_tag 'available_albums', grouped_options_for_select(grouped_options) %>
<% end %>
</fieldset>

View File

@ -0,0 +1,29 @@
<div class="row">
<div class="span12">
<% @collections.in_groups_of(4).each do |group| %>
<% unless group.empty? %>
<ul class="thumbnails">
<% group.compact.each_with_index do |collection, index| %>
<li class="span3">
<div class="thumbnail">
<%= image_tag collection.albums.first.photos.first.attachment.thumb.url %>
<div class="caption">
<h5 class="title"><%= collection.title %></h5>
<em class="descr"><%= collection.description %></em>
<div class="controls">
<p class="view-btn"><%= link_to 'View', (collection_path(collection) unless collection.albums.empty? || collection.albums.first.photos.empty?), {:class => 'btn btn-primary'} %></p>
<div class="tooltips">
<span rel="popover" class="icon-th-large icon-popover" data-content="<%= t(:albums_counter, :count => collection.albums.size) %>"></span>
<span rel="popover" class="icon-th icon-popover" data-content="<%= t(:photos_counter, :count => collection.photos_count) %>"></span>
</div>
<%= ratings_for collection %>
</div>
</div>
</div>
</li>
<% end %>
</ul>
<% end %>
<% end %>
</div>
</div>

View File

@ -1,14 +1,6 @@
<div id="multipleimages">
<% for collection in @collections %>
<div class="thumb">
<h3><%= link_to collection.title, collection %></h3>
<%= link_to (image_tag collection.albums.find(:first).photos.first.file.collection.url ), collection_path(collection) unless collection.albums.empty? || collection.albums.find(:first).photos.empty? %>
</div>
<% end %>
</div>
<h1><%= t('activerecord.models.collection.pluralize') %></h1>
<%= paginate @collections %>
<%= render 'row_collections' %>
<%= paginate @collections %>
<%= content_for :action_links do %>
<% if has_role?("admin") %>
<%= link_to "New collection", new_collection_path %>
<% end %>
<% end %>

View File

@ -1,7 +1,8 @@
<h1>New collection</h1>
<%= form_for @collection do |f| %>
<%= form_for @collection, :html => {:class => 'form-horizontal'} do |f| %>
<legend><%= t('activerecord.actions.new', :model => I18n.t('activerecord.models.collection.one')) %></legend>
<%= f.error_messages %>
<%= render :partial => "form", :object => f %>
<%= f.submit "Create" %>
<div class="form-actions">
<%= f.button "Create", :class => 'btn btn-primary btn-large' %>
</div>
<% end %>

View File

@ -1,22 +1,12 @@
<h2><%= h @collection.title %></h2>
<p><%= h @collection.description %></p>
<h2><%= @collection.title %></h2>
<p><%= @collection.description %></p>
<% for album in @albums %>
<div class="row">
<div class="title">
<%= render :partial => "photos/thumb", :locals => {:photo => album.photos.first } unless album.photos.empty? %>
<p><%= link_to album.title, collection_album_path(@collection, album) %></p>
</div>
<div class="image">
<%= render :partial => "photos/thumb", :collection => album.photos.find(:all, :limit => 5, :offset => 1), :as => :photo %>
</div>
</div>
<% end %>
<%= render :partial => 'albums/row_collections' %>
<%= content_for :action_links do %>
<% if has_role?("admin") %>
<%= link_to "PDF", collection_path(@collection, :format => 'pdf') %> |&nbsp;
<%= link_to "Edit collection", edit_collection_path(@collection) %> |
<%= link_to "New album", new_collection_album_path(@collection) %>
<% end %>
<% if current_user and current_user.has_role?("admin") %>
<li><%= link_to "PDF", collection_path(@collection, :format => 'pdf') %></li>
<li><%= link_to "Edit collection", edit_collection_path(@collection) %></li>
<li><%= link_to "New album", new_collection_album_path(@collection) %></li>
<% end %>
<% end %>

View File

@ -0,0 +1,24 @@
<%- if controller_name != 'sessions' %>
<%= link_to t('devise.sign_in'), login_path %><br />
<% end -%>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to t('devise.sign_up'), signup_path %><br />
<% end -%>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
<%= link_to t('devise.forgot_your_password'), new_password_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
<%= link_to t('devise.send_confirmation_instructions'), new_confirmation_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
<%= link_to t('devise.send_unlock_instructions'), new_unlock_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.omniauthable? %>
<%- resource_class.omniauth_providers.each do |provider| %>
<%= link_to t('devise.sign_in_with', :provider => provider.to_s.titleize), omniauth_authorize_path(resource_name, provider) %><br />
<% end -%>
<% end -%>

View File

@ -0,0 +1,12 @@
<h2>Resend confirmation instructions</h2>
<%= form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.submit "Resend confirmation instructions" %></div>
<% end %>
<%= render "links" %>

View File

@ -0,0 +1,5 @@
<p>Welcome <%= @resource.email %>!</p>
<p>You can confirm your account email through the link below:</p>
<p><%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %></p>

View File

@ -0,0 +1,8 @@
<p>Hello <%= @resource.email %>!</p>
<p>Someone has requested a link to change your password, and you can do this through the link below.</p>
<p><%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %></p>
<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>

View File

@ -0,0 +1,7 @@
<p>Hello <%= @resource.email %>!</p>
<p>Your account has been locked due to an excessive amount of unsuccessful sign in attempts.</p>
<p>Click the link below to unlock your account:</p>
<p><%= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @resource.unlock_token) %></p>

View File

@ -0,0 +1,16 @@
<h2>Change your password</h2>
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| %>
<%= devise_error_messages! %>
<%= f.hidden_field :reset_password_token %>
<div><%= f.label :password, "New password" %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation, "Confirm new password" %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Change my password" %></div>
<% end %>
<%= render "links" %>

View File

@ -0,0 +1,12 @@
<h2>Forgot your password?</h2>
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.submit "Send me reset password instructions" %></div>
<% end %>
<%= render "links" %>

View File

@ -0,0 +1,25 @@
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, :autocomplete => "off" %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %></div>
<div><%= f.submit "Update" %></div>
<% end %>
<h3>Cancel my account</h3>
<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p>
<%= link_to "Back", :back %>

View File

@ -0,0 +1,18 @@
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "links" %>

View File

@ -0,0 +1,17 @@
<h2><%= t("devise.sign_in") %></h2>
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<% if devise_mapping.rememberable? -%>
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<% end -%>
<div><%= f.submit "Sign in" %></div>
<% end %>
<%= render "links" %>

View File

@ -0,0 +1,12 @@
<h2>Resend unlock instructions</h2>
<%= form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.submit "Resend unlock instructions" %></div>
<% end %>
<%= render "links" %>

View File

@ -0,0 +1,5 @@
<div class="row">
<%= render 'shared/home_slider' %>
</div>
<h2><%= t('activerecord.models.collection.popular') %></h2>
<%= render :partial => 'collections/row_collections' %>

View File

@ -0,0 +1,13 @@
<%# Link to the "First" page
- available local variables
url: url to the first page
current_page: a page object for the currently displayed page
num_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
<% unless current_page.first? %>
<li class="first">
<%= link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote %>
</li>
<% end %>

View File

@ -0,0 +1,8 @@
<%# Non-link tag that stands for skipped pages...
- available local variables
current_page: a page object for the currently displayed page
num_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
<li class="page gap disabled"><a href="#" onclick="return false;"><%= raw(t 'views.pagination.truncate') %></a></li>

View File

@ -0,0 +1,13 @@
<%# Link to the "Last" page
- available local variables
url: url to the last page
current_page: a page object for the currently displayed page
num_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
<% unless current_page.last? %>
<li class="last next"><%# "next" class present for border styling in twitter bootstrap %>
<%= link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote} %>
</li>
<% end %>

View File

@ -0,0 +1,13 @@
<%# Link to the "Next" page
- available local variables
url: url to the next page
current_page: a page object for the currently displayed page
num_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
<% unless current_page.last? %>
<li class="next_page">
<%= link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote %>
</li>
<% end %>

View File

@ -0,0 +1,12 @@
<%# Link showing page number
- available local variables
page: a page object for "this" page
url: url to this page
current_page: a page object for the currently displayed page
num_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
<li class="page<%= ' active' if page.current? %>">
<%= link_to page, url, opts = {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} %>
</li>

View File

@ -0,0 +1,25 @@
<%# The container tag
- available local variables
current_page: a page object for the currently displayed page
num_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
paginator: the paginator that renders the pagination tags inside
-%>
<%= paginator.render do -%>
<div class="pagination">
<ul>
<%= first_page_tag unless current_page.first? %>
<%= prev_page_tag unless current_page.first? %>
<% each_page do |page| -%>
<% if page.left_outer? || page.right_outer? || page.inside_window? -%>
<%= page_tag page %>
<% elsif !page.was_truncated? -%>
<%= gap_tag %>
<% end -%>
<% end -%>
<%= next_page_tag unless current_page.last? %>
<%= last_page_tag unless current_page.last? %>
</ul>
</div>
<% end -%>

View File

@ -0,0 +1,13 @@
<%# Link to the "Previous" page
- available local variables
url: url to the previous page
current_page: a page object for the currently displayed page
num_pages: total number of pages
per_page: number of items to fetch per page
remote: data-remote
-%>
<% unless current_page.first? %>
<li class="prev">
<%= link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote %>
</li>
<% end %>

View File

@ -1,13 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title><%= ENV['TITLE'] || "Photos" %></title>
<meta name="viewport" content="width=device-width">
<meta name="viewport" content="initial-scale=1.0">
<%= yield :head %>
<%= stylesheet_link_tag 'application' %>
<%= csrf_meta_tag %>
<%= render :partial => 'shared/head' %>
</head>
<body>
<div id="container">
@ -43,7 +37,6 @@
</div>
</div>
<%= javascript_include_tag 'jquery-1.4.2.js', 'rails', 'balder' %>
<%= yield :javascript %>
</body>
</html>

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<%= render :partial => 'shared/head' %>
</head>
<body>
<%= render :partial => 'shared/nav_bar' %>
<div class="container">
<div class="row">
<div class="span12">
<%= render :partial => 'shared/notifications' %>
<%= render_breadcrumbs %>
<%= yield %>
</div>
</div>
<hr>
<footer>
<p>&copy; Photomix 2012</p>
</footer>
</div>
</body>
</html>

View File

@ -1,14 +1,14 @@
<%= content_for :javascript do %>
<%= javascript_include_tag "tag/tag" -%>
<%= javascript_include_tag "tag/tag" -%>
<% end %>
<%= hidden_field_tag :all_tags, @tags %>
<%= form.label :title %><br />
<%= form.text_field :title %><br />
<br />
<br/>
<%= form.label :tag_list %><br />
<%= form.text_field :tag_list, { :autocomplete => "off", :class => 'tag_list'} %><br />
<br />
<%= form.text_field :tag_list, {:autocomplete => "off", :class => 'tag_list'} %><br />
<br/>
<%= form.label :description %><br />
<%= form.text_area :description %><br />
<br/>
<p>On disk: ~/<%= @photo.file.path %></p>
<p>On disk: ~/<%= @photo.attachment.path %></p>

View File

@ -1 +1 @@
<%= image_tag photo.file.single.url %><br/>
<%= image_tag photo.attachment.single.url %><br/>

View File

@ -0,0 +1,22 @@
<div class="row">
<div class="span12">
<% @photos.in_groups_of(4).each do |group| %>
<% unless group.empty? %>
<ul class="thumbnails">
<% group.compact.each_with_index do |photo, index| %>
<li class="span3">
<div class="thumbnail">
<%= link_to image_tag(photo.attachment.thumb.url), photo.attachment.largest.url, :class => 'fancybox-thumb', :rel => "fancybox-thumb" %>
<div class="caption">
<h5 class="title"><%= photo.title %></h5>
<em class="descr"><%= photo.description %></em>
<%= ratings_for photo %>
</div>
</div>
</li>
<% end %>
</ul>
<% end %>
<% end %>
</div>
</div>

View File

@ -1 +1 @@
<%= link_to (image_tag eval('photo.file.' + (defined?(photosize) ? photosize : "album") + '.url') ), [photo.album.collections.first, photo.album, photo] %>
<%= link_to image_tag(eval('photo.attachment.' + (defined?(photosize) ? photosize : "thumb") + '.url')), [photo.album.collections.first, photo.album, photo] %>

View File

@ -1,17 +1,17 @@
<h1>Edit Photo</h1>
<%= image_tag @photo.file.preview.url %>
<%= image_tag @photo.attachment.preview.url %>
<%= form_for @photo do |f| %>
<%= hidden_field_tag :collection_id, params[:collection_id] %>
<%= hidden_field_tag :album_id, params[:album_id] %>
<%= f.error_messages %>
<%= render :partial => "form", :object => f %>
<%= f.submit "Update" %>
<%= hidden_field_tag :collection_id, params[:collection_id] %>
<%= hidden_field_tag :album_id, params[:album_id] %>
<%= f.error_messages %>
<%= render :partial => "form", :object => f %>
<%= f.submit "Update" %>
<% end %>
<%= content_for :action_links do %>
<%= link_to("Delete photo", { :action => "destroy", :id => @photo, :collection_id => params[:collection_id] },
:confirm => "Are you sure you want to delete this photo?",
:method => :delete) %>
<%= link_to("Delete photo", {:action => "destroy", :id => @photo, :collection_id => params[:collection_id]},
:confirm => "Are you sure you want to delete this photo?",
:method => :delete) %>
<% end %>

View File

@ -1,15 +1,15 @@
<%= form_for :photos, :url => update_multiple_photos_path, :html => { :method => :put } do |f| %>
<% for photo in @photos %>
<p>
<%= f.fields_for photo, :index => photo.id do |p|%>
<%= p.check_box :_delete %>
<%= render :partial => "photos/thumb", :locals => {:photo => photo } %>
<%= p.text_field :title %>
<%= p.text_field :tags, :value => photo.tag_list %>
<% end%>
</p>
<% end%>
<p><%= f.submit "Submit" %></p>
<%= form_for :photos, :url => update_multiple_photos_path, :html => {:method => :put} do |f| %>
<% for photo in @photos %>
<p>
<%= f.fields_for photo, :index => photo.id do |p| %>
<%= p.check_box :_delete %>
<%= render :partial => "photos/thumb", :locals => {:photo => photo} %>
<%= p.text_field :title %>
<%= p.text_field :tags, :value => photo.tag_list %>
<% end %>
</p>
<% end %>
<p><%= f.submit "Submit" %></p>
<% end %>
<br /><%= link_to "Back to #{@album.title}", @album %>
<br/><%= link_to "Back to #{@album.title}", @album %>

View File

@ -1,6 +1,9 @@
<ul><%= render :partial => 'photos/thumb',:collection => @photos, :as => :photo %></ul>
<%#= render :partial => 'photos/thumb', :collection => @photos, :as => :photo %>
<%= paginate @photos %>
<%= render :partial => 'photos/row_collections' %>
<%= paginate @photos %>
<%= content_for :action_links do %>
<%= link_to "Show albums containing photos tagged with #{params[:q]}", albums_path(:q => params[:q]) if params[:q] %>
<%= link_to "Show all photos tagged with #{params[:tag_id]}", tag_photos_path(params[:tag_id]) if params[:tag_id] && params[:album_id] %>
<%= link_to "Show albums containing photos tagged with #{params[:q]}", albums_path(:q => params[:q]) if params[:q] %>
<%= link_to "Show all photos tagged with #{params[:tag_id]}", tag_photos_path(params[:tag_id]) if params[:tag_id] && params[:album_id] %>
<% end %>

View File

@ -1,34 +1,34 @@
<h2><%= @photo.title%></h2>
<h2><%= @photo.title %></h2>
<div id="fullimage">
<div id="navigation">
<p class="links">
<% unless @previous.nil? %>
<%= link_to "Previous", [ @photo.album.collections.first, @photo.album, @previous] %>
<% unless @next.nil? %>
|
<% end %>
<% end %>
<% unless @next.nil? %>
<%= link_to "Next", [ @photo.album.collections.first, @photo.album, @next] %>
<% end %>
</p>
</div>
<p><%= link_to_if @next, image_tag(@photo.file.single.url ), [ @photo.album.collections.first, @photo.album, @next] %></p>
<div id="navigation">
<p class="links">
<% unless @previous.nil? %>
<%= link_to "Previous", [@photo.album.collections.first, @photo.album, @previous] %>
<% unless @next.nil? %>
|
<% end %>
<% end %>
<% unless @next.nil? %>
<%= link_to "Next", [@photo.album.collections.first, @photo.album, @next] %>
<% end %>
</p>
</div>
<p><%= link_to_if @next, image_tag(@photo.attachment.single.url), [@photo.album.collections.first, @photo.album, @next] %></p>
</div>
<p><%= @photo.description %></p>
<p>Tagged with:
<% for tag in @photo.tags.map{|tag|tag.title}.sort %>
<%= link_to tag, tag_photos_path(tag) %>
<% end %>
<p>Tagged with:
<% for tag in @photo.tags.map { |tag| tag.title }.sort %>
<%= link_to tag, tag_photos_path(tag) %>
<% end %>
<%= content_for :action_links do %>
<% if has_role?("admin") %>
<% if params[:collection_id] %>
<%= link_to "Edit photo", edit_collection_album_photo_path(params[:collection_id], params[:album_id], @photo) %>
<% else %>
<%= link_to "Edit photo", edit_photo_path(@photo) %>
<% end %>
<% end %>
<%= content_for :action_links do %>
<% if current_user and current_user.has_role?("admin") %>
<% if params[:collection_id] %>
<%= link_to "Edit photo", edit_collection_album_photo_path(params[:collection_id], params[:album_id], @photo) %>
<% else %>
<%= link_to "Edit photo", edit_photo_path(@photo) %>
<% end %>
<% end %>
<% end %>

View File

@ -1,12 +1,12 @@
<%= form_for :photos, :url => update_multiple_photos_path, :html => { :method => :put } do |f| %>
<% for photo in @photos %>
<p>
<%= f.fields_for photo do |p|%>
<%= render :partial => "photos/thumb", :locals => {:photo => photo } %>
<%= p.text_field :title, :index => photo.id %>
<%= p.text_field :tags, :index => photo.id, :value => photo.tag_list %>
<% end%>
</p>
<% end%>
<p><%= f.submit "Submit" %></p>
<%= form_for :photos, :url => update_multiple_photos_path, :html => {:method => :put} do |f| %>
<% for photo in @photos %>
<p>
<%= f.fields_for photo do |p| %>
<%= render :partial => "photos/thumb", :locals => {:photo => photo} %>
<%= p.text_field :title, :index => photo.id %>
<%= p.text_field :tags, :index => photo.id, :value => photo.tag_list %>
<% end %>
</p>
<% end %>
<p><%= f.submit "Submit" %></p>
<% end %>

View File

@ -1,86 +1,78 @@
<%= content_for :javascript do %>
<style type="text/css">@import url(/javascripts/plupload/js/jquery.plupload.queue/css/jquery.plupload.queue.css);</style>
<%= javascript_include_tag "plupload/js/plupload.full.js" -%>
<%= javascript_include_tag "plupload/js/jquery.plupload.queue/jquery.plupload.queue.js" -%>
<script type="text/javascript">
$(document).ready(function () {
$("#uploader").pluploadQueue({
runtimes:'flash,html5,browserplus,silverlight,gears',
url:'<%= photos_path %>',
max_file_size:'10mb',
multipart:true,
multipart_params:{
'<%= get_session_key %>':encodeURIComponent('<%= cookies[get_session_key] %>'),
'authenticity_token':'<%= form_authenticity_token %>',
'photo[album_id]':"<%= @album.id %>"
},
<script type="text/javascript">
$(document).ready(function() {
$("#uploader").pluploadQueue({
// General settings
runtimes : 'flash,html5,browserplus,silverlight,gears',
url : '<%= photos_path %>',
max_file_size : '10mb',
multipart: true,
multipart_params: {
'<%= get_session_key %>' : encodeURIComponent('<%= u cookies[get_session_key] %>'),
'authenticity_token' : '<%= form_authenticity_token %>',
'photo[album_id]' : "<%= @album.id %>"
},
// Resize images on clientside if we can
//resize : {width : 320, height : 240, quality : 90},
// Resize images on clientside if we can
//resize : {width : 320, height : 240, quality : 90},
// Specify what files to browse for
filters:[
{title:"Image files", extensions:"jpg,gif,png,bmp,jpeg,tif,tiff,JPG,GIF,PNG,BMP,JPEG,TIF,TIFF"}
],
// Specify what files to browse for
filters : [
{title : "Image files", extensions : "jpg,gif,png,bmp,jpeg,tif,tiff"}
],
// Flash settings
flash_swf_url:'/assets/plupload.flash.swf',
// Flash settings
flash_swf_url : '/javascripts/plupload/js/plupload.flash.swf',
// Silverlight settings
silverlight_xap_url:'/assets/plupload.silverlight.xap',
// Silverlight settings
silverlight_xap_url : '/javascripts/plupload/js/plupload.silverlight.xap',
// Post init events, bound after the internal events
init : {
// Post init events, bound after the internal events
init:{
FileUploaded: function(up, file, info) {
// Called when a file has finished uploading
res = info.response;
if (res.substring(0, 7) === "FILEID:") {
var image = $('<img>').appendTo('#thumbs')
image.css('display','none')
image.attr('src', res.substring(7) )
image.fadeIn('slow')
}
}
}
});
FileUploaded:function (up, file, info) {
// Called when a file has finished uploading
res = info.response;
if (res.substring(0, 7) === "FILEID:") {
var image = $('<img>').appendTo('#thumbs')
image.css('display', 'none')
image.attr('src', res.substring(7))
image.fadeIn('slow')
}
}
}
});
// Client side form validation
$('form').submit(function(e) {
var uploader = $('#uploader').pluploadQueue();
// Client side form validation
$('form').submit(function (e) {
var uploader = $('#uploader').pluploadQueue();
// Validate number of uploaded files
if (uploader.total.uploaded == 0) {
// Files in queue upload them first
if (uploader.files.length > 0) {
// When all files are uploaded submit form
uploader.bind('UploadProgress', function() {
if (uploader.total.uploaded == uploader.files.length)
$('form').submit();
});
uploader.start();
} else
alert('You must at least upload one file.');
e.preventDefault();
}
});
})
</script>
// Validate number of uploaded files
if (uploader.total.uploaded == 0) {
// Files in queue upload them first
if (uploader.files.length > 0) {
// When all files are uploaded submit form
uploader.bind('UploadProgress', function () {
if (uploader.total.uploaded == uploader.files.length)
$('form').submit();
});
uploader.start();
} else
alert('You must at least upload one file.');
e.preventDefault();
}
});
})
</script>
<% end %>
<form>
<div id="uploader">
<p>You browser doesn't have Flash, Silverlight, Gears, BrowserPlus or HTML5 support.</p>
</div>
<div id="uploader">
<p>You browser doesn't have Flash, Silverlight, Gears, BrowserPlus or HTML5 support.</p>
</div>
<br>
<br>
<div id="thumbs"></div>
<div id="thumbs"></div>
</form>
<br><%= link_to "Edit uploaded photos", untouched_album_photos_path( @album ) %>
<br><%= link_to "Edit uploaded photos", untouched_album_photos_path(@album) %>
<br><%= link_to "Back to #{@album.title}", @album %>

View File

@ -0,0 +1,40 @@
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= ENV['TITLE'] || "Photos" %></title>
<%= csrf_meta_tags %>
<!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
<![endif]-->
<%= yield :styles %>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
<%= yield :head %>
<!-- For third-generation iPad with high-resolution Retina display: -->
<!-- Size should be 144 x 144 pixels -->
<%#= favicon_link_tag 'images/apple-touch-icon-144x144-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '144x144' %>
<!-- For iPhone with high-resolution Retina display: -->
<!-- Size should be 114 x 114 pixels -->
<%#= favicon_link_tag 'images/apple-touch-icon-114x114-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '114x114' %>
<!-- For first- and second-generation iPad: -->
<!-- Size should be 72 x 72 pixels -->
<%#= favicon_link_tag 'images/apple-touch-icon-72x72-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '72x72' %>
<!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: -->
<!-- Size should be 57 x 57 pixels -->
<%#= favicon_link_tag 'images/apple-touch-icon-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png' %>
<!-- For all other devices -->
<!-- Size should be 32 x 32 pixels -->
<%#= favicon_link_tag 'images/favicon.ico', :rel => 'shortcut icon' %>
<%= yield :javascript %>
<%= raw ajaxful_rating_style %>
<%= raw ajaxful_rating_script %>

View File

@ -0,0 +1,40 @@
<%= content_for :styles do %>
<%= stylesheet_link_tag "anythingslider/anythingslider" %>
<style type="text/css">
#home-slider {
height: 600px;
}
.slider-wrapper {
margin: 0 auto;
margin-bottom: 20px;
}
</style>
<% end %>
<%= content_for :head do %>
<%#= stylesheet_link_tag "anythingslider/anythingslider", "anythingslider/theme-metallic", "anythingslider/animate" %>
<%= javascript_include_tag "anythingslider/jquery.anythingslider.min" %>
<script>
$(function () {
$('#home-slider').anythingSlider({
// theme:'metallic',
// expand:true,
//resizeContents: false,
autoPlay:false
});
});
</script>
<% end %>
<div class="span12 slider-wrapper">
<ul id="home-slider">
<% @popular_photos.each do |photo| %>
<li><%= image_tag photo.attachment.largest.url %></li>
<% end %>
</ul>
</div>

View File

@ -0,0 +1,24 @@
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="/">Photomix</a>
<div class="nav-collapse">
<ul class="nav">
<li <%= "class='active'" if params['controller'].eql?("collections") %>><%= link_to pluralize(t('activerecord.models.collection.one'), 3, ["Коллекция", "Коллекции", "Коллекций"]), collections_path %></li>
<li <%= "class='active'" if params['controller'].eql?("albums") %>><%= link_to pluralize(t('activerecord.models.album'), 3, ["Альбом", "Альбомы", "Альбомов"]), albums_path %></li>
<li <%= "class='active'" if params['controller'].eql?("photos") %>><%= link_to pluralize(t('activerecord.models.photo'), 3, ["Фотография", "Фотографии", "Фотографий"]), photos_path %></li>
</ul>
<form action="" class="navbar-search pull-right">
<input type="text" placeholder="Search" class="search-query span2">
</form>
<%= render :partial => 'shared/user_links' %>
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show More