mirror of
https://github.com/Retrospring/retrospring.git
synced 2025-03-16 00:20:00 +01:00
Merge branch 'master' into privacy
This commit is contained in:
commit
fd4e66bb75
34 changed files with 372 additions and 100 deletions
1
Gemfile
1
Gemfile
|
@ -20,6 +20,7 @@ gem 'bcrypt', '~> 3.1.7'
|
||||||
gem 'haml'
|
gem 'haml'
|
||||||
gem 'bootstrap-sass', '~> 3.2.0.1'
|
gem 'bootstrap-sass', '~> 3.2.0.1'
|
||||||
gem 'bootswatch-rails'
|
gem 'bootswatch-rails'
|
||||||
|
gem 'sweetalert-rails'
|
||||||
gem 'will_paginate'
|
gem 'will_paginate'
|
||||||
gem 'will_paginate-bootstrap'
|
gem 'will_paginate-bootstrap'
|
||||||
gem 'http_accept_language'
|
gem 'http_accept_language'
|
||||||
|
|
|
@ -298,6 +298,8 @@ GEM
|
||||||
colorize (>= 0.7.0)
|
colorize (>= 0.7.0)
|
||||||
net-scp (>= 1.1.2)
|
net-scp (>= 1.1.2)
|
||||||
net-ssh (>= 2.8.0)
|
net-ssh (>= 2.8.0)
|
||||||
|
sweetalert-rails (0.3.3)
|
||||||
|
railties (>= 3.1.0)
|
||||||
thin (1.6.3)
|
thin (1.6.3)
|
||||||
daemons (~> 1.0, >= 1.0.9)
|
daemons (~> 1.0, >= 1.0.9)
|
||||||
eventmachine (~> 1.0)
|
eventmachine (~> 1.0)
|
||||||
|
@ -387,6 +389,7 @@ DEPENDENCIES
|
||||||
simplecov
|
simplecov
|
||||||
sinatra
|
sinatra
|
||||||
spring
|
spring
|
||||||
|
sweetalert-rails
|
||||||
thin
|
thin
|
||||||
turbolinks
|
turbolinks
|
||||||
twitter
|
twitter
|
||||||
|
|
20
Rakefile
20
Rakefile
|
@ -93,6 +93,26 @@ namespace :justask do
|
||||||
puts "#{user.screen_name} no longer an moderator."
|
puts "#{user.screen_name} no longer an moderator."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc "Gives supporter status to an user."
|
||||||
|
task :sup, [:screen_name] => :environment do |t, args|
|
||||||
|
fail "screen name required" if args[:screen_name].nil?
|
||||||
|
user = User.find_by_screen_name(args[:screen_name])
|
||||||
|
fail "user #{args[:screen_name]} not found" if user.nil?
|
||||||
|
user.supporter = true
|
||||||
|
user.save!
|
||||||
|
puts "#{user.screen_name} is now an moderator."
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Removes supporter status from an user."
|
||||||
|
task :desup, [:screen_name] => :environment do |t, args|
|
||||||
|
fail "screen name required" if args[:screen_name].nil?
|
||||||
|
user = User.find_by_screen_name(args[:screen_name])
|
||||||
|
fail "user #{args[:screen_name]} not found" if user.nil?
|
||||||
|
user.supporter = false
|
||||||
|
user.save!
|
||||||
|
puts "#{user.screen_name} no longer an moderator."
|
||||||
|
end
|
||||||
|
|
||||||
desc "Lists all users."
|
desc "Lists all users."
|
||||||
task lusers: :environment do
|
task lusers: :environment do
|
||||||
User.all.each do |u|
|
User.all.each do |u|
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
$(document).on "click", "a[data-action=ab-comment-destroy]", (ev) ->
|
$(document).on "click", "a[data-action=ab-comment-destroy]", (ev) ->
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
if confirm 'Are you sure?'
|
btn = $(this)
|
||||||
btn = $(this)
|
cid = btn[0].dataset.cId
|
||||||
cid = btn[0].dataset.cId
|
swal
|
||||||
|
title: "Really delete?"
|
||||||
|
text: "You will not be able to recover this comment."
|
||||||
|
type: "warning"
|
||||||
|
showCancelButton: true
|
||||||
|
confirmButtonColor: "#DD6B55"
|
||||||
|
confirmButtonText: "Delete"
|
||||||
|
closeOnConfirm: true
|
||||||
|
, ->
|
||||||
$.ajax
|
$.ajax
|
||||||
url: '/ajax/destroy_comment'
|
url: '/ajax/destroy_comment'
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
$(document).on "click", "a[data-action=ab-comment-report]", (ev) ->
|
$(document).on "click", "a[data-action=ab-comment-report]", (ev) ->
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
if confirm 'Are you sure you want to report this comment?'
|
btn = $(this)
|
||||||
btn = $(this)
|
cid = btn[0].dataset.cId
|
||||||
cid = btn[0].dataset.cId
|
swal
|
||||||
|
title: "Really report?"
|
||||||
|
text: "A moderator will review this comment and decide what happens."
|
||||||
|
type: "warning"
|
||||||
|
showCancelButton: true
|
||||||
|
confirmButtonColor: "#DD6B55"
|
||||||
|
confirmButtonText: "Report"
|
||||||
|
closeOnConfirm: true
|
||||||
|
, ->
|
||||||
$.ajax
|
$.ajax
|
||||||
url: '/ajax/report'
|
url: '/ajax/report'
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
$(document).on "click", "a[data-action=ab-destroy]", (ev) ->
|
$(document).on "click", "a[data-action=ab-destroy]", (ev) ->
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
if confirm 'Are you sure?'
|
btn = $(this)
|
||||||
btn = $(this)
|
aid = btn[0].dataset.aId
|
||||||
aid = btn[0].dataset.aId
|
swal
|
||||||
|
title: "Really delete?"
|
||||||
|
text: "The question will be moved back to your inbox."
|
||||||
|
type: "warning"
|
||||||
|
showCancelButton: true
|
||||||
|
confirmButtonColor: "#DD6B55"
|
||||||
|
confirmButtonText: "Delete"
|
||||||
|
closeOnConfirm: true
|
||||||
|
, ->
|
||||||
$.ajax
|
$.ajax
|
||||||
url: '/ajax/destroy_answer' # TODO: find a way to use rake routes instead of hardcoding them here
|
url: '/ajax/destroy_answer' # TODO: find a way to use rake routes instead of hardcoding them here
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
$(document).on "click", "a[data-action=ab-report]", (ev) ->
|
$(document).on "click", "a[data-action=ab-report]", (ev) ->
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
if confirm 'Are you sure you want to report this answer?'
|
btn = $(this)
|
||||||
btn = $(this)
|
aid = btn[0].dataset.aId
|
||||||
aid = btn[0].dataset.aId
|
swal
|
||||||
|
title: "Really report?"
|
||||||
|
text: "A moderator will review this answer and decide what happens."
|
||||||
|
type: "warning"
|
||||||
|
showCancelButton: true
|
||||||
|
confirmButtonColor: "#DD6B55"
|
||||||
|
confirmButtonText: "Report"
|
||||||
|
closeOnConfirm: true
|
||||||
|
, ->
|
||||||
$.ajax
|
$.ajax
|
||||||
url: '/ajax/report' # TODO: find a way to use rake routes instead of hardcoding them here
|
url: '/ajax/report' # TODO: find a way to use rake routes instead of hardcoding them here
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#= require growl
|
#= require growl
|
||||||
#= require cheet
|
#= require cheet
|
||||||
#= require jquery.guillotine
|
#= require jquery.guillotine
|
||||||
|
#= require sweet-alert
|
||||||
#= require_tree .
|
#= require_tree .
|
||||||
|
|
||||||
NProgress.configure
|
NProgress.configure
|
||||||
|
@ -24,3 +25,9 @@ window.showNotification = (text, success=true) ->
|
||||||
|
|
||||||
$(document).on "click", "button#create-account", ->
|
$(document).on "click", "button#create-account", ->
|
||||||
Turbolinks.visit "/sign_up"
|
Turbolinks.visit "/sign_up"
|
||||||
|
|
||||||
|
_ready = ->
|
||||||
|
sweetAlertInitialize()
|
||||||
|
|
||||||
|
$(document).ready _ready
|
||||||
|
$(document).on 'page:load', _ready
|
|
@ -22,7 +22,15 @@
|
||||||
($ document).on "click", "button#ib-delete-all", ->
|
($ document).on "click", "button#ib-delete-all", ->
|
||||||
btn = ($ this)
|
btn = ($ this)
|
||||||
count = btn[0].dataset.ibCount
|
count = btn[0].dataset.ibCount
|
||||||
if confirm "Really delete #{count} questions?"
|
swal
|
||||||
|
title: "Really delete #{count} questions?"
|
||||||
|
text: "They will be gone forever."
|
||||||
|
type: "warning"
|
||||||
|
showCancelButton: true
|
||||||
|
confirmButtonColor: "#DD6B55"
|
||||||
|
confirmButtonText: "Delete"
|
||||||
|
closeOnConfirm: true
|
||||||
|
, ->
|
||||||
btn.button "loading"
|
btn.button "loading"
|
||||||
succ = no
|
succ = no
|
||||||
$.ajax
|
$.ajax
|
||||||
|
@ -71,6 +79,7 @@ $(document).on "click", "button[name=ib-answer]", ->
|
||||||
id: iid
|
id: iid
|
||||||
answer: $("textarea[name=ib-answer][data-id=#{iid}]").val()
|
answer: $("textarea[name=ib-answer][data-id=#{iid}]").val()
|
||||||
share: JSON.stringify shareTo
|
share: JSON.stringify shareTo
|
||||||
|
inbox: true
|
||||||
success: (data, status, jqxhr) ->
|
success: (data, status, jqxhr) ->
|
||||||
if data.success
|
if data.success
|
||||||
$("div.inbox-box[data-id=#{iid}]").slideUp()
|
$("div.inbox-box[data-id=#{iid}]").slideUp()
|
||||||
|
@ -84,8 +93,16 @@ $(document).on "click", "button[name=ib-answer]", ->
|
||||||
|
|
||||||
|
|
||||||
$(document).on "click", "button[name=ib-destroy]", ->
|
$(document).on "click", "button[name=ib-destroy]", ->
|
||||||
if confirm 'Are you sure?'
|
btn = $(this)
|
||||||
btn = $(this)
|
swal
|
||||||
|
title: "Really delete?"
|
||||||
|
text: "This question will be gone forever."
|
||||||
|
type: "warning"
|
||||||
|
showCancelButton: true
|
||||||
|
confirmButtonColor: "#DD6B55"
|
||||||
|
confirmButtonText: "Delete"
|
||||||
|
closeOnConfirm: true
|
||||||
|
, ->
|
||||||
btn.button "loading"
|
btn.button "loading"
|
||||||
iid = btn[0].dataset.ibId
|
iid = btn[0].dataset.ibId
|
||||||
$("textarea[name=ib-answer][data-id=#{iid}]").attr "readonly", "readonly"
|
$("textarea[name=ib-answer][data-id=#{iid}]").attr "readonly", "readonly"
|
||||||
|
|
|
@ -68,9 +68,17 @@ $(document).on "input", "input[name=mod-comment-new]", (evt) ->
|
||||||
# destroy
|
# destroy
|
||||||
$(document).on "click", "a[data-action=mod-comment-destroy]", (ev) ->
|
$(document).on "click", "a[data-action=mod-comment-destroy]", (ev) ->
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
if confirm 'Are you sure?'
|
btn = $(this)
|
||||||
btn = $(this)
|
cid = btn[0].dataset.id
|
||||||
cid = btn[0].dataset.id
|
swal
|
||||||
|
title: "Really delete?"
|
||||||
|
text: "You will not be able to recover this comment."
|
||||||
|
type: "warning"
|
||||||
|
showCancelButton: true
|
||||||
|
confirmButtonColor: "#DD6B55"
|
||||||
|
confirmButtonText: "Delete"
|
||||||
|
closeOnConfirm: true
|
||||||
|
, ->
|
||||||
$.ajax
|
$.ajax
|
||||||
url: '/ajax/mod/destroy_comment'
|
url: '/ajax/mod/destroy_comment'
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
$(document).on "click", "button[name=mod-delete-report]", ->
|
$(document).on "click", "button[name=mod-delete-report]", ->
|
||||||
if confirm 'Are you sure?'
|
btn = $(this)
|
||||||
btn = $(this)
|
id = btn[0].dataset.id
|
||||||
id = btn[0].dataset.id
|
swal
|
||||||
|
title: "Really delete?"
|
||||||
|
text: "You will not be able to recover this report."
|
||||||
|
type: "warning"
|
||||||
|
showCancelButton: true
|
||||||
|
confirmButtonColor: "#DD6B55"
|
||||||
|
confirmButtonText: "Delete"
|
||||||
|
closeOnConfirm: true
|
||||||
|
, ->
|
||||||
$.ajax
|
$.ajax
|
||||||
url: '/ajax/mod/destroy_report'
|
url: '/ajax/mod/destroy_report'
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
|
|
37
app/assets/javascripts/question.coffee
Normal file
37
app/assets/javascripts/question.coffee
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
$(document).on "keydown", "textarea#q-answer", (evt) ->
|
||||||
|
qid = $(this)[0].dataset.id
|
||||||
|
if evt.keyCode == 13 and evt.ctrlKey
|
||||||
|
# trigger warning:
|
||||||
|
$("button#q-answer[data-q-id=#{qid}]").trigger 'click'
|
||||||
|
|
||||||
|
|
||||||
|
$(document).on "click", "button#q-answer", ->
|
||||||
|
btn = $(this)
|
||||||
|
btn.button "loading"
|
||||||
|
qid = btn[0].dataset.qId
|
||||||
|
$("textarea#q-answer[data-q=#{qid}]").attr "readonly", "readonly"
|
||||||
|
|
||||||
|
shareTo = []
|
||||||
|
($ "input[type=checkbox][name=share][data-q-id=#{qid}]:checked").each (i, share) ->
|
||||||
|
shareTo.push share.dataset.service
|
||||||
|
|
||||||
|
$.ajax
|
||||||
|
url: '/ajax/answer'
|
||||||
|
type: 'POST'
|
||||||
|
dataType: 'json'
|
||||||
|
data:
|
||||||
|
id: qid
|
||||||
|
answer: $("textarea#q-answer[data-id=#{qid}]").val()
|
||||||
|
share: JSON.stringify shareTo
|
||||||
|
inbox: false
|
||||||
|
success: (data, status, jqxhr) ->
|
||||||
|
if data.success
|
||||||
|
$("div#q-answer-box").slideUp()
|
||||||
|
($ "div#answers").prepend data.render
|
||||||
|
showNotification data.message, data.success
|
||||||
|
error: (jqxhr, status, error) ->
|
||||||
|
console.log jqxhr, status, error
|
||||||
|
showNotification "An error occurred, a developer should check the console for details", false
|
||||||
|
complete: (jqxhr, status) ->
|
||||||
|
btn.button "reset"
|
||||||
|
$("textarea#q-answer[data-id=#{qid}]").removeAttr "readonly"
|
|
@ -50,7 +50,16 @@ $(document).on "click", "a[data-action=report-user]", (ev) ->
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
btn = $(this)
|
btn = $(this)
|
||||||
target = btn[0].dataset.target
|
target = btn[0].dataset.target
|
||||||
if confirm "Are you sure you want to report #{target}?"
|
|
||||||
|
swal
|
||||||
|
title: "Really report #{target}?"
|
||||||
|
text: "A moderator will review this user and decide what happens."
|
||||||
|
type: "warning"
|
||||||
|
showCancelButton: true
|
||||||
|
confirmButtonColor: "#DD6B55"
|
||||||
|
confirmButtonText: "Report"
|
||||||
|
closeOnConfirm: true
|
||||||
|
, ->
|
||||||
$.ajax
|
$.ajax
|
||||||
url: '/ajax/report'
|
url: '/ajax/report'
|
||||||
type: 'POST'
|
type: 'POST'
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
*= require rails_bootstrap_forms
|
*= require rails_bootstrap_forms
|
||||||
*= require growl
|
*= require growl
|
||||||
*= require jquery.guillotine
|
*= require jquery.guillotine
|
||||||
|
*= require sweet-alert
|
||||||
*= require_self
|
*= require_self
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
body {
|
body {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
background-color: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "scss/answerbox";
|
@import "scss/answerbox";
|
||||||
|
@ -64,4 +65,12 @@ body {
|
||||||
|
|
||||||
.about--moderator li {
|
.about--moderator li {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.j2-up {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sweet-overlay {
|
||||||
|
z-index: 1031;
|
||||||
}
|
}
|
|
@ -6,13 +6,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile--displayname {
|
.profile--displayname {
|
||||||
margin-top: -2px;
|
font-weight: 700;
|
||||||
margin-bottom: 2px;
|
font-size: 1.2em;
|
||||||
|
margin-top: -0.165em;
|
||||||
|
line-height: 1.33em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile--username {
|
.profile--username {
|
||||||
margin-top: 0px;
|
font-size: 0.9em;
|
||||||
margin-bottom: 2px;
|
color: rgba(0, 0, 0, 0.4);
|
||||||
|
line-height: 1.33;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile--followtag {
|
||||||
|
margin: 0px 0px 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile--admin {
|
.profile--admin {
|
||||||
|
@ -23,6 +30,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile--moderator {
|
.profile--moderator {
|
||||||
|
color: $brand-success;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile--supporter {
|
||||||
color: $brand-warning;
|
color: $brand-warning;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -31,6 +45,8 @@
|
||||||
|
|
||||||
.profile--text {
|
.profile--text {
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
|
line-height: 1.5em;
|
||||||
|
margin-top: 0.65em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile--header {
|
.profile--header {
|
||||||
|
@ -69,4 +85,12 @@
|
||||||
|
|
||||||
.profile--follow-btn {
|
.profile--follow-btn {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile--avatar {
|
||||||
|
border-top-left-radius: 2px;
|
||||||
|
border-top-right-radius: 2px;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
border: medium none;
|
||||||
}
|
}
|
|
@ -1,4 +1,53 @@
|
||||||
class Ajax::AnswerController < ApplicationController
|
class Ajax::AnswerController < ApplicationController
|
||||||
|
def create
|
||||||
|
params.require :id
|
||||||
|
params.require :answer
|
||||||
|
params.require :share
|
||||||
|
params.require :inbox
|
||||||
|
|
||||||
|
inbox = (params[:inbox] == 'true')
|
||||||
|
|
||||||
|
if inbox
|
||||||
|
inbox_entry = Inbox.find(params[:id])
|
||||||
|
|
||||||
|
unless current_user == inbox_entry.user
|
||||||
|
@status = :fail
|
||||||
|
@message = "question not in your inbox"
|
||||||
|
@success = false
|
||||||
|
return
|
||||||
|
end
|
||||||
|
else
|
||||||
|
question = Question.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
answer = nil
|
||||||
|
|
||||||
|
begin
|
||||||
|
answer = if inbox
|
||||||
|
inbox_entry.answer params[:answer], current_user
|
||||||
|
else
|
||||||
|
current_user.answer question, params[:answer]
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
@status = :err
|
||||||
|
@message = "An error occurred"
|
||||||
|
@success = false
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
services = JSON.parse params[:share]
|
||||||
|
ShareWorker.perform_async(current_user.id, answer.id, services)
|
||||||
|
|
||||||
|
|
||||||
|
@status = :okay
|
||||||
|
@message = "Successfully answered question."
|
||||||
|
@success = true
|
||||||
|
unless inbox
|
||||||
|
@question = 1
|
||||||
|
@render = render_to_string(partial: 'shared/answerbox', locals: { a: answer, show_question: false })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
params.require :answer
|
params.require :answer
|
||||||
|
|
||||||
|
|
|
@ -21,39 +21,6 @@ class Ajax::InboxController < ApplicationController
|
||||||
inbox.update(new: false)
|
inbox.update(new: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
|
||||||
params.require :id
|
|
||||||
params.require :answer
|
|
||||||
params.require :share
|
|
||||||
|
|
||||||
inbox = Inbox.find(params[:id])
|
|
||||||
|
|
||||||
unless current_user == inbox.user
|
|
||||||
@status = :fail
|
|
||||||
@message = "question not in your inbox"
|
|
||||||
@success = false
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
answer = nil
|
|
||||||
|
|
||||||
begin
|
|
||||||
answer = inbox.answer params[:answer], current_user
|
|
||||||
rescue
|
|
||||||
@status = :err
|
|
||||||
@message = "An error occurred"
|
|
||||||
@success = false
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
services = JSON.parse params[:share]
|
|
||||||
ShareWorker.perform_async(current_user.id, answer.id, services)
|
|
||||||
|
|
||||||
@status = :okay
|
|
||||||
@message = "Successfully answered question."
|
|
||||||
@success = true
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove
|
def remove
|
||||||
params.require :id
|
params.require :id
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
class QuestionController < ApplicationController
|
class QuestionController < ApplicationController
|
||||||
def show
|
def show
|
||||||
@question = Question.find(params[:id])
|
@question = Question.find(params[:id])
|
||||||
@answers = @question.answers.reverse_order
|
@answers = @question.answers.reverse_order.paginate(page: params[:page])
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
format.js
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,6 +4,14 @@ class Answer < ActiveRecord::Base
|
||||||
has_many :comments, dependent: :destroy
|
has_many :comments, dependent: :destroy
|
||||||
has_many :smiles, dependent: :destroy
|
has_many :smiles, dependent: :destroy
|
||||||
|
|
||||||
|
after_create do
|
||||||
|
Inbox.where(user: self.user, question: self.question).destroy_all
|
||||||
|
|
||||||
|
Notification.notify self.question.user, self unless self.question.author_is_anonymous
|
||||||
|
self.user.increment! :answered_count
|
||||||
|
self.question.increment! :answer_count
|
||||||
|
end
|
||||||
|
|
||||||
before_destroy do
|
before_destroy do
|
||||||
# mark a report as deleted if it exists
|
# mark a report as deleted if it exists
|
||||||
rep = Report.where(target_id: self.id).first
|
rep = Report.where(target_id: self.id).first
|
||||||
|
|
|
@ -2,13 +2,8 @@ class Inbox < ActiveRecord::Base
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :question
|
belongs_to :question
|
||||||
|
|
||||||
def answer(answer, user)
|
def answer(answer_content, user)
|
||||||
answer = Answer.create!(content: answer,
|
answer = user.answer(self.question, answer_content)
|
||||||
user: user,
|
|
||||||
question: self.question)
|
|
||||||
Notification.notify self.question.user, answer unless self.question.author_is_anonymous
|
|
||||||
user.increment! :answered_count
|
|
||||||
self.question.increment! :answer_count
|
|
||||||
self.destroy
|
self.destroy
|
||||||
answer
|
answer
|
||||||
end
|
end
|
||||||
|
|
|
@ -92,6 +92,22 @@ class User < ActiveRecord::Base
|
||||||
friends.include? target_user
|
friends.include? target_user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# answers a question
|
||||||
|
# @param question [Question] the question to answer
|
||||||
|
# @param content [String] the answer content
|
||||||
|
def answer(question, content)
|
||||||
|
Answer.create!(content: content,
|
||||||
|
user: self,
|
||||||
|
question: question)
|
||||||
|
end
|
||||||
|
|
||||||
|
# has the user answered +question+ yet?
|
||||||
|
# @param question [Question]
|
||||||
|
def answered?(question)
|
||||||
|
question.answers.each { |a| return true if a.user_id == self.id }
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
# smiles an answer
|
# smiles an answer
|
||||||
# @param answer [Answer] the answer to smile
|
# @param answer [Answer] the answer to smile
|
||||||
def smile(answer)
|
def smile(answer)
|
||||||
|
@ -125,6 +141,7 @@ class User < ActiveRecord::Base
|
||||||
self.moderator? || self.admin?
|
self.moderator? || self.admin?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# region stuff used for reporting/moderation
|
||||||
def report(object)
|
def report(object)
|
||||||
Report.create(type: "Reports::#{object.class}", target_id: object.id, user_id: self.id)
|
Report.create(type: "Reports::#{object.class}", target_id: object.id, user_id: self.id)
|
||||||
end
|
end
|
||||||
|
@ -156,6 +173,7 @@ class User < ActiveRecord::Base
|
||||||
def report_comment(report, content)
|
def report_comment(report, content)
|
||||||
ModerationComment.create!(user: self, report: report, content: content)
|
ModerationComment.create!(user: self, report: report, content: content)
|
||||||
end
|
end
|
||||||
|
# endregion
|
||||||
|
|
||||||
def cropping?
|
def cropping?
|
||||||
!crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
|
!crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
|
||||||
|
|
2
app/views/ajax/answer/create.json.jbuilder
Normal file
2
app/views/ajax/answer/create.json.jbuilder
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
json.partial! 'ajax/shared/status'
|
||||||
|
json.render @render if @render
|
|
@ -1 +0,0 @@
|
||||||
json.partial! 'ajax/shared/status'
|
|
|
@ -24,6 +24,9 @@
|
||||||
= nav_entry "Inbox", "/inbox", badge: inbox_count
|
= nav_entry "Inbox", "/inbox", badge: inbox_count
|
||||||
= render "layouts/notifications"
|
= render "layouts/notifications"
|
||||||
%ul.nav.navbar-nav.navbar-right
|
%ul.nav.navbar-nav.navbar-right
|
||||||
|
%li
|
||||||
|
.btn.btn-primary.navbar-btn.btn-sm.hidden-xs{"data-target" => "#modal-ask-followers", "data-toggle" => "modal", :type => "button"}
|
||||||
|
%i.fa.fa-pencil-square-o
|
||||||
%li.dropdown
|
%li.dropdown
|
||||||
%a.dropdown-toggle{href: "#", "data-toggle" => "dropdown"}
|
%a.dropdown-toggle{href: "#", "data-toggle" => "dropdown"}
|
||||||
= current_user.screen_name
|
= current_user.screen_name
|
||||||
|
@ -46,6 +49,5 @@
|
||||||
|
|
||||||
- if user_signed_in?
|
- if user_signed_in?
|
||||||
= render 'shared/modal_ask_followers'
|
= render 'shared/modal_ask_followers'
|
||||||
- if user_signed_in?
|
%button.btn.btn-primary.btn-fab.visible-xs{"data-target" => "#modal-ask-followers", "data-toggle" => "modal", :type => "button"}
|
||||||
%button.btn.btn-primary.btn-fab{"data-target" => "#modal-ask-followers", "data-toggle" => "modal", :type => "button"}
|
%i.fa.fa-pencil-square-o
|
||||||
%i.fa.fa-pencil-square-o
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
.container.j2-page
|
.container.j2-page
|
||||||
/ TODO: make this pretty (it's currently C-c'd straight from shared/_answerbox)
|
/ TODO: make this pretty (it's currently C-c'd straight from shared/_answerbox)
|
||||||
.panel-heading
|
.panel.panel-default
|
||||||
.media
|
.panel-body
|
||||||
- unless @question.author_is_anonymous
|
.media
|
||||||
%a.pull-left{href: show_user_profile_path(@question.user.screen_name)}
|
- unless @question.author_is_anonymous
|
||||||
%img.img-rounded.answerbox--img{src: gravatar_url(@question.user)}
|
%a.pull-left{href: show_user_profile_path(@question.user.screen_name)}
|
||||||
|
%img.img-rounded.answerbox--img{src: gravatar_url(@question.user)}
|
||||||
.media-body
|
.media-body
|
||||||
%h6.text-muted.media-heading.answerbox--question-user
|
%h6.text-muted.media-heading.answerbox--question-user
|
||||||
= user_screen_name @question.user, @question.author_is_anonymous
|
= user_screen_name @question.user, @question.author_is_anonymous
|
||||||
|
@ -13,6 +14,27 @@
|
||||||
ago
|
ago
|
||||||
%p.answerbox--question-text= @question.content
|
%p.answerbox--question-text= @question.content
|
||||||
|
|
||||||
- @answers.each do |a|
|
#answers
|
||||||
= render 'shared/answerbox', a: a, show_question: false
|
- @answers.each do |a|
|
||||||
|
= render 'shared/answerbox', a: a, show_question: false
|
||||||
|
|
||||||
|
#pagination= will_paginate @answers, renderer: BootstrapPagination::Rails, page_links: false
|
||||||
|
|
||||||
|
- if @answers.next_page
|
||||||
|
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @answers.current_page }}
|
||||||
|
Load more
|
||||||
|
|
||||||
|
- if user_signed_in? and !current_user.answered? @question and current_user != @question.user
|
||||||
|
.panel.panel-default#q-answer-box
|
||||||
|
.panel-heading
|
||||||
|
%h3.panel-title This question was not in your inbox? Answer it here!
|
||||||
|
.panel-body
|
||||||
|
%textarea#q-answer.form-control{placeholder: 'Write your answer here...', data: { id: @question.id }}
|
||||||
|
%br/
|
||||||
|
%button#q-answer.btn.btn-success{data: { q_id: @question.id }}
|
||||||
|
Answer
|
||||||
|
- current_user.services.each do |service|
|
||||||
|
%label
|
||||||
|
%input{type: 'checkbox', name: 'share', checked: :checked, data: { q_id: @question.id, service: service.provider }}
|
||||||
|
Post to
|
||||||
|
= service.provider.capitalize
|
8
app/views/question/show.js.erb
Normal file
8
app/views/question/show.js.erb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
$('#answers').append('<% @answers.each do |answer|
|
||||||
|
%><%= j render 'shared/answerbox', a: answer, show_question: false
|
||||||
|
%><% end %>');
|
||||||
|
<% if @answers.next_page %>
|
||||||
|
$('#pagination').html('<%= j will_paginate @answers, renderer: BootstrapPagination::Rails, page_links: false %>');
|
||||||
|
<% else %>
|
||||||
|
$('#pagination, #load-more-btn').remove();
|
||||||
|
<% end %>
|
|
@ -1,26 +1,42 @@
|
||||||
.panel.panel-default
|
.panel.panel-default
|
||||||
|
%img.profile--avatar{src: @user.profile_picture.url(:large)}
|
||||||
.panel-body
|
.panel-body
|
||||||
.media
|
- if @user.display_name.blank?
|
||||||
.pull-left
|
.profile--displayname
|
||||||
%img.img-rounded.profile--img{src: gravatar_url(@user)}
|
= @user.screen_name
|
||||||
.media-body
|
|
||||||
- if @user.display_name.blank?
|
|
||||||
%h2= @user.screen_name
|
|
||||||
- else
|
|
||||||
%h2.profile--displayname= @user.display_name
|
|
||||||
%h4.text-muted.profile--username= @user.screen_name
|
|
||||||
- if @user.admin?
|
- if @user.admin?
|
||||||
%p.profile--admin
|
%span.label.label-danger.j2-up
|
||||||
%i.fa.fa-flask
|
%i.fa.fa-flask
|
||||||
Admin
|
Admin
|
||||||
- if @user.moderator?
|
- if @user.moderator?
|
||||||
%p.profile--moderator
|
%span.label.label-success.j2-up
|
||||||
%i.fa.fa-users
|
%i.fa.fa-users
|
||||||
Mod
|
Mod
|
||||||
|
- if @user.supporter?
|
||||||
|
%span.label.label-warning.j2-up
|
||||||
|
%i.fa.fa-star
|
||||||
|
Supporter
|
||||||
|
- else
|
||||||
|
.profile--displayname
|
||||||
|
= @user.display_name
|
||||||
|
- if @user.admin?
|
||||||
|
%span.label.label-danger.j2-up
|
||||||
|
%i.fa.fa-flask
|
||||||
|
Admin
|
||||||
|
- if @user.moderator?
|
||||||
|
%span.label.label-success.j2-up
|
||||||
|
%i.fa.fa-users
|
||||||
|
Mod
|
||||||
|
- if @user.supporter?
|
||||||
|
%span.label.label-warning.j2-up
|
||||||
|
%i.fa.fa-star
|
||||||
|
Supporter
|
||||||
|
.profile--username
|
||||||
|
= @user.screen_name
|
||||||
- if @user.following? current_user
|
- if @user.following? current_user
|
||||||
%p
|
%p.profile--followtag
|
||||||
%span.label.label-default
|
%span.label.label-default.j2-up
|
||||||
FOLLOWS YOU
|
Follows you
|
||||||
- unless @user.bio.blank?
|
- unless @user.bio.blank?
|
||||||
%p.profile--text= @user.bio
|
%p.profile--text= @user.bio
|
||||||
- unless @user.website.blank?
|
- unless @user.website.blank?
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
.profile--header
|
.profile--header
|
||||||
.container.j2-page
|
.container.j2-page
|
||||||
.col-md-4.col-xs-12.col-sm-4
|
.col-md-3.col-xs-12.col-sm-4
|
||||||
= render 'user/profile_info'
|
= render 'user/profile_info'
|
||||||
.hidden-xs= render 'shared/links'
|
.hidden-xs= render 'shared/links'
|
||||||
.col-md-8.col-xs-12.col-sm-8
|
.col-md-9.col-xs-12.col-sm-8
|
||||||
%h1.j2-lh.hidden-xs= @title
|
%h1.j2-lh.hidden-xs= @title
|
||||||
%h1.visible-xs= @title
|
%h1.visible-xs= @title
|
||||||
#questions
|
#questions
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
.profile--header
|
.profile--header
|
||||||
.container.j2-page
|
.container.j2-page
|
||||||
.col-md-4.col-xs-12.col-sm-4
|
.col-md-3.col-xs-12.col-sm-4
|
||||||
= render 'user/profile_info'
|
= render 'user/profile_info'
|
||||||
.hidden-xs= render 'shared/links'
|
.hidden-xs= render 'shared/links'
|
||||||
.col-md-8.col-xs-12.col-sm-8
|
.col-md-9.col-xs-12.col-sm-8
|
||||||
= render 'shared/questionbox'
|
= render 'shared/questionbox'
|
||||||
#answers
|
#answers
|
||||||
- @answers.each do |a|
|
- @answers.each do |a|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
.profile--header
|
.profile--header
|
||||||
.container.j2-page
|
.container.j2-page
|
||||||
.col-md-4.col-xs-12.col-sm-4
|
.col-md-3.col-xs-12.col-sm-4
|
||||||
= render 'user/profile_info'
|
= render 'user/profile_info'
|
||||||
.hidden-xs= render 'shared/links'
|
.hidden-xs= render 'shared/links'
|
||||||
.col-md-8.col-xs-12.col-sm-8
|
.col-md-9.col-xs-12.col-sm-8
|
||||||
%h1.j2-lh.hidden-xs= @title
|
%h1.j2-lh.hidden-xs= @title
|
||||||
%h1.visible-xs= @title
|
%h1.visible-xs= @title
|
||||||
#users
|
#users
|
||||||
|
|
|
@ -61,10 +61,10 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
namespace :ajax do
|
namespace :ajax do
|
||||||
match '/ask', to: 'question#create', via: :post, as: :ask
|
match '/ask', to: 'question#create', via: :post, as: :ask
|
||||||
match '/answer', to: 'inbox#destroy', via: :post, as: :answer
|
|
||||||
match '/generate_question', to: 'inbox#create', via: :post, as: :generate_question
|
match '/generate_question', to: 'inbox#create', via: :post, as: :generate_question
|
||||||
match '/delete_inbox', to: 'inbox#remove', via: :post, as: :delete_inbox
|
match '/delete_inbox', to: 'inbox#remove', via: :post, as: :delete_inbox
|
||||||
match '/delete_all_inbox', to: 'inbox#remove_all', via: :post, as: :delete_all_inbox
|
match '/delete_all_inbox', to: 'inbox#remove_all', via: :post, as: :delete_all_inbox
|
||||||
|
match '/answer', to: 'answer#create', via: :post, as: :answer
|
||||||
match '/destroy_answer', to: 'answer#destroy', via: :post, as: :destroy_answer
|
match '/destroy_answer', to: 'answer#destroy', via: :post, as: :destroy_answer
|
||||||
match '/create_friend', to: 'friend#create', via: :post, as: :create_friend
|
match '/create_friend', to: 'friend#create', via: :post, as: :create_friend
|
||||||
match '/destroy_friend', to: 'friend#destroy', via: :post, as: :destroy_friend
|
match '/destroy_friend', to: 'friend#destroy', via: :post, as: :destroy_friend
|
||||||
|
|
5
db/migrate/20150102231343_add_supporter_to_users.rb
Normal file
5
db/migrate/20150102231343_add_supporter_to_users.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class AddSupporterToUsers < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :users, :supporter, :boolean, default: false
|
||||||
|
end
|
||||||
|
end
|
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20141229133149) do
|
ActiveRecord::Schema.define(version: 20150102231343) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -168,6 +168,7 @@ ActiveRecord::Schema.define(version: 20141229133149) do
|
||||||
t.integer "crop_y"
|
t.integer "crop_y"
|
||||||
t.integer "crop_w"
|
t.integer "crop_w"
|
||||||
t.integer "crop_h"
|
t.integer "crop_h"
|
||||||
|
t.boolean "supporter", default: false
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
|
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
|
||||||
|
|
Loading…
Reference in a new issue