fix js bug when changing layout in page editing + improve nav tag

This commit is contained in:
dinedine 2010-07-22 01:35:30 +02:00
parent c4f4979203
commit 35e0120cab
10 changed files with 156 additions and 143 deletions

18
Gemfile
View File

@ -13,7 +13,7 @@ gem 'mongoid_acts_as_tree', '0.1.5'
gem 'mongo_session_store', '2.0.0.pre'
gem 'warden'
gem 'devise', '1.1.rc1'
gem 'haml', '3.0.1'
gem 'haml', '3.0.13'
gem 'rmagick', '2.12.2'
gem 'aws'
gem 'mimetype-fu', :require => 'mimetype_fu'
@ -36,12 +36,12 @@ group :development do
end
group :test do
gem 'rspec-rails', '2.0.0.beta.11'
gem 'factory_girl_rails'
gem 'capybara'
gem 'cucumber'
gem 'cucumber-rails'
gem 'spork'
gem 'launchy'
gem 'mocha', :git => 'git://github.com/floehopper/mocha.git'
gem 'rspec-rails', '2.0.0.beta.11'
gem 'factory_girl_rails'
gem 'capybara'
gem 'cucumber'
gem 'cucumber-rails'
gem 'spork'
gem 'launchy'
gem 'mocha', :git => 'git://github.com/floehopper/mocha.git'
end

View File

@ -1,12 +1,15 @@
module Admin
class PagePartsController < BaseController
layout nil
respond_to :json
def index
parts = current_site.layouts.find(params[:layout_id]).parts
render :json => { :parts => parts }
respond_with parts.collect(&:attributes)
end
end
end

View File

@ -1,31 +1,31 @@
module Admin
class PagesController < BaseController
sections 'contents'
respond_to :json, :only => [:update, :sort]
respond_to :json, :only => [:update, :sort, :get_path]
def index
@pages = current_site.pages.roots
end
def new
@page = current_site.pages.build
@page.parts << PagePart.build_body_part
end
def sort
@page = current_site.pages.find(params[:id])
@page.sort_children!(params[:children])
respond_with @page
end
def get_path
page = current_site.pages.build(:parent => current_site.pages.find(params[:parent_id]), :slug => params[:slug].slugify)
render :json => { :url => page.url, :slug => page.slug }
end
end
end

View File

@ -34,9 +34,6 @@ class Site
named_scope :match_domain, lambda { |domain| { :where => { :domains => domain } } }
named_scope :match_domain_with_exclusion_of, lambda { |domain, site| { :where => { :domains => domain, :_id.ne => site.id } } }
## behaviours ##
liquid_methods :name, :meta_keywords, :meta_description
## methods ##
def accounts

View File

@ -1,14 +1,14 @@
en:
admin:
admin:
buttons:
login: Log in
send_password: Send
change_password: Update
new_item: "+ add"
messages:
confirm: Are you sure ?
shared:
header:
welcome: Welcome, %{name}
@ -30,7 +30,7 @@ en:
back: Back without saving
create: Create
update: Update
custom_fields:
edit:
title: Editing custom field
@ -40,7 +40,7 @@ en:
category: Select
boolean: Checkbox
date: Date
file: File
file: File
text_formatting:
none: None
html: HTML
@ -53,7 +53,7 @@ en:
custom_form:
edit_categories: Edit options
delete_file: Delete file
sessions:
new:
title: Login
@ -70,8 +70,8 @@ en:
title: Update my password
link: "&rarr; Back to login page"
password: "Your new password"
password_confirmation: "Confirmation of your new password"
password_confirmation: "Confirmation of your new password"
pages:
index:
title: Listing pages
@ -96,7 +96,7 @@ en:
day: 1 day
week: 1 week
month: 1 month
layouts:
index:
title: Listing layouts
@ -127,28 +127,28 @@ en:
help: "Fill in the form below to update your snippet."
snippet:
updated_at: Updated at
sites:
new:
title: New site
help: "Fill in the form below to create your new site."
current_sites:
edit:
new_membership: add account
help: "The site name can be updated by clicking it."
ask_for_name: "Please type the new site name"
memberships:
new:
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."
accounts:
new:
title: New account
help: "Fill in the form below to add a new account."
my_accounts:
edit:
help: "Your name can be updated by clicking it."
@ -156,7 +156,7 @@ en:
en: English
fr: French
ask_for_name: "Please type your new name"
theme_assets:
index:
title: Listing theme files
@ -180,7 +180,7 @@ en:
images:
title: Listing images
no_items: "There are no files for now."
asset_collections:
index:
title: Asset collections
@ -196,7 +196,7 @@ en:
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:
new:
title: New asset
@ -204,7 +204,7 @@ en:
edit:
title: Edit asset
help: "Fill in the form below to update your asset."
content_types:
index:
new: new model
@ -220,27 +220,27 @@ en:
order_by:
updated_at: 'By "updated at" date'
position_in_list: Manually
contents:
index:
title: 'Listing "%{type}"'
edit: edit model
destroy: remove model
download: download items
new: new item
new: new item
category_noname: "No name"
lastest_items: "Lastest items"
updated_at: "Updated at"
list:
no_items: "There are no items for now. Just click <a href=\"%{url}\">here</a> to create the first one."
new:
title: '%{type} &mdash; new item'
title: '%{type} &mdash; new item'
edit:
title: '%{type} &mdash; editing item'
image_picker:
link: Insert an image into the code
formtastic:
titles:
information: General information
@ -268,7 +268,7 @@ en:
custom_fields:
field:
_alias: Alias
hints:
page:
published: "Only authenticated accounts can view unpublished pages."
@ -277,8 +277,8 @@ en:
snippet:
slug: "You need to know it in order to insert the snippet inside a page or a layout"
site:
meta_keywords: "Meta keywords used within the head tag of the page. They are separeted by an empty space. Required for SEO."
meta_description: "Meta description used within the head tag of the page. Required for SEO."
meta_keywords: "Meta keywords used within the head tag of the page. They are separeted by an empty space. Required for SEO."
meta_description: "Meta description used within the head tag of the page. Required for SEO."
domain_name: "ex: locomotiveapp.org"
theme_asset:
slug: "You do not need to add the extension file (.css or .js)"
@ -288,4 +288,4 @@ en:
field:
_alias: "Property available in liquid templates"
hint: "Text displayed in the model form just below the field"

