Merge branch 'master' into 263-refactoring

Conflicts:
	db/schema.rb
This commit is contained in:
Pavel Chipiga 2012-07-27 00:19:36 +03:00
commit fb60dac748
22 changed files with 520 additions and 2 deletions

View File

@ -0,0 +1,18 @@
function setCookie (name, value, expires, path, domain, secure) {
document.cookie = name + "=" + escape(value) +
((expires) ? "; expires=" + expires : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "");
}
$(document).ready(function() {
if ($(".alert").size()) {
$(".alert").alert()
}
$('#close-alert').click(function () {
setCookie("flash_notify_hash", FLASH_HASH_ID, FLASH_EXPIRES_AT);
});
});

View File

@ -1186,3 +1186,63 @@ hr.bootstrap {
.modal-body-fork {
max-height: 280px;
}
/* Flash Notifies */
.flash_notify {
.alert-success {
color: #468847;
background-color: #DFF0D8;
border-color: #D6E9C6;
}
.alert {
padding: 8px 35px 8px 14px;
margin-bottom: 18px;
color: #C09853;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
background-color: #FCF8E3;
border: 1px solid #FBEED5;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.alert-danger, .alert-error {
color: #B94A48;
background-color: #F2DEDE;
border-color: #EED3D7;
}
.alert-info {
color: #3A87AD;
background-color: #D9EDF7;
border-color: #BCE8F1;
}
.alert .close {
position: relative;
top: -2px;
right: -21px;
line-height: 18px;
}
button.close {
padding: 0;
cursor: pointer;
background: transparent;
border: 0;
-webkit-appearance: none;
}
.close {
float: right;
font-size: 20px;
font-weight: bold;
line-height: 18px;
color: black;
text-shadow: 0 1px 0 white;
opacity: 0.2;
filter: alpha(opacity=20);
}
}

View File

@ -0,0 +1,41 @@
class Admin::FlashNotifiesController < Admin::BaseController
def index
@flash_notifies = FlashNotify.paginate(:page => params[:page], :per_page => 20)
end
def new
@flash_notify = FlashNotify.new(:published => true)
end
def create
@flash_notify = FlashNotify.new(params[:flash_notify])
if @flash_notify.save
flash[:notice] = t("flash.flash_notify.saved")
redirect_to admin_flash_notifies_path
else
flash[:error] = t("flash.flash_notify.save_error")
flash[:warning] = @flash_notify.errors.full_messages.join('. ')
render :new
end
end
def update
if @flash_notify.update_attributes(params[:flash_notify])
flash[:notice] = t("flash.flash_notify.saved")
redirect_to admin_flash_notifies_path
else
flash[:error] = t("flash.flash_notify.save_error")
flash[:warning] = @flash_notify.errors.full_messages.join('. ')
render :edit
end
end
def destroy
if @flash_notify.destroy
flash[:notice] = t("flash.flash_notify.destroyed")
else
flash[:error] = t("flash.flash_notify.destroy_error")
end
redirect_to admin_flash_notifies_path
end
end

View File

@ -0,0 +1,24 @@
require 'digest/md5'
class FlashNotify < ActiveRecord::Base
# attr_accessible :title, :body
STATUSES = %w[error success info]
validates :status, :inclusion => {:in => STATUSES}
validates :body_ru, :body_en, :status, :presence => true
scope :published, where(:published => true)
def hash_id
@digest ||= Digest::MD5.hexdigest("#{self.id}-#{self.updated_at}")
end
def body(language)
read_attribute("body_#{language}")
end
def should_show?(cookie_hash_id)
cookie_hash_id != hash_id && published
end
end

View File

@ -0,0 +1,21 @@
.leftlist= f.label :body_ru, t("activerecord.attributes.flash_notify.body_ru"), :class => :label
.rightlist= f.text_area :body_ru, :class => 'text_field'
.both
.leftlist= f.label :body_en, t("activerecord.attributes.flash_notify.body_en"), :class => :label
.rightlist= f.text_area :body_en, :class => 'text_field'
.both
.leftlist= f.label :status, t("activerecord.attributes.flash_notify.status"), :class => :label
.rightlist= f.select :status, FlashNotify::STATUSES
.both
.leftlist= f.label :published, t("activerecord.attributes.flash_notify.published"), :class => :label
.rightlist= f.check_box :published
.both
.button_block
= submit_tag t("layout.save")
%span.text_button_padding= t("layout.or")
= link_to t("layout.cancel"), admin_flash_notifies_path, :class => "button"

View File

@ -0,0 +1,6 @@
%h3= t("layout.flash_notifies.edit_header")
= form_for @flash_notify, :url => admin_flash_notify_path(@flash_notify), :html => { :class => :form } do |f|
= render "form", :f => f
= render 'submenu'

View File

@ -0,0 +1,22 @@
= link_to t("layout.flash_notifies.new"), new_admin_flash_notify_path, :class => 'button' if can? :create, FlashNotify
%table#myTable.tablesorter.flash_notifys{:cellspacing => "0", :cellpadding => "0"}
%thead
%tr
%th.th1= t("activerecord.attributes.flash_notify.body_en")
%th.th2= t("activerecord.attributes.flash_notify.body_ru")
%th.th3= t("activerecord.attributes.flash_notify.published")
%th.th3= t("layout.flash_notifies.actions")
%tbody
- @flash_notifies.each do |flash_notify|
%tr{:class => cycle("odd", "even")}
%td= flash_notify.body_en.truncate 18
%td= flash_notify.body_ru.truncate 18
%td= flash_notify.published
%td
= link_to t("layout.flash_notifies.edit"), edit_admin_flash_notify_path(flash_notify)
= link_to t("layout.flash_notifies.delete"), admin_flash_notify_path(flash_notify), :method => :delete, :confirm => t("layout.mass_builds.cancel_confirm") if can?(:delete, flash_notify)
= will_paginate @flash_notifies
= render 'submenu'

View File

@ -0,0 +1,6 @@
%h3= t("layout.flash_notifies.new_header")
= form_for @flash_notify, :url => admin_flash_notifies_path, :html => { :class => :form } do |f|
= render "form", :f => f
= render 'submenu'

View File

@ -0,0 +1,10 @@
- if current_user || APP_CONFIG['anonymous_access']
.flash_notify
- if (flash_notify = FlashNotify.published.first) && flash_notify.should_show?(cookies[:flash_notify_hash])
.alert{:class => "alert-#{flash_notify.status}"}
= flash_notify.body I18n.locale
%a.close#close-alert{:'data-dismiss'=>"alert", :href=>"#"} &times;
:javascript
var FLASH_HASH_ID = "#{flash_notify.hash_id}";
var FLASH_EXPIRES_AT = "#{Date.today + 1.year}";

View File

@ -47,6 +47,7 @@
= yield :feed_tabs
.both
= render "layouts/flashes"
= render "layouts/notifies"
%article
- if content_for?(:sidebar)
%aside= yield :sidebar

View File

@ -37,5 +37,6 @@ en:
admins_menu:
users: Users
register_requests: Invites
flash_notifies: Notifies
event_logs: Event log
resque_server: Resque

View File

@ -37,5 +37,6 @@ ru:
admins_menu:
users: Пользователи
register_requests: Инвайты
flash_notifies: Оповещения
event_logs: Лог событий
resque_server: Resque

View File

@ -0,0 +1,28 @@
en:
layout:
flash_notifies:
list_header: Notifies
new: New notify
new_header: New notify
actions: Actions
edit: Edit
edit_header: Edit notify
delete: Delete
flash:
flash_notify:
saved: Notify added
save_error: Unable to add notify
destroyed: Notify deleted
activerecord:
models:
flash_notify: Notify
attributes:
flash_notify:
body_ru: Body Ru
body_en: Body En
published: Published
status: Status
created_at: Created
updated_at: Updated

View File

@ -0,0 +1,28 @@
ru:
layout:
flash_notifies:
list_header: Оповещения
new: Новое оповещение
new_header: Новое оповещение
actions: Действия
edit: Редактирование
edit_header: Редактировать оповещение
delete: Удалить
flash:
flash_notify:
saved: Оповещение сохранено
save_error: Не получилось сохранить оповещение
destroyed: Оповещение удалено
activerecord:
models:
flash_notify: Оповещение
attributes:
flash_notify:
body_ru: Текст Ru
body_en: Текст En
published: Опубликовано
status: Статус
created_at: Создано
updated_at: Обновлено

View File

@ -32,6 +32,7 @@ Rosa::Application.routes.draw do
get :reject
end
end
resources :flash_notifies
resources :event_logs, :only => :index
constraints Rosa::Constraints::AdminAccess do
mount Resque::Server => 'resque'

View File

@ -0,0 +1,11 @@
class CreateFlashNotifies < ActiveRecord::Migration
def change
create_table :flash_notifies do |t|
t.text :body_ru, :null => false
t.text :body_en, :null => false
t.string :status, :null => false
t.boolean :published, :null => false, :default => true
t.timestamps
end
end
end

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20120703101719) do
ActiveRecord::Schema.define(:version => 20120719045806) do
create_table "activity_feeds", :force => true do |t|
t.integer "user_id", :null => false
@ -159,6 +159,15 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.datetime "updated_at"
end
create_table "flash_notifies", :force => true do |t|
t.text "body_ru", :null => false
t.text "body_en", :null => false
t.string "status", :null => false
t.boolean "published", :default => true, :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "groups", :force => true do |t|
t.integer "owner_id"
t.datetime "created_at"

