first attempt of an installation wizzard
This commit is contained in:
parent
d677fed14b
commit
680a42b8f5
1
.gitignore
vendored
1
.gitignore
vendored
@ -14,6 +14,7 @@ public/javascripts/all.js
|
||||
public/javascripts/plugins
|
||||
public/images/plugins
|
||||
public/fonts
|
||||
public/sites_previous
|
||||
pkg
|
||||
rails_3_gems
|
||||
doc/performance.txt
|
||||
|
@ -49,7 +49,7 @@ module Admin
|
||||
end
|
||||
|
||||
def set_locale
|
||||
I18n.locale = current_admin.locale
|
||||
I18n.locale = current_admin.locale rescue Locomotive.config.default_locale
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -7,8 +7,6 @@ module Admin
|
||||
|
||||
skip_before_filter :validate_site_membership
|
||||
|
||||
skip_before_filter :set_locale, :only => :create
|
||||
|
||||
before_filter :authenticate_admin!, :only => :new
|
||||
|
||||
def new
|
||||
|
@ -17,22 +17,20 @@ module Admin
|
||||
:failed => @job && @job.last_error.present?
|
||||
} }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def new; end
|
||||
|
||||
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' }
|
||||
|
||||
flash[:notice] = t('flash.admin.imports.create.notice')
|
||||
|
||||
redirect_to admin_import_url
|
||||
else
|
||||
rescue
|
||||
@error = t('errors.messages.invalid_theme_file')
|
||||
flash[:alert] = t('flash.admin.imports.create.alert')
|
||||
|
||||
@ -40,23 +38,5 @@ module Admin
|
||||
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
|
71
app/controllers/admin/installation_controller.rb
Normal file
71
app/controllers/admin/installation_controller.rb
Normal 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
|
@ -7,7 +7,7 @@ module Admin
|
||||
|
||||
before_filter :require_site
|
||||
|
||||
helper 'admin/base', 'admin/login'
|
||||
helper 'admin/base', 'admin/box'
|
||||
|
||||
end
|
||||
end
|
||||
|
@ -7,7 +7,7 @@ module Admin
|
||||
|
||||
before_filter :require_site
|
||||
|
||||
helper 'admin/base', 'admin/login'
|
||||
helper 'admin/base', 'admin/box'
|
||||
|
||||
protected
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
module Admin::LoginHelper
|
||||
module Admin::BoxHelper
|
||||
|
||||
def login_flash_message
|
||||
def box_flash_message
|
||||
if not flash.empty?
|
||||
content_tag :div, flash.values.first,
|
||||
:id => "flash-#{flash.keys.first}",
|
||||
@ -10,8 +10,12 @@ module Admin::LoginHelper
|
||||
end
|
||||
end
|
||||
|
||||
def login_button_tag(label)
|
||||
def box_button_tag(label)
|
||||
content_tag(:button, content_tag(:span, label), :type => 'submit', :class => 'button')
|
||||
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
|
@ -15,7 +15,7 @@ class ThemeAssetUploader < AssetUploader
|
||||
end
|
||||
|
||||
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
|
||||
|
@ -8,7 +8,7 @@
|
||||
%p.notice= t('.notice')
|
||||
|
||||
.footer
|
||||
= login_button_tag t('admin.buttons.switch_to_site')
|
||||
= box_button_tag t('admin.buttons.switch_to_site')
|
||||
|
||||
:javascript
|
||||
$(document).ready(function() { $('form').submit(); });
|
23
app/views/admin/installation/step_1.html.haml
Normal file
23
app/views/admin/installation/step_1.html.haml
Normal 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)
|
25
app/views/admin/installation/step_2.html.haml
Normal file
25
app/views/admin/installation/step_2.html.haml
Normal 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)
|
22
app/views/admin/installation/step_3.html.haml
Normal file
22
app/views/admin/installation/step_3.html.haml
Normal 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')
|
@ -2,7 +2,7 @@
|
||||
!!!
|
||||
%html{ :xmlns => 'http://www.w3.org/1999/xhtml' }
|
||||
%head
|
||||
%title= escape_once("#{Locomotive.config.name} — #{current_site.name}")
|
||||
%title= yield(:head_title) || escape_once("#{Locomotive.config.name} — #{current_site.name}")
|
||||
|
||||
= javascript_include_tag 'admin/jquery'
|
||||
|
||||
@ -10,10 +10,12 @@
|
||||
/ [if IE]
|
||||
= stylesheet_link_tag('admin/blueprint/ie', :media => 'screen')
|
||||
|
||||
%body
|
||||
= yield :head
|
||||
|
||||
%body{ :class => @controller.controller_name }
|
||||
#wrapper
|
||||
#light.container
|
||||
#panel.container
|
||||
%h1= title
|
||||
%h1!= title
|
||||
|
||||
= yield
|
@ -5,7 +5,7 @@
|
||||
= f.hidden_field :reset_password_token
|
||||
|
||||
.inner
|
||||
= login_flash_message
|
||||
= box_flash_message
|
||||
|
||||
= f.inputs do
|
||||
= f.input :password, :label => t('.password'), :required => false
|
||||
@ -15,4 +15,4 @@
|
||||
= link_to preserve(t('.link')), new_admin_session_path
|
||||
|
||||
.footer
|
||||
= login_button_tag t('admin.buttons.change_password')
|
||||
= box_button_tag t('admin.buttons.change_password')
|
||||
|
@ -5,7 +5,7 @@
|
||||
= f.hidden_field :reset_password_token
|
||||
|
||||
.inner
|
||||
= login_flash_message
|
||||
= box_flash_message
|
||||
|
||||
= f.inputs do
|
||||
= f.input :email, :label => t('.email'), :required => false
|
||||
@ -14,4 +14,4 @@
|
||||
= link_to preserve(t('.link')), new_admin_session_path
|
||||
|
||||
.footer
|
||||
= login_button_tag t('admin.buttons.send_password')
|
||||
= box_button_tag t('admin.buttons.send_password')
|
@ -4,7 +4,7 @@
|
||||
= f.hidden_field :remember_me, :value => 'true'
|
||||
|
||||
.inner
|
||||
= login_flash_message
|
||||
= box_flash_message
|
||||
|
||||
= f.inputs do
|
||||
= f.input :email, :label => t('.email'), :required => false
|
||||
@ -14,4 +14,4 @@
|
||||
= link_to t('.link'), new_admin_password_path
|
||||
|
||||
.footer
|
||||
= login_button_tag t('admin.buttons.login')
|
||||
= box_button_tag t('admin.buttons.login')
|
||||
|
@ -25,4 +25,7 @@ Locomotive.configure do |config|
|
||||
# Ex:
|
||||
# config.heroku = { :name => '<my heroku app name>', :login => 'john@doe.net', :password => 'easy' }
|
||||
config.heroku = false
|
||||
|
||||
# default locale (for now, only en and fr are supported)
|
||||
config.default_locale = :en
|
||||
end
|
||||
|
@ -266,6 +266,33 @@ en:
|
||||
success: "Your site was successfully updated."
|
||||
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 — 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 — 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:
|
||||
titles:
|
||||
information: General information
|
||||
|
@ -8,8 +8,8 @@ defaults: &defaults
|
||||
|
||||
development:
|
||||
<<: *defaults
|
||||
# database: locomotive_dev
|
||||
database: locomotive_hosting_production
|
||||
database: locomotive_dev_tmp
|
||||
# database: locomotive_hosting_production
|
||||
|
||||
test:
|
||||
<<: *defaults
|
||||
|
@ -1,9 +1,9 @@
|
||||
# Locomotive::Application.routes.draw do |map|
|
||||
Rails.application.routes.draw do
|
||||
|
||||
# constraints(Locomotive::Routing::DefaultConstraint) do
|
||||
# root :to => 'home#show'
|
||||
# end
|
||||
constraints(Locomotive::Routing::DefaultConstraint) do
|
||||
root :to => 'admin/sessions#new'
|
||||
end
|
||||
|
||||
# admin authentication
|
||||
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]
|
||||
|
||||
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
|
||||
|
||||
# sitemap
|
||||
|
14
doc/TODO
14
doc/TODO
@ -8,13 +8,16 @@ BOARD:
|
||||
- import tool:
|
||||
- add samples 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)
|
||||
- write my first tutorial about locomotive
|
||||
|
||||
- cosmetic / ui bugs:
|
||||
- cosmetic / ui bugs / bugs:
|
||||
- increase the input field for domain names
|
||||
- drag&drop for assets ('last' class issue)
|
||||
- paginate is not working
|
||||
- segmentation with with_scope
|
||||
- asset whitelist
|
||||
|
||||
- api
|
||||
- handle html request (for now, it's just json)
|
||||
@ -22,6 +25,9 @@ BOARD:
|
||||
- refactor slugify method (use parameterize + create a module)
|
||||
- [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
|
||||
- detect if new installation
|
||||
- no-site error redirects to the first step
|
||||
|
@ -5,3 +5,4 @@ require 'locomotive/carrierwave/patches'
|
||||
# register missing mime types
|
||||
EXTENSIONS[:eot] = 'application/vnd.ms-fontobject'
|
||||
EXTENSIONS[:woff] = 'application/x-woff'
|
||||
EXTENSIONS[:otf] = 'application/octet-stream'
|
@ -10,7 +10,8 @@ module Locomotive
|
||||
:locales => %w{en fr},
|
||||
:cookie_key => '_locomotive_session',
|
||||
:enable_logs => false,
|
||||
:heroku => false
|
||||
:heroku => false,
|
||||
:default_locale => :en
|
||||
}
|
||||
|
||||
cattr_accessor :settings
|
||||
|
@ -28,7 +28,11 @@ module Locomotive
|
||||
|
||||
asset.attributes = { :source => File.open(asset_path), :performing_plain_text => false, :hidden => !visible }
|
||||
|
||||
begin
|
||||
asset.save!
|
||||
rescue Exception => e
|
||||
puts "\t\t !!! asset_path = #{asset_path}, folder = #{folder}, error = #{e.message}"
|
||||
end
|
||||
|
||||
site.reload
|
||||
end
|
||||
|
@ -10,7 +10,7 @@ module Locomotive
|
||||
return if content_types.nil?
|
||||
|
||||
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
|
||||
|
||||
|
@ -4,12 +4,13 @@ module Locomotive
|
||||
module Import
|
||||
class Job
|
||||
|
||||
def initialize(identifier, site = nil, enabled = {})
|
||||
raise "Theme identifier not found" if identifier.blank?
|
||||
|
||||
@identifier = identifier
|
||||
def initialize(zipfile, site, enabled = {})
|
||||
@site = site
|
||||
@enabled = enabled
|
||||
|
||||
@identifier = self.store_zipfile(zipfile)
|
||||
|
||||
raise "Theme identifier not found" if @identifier.blank?
|
||||
end
|
||||
|
||||
def before(worker)
|
||||
@ -72,7 +73,23 @@ module Locomotive
|
||||
FileUtils.mkdir_p(self.themes_folder)
|
||||
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.retrieve_from_store!(@identifier)
|
||||
@ -93,7 +110,7 @@ module Locomotive
|
||||
def unzip!
|
||||
self.prepare_folder
|
||||
|
||||
self.retrieve_zip_file
|
||||
self.retrieve_zipfile
|
||||
|
||||
self.log "unzip #{@theme_file}"
|
||||
|
||||
|
@ -20,7 +20,7 @@ module Locomotive
|
||||
end
|
||||
|
||||
def self.add_page(fullpath, context)
|
||||
puts "....adding #{fullpath}"
|
||||
puts "\t\t....adding #{fullpath}"
|
||||
|
||||
page = context[:done][fullpath]
|
||||
|
||||
|
@ -58,7 +58,7 @@ module Locomotive
|
||||
# input: url of the image OR asset drop
|
||||
def image_tag(input, *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
|
||||
|
||||
# Embed a flash movie into a page
|
||||
|
@ -26,6 +26,8 @@ module Locomotive
|
||||
end
|
||||
|
||||
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?
|
||||
end
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 485 B |
@ -65,6 +65,11 @@ body { background: #000 url(/images/admin/background/body.png) repeat 0 0; }
|
||||
color: #222;
|
||||
}
|
||||
|
||||
#panel fieldset ol li input[type=file] {
|
||||
background: none;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#panel fieldset ol li p.inline-errors {
|
||||
padding: 3px 5px;
|
||||
margin: 5px 0px;
|
||||
|
50
public/stylesheets/admin/installation.css
Normal file
50
public/stylesheets/admin/installation.css
Normal 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 {
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user