View File

@ -5,5 +5,5 @@ site.memberships.build :account => account, :admin => true
site.save!
puts "Your first website has been created !"
puts "Admin url: http://test.example.com/admin"
puts "Admin url: http://test.example.com:3000/admin"
puts "Crendetials: admin@example.com / locomotive"

View File

@ -1,8 +1,8 @@
BOARD:
BOARD:
- refactor slugify method (use parameterize + create a module)
- send email when new content added thru api
BACKLOG:
- rack app to map pretty asset url to S3

View File

@ -0,0 +1,15 @@
module Locomotive
module Liquid
module Drops
class Site < Base
liquid_attributes << :name << :meta_keywords << :meta_description
def index
@index ||= @source.pages.index.first
end
end
end
end
end

View File

@ -28,8 +28,6 @@ module Locomotive
path = [path, File.join(dirname, 'content_type_template').gsub(/^\//, '')]
end
# TODO: path is not correctly built + find content instance in order to render a 404 page if not found
if page = current_site.pages.any_in(:fullpath => [*path]).first
if not page.published? and current_admin.nil?
page = nil

View File

@ -1,88 +1,88 @@
$(document).ready(function() {
// slider
var resetSlider = function() {
$('#page-parts .wrapper ul').wslide({
width: 880,
height: 400,
autolink: false,
duration: 300,
horiz: true
});
}
resetSlider();
// codemirror
$('#parts code textarea').each(function() { addCodeMirrorEditor('liquid', $(this)); });
var refreshParts = function(parts) {
// console.log('refreshParts');
$('#page-parts .nav a').removeClass('enabled');
$(parts).each(function() {
// console.log("iterating..." + this.slug);
var control = $('#control-part-' + this.slug);
// adding missing part
if (control.size() == 0) {
// console.log('adding part');
var nbParts = $('#page-parts .nav a').size();
$('#page-parts .nav .clear').before('<a id="control-part-' + this.slug + '" class="enabled part-' + nbParts + '" href="#parts-' + (nbParts + 1) + '"><span>' + this.name + '</span></a>');
var textareaInput = '<textarea rows="20" name="page[parts_attributes][' + nbParts + '][value]" id="page_parts_attributes_' + nbParts + '_value"/>';
var hiddenInputs = '<input type="hidden" name="page[parts_attributes][' + nbParts + '][name]" value="' + this.name + '" />'
hiddenInputs += '<input type="hidden" name="page[parts_attributes][' + nbParts + '][slug]" value="' + this.slug + '" />'
$('#page-parts .wrapper ul').append('<li id="part-' + nbParts + '" class="new"><code>' + textareaInput + '</code>' + hiddenInputs + '</li>');
resetSlider();
$('#parts li:last code textarea').each(function() { addCodeMirrorEditor('liquid', $(this)); });
} else {
var index = parseInt(control.attr('class').match(/part-(.+)/)[1]) + 1;
var wrapper = $('#parts-' + index);
// updating part
wrapper.find('input.disabled').val(this.disabled == true ? 'true' : 'false');
if (this.disabled == false) {
control.html('<span>' + this.name + '</span>').addClass('enabled').show();
wrapper.show();
} else {
control.hide();
wrapper.hide();
}
}
});
// removing or hiding parts
$('#page-parts .nav a:not(.enabled)').each(function() {
var index = parseInt($(this).attr('class').match(/part-(.+)/)[1]) + 1;
var wrapper = $('#parts-' + index);
if (wrapper.hasClass('new')) {
$(this).remove(); wrapper.remove();
} else {
wrapper.find('input.disabled').val('true');
$(this).hide(); wrapper.hide();
}
});
// go to the first one if we hid the selected wrapper
var selectedNav = $('#page-parts .nav a.on');
if (selectedNav.size() == 1) {
var index = parseInt(selectedNav.attr('class').match(/part-(.+)/)[1]) + 1;
if ($('#parts-' + index + ':visible').size() == 0)
$('#page-parts .nav a:first').click();
} else
$('#page-parts .nav a:first').click();
}
var loadPartsFromLayout = function() {
if ($('#page_layout_id').val() == '')
return ;
var url = $('#page_layout_id').attr('data_url').replace('_id_to_replace_', $('#page_layout_id').val());
$.get(url, '', function(data) { refreshParts(data.parts); }, 'json');
}
$('#page_layout_id').change(loadPartsFromLayout);
// slider
var resetSlider = function() {
$('#page-parts .wrapper ul').wslide({
width: 880,
height: 400,
autolink: false,
duration: 300,
horiz: true
});
}
resetSlider();
// codemirror
$('#parts code textarea').each(function() { addCodeMirrorEditor('liquid', $(this)); });
var refreshParts = function(parts) {
// console.log('refreshParts');
$('#page-parts .nav a').removeClass('enabled');
$(parts).each(function() {
// console.log("iterating..." + this.slug);
var control = $('#control-part-' + this.slug);
// adding missing part
if (control.size() == 0) {
// console.log('adding part');
var nbParts = $('#page-parts .nav a').size();
$('#page-parts .nav .clear').before('<a id="control-part-' + this.slug + '" class="enabled part-' + nbParts + '" href="#parts-' + (nbParts + 1) + '"><span>' + this.name + '</span></a>');
var textareaInput = '<textarea rows="20" name="page[parts_attributes][' + nbParts + '][value]" id="page_parts_attributes_' + nbParts + '_value"/>';
var hiddenInputs = '<input type="hidden" name="page[parts_attributes][' + nbParts + '][name]" value="' + this.name + '" />'
hiddenInputs += '<input type="hidden" name="page[parts_attributes][' + nbParts + '][slug]" value="' + this.slug + '" />'
$('#page-parts .wrapper ul').append('<li id="part-' + nbParts + '" class="new"><code>' + textareaInput + '</code>' + hiddenInputs + '</li>');
resetSlider();
$('#parts li:last code textarea').each(function() { addCodeMirrorEditor('liquid', $(this)); });
} else {
var index = parseInt(control.attr('class').match(/part-(.+)/)[1]) + 1;
var wrapper = $('#parts-' + index);
// updating part
wrapper.find('input.disabled').val(this.disabled == true ? 'true' : 'false');
if (this.disabled == false) {
control.html('<span>' + this.name + '</span>').addClass('enabled').show();
wrapper.show();
} else {
control.hide();
wrapper.hide();
}
}
});
// removing or hiding parts
$('#page-parts .nav a:not(.enabled)').each(function() {
var index = parseInt($(this).attr('class').match(/part-(.+)/)[1]) + 1;
var wrapper = $('#parts-' + index);
if (wrapper.hasClass('new')) {
$(this).remove(); wrapper.remove();
} else {
wrapper.find('input.disabled').val('true');
$(this).hide(); wrapper.hide();
}
});
// go to the first one if we hide the selected wrapper
var selectedNav = $('#page-parts .nav a.on');
if (selectedNav.size() == 1) {
var index = parseInt(selectedNav.attr('class').match(/part-(.+)/)[1]) + 1;
if ($('#parts-' + index + ':visible').size() == 0)
$('#page-parts .nav a:first').click();
} else
$('#page-parts .nav a:first').click();
}
var loadPartsFromLayout = function() {
if ($('#page_layout_id').val() == '')
return ;
var url = $('#page_layout_id').attr('data_url').replace('_id_to_replace_', $('#page_layout_id').val());
$.get(url, '', function(data) { refreshParts(data); }, 'json');
}
$('#page_layout_id').change(loadPartsFromLayout);
});