Merge branch 'nccu_0509' of https://github.com/Rulingcom/orbit into nccu_0509

Conflicts:
	config/locales/zh_tw.yml
This commit is contained in:
Matthew K. Fu JuYuan committed 2012-05-14 12:36:09 +08:00
commit 2cd67356a5
80 files changed
+1216 -511

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

+391
View File
@@ -0,0 +1,391 @@
/*
* jQuery UI Nested Sortable
* v 1.3.4 / 28 apr 2011
* http://mjsarfatti.com/sandbox/nestedSortable
*
* Depends:
* jquery.ui.sortable.js 1.8+
*
* License CC BY-SA 3.0
* Copyright 2010-2011, Manuele J Sarfatti
*/
(function($) {
$.widget("ui.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
options: {
tabSize: 20,
disableNesting: 'ui-nestedSortable-no-nesting',
errorClass: 'ui-nestedSortable-error',
listType: 'ol',
maxLevels: 0,
revertOnError: 1
},
_create: function() {
this.element.data('sortable', this.element.data('nestedSortable'));
return $.ui.sortable.prototype._create.apply(this, arguments);
},
destroy: function() {
this.element
.removeData("nestedSortable")
.unbind(".nestedSortable");
return $.ui.sortable.prototype.destroy.apply(this, arguments);
},
_mouseDrag: function(event) {
//Compute the helpers position
this.position = this._generatePosition(event);
this.positionAbs = this._convertPositionTo("absolute");
if (!this.lastPositionAbs) {
this.lastPositionAbs = this.positionAbs;
}
//Do scrolling
if(this.options.scroll) {
var o = this.options, scrolled = false;
if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
} else {
if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
}
if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
$.ui.ddmanager.prepareOffsets(this, event);
}
//Regenerate the absolute position used for position checks
this.positionAbs = this._convertPositionTo("absolute");
//Set the helper position
if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
//Rearrange
for (var i = this.items.length - 1; i >= 0; i--) {
//Cache variables and intersection, continue if no intersection
var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
if (!intersection) continue;
if(itemElement != this.currentItem[0] //cannot intersect with itself
&& this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
&& !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
&& (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
) {
$(itemElement).mouseenter();
this.direction = intersection == 1 ? "down" : "up";
if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
$(itemElement).mouseleave();
this._rearrange(event, item);
} else {
break;
}
// Clear emtpy ul's/ol's
this._clearEmpty(itemElement);
this._trigger("change", event, this._uiHash());
break;
}
}
var parentItem = (this.placeholder[0].parentNode.parentNode
&& $(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
? $(this.placeholder[0].parentNode.parentNode)
: null,
level = this._getLevel(this.placeholder),
childLevels = this._getChildLevels(this.helper),
previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
if (previousItem != null) {
while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0]) {
if (previousItem[0].previousSibling) {
previousItem = $(previousItem[0].previousSibling);
} else {
previousItem = null;
break;
}
}
}
newList = document.createElement(o.listType);
this.beyondMaxLevels = 0;
// If the item is moved to the left, send it to its parent level
if (parentItem != null && this.positionAbs.left < parentItem.offset().left) {
parentItem.after(this.placeholder[0]);
this._clearEmpty(parentItem[0]);
this._trigger("change", event, this._uiHash());
}
// If the item is below another one and is moved to the right, make it a children of it
else if (previousItem != null && this.positionAbs.left > previousItem.offset().left + o.tabSize) {
this._isAllowed(previousItem, level+childLevels+1);
if (!previousItem.children(o.listType).length) {
previousItem[0].appendChild(newList);
}
previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
this._trigger("change", event, this._uiHash());
}
else {
this._isAllowed(parentItem, level+childLevels);
}
//Post events to containers
this._contactContainers(event);
//Interconnect with droppables
if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
//Call callbacks
this._trigger('sort', event, this._uiHash());
this.lastPositionAbs = this.positionAbs;
return false;
},
_mouseStop: function(event, noPropagation) {
// If the item is in a position not allowed, send it back
if (this.beyondMaxLevels) {
this.placeholder.removeClass(this.options.errorClass);
if (this.options.revertOnError) {
if (this.domPosition.prev) {
$(this.domPosition.prev).after(this.placeholder);
} else {
$(this.domPosition.parent).prepend(this.placeholder);
}
this._trigger("revert", event, this._uiHash());
} else {
var parent = this.placeholder.parent().closest(this.options.items);
for (var i = this.beyondMaxLevels - 1; i > 0; i--) {
parent = parent.parent().closest(this.options.items);
}
parent.after(this.placeholder);
this._trigger("change", event, this._uiHash());
}
}
// Clean last empty ul/ol
for (var i = this.items.length - 1; i >= 0; i--) {
var item = this.items[i].item[0];
this._clearEmpty(item);
}
$.ui.sortable.prototype._mouseStop.apply(this, arguments);
},
serialize: function(o) {
var items = this._getItemsAsjQuery(o && o.connected),
str = []; o = o || {};
$(items).each(function() {
var res = ($(o.item || this).attr(o.attribute || 'id') || '')
.match(o.expression || (/(.+)[-=_](.+)/)),
pid = ($(o.item || this).parent(o.listType)
.parent('li')
.attr(o.attribute || 'id') || '')
.match(o.expression || (/(.+)[-=_](.+)/));
if (res) {
str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']')
+ '='
+ (pid ? (o.key && o.expression ? pid[1] : pid[2]) : 'root'));
}
});
if(!str.length && o.key) {
str.push(o.key + '=');
}
return str.join('&');
},
toHierarchy: function(o) {
o = o || {};
var sDepth = o.startDepthCount || 0,
ret = [];
$(this.element).children('li').each(function () {
var level = _recursiveItems($(this));
ret.push(level);
});
return ret;
function _recursiveItems(li) {
var id = ($(li).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
if (id) {
var item = {"id" : id[2]};
if ($(li).children(o.listType).children('li').length > 0) {
item.children = [];
$(li).children(o.listType).children('li').each(function() {
var level = _recursiveItems($(this));
item.children.push(level);
});
}
return item;
}
}
},
toArray: function(o) {
o = o || {};
var sDepth = o.startDepthCount || 0,
ret = [],
left = 2;
ret.push({
"item_id": 'root',
"parent_id": 'none',
"depth": sDepth,
"left": '1',
"right": ($('li', this.element).length + 1) * 2
});
$(this.element).children('li').each(function () {
left = _recursiveArray(this, sDepth + 1, left);
});
ret = ret.sort(function(a,b){ return (a.left - b.left); });
return ret;
function _recursiveArray(item, depth, left) {
var right = left + 1,
id,
pid;
if ($(item).children(o.listType).children('li').length > 0) {
depth ++;
$(item).children(o.listType).children('li').each(function () {
right = _recursiveArray($(this), depth, right);
});
depth --;
}
id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
if (depth === sDepth + 1) {
pid = 'root';
} else {
var parentItem = ($(item).parent(o.listType)
.parent('li')
.attr(o.attribute || 'id'))
.match(o.expression || (/(.+)[-=_](.+)/));
pid = parentItem[2];
}
if (id) {
ret.push({"item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right});
}
left = right + 1;
return left;
}
},
_clearEmpty: function(item) {
var emptyList = $(item).children(this.options.listType);
if (emptyList.length && !emptyList.children().length) {
emptyList.remove();
}
},
_getLevel: function(item) {
var level = 1;
if (this.options.listType) {
var list = item.closest(this.options.listType);
while (!list.is('.ui-sortable')) {
level++;
list = list.parent().closest(this.options.listType);
}
}
return level;
},
_getChildLevels: function(parent, depth) {
var self = this,
o = this.options,
result = 0;
depth = depth || 0;
$(parent).children(o.listType).children(o.items).each(function (index, child) {
result = Math.max(self._getChildLevels(child, depth + 1), result);
});
return depth ? result + 1 : result;
},
_isAllowed: function(parentItem, levels) {
var o = this.options;
// Are we trying to nest under a no-nest or are we nesting too deep?
if (parentItem == null || !(parentItem.hasClass(o.disableNesting))) {
if (o.maxLevels < levels && o.maxLevels != 0) {
this.placeholder.addClass(o.errorClass);
this.beyondMaxLevels = levels - o.maxLevels;
} else {
this.placeholder.removeClass(o.errorClass);
this.beyondMaxLevels = 0;
}
} else {
this.placeholder.addClass(o.errorClass);
if (o.maxLevels < levels && o.maxLevels != 0) {
this.beyondMaxLevels = levels - o.maxLevels;
} else {
this.beyondMaxLevels = 1;
}
}
}
}));
$.ui.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.ui.nestedSortable.prototype.options);
})(jQuery);
+8
View File
@@ -0,0 +1,8 @@
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
//= require jquery
//= require jquery_ujs
@@ -32,3 +32,24 @@ $('.part_kind').live('click', function() {
$('.part_kind_partial').hide();
$('#part_' + $(this).attr('value')).show();
});
$(document).ready(function(){
$('ol.sortable').nestedSortable({
disableNesting: 'no-nest',
forcePlaceholderSize: true,
handle: 'i',
helper: 'clone',
items: 'li',
maxLevels: 3,
opacity: .5,
placeholder: 'placeholder',
revert: 250,
tabSize: 25,
tolerance: 'pointer',
toleranceElement: '> div',
stop: function(event, ui) {
$.post("<%= Rails.application.routes.url_helpers.admin_update_position_path %>", { id: ui.item.attr('id'), parent_id: ui.item.parent().closest('li').attr('id'), position: ui.item.index() } );
}
});
});
+7 -1
View File
@@ -5,6 +5,9 @@
// the compiled file.
//
//= require jquery
//= require jquery.ui.draggable
//= require jquery.ui.droppable
//= require jquery.ui.sortable
//= require jquery_ujs
//= require bootstrap
//= require jquery.isotope.min
@@ -12,4 +15,7 @@
//= require orbit-1.0
//= require orbit-bar-search
//= require side_bar_history
//= require page_edit
//= require page_edit
//= require tinymce-jquery
//= require tinymce_orbit
//= require lib/jquery.ui.nestedSortable.js
+5 -1
View File
@@ -1,4 +1,4 @@
$(function() {
function load_tinymce() {
$('.tinymce_textarea').tinymce({
theme: 'advanced',
plugins : "autolink,lists,spellchecker,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
@@ -22,4 +22,8 @@ $(function() {
external_image_list_url : "js/image_list.js",
media_external_list_url : "js/media_list.js"
});
}
$(document).ready(function() {
load_tinymce();
});
+29 -4
View File
@@ -6,13 +6,14 @@
.nav-list li {
position: relative;
}
.nav-list ul {
margin-left: 10px;
.nav-list ol {
margin-left: 20px;
}
.nav-list ul li {
.nav-list ol li {
padding: 5px 0;
list-style: none;
}
.nav-list ul li a {
.nav-list ol li a {
font-size: 13px;
padding: 3px 0px;
display: block;
@@ -148,4 +149,28 @@
}
#main-sidebar .quick-edit a:hover {
background-color: #DDDDDD;
}
ol.nav>li>.icons-moves {
display: none;
}
.sortable i {
position: absolute;
left: -20px;
top: 6px;
margin-right: 0;
opacity: 0.3;
filter: alpha(opacity=30);
}
.sortable i:hover {
cursor:move;
opacity: 0.7;
filter: alpha(opacity=70);
}
.placeholder {
background-color: rgba(0,136,204,.6);
border-radius: 3px;
}
.ui-nestedSortable-error {
background: rgba(255,206,206,.6);
color: #8a1f11;
}
+81 -5
View File
@@ -110,10 +110,8 @@
padding:6px;
}
#orbit-bar .nav > li.search {
background-image: none;
overflow: hidden;
width: 28px;
margin-bottom: 0;
position: relative;
}
#orbit-bar .nav > li > a.orbit-bar-home {
@@ -685,6 +683,33 @@
#banner [id^="slideshow-"] {
z-index: 2 !important;
}
#back_main .editable {
position: relative;
}
#back_main .editable:after {
content: '';
clear: both;
display: block;
visibility: hidden;
height: 0;
}
#back_main .edit_link a {
position: absolute;
z-index: 10;
width: 100%;
height: 100%;
top: 0;
left: 0;
text-indent: -9999px;
background: url(<%= asset_path 'editicon.png' %>) no-repeat center center rgba(255,255,255,.8);
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 1);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 1);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 1);
}
[class^="icons-"] {
display: inline-block;
width: 16px;
@@ -1243,12 +1268,63 @@
.icons-plus {
background-position: -288px -576px;
}
/*20*/
.icons-power {
background-position: -0px -608px;
}
/*20*/
.icons- {
background-position: -0px -608px;
.icons-output {
background-position: -32px -608px;
}
.icons-col-resize {
background-position: -64px -608px;
}
.icons-move {
background-position: -96px -608px;
}
.icons-size-out {
background-position: -128px -608px;
}
.icons-size-in {
background-position: -160px -608px;
}
.icons-slash {
background-position: -192px -608px;
}
.icons-level {
background-position: -224px -608px;
}
.icons-share {
background-position: -256px -608px;
}
.icons-share2 {
background-position: -288px -608px;
}
.icons-re {
background-position: -320px -608px;
}
.icons-insert {
background-position: -352px -608px;
}
.icons-insert2 {
background-position: -384px -608px;
}
.icons-download {
background-position: -416px -608px;
}
.icons-tag-rignt {
background-position: -448px -608px;
}
.icons-tag-top {
background-position: -480px -608px;
}
.icons-tag-bottom {
background-position: -512px -608px;
}
.icons-tag-left {
background-position: -544px -608px;
}
.icons-moves {
background-position: -576px -608px;
}
/*21*/
.icons- {
@@ -15,6 +15,12 @@ class Admin::ItemsController < ApplicationController
@item = get_homepage
end
end
def update_position
item = Item.find(params[:id])
item.shift_to(params[:parent_id], params[:position])
render :nothing => true
end
protected
@@ -11,7 +11,17 @@ class Admin::ModuleAppsController < ApplicationController
def reload_frontend_pages
@module_app = ModuleApp.find(params[:id])
@categories = @module_app.key.eql?('announcement') ? BulletinCategory.all : nil
case @module_app.key
when 'announcement'
@categories = BulletinCategory.all
@tags = AnnouncementTag.all
when 'news'
@categories = NewsBulletinCategory.all
@tags = NewsTag.all
when 'web_resource'
@categories = WebLinkCategory.all
@tags = WebResourceTag.all
end
respond_to do |format|
format.js {}
end
@@ -22,17 +22,20 @@ class Admin::PagePartsController < ApplicationController
def edit
@part = PagePart.find(params[:id])
@module_apps = ModuleApp.all(:conditions => {:enable_frontend => true})
@module_apps = ModuleApp.excludes(widgets: nil).where(enable_frontend: true).order_by(:title, :asc)
@module_app = @part.module_app ? @part.module_app : @module_apps[0]
@r_tag = @part.public_r_tag.blank? ? LIST[:public_r_tags][0] : @part.public_r_tag
@tag_objects = @r_tag.classify.constantize.all rescue nil
case @module_app.key
when 'announcement'
@categories = BulletinCategory.all
@tags = AnnouncementTag.all
when 'news'
@categories = NewsBulletinCategory.all
@tags = NewsTag.all
when 'web_resource'
@categories = WebLinkCategory.all
@tags = WebResourceTag.all
end
end
@@ -69,10 +72,13 @@ class Admin::PagePartsController < ApplicationController
case @module_app.key
when 'announcement'
@categories = BulletinCategory.all
@tags = AnnouncementTag.all
when 'news'
@categories = NewsBulletinCategory.all
@tags = NewsTag.all
when 'web_resource'
@categories = WebLinkCategory.all
@tags = WebResourceTag.all
end
respond_to do |format|
format.js {}
+5 -2
View File
@@ -20,14 +20,14 @@ class Admin::PagesController < ApplicationController
def new
@item = Page.new
@item.parent = Item.find(params[:parent_id]) rescue nil
@apps = ModuleApp.all
@apps = ModuleApp.excludes(app_pages: nil).entries
@designs = Design.all.entries
@design = Design.first
end
def edit
@item = Page.find(params[:id])
@apps = ModuleApp.all
@apps = ModuleApp.excludes(app_pages: nil).entries
@designs = Design.all.entries
@design = @item.design ? @item.design : @designs.first
@app_frontend_urls = @item.module_app.app_pages if @item.module_app
@@ -35,10 +35,13 @@ class Admin::PagesController < ApplicationController
case @item.module_app.key
when 'announcement'
@categories = BulletinCategory.all
@tags = AnnouncementTag.all
when 'news'
@categories = NewsBulletinCategory.all
@tags = NewsTag.all
when 'web_resource'
@categories = WebLinkCategory.all
@tags = WebResourceTag.all
end
else
@categories = nil
+2 -2
View File
@@ -99,9 +99,9 @@ class ApplicationController < ActionController::Base
end
# Render the page
def render_page(param={})
def render_page
if @item
render :text => process_page(@item, param[:id], param), :layout => 'page_layout'
render :text => parse_page_noko(@item), :layout => 'page_layout'
else
render :text => '404 Not Found'
end
+1 -1
View File
@@ -24,7 +24,7 @@ class OrbitBackendController< ApplicationController
def check_user_can_use
unless check_permission
#redirect_to polymorphic_path(['panel',@app_title,'back_end','public'])
render :text => '403 Forbidden'
redirect_to root_url
end
end
@@ -1,7 +1,7 @@
class OrbitFrontendComponentController< ApplicationController
before_filter :setup_vars
before_filter {|c| c.front_end_available(@app_title)}
layout :false
layout "module_widget"
def setup_vars
@app_title = request.fullpath.split('/')[2]
+12 -10
View File
@@ -15,11 +15,11 @@ class PagesController < ApplicationController
def show
#begin
@item = Item.first(:conditions => {:full_name => params[:page_name]})
@item = Item.first(:conditions => {:path => params[:page_name]})
if @item && @item.is_published && (@item.enabled_for.nil? ? true : @item.enabled_for.include?(I18n.locale.to_s))
case @item._type
when 'Page'
render_page(params)
render_page
when 'Link'
redirect_to "http://#{@item[:url]}"
end
@@ -32,17 +32,19 @@ class PagesController < ApplicationController
end
def index_from_link
if params[:page]
redirect_to "/#{@item.full_name}?page=#{params[:page]}&category_id=#{params[:category_id]}&tag_id=#{params[:tag_id]}"
else
redirect_to "/#{@item.full_name}?category_id=#{params[:category_id]}&tag_id=#{params[:tag_id]}"
end
url = "/#{@item.path}"
options = ''
options << "?page_main=#{params[:page_main]}" unless params[:page_main].blank?
options << "#{options.blank? ? '?' : '&'}category_id=#{params[:category_id]}" unless params[:category_id].blank?
options << "#{options.blank? ? '?' : '&'}tag_id=#{params[:tag_id]}" unless params[:tag_id].blank?
redirect_to url + options
end
def show_from_link
# debugger
# a=1
redirect_to "/#{@item.full_name}?id=#{params[:id]}&preview=#{params[:preview]}"
url = "/#{@item.path}?id=#{params[:id]}"
options = ''
options << "&preview=#{params[:preview]}" unless params[:preview].blank?
redirect_to url + options
end
def load_orbit_bar
+8 -6
View File
@@ -8,9 +8,10 @@ module Admin::ItemHelper
dest = admin_page_path(node)
when 'Link'
dest = admin_link_path(node)
no_nested = 'no-nest'
end
ret << "<ul>" unless node.parent.nil?
ret << "<li>"
ret << "<li id='#{node.id}' class='#{no_nested}'>"
ret << "<i class='icons-moves'></i>"
ret << "<div class='with_action'>"
ret << (link_to node.i18n_variable[I18n.locale], dest)
ret << "<div class='quick-edit hide'>"
@@ -22,22 +23,23 @@ module Admin::ItemHelper
ret << "</div>"
ret << render_children(node)
ret << "</li>"
ret << "</ul>" unless node.parent.nil?
end
ret.html_safe
end
def render_children(parent)
children = parent.ordered_children
if !children.entries.blank?
children = parent.children
if !parent.children.entries.blank?
ret = ''
ret << "<ol class='#{'sortable' if parent.parent.nil?}'>"
children.each do |child|
ret << render_node_and_children(child)
end
ret << '</ol>'
ret
else
''
end
end
end
end
+2 -6
View File
@@ -103,11 +103,7 @@ module ApplicationHelper
def active_for_action(controller_name, action_name)
((controller.controller_name.eql?(controller_name) || request.fullpath.eql?(controller_name)) && controller.action_name.eql?(action_name)) ? 'active' : nil
end
def process_page(page, id, params)
parse_page_noko(page, id, params)
end
def page_metas(page)
tmp_meta = {}
metas = ''
@@ -128,7 +124,7 @@ module ApplicationHelper
def page_title(page)
res = "<title>"
page_title = page.title ? page.title[I18n.locale] : page.i18n_variable[I18n.locale]
if page.is_home? && @site.title
if page.root? && @site.title
res << @site.title[I18n.locale]
elsif @site.title && @site.title_always_on
res << @site.title[I18n.locale] + ' - ' + page_title
+33 -54
View File
@@ -2,59 +2,31 @@ class Item
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Tree
include Mongoid::Tree::Ordering
field :name, :index => true
field :full_name, :index => true
field :position, :type => Integer
field :is_published, :type => Boolean, :default => false, :index => true
field :enabled_for, :type => Array, :default => nil
field :menu_enabled_for, :type => Array, :default => nil
field :name
field :path
field :is_published, :type => Boolean, :default => false
field :enabled_for, :type => Array, :default => nil
field :menu_enabled_for, :type => Array, :default => nil
validates_format_of :name, :with => /^[0-9a-zA-Z\-_]+$/
validates :name, :exclusion => { :in => LIST[:forbidden_item_names] }
validates_uniqueness_of :name, :scope => :parent_id
validates_presence_of :name, :full_name, :position
validates_presence_of :name
validates_associated :parent, :children
after_rearrange :rebuild_path
belongs_to :parent, :class_name => "Item"
has_one :i18n_variable, :as => :language_value, :autosave => true, :dependent => :destroy
has_many :children, :class_name => "Item", :as => 'parent'
before_validation :setup_default_value
def self.find_by_name(item_name)
Item.first(:conditions => { :name => item_name, :is_published => true })
end
# Get an array of ancestors
def ancestors
node, nodes = self, []
nodes << node = node.parent while !node.parent.blank? rescue nil
nodes.reverse
end
# Get an array of ancestor's id
def ancestor_ids
node, nodes = self, []
while !node.parent.blank? do
node = node.parent rescue nil
nodes << node.id if node
end
# nodes << node = node.parent while !node.parent.blank? rescue nil
nodes.reverse
end
# Build the url from the array of ancestors
def url
urls = ancestors.map{ |a| a.name } << self.name
urls.join("/")
end
def ordered_children
self.children.asc(:position)
end
def ordered_and_visible_children
objects = ordered_children
def visible_children
objects = self.children
a = []
if objects
objects.each do |object|
@@ -63,23 +35,30 @@ class Item
end
a
end
def shift_to(new_parent, position)
unless self.parent_id.to_s.eql?(new_parent) && self.position.eql?(position.to_i)
new_parent = Item.find(new_parent)
current_position_sibling = find_by_parent_and_position(new_parent, position.to_i)
if current_position_sibling
current_position_sibling.at_bottom? ? move_below(current_position_sibling) : move_above(current_position_sibling)
elsif self.parent != new_parent
self.parent = new_parent
save!
end
end
end
protected
def setup_default_value
# Set the position value within the parent scope
if self.position.blank?
max_page = Item.where(:parent_id => self.parent_id).count
self.position = (max_page)? max_page + 1 : 1
end
# Build the full_name from the ancestors array
full_node = self.ancestors.map{ |a| a.name }.push( self.name )
# Remove root node if not root
full_node.shift if full_node.size >= 2
self.full_name = full_node.join("/")
def rebuild_path
self.path = (self.ancestors_and_self - [Item.root]).collect{|x| x.name unless x.root?}.join('/')
end
def find_by_parent_and_position(parent, position)
parent.children.detect{|child| child.position == position}
end
# Enable the validation for parent_id
def validates_presence_of_parent_id?
true
+2 -4
View File
@@ -3,6 +3,8 @@ class Page < Item
field :content
field :app_frontend_url
field :theme_id, :type => BSON::ObjectId, :default => nil
field :category
field :tag
belongs_to :design
belongs_to :module_app
@@ -15,10 +17,6 @@ class Page < Item
before_save :create_parts, :set_key
# embeds_many :custom_images, :class_name => 'Image', as: :design_image
def is_home?
self.parent ? false : true
end
def title
@title ||= I18nVariable.first(:conditions => {:key => 'title', :language_value_id => self.id, :language_value_type => self.class}) rescue nil
+19 -1
View File
@@ -11,9 +11,27 @@ class PagePart
field :public_r_tag_option, :default => nil
field :widget_path
has_one :i18n_variable, :as => :language_value, :autosave => true, :dependent => :destroy
has_one :i18n_variable, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy
has_one :title, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy
belongs_to :page
belongs_to :module_app
before_save :set_key
def i18n_variable
@i18n_variable ||= I18nVariable.first(:conditions => {:key => 'i18n_variable', :language_value_id => self.id, :language_value_type => self.class}) rescue nil
end
def title
@title ||= I18nVariable.first(:conditions => {:key => 'title', :language_value_id => self.id, :language_value_type => self.class}) rescue nil
end
protected
def set_key
title.key = 'title' if title && (title.key.blank? rescue true)
i18n_variable.key = 'i18n_variable' if i18n_variable && (i18n_variable.key.blank? rescue true)
end
end
@@ -1 +1 @@
<%= render_node_and_children(Item.first(:conditions => {:parent_id => nil})) %>
<%= render_node_and_children(Item.first(:conditions => {:parent_id => nil})) %>
@@ -1,2 +1,3 @@
$('#app_page_url').html("<%= escape_javascript(select 'page', 'app_frontend_url', @module_app.app_pages) %>");
$('#app_page_category').html("<%= escape_javascript(select 'page', 'category', @categories.collect{|category| [category.i18n_variable[I18n.locale], category.id]}) if @categories %>");
$('#app_page_category').html("<%= j (select 'page', 'category', @categories.collect{|category| [category.i18n_variable[I18n.locale], category.id]}, {:include_blank => true}) if @categories %>");
$('#app_page_tag').html("<%= j (select 'page', 'tag', @tags.collect{|tag| [tag[I18n.locale], tag.id]}, {:include_blank => true}) if @tags %>");
+1 -1
View File
@@ -2,7 +2,7 @@
<% LIST[:page_part_kinds].each do |kind| %>
<%= f.radio_button :kind, kind, :class => 'part_kind' %>
<%= t(kind) %>
<%= t(kind, :scope => 'admin.page_part_kinds') %>
<% end %>
<% LIST[:page_part_kinds].each do |kind| %>
@@ -1,3 +1,14 @@
<div>
<%= f.fields_for :title, @part.title do |f| %>
<% @site_valid_locales.each do |locale| %>
<p>
<%= f.label :locale, "#{t('admin.title')} #{I18nVariable.from_locale(locale)}" %>
<%= f.text_field locale %>
</p>
<% end %>
<% end %>
</div>
<span id='module_app_list'>
<%= f.select :module_app, options_from_collection_for_select(@module_apps, :id, :title, :selected => @module_app.id), {}, {:rel => admin_page_parts_path} %>
</span>
@@ -6,7 +17,12 @@
<%= f.select :widget_path, @module_app.widgets.collect{|widget| [widget.humanize, widget]}, :selected => @part.widget_path %>
</span>
:
<span id="widget_category">
<%= render 'widget_categories' %>
</span>
<%= t :or_lower %>
<span id="widget_tag">
<%= render 'widget_tags' %>
</span>
+8 -2
View File
@@ -2,7 +2,13 @@
<% @site_valid_locales.each do |locale| %>
<div>
<%= I18nVariable.from_locale(locale) %>
<%= f.text_area locale %>
<%= f.text_area locale, :class => 'tinymce_textarea' %>
</div>
<% end %>
<% end %>
<% end %>
<script>
$(document).ready(function() {
load_tinymce();
});
</script>
@@ -0,0 +1 @@
<%= select 'page_part', 'tag', @tags.collect{|category| [category[I18n.locale], category.id]}, :selected => (@part ? @part[:tag] : nil), :include_blank => true if @tags && @tags.size > 0 %>
@@ -1,2 +1,3 @@
$('#widget_list select').html("<%= j options_for_select(@module_app.widgets.collect{|widget| [widget.humanize, widget]}) %>")
$('#widget_category').html("<%= j render 'widget_categories' %>")
$('#widget_category').html("<%= j render 'widget_categories' %>")
$('#widget_tag').html("<%= j render 'widget_tags' %>")
+10 -9
View File
@@ -1,10 +1,11 @@
<%= flash_messages %>
<h1><%= t('admin.editing_page') %></h1>
<%= form_for @item, :url => admin_page_path(@item) do |f| %>
<%= render :partial => "form", :locals => { :f => f } %>
<p>
<%= f.submit t('update') %> <%= link_back %>
</p>
<% end %>
<div id="poststuff">
<h1><%= t('admin.editing_page') %></h1>
<%= form_for @item, :url => admin_page_path(@item), :html => { :class => 'form-horizontal edit_page' } do |f| %>
<%= render :partial => "form", :locals => { :f => f } %>
<div class="form-actions">
<%= f.submit t('update'), :class => 'btn btn-primary' %>
<%= link_to t('cancel'), get_go_back, :class=>"btn" %>
</div>
<% end %>
</div>
+87 -44
View File
@@ -1,52 +1,95 @@
<%= f.error_messages %>
<%= f.hidden_field :parent, :value => (@item.parent.id rescue nil) %>
<p>
<%= f.label :name, t('admin.name') %>
<%= f.text_field :name, :class => 'text' %>
</p>
<div class="control-group">
<%= f.label :name, t('admin.name'), :class => 'control-label' %>
<div class="controls">
<%= f.text_field :name, :class => 'text input-xlarge' %>
<!-- <p class="help-block">In addition to freeform text, any HTML5 text-based input appears like so.</p> -->
</div>
</div>
<%= f.fields_for :i18n_variable, (@item.new_record? ? @item.build_i18n_variable : @item.i18n_variable) do |f| %>
<% @site_valid_locales.each do |locale| %>
<p>
<%= f.label :locale, "#{t('admin.title')} #{I18nVariable.from_locale(locale)}" %>
<%= f.text_field locale %>
</p>
<% end %>
<% @site_valid_locales.each do |locale| %>
<div class="control-group">
<%= f.label :locale, "#{t('admin.title')} #{I18nVariable.from_locale(locale)}", :class => 'control-label' %>
<div class="controls">
<%= f.text_field locale, :class => 'text input-xlarge' %>
<!-- <p class="help-block">In addition to freeform text, any HTML5 text-based input appears like so.</p> -->
</div>
</div>
<% end %>
<% end %>
<p>
<%= t('admin.design_name') %>
<%= f.collection_select :design, @designs, :id, :title, {:selected => @design.id}, {:rel => admin_pages_path} %>
</p>
<p>
<%= t('admin.theme') %>
<%= f.select :theme_id, @design.themes.collect { |t| [t.name.capitalize, t.id] }, :include_blank => true %>
</p>
<p>
<%= t('admin.module_app') %>
<%= render :partial => "app_selector", :locals => { :f => f } %>
<span id="app_page_url"><%= select('page','app_frontend_url', @app_frontend_urls, :selected => @item.app_frontend_url ) rescue ''%> </span>
<span id="app_page_category"><%= select('page','category', @categories.collect{|category| [category.i18n_variable[I18n.locale], category.id]}, :selected => @item[:category], :include_blank => true ) rescue ''%> </span>
</p>
<p>
<%= f.label :is_published, "#{t('admin.is_published')} ?" %>
<%= f.radio_button :is_published, true %>Yes <%= f.radio_button :is_published, false %> No
</p>
<p>
<%= f.label :menu_enabled_for, "#{t('admin.menu_enabled_for')}:" %>
<% @site_valid_locales.each do |valid_locale| %>
<%= check_box_tag 'page[menu_enabled_for][]', valid_locale, (@item.menu_enabled_for.nil? ? true : @item.menu_enabled_for.include?(valid_locale)) %>
<%= I18nVariable.from_locale(valid_locale) %>
<% end %>
<%= hidden_field_tag 'page[menu_enabled_for][]', '' %>
</p>
<p>
<%= f.label :enabled_for, "#{t('admin.enabled_for')}:" %>
<% @site_valid_locales.each do |valid_locale| %>
<%= check_box_tag 'page[enabled_for][]', valid_locale, (@item.enabled_for.nil? ? true : @item.enabled_for.include?(valid_locale)) %>
<%= I18nVariable.from_locale(valid_locale) %>
<% end %>
<%= hidden_field_tag 'page[enabled_for][]', '' %>
</p>
<div class="control-group">
<%= f.label :name, t('admin.design_name'), :class => 'control-label' %>
<div class="controls">
<%= f.collection_select :design, @designs, :id, :title, {:selected => @design.id}, {:rel => admin_pages_path} %>
<!-- <p class="help-block">In addition to freeform text, any HTML5 text-based input appears like so.</p> -->
</div>
</div>
<div class="control-group">
<%= f.label :name, t('admin.theme'), :class => 'control-label' %>
<div class="controls">
<%= f.select :theme_id, @design.themes.collect { |t| [t.name.capitalize, t.id] }, :include_blank => true %>
<!-- <p class="help-block">In addition to freeform text, any HTML5 text-based input appears like so.</p> -->
</div>
</div>
<div class="control-group">
<%= f.label :name, t('admin.module_app'), :class => 'control-label' %>
<div class="controls">
<%= render :partial => "app_selector", :locals => { :f => f } %>
<span id="app_page_url">
<%= select('page','app_frontend_url', @app_frontend_urls, :selected => @item.app_frontend_url ) rescue ''%>
</span>
<span id="app_page_category">
<%= select('page','category', @categories.collect{|category| [category.i18n_variable[I18n.locale], category.id]}, :selected => @item[:category], :include_blank => true ) rescue ''%>
</span>
<span id="app_page_tag">
<%= select('page','tag', @tags.collect{|tag| [tag[I18n.locale], tag.id]}, :selected => @item[:tag], :include_blank => true ) rescue ''%>
</span>
<!-- <p class="help-block">In addition to freeform text, any HTML5 text-based input appears like so.</p> -->
</div>
</div>
<div class="control-group">
<%= f.label :is_published, "#{t('admin.is_published')} ?", :class => 'control-label' %>
<div class="controls">
<label class="radio">
<%= f.radio_button :is_published, true %>
Yes
</label>
<label class="radio">
<%= f.radio_button :is_published, false %>
No
</label>
<!-- <p class="help-block">In addition to freeform text, any HTML5 text-based input appears like so.</p> -->
</div>
</div>
<div class="control-group">
<%= f.label :menu_enabled_for, "#{t('admin.menu_enabled_for')}:", :class => 'control-label' %>
<div class="controls">
<% @site_valid_locales.each do |valid_locale| %>
<label class="checkbox">
<%= check_box_tag 'page[menu_enabled_for][]', valid_locale, (@item.menu_enabled_for.nil? ? true : @item.menu_enabled_for.include?(valid_locale)) %>
<%= I18nVariable.from_locale(valid_locale) %>
</label>
<% end %>
<%= hidden_field_tag 'page[menu_enabled_for][]', '' %>
<!-- <p class="help-block">In addition to freeform text, any HTML5 text-based input appears like so.</p> -->
</div>
</div>
<div class="control-group">
<%= f.label :enabled_for, "#{t('admin.enabled_for')}:", :class => 'control-label' %>
<div class="controls">
<% @site_valid_locales.each do |valid_locale| %>
<label class="checkbox">
<%= check_box_tag 'page[enabled_for][]', valid_locale, (@item.enabled_for.nil? ? true : @item.enabled_for.include?(valid_locale)) %>
<%= I18nVariable.from_locale(valid_locale) %>
</label>
<% end %>
<%= hidden_field_tag 'page[enabled_for][]', '' %>
<!-- <p class="help-block">In addition to freeform text, any HTML5 text-based input appears like so.</p> -->
</div>
</div>
+10 -12
View File
@@ -1,13 +1,11 @@
<h1><%= t('admin.new_page') %></h1>
<%= flash_messages %>
<%= form_for @item, :url => admin_pages_path, :html => { :class => 'form' } do |f| %>
<%= render :partial => "form", :locals => { :f => f } %>
<p>
<%= f.submit t('create') %> <%= link_back %>
</p>
<% end %>
<div id="poststuff">
<h1><%= t('admin.new_page') %></h1>
<%= form_for @item, :url => admin_pages_path, :html => { :class => 'form-horizontal edit_page' } do |f| %>
<%= render :partial => "form", :locals => { :f => f } %>
<div class="form-actions">
<%= f.submit t('update'), :class => 'btn btn-primary' %>
<%= link_to t('cancel'), get_go_back, :class=>"btn" %>
</div>
<% end %>
</div>
+3 -1
View File
@@ -5,7 +5,9 @@
<%= javascript_include_tag "html5" %>
<![endif]-->
<%#= stylesheet_link_tag "module_widget" %>
<%= javascript_include_tag "module_widget" %>
<%= javascript_include_tag "module" %>
<%#= javascript_include_tag "#{@app_title}/module_widget" %>
<%= yield :page_specific_javascript %>
<%= csrf_meta_tag %>
</head>
<body>
+2 -2
View File
@@ -23,9 +23,9 @@
</div>
<div class="viewport">
<div id='back_sidebar' class="overview">
<ul class="nav nav-list">
<ol class="nav nav-list">
<%= yield :sidebar %>
</ul>
</ol>
</div>
</div>
</nav>