Compare commits
No commits in common. "master" and "gh-pages" have entirely different histories.
19
.gitignore
vendored
|
@ -1,19 +0,0 @@
|
|||
.bundle
|
||||
.rvmrc
|
||||
db/*.sqlite3
|
||||
log/*.log
|
||||
tmp
|
||||
.DS_Store
|
||||
doc/api
|
||||
doc/app
|
||||
config/database.yml
|
||||
config/settings.yml
|
||||
config/deploy.rb
|
||||
config/deploy
|
||||
Capfile
|
||||
public/thumbs
|
||||
public/uploads
|
||||
public/assets
|
||||
vendor/cache
|
||||
.idea
|
||||
.sass-cache
|
1
CNAME
Normal file
|
@ -0,0 +1 @@
|
|||
balderapp.com
|
62
Gemfile
|
@ -1,62 +0,0 @@
|
|||
source 'http://rubygems.org'
|
||||
|
||||
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'
|
||||
|
||||
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'
|
||||
|
||||
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.
|
||||
gem 'fog'
|
||||
|
||||
# -- Photo resizing
|
||||
# MiniMagick
|
||||
gem "mini_magick"
|
||||
|
||||
# ImageMagick:
|
||||
#gem "rmagick", :require => 'RMagick'
|
||||
|
||||
# FreeImage:
|
||||
#gem "RubyInline"
|
||||
#gem "image_science", :git => 'git://github.com/perezd/image_science.git'
|
||||
|
||||
# -- EXIF
|
||||
# Mini exif tool. Can be disabled. Remove exif_read and exif_write filters in photo model
|
||||
gem "mini_exiftool"
|
341
Gemfile.lock
|
@ -1,341 +0,0 @@
|
|||
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.7)
|
||||
actionpack (= 3.2.7)
|
||||
mail (~> 2.4.4)
|
||||
actionpack (3.2.7)
|
||||
activemodel (= 3.2.7)
|
||||
activesupport (= 3.2.7)
|
||||
builder (~> 3.0.0)
|
||||
erubis (~> 2.7.0)
|
||||
journey (~> 1.0.4)
|
||||
rack (~> 1.4.0)
|
||||
rack-cache (~> 1.2)
|
||||
rack-test (~> 0.6.1)
|
||||
sprockets (~> 2.1.3)
|
||||
activemodel (3.2.7)
|
||||
activesupport (= 3.2.7)
|
||||
builder (~> 3.0.0)
|
||||
activerecord (3.2.7)
|
||||
activemodel (= 3.2.7)
|
||||
activesupport (= 3.2.7)
|
||||
arel (~> 3.0.2)
|
||||
tzinfo (~> 0.3.29)
|
||||
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)
|
||||
bcrypt-ruby (3.0.1)
|
||||
builder (3.0.0)
|
||||
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.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.14)
|
||||
formatador (~> 0.2.0)
|
||||
mime-types
|
||||
multi_json (~> 1.0)
|
||||
net-scp (~> 1.0.4)
|
||||
net-ssh (>= 2.1.3)
|
||||
nokogiri (~> 1.5.0)
|
||||
ruby-hmac
|
||||
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.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.19)
|
||||
mini_exiftool (1.6.0)
|
||||
mini_magick (3.4)
|
||||
subexec (~> 0.2.1)
|
||||
multi_json (1.3.6)
|
||||
multipart-post (1.1.5)
|
||||
net-scp (1.0.4)
|
||||
net-ssh (>= 1.99.1)
|
||||
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.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.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, < 2.0)
|
||||
raindrops (0.10.0)
|
||||
rake (0.9.2.2)
|
||||
rdoc (3.12)
|
||||
json (~> 1.4)
|
||||
ruby-hmac (0.4.0)
|
||||
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)
|
||||
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.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
|
||||
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
|
||||
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
|
8
LICENSE
|
@ -1,8 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
Copyright (c) 2011 Espen Antonsen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
157
README.md
|
@ -1,157 +0,0 @@
|
|||
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/
|
7
Rakefile
|
@ -1,7 +0,0 @@
|
|||
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
||||
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
||||
|
||||
require File.expand_path('../config/application', __FILE__)
|
||||
require 'rake'
|
||||
|
||||
Photomix::Application.load_tasks
|
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 302 B |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 1.5 KiB |
|
@ -1,59 +0,0 @@
|
|||
// 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
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
jQuery(function($) {
|
||||
|
||||
if ( $('.tag_list').length ) {
|
||||
$('.tag_list').tagSuggest({
|
||||
tags: $('#all_tags').val().split('\'')
|
||||
})
|
||||
}
|
||||
|
||||
var map, latlng
|
||||
if ( $('#map_canvas').length && $('#album_latitude').val() > '' && $('#album_longitude').val() > '' ) {
|
||||
latlng = new google.maps.LatLng($('#album_latitude').val(), $('#album_longitude').val());
|
||||
mapInitialize()
|
||||
$('#map_canvas').show()
|
||||
}
|
||||
if ( $('#map_canvas').length && $('#photo_latitude').val() > '' && $('#photo_longitude').val() > '' ) {
|
||||
latlng = new google.maps.LatLng($('#photo_latitude').val(), $('#photo_longitude').val());
|
||||
mapInitialize()
|
||||
$('#map_canvas').show()
|
||||
}
|
||||
|
||||
$('#collection_albums .delete').live('click', function() {
|
||||
$(this).parent('span').fadeOut('slow', function() { $(this).remove() })
|
||||
})
|
||||
|
||||
$("#available_albums").change( function() {
|
||||
if ( this.value == '' ) {
|
||||
return false
|
||||
}
|
||||
else if ( $('#collection_album_list_' + this.value).length ) {
|
||||
$('#collection_album_list_' + this.value).parent('span').fadeTo('slow', 0.33, function () {
|
||||
$(this).fadeTo('slow', 1)
|
||||
})
|
||||
return false
|
||||
}
|
||||
$.getJSON("/albums/" + this.value + '/photos',
|
||||
function(data){
|
||||
console.log( data[0].photo.file.album.url );
|
||||
html = '<span style="display:none;"><img src="/images/delete-24x24.png" border="" class="delete" />'
|
||||
html += '<img alt="' + $("#available_albums :selected").val() + '_collection" src=' + data[0].photo.file.album.url + ' />'
|
||||
html += '<input id="collection_album_list_' + $("#available_albums :selected").val() + '" name="collection[album_list][' + $("#available_albums :selected").val() + ']" type="hidden" />'
|
||||
html += '</span>'
|
||||
$('#collection_albums').append(html)
|
||||
$('#collection_album_list_' + $('#available_albums :selected').val() ).parent('span').fadeIn('slow')
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
$("#album_address").change( function() {
|
||||
if( !map ) {
|
||||
mapInitialize()
|
||||
$('#map_canvas').show()
|
||||
}
|
||||
var geocoder = new google.maps.Geocoder()
|
||||
var address = this.value
|
||||
if (geocoder) {
|
||||
geocoder.geocode( { 'address': address}, function(results, status) {
|
||||
if (status == google.maps.GeocoderStatus.OK) {
|
||||
if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
|
||||
map.set_center(results[0].geometry.location)
|
||||
mapCreateMarker( {
|
||||
title: $('#album_title').val(),
|
||||
address: results[0].formatted_address,
|
||||
position: results[0].geometry.location
|
||||
}
|
||||
)
|
||||
} else {
|
||||
//alert("No results found")
|
||||
}
|
||||
} else {
|
||||
//alert("Geocode was not successful for the following reason: " + status)
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
function mapInitialize() {
|
||||
var myOptions = {
|
||||
zoom: 13,
|
||||
center: latlng,
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||
}
|
||||
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions)
|
||||
}
|
||||
|
||||
function mapCreateMarker(location) {
|
||||
var marker = new google.maps.Marker({
|
||||
map: map,
|
||||
position: location.position,
|
||||
title: location.title
|
||||
})
|
||||
|
||||
var infowindow = new google.maps.InfoWindow({
|
||||
content: '<b>' + location.title + '</b><br/>' + location.address
|
||||
})
|
||||
|
||||
google.maps.event.addListener(marker, 'click', function() {
|
||||
infowindow.open(map,marker)
|
||||
})
|
||||
}
|
||||
|
||||
})
|
|
@ -1,4 +0,0 @@
|
|||
jQuery ->
|
||||
$("a[rel=popover]").popover()
|
||||
$(".tooltip").tooltip()
|
||||
$("a[rel=tooltip]").tooltip()
|
|
@ -1,2 +0,0 @@
|
|||
// Place all the behaviors and hooks related to the matching controller here.
|
||||
// All this logic will automatically be available in application.js.
|
|
@ -1,267 +0,0 @@
|
|||
/*
|
||||
@author: remy sharp / http://remysharp.com
|
||||
@url: http://remysharp.com/2007/12/28/jquery-tag-suggestion/
|
||||
@usage: setGlobalTags(['javascript', 'jquery', 'java', 'json']); // applied tags to be used for all implementations
|
||||
$('input.tags').tagSuggest(options);
|
||||
|
||||
The selector is the element that the user enters their tag list
|
||||
@params:
|
||||
matchClass - class applied to the suggestions, defaults to 'tagMatches'
|
||||
tagContainer - the type of element uses to contain the suggestions, defaults to 'span'
|
||||
tagWrap - the type of element the suggestions a wrapped in, defaults to 'span'
|
||||
sort - boolean to force the sorted order of suggestions, defaults to false
|
||||
url - optional url to get suggestions if setGlobalTags isn't used. Must return array of suggested tags
|
||||
tags - optional array of tags specific to this instance of element matches
|
||||
delay - optional sets the delay between keyup and the request - can help throttle ajax requests, defaults to zero delay
|
||||
separator - optional separator string, defaults to ' ' (Brian J. Cardiff)
|
||||
@license: Creative Commons License - ShareAlike http://creativecommons.org/licenses/by-sa/3.0/
|
||||
@version: 1.4
|
||||
@changes: fixed filtering to ajax hits
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var globalTags = [];
|
||||
|
||||
// creates a public function within our private code.
|
||||
// tags can either be an array of strings OR
|
||||
// array of objects containing a 'tag' attribute
|
||||
window.setGlobalTags = function(tags /* array */) {
|
||||
globalTags = getTags(tags);
|
||||
};
|
||||
|
||||
function getTags(tags) {
|
||||
var tag, i, goodTags = [];
|
||||
for (i = 0; i < tags.length; i++) {
|
||||
tag = tags[i];
|
||||
if (typeof tags[i] == 'object') {
|
||||
tag = tags[i].tag;
|
||||
}
|
||||
goodTags.push(tag.toLowerCase());
|
||||
}
|
||||
|
||||
return goodTags;
|
||||
}
|
||||
|
||||
$.fn.tagSuggest = function (options) {
|
||||
var defaults = {
|
||||
'matchClass' : 'tagMatches',
|
||||
'tagContainer' : 'span',
|
||||
'tagWrap' : 'span',
|
||||
'sort' : true,
|
||||
'tags' : null,
|
||||
'url' : null,
|
||||
'delay' : 0,
|
||||
'separator' : ' '
|
||||
};
|
||||
|
||||
var i, tag, userTags = [], settings = $.extend({}, defaults, options);
|
||||
|
||||
if (settings.tags) {
|
||||
userTags = getTags(settings.tags);
|
||||
} else {
|
||||
userTags = globalTags;
|
||||
}
|
||||
|
||||
return this.each(function () {
|
||||
var tagsElm = $(this);
|
||||
var elm = this;
|
||||
var matches, fromTab = false;
|
||||
var suggestionsShow = false;
|
||||
var workingTags = [];
|
||||
var currentTag = {"position": 0, tag: ""};
|
||||
var tagMatches = document.createElement(settings.tagContainer);
|
||||
|
||||
function showSuggestionsDelayed(el, key) {
|
||||
if (settings.delay) {
|
||||
if (elm.timer) clearTimeout(elm.timer);
|
||||
elm.timer = setTimeout(function () {
|
||||
showSuggestions(el, key);
|
||||
}, settings.delay);
|
||||
} else {
|
||||
showSuggestions(el, key);
|
||||
}
|
||||
}
|
||||
|
||||
function showSuggestions(el, key) {
|
||||
workingTags = el.value.split(settings.separator);
|
||||
matches = [];
|
||||
var i, html = '', chosenTags = {}, tagSelected = false;
|
||||
|
||||
// we're looking to complete the tag on currentTag.position (to start with)
|
||||
currentTag = { position: currentTags.length-1, tag: '' };
|
||||
|
||||
for (i = 0; i < currentTags.length && i < workingTags.length; i++) {
|
||||
if (!tagSelected &&
|
||||
currentTags[i].toLowerCase() != workingTags[i].toLowerCase()) {
|
||||
currentTag = { position: i, tag: workingTags[i].toLowerCase() };
|
||||
tagSelected = true;
|
||||
}
|
||||
// lookup for filtering out chosen tags
|
||||
chosenTags[currentTags[i].toLowerCase()] = true;
|
||||
}
|
||||
|
||||
if (currentTag.tag) {
|
||||
// collect potential tags
|
||||
if (settings.url) {
|
||||
$.ajax({
|
||||
'url' : settings.url,
|
||||
'dataType' : 'json',
|
||||
'data' : { 'tag' : currentTag.tag },
|
||||
'async' : false, // wait until this is ajax hit is complete before continue
|
||||
'success' : function (m) {
|
||||
matches = m;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (i = 0; i < userTags.length; i++) {
|
||||
if (userTags[i].indexOf(currentTag.tag) === 0) {
|
||||
matches.push(userTags[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matches = $.grep(matches, function (v, i) {
|
||||
return !chosenTags[v.toLowerCase()];
|
||||
});
|
||||
|
||||
if (settings.sort) {
|
||||
matches = matches.sort();
|
||||
}
|
||||
|
||||
for (i = 0; i < matches.length; i++) {
|
||||
html += '<' + settings.tagWrap + ' class="_tag_suggestion">' + matches[i] + '</' + settings.tagWrap + '>';
|
||||
}
|
||||
|
||||
tagMatches.html(html);
|
||||
suggestionsShow = !!(matches.length);
|
||||
} else {
|
||||
hideSuggestions();
|
||||
}
|
||||
}
|
||||
|
||||
function hideSuggestions() {
|
||||
tagMatches.empty();
|
||||
matches = [];
|
||||
suggestionsShow = false;
|
||||
}
|
||||
|
||||
function setSelection() {
|
||||
var v = tagsElm.val();
|
||||
|
||||
// tweak for hintted elements
|
||||
// http://remysharp.com/2007/01/25/jquery-tutorial-text-box-hints/
|
||||
if (v == tagsElm.attr('title') && tagsElm.is('.hint')) v = '';
|
||||
|
||||
currentTags = v.split(settings.separator);
|
||||
hideSuggestions();
|
||||
}
|
||||
|
||||
function chooseTag(tag) {
|
||||
var i, index;
|
||||
for (i = 0; i < currentTags.length; i++) {
|
||||
if (currentTags[i].toLowerCase() != workingTags[i].toLowerCase()) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == workingTags.length - 1) tag = tag + settings.separator;
|
||||
|
||||
workingTags[i] = tag;
|
||||
|
||||
tagsElm.val(workingTags.join(settings.separator));
|
||||
tagsElm.blur().focus();
|
||||
setSelection();
|
||||
}
|
||||
|
||||
function handleKeys(ev) {
|
||||
fromTab = false;
|
||||
var type = ev.type;
|
||||
var resetSelection = false;
|
||||
|
||||
switch (ev.keyCode) {
|
||||
case 37: // ignore cases (arrow keys)
|
||||
case 38:
|
||||
case 39:
|
||||
case 40: {
|
||||
hideSuggestions();
|
||||
return true;
|
||||
}
|
||||
case 224:
|
||||
case 17:
|
||||
case 16:
|
||||
case 18: {
|
||||
return true;
|
||||
}
|
||||
|
||||
case 8: {
|
||||
// delete - hide selections if we're empty
|
||||
if (this.value == '') {
|
||||
hideSuggestions();
|
||||
setSelection();
|
||||
return true;
|
||||
} else {
|
||||
type = 'keyup'; // allow drop through
|
||||
resetSelection = true;
|
||||
showSuggestionsDelayed(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 9: // return and tab
|
||||
case 13: {
|
||||
if (suggestionsShow) {
|
||||
// complete
|
||||
chooseTag(matches[0]);
|
||||
|
||||
fromTab = true;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
case 27: {
|
||||
hideSuggestions();
|
||||
setSelection();
|
||||
return true;
|
||||
}
|
||||
case 32: {
|
||||
setSelection();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == 'keyup') {
|
||||
switch (ev.charCode) {
|
||||
case 9:
|
||||
case 13: {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (resetSelection) {
|
||||
setSelection();
|
||||
}
|
||||
showSuggestionsDelayed(this, ev.charCode);
|
||||
}
|
||||
}
|
||||
|
||||
tagsElm.after(tagMatches).keypress(handleKeys).keyup(handleKeys).blur(function () {
|
||||
if (fromTab == true || suggestionsShow) { // tweak to support tab selection for Opera & IE
|
||||
fromTab = false;
|
||||
tagsElm.focus();
|
||||
}
|
||||
});
|
||||
|
||||
// replace with jQuery version
|
||||
tagMatches = $(tagMatches).click(function (ev) {
|
||||
if (ev.target.nodeName == settings.tagWrap.toUpperCase() && $(ev.target).is('._tag_suggestion')) {
|
||||
chooseTag(ev.target.innerHTML);
|
||||
}
|
||||
}).addClass(settings.matchClass);
|
||||
|
||||
// initialise
|
||||
setSelection();
|
||||
});
|
||||
};
|
||||
})(jQuery);
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -1,191 +0,0 @@
|
|||
/*
|
||||
*= 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;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
@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;
|
|
@ -1,3 +0,0 @@
|
|||
// 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/
|
|
@ -1,177 +0,0 @@
|
|||
/*
|
||||
Plupload
|
||||
------------------------------------------------------------------- */
|
||||
|
||||
.plupload_button {
|
||||
display: -moz-inline-box; /* FF < 3*/
|
||||
display: inline-block;
|
||||
font: normal 12px sans-serif;
|
||||
text-decoration: none;
|
||||
color: #42454a;
|
||||
border: 1px solid #bababa;
|
||||
padding: 2px 8px 3px 20px;
|
||||
margin-right: 4px;
|
||||
background: #f3f3f3 url(asset_path("buttons.png")) no-repeat 0 center;
|
||||
outline: 0;
|
||||
|
||||
/* Optional rounded corners for browsers that support it */
|
||||
-moz-border-radius: 3px;
|
||||
-khtml-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.plupload_button:hover {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.plupload_disabled, a.plupload_disabled:hover {
|
||||
color: #737373;
|
||||
border-color: #c5c5c5;
|
||||
background: #ededed url(asset_path('buttons-disabled.png')) no-repeat 0 center;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.plupload_add {
|
||||
background-position: -181px center;
|
||||
}
|
||||
|
||||
.plupload_wrapper {
|
||||
font: normal 11px Verdana,sans-serif;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.plupload_container {
|
||||
padding: 8px;
|
||||
background: url(asset_path('transp50.png'));
|
||||
/*-moz-border-radius: 5px;*/
|
||||
}
|
||||
|
||||
.plupload_container input {
|
||||
border: 1px solid #DDD;
|
||||
font: normal 11px Verdana,sans-serif;
|
||||
width: 98%;
|
||||
}
|
||||
|
||||
.plupload_header {background: #2A2C2E url(asset_path('backgrounds.gif')) repeat-x;}
|
||||
.plupload_header_content {
|
||||
background: url(asset_path('backgrounds.gif')) no-repeat 0 -317px;
|
||||
min-height: 56px;
|
||||
padding-left: 60px;
|
||||
color: #FFF;
|
||||
}
|
||||
.plupload_header_title {
|
||||
font: normal 18px sans-serif;
|
||||
padding: 6px 0 3px;
|
||||
}
|
||||
.plupload_header_text {
|
||||
font: normal 12px sans-serif;
|
||||
}
|
||||
|
||||
.plupload_filelist {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.plupload_scroll .plupload_filelist {
|
||||
height: 185px;
|
||||
background: #F5F5F5;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.plupload_filelist li {
|
||||
padding: 10px 8px;
|
||||
background: #F5F5F5 url(asset_path('backgrounds.gif')) repeat-x 0 -156px;
|
||||
border-bottom: 1px solid #DDD;
|
||||
}
|
||||
|
||||
.plupload_filelist_header, .plupload_filelist_footer {
|
||||
background: #DFDFDF;
|
||||
padding: 8px 8px;
|
||||
color: #42454A;
|
||||
}
|
||||
.plupload_filelist_header {
|
||||
border-top: 1px solid #EEE;
|
||||
border-bottom: 1px solid #CDCDCD;
|
||||
}
|
||||
|
||||
.plupload_filelist_footer {border-top: 1px solid #FFF; height: 22px; line-height: 20px; vertical-align: middle;}
|
||||
.plupload_file_name {float: left; overflow: hidden}
|
||||
.plupload_file_status {color: #777;}
|
||||
.plupload_file_status span {color: #42454A;}
|
||||
.plupload_file_size, .plupload_file_status, .plupload_progress {
|
||||
float: right;
|
||||
width: 80px;
|
||||
}
|
||||
.plupload_file_size, .plupload_file_status, .plupload_file_action {text-align: right;}
|
||||
|
||||
.plupload_filelist .plupload_file_name {width: 205px}
|
||||
|
||||
.plupload_file_action {
|
||||
float: right;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.plupload_file_action * {
|
||||
display: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
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(asset_path('delete.gif'));
|
||||
}
|
||||
|
||||
li.plupload_failed a {
|
||||
background: url(asset_path('error.gif'));
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
li.plupload_done a {
|
||||
background: url(asset_path('done.gif'));
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.plupload_progress, .plupload_upload_status {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.plupload_progress_container {
|
||||
margin-top: 3px;
|
||||
border: 1px solid #CCC;
|
||||
background: #FFF;
|
||||
padding: 1px;
|
||||
}
|
||||
.plupload_progress_bar {
|
||||
width: 0px;
|
||||
height: 7px;
|
||||
background: #CDEB8B;
|
||||
}
|
||||
|
||||
.plupload_scroll .plupload_filelist_header .plupload_file_action, .plupload_scroll .plupload_filelist_footer .plupload_file_action {
|
||||
margin-right: 17px;
|
||||
}
|
||||
|
||||
/* Floats */
|
||||
|
||||
.plupload_clear,.plupload_clearer {clear: both;}
|
||||
.plupload_clearer, .plupload_progress_bar {
|
||||
display: block;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
li.plupload_droptext {
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border: 0;
|
||||
line-height: 165px;
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
Plupload
|
||||
------------------------------------------------------------------- */
|
||||
|
||||
.plupload_button {cursor: pointer;}
|
||||
|
||||
.plupload_wrapper {
|
||||
font: normal 11px Verdana,sans-serif;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.plupload .plupload_container input {width: 98%;}
|
||||
.plupload .plupload_filelist_footer {border-width: 1px 0 0 0}
|
||||
.plupload .plupload_filelist_header {border-width: 0 0 1px 0}
|
||||
div.plupload .plupload_file {border-width: 0 0 1px 0}
|
||||
div.plupload div.plupload_header {border-width: 0 0 1px 0; position: relative;}
|
||||
|
||||
.plupload_file .ui-icon {
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.plupload_header_content {
|
||||
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(asset_path('plupload-bw.png'));}
|
||||
.plupload_header_title {
|
||||
font: normal 18px sans-serif;
|
||||
padding: 6px 0 3px;
|
||||
}
|
||||
.plupload_header_text {font: normal 12px sans-serif;}
|
||||
|
||||
.plupload_filelist,
|
||||
.plupload_filelist_content {
|
||||
border-collapse: collapse;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
-moz-user-select:none;
|
||||
-webkit-user-select:none;
|
||||
user-select:none;
|
||||
}
|
||||
|
||||
.plupload_cell {padding: 8px 6px;}
|
||||
|
||||
.plupload_file {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.plupload .ui-sortable-helper,
|
||||
.plupload .ui-sortable .plupload_file {
|
||||
cursor:move;
|
||||
}
|
||||
|
||||
.plupload_scroll {
|
||||
max-height: 180px;
|
||||
min-height: 168px;
|
||||
_height: 168px;
|
||||
}
|
||||
|
||||
.plupload_file_size, .plupload_file_status {text-align: right;}
|
||||
.plupload_file_size, .plupload_file_status {width: 52px;}
|
||||
.plupload_file_action {width: 16px;}
|
||||
.plupload_file_name {
|
||||
overflow: hidden;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.plupload_file_rename {
|
||||
width:95%;
|
||||
}
|
||||
|
||||
.plupload_progress {width: 60px;}
|
||||
.plupload_progress_container {padding: 1px;}
|
||||
|
||||
|
||||
/* Floats */
|
||||
|
||||
.plupload_right {float: right;}
|
||||
.plupload_left {float: left;}
|
||||
.plupload_clear,.plupload_clearer {clear: both;}
|
||||
.plupload_clearer, .plupload_progress_bar {
|
||||
display: block;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
.plupload_clearer {height: 0;}
|
||||
|
||||
/* Misc */
|
||||
.plupload_hidden {display: none;}
|
||||
.plupload_droptext {
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border: 0;
|
||||
line-height: 165px;
|
||||
}
|
||||
|
||||
.plupload_buttons, .plupload_upload_status {float: left}
|
||||
|
||||
.plupload_message {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.plupload_message p {
|
||||
padding:0.7em;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.plupload_message strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
plupload_message i {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.plupload_message p span.ui-icon {
|
||||
float: left;
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
|
||||
.plupload_header_content .ui-state-error,
|
||||
.plupload_header_content .ui-state-highlight {
|
||||
border:none;
|
||||
}
|
||||
|
||||
.plupload_message_close {
|
||||
position:absolute;
|
||||
top:5px;
|
||||
right:5px;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.plupload .ui-sortable-placeholder {
|
||||
height:35px;
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
class AlbumsController < ApplicationController
|
||||
before_filter :check_public_access
|
||||
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.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}
|
||||
#@albums = Album.find(:all, :select => 'DISTINCT albums.id, albums.title', :limit => 20, :conditions => { :tags => {:title => search}}, :joins => 'LEFT OUTER JOIN photos ON albums.id = photos.album_id LEFT OUTER JOIN photo_tags ON photos.id = photo_tags.photo_id LEFT OUTER JOIN tags ON photo_tags.tag_id = tags.id', :order => "albums.title ASC" )
|
||||
#@albums = Album.find(:all, :select => 'DISTINCT album_id', :conditions => [ "title LIKE :q OR description LIKE :q OR id IN ( SELECT DISTINCT photos.album_id FROM photos WHERE photos.description LIKE :q OR photos.title LIKE :q OR photos.id IN ( SELECT photo_id FROM photo_tags LEFT OUTER JOIN tags ON photo_tags.tag_id = tags.id WHERE tags.title LIKE :q) )", { :q => '%' + params[:q] + '%' } ], :order => 'title')
|
||||
params[:q].split(" AND ").each {|q|
|
||||
qphotos = Photo.find(:all, :select => 'DISTINCT album_id', :conditions => [ "description LIKE :q OR title LIKE :q OR id IN ( SELECT photo_id FROM photo_tags LEFT OUTER JOIN tags ON photo_tags.tag_id = tags.id WHERE tags.title LIKE :q)", { :q => '%' + q + '%' } ])
|
||||
qalbums = Album.find(:all, :conditions => ['title LIKE :q OR description LIKE :q OR id IN (:ids)', { :ids => qphotos.map{|p|p.album_id}, :q => '%' + q + '%' }], :order => 'title' )
|
||||
if @albums
|
||||
@albums = @albums & qalbums
|
||||
else
|
||||
@albums = qalbums
|
||||
end
|
||||
}
|
||||
else
|
||||
@albums = Album.popular.page(@page).per(@per_page)
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @albums }
|
||||
format.xml { render :xml => @albums }
|
||||
end
|
||||
end
|
||||
|
||||
def untouched
|
||||
@albums = Album.untouched()
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @albums }
|
||||
format.xml { render :xml => @albums }
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@album = Album.find( params[:id])
|
||||
@photos = @album.photos.popular
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @album }
|
||||
format.xml { render :xml => @album }
|
||||
format.pdf { render :pdf => @album.title }
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
@album = Album.new
|
||||
end
|
||||
|
||||
def create
|
||||
@album = Album.new(params[:album])
|
||||
|
||||
if @album.save
|
||||
flash[:notice] = "Album created! Now add some nice photos."
|
||||
if params[:collection_id]
|
||||
@album.collections << Collection.find( params[:collection_id] )
|
||||
redirect_to upload_collection_album_photos_path(params[:collection_id], @album )
|
||||
else
|
||||
redirect_to upload_album_photos_path( @album )
|
||||
end
|
||||
else
|
||||
render :action => :new
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@album = Album.find( params[:id])
|
||||
end
|
||||
|
||||
def update
|
||||
@album = Album.find( params[:id])
|
||||
if @album.update_attributes(params[:album])
|
||||
flash[:notice] = "Album updated!"
|
||||
if params[:collection_id]
|
||||
redirect_to collection_album_path(params[:collection_id], @album )
|
||||
else
|
||||
redirect_to @album
|
||||
end
|
||||
else
|
||||
render :action => :edit
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@album = Album.find( params[:id])
|
||||
if @album.destroy
|
||||
if params[:collection_id]
|
||||
redirect_to collection_path(params[:collection_id] )
|
||||
else
|
||||
redirect_to albums_path
|
||||
end
|
||||
else
|
||||
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
|
|
@ -1,51 +0,0 @@
|
|||
# Filters added to this controller apply to all controllers in the application.
|
||||
# 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
|
||||
|
||||
before_filter :set_locale
|
||||
before_filter :authenticate_user!, :set_current_user
|
||||
before_filter :setup, :set_pagination_params
|
||||
|
||||
private
|
||||
# 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 setup
|
||||
redirect_to new_account_path if User.all.size == 0
|
||||
end
|
||||
|
||||
def check_public_access
|
||||
require_user if ENV['PRIVATE'] == '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
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
end
|
|
@ -1,86 +0,0 @@
|
|||
class CollectionsController < ApplicationController
|
||||
before_filter :check_public_access
|
||||
skip_before_filter :authenticate_user!, :only => [:index, :show]
|
||||
add_breadcrumb I18n.t('home_page'), :root_path, :title => I18n.t('home_page')
|
||||
|
||||
def index
|
||||
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 }
|
||||
format.xml { render :xml => @collections }
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@collection = Collection.find( params[:id] )
|
||||
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 }
|
||||
format.xml { render :xml => @collection }
|
||||
format.pdf { render :pdf => @collection.title }
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
@collection = Collection.new(params[:collection])
|
||||
if @collection.save
|
||||
flash[:notice] = "Collection created! Now lets add a new album."
|
||||
redirect_to new_collection_album_path(@collection)
|
||||
else
|
||||
render :action => :new
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@collection = Collection.find( params[:id])
|
||||
end
|
||||
|
||||
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
|
||||
else
|
||||
render :action => :edit
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@collection = Collection.find( params[:id])
|
||||
if @collection.destroy
|
||||
redirect_to collections_path
|
||||
else
|
||||
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
|
|
@ -1,16 +0,0 @@
|
|||
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
|
|
@ -1,16 +0,0 @@
|
|||
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
|
|
@ -1,157 +0,0 @@
|
|||
class PhotosController < ApplicationController
|
||||
before_filter :check_public_access
|
||||
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.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.order("photos.id ASC")
|
||||
elsif params[:album_id]
|
||||
@album = Album.find( params[:album_id])
|
||||
@photos = @album.photos.order("photos.id ASC")
|
||||
elsif params[:q]
|
||||
#search = params[:q]
|
||||
#search = search.split("AND").map{|q|q.strip}
|
||||
#@photos = Photo.find(:all, :select => 'DISTINCT photos.id, photos.album_id, photos.title, photos.path', :limit => 20, :conditions => { :tags => {:title => search}}, :joins => 'LEFT OUTER JOIN photo_tags ON photos.id = photo_tags.photo_id LEFT OUTER JOIN tags ON photo_tags.tag_id = tags.id', :include => [:album], :order => "photos.title ASC" )
|
||||
params[:q].split(" AND ").each {|q|
|
||||
qphotos = Photo.find(:all, :limit => 20, :conditions => [ "photos.description LIKE :q OR photos.title LIKE :q OR photos.id IN ( SELECT photo_id FROM photo_tags LEFT OUTER JOIN tags ON photo_tags.tag_id = tags.id WHERE tags.title = :t) ", { :q => '%' + q + '%', :t => q } ], :include => :album, :order => "photos.id ASC" )
|
||||
if @photos
|
||||
@photos = @photos & qphotos
|
||||
else
|
||||
@photos = qphotos
|
||||
end
|
||||
}
|
||||
else
|
||||
@photos = Photo.popular.page(@page).per(@per_page)
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @photos }
|
||||
format.xml { render :xml => @photos }
|
||||
end
|
||||
end
|
||||
|
||||
def untouched
|
||||
if params[:album_id]
|
||||
@album = Album.find( params[:album_id])
|
||||
@photos = @album.photos.untouched.page(@page).per(@per_page)
|
||||
else
|
||||
@photos = Photo.untouched().page(@page).per(@per_page)
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @photos }
|
||||
format.xml { render :xml => @photos }
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@photo = Photo.find( params[:id] )
|
||||
previous_rs = Photo.previous( @photo.id, @photo.album )
|
||||
@previous = previous_rs.first unless previous_rs.empty?
|
||||
next_rs = Photo.next( @photo.id, @photo.album )
|
||||
@next = next_rs.first unless next_rs.empty?
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @photo }
|
||||
format.xml { render :xml => @photo }
|
||||
end
|
||||
end
|
||||
|
||||
def scan
|
||||
require "scan"
|
||||
ScanFiles.Scan(false)
|
||||
redirect_to(root_path)
|
||||
end
|
||||
|
||||
def new
|
||||
@photo = Photo.new
|
||||
end
|
||||
|
||||
def upload
|
||||
@album = Album.find( params[:album_id])
|
||||
end
|
||||
|
||||
def create
|
||||
@photo = Photo.new(params[:photo])
|
||||
@photo.attachment = params[:file]
|
||||
respond_to do |format|
|
||||
if @photo.save
|
||||
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 }
|
||||
format.xml { render :xml => @photo.errors, :status => 500 }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@photo = Photo.find( params[:id])
|
||||
@tags = Tag.all.map { |tag| tag.title }.join('\',\'')
|
||||
end
|
||||
|
||||
def edit_multiple
|
||||
if params[:album_id]
|
||||
@album = Album.find( params[:album_id] )
|
||||
@photos = @album.photos
|
||||
else
|
||||
@photos = Photo.find( params[:photo_ids] )
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@photo = Photo.find( params[:id])
|
||||
if @photo.update_attributes(params[:photo])
|
||||
flash[:notice] = "Photo updated!"
|
||||
if params[:collection_id]
|
||||
redirect_to collection_album_photo_path( params[:collection_id], params[:album_id], @photo )
|
||||
elsif params[:album_id]
|
||||
redirect_to album_photo_path( params[:album_id], @photo )
|
||||
else
|
||||
redirect_to @photo
|
||||
end
|
||||
else
|
||||
render :action => :edit
|
||||
end
|
||||
end
|
||||
|
||||
def update_multiple
|
||||
@photos = params[:photos][:photo]
|
||||
@photos.each do |photo_item|
|
||||
photo = Photo.find( photo_item[0] )
|
||||
if photo_item[1][:_delete] == "1"
|
||||
photo.destroy
|
||||
else
|
||||
photo.title = photo_item[1][:title]
|
||||
photo.tag_list = photo_item[1][:tags]
|
||||
photo.save
|
||||
end
|
||||
end
|
||||
flash[:notice] = "Updated photos!"
|
||||
redirect_to photos_path
|
||||
end
|
||||
|
||||
def destroy
|
||||
@photo = Photo.find( params[:id])
|
||||
@album = @photo.album
|
||||
if @photo.destroy
|
||||
if params[:collection_id]
|
||||
redirect_to collection_album_path( params[:collection_id], @album )
|
||||
else
|
||||
redirect_to @album
|
||||
end
|
||||
else
|
||||
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
|
|
@ -1,16 +0,0 @@
|
|||
class TagsController < ApplicationController
|
||||
before_filter :check_public_access
|
||||
|
||||
def index
|
||||
if params[:album_id]
|
||||
@tags = Album.find( params[:album_id] ).photo_tags
|
||||
else
|
||||
@tags = Tag.order('title')
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @tags }
|
||||
format.xml { render :xml => @tags }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,49 +0,0 @@
|
|||
class UsersController < ApplicationController
|
||||
before_filter :check_public_access
|
||||
skip_before_filter :authenticate_user!, :only => [:new, :create]
|
||||
skip_filter :setup
|
||||
|
||||
def new
|
||||
@user = User.new
|
||||
end
|
||||
|
||||
def create
|
||||
@user = User.new(params[:user])
|
||||
if @user.save
|
||||
if User.all.length == 1
|
||||
@user.roles << Role.create(:name => 'admin')
|
||||
end
|
||||
flash[:notice] = "Account registered!"
|
||||
redirect_back_or_default new_collection_path
|
||||
else
|
||||
render :action => :new
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@user = @current_user
|
||||
end
|
||||
|
||||
def edit
|
||||
@user = @current_user
|
||||
end
|
||||
|
||||
def update
|
||||
@user = @current_user # makes our views "cleaner" and more consistent
|
||||
if @user.update_attributes(params[:user])
|
||||
flash[:notice] = "Account updated!"
|
||||
redirect_to account_path
|
||||
else
|
||||
render :action => :edit
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@user = @current_user
|
||||
if @user.destroy
|
||||
redirect_to users_path
|
||||
else
|
||||
redirect_to @user
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,10 +0,0 @@
|
|||
module AlbumsHelper
|
||||
def new_upload_path_with_session_information
|
||||
session_key = self.get_session_key
|
||||
photos_path(session_key => cookies[session_key], request_forgery_protection_token => form_authenticity_token)
|
||||
end
|
||||
|
||||
def get_session_key
|
||||
Rails.application.config.session_options[:key]
|
||||
end
|
||||
end
|
|
@ -1,34 +0,0 @@
|
|||
# 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('li', (content_tag('a', t(:home_page), :href => root_path ) if include_home))
|
||||
|
||||
nocrumb = ["collections", "albums", "photos", "tags", "new", "edit", "tags"]
|
||||
|
||||
levels.each_with_index do |level, index|
|
||||
level = level.gsub(/^[0-9]+\-/,"") #if levels[index-1] == "photos"
|
||||
level = level.gsub("-", " ")
|
||||
if index+1 == levels.length
|
||||
#links += " #{sep} #{level.upcase}" unless nocrumb.include?(level)
|
||||
#elsif !nocrumb.include?(level)
|
||||
links += " " + sep + " "
|
||||
links += content_tag('li', content_tag('a', level, :href => '/'+levels[0..index].join('/')))
|
||||
end
|
||||
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
|
|
@ -1,2 +0,0 @@
|
|||
module HomeHelper
|
||||
end
|
|
@ -1,3 +0,0 @@
|
|||
module UsersHelper
|
||||
|
||||
end
|
|
@ -1,18 +0,0 @@
|
|||
require 'rack/utils'
|
||||
|
||||
class FlashSessionCookieMiddleware
|
||||
def initialize(app, session_key = '_session_id')
|
||||
@app = app
|
||||
@session_key = session_key
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/
|
||||
req = Rack::Request.new(env)
|
||||
env['HTTP_COOKIE'] = [ @session_key,
|
||||
req.params[@session_key] ].join('=').freeze unless req.params[@session_key].nil?
|
||||
env['HTTP_ACCEPT'] = "#{req.params['_http_accept']}".freeze unless req.params['_http_accept'].nil?
|
||||
end
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
|
@ -1,63 +0,0 @@
|
|||
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
|
|
@ -1,107 +0,0 @@
|
|||
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
|
||||
|
||||
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
|
||||
}
|
||||
return tags
|
||||
end
|
||||
|
||||
def tags=(tags)
|
||||
tags = tags.split(" ").sort
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
# add universial tags to all photos in album
|
||||
(tags - current_tags).each do |tag|
|
||||
self.photos.each { |photo|
|
||||
photo.tag(tag)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def photo_tags
|
||||
tags = Array.new
|
||||
self.photos.each { |photo|
|
||||
tags = tags | photo.tags
|
||||
}
|
||||
return tags
|
||||
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 )
|
||||
#Dir.delete( APP_CONFIG[:thumbs_path] + self.path ) if File.exists?( APP_CONFIG[:thumbs_path] + self.path )
|
||||
end
|
||||
end
|
|
@ -1,27 +0,0 @@
|
|||
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
|
||||
|
||||
def album_list=(albums)
|
||||
self.albums = Album.find(albums.map{|album|album[0]})
|
||||
end
|
||||
|
||||
end
|
|
@ -1,4 +0,0 @@
|
|||
class CollectionAlbum < ActiveRecord::Base
|
||||
belongs_to :album
|
||||
belongs_to :collection
|
||||
end
|
|
@ -1,90 +0,0 @@
|
|||
class Photo < ActiveRecord::Base
|
||||
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 :attachment, FileUploader
|
||||
|
||||
before_create :exif_read
|
||||
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"} }
|
||||
|
||||
def to_param
|
||||
"#{id}-#{title.parameterize}"
|
||||
end
|
||||
|
||||
def tag(title)
|
||||
return if self.tags.collect{|tag|tag.title}.include?( title )
|
||||
self.photo_tags.create(:tag => Tag.find_or_create_by_title( :title => title) )
|
||||
self.reload
|
||||
end
|
||||
|
||||
def untag(title)
|
||||
return if !self.tags.collect{|tag|tag.title}.include?( title )
|
||||
# perhaps not the best way but it finds the correct PhotoTag and deletes it
|
||||
self.photo_tags.select{|photo_tag|
|
||||
photo_tag.tag.title == title
|
||||
}.each {|photo_tag|photo_tag.destroy}
|
||||
self.reload
|
||||
end
|
||||
|
||||
def tag_list
|
||||
return self.tags.order('title').map{ |t| t.title }.sort.join(" ")
|
||||
end
|
||||
|
||||
def tag_list=(tags)
|
||||
ts = Array.new
|
||||
tags.split(" ").each do |tag|
|
||||
ts.push( Tag.find_or_create_by_title( :title => tag.downcase) )
|
||||
end
|
||||
self.tags = ts
|
||||
end
|
||||
|
||||
def _delete
|
||||
0
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def set_visible
|
||||
update_attribute(:public, true) unless self.public
|
||||
end
|
||||
|
||||
def set_title
|
||||
update_attribute(:title, self.attachment.file.basename.titleize) unless self.title
|
||||
end
|
||||
|
||||
def exif_read
|
||||
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?
|
||||
self.description = photo.ImageDescription if self.description.nil? && photo.ImageDescription != 'Exif_JPEG_PICTURE'
|
||||
self.tag_list = (self.tags.empty? ? "" : self.album.tag_list) + " " + (photo.Keywords.nil? ? "" : photo.Keywords.to_a.map { |tag| tag.gsub(" ", "_") }.join(" "))
|
||||
end
|
||||
|
||||
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.attachment.file.file)
|
||||
photo.GPSLongitude = self.longitude
|
||||
photo.GPSLatitude = self.latitude
|
||||
photo.DocumentName = self.title
|
||||
photo.ImageDescription = self.description
|
||||
photo.Keywords = self.tags
|
||||
photo.save
|
||||
end
|
||||
|
||||
end
|
|
@ -1,4 +0,0 @@
|
|||
class PhotoTag < ActiveRecord::Base
|
||||
belongs_to :tag
|
||||
belongs_to :photo
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
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
|
|
@ -1,5 +0,0 @@
|
|||
class Role < ActiveRecord::Base
|
||||
attr_accessible :name
|
||||
|
||||
has_and_belongs_to_many :users
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
class SecretLinkObserver < ActiveRecord::Observer
|
||||
observe :collection, :album, :photo
|
||||
|
||||
def before_create(record)
|
||||
record.url = ::SecureRandom.hex(16)
|
||||
end
|
||||
end
|
|
@ -1,23 +0,0 @@
|
|||
class Tag < ActiveRecord::Base
|
||||
has_many :photo_tags, :dependent => :destroy
|
||||
has_many :photos, :through => :photo_tags
|
||||
|
||||
validates_uniqueness_of :title
|
||||
|
||||
before_validation :downcase_title
|
||||
|
||||
def self.tag_list
|
||||
return self.find(:all).map { |tag| tag.title }.join('\',\'')
|
||||
end
|
||||
|
||||
def to_param
|
||||
title.parameterize
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def downcase_title
|
||||
self.title.downcase! if attribute_present?("title")
|
||||
end
|
||||
|
||||
end
|
|
@ -1,45 +0,0 @@
|
|||
class User < ActiveRecord::Base
|
||||
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
|
|
@ -1,98 +0,0 @@
|
|||
# encoding: utf-8
|
||||
|
||||
class FileUploader < CarrierWave::Uploader::Base
|
||||
|
||||
@@generate_file_name = ''
|
||||
@@original_filename = ''
|
||||
|
||||
|
||||
# Include RMagick or ImageScience support
|
||||
# include CarrierWave::RMagick
|
||||
# include CarrierWave::ImageScience
|
||||
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
|
||||
else
|
||||
storage :file
|
||||
end
|
||||
|
||||
# Override the directory where uploaded files will be stored
|
||||
# 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}/#{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
|
||||
# def default_url
|
||||
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
|
||||
# end
|
||||
|
||||
# Process files as they are uploaded.
|
||||
# process :scale => [200, 300]
|
||||
#
|
||||
# def scale(width, height)
|
||||
# # do something
|
||||
# end
|
||||
|
||||
# Create different versions of your uploaded files
|
||||
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
|
||||
end
|
|
@ -1,28 +0,0 @@
|
|||
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
|
|
@ -1 +0,0 @@
|
|||
<p><%= render :partial => "photos/thumb", :locals => { :photo => album.photos.find(:first), :photosize => 'collection' } unless album.photos.empty? %></p>
|
|
@ -1,63 +0,0 @@
|
|||
<%= content_for :javascript do %>
|
||||
<%= javascript_include_tag "http://maps.google.com/maps/api/js?sensor=true" -%>
|
||||
<%= javascript_include_tag "tag/tag" -%>
|
||||
<% end %>
|
||||
|
||||
<div id="map_canvas"></div>
|
||||
|
||||
<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 %>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
<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>
|
|
@ -1,28 +0,0 @@
|
|||
<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>
|
|
@ -1,17 +0,0 @@
|
|||
<h1>Edit Album</h1>
|
||||
|
||||
<%= form_for @album do |f| %>
|
||||
<%= f.error_messages %>
|
||||
<%= render :partial => "form", :object => f %>
|
||||
<%= f.submit "Update" %>
|
||||
<% end %>
|
||||
|
||||
|
||||
<%= content_for :action_links do %>
|
||||
<% if has_role?("admin") %>
|
||||
|
||||
<%= link_to("Delete album", { :action => "destroy", :id => @album, :collection_id => params[:collection_id] },
|
||||
:confirm => "Are you sure you want to delete this album?",
|
||||
:method => :delete) %>
|
||||
<% end %>
|
||||
<% end %>
|
|
@ -1,11 +0,0 @@
|
|||
<%= 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 current_user and current_user.has_role?("admin") %>
|
||||
<%= " | " if params[:q] %>
|
||||
<%= link_to "New album", new_album_path() %>
|
||||
<% end %>
|
||||
<% end %>
|
|
@ -1,9 +0,0 @@
|
|||
<%= 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 %>
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
<h2><%= @album.title %></h2>
|
||||
<%= 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>
|
||||
<% end %>
|
||||
|
||||
<% unless @album.collections.empty? %>
|
||||
<p>Part of:
|
||||
<% for collection in @album.collections.order('title') %>
|
||||
<%= link_to collection.title, collection_path(collection) %>
|
||||
<% end %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
|
||||
<% if current_user and current_user.has_role?("admin") %>
|
||||
<p><%= @album.address %></p>
|
||||
<p><%= @album.note %></p>
|
||||
<% end %>
|
||||
|
||||
|
||||
|
||||
<%= content_for :action_links do %>
|
||||
<% 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 %>
|
|
@ -1,3 +0,0 @@
|
|||
<h1><%= @album.title %></h1>
|
||||
|
||||
<%= render :partial => @album.photos %>
|
|
@ -1,11 +0,0 @@
|
|||
<% 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 %>
|
|
@ -1,49 +0,0 @@
|
|||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<% 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 %>
|
||||
|
||||
<%
|
||||
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>
|
|
@ -1,29 +0,0 @@
|
|||
<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>
|
|
@ -1,13 +0,0 @@
|
|||
<h1>Edit collection</h1>
|
||||
|
||||
<%= form_for @collection do |f| %>
|
||||
<%= f.error_messages %>
|
||||
<%= render :partial => "form", :object => f %>
|
||||
<%= f.submit "Update" %>
|
||||
<% end %>
|
||||
|
||||
<%= content_for :action_links do %>
|
||||
<%= link_to("Delete this collection", { :action => "destroy", :id => @collection },
|
||||
:confirm => "Are you sure you want to delete this collection?",
|
||||
:method => :delete) %>
|
||||
<% end %>
|
|
@ -1,6 +0,0 @@
|
|||
<h1><%= t('activerecord.models.collection.pluralize') %></h1>
|
||||
<%= paginate @collections %>
|
||||
<%= render 'row_collections' %>
|
||||
<%= paginate @collections %>
|
||||
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
<%= 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 %>
|
||||
<div class="form-actions">
|
||||
<%= f.button "Create", :class => 'btn btn-primary btn-large' %>
|
||||
</div>
|
||||
<% end %>
|
|
@ -1,12 +0,0 @@
|
|||
<h2><%= @collection.title %></h2>
|
||||
<p><%= @collection.description %></p>
|
||||
|
||||
<%= render :partial => 'albums/row_collections' %>
|
||||
|
||||
<%= content_for :action_links do %>
|
||||
<% 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 %>
|
|
@ -1,8 +0,0 @@
|
|||
<h2><%= h @collection.title %></h2>
|
||||
<p><%= h @collection.description %></p>
|
||||
|
||||
<% for album in @collection.albums %>
|
||||
<h3><%= album.title %></h3>
|
||||
<p><%= render :partial => album.photos %></p>
|
||||
|
||||
<% end %>
|
|
@ -1,24 +0,0 @@
|
|||
<%- 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 -%>
|
|
@ -1,12 +0,0 @@
|
|||
<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" %>
|
|
@ -1,5 +0,0 @@
|
|||
<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>
|
|
@ -1,8 +0,0 @@
|
|||
<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>
|
|
@ -1,7 +0,0 @@
|
|||
<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>
|
|
@ -1,16 +0,0 @@
|
|||
<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" %>
|
|
@ -1,12 +0,0 @@
|
|||
<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" %>
|
|
@ -1,25 +0,0 @@
|
|||
<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 %>
|
|
@ -1,18 +0,0 @@
|
|||
<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" %>
|
|
@ -1,17 +0,0 @@
|
|||
<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" %>
|
|
@ -1,12 +0,0 @@
|
|||
<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" %>
|
|
@ -1,5 +0,0 @@
|
|||
<div class="row">
|
||||
<%= render 'shared/home_slider' %>
|
||||
</div>
|
||||
<h2><%= t('activerecord.models.collection.popular') %></h2>
|
||||
<%= render :partial => 'collections/row_collections' %>
|
|
@ -1,13 +0,0 @@
|
|||
<%# 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 %>
|
|
@ -1,8 +0,0 @@
|
|||
<%# 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>
|
|
@ -1,13 +0,0 @@
|
|||
<%# 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 %>
|
|
@ -1,13 +0,0 @@
|
|||
<%# 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 %>
|
|
@ -1,12 +0,0 @@
|
|||
<%# 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>
|
|
@ -1,25 +0,0 @@
|
|||
<%# 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 -%>
|
|
@ -1,13 +0,0 @@
|
|||
<%# 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 %>
|
|
@ -1,42 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<%= render :partial => 'shared/head' %>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="header">
|
||||
<div id="action_links">
|
||||
<%= yield :action_links %>
|
||||
<% if current_user %>
|
||||
Logged in as <%= current_user.name %>
|
||||
<%= link_to 'Logout', logout_path %>
|
||||
<% end %>
|
||||
</div>
|
||||
<h1>
|
||||
<%= link_to(if ENV['LOGO'] then image_tag(ENV['LOGO']) else (ENV['TITLE'] || "Photos") end, root_path) %>
|
||||
</h1>
|
||||
<%= form_tag albums_path, { :id => :search } do -%>
|
||||
<input type="text" name="q" class="textfield"/>
|
||||
<input type="submit" value="Search" class="button" />
|
||||
<% end -%>
|
||||
<hr class="seperator" />
|
||||
<%= breadcrumbs %>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<p id="notice"><%= flash[:notice] %></p>
|
||||
<%= yield %>
|
||||
</div>
|
||||
|
||||
<div id="footer">
|
||||
|
||||
<hr class="seperator" />
|
||||
© <a href="http://balderapp.com">Balder - open source photo gallery</a>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,22 +0,0 @@
|
|||
<!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>© Photomix 2012</p>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||
<%= content_for :javascript do %>
|
||||
<%= javascript_include_tag "tag/tag" -%>
|
||||
<% end %>
|
||||
<%= hidden_field_tag :all_tags, @tags %>
|
||||
<%= form.label :title %><br />
|
||||
<%= form.text_field :title %><br />
|
||||
<br/>
|
||||
<%= form.label :tag_list %><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.attachment.path %></p>
|
|
@ -1 +0,0 @@
|
|||
<%= image_tag photo.attachment.single.url %><br/>
|
|
@ -1,22 +0,0 @@
|
|||
<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>
|
|
@ -1 +0,0 @@
|
|||
<%= link_to image_tag(eval('photo.attachment.' + (defined?(photosize) ? photosize : "thumb") + '.url')), [photo.album.collections.first, photo.album, photo] %>
|
|
@ -1,17 +0,0 @@
|
|||
<h1>Edit Photo</h1>
|
||||
|
||||
<%= 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" %>
|
||||
<% 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) %>
|
||||
<% end %>
|
|
@ -1,15 +0,0 @@
|
|||
<%= 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 %>
|
|
@ -1,9 +0,0 @@
|
|||
<%#= 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] %>
|
||||
<% end %>
|
|
@ -1,34 +0,0 @@
|
|||
<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.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 %>
|
||||
|
||||
<%= 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 %>
|
|
@ -1,12 +0,0 @@
|
|||
<%= 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 %>
|
|
@ -1,78 +0,0 @@
|
|||
<%= content_for :javascript do %>
|
||||
<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 %>"
|
||||
},
|
||||
|
||||
// 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"}
|
||||
],
|
||||
|
||||
// Flash settings
|
||||
flash_swf_url:'/assets/plupload.flash.swf',
|
||||
|
||||
// Silverlight settings
|
||||
silverlight_xap_url:'/assets/plupload.silverlight.xap',
|
||||
|
||||
// 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')
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 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>
|
||||
<% end %>
|
||||
|
||||
<form>
|
||||
<div id="uploader">
|
||||
<p>You browser doesn't have Flash, Silverlight, Gears, BrowserPlus or HTML5 support.</p>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div id="thumbs"></div>
|
||||
</form>
|
||||
|
||||
<br><%= link_to "Edit uploaded photos", untouched_album_photos_path(@album) %>
|
||||
<br><%= link_to "Back to #{@album.title}", @album %>
|
|
@ -1,40 +0,0 @@
|
|||
<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 %>
|