the BIG MERGE is now done

This commit is contained in:
did 2011-07-04 15:43:05 +02:00
commit 91f2f145b3
251 changed files with 4242 additions and 2266 deletions

36
Gemfile
View File

@ -2,28 +2,32 @@ source :rubygems
# add in all the runtime dependencies # add in all the runtime dependencies
gem 'rake', '0.8.7' gem 'rake', '0.9.2'
gem 'rails', '3.0.7' gem 'rails', '3.0.9'
gem 'warden' gem 'warden'
gem 'devise', '= 1.1.3' gem 'devise', '1.3.4'
gem 'mongoid', '~> 2.0.2' gem 'mongoid', '~> 2.0.2'
gem 'bson_ext', '~> 1.3.0' gem 'bson_ext', '~> 1.3.0'
gem 'locomotive_mongoid_acts_as_tree', '0.1.5.7', :require => 'mongoid_acts_as_tree' gem 'locomotive_mongoid_acts_as_tree', '0.1.5.7', :require => 'mongoid_acts_as_tree'
gem 'will_paginate' gem 'will_paginate'
gem 'haml', '3.0.25' gem 'haml', '3.1.2'
gem 'sass', '3.1.2'
gem 'locomotive_liquid', '2.2.2', :require => 'liquid' gem 'locomotive_liquid', '2.2.2', :require => 'liquid'
gem 'formtastic', '~> 1.2.3' gem 'formtastic', '~> 1.2.3'
gem 'inherited_resources', '~> 1.1.2' gem 'inherited_resources', '~> 1.1.2'
gem 'rmagick', '2.12.2' gem 'rmagick', '2.12.2'
gem 'locomotive_carrierwave', '0.5.0.1.beta3', :require => 'carrierwave' gem 'locomotive_carrierwave', '0.5.4.beta3'
gem 'dragonfly', '~> 0.9.1'
gem 'rack-cache', :require => 'rack/cache'
gem 'custom_fields', '1.0.0.beta.15' gem 'custom_fields', '1.0.0.beta.21'
gem 'fog', '0.3.7' gem 'cancan'
gem 'fog', '0.8.2'
gem 'mimetype-fu' gem 'mimetype-fu'
gem 'actionmailer-with-request', :require => 'actionmailer_with_request' gem 'actionmailer-with-request', :require => 'actionmailer_with_request'
gem 'heroku', '1.19.1' gem 'heroku', '1.19.1'
@ -38,30 +42,32 @@ gem 'SystemTimer', :platforms => :ruby_18
# The rest of the dependencies are for use when in the locomotive dev environment # The rest of the dependencies are for use when in the locomotive dev environment
group :development do group :development do
# Using unicorn_rails instead of webrick (default server) gem 'unicorn' # Using unicorn_rails instead of webrick (default server)
gem 'unicorn'
gem 'rspec-rails', '2.6.1' # in order to have rspec tasks and generators
end end
group :development, :test do group :test, :development do
gem 'linecache', '0.43', :platforms => :mri_18
gem 'ruby-debug', :platforms => :mri_18 gem 'ruby-debug', :platforms => :mri_18
gem 'ruby-debug19', :platforms => :mri_19 gem 'ruby-debug19', :platforms => :mri_19
gem 'bushido_stub', :git => 'git://github.com/did/bushido_stub.git' gem 'bushido_stub', :git => 'git://github.com/did/bushido_stub.git'
gem 'cucumber-rails', '1.0.2'
end end
group :test do group :test do
gem 'autotest' gem 'autotest'
gem 'ZenTest' gem 'ZenTest'
gem 'growl-glue' gem 'growl-glue'
gem 'rspec-rails', '2.3.1' gem 'rspec-rails', '2.6.1'
gem 'factory_girl_rails' gem 'factory_girl_rails'
gem 'pickle' gem 'pickle'
gem 'xpath', '0.1.3' gem 'xpath', '~> 0.1.4'
gem 'capybara' gem 'capybara'
gem 'database_cleaner' gem 'database_cleaner'
gem 'cucumber', '0.8.5'
gem 'cucumber-rails'
gem 'spork' gem 'spork'
gem 'launchy' gem 'launchy'
gem 'mocha', :git => 'git://github.com/floehopper/mocha.git' gem 'mocha', :git => 'git://github.com/floehopper/mocha.git'

View File

@ -22,14 +22,14 @@ GEM
SystemTimer (1.2.3) SystemTimer (1.2.3)
ZenTest (4.5.0) ZenTest (4.5.0)
abstract (1.0.0) abstract (1.0.0)
actionmailer (3.0.7) actionmailer (3.0.9)
actionpack (= 3.0.7) actionpack (= 3.0.9)
mail (~> 2.2.15) mail (~> 2.2.19)
actionmailer-with-request (0.3.0) actionmailer-with-request (0.3.0)
rails (>= 3) rails (>= 3)
actionpack (3.0.7) actionpack (3.0.9)
activemodel (= 3.0.7) activemodel (= 3.0.9)
activesupport (= 3.0.7) activesupport (= 3.0.9)
builder (~> 2.1.2) builder (~> 2.1.2)
erubis (~> 2.6.6) erubis (~> 2.6.6)
i18n (~> 0.5.0) i18n (~> 0.5.0)
@ -37,19 +37,19 @@ GEM
rack-mount (~> 0.6.14) rack-mount (~> 0.6.14)
rack-test (~> 0.5.7) rack-test (~> 0.5.7)
tzinfo (~> 0.3.23) tzinfo (~> 0.3.23)
activemodel (3.0.7) activemodel (3.0.9)
activesupport (= 3.0.7) activesupport (= 3.0.9)
builder (~> 2.1.2) builder (~> 2.1.2)
i18n (~> 0.5.0) i18n (~> 0.5.0)
activerecord (3.0.7) activerecord (3.0.9)
activemodel (= 3.0.7) activemodel (= 3.0.9)
activesupport (= 3.0.7) activesupport (= 3.0.9)
arel (~> 2.0.2) arel (~> 2.0.10)
tzinfo (~> 0.3.23) tzinfo (~> 0.3.23)
activeresource (3.0.7) activeresource (3.0.9)
activemodel (= 3.0.7) activemodel (= 3.0.9)
activesupport (= 3.0.7) activesupport (= 3.0.9)
activesupport (3.0.7) activesupport (3.0.9)
archive-tar-minitar (0.5.2) archive-tar-minitar (0.5.2)
arel (2.0.10) arel (2.0.10)
autotest (4.4.6) autotest (4.4.6)
@ -62,33 +62,31 @@ GEM
highline (>= 1.6.1) highline (>= 1.6.1)
json (>= 1.4.6) json (>= 1.4.6)
rest-client (>= 1.6.1) rest-client (>= 1.6.1)
capybara (0.4.1.2) cancan (1.6.5)
celerity (>= 0.7.9) capybara (1.0.0)
culerity (>= 0.2.4)
mime-types (>= 1.16) mime-types (>= 1.16)
nokogiri (>= 1.3.3) nokogiri (>= 1.3.3)
rack (>= 1.0.0) rack (>= 1.0.0)
rack-test (>= 0.5.4) rack-test (>= 0.5.4)
selenium-webdriver (>= 0.0.27) selenium-webdriver (~> 0.2.0)
xpath (~> 0.1.3) xpath (~> 0.1.4)
celerity (0.8.9)
childprocess (0.1.9) childprocess (0.1.9)
ffi (~> 1.0.6) ffi (~> 1.0.6)
columnize (0.3.3) columnize (0.3.3)
configuration (1.3.1) configuration (1.3.1)
crack (0.1.8) crack (0.1.8)
cucumber (0.8.5) cucumber (1.0.0)
builder (~> 2.1.2) builder (>= 2.1.2)
diff-lcs (~> 1.1.2) diff-lcs (>= 1.1.2)
gherkin (~> 2.1.4) gherkin (~> 2.4.1)
json_pure (~> 1.4.3) json (>= 1.4.6)
term-ansicolor (~> 1.0.4) term-ansicolor (>= 1.0.5)
cucumber-rails (0.3.2) cucumber-rails (1.0.2)
cucumber (>= 0.8.0) capybara (>= 1.0.0)
culerity (0.2.15) cucumber (~> 1.0.0)
custom_fields (1.0.0.beta.15) nokogiri (>= 1.4.6)
activesupport (>= 3.0.7) custom_fields (1.0.0.beta.21)
locomotive_carrierwave activesupport (~> 3.0.9)
mongoid (= 2.0.2) mongoid (= 2.0.2)
daemons (1.1.4) daemons (1.1.4)
database_cleaner (0.6.7) database_cleaner (0.6.7)
@ -98,10 +96,13 @@ GEM
delayed_job_mongoid (1.0.2) delayed_job_mongoid (1.0.2)
delayed_job (~> 2.1.1) delayed_job (~> 2.1.1)
mongoid (~> 2.0.0.rc) mongoid (~> 2.0.0.rc)
devise (1.1.3) devise (1.3.4)
bcrypt-ruby (~> 2.1.2) bcrypt-ruby (~> 2.1.2)
warden (~> 0.10.7) orm_adapter (~> 0.0.3)
warden (~> 1.0.3)
diff-lcs (1.1.2) diff-lcs (1.1.2)
dragonfly (0.9.4)
rack
erubis (2.6.6) erubis (2.6.6)
abstract (>= 1.0.0) abstract (>= 1.0.0)
excon (0.6.3) excon (0.6.3)
@ -110,29 +111,29 @@ GEM
factory_girl (~> 1.3) factory_girl (~> 1.3)
railties (>= 3.0.0) railties (>= 3.0.0)
ffi (1.0.9) ffi (1.0.9)
fog (0.3.7) fog (0.8.2)
builder builder
excon (>= 0.2.3) excon (~> 0.6.1)
formatador (>= 0.0.15) formatador (>= 0.1.3)
json json
mime-types mime-types
net-ssh (~> 2.0.23) net-ssh (>= 2.1.3)
nokogiri (~> 1.4.3.1) nokogiri (>= 1.4.4)
ruby-hmac ruby-hmac
formatador (0.1.4) formatador (0.1.4)
formtastic (1.2.4) formtastic (1.2.4)
actionpack (>= 2.3.7) actionpack (>= 2.3.7)
activesupport (>= 2.3.7) activesupport (>= 2.3.7)
i18n (~> 0.4) i18n (~> 0.4)
gherkin (2.1.5) gherkin (2.4.1)
trollop (~> 1.16.2) json (>= 1.4.6)
growl-glue (1.0.7) growl-glue (1.0.7)
haml (3.0.25) haml (3.1.2)
has_scope (0.5.0) has_scope (0.5.0)
heroku (1.19.1) heroku (1.19.1)
activesupport (>= 2.1.0) activesupport (>= 2.1.0)
launchy (~> 0.3.2) launchy (~> 0.3.2)
rest-client (>= 1.4.0, < 1.7.0) rest-client (< 1.7.0, >= 1.4.0)
highline (1.6.2) highline (1.6.2)
httparty (0.7.8) httparty (0.7.8)
crack (= 0.1.8) crack (= 0.1.8)
@ -143,16 +144,15 @@ GEM
jammit (0.6.3) jammit (0.6.3)
yui-compressor (>= 0.9.3) yui-compressor (>= 0.9.3)
json (1.5.3) json (1.5.3)
json_pure (1.4.6) json_pure (1.5.3)
kgio (2.5.0) kgio (2.5.0)
launchy (0.3.7) launchy (0.3.7)
configuration (>= 0.0.5) configuration (>= 0.0.5)
rake (>= 0.8.1) rake (>= 0.8.1)
linecache (0.46) linecache (0.43)
rbx-require-relative (> 0.0.4)
linecache19 (0.5.12) linecache19 (0.5.12)
ruby_core_source (>= 0.1.4) ruby_core_source (>= 0.1.4)
locomotive_carrierwave (0.5.0.1.beta3) locomotive_carrierwave (0.5.4.beta3)
activesupport (~> 3.0) activesupport (~> 3.0)
locomotive_jammit-s3 (0.5.4.4) locomotive_jammit-s3 (0.5.4.4)
jammit (>= 0.5.4) jammit (>= 0.5.4)
@ -175,51 +175,56 @@ GEM
activemodel (~> 3.0) activemodel (~> 3.0)
mongo (~> 1.3) mongo (~> 1.3)
tzinfo (~> 0.3.22) tzinfo (~> 0.3.22)
net-ssh (2.0.24) net-ssh (2.1.4)
nokogiri (1.4.3.1) nokogiri (1.5.0)
open4 (1.0.1) open4 (1.1.0)
orm_adapter (0.0.5)
pickle (0.4.7) pickle (0.4.7)
cucumber (>= 0.8) cucumber (>= 0.8)
rake rake
polyglot (0.3.1) polyglot (0.3.1)
proxies (0.2.1) proxies (0.2.1)
rack (1.2.3) rack (1.2.3)
rack-cache (1.0.2)
rack (>= 0.4)
rack-mount (0.6.14) rack-mount (0.6.14)
rack (>= 1.0.0) rack (>= 1.0.0)
rack-test (0.5.7) rack-test (0.5.7)
rack (>= 1.0) rack (>= 1.0)
rails (3.0.7) rails (3.0.9)
actionmailer (= 3.0.7) actionmailer (= 3.0.9)
actionpack (= 3.0.7) actionpack (= 3.0.9)
activerecord (= 3.0.7) activerecord (= 3.0.9)
activeresource (= 3.0.7) activeresource (= 3.0.9)
activesupport (= 3.0.7) activesupport (= 3.0.9)
bundler (~> 1.0) bundler (~> 1.0)
railties (= 3.0.7) railties (= 3.0.9)
railties (3.0.7) railties (3.0.9)
actionpack (= 3.0.7) actionpack (= 3.0.9)
activesupport (= 3.0.7) activesupport (= 3.0.9)
rake (>= 0.8.7) rake (>= 0.8.7)
rdoc (~> 3.4)
thor (~> 0.14.4) thor (~> 0.14.4)
rake (0.8.7) raindrops (0.7.0)
rbx-require-relative (0.0.5) rake (0.9.2)
rdoc (3.8)
responders (0.6.4) responders (0.6.4)
rest-client (1.6.3) rest-client (1.6.3)
mime-types (>= 1.16) mime-types (>= 1.16)
rmagick (2.12.2) rmagick (2.12.2)
rspec (2.3.0) rspec (2.6.0)
rspec-core (~> 2.3.0) rspec-core (~> 2.6.0)
rspec-expectations (~> 2.3.0) rspec-expectations (~> 2.6.0)
rspec-mocks (~> 2.3.0) rspec-mocks (~> 2.6.0)
rspec-core (2.3.1) rspec-core (2.6.4)
rspec-expectations (2.3.0) rspec-expectations (2.6.0)
diff-lcs (~> 1.1.2) diff-lcs (~> 1.1.2)
rspec-mocks (2.3.0) rspec-mocks (2.6.0)
rspec-rails (2.3.1) rspec-rails (2.6.1)
actionpack (~> 3.0) actionpack (~> 3.0)
activesupport (~> 3.0) activesupport (~> 3.0)
railties (~> 3.0) railties (~> 3.0)
rspec (~> 2.3.0) rspec (~> 2.6.0)
ruby-debug (0.10.4) ruby-debug (0.10.4)
columnize (>= 0.1) columnize (>= 0.1)
ruby-debug-base (~> 0.10.4.0) ruby-debug-base (~> 0.10.4.0)
@ -239,6 +244,7 @@ GEM
rubyzip (0.9.4) rubyzip (0.9.4)
s3 (0.3.8) s3 (0.3.8)
proxies (~> 0.2.0) proxies (~> 0.2.0)
sass (3.1.2)
selenium-webdriver (0.2.2) selenium-webdriver (0.2.2)
childprocess (>= 0.1.9) childprocess (>= 0.1.9)
ffi (>= 1.0.7) ffi (>= 1.0.7)
@ -249,15 +255,15 @@ GEM
thor (0.14.6) thor (0.14.6)
treetop (1.4.9) treetop (1.4.9)
polyglot (>= 0.3.1) polyglot (>= 0.3.1)
trollop (1.16.2) tzinfo (0.3.29)
tzinfo (0.3.28) unicorn (4.0.1)
unicorn (3.7.0) kgio (~> 2.4)
kgio (~> 2.3)
rack rack
warden (0.10.7) raindrops (~> 0.6)
rack (>= 1.0.0) warden (1.0.4)
rack (>= 1.0)
will_paginate (2.3.15) will_paginate (2.3.15)
xpath (0.1.3) xpath (0.1.4)
nokogiri (~> 1.3) nokogiri (~> 1.3)
yui-compressor (0.9.6) yui-compressor (0.9.6)
POpen4 (>= 0.1.4) POpen4 (>= 0.1.4)
@ -274,24 +280,26 @@ DEPENDENCIES
bson_ext (~> 1.3.0) bson_ext (~> 1.3.0)
bushido bushido
bushido_stub! bushido_stub!
cancan
capybara capybara
cucumber (= 0.8.5) cucumber-rails (= 1.0.2)
cucumber-rails custom_fields (= 1.0.0.beta.21)
custom_fields (= 1.0.0.beta.15)
database_cleaner database_cleaner
delayed_job (= 2.1.4) delayed_job (= 2.1.4)
delayed_job_mongoid (= 1.0.2) delayed_job_mongoid (= 1.0.2)
devise (= 1.1.3) devise (= 1.3.4)
dragonfly (~> 0.9.1)
factory_girl_rails factory_girl_rails
fog (= 0.3.7) fog (= 0.8.2)
formtastic (~> 1.2.3) formtastic (~> 1.2.3)
growl-glue growl-glue
haml (= 3.0.25) haml (= 3.1.2)
heroku (= 1.19.1) heroku (= 1.19.1)
httparty (>= 0.6.1) httparty (>= 0.6.1)
inherited_resources (~> 1.1.2) inherited_resources (~> 1.1.2)
launchy launchy
locomotive_carrierwave (= 0.5.0.1.beta3) linecache (= 0.43)
locomotive_carrierwave (= 0.5.4.beta3)
locomotive_jammit-s3 locomotive_jammit-s3
locomotive_liquid (= 2.2.2) locomotive_liquid (= 2.2.2)
locomotive_mongoid_acts_as_tree (= 0.1.5.7) locomotive_mongoid_acts_as_tree (= 0.1.5.7)
@ -299,15 +307,17 @@ DEPENDENCIES
mocha! mocha!
mongoid (~> 2.0.2) mongoid (~> 2.0.2)
pickle pickle
rails (= 3.0.7) rack-cache
rake (= 0.8.7) rails (= 3.0.9)
rake (= 0.9.2)
rmagick (= 2.12.2) rmagick (= 2.12.2)
rspec-rails (= 2.3.1) rspec-rails (= 2.6.1)
ruby-debug ruby-debug
ruby-debug19 ruby-debug19
rubyzip rubyzip
sass (= 3.1.2)
spork spork
unicorn unicorn
warden warden
will_paginate will_paginate
xpath (= 0.1.3) xpath (~> 0.1.4)

