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
|
group :development do
|
||||||
gem 'spring'
|
gem 'spring'
|
||||||
|
|
||||||
|
# Capistrano for deployment
|
||||||
|
gem 'capistrano', '~> 3.1'
|
||||||
|
gem 'capistrano-rvm', group: :rvm
|
||||||
|
gem 'capistrano-rails', '~> 1.1'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :production do
|
group :production do
|
||||||
|
|
26
Gemfile.lock
26
Gemfile.lock
|
@ -44,6 +44,21 @@ GEM
|
||||||
railties (>= 3.1)
|
railties (>= 3.1)
|
||||||
buftok (0.2.0)
|
buftok (0.2.0)
|
||||||
builder (3.2.2)
|
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)
|
capybara (2.4.4)
|
||||||
mime-types (>= 1.16)
|
mime-types (>= 1.16)
|
||||||
nokogiri (>= 1.3.3)
|
nokogiri (>= 1.3.3)
|
||||||
|
@ -60,6 +75,7 @@ GEM
|
||||||
coffee-script-source
|
coffee-script-source
|
||||||
execjs
|
execjs
|
||||||
coffee-script-source (1.8.0)
|
coffee-script-source (1.8.0)
|
||||||
|
colorize (0.7.5)
|
||||||
connection_pool (2.1.0)
|
connection_pool (2.1.0)
|
||||||
daemons (1.1.9)
|
daemons (1.1.9)
|
||||||
database_cleaner (1.3.0)
|
database_cleaner (1.3.0)
|
||||||
|
@ -131,6 +147,9 @@ GEM
|
||||||
mysql2 (0.3.17)
|
mysql2 (0.3.17)
|
||||||
naught (1.0.0)
|
naught (1.0.0)
|
||||||
nested_form (0.3.2)
|
nested_form (0.3.2)
|
||||||
|
net-scp (1.2.1)
|
||||||
|
net-ssh (>= 2.6.5)
|
||||||
|
net-ssh (2.9.1)
|
||||||
nokogiri (1.6.5)
|
nokogiri (1.6.5)
|
||||||
mini_portile (~> 0.6.0)
|
mini_portile (~> 0.6.0)
|
||||||
nprogress-rails (0.1.6.3)
|
nprogress-rails (0.1.6.3)
|
||||||
|
@ -254,6 +273,10 @@ GEM
|
||||||
actionpack (>= 3.0)
|
actionpack (>= 3.0)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
sprockets (>= 2.8, < 4.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)
|
thin (1.6.3)
|
||||||
daemons (~> 1.0, >= 1.0.9)
|
daemons (~> 1.0, >= 1.0.9)
|
||||||
eventmachine (~> 1.0)
|
eventmachine (~> 1.0)
|
||||||
|
@ -302,6 +325,9 @@ DEPENDENCIES
|
||||||
bootstrap-sass (~> 3.2.0.1)
|
bootstrap-sass (~> 3.2.0.1)
|
||||||
bootstrap_form
|
bootstrap_form
|
||||||
bootswatch-rails
|
bootswatch-rails
|
||||||
|
capistrano (~> 3.1)
|
||||||
|
capistrano-rails (~> 1.1)
|
||||||
|
capistrano-rvm
|
||||||
capybara
|
capybara
|
||||||
coffee-rails (~> 4.1.0)
|
coffee-rails (~> 4.1.0)
|
||||||
database_cleaner
|
database_cleaner
|
||||||
|
|
18
Rakefile
18
Rakefile
|
@ -79,4 +79,22 @@ namespace :justask do
|
||||||
puts "#{sprintf "%3d", u.id}. #{u.screen_name}"
|
puts "#{sprintf "%3d", u.id}. #{u.screen_name}"
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#= require nprogress
|
#= require nprogress
|
||||||
#= require nprogress-turbolinks
|
#= require nprogress-turbolinks
|
||||||
#= require growl
|
#= require growl
|
||||||
|
#= require cheet
|
||||||
#= require_tree .
|
#= require_tree .
|
||||||
|
|
||||||
NProgress.configure
|
NProgress.configure
|
||||||
|
|
|
@ -8,18 +8,51 @@
|
||||||
success: (data, status, jqxhr) ->
|
success: (data, status, jqxhr) ->
|
||||||
if data.success
|
if data.success
|
||||||
($ "div#entries").prepend(data.render) # TODO: slideDown or something
|
($ "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) ->
|
error: (jqxhr, status, error) ->
|
||||||
console.log jqxhr, status, error
|
console.log jqxhr, status, error
|
||||||
showNotification "An error occurred, a developer should check the console for details", false
|
showNotification "An error occurred, a developer should check the console for details", false
|
||||||
complete: (jqxhr, status) ->
|
complete: (jqxhr, status) ->
|
||||||
btn.button "reset"
|
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) ->
|
$(document).on "keydown", "textarea[name=ib-answer]", (evt) ->
|
||||||
iid = $(this)[0].dataset.id
|
iid = $(this)[0].dataset.id
|
||||||
if evt.keyCode == 13 and evt.ctrlKey
|
if evt.keyCode == 13 and evt.ctrlKey
|
||||||
# trigger warning:
|
# trigger warning:
|
||||||
$("button[name=ib-answer][data-ib-id=#{iid}]").trigger 'click'
|
$("button[name=ib-answer][data-ib-id=#{iid}]").trigger 'click'
|
||||||
|
|
||||||
|
|
||||||
$(document).on "click", "button[name=ib-answer]", ->
|
$(document).on "click", "button[name=ib-answer]", ->
|
||||||
btn = $(this)
|
btn = $(this)
|
||||||
btn.button "loading"
|
btn.button "loading"
|
||||||
|
@ -48,6 +81,7 @@ $(document).on "click", "button[name=ib-answer]", ->
|
||||||
btn.button "reset"
|
btn.button "reset"
|
||||||
$("textarea[name=ib-answer][data-id=#{iid}]").removeAttr "readonly"
|
$("textarea[name=ib-answer][data-id=#{iid}]").removeAttr "readonly"
|
||||||
|
|
||||||
|
|
||||||
$(document).on "click", "button[name=ib-destroy]", ->
|
$(document).on "click", "button[name=ib-destroy]", ->
|
||||||
if confirm 'Are you sure?'
|
if confirm 'Are you sure?'
|
||||||
btn = $(this)
|
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 ":^)"
|
|
@ -54,3 +54,7 @@ body {
|
||||||
.smiles {
|
.smiles {
|
||||||
margin-bottom: 7px;
|
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;
|
color: $gray-dark;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,3 +34,32 @@
|
||||||
background-color: darken($navbar-inverse-bg, 10%);
|
background-color: darken($navbar-inverse-bg, 10%);
|
||||||
background-size: cover;
|
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."
|
@message = "Successfully deleted question."
|
||||||
@success = true
|
@success = true
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class UserController < ApplicationController
|
class UserController < ApplicationController
|
||||||
def show
|
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])
|
@answers = @user.answers.reverse_order.paginate(page: params[:page])
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
|
@ -23,7 +23,7 @@ class UserController < ApplicationController
|
||||||
|
|
||||||
def followers
|
def followers
|
||||||
@title = '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])
|
@users = @user.followers.reverse_order.paginate(page: params[:page])
|
||||||
@type = :friend
|
@type = :friend
|
||||||
render 'show_follow'
|
render 'show_follow'
|
||||||
|
@ -31,9 +31,15 @@ class UserController < ApplicationController
|
||||||
|
|
||||||
def friends
|
def friends
|
||||||
@title = 'Following'
|
@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])
|
@users = @user.friends.reverse_order.paginate(page: params[:page])
|
||||||
@type = :friend
|
@type = :friend
|
||||||
render 'show_follow'
|
render 'show_follow'
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -33,6 +33,15 @@ class User < ActiveRecord::Base
|
||||||
|
|
||||||
# validates :website, format: { with: WEBSITE_REGEX }
|
# 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)
|
def login=(login)
|
||||||
@login = login
|
@login = login
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
.container.j2-page
|
.container.j2-page
|
||||||
= render 'layouts/messages'
|
|
||||||
.alert.alert-info
|
|
||||||
.row
|
.row
|
||||||
.col-md-9.col-sm-8.col-xs-12
|
.col-md-3.col-xs-12.col-sm-3
|
||||||
Out of questions?
|
.panel.panel-default.inbox--panel
|
||||||
.col-md-3.col-sm-5.col-xs-12
|
.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
|
%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
|
#entries
|
||||||
- @inbox.each do |i|
|
- @inbox.each do |i|
|
||||||
= render 'inbox/entry', i: i
|
= render 'inbox/entry', i: i
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
%button.navbar-toggle{"data-target" => "#j2-main-navbar-collapse", "data-toggle" => "collapse", type: "button"}
|
%button.navbar-toggle{"data-target" => "#j2-main-navbar-collapse", "data-toggle" => "collapse", type: "button"}
|
||||||
%span.sr-only Toggle navigation
|
%span.sr-only Toggle navigation
|
||||||
- if user_signed_in?
|
- 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
|
%span.icon-bar.navbar--inbox-animation
|
||||||
%span.icon-bar.navbar--inbox-animation
|
%span.icon-bar.navbar--inbox-animation
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
%h6.text-muted.media-heading.answerbox--question-user
|
%h6.text-muted.media-heading.answerbox--question-user
|
||||||
= user_screen_name a.question.user, a.question.author_is_anonymous
|
= user_screen_name a.question.user, a.question.author_is_anonymous
|
||||||
asked
|
asked
|
||||||
|
- 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)
|
= time_ago_in_words(a.question.created_at)
|
||||||
ago
|
ago
|
||||||
- unless a.question.author_is_anonymous
|
- unless a.question.author_is_anonymous
|
||||||
|
@ -45,6 +49,6 @@
|
||||||
.row
|
.row
|
||||||
.col-md-6.col-md-offset-6.col-sm-8.col-sm-offset-4.col-xs-6.col-xs-offset-6.text-right
|
.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
|
= 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-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,7 +12,8 @@
|
||||||
%button.btn.btn-info.btn-sm{type: :button, name: 'ab-smile', data: { a_id: a.id, action: :smile }}
|
%button.btn.btn-info.btn-sm{type: :button, name: 'ab-smile', data: { a_id: a.id, action: :smile }}
|
||||||
%i.fa.fa-smile-o
|
%i.fa.fa-smile-o
|
||||||
%span{id: "ab-smile-count-#{a.id}"}= a.smile_count
|
%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 }}
|
- 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
|
%i.fa.fa-comments
|
||||||
%span{id: "ab-comment-count-#{a.id}"}= a.comment_count
|
%span{id: "ab-comment-count-#{a.id}"}= a.comment_count
|
||||||
- if privileged? a.user
|
- if privileged? a.user
|
||||||
|
|
|
@ -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?
|
- unless user_signed_in?
|
||||||
#question-box-promote.row{:style => "display: none;"}
|
#question-box-promote.row{:style => "display: none;"}
|
||||||
.row
|
.row
|
||||||
.col-xs-12
|
.col-xs-12.text-center
|
||||||
%strong Your question has been sent.
|
%strong Your question has been sent.
|
||||||
.row
|
.row
|
||||||
.col-sm-1
|
.col-sm-1
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
- if user_signed_in?
|
- if user_signed_in?
|
||||||
- type ||= :nil
|
- type ||= :nil
|
||||||
- if user == current_user
|
- 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
|
- else
|
||||||
- if current_user.following? user
|
- 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
|
Unfollow
|
||||||
- else
|
- 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
|
Follow
|
|
@ -23,20 +23,5 @@
|
||||||
%p.profile--text
|
%p.profile--text
|
||||||
%i.fa.fa-location-arrow
|
%i.fa.fa-location-arrow
|
||||||
= @user.location
|
= @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
|
.profile--header
|
||||||
.container.j2-page
|
.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'
|
= render 'user/profile_info'
|
||||||
.hidden-xs= render 'shared/links'
|
.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'
|
= render 'shared/questionbox'
|
||||||
#answers
|
#answers
|
||||||
- @answers.each do |a|
|
- @answers.each do |a|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
.profile--header
|
||||||
.container.j2-page
|
.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'
|
= render 'user/profile_info'
|
||||||
.hidden-xs= render 'shared/links'
|
.hidden-xs= render 'shared/links'
|
||||||
.col-md-9.col-xs-12.col-sm-9
|
.col-md-8.col-xs-12.col-sm-8
|
||||||
%h1= @title
|
%h1.j2-lh.hidden-xs= @title
|
||||||
|
%h1.visible-xs= @title
|
||||||
#users
|
#users
|
||||||
- @users.each do |user|
|
- @users.each do |user|
|
||||||
.col-sm-6
|
.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 '/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 '/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
|
||||||
|
@ -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/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/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/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
|
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);
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<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">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
|
@ -12,6 +12,9 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a { color: #4183c4; text-decoration: none; }
|
||||||
|
a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
div.dialog {
|
div.dialog {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
max-width: 33em;
|
max-width: 33em;
|
||||||
|
@ -37,6 +40,8 @@
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.dialog img { margin-bottom: 0.5em; }
|
||||||
|
|
||||||
div.dialog > p {
|
div.dialog > p {
|
||||||
margin: 0 0 1em;
|
margin: 0 0 1em;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
@ -51,9 +56,20 @@
|
||||||
color: #666;
|
color: #666;
|
||||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
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>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="dialog">
|
<div class="dialog">
|
||||||
<div>
|
<div>
|
||||||
|
@ -62,5 +78,9 @@
|
||||||
</div>
|
</div>
|
||||||
<p>If you think you found a bug, please let us know.</p>
|
<p>If you think you found a bug, please let us know.</p>
|
||||||
</div>
|
</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>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a { color: #4183c4; text-decoration: none; }
|
||||||
|
a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
div.dialog {
|
div.dialog {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
max-width: 33em;
|
max-width: 33em;
|
||||||
|
@ -37,6 +40,8 @@
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.dialog img { margin-bottom: 0.5em; }
|
||||||
|
|
||||||
div.dialog > p {
|
div.dialog > p {
|
||||||
margin: 0 0 1em;
|
margin: 0 0 1em;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
@ -51,16 +56,31 @@
|
||||||
color: #666;
|
color: #666;
|
||||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
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>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="dialog">
|
<div class="dialog">
|
||||||
<div>
|
<div>
|
||||||
<h1>The change you wanted was rejected.</h1>
|
<h1>The change you wanted was rejected.</h1>
|
||||||
<p>Maybe you tried to change something you didn't have access to.</p>
|
<p>Maybe you tried to change something you didn't have access to.</p>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a { color: #4183c4; text-decoration: none; }
|
||||||
|
a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
div.dialog {
|
div.dialog {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
max-width: 33em;
|
max-width: 33em;
|
||||||
|
@ -37,6 +40,8 @@
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.dialog img { margin-bottom: 0.5em; }
|
||||||
|
|
||||||
div.dialog > p {
|
div.dialog > p {
|
||||||
margin: 0 0 1em;
|
margin: 0 0 1em;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
@ -51,15 +56,30 @@
|
||||||
color: #666;
|
color: #666;
|
||||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
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>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="dialog">
|
<div class="dialog">
|
||||||
<div>
|
<div>
|
||||||
<h1>We're sorry, but something went wrong.</h1>
|
<h1>Looks like something went wrong!</h1>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</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