first attempt of an installation wizzard

This commit is contained in:
dinedine 2010-10-27 02:11:44 +02:00
parent d677fed14b
commit 680a42b8f5
33 changed files with 310 additions and 63 deletions

1
.gitignore vendored
View File

@ -14,6 +14,7 @@ public/javascripts/all.js
public/javascripts/plugins public/javascripts/plugins
public/images/plugins public/images/plugins
public/fonts public/fonts
public/sites_previous
pkg pkg
rails_3_gems rails_3_gems
doc/performance.txt doc/performance.txt

View File

@ -49,7 +49,7 @@ module Admin
end end
def set_locale def set_locale
I18n.locale = current_admin.locale I18n.locale = current_admin.locale rescue Locomotive.config.default_locale
end end
end end

View File

@ -7,8 +7,6 @@ module Admin
skip_before_filter :validate_site_membership skip_before_filter :validate_site_membership
skip_before_filter :set_locale, :only => :create
before_filter :authenticate_admin!, :only => :new before_filter :authenticate_admin!, :only => :new
def new def new

View File

@ -17,22 +17,20 @@ module Admin
:failed => @job && @job.last_error.present? :failed => @job && @job.last_error.present?
} } } }
end end
end end
def new; end def new; end
def create def create
identifier = store_zipfile! begin
job = Locomotive::Import::Job.new(params[:zipfile], current_site)
if identifier
job = Locomotive::Import::Job.new(identifier, current_site)
Delayed::Job.enqueue job, { :site => current_site, :job_type => 'import' } Delayed::Job.enqueue job, { :site => current_site, :job_type => 'import' }
flash[:notice] = t('flash.admin.imports.create.notice') flash[:notice] = t('flash.admin.imports.create.notice')
redirect_to admin_import_url redirect_to admin_import_url
else rescue
@error = t('errors.messages.invalid_theme_file') @error = t('errors.messages.invalid_theme_file')
flash[:alert] = t('flash.admin.imports.create.alert') flash[:alert] = t('flash.admin.imports.create.alert')
@ -40,23 +38,5 @@ module Admin
end end
end end
protected
def store_zipfile!
return nil if params[:zipfile].blank?
file = CarrierWave::SanitizedFile.new(params[:zipfile])
uploader = ThemeUploader.new(current_site)
begin
uploader.store!(file)
rescue CarrierWave::IntegrityError
return nil
end
uploader.identifier
end
end end
end end

View File

@ -0,0 +1,71 @@
module Admin
class InstallationController < BaseController
layout '/admin/layouts/box'
skip_before_filter :require_site
skip_before_filter :authenticate_admin!
skip_before_filter :verify_authenticity_token
skip_before_filter :validate_site_membership
before_filter :is_step_already_done?
def show
request.get? ? self.handle_get : self.handle_post
end
protected
def handle_get
case params[:step].to_i
when 2 then @account = Account.new
when 3 then @site = Site.new
end
render "step_#{params[:step]}"
end
def handle_post
case params[:step].to_i
when 2 # create account
@account = Account.create(params[:account])
if @account.valid?
redirect_to admin_installation_step_url(3)
else
render 'step_2'
end
when 3 # create site
@site = Site.new(params[:site])
@site.memberships.build :account => Account.first, :admin => true
@site.save
if @site.valid?
# begin
job = Locomotive::Import::Job.new(params[:zipfile], @site)
Delayed::Job.enqueue job, { :site => @site, :job_type => 'import' }
# rescue;
# end # not a big deal if it did not work
redirect_to admin_session_url(:host => Site.first.domains.first, :port => request.port)
else
render 'step_3'
end
end
end
def is_step_already_done?
case params[:step].to_i
when 2 # already an account in db
if Account.count > 0
@step_done = t('admin.installation.step_2.done', Account.first.attributes)
render 'step_2' and return false
end
else
true
end
end
end
end

View File

@ -7,7 +7,7 @@ module Admin
before_filter :require_site before_filter :require_site
helper 'admin/base', 'admin/login' helper 'admin/base', 'admin/box'
end end
end end

View File

@ -7,7 +7,7 @@ module Admin
before_filter :require_site before_filter :require_site
helper 'admin/base', 'admin/login' helper 'admin/base', 'admin/box'
protected protected