View File

@ -19,7 +19,7 @@ h2. Gems
Here is a short list of main gems used in the application. Here is a short list of main gems used in the application.
* Rails 3.0.7 * Rails 3.0.9
* Mongoid 2.0.2 (with MongoDB 1.6) * Mongoid 2.0.2 (with MongoDB 1.6)
* Liquid * Liquid
* Devise * Devise

View File

@ -1,20 +1,21 @@
require File.expand_path('../config/application', __FILE__) require File.expand_path('../config/application', __FILE__)
require 'rubygems'
require 'rake' require 'rake'
# require 'rake/testtask' require 'rdoc/task'
require 'rake/rdoctask' require 'rubygems/package_task'
require 'rake/gempackagetask'
Locomotive::Application.load_tasks Locomotive::Application.load_tasks
gemspec = eval(File.read('locomotive_cms.gemspec')) gemspec = eval(File.read('locomotive_cms.gemspec'))
Rake::GemPackageTask.new(gemspec) do |pkg| Gem::PackageTask.new(gemspec) do |pkg|
pkg.gem_spec = gemspec pkg.gem_spec = gemspec
end end
desc "build the gem and release it to rubygems.org" desc 'build the gem and release it to rubygems.org'
task :release => :gem do task :release => :gem do
sh "gem push pkg/locomotive_cms-#{gemspec.version}.gem" sh "gem push pkg/custom_fields-#{gemspec.version}.gem"
end end
task :default => [:rspec, :cucumber] task :default => [:spec, :cucumber]

View File

@ -1,25 +0,0 @@
module Admin
class AssetCollectionsController < BaseController
sections 'assets'
before_filter :set_collections
def index
if not @asset_collections.empty?
redirect_to(edit_admin_asset_collection_url(@asset_collections.first)) and return
end
end
def show
@asset_collection = current_site.asset_collections.find(params[:id])
render :action => 'edit'
end
protected
def set_collections
@asset_collections = current_site.asset_collections.not_internal.order_by([[:name, :asc]])
end
end
end

View File

@ -1,29 +1,55 @@
module Admin module Admin
class AssetsController < BaseController class AssetsController < BaseController
sections 'assets' include ActionView::Helpers::SanitizeHelper
include ActionView::Helpers::TextHelper
before_filter :set_collections_and_current_collection respond_to :json, :only => [:index, :create, :destroy]
respond_to :json, :only => :update def index
index! do |response|
def create response.json do
create! { edit_admin_asset_collection_url(@asset_collection) } render :json => { :assets => @assets.collect { |asset| asset_to_json(asset) } }
end
end
end end
def update def create
update! { edit_admin_asset_collection_url(@asset_collection) } @asset = current_site.assets.build(:name => params[:name], :source => params[:file])
create! do |success, failure|
success.json do
render :json => asset_to_json(@asset)
end
failure.json do
render :json => { :status => 'error' }
end
end
rescue Exception => e
render :json => { :status => 'error', :message => e.message }
end end
protected protected
def begin_of_association_chain def collection
@asset_collection if params[:image]
@assets ||= begin_of_association_chain.assets.only_image
else
@assets ||= begin_of_association_chain.assets
end
end end
def set_collections_and_current_collection def asset_to_json(asset)
@asset_collections = current_site.asset_collections.not_internal.order_by([[:name, :asc]]) {
@asset_collection = current_site.asset_collections.find(params[:collection_id]) :status => 'success',
:filename => asset.source_filename,
:short_name => truncate(asset.name, :length => 15),
:extname => truncate(asset.extname, :length => 3),
:content_type => asset.content_type,
:url => asset.source.url,
:vignette_url => asset.vignette_url,
:destroy_url => admin_asset_url(asset, :json)
}
end end
end end

View File

@ -9,11 +9,13 @@ module Admin
before_filter :require_site before_filter :require_site
load_and_authorize_resource
before_filter :validate_site_membership before_filter :validate_site_membership
before_filter :set_locale before_filter :set_locale
helper_method :sections, :current_site_url, :site_url, :page_url helper_method :sections, :current_site_url, :site_url, :page_url, :current_ability
# https://rails.lighthouseapp.com/projects/8994/tickets/1905-apphelpers-within-plugin-not-being-mixed-in # https://rails.lighthouseapp.com/projects/8994/tickets/1905-apphelpers-within-plugin-not-being-mixed-in
Dir[File.dirname(__FILE__) + "/../../helpers/**/*_helper.rb"].each do |file| Dir[File.dirname(__FILE__) + "/../../helpers/**/*_helper.rb"].each do |file|
@ -26,8 +28,24 @@ module Admin
respond_to :html respond_to :html
rescue_from CanCan::AccessDenied do |exception|
::Locomotive::Logger.info "[CanCan::AccessDenied] #{exception.inspect}"
if request.xhr?
render :json => { :error => exception.message }
else
flash[:alert] = exception.message
redirect_to admin_pages_url
end
end
protected protected
def current_ability
@current_ability ||= Ability.new(current_admin, current_site)
end
def require_admin def require_admin
authenticate_admin! authenticate_admin!
end end

View File

@ -5,7 +5,11 @@ module Admin
before_filter :set_content_type before_filter :set_content_type
respond_to :json, :only => :update respond_to :json, :only => [:update, :sort]
skip_load_and_authorize_resource
before_filter :authorize_content
def index def index
@contents = @content_type.list_or_group_contents @contents = @content_type.list_or_group_contents
@ -20,7 +24,7 @@ module Admin
end end
def sort def sort
@content_type.sort_contents!(params[:order]) @content_type.sort_contents!(params[:children])
respond_with(@content_type, :location => admin_contents_url(@content_type.slug)) respond_with(@content_type, :location => admin_contents_url(@content_type.slug))
end end
@ -39,5 +43,9 @@ module Admin
set_content_type set_content_type
end end
def authorize_content
authorize! params[:action].to_sym, ContentInstance
end
end end
end end

View File

@ -9,6 +9,8 @@ module Admin
before_filter :require_admin, :only => :new before_filter :require_admin, :only => :new
skip_load_and_authorize_resource
def new def new
if site = current_admin.sites.detect { |s| s._id.to_s == params[:target_id] } if site = current_admin.sites.detect { |s| s._id.to_s == params[:target_id] }
if Rails.env == 'development' if Rails.env == 'development'

View File

@ -7,6 +7,10 @@ module Admin
actions :edit, :update actions :edit, :update
skip_load_and_authorize_resource
load_and_authorize_resource :class => 'Site'
respond_to :json, :only => :update respond_to :json, :only => :update
def update def update

View File

@ -5,6 +5,8 @@ module Admin
before_filter :set_parent_and_fields before_filter :set_parent_and_fields
skip_load_and_authorize_resource
def edit def edit
@field = @fields.find(params[:id]) @field = @fields.find(params[:id])
render :action => "edit_#{@field.kind.downcase}" render :action => "edit_#{@field.kind.downcase}"
@ -23,14 +25,9 @@ module Admin
protected protected
def set_parent_and_fields def set_parent_and_fields
if params[:parent] == 'asset_collection'
@parent = current_site.asset_collections.where(:slug => params[:slug]).first
@fields = @parent.asset_custom_fields
else
@parent = current_site.content_types.where(:slug => params[:slug]).first @parent = current_site.content_types.where(:slug => params[:slug]).first
@fields = @parent.content_custom_fields @fields = @parent.content_custom_fields
end end
end
end end
end end

View File

@ -0,0 +1,20 @@
module Admin
class ExportController < BaseController
skip_load_and_authorize_resource
before_filter :authorize_export
def new
zipfile = ::Locomotive::Export.run!(current_site, current_site.name.parameterize)
send_file zipfile, :type => 'application/zip', :disposition => 'attachment'
end
protected
def authorize_export
authorize! :export, Site
end
end
end

View File

@ -1,55 +0,0 @@
module Admin
class ImagesController < BaseController
include ActionView::Helpers::SanitizeHelper
include ActionView::Helpers::TextHelper
defaults :collection_name => 'assets', :instance_name => 'asset'
respond_to :json, :only => [:index, :create, :destroy]
def index
index! do |response|
response.json do
render :json => { :images => @assets.collect { |image| image_to_json(image) } }
end
end
end
def create
params[:asset] = { :name => params[:name], :source => params[:file] } if params[:file]
create! do |success, failure|
success.json do
render :json => image_to_json(@asset)
end
failure.json do
render :json => { :status => 'error' }
end
end
rescue Exception => e
render :json => { :status => 'error', :message => e.message }
end
protected
def collection
@assets ||= begin_of_association_chain.assets
end
def begin_of_association_chain
@asset_collection ||= AssetCollection.find_or_create_internal(current_site)
end
def image_to_json(image)
{
:status => 'success',
:name => truncate(image.name, :length => 15),
:url => image.source.url,
:vignette_url => image.vignette_url,
:destroy_url => admin_image_url(image, :json)
}
end
end
end

View File

@ -1,10 +1,14 @@
module Admin module Admin
class ImportsController < BaseController class ImportController < BaseController
sections 'settings', 'site' sections 'settings', 'site'
actions :show, :new, :create actions :show, :new, :create
skip_load_and_authorize_resource
before_filter :authorize_import
def show def show
@job = Delayed::Job.where({ :job_type => 'import', :site_id => current_site.id }).last @job = Delayed::Job.where({ :job_type => 'import', :site_id => current_site.id }).last
@ -28,7 +32,7 @@ module Admin
:reset => Boolean.set(params[:reset]) :reset => Boolean.set(params[:reset])
}) })
flash[:notice] = t("flash.admin.imports.create.#{Locomotive.config.delayed_job ? 'notice' : 'done'}") flash[:notice] = t("flash.admin.import.create.#{Locomotive.config.delayed_job ? 'notice' : 'done'}")
redirect_to Locomotive.config.delayed_job ? admin_import_url : new_admin_import_url redirect_to Locomotive.config.delayed_job ? admin_import_url : new_admin_import_url
rescue Exception => e rescue Exception => e
@ -41,5 +45,11 @@ module Admin
end end
end end
protected
def authorize_import
authorize! :import, Site
end
end end
end end

View File

@ -15,6 +15,8 @@ module Admin
before_filter :allow_installation? before_filter :allow_installation?
skip_load_and_authorize_resource
def show def show
request.get? ? self.handle_get : self.handle_post request.get? ? self.handle_get : self.handle_post
end end

View File

@ -7,6 +7,8 @@ module Admin
respond_to :json, :only => :update respond_to :json, :only => :update
skip_load_and_authorize_resource
def update def update
update! { edit_admin_my_account_url } update! { edit_admin_my_account_url }
end end

View File

@ -33,7 +33,7 @@ module Admin
end end
def get_path def get_path
page = current_site.pages.build(:parent => current_site.pages.find(params[:parent_id]), :slug => params[:slug].slugify) page = current_site.pages.build(:parent => current_site.pages.find(params[:parent_id]), :slug => params[:slug].permalink)
render :json => { :url => page_url(page), :slug => page.slug } render :json => { :url => page_url(page), :slug => page.slug }
end end

View File

@ -7,6 +7,8 @@ module Admin
respond_to :xml respond_to :xml
skip_load_and_authorize_resource
def show def show
@pages = current_site.pages.published @pages = current_site.pages.published
end end

View File

@ -49,8 +49,8 @@ module Admin
def sanitize_params def sanitize_params
params[:theme_asset] = { :source => params[:file] } if params[:file] params[:theme_asset] = { :source => params[:file] } if params[:file]
performing_plain_text = params[:theme_asset][:performing_plain_text] # performing_plain_text = params[:theme_asset][:performing_plain_text]
params[:theme_asset].delete(:content_type) if performing_plain_text.blank? || performing_plain_text == 'false' # params[:theme_asset].delete(:content_type) if performing_plain_text.blank? || performing_plain_text == 'false'
end end
end end