View File

@ -0,0 +1,124 @@
require 'spec_helper'
describe Admin::FlashNotifiesController do
before(:each) do
stub_symlink_methods
@user = FactoryGirl.create(:user)
@create_params = {
:flash_notify => {
:body_ru => "Hello! I`m ru body",
:body_en => "Hello! I`m en body",
:status => "error",
:published => true
}
}
@flash_notify = FactoryGirl.create(:flash_notify)
@flash_notify2 = FactoryGirl.create(:flash_notify)
@update_params = {
:id => @flash_notify,
:flash_notify => {
:body_ru => "updated!"
}
}
end
context 'for guest' do
[:index, :create, :update, :edit, :new, :destroy].each do |action|
it "should not be able to perform #{ action } action" do
get action, :id => @flash_notify
response.should redirect_to(new_user_session_path)
end
end
it 'should not change objects count on create' do
lambda { post :create, @create_params }.should change{ FlashNotify.count }.by(0)
end
it 'should not change objects count on destroy' do
lambda { delete :destroy, :id => @flash_notify }.should change{ FlashNotify.count }.by(0)
end
it 'should not change flash notify body on update' do
put :update, @update_params
@flash_notify.reload.body_ru.should_not == "updated!"
end
end
context 'for global admin' do
before(:each) do
@admin = FactoryGirl.create(:admin)
@user = FactoryGirl.create(:user)
set_session_for(@admin)
end
it 'should load 2 flash notifies objects on index' do
get :index
assigns[:flash_notifies].count.should == 2
end
[:index, :new, :edit].each do |action|
it "should be able to perform #{action} action" do
get action, :id => @flash_notify
response.should render_template(action)
end
end
it 'should be able to perform create action' do
post :create, @create_params
response.should redirect_to(admin_flash_notifies_path)
end
it 'should change objects count on create' do
lambda { post :create, @create_params }.should change{ FlashNotify.count }.by(1)
end
it 'should be able to perform destroy action' do
delete :destroy, :id => @flash_notify
response.should redirect_to(admin_flash_notifies_path)
end
it 'should change objects count on destroy' do
lambda { delete :destroy, :id => @flash_notify }.should change{ FlashNotify.count }.by(-1)
end
it 'should be able to perform update action' do
put :update, @update_params
response.should redirect_to(admin_flash_notifies_path)
end
it 'should change flash notify body on update' do
put :update, @update_params
@flash_notify.reload.body_ru.should == "updated!"
end
end
context 'for simple user' do
before(:each) do
@user = FactoryGirl.create(:user)
set_session_for(@user)
end
[:index, :create, :update, :edit, :new, :destroy].each do |action|
it "should not be able to perform #{ action } action" do
get action, :id => @flash_notify
response.should redirect_to(forbidden_path)
end
end
it 'should not change objects count on create' do
lambda { post :create, @create_params }.should change{ FlashNotify.count }.by(0)
end
it 'should not change objects count on destroy' do
lambda { delete :destroy, :id => @flash_notify }.should change{ FlashNotify.count }.by(0)
end
it 'should not change flash notify body on update' do
put :update, @update_params
@flash_notify.reload.body_ru.should_not == "updated!"
end
end
end

