Merge kyledrake changes

This commit is contained in:
Victoria Wang 2014-10-21 16:22:59 -07:00
commit f8a27aec6c
8 changed files with 152 additions and 91 deletions

100
app.rb
View file

@ -376,7 +376,7 @@ get '/tags/autocomplete/:name.json' do |name|
Tag.autocomplete(name).collect {|t| t[:name]}.to_json Tag.autocomplete(name).collect {|t| t[:name]}.to_json
end end
get '/browse/?' do def browse_sites_dataset
@current_page = params[:current_page] @current_page = params[:current_page]
@current_page = @current_page.to_i @current_page = @current_page.to_i
@current_page = 1 if @current_page == 0 @current_page = 1 if @current_page == 0
@ -397,13 +397,13 @@ get '/browse/?' do
case params[:sort_by] case params[:sort_by]
when 'hits' when 'hits'
site_dataset.order!(:hits.desc) site_dataset.order!(:hits.desc, :updated_at.desc)
when 'views' when 'views'
site_dataset.order!(:views.desc) site_dataset.order!(:views.desc, :updated_at.desc)
when 'newest' when 'newest'
site_dataset.order!(:created_at.desc) site_dataset.order!(:created_at.desc, :views.desc)
when 'oldest' when 'oldest'
site_dataset.order!(:created_at) site_dataset.order!(:created_at, :views.desc)
when 'random' when 'random'
site_dataset.where! 'random() < 0.01' site_dataset.where! 'random() < 0.01'
when 'last_updated' when 'last_updated'
@ -412,7 +412,7 @@ get '/browse/?' do
else else
if params[:tag] if params[:tag]
params[:sort_by] = 'views' params[:sort_by] = 'views'
site_dataset.order!(:views.desc) site_dataset.order!(:views.desc, :updated_at.desc)
else else
params[:sort_by] = 'last_updated' params[:sort_by] = 'last_updated'
site_dataset.order!(:updated_at.desc, :views.desc) site_dataset.order!(:updated_at.desc, :views.desc)
@ -427,12 +427,28 @@ get '/browse/?' do
site_dataset.where! ['tags.is_nsfw = ?', (params[:is_nsfw] == 'true' ? true : false)] site_dataset.where! ['tags.is_nsfw = ?', (params[:is_nsfw] == 'true' ? true : false)]
end end
site_dataset
end
get '/browse/?' do
params.delete 'tag' if params[:tag].nil? || params[:tag].empty?
site_dataset = browse_sites_dataset
site_dataset = site_dataset.paginate @current_page, 300 site_dataset = site_dataset.paginate @current_page, 300
@page_count = site_dataset.page_count || 1 @page_count = site_dataset.page_count || 1
@sites = site_dataset.all @sites = site_dataset.all
erb :browse erb :browse
end end
get '/surf/?' do
params.delete 'tag' if params[:tag].nil? || params[:tag].empty?
site_dataset = browse_sites_dataset
site_dataset = site_dataset.paginate @current_page, 1
@page_count = site_dataset.page_count || 1
@site = site_dataset.first
redirect "/browse?#{Rack::Utils.build_query params}" if @site.nil?
erb :'surf', layout: false
end
get '/surf/:username' do |username| get '/surf/:username' do |username|
@site = Site.select(:id, :username, :title, :domain, :views).where(username: username).first @site = Site.select(:id, :username, :title, :domain, :views).where(username: username).first
@title = @site.title @title = @site.title
@ -491,70 +507,36 @@ post '/create_validate' do
end end
post '/create' do post '/create' do
content_type :json
require_unbanned_ip require_unbanned_ip
dashboard_if_signed_in dashboard_if_signed_in
@site = Site.new( @site = Site.new(
username: params[:username], username: params[:username],
password: params[:password], password: params[:password],
email: params[:email], email: params[:email],
new_tags_string: params[:tags], new_tags_string: params[:tags],
is_nsfw: params[:is_nsfw],
ip: request.ip ip: request.ip
) )
recaptcha_is_valid = ENV['RACK_ENV'] == 'test' || recaptcha_valid? if !@site.valid?
return {result: 'error'}.to_json
if @site.valid? && recaptcha_is_valid
DB.transaction do
if !params[:stripe_token].nil? && params[:stripe_token] != ''
customer = Stripe::Customer.create(
card: params[:stripe_token],
description: @site.username,
email: @site.email,
plan: params[:selected_plan]
)
@site.stripe_customer_id = customer.id
plan_name = customer.subscriptions.first['plan']['name']
EmailWorker.perform_async({
from: 'web@neocities.org',
reply_to: 'contact@neocities.org',
to: @site.email,
subject: "[Neocities] You've become a supporter!",
body: Tilt.new('./views/templates/email_subscription.erb', pretty: true).render(self, plan_name: plan_name)
})
end
@site.save
end
EmailWorker.perform_async({
from: 'web@neocities.org',
reply_to: 'contact@neocities.org',
to: @site.email,
subject: "[Neocities] Welcome to Neocities!",
body: Tilt.new('./views/templates/email_welcome.erb', pretty: true).render(self)
})
EmailWorker.perform_async({
from: 'web@neocities.org',
reply_to: 'contact@neocities.org',
to: @site.email,
subject: "[Neocities] Welcome to Neocities!",
body: Tilt.new('./views/templates/email_welcome.erb', pretty: true).render(self)
})
send_confirmation_email @site
session[:id] = @site.id
redirect '/'
else
@site.errors.add :captcha, 'You must type in the captcha correctly! Try again.' if !recaptcha_is_valid
erb :'/new'
end end
@site.save
EmailWorker.perform_async({
from: 'web@neocities.org',
reply_to: 'contact@neocities.org',
to: @site.email,
subject: "[Neocities] Welcome to Neocities!",
body: Tilt.new('./views/templates/email_welcome.erb', pretty: true).render(self)
})
send_confirmation_email @site
session[:id] = @site.id
{result: 'ok'}.to_json
end end
get '/dashboard' do get '/dashboard' do