View File

@ -1,7 +1,7 @@
module Admin::AccountsHelper module Admin::AccountsHelper
def admin_on?(site = current_site) def admin_on?(site = current_site)
site.memberships.detect { |a| a.admin? && a.account == current_admin } site.memberships.detect { |m| m.admin? && m.account == current_admin }
end end
end end

View File

@ -45,15 +45,43 @@ module Admin::CustomFieldsHelper
end.compact end.compact
end end
def options_for_has_one(field) def options_for_has_one(field, value)
target_contents_from_field(field).collect { |c| [c._label, c._id] } self.options_for_has_one_or_has_many(field) do |groups|
grouped_options_for_select(groups.collect do |g|
if g[:items].empty?
nil
else
[g[:name], g[:items].collect { |c| [c._label, c._id] }]
end
end.compact, value)
end
end end
alias :options_for_has_many :options_for_has_one def options_for_has_many(field)
self.options_for_has_one_or_has_many(field)
end
def target_contents_from_field(field) def options_for_has_one_or_has_many(field, &block)
content_type = field.target.constantize._parent content_type = field.target.constantize._parent
content_type.ordered_contents
if content_type.groupable?
grouped_contents = content_type.list_or_group_contents
if block_given?
block.call(grouped_contents)
else
grouped_contents.collect do |g|
if g[:items].empty?
nil
else
{ :name => g[:name], :items => g[:items].collect { |c| [c._label, c._id] } }
end
end.compact
end
else
contents = content_type.ordered_contents
contents.collect { |c| [c._label, c._id] }
end
end end
end end

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

@ -0,0 +1,68 @@
class Ability
include CanCan::Ability
ROLES = %w(admin designer author)
def initialize(account, site)
@account, @site = account, site
alias_action :index, :show, :edit, :update, :to => :touch
@membership = @site.memberships.where(:account_id => @account.id).first
return false if @membership.blank?
if @membership.admin?
setup_admin_permissions!
else
setup_default_permissions!
setup_designer_permissions! if @membership.designer?
setup_author_permissions! if @membership.author?
end
end
def setup_default_permissions!
cannot :manage, :all
end
def setup_author_permissions!
can :touch, [Page, ThemeAsset]
can :sort, Page
can :manage, [ContentInstance, Asset]
can :touch, Site do |site|
site == @site
end
end
def setup_designer_permissions!
can :manage, Page
can :manage, ContentInstance
can :manage, ContentType
can :manage, Snippet
can :manage, ThemeAsset
can :manage, Site do |site|
site == @site
end
can :import, Site
can :export, Site
can :point, Site
can :manage, Membership
end
def setup_admin_permissions!
can :manage, :all
end
end

View File

@ -5,9 +5,7 @@ class Account
include Locomotive::Mongoid::Document include Locomotive::Mongoid::Document
# devise modules # devise modules
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :encryptable, :encryptor => :sha1
# attr_accessible :email, :password, :password_confirmation # TODO
## attributes ## ## attributes ##
field :name field :name

View File

@ -3,12 +3,11 @@ class Asset
include Mongoid::Document include Mongoid::Document
include Mongoid::Timestamps include Mongoid::Timestamps
## Extensions ## ## extensions ##
include Extensions::Asset::Types
include Extensions::Asset::Vignette include Extensions::Asset::Vignette
include CustomFields::ProxyClassEnabler
## fields ## ## fields ##
field :name, :type => String
field :content_type, :type => String field :content_type, :type => String
field :width, :type => Integer field :width, :type => Integer
field :height, :type => Integer field :height, :type => Integer
@ -17,32 +16,24 @@ class Asset
mount_uploader :source, AssetUploader mount_uploader :source, AssetUploader
## associations ## ## associations ##
embedded_in :collection, :class_name => 'AssetCollection', :inverse_of => :assets referenced_in :site
## validations ## ## validations ##
validates_presence_of :name, :source validates_presence_of :source
## behaviours ## ## behaviours ##
## methods ## ## methods ##
%w{image stylesheet javascript pdf media}.each do |type| alias :name :source_filename
define_method("#{type}?") do
self.content_type.to_s == type
end
end
def extname def extname
return nil unless self.source? return nil unless self.source?
File.extname(self.source_filename).gsub(/^\./, '') File.extname(self.source_filename).gsub(/^\./, '')
end end
def site_id # needed by the uploader of custom fields
self.collection.site_id
end
def to_liquid def to_liquid
Locomotive::Liquid::Drops::Asset.new(self) { :url => self.source.url }.merge(self.attributes).stringify_keys
end end
end end

View File

@ -1,81 +0,0 @@
class AssetCollection
include Locomotive::Mongoid::Document
## fields ##
field :name
field :slug
field :internal, :type => Boolean, :default => false
## associations ##
referenced_in :site
embeds_many :assets, :validate => false
## behaviours ##
custom_fields_for :assets
liquid_methods :name, :ordered_assets
## callbacks ##
before_validation :normalize_slug
before_save :store_asset_positions!
after_destroy :remove_uploaded_files
## validations ##
validates_presence_of :site, :name, :slug
validates_uniqueness_of :slug, :scope => :site_id
## named scopes ##
scope :internal, :where => { :internal => true }
scope :not_internal, :where => { :internal => false }
## methods ##
def ordered_assets
self.assets.sort { |a, b| (a.position || 0) <=> (b.position || 0) }
end
def assets_order
self.ordered_assets.collect(&:id).join(',')
end
def assets_order=(order)
@assets_order = order
end
def self.find_or_create_internal(site)
site.asset_collections.internal.first || site.asset_collections.create(:name => 'system', :slug => 'system', :internal => true)
end
protected
def normalize_slug
self.slug = self.name.clone if self.slug.blank? && self.name.present?
self.slug.slugify! if self.slug.present?
end
def store_asset_positions!
return if @assets_order.nil?
ids = @assets_order.split(',').collect { |id| BSON::ObjectId(id) }
ids.each_with_index do |asset_id, index|
self.assets.find(asset_id).position = index
end
self.assets.clone.each do |asset|
if !ids.include?(asset._id)
self.assets.delete(asset)
asset.send(:delete)
end
end
end
def remove_uploaded_files # callbacks are not called on each asset so we do it manually
self.assets.each do |asset|
self.asset_custom_fields.each do |field|
asset.send(:"remove_#{field._name}!") if field.kind == 'file'
end
end
end
end

View File

@ -14,12 +14,14 @@ class ContentInstance
## validations ## ## validations ##
validate :require_highlighted_field validate :require_highlighted_field
validate :validate_uniqueness_of_slug
validates_presence_of :_slug
## associations ## ## associations ##
embedded_in :content_type, :inverse_of => :contents embedded_in :content_type, :inverse_of => :contents
## callbacks ## ## callbacks ##
before_save :set_slug before_validation :set_slug
before_save :set_visibility before_save :set_visibility
before_create :add_to_list_bottom before_create :add_to_list_bottom
after_create :send_notifications after_create :send_notifications
@ -67,8 +69,8 @@ class ContentInstance
protected protected
def set_slug def set_slug
_alias = self.highlighted_field_alias self._slug = self.highlighted_field_value.clone if self._slug.blank? && self.highlighted_field_value.present?
self._slug = self.send(_alias).parameterize('_') self._slug.permalink! if self._slug.present?
end end
def set_visibility def set_visibility
@ -77,7 +79,6 @@ class ContentInstance
end end
def add_to_list_bottom def add_to_list_bottom
Rails.logger.debug "add_to_list_bottom"
self._position_in_list = self.content_type.contents.size self._position_in_list = self.content_type.contents.size
end end
@ -88,6 +89,12 @@ class ContentInstance
end end
end end
def validate_uniqueness_of_slug
if self._parent.contents.any? { |c| c._id != self._id && c._slug == self._slug }
self.errors.add(:_slug, :taken)
end
end
def highlighted_field_alias def highlighted_field_alias
self.content_type.highlighted_field._alias.to_sym self.content_type.highlighted_field._alias.to_sym
end end

View File

@ -107,8 +107,8 @@ class ContentType
self.asc_order? ? list : list.reverse self.asc_order? ? list : list.reverse
end end
def sort_contents!(order) def sort_contents!(ids)
order.split(',').each_with_index do |id, position| ids.each_with_index do |id, position|
self.contents.find(BSON::ObjectId(id))._position_in_list = position self.contents.find(BSON::ObjectId(id))._position_in_list = position
end end
self.save self.save
@ -131,7 +131,7 @@ class ContentType
def normalize_slug def normalize_slug
self.slug = self.name.clone if self.slug.blank? && self.name.present? self.slug = self.name.clone if self.slug.blank? && self.name.present?
self.slug.slugify! if self.slug.present? self.slug.permalink! if self.slug.present?
end end
def remove_uploaded_files # callbacks are not called on each content so we do it manually def remove_uploaded_files # callbacks are not called on each content so we do it manually

View File

@ -0,0 +1,19 @@
module Extensions
module Asset
module Types
extend ActiveSupport::Concern
included do
%w{media image stylesheet javascript font pdf}.each do |type|
scope :"only_#{type}", where(:content_type => type)
define_method("#{type}?") do
self.content_type.to_s == type
end
end
end
end
end
end

View File

@ -7,7 +7,7 @@ module Extensions
if self.width < 80 && self.height < 80 if self.width < 80 && self.height < 80
self.source.url self.source.url
else else
self.source.url(:medium) Locomotive::Dragonfly.resize_url(self.source, '80x80#')
end end
end end
end end

View File

@ -42,14 +42,6 @@ module Extensions
@item_parsing_errors.try(:each) { |msg| self.errors.add :item_template, msg } @item_parsing_errors.try(:each) { |msg| self.errors.add :item_template, msg }
end end
# def item_template
# self.read_attribute(:default_item_template) || self.default_item_template
# end
#
# def default_item_template
# '{{ content.highlighted_field_value }}'
# end
end end
end end

View File

@ -28,9 +28,9 @@ module Extensions
module ClassMethods module ClassMethods
# Warning: used only in read-only # Warning: should be used only in read-only
def quick_tree(site) def quick_tree(site, minimal_attributes = true)
pages = site.pages.minimal_attributes.order_by([[:depth, :asc], [:position, :asc]]).to_a pages = (minimal_attributes ? site.pages.minimal_attributes : site.pages).order_by([[:depth, :asc], [:position, :asc]]).to_a
tmp = [] tmp = []

View File

@ -4,6 +4,7 @@ module Extensions
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
field :seo_title, :type => String
field :meta_keywords, :type => String field :meta_keywords, :type => String
field :meta_description, :type => String field :meta_description, :type => String
end end

View File

@ -6,7 +6,7 @@ module Extensions
def create_first_one(attributes) def create_first_one(attributes)
site = self.new(attributes) site = self.new(attributes)
site.memberships.build :account => Account.first, :admin => true site.memberships.build :account => Account.first, :role => 'admin'
site.save site.save
@ -27,7 +27,7 @@ module Extensions
begin begin
Locomotive::Import::Job.run!(source, site, { :samples => true }) Locomotive::Import::Job.run!(source, site, { :samples => true })
rescue Exception => e rescue Exception => e
logger.error "The import of the site template failed because of #{e.message}" Rails.logger.error "The import of the site template failed because of #{e.message}"
end end
end end

View File

@ -3,7 +3,8 @@ class Membership
include Locomotive::Mongoid::Document include Locomotive::Mongoid::Document
## fields ## ## fields ##
field :admin, :type => Boolean, :default => false # field :admin, :type => Boolean, :default => false
field :role, :default => 'author'
## associations ## ## associations ##
referenced_in :account, :validate => false referenced_in :account, :validate => false
@ -12,8 +13,17 @@ class Membership
## validations ## ## validations ##
validates_presence_of :account validates_presence_of :account
## callbacks ##
before_save :define_role
## methods ## ## methods ##
Ability::ROLES.each do |_role|
define_method("#{_role}?") do
self.role == _role
end
end
def email; @email; end def email; @email; end
def email=(email) def email=(email)
@ -36,4 +46,14 @@ class Membership
end end
end end
def ability
@ability ||= Ability.new(self.account, self.site)
end
protected
def define_role
self.role = Ability::ROLES.include?(role.downcase) ? role.downcase : Ability::ROLES.first
end
end end

View File

@ -97,7 +97,7 @@ class Page
def normalize_slug def normalize_slug
self.slug = self.title.clone if self.slug.blank? && self.title.present? self.slug = self.title.clone if self.slug.blank? && self.title.present?
self.slug.slugify!(:without_extension => true) if self.slug.present? self.slug.permalink! if self.slug.present?
end end
def set_default_raw_template def set_default_raw_template

View File

@ -5,17 +5,17 @@ class Site
## Extensions ## ## Extensions ##
extend Extensions::Site::SubdomainDomains extend Extensions::Site::SubdomainDomains
extend Extensions::Site::FirstInstallation extend Extensions::Site::FirstInstallation
extend Extensions::Site::FirstInstallation
include Extensions::Shared::Seo
## fields ## ## fields ##
field :name field :name
field :meta_keywords
field :meta_description
## associations ## ## associations ##
references_many :pages, :validate => false references_many :pages, :validate => false
references_many :snippets, :dependent => :destroy, :validate => false references_many :snippets, :dependent => :destroy, :validate => false
references_many :theme_assets, :dependent => :destroy, :validate => false references_many :theme_assets, :dependent => :destroy, :validate => false
references_many :asset_collections, :dependent => :destroy, :validate => false references_many :assets, :dependent => :destroy, :validate => false
references_many :content_types, :dependent => :destroy, :validate => false references_many :content_types, :dependent => :destroy, :validate => false
embeds_many :memberships embeds_many :memberships
@ -28,6 +28,7 @@ class Site
## behaviours ## ## behaviours ##
enable_subdomain_n_domains_if_multi_sites enable_subdomain_n_domains_if_multi_sites
accepts_nested_attributes_for :memberships
## methods ## ## methods ##

View File

@ -26,7 +26,7 @@ class Snippet
def normalize_slug def normalize_slug
# TODO: refactor it # TODO: refactor it
self.slug = self.name.clone if self.slug.blank? && self.name.present? self.slug = self.name.clone if self.slug.blank? && self.name.present?
self.slug.slugify!(:without_extension => true, :downcase => true) if self.slug.present? self.slug.permalink! if self.slug.present?
end end
def update_templates def update_templates

View File

