Merge branch 'master' into notifications-tooltips
This commit is contained in:
commit
a37cd95f46
|
@ -0,0 +1 @@
|
|||
full
|
|
@ -0,0 +1,24 @@
|
|||
# Load DSL and set up stages
|
||||
require 'capistrano/setup'
|
||||
|
||||
# Include default deployment tasks
|
||||
require 'capistrano/deploy'
|
||||
|
||||
# Include tasks from other gems included in your Gemfile
|
||||
#
|
||||
# For documentation on these, see for example:
|
||||
#
|
||||
# https://github.com/capistrano/rvm
|
||||
# https://github.com/capistrano/rbenv
|
||||
# https://github.com/capistrano/chruby
|
||||
# https://github.com/capistrano/bundler
|
||||
# https://github.com/capistrano/rails
|
||||
# https://github.com/capistrano/passenger
|
||||
#
|
||||
require 'capistrano/rvm'
|
||||
require 'capistrano/bundler'
|
||||
require 'capistrano/rails'
|
||||
require 'capistrano/console'
|
||||
|
||||
# Load custom tasks from `lib/capistrano/tasks' if you have any defined
|
||||
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
|
5
Gemfile
5
Gemfile
|
@ -48,6 +48,11 @@ gem 'foreman'
|
|||
|
||||
group :development do
|
||||
gem 'spring'
|
||||
|
||||
# Capistrano for deployment
|
||||
gem 'capistrano', '~> 3.1'
|
||||
gem 'capistrano-rvm', group: :rvm
|
||||
gem 'capistrano-rails', '~> 1.1'
|
||||
end
|
||||
|
||||
group :production do
|
||||
|
|
26
Gemfile.lock
26
Gemfile.lock
|
@ -44,6 +44,21 @@ GEM
|
|||
railties (>= 3.1)
|
||||
buftok (0.2.0)
|
||||
builder (3.2.2)
|
||||
capistrano (3.3.5)
|
||||
capistrano-stats (~> 1.1.0)
|
||||
i18n
|
||||
rake (>= 10.0.0)
|
||||
sshkit (~> 1.3)
|
||||
capistrano-bundler (1.1.3)
|
||||
capistrano (~> 3.1)
|
||||
sshkit (~> 1.2)
|
||||
capistrano-rails (1.1.2)
|
||||
capistrano (~> 3.1)
|
||||
capistrano-bundler (~> 1.1)
|
||||
capistrano-rvm (0.1.2)
|
||||
capistrano (~> 3.0)
|
||||
sshkit (~> 1.2)
|
||||
capistrano-stats (1.1.1)
|
||||
capybara (2.4.4)
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
|
@ -60,6 +75,7 @@ GEM
|
|||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.8.0)
|
||||
colorize (0.7.5)
|
||||
connection_pool (2.1.0)
|
||||
daemons (1.1.9)
|
||||
database_cleaner (1.3.0)
|
||||
|
@ -131,6 +147,9 @@ GEM
|
|||
mysql2 (0.3.17)
|
||||
naught (1.0.0)
|
||||
nested_form (0.3.2)
|
||||
net-scp (1.2.1)
|
||||
net-ssh (>= 2.6.5)
|
||||
net-ssh (2.9.1)
|
||||
nokogiri (1.6.5)
|
||||
mini_portile (~> 0.6.0)
|
||||
nprogress-rails (0.1.6.3)
|
||||
|
@ -254,6 +273,10 @@ GEM
|
|||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sshkit (1.6.1)
|
||||
colorize (>= 0.7.0)
|
||||
net-scp (>= 1.1.2)
|
||||
net-ssh (>= 2.8.0)
|
||||
thin (1.6.3)
|
||||
daemons (~> 1.0, >= 1.0.9)
|
||||
eventmachine (~> 1.0)
|
||||
|
@ -302,6 +325,9 @@ DEPENDENCIES
|
|||
bootstrap-sass (~> 3.2.0.1)
|
||||
bootstrap_form
|
||||
bootswatch-rails
|
||||
capistrano (~> 3.1)
|
||||
capistrano-rails (~> 1.1)
|
||||
capistrano-rvm
|
||||
capybara
|
||||
coffee-rails (~> 4.1.0)
|
||||
database_cleaner
|
||||
|
|
18
Rakefile
18
Rakefile
|
@ -79,4 +79,22 @@ namespace :justask do
|
|||
puts "#{sprintf "%3d", u.id}. #{u.screen_name}"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Fixes the notifications"
|
||||
task fix_notifications: :environment do
|
||||
format = '%t (%c/%C) [%b>%i] %e'
|
||||
total = Notification.count
|
||||
progress = ProgressBar.create title: 'Processing notifications', format: format, starting_at: 0, total: total
|
||||
destroyed_count = 0
|
||||
|
||||
Notification.all.each do |n|
|
||||
if n.target.nil?
|
||||
n.destroy
|
||||
destroyed_count += 1
|
||||
end
|
||||
progress.increment
|
||||
end
|
||||
|
||||
puts "Purged #{destroyed_count} dead notifications."
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#= require nprogress
|
||||
#= require nprogress-turbolinks
|
||||
#= require growl
|
||||
#= require cheet
|
||||
#= require_tree .
|
||||
|
||||
NProgress.configure
|
||||
|
|
|
@ -8,18 +8,51 @@
|
|||
success: (data, status, jqxhr) ->
|
||||
if data.success
|
||||
($ "div#entries").prepend(data.render) # TODO: slideDown or something
|
||||
# GitHub issue #26:
|
||||
del_all_btn = ($ "button#ib-delete-all")
|
||||
del_all_btn.removeAttr 'disabled'
|
||||
del_all_btn[0].dataset.ibCount = 1
|
||||
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"
|
||||
|
||||
|
||||
($ document).on "click", "button#ib-delete-all", ->
|
||||
btn = ($ this)
|
||||
count = btn[0].dataset.ibCount
|
||||
if confirm "Really delete #{count} questions?"
|
||||
btn.button "loading"
|
||||
succ = no
|
||||
$.ajax
|
||||
url: '/ajax/delete_all_inbox'
|
||||
type: 'POST'
|
||||
dataType: 'json'
|
||||
success: (data, status, jqxhr) ->
|
||||
if data.success
|
||||
succ = yes
|
||||
entries = ($ "div#entries")
|
||||
entries.slideUp 400, ->
|
||||
entries.html("Nothing to see here.")
|
||||
entries.fadeIn()
|
||||
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"
|
||||
if succ
|
||||
btn.attr "disabled", "disabled" # this doesn't really work like I wanted it to…
|
||||
btn[0].dataset.ibCount = 0
|
||||
|
||||
|
||||
$(document).on "keydown", "textarea[name=ib-answer]", (evt) ->
|
||||
iid = $(this)[0].dataset.id
|
||||
if evt.keyCode == 13 and evt.ctrlKey
|
||||
# trigger warning:
|
||||
$("button[name=ib-answer][data-ib-id=#{iid}]").trigger 'click'
|
||||
|
||||
|
||||
$(document).on "click", "button[name=ib-answer]", ->
|
||||
btn = $(this)
|
||||
btn.button "loading"
|
||||
|
@ -48,6 +81,7 @@ $(document).on "click", "button[name=ib-answer]", ->
|
|||
btn.button "reset"
|
||||
$("textarea[name=ib-answer][data-id=#{iid}]").removeAttr "readonly"
|
||||
|
||||
|
||||
$(document).on "click", "button[name=ib-destroy]", ->
|
||||
if confirm 'Are you sure?'
|
||||
btn = $(this)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
cheet 'up up down down left right left right b a', ->
|
||||
($ "body").addClass 'fa-spin'
|
||||
($ "p.answerbox--question-text").each (i) -> ($ this).html ":^)"
|
|
@ -53,4 +53,8 @@ body {
|
|||
|
||||
.smiles {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.j2-lh {
|
||||
color: #fff;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
.answerbox .text-muted a, .answerbox .text-muted a:hover {
|
||||
.text-muted a, .answerbox .text-muted a:hover {
|
||||
color: $gray-dark;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
|
|
@ -33,4 +33,33 @@
|
|||
height: 40vh;
|
||||
background-color: darken($navbar-inverse-bg, 10%);
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.profile--panel .panel-heading {
|
||||
color: $brand-primary;
|
||||
border-bottom: 2px solid $brand-primary;
|
||||
background-color: #fff;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.profile--panel .panel-body {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.inbox--panel .panel-heading {
|
||||
color: $brand-info;
|
||||
border-bottom: 2px solid $brand-info;
|
||||
background-color: #fff;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.warning--panel .panel-heading {
|
||||
color: $brand-danger;
|
||||
border-bottom: 2px solid $brand-danger;
|
||||
background-color: #fff;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.profile--follow-btn {
|
||||
margin-top: 5px;
|
||||
}
|
|
@ -85,4 +85,20 @@ class Ajax::InboxController < ApplicationController
|
|||
@message = "Successfully deleted question."
|
||||
@success = true
|
||||
end
|
||||
|
||||
def remove_all
|
||||
begin
|
||||
Inbox.where(user: current_user).each { |i| i.remove }
|
||||
rescue
|
||||
@status = :err
|
||||
@message = "An error occurred"
|
||||
@success = false
|
||||
return
|
||||
end
|
||||
|
||||
@status = :okay
|
||||
@message = "Successfully deleted questions."
|
||||
@success = true
|
||||
render 'ajax/inbox/remove'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class UserController < ApplicationController
|
||||
def show
|
||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first
|
||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
||||
@answers = @user.answers.reverse_order.paginate(page: params[:page])
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
@ -23,7 +23,7 @@ class UserController < ApplicationController
|
|||
|
||||
def followers
|
||||
@title = 'Followers'
|
||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first
|
||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
||||
@users = @user.followers.reverse_order.paginate(page: params[:page])
|
||||
@type = :friend
|
||||
render 'show_follow'
|
||||
|
@ -31,9 +31,15 @@ class UserController < ApplicationController
|
|||
|
||||
def friends
|
||||
@title = 'Following'
|
||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first
|
||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
||||
@users = @user.friends.reverse_order.paginate(page: params[:page])
|
||||
@type = :friend
|
||||
render 'show_follow'
|
||||
end
|
||||
|
||||
def questions
|
||||
@title = 'Questions'
|
||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
||||
@questions = @user.questions.where(author_is_anonymous: false).reverse_order.paginate(page: params[:page])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,6 +33,15 @@ class User < ActiveRecord::Base
|
|||
|
||||
# validates :website, format: { with: WEBSITE_REGEX }
|
||||
|
||||
before_save do
|
||||
self.display_name = 'WRYYYYYYYY' if display_name == 'Dio Brando'
|
||||
self.website = if website.match %r{\Ahttps?://}
|
||||
website
|
||||
else
|
||||
"http://#{website}"
|
||||
end unless website.blank?
|
||||
end
|
||||
|
||||
def login=(login)
|
||||
@login = login
|
||||
end
|
||||
|
|
|
@ -1,19 +1,26 @@
|
|||
.container.j2-page
|
||||
= render 'layouts/messages'
|
||||
.alert.alert-info
|
||||
.row
|
||||
.col-md-9.col-sm-8.col-xs-12
|
||||
Out of questions?
|
||||
.col-md-3.col-sm-5.col-xs-12
|
||||
%button.btn.btn-block.btn-info{type: :button, id: 'ib-generate-question'} Get new question
|
||||
.row
|
||||
.col-md-3.col-xs-12.col-sm-3
|
||||
.panel.panel-default.inbox--panel
|
||||
.panel-heading
|
||||
%h3.panel-title Out of questions?
|
||||
.panel-body
|
||||
%button.btn.btn-block.btn-info{type: :button, id: 'ib-generate-question'} Get new question
|
||||
%a.btn.btn-block.btn-primary{target: '_blank', href: "https://twitter.com/intent/tweet?text=Ask%20me%20anything%21&url=#{show_user_profile_url(current_user.screen_name)}"} Share on Twitter
|
||||
.panel.panel-default.warning--panel
|
||||
.panel-heading
|
||||
%h3.panel-title Actions
|
||||
.panel-body
|
||||
%button.btn.btn-block.btn-danger{type: :button, id: 'ib-delete-all', disabled: (@inbox.empty? ? 'disabled' : nil), data: { ib_count: @inbox.count }} Delete all questions
|
||||
.col-md-9.col-xs-12.col-sm-9
|
||||
= render 'layouts/messages'
|
||||
#entries
|
||||
- @inbox.each do |i|
|
||||
= render 'inbox/entry', i: i
|
||||
|
||||
#entries
|
||||
- @inbox.each do |i|
|
||||
= render 'inbox/entry', i: i
|
||||
- if @inbox.empty?
|
||||
|
||||
- if @inbox.empty?
|
||||
|
||||
Nothing to see here.
|
||||
Nothing to see here.
|
||||
|
||||
= render "shared/links"
|
||||
- @inbox.update_all(new: false)
|
|
@ -4,7 +4,7 @@
|
|||
%button.navbar-toggle{"data-target" => "#j2-main-navbar-collapse", "data-toggle" => "collapse", type: "button"}
|
||||
%span.sr-only Toggle navigation
|
||||
- if user_signed_in?
|
||||
- unless inbox_count.nil?
|
||||
- unless inbox_count.nil? or notification_count.nil?
|
||||
%span.icon-bar.navbar--inbox-animation
|
||||
%span.icon-bar.navbar--inbox-animation
|
||||
%span.icon-bar.navbar--inbox-animation
|
||||
|
|
|
@ -9,7 +9,11 @@
|
|||
%h6.text-muted.media-heading.answerbox--question-user
|
||||
= user_screen_name a.question.user, a.question.author_is_anonymous
|
||||
asked
|
||||
= time_ago_in_words(a.question.created_at)
|
||||
- if @user.nil? or a.question.author_is_anonymous
|
||||
= time_ago_in_words(a.question.created_at)
|
||||
- else
|
||||
%a{href: show_user_question_path(a.question.user.screen_name, a.question.id)}
|
||||
= time_ago_in_words(a.question.created_at)
|
||||
ago
|
||||
- unless a.question.author_is_anonymous
|
||||
- if a.question.answer_count > 1
|
||||
|
@ -45,6 +49,6 @@
|
|||
.row
|
||||
.col-md-6.col-md-offset-6.col-sm-8.col-sm-offset-4.col-xs-6.col-xs-offset-6.text-right
|
||||
= render 'shared/answerbox_buttons', a: a
|
||||
.panel-footer{id: "ab-comments-section-#{a.id}", style: 'display: none'}
|
||||
.panel-footer{id: "ab-comments-section-#{a.id}", style: @display_all.nil? ? 'display: none' : nil }
|
||||
%div{id: "ab-smiles-#{a.id}"}= render 'shared/smiles', a: a
|
||||
%div{id: "ab-comments-#{a.id}"}= render 'shared/comments', a: a
|
||||
%div{id: "ab-comments-#{a.id}"}= render 'shared/comments', a: a
|
|
@ -12,9 +12,10 @@
|
|||
%button.btn.btn-info.btn-sm{type: :button, name: 'ab-smile', data: { a_id: a.id, action: :smile }}
|
||||
%i.fa.fa-smile-o
|
||||
%span{id: "ab-smile-count-#{a.id}"}= a.smile_count
|
||||
%button.btn.btn-primary.btn-sm{type: :button, name: 'ab-comments', data: { a_id: a.id, state: :hidden }}
|
||||
%i.fa.fa-comments
|
||||
%span{id: "ab-comment-count-#{a.id}"}= a.comment_count
|
||||
- unless @display_all
|
||||
%button.btn.btn-primary.btn-sm{type: :button, name: 'ab-comments', data: { a_id: a.id, state: :hidden }}
|
||||
%i.fa.fa-comments
|
||||
%span{id: "ab-comment-count-#{a.id}"}= a.comment_count
|
||||
- if privileged? a.user
|
||||
%button.btn.btn-danger.btn-sm{name: 'ab-destroy', data: { a_id: a.id }}
|
||||
%i.fa.fa-trash-o
|
|
@ -0,0 +1,16 @@
|
|||
.panel.panel-default
|
||||
.panel-body
|
||||
.media
|
||||
.media-body
|
||||
%h6.media-heading.text-muted.answerbox--question-user
|
||||
= user_screen_name q.user
|
||||
asked
|
||||
%a{href: show_user_question_path(q.user.screen_name, q.id)}
|
||||
= time_ago_in_words(q.created_at)
|
||||
ago
|
||||
- if q.answer_count > 1
|
||||
·
|
||||
%a{href: show_user_question_path(q.user.screen_name, q.id)}
|
||||
#{q.answer_count} answers
|
||||
%p.answerbox--question-text
|
||||
= q.content
|
|
@ -23,7 +23,7 @@
|
|||
- unless user_signed_in?
|
||||
#question-box-promote.row{:style => "display: none;"}
|
||||
.row
|
||||
.col-xs-12
|
||||
.col-xs-12.text-center
|
||||
%strong Your question has been sent.
|
||||
.row
|
||||
.col-sm-1
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
- if user_signed_in?
|
||||
- type ||= :nil
|
||||
- if user == current_user
|
||||
%a.btn.btn-default.btn-block{href: edit_user_profile_path} Edit profile
|
||||
%a.btn.btn-default.btn-block.profile--follow-btn{href: edit_user_profile_path} Edit profile
|
||||
- else
|
||||
- if current_user.following? user
|
||||
%button#editprofile.btn.btn-default.btn-block{type: :button, name: 'user-action', data: { action: :unfollow, type: type, target: user.screen_name }}
|
||||
%button#editprofile.btn.btn-default.btn-block.profile--follow-btn{type: :button, name: 'user-action', data: { action: :unfollow, type: type, target: user.screen_name }}
|
||||
Unfollow
|
||||
- else
|
||||
%button#editprofile.btn.btn-primary.btn-block{type: :button, name: 'user-action', data: { action: :follow, type: type, target: user.screen_name }}
|
||||
%button#editprofile.btn.btn-primary.btn-block.profile--follow-btn{type: :button, name: 'user-action', data: { action: :follow, type: type, target: user.screen_name }}
|
||||
Follow
|
|
@ -23,20 +23,5 @@
|
|||
%p.profile--text
|
||||
%i.fa.fa-location-arrow
|
||||
= @user.location
|
||||
.row
|
||||
%a{href: show_user_followers_path(@user.screen_name)}
|
||||
.col-md-6.col-sm-6.col-xs-6
|
||||
%h4.entry-text#follower-count= @user.follower_count
|
||||
%h6.entry-subtext Followers
|
||||
%a{href: show_user_friends_path(@user.screen_name)}
|
||||
.col-md-6.col-sm-6.col-xs-6
|
||||
%h4.entry-text#friend-count= @user.friend_count
|
||||
%h6.entry-subtext Following
|
||||
.row
|
||||
.col-md-6.col-sm-6.col-xs-6
|
||||
%h4.entry-text#asked-count= @user.asked_count
|
||||
%h6.entry-subtext Questions
|
||||
.col-md-6.col-sm-6.col-xs-6
|
||||
%h4.entry-text#answered-count= @user.answered_count
|
||||
%h6.entry-subtext Answers
|
||||
= render 'user/actions', user: @user, type: :follower
|
||||
= render 'user/actions', user: @user, type: :follower
|
||||
= render 'user/stats', user: @user
|
|
@ -0,0 +1,22 @@
|
|||
.panel.panel-default.profile--panel
|
||||
.panel-heading
|
||||
%h3.panel-title Stats
|
||||
.panel-body
|
||||
.row
|
||||
%a{href: show_user_followers_path(@user.screen_name)}
|
||||
.col-md-6.col-sm-6.col-xs-6
|
||||
%h4.entry-text#follower-count= @user.follower_count
|
||||
%h6.entry-subtext Followers
|
||||
%a{href: show_user_friends_path(@user.screen_name)}
|
||||
.col-md-6.col-sm-6.col-xs-6
|
||||
%h4.entry-text#friend-count= @user.friend_count
|
||||
%h6.entry-subtext Following
|
||||
.row
|
||||
%a{href: show_user_questions_path(@user.screen_name)}
|
||||
.col-md-6.col-sm-6.col-xs-6
|
||||
%h4.entry-text#asked-count= @user.asked_count
|
||||
%h6.entry-subtext Questions
|
||||
%a{href: show_user_profile_path(@user.screen_name)}
|
||||
.col-md-6.col-sm-6.col-xs-6
|
||||
%h4.entry-text#answered-count= @user.answered_count
|
||||
%h6.entry-subtext Answers
|
|
@ -0,0 +1,18 @@
|
|||
.profile--header
|
||||
.container.j2-page
|
||||
.col-md-4.col-xs-12.col-sm-4
|
||||
= render 'user/profile_info'
|
||||
.hidden-xs= render 'shared/links'
|
||||
.col-md-8.col-xs-12.col-sm-8
|
||||
%h1.j2-lh.hidden-xs= @title
|
||||
%h1.visible-xs= @title
|
||||
#questions
|
||||
- @questions.each do |q|
|
||||
= render 'shared/question', q: q
|
||||
|
||||
#pagination= will_paginate @questions, renderer: BootstrapPagination::Rails, page_links: false
|
||||
|
||||
- if @questions.next_page
|
||||
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @questions.current_page }}
|
||||
Load more
|
||||
.visible-xs= render 'shared/links'
|
|
@ -0,0 +1,8 @@
|
|||
$('#questions').append('<% @questions.each do |q|
|
||||
%><%= j render 'shared/question', q: q
|
||||
%><% end %>');
|
||||
<% if @questions.next_page %>
|
||||
$('#pagination').html('<%= j will_paginate @questions, renderer: BootstrapPagination::Rails, page_links: false %>');
|
||||
<% else %>
|
||||
$('#pagination, #load-more-btn').remove();
|
||||
<% end %>
|
|
@ -1,9 +1,9 @@
|
|||
.profile--header
|
||||
.container.j2-page
|
||||
.col-md-3.col-xs-12.col-sm-3
|
||||
.col-md-4.col-xs-12.col-sm-4
|
||||
= render 'user/profile_info'
|
||||
.hidden-xs= render 'shared/links'
|
||||
.col-md-9.col-xs-12.col-sm-9
|
||||
.col-md-8.col-xs-12.col-sm-8
|
||||
= render 'shared/questionbox'
|
||||
#answers
|
||||
- @answers.each do |a|
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
.profile--header
|
||||
.container.j2-page
|
||||
.col-md-3.col-xs-12.col-sm-3
|
||||
.col-md-4.col-xs-12.col-sm-4
|
||||
= render 'user/profile_info'
|
||||
.hidden-xs= render 'shared/links'
|
||||
.col-md-9.col-xs-12.col-sm-9
|
||||
%h1= @title
|
||||
.col-md-8.col-xs-12.col-sm-8
|
||||
%h1.j2-lh.hidden-xs= @title
|
||||
%h1.visible-xs= @title
|
||||
#users
|
||||
- @users.each do |user|
|
||||
.col-sm-6
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'cap' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('capistrano', 'cap')
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'capify' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
|
||||
load Gem.bin_path('capistrano', 'capify')
|
|
@ -0,0 +1,31 @@
|
|||
# config valid only for current version of Capistrano
|
||||
lock '3.3.5'
|
||||
|
||||
set :application, 'justask'
|
||||
set :repo_url, 'git@git.rrerr.net:justask/justask.git'
|
||||
ask :branch, :master
|
||||
set :deploy_to, '/home/justask/cap/'
|
||||
set :scm, :git
|
||||
set :format, :pretty
|
||||
set :log_level, :debug
|
||||
|
||||
# RVM
|
||||
set :rvm_type, :user
|
||||
set :rvm_ruby_version, '2.0.0'
|
||||
|
||||
# Rails
|
||||
set :conditionally_migrate, true
|
||||
|
||||
namespace :deploy do
|
||||
|
||||
after :updated do
|
||||
|
||||
end
|
||||
|
||||
after :restart, :clear_cache do
|
||||
on roles(:web), in: :groups, limit: 3, wait: 10 do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
server 'rrerr.net', user: 'justask', roles: %w{web app}
|
||||
|
||||
set :ssh_options, {
|
||||
keys: %w(~/.ssh/id_rsa),
|
||||
forward_agent: false,
|
||||
auth_methods: %w(publickey)
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
# Simple Role Syntax
|
||||
# ==================
|
||||
# Supports bulk-adding hosts to roles, the primary server in each group
|
||||
# is considered to be the first unless any hosts have the primary
|
||||
# property set. Don't declare `role :all`, it's a meta role.
|
||||
|
||||
role :app, %w{deploy@example.com}
|
||||
role :web, %w{deploy@example.com}
|
||||
role :db, %w{deploy@example.com}
|
||||
|
||||
|
||||
# Extended Server Syntax
|
||||
# ======================
|
||||
# This can be used to drop a more detailed server definition into the
|
||||
# server list. The second argument is a, or duck-types, Hash and is
|
||||
# used to set extended properties on the server.
|
||||
|
||||
server 'example.com', user: 'deploy', roles: %w{web app}, my_property: :my_value
|
||||
|
||||
|
||||
# Custom SSH Options
|
||||
# ==================
|
||||
# You may pass any option but keep in mind that net/ssh understands a
|
||||
# limited set of options, consult[net/ssh documentation](http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start).
|
||||
#
|
||||
# Global options
|
||||
# --------------
|
||||
# set :ssh_options, {
|
||||
# keys: %w(/home/rlisowski/.ssh/id_rsa),
|
||||
# forward_agent: false,
|
||||
# auth_methods: %w(password)
|
||||
# }
|
||||
#
|
||||
# And/or per server (overrides global)
|
||||
# ------------------------------------
|
||||
# server 'example.com',
|
||||
# user: 'user_name',
|
||||
# roles: %w{web app},
|
||||
# ssh_options: {
|
||||
# user: 'user_name', # overrides user setting above
|
||||
# keys: %w(/home/user_name/.ssh/id_rsa),
|
||||
# forward_agent: false,
|
||||
# auth_methods: %w(publickey password)
|
||||
# # password: 'please use keys'
|
||||
# }
|
|
@ -46,6 +46,7 @@ Rails.application.routes.draw do
|
|||
match '/answer', to: 'inbox#destroy', via: :post, as: :answer
|
||||
match '/generate_question', to: 'inbox#create', via: :post, as: :generate_question
|
||||
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 '/destroy_answer', to: 'answer#destroy', via: :post, as: :destroy_answer
|
||||
match '/create_friend', to: 'friend#create', via: :post, as: :create_friend
|
||||
match '/destroy_friend', to: 'friend#destroy', via: :post, as: :destroy_friend
|
||||
|
@ -71,4 +72,5 @@ Rails.application.routes.draw do
|
|||
match '/:username/q/:id', to: 'question#show', via: 'get', as: :show_user_question_alt
|
||||
match '/:username/followers(/p/:page)', to: 'user#followers', via: 'get', as: :show_user_followers_alt, defaults: {page: 1}
|
||||
match '/:username/friends(/p/:page)', to: 'user#friends', via: 'get', as: :show_user_friends_alt, defaults: {page: 1}
|
||||
match '/:username/questions(/p/:page)', to: 'user#questions', via: 'get', as: :show_user_questions, defaults: {page: 1}
|
||||
end
|
||||
|
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Louis Acresti
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
(function (global) {
|
||||
'use strict';
|
||||
|
||||
var cheet,
|
||||
sequences = {},
|
||||
keys = {
|
||||
backspace: 8,
|
||||
tab: 9,
|
||||
enter: 13,
|
||||
'return': 13,
|
||||
shift: 16,
|
||||
'⇧': 16,
|
||||
control: 17,
|
||||
ctrl: 17,
|
||||
'⌃': 17,
|
||||
alt: 18,
|
||||
option: 18,
|
||||
'⌥': 18,
|
||||
pause: 19,
|
||||
capslock: 20,
|
||||
esc: 27,
|
||||
space: 32,
|
||||
pageup: 33,
|
||||
pagedown: 34,
|
||||
end: 35,
|
||||
home: 36,
|
||||
left: 37,
|
||||
L: 37,
|
||||
'←': 37,
|
||||
up: 38,
|
||||
U: 38,
|
||||
'↑': 38,
|
||||
right: 39,
|
||||
R: 39,
|
||||
'→': 39,
|
||||
down: 40,
|
||||
D: 40,
|
||||
'↓': 40,
|
||||
insert: 45,
|
||||
'delete': 46,
|
||||
'0': 48,
|
||||
'1': 49,
|
||||
'2': 50,
|
||||
'3': 51,
|
||||
'4': 52,
|
||||
'5': 53,
|
||||
'6': 54,
|
||||
'7': 55,
|
||||
'8': 56,
|
||||
'9': 57,
|
||||
a: 65,
|
||||
b: 66,
|
||||
c: 67,
|
||||
d: 68,
|
||||
e: 69,
|
||||
f: 70,
|
||||
g: 71,
|
||||
h: 72,
|
||||
i: 73,
|
||||
j: 74,
|
||||
k: 75,
|
||||
l: 76,
|
||||
m: 77,
|
||||
n: 78,
|
||||
o: 79,
|
||||
p: 80,
|
||||
q: 81,
|
||||
r: 82,
|
||||
s: 83,
|
||||
t: 84,
|
||||
u: 85,
|
||||
v: 86,
|
||||
w: 87,
|
||||
x: 88,
|
||||
y: 89,
|
||||
z: 90,
|
||||
'⌘': 91,
|
||||
command: 91,
|
||||
kp_0: 96,
|
||||
kp_1: 97,
|
||||
kp_2: 98,
|
||||
kp_3: 99,
|
||||
kp_4: 100,
|
||||
kp_5: 101,
|
||||
kp_6: 102,
|
||||
kp_7: 103,
|
||||
kp_8: 104,
|
||||
kp_9: 105,
|
||||
kp_multiply: 106,
|
||||
kp_plus: 107,
|
||||
kp_minus: 109,
|
||||
kp_decimal: 110,
|
||||
kp_divide: 111,
|
||||
f1: 112,
|
||||
f2: 113,
|
||||
f3: 114,
|
||||
f4: 115,
|
||||
f5: 116,
|
||||
f6: 117,
|
||||
f7: 118,
|
||||
f8: 119,
|
||||
f9: 120,
|
||||
f10: 121,
|
||||
f11: 122,
|
||||
f12: 123,
|
||||
equal: 187,
|
||||
'=': 187,
|
||||
comma: 188,
|
||||
',': 188,
|
||||
minus: 189,
|
||||
'-': 189,
|
||||
period: 190,
|
||||
'.': 190
|
||||
},
|
||||
Sequence,
|
||||
NOOP = function NOOP() {},
|
||||
held = {};
|
||||
|
||||
Sequence = function Sequence (str, next, fail, done) {
|
||||
var i;
|
||||
|
||||
this.str = str;
|
||||
this.next = next ? next : NOOP;
|
||||
this.fail = fail ? fail : NOOP;
|
||||
this.done = done ? done : NOOP;
|
||||
|
||||
this.seq = str.split(' ');
|
||||
this.keys = [];
|
||||
|
||||
for (i=0; i<this.seq.length; ++i) {
|
||||
this.keys.push(keys[this.seq[i]]);
|
||||
}
|
||||
|
||||
this.idx = 0;
|
||||
};
|
||||
|
||||
Sequence.prototype.keydown = function keydown (keyCode) {
|
||||
var i = this.idx;
|
||||
if (keyCode !== this.keys[i]) {
|
||||
if (i > 0) {
|
||||
this.reset();
|
||||
this.fail(this.str);
|
||||
cheet.__fail(this.str);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.next(this.str, this.seq[i], i, this.seq);
|
||||
cheet.__next(this.str, this.seq[i], i, this.seq);
|
||||
|
||||
if (++this.idx === this.keys.length) {
|
||||
this.done(this.str);
|
||||
cheet.__done(this.str);
|
||||
this.reset();
|
||||
}
|
||||
};
|
||||
|
||||
Sequence.prototype.reset = function () {
|
||||
this.idx = 0;
|
||||
};
|
||||
|
||||
cheet = function cheet (str, handlers) {
|
||||
var next, fail, done;
|
||||
|
||||
if (typeof handlers === 'function') {
|
||||
done = handlers;
|
||||
} else if (handlers !== null && handlers !== undefined) {
|
||||
next = handlers.next;
|
||||
fail = handlers.fail;
|
||||
done = handlers.done;
|
||||
}
|
||||
|
||||
sequences[str] = new Sequence(str, next, fail, done);
|
||||
};
|
||||
|
||||
cheet.disable = function disable (str) {
|
||||
delete sequences[str];
|
||||
};
|
||||
|
||||
function keydown (e) {
|
||||
var id,
|
||||
k = e ? e.keyCode : event.keyCode;
|
||||
|
||||
if (held[k]) return;
|
||||
held[k] = true;
|
||||
|
||||
for (id in sequences) {
|
||||
sequences[id].keydown(k);
|
||||
}
|
||||
}
|
||||
|
||||
function keyup (e) {
|
||||
var k = e ? e.keyCode : event.keyCode;
|
||||
held[k] = false;
|
||||
}
|
||||
|
||||
function resetHeldKeys (e) {
|
||||
var k;
|
||||
for (k in held) {
|
||||
held[k] = false;
|
||||
}
|
||||
}
|
||||
|
||||
function on (obj, type, fn) {
|
||||
if (obj.addEventListener) {
|
||||
obj.addEventListener(type, fn, false);
|
||||
} else if (obj.attachEvent) {
|
||||
obj['e' + type + fn] = fn;
|
||||
obj[type + fn] = function () {
|
||||
obj['e' + type + fn](window.event);
|
||||
};
|
||||
obj.attachEvent('on' + type, obj[type + fn]);
|
||||
}
|
||||
}
|
||||
|
||||
on(window, 'keydown', keydown);
|
||||
on(window, 'keyup', keyup);
|
||||
on(window, 'blur', resetHeldKeys);
|
||||
on(window, 'focus', resetHeldKeys);
|
||||
|
||||
cheet.__next = NOOP;
|
||||
cheet.next = function next (fn) {
|
||||
cheet.__next = fn === null ? NOOP : fn;
|
||||
};
|
||||
|
||||
cheet.__fail = NOOP;
|
||||
cheet.fail = function fail (fn) {
|
||||
cheet.__fail = fn === null ? NOOP : fn;
|
||||
};
|
||||
|
||||
cheet.__done = NOOP;
|
||||
cheet.done = function done (fn) {
|
||||
cheet.__done = fn === null ? NOOP : fn;
|
||||
};
|
||||
|
||||
cheet.reset = function reset (id) {
|
||||
var seq = sequences[id];
|
||||
if (!(seq instanceof Sequence)) {
|
||||
console.warn('cheet: Unknown sequence: ' + id);
|
||||
return;
|
||||
}
|
||||
|
||||
seq.reset();
|
||||
};
|
||||
|
||||
global.cheet = cheet;
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define([], function () { return cheet; });
|
||||
} else if (typeof module !== 'undefined' && module !== null) {
|
||||
module.exports = cheet;
|
||||
}
|
||||
|
||||
})(this);
|
110
public/404.html
110
public/404.html
|
@ -1,59 +1,75 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The page you were looking for doesn't exist (404)</title>
|
||||
<title>Page not found!!1! (404)</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
body {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
body {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
a { color: #4183c4; text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
|
||||
div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #00A0F0 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 100%;
|
||||
color: #0b79C5;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #00A0F0 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
h1 {
|
||||
font-size: 100%;
|
||||
color: #0b79C5;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
div.dialog img { margin-bottom: 0.5em; }
|
||||
|
||||
div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
div.links {
|
||||
margin-top: 2em;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
div.links a {
|
||||
color: #666;
|
||||
font-weight: 200;
|
||||
font-size: 14px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="dialog">
|
||||
<div>
|
||||
|
@ -62,5 +78,9 @@
|
|||
</div>
|
||||
<p>If you think you found a bug, please let us know.</p>
|
||||
</div>
|
||||
<div class="links">
|
||||
<a href="https://github.com/justask/justask-bugs/issues">Bug tracker</a> ·
|
||||
<a href="https://twitter.com/justask_2">Twitter</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
110
public/422.html
110
public/422.html
|
@ -4,63 +4,83 @@
|
|||
<title>The change you wanted was rejected (422)</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
body {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
body {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
a { color: #4183c4; text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
|
||||
div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #00A0F0 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 100%;
|
||||
color: #0b79C5;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #00A0F0 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
h1 {
|
||||
font-size: 100%;
|
||||
color: #0b79C5;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
div.dialog img { margin-bottom: 0.5em; }
|
||||
|
||||
div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
div.links {
|
||||
margin-top: 2em;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
div.links a {
|
||||
color: #666;
|
||||
font-weight: 200;
|
||||
font-size: 14px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="dialog">
|
||||
<div>
|
||||
<h1>The change you wanted was rejected.</h1>
|
||||
<p>Maybe you tried to change something you didn't have access to.</p>
|
||||
</div>
|
||||
<p>If you think you found a bug, please let us know.</p>
|
||||
<p>If you think you found a bug, please <a href="https://github.com/justask/justask-bugs/issues">please let us know</a>.</p>
|
||||
</div>
|
||||
<div class="links">
|
||||
<a href="https://github.com/justask/justask-bugs/issues">Bug tracker</a> ·
|
||||
<a href="https://twitter.com/justask_2">Twitter</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
112
public/500.html
112
public/500.html
|
@ -4,62 +4,82 @@
|
|||
<title>We're sorry, but something went wrong (500)</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
body {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
body {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
a { color: #4183c4; text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
|
||||
div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #00A0F0 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 100%;
|
||||
color: #0b79C5;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #00A0F0 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
h1 {
|
||||
font-size: 100%;
|
||||
color: #0b79C5;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
div.dialog img { margin-bottom: 0.5em; }
|
||||
|
||||
div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
div.links {
|
||||
margin-top: 2em;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
div.links a {
|
||||
color: #666;
|
||||
font-weight: 200;
|
||||
font-size: 14px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="dialog">
|
||||
<div>
|
||||
<h1>We're sorry, but something went wrong.</h1>
|
||||
<h1>Looks like something went wrong!</h1>
|
||||
</div>
|
||||
<p>If you think you found a bug, please let us know.</p>
|
||||
<p>This usually happens due to an error in our code. If you think you found a bug, <a href="https://github.com/justask/justask-bugs/issues">please let us know</a>.</p>
|
||||
</div>
|
||||
<div class="links">
|
||||
<a href="https://github.com/justask/justask-bugs/issues">Bug tracker</a> ·
|
||||
<a href="https://twitter.com/justask_2">Twitter</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Unicorn! (502)</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
body {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a { color: #4183c4; text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
|
||||
div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
|
||||
div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #00A0F0 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 100%;
|
||||
color: #0b79C5;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
div.dialog img { margin-bottom: 0.5em; }
|
||||
|
||||
div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
div.links {
|
||||
margin-top: 2em;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
div.links a {
|
||||
color: #666;
|
||||
font-weight: 200;
|
||||
font-size: 14px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="dialog">
|
||||
<div>
|
||||
<h1>This page takes way too long to load!</h1>
|
||||
<img src="images/angry_unicorn.png" alt="Unicorn">
|
||||
</div>
|
||||
<p>Sorry about that. Please try refreshing and contact us if the problem persists.</p>
|
||||
</div>
|
||||
<div class="links">
|
||||
<a href="https://github.com/justask/justask-bugs/issues">Bug tracker</a> ·
|
||||
<a href="https://twitter.com/justask_2">Twitter</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
|
@ -0,0 +1,9 @@
|
|||
FactoryGirl.define do
|
||||
factory :notification do
|
||||
target_type "MyString"
|
||||
target_id 1
|
||||
recipient_id 1
|
||||
new false
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
include Warden::Test::Helpers
|
||||
Warden.test_mode!
|
||||
|
||||
feature "User profile page", :devise do
|
||||
|
||||
after :each do
|
||||
Warden.test_reset!
|
||||
end
|
||||
|
||||
scenario "user gets followed", js: true do
|
||||
me = FactoryGirl.create(:user)
|
||||
other = FactoryGirl.create(:user)
|
||||
|
||||
login_as me, scope: :user
|
||||
visit show_user_profile_path(other.screen_name)
|
||||
page.driver.render Rails.root.join("tmp/#{Time.now.to_i}_1.png"), full: true
|
||||
|
||||
click_button "Follow"
|
||||
wait_for_ajax
|
||||
page.driver.render Rails.root.join("tmp/#{Time.now.to_i}_2.png"), full: true
|
||||
|
||||
expect(page).to have_text("FOLLOWING")
|
||||
|
||||
click_link 'Followers'
|
||||
page.driver.render Rails.root.join("tmp/#{Time.now.to_i}_3.png"), full: true
|
||||
expect(page).to have_text(me.screen_name)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Notification, :type => :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
Loading…
Reference in New Issue