View File

@ -0,0 +1,10 @@
# -*- encoding : utf-8 -*-
FactoryGirl.define do
factory :flash_notify do
body_ru { FactoryGirl.generate(:string) }
body_en { FactoryGirl.generate(:string) }
status "error"
published true
end
end

View File

@ -0,0 +1,5 @@
require 'spec_helper'
describe FlashNotify do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,90 @@
/* ==========================================================
* bootstrap-alert.js v2.0.4
* http://twitter.github.com/bootstrap/javascript.html#alerts
* ==========================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================== */
!function ($) {
"use strict"; // jshint ;_;
/* ALERT CLASS DEFINITION
* ====================== */
var dismiss = '[data-dismiss="alert"]'
, Alert = function (el) {
$(el).on('click', dismiss, this.close)
}
Alert.prototype.close = function (e) {
var $this = $(this)
, selector = $this.attr('data-target')
, $parent
if (!selector) {
selector = $this.attr('href')
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
}
$parent = $(selector)
e && e.preventDefault()
$parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
$parent.trigger(e = $.Event('close'))
if (e.isDefaultPrevented()) return
$parent.removeClass('in')
function removeElement() {
$parent
.trigger('closed')
.remove()
}
$.support.transition && $parent.hasClass('fade') ?
$parent.on($.support.transition.end, removeElement) :
removeElement()
}
/* ALERT PLUGIN DEFINITION
* ======================= */
$.fn.alert = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('alert')
if (!data) $this.data('alert', (data = new Alert(this)))
if (typeof option == 'string') data[option].call($this)
})
}
$.fn.alert.Constructor = Alert
/* ALERT DATA-API
* ============== */
$(function () {
$('body').on('click.alert.data-api', dismiss, Alert.prototype.close)
})
}(window.jQuery);

View File

@ -12,6 +12,7 @@
//= require bootstrap-dropdown
// require bootstrap-tooltip
// require bootstrap-popover
//= require bootstrap-alert
//= require chosen.jquery
// require html5shiv
// require_tree .