@ -2,6 +2,9 @@ class ThemeAsset
include Locomotive::Mongoid::Document include Locomotive::Mongoid::Document
## extensions ##
include Extensions::Asset::Types
## fields ## ## fields ##
field :local_path field :local_path
field :content_type field :content_type
@ -35,16 +38,10 @@ class ThemeAsset
scope :visible, lambda { |all| all ? {} : { :where => { :hidden => false } } } scope :visible, lambda { |all| all ? {} : { :where => { :hidden => false } } }
## accessors ## ## accessors ##
attr_accessor :plain_text_name, :plain_text, :performing_plain_text attr_accessor :plain_text_name, :plain_text, :plain_text_type, :performing_plain_text
## methods ## ## methods ##
%w{media image stylesheet javascript font}.each do |type|
define_method("#{type}?") do
self.content_type.to_s == type
end
end
def stylesheet_or_javascript? def stylesheet_or_javascript?
self.stylesheet? || self.javascript? self.stylesheet? || self.javascript?
end end
@ -77,11 +74,17 @@ class ThemeAsset
end end
end end
def plain_text_type
@plain_text_type || (stylesheet_or_javascript? ? self.content_type : nil)
end
def performing_plain_text? def performing_plain_text?
Boolean.set(self.performing_plain_text) || false Boolean.set(self.performing_plain_text) || false
end end
def store_plain_text def store_plain_text
self.content_type ||= @plain_text_type if self.performing_plain_text?
data = self.performing_plain_text? ? self.plain_text : self.source.read data = self.performing_plain_text? ? self.plain_text : self.source.read
return if !self.stylesheet_or_javascript? || self.plain_text_name.blank? || data.blank? return if !self.stylesheet_or_javascript? || self.plain_text_name.blank? || data.blank?
@ -95,7 +98,7 @@ class ThemeAsset
end end
def to_liquid def to_liquid
{ :url => self.source.url }.merge(self.attributes) { :url => self.source.url }.merge(self.attributes).stringify_keys
end end
def self.all_grouped_by_folder(site, include_all = true) def self.all_grouped_by_folder(site, include_all = true)

View File

@ -2,72 +2,10 @@
class AssetUploader < CarrierWave::Uploader::Base class AssetUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick include Locomotive::CarrierWave::Uploader::Asset
def store_dir def store_dir
self.build_store_dir('sites', model.collection.site_id, 'assets', model.id) self.build_store_dir('sites', model.site_id, 'assets', model.id)
end
version :thumb, :if => :image? do
process :resize_to_fill => [50, 50]
process :convert => 'png'
end
version :medium, :if => :image? do
process :resize_to_fill => [80, 80]
process :convert => 'png'
end
version :preview, :if => :image? do
process :resize_to_fit => [880, 1100]
process :convert => 'png'
end
process :set_content_type
process :set_size
process :set_width_and_height
def set_content_type(*args)
value = :other
content_type = file.content_type == 'application/octet-stream' ? File.mime_type?(original_filename) : file.content_type
self.class.content_types.each_pair do |type, rules|
rules.each do |rule|
case rule
when String then value = type if content_type == rule
when Regexp then value = type if (content_type =~ rule) == 0
end
end
end
model.content_type = value
end
def set_size(*args)
model.size = file.size
end
def set_width_and_height
if model.image?
magick = ::Magick::Image.read(current_path).first
model.width, model.height = magick.columns, magick.rows
end
end
def image?
model.image?
end
def self.content_types
{
:image => ['image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png', 'image/jpg', 'image/x-icon'],
:media => [/^video/, 'application/x-shockwave-flash', 'application/x-swf', /^audio/, 'application/ogg', 'application/x-mp3'],
:pdf => ['application/pdf', 'application/x-pdf'],
:stylesheet => ['text/css'],
:javascript => ['text/javascript', 'text/js', 'application/x-javascript', 'application/javascript'],
:font => ['application/x-font-ttf', 'application/vnd.ms-fontobject', 'image/svg+xml', 'application/x-woff']
}
end end
end end

View File

@ -4,8 +4,4 @@ class EditableFileUploader < ::CarrierWave::Uploader::Base
self.build_store_dir('sites', model.page.site_id, 'pages', model.page.id, 'files') self.build_store_dir('sites', model.page.site_id, 'pages', model.page.id, 'files')
end end
# def cache_dir
# "#{Rails.root}/tmp/uploads"
# end
end end

View File

@ -1,17 +1,11 @@
# encoding: utf-8 # encoding: utf-8
class ThemeAssetUploader < AssetUploader class ThemeAssetUploader < CarrierWave::Uploader::Base
process :set_content_type include Locomotive::CarrierWave::Uploader::Asset
process :set_size
process :set_width_and_height
def store_dir def store_dir
self.build_store_dir('sites', (model.site_id_was || model.site_id).to_s, 'theme', model.folder_was || model.folder) self.build_store_dir('sites', model.site_id, 'theme', model.folder)
end
def stale_model?
!model.new_record? && model.folder_changed?
end end
def extension_white_list def extension_white_list

View File

@ -1,36 +0,0 @@
- title link_to(@asset_collection.name.blank? ? @asset_collection.name_was : @asset_collection.name, '#', :rel => 'asset_collection_name', :title => t('.ask_for_name'), :class => 'editable')
- content_for :head do
= include_javascripts :asset_collections
= include_stylesheets :fancybox
- content_for :submenu do
= render 'admin/shared/menu/assets'
- content_for :actions do
= render 'admin/shared/actions/assets'
%p!= t('.help')
- content_for :buttons do
= admin_button_tag :add_asset, new_admin_asset_url(@asset_collection), :class => 'new'
%p.no-items{ :style => "#{'display: none' unless @asset_collection.assets.empty? }" }
!= t('.no_items', :url => new_admin_asset_url(@asset_collection))
%ul#assets.assets.sortable
= render :partial => 'asset', :collection => @asset_collection.ordered_assets
%li.clear
= semantic_form_for @asset_collection, :url => admin_asset_collection_url(@asset_collection), :html => { :multipart => true } do |f|
= f.hidden_field :assets_order
= f.foldable_inputs :name => :options do
= f.input :name
= f.input :slug, :required => false
= render 'admin/custom_fields/index', :form => f, :collection_name => 'assets'
= render 'admin/shared/form_actions', :delete_button => link_to(content_tag(:em, escape_once('&nbsp;')) + t('.destroy'), admin_asset_collection_url(@asset_collection), :confirm => t('admin.messages.confirm'), :method => :delete, :class => 'button small remove'), :button_label => :update
= render 'admin/custom_fields/edit_field'

View File

@ -1,11 +0,0 @@
- title t('.title')
- content_for :submenu do
= render 'admin/shared/menu/assets'
- content_for :actions do
= render 'admin/shared/actions/assets'
%p!= t('.help')
%p.no-items!= t('.no_items', :url => new_admin_asset_collection_url)

View File

@ -1,20 +0,0 @@
- title t('.title')
- content_for :head do
= include_javascripts :asset_collections
- content_for :submenu do
= render 'admin/shared/menu/assets'
- content_for :actions do
= render 'admin/shared/actions/assets'
%p!= t('.help')
= semantic_form_for @asset_collection, :url => admin_asset_collections_url do |f|
= f.inputs :name => :information do
= f.input :name
= f.input :slug, :required => false
= render 'admin/shared/form_actions', :back_url => admin_asset_collections_url, :button_label => :create

View File

@ -1,5 +1,5 @@
%li{ :id => "asset-#{asset.id}", :class => "asset #{'last' if (asset_counter + 1) % 6 == 0}"} %li{ :id => "asset-#{asset.id}", :class => "asset #{'last' if (asset_counter + 1) % 6 == 0}"}
%h4= link_to truncate(asset.name, :length => 17), edit_admin_asset_path(@asset_collection, asset) %h4= link_to truncate(asset.name, :length => 17), edit_admin_asset_path(asset)
= vignette_tag(asset) = vignette_tag(asset)
.actions .actions
= link_to image_tag('admin/list/icons/cross.png'), '#', :class => 'remove', :confirm => t('admin.messages.confirm') = link_to image_tag('admin/list/icons/cross.png'), '#', :class => 'remove', :confirm => t('admin.messages.confirm')

View File

@ -1,17 +0,0 @@
- content_for :head do
= include_javascripts :edit_custom_fields, :assets
= include_stylesheets :fancybox
= f.inputs :name => :information do
= f.input :name
= f.input :source, :hint_options => @asset.persisted? ? { :url => link_to(@asset.source_filename, @asset.source.url), :escaping => false } : {}
- unless @asset.custom_fields.blank?
= render 'admin/custom_fields/custom_form', :form => f, :title => :other_fields, :parent => @asset_collection
- if @asset.image? && @asset.valid?
= f.foldable_inputs :name => "#{t('formtastic.titles.preview')} #{image_dimensions_and_size(@asset)}", :class => 'preview' do
%li
.image
.inside
= image_tag(@asset.source.url(:preview))

View File

@ -1,18 +0,0 @@
- title t('.title')
- content_for :submenu do
= render 'admin/shared/menu/assets'
- content_for :actions do
= render 'admin/shared/actions/assets'
- content_for :buttons do
= admin_button_tag t('admin.asset_collections.edit.add_asset'), new_admin_asset_url(@asset_collection), :class => 'new'
%p!= t('.help')
= semantic_form_for @asset, :url => admin_asset_url(@asset_collection, @asset), :html => { :multipart => true, :class => 'save-with-shortcut' } do |form|
= render 'form', :f => form
= render 'admin/shared/form_actions', :back_url => edit_admin_asset_collection_url(@asset_collection), :button_label => :update

View File

@ -1,15 +0,0 @@
- title t('.title')
- content_for :submenu do
= render 'admin/shared/menu/assets'
- content_for :actions do
= render 'admin/shared/actions/assets'
%p!= t('.help')
= semantic_form_for @asset, :url => admin_assets_url(@asset_collection), :html => { :multipart => true } do |form|
= render 'form', :f => form
= render 'admin/shared/form_actions', :back_url => edit_admin_asset_collection_url(@asset_collection), :button_label => :create

View File

@ -3,7 +3,7 @@
= include_stylesheets :fancybox = include_stylesheets :fancybox
= f.inputs :name => :information do = f.inputs :name => :information do
= f.input :name = f.input :name, :wrapper_html => { :class => 'highlighted' }
= f.input :slug = f.input :slug
= f.input :description = f.input :description
@ -13,10 +13,9 @@
= f.foldable_inputs :name => :presentation, :class => 'switchable' do = f.foldable_inputs :name => :presentation, :class => 'switchable' do
= f.input :highlighted_field_name, :as => :select, :collection => options_for_highlighted_field(f.object, 'contents'), :include_blank => false = f.input :highlighted_field_name, :as => :select, :collection => options_for_highlighted_field(f.object, 'contents'), :include_blank => false
= f.input :group_by_field_name, :as => :select, :collection => options_for_group_by_field(f.object, 'contents') = f.input :group_by_field_name, :as => :select, :collection => options_for_group_by_field(f.object, 'contents')
= f.custom_input :raw_item_template, :css => 'small-code' do = f.custom_input :item_template, :css => 'small-code' do
%code{ :class => 'html' } %code{ :class => 'html' }
= f.text_area :raw_item_template, :class => 'small' = f.text_area :raw_item_template, :class => 'small'
= f.errors_on :item_template
= f.foldable_inputs :name => :options, :class => 'switchable' do = f.foldable_inputs :name => :options, :class => 'switchable' do
= f.input :order_by, :as => :select, :collection => options_for_order_by(f.object, 'contents'), :include_blank => false = f.input :order_by, :as => :select, :collection => options_for_order_by(f.object, 'contents'), :include_blank => false

View File

@ -7,8 +7,8 @@
= render 'admin/shared/actions/contents' = render 'admin/shared/actions/contents'
- content_for :buttons do - content_for :buttons do
= admin_button_tag :show_items, admin_contents_url(@content_type.slug), :class => 'show' = admin_button_tag :show_items, admin_contents_url(@content_type.slug_was), :class => 'show'
= admin_button_tag :new_item, new_admin_content_url(@content_type.slug), :class => 'new' = admin_button_tag :new_item, new_admin_content_url(@content_type.slug_was), :class => 'new'
%p!= t('.help') %p!= t('.help')
@ -16,6 +16,6 @@
= render 'form', :f => f = render 'form', :f => f
= render 'admin/shared/form_actions', :back_url => admin_contents_url(@content_type.slug), :button_label => :update = render 'admin/shared/form_actions', :back_url => admin_contents_url(@content_type.slug_was), :button_label => :update
= render 'admin/custom_fields/edit_field' = render 'admin/custom_fields/edit_field'

View File

@ -2,9 +2,11 @@
= include_javascripts :edit_custom_fields, :contents = include_javascripts :edit_custom_fields, :contents
= include_stylesheets :fancybox = include_stylesheets :fancybox
= f.foldable_inputs :name => :meta do = render 'admin/custom_fields/custom_form', :form => f, :title => :attributes, :parent => @content_type
= f.foldable_inputs :name => :advanced_options do
= f.input :_slug
= f.input :seo_title
= f.input :meta_keywords = f.input :meta_keywords
= f.input :meta_description = f.input :meta_description
= render 'admin/custom_fields/custom_form', :form => f, :title => :attributes, :parent => @content_type

View File

@ -1,7 +1,7 @@
- if contents.empty? - if contents.empty?
%p.no-items!= t('.no_items', :url => new_admin_content_url(@content_type.slug)) %p.no-items!= t('.no_items', :url => new_admin_content_url(@content_type.slug))
- else - else
%ul{ :id => 'contents-list', :class => "list #{'sortable' if @content_type.order_by == '_position_in_list'}" } %ul{ :id => 'contents-list', :class => "list #{'sortable' if @content_type.order_by == '_position_in_list'}", :'data-url' => sort_admin_contents_path(@content_type.slug, :json) }
- contents.each do |content| - contents.each do |content|
%li.content{ :id => "content-#{content._id}" } %li.content{ :id => "content-#{content._id}" }
%em %em
@ -12,4 +12,4 @@
!= t('admin.contents.index.updated_at') != t('admin.contents.index.updated_at')
= l content.updated_at, :format => :short rescue 'n/a' = l content.updated_at, :format => :short rescue 'n/a'
= link_to image_tag('admin/list/icons/trash.png'), admin_content_path(@content_type.slug, content), :class => 'remove', :confirm => t('admin.messages.confirm'), :method => :delete = link_to image_tag('admin/list/icons/trash.png', :alt => t('admin.buttons.delete')), admin_content_path(@content_type.slug, content), :class => 'remove', :confirm => t('admin.messages.confirm'), :method => :delete

View File

@ -7,7 +7,9 @@
= render 'admin/shared/actions/contents' = render 'admin/shared/actions/contents'
- content_for :buttons do - content_for :buttons do
- if can?(:manage, ContentType)
= admin_button_tag t('admin.contents.index.edit'), edit_admin_content_type_url(@content_type), :class => 'edit' = admin_button_tag t('admin.contents.index.edit'), edit_admin_content_type_url(@content_type), :class => 'edit'
= admin_button_tag t('admin.contents.index.new'), new_admin_content_url(@content_type.slug), :class => 'new' = admin_button_tag t('admin.contents.index.new'), new_admin_content_url(@content_type.slug), :class => 'new'
%p= @content_type.description %p= @content_type.description

View File

@ -10,7 +10,9 @@
= include_javascripts :contents = include_javascripts :contents
- content_for :buttons do - content_for :buttons do
- if can?(:manage, ContentType)
= admin_button_tag :edit, edit_admin_content_type_url(@content_type), :class => 'edit' = admin_button_tag :edit, edit_admin_content_type_url(@content_type), :class => 'edit'
= admin_button_tag :new, new_admin_content_url(@content_type.slug), :class => 'new' = admin_button_tag :new, new_admin_content_url(@content_type.slug), :class => 'new'
- if @content_type.description.present? - if @content_type.description.present?
@ -24,7 +26,7 @@
- else - else
= render 'list', :contents => @contents = render 'list', :contents => @contents
= form_tag sort_admin_contents_path(@content_type.slug), :method => :put, :class => 'formtastic' do - if can?(:manage, ContentType)
= hidden_field_tag :order #local-actions-bottom-bar
%p.tleft
= render 'admin/shared/form_actions', :delete_button => link_to(content_tag(:em, escape_once('&nbsp;')) + t('.destroy'), admin_content_type_url(@content_type), :confirm => t('admin.messages.confirm'), :method => :delete, :class => 'button small remove'), :button_label => :update = link_to(content_tag(:em, escape_once('&nbsp;')) + t('.destroy'), admin_content_type_url(@content_type), :confirm => t('admin.messages.confirm'), :method => :delete, :class => 'button small remove')

