From c91b2144f4bf1cae1ac217bbcb2cc66f4da3a15e Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Wed, 9 Apr 2014 14:14:02 +0300
Subject: [PATCH 01/64] sphinx search return 100 ids
---
app/models/fun.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/models/fun.rb b/app/models/fun.rb
index 3b02f19..5c6716b 100644
--- a/app/models/fun.rb
+++ b/app/models/fun.rb
@@ -176,7 +176,7 @@ def search_fun_ids(query, types=[])
type_index = []
unless types.nil?
DEF_TYPES.each{|t| type_index << DEF_TYPES.index(t) if t.in? types }
- Fun.search_for_ids(query, with: {type: type_index}, max_matches: 100, per_page: 10)
+ Fun.search_for_ids(query, with: {type: type_index}, max_matches: 100, per_page: 100)
end
end
From cb6923926fcd437218ece5d0e320817923f9a6e5 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Wed, 9 Apr 2014 15:41:08 +0300
Subject: [PATCH 02/64] fix error for nil type
---
app/models/fun.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/models/fun.rb b/app/models/fun.rb
index 5c6716b..fc9821d 100644
--- a/app/models/fun.rb
+++ b/app/models/fun.rb
@@ -187,7 +187,7 @@ def create_tag_cloud(type)
type.each do |t|
tags.concat t.capitalize.constantize.tag_counts_on(:tags)
end
- elsif type != 'unknown'
+ elsif type
tags = type.capitalize.constantize.tag_counts_on(:tags)
end
tags.uniq.shuffle
From dcdb91f247362463570fccd2168289dc4052714a Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Wed, 9 Apr 2014 16:38:52 +0300
Subject: [PATCH 03/64] dry navigation
---
app/views/layouts/_navigation.html.slim | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/app/views/layouts/_navigation.html.slim b/app/views/layouts/_navigation.html.slim
index 8f682ab..016f040 100644
--- a/app/views/layouts/_navigation.html.slim
+++ b/app/views/layouts/_navigation.html.slim
@@ -5,10 +5,7 @@ section.nav_bar
= link_to_type 'video'
= link_to_type 'post'
nav.menu[role="navigation"]
- - if request.path == '/'
- = link_to_menu "Новое", request.path, {class: 'new_funs', rel: 'tooltip', title: t('funs.titles.new')}
- - else
- = link_to_menu "Новое", new_path, { class: 'new_funs' , rel: 'tooltip', title: t('funs.titles.new') }
+ = link_to_menu "Новое", (request.path == '/' ? request.path : new_path), { class: 'new_funs' , rel: 'tooltip', title: t('funs.titles.new') }
= link_to_menu "Популярное", hot_path, {class: 'popular_funs' , rel: 'tooltip', title: t('funs.titles.popular')}
= link_to_menu "Обсуждаемое", discuss_path, { class: 'discussed_funs', rel: 'tooltip', title: t('funs.titles.discussed')}
= link_to_menu "Песочница", sandbox_path, { class: 'sandbox_funs', rel: 'tooltip', title: t('funs.titles.sandbox')}
From 196d9eb53cf8530908574810bcd59a0a8c383d10 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 10 Apr 2014 12:52:12 +0300
Subject: [PATCH 04/64] edit fun
---
app/assets/javascripts/application.js | 8 +++-
.../javascripts/funs/{add_fun.js => popup.js} | 17 +++-----
app/assets/stylesheets/inc/_helpers.css.scss | 7 +++-
app/assets/stylesheets/inc/_modals.css.scss | 40 ++++++++++++-------
app/controllers/funs_controller.rb | 14 +++++--
app/views/funs/edit.html.slim | 26 ++++++------
app/views/funs/images/_edit.html.slim | 24 ++++++-----
app/views/funs/posts/_edit.html.slim | 7 ++--
app/views/funs/show.html.slim | 1 +
app/views/funs/videos/_edit.html.slim | 8 ++--
app/views/layouts/_header.html.slim | 2 +-
config/locales/ru.yml | 1 +
12 files changed, 92 insertions(+), 63 deletions(-)
rename app/assets/javascripts/funs/{add_fun.js => popup.js} (69%)
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 83f030e..f7c30f1 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -140,8 +140,14 @@ $(function(){
]
});
return false
- }
+ };
+ // Initialize fancybox for add box
+
+ $('.fancybox_ajax').not('[data-auth]').fancybox({
+ type: 'ajax',
+ padding : 0
+ });
});
function show_notice(text, type, options) {
diff --git a/app/assets/javascripts/funs/add_fun.js b/app/assets/javascripts/funs/popup.js
similarity index 69%
rename from app/assets/javascripts/funs/add_fun.js
rename to app/assets/javascripts/funs/popup.js
index ecc7529..8ebd7c2 100644
--- a/app/assets/javascripts/funs/add_fun.js
+++ b/app/assets/javascripts/funs/popup.js
@@ -1,12 +1,5 @@
$(function(){
- // Initialize fancybox for add box
-
- $('.link_new_fun').not('[data-auth]').fancybox({
- type: 'ajax',
- padding : 0
- });
-
$(document).on('show', '.add_fun_form a[data-toggle="tab"]', function(e){
$('.add_fun_form .tab_content').find('input, textarea').attr('disabled', 'disabled');
$('.add_fun_form .tab_content ' + e.target.hash).find('input, textarea').removeAttr('disabled');
@@ -16,17 +9,17 @@ $(function(){
$('#new_fun').resetClientSideValidations();
});
- $(document).on('ajax:success', '#new_fun', function(evt, data, status, xhr){
+ $(document).on('ajax:success', '#new_fun, #edit_fun', function(evt, data, status, xhr){
$.fancybox.close();
if (data.success){
- window.location.href = data.path;
- }
- else{
+ if (data.path) window.location.href = data.path;
+ else window.location.reload()
+ }else{
show_notice(data.notice, 'error')
}
});
- $(document).on('ajax:beforeSend, submit', '#new_fun, #new_report', function(evt, data, status, xhr){
+ $(document).on('ajax:beforeSend, submit', '#new_fun, #edit_fun, #new_report', function(){
$('.add_fun_form').append($('
'));
});
diff --git a/app/assets/stylesheets/inc/_helpers.css.scss b/app/assets/stylesheets/inc/_helpers.css.scss
index f85a175..e5694a3 100644
--- a/app/assets/stylesheets/inc/_helpers.css.scss
+++ b/app/assets/stylesheets/inc/_helpers.css.scss
@@ -7,4 +7,9 @@
.even { background: #f5f5f6;
&:hover {background: #f1f1f3;}
-}
\ No newline at end of file
+}
+.text-left {text-align: left}
+.text-center {text-align: center}
+.text-right {text-align: right}
+.vertical-space-sm {margin-top: 5px; margin-bottom: 5px;}
+.vertical-space {margin-top: 10px; margin-bottom: 10px;}
\ No newline at end of file
diff --git a/app/assets/stylesheets/inc/_modals.css.scss b/app/assets/stylesheets/inc/_modals.css.scss
index ce251ac..dbed5a5 100644
--- a/app/assets/stylesheets/inc/_modals.css.scss
+++ b/app/assets/stylesheets/inc/_modals.css.scss
@@ -245,6 +245,14 @@
}
.add {
@include btn-upload(44px);
+ &._ajax {
+ background: #FFD491;
+ border-color: #F7BB5F;
+ @include text-shadow(0 0px 1px rgba(0, 0, 0, 0.6));
+ span {
+ background: asset_url("btn-loading.gif", image) no-repeat right 0;;
+ }
+ }
}
}
.error-block {
@@ -256,8 +264,11 @@
#upload_image_botton {
float: right;
}
- }
- &.add_fun_form {
+ .column2 {
+ width: 230px;
+ margin-bottom: 5px;
+ #upload_image_botton { float: none; }
+ }
.__ajax {
position: absolute;
top: 0;
@@ -268,19 +279,6 @@
z-index: 1000;
background: url('/assets/__loading.gif') no-repeat center rgba(255, 255, 255, .45);
}
- .modal_footer {
- .add {
- @include btn-upload(44px);
- &._ajax {
- background: #FFD491;
- border-color: #F7BB5F;
- @include text-shadow(0 0px 1px rgba(0, 0, 0, 0.6));
- span {
- background: asset_url("btn-loading.gif", image) no-repeat right 0;;
- }
- }
- }
- }
}
}
@@ -395,6 +393,18 @@
width: 112px;
padding: 3px 18px;
}
+ .column2 {
+ .url { width: 228px; }
+ input {
+ width: 228px;
+ &.url { width: 188px; }
+ }
+ .btn-file { width: 192px; }
+ }
+ .full-width {
+ width: 100%;
+ input.url { width: 430px }
+ }
}
#add_video {
.url {
diff --git a/app/controllers/funs_controller.rb b/app/controllers/funs_controller.rb
index d7a83cc..fcdfb63 100644
--- a/app/controllers/funs_controller.rb
+++ b/app/controllers/funs_controller.rb
@@ -46,6 +46,8 @@ def new
# GET /funs/1/edit
def edit
@fun = Fun.find(params[:id])
+
+ render layout: false if request.xhr?
end
# POST /funs
@@ -65,10 +67,14 @@ def create
# PUT /funs/1
def update
- if @fun.content.update_attributes(params[:fun][:content_attributes])
- redirect_to @fun, notice: t('funs.updated')
- else
- render 'edit'
+ respond_to do |format|
+ if @fun.content.update_attributes(params[:fun][:content_attributes])
+ format.html { redirect_to @fun, notice: t('funs.updated') }
+ format.json { render json: { success: true, path: fun_path(@fun) } }
+ else
+ format.html { render 'edit' }
+ format.json { render json: { success: false, notice: t('funs.update_error') } }
+ end
end
end
diff --git a/app/views/funs/edit.html.slim b/app/views/funs/edit.html.slim
index 75df0af..04355ed 100644
--- a/app/views/funs/edit.html.slim
+++ b/app/views/funs/edit.html.slim
@@ -1,13 +1,15 @@
-.container.page-layout
- h1 Редактирование фана
- .profile_layout
- section.content[role='main']
- = simple_form_for @fun, url: fun_path(@fun), html: { method: :put, class: 'form-horizontal', id: 'new_fun' }, validate: true do |fun|
- = fun.input :content_type, as: :hidden, wrapper: :none
- = fun.simple_fields_for :content_attributes, @fun.content, validate: true do |f|
- = render "funs/#{@fun.content_type.downcase.pluralize}/edit", f: f
+/* ********** MODAL **************** */
+/* edit fun */
+.modal.add_fun_form
+ .modal_header Редактирование фана
+ .modal_body
+ .tabs_box
+ .tab_content
+ = simple_form_for @fun, url: fun_path(@fun), wrapper: :none, remote: true, html: {:'data-type' => 'json', id: 'edit_fun'}, validate: true do |form|
+ div.tab_pane.active= render "funs/#{@fun.content_type.downcase.pluralize}/edit", fun: @fun, form: form
+ .modal_footer
+ a.cancel[href="#"] Отменить
+ a.add[href="#" rel='submit' data-form='#edit_fun']:span Сохранить
- .divider
- .control-group
- .controls
- a.save[href='#' rel='submit']Сохранить
\ No newline at end of file
+javascript:
+ $('#edit_fun').enableClientSideValidations();
\ No newline at end of file
diff --git a/app/views/funs/images/_edit.html.slim b/app/views/funs/images/_edit.html.slim
index 89bede0..33acc3f 100644
--- a/app/views/funs/images/_edit.html.slim
+++ b/app/views/funs/images/_edit.html.slim
@@ -1,19 +1,21 @@
-= f.input :title, :validate => { :presence => true }
-.control-row
- = f.input :remote_file_url
- .help-inline или
- span.fileupload-new#upload_image_botton
- span.btn-file
- span.fileupload-preview
- span.fileupload-new Загрузить
- = f.file_field :file, accept: 'image/jpeg,image/png,image/gif', validate: false, wrapper: :none
+= form.simple_fields_for :content_attributes, fun.content do |f|
+ = f.input :title
+ .column2.pull-right.control-row
+ span.fileupload-new#upload_image_botton
+ span.btn-file
+ span.fileupload-preview
+ span.fileupload-new Загрузить
+ = f.file_field :file, accept: 'image/jpeg,image/png,image/gif', validate: false, wrapper: :none
+ .text-center.vertical-space-sm или
+ = f.input :remote_file_url
+ .column2= fun_image(@fun, version: :small)
-= f.input :tag_list
+ = f.input :tag_list
javascript:
$('#upload_image_botton').inputfileupload({
maxFileSize: 15000000,
onFailMaxSize: function(){
- $('#upload_image_botton').closest('.control-row').append($('Размер файла больше допустимого, попробуйте загрузить меньшего размера.
'))
+ $('#upload_image_botton').closest('.column2').append($('Размер файла больше допустимого, попробуйте загрузить меньшего размера.
'))
}
});
diff --git a/app/views/funs/posts/_edit.html.slim b/app/views/funs/posts/_edit.html.slim
index 9bd6d00..615b89b 100644
--- a/app/views/funs/posts/_edit.html.slim
+++ b/app/views/funs/posts/_edit.html.slim
@@ -1,3 +1,4 @@
-= f.input :title
-= f.input :body, validate: true
-= f.input :tag_list
\ No newline at end of file
+= form.simple_fields_for :content_attributes, fun.content do |f|
+ = f.input :title
+ = f.input :body
+ = f.input :tag_list
\ No newline at end of file
diff --git a/app/views/funs/show.html.slim b/app/views/funs/show.html.slim
index d86cdd8..5f6d1be 100644
--- a/app/views/funs/show.html.slim
+++ b/app/views/funs/show.html.slim
@@ -14,6 +14,7 @@
span.date_block
= time_ago_in_words @fun.created_at
| назад
+ = link_to 'edit', edit_fun_path(@fun), class: 'fancybox_ajax'
- if @fun.content.title?
h1.title
= title @fun.content.title
diff --git a/app/views/funs/videos/_edit.html.slim b/app/views/funs/videos/_edit.html.slim
index 516fe5f..21224d2 100644
--- a/app/views/funs/videos/_edit.html.slim
+++ b/app/views/funs/videos/_edit.html.slim
@@ -1,3 +1,5 @@
-= f.input :title
-= f.input :url
-= f.input :tag_list
+= form.simple_fields_for :content_attributes, fun.content do |f|
+ = f.input :title
+ .text-center= fun_image(@fun, version: :small)
+ = f.input :url, wrapper_html: { class: 'full-width' }
+ = f.input :tag_list
\ No newline at end of file
diff --git a/app/views/layouts/_header.html.slim b/app/views/layouts/_header.html.slim
index f127815..8d9bbcf 100644
--- a/app/views/layouts/_header.html.slim
+++ b/app/views/layouts/_header.html.slim
@@ -8,7 +8,7 @@ header.main_panel[role="banner"]
.item_outer
- data = user_signed_in? ? {} : {:'data-auth' => 'true'}
.item.add_fun
- a.item_link.link_new_fun *data href="#{new_fun_path}"
+ a.item_link.fancybox_ajax *data href="#{new_fun_path}"
span.span_cell Добавить фан
.item_outer
= link_to_users
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 965b5b4..b314c71 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -71,6 +71,7 @@ ru:
followers: "Количество подписчиков"
created_at: "Дата регистрации"
social_likes: "Проголосовать в соц сетях"
+ update_error: "Произошла ошибка при сохранении фана :( Проверьте данные и повторите попытку"
reposts:
created: "Фан успешно скопирован вам на стену."
button: "Репостить"
From f9ccb41c542b1a4824e85f30b7f6aa3c8687c625 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 10 Apr 2014 14:35:17 +0300
Subject: [PATCH 05/64] fix in_sandbox& method
---
app/models/fun.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/models/fun.rb b/app/models/fun.rb
index fc9821d..106aeb1 100644
--- a/app/models/fun.rb
+++ b/app/models/fun.rb
@@ -110,7 +110,7 @@ def unlike_by(user)
end
def in_sandbox?
- !published_at.nil?
+ published_at.nil?
end
# get related funs without funs liked by user
From 6b5f8eb008430af84fbd3e5300e2e2f0c6ef7de5 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 10 Apr 2014 14:37:02 +0300
Subject: [PATCH 06/64] refactoring destroy rule
---
app/models/ability.rb | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 02158f2..89b5a6f 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -8,11 +8,9 @@ def initialize(user)
elsif user.role? :user
can [:create, :feed, :autocomplete_tags], Fun
can :destroy, Fun do |fun|
- fun.user_id == user.id && if fun.repost?
- true
- else
- fun.repost_counter == 0 && ! fun.published_at
- end
+ fun.user_id == user.id && (
+ fun.repost? || (fun.repost_counter == 0 && ! fun.in_sandbox?)
+ )
end
can :create, :repost
can [:create, :destroy], [UserRelationship, :like]
From 96eb2a787f67f649efd2dcc899a85457faee6383 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 10 Apr 2014 16:33:41 +0300
Subject: [PATCH 07/64] fun edit/delete buttons
---
app/assets/images/btn-fun-delete.png | Bin 2315 -> 0 bytes
app/assets/images/btn-fun-icons.png | Bin 0 -> 2317 bytes
app/assets/stylesheets/funs.css.scss | 21 ++++++++++++++++----
app/assets/stylesheets/inc/_modals.css.scss | 9 +++++++++
app/helpers/funs_helper.rb | 11 +++++++++-
app/views/funs/edit.html.slim | 8 ++++++--
app/views/funs/show.html.slim | 4 ++--
config/locales/ru.yml | 3 +++
8 files changed, 47 insertions(+), 9 deletions(-)
delete mode 100644 app/assets/images/btn-fun-delete.png
create mode 100644 app/assets/images/btn-fun-icons.png
diff --git a/app/assets/images/btn-fun-delete.png b/app/assets/images/btn-fun-delete.png
deleted file mode 100644
index 290766949d1a9bbc28ccd467c4bebe2464cd2f55..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 2315
zcmaJ>eK=HUA0A1U6wyf3mg5LZ=F?2m%$gL()MTbK$VV?3Glv<>oH28l@zGl8LqgGN
zYFWy*+U=!K+ZSG&LcUU~6st&xMDj-2ls($C?;mgbT-Q0z$93QL@Av$E_w^j`+_KTo
zV3`39hco1Ef&|#?h<#@I^RRz8{B;91S)lHIs2387s)b4zw?T}AzyMb!41)!*P#hao
z4?E*wb
z%vZR<66vNmCF~Wq#ak2?A!3R_mvw-%hJ^{pU{nZbWRY?eOTz{~=(4c&%rOZBK0we2
zHuzUketb{B4N<}Xok%8#$ZIIT8XA#8BQt4CM}SJEkVzCOiOe8S$SgX8MWz5B2Z%*e
zibGifi1RTPwqt`56jiWDB(+*iR67w7Wf+OVWHL!)Dv3%ZU;gbEUcNS?XUERfItXQ)i}39Ui}
z@Zb6VUtyJZtO6zpU=;H3V&+XFcVv^O}rM%yh9NF3{@>X*ZiY6ne#vSYBOLQeM?{Jn{YTXt}Zes=VGOmbZ>OO*6t;nwT#4Y3Vju
z85u?y`}x%dey8l`K}ji4j~-7D7}#uNZDV88BmF&D;&9mLl#c!StlTogJxRtTI*}{)
zyb;!ff)Sa$)THOBsi|cJ1qJ})G)vYl$USmZ7;Ji3XR0K}njvt_`Z1-yuebLLL?Y3UJmOLAe`6@J_eP@CuhB!D
zt!ZC{o2wb;aV~A`_wTEtv7vJmws`qqrG3<5$b8EaUg)jptsTJ&yY16_E3a3(
z7bkmocrfDP?L-L+?LFfs
zc>b3rp6p0@)&iuS*g;_V*ZX=}{kCl`)y(ZezG$kZ<-x-{r3>(Q{2TiR*2kYZ_@_Q6
zXdCG{+1Wnl^K<9Vouf`zw^L`|xT!R`#GT{YOBfrc%Led=EARx>KA*bIhRStaI5hzSE}7ycc0&{<>QHfk_7=51RyZRAV5WXf
zZmxJ}XebJ#*{*0`m~?1=0wtlIx0c}IQpGJ##D8~eRkg*rcjhiv_WL{U3~sd3lkiw&
zHH>+dV}viilw@7``O!LA%H8}i;?kb+xc0Fz>T*lVrO^BtHPg~+wOPykdlBhoo3BZW
zTN7OB6Yi0&ke_gNdQ|zJ{-LlzAKz!
zm@S+)m}(03Mb|5$4RRbto9j4v0&B;Dg;8aR?*&HY?~C}Qe$zR-PXG?}27%p4>*|0N
z0np|h!-Z!yDM2Q){l~1EH*W^__4VxrOz1bWG9u6Xs%>*VxwwC$V0Xy2P%zFrgl@^Y
zvwXdo-#)LZGFoh6eJ&l0fLM90y!eFXYraJ%Ut5H~9F@srllQdCm=RE0%7x5UOeHmC
zs|~M?nzq^L*T9urKfCJ2u1A^k!sGOFHkfs9ZS(qN*|#>VGZiYFd-tO38=ak<88pw<
zWGwz`tCdy9<|9qFZpCc70#gnK)#HXIHeL>UYx&f1z38`0eiL5rMztmiU-`T+G8GIz
zSXNfnBVas^DfbTw3UUrh&z&jlfoiSMzv>e852d9|nO$I3JvkkKF5aU!EPeMPBeG*v>Y&lXZ0
zF1=+-Y1#y_OX-u_7HoMiioP0g>zc|gdD;Oa{-Im3#^27?_{ibu>l~GYIC|fq7GCMq<*lfweAV@+J&2Xh=EYAgX($f7s5LSz^777z
z3J&w+O{F}KQUp|2G?rh~#?wdl?%jJX_)hpQNp(GLPEJl;D^Ddcc7fZF+pa#wKOMeG
ziCw-bvKznnQ6JtuP+q;((1a_00_1PnIL@zIG-?v=ojWi+Y4XQ8oGvc#VXvLZF(LL8
P<8WN}Eznul;N5=$J?YC2
diff --git a/app/assets/images/btn-fun-icons.png b/app/assets/images/btn-fun-icons.png
new file mode 100644
index 0000000000000000000000000000000000000000..147124c892f7a5330fca72f53865405219b893a9
GIT binary patch
literal 2317
zcmV+o3G()dP)v&1+pd>aXq-vVb+}N~92>r8#WSx-O$BJ~6p+zgxB-9nu
zp)m;_881KuQo|uiz%_(4j*Duo~S0D8^ShpaD4`*V)-Axs6RM0=fby
z1{{DLC^DwZ09hadOaa$#C%Bjgs~B)4z{)@%&`?uTvtz}I70pFOMYRAkGcy;jU%&p*
z;Nalla5y{wTmw=-wzIQSU&^A9NMsA}6JR~iYz%({^a1axs`~e@1vX%dfijoNRoT|o
z_N!9)7&&$xCO^whbgxBtS`c+RNQ%4O?(Xh>Es;o!194z#G3ZDnvIaOHgz&gr
zuGq?zD=QohM;$;WlZjrtc5Nb&Ncg0bW56y|RWB_FY{;M(C~t3X-(Fr`{-}NMoeeV7
z1u_eY0AcJ+O3)<;JEHL^vNbzT3XuTcDo0F1M?$n1)PnIjq6HsqaE_IxAPLPC}1x^wC)F2U4Bdv;Ht}y*-P?s
z6b1ROKT)DhbgWyqE&w>qQI13+TZIr_kH_
zcv^)J-bf_!@O)rLb#?V4^5RiYbOS^nHoS=Nw4$`W0i|o8bPY=D8wgJ;V#A9!Hm2yv
zi$__tYSkmg-))w~Pu*_!zl~fDKr|X99*@)C-%mQ7CY?^x-``I>9w!=&ngeQayWK;;
z&k6&DOTq4NI5x@HKl6u62oNA6e?XMo4|aDR8o=&`>?CsF_xU4h%$Kns#f{HwGUR13
zE&8C#z8uzK)GNM6d%DL`i?uvjeR^KM0edu=wG&kW&oI`RAc6crUQGcz*_
z>-YO{I-PTXZ8lpuaIYCyd@EOwt}zev+iI5ihfW7HP1DA4dh>Z!0?1j-79v}S^sJ^a
z=1K`pFPf%}8+C^H@`z1OPmh`xEoin7*+QfXnl`uT>FF^bW(Ljy*-R#LR`^;C;5>-%
z@0lY5vpj@<&ka~95qEDUlgacNb%thI^K2rK_}mOJJUl!{24;B-4-d})P9zc|zz6ez
zr-p`x4vV@Spey;COqa-W&m+fzH#D2PgdThnITl2odp+3z{w~E2FNi&djS#PEOtfy!92}P$=|i%IZBL?t3&3q3MuK
zA%jmtB09SX64CrvHf6v{#M;M5S-nR>q0lEl+6=6!>Io@jdVG95IGdWRR#a7;bHJQV
zC#tGqwcf~xw!)f2P8#=UeZ`%>~J_9FcZDv`nIU0>}=FA!Vem_-JRRjV7B9RF7_4S0qVV-#6iCcHg
zsq4_yt#JCH;PgcWp9?}Gd3V|Wg<$Uwbt+13-8H9DDfaK*tpNIt*ENHJlFie=lOIyk%EWTNG^;EdM+z8RY{tvOy$rmy5`>A
zUTiiS6B84(wY72K!UcMIdT4HLrn$NKEC0xnUGw{c3LWbu|A-0>^$IG!2M?{$X{k0{
zV#{#NJv}{ibaZg?O10OGI>50i>(4$
n%|`T&Yrf-}@3`jM?3(`vGwQ_9Lfj}Y00000NkvXXu0mjfIaXbz
literal 0
HcmV?d00001
diff --git a/app/assets/stylesheets/funs.css.scss b/app/assets/stylesheets/funs.css.scss
index 7cde8bb..e3df09e 100644
--- a/app/assets/stylesheets/funs.css.scss
+++ b/app/assets/stylesheets/funs.css.scss
@@ -872,7 +872,7 @@ html, body {
}
&:hover {
a.btn-fun-delete {
- background: asset_url("btn-fun-delete.png", image) no-repeat -21px 0;
+ background: asset_url("btn-fun-icons.png", image) no-repeat -22px 0;
height: 21px;
width: 21px;
position: absolute;
@@ -880,7 +880,7 @@ html, body {
right: -8px;
z-index: 1001;
&:hover {
- background: asset_url("btn-fun-delete.png", image) no-repeat 0 0;
+ background: asset_url("btn-fun-icons.png", image) no-repeat 0 0;
cursor: pointer;
}
}
@@ -2188,7 +2188,7 @@ html, body {
&:hover{
a {
&.btn-fun-delete{
- background: asset_url("btn-fun-delete.png", image) no-repeat -21px 0;
+ background: asset_url("btn-fun-icons.png", image) no-repeat -22px 0;
height: 21px;
width: 21px;
position: absolute;
@@ -2196,7 +2196,20 @@ html, body {
right: -8px;
z-index: 1001;
&:hover{
- background: asset_url("btn-fun-delete.png", image) no-repeat 0 0;
+ background: asset_url("btn-fun-icons.png", image) no-repeat 0 0;
+ cursor: pointer;
+ }
+ }
+ &.btn-fun-edit{
+ background: asset_url("btn-fun-icons.png", image) no-repeat -22px -22px;
+ height: 21px;
+ width: 21px;
+ position: absolute;
+ top: -8px;
+ right: -8px;
+ z-index: 1001;
+ &:hover{
+ background: asset_url("btn-fun-icons.png", image) no-repeat 0 -22px;
cursor: pointer;
}
}
diff --git a/app/assets/stylesheets/inc/_modals.css.scss b/app/assets/stylesheets/inc/_modals.css.scss
index dbed5a5..13bd115 100644
--- a/app/assets/stylesheets/inc/_modals.css.scss
+++ b/app/assets/stylesheets/inc/_modals.css.scss
@@ -254,6 +254,15 @@
}
}
}
+ .inner_wrapper {
+ padding: 0 15px;
+ a {
+ margin-right: 0;
+ & + a {
+ margin-left: 15px;
+ }
+ }
+ }
}
.error-block {
margin-bottom: 0;
diff --git a/app/helpers/funs_helper.rb b/app/helpers/funs_helper.rb
index 16e3ce8..8dbd04e 100644
--- a/app/helpers/funs_helper.rb
+++ b/app/helpers/funs_helper.rb
@@ -140,9 +140,18 @@ def fun_add_line(fun, link = false)
end
end
+ def edit_fun_link(fun, options = nil, text = '')
+ if can? :update, fun
+ data = { class: 'btn-fun-edit fancybox_ajax', rel: 'tooltip', title: t('funs.titles.edit') }
+ data.merge! options if options.is_a? Hash
+
+ link_to text, edit_fun_path(fun), data
+ end
+ end
+
def remove_fun_link(fun)
if can? :destroy, fun
- link_to '', url_for(action: 'show', controller: 'funs', id: fun), class: 'btn-fun-delete', method: :delete, remote: true, data: { type: :json }, confirm: t('funs.confirm.delete') , rel: 'tooltip', title: t('funs.titles.delete')
+ link_to '', fun, class: 'btn-fun-delete', method: :delete, remote: true, data: { type: :json }, confirm: t('funs.confirm.delete') , rel: 'tooltip', title: t('funs.titles.delete')
end
end
diff --git a/app/views/funs/edit.html.slim b/app/views/funs/edit.html.slim
index 04355ed..ab10ad4 100644
--- a/app/views/funs/edit.html.slim
+++ b/app/views/funs/edit.html.slim
@@ -8,8 +8,12 @@
= simple_form_for @fun, url: fun_path(@fun), wrapper: :none, remote: true, html: {:'data-type' => 'json', id: 'edit_fun'}, validate: true do |form|
div.tab_pane.active= render "funs/#{@fun.content_type.downcase.pluralize}/edit", fun: @fun, form: form
.modal_footer
- a.cancel[href="#"] Отменить
- a.add[href="#" rel='submit' data-form='#edit_fun']:span Сохранить
+ .inner_wrapper
+ - if can? :destroy, @fun
+ = link_to t('global.delete'), @fun, class: 'cancel pull-left', method: :delete, confirm: t('funs.confirm.delete')
+
+ a.cancel[href="#"] Отменить
+ a.add[href="#" rel='submit' data-form='#edit_fun']:span Сохранить
javascript:
$('#edit_fun').enableClientSideValidations();
\ No newline at end of file
diff --git a/app/views/funs/show.html.slim b/app/views/funs/show.html.slim
index 5f6d1be..ada5406 100644
--- a/app/views/funs/show.html.slim
+++ b/app/views/funs/show.html.slim
@@ -1,5 +1,5 @@
- fun_meta(@fun)
-= render "layouts/social_plugin"
+= render 'layouts/social_plugin'
.container.post_layout
section.content[role="main"]
article.post_frame.load_buttons
@@ -14,7 +14,6 @@
span.date_block
= time_ago_in_words @fun.created_at
| назад
- = link_to 'edit', edit_fun_path(@fun), class: 'fancybox_ajax'
- if @fun.content.title?
h1.title
= title @fun.content.title
@@ -26,6 +25,7 @@
a[href="https://twitter.com/share" rel="nofollow" class="twitter-share-button" data-via="bitfun" data-lang="ru" data-related="butfun" data-text="#{@fun.content.title || t('meta_tags.main.title')}"] Tweet
.follow_parent
= follow_link(@fun.user)
+ = edit_fun_link @fun
.post_object
= render_fun_partial @fun, :show
.post_nav
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index b314c71..12c6486 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -1,4 +1,6 @@
ru:
+ global:
+ delete: Удалить
activerecord:
errors:
models:
@@ -71,6 +73,7 @@ ru:
followers: "Количество подписчиков"
created_at: "Дата регистрации"
social_likes: "Проголосовать в соц сетях"
+ edit: "Редактировать фан"
update_error: "Произошла ошибка при сохранении фана :( Проверьте данные и повторите попытку"
reposts:
created: "Фан успешно скопирован вам на стену."
From ac4c0d5408d816d050e22c79ca344683db29fb4a Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 11 Apr 2014 10:35:20 +0300
Subject: [PATCH 08/64] refresh cloud tags
---
app/controllers/funs_controller.rb | 2 +-
app/views/funs/_tag_cloud.html.slim | 2 +-
app/views/funs/index.html.slim | 3 ++-
app/views/funs/index.js.erb | 5 +++++
4 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/app/controllers/funs_controller.rb b/app/controllers/funs_controller.rb
index fcdfb63..b6deeb5 100644
--- a/app/controllers/funs_controller.rb
+++ b/app/controllers/funs_controller.rb
@@ -13,7 +13,7 @@ def index
if params[:query]
funs_ids = Fun.search_fun_ids(params[:query], type)
@funs = @funs.where(id: funs_ids)
- @tags = Fun.create_tag_cloud type
+ @tags = Fun.create_tag_cloud type if (params[:page].nil? || !request.xhr?)
end
cookies_store.set params.select { |k,v| k.in? %w(type view interval sort) }
diff --git a/app/views/funs/_tag_cloud.html.slim b/app/views/funs/_tag_cloud.html.slim
index 3d8a59b..22c9161 100644
--- a/app/views/funs/_tag_cloud.html.slim
+++ b/app/views/funs/_tag_cloud.html.slim
@@ -1,2 +1,2 @@
-- tag_cloud(@tags, %w(small middle big biggest)) do |tag, css_class|
+- tag_cloud(tags, %w(small middle big biggest)) do |tag, css_class|
= link_to tag.name, search_tags_path(query: tag.name), class: "#{css_class} tags"
\ No newline at end of file
diff --git a/app/views/funs/index.html.slim b/app/views/funs/index.html.slim
index ea64480..e2bff83 100644
--- a/app/views/funs/index.html.slim
+++ b/app/views/funs/index.html.slim
@@ -13,7 +13,8 @@
.icon-search
a.find.btn[href="#"] Искать
.clearfix
- = render 'tag_cloud'
+ - if @tags
+ #bitfun_cloud_wrapper= render 'tag_cloud', tags: @tags
div *data class="container main_layout#{view_partial == 'box' ? ' grid' : ''}"
section.content[role="main"]
diff --git a/app/views/funs/index.js.erb b/app/views/funs/index.js.erb
index 9214497..f44f2b4 100644
--- a/app/views/funs/index.js.erb
+++ b/app/views/funs/index.js.erb
@@ -9,4 +9,9 @@ elsif ! params[:page]
content << render('funs/empty')
end
%>
+<%if @tags%>
+ <%= javascript_tag do %>
+ $('#bitfun_cloud_wrapper').html('<%= render 'tag_cloud', tags: @tags%>');
+ <%end%>
+<%end%>
<%= content.html_safe %>
\ No newline at end of file
From 0b7d9a3e19dc3add012505bf411f111c1e2e34c4 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 11 Apr 2014 10:52:19 +0300
Subject: [PATCH 09/64] fix fun destroy rule
---
app/models/ability.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 89b5a6f..57a211d 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -9,7 +9,7 @@ def initialize(user)
can [:create, :feed, :autocomplete_tags], Fun
can :destroy, Fun do |fun|
fun.user_id == user.id && (
- fun.repost? || (fun.repost_counter == 0 && ! fun.in_sandbox?)
+ fun.repost? || (fun.repost_counter == 0 && fun.in_sandbox?)
)
end
can :create, :repost
From ef2068702d07c3d3a87ec1d626eac0c9f3d68c0a Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 14 Apr 2014 09:37:08 +0300
Subject: [PATCH 10/64] notification model
---
app/models/notification.rb | 12 ++++++++++++
.../20140411085401_create_notifications.rb | 16 ++++++++++++++++
db/schema.rb | 14 +++++++++++++-
3 files changed, 41 insertions(+), 1 deletion(-)
create mode 100644 app/models/notification.rb
create mode 100644 db/migrate/20140411085401_create_notifications.rb
diff --git a/app/models/notification.rb b/app/models/notification.rb
new file mode 100644
index 0000000..b47f883
--- /dev/null
+++ b/app/models/notification.rb
@@ -0,0 +1,12 @@
+class Notification < ActiveRecord::Base
+ attr_accessible :target_id, :target_type,
+ :target, :action,
+ :user_id
+
+ belongs_to :target, polymorphic: true
+ belongs_to :user
+
+ validates_presence_of :target_id
+ validates_presence_of :user_id
+ validates_presence_of :action
+end
diff --git a/db/migrate/20140411085401_create_notifications.rb b/db/migrate/20140411085401_create_notifications.rb
new file mode 100644
index 0000000..a7b26ca
--- /dev/null
+++ b/db/migrate/20140411085401_create_notifications.rb
@@ -0,0 +1,16 @@
+class CreateNotifications < ActiveRecord::Migration
+ def change
+ create_table :notifications do |t|
+
+ t.string :action
+ t.references :target, polymorphic: true
+ t.integer :user_id
+ t.integer :receiver_id
+
+ t.timestamp :created_at
+ end
+
+ add_index :notifications, [:target_id, :target_type]
+ add_index :notifications, :user_id
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 66ba574..8112d60 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20130906075059) do
+ActiveRecord::Schema.define(:version => 20140411085401) do
create_table "funs", :force => true do |t|
t.integer "user_id"
@@ -47,6 +47,18 @@
t.string "cached_tag_list"
end
+ create_table "notifications", :force => true do |t|
+ t.string "action"
+ t.integer "target_id"
+ t.string "target_type"
+ t.integer "user_id"
+ t.integer "receiver_id"
+ t.datetime "created_at"
+ end
+
+ add_index "notifications", ["target_id", "target_type"], :name => "index_notifications_on_target_id_and_target_type"
+ add_index "notifications", ["user_id"], :name => "index_notifications_on_user_id"
+
create_table "posts", :force => true do |t|
t.string "title"
t.text "body"
From ce7d0092d13c169ed19158fd440597ad57fb3ce8 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 14 Apr 2014 09:37:46 +0300
Subject: [PATCH 11/64] create notification on fun create
---
app/models/fun.rb | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/app/models/fun.rb b/app/models/fun.rb
index 106aeb1..2d9baee 100644
--- a/app/models/fun.rb
+++ b/app/models/fun.rb
@@ -4,6 +4,7 @@ class Fun < ActiveRecord::Base
after_destroy :delete_content
before_destroy :delete_likes
before_destroy :delete_reposts
+ after_create :create_notification
# Kaminari pagination config
paginates_per 10
@@ -20,6 +21,7 @@ class Fun < ActiveRecord::Base
belongs_to :content, polymorphic: true
accepts_nested_attributes_for :content, allow_destroy: true
has_many :reports, dependent: :destroy
+ has_many :notifications, as: :target, dependent: :destroy
# Reposts
has_many :reposts, class_name: 'Fun', foreign_key: 'parent_id'
@@ -217,4 +219,10 @@ def delete_reposts
def delete_content
content.destroy unless repost?
end
+
+ private
+
+ def create_notification
+ self.notifications.create(user_id: user_id, action: :create)
+ end
end
\ No newline at end of file
From 8119f04f0e568777c59233f88b4dfc42a1a44467 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 14 Apr 2014 11:29:01 +0300
Subject: [PATCH 12/64] fix fancybox popup bug
---
app/assets/javascripts/application.js | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index f7c30f1..6a69b7c 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -146,7 +146,12 @@ $(function(){
$('.fancybox_ajax').not('[data-auth]').fancybox({
type: 'ajax',
- padding : 0
+ padding : 0,
+ helpers: {
+ overlay: {
+ locked: false
+ }
+ }
});
});
From 391aa54e589cde06e19e1f114e6481d5d4b166e0 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 14 Apr 2014 11:33:48 +0300
Subject: [PATCH 13/64] extend vote model
---
lib/acts_as_votable/vote.rb | 15 +++++++++++++++
1 file changed, 15 insertions(+)
create mode 100644 lib/acts_as_votable/vote.rb
diff --git a/lib/acts_as_votable/vote.rb b/lib/acts_as_votable/vote.rb
new file mode 100644
index 0000000..3557b83
--- /dev/null
+++ b/lib/acts_as_votable/vote.rb
@@ -0,0 +1,15 @@
+module ActsAsVotable
+ class Vote < ActiveRecord::Base
+
+ after_create :create_notification
+ has_many :notifications, as: :target, dependent: :destroy
+
+ private
+
+ def create_notification
+ notifications.create(user_id: voter_id, action: :create, receiver_id: votable.user_id)
+ end
+
+ end
+
+end
\ No newline at end of file
From 4cc34f1ff5d5c5f0133b732f245a1cc9cb2d9580 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 14 Apr 2014 11:34:22 +0300
Subject: [PATCH 14/64] add field to notification
---
app/models/notification.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/models/notification.rb b/app/models/notification.rb
index b47f883..ad47fc5 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -1,7 +1,7 @@
class Notification < ActiveRecord::Base
attr_accessible :target_id, :target_type,
:target, :action,
- :user_id
+ :user_id, :receiver_id
belongs_to :target, polymorphic: true
belongs_to :user
From 67b7cffad36d1b8178641fa5d083ee8ac9eb0de6 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 14 Apr 2014 11:35:33 +0300
Subject: [PATCH 15/64] change autoload from lib
---
config/initializers/autoload.rb | 10 ++++++++++
config/initializers/carrierwave.rb | 3 ---
2 files changed, 10 insertions(+), 3 deletions(-)
create mode 100644 config/initializers/autoload.rb
delete mode 100644 config/initializers/carrierwave.rb
diff --git a/config/initializers/autoload.rb b/config/initializers/autoload.rb
new file mode 100644
index 0000000..5032c53
--- /dev/null
+++ b/config/initializers/autoload.rb
@@ -0,0 +1,10 @@
+dirs = [
+ %w'lib acts_as_votable',
+ %w'lib carrierwave processing'
+]
+
+dirs.each do |folders|
+ dir = Rails.root.join *folders
+ $LOAD_PATH.unshift(dir)
+ Dir[File.join(dir, '*.rb')].each {|file| require File.basename(file) }
+end
\ No newline at end of file
diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb
deleted file mode 100644
index 3adb31c..0000000
--- a/config/initializers/carrierwave.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-dir = Rails.root.join('lib', 'carrierwave/processing')
-$LOAD_PATH.unshift(dir)
-Dir[File.join(dir, "*.rb")].each {|file| require File.basename(file) }
\ No newline at end of file
From bfbd7eb417c34f75994b159c405cf78a512f9d7b Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 15 Apr 2014 11:16:29 +0300
Subject: [PATCH 16/64] notification list
---
app/controllers/notifications_controller.rb | 7 +++++++
app/models/ability.rb | 1 +
app/models/fun.rb | 2 +-
app/models/notification.rb | 9 +++++----
app/views/notifications/index.html.slim | 8 ++++++++
config/routes.rb | 2 ++
db/migrate/20140411085401_create_notifications.rb | 3 ++-
db/schema.rb | 4 +++-
lib/acts_as_votable/vote.rb | 5 +++--
9 files changed, 32 insertions(+), 9 deletions(-)
create mode 100644 app/controllers/notifications_controller.rb
create mode 100644 app/views/notifications/index.html.slim
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
new file mode 100644
index 0000000..5df5838
--- /dev/null
+++ b/app/controllers/notifications_controller.rb
@@ -0,0 +1,7 @@
+class NotificationsController < ApplicationController
+ authorize_resource
+
+ def index
+ @notifications = Fun.unscoped { Notification.includes(:user, :target, :subject).all }
+ end
+end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 57a211d..0f289c1 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -19,6 +19,7 @@ def initialize(user)
can :create, Report
can :read, :all
cannot [:destroy, :read], Report
+ cannot :show, Notification
else
can :read, :all
end
diff --git a/app/models/fun.rb b/app/models/fun.rb
index 2d9baee..e54733e 100644
--- a/app/models/fun.rb
+++ b/app/models/fun.rb
@@ -21,7 +21,7 @@ class Fun < ActiveRecord::Base
belongs_to :content, polymorphic: true
accepts_nested_attributes_for :content, allow_destroy: true
has_many :reports, dependent: :destroy
- has_many :notifications, as: :target, dependent: :destroy
+ has_many :notifications, as: :subject, dependent: :destroy
# Reposts
has_many :reposts, class_name: 'Fun', foreign_key: 'parent_id'
diff --git a/app/models/notification.rb b/app/models/notification.rb
index ad47fc5..89d5aa9 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -1,12 +1,13 @@
class Notification < ActiveRecord::Base
- attr_accessible :target_id, :target_type,
- :target, :action,
- :user_id, :receiver_id
+ attr_accessible :target_id, :target_type, :target,
+ :subject_id, :subject_type, :subject,
+ :action, :user_id, :receiver_id
+ belongs_to :subject, polymorphic: true
belongs_to :target, polymorphic: true
belongs_to :user
- validates_presence_of :target_id
+ validates_presence_of :subject_id
validates_presence_of :user_id
validates_presence_of :action
end
diff --git a/app/views/notifications/index.html.slim b/app/views/notifications/index.html.slim
new file mode 100644
index 0000000..276b9e4
--- /dev/null
+++ b/app/views/notifications/index.html.slim
@@ -0,0 +1,8 @@
+.container.rating_layout
+ .topics_block
+ .title_page
+ h1 Notification list
+ .rating_layout
+ ul
+ - @notifications.each do |n|
+ li #{link_to(n.user.login, n.user)} #{n.action} #{n.subject.class.name} #{link_to n.target.class.name, n.target if n.target} #{n.created_at}
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 72333b4..402b8ef 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,6 +2,8 @@
root to: 'funs#index'
+ resources :notifications, only: :index
+
get 'reports', to: 'reports#index'
resources :funs do
resources :reports, except: :index
diff --git a/db/migrate/20140411085401_create_notifications.rb b/db/migrate/20140411085401_create_notifications.rb
index a7b26ca..8bd35e4 100644
--- a/db/migrate/20140411085401_create_notifications.rb
+++ b/db/migrate/20140411085401_create_notifications.rb
@@ -3,6 +3,7 @@ def change
create_table :notifications do |t|
t.string :action
+ t.references :subject, polymorphic: true
t.references :target, polymorphic: true
t.integer :user_id
t.integer :receiver_id
@@ -10,7 +11,7 @@ def change
t.timestamp :created_at
end
- add_index :notifications, [:target_id, :target_type]
+ add_index :notifications, [:subject_id, :subject_type]
add_index :notifications, :user_id
end
end
diff --git a/db/schema.rb b/db/schema.rb
index 8112d60..a83a27a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -49,6 +49,8 @@
create_table "notifications", :force => true do |t|
t.string "action"
+ t.integer "subject_id"
+ t.string "subject_type"
t.integer "target_id"
t.string "target_type"
t.integer "user_id"
@@ -56,7 +58,7 @@
t.datetime "created_at"
end
- add_index "notifications", ["target_id", "target_type"], :name => "index_notifications_on_target_id_and_target_type"
+ add_index "notifications", ["subject_id", "subject_type"], :name => "index_notifications_on_subject_id_and_subject_type"
add_index "notifications", ["user_id"], :name => "index_notifications_on_user_id"
create_table "posts", :force => true do |t|
diff --git a/lib/acts_as_votable/vote.rb b/lib/acts_as_votable/vote.rb
index 3557b83..7b33262 100644
--- a/lib/acts_as_votable/vote.rb
+++ b/lib/acts_as_votable/vote.rb
@@ -2,12 +2,13 @@ module ActsAsVotable
class Vote < ActiveRecord::Base
after_create :create_notification
- has_many :notifications, as: :target, dependent: :destroy
+ has_many :notifications, as: :subject, dependent: :destroy
private
def create_notification
- notifications.create(user_id: voter_id, action: :create, receiver_id: votable.user_id)
+ notifications.create(user_id: voter_id, action: :create,
+ receiver_id: votable.user_id, target: votable)
end
end
From 89811a392e8de17966def06bae788f76e6affcd2 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 15 Apr 2014 11:19:32 +0300
Subject: [PATCH 17/64] show only my notifications
---
app/controllers/notifications_controller.rb | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
index 5df5838..3f305cf 100644
--- a/app/controllers/notifications_controller.rb
+++ b/app/controllers/notifications_controller.rb
@@ -2,6 +2,8 @@ class NotificationsController < ApplicationController
authorize_resource
def index
- @notifications = Fun.unscoped { Notification.includes(:user, :target, :subject).all }
+ @notifications = Fun.unscoped do
+ Notification.includes(:user, :target, :subject).where(receiver_id: current_user.id)
+ end
end
end
From 197e580447baaf2f28d46b7718001312d2fbff86 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 15 Apr 2014 15:30:12 +0300
Subject: [PATCH 18/64] photo frame customization
---
app/assets/stylesheets/funs.css.scss | 88 +--------------
.../stylesheets/inc/_photo_frames.css.scss | 106 ++++++++++++++++++
app/views/notifications/index.html.slim | 9 +-
3 files changed, 115 insertions(+), 88 deletions(-)
create mode 100644 app/assets/stylesheets/inc/_photo_frames.css.scss
diff --git a/app/assets/stylesheets/funs.css.scss b/app/assets/stylesheets/funs.css.scss
index e3df09e..51f96db 100644
--- a/app/assets/stylesheets/funs.css.scss
+++ b/app/assets/stylesheets/funs.css.scss
@@ -10,6 +10,7 @@
@import 'inc/_tooltips.css.scss';
@import 'inc/_modals.css.scss';
@import 'inc/_tagit.css.scss';
+@import 'inc/photo_frames.css.scss';
html, body {
font-family: $baseFontFamily;
@@ -887,93 +888,6 @@ html, body {
}
}
-.photo_frame {
- @include inline-block;
- position: relative;
- height: 70px;
- width: 70px;
- .photo_box {
- border: 5px solid #5b5985;
- display: block;
- &, img {
- height: 60px;
- width: 60px;
- border-radius: 50%;
- }
- }
- .arrow {
- border: {
- top: 8px solid transparent;
- left: 8px solid #5b5985;
- bottom: 8px solid transparent;
- }
- position: absolute;
- right: -5px;
- top: 50%;
- margin-top: -8px;
- }
- .circle_content_obj {
- background: #5b5985;
- border: 1px solid #363453;
- height: 28px;
- width: 28px;
- position: absolute;
- border-radius: 50%;
- right: 0;
- bottom: -5px;
- > div {
- height: 16px;
- width: 16px;
- margin: 6px 0 0 6px;
- }
- .image {
- background: asset_url("content-obj-icons.png", image) no-repeat left -42px;
- }
- .video {
- background: asset_url("content-obj-icons.png", image) no-repeat -21px -42px;
- }
- .post {
- background: asset_url("content-obj-icons.png", image) no-repeat -42px -42px;
- }
- &:hover{cursor: default;}
- }
- .circle_follow_status {
- position: absolute;
- left: -15px;
- top: 50%;
- margin-top: -15px;
- line-height: 24px;
- text-align: center;
- a {
- display: block;
- height: 32px;
- width: 32px;
- background: {
- image: asset_url("follow-icons.png", image);
- repeat: no-repeat;
- }
- &.follow {
- background-position: -35px -35px;
- &:hover {
- background-position: -35px 0;
- }
- }
- &.unfollow {
- background-position: -70px -105px;
- &:hover {
- background-position: -70px -70px;
- }
- }
- &.settings {
- background-position: -106px 0;
- }
- }
- }
- &:hover {
- cursor: pointer;
- }
-}
-
.tabs_box {
.nav_tabs {
li {
diff --git a/app/assets/stylesheets/inc/_photo_frames.css.scss b/app/assets/stylesheets/inc/_photo_frames.css.scss
new file mode 100644
index 0000000..d27d81b
--- /dev/null
+++ b/app/assets/stylesheets/inc/_photo_frames.css.scss
@@ -0,0 +1,106 @@
+.photo_frame {
+ @include inline-block;
+ position: relative;
+ height: 70px;
+ width: 70px;
+ .photo_box {
+ border: 5px solid #5b5985;
+ display: block;
+ &, img {
+ height: 60px;
+ width: 60px;
+ border-radius: 50%;
+ }
+ }
+ .arrow {
+ border: {
+ top: 8px solid transparent;
+ left: 8px solid #5b5985;
+ bottom: 8px solid transparent;
+ }
+ position: absolute;
+ right: -5px;
+ top: 50%;
+ margin-top: -8px;
+ }
+ .circle_content_obj {
+ background: #5b5985;
+ border: 1px solid #363453;
+ height: 28px;
+ width: 28px;
+ position: absolute;
+ border-radius: 50%;
+ right: 0;
+ bottom: -5px;
+ > div {
+ height: 16px;
+ width: 16px;
+ margin: 6px 0 0 6px;
+ }
+ .image {
+ background: asset_url("content-obj-icons.png", image) no-repeat left -42px;
+ }
+ .video {
+ background: asset_url("content-obj-icons.png", image) no-repeat -21px -42px;
+ }
+ .post {
+ background: asset_url("content-obj-icons.png", image) no-repeat -42px -42px;
+ }
+ &:hover{cursor: default;}
+ }
+ .circle_follow_status {
+ position: absolute;
+ left: -15px;
+ top: 50%;
+ margin-top: -15px;
+ line-height: 24px;
+ text-align: center;
+ a {
+ display: block;
+ height: 32px;
+ width: 32px;
+ background: {
+ image: asset_url("follow-icons.png", image);
+ repeat: no-repeat;
+ }
+ &.follow {
+ background-position: -35px -35px;
+ &:hover {
+ background-position: -35px 0;
+ }
+ }
+ &.unfollow {
+ background-position: -70px -105px;
+ &:hover {
+ background-position: -70px -70px;
+ }
+ }
+ &.settings {
+ background-position: -106px 0;
+ }
+ }
+ }
+ &:hover {
+ cursor: pointer;
+ }
+
+ &.photo_frame_shadow{
+ .photo_box {
+ @include box-shadow(0 1px 3px rgba(91, 89, 133, .25), inset 0 0 8px rgba(0, 0, 0, .15));
+ }
+ }
+
+ &.photo_frame_sm {
+ width: 36px;
+ height: 36px;
+ .photo_box {
+ border: solid 3px #5b5985;
+ height: 30px;
+ width: 30px;
+ img {
+ height: 30px;
+ width: 30px;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/views/notifications/index.html.slim b/app/views/notifications/index.html.slim
index 276b9e4..f8937ff 100644
--- a/app/views/notifications/index.html.slim
+++ b/app/views/notifications/index.html.slim
@@ -5,4 +5,11 @@
.rating_layout
ul
- @notifications.each do |n|
- li #{link_to(n.user.login, n.user)} #{n.action} #{n.subject.class.name} #{link_to n.target.class.name, n.target if n.target} #{n.created_at}
\ No newline at end of file
+ li
+ .photo_frame
+ = link_to show_avatar(n.user), n.user, class: 'photo_box'
+ = link_to n.user.login, n.user
+ = n.action
+ = n.subject.class.name
+ = link_to n.target.class.name, n.target if n.target
+ = n.created_at
\ No newline at end of file
From 204d1b3b96f228b2731495bf14b4e16216e74ad6 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Wed, 16 Apr 2014 10:45:07 +0300
Subject: [PATCH 19/64] comments without design
---
Gemfile | 2 +
Gemfile.lock | 7 +++
app/assets/javascripts/comments.js.coffee | 52 +++++++++++++++++
app/controllers/comments_controller.rb | 58 +++++++++++++++++++
app/controllers/funs_controller.rb | 3 +
app/helpers/funs_helper.rb | 9 +++
app/models/comment.rb | 42 ++++++++++++++
app/models/fun.rb | 1 +
app/views/comments/_comment.html.slim | 22 +++++++
app/views/comments/_list.html.slim | 11 ++++
app/views/funs/show.html.slim | 1 +
config/routes.rb | 5 ++
...as_commentable_with_threading_migration.rb | 21 +++++++
...0416070220_add_cached_votes_to_comments.rb | 19 ++++++
db/schema.rb | 25 +++++++-
lib/awesome_nested_tree.rb | 27 +++++++++
16 files changed, 304 insertions(+), 1 deletion(-)
create mode 100644 app/assets/javascripts/comments.js.coffee
create mode 100644 app/controllers/comments_controller.rb
create mode 100644 app/models/comment.rb
create mode 100644 app/views/comments/_comment.html.slim
create mode 100644 app/views/comments/_list.html.slim
create mode 100644 db/migrate/20140415144524_acts_as_commentable_with_threading_migration.rb
create mode 100644 db/migrate/20140416070220_add_cached_votes_to_comments.rb
create mode 100644 lib/awesome_nested_tree.rb
diff --git a/Gemfile b/Gemfile
index 1149488..3cf760c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -112,6 +112,8 @@ gem 'jquery-fileupload-rails'
gem 'jquery-rails'
gem 'jquery-ui-rails'
+gem 'acts_as_commentable_with_threading'
+
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 4e2e86c..3d28228 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -30,9 +30,15 @@ GEM
multi_json (~> 1.0)
acts-as-taggable-on (2.4.1)
rails (>= 3, < 5)
+ acts_as_commentable_with_threading (1.2.0)
+ activerecord (>= 3.0)
+ activesupport (>= 3.0)
+ awesome_nested_set (>= 2.0)
acts_as_votable (0.5.0)
rails (>= 3.0.0)
arel (3.0.2)
+ awesome_nested_set (2.1.6)
+ activerecord (>= 3.0.0)
bcrypt-ruby (3.0.1)
better_errors (0.9.0)
coderay (>= 1.0.0)
@@ -261,6 +267,7 @@ PLATFORMS
DEPENDENCIES
acts-as-taggable-on
+ acts_as_commentable_with_threading
acts_as_votable (~> 0.5.0)
better_errors
binding_of_caller
diff --git a/app/assets/javascripts/comments.js.coffee b/app/assets/javascripts/comments.js.coffee
new file mode 100644
index 0000000..293634e
--- /dev/null
+++ b/app/assets/javascripts/comments.js.coffee
@@ -0,0 +1,52 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
+
+
+jQuery ->
+ # Create a comment
+ $list = $('.comment-list')
+ $form = $list.find('.new_comment')
+ .on 'ajax:beforeSend', (e, xhr, settings) ->
+ $(this).find('textarea').addClass('uneditable-input').attr('disabled', 'disabled')
+ .on 'ajax:success', (e, response, status, xhr) ->
+ $this = $(this)
+ $this.find('textarea').removeClass('uneditable-input').removeAttr('disabled', 'disabled').val('');
+
+ if xhr.getResponseHeader('Content-Type').indexOf('javascript') == -1
+ $(response).hide().appendTo($this.prev()).show('slow')
+
+ $list
+ .on 'ajax:beforeSend', '.close', ->
+ $(this).closest('.comment').fadeTo('fast', 0.5)
+ .on 'ajax:success', '.close', ->
+ $(this).closest('.comment').hide('fast')
+ .on 'ajax:error', '.close', ->
+ $(this).closest('.comment').fadeTo('fast', 1)
+
+ .on 'click', '.comment_for', (e) ->
+ e.preventDefault()
+ $this = $(this)
+ return false unless $form.length
+ $form.next(':hidden').show()
+ $this.hide().before($form)
+ $form.find('input[name*=parent_id]').val($this.data('id') || '')
+
+ .on 'ajax:before', '.voting', ->
+ $this = $(this)
+ return false if $this.data('sending')
+ $this.data('sending', true)
+
+ .on 'ajax:success', '.voting', (e, response) ->
+ $this = $(this)
+ $this.find('.count-likes').val(response.like)
+ $this.find('.count-dislikes').val(response.dislike)
+ $this.find('.btn').removeClass('disabled').data('method', false)
+
+ if response.vote
+ $this.find('.btn').first().addClass('disabled').data('method', 'delete')
+ else if response.vote == false
+ $this.find('.btn').last().addClass('disabled').data('method', 'delete')
+
+ .on 'ajax:complete', '.voting', ->
+ $(this).data('sending', false)
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
new file mode 100644
index 0000000..8d3d091
--- /dev/null
+++ b/app/controllers/comments_controller.rb
@@ -0,0 +1,58 @@
+class CommentsController < ApplicationController
+ before_filter :load_obj_and_build_comment, only: :create
+ load_resource except: :create
+ authorize_resource
+
+ def create
+ if @comment.save
+
+ unless params[:comment][:parent_id].blank?
+ parent = @obj.comment_threads.find_by(id: params[:comment][:parent_id])
+
+ @comment.move_to_child_of parent if parent
+ end
+
+ render partial: 'comments/comment', locals: { comment: @comment },
+ layout: false, status: :created
+ else
+ render js: "alert('error saving');"
+ end
+ end
+
+ def destroy
+ if @comment.destroy
+ render json: @comment, status: :ok
+ else
+ render js: "alert('error deleting comment');"
+ end
+ end
+
+ def vote
+ vote = params[:type] != 'dislike'
+ if current_user.voted_as_when_voted_for(@comment) != vote
+ @comment.vote voter: current_user, vote: vote
+ end
+ render json: likes_data
+ end
+
+ def unvote
+ @comment.unliked_by current_user
+ render json: likes_data
+ end
+
+ private
+
+ def load_obj_and_build_comment
+ data = params[:comment]
+ @obj = Comment.find_commentable(data[:commentable_type], data[:commentable_id])
+ @comment = Comment.build_from(@obj, current_user.id, data[:body])
+ end
+
+ def likes_data
+ {
+ like: @comment.count_votes_up,
+ dislike: @comment.cached_votes_down,
+ vote: current_user.voted_as_when_voted_for(@comment)
+ }
+ end
+end
diff --git a/app/controllers/funs_controller.rb b/app/controllers/funs_controller.rb
index b6deeb5..5d8fd0a 100644
--- a/app/controllers/funs_controller.rb
+++ b/app/controllers/funs_controller.rb
@@ -34,6 +34,9 @@ def feed
# GET /funs/1
def show
+ @tree = AwesomeNestedTree.new @fun.comment_threads.includes(:user)
+ @new_comment = Comment.build_from(@fun)
+
@funs = @fun.get_month_trends(current_user, cookies_store[:type]).includes(:user, :content).limit 9
respond_to :html, :js
end
diff --git a/app/helpers/funs_helper.rb b/app/helpers/funs_helper.rb
index 8dbd04e..727b238 100644
--- a/app/helpers/funs_helper.rb
+++ b/app/helpers/funs_helper.rb
@@ -220,4 +220,13 @@ def link_to_fun_title(fun)
end
end
+ def vote_link(text, url, voted)
+ options = { class: [:btn], remote: true }
+ if voted
+ options[:class] << :disabled
+ options[:method] = :delete
+ end
+ link_to text, url, options
+ end
+
end
\ No newline at end of file
diff --git a/app/models/comment.rb b/app/models/comment.rb
new file mode 100644
index 0000000..cb92951
--- /dev/null
+++ b/app/models/comment.rb
@@ -0,0 +1,42 @@
+class Comment < ActiveRecord::Base
+ attr_accessible :commentable, :body, :user_id
+ acts_as_nested_set scope: [:commentable_id, :commentable_type]
+
+ validates :body, :user, presence: true
+
+ # NOTE: install the acts_as_votable plugin if you
+ # want user to vote on the quality of comments.
+ acts_as_votable
+
+ belongs_to :commentable, polymorphic: true
+
+ # NOTE: Comments belong to a user
+ belongs_to :user
+
+ # Helper class method to lookup all comments assigned
+ # to all commentable types for a given user.
+ scope :find_comments_by_user, lambda { |user|
+ where(user_id: user.id).order('created_at DESC')
+ }
+
+ # Helper class method to look up all comments for
+ # commentable class name and commentable id.
+ scope :find_comments_for_commentable, lambda { |commentable_str, commentable_id|
+ where(commentable_type: commentable_str.to_s, commentable_id: commentable_id).order('created_at DESC')
+ }
+
+ class << self
+ # Helper class method that allows you to build a comment
+ # by passing a commentable object, a user_id, and comment text
+ # example in readme
+ def build_from(obj, user_id = nil, comment = '')
+ new commentable: obj, body: comment, user_id: user_id
+ end
+
+ # Helper class method to look up a commentable object
+ # given the commentable class name and id
+ def find_commentable(commentable_str, commentable_id)
+ commentable_str.constantize.find(commentable_id)
+ end
+ end
+end
diff --git a/app/models/fun.rb b/app/models/fun.rb
index e54733e..e00e823 100644
--- a/app/models/fun.rb
+++ b/app/models/fun.rb
@@ -29,6 +29,7 @@ class Fun < ActiveRecord::Base
# Initialize "acts_as_votable" gem for "likes"
acts_as_votable
+ acts_as_commentable
def attributes=(attributes = {})
self.content_type = attributes[:content_type]
diff --git a/app/views/comments/_comment.html.slim b/app/views/comments/_comment.html.slim
new file mode 100644
index 0000000..1ca81a6
--- /dev/null
+++ b/app/views/comments/_comment.html.slim
@@ -0,0 +1,22 @@
+.comment
+ - if can? :destroy, Comment
+ = link_to '×', comment_path(comment), method: :delete, remote: true, confirm: 'Are you sure you want to remove this comment?', disable_with: '×', class: 'close'
+ span.muted= l comment.created_at
+ strong= comment.user.login
+
+ - vote = current_user ? current_user.voted_as_when_voted_for(comment) : nil
+ .input-prepend.input-append.voting
+ = vote_link '+', vote_comment_path(comment), vote
+ input.span1.text-center.text-success.count-likes disabled=true value=comment.count_votes_up type=:text
+ input.span1.text-center.text-error.count-dislikes disabled=true value=comment.count_votes_down type=:text
+ = vote_link '-', vote_comment_path(comment, :dislike), vote === false
+
+ div= comment.body
+
+ blockquote
+ - unless comment.leaf?
+ = render partial: 'comments/comment', collection: tree.children(comment.id), as: :comment, locals: { tree: tree }
+ - if can? :create, Comment
+ = link_to 'answer', 'javascript:;', class: 'comment_for', data: { id: comment.id }
+
+ hr
\ No newline at end of file
diff --git a/app/views/comments/_list.html.slim b/app/views/comments/_list.html.slim
new file mode 100644
index 0000000..9d77433
--- /dev/null
+++ b/app/views/comments/_list.html.slim
@@ -0,0 +1,11 @@
+.comment-list
+ = render partial: 'comments/comment', collection: tree.root, as: :comment, locals: { tree: tree }
+ - if can? :create, Comment
+ = form_for new_comment, remote: true do |f|
+ = f.text_area :body, rows: 3, class: 'input-block-level'
+ = f.hidden_field :parent_id
+ = f.hidden_field :commentable_id
+ = f.hidden_field :commentable_type
+ = f.button :submit, class: 'btn btn-primary', disable_with: 'Submitting…'
+
+ = link_to 'Add comment', 'javascript:;', class: 'comment_for', style: 'display:none'
\ No newline at end of file
diff --git a/app/views/funs/show.html.slim b/app/views/funs/show.html.slim
index ada5406..c9dce9b 100644
--- a/app/views/funs/show.html.slim
+++ b/app/views/funs/show.html.slim
@@ -36,6 +36,7 @@
.tags
= show_cached_tags @fun
a[name='comments']
+ = render partial: 'comments/list', locals: { new_comment: @new_comment, tree: @tree }
.comments_block#vk_comments
javascript:
VK.Widgets.Like("vk_like", {type: "mini", height: 20, pageTitle: "#{@fun.content.title}", pageUrl: "#{fun_url(@fun)}", pageImage: "#{fun_image_url(@fun, :small)}"});
diff --git a/config/routes.rb b/config/routes.rb
index 402b8ef..371fe12 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,6 +2,11 @@
root to: 'funs#index'
+ resources :comments, only: [:create, :destroy] do
+ get 'vote(/:type)', action: :vote, on: :member, as: :vote
+ delete 'vote(/:type)', action: :unvote, on: :member
+ end
+
resources :notifications, only: :index
get 'reports', to: 'reports#index'
diff --git a/db/migrate/20140415144524_acts_as_commentable_with_threading_migration.rb b/db/migrate/20140415144524_acts_as_commentable_with_threading_migration.rb
new file mode 100644
index 0000000..b8fbb9d
--- /dev/null
+++ b/db/migrate/20140415144524_acts_as_commentable_with_threading_migration.rb
@@ -0,0 +1,21 @@
+class ActsAsCommentableWithThreadingMigration < ActiveRecord::Migration
+ def self.up
+ create_table :comments, force: true do |t|
+ t.integer :commentable_id, default: 0
+ t.string :commentable_type
+ t.string :title
+ t.text :body
+ t.string :subject
+ t.integer :user_id, default: 0, null: false
+ t.integer :parent_id, :lft, :rgt
+ t.timestamps
+ end
+
+ add_index :comments, :user_id
+ add_index :comments, [:commentable_id, :commentable_type]
+ end
+
+ def self.down
+ drop_table :comments
+ end
+end
diff --git a/db/migrate/20140416070220_add_cached_votes_to_comments.rb b/db/migrate/20140416070220_add_cached_votes_to_comments.rb
new file mode 100644
index 0000000..7bfffd3
--- /dev/null
+++ b/db/migrate/20140416070220_add_cached_votes_to_comments.rb
@@ -0,0 +1,19 @@
+class AddCachedVotesToComments < ActiveRecord::Migration
+ def self.up
+ add_column :comments, :cached_votes_score, :integer, default: 0
+ add_column :comments, :cached_votes_up, :integer, default: 0
+ add_column :comments, :cached_votes_down, :integer, default: 0
+ add_index :comments, :cached_votes_score
+ add_index :comments, :cached_votes_up
+ add_index :comments, :cached_votes_down
+
+ # Uncomment this line to force caching of existing votes
+ Comment.find_each(&:update_cached_votes)
+ end
+
+ def self.down
+ remove_column :comments, :cached_votes_score
+ remove_column :comments, :cached_votes_up
+ remove_column :comments, :cached_votes_down
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a83a27a..ea1ca0b 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,30 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20140411085401) do
+ActiveRecord::Schema.define(:version => 20140416070220) do
+
+ create_table "comments", :force => true do |t|
+ t.integer "commentable_id", :default => 0
+ t.string "commentable_type"
+ t.string "title"
+ t.text "body"
+ t.string "subject"
+ t.integer "user_id", :default => 0, :null => false
+ t.integer "parent_id"
+ t.integer "lft"
+ t.integer "rgt"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ t.integer "cached_votes_score", :default => 0
+ t.integer "cached_votes_up", :default => 0
+ t.integer "cached_votes_down", :default => 0
+ end
+
+ add_index "comments", ["cached_votes_down"], :name => "index_comments_on_cached_votes_down"
+ add_index "comments", ["cached_votes_score"], :name => "index_comments_on_cached_votes_score"
+ add_index "comments", ["cached_votes_up"], :name => "index_comments_on_cached_votes_up"
+ add_index "comments", ["commentable_id", "commentable_type"], :name => "index_comments_on_commentable_id_and_commentable_type"
+ add_index "comments", ["user_id"], :name => "index_comments_on_user_id"
create_table "funs", :force => true do |t|
t.integer "user_id"
diff --git a/lib/awesome_nested_tree.rb b/lib/awesome_nested_tree.rb
new file mode 100644
index 0000000..054b29b
--- /dev/null
+++ b/lib/awesome_nested_tree.rb
@@ -0,0 +1,27 @@
+class AwesomeNestedTree
+
+ attr_reader :all, :root
+
+ def initialize(all)
+ @all = all
+ @root = []
+ @children = {}
+
+ @all.map do |item|
+ if item.parent_id
+ @children[item.parent_id] ||= []
+ @children[item.parent_id] << item
+ else
+ @root << item
+ end
+ end
+ end
+
+ def children?(id)
+ @children.key? id
+ end
+
+ def children(id)
+ @children[id]
+ end
+end
\ No newline at end of file
From 1c86d3c2414b68effe46fbcbf2779a6c5c397a68 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Wed, 16 Apr 2014 11:45:07 +0300
Subject: [PATCH 20/64] answer to comment
---
app/controllers/comments_controller.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index 8d3d091..a4b85e6 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -7,7 +7,7 @@ def create
if @comment.save
unless params[:comment][:parent_id].blank?
- parent = @obj.comment_threads.find_by(id: params[:comment][:parent_id])
+ parent = @obj.comment_threads.find(params[:comment][:parent_id]) rescue nil
@comment.move_to_child_of parent if parent
end
From c4bbc03e57eece91d76ec4cf0ffa52f27e87937f Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Wed, 16 Apr 2014 11:45:47 +0300
Subject: [PATCH 21/64] comment rights
---
app/models/ability.rb | 2 ++
1 file changed, 2 insertions(+)
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 0f289c1..0bf76cb 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -18,6 +18,8 @@ def initialize(user)
can :update, User, id: user.id
can :create, Report
can :read, :all
+ can :create, Comment
+ can :destroy, Comment, user_id: user.id, leaf?: true
cannot [:destroy, :read], Report
cannot :show, Notification
else
From f3fc8a6d5fa0a19a22f11fb70fe76b2bb6610648 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Wed, 16 Apr 2014 12:54:14 +0300
Subject: [PATCH 22/64] cache commentable comments count
---
app/models/comment.rb | 9 +++++++++
app/models/fun.rb | 6 +++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/app/models/comment.rb b/app/models/comment.rb
index cb92951..fb76a53 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -1,4 +1,7 @@
class Comment < ActiveRecord::Base
+ after_create :update_commentable_counter
+ after_destroy :update_commentable_counter
+
attr_accessible :commentable, :body, :user_id
acts_as_nested_set scope: [:commentable_id, :commentable_type]
@@ -39,4 +42,10 @@ def find_commentable(commentable_str, commentable_id)
commentable_str.constantize.find(commentable_id)
end
end
+
+ private
+
+ def update_commentable_counter
+ commentable.update_comments_count if commentable.respond_to? :update_comments_count
+ end
end
diff --git a/app/models/fun.rb b/app/models/fun.rb
index e00e823..b208557 100644
--- a/app/models/fun.rb
+++ b/app/models/fun.rb
@@ -1,5 +1,5 @@
class Fun < ActiveRecord::Base
- attr_accessible :content_attributes, :content_type, :comments_count
+ attr_accessible :content_attributes, :content_type
attr_accessible :content_id, :content_type, :user_id, :owner_id, as: :admin
after_destroy :delete_content
before_destroy :delete_likes
@@ -221,6 +221,10 @@ def delete_content
content.destroy unless repost?
end
+ def update_comments_count
+ update_attribute :comments_counter, comment_threads.count
+ end
+
private
def create_notification
From a0c56e21ef5c60f1673b3b0ef7b448d726b846e3 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Wed, 16 Apr 2014 12:54:35 +0300
Subject: [PATCH 23/64] remove vk comments
---
app/controllers/socials_controller.rb | 18 ------------------
app/views/funs/show.html.slim | 11 ++++-------
2 files changed, 4 insertions(+), 25 deletions(-)
diff --git a/app/controllers/socials_controller.rb b/app/controllers/socials_controller.rb
index be8efd2..8710944 100644
--- a/app/controllers/socials_controller.rb
+++ b/app/controllers/socials_controller.rb
@@ -1,26 +1,8 @@
class SocialsController < ApplicationController
before_filter :only_xhr_request
- def vkontakte_comments
- if check_sign params
- @fun = Fun.find(params[:id])
- @fun.update_attribute :comments_counter, params[:num]
- head :ok
- else
- head :bad_request
- end
- end
-
def social_likes
@fun = Fun.find(params[:id])
render layout: false
end
-
- private
-
- def check_sign(params)
- checkstr = Settings.widgets.vkontakte.comments.secret.to_s + params[:date].to_s + params[:num].to_s + params[:last_comment].to_s
- params[:sign].to_s == Digest::MD5.hexdigest(checkstr.encode('windows-1251'))
- end
-
end
\ No newline at end of file
diff --git a/app/views/funs/show.html.slim b/app/views/funs/show.html.slim
index c9dce9b..4817103 100644
--- a/app/views/funs/show.html.slim
+++ b/app/views/funs/show.html.slim
@@ -23,6 +23,8 @@
#vk_like
.fb-like[data-href="#{fun_url(@fun)}" data-send="false" data-layout="button_count" data-width="450" data-show-faces="true" data-font="arial"]
a[href="https://twitter.com/share" rel="nofollow" class="twitter-share-button" data-via="bitfun" data-lang="ru" data-related="butfun" data-text="#{@fun.content.title || t('meta_tags.main.title')}"] Tweet
+ javascript:
+ VK.Widgets.Like("vk_like", {type: "mini", height: 20, pageTitle: "#{@fun.content.title}", pageUrl: "#{fun_url(@fun)}", pageImage: "#{fun_image_url(@fun, :small)}"});
.follow_parent
= follow_link(@fun.user)
= edit_fun_link @fun
@@ -36,13 +38,8 @@
.tags
= show_cached_tags @fun
a[name='comments']
- = render partial: 'comments/list', locals: { new_comment: @new_comment, tree: @tree }
- .comments_block#vk_comments
- javascript:
- VK.Widgets.Like("vk_like", {type: "mini", height: 20, pageTitle: "#{@fun.content.title}", pageUrl: "#{fun_url(@fun)}", pageImage: "#{fun_image_url(@fun, :small)}"});
- VK.Widgets.Comments("vk_comments", { limit: 15, width: "670", attach: "*", onChange: function(num, last_comment, date, sign){
- $.post( "#{vk_comments_callback_path(@fun.id)}", { num: num.toString(), last_comment:last_comment , date: date, sign:sign } );
- } }, #{@fun.id});
+ .comments_block
+ = render partial: 'comments/list', locals: { new_comment: @new_comment, tree: @tree }
.aside.sidebar
section.vertical_carousel
From ee2c9332a1acb6b7f536387b86ce3dbaa7cde9c8 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 17 Apr 2014 09:45:05 +0300
Subject: [PATCH 24/64] comments design
---
app/assets/images/chat.png | Bin 0 -> 375 bytes
app/assets/stylesheets/funs.css.scss | 105 ++++++++++++++++++-
app/assets/stylesheets/inc/_helpers.css.scss | 9 +-
app/helpers/funs_helper.rb | 8 +-
app/views/comments/_comment.html.slim | 42 ++++----
app/views/comments/_list.html.slim | 27 +++--
6 files changed, 156 insertions(+), 35 deletions(-)
create mode 100644 app/assets/images/chat.png
diff --git a/app/assets/images/chat.png b/app/assets/images/chat.png
new file mode 100644
index 0000000000000000000000000000000000000000..8558b64a25237da137835508138f9f87ddbfb7ba
GIT binary patch
literal 375
zcmeAS@N?(olHy`uVBq!ia0vp^f*>{r8<6y`Y?T61Y)RhkE)4%caKYZ?lYt_f1s;*b
z3=G`DAk4@xYmNj^kiEpy*OmPqivW+NfZ(J6Zw3ZN7Ec$)5RLOwFBy6<2MQefcz>M|
zrv^vXVvbv#OV_doNORA=-qC);_V_zhpUqVa&Rf2+U7Hl4p>#t-MbOl2wpv>FXZ`zU
zYK%Xh?ervXG=U_{a$fEs84&@p6*X;GL#Y)F1pMx
zUE*Pm(zmv5iFQ+_3kMu0wK2{+ru{(7byC~
Date: Thu, 17 Apr 2014 09:45:46 +0300
Subject: [PATCH 25/64] fix scss style
---
app/assets/stylesheets/funs.css.scss | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/assets/stylesheets/funs.css.scss b/app/assets/stylesheets/funs.css.scss
index 1def670..1a53d15 100644
--- a/app/assets/stylesheets/funs.css.scss
+++ b/app/assets/stylesheets/funs.css.scss
@@ -1292,7 +1292,7 @@ html, body {
.like_box, .repost_box, .complain_box { padding: 0 1px; margin-right: 0; }
.item_adds {
- background: url(/assets/post-navbar-bg.png) repeat-x 0 -50px;
+ background: asset_url("post-navbar-bg.png", image) repeat-x 0 -50px;
padding-bottom: 0;
float: left;
overflow: hidden;
From b0893d4de06cedd14aaaa272b866f29d4655a133 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 17 Apr 2014 09:54:03 +0300
Subject: [PATCH 26/64] user cannot destroy own comment
---
app/models/ability.rb | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 0bf76cb..8b9d5ca 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -19,7 +19,6 @@ def initialize(user)
can :create, Report
can :read, :all
can :create, Comment
- can :destroy, Comment, user_id: user.id, leaf?: true
cannot [:destroy, :read], Report
cannot :show, Notification
else
From ee734a86798d36867f2b51a7ba4b0406e50028c2 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 17 Apr 2014 10:13:59 +0300
Subject: [PATCH 27/64] comment remove btn
---
app/assets/stylesheets/funs.css.scss | 23 ++++++++++++++++++++++-
app/views/comments/_comment.html.slim | 4 ++--
app/views/comments/_list.html.slim | 2 +-
config/locales/ru.yml | 6 +++---
4 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/app/assets/stylesheets/funs.css.scss b/app/assets/stylesheets/funs.css.scss
index 1a53d15..ba2c9be 100644
--- a/app/assets/stylesheets/funs.css.scss
+++ b/app/assets/stylesheets/funs.css.scss
@@ -22,6 +22,16 @@ html, body {
@include btn-orange(35px);
}
+.btn-close-sm {
+ background: asset_url('btn-fun-icons.png', image) no-repeat -22px 0;
+ height: 21px;
+ width: 21px;
+ &:hover {
+ background-position: 0 0;
+ cursor: pointer;
+ }
+}
+
.page {
margin: $page_margin_top auto 0;
width: $page_width;
@@ -2339,7 +2349,7 @@ and (orientation:landscape) {
.info_list{
color: #474747;
font-size: 13px;
- .list_title{
+ .info_list_title{
color: #000000;
font: {
weight: bold;
@@ -2354,6 +2364,7 @@ and (orientation:landscape) {
border-top: 1px solid #e2e2e2;
padding-top: 20px;
margin-top: 20px;
+ position: relative;
.info_body{
margin-left: 90px;
}
@@ -2382,6 +2393,16 @@ and (orientation:landscape) {
}
&:hover{ text-decoration: underline; }
}
+ .btn-close-sm {
+ display: none;
+ position: absolute;
+ top: -10px;
+ right: -10px;
+ z-index: 1001;
+ }
+ &:hover {
+ > .btn-close-sm { display: block}
+ }
}
}
diff --git a/app/views/comments/_comment.html.slim b/app/views/comments/_comment.html.slim
index 36f30ad..e5918a8 100644
--- a/app/views/comments/_comment.html.slim
+++ b/app/views/comments/_comment.html.slim
@@ -1,6 +1,6 @@
.comment.info_element
- /- if can? :destroy, Comment
- / = link_to '×', comment_path(comment), method: :delete, remote: true, confirm: 'Are you sure you want to remove this comment?', disable_with: '×', class: 'close'
+ - if can? :destroy, Comment
+ = link_to '', comment_path(comment), method: :delete, remote: true, confirm: t('comment.confirm.delete'), class: 'btn-close-sm'
.photo_frame.pull-left
= link_to show_avatar(comment.user), comment.user, class: 'photo_box'
diff --git a/app/views/comments/_list.html.slim b/app/views/comments/_list.html.slim
index b648f44..5459ed9 100644
--- a/app/views/comments/_list.html.slim
+++ b/app/views/comments/_list.html.slim
@@ -1,5 +1,5 @@
.comment-list.info_list
- .list_title
+ .info_list_title
' Комментарии
span.gray
| (
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 12c6486..19c27d0 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -205,6 +205,6 @@ ru:
tag_list: 'Введите теги (через запятую)'
remote_file_url: 'Вставьте ссылку на изображение'
url: 'Вставьте ссылку на видео (youtube или vimeo)'
-
-
-
+ comment:
+ confirm:
+ delete: Вы действительно хотите удалить этот комментарий?
\ No newline at end of file
From e4f6afd6365cf633df3cbc8a57f447c2596257f7 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 17 Apr 2014 10:48:20 +0300
Subject: [PATCH 28/64] comments design (end)
---
app/assets/stylesheets/funs.css.scss | 46 ++++++++++----------
app/assets/stylesheets/inc/_helpers.css.scss | 3 +-
app/views/comments/_comment.html.slim | 7 ++-
app/views/comments/_list.html.slim | 5 ++-
config/locales/ru.yml | 6 ++-
5 files changed, 35 insertions(+), 32 deletions(-)
diff --git a/app/assets/stylesheets/funs.css.scss b/app/assets/stylesheets/funs.css.scss
index ba2c9be..8459c9e 100644
--- a/app/assets/stylesheets/funs.css.scss
+++ b/app/assets/stylesheets/funs.css.scss
@@ -2360,39 +2360,36 @@ and (orientation:landscape) {
color: #cacaca;
}
}
+ .info_action{
+ color: #8e8da9;
+ display: inline-block;
+ margin-top: 7px;
+ &.answer{
+ padding-left: 20px;
+ background: {
+ image: asset_url('chat.png', image);
+ repeat: no-repeat;
+ position: 0 50%;
+ }
+ }
+ &:hover{ text-decoration: underline; }
+ }
+ .info_muted{
+ color: #aaaaaa;
+ }
.info_element{
border-top: 1px solid #e2e2e2;
padding-top: 20px;
margin-top: 20px;
position: relative;
- .info_body{
- margin-left: 90px;
- }
+ .info_body{ margin-left: 90px; }
.info_title{
color: #6d6b93;
&:hover{ text-decoration: underline; }
}
- .info_muted{
- color: #aaaaaa;
- margin-top: 5px;
- }
- .info_content{
- margin-top: 15px;
- }
- .info_action{
- color: #8e8da9;
- display: inline-block;
- margin-top: 7px;
- &.answer{
- padding-left: 20px;
- background: {
- image: asset_url('chat.png', image);
- repeat: no-repeat;
- position: 0 50%;
- }
- }
- &:hover{ text-decoration: underline; }
- }
+ .info_muted{ margin-top: 5px; }
+ .info_content{ margin-top: 15px; }
+ .info_action{ display: inline-block; margin-top: 7px; }
.btn-close-sm {
display: none;
position: absolute;
@@ -2404,6 +2401,7 @@ and (orientation:landscape) {
> .btn-close-sm { display: block}
}
}
+
}
.btn-action{
diff --git a/app/assets/stylesheets/inc/_helpers.css.scss b/app/assets/stylesheets/inc/_helpers.css.scss
index 1b05640..b37da6a 100644
--- a/app/assets/stylesheets/inc/_helpers.css.scss
+++ b/app/assets/stylesheets/inc/_helpers.css.scss
@@ -19,4 +19,5 @@
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-}
\ No newline at end of file
+}
+.hidden { display: none; }
\ No newline at end of file
diff --git a/app/views/comments/_comment.html.slim b/app/views/comments/_comment.html.slim
index e5918a8..369f8eb 100644
--- a/app/views/comments/_comment.html.slim
+++ b/app/views/comments/_comment.html.slim
@@ -18,11 +18,10 @@
' добавил
span.date_block= comment.created_at
-
.info_content= comment.body
+ - if can? :create, Comment
+ = link_to t('comment.button.answer'), 'javascript:;', class: 'comment_for info_action answer', data: { id: comment.id }
blockquote.info_list
- unless comment.leaf?
- = render partial: 'comments/comment', collection: tree.children(comment.id), as: :comment, locals: { tree: tree }
- - if can? :create, Comment
- = link_to 'answer', 'javascript:;', class: 'comment_for info_action answer', data: { id: comment.id }
\ No newline at end of file
+ = render partial: 'comments/comment', collection: tree.children(comment.id), as: :comment, locals: { tree: tree }
\ No newline at end of file
diff --git a/app/views/comments/_list.html.slim b/app/views/comments/_list.html.slim
index 5459ed9..448b273 100644
--- a/app/views/comments/_list.html.slim
+++ b/app/views/comments/_list.html.slim
@@ -6,7 +6,7 @@
span.total_comments= tree.all.length
| )
= render partial: 'comments/comment', collection: tree.root, as: :comment, locals: { tree: tree }
- .info_element
+ .info_element.form_wrapper.hidden
- if can? :create, Comment
.photo_frame.pull-left
= link_to show_avatar(current_user), current_user, class: 'photo_box'
@@ -19,4 +19,5 @@
=link_to :submit, 'javascript:;', class: 'btn-orange'
- = link_to 'Add comment', 'javascript:;', class: 'comment_for', style: 'display:none'
\ No newline at end of file
+ = link_to t('comment.button.new'), 'javascript:;', class: 'comment_for info_action answer pull-right'
+ .clearfix
\ No newline at end of file
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 19c27d0..0e0ac29 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -207,4 +207,8 @@ ru:
url: 'Вставьте ссылку на видео (youtube или vimeo)'
comment:
confirm:
- delete: Вы действительно хотите удалить этот комментарий?
\ No newline at end of file
+ delete: Вы действительно хотите удалить этот комментарий?
+ button:
+ new: Добавить комментарий
+ create: Сохранить комментарий
+ answer: Ответить
\ No newline at end of file
From 1d7d4059b97cf14d29548802c130f8c823bbe92e Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 17 Apr 2014 15:59:31 +0300
Subject: [PATCH 29/64] comments for not signed user
---
app/assets/javascripts/application.js | 14 ++++-
app/assets/javascripts/comments.js.coffee | 55 ++++++++++++++------
app/assets/stylesheets/funs.css.scss | 9 +++-
app/assets/stylesheets/inc/_helpers.css.scss | 2 +-
app/controllers/comments_controller.rb | 3 +-
app/helpers/funs_helper.rb | 2 +-
app/helpers/users_helper.rb | 18 +++++++
app/views/comments/_comment.html.slim | 3 +-
app/views/comments/_list.html.slim | 8 +--
9 files changed, 83 insertions(+), 31 deletions(-)
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 6a69b7c..661308e 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -116,13 +116,23 @@ $(function(){
$.fancybox.close()
});
+ var showAuthRequire = function(){
+ show_notice('Авторизируйтесь или зарегистрируйтесь, чтобы можно было выполнять это действие.', 'error');
+ };
+
$(document).on('click', 'a[data-auth]', function(e){
e.preventDefault();
- show_notice('Авторизируйтесь или зарегистрируйтесь, чтобы можно было выполнять это действие.', 'error');
+ showAuthRequire();
});
+
+
$.rails.allowAction = function(element){
- if ( ! element.attr('data-confirm')) return true
+ if ( element.data('auth')){
+ showAuthRequire();
+ return false;
+ }
+ if ( ! element.attr('data-confirm')) return true;
show_notice(element.data('confirm'), 'confirm', {
buttons: [
diff --git a/app/assets/javascripts/comments.js.coffee b/app/assets/javascripts/comments.js.coffee
index 293634e..1862b3b 100644
--- a/app/assets/javascripts/comments.js.coffee
+++ b/app/assets/javascripts/comments.js.coffee
@@ -5,32 +5,52 @@
jQuery ->
# Create a comment
- $list = $('.comment-list')
- $form = $list.find('.new_comment')
+
+ checkVotingScore = ($voting) ->
+ if parseInt($voting.find('.vote_result').text()) < 0
+ $voting.addClass 'red'
+ else
+ $voting.removeClass 'red'
+
+ $list = $ '.comment-list'
+
+ $list.find('.voting').each ->
+ checkVotingScore $(this)
+
+ $form = $list.find('.form_wrapper')
.on 'ajax:beforeSend', (e, xhr, settings) ->
- $(this).find('textarea').addClass('uneditable-input').attr('disabled', 'disabled')
+ $(this).find('textarea').attr('disabled', 'disabled')
.on 'ajax:success', (e, response, status, xhr) ->
$this = $(this)
- $this.find('textarea').removeClass('uneditable-input').removeAttr('disabled', 'disabled').val('');
+ $this.find('textarea').removeAttr('disabled', 'disabled').val('');
if xhr.getResponseHeader('Content-Type').indexOf('javascript') == -1
- $(response).hide().appendTo($this.prev()).show('slow')
+ $form.before($(response).hide())
$list
- .on 'ajax:beforeSend', '.close', ->
+ .on 'ajax:beforeSend', '.btn-close-sm', ->
$(this).closest('.comment').fadeTo('fast', 0.5)
- .on 'ajax:success', '.close', ->
+ .on 'ajax:success', '.btn-close-sm', (e, response) ->
$(this).closest('.comment').hide('fast')
- .on 'ajax:error', '.close', ->
+ .on 'ajax:error', '.btn-close-sm', ->
$(this).closest('.comment').fadeTo('fast', 1)
.on 'click', '.comment_for', (e) ->
e.preventDefault()
$this = $(this)
- return false unless $form.length
- $form.next(':hidden').show()
- $this.hide().before($form)
- $form.find('input[name*=parent_id]').val($this.data('id') || '')
+ return true unless $form.length
+ $this.addClass('hidden')
+
+ $into = $this.siblings('.info_list').last()
+ $into = $this.closest('.info_list') unless $into.length
+
+ return true unless $into.length
+
+ $form.addClass('hidden').find('input[name*=parent_id]').val($this.data('id') || '')
+ $into.append $form
+ $list.find('.comment_for.hidden').not($this).removeClass('hidden')
+
+ $form.removeClass 'hidden'
.on 'ajax:before', '.voting', ->
$this = $(this)
@@ -39,14 +59,15 @@ jQuery ->
.on 'ajax:success', '.voting', (e, response) ->
$this = $(this)
- $this.find('.count-likes').val(response.like)
- $this.find('.count-dislikes').val(response.dislike)
- $this.find('.btn').removeClass('disabled').data('method', false)
+ $this.find('.vote_result').text(parseInt(response.score) || 0)
+ $this.find('.btn-action').removeClass('orange').data('method', false)
+
+ checkVotingScore $this
if response.vote
- $this.find('.btn').first().addClass('disabled').data('method', 'delete')
+ $this.find('.btn-action').first().addClass('orange').data('method', 'delete')
else if response.vote == false
- $this.find('.btn').last().addClass('disabled').data('method', 'delete')
+ $this.find('.btn-action').last().addClass('orange').data('method', 'delete')
.on 'ajax:complete', '.voting', ->
$(this).data('sending', false)
diff --git a/app/assets/stylesheets/funs.css.scss b/app/assets/stylesheets/funs.css.scss
index 8459c9e..3516fd7 100644
--- a/app/assets/stylesheets/funs.css.scss
+++ b/app/assets/stylesheets/funs.css.scss
@@ -2401,7 +2401,9 @@ and (orientation:landscape) {
> .btn-close-sm { display: block}
}
}
-
+ .info_list{
+ margin-left: -60px;
+ }
}
.btn-action{
@@ -2431,7 +2433,10 @@ and (orientation:landscape) {
.voting{
color: #5b5985;
- font-size: 16px;
+ font: {
+ size: 16px;
+ weight: bold;
+ }
line-height: 30px;
position: relative;
min-width: 40px;
diff --git a/app/assets/stylesheets/inc/_helpers.css.scss b/app/assets/stylesheets/inc/_helpers.css.scss
index b37da6a..168fe13 100644
--- a/app/assets/stylesheets/inc/_helpers.css.scss
+++ b/app/assets/stylesheets/inc/_helpers.css.scss
@@ -20,4 +20,4 @@
-moz-box-sizing: border-box;
box-sizing: border-box;
}
-.hidden { display: none; }
\ No newline at end of file
+.hidden { display: none !important; }
\ No newline at end of file
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index a4b85e6..233470d 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -50,8 +50,7 @@ def load_obj_and_build_comment
def likes_data
{
- like: @comment.count_votes_up,
- dislike: @comment.cached_votes_down,
+ score: @comment.cached_votes_score,
vote: current_user.voted_as_when_voted_for(@comment)
}
end
diff --git a/app/helpers/funs_helper.rb b/app/helpers/funs_helper.rb
index d26e470..6aef9ff 100644
--- a/app/helpers/funs_helper.rb
+++ b/app/helpers/funs_helper.rb
@@ -226,7 +226,7 @@ def vote_link(class_name, url, voted)
options[:class] << :orange
options[:method] = :delete
end
- link_to '', url, options
+ auth_link_to '', url, options
end
end
\ No newline at end of file
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index f1f69c9..782f5c2 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -84,4 +84,22 @@ def omniauth_link(resource, provider)
end
end
+ def auth_link_to(*args, &block)
+ if block_given?
+ name = capture(&block)
+ options = args.first || {}
+ html_options = args.second
+ else
+ name = args[0]
+ options = args[1] || {}
+ html_options = args[2]
+ end
+
+ unless user_signed_in?
+ html_options[:data] ||= {}
+ html_options[:data][:auth] = true
+ end
+
+ link_to(name, options, html_options)
+ end
end
\ No newline at end of file
diff --git a/app/views/comments/_comment.html.slim b/app/views/comments/_comment.html.slim
index 369f8eb..0504a12 100644
--- a/app/views/comments/_comment.html.slim
+++ b/app/views/comments/_comment.html.slim
@@ -20,8 +20,7 @@
.info_content= comment.body
- - if can? :create, Comment
- = link_to t('comment.button.answer'), 'javascript:;', class: 'comment_for info_action answer', data: { id: comment.id }
+ = auth_link_to t('comment.button.answer'), 'javascript:;', class: 'comment_for info_action answer', data: { id: comment.id }
blockquote.info_list
- unless comment.leaf?
= render partial: 'comments/comment', collection: tree.children(comment.id), as: :comment, locals: { tree: tree }
\ No newline at end of file
diff --git a/app/views/comments/_list.html.slim b/app/views/comments/_list.html.slim
index 448b273..e8e55ee 100644
--- a/app/views/comments/_list.html.slim
+++ b/app/views/comments/_list.html.slim
@@ -6,8 +6,8 @@
span.total_comments= tree.all.length
| )
= render partial: 'comments/comment', collection: tree.root, as: :comment, locals: { tree: tree }
- .info_element.form_wrapper.hidden
- - if can? :create, Comment
+ - if can? :create, Comment
+ .info_element.form_wrapper
.photo_frame.pull-left
= link_to show_avatar(current_user), current_user, class: 'photo_box'
.arrow
@@ -17,7 +17,7 @@
= f.input :commentable_id, as: :hidden
= f.input :commentable_type, as: :hidden
- =link_to :submit, 'javascript:;', class: 'btn-orange'
+ =link_to t('comment.button.create'), 'javascript:;', class: 'btn-orange', rel: :submit
- = link_to t('comment.button.new'), 'javascript:;', class: 'comment_for info_action answer pull-right'
+ = auth_link_to t('comment.button.new'), 'javascript:;', class: ('comment_for info_action answer pull-right' + (can?(:create, Comment) ? ' hidden' : ''))
.clearfix
\ No newline at end of file
From e47d78d2e56fcff513ac0147e564c9d61cfb0f94 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 17 Apr 2014 16:01:05 +0300
Subject: [PATCH 30/64] like box for reposted fun
---
app/controllers/socials_controller.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/controllers/socials_controller.rb b/app/controllers/socials_controller.rb
index 8710944..68aec7d 100644
--- a/app/controllers/socials_controller.rb
+++ b/app/controllers/socials_controller.rb
@@ -2,7 +2,7 @@ class SocialsController < ApplicationController
before_filter :only_xhr_request
def social_likes
- @fun = Fun.find(params[:id])
+ @fun = Fun.unscoped.find(params[:id])
render layout: false
end
end
\ No newline at end of file
From 4da0b968f0b4abddd8a843160ff995a573ec977b Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 17 Apr 2014 16:15:02 +0300
Subject: [PATCH 31/64] fix comment unvote
---
app/controllers/comments_controller.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index 233470d..7836f9f 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -36,7 +36,7 @@ def vote
end
def unvote
- @comment.unliked_by current_user
+ current_user.unvote_for @comment
render json: likes_data
end
From df90cece86763221e6b4710f2e82e8b751d8b026 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 17 Apr 2014 17:29:07 +0300
Subject: [PATCH 32/64] comments scroll to showed form
---
app/assets/javascripts/comments.js.coffee | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/app/assets/javascripts/comments.js.coffee b/app/assets/javascripts/comments.js.coffee
index 1862b3b..9848c68 100644
--- a/app/assets/javascripts/comments.js.coffee
+++ b/app/assets/javascripts/comments.js.coffee
@@ -6,6 +6,18 @@
jQuery ->
# Create a comment
+ scrollToElement = ($target) ->
+ $window = $(window)
+ wb = $window.scrollTop() + $window.height()
+ tb = $target.offset().top + $target.outerHeight()
+
+ if tb + 10 > wb
+
+ $('html, body').animate(
+ scrollTop: tb - $window.height() + 10
+ 500
+ );
+
checkVotingScore = ($voting) ->
if parseInt($voting.find('.vote_result').text()) < 0
$voting.addClass 'red'
@@ -51,6 +63,7 @@ jQuery ->
$list.find('.comment_for.hidden').not($this).removeClass('hidden')
$form.removeClass 'hidden'
+ scrollToElement $form
.on 'ajax:before', '.voting', ->
$this = $(this)
From e4b23a375d91103a70bf9109e008556abd81366a Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 18 Apr 2014 10:05:23 +0300
Subject: [PATCH 33/64] comment depth
---
app/assets/javascripts/comments.js.coffee | 35 +++++++++++--------
app/controllers/comments_controller.rb | 6 ++--
app/models/comment.rb | 6 ++++
app/views/comments/_comment.html.slim | 4 +--
...as_commentable_with_threading_migration.rb | 2 +-
db/schema.rb | 1 +
6 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/app/assets/javascripts/comments.js.coffee b/app/assets/javascripts/comments.js.coffee
index 9848c68..13ffadb 100644
--- a/app/assets/javascripts/comments.js.coffee
+++ b/app/assets/javascripts/comments.js.coffee
@@ -4,7 +4,7 @@
jQuery ->
- # Create a comment
+ $list = $ '.comment-list'
scrollToElement = ($target) ->
$window = $(window)
@@ -18,34 +18,41 @@ jQuery ->
500
);
+ changeTotal = (diff) ->
+ $list.find('.total_comments').each ->
+ $this = $(this)
+ $this.text(Math.max(0, parseInt($this.text()) + diff))
+
checkVotingScore = ($voting) ->
if parseInt($voting.find('.vote_result').text()) < 0
$voting.addClass 'red'
else
$voting.removeClass 'red'
- $list = $ '.comment-list'
-
$list.find('.voting').each ->
checkVotingScore $(this)
$form = $list.find('.form_wrapper')
- .on 'ajax:beforeSend', (e, xhr, settings) ->
+ .on 'ajax:beforeSend', ->
+ return false unless $.trim($(this).find('textarea').val()).length
+ .on 'ajax:beforeSend', ->
$(this).find('textarea').attr('disabled', 'disabled')
- .on 'ajax:success', (e, response, status, xhr) ->
- $this = $(this)
- $this.find('textarea').removeAttr('disabled', 'disabled').val('');
-
- if xhr.getResponseHeader('Content-Type').indexOf('javascript') == -1
- $form.before($(response).hide())
+ .on 'ajax:success', (e, response) ->
+ $(this).find('textarea').val('')
+ $(response).hide().insertBefore($form).show 'slow'
+ changeTotal 1
+ .on 'ajax:complete', ->
+ $(this).find('textarea').removeAttr('disabled');
$list
.on 'ajax:beforeSend', '.btn-close-sm', ->
- $(this).closest('.comment').fadeTo('fast', 0.5)
- .on 'ajax:success', '.btn-close-sm', (e, response) ->
- $(this).closest('.comment').hide('fast')
+ $(this).closest('.comment').fadeTo 'fast', 0.5
+ .on 'ajax:success', '.btn-close-sm', ->
+ $(this).closest('.comment').hide 'fast', ->
+ changeTotal -1 - $(this).find('.comment').length
+ $(this).remove()
.on 'ajax:error', '.btn-close-sm', ->
- $(this).closest('.comment').fadeTo('fast', 1)
+ $(this).closest('.comment').fadeTo 'fast', 1
.on 'click', '.comment_for', (e) ->
e.preventDefault()
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index 7836f9f..ee883bd 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -9,13 +9,13 @@ def create
unless params[:comment][:parent_id].blank?
parent = @obj.comment_threads.find(params[:comment][:parent_id]) rescue nil
- @comment.move_to_child_of parent if parent
+ @comment.move_to_child_of parent if parent && parent.allowed_to_answer?
end
render partial: 'comments/comment', locals: { comment: @comment },
layout: false, status: :created
else
- render js: "alert('error saving');"
+ render nothing: true, status: 400
end
end
@@ -23,7 +23,7 @@ def destroy
if @comment.destroy
render json: @comment, status: :ok
else
- render js: "alert('error deleting comment');"
+ render nothing: true, status: 400
end
end
diff --git a/app/models/comment.rb b/app/models/comment.rb
index fb76a53..29ecc27 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -5,6 +5,8 @@ class Comment < ActiveRecord::Base
attr_accessible :commentable, :body, :user_id
acts_as_nested_set scope: [:commentable_id, :commentable_type]
+ ANSWER_DEPTH = 7
+
validates :body, :user, presence: true
# NOTE: install the acts_as_votable plugin if you
@@ -28,6 +30,10 @@ class Comment < ActiveRecord::Base
where(commentable_type: commentable_str.to_s, commentable_id: commentable_id).order('created_at DESC')
}
+ def allowed_to_answer?
+ depth.to_i < ANSWER_DEPTH
+ end
+
class << self
# Helper class method that allows you to build a comment
# by passing a commentable object, a user_id, and comment text
diff --git a/app/views/comments/_comment.html.slim b/app/views/comments/_comment.html.slim
index 0504a12..b5514d7 100644
--- a/app/views/comments/_comment.html.slim
+++ b/app/views/comments/_comment.html.slim
@@ -19,8 +19,8 @@
span.date_block= comment.created_at
.info_content= comment.body
-
- = auth_link_to t('comment.button.answer'), 'javascript:;', class: 'comment_for info_action answer', data: { id: comment.id }
+ - if comment.allowed_to_answer?
+ = auth_link_to t('comment.button.answer'), 'javascript:;', class: 'comment_for info_action answer', data: { id: comment.id }
blockquote.info_list
- unless comment.leaf?
= render partial: 'comments/comment', collection: tree.children(comment.id), as: :comment, locals: { tree: tree }
\ No newline at end of file
diff --git a/db/migrate/20140415144524_acts_as_commentable_with_threading_migration.rb b/db/migrate/20140415144524_acts_as_commentable_with_threading_migration.rb
index b8fbb9d..d11c242 100644
--- a/db/migrate/20140415144524_acts_as_commentable_with_threading_migration.rb
+++ b/db/migrate/20140415144524_acts_as_commentable_with_threading_migration.rb
@@ -7,7 +7,7 @@ def self.up
t.text :body
t.string :subject
t.integer :user_id, default: 0, null: false
- t.integer :parent_id, :lft, :rgt
+ t.integer :parent_id, :lft, :rgt, :depth
t.timestamps
end
diff --git a/db/schema.rb b/db/schema.rb
index ea1ca0b..4f2a621 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -23,6 +23,7 @@
t.integer "parent_id"
t.integer "lft"
t.integer "rgt"
+ t.integer "depth"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "cached_votes_score", :default => 0
From 85ad35ec092748a99beaf0c626f3fe094fd6fe35 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 18 Apr 2014 16:15:15 +0300
Subject: [PATCH 34/64] time ago script
---
Gemfile | 2 +
Gemfile.lock | 3 +
app/assets/javascripts/date-time-format.js | 100 +++++++++++++++++++++
3 files changed, 105 insertions(+)
create mode 100644 app/assets/javascripts/date-time-format.js
diff --git a/Gemfile b/Gemfile
index 3cf760c..9229f1b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -114,6 +114,8 @@ gem 'jquery-ui-rails'
gem 'acts_as_commentable_with_threading'
+gem 'momentjs-rails'
+
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 3d28228..faed5d4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -143,6 +143,8 @@ GEM
railties
middleware (0.1.0)
mime-types (1.23)
+ momentjs-rails (2.5.1)
+ railties (>= 3.1)
multi_json (1.7.7)
multipart-post (1.2.0)
mysql2 (0.3.15)
@@ -290,6 +292,7 @@ DEPENDENCIES
mailcatcher
meta-tags
meta_request
+ momentjs-rails
mysql2 (>= 0.3.13)
omniauth
omniauth-facebook
diff --git a/app/assets/javascripts/date-time-format.js b/app/assets/javascripts/date-time-format.js
new file mode 100644
index 0000000..1bc146e
--- /dev/null
+++ b/app/assets/javascripts/date-time-format.js
@@ -0,0 +1,100 @@
+!function ($, moment) {
+
+ "use strict"; // jshint ;_
+
+ var settings = {
+ datetime: false,
+ refreshMillis: 20000,
+ todayFormat: '[сегодня в] HH:mm',
+ yesterdayFormat: '[вчера в] HH:mm',
+ thisYearFormat: 'D MMM в HH:mm',
+ defaultFormat: 'D MMM YYYY в HH:mm',
+ innerSelector: false,
+ onComplete: false
+ };
+
+ var DateTimeFormat = function (element, options) {
+ options = typeof options == 'object' ? options : {};
+
+ this.$element = $(element);
+ this.options = $.extend({}, settings, typeof options == 'object' ? options : {});
+ this.dateTimeStr = this.options.datetime || this.$element.data('iso8601');
+
+ if ( ! (this.dateTimeStr && moment(this.dateTimeStr).isValid())) return;
+
+ this.moment = moment(this.dateTimeStr);
+
+ this.init();
+ };
+
+ DateTimeFormat.prototype = {
+
+ init: function() {
+ this.setText().startInterval();
+ if ($.isFunction(this.options.onComplete))
+ this.options.onComplete(this.$element, this)
+ },
+
+ setText: function(){
+ if (this.options.innerSelector){
+ this.$element.find(this.options.innerSelector).text(this.getMomentStr())
+ }else{
+ this.$element.text(this.getMomentStr())
+ }
+ return this;
+ },
+
+ startInterval: function() {
+ if (this.options.refreshMillis > 0){
+ if (this.isLessThenHour()){
+ if(!this.intervalId){
+ this.intervalId = setInterval($.proxy(this.refreshText, this), this.options.refreshMillis);
+ }
+ }
+ }
+ return this
+ },
+
+ refreshText: function(){
+ this.setText();
+
+ if (this.intervalId && ! this.isLessThenHour()){
+ clearInterval(this.intervalId);
+ }
+ },
+
+ getMomentStr: function () {
+ if (this.isLessThenHour()) return this.moment.fromNow();
+ if (this.isToday()) return this.moment.format(this.options.todayFormat);
+ if (this.isYesterday()) return this.moment.format(this.options.yesterdayFormat);
+ if (this.isThisYear()) return this.moment.format(this.options.thisYearFormat);
+
+ return this.moment.format(this.options.defaultFormat);
+ },
+ isLessThenHour: function () {
+ return this.moment.isAfter(moment().subtract(1, 'hour'))
+ },
+ isToday: function () {
+ return this.moment.isSame(moment(), 'day')
+ },
+ isYesterday: function () {
+ return this.moment.isSame(moment().subtract(1, 'day'), 'day');
+ },
+ isThisYear: function () {
+ return this.moment.isSame(moment(), 'year')
+ }
+ };
+
+ /* DateTimeFormat PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.datetimeformat = function (options) {
+ return this.each(function () {
+ var $this = $(this), data = $this.data('datetimeformat');
+ if (!data) $this.data('datetimeformat', (new DateTimeFormat(this, options)))
+ if (typeof options == 'string') data[options]()
+ })
+ };
+
+ $.fn.datetimeformat.Constructor = DateTimeFormat;
+}(window.jQuery, moment);
From 012fc5ed98ad9d1b351c685980bd64c512dcdac1 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 18 Apr 2014 16:15:28 +0300
Subject: [PATCH 35/64] time ago helper
---
app/helpers/dates_helper.rb | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 app/helpers/dates_helper.rb
diff --git a/app/helpers/dates_helper.rb b/app/helpers/dates_helper.rb
new file mode 100644
index 0000000..0853754
--- /dev/null
+++ b/app/helpers/dates_helper.rb
@@ -0,0 +1,5 @@
+module DatesHelper
+ def time_ago_format(date)
+ content_tag :span, '', class: 'date_block date-time-format', data: {iso8601: date.to_time.iso8601}
+ end
+end
\ No newline at end of file
From 496bfc7c40946a926ab14a0e785cb49bcd4f93fa Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 18 Apr 2014 16:15:55 +0300
Subject: [PATCH 36/64] time ago auto initialize
---
app/assets/javascripts/application.js | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 661308e..a2b50d4 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -11,6 +11,8 @@
//= require source/bootstrap-tab
//= require rails.validations
//= require hogan.js
+//= require moment
+//= require moment/ru
//= require_tree .
$(function(){
@@ -163,6 +165,20 @@ $(function(){
}
}
});
+
+ $.fn.findAndFormatDateTime = function(){
+ $(this).find('.date-time-format').datetimeformat({
+ onComplete: function(element, object){
+ element.tooltipster({
+ theme: 'tooltips_theme',
+ offsetY: -5,
+ content: object.moment.format('YYYY-MM-DD HH:mm')
+ });
+ }
+ });
+ };
+
+ $(document).findAndFormatDateTime();
});
function show_notice(text, type, options) {
From bf40ceab93a59d1bba3260f76ea0ffda438b4cb4 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 18 Apr 2014 16:16:13 +0300
Subject: [PATCH 37/64] time ago in comments
---
app/assets/javascripts/comments.js.coffee | 2 +-
app/views/comments/_comment.html.slim | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/assets/javascripts/comments.js.coffee b/app/assets/javascripts/comments.js.coffee
index 13ffadb..64e39a5 100644
--- a/app/assets/javascripts/comments.js.coffee
+++ b/app/assets/javascripts/comments.js.coffee
@@ -39,7 +39,7 @@ jQuery ->
$(this).find('textarea').attr('disabled', 'disabled')
.on 'ajax:success', (e, response) ->
$(this).find('textarea').val('')
- $(response).hide().insertBefore($form).show 'slow'
+ $(response).hide().insertBefore($form).show('slow').findAndFormatDateTime();
changeTotal 1
.on 'ajax:complete', ->
$(this).find('textarea').removeAttr('disabled');
diff --git a/app/views/comments/_comment.html.slim b/app/views/comments/_comment.html.slim
index b5514d7..d5f7e3a 100644
--- a/app/views/comments/_comment.html.slim
+++ b/app/views/comments/_comment.html.slim
@@ -16,7 +16,7 @@
= link_to comment.user.login, comment.user.login, class: 'info_title'
.info_muted
' добавил
- span.date_block= comment.created_at
+ = time_ago_format comment.created_at
.info_content= comment.body
- if comment.allowed_to_answer?
From def4620695dbe43a5bce806166f754447972cbcf Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 18 Apr 2014 16:16:35 +0300
Subject: [PATCH 38/64] time ago on show fun page
---
app/views/funs/show.html.slim | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/app/views/funs/show.html.slim b/app/views/funs/show.html.slim
index 4817103..73de7e0 100644
--- a/app/views/funs/show.html.slim
+++ b/app/views/funs/show.html.slim
@@ -11,9 +11,7 @@
.poster
= link_to @fun.user.login, @fun.user
span добавил •
- span.date_block
- = time_ago_in_words @fun.created_at
- | назад
+ = time_ago_format @fun.created_at
- if @fun.content.title?
h1.title
= title @fun.content.title
From 938364afdccd5e479e16e7ce2ba7fed9d574fcfb Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 18 Apr 2014 17:50:27 +0300
Subject: [PATCH 39/64] replace time_ago_in_words by js
---
app/assets/javascripts/funs/filters.js | 1 +
app/assets/javascripts/funs/wall.js | 1 +
app/assets/javascripts/users/wall.js | 2 ++
app/views/funs/_box.html.slim | 4 +---
app/views/funs/_list.html.slim | 4 +---
5 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/app/assets/javascripts/funs/filters.js b/app/assets/javascripts/funs/filters.js
index 46414f0..e0be964 100644
--- a/app/assets/javascripts/funs/filters.js
+++ b/app/assets/javascripts/funs/filters.js
@@ -38,6 +38,7 @@ $(function(){
wall.html(data.responseText);
wall.initButtonTooltips();
wall.initTooltips();
+ wall.findAndFormatDateTime();
$(window).data('endelessscroll').resetFiring();
if (postData.view == 'box'){
diff --git a/app/assets/javascripts/funs/wall.js b/app/assets/javascripts/funs/wall.js
index bff0416..7d45b0c 100644
--- a/app/assets/javascripts/funs/wall.js
+++ b/app/assets/javascripts/funs/wall.js
@@ -111,6 +111,7 @@ $(function(){
$newElems.imagesLoaded(function(){
$newElems.animate({ opacity: 1 }).initButtonTooltips();
$newElems.initTooltips();
+ $newElems.findAndFormatDateTime();
if ($wall.data('masonry')) $wall.masonry( 'appended', $newElems, true );
$wall.append($newElems);
});
diff --git a/app/assets/javascripts/users/wall.js b/app/assets/javascripts/users/wall.js
index b8d6027..c8598a6 100644
--- a/app/assets/javascripts/users/wall.js
+++ b/app/assets/javascripts/users/wall.js
@@ -31,6 +31,7 @@ $(function(){
wall.html(data.responseText);
wall.initButtonTooltips();
wall.initTooltips();
+ wall.findAndFormatDateTime();
$(window).data('endelessscroll').resetFiring();
if (currentState == 'box'){
@@ -65,6 +66,7 @@ $(function(){
wall.html(data.responseText);
wall.initButtonTooltips();
wall.initTooltips();
+ wall.findAndFormatDateTime();
$(window).data('endelessscroll').resetFiring();
if (currentState == 'box'){
if (wall.data('masonry')) wall.masonry('reload');
diff --git a/app/views/funs/_box.html.slim b/app/views/funs/_box.html.slim
index 3e96cbd..a7ad6b9 100644
--- a/app/views/funs/_box.html.slim
+++ b/app/views/funs/_box.html.slim
@@ -12,9 +12,7 @@ article.post_frame.post_card
= link_to fun.content.title, fun
- else
= fun_add_line fun
- span.date_block
- = time_ago_in_words fun.created_at
- | назад
+ = time_ago_format fun.created_at
.post_object
.arrow
= render_fun_partial fun, :box
diff --git a/app/views/funs/_list.html.slim b/app/views/funs/_list.html.slim
index 51b2e9c..7a5eab6 100644
--- a/app/views/funs/_list.html.slim
+++ b/app/views/funs/_list.html.slim
@@ -10,9 +10,7 @@ article.post_frame
= link_to fun.user.login, fun.user
= fun_add_line(fun, true) || ' добавил '
| •
- span.date_block
- = time_ago_in_words fun.created_at
- | назад
+ = time_ago_format fun.created_at
- if fun.content.title?
.title
h2 = link_to fun.content.title, fun
From c38d1ebebe0cb8064227c4fde1ce063ad4b91655 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 09:31:23 +0300
Subject: [PATCH 40/64] remove notification on fun create
---
app/models/fun.rb | 8 --------
1 file changed, 8 deletions(-)
diff --git a/app/models/fun.rb b/app/models/fun.rb
index b208557..5f31f4f 100644
--- a/app/models/fun.rb
+++ b/app/models/fun.rb
@@ -4,7 +4,6 @@ class Fun < ActiveRecord::Base
after_destroy :delete_content
before_destroy :delete_likes
before_destroy :delete_reposts
- after_create :create_notification
# Kaminari pagination config
paginates_per 10
@@ -21,7 +20,6 @@ class Fun < ActiveRecord::Base
belongs_to :content, polymorphic: true
accepts_nested_attributes_for :content, allow_destroy: true
has_many :reports, dependent: :destroy
- has_many :notifications, as: :subject, dependent: :destroy
# Reposts
has_many :reposts, class_name: 'Fun', foreign_key: 'parent_id'
@@ -224,10 +222,4 @@ def delete_content
def update_comments_count
update_attribute :comments_counter, comment_threads.count
end
-
- private
-
- def create_notification
- self.notifications.create(user_id: user_id, action: :create)
- end
end
\ No newline at end of file
From e4215c1a9ec20c47e5a6dced5fc52122947b565d Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 09:37:52 +0300
Subject: [PATCH 41/64] notification on comment create
---
app/models/comment.rb | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 29ecc27..7bbe0fe 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -1,6 +1,7 @@
class Comment < ActiveRecord::Base
after_create :update_commentable_counter
after_destroy :update_commentable_counter
+ after_create :create_notification
attr_accessible :commentable, :body, :user_id
acts_as_nested_set scope: [:commentable_id, :commentable_type]
@@ -18,6 +19,8 @@ class Comment < ActiveRecord::Base
# NOTE: Comments belong to a user
belongs_to :user
+ has_many :notifications, as: :subject, dependent: :destroy
+
# Helper class method to lookup all comments assigned
# to all commentable types for a given user.
scope :find_comments_by_user, lambda { |user|
@@ -54,4 +57,8 @@ def find_commentable(commentable_str, commentable_id)
def update_commentable_counter
commentable.update_comments_count if commentable.respond_to? :update_comments_count
end
+
+ def create_notification
+ self.notifications.create(user_id: user_id, action: :create)
+ end
end
From 0e8a09dcc91c98a97a2e4a3e6dd60310ef4b9a6e Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 09:44:44 +0300
Subject: [PATCH 42/64] gem meta_request only for development
---
Gemfile | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Gemfile b/Gemfile
index 9229f1b..347281b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -63,7 +63,6 @@ gem 'thin'
# Show error in better format
gem 'better_errors'
gem 'binding_of_caller'
-gem 'meta_request'
# use this gem only for testing VK widgets
gem 'localtunnel'
@@ -91,6 +90,10 @@ gem 'bourbon'
gem 'sass-rails', '~> 3.2.3'
+group :development do
+ gem 'meta_request'
+end
+
group :assets do
# Toolkit from Twitter designed to kickstart development of webapps and sites
# gem "bootstrap-sass"
From f607b33d68214440b31512018f4643ffd48fbb47 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 10:04:55 +0300
Subject: [PATCH 43/64] update gem meta_request and dependencies
---
Gemfile.lock | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index faed5d4..375dee5 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -98,7 +98,7 @@ GEM
chardet (>= 0.9.0)
hoe (>= 1.2.0)
httpauth (0.2.0)
- i18n (0.6.4)
+ i18n (0.6.9)
innertube (1.1.0)
joiner (0.2.0)
activerecord (>= 3.1.0, < 4.1.0)
@@ -112,7 +112,7 @@ GEM
jquery-ui-rails (4.0.3)
jquery-rails
railties (>= 3.1.0)
- json (1.8.0)
+ json (1.8.1)
jwt (0.1.8)
multi_json (>= 1.5)
kaminari (0.14.1)
@@ -137,7 +137,7 @@ GEM
thin (~> 1.5.0)
meta-tags (1.5.0)
actionpack
- meta_request (0.2.7)
+ meta_request (0.3.0)
callsite
rack-contrib
railties
@@ -145,7 +145,7 @@ GEM
mime-types (1.23)
momentjs-rails (2.5.1)
railties (>= 3.1)
- multi_json (1.7.7)
+ multi_json (1.9.2)
multipart-post (1.2.0)
mysql2 (0.3.15)
net-ssh (2.6.7)
@@ -187,7 +187,7 @@ GEM
rack (>= 0.9.1)
rack-protection (1.5.0)
rack
- rack-ssl (1.3.3)
+ rack-ssl (1.3.4)
rack
rack-test (0.6.2)
rack (>= 1.0)
@@ -206,7 +206,7 @@ GEM
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
- rake (10.1.0)
+ rake (10.3.1)
rdoc (3.12.2)
json (~> 1.4)
riddle (1.5.10)
@@ -250,7 +250,7 @@ GEM
joiner (>= 0.2.0)
middleware (>= 0.1.0)
riddle (>= 1.5.10)
- thor (0.18.1)
+ thor (0.19.1)
tilt (1.4.1)
treetop (1.4.14)
polyglot
From 98a123e2bd291f5eed94af06e504eee63e4db26e Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 11:52:32 +0300
Subject: [PATCH 44/64] change user votes cache
---
app/models/user.rb | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/app/models/user.rb b/app/models/user.rb
index 6af4ec5..f5c2d0d 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -154,14 +154,20 @@ def reposted?(fun)
fun.id.in? reposted_ids
end
- # Get funs ids which user voted
- def voted_ids
- @voted_ids ||= votes.where(votable_type: Fun).pluck(:votable_id)
+ def my_votes
+ @votes_cache ||= {}.tap do |h|
+ votes.each do |v|
+ ts = v.votable_type.to_sym
+ h[ts] ||= {}
+ h[ts][v.votable_id] = v.vote_flag
+ end
+ end
end
# Check if user already voted
- def voted?(fun)
- fun.id.in? voted_ids
+ def voted?(votable)
+ ts = votable.class.name.to_sym
+ my_votes.key?(ts) ? my_votes[ts][votable.id] : nil
end
# User feeds
From 58ce28ca51017e4b4ca7e22bf75f955dda2fb6dc Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 11:53:12 +0300
Subject: [PATCH 45/64] get cached user votes for comments
---
app/views/comments/_comment.html.slim | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/app/views/comments/_comment.html.slim b/app/views/comments/_comment.html.slim
index d5f7e3a..d785f0f 100644
--- a/app/views/comments/_comment.html.slim
+++ b/app/views/comments/_comment.html.slim
@@ -7,11 +7,10 @@
.arrow
.info_body
- - vote = current_user ? current_user.voted_as_when_voted_for(comment) : nil
.voting.pull-right
- = vote_link :plus, vote_comment_path(comment), vote
+ = vote_link :plus, vote_comment_path(comment), current_user.voted?(comment)
span.vote_result= comment.cached_votes_score
- = vote_link :minus, vote_comment_path(comment, :dislike), vote === false
+ = vote_link :minus, vote_comment_path(comment, :dislike), current_user.voted?(comment) === false
= link_to comment.user.login, comment.user.login, class: 'info_title'
.info_muted
From f84e21263115ab715bdc51f4510b4b991f939309 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 13:01:16 +0300
Subject: [PATCH 46/64] count liked funs on user page
---
app/models/user.rb | 4 ++++
app/views/users/show.html.slim | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/app/models/user.rb b/app/models/user.rb
index f5c2d0d..f502cf4 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -164,6 +164,10 @@ def my_votes
end
end
+ def votes_count_for(type)
+ my_votes.key?(type) ? my_votes[type].length : 0
+ end
+
# Check if user already voted
def voted?(votable)
ts = votable.class.name.to_sym
diff --git a/app/views/users/show.html.slim b/app/views/users/show.html.slim
index f375aa2..1a6e8d4 100644
--- a/app/views/users/show.html.slim
+++ b/app/views/users/show.html.slim
@@ -50,7 +50,7 @@ div[class="container feed_layout#{view_partial == 'box' ? ' grid' : ''}"]
a.switch.hold_right[href="#{likes_user_path @user}" rel='tooltip' title="#{t('funs.titles.profile.likes')}"]
span.toggle_slider
span.toggle_name
- = t('user.likes', count: @user.voted_ids.count)
+ = t('user.likes', count: @user.votes_count_for(:Fun))
.tumbler_switch.toggle_view#user_switch_view
.toggle_track
From 114ed3da23ce25cd87df15d402212b5b94357722 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 14:51:31 +0300
Subject: [PATCH 47/64] user can vote at comments
---
app/models/ability.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 8b9d5ca..c2104fa 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -18,7 +18,7 @@ def initialize(user)
can :update, User, id: user.id
can :create, Report
can :read, :all
- can :create, Comment
+ can [:create, :vote, :unvote], Comment
cannot [:destroy, :read], Report
cannot :show, Notification
else
From f67957e8d9636905f287daf20c01f4ceafc91919 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 14:53:29 +0300
Subject: [PATCH 48/64] notification belongs to fun
---
app/models/notification.rb | 3 ++-
db/migrate/20140411085401_create_notifications.rb | 1 +
db/schema.rb | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/app/models/notification.rb b/app/models/notification.rb
index 89d5aa9..a23ad1e 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -1,11 +1,12 @@
class Notification < ActiveRecord::Base
attr_accessible :target_id, :target_type, :target,
:subject_id, :subject_type, :subject,
- :action, :user_id, :receiver_id
+ :action, :user_id, :receiver_id, :fun
belongs_to :subject, polymorphic: true
belongs_to :target, polymorphic: true
belongs_to :user
+ belongs_to :fun
validates_presence_of :subject_id
validates_presence_of :user_id
diff --git a/db/migrate/20140411085401_create_notifications.rb b/db/migrate/20140411085401_create_notifications.rb
index 8bd35e4..684f238 100644
--- a/db/migrate/20140411085401_create_notifications.rb
+++ b/db/migrate/20140411085401_create_notifications.rb
@@ -7,6 +7,7 @@ def change
t.references :target, polymorphic: true
t.integer :user_id
t.integer :receiver_id
+ t.integer :fun_id
t.timestamp :created_at
end
diff --git a/db/schema.rb b/db/schema.rb
index 4f2a621..a8145f7 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -79,6 +79,7 @@
t.string "target_type"
t.integer "user_id"
t.integer "receiver_id"
+ t.integer "fun_id"
t.datetime "created_at"
end
From fc0ee0ed1c19393fb19e47839c1d64ebdf46ce1a Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 15:02:54 +0300
Subject: [PATCH 49/64] save notifications with fun
---
app/models/comment.rb | 9 ++++++++-
app/models/fun.rb | 4 ++++
lib/acts_as_votable/vote.rb | 11 +++++++----
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 7bbe0fe..6affbac 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -52,6 +52,10 @@ def find_commentable(commentable_str, commentable_id)
end
end
+ def notification_fun
+ commentable
+ end
+
private
def update_commentable_counter
@@ -59,6 +63,9 @@ def update_commentable_counter
end
def create_notification
- self.notifications.create(user_id: user_id, action: :create)
+ return if user_id == commentable.user_id
+
+ notifications.create(user_id: user_id, action: :create,
+ receiver_id: commentable.user_id, fun: commentable )
end
end
diff --git a/app/models/fun.rb b/app/models/fun.rb
index 5f31f4f..7ce5fb7 100644
--- a/app/models/fun.rb
+++ b/app/models/fun.rb
@@ -129,6 +129,10 @@ def get_month_trends(user, type)
Fun.exclude_funs(exclude).where(published_at: month_range).filter_by_type(type).order('cached_votes_total DESC')
end
+ def notification_fun
+ self
+ end
+
class << self
def reposters
diff --git a/lib/acts_as_votable/vote.rb b/lib/acts_as_votable/vote.rb
index 7b33262..bd7f6b7 100644
--- a/lib/acts_as_votable/vote.rb
+++ b/lib/acts_as_votable/vote.rb
@@ -7,10 +7,13 @@ class Vote < ActiveRecord::Base
private
def create_notification
- notifications.create(user_id: voter_id, action: :create,
- receiver_id: votable.user_id, target: votable)
- end
+ return if voter_id == votable.user_id
- end
+ data = { user_id: voter_id, action: :create, receiver_id: votable.user_id }
+ data[:fun] = votable.notification_fun if votable.respond_to? :notification_fun
+ data[:target] = votable unless data[:fun] || data[:fun] == votable
+ notifications.create(data)
+ end
+ end
end
\ No newline at end of file
From d5a81c6fcf8461f55978eb253c2bf89fffec0e5e Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 15:32:18 +0300
Subject: [PATCH 50/64] remove unneeded arrow
---
app/views/funs/_box.html.slim | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/views/funs/_box.html.slim b/app/views/funs/_box.html.slim
index a7ad6b9..a75d704 100644
--- a/app/views/funs/_box.html.slim
+++ b/app/views/funs/_box.html.slim
@@ -14,7 +14,6 @@ article.post_frame.post_card
= fun_add_line fun
= time_ago_format fun.created_at
.post_object
- .arrow
= render_fun_partial fun, :box
.post_nav
= small_like_button fun
From 79e439e23db69f83837a2220c63ce236c108722e Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 16:02:04 +0300
Subject: [PATCH 51/64] set comment parent before create
---
app/controllers/comments_controller.rb | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index ee883bd..3eb189c 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -4,14 +4,13 @@ class CommentsController < ApplicationController
authorize_resource
def create
- if @comment.save
-
- unless params[:comment][:parent_id].blank?
- parent = @obj.comment_threads.find(params[:comment][:parent_id]) rescue nil
+ unless params[:comment][:parent_id].blank?
+ parent = @obj.comment_threads.find(params[:comment][:parent_id]) rescue nil
- @comment.move_to_child_of parent if parent && parent.allowed_to_answer?
- end
+ @comment.parent = parent if parent && parent.allowed_to_answer?
+ end
+ if @comment.save
render partial: 'comments/comment', locals: { comment: @comment },
layout: false, status: :created
else
From a2b3e7d1b6ac08d8a5374c821ea6c0ce921bee21 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 16:11:47 +0300
Subject: [PATCH 52/64] duplicate notification if comment have a parent
---
app/models/comment.rb | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 6affbac..a15edf8 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -63,9 +63,14 @@ def update_commentable_counter
end
def create_notification
- return if user_id == commentable.user_id
+ data = { user_id: user_id, action: :create, fun: commentable }
- notifications.create(user_id: user_id, action: :create,
- receiver_id: commentable.user_id, fun: commentable )
+ if user_id != commentable.user_id
+ notifications.create(data.merge(receiver_id: commentable.user_id))
+ end
+
+ if parent && user_id != parent.user_id && commentable.user_id != parent.user_id
+ notifications.create(data.merge(receiver_id: parent.user_id, target: parent))
+ end
end
end
From f461a3e7dbda35aa79e5501b5ec27b51f8a2e35a Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Tue, 22 Apr 2014 16:38:53 +0300
Subject: [PATCH 53/64] fix show user url
---
app/views/comments/_comment.html.slim | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/comments/_comment.html.slim b/app/views/comments/_comment.html.slim
index d785f0f..ea3752f 100644
--- a/app/views/comments/_comment.html.slim
+++ b/app/views/comments/_comment.html.slim
@@ -12,7 +12,7 @@
span.vote_result= comment.cached_votes_score
= vote_link :minus, vote_comment_path(comment, :dislike), current_user.voted?(comment) === false
- = link_to comment.user.login, comment.user.login, class: 'info_title'
+ = link_to comment.user.login, comment.user, class: 'info_title'
.info_muted
' добавил
= time_ago_format comment.created_at
From 24eb84f26ad55aac3278bc39d62c75b3927addf1 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 24 Apr 2014 11:39:47 +0300
Subject: [PATCH 54/64] notification group
---
app/models/notification/group.rb | 21 ++++++++++++++++
app/models/notification/list.rb | 43 ++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+)
create mode 100644 app/models/notification/group.rb
create mode 100644 app/models/notification/list.rb
diff --git a/app/models/notification/group.rb b/app/models/notification/group.rb
new file mode 100644
index 0000000..2e17983
--- /dev/null
+++ b/app/models/notification/group.rb
@@ -0,0 +1,21 @@
+class Notification::Group
+ attr_accessor :notifications, :time, :field, :value
+
+ PERIOD = 30
+ FIELDS = [:subject, :user, :target]
+
+ def initialize(time, field, value, notifications = [])
+ @time = time - PERIOD.minutes
+ @field = field
+ @value = value
+ @notifications = notifications
+ end
+
+ def accept?(notification)
+ notification.group_param(field) == value && time < notification.created_at
+ end
+
+ def user
+ notifications.first.user
+ end
+end
\ No newline at end of file
diff --git a/app/models/notification/list.rb b/app/models/notification/list.rb
new file mode 100644
index 0000000..822b355
--- /dev/null
+++ b/app/models/notification/list.rb
@@ -0,0 +1,43 @@
+class Notification::List
+ def initialize(notifications)
+ @groups = []
+
+ notifications.each do |notification|
+
+ create = Notification::Group::FIELDS - append_to_groups(notification)
+ create.each do |k|
+ @groups << Notification::Group.new(notification.created_at, k,
+ notification.group_param(k), [notification])
+ end
+ end
+
+ clear_repeats
+ end
+
+ def append_to_groups(notification)
+ [].tap do |exist|
+ each do |group|
+ if group.accept?(notification)
+ group.notifications << notification
+ exist << group.field
+ end
+ end
+ end.uniq
+ end
+
+ def each
+ @groups.each{ |g| yield g }
+ end
+
+ def clear_repeats
+ used = {}
+ weights = []
+ @groups.each_with_index{ |g, i| weights << [i, g.notifications.length] }
+ weights.sort{ |a, b| b[1] <=> a[1] }.each do |w|
+ @groups[w[0]].notifications.delete_if do |notification|
+ used[notification.id].tap { used[notification.id] = true }
+ end
+ end
+ @groups.delete_if{ |group| group.notifications.empty? }
+ end
+end
\ No newline at end of file
From d0be9b4c2edcfa88a4d195ee81f09a311c174401 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Thu, 24 Apr 2014 16:36:50 +0300
Subject: [PATCH 55/64] notification list
---
app/assets/javascripts/notification.js.coffee | 10 ++++++
app/assets/stylesheets/funs.css.scss | 33 +++++++++++++++++--
app/controllers/notifications_controller.rb | 5 ++-
app/models/ability.rb | 1 +
app/models/notification.rb | 9 +++++
app/models/notification/group.rb | 4 +--
app/views/notifications/_group.html.slim | 16 +++++++++
app/views/notifications/_record.html.slim | 15 +++++++++
app/views/notifications/index.html.slim | 22 +++++--------
9 files changed, 97 insertions(+), 18 deletions(-)
create mode 100644 app/assets/javascripts/notification.js.coffee
create mode 100644 app/views/notifications/_group.html.slim
create mode 100644 app/views/notifications/_record.html.slim
diff --git a/app/assets/javascripts/notification.js.coffee b/app/assets/javascripts/notification.js.coffee
new file mode 100644
index 0000000..35a8ff2
--- /dev/null
+++ b/app/assets/javascripts/notification.js.coffee
@@ -0,0 +1,10 @@
+$ ->
+ marker = '.hidden_mark'
+ $('.notification_list').on 'click', '.click_handler', (e) ->
+ e.preventDefault
+ $this = $ this
+ $marker = $this.closest(marker)
+ $group = $this.closest('.notification_group')
+
+ $marker.addClass('hidden')
+ $group.find('.hidden').not($marker).removeClass('hidden')
\ No newline at end of file
diff --git a/app/assets/stylesheets/funs.css.scss b/app/assets/stylesheets/funs.css.scss
index 3516fd7..ef3c4db 100644
--- a/app/assets/stylesheets/funs.css.scss
+++ b/app/assets/stylesheets/funs.css.scss
@@ -2351,6 +2351,7 @@ and (orientation:landscape) {
font-size: 13px;
.info_list_title{
color: #000000;
+ margin-bottom: 15px;
font: {
weight: bold;
size: 18px;
@@ -2379,8 +2380,8 @@ and (orientation:landscape) {
}
.info_element{
border-top: 1px solid #e2e2e2;
- padding-top: 20px;
- margin-top: 20px;
+ padding: 15px 0 0 10px;
+ margin-top: 15px;
position: relative;
.info_body{ margin-left: 90px; }
.info_title{
@@ -2403,6 +2404,9 @@ and (orientation:landscape) {
}
.info_list{
margin-left: -60px;
+ .info_element{
+ padding-left: 0;
+ }
}
}
@@ -2450,4 +2454,29 @@ and (orientation:landscape) {
&.plus { left: 0 }
&.minus { right: 0 }
}
+}
+
+.notification_list{
+ .info_element{
+ margin-top: 0;
+ padding-bottom: 15px;
+ }
+ .click_handler:hover{
+ cursor: pointer;
+ background-color: #f2f2f2;
+
+ .arrow_expand{
+ position: absolute;
+ top: 15px;
+ right: 15px;
+ border-left: 6px solid transparent;
+ border-right: 6px solid transparent;
+ border-top: 6px solid #5b5985;
+
+ &.expanded{
+ border-top: 0px solid transparent;
+ border-bottom: 6px solid #5b5985;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
index 3f305cf..cf7d6dc 100644
--- a/app/controllers/notifications_controller.rb
+++ b/app/controllers/notifications_controller.rb
@@ -3,7 +3,10 @@ class NotificationsController < ApplicationController
def index
@notifications = Fun.unscoped do
- Notification.includes(:user, :target, :subject).where(receiver_id: current_user.id)
+ Notification.includes(:fun, :user, :target, :subject)
+ .where(receiver_id: current_user.id).order('created_at DESC').all
end
+
+ @list = Notification::List.new(@notifications)
end
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index c2104fa..a6d5a87 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -23,6 +23,7 @@ def initialize(user)
cannot :show, Notification
else
can :read, :all
+ cannot :read, Notification
end
end
end
\ No newline at end of file
diff --git a/app/models/notification.rb b/app/models/notification.rb
index a23ad1e..6b84277 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -11,4 +11,13 @@ class Notification < ActiveRecord::Base
validates_presence_of :subject_id
validates_presence_of :user_id
validates_presence_of :action
+
+ def group_param(key)
+ case key
+ when :subject then "#{subject_type}_#{subject_id}"
+ when :user then user_id
+ when :target then target_id ? "#{target_type}_#{target_id}" :fun_id
+ else nil
+ end
+ end
end
diff --git a/app/models/notification/group.rb b/app/models/notification/group.rb
index 2e17983..dea717d 100644
--- a/app/models/notification/group.rb
+++ b/app/models/notification/group.rb
@@ -15,7 +15,7 @@ def accept?(notification)
notification.group_param(field) == value && time < notification.created_at
end
- def user
- notifications.first.user
+ def first
+ notifications.first
end
end
\ No newline at end of file
diff --git a/app/views/notifications/_group.html.slim b/app/views/notifications/_group.html.slim
new file mode 100644
index 0000000..d1b68e7
--- /dev/null
+++ b/app/views/notifications/_group.html.slim
@@ -0,0 +1,16 @@
+.notification_group
+ .info_element.click_handler.hidden_mark
+ .arrow_expand
+ .photo_frame.pull-left
+ = link_to show_avatar(group.first.user), group.first.user, class: 'photo_box'
+ .arrow
+
+ .info_body
+ | #{group.field} #{group.value}
+ .info_muted
+ = time_ago_format group.first.created_at
+ .info_content= group.notifications.length
+ .clearfix
+ .group_details.hidden.hidden_mark
+ - group.notifications.each_with_index do |notification, index|
+ = render 'notifications/record', notification: notification, add_class: (index.zero? ? 'click_handler' : '')
\ No newline at end of file
diff --git a/app/views/notifications/_record.html.slim b/app/views/notifications/_record.html.slim
new file mode 100644
index 0000000..0fa3258
--- /dev/null
+++ b/app/views/notifications/_record.html.slim
@@ -0,0 +1,15 @@
+.info_element class="#{(defined? add_class) ? add_class : ''}"
+ .arrow_expand.expanded
+ .photo_frame.pull-left
+ = link_to show_avatar(notification.user), notification.user, class: 'photo_box'
+ .arrow
+
+ .info_body
+ = link_to notification.user.login, notification.user, class: 'info_title'
+ .info_muted
+ = time_ago_format notification.created_at
+
+ .info_content
+ ' #{notification.action} #{notification.subject.class.name}
+ = link_to notification.target.class.name, notification.target if notification.target
+ .clearfix
\ No newline at end of file
diff --git a/app/views/notifications/index.html.slim b/app/views/notifications/index.html.slim
index f8937ff..e143ec6 100644
--- a/app/views/notifications/index.html.slim
+++ b/app/views/notifications/index.html.slim
@@ -1,15 +1,11 @@
.container.rating_layout
- .topics_block
- .title_page
- h1 Notification list
.rating_layout
- ul
- - @notifications.each do |n|
- li
- .photo_frame
- = link_to show_avatar(n.user), n.user, class: 'photo_box'
- = link_to n.user.login, n.user
- = n.action
- = n.subject.class.name
- = link_to n.target.class.name, n.target if n.target
- = n.created_at
\ No newline at end of file
+ .info_list.notification_list
+ .info_list_title
+ ' Notifications list
+
+ - @list.each do |group|
+ - if group.notifications.length > 1
+ = render 'notifications/group', group: group
+ - else
+ = render 'notifications/record', notification: group.first
\ No newline at end of file
From b052c65e92e51fe28dffe436ec446fcbe958193c Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 25 Apr 2014 15:10:34 +0300
Subject: [PATCH 56/64] notification list
---
app/assets/stylesheets/funs.css.scss | 8 ++--
app/controllers/notifications_controller.rb | 2 +-
app/helpers/notifications_helper.rb | 24 +++++++++++
app/models/notification.rb | 22 ++++++++--
app/models/notification/group.rb | 21 +++++++++-
app/models/notification/list.rb | 7 +++-
app/views/notifications/_group.html.slim | 5 ++-
app/views/notifications/_record.html.slim | 8 +---
.../notifications/record/_comment.html.slim | 9 +++++
.../notifications/record/_default.html.slim | 8 ++++
config/locales/ru.yml | 40 ++++++++++++++++++-
11 files changed, 133 insertions(+), 21 deletions(-)
create mode 100644 app/helpers/notifications_helper.rb
create mode 100644 app/views/notifications/record/_comment.html.slim
create mode 100644 app/views/notifications/record/_default.html.slim
diff --git a/app/assets/stylesheets/funs.css.scss b/app/assets/stylesheets/funs.css.scss
index ef3c4db..1aab827 100644
--- a/app/assets/stylesheets/funs.css.scss
+++ b/app/assets/stylesheets/funs.css.scss
@@ -2384,10 +2384,6 @@ and (orientation:landscape) {
margin-top: 15px;
position: relative;
.info_body{ margin-left: 90px; }
- .info_title{
- color: #6d6b93;
- &:hover{ text-decoration: underline; }
- }
.info_muted{ margin-top: 5px; }
.info_content{ margin-top: 15px; }
.info_action{ display: inline-block; margin-top: 7px; }
@@ -2401,6 +2397,10 @@ and (orientation:landscape) {
&:hover {
> .btn-close-sm { display: block}
}
+ a{
+ color: #6d6b93;
+ &:hover{ text-decoration: underline; }
+ }
}
.info_list{
margin-left: -60px;
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
index cf7d6dc..9e53f1e 100644
--- a/app/controllers/notifications_controller.rb
+++ b/app/controllers/notifications_controller.rb
@@ -3,7 +3,7 @@ class NotificationsController < ApplicationController
def index
@notifications = Fun.unscoped do
- Notification.includes(:fun, :user, :target, :subject)
+ Notification.includes({ fun: :content } , :user, :target, :subject)
.where(receiver_id: current_user.id).order('created_at DESC').all
end
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
new file mode 100644
index 0000000..c5ad044
--- /dev/null
+++ b/app/helpers/notifications_helper.rb
@@ -0,0 +1,24 @@
+module NotificationsHelper
+
+ def notification_group_users(group)
+ [].tap do |parts|
+ parts << link_to(group.first.user.login, group.first.user, class: 'info_title')
+ rest = group.users_count - 1
+ parts << t('notification.group.also_users', count: rest) if rest > 0
+ end.join(' ').html_safe
+ end
+
+ def notification_group_actions(group)
+ [].tap do |parts|
+ group.collect_msg_keys.each do |action, count|
+ parts << t("notification.group.#{group.field}.#{action}", count: count)
+ end
+ end.join(', ').html_safe
+ end
+
+ def notification_partial(notification)
+ partial = (notification.subject_type == 'Comment') ? 'comment' : 'default'
+ render "notifications/record/#{partial}", notification: notification
+ end
+
+end
\ No newline at end of file
diff --git a/app/models/notification.rb b/app/models/notification.rb
index 6b84277..df45ac8 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -14,10 +14,26 @@ class Notification < ActiveRecord::Base
def group_param(key)
case key
- when :subject then "#{subject_type}_#{subject_id}"
- when :user then user_id
- when :target then target_id ? "#{target_type}_#{target_id}" :fun_id
+ when :user then "#{user_id}_#{subject_type}_#{target_type}"
+ when :target then group_target_key
else nil
end
end
+
+ def group_target_key
+ sub = target_id ? "#{target_type}_#{target_id}" : fun_id
+ "#{subject_type}_#{sub}"
+ end
+
+ def msg_key(prefix = true)
+ [].tap do |parts|
+ parts.push(:notification) if prefix
+ parts << normalize_key(subject_type)
+ parts << (target_id ? normalize_key(target_type) : :fun)
+ end.join('.')
+ end
+
+ def normalize_key(key)
+ key.downcase.gsub(/[^a-z]/, '')
+ end
end
diff --git a/app/models/notification/group.rb b/app/models/notification/group.rb
index dea717d..e8ed737 100644
--- a/app/models/notification/group.rb
+++ b/app/models/notification/group.rb
@@ -1,8 +1,9 @@
class Notification::Group
attr_accessor :notifications, :time, :field, :value
- PERIOD = 30
- FIELDS = [:subject, :user, :target]
+ PERIOD = 10
+ FIELDS = [:target, :user]
+ WEIGHTS = {target: 2}
def initialize(time, field, value, notifications = [])
@time = time - PERIOD.minutes
@@ -18,4 +19,20 @@ def accept?(notification)
def first
notifications.first
end
+
+ def weight
+ notifications.length * (WEIGHTS[field] || 1)
+ end
+
+ def collect_msg_keys
+ Hash.new(0).tap do |hash|
+ notifications.each do |notification|
+ hash[notification.msg_key(false)] += 1
+ end
+ end
+ end
+
+ def users_count
+ notifications.collect(&:user_id).uniq.length
+ end
end
\ No newline at end of file
diff --git a/app/models/notification/list.rb b/app/models/notification/list.rb
index 822b355..31581aa 100644
--- a/app/models/notification/list.rb
+++ b/app/models/notification/list.rb
@@ -11,6 +11,7 @@ def initialize(notifications)
end
end
+ remove_illogical
clear_repeats
end
@@ -32,7 +33,7 @@ def each
def clear_repeats
used = {}
weights = []
- @groups.each_with_index{ |g, i| weights << [i, g.notifications.length] }
+ @groups.each_with_index{ |g, i| weights << [i, g.weight] }
weights.sort{ |a, b| b[1] <=> a[1] }.each do |w|
@groups[w[0]].notifications.delete_if do |notification|
used[notification.id].tap { used[notification.id] = true }
@@ -40,4 +41,8 @@ def clear_repeats
end
@groups.delete_if{ |group| group.notifications.empty? }
end
+
+ def remove_illogical
+ @groups.delete_if{ |group| group.field == :target && group.users_count < 2 }
+ end
end
\ No newline at end of file
diff --git a/app/views/notifications/_group.html.slim b/app/views/notifications/_group.html.slim
index d1b68e7..1c7b45f 100644
--- a/app/views/notifications/_group.html.slim
+++ b/app/views/notifications/_group.html.slim
@@ -6,10 +6,11 @@
.arrow
.info_body
- | #{group.field} #{group.value}
+ = notification_group_users(group)
.info_muted
= time_ago_format group.first.created_at
- .info_content= group.notifications.length
+ .info_content
+ = notification_group_actions(group)
.clearfix
.group_details.hidden.hidden_mark
- group.notifications.each_with_index do |notification, index|
diff --git a/app/views/notifications/_record.html.slim b/app/views/notifications/_record.html.slim
index 0fa3258..6a4eb86 100644
--- a/app/views/notifications/_record.html.slim
+++ b/app/views/notifications/_record.html.slim
@@ -5,11 +5,5 @@
.arrow
.info_body
- = link_to notification.user.login, notification.user, class: 'info_title'
- .info_muted
- = time_ago_format notification.created_at
-
- .info_content
- ' #{notification.action} #{notification.subject.class.name}
- = link_to notification.target.class.name, notification.target if notification.target
+ = notification_partial(notification)
.clearfix
\ No newline at end of file
diff --git a/app/views/notifications/record/_comment.html.slim b/app/views/notifications/record/_comment.html.slim
new file mode 100644
index 0000000..d784ed3
--- /dev/null
+++ b/app/views/notifications/record/_comment.html.slim
@@ -0,0 +1,9 @@
+= link_to notification.user.login, notification.user
+.info_muted
+ = time_ago_format notification.created_at
+ '
+ = t(notification.msg_key)
+ '
+ = link_to(notification.fun.content.title ? notification.fun.content.title : 'фану', notification.fun)
+.info_content
+ = notification.subject.body
\ No newline at end of file
diff --git a/app/views/notifications/record/_default.html.slim b/app/views/notifications/record/_default.html.slim
new file mode 100644
index 0000000..41ac809
--- /dev/null
+++ b/app/views/notifications/record/_default.html.slim
@@ -0,0 +1,8 @@
+= link_to notification.user.login, notification.user
+.info_muted
+ = time_ago_format notification.created_at
+
+.info_content
+ = t(notification.msg_key)
+ '
+ = link_to(notification.fun.content.title.empty? ? 'фан' : notification.fun.content.title , notification.fun)
\ No newline at end of file
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 0e0ac29..bd69a42 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -211,4 +211,42 @@ ru:
button:
new: Добавить комментарий
create: Сохранить комментарий
- answer: Ответить
\ No newline at end of file
+ answer: Ответить
+ notification:
+ group:
+ also_users:
+ zero:
+ one: и еще %{count} пользователь
+ few: и еще %{count} пользователя
+ other: и еще %{count} пользователей
+ user:
+ actsasvotablevote:
+ fun:
+ one: оценил Ваш фан
+ few: оценил %{count} Ваших фана
+ other: оценил %{count} Ваших фанов
+ comment:
+ one: оценил Ваш комментарий
+ few: оценил %{count} Ваш комментария
+ other: оценил %{count} Ваш комментариев
+ comment:
+ fun:
+ one: откомментировал Ваш фан
+ few: добавил %{count} комментария к Вашим фанам
+ other: добавил %{count} комментариев к Вашим фанам
+ comment:
+ one: ответил на Ваш коментарий
+ few: оставил %{count} ответа к Вашим комментариям
+ other: оставил %{count} ответов к Вашим комментариям
+ target:
+ comment:
+ fun: откомментировали Ваш фан
+ actsasvotablevote:
+ fun: оценили Ваш фан
+
+ actsasvotablevote:
+ fun: понравился
+ comment: понравился комментарий к
+ comment:
+ comment: в ответах на комментарий к
+ fun: в комментариях к
\ No newline at end of file
From bee2df8266c1c6f880b87fba53b18da507115e80 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 25 Apr 2014 16:18:54 +0300
Subject: [PATCH 57/64] notification list (small photos)
---
app/assets/stylesheets/funs.css.scss | 5 +++++
app/views/notifications/_group.html.slim | 3 +--
app/views/notifications/_record.html.slim | 3 +--
app/views/notifications/record/_comment.html.slim | 3 ++-
app/views/notifications/record/_default.html.slim | 3 ++-
config/locales/ru.yml | 2 +-
6 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/app/assets/stylesheets/funs.css.scss b/app/assets/stylesheets/funs.css.scss
index 1aab827..677d643 100644
--- a/app/assets/stylesheets/funs.css.scss
+++ b/app/assets/stylesheets/funs.css.scss
@@ -2460,6 +2460,11 @@ and (orientation:landscape) {
.info_element{
margin-top: 0;
padding-bottom: 15px;
+ .info_body{
+ margin-left: 50px;
+ margin-right: 40px;
+ }
+ .info_content{ margin-top: 5px}
}
.click_handler:hover{
cursor: pointer;
diff --git a/app/views/notifications/_group.html.slim b/app/views/notifications/_group.html.slim
index 1c7b45f..9085c2c 100644
--- a/app/views/notifications/_group.html.slim
+++ b/app/views/notifications/_group.html.slim
@@ -1,9 +1,8 @@
.notification_group
.info_element.click_handler.hidden_mark
.arrow_expand
- .photo_frame.pull-left
+ .photo_frame.pull-left.photo_frame_sm
= link_to show_avatar(group.first.user), group.first.user, class: 'photo_box'
- .arrow
.info_body
= notification_group_users(group)
diff --git a/app/views/notifications/_record.html.slim b/app/views/notifications/_record.html.slim
index 6a4eb86..ee2ae04 100644
--- a/app/views/notifications/_record.html.slim
+++ b/app/views/notifications/_record.html.slim
@@ -1,8 +1,7 @@
.info_element class="#{(defined? add_class) ? add_class : ''}"
.arrow_expand.expanded
- .photo_frame.pull-left
+ .photo_frame.pull-left.photo_frame_sm
= link_to show_avatar(notification.user), notification.user, class: 'photo_box'
- .arrow
.info_body
= notification_partial(notification)
diff --git a/app/views/notifications/record/_comment.html.slim b/app/views/notifications/record/_comment.html.slim
index d784ed3..d17adde 100644
--- a/app/views/notifications/record/_comment.html.slim
+++ b/app/views/notifications/record/_comment.html.slim
@@ -1,5 +1,6 @@
= link_to notification.user.login, notification.user
-.info_muted
+'
+span.info_muted
= time_ago_format notification.created_at
'
= t(notification.msg_key)
diff --git a/app/views/notifications/record/_default.html.slim b/app/views/notifications/record/_default.html.slim
index 41ac809..de69551 100644
--- a/app/views/notifications/record/_default.html.slim
+++ b/app/views/notifications/record/_default.html.slim
@@ -1,5 +1,6 @@
= link_to notification.user.login, notification.user
-.info_muted
+'
+span.info_muted
= time_ago_format notification.created_at
.info_content
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index bd69a42..2036508 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -228,7 +228,7 @@ ru:
comment:
one: оценил Ваш комментарий
few: оценил %{count} Ваш комментария
- other: оценил %{count} Ваш комментариев
+ other: оценил %{count} Ваших комментариев
comment:
fun:
one: откомментировал Ваш фан
From 16fd0f85a8c11c630b29d46d7e97850fa7eba18b Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Fri, 25 Apr 2014 18:05:51 +0300
Subject: [PATCH 58/64] notification list (fix)
---
app/assets/stylesheets/funs.css.scss | 8 ++++----
app/helpers/notifications_helper.rb | 18 +++++++++++++++++-
app/views/comments/_comment.html.slim | 2 +-
app/views/notifications/_group.html.slim | 3 +++
.../notifications/record/_comment.html.slim | 4 ++--
.../notifications/record/_default.html.slim | 4 ++--
config/locales/ru.yml | 7 +++++--
lib/acts_as_votable/vote.rb | 2 +-
8 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/app/assets/stylesheets/funs.css.scss b/app/assets/stylesheets/funs.css.scss
index 677d643..b706bfc 100644
--- a/app/assets/stylesheets/funs.css.scss
+++ b/app/assets/stylesheets/funs.css.scss
@@ -2397,10 +2397,10 @@ and (orientation:landscape) {
&:hover {
> .btn-close-sm { display: block}
}
- a{
- color: #6d6b93;
- &:hover{ text-decoration: underline; }
- }
+ }
+ .info_link{
+ color: #6d6b93;
+ &:hover{ text-decoration: underline; }
}
.info_list{
margin-left: -60px;
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index c5ad044..4d4e8f3 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -2,7 +2,7 @@ module NotificationsHelper
def notification_group_users(group)
[].tap do |parts|
- parts << link_to(group.first.user.login, group.first.user, class: 'info_title')
+ parts << link_to(group.first.user.login, group.first.user, class: 'info_link')
rest = group.users_count - 1
parts << t('notification.group.also_users', count: rest) if rest > 0
end.join(' ').html_safe
@@ -21,4 +21,20 @@ def notification_partial(notification)
render "notifications/record/#{partial}", notification: notification
end
+ def notification_fun_link(notification, prefix = false)
+
+ unless prefix
+ prefix = 'funs.forms.w1'
+ if [notification.subject_type, notification.target_type].include? 'Comment'
+ prefix = 'funs.forms.w2'
+ end
+ end
+
+ if notification.fun.content.title.empty?
+ link_to(t(prefix), notification.fun, class: 'info_link')
+ else
+ "#{t(prefix)} #{link_to(notification.fun.content.title, notification.fun, class: 'info_link')}".html_safe
+ end
+ end
+
end
\ No newline at end of file
diff --git a/app/views/comments/_comment.html.slim b/app/views/comments/_comment.html.slim
index ea3752f..da3bbb1 100644
--- a/app/views/comments/_comment.html.slim
+++ b/app/views/comments/_comment.html.slim
@@ -12,7 +12,7 @@
span.vote_result= comment.cached_votes_score
= vote_link :minus, vote_comment_path(comment, :dislike), current_user.voted?(comment) === false
- = link_to comment.user.login, comment.user, class: 'info_title'
+ = link_to comment.user.login, comment.user, class: 'info_link'
.info_muted
' добавил
= time_ago_format comment.created_at
diff --git a/app/views/notifications/_group.html.slim b/app/views/notifications/_group.html.slim
index 9085c2c..8d6700b 100644
--- a/app/views/notifications/_group.html.slim
+++ b/app/views/notifications/_group.html.slim
@@ -10,6 +10,9 @@
= time_ago_format group.first.created_at
.info_content
= notification_group_actions(group)
+ - if group.field == :target
+ '
+ = notification_fun_link(group.first)
.clearfix
.group_details.hidden.hidden_mark
- group.notifications.each_with_index do |notification, index|
diff --git a/app/views/notifications/record/_comment.html.slim b/app/views/notifications/record/_comment.html.slim
index d17adde..4162904 100644
--- a/app/views/notifications/record/_comment.html.slim
+++ b/app/views/notifications/record/_comment.html.slim
@@ -1,10 +1,10 @@
-= link_to notification.user.login, notification.user
+= link_to notification.user.login, notification.user, class: 'info_link'
'
span.info_muted
= time_ago_format notification.created_at
'
= t(notification.msg_key)
'
- = link_to(notification.fun.content.title ? notification.fun.content.title : 'фану', notification.fun)
+ = notification_fun_link(notification)
.info_content
= notification.subject.body
\ No newline at end of file
diff --git a/app/views/notifications/record/_default.html.slim b/app/views/notifications/record/_default.html.slim
index de69551..235b9b7 100644
--- a/app/views/notifications/record/_default.html.slim
+++ b/app/views/notifications/record/_default.html.slim
@@ -1,4 +1,4 @@
-= link_to notification.user.login, notification.user
+= link_to notification.user.login, notification.user, class: 'info_link'
'
span.info_muted
= time_ago_format notification.created_at
@@ -6,4 +6,4 @@ span.info_muted
.info_content
= t(notification.msg_key)
'
- = link_to(notification.fun.content.title.empty? ? 'фан' : notification.fun.content.title , notification.fun)
\ No newline at end of file
+ = notification_fun_link(notification)
\ No newline at end of file
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 2036508..7ac487e 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -75,6 +75,9 @@ ru:
social_likes: "Проголосовать в соц сетях"
edit: "Редактировать фан"
update_error: "Произошла ошибка при сохранении фана :( Проверьте данные и повторите попытку"
+ forms:
+ w1: фан
+ w2: фанy
reposts:
created: "Фан успешно скопирован вам на стену."
button: "Репостить"
@@ -240,9 +243,9 @@ ru:
other: оставил %{count} ответов к Вашим комментариям
target:
comment:
- fun: откомментировали Ваш фан
+ fun: откомментировали
actsasvotablevote:
- fun: оценили Ваш фан
+ fun: оценили
actsasvotablevote:
fun: понравился
diff --git a/lib/acts_as_votable/vote.rb b/lib/acts_as_votable/vote.rb
index bd7f6b7..590a250 100644
--- a/lib/acts_as_votable/vote.rb
+++ b/lib/acts_as_votable/vote.rb
@@ -11,7 +11,7 @@ def create_notification
data = { user_id: voter_id, action: :create, receiver_id: votable.user_id }
data[:fun] = votable.notification_fun if votable.respond_to? :notification_fun
- data[:target] = votable unless data[:fun] || data[:fun] == votable
+ data[:target] = votable unless data[:fun] && data[:fun] == votable
notifications.create(data)
end
From dc7722c4f54624a424ba2d98eccad32e01730c26 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 28 Apr 2014 10:10:40 +0300
Subject: [PATCH 59/64] fix condition in fun_image_path
---
app/helpers/funs_helper.rb | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/helpers/funs_helper.rb b/app/helpers/funs_helper.rb
index 6aef9ff..6bb262c 100644
--- a/app/helpers/funs_helper.rb
+++ b/app/helpers/funs_helper.rb
@@ -166,10 +166,10 @@ def report_fun_link(fun)
def fun_image_path(fun, versions = {})
type = fun.content.class.to_s
column = type == 'Image' ? :file : :image # fun.content.class.uploaders
- unless type == 'Post'
- fun.content.try(column).url(*versions)
- else
+ if type == 'Post'
asset_path('social_logo.png')
+ else
+ fun.content.try(column).url(*versions)
end
end
From ea5d61bf3d50d919d8cc274da9ab4b62f566c4d0 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 28 Apr 2014 10:41:08 +0300
Subject: [PATCH 60/64] notification fun preview
---
app/assets/stylesheets/funs.css.scss | 14 ++++++++++++--
app/helpers/notifications_helper.rb | 6 ++++++
app/views/notifications/_record.html.slim | 2 ++
3 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/app/assets/stylesheets/funs.css.scss b/app/assets/stylesheets/funs.css.scss
index b706bfc..1a2d201 100644
--- a/app/assets/stylesheets/funs.css.scss
+++ b/app/assets/stylesheets/funs.css.scss
@@ -2383,7 +2383,10 @@ and (orientation:landscape) {
padding: 15px 0 0 10px;
margin-top: 15px;
position: relative;
- .info_body{ margin-left: 90px; }
+ .info_body{
+ margin-left: 90px;
+ word-wrap: break-word;
+ }
.info_muted{ margin-top: 5px; }
.info_content{ margin-top: 15px; }
.info_action{ display: inline-block; margin-top: 7px; }
@@ -2464,7 +2467,14 @@ and (orientation:landscape) {
margin-left: 50px;
margin-right: 40px;
}
- .info_content{ margin-top: 5px}
+ .info_content{ margin-top: 5px }
+ .preview{
+ float: right;
+ width: 50px;
+ max-height: 50px;
+ overflow: hidden;
+ img{ width: 100%; }
+ }
}
.click_handler:hover{
cursor: pointer;
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index 4d4e8f3..65e0eb2 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -37,4 +37,10 @@ def notification_fun_link(notification, prefix = false)
end
end
+ def notification_fun_preview(notification)
+ unless notification.fun.content_type == 'Post'
+ link_to fun_image(notification.fun, version: :small), notification.fun, class: 'preview'
+ end
+ end
+
end
\ No newline at end of file
diff --git a/app/views/notifications/_record.html.slim b/app/views/notifications/_record.html.slim
index ee2ae04..3a6e7ff 100644
--- a/app/views/notifications/_record.html.slim
+++ b/app/views/notifications/_record.html.slim
@@ -4,5 +4,7 @@
= link_to show_avatar(notification.user), notification.user, class: 'photo_box'
.info_body
+ = notification_fun_preview(notification)
+
= notification_partial(notification)
.clearfix
\ No newline at end of file
From 654baa532c1c3537de45776441f626a26ffcf499 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 28 Apr 2014 15:28:25 +0300
Subject: [PATCH 61/64] notification endless
---
app/assets/javascripts/notification.js.coffee | 35 +++++++++++++++++--
app/controllers/notifications_controller.rb | 10 +++---
app/models/notification.rb | 2 ++
app/models/user.rb | 12 +++++++
app/views/notifications/_list.html.slim | 8 +++++
app/views/notifications/index.html.slim | 6 +---
app/views/notifications/index.js.slim | 1 +
7 files changed, 62 insertions(+), 12 deletions(-)
create mode 100644 app/views/notifications/_list.html.slim
create mode 100644 app/views/notifications/index.js.slim
diff --git a/app/assets/javascripts/notification.js.coffee b/app/assets/javascripts/notification.js.coffee
index 35a8ff2..d193dab 100644
--- a/app/assets/javascripts/notification.js.coffee
+++ b/app/assets/javascripts/notification.js.coffee
@@ -1,10 +1,41 @@
$ ->
marker = '.hidden_mark'
- $('.notification_list').on 'click', '.click_handler', (e) ->
+ $list = $('.notification_list').on 'click', '.click_handler', (e) ->
e.preventDefault
$this = $ this
$marker = $this.closest(marker)
$group = $this.closest('.notification_group')
$marker.addClass('hidden')
- $group.find('.hidden').not($marker).removeClass('hidden')
\ No newline at end of file
+ $group.find('.hidden').not($marker).removeClass('hidden')
+
+ if ($list.length)
+ $(window).endlessScroll
+ fireOnce: true,
+ fireDelay: false,
+ intervalFrequency: 250,
+ inflowPixels: 200,
+ loader: '',
+ ceaseFireOnEmpty: false,
+ callback: () ->
+ window.endlessScrolllLoading = true;
+ url = $('input[name=next]').last().val()
+
+ return false unless url
+
+ $('').insertAfter($list)
+ $.ajax
+ cache: false
+ url: url
+ complete: (data) ->
+ return true unless (data.status == 200)
+
+ $(window).data('endelessscroll').stopFiring() unless data.responseText.length
+ window.endlessScrolllLoading = false
+ $elements = $(data.responseText)
+
+ $elements.initButtonTooltips()
+ $elements.initTooltips()
+ $elements.findAndFormatDateTime()
+ $list.append($elements)
+ $('#loading').remove()
\ No newline at end of file
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
index 9e53f1e..633aa22 100644
--- a/app/controllers/notifications_controller.rb
+++ b/app/controllers/notifications_controller.rb
@@ -1,12 +1,12 @@
class NotificationsController < ApplicationController
authorize_resource
- def index
- @notifications = Fun.unscoped do
- Notification.includes({ fun: :content } , :user, :target, :subject)
- .where(receiver_id: current_user.id).order('created_at DESC').all
- end
+ respond_to :html, :js
+ def index
+ @notifications = current_user.notifications_before(params[:date])
@list = Notification::List.new(@notifications)
+
+ respond_with(@notifications, @list)
end
end
diff --git a/app/models/notification.rb b/app/models/notification.rb
index df45ac8..2c82481 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -12,6 +12,8 @@ class Notification < ActiveRecord::Base
validates_presence_of :user_id
validates_presence_of :action
+ scope :limited, limit(30)
+
def group_param(key)
case key
when :user then "#{user_id}_#{subject_type}_#{target_type}"
diff --git a/app/models/user.rb b/app/models/user.rb
index f502cf4..a7fd734 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -47,6 +47,8 @@ def funs_with_reposts
# Authorization services (FB, VK, TW)
has_many :identities
+ has_many :notifications, foreign_key: :receiver_id
+
# Validation rules
validates :email, uniqueness: true, format: { with: email_regexp }, if: :email_required?
@@ -220,6 +222,16 @@ def send_welcome_email
UserMailer.welcome_email(self).deliver if email.present?
end
+ def notifications_before(date = null)
+ Fun.unscoped do
+ query = notifications.includes({ fun: :content }, :user, :target, :subject)
+
+ query = query.where('created_at < ?', date) if date
+
+ query.order('created_at DESC').limited.all
+ end
+ end
+
class << self
def sort_column(column)
diff --git a/app/views/notifications/_list.html.slim b/app/views/notifications/_list.html.slim
new file mode 100644
index 0000000..df5ce0e
--- /dev/null
+++ b/app/views/notifications/_list.html.slim
@@ -0,0 +1,8 @@
+- list.each do |group|
+ - if group.notifications.length > 1
+ = render 'notifications/group', group: group
+ - else
+ = render 'notifications/record', notification: group.first
+
+- unless notifications.length.zero?
+ input type='hidden' name='next' value=url_for(format: :js, date: notifications.last.created_at)
\ No newline at end of file
diff --git a/app/views/notifications/index.html.slim b/app/views/notifications/index.html.slim
index e143ec6..eab3b93 100644
--- a/app/views/notifications/index.html.slim
+++ b/app/views/notifications/index.html.slim
@@ -4,8 +4,4 @@
.info_list_title
' Notifications list
- - @list.each do |group|
- - if group.notifications.length > 1
- = render 'notifications/group', group: group
- - else
- = render 'notifications/record', notification: group.first
\ No newline at end of file
+ = render 'list', list: @list, notifications: @notifications
\ No newline at end of file
diff --git a/app/views/notifications/index.js.slim b/app/views/notifications/index.js.slim
new file mode 100644
index 0000000..af38283
--- /dev/null
+++ b/app/views/notifications/index.js.slim
@@ -0,0 +1 @@
+= render 'list', list: @list, notifications: @notifications
\ No newline at end of file
From 33a59a3cab67379d8c3f5e84b6f1f8d1ed090a46 Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 28 Apr 2014 15:33:53 +0300
Subject: [PATCH 62/64] notification link in dropdown
---
app/views/layouts/_header.html.slim | 1 +
1 file changed, 1 insertion(+)
diff --git a/app/views/layouts/_header.html.slim b/app/views/layouts/_header.html.slim
index 8d9bbcf..299b1cc 100644
--- a/app/views/layouts/_header.html.slim
+++ b/app/views/layouts/_header.html.slim
@@ -28,6 +28,7 @@ header.main_panel[role="banner"]
ul.top
li = link_to 'Моя страница', user_path(current_user)
li = link_to 'Мои подписки', feed_path
+ li = link_to 'Мои уведомления', notifications_path
- if can? :read, Report
li = link_to "Жалобы (#{Report.count})", reports_path
ul.down
From 42667109748cd7a3f42cae78f2198adcfdbc10fe Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 28 Apr 2014 15:38:33 +0300
Subject: [PATCH 63/64] notification index title i18n
---
app/views/notifications/index.html.slim | 4 ++--
config/locales/ru.yml | 4 +++-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/app/views/notifications/index.html.slim b/app/views/notifications/index.html.slim
index eab3b93..86e9c9e 100644
--- a/app/views/notifications/index.html.slim
+++ b/app/views/notifications/index.html.slim
@@ -1,7 +1,7 @@
.container.rating_layout
.rating_layout
.info_list.notification_list
- .info_list_title
- ' Notifications list
+ .info_list_title= t 'notification.title.index'
+
= render 'list', list: @list, notifications: @notifications
\ No newline at end of file
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 7ac487e..6244705 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -252,4 +252,6 @@ ru:
comment: понравился комментарий к
comment:
comment: в ответах на комментарий к
- fun: в комментариях к
\ No newline at end of file
+ fun: в комментариях к
+ title:
+ index: Мои уведомления
\ No newline at end of file
From 6270255728bc2e5d92fad792958304ab32e79eff Mon Sep 17 00:00:00 2001
From: Blaze34 <30avenyamadeo@gmail.com>
Date: Mon, 28 Apr 2014 16:16:16 +0300
Subject: [PATCH 64/64] fix scripts
---
app/assets/javascripts/funs/wall.js | 5 ++---
app/assets/javascripts/users/wall.js | 17 ++++++++++-------
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/app/assets/javascripts/funs/wall.js b/app/assets/javascripts/funs/wall.js
index 7d45b0c..e450d80 100644
--- a/app/assets/javascripts/funs/wall.js
+++ b/app/assets/javascripts/funs/wall.js
@@ -100,8 +100,7 @@ $(function(){
url: url,
dataType: 'script',
complete: function(data) {
- if (data.status == 200)
- {
+ if (data.status == 200){
$('#next_url').data('url', url.replace('page=' + (i + 1), 'page=' + (i + 2)));
if (data.responseText.length == 0) $(window).data('endelessscroll').stopFiring();
@@ -114,8 +113,8 @@ $(function(){
$newElems.findAndFormatDateTime();
if ($wall.data('masonry')) $wall.masonry( 'appended', $newElems, true );
$wall.append($newElems);
+ $('#loading').remove();
});
- $('#loading').remove();
}
}
});
diff --git a/app/assets/javascripts/users/wall.js b/app/assets/javascripts/users/wall.js
index c8598a6..121dc88 100644
--- a/app/assets/javascripts/users/wall.js
+++ b/app/assets/javascripts/users/wall.js
@@ -24,8 +24,7 @@ $(function(){
data: { view: currentState },
dataType: 'script',
complete: function(data) {
- if (data.status == 200)
- {
+ if (data.status == 200){
var wall = $('.post_wall');
wall.html(data.responseText);
@@ -36,8 +35,10 @@ $(function(){
if (currentState == 'box'){
layout.addClass('grid');
- if (wall.data('masonry')) wall.masonry('reload');
- else wall.masonry({ itemSelector : '.post_card', gutterWidth: 20 })
+ wall.imagesLoaded(function(){
+ if (wall.data('masonry')) wall.masonry('reload');
+ else wall.masonry({ itemSelector : '.post_card', gutterWidth: 20 })
+ });
}
else{
if (wall.data('masonry')) wall.masonry('destroy');
@@ -60,8 +61,7 @@ $(function(){
url: url,
dataType: 'script',
complete: function(data) {
- if (data.status == 200)
- {
+ if (data.status == 200){
var wall = $('.post_wall');
wall.html(data.responseText);
wall.initButtonTooltips();
@@ -69,7 +69,10 @@ $(function(){
wall.findAndFormatDateTime();
$(window).data('endelessscroll').resetFiring();
if (currentState == 'box'){
- if (wall.data('masonry')) wall.masonry('reload');
+ wall.imagesLoaded(function(){
+ if (wall.data('masonry')) wall.masonry('reload');
+ else wall.masonry({ itemSelector : '.post_card', gutterWidth: 20 })
+ });
}
}
$('#ajax_loading').remove();