View File

@ -1,6 +1,6 @@
module Admin::LoginHelper module Admin::BoxHelper
def login_flash_message def box_flash_message
if not flash.empty? if not flash.empty?
content_tag :div, flash.values.first, content_tag :div, flash.values.first,
:id => "flash-#{flash.keys.first}", :id => "flash-#{flash.keys.first}",
@ -10,8 +10,12 @@ module Admin::LoginHelper
end end
end end
def login_button_tag(label) def box_button_tag(label)
content_tag(:button, content_tag(:span, label), :type => 'submit', :class => 'button') content_tag(:button, content_tag(:span, label), :type => 'submit', :class => 'button')
end end
def next_installation_step_link(step = 1, label = nil)
link_to(content_tag(:span, label || t('admin.installation.common.next')), admin_installation_step_url(step), :class => 'button')
end
end end

View File

@ -15,7 +15,7 @@ class ThemeAssetUploader < AssetUploader
end end
def extension_white_list def extension_white_list
%w(jpg jpeg gif png css js swf flv eot svg ttf woff) %w(jpg jpeg gif png css js swf flv eot svg ttf woff otf)
end end
end end

View File

@ -8,7 +8,7 @@
%p.notice= t('.notice') %p.notice= t('.notice')
.footer .footer
= login_button_tag t('admin.buttons.switch_to_site') = box_button_tag t('admin.buttons.switch_to_site')
:javascript :javascript
$(document).ready(function() { $('form').submit(); }); $(document).ready(function() { $('form').submit(); });

View File

@ -0,0 +1,23 @@
- content_for :head_title do
= t('admin.installation.common.title')
- title t('.title')
= stylesheet_link_tag 'admin/installation'
.inner
%p.explanations
= t('.explanations')
%dl
%dt!= t('.database.label', :name => Mongoid.config.database.name)
%dd
%p.notes!= t('.database.notes')
%dt!= t('.default_domain.label', :name => Locomotive.config.default_domain)
%dd
%p.notes!= t('.default_domain.notes', :domain => Locomotive.config.default_domain)
.footer
= next_installation_step_link(2)

View File

@ -0,0 +1,25 @@
- content_for :head_title do
= t('admin.installation.common.title')
- title t('.title')
= stylesheet_link_tag 'admin/installation'
- if @step_done.blank?
= semantic_form_for(@account, :url => admin_installation_step_url(2)) do |f|
.inner
= f.inputs do
= f.input :name, :label => t('.name'), :required => false
= f.input :email, :label => t('.email'), :required => false
= f.input :password, :label => t('.password'), :required => false
= f.input :password_confirmation, :label => t('.password_confirmation'), :required => false
.footer
= box_button_tag t('.next')
- else
.inner
%p.done
!= @step_done
.footer
= next_installation_step_link(3)

View File

@ -0,0 +1,22 @@
- content_for :head_title do
= t('admin.installation.common.title')
- title t('.title')
= stylesheet_link_tag 'admin/installation'
= semantic_form_for(@site, :url => admin_installation_step_url(3), :html => { :multipart => true }) do |f|
.inner
%p.explanations
!= t('.explanations')
= f.inputs do
= f.input :name, :required => false
= f.input :subdomain, :required => false
%li{ :class => 'string optional', :id => 'zipfile_input' }
%label{ :for => 'zipfile' }= t('formtastic.labels.import.new.source')
= file_field_tag 'zipfile'
.footer
= box_button_tag t('.next')

View File

@ -2,7 +2,7 @@
!!! !!!
%html{ :xmlns => 'http://www.w3.org/1999/xhtml' } %html{ :xmlns => 'http://www.w3.org/1999/xhtml' }
%head %head
%title= escape_once("#{Locomotive.config.name} &mdash; #{current_site.name}") %title= yield(:head_title) || escape_once("#{Locomotive.config.name} &mdash; #{current_site.name}")
= javascript_include_tag 'admin/jquery' = javascript_include_tag 'admin/jquery'
@ -10,10 +10,12 @@
/ [if IE] / [if IE]
= stylesheet_link_tag('admin/blueprint/ie', :media => 'screen') = stylesheet_link_tag('admin/blueprint/ie', :media => 'screen')
%body = yield :head
%body{ :class => @controller.controller_name }
#wrapper #wrapper
#light.container #light.container
#panel.container #panel.container
%h1= title %h1!= title
= yield = yield