View File

@ -6,7 +6,8 @@
- content_for :actions do - content_for :actions do
= render 'admin/shared/actions/contents' = render 'admin/shared/actions/contents'
- content_for :buttons do - if can?(:manage, ContentType)
- content_for :buttons do
= admin_button_tag t('admin.contents.index.edit'), edit_admin_content_type_url(@content_type), :class => 'edit' = admin_button_tag t('admin.contents.index.edit'), edit_admin_content_type_url(@content_type), :class => 'edit'
%p= @content_type.description %p= @content_type.description

View File

@ -4,12 +4,13 @@
= f.foldable_inputs :name => :information, :style => "#{'display: none' unless @site.new_record?}" do = f.foldable_inputs :name => :information, :style => "#{'display: none' unless @site.new_record?}" do
= f.input :name, :required => false = f.input :name, :required => false
= f.foldable_inputs :name => :meta do = f.foldable_inputs :name => :seo do
= f.input :seo_title
= f.input :meta_keywords = f.input :meta_keywords
= f.input :meta_description = f.input :meta_description
- if manage_subdomain_or_domains? - if can?(:point, Site)
- if manage_subdomain_or_domains?
= f.foldable_inputs :name => :access_points, :class => 'editable-list off' do = f.foldable_inputs :name => :access_points, :class => 'editable-list off' do
= f.custom_input :subdomain, :css => 'path' do = f.custom_input :subdomain, :css => 'path' do
@ -41,12 +42,27 @@
%button{ :class => 'button light add', :type => 'button' } %button{ :class => 'button light add', :type => 'button' }
%span!= t('admin.buttons.new_item') %span!= t('admin.buttons.new_item')
= f.foldable_inputs :name => :memberships, :class => 'memberships' do - if can?(:manage, Membership)
- @site.memberships.each_with_index do |membership, index|
- account = membership.account = f.foldable_inputs :name => :memberships, :class => 'memberships off' do
%li{ :class => "item #{'last' if index == @site.memberships.size - 1}" } = f.semantic_fields_for :memberships do |fm|
- membership, account = fm.object, fm.object.account
%li.item.membership{ :'data-role' => membership.role }
%strong= account.name %strong= account.name
%em= account.email
- if account != current_admin %em.email= account.email
- if current_admin != account
.role
%em.editable= t("admin.memberships.roles.#{membership.role}")
= fm.select :role, Ability::ROLES.collect { |r| [t("admin.memberships.roles.#{r}"), r] }, :include_blank => false
%span.actions %span.actions
= link_to image_tag('admin/form/icons/trash.png'), admin_membership_url(membership), :class => 'remove first', :confirm => t('admin.messages.confirm'), :method => :delete = link_to image_tag('admin/form/icons/trash.png'), admin_membership_url(membership), :class => 'remove first', :confirm =>t('admin.messages.confirm'), :method => :delete
- else
.role
%em.locked= t("admin.memberships.roles.#{membership.role}")

View File

@ -3,7 +3,9 @@
- content_for :submenu do - content_for :submenu do
= render 'admin/shared/menu/settings' = render 'admin/shared/menu/settings'
- content_for :buttons do - if can?(:manage, @site)
- content_for :buttons do
= admin_button_tag :export, new_admin_export_url, :class => 'new'
= admin_button_tag :import, new_admin_import_url, :class => 'new' = admin_button_tag :import, new_admin_import_url, :class => 'new'
= admin_button_tag t('.new_membership'), new_admin_membership_url, :class => 'new' = admin_button_tag t('.new_membership'), new_admin_membership_url, :class => 'new'

View File

@ -2,8 +2,9 @@
= form.inputs :name => title || :attributes do = form.inputs :name => title || :attributes do
- form.object.custom_fields.each do |field| - form.object.custom_fields.each do |field|
- required = highlighted_field_name == field._name || field.required - highlighted = highlighted_field_name == field._name
- required = highlighted || field.required
= render "/admin/custom_fields/types/#{field.kind}", :form => form, :parent => parent, :field => field, :required => required = render "/admin/custom_fields/types/#{field.kind}", :form => form, :parent => parent, :field => field, :required => required, :highlighted => highlighted
= render '/admin/custom_fields/category_tmpl' = render '/admin/custom_fields/category_tmpl'

View File

@ -29,7 +29,7 @@
&mdash; &mdash;
%em {{kind_name}} %em.editable {{kind_name}}
= select_tag '{{base_name}}[kind]', options_for_select(options_for_field_kind), :'data-field' => 'kind' = select_tag '{{base_name}}[kind]', options_for_select(options_for_field_kind), :'data-field' => 'kind'

View File

@ -1,2 +1,2 @@
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'toggle' do = form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'toggle', :required => required do
= form.check_box field._alias.to_sym = form.check_box field._alias.to_sym

View File

@ -1,4 +1,4 @@
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'toggle' do = form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'toggle', :required => required do
= form.select field._name.to_sym, field.ordered_category_items.collect { |item| [item.name, item.id] } = form.select field._name.to_sym, field.ordered_category_items.collect { |item| [item.name, item.id] }
%button.button.light.edit-categories-link{ :type => 'button', :'data-url' => edit_admin_custom_field_path(parent.class.model_name.underscore, parent.slug, field) } %button.button.light.edit-categories-link{ :type => 'button', :'data-url' => edit_admin_custom_field_path(parent.class.model_name.underscore, parent.slug, field) }
%span!= t('.edit_categories') %span!= t('.edit_categories')

View File

@ -1 +1 @@
= form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :input_html => { :class => 'date' } = form.input :"formatted_#{field._alias}", :label => field.label, :hint => field.hint, :input_html => { :class => 'date' }, :wrapper_html => { :class => 'date' }, :required => required

View File

@ -1,4 +1,4 @@
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'file' do = form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'file', :required => required do
= form.file_field field._name.to_sym = form.file_field field._name.to_sym
- if form.object.send(:"#{field._name}?") - if form.object.send(:"#{field._name}?")
%p.remove %p.remove

View File

@ -1,6 +1,6 @@
- field.target.constantize.reload_parent! # to make sure all the contents from the parent are loaded - field.target.constantize.reload_parent! # to make sure all the contents from the parent are loaded
= form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'has-many' do = form.custom_input field._alias.to_sym, :label => field.label, :hint => field.hint, :css => 'has-many', :required => required do
.has-many-selector .has-many-selector

View File

@ -1,4 +1,6 @@
- field.target.constantize.reload_parent! # to make sure all the contents from the parent are loaded - field.target.constantize.reload_parent! # to make sure all the contents from the parent are loaded
= form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :input_html => { :class => 'has_one' }, :as => :select, :collection => options_for_has_one(field), :selected => form.object.send(field._alias.to_sym).try(:_id) - selected_id = form.object.send(field._alias.to_sym).try(:_id)
= form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :input_html => { :class => 'has_one' }, :as => :select, :collection => options_for_has_one(field, selected_id), :selected => selected_id, :required => required

View File

@ -1 +1 @@
= form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :required => required = form.input field._alias.to_sym, :label => field.label, :hint => field.hint, :required => required, :wrapper_html => { :class => "#{'highlighted' if highlighted}" }

View File

@ -9,7 +9,7 @@
%p!= t('.help') %p!= t('.help')
%ul{ :id => 'import-steps', :class => 'list', :'data-url' => admin_import_url(:json), :'data-success-message' => t('.messages.success'), :'data-failure-message' => t('.messages.failure') } %ul{ :id => 'import-steps', :class => 'list', :'data-url' => admin_import_url(:json), :'data-success-message' => t('.messages.success'), :'data-failure-message' => t('.messages.failure') }
- %w(site content_types assets asset_collections snippets pages).each do |step| - %w(site content_types assets snippets pages).each do |step|
%li{ :id => "#{step}-step" } %li{ :id => "#{step}-step" }
%em %em
%strong %strong

View File

@ -8,7 +8,7 @@
- if multi_sites? - if multi_sites?
- content_for :buttons do - content_for :buttons do
= admin_button_tag t('.new_site'), new_admin_site_url, :class => 'new' = admin_button_tag t('.new_site'), new_admin_site_url, :class => 'new' if can?(:manage, Site)
%p= t('.help') %p= t('.help')

View File

@ -2,23 +2,30 @@
= include_javascripts :image_picker, :edit_page = include_javascripts :image_picker, :edit_page
= include_stylesheets :editable_elements, :fancybox = include_stylesheets :editable_elements, :fancybox
= f.foldable_inputs :name => :information do - if can?(:manage, @page)
= f.input :title = f.foldable_inputs :name => :information do
= f.input :title, :wrapper_html => { :class => 'highlighted' }
- if not @page.index? and not @page.not_found? - if not @page.index? and not @page.not_found?
= f.input :parent_id, :as => :select, :collection => parent_pages_options, :include_blank => false = f.input :parent_id, :as => :select, :collection => parent_pages_options, :include_blank => false
= f.input :slug, :required => false, :hint => @page.slug.blank? ? '&nbsp;' : page_url(@page), :input_html => { :data_url => get_path_admin_pages_url, :disabled => @page.index? || @page.not_found? }, :wrapper_html => { :style => "#{'display: none' if @page.templatized?}; height: 50px" } = f.input :slug, :required => false, :hint => @page.slug.blank? ? '&nbsp;' : page_url(@page), :input_html => { :'data-url' => get_path_admin_pages_url, :disabled => @page.index? || @page.not_found? }, :wrapper_html => { :style => "#{'display: none' if @page.templatized?};" }
= f.foldable_inputs :name => :meta do = render 'editable_elements', :page => @page
= f.foldable_inputs :name => :seo do
= f.input :seo_title
= f.input :meta_keywords = f.input :meta_keywords
= f.input :meta_description = f.input :meta_description
= f.foldable_inputs :name => :advanced_options do - if can?(:manage, @page)
= f.input :content_type_id, :as => :select, :collection => current_site.content_types.all.to_a, :include_blank => false, :wrapper_html => { :style => "#{'display: none' unless @page.templatized?}; height: 50px" } = f.foldable_inputs :name => :advanced_options, :id => 'advanced-options' do
= f.input :content_type_id, :as => :select, :collection => current_site.content_types.all.to_a, :include_blank => false, :wrapper_html => { :style => "#{'display: none' unless @page.templatized?}" }
= f.custom_input :templatized, :css => 'toggle', :style => "#{'display: none' if @page.redirect?}" do = f.custom_input :templatized, :css => 'toggle', :style => "#{'display: none' if @page.redirect?}" do
= f.check_box :templatized = f.check_box :templatized
@ -36,13 +43,12 @@
= f.input :redirect_url, :required => true, :wrapper_html => { :style => "#{'display: none' unless @page.redirect?}" } = f.input :redirect_url, :required => true, :wrapper_html => { :style => "#{'display: none' unless @page.redirect?}" }
= render 'editable_elements', :page => @page
= f.foldable_inputs :name => :raw_template do = f.foldable_inputs :name => :raw_template do
= f.custom_input :value, :css => 'code full', :with_label => false do = f.custom_input :value, :css => 'code full', :with_label => false do
= f.label :raw_template = f.label :raw_template
%code{ :class => 'html' } %code{ :class => 'html' }
= f.text_area :raw_template = f.text_area :raw_template
= f.errors_on :template = f.errors_on :template
.more .more
= link_to t('admin.image_picker.link'), admin_theme_assets_path, :id => 'image-picker-link' = link_to t('admin.image_picker.link'), admin_theme_assets_path, :id => 'image-picker-link', :class => 'picture'

View File