View file

@ -91,7 +91,7 @@ class Site < Sequel::Model
} }
} }
SUGGESTIONS_LIMIT = 32 SUGGESTIONS_LIMIT = 30
SUGGESTIONS_VIEWS_MIN = 500 SUGGESTIONS_VIEWS_MIN = 500
CHILD_SITES_MAX = 100 CHILD_SITES_MAX = 100
@ -902,7 +902,7 @@ class Site < Sequel::Model
suggestions_dataset = Site.exclude(id: id).order(:views.desc, :updated_at.desc) suggestions_dataset = Site.exclude(id: id).order(:views.desc, :updated_at.desc)
suggestions = suggestions_dataset.where(tags: tags).limit(limit, offset).all suggestions = suggestions_dataset.where(tags: tags).limit(limit, offset).all
return suggestions if suggestions.length == 32 return suggestions if suggestions.length == limit
suggestions += suggestions_dataset.where("views >= #{SUGGESTIONS_VIEWS_MIN}").limit(limit-suggestions.length).order(Sequel.lit('RANDOM()')).all suggestions += suggestions_dataset.where("views >= #{SUGGESTIONS_VIEWS_MIN}").limit(limit-suggestions.length).order(Sequel.lit('RANDOM()')).all
end end

View file

@ -30,7 +30,7 @@ describe 'site page' do
visit "/browse?tag=#{tag}" visit "/browse?tag=#{tag}"
page.find('.website-Gallery .title a')['href'].must_match /#{blocked_site.host}/ page.find('.website-Gallery .title a')['href'].must_match /\/surf\/#{blocked_site.username}/
visit "/site/#{blocked_site.username}" visit "/site/#{blocked_site.username}"

View file