View File

@ -5,7 +5,7 @@
= f.hidden_field :reset_password_token = f.hidden_field :reset_password_token
.inner .inner
= login_flash_message = box_flash_message
= f.inputs do = f.inputs do
= f.input :password, :label => t('.password'), :required => false = f.input :password, :label => t('.password'), :required => false
@ -15,4 +15,4 @@
= link_to preserve(t('.link')), new_admin_session_path = link_to preserve(t('.link')), new_admin_session_path
.footer .footer
= login_button_tag t('admin.buttons.change_password') = box_button_tag t('admin.buttons.change_password')

View File

@ -5,7 +5,7 @@
= f.hidden_field :reset_password_token = f.hidden_field :reset_password_token
.inner .inner
= login_flash_message = box_flash_message
= f.inputs do = f.inputs do
= f.input :email, :label => t('.email'), :required => false = f.input :email, :label => t('.email'), :required => false
@ -14,4 +14,4 @@
= link_to preserve(t('.link')), new_admin_session_path = link_to preserve(t('.link')), new_admin_session_path
.footer .footer
= login_button_tag t('admin.buttons.send_password') = box_button_tag t('admin.buttons.send_password')

View File

@ -4,7 +4,7 @@
= f.hidden_field :remember_me, :value => 'true' = f.hidden_field :remember_me, :value => 'true'
.inner .inner
= login_flash_message = box_flash_message
= f.inputs do = f.inputs do
= f.input :email, :label => t('.email'), :required => false = f.input :email, :label => t('.email'), :required => false
@ -14,4 +14,4 @@
= link_to t('.link'), new_admin_password_path = link_to t('.link'), new_admin_password_path
.footer .footer
= login_button_tag t('admin.buttons.login') = box_button_tag t('admin.buttons.login')

View File

@ -25,4 +25,7 @@ Locomotive.configure do |config|
# Ex: # Ex:
# config.heroku = { :name => '<my heroku app name>', :login => 'john@doe.net', :password => 'easy' } # config.heroku = { :name => '<my heroku app name>', :login => 'john@doe.net', :password => 'easy' }
config.heroku = false config.heroku = false
# default locale (for now, only en and fr are supported)
config.default_locale = :en
end end

View File

@ -266,6 +266,33 @@ en:
success: "Your site was successfully updated." success: "Your site was successfully updated."
failure: "The import did not work." failure: "The import did not work."
installation:
common:
title: First Locomotive Installation
next: Next
step_1:
title: Step 1/3
explanations: Here is the first step of the Locomotive installation. Please read carefully what is written below.
database:
label: "Database name: <em>%{name}</em>"
notes: "All the mongodb connection settings can be found in the <b>config/mongoid.yml</b> file of your application."
default_domain:
label: "Default domain name: <em>%{name}</em>"
notes: "Basically, Locomotive is a multi websites platform. Each site instance has a default entry based on the default domain name. Obviously, you are free to map other domains to your site instance working like aliases. <br/>The default domain name value can be found in the <b>config/initializers/locomotive.rb</b> file."
step_2:
title: "Step 2/3 &mdash; Create account"
name: Account name
email: Email
password: Password
password_confirmation: Password confirmation
done: "You have already added an account:<br/><strong>%{name}</strong>, <em>%{email}</em>"
next: Create account
step_3:
title: "Step 3/3 &mdash; Create site"
explanations: "This is the last step of the installation. You can upload a theme as a zip file. We have free available themes <a href=\"http://www.locomotivecms.com/docs/themes\">here</a>."
next: Create site
formtastic: formtastic:
titles: titles:
information: General information information: General information

View File

@ -8,8 +8,8 @@ defaults: &defaults
development: development:
<<: *defaults <<: *defaults
# database: locomotive_dev database: locomotive_dev_tmp
database: locomotive_hosting_production # database: locomotive_hosting_production
test: test:
<<: *defaults <<: *defaults

View File