@ -1,5 +1,8 @@
%li{ :id => "item-#{page.id}", :class => "#{'not-found' if page.not_found? } #{'templatized' if page.templatized?}"} %li{ :id => "item-#{page.id}", :class => "#{'not-found' if page.not_found? } #{'templatized' if page.templatized?}"}
- with_children = !page.children.empty?
- children = can?(:manage, page) ? page.children : page.children.find_all { |p| !p.templatized? }
- with_children = !children.empty?
- if not page.index? and with_children - if not page.index? and with_children
= image_tag 'admin/list/icons/node_closed.png', :class => 'toggler' = image_tag 'admin/list/icons/node_closed.png', :class => 'toggler'
@ -10,9 +13,10 @@
%span!= t('.updated_at') %span!= t('.updated_at')
= l page.updated_at, :format => :short = l page.updated_at, :format => :short
- if not page.index? and not page.not_found? - if !page.index_or_not_found? && can?(:manage, page)
= link_to image_tag('admin/list/icons/trash.png'), admin_page_url(page), :class => 'remove', :confirm => t('admin.messages.confirm'), :method => :delete = link_to image_tag('admin/list/icons/trash.png'), admin_page_url(page), :class => 'remove', :confirm => t('admin.messages.confirm'), :method => :delete
- if with_children - if with_children
%ul{ :id => "folder-#{page._id}", :class => "folder depth-#{(page.depth || 0) + 1}", :data_url => sort_admin_page_url(page), :style => "display: #{cookies["folder-#{page._id}"] || 'block'}" } %ul{ :id => "folder-#{page._id}", :class => "folder depth-#{(page.depth || 0) + 1}", :'data-url' => sort_admin_page_url(page), :style => "display: #{cookies["folder-#{page._id}"] || 'block'}" }
= render page.children
= render children

View File

@ -9,7 +9,8 @@
- content_for :actions do - content_for :actions do
= render 'admin/shared/actions/contents' = render 'admin/shared/actions/contents'
- content_for :buttons do - if can? :create, Page
- content_for :buttons do
= admin_button_tag :new, new_admin_page_url, :class => 'new' = admin_button_tag :new, new_admin_page_url, :class => 'new'
%p!= t('.help') %p!= t('.help')

View File

@ -1,4 +1,4 @@
.actions #local-actions-bottom-bar
.span-12 .span-12
%p %p
- if defined?(back_url) - if defined?(back_url)

View File

@ -1,5 +1,4 @@
%ul#menu %ul#menu
= admin_menu_item('contents', admin_pages_url) = admin_menu_item('contents', admin_pages_url)
= admin_menu_item('assets', admin_asset_collections_url)
= admin_menu_item('settings', edit_admin_current_site_url) = admin_menu_item('settings', edit_admin_current_site_url)
%li.clear %li.clear

View File

@ -1 +0,0 @@
= link_to content_tag(:span, t('admin.asset_collections.index.new')), new_admin_asset_collection_url

View File

@ -1 +1,2 @@
= link_to content_tag(:em) + content_tag(:span, t('admin.content_types.index.new')), new_admin_content_type_url - if can? :manage, ContentType
= link_to content_tag(:em) + content_tag(:span, t('admin.content_types.index.new')), new_admin_content_type_url

View File

@ -1,3 +0,0 @@
- @asset_collections.each do |c|
%li
= link_to content_tag(:span, truncate(c.name, :length => 20)), edit_admin_asset_collection_url(c), :class => "#{'on' if @asset_collection.id == c.id}"

View File

@ -1,4 +1,5 @@
= admin_submenu_item 'pages', admin_pages_url do = admin_submenu_item 'pages', admin_pages_url do
- if can? :manage, @page
.header .header
%p= link_to t('admin.pages.index.new'), new_admin_page_url %p= link_to t('admin.pages.index.new'), new_admin_page_url
.inner .inner
@ -12,6 +13,10 @@
- each_content_type_menu_item do |content_type| - each_content_type_menu_item do |content_type|
.header .header
%p= link_to t('admin.contents.index.new'), new_admin_content_url(content_type.slug) %p= link_to t('admin.contents.index.new'), new_admin_content_url(content_type.slug)
- if can? :manage, content_type
%p.edit= link_to t('admin.contents.index.edit'), edit_admin_content_type_url(content_type)
.inner .inner
%h2!= t('admin.contents.index.lastest_items') %h2!= t('admin.contents.index.lastest_items')
%ul %ul

View File

@ -11,4 +11,4 @@
%code{ :class => 'html' } %code{ :class => 'html' }
= f.text_area :template = f.text_area :template
.more .more
= link_to t('admin.image_picker.link'), admin_theme_assets_path, :id => 'image-picker-link' = link_to t('admin.image_picker.link'), admin_theme_assets_path, :id => 'image-picker-link', :class => 'picture'

View File

@ -6,7 +6,7 @@
- content_for :buttons do - content_for :buttons do
= admin_button_tag t('admin.snippets.index.new'), new_admin_snippet_url, :class => 'new' = admin_button_tag t('admin.snippets.index.new'), new_admin_snippet_url, :class => 'new'
%p!= t('.help') %p!= t('.help', :slug => @snippet.slug)
= semantic_form_for @snippet, :url => admin_snippet_url(@snippet), :html => { :class => 'save-with-shortcut' } do |form| = semantic_form_for @snippet, :url => admin_snippet_url(@snippet), :html => { :class => 'save-with-shortcut' } do |form|

View File

@ -19,14 +19,14 @@
- if @theme_asset.new_record? - if @theme_asset.new_record?
= f.input :plain_text_name = f.input :plain_text_name
= f.custom_input :content_type do = f.custom_input :plain_text_type do
= f.select :content_type, %w(stylesheet javascript) = f.select :plain_text_type, %w(stylesheet javascript)
= f.custom_input :plain_text, :css => 'full', :with_label => false do = f.custom_input :plain_text, :css => 'full', :with_label => false do
%code{ :class => (@theme_asset.size && @theme_asset.size > 40000 ? 'nude' : (@theme_asset.content_type || 'stylesheet')) } %code{ :class => (@theme_asset.size && @theme_asset.size > 40000 ? 'nude' : (@theme_asset.content_type || 'stylesheet')) }
= f.text_area :plain_text = f.text_area :plain_text
.more .more
= link_to t('admin.image_picker.link'), admin_theme_assets_path, :id => 'image-picker-link' = link_to t('admin.image_picker.link'), admin_theme_assets_path, :id => 'image-picker-link', :class => 'picture'
%span.alt %span.alt
!= t('admin.theme_assets.form.choose_file') != t('admin.theme_assets.form.choose_file')

View File

@ -3,10 +3,16 @@
- content_for :submenu do - content_for :submenu do
= render 'admin/shared/menu/settings' = render 'admin/shared/menu/settings'
- content_for :buttons do - if can?(:manage, ThemeAsset)
- content_for :buttons do
= admin_button_tag t('admin.theme_assets.index.new'), new_admin_theme_asset_url, :class => 'new' = admin_button_tag t('admin.theme_assets.index.new'), new_admin_theme_asset_url, :class => 'new'
%p!= t('.help', :url => @theme_asset.source.url) %p
- if %w(image javascript stylesheet).include?(@theme_asset.content_type.to_s)
!= t(".help_#{@theme_asset.content_type}", :path => @theme_asset.local_path(true), :width => @theme_asset.width, :height => @theme_asset.height)
!= t('.help', :url => @theme_asset.source.url)
= semantic_form_for @theme_asset, :url => admin_theme_asset_url(@theme_asset), :html => { :multipart => true, :class => 'save-with-shortcut' } do |form| = semantic_form_for @theme_asset, :url => admin_theme_asset_url(@theme_asset), :html => { :multipart => true, :class => 'save-with-shortcut' } do |form|

View File

@ -4,29 +4,31 @@
= render 'admin/shared/menu/settings' = render 'admin/shared/menu/settings'
- content_for :buttons do - content_for :buttons do
= admin_button_tag t('admin.theme_assets.index.all'), all_admin_theme_assets_url, :class => 'show' = admin_button_tag t('admin.theme_assets.index.all'), all_admin_theme_assets_url, :class => 'show' if can?(:manage, ThemeAsset)
= admin_button_tag t('admin.snippets.index.new'), new_admin_snippet_url, :class => 'new' = admin_button_tag t('admin.snippets.index.new'), new_admin_snippet_url, :class => 'new' if can?(:manage, Snippet)
= admin_button_tag :new, new_admin_theme_asset_url, :class => 'new' = admin_button_tag :new, new_admin_theme_asset_url, :class => 'new' if can?(:manage, ThemeAsset)
%p!= t('.help') %p!= t('.help')
%h3!= t('.snippets') - if can?(:manage, Snippet)
- if @snippets.empty? %h3!= t('.snippets')
- if @snippets.empty?
%p.no-items!= t('admin.snippets.index.no_items', :url => new_admin_snippet_url) %p.no-items!= t('admin.snippets.index.no_items', :url => new_admin_snippet_url)
- else - else
%ul.list.theme-assets %ul.list.theme-assets
= render @snippets = render @snippets
%br %br
%h3!= t('.css_and_js') - if can?(:manage, ThemeAsset)
- if @js_and_css_assets.empty? %h3!= t('.css_and_js')
- if @js_and_css_assets.empty?
%p.no-items!= t('.no_items', :url => new_admin_theme_asset_url) %p.no-items!= t('.no_items', :url => new_admin_theme_asset_url)
- else - else
%ul.list.theme-assets %ul.list.theme-assets
= render :partial => 'asset', :collection => @js_and_css_assets = render :partial => 'asset', :collection => @js_and_css_assets
%br %br
%h3!= t('.images') %h3!= t('.images')
- if @assets[:images].nil? - if @assets[:images].nil?
@ -35,7 +37,8 @@
%ul.list.theme-assets %ul.list.theme-assets
= render :partial => 'asset', :collection => @assets[:images] = render :partial => 'asset', :collection => @assets[:images]
- if @assets[:fonts] - if can?(:manage, ThemeAsset)
- if @assets[:fonts]
%br %br
%h3!= t('.fonts') %h3!= t('.fonts')

View File

@ -45,7 +45,5 @@ module Locomotive
# Configure sensitive parameters which will be filtered from the log file. # Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters << :password config.filter_parameters << :password
config.middleware.insert_after Rack::Lock, '::Locomotive::Middlewares::Fonts', :path => %r{^/fonts}
end end
end end

View File

@ -38,13 +38,6 @@ javascripts:
- public/javascripts/admin/plugins/mustache.js - public/javascripts/admin/plugins/mustache.js
- public/javascripts/admin/custom_fields/category.js - public/javascripts/admin/custom_fields/category.js
- public/javascripts/admin/custom_fields/has_many.js - public/javascripts/admin/custom_fields/has_many.js
asset_collections:
- public/javascripts/admin/plugins/fancybox.js
- public/javascripts/admin/plugins/mustache.js
- public/javascripts/admin/custom_fields.js
- public/javascripts/admin/asset_collections.js
assets:
- public/javascripts/admin/assets.js
contents: contents:
- public/javascripts/admin/plugins/tiny_mce/tinymce.js - public/javascripts/admin/plugins/tiny_mce/tinymce.js
- public/javascripts/admin/contents.js - public/javascripts/admin/contents.js

View File

@ -1,2 +1,8 @@
default: features --require features --format pretty --color --tags ~@wip <%
wip: features --require features --tags @wip rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} --strict --tags ~@wip"
%>
default: <%= std_opts %> features
wip: --tags @wip:3 --wip features
rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip

View File

@ -1,90 +1,104 @@
require 'locomotive' require 'locomotive'
## patches ##
module Devise
module Models
class << self
def hook(base)
if base.is_a?(Module)
base.class_eval do
attr_accessor :devise_modules
def devise_modules
@devise_modules ||= []
end
end
else
base.class_eval do
class_attribute :devise_modules, :instance_writer => false
self.devise_modules ||= []
end
end
end
alias :included :hook
alias :extended :hook
end
end
end
# Use this hook to configure devise mailer, warden hooks and so forth. The first # Use this hook to configure devise mailer, warden hooks and so forth. The first
# four configuration values can also be set straight in your models. # four configuration values can also be set straight in your models.
Devise.setup do |config| Devise.setup do |config|
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in DeviseMailer. # Configure the e-mail address which will be shown in DeviseMailer.
config.mailer_sender = Locomotive.config.mailer_sender config.mailer_sender = Locomotive.config.mailer_sender
# Configure the class responsible to send e-mails.
# config.mailer = "Devise::Mailer"
# ==> ORM configuration
# Load and configure the ORM. Supports :active_record (default) and
# :mongoid (bson_ext recommended) by default. Other ORMs may be
# available as additional gems.
require 'devise/orm/mongoid'
# ==> Configuration for any authentication mechanism # ==> Configuration for any authentication mechanism
# Configure which keys are used when authenticating an user. By default is # Configure which keys are used when authenticating a user. The default is
# just :email. You can configure it to use [:username, :subdomain], so for # just :email. You can configure it to use [:username, :subdomain], so for
# authenticating an user, both parameters are required. Remember that those # authenticating a user, both parameters are required. Remember that those
# parameters are used only when authenticating and not when retrieving from # parameters are used only when authenticating and not when retrieving from
# session. If you need permissions, you should implement that in a before filter. # session. If you need permissions, you should implement that in a before filter.
# You can also supply a hash where the value is a boolean determining whether
# or not authentication should be aborted when the value is not present.
# config.authentication_keys = [ :email ] # config.authentication_keys = [ :email ]
# Configure parameters from the request object used for authentication. Each entry
# given should be a request method and it will automatically be passed to the
# find_for_authentication method and considered in your model lookup. For instance,
# if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
# The same considerations mentioned for authentication_keys also apply to request_keys.
# config.request_keys = []
# Configure which authentication keys should be case-insensitive.
# These keys will be downcased upon creating or modifying a user and when used
# to authenticate or find a user. Default is :email.
config.case_insensitive_keys = [ :email ]
# Tell if authentication through request.params is enabled. True by default. # Tell if authentication through request.params is enabled. True by default.
# config.params_authenticatable = true # config.params_authenticatable = true
# Tell if authentication through HTTP Basic Auth is enabled. True by default. # Tell if authentication through HTTP Basic Auth is enabled. False by default.
# config.http_authenticatable = true # config.http_authenticatable = false
# The realm used in Http Basic Authentication # If http headers should be returned for AJAX requests. True by default.
# config.http_authenticatable_on_xhr = true
# The realm used in Http Basic Authentication. "Application" by default.
# config.http_authentication_realm = "Application" # config.http_authentication_realm = "Application"
# ==> Configuration for :database_authenticatable # ==> Configuration for :database_authenticatable
# Invoke `rake secret` and use the printed value to setup a pepper to generate # For bcrypt, this is the cost for hashing the password and defaults to 10. If
# the encrypted password. By default no pepper is used. # using other encryptors, it sets how many times you want the password re-encrypted.
# config.pepper = "rake secret output" config.stretches = 10
# Configure how many times you want the password is reencrypted. Default is 10. # Setup a pepper to generate the encrypted password.
# config.stretches = 10 # config.pepper = "de368d6a1517489510a2ae145328ff1c238f03b02da8f57032936a353835e2ca20561decfb5f7bfafad095fa73cee55b101ed11a0d0f913429d3d9bd114d810e"
# Define which will be the encryption algorithm. Supported algorithms are :sha1
# (default), :sha512 and :bcrypt. Devise also supports encryptors from others
# authentication tools as :clearance_sha1, :authlogic_sha512 (then you should set
# stretches above to 20 for default behavior) and :restful_authentication_sha1
# (then you should set stretches to 10, and copy REST_AUTH_SITE_KEY to pepper)
config.encryptor = :sha1
# ==> Configuration for :confirmable # ==> Configuration for :confirmable
# The time you want give to your user to confirm his account. During this time # The time you want to give your user to confirm his account. During this time
# he will be able to access your application without confirming. Default is nil. # he will be able to access your application without confirming. Default is 0.days
# When confirm_within is zero, the user won't be able to sign in without confirming.
# You can use this to let your user access some features of your application
# without confirming the account, but blocking it after a certain period
# (ie 2 days).
# config.confirm_within = 2.days # config.confirm_within = 2.days
# Defines which key will be used when confirming an account
# config.confirmation_keys = [ :email ]
# ==> Configuration for :rememberable # ==> Configuration for :rememberable
# The time the user will be remembered without asking for credentials again. # The time the user will be remembered without asking for credentials again.
# config.remember_for = 2.weeks config.remember_for = 2.weeks
# If true, a valid remember token can be re-used between multiple browsers.
# config.remember_across_browsers = true
# If true, extends the user's remember period when remembered via cookie.
# config.extend_remember_period = false
# If true, uses the password salt as remember token. This should be turned
# to false if you are not using database authenticatable.
config.use_salt_as_remember_token = true
# Options to be passed to the created cookie. For instance, you can set
# :secure => true in order to force SSL only cookies.
# config.cookie_options = {}
# ==> Configuration for :validatable # ==> Configuration for :validatable
# Range for password length # Range for password length. Default is 6..128.
# config.password_length = 6..20 # config.password_length = 6..128
# Regex to use to validate the email address # Regex to use to validate the email address
# config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i # config.email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
# ==> Configuration for :timeoutable # ==> Configuration for :timeoutable
# The time you want to timeout the user session without activity. After this # The time you want to timeout the user session without activity. After this
# time the user will be asked for credentials again. # time the user will be asked for credentials again. Default is 30 minutes.
# config.timeout_in = 10.minutes # config.timeout_in = 30.minutes
# ==> Configuration for :lockable # ==> Configuration for :lockable
# Defines which strategy will be used to lock an account. # Defines which strategy will be used to lock an account.
@ -92,9 +106,12 @@ Devise.setup do |config|
# :none = No lock strategy. You should handle locking by yourself. # :none = No lock strategy. You should handle locking by yourself.
# config.lock_strategy = :failed_attempts # config.lock_strategy = :failed_attempts
# Defines which key will be used when locking and unlocking an account
# config.unlock_keys = [ :email ]
# Defines which strategy will be used to unlock an account. # Defines which strategy will be used to unlock an account.
# :email = Sends an unlock link to the user email # :email = Sends an unlock link to the user email
# :time = Reanables login after a certain ammount of time (see :unlock_in below) # :time = Re-enables login after a certain amount of time (see :unlock_in below)
# :both = Enables both strategies # :both = Enables both strategies
# :none = No unlock strategy. You should handle unlocking by yourself. # :none = No unlock strategy. You should handle unlocking by yourself.
# config.unlock_strategy = :both # config.unlock_strategy = :both
@ -106,35 +123,74 @@ Devise.setup do |config|
# Time interval to unlock the account if :time is enabled as unlock_strategy. # Time interval to unlock the account if :time is enabled as unlock_strategy.
# config.unlock_in = 1.hour # config.unlock_in = 1.hour
# ==> Configuration for :recoverable
#
# Defines which key will be used when recovering the password for an account
# config.reset_password_keys = [ :email ]
# Time interval you can reset your password with a reset password key.
# Don't put a too small interval or your users won't have the time to
# change their passwords.
config.reset_password_within = 2.hours
# ==> Configuration for :encryptable
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
# :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
# and :restful_authentication_sha1 (then you should set stretches to 10, and copy
# REST_AUTH_SITE_KEY to pepper)
# config.encryptor = :sha1
# ==> Configuration for :token_authenticatable # ==> Configuration for :token_authenticatable
# Defines name of the authentication token params key # Defines name of the authentication token params key
# config.token_authentication_key = :auth_token # config.token_authentication_key = :auth_token
# ==> General configuration # If true, authentication through token does not store user in session and needs
# Load and configure the ORM. Supports :active_record (default), :mongoid # to be supplied on each request. Useful if you are using the token as API token.
# and :data_mapper (experimental). # config.stateless_token = false
require 'active_support/core_ext/class/attribute'
require 'devise/orm/mongoid'
# ==> Scopes configuration
# Turn scoped views on. Before rendering "sessions/new", it will first check for # Turn scoped views on. Before rendering "sessions/new", it will first check for
# "sessions/users/new". It's turned off by default because it's slower if you # "users/sessions/new". It's turned off by default because it's slower if you
# are using only default views. # are using only default views.
config.scoped_views = true config.scoped_views = true
# Configure the default scope used by Devise. By default it's the first devise # Configure the default scope given to Warden. By default it's the first
# role declared in your routes. # devise role declared in your routes (usually :user).
config.default_scope = :account config.default_scope = :account
# If you want to use other strategies, that are not (yet) supported by Devise, # Configure sign_out behavior.
# you can configure them inside the config.warden block. The example below # Sign_out action can be scoped (i.e. /users/sign_out affects only :user scope).
# allows you to setup OAuth, using http://github.com/roman/warden_oauth # The default is true, which means any logout action will sign out all active scopes.
# config.sign_out_all_scopes = true
# ==> Navigation configuration
# Lists the formats that should be treated as navigational. Formats like
# :html, should redirect to the sign in page when the user does not have
# access, but formats like :xml or :json, should return 401.
#
# If you have any extra navigational formats, like :iphone or :mobile, you
# should add them to the navigational formats lists.
#
# The :"*/*" and "*/*" formats below is required to match Internet
# Explorer requests.
# config.navigational_formats = [:"*/*", "*/*", :html]
# The default HTTP method used to sign out a resource. Default is :get.
# config.sign_out_via = :get
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo'
# ==> Warden configuration
# If you want to use other strategies, that are not supported by Devise, or
# change the failure app, you can configure them inside the config.warden block.
# #
# config.warden do |manager| # config.warden do |manager|
# manager.oauth(:twitter) do |twitter| # manager.failure_app = AnotherApp
# twitter.consumer_secret = <YOUR CONSUMER SECRET> # manager.intercept_401 = false
# twitter.consumer_key = <YOUR CONSUMER KEY> # manager.default_strategies(:scope => :user).unshift :some_external_strategy
# twitter.options :site => 'http://twitter.com'
# end
# manager.default_strategies(:scope => :user).unshift :twitter_oauth
# end # end
end end