@ -2,6 +2,10 @@
function getPage(currentPage) { function getPage(currentPage) {
document.location.href = '/browse?current_page='+currentPage+'&'+$('#search_criteria').serialize(); document.location.href = '/browse?current_page='+currentPage+'&'+$('#search_criteria').serialize();
} }
function surf(currentPage) {
document.location.href = '/surf?current_page='+currentPage+'&'+$('#search_criteria').serialize();
}
</script> </script>
<div class="header-Outro with-columns browse-page"> <div class="header-Outro with-columns browse-page">
@ -14,12 +18,9 @@
<% end %> <% end %>
</div> </div>
<div class="col col-50 filter"> <form id="search_criteria" action="/browse" method="GET">
<form id="search_criteria" action="/browse" method="GET"> <div class="col col-50 filter">
<fieldset class="grouping"> <fieldset class="grouping">
<% if params[:tag] %>
<input name="tag" type="hidden" value="<%= params[:tag] %>">
<% end %>
<label class="text-Label" for="sort_by">Sort By:</label> <label class="text-Label" for="sort_by">Sort By:</label>
<div class="select-Container"> <div class="select-Container">
<select name="sort_by" id="sort_by" class="input-Select"> <select name="sort_by" id="sort_by" class="input-Select">
@ -38,19 +39,17 @@
--> -->
<input class="btn-Action" type="submit" value="Update"> <input class="btn-Action" type="submit" value="Update">
</fieldset> </fieldset>
</form> </div>
</div> <div class="col col-50 filter">
<div class="col col-50 filter"> <form method="GET" action="browse">
<form method="GET" action="browse">
<fieldset class="grouping"> <fieldset class="grouping">
<label class="text-Label" for="tag">Search by tag:</label> <label class="text-Label" for="tag">Search by tag:</label>
<input class="input-Area typeahead" name="tag" type="text" placeholder="pokemon" value="" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" dir="auto"> <input class="input-Area typeahead" name="tag" type="text" placeholder="pokemon" value="<%= params[:tag] %>" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" dir="auto">
<input style="vertical-align: -4px;margin-left: 4px;" type="submit" class="btn-Action" value="Search"> <input style="vertical-align: -4px;margin-left: 4px;" type="submit" class="btn-Action" value="Search">
</fieldset> </fieldset>
</form> </div>
</div> </div>
</form>
</div>
</div> </div>
<div class="browse-page"> <div class="browse-page">
@ -62,9 +61,9 @@
</div> </div>
<% else %> <% else %>
<ul class="row website-Gallery content int-Gall"> <ul class="row website-Gallery content int-Gall">
<% @sites.each do |site| %> <% @sites.each_with_index do |site,i| %>
<li> <li>
<a href="/surf/<%= site.username %>" class="neo-Screen-Shot" target="_blank" title="<%= site.title %>"> <a href="" class="neo-Screen-Shot" target="_blank" title="<%= site.title %>" onclick="surf(<%= i+1 %>); return false">
<span class="img-Holder" style="background:url(<%= site.screenshot_url('index.html', '540x405') %>) no-repeat;"> <span class="img-Holder" style="background:url(<%= site.screenshot_url('index.html', '540x405') %>) no-repeat;">
<img src="/img/placeholder.png" alt="<%= site.title %>" /> <img src="/img/placeholder.png" alt="<%= site.title %>" />
</span> </span>

View file

@ -3,7 +3,7 @@
<div class="col col-66"> <div class="col col-66">
<h3>Your Feed</h3> <h3>Your Feed</h3>
<div class="feed-filter"> <div class="feed-filter">
<% if !@events.empty? %> <% if !@events.empty? || params[:activity] == 'mine' %>
<a href="/" <% if params[:activity] != 'mine' %>class="selected"<% end %>>All Activity</a> <a href="/" <% if params[:activity] != 'mine' %>class="selected"<% end %>>All Activity</a>
&nbsp;&nbsp; &nbsp;&nbsp;
<a href="/?activity=mine" <% if params[:activity] == 'mine' %>class="selected"<% end %>> <a href="/?activity=mine" <% if params[:activity] == 'mine' %>class="selected"<% end %>>
@ -25,6 +25,12 @@
<div class="col col-66"> <div class="col col-66">
<% if !@events.empty? %> <% if !@events.empty? %>
<%== erb :'_news', layout: false, locals: {site: current_site, events: @events} %> <%== erb :'_news', layout: false, locals: {site: current_site, events: @events} %>
<% elsif params[:activity] == 'mine' %>
<div class="welcome">
<h4>No updates on your site yet!</h4>
<p>
You should <a href="/dashboard">start editing your site</a>!
</div>
<% else %> <% else %>
<div class="welcome"> <div class="welcome">
<h4>Welcome to your Neocities news feed!</h4> <h4>Welcome to your Neocities news feed!</h4>