@ -1,9 +1,9 @@
# Locomotive::Application.routes.draw do |map| # Locomotive::Application.routes.draw do |map|
Rails.application.routes.draw do Rails.application.routes.draw do
# constraints(Locomotive::Routing::DefaultConstraint) do constraints(Locomotive::Routing::DefaultConstraint) do
# root :to => 'home#show' root :to => 'admin/sessions#new'
# end end
# admin authentication # admin authentication
devise_for :admin, :class_name => 'Account', :controllers => { :sessions => 'admin/sessions', :passwords => 'admin/passwords' } devise_for :admin, :class_name => 'Account', :controllers => { :sessions => 'admin/sessions', :passwords => 'admin/passwords' }
@ -52,6 +52,11 @@ Rails.application.routes.draw do
resources :cross_domain_sessions, :only => [:new, :create] resources :cross_domain_sessions, :only => [:new, :create]
resource :import, :only => [:new, :show, :create] resource :import, :only => [:new, :show, :create]
# installation guide
match '/installation' => 'installation#show', :defaults => { :step => 1 }, :as => :installation
match '/installation/:step' => 'installation#show', :as => :installation_step
end end
# sitemap # sitemap

View File

@ -8,13 +8,16 @@ BOARD:
- import tool: - import tool:
- add samples option - add samples option
- remove existing pages / contents option - remove existing pages / contents option
- do not override existing site name
- page templatized (tied to content type)
- samples
- global regions: keyword in editable element (http://www.mongodb.org/display/DOCS/Updating) - cosmetic / ui bugs / bugs:
- write my first tutorial about locomotive
- cosmetic / ui bugs:
- increase the input field for domain names - increase the input field for domain names
- drag&drop for assets ('last' class issue) - drag&drop for assets ('last' class issue)
- paginate is not working
- segmentation with with_scope
- asset whitelist
- api - api
- handle html request (for now, it's just json) - handle html request (for now, it's just json)
@ -22,6 +25,9 @@ BOARD:
- refactor slugify method (use parameterize + create a module) - refactor slugify method (use parameterize + create a module)
- [content types] the "display column" selector should not include file types - [content types] the "display column" selector should not include file types
- global regions: keyword in editable element (http://www.mongodb.org/display/DOCS/Updating)
- write my first tutorial about locomotive
- installation guide - installation guide
- detect if new installation - detect if new installation
- no-site error redirects to the first step - no-site error redirects to the first step

View File

@ -5,3 +5,4 @@ require 'locomotive/carrierwave/patches'
# register missing mime types # register missing mime types
EXTENSIONS[:eot] = 'application/vnd.ms-fontobject' EXTENSIONS[:eot] = 'application/vnd.ms-fontobject'
EXTENSIONS[:woff] = 'application/x-woff' EXTENSIONS[:woff] = 'application/x-woff'
EXTENSIONS[:otf] = 'application/octet-stream'

View File

@ -10,7 +10,8 @@ module Locomotive
:locales => %w{en fr}, :locales => %w{en fr},
:cookie_key => '_locomotive_session', :cookie_key => '_locomotive_session',
:enable_logs => false, :enable_logs => false,
:heroku => false :heroku => false,
:default_locale => :en
} }
cattr_accessor :settings cattr_accessor :settings

View File

@ -28,7 +28,11 @@ module Locomotive
asset.attributes = { :source => File.open(asset_path), :performing_plain_text => false, :hidden => !visible } asset.attributes = { :source => File.open(asset_path), :performing_plain_text => false, :hidden => !visible }
asset.save! begin
asset.save!
rescue Exception => e
puts "\t\t !!! asset_path = #{asset_path}, folder = #{folder}, error = #{e.message}"
end
site.reload site.reload
end end

View File

@ -10,7 +10,7 @@ module Locomotive
return if content_types.nil? return if content_types.nil?
content_types.each do |name, attributes| content_types.each do |name, attributes|
puts "....content_type = #{attributes['slug']}" puts "\t\t....content_type = #{attributes['slug']}"
content_type = site.content_types.where(:slug => attributes['slug']).first content_type = site.content_types.where(:slug => attributes['slug']).first

View File