View File

@ -0,0 +1,31 @@
require 'locomotive'
unless Locomotive.engine?
require 'dragonfly'
## initialize Dragonfly ##
app = Dragonfly[:images]
app.configure_with(:rails)
app.configure_with(:imagemagick)
## configure it ##
Dragonfly[:images].configure do |c|
# Convert absolute location needs to be specified
# to avoid issues with Phusion Passenger not using $PATH
convert = `which convert`.strip.presence || "/usr/local/bin/convert"
c.convert_command = convert
c.identify_command = convert
c.allow_fetch_url = true
c.allow_fetch_file = true
c.url_format = '/images/dynamic/:job/:basename.:format'
end
end

View File

@ -62,4 +62,16 @@ Locomotive.configure do |config|
# config.mailer_sender = 'support' # config.mailer_sender = 'support'
# # => 'support@heroku.com' (Heroku), 'support@bushi.do' (Bushido), 'support@example.com' (Dev) or 'support@<your_hosting_platform>' (Multi-sites) # # => 'support@heroku.com' (Heroku), 'support@bushi.do' (Bushido), 'support@example.com' (Dev) or 'support@<your_hosting_platform>' (Multi-sites)
config.mailer_sender = 'support' config.mailer_sender = 'support'
# Rack-cache settings, mainly used for the inline resizing image module. Default options:
# config.rack_cache = {
# :verbose => true,
# :metastore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/meta"), # URI encoded in case of spaces
# :entitystore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/body")
# }
# If you do want to disable it for good, just use the following syntax
# config.rack_cache = false
#
# Note: by default, rack/cache is disabled in the Heroku platform
end unless Locomotive.engine? || Rails.env.test? end unless Locomotive.engine? || Rails.env.test?

View File

@ -6,4 +6,5 @@ require 'digest/sha1'
# Make sure the secret is at least 30 characters and all random, # Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks. # no regular words or you'll be exposed to dictionary attacks.
token = ENV['BUSHIDO_SALT'] || 'aa84844b97e90edda8e005a686d82c3bef1f8e20a1255301f1d0886fc592a45ef2393d64b0c3d3ea858b1f6406ad6f15305666264716a79fcfa17de93ad0d69d' token = ENV['BUSHIDO_SALT'] || 'aa84844b97e90edda8e005a686d82c3bef1f8e20a1255301f1d0886fc592a45ef2393d64b0c3d3ea858b1f6406ad6f15305666264716a79fcfa17de93ad0d69d'
Rails.application.config.secret_token = Digest::SHA1.hexdigest(token) Rails.application.config.secret_token = Digest::SHA1.hexdigest(token)

View File

@ -61,8 +61,10 @@ de:
title: Optionen title: Optionen
help: Organisiere alle Optionen für die Auswahlbox. help: Organisiere alle Optionen für die Auswahlbox.
collection_label: Liste der Optionen collection_label: Liste der Optionen
custom_form: types:
category:
edit_categories: Optionen edit_categories: Optionen
file:
delete_file: Datei löschen delete_file: Datei löschen
index: index:
is_required: ist erforderlich is_required: ist erforderlich
@ -190,22 +192,6 @@ de:
title: Bilder anzeigen title: Bilder anzeigen
no_items: "Momentan gibt es keine Bilder." no_items: "Momentan gibt es keine Bilder."
asset_collections:
index:
title: Galerie
help: "Der Name der Galerie kann durch darauf klicken bearbeitet werden. Du kannst die Bilder in einer Galerie bearbeiten, indem du neue Felder hinzufügst."
new: neue Galerie
no_items: "Momentan gibt es keine Galerien. Klicke einfach <a href='%{url}'>hier</a>, um eine neue Galerie zu erstellen."
new:
title: Neue Galerie
help: "Gib erst mal einen Namen ein. Alle anderen Einstellungen kannst du vornehmen, sobald das Formular abgesendet ist."
edit:
help: "Der Name der Galerie kann durch darauf klicken bearbeitet werden. Du kannst Bilder in einer Galerie bearbeiten, indem du neue Felder hinzufügst."
add_asset: Bild hinzufügen
destroy: Galerie löschen
no_items: "Momentan gibt es keine Bilder. Klicke einfach <a href='%{url}'>hier</a>, um das erste Bild zu erstellen."
ask_for_name: "Gib den neuen Namen ein"
assets: assets:
new: new:
title: Neues Bild title: Neues Bild
@ -276,7 +262,7 @@ de:
title: Cross-Domain Authentifizierung title: Cross-Domain Authentifizierung
notice: Du wirst zu der Webseite in ein paar Sekunden weitergeleitet. notice: Du wirst zu der Webseite in ein paar Sekunden weitergeleitet.
imports: import:
new: new:
title: Import title: Import
help: "Passe bitte auf, wenn du ein neues Template für deine bestehende Webseite hochlädst. Deine bestehenden Daten könnten verändert oder gelöscht werden!" help: "Passe bitte auf, wenn du ein neues Template für deine bestehende Webseite hochlädst. Deine bestehenden Daten könnten verändert oder gelöscht werden!"
@ -287,7 +273,6 @@ de:
site: Webseiten-Informationen site: Webseiten-Informationen
content_types: Benutzerdefinierte Inhalts-Typen content_types: Benutzerdefinierte Inhalts-Typen
assets: Template-Dateien assets: Template-Dateien
asset_collections: Galerien
snippets: Snippets snippets: Snippets
pages: Seiten pages: Seiten
messages: messages:

View File

@ -6,6 +6,7 @@ en:
change_password: Update change_password: Update
new_item: "+ add" new_item: "+ add"
switch_to_site: Go switch_to_site: Go
delete: "Delete"
messages: messages:
confirm: Are you sure ? confirm: Are you sure ?
@ -60,8 +61,10 @@ en:
title: Edit options title: Edit options
help: Manage the list of options for your select box. help: Manage the list of options for your select box.
collection_label: List of options collection_label: List of options
custom_form: types:
category:
edit_categories: Edit options edit_categories: Edit options
file:
delete_file: Delete file delete_file: Delete file
index: index:
is_required: is required is_required: is required
@ -99,7 +102,7 @@ en:
updated_at: updated at updated_at: updated at
edit: edit:
show: show show: show
help: "The page title can be updated by clicking it." help: "The page title can be updated by clicking it. To apply your changes, click on the \"Update\" button."
ask_for_title: "Please type the new page title" ask_for_title: "Please type the new page title"
form: form:
delete_file: Delete file delete_file: Delete file
@ -123,7 +126,7 @@ en:
help: "Fill in the form below to update your snippet." help: "Fill in the form below to update your snippet."
edit: edit:
title: Editing snippet title: Editing snippet
help: "Fill in the form below to update your snippet." help: "Include your snippet in your page templates with the following liquid code : <span class='code'>{% include '%{slug}' %}</span>."
snippet: snippet:
updated_at: Updated at updated_at: Updated at
@ -134,12 +137,17 @@ en:
current_sites: current_sites:
edit: edit:
export: export
import: import import: import
new_membership: add account new_membership: add account
help: "The site name can be updated by clicking it." help: "The site name can be updated by clicking it. To apply your changes, click on the \"Update\" button."
ask_for_name: "Please type the new site name" ask_for_name: "Please type the new site name"
memberships: memberships:
roles:
admin: Administrator
designer: Designer
author: Author
new: new:
title: New membership title: New membership
help: "Please give the account email to add. If it does not exist, you will be redirected to the account creation form." help: "Please give the account email to add. If it does not exist, you will be redirected to the account creation form."
@ -151,7 +159,7 @@ en:
my_accounts: my_accounts:
edit: edit:
help: "Your name can be updated by clicking it." help: "Your name can be updated by clicking it. To apply your changes, click on the \"Update\" button."
new_site: new site new_site: new site
en: English en: English
de: German de: German
@ -163,7 +171,7 @@ en:
theme_assets: theme_assets:
index: index:
title: Listing theme files title: Listing theme files
help: "The theme files section is the place where you manage the files needed by your layout, ...etc. If you need to manage an image gallery, go to the Assets section instead." help: "The theme files section is the place where you manage the files needed by your layout, snippets...etc. If you need to manage an image gallery, create a new content type instead.<br/><b>Warning:</b> you may not see all the assets depending on your rights."
all: all assets all: all assets
new: new file new: new file
snippets: Snippets snippets: Snippets
@ -171,7 +179,7 @@ en:
fonts: Fonts fonts: Fonts
images: Images images: Images
medias: Medias medias: Medias
no_items: "There are no files for now. Just click <a href=\"%{url}\">here</a> to create the first one." no_items: "There are no files for now."
asset: asset:
updated_at: Updated at updated_at: Updated at
new: new:
@ -179,7 +187,10 @@ en:
help: "You have the choice to either upload any file or to copy/paste a stylesheet or a javascript in plain text." help: "You have the choice to either upload any file or to copy/paste a stylesheet or a javascript in plain text."
edit: edit:
title: "Editing %{file}" title: "Editing %{file}"
help: "This asset is accessible from the following url: <a href='%{url}'>%{url}</a>" help: "This asset is accessible directly from the following url: <a href='%{url}'>%{url}</a>"
help_image: "Include your image in your page templates or snippets with the following liquid code : <span class='code'>{{ '%{path}' | theme_image_tag }}</span>.<br/>Your current image dimensions : <b>%{width}px x %{height}px</b>.<br/>"
help_javascript: "Include your javascript file in your page templates or snippets with the following code : <span class='code'>{{ '%{path}' | javascript_tag }}</span>.<br/>"
help_stylesheet: "Include your stylesheet file in your page templates or snippets with the following code : <span class='code'>{{ '%{path}' | stylesheet_tag }}</span>.<br/>"
form: form:
picker_link: Insert a file into the code picker_link: Insert a file into the code
choose_file: Choose file choose_file: Choose file
@ -188,22 +199,6 @@ en:
title: Listing images title: Listing images
no_items: "There are no files for now." no_items: "There are no files for now."
asset_collections:
index:
title: Asset collections
help: "The collection name can be updated by clicking it. You can customize assets in a collection by adding new fields."
new: new collection
no_items: "There are no collections for now. Just click <a href=\"%{url}\">here</a> to create the first one."
new:
title: New collection
help: "For now, just type a name. Other settings will come once the form is sent."
edit:
help: "The collection name can be updated by clicking it. You can customize assets in a collection by adding new fields."
add_asset: add asset
destroy: remove collection
no_items: "There are no assets for now. Just click <a href=\"%{url}\">here</a> to create the first one."
ask_for_name: "Please type the new name"
assets: assets:
new: new:
title: New asset title: New asset
@ -225,8 +220,8 @@ en:
new_item: new item new_item: new item
form: form:
order_by: order_by:
created_at: 'By "created at" date' created_at: 'By creation date'
updated_at: 'By "updated at" date' updated_at: 'By updating date'
position_in_list: Manually position_in_list: Manually
order_direction: order_direction:
asc: Ascending asc: Ascending
@ -257,7 +252,7 @@ en:
title: Cross-domain authentication title: Cross-domain authentication
notice: You will be redirected to the website in a couple of seconds. notice: You will be redirected to the website in a couple of seconds.
imports: import:
new: new:
title: Import site template title: Import site template
help: "Be careful when you upload a new template for your existing website, your current data could be modified or even removed." help: "Be careful when you upload a new template for your existing website, your current data could be modified or even removed."
@ -268,7 +263,6 @@ en:
site: Site information site: Site information
content_types: Custom content types content_types: Custom content types
assets: Theme files assets: Theme files
asset_collections: Asset collections
snippets: Snippets snippets: Snippets
pages: Pages pages: Pages
messages: messages:

View File