View file

@ -154,25 +154,26 @@
</div> </div>
</div> </div>
<% else %> <% else %>
<form action="/new" method="get" class="signup-Form"> <form id="createSiteForm" action="/new" method="POST" class="signup-Form" onsubmit="createSite(); return false">
<input type="hidden" name="csrf_token" value="<%= csrf_token %>">
<fieldset class="content"> <fieldset class="content">
<h2 class="gamma">Sign up for free</h2> <h2 class="gamma">Sign up for free</h2>
<hr /> <hr />
<label for="create-Input">Username</label> <label for="create-Input">Username</label>
<input type="text" class="input-Area" id="create-Input" name="username" placeholder="my-site-name" data-placement="left" data-trigger="manual" /> <input type="text" class="input-Area" id="create-Input" name="username" placeholder="my-site-name" data-placement="left" data-trigger="manual" autocapitalize="off" autocorrect="off" autocomplete="off" />
<label for="create-Input" id="domain-name">.neocities.org</label> <label for="create-Input" id="domain-name">.neocities.org</label>
<label for="tags-input">Tags (your interests, site topics)</label> <label for="tags-input">Tags (your interests, site topics)</label>
<input type="text" class="input-Area" id="tags-input" name="new_tags_string" placeholder="art, videogames, food, music, programming, gardening, cats" data-placement="left" data-trigger="manual" /> <input type="text" class="input-Area" id="tags-input" name="new_tags_string" placeholder="art, videogames, food, music, programming, gardening, cats" data-placement="left" data-trigger="manual" autocapitalize="off" autocorrect="off" autocomplete="off" />
<div class="col col-50" style="padding-left:0;"> <div class="col col-50" style="padding-left:0;">
<label for="password-input">Password</label> <label for="password-input">Password</label>
<input type="text" class="input-Area" id="password-input" name="password" placeholder="password" data-placement="left" data-trigger="manual" /> <input type="password" class="input-Area" id="password-input" name="password" placeholder="password" data-placement="left" data-trigger="manual" autocapitalize="off" autocorrect="off" autocomplete="off" />
</div> </div>
<div class="col col-50"> <div class="col col-50">
<label for="email-input">Email</label> <label for="email-input">Email</label>
<input type="text" class="input-Area" id="email-input" name="email" placeholder="me@example.com" data-placement="left" data-trigger="manual" /> <input type="text" class="input-Area" id="email-input" name="email" placeholder="me@example.com" data-placement="left" data-trigger="manual" autocapitalize="off" autocorrect="off" autocomplete="off" />
</div> </div>
<input type="submit" value="Create My Site" class="btn-Action float-Right" /> <input type="submit" value="Create My Site" class="btn-Action float-Right" />
@ -336,7 +337,14 @@
<script src="/js/app.min.js"></script> <script src="/js/app.min.js"></script>
<script src="/js/bootstrap.min.js"></script> <script src="/js/bootstrap.min.js"></script>
<script> <script>
$('input[type=text]').change(function(obj) { function createSite() {
$.post('/create', $('#createSiteForm').serialize(), function(res) {
if(res.result == 'ok')
location.reload()
})
}
$('input[type=text]').on('change focusout', function(obj) {
$.post('/create_validate', {field: obj.target.name, value: obj.target.value, csrf_token: '<%= csrf_token %>'}, function(res) { $.post('/create_validate', {field: obj.target.name, value: obj.target.value, csrf_token: '<%= csrf_token %>'}, function(res) {
if(res.result == 'ok') { if(res.result == 'ok') {
return $(obj.target).tooltip('hide') return $(obj.target).tooltip('hide')

View file

@ -60,8 +60,6 @@
name: 'tags', name: 'tags',
source: function(query, callback) { source: function(query, callback) {
$.get('/tags/autocomplete/'+query+'.json', function(data) { $.get('/tags/autocomplete/'+query+'.json', function(data) {
console.log(data)
var suggestions = JSON.parse(data) var suggestions = JSON.parse(data)
var suggestionObjects = [] var suggestionObjects = []
for(var i=0; i<suggestions.length; i++) for(var i=0; i<suggestions.length; i++)

View file

@ -89,17 +89,57 @@
</style> </style>
</head> </head>
<body> <body>
<script type="text/javascript">
function getPage(currentPage) {
document.location.href = '/surf?current_page='+currentPage+'&'+$('#search_criteria').serialize()
}
function backToBrowse() {
document.location.href = '/browse?'+$('#search_criteria').serialize()
}
</script>
<a href="/" id="logo"></a> <a href="/" id="logo"></a>
<div id="top-bar"> <div id="top-bar">
<ul class="browse-actions"> <ul class="browse-actions">
<li><a href="/">Neocities</a></li> <li>
<li><input type="text" placeholder="Browse by tag..." /></li> <a href="/browse" onclick="backToBrowse(<%= @current_page %>); return false">Neocities</a>
<li><a href=""><i class="fa fa-caret-left"></i> Prev</a></li> </li>
<li><a href="">Next <i class="fa fa-caret-right"></i></a></li> <% if @current_page %>
<li>
<form id="search_criteria" onsubmit="getPage(1); return false">
<input type="hidden" name="sort_by" value="<%= params[:sort_by] %>">
<input class="typeahead" name="tag" type="text" placeholder="Browse by tag..." value="<%= params[:tag] %>" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" dir="auto" />
</form>
</li>
<li>
<% if @current_page > 1 %>
<a href="" onclick="getPage(<%= @current_page - 1 %>); return false">
<i class="fa fa-caret-left"></i> Prev
</a>
<% end %>
</li>
<li>
<% if @current_page != @page_count %>
<a href="" onclick="getPage(<%= @current_page + 1 %>); return false">Next <i class="fa fa-caret-right"></i></a>
<% end %>
</li>
<% end %>
</ul> </ul>
<ul class="site-actions"> <ul class="site-actions">
<li><a href="/site/<%= @site.username %>"><i class="fa fa-user"></i> <strong><%= @site.username %></strong></a></li> <li><a href="/site/<%= @site.username %>"><i class="fa fa-user"></i> <strong><%= @site.username %></strong></a></li>
<li><a href=""><i class="fa fa-plus"></i> Follow</a></li>
<% if current_site && current_site != @site %>
<li>
<a id="followLink" href="" onclick="toggleFollow(<%= @site.id %>); return false">
<% if current_site.is_following? @site %>
<i class="fa fa-times"></i> Unfollow
<% else %>
<i class="fa fa-plus"></i> Follow
<% end %>
</a>
</li>
<% end %>
<li> <li>
<a href="" id="shareButton" data-container="body" data-toggle="popover" data-placement="bottom" data-content='<%== erb :'_share', layout: false, locals: {site: @site} %>' onclick="return false"> <a href="" id="shareButton" data-container="body" data-toggle="popover" data-placement="bottom" data-content='<%== erb :'_share', layout: false, locals: {site: @site} %>' onclick="return false">
<i class="fa fa-share-alt"></i> Share <i class="fa fa-share-alt"></i> Share
@ -113,10 +153,38 @@
<script src="/js/jquery-1.11.0.min.js"></script> <script src="/js/jquery-1.11.0.min.js"></script>
<script src="/js/bootstrap.min.js"></script> <script src="/js/bootstrap.min.js"></script>
<script src="/js/typeahead.bundle.js"></script>
<script> <script>
$(function() { $(function() {
$('#shareButton').popover({html: true}) $('#shareButton').popover({html: true})
}) })
$('.typeahead').typeahead({
minLength: 2,
highlight: true
}, {
name: 'tags',
source: function(query, callback) {
$.get('/tags/autocomplete/'+query+'.json', function(data) {
var suggestions = JSON.parse(data)
var suggestionObjects = []
for(var i=0; i<suggestions.length; i++)
suggestionObjects.push({value: suggestions[i]})
callback(suggestionObjects)
})
}
})
function toggleFollow(id) {
$.post('/site/'+id+'/toggle_follow', {csrf_token: '<%= csrf_token %>'}, function(res) {
if(res.result == 'followed')
$('#followLink').html('<i class="fa fa-times"></i> Unfollow')
if(res.result == 'unfollowed')
$('#followLink').html('<i class="fa fa-plus"></i> Follow')
})
}
</script> </script>
</body> </body>
</html> </html>