@ -4,12 +4,13 @@ module Locomotive
module Import module Import
class Job class Job
def initialize(identifier, site = nil, enabled = {}) def initialize(zipfile, site, enabled = {})
raise "Theme identifier not found" if identifier.blank?
@identifier = identifier
@site = site @site = site
@enabled = enabled @enabled = enabled
@identifier = self.store_zipfile(zipfile)
raise "Theme identifier not found" if @identifier.blank?
end end
def before(worker) def before(worker)
@ -72,7 +73,23 @@ module Locomotive
FileUtils.mkdir_p(self.themes_folder) FileUtils.mkdir_p(self.themes_folder)
end end
def retrieve_zip_file def store_zipfile(zipfile)
return nil if zipfile.blank?
file = CarrierWave::SanitizedFile.new(zipfile)
uploader = ThemeUploader.new(@site)
begin
uploader.store!(file)
rescue CarrierWave::IntegrityError
return nil
end
uploader.identifier
end
def retrieve_zipfile
uploader = ThemeUploader.new(@site) uploader = ThemeUploader.new(@site)
uploader.retrieve_from_store!(@identifier) uploader.retrieve_from_store!(@identifier)
@ -93,7 +110,7 @@ module Locomotive
def unzip! def unzip!
self.prepare_folder self.prepare_folder
self.retrieve_zip_file self.retrieve_zipfile
self.log "unzip #{@theme_file}" self.log "unzip #{@theme_file}"

View File

@ -20,7 +20,7 @@ module Locomotive
end end
def self.add_page(fullpath, context) def self.add_page(fullpath, context)
puts "....adding #{fullpath}" puts "\t\t....adding #{fullpath}"
page = context[:done][fullpath] page = context[:done][fullpath]

View File

@ -58,7 +58,7 @@ module Locomotive
# input: url of the image OR asset drop # input: url of the image OR asset drop
def image_tag(input, *args) def image_tag(input, *args)
image_options = inline_options(args_to_options(args)) image_options = inline_options(args_to_options(args))
"<img src=\"#{File.join('/', get_url_from_asset(input))}\" #{image_options}/>" "<img src=\"#{get_url_from_asset(input)}\" #{image_options}/>"
end end
# Embed a flash movie into a page # Embed a flash movie into a page

View File

@ -17,7 +17,7 @@ module Locomotive
protected protected
def fetch_site def fetch_site
Locomotive.logger "[fetch site] host = #{request.host} / #{request.env['HTTP_HOST']}" Locomotive.logger "[fetch site] host = #{request.host} / #{request.env['HTTP_HOST']}"
@current_site ||= Site.match_domain(request.host).first @current_site ||= Site.match_domain(request.host).first
end end
@ -26,6 +26,8 @@ module Locomotive
end end
def require_site def require_site
redirect_to admin_installation_url and return false if Account.count == 0 || Site.count == 0
render_no_site_error and return false if current_site.nil? render_no_site_error and return false if current_site.nil?
end end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 485 B

View File

@ -65,6 +65,11 @@ body { background: #000 url(/images/admin/background/body.png) repeat 0 0; }
color: #222; color: #222;
} }
#panel fieldset ol li input[type=file] {
background: none;
padding: 0px;
}
#panel fieldset ol li p.inline-errors { #panel fieldset ol li p.inline-errors {
padding: 3px 5px; padding: 3px 5px;
margin: 5px 0px; margin: 5px 0px;

View File

@ -0,0 +1,50 @@
#panel .inner {
padding-left: 20px;
padding-right: 20px;
color: #222;
}
#panel .inner p.explanations {
margin-top: 10px;
font-size: 1.2em;
}
#panel .inner p.explanations a {
color: #1F82BC;
text-decoration: none;
}
#panel .inner p.explanations a:hover {
text-decoration: underline;
}
#panel .inner p.done {
margin: 20px 0px 15px;
font-size: 1.2em;
}
#panel .inner p {
margin-bottom: 5px;
text-align: justify;
}
#panel .inner dl {
margin-bottom: 0px;
font-size: 1.2em;
}
#panel .inner dt {
margin-bottom: 7px;
}
#panel .inner dt em {
margin-left: 10px;
font-size: 1.1em;
color: #666;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);
}
#panel .inner dd p {
}