Merge branch 'master' into groups
Conflicts: db/schema.rb
7
Gemfile
|
@ -28,7 +28,6 @@ gem 'devise'
|
||||||
gem 'devise-async'
|
gem 'devise-async'
|
||||||
gem 'bootstrap_form'
|
gem 'bootstrap_form'
|
||||||
gem 'font-kit-rails'
|
gem 'font-kit-rails'
|
||||||
gem 'nprogress-rails'
|
|
||||||
gem 'font-awesome-rails', '~> 4.2.0.0'
|
gem 'font-awesome-rails', '~> 4.2.0.0'
|
||||||
gem 'rails-assets-growl'
|
gem 'rails-assets-growl'
|
||||||
gem "paperclip", "~> 4.2"
|
gem "paperclip", "~> 4.2"
|
||||||
|
@ -38,7 +37,6 @@ gem 'ruby-progressbar'
|
||||||
|
|
||||||
gem 'rails_admin'
|
gem 'rails_admin'
|
||||||
|
|
||||||
gem 'twitter'
|
|
||||||
gem 'sidekiq'
|
gem 'sidekiq'
|
||||||
gem 'sinatra', require: false
|
gem 'sinatra', require: false
|
||||||
|
|
||||||
|
@ -50,6 +48,11 @@ gem 'redcarpet'
|
||||||
# OmniAuth and providers
|
# OmniAuth and providers
|
||||||
gem 'omniauth'
|
gem 'omniauth'
|
||||||
gem 'omniauth-twitter'
|
gem 'omniauth-twitter'
|
||||||
|
gem 'omniauth-tumblr'
|
||||||
|
|
||||||
|
# OAuth clients
|
||||||
|
gem 'twitter'
|
||||||
|
gem 'tumblr_client'
|
||||||
|
|
||||||
gem 'foreman'
|
gem 'foreman'
|
||||||
gem 'redis'
|
gem 'redis'
|
||||||
|
|
15
Gemfile.lock
|
@ -111,6 +111,8 @@ GEM
|
||||||
i18n (~> 0.5)
|
i18n (~> 0.5)
|
||||||
faraday (0.9.0)
|
faraday (0.9.0)
|
||||||
multipart-post (>= 1.2, < 3)
|
multipart-post (>= 1.2, < 3)
|
||||||
|
faraday_middleware (0.9.1)
|
||||||
|
faraday (>= 0.7.4, < 0.10)
|
||||||
font-awesome-rails (4.2.0.0)
|
font-awesome-rails (4.2.0.0)
|
||||||
railties (>= 3.2, < 5.0)
|
railties (>= 3.2, < 5.0)
|
||||||
font-kit-rails (1.1.0)
|
font-kit-rails (1.1.0)
|
||||||
|
@ -163,7 +165,6 @@ GEM
|
||||||
mini_portile (~> 0.6.0)
|
mini_portile (~> 0.6.0)
|
||||||
nokogumbo (1.2.0)
|
nokogumbo (1.2.0)
|
||||||
nokogiri
|
nokogiri
|
||||||
nprogress-rails (0.1.6.3)
|
|
||||||
oauth (0.4.7)
|
oauth (0.4.7)
|
||||||
omniauth (1.2.2)
|
omniauth (1.2.2)
|
||||||
hashie (>= 1.2, < 4)
|
hashie (>= 1.2, < 4)
|
||||||
|
@ -171,6 +172,8 @@ GEM
|
||||||
omniauth-oauth (1.0.1)
|
omniauth-oauth (1.0.1)
|
||||||
oauth
|
oauth
|
||||||
omniauth (~> 1.0)
|
omniauth (~> 1.0)
|
||||||
|
omniauth-tumblr (1.1)
|
||||||
|
omniauth-oauth (~> 1.0)
|
||||||
omniauth-twitter (1.1.0)
|
omniauth-twitter (1.1.0)
|
||||||
multi_json (~> 1.3)
|
multi_json (~> 1.3)
|
||||||
omniauth-oauth (~> 1.0)
|
omniauth-oauth (~> 1.0)
|
||||||
|
@ -309,6 +312,13 @@ GEM
|
||||||
tilt (1.4.1)
|
tilt (1.4.1)
|
||||||
timers (4.0.1)
|
timers (4.0.1)
|
||||||
hitimes
|
hitimes
|
||||||
|
tumblr_client (0.8.5)
|
||||||
|
faraday (~> 0.9.0)
|
||||||
|
faraday_middleware (~> 0.9.0)
|
||||||
|
json
|
||||||
|
mime-types
|
||||||
|
oauth
|
||||||
|
simple_oauth
|
||||||
turbolinks (2.5.3)
|
turbolinks (2.5.3)
|
||||||
coffee-rails
|
coffee-rails
|
||||||
twitter (5.13.0)
|
twitter (5.13.0)
|
||||||
|
@ -368,8 +378,8 @@ DEPENDENCIES
|
||||||
jquery-rails
|
jquery-rails
|
||||||
jquery-turbolinks
|
jquery-turbolinks
|
||||||
mysql2
|
mysql2
|
||||||
nprogress-rails
|
|
||||||
omniauth
|
omniauth
|
||||||
|
omniauth-tumblr
|
||||||
omniauth-twitter
|
omniauth-twitter
|
||||||
paperclip (~> 4.2)
|
paperclip (~> 4.2)
|
||||||
pg
|
pg
|
||||||
|
@ -391,6 +401,7 @@ DEPENDENCIES
|
||||||
spring
|
spring
|
||||||
sweetalert-rails
|
sweetalert-rails
|
||||||
thin
|
thin
|
||||||
|
tumblr_client
|
||||||
turbolinks
|
turbolinks
|
||||||
twitter
|
twitter
|
||||||
uglifier (>= 1.3.0)
|
uglifier (>= 1.3.0)
|
||||||
|
|
22
Rakefile
|
@ -90,7 +90,27 @@ namespace :justask do
|
||||||
fail "user #{args[:screen_name]} not found" if user.nil?
|
fail "user #{args[:screen_name]} not found" if user.nil?
|
||||||
user.moderator = false
|
user.moderator = false
|
||||||
user.save!
|
user.save!
|
||||||
puts "#{user.screen_name} no longer an moderator."
|
puts "#{user.screen_name} is no longer an moderator."
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Hits an user with the banhammer."
|
||||||
|
task :ban, [: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.banned = true
|
||||||
|
user.save!
|
||||||
|
puts "#{user.screen_name} got hit by\033[5m YE OLDE BANHAMMER\033[0m!!1!"
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Removes banned status from an user."
|
||||||
|
task :unban, [: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.banned = false
|
||||||
|
user.save!
|
||||||
|
puts "#{user.screen_name} is no longer banned."
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Gives supporter status to an user."
|
desc "Gives supporter status to an user."
|
||||||
|
|
|
@ -3,16 +3,13 @@
|
||||||
#= require jquery.turbolinks
|
#= require jquery.turbolinks
|
||||||
#= require turbolinks
|
#= require turbolinks
|
||||||
#= require bootstrap
|
#= require bootstrap
|
||||||
#= require nprogress
|
|
||||||
#= require nprogress-turbolinks
|
|
||||||
#= require growl
|
#= require growl
|
||||||
#= require cheet
|
#= require cheet
|
||||||
#= require jquery.guillotine
|
#= require jquery.guillotine
|
||||||
#= require sweet-alert
|
#= require sweet-alert
|
||||||
#= require_tree .
|
#= require_tree .
|
||||||
|
|
||||||
NProgress.configure
|
Turbolinks.enableProgressBar()
|
||||||
showSpinner: false
|
|
||||||
|
|
||||||
window.showNotification = (text, success=true) ->
|
window.showNotification = (text, success=true) ->
|
||||||
args =
|
args =
|
||||||
|
|
18
app/assets/javascripts/piwik.js.erb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
|
||||||
|
<% if Rails.env.production? %>
|
||||||
|
var _paq = _paq || [];
|
||||||
|
_paq.push(['trackPageView']);
|
||||||
|
_paq.push(['enableLinkTracking']);
|
||||||
|
_paq.push(['setCustomUrl', document.location]);
|
||||||
|
_paq.push(['setDocumentTitle', document.title]);
|
||||||
|
(function() {
|
||||||
|
var u="//stat.rrerr.net/";
|
||||||
|
_paq.push(['setTrackerUrl', u+'piwik.php']);
|
||||||
|
_paq.push(['setSiteId', 9]);
|
||||||
|
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||||
|
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
|
||||||
|
})();
|
||||||
|
<% else %>
|
||||||
|
console.log("i track'd ur bich");
|
||||||
|
<% end %>
|
|
@ -34,6 +34,8 @@ body { padding-top: $navbar-height; }
|
||||||
|
|
||||||
@import "font-awesome";
|
@import "font-awesome";
|
||||||
|
|
||||||
$nprogress-color: darken($navbar-inverse-bg, 15%);
|
html.turbolinks-progress-bar::before {
|
||||||
@import 'nprogress';
|
background-color: darken($navbar-inverse-bg, 15%) !important;
|
||||||
@import 'nprogress-bootstrap';
|
box-shadow: 0px 0px 10px darken($navbar-inverse-bg, 15%), 0px 0px 5px darken($navbar-inverse-bg, 15%);
|
||||||
|
height: 2px !important;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.text-muted a, .answerbox .text-muted a:hover {
|
.answerbox .text-muted a, .answerbox .text-muted a:hover {
|
||||||
color: $gray-dark;
|
color: $gray;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.answerbox--question-text {
|
.answerbox--question-text {
|
||||||
font-weight: bold;
|
color: $gray;
|
||||||
color: $gray-darker;
|
}
|
||||||
|
|
||||||
|
.answerbox--answer-text {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #000;
|
||||||
|
line-height: 1.3em;
|
||||||
}
|
}
|
|
@ -121,3 +121,7 @@
|
||||||
.panel-badge-warning {
|
.panel-badge-warning {
|
||||||
background-color: #FF9800;
|
background-color: #FF9800;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user--banned {
|
||||||
|
text-decoration: line-through !important;
|
||||||
|
}
|
|
@ -4,6 +4,18 @@ class ApplicationController < ActionController::Base
|
||||||
protect_from_forgery with: :exception
|
protect_from_forgery with: :exception
|
||||||
|
|
||||||
before_filter :configure_permitted_parameters, if: :devise_controller?
|
before_filter :configure_permitted_parameters, if: :devise_controller?
|
||||||
|
before_filter :banned?
|
||||||
|
|
||||||
|
# check if user got hit by the banhammer of doom
|
||||||
|
def banned?
|
||||||
|
if current_user.present? && current_user.banned?
|
||||||
|
name = current_user.screen_name
|
||||||
|
# obligatory '2001: A Space Odyssey' reference
|
||||||
|
flash[:notice] = "I'm sorry, #{name}, I'm afraid I can't do that."
|
||||||
|
sign_out current_user
|
||||||
|
redirect_to new_user_session_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,10 @@ class NotificationsController < ApplicationController
|
||||||
Notification.for(current_user)
|
Notification.for(current_user)
|
||||||
else
|
else
|
||||||
Notification.for(current_user).where('LOWER(target_type) = ?', @type)
|
Notification.for(current_user).where('LOWER(target_type) = ?', @type)
|
||||||
|
end.paginate(page: params[:page])
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
format.js
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,21 +1,12 @@
|
||||||
module MarkdownHelper
|
module MarkdownHelper
|
||||||
|
|
||||||
def markdown(content)
|
def markdown(content)
|
||||||
md = Redcarpet::Markdown.new(FlavoredMarkdown,
|
md = Redcarpet::Markdown.new(FlavoredMarkdown, MARKDOWN_OPTS)
|
||||||
filter_html: true,
|
|
||||||
escape_html: true,
|
|
||||||
no_images: true,
|
|
||||||
no_styles: true,
|
|
||||||
safe_links_only: true,
|
|
||||||
xhtml: false,
|
|
||||||
hard_wrap: true,
|
|
||||||
no_intra_emphasis: true,
|
|
||||||
tables: true,
|
|
||||||
fenced_code_blocks: true,
|
|
||||||
autolink: true,
|
|
||||||
disable_indented_code_blocks: true,
|
|
||||||
strikethrough: true,
|
|
||||||
superscript: true)
|
|
||||||
Sanitize.fragment(md.render(content), EVIL_TAGS).html_safe
|
Sanitize.fragment(md.render(content), EVIL_TAGS).html_safe
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def strip_markdown(content)
|
||||||
|
md = Redcarpet::Markdown.new(Redcarpet::Render::StripDown, MARKDOWN_OPTS)
|
||||||
|
CGI.unescape_html(Sanitize.fragment(md.render(content), EVIL_TAGS)).strip
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -4,7 +4,7 @@ module UserHelper
|
||||||
def user_screen_name(user, anonymous=false, url=true)
|
def user_screen_name(user, anonymous=false, url=true)
|
||||||
return APP_CONFIG['anonymous_name'] if user.nil? || anonymous
|
return APP_CONFIG['anonymous_name'] if user.nil? || anonymous
|
||||||
name = user.display_name.blank? ? user.screen_name : user.display_name
|
name = user.display_name.blank? ? user.screen_name : user.display_name
|
||||||
return link_to(name, show_user_profile_path(user.screen_name)) if url
|
return link_to(name, show_user_profile_path(user.screen_name), class: "#{"user--banned" if user.banned?}") if url
|
||||||
name
|
name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
45
app/models/services/tumblr.rb
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
class Services::Tumblr < Service
|
||||||
|
include Rails.application.routes.url_helpers
|
||||||
|
include MarkdownHelper
|
||||||
|
|
||||||
|
def provider
|
||||||
|
"tumblr"
|
||||||
|
end
|
||||||
|
|
||||||
|
def post(answer)
|
||||||
|
Rails.logger.debug "posting to Tumblr {'answer' => #{answer.id}, 'user' => #{self.user_id}}"
|
||||||
|
create_post answer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def client
|
||||||
|
@client ||= Tumblr::Client.new(
|
||||||
|
consumer_key: APP_CONFIG['sharing']['tumblr']['consumer_key'],
|
||||||
|
consumer_secret: APP_CONFIG['sharing']['tumblr']['consumer_secret'],
|
||||||
|
oauth_token: self.access_token,
|
||||||
|
oauth_token_secret: self.access_secret
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_post(answer)
|
||||||
|
answer_url = show_user_answer_url(
|
||||||
|
id: answer.id,
|
||||||
|
username: answer.user.screen_name,
|
||||||
|
host: APP_CONFIG['hostname'],
|
||||||
|
protocol: (APP_CONFIG['https'] ? :https : :http)
|
||||||
|
)
|
||||||
|
asker = if answer.question.author_is_anonymous?
|
||||||
|
APP_CONFIG['anonymous_name']
|
||||||
|
else
|
||||||
|
answer.question.user.display_name.blank? ? answer.question.user.screen_name : answer.question.user.display_name
|
||||||
|
end
|
||||||
|
client.text(
|
||||||
|
self.uid,
|
||||||
|
title: "#{asker} asked: #{answer.question.content}",
|
||||||
|
body: "#{answer.content}\n\n[Smile or comment on the answer here](#{answer_url})",
|
||||||
|
format: 'markdown',
|
||||||
|
tweet: 'off'
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,6 @@
|
||||||
class Services::Twitter < Service
|
class Services::Twitter < Service
|
||||||
include Rails.application.routes.url_helpers
|
include Rails.application.routes.url_helpers
|
||||||
|
include MarkdownHelper
|
||||||
|
|
||||||
def provider
|
def provider
|
||||||
"twitter"
|
"twitter"
|
||||||
|
@ -27,8 +28,8 @@ class Services::Twitter < Service
|
||||||
|
|
||||||
def prepare_tweet(answer)
|
def prepare_tweet(answer)
|
||||||
# TODO: improve this.
|
# TODO: improve this.
|
||||||
question_content = answer.question.content
|
question_content = strip_markdown answer.question.content
|
||||||
answer_content = answer.content
|
answer_content = strip_markdown answer.content
|
||||||
answer_url = show_user_answer_url(
|
answer_url = show_user_answer_url(
|
||||||
id: answer.id,
|
id: answer.id,
|
||||||
username: answer.user.screen_name,
|
username: answer.user.screen_name,
|
||||||
|
|
|
@ -31,11 +31,11 @@ class User < ActiveRecord::Base
|
||||||
SCREEN_NAME_REGEX = /\A[a-zA-Z0-9_]{1,16}\z/
|
SCREEN_NAME_REGEX = /\A[a-zA-Z0-9_]{1,16}\z/
|
||||||
WEBSITE_REGEX = /https?:\/\/([A-Za-z.\-]+)\/?(?:.*)/i
|
WEBSITE_REGEX = /https?:\/\/([A-Za-z.\-]+)\/?(?:.*)/i
|
||||||
|
|
||||||
validates :screen_name, presence: true, format: { with: SCREEN_NAME_REGEX }, uniqueness: { case_sensitive: false }#,
|
before_validation do
|
||||||
#exclusion: { in: %w(justask_admin retrospring_admin admin justask retrospring support about public
|
screen_name.strip!
|
||||||
# notifications inbox sign_in sign_up sidekiq moderation moderator mod administrator
|
end
|
||||||
# siteadmin site_admin),
|
|
||||||
# message: "%{value} is reserved." }
|
validates :screen_name, presence: true, format: { with: SCREEN_NAME_REGEX }, uniqueness: { case_sensitive: false }, screen_name: true
|
||||||
|
|
||||||
validates :display_name, length: { maximum: 50 }
|
validates :display_name, length: { maximum: 50 }
|
||||||
validates :bio, length: { maximum: 200 }
|
validates :bio, length: { maximum: 200 }
|
||||||
|
|
11
app/validators/screen_name_validator.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
class ScreenNameValidator < ActiveModel::EachValidator
|
||||||
|
FORBIDDEN_SCREEN_NAMES = %w(justask_admin retrospring_admin admin justask retrospring support about public
|
||||||
|
notifications inbox sign_in sign_up sidekiq moderation moderator mod administrator
|
||||||
|
siteadmin site_admin help retro_spring retroospring retrosprlng niisding nllsding)
|
||||||
|
|
||||||
|
def validate_each(record, attribute, value)
|
||||||
|
if FORBIDDEN_SCREEN_NAMES.include? value.downcase
|
||||||
|
record.errors[attribute] << "Thou shalt not use this username! Please choose another one."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,8 +5,13 @@
|
||||||
%meta{'http-equiv' => 'X-UA-Compatible' ,content: 'IE=edge'}
|
%meta{'http-equiv' => 'X-UA-Compatible' ,content: 'IE=edge'}
|
||||||
%meta{name: 'viewport', content: 'width=device-width, initial-scale=1, user-scalable=no'}
|
%meta{name: 'viewport', content: 'width=device-width, initial-scale=1, user-scalable=no'}
|
||||||
%meta{name: 'theme-color', content: '#0C84E4'}
|
%meta{name: 'theme-color', content: '#0C84E4'}
|
||||||
|
%meta{name: "mobile-web-app-capable", content: "yes"}
|
||||||
%meta{name: "apple-mobile-web-app-capable", content: "yes"}
|
%meta{name: "apple-mobile-web-app-capable", content: "yes"}
|
||||||
%meta{name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent'}
|
%meta{name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent'}
|
||||||
|
%link{rel: 'apple-touch-icon', href: '/apple-touch-icon-precomposed.png'}
|
||||||
|
%link{rel: 'icon', href: '/images/favicon/favicon-16.png', sizes: '16x16'}
|
||||||
|
%link{rel: 'icon', href: '/icon-152.png', sizes: '152x152'}
|
||||||
|
%link{rel: 'icon', href: '/images/favicon/favicon-32.png', sizes: '32x32'}
|
||||||
%title= APP_CONFIG['site_name']
|
%title= APP_CONFIG['site_name']
|
||||||
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
|
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
|
||||||
= javascript_include_tag 'application', 'data-turbolinks-track' => true
|
= javascript_include_tag 'application', 'data-turbolinks-track' => true
|
||||||
|
@ -27,19 +32,6 @@
|
||||||
= debug params
|
= debug params
|
||||||
|
|
||||||
- if Rails.env.production?
|
- if Rails.env.production?
|
||||||
:javascript
|
|
||||||
var _paq = _paq || [];
|
|
||||||
_paq.push(['trackPageView']);
|
|
||||||
_paq.push(['enableLinkTracking']);
|
|
||||||
_paq.push(['setCustomUrl', document.location]);
|
|
||||||
_paq.push(['setDocumentTitle', document.title]);
|
|
||||||
(function() {
|
|
||||||
var u="//stat.rrerr.net/";
|
|
||||||
_paq.push(['setTrackerUrl', u+'piwik.php']);
|
|
||||||
_paq.push(['setSiteId', 9]);
|
|
||||||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
|
||||||
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
|
|
||||||
})();
|
|
||||||
%noscript
|
%noscript
|
||||||
%p
|
%p
|
||||||
%img{:alt => "", :src => "//stat.rrerr.net/piwik.php?idsite=9", :style => "border:0;"}/
|
%img{:alt => "", :src => "//stat.rrerr.net/piwik.php?idsite=9", :style => "border:0;"}/
|
||||||
|
|
57
app/views/notifications/_notification.html.haml
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
%li.list-group-item{class: (notification.new? ? 'list-group-item-warning' : '')}
|
||||||
|
.media
|
||||||
|
- case notification.target_type
|
||||||
|
- when "Answer"
|
||||||
|
.pull-left
|
||||||
|
%img.img-rounded.notification--img{src: gravatar_url(notification.target.user)}
|
||||||
|
.media-body
|
||||||
|
%h6.media-heading.notification--user
|
||||||
|
= user_screen_name notification.target.user
|
||||||
|
%p.notification--text
|
||||||
|
answered
|
||||||
|
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.id), title: "#{notification.target.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
|
||||||
|
your question
|
||||||
|
= time_ago_in_words notification.target.created_at
|
||||||
|
ago
|
||||||
|
.notification--icon
|
||||||
|
%i.fa.fa-exclamation
|
||||||
|
- when "Relationship"
|
||||||
|
.pull-left
|
||||||
|
%img.img-rounded.notification--img{src: gravatar_url(notification.target.source)}
|
||||||
|
.media-body
|
||||||
|
%h6.media-heading.notification--user
|
||||||
|
= user_screen_name notification.target.source
|
||||||
|
%p.notification--text
|
||||||
|
followed you
|
||||||
|
= time_ago_in_words notification.target.created_at
|
||||||
|
ago
|
||||||
|
.notification--icon
|
||||||
|
%i.fa.fa-users
|
||||||
|
- when "Smile"
|
||||||
|
.pull-left
|
||||||
|
%img.img-rounded.notification--img{src: gravatar_url(notification.target.user)}
|
||||||
|
.media-body
|
||||||
|
%h6.media-heading.notification--user
|
||||||
|
= user_screen_name notification.target.user
|
||||||
|
%p.notification--text
|
||||||
|
smiled at
|
||||||
|
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id), title: "#{notification.target.answer.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
|
||||||
|
your answer
|
||||||
|
= time_ago_in_words notification.target.created_at
|
||||||
|
ago
|
||||||
|
.notification--icon
|
||||||
|
%i.fa.fa-smile-o
|
||||||
|
- when "Comment"
|
||||||
|
.pull-left
|
||||||
|
%img.img-rounded.notification--img{src: gravatar_url(notification.target.user)}
|
||||||
|
.media-body
|
||||||
|
%h6.media-heading.notification--user
|
||||||
|
= user_screen_name notification.target.user
|
||||||
|
%p.notification--text
|
||||||
|
commented on
|
||||||
|
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id), title: "#{notification.target.answer.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
|
||||||
|
your answer
|
||||||
|
= time_ago_in_words notification.target.created_at
|
||||||
|
ago
|
||||||
|
.notification--icon
|
||||||
|
%i.fa.fa-comments
|
|
@ -1,63 +1,13 @@
|
||||||
.container.j2-page
|
.container.j2-page
|
||||||
= render 'notification_tabs'
|
= render 'notification_tabs'
|
||||||
.col-md-9.col-xs-12.col-sm-9
|
.col-md-9.col-xs-12.col-sm-9
|
||||||
%ul.list-group
|
%ul#notifications.list-group
|
||||||
- @notifications.each do |notification|
|
- @notifications.each do |notification|
|
||||||
%li.list-group-item{class: (notification.new? ? 'list-group-item-warning' : '')}
|
= render 'notifications/notification', notification: notification
|
||||||
.media
|
|
||||||
- case notification.target_type
|
#pagination= will_paginate @notifications, renderer: BootstrapPagination::Rails, page_links: false
|
||||||
- when "Answer"
|
|
||||||
.pull-left
|
- if @notifications.next_page
|
||||||
%img.img-rounded.notification--img{src: gravatar_url(notification.target.user)}
|
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @notifications.current_page }}
|
||||||
.media-body
|
Load more
|
||||||
%h6.media-heading.notification--user
|
|
||||||
= user_screen_name notification.target.user
|
|
||||||
%p.notification--text
|
|
||||||
answered
|
|
||||||
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.id), title: "#{notification.target.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
|
|
||||||
your question
|
|
||||||
= time_ago_in_words notification.target.created_at
|
|
||||||
ago
|
|
||||||
.notification--icon
|
|
||||||
%i.fa.fa-exclamation
|
|
||||||
- when "Relationship"
|
|
||||||
.pull-left
|
|
||||||
%img.img-rounded.notification--img{src: gravatar_url(notification.target.source)}
|
|
||||||
.media-body
|
|
||||||
%h6.media-heading.notification--user
|
|
||||||
= user_screen_name notification.target.source
|
|
||||||
%p.notification--text
|
|
||||||
followed you
|
|
||||||
= time_ago_in_words notification.target.created_at
|
|
||||||
ago
|
|
||||||
.notification--icon
|
|
||||||
%i.fa.fa-users
|
|
||||||
- when "Smile"
|
|
||||||
.pull-left
|
|
||||||
%img.img-rounded.notification--img{src: gravatar_url(notification.target.user)}
|
|
||||||
.media-body
|
|
||||||
%h6.media-heading.notification--user
|
|
||||||
= user_screen_name notification.target.user
|
|
||||||
%p.notification--text
|
|
||||||
smiled at
|
|
||||||
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id), title: "#{notification.target.answer.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
|
|
||||||
your answer
|
|
||||||
= time_ago_in_words notification.target.created_at
|
|
||||||
ago
|
|
||||||
.notification--icon
|
|
||||||
%i.fa.fa-smile-o
|
|
||||||
- when "Comment"
|
|
||||||
.pull-left
|
|
||||||
%img.img-rounded.notification--img{src: gravatar_url(notification.target.user)}
|
|
||||||
.media-body
|
|
||||||
%h6.media-heading.notification--user
|
|
||||||
= user_screen_name notification.target.user
|
|
||||||
%p.notification--text
|
|
||||||
commented on
|
|
||||||
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id), title: "#{notification.target.answer.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
|
|
||||||
your answer
|
|
||||||
= time_ago_in_words notification.target.created_at
|
|
||||||
ago
|
|
||||||
.notification--icon
|
|
||||||
%i.fa.fa-comments
|
|
||||||
- Notification.for(current_user).update_all(new: false)
|
- Notification.for(current_user).update_all(new: false)
|
8
app/views/notifications/index.js.erb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
$('#notifications').append('<% @notifications.each do |notification|
|
||||||
|
%><%= j render 'notifications/notification', notification: notification
|
||||||
|
%><% end %>');
|
||||||
|
<% if @notifications.next_page %>
|
||||||
|
$('#pagination').html('<%= j will_paginate @notifications, renderer: BootstrapPagination::Rails, page_links: false %>');
|
||||||
|
<% else %>
|
||||||
|
$('#pagination, #load-more-btn').remove();
|
||||||
|
<% end %>
|
|
@ -20,10 +20,11 @@
|
||||||
·
|
·
|
||||||
%a{href: show_user_question_path(a.question.user.screen_name, a.question.id)}
|
%a{href: show_user_question_path(a.question.user.screen_name, a.question.id)}
|
||||||
#{a.question.answer_count} answers
|
#{a.question.answer_count} answers
|
||||||
%p.answerbox--question-text
|
.answerbox--question-text
|
||||||
= a.question.content
|
= a.question.content
|
||||||
.panel-body
|
.panel-body
|
||||||
- if @display_all.nil?
|
- if @display_all.nil?
|
||||||
|
.answerbox--answer-text
|
||||||
= markdown a.content[0..255]
|
= markdown a.content[0..255]
|
||||||
- if a.content.length > 255
|
- if a.content.length > 255
|
||||||
[...]
|
[...]
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
%a.btn.btn-primary{href: show_user_answer_path(a.user.screen_name, a.id)}
|
%a.btn.btn-primary{href: show_user_answer_path(a.user.screen_name, a.id)}
|
||||||
Read the entire answer
|
Read the entire answer
|
||||||
- else
|
- else
|
||||||
|
.answerbox--answer-text
|
||||||
= markdown a.content
|
= markdown a.content
|
||||||
- if @user.nil?
|
- if @user.nil?
|
||||||
.row
|
.row
|
||||||
|
|
|
@ -6,6 +6,11 @@
|
||||||
- else
|
- else
|
||||||
= @user.motivation_header
|
= @user.motivation_header
|
||||||
.panel-body
|
.panel-body
|
||||||
|
- if @user.banned?
|
||||||
|
.row
|
||||||
|
.col-xs-12.text-center
|
||||||
|
%strong This user got hit with ye olde banhammer.
|
||||||
|
- else
|
||||||
- if user_signed_in? or @user.privacy_allow_anonymous_questions?
|
- if user_signed_in? or @user.privacy_allow_anonymous_questions?
|
||||||
#question-box
|
#question-box
|
||||||
.row
|
.row
|
||||||
|
|
|
@ -106,9 +106,7 @@
|
||||||
People that believe in our vision, and that's why we love them <3
|
People that believe in our vision, and that's why we love them <3
|
||||||
%ul.about--moderator
|
%ul.about--moderator
|
||||||
- User.where(supporter: true).each do |sup|
|
- User.where(supporter: true).each do |sup|
|
||||||
%li
|
%a{href: show_user_profile_path(sup.screen_name), title: sup.screen_name, data: { toggle: :tooltip, placement: :top }}
|
||||||
%a{href: show_user_profile_path(sup.screen_name)}
|
%img.img-rounded.answerbox--img-small{src: sup.profile_picture.url(:medium)}
|
||||||
%img.answerbox--img-small{src: User.find_by_screen_name(sup.screen_name).profile_picture.url(:medium)}
|
|
||||||
= sup.screen_name
|
|
||||||
|
|
||||||
= render "shared/links"
|
= render "shared/links"
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
.profile--panel-badge.panel-badge-warning
|
.profile--panel-badge.panel-badge-warning
|
||||||
%i.fa.fa-star
|
%i.fa.fa-star
|
||||||
Supporter
|
Supporter
|
||||||
|
- if @user.banned?
|
||||||
|
.profile--panel-badge.panel-badge-default
|
||||||
|
%i.fa.fa-ban
|
||||||
|
Banned
|
||||||
- if @user.following? current_user
|
- if @user.following? current_user
|
||||||
.profile--panel-badge.panel-badge-default
|
.profile--panel-badge.panel-badge-default
|
||||||
Follows you
|
Follows you
|
||||||
|
|
|
@ -19,5 +19,6 @@ module Justask
|
||||||
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
||||||
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||||
# config.i18n.default_locale = :de
|
# config.i18n.default_locale = :de
|
||||||
|
config.autoload_paths += %W["#{config.root}/app/validators"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
Rails.application.config.middleware.use OmniAuth::Builder do
|
Rails.application.config.middleware.use OmniAuth::Builder do
|
||||||
if APP_CONFIG['sharing']['twitter']['enabled']
|
%w(facebook twitter tumblr).each do |service|
|
||||||
provider :twitter, APP_CONFIG['sharing']['twitter']['consumer_key'], APP_CONFIG['sharing']['twitter']['consumer_secret']
|
if APP_CONFIG['sharing'][service]['enabled']
|
||||||
|
provider service.to_sym, APP_CONFIG['sharing'][service]['consumer_key'], APP_CONFIG['sharing'][service]['consumer_secret']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -41,6 +41,7 @@ RailsAdmin.config do |config|
|
||||||
Report
|
Report
|
||||||
Service
|
Service
|
||||||
Services::Twitter
|
Services::Twitter
|
||||||
|
Services::Tumblr
|
||||||
Smile
|
Smile
|
||||||
User
|
User
|
||||||
]
|
]
|
||||||
|
|
18
config/initializers/redcarpet.rb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
require 'redcarpet/render_strip'
|
||||||
|
|
||||||
|
MARKDOWN_OPTS = {
|
||||||
|
filter_html: true,
|
||||||
|
escape_html: true,
|
||||||
|
no_images: true,
|
||||||
|
no_styles: true,
|
||||||
|
safe_links_only: true,
|
||||||
|
xhtml: false,
|
||||||
|
hard_wrap: true,
|
||||||
|
no_intra_emphasis: true,
|
||||||
|
tables: true,
|
||||||
|
fenced_code_blocks: true,
|
||||||
|
autolink: true,
|
||||||
|
disable_indented_code_blocks: true,
|
||||||
|
strikethrough: true,
|
||||||
|
superscript: false
|
||||||
|
}
|
|
@ -21,6 +21,11 @@ sharing:
|
||||||
consumer_secret: ''
|
consumer_secret: ''
|
||||||
facebook:
|
facebook:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
tumblr:
|
||||||
|
enabled: true
|
||||||
|
# Get the tokens from https://www.tumblr.com/oauth/apps
|
||||||
|
consumer_key: ''
|
||||||
|
consumer_secret: ''
|
||||||
|
|
||||||
# Redis
|
# Redis
|
||||||
redis_url: "redis://localhost:6379"
|
redis_url: "redis://localhost:6379"
|
5
db/migrate/20150112210754_add_banned_to_users.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class AddBannedToUsers < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :users, :banned, :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: 20150108121010) do
|
ActiveRecord::Schema.define(version: 20150112210755) 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"
|
||||||
|
@ -197,6 +197,7 @@ ActiveRecord::Schema.define(version: 20150108121010) do
|
||||||
t.boolean "privacy_allow_public_timeline", default: true
|
t.boolean "privacy_allow_public_timeline", default: true
|
||||||
t.boolean "privacy_allow_stranger_answers", default: true
|
t.boolean "privacy_allow_stranger_answers", default: true
|
||||||
t.boolean "privacy_show_in_search", default: true
|
t.boolean "privacy_show_in_search", default: true
|
||||||
|
t.boolean "banned", 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
|
||||||
|
|
BIN
public/apple-touch-icon-precomposed.png
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
public/icon-152.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/images/favicon/favicon-16.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
public/images/favicon/favicon-32.png
Normal file
After Width: | Height: | Size: 3.4 KiB |