@ -16,6 +16,7 @@ fr:
change_password: Mettre à jour change_password: Mettre à jour
new_item: "+ ajouter" new_item: "+ ajouter"
switch_to_site: Aller switch_to_site: Aller
delete: "Supprimer"
messages: messages:
confirm: "Êtes-vous sûr(e) ?" confirm: "Êtes-vous sûr(e) ?"
@ -60,8 +61,10 @@ fr:
title: Editer options title: Editer options
help: Gèrer la liste des options de votre liste déroulante help: Gèrer la liste des options de votre liste déroulante
collection_label: Liste des options collection_label: Liste des options
custom_form: types:
category:
edit_categories: Editer options edit_categories: Editer options
file:
delete_file: Supprimer fichier delete_file: Supprimer fichier
index: index:
is_required: est obligatoire is_required: est obligatoire
@ -99,7 +102,7 @@ fr:
updated_at: Mise à jour le updated_at: Mise à jour le
edit: edit:
show: voir show: voir
help: "Le titre de la page est modifiable en cliquant dessus." help: "Le titre de la page est modifiable en cliquant dessus. Pour appliquer votre modification, cliquez après sur le bouton \"Modifier\""
ask_for_title: "Veuillez entrer le nouveau titre" ask_for_title: "Veuillez entrer le nouveau titre"
form: form:
delete_file: Supprimer fichier delete_file: Supprimer fichier
@ -124,6 +127,7 @@ fr:
edit: edit:
title: Edition snippet title: Edition snippet
help: "Remplissez le formulaire ci-dessous pour mettre à jour votre snippet." help: "Remplissez le formulaire ci-dessous pour mettre à jour votre snippet."
help: "Utilisez votre snippet dans le template d'une page avec le code Liquid suivant : <span class='code'>{% include '%{slug}' %}</span>."
snippet: snippet:
updated_at: Mis à jour le updated_at: Mis à jour le
@ -134,9 +138,10 @@ fr:
current_sites: current_sites:
edit: edit:
export: exporter
import: importer import: importer
new_membership: ajouter compte new_membership: ajouter compte
help: "Le nom du site est modifiable en cliquant dessus." help: "Le nom du site est modifiable en cliquant dessus. Pour appliquer votre modification, cliquez après sur le bouton \"Modifier\""
ask_for_name: "Veuillez entrer le nouveau nom" ask_for_name: "Veuillez entrer le nouveau nom"
memberships: memberships:
@ -151,7 +156,7 @@ fr:
my_accounts: my_accounts:
edit: edit:
help: "Votre nom est modifiable en cliquant dessus." help: "Votre nom est modifiable en cliquant dessus. Pour appliquer votre modification, cliquez après sur le bouton \"Modifier\""
new_site: nouveau site new_site: nouveau site
en: en Anglais en: en Anglais
de: en Allemand de: en Allemand
@ -163,7 +168,7 @@ fr:
theme_assets: theme_assets:
index: index:
title: Liste des fichiers du thème title: Liste des fichiers du thème
help: "Les fichiers du thème sont utilisés pour construire le gabarit de vos pages. Si vous avez besoin d'une galerie d'images, la section Média est plus adéquate." help: "Les fichiers du thème sont utilisés pour construire le gabarit de vos pages. Si vous avez besoin d'une galerie d'images, créer un modèle sera plus adéquate.<br/><b>Attention : </b> Suivant les droits que vous avez, il se peut que vous ne puissiez pas voir tous les fichiers."
all: tous les fichiers all: tous les fichiers
new: nouveau fichier new: nouveau fichier
snippets: Snippets snippets: Snippets
@ -171,7 +176,7 @@ fr:
images: Images images: Images
medias: Médias medias: Médias
fonts: Polices fonts: Polices
no_items: "Il n'existe pas de fichiers. Vous pouvez commencer par créer un <a href='%{url}'>ici</a>." no_items: "Il n'existe pas de fichiers."
asset: asset:
updated_at: Mis à jour le updated_at: Mis à jour le
new: new:
@ -180,6 +185,11 @@ fr:
edit: edit:
title: "Edition %{file}" title: "Edition %{file}"
help: "L'url du fichier est <a href='%{url}'>%{url}</a>" help: "L'url du fichier est <a href='%{url}'>%{url}</a>"
help: "L'url du fichier est directement disponible : <a href='%{url}'>%{url}</a>"
help_image: "Utilisez votre image dans le template de vos pages ou snippets avec le code Liquid suivant : <span class='code'>{{ '%{path}' | theme_image_tag }}</span>.<br/>. Votre image a comme dimensions : <b>%{width}px x %{height}px</b>.<br/>"
help_javascript: "Utilisez votre javascript dans le template de vos pages avec le code Liquid suivant : <span class='code'>{{ '%{path}' | javascript_tag }}</span>.<br/>"
help_stylesheet: "Utilisez votre stylesheet dans le template de vos pages avec le code Liquid suivant : <span class='code'>{{ '%{path}' | stylesheet_tag }}</span>.<br/>"
form: form:
choose_file: Choisir fichier choose_file: Choisir fichier
choose_plain_text: Passer en mode texte choose_plain_text: Passer en mode texte
@ -187,22 +197,6 @@ fr:
title: Liste des images title: Liste des images
no_items: "Il n'y a pas d'images." no_items: "Il n'y a pas d'images."
asset_collections:
index:
title: Collections
help: "Le nom de la collection est modifiable en cliquant dessus. Vous pouvez personnaliser une collection en ajoutant d'autres champs à vos médias."
new: nouvelle collection
no_items: "Il n'existe pas de collections. Vous pouvez commencer par créer une <a href='%{url}'>ici</a>."
new:
title: Nouvelle collection
help: "Pour le moment, veuillez rentrer le nom. Les autres options viendront dans le formulaire suivant."
edit:
help: "Le nom de la collection est modifiable en cliquant dessus. Vous pouvez personnaliser une collection en ajoutant d'autres champs à vos médias."
add_asset: ajouter média
destroy: supprimer collection
no_items: "Il n'existe pas de médias. Vous pouvez commencer par créer un <a href='%{url}'>ici</a>."
ask_for_name: "Veuillez entrer le nouveau nom"
assets: assets:
new: new:
title: "Nouveau média" title: "Nouveau média"
@ -224,7 +218,7 @@ fr:
new_item: nouvel élément new_item: nouvel élément
form: form:
order_by: order_by:
created_at: 'Par date création' created_at: 'Par date de création'
updated_at: 'Par date de mise à jour' updated_at: 'Par date de mise à jour'
position_in_list: Manuellement position_in_list: Manuellement
order_direction: order_direction:
@ -256,7 +250,7 @@ fr:
title: Transfert vers un autre site title: Transfert vers un autre site
notice: Vous allez être redirigé(e) vers le site dans quelques secondes. notice: Vous allez être redirigé(e) vers le site dans quelques secondes.
imports: import:
new: new:
title: Importer template de site title: Importer template de site
help: "Faites attention quand vous envoyez un nouveau template sur votre site, les données de celui-ci pourront être modifiées voire même supprimées." help: "Faites attention quand vous envoyez un nouveau template sur votre site, les données de celui-ci pourront être modifiées voire même supprimées."
@ -267,7 +261,6 @@ fr:
site: Informations sur le site site: Informations sur le site
content_types: Modèles de données personnalisés content_types: Modèles de données personnalisés
assets: Fichiers du thème assets: Fichiers du thème
asset_collections: Collections de média
snippets: Snippets snippets: Snippets
pages: Pages pages: Pages
messages: messages:

View File

@ -60,8 +60,10 @@ it:
title: Modifica opzioni title: Modifica opzioni
help: Amministra la lista opzioni del select box. help: Amministra la lista opzioni del select box.
collection_label: Lista delle opzioni collection_label: Lista delle opzioni
custom_form: types:
category:
edit_categories: Modifica opzioni edit_categories: Modifica opzioni
file:
delete_file: Elimina file delete_file: Elimina file
index: index:
is_required: è richiesto is_required: è richiesto
@ -188,22 +190,6 @@ it:
title: Lista immagini title: Lista immagini
no_items: "Per ora non ci sono file." no_items: "Per ora non ci sono file."
asset_collections:
index:
title: Collezioni di risorse
help: "Puoi cambiare il nome della collezione cliccandoci sopra. Puoi personalizzare le risorse in una collezione aggiugendo nuovi campi."
new: nuov collezione
no_items: "Per ora non ci sono collezioni. Clicca <a href=\"%{url}\">qui</a> per creare la prima."
new:
title: Nuova collezione
help: "Per ora inserisci solo in nome. Altre opzioni appariranno dopo aver inviato il modulo."
edit:
help: "Puoi cambiare il nome della collezione cliccandoci sopra. Puoi personalizzare le risorse in una collezione aggiugendo nuovi campi."
add_asset: aggiungi risorsa
destroy: elimina collezione
no_items: "Per ora non ci sono risorse. Clicca <a href=\"%{url}\">qui</a> per creare la prima."
ask_for_name: "Prego, digita il nuovo nome"
assets: assets:
new: new:
title: Nuova risorsa title: Nuova risorsa
@ -257,7 +243,7 @@ it:
title: Autenticazione cross-domain title: Autenticazione cross-domain
notice: Sarai rediretto al sito web in pochi secondi. notice: Sarai rediretto al sito web in pochi secondi.
imports: import:
new: new:
title: Importa title: Importa
help: "Fai attenzione quando carichi un nuovo tema per il tuo sito, gli attuali dati potrebbero essere modificati o eliminati." help: "Fai attenzione quando carichi un nuovo tema per il tuo sito, gli attuali dati potrebbero essere modificati o eliminati."
@ -268,7 +254,6 @@ it:
site: Informazioni sito site: Informazioni sito
content_types: Tipi di contenuti personalizzati content_types: Tipi di contenuti personalizzati
assets: File del tema assets: File del tema
asset_collections: Collezioni di risorse
snippets: Frammenti snippets: Frammenti
pages: Pagine pages: Pagine
messages: messages:

View File

@ -60,8 +60,10 @@ pt-BR:
title: Editar opções title: Editar opções
help: Gerenciar a lista de opções da sua caixa de seleçõa. help: Gerenciar a lista de opções da sua caixa de seleçõa.
collection_label: Lista de opções collection_label: Lista de opções
custom_form: types:
category:
edit_categories: Editar opções edit_categories: Editar opções
file:
delete_file: Excluir arquivo delete_file: Excluir arquivo
sessions: sessions:
@ -185,22 +187,6 @@ pt-BR:
title: Listando imagens title: Listando imagens
no_items: "Não existem imagens ainda." no_items: "Não existem imagens ainda."
asset_collections:
index:
title: Coleções de arquivos
help: "O nome da coleção pode ser alterado clicando nele. Você pode customizar os arquivos nas coleções adicionando campos."
new: nova coleção
no_items: "Não existem coleções ainda. Clique <a href=\"%{url}\">aqui</a> para criar a primeira."
new:
title: Nova Coleção
help: "Por enquanto, apenas insira o nome. Outras opções irão aparecer após o formulário ser enviado."
edit:
help: "O nome da coleção pode ser alterado clicando nele. Você pode customizar os arquivos nas coleções adicionando campos."
add_asset: adicionar arquivo
destroy: excluir coleção
no_items: "Não existem coleções ainda. Clique <a href=\"%{url}\">aqui</a> para criar a primeira."
ask_for_name: Por favor preencha o novo nome"
assets: assets:
new: new:
title: Novo arquivo title: Novo arquivo
@ -251,7 +237,7 @@ pt-BR:
title: Autenticação por mútiplos domínios. title: Autenticação por mútiplos domínios.
notice: Você será redirecionado para o site em alguns segundos. notice: Você será redirecionado para o site em alguns segundos.
imports: import:
new: new:
title: Importar title: Importar
help: "Tenha cuidado ao enviar um novo tema ao seu site que já existe, seus dados atuais podem ser atualizados ou até removidos." help: "Tenha cuidado ao enviar um novo tema ao seu site que já existe, seus dados atuais podem ser atualizados ou até removidos."
@ -262,7 +248,6 @@ pt-BR:
site: Informações do site site: Informações do site
content_types: Tipos de Conteúdo customizados content_types: Tipos de Conteúdo customizados
assets: Arquivos do Tema assets: Arquivos do Tema
asset_collections: Coleções de Arquivos
snippets: Blocos snippets: Blocos
pages: Páginas pages: Páginas
messages: messages:

View File

@ -72,11 +72,7 @@ de:
highlighted_field_name: Hervorgehobener Feld-Name highlighted_field_name: Hervorgehobener Feld-Name
group_by_field_name: Gruppierung nach Feld-Name group_by_field_name: Gruppierung nach Feld-Name
api_enabled: API aktiviert api_enabled: API aktiviert
asset_collection:
name: Name
slug: Slug
asset: asset:
name: Name
source: Quelle source: Quelle
account: account:
email: Email email: Email

View File

@ -63,6 +63,7 @@ fr:
redirect: Redirection redirect: Redirection
redirect_url: Url de redirection redirect_url: Url de redirection
cache_strategy: Cache cache_strategy: Cache
seo_title: Titre SEO
content_type: content_type:
name: Nom name: Nom
description: Description description: Description
@ -71,11 +72,7 @@ fr:
highlighted_field_name: Champ mis en avant highlighted_field_name: Champ mis en avant
group_by_field_name: Champ pour grouper group_by_field_name: Champ pour grouper
api_enabled: Activation API api_enabled: Activation API
asset_collection:
name: Nom
slug: Raccourci
asset: asset:
name: Nom
source: Fichier source: Fichier
account: account:
email: E-mail email: E-mail

View File

@ -77,11 +77,7 @@ it:
highlighted_field_name: Campo evidenziato highlighted_field_name: Campo evidenziato
group_by_field_name: Raggruppa per nome campo group_by_field_name: Raggruppa per nome campo
api_enabled: API Attiva api_enabled: API Attiva
asset_collection:
name: Nome
slug: Slug
asset: asset:
name: Nome
source: Sorgente source: Sorgente
account: account:
email: Email email: Email

View File

@ -71,11 +71,7 @@ pt-BR:
highlighted_field_name: Nome do Campo em destaque highlighted_field_name: Nome do Campo em destaque
group_by_field_name: Agrupar por name do campo group_by_field_name: Agrupar por name do campo
api_enabled: Activation API api_enabled: Activation API
asset_collection:
name: Nome
slug: Slug
asset: asset:
name: Nome
source: Arquivo source: Arquivo
account: account:
email: Email email: Email

View File

@ -73,16 +73,6 @@ de:
alert: "Account wurde nicht erstellt." alert: "Account wurde nicht erstellt."
already_created: "Account wurde bereits zu dieser Webseite hinzugefügt." already_created: "Account wurde bereits zu dieser Webseite hinzugefügt."
asset_collections:
create:
notice: "Sammlung wurde erfolgreich erstellt."
alert: "Sammlung wurde nicht erstellt."
update:
notice: "Sammlung wurde erfolreich aktualisiert."
alert: "Sammlung wurde nicht aktualisiert."
destroy:
notice: "Sammlung wurde erfolgreich gelöscht."
assets: assets:
create: create:
notice: "Asset wurde erfolgreich erstellt." notice: "Asset wurde erfolgreich erstellt."
@ -109,7 +99,7 @@ de:
create: create:
alert: "Du musst dich einloggen" alert: "Du musst dich einloggen"
imports: import:
create: create:
done: "Deine Webseite wurde erfolreich aktualisiert." done: "Deine Webseite wurde erfolreich aktualisiert."
notice: "Deine Webseite wird aktualisiert." notice: "Deine Webseite wird aktualisiert."

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