refactor tags, whitespace

This commit is contained in:
Kyle Drake 2014-06-08 18:32:33 -07:00
parent e9b7826621
commit e0efe996b0
6 changed files with 107 additions and 46 deletions

1
.gitignore vendored
View file

@ -22,3 +22,4 @@ public/assets/css/.sass-cache/
public/site_thumbnails public/site_thumbnails
public/sites public/sites
public/site_screenshots public/site_screenshots
*.swp

8
app.rb
View file

@ -99,10 +99,6 @@ post '/site/:sitename/comment' do |sitename|
redirect "/site/#{sitename}" redirect "/site/#{sitename}"
end end
get '/tags_mockup' do
erb :'tags_mockup'
end
get '/browse_mockup' do get '/browse_mockup' do
erb :'browse_mockup' erb :'browse_mockup'
end end
@ -225,7 +221,7 @@ end
post '/tags/add' do post '/tags/add' do
require_login require_login
current_site.new_tags = params[:tags] current_site.new_tags_string = params[:tags]
current_site.save validate: false current_site.save validate: false
redirect request.referer redirect request.referer
end end
@ -299,7 +295,7 @@ post '/create' do
username: params[:username], username: params[:username],
password: params[:password], password: params[:password],
email: params[:email], email: params[:email],
new_tags: params[:tags], new_tags_string: params[:tags],
is_nsfw: params[:is_nsfw], is_nsfw: params[:is_nsfw],
ip: request.ip ip: request.ip
) )

View file

@ -138,12 +138,8 @@ class Site < Sequel::Model
values[:password] = BCrypt::Password.create plaintext, cost: (self.class.bcrypt_cost || BCrypt::Engine::DEFAULT_COST) values[:password] = BCrypt::Password.create plaintext, cost: (self.class.bcrypt_cost || BCrypt::Engine::DEFAULT_COST)
end end
def new_tags=(tags_string) def new_tags_string=(tags_string)
tags_string.gsub! ', ', ',' @new_tags_string = tags_string
tags = tags_string.split ','
tags_string.gsub! /[^a-zA-Z0-9, ]/, ''
tags.collect! {|c| (c.match(/^\w+\s\w+/) || c.match(/^\w+/)).to_s }
@new_tag_strings = tags.sort
end end
def before_validation def before_validation
@ -213,7 +209,7 @@ class Site < Sequel::Model
end end
def store_file(filename, uploaded) def store_file(filename, uploaded)
if File.exist?(file_path(filename)) && if File.exist?(file_path(filename)) &&
Digest::SHA2.file(file_path(filename)).digest == Digest::SHA2.file(uploaded.path).digest Digest::SHA2.file(file_path(filename)).digest == Digest::SHA2.file(uploaded.path).digest
return false return false
end end
@ -287,18 +283,18 @@ class Site < Sequel::Model
end end
def after_save def after_save
if @new_tag_strings if @new_filtered_tags
@new_tag_strings.each do |new_tag_string| @new_filtered_tags.each do |new_tag_string|
add_tag_name new_tag_string add_tag_name new_tag_string
end end
@new_filtered_tags = []
@new_tags_string = nil
end end
super super
end end
def add_tag_name(name) def add_tag_name(name)
if tags_dataset.filter(name: name).first.nil? add_tag Tag[name: name] || Tag.create(name: name)
add_tag Tag[name: name] || Tag.create(name: name)
end
end end
def after_create def after_create
@ -350,6 +346,37 @@ class Site < Sequel::Model
errors.add :domain, "Domain provided is already being used by another site, please choose another." errors.add :domain, "Domain provided is already being used by another site, please choose another."
end end
end end
if @new_tags_string
new_tags = @new_tags_string.split ','
new_tags.uniq!
new_tags.compact!
@new_filtered_tags = []
if new_tags.length > 5
error.add :tags, 'Cannot have more than 5 tags.'
end
new_tags.each do |tag|
tag.strip!
if tag.match(/[^a-zA-Z0-9 ]/)
errors.add :tags, "Tag \"#{tag}\" can only contain letters (A-Z) and numbers (0-9)."
break
end
if tag.match(/ /)
errors.add :tags, "Tag \"#{tag}\" cannot have more than one space between words."
break
end
if tag.split(' ').length > 2
errors.add :tags, "Tag \"#{tag}\" cannot be more than two words."
break
end
@new_filtered_tags << tag
end
end
end end
def render_template(name) def render_template(name)

View file

@ -84,13 +84,50 @@ describe 'signup' do
click_button 'Create Home Page' click_button 'Create Home Page'
page.must_have_content 'A valid user/site name is required' page.must_have_content 'A valid user/site name is required'
end end
it 'fails with username greater than 32 characters' do it 'fails with username greater than 32 characters' do
fill_in_valid fill_in_valid
fill_in 'username', with: SecureRandom.hex+'1' fill_in 'username', with: SecureRandom.hex+'1'
click_button 'Create Home Page' click_button 'Create Home Page'
page.must_have_content 'cannot exceed 32 characters' page.must_have_content 'cannot exceed 32 characters'
end end
it 'fails with invalid tag chars' do
fill_in_valid
fill_in 'tags', with: '$POLICE OFFICER$$$$$, derp'
click_button 'Create Home Page'
page.must_have_content /Tag.+can only contain/
end
it 'fails for tag with too many spaces' do
fill_in_valid
fill_in 'tags', with: 'police officer, hi'
click_button 'Create Home Page'
page.must_have_content /Tag.+cannot have more than one space/
end
it 'succeeds with no tags' do
fill_in_valid
fill_in 'tags', with: ''
click_button 'Create Home Page'
page.must_have_content 'Your Feed'
end
it 'succeeds with a single tag' do
fill_in_valid
fill_in 'tags', with: 'derpie'
click_button 'Create Home Page'
page.must_have_content 'Your Feed'
Site.last.tags.first.name.must_equal 'derpie'
end
it 'succeeds with valid tags' do
fill_in_valid
fill_in 'tags', with: 'derpie, shoujo manga'
click_button 'Create Home Page'
page.must_have_content 'Your Feed'
Site.last.tags.collect {|t| t.name}.must_equal ['derpie', 'shoujo manga']
end
end end
describe 'signin' do describe 'signin' do
@ -105,7 +142,7 @@ describe 'signin' do
before do before do
Capybara.reset_sessions! Capybara.reset_sessions!
end end
it 'fails for invalid login' do it 'fails for invalid login' do
visit '/' visit '/'
click_link 'Sign In' click_link 'Sign In'
@ -114,7 +151,7 @@ describe 'signin' do
click_button 'Sign In' click_button 'Sign In'
page.must_have_content 'Invalid login' page.must_have_content 'Invalid login'
end end
it 'fails for missing login' do it 'fails for missing login' do
visit '/' visit '/'
click_link 'Sign In' click_link 'Sign In'
@ -124,7 +161,7 @@ describe 'signin' do
click_button 'Sign In' click_button 'Sign In'
page.must_have_content 'Invalid login' page.must_have_content 'Invalid login'
end end
it 'logs in with proper credentials' do it 'logs in with proper credentials' do
visit '/' visit '/'
click_button 'Create My Website' click_button 'Create My Website'
@ -140,4 +177,4 @@ describe 'signin' do
click_button 'Sign In' click_button 'Sign In'
page.must_have_content 'Your Feed' page.must_have_content 'Your Feed'
end end
end end

View file

@ -34,7 +34,7 @@ describe 'api info' do
it 'succeeds for valid sitename' do it 'succeeds for valid sitename' do
create_site create_site
@site.update hits: 31337, domain: 'derp.com', new_tags: 'derpie, man' @site.update hits: 31337, domain: 'derp.com', new_tags_string: 'derpie, man'
get '/api/info', sitename: @user get '/api/info', sitename: @user
res[:result].must_equal 'success' res[:result].must_equal 'success'
res[:info][:sitename].must_equal @site.username res[:info][:sitename].must_equal @site.username

View file

@ -27,7 +27,7 @@
</div> </div>
</div> </div>
<% end %> <% end %>
<p> <p>
First, enter a username. This will also be used as your site name.<br><b>Do not forget this, it will be used to sign in to and manage your home page.</b> It can only contain letters, numbers, underscores and hyphens, and can only be 32 characters long. First, enter a username. This will also be used as your site name.<br><b>Do not forget this, it will be used to sign in to and manage your home page.</b> It can only contain letters, numbers, underscores and hyphens, and can only be 32 characters long.
</p> </p>
@ -35,7 +35,7 @@
<p> <p>
<input class="input-Area" name="username" type="text" placeholder="yourusername" value="<%= @site.username %>" autocapitalize="off" autocorrect="off" style="width: 200px">.neocities.org <input class="input-Area" name="username" type="text" placeholder="yourusername" value="<%= @site.username %>" autocapitalize="off" autocorrect="off" style="width: 200px">.neocities.org
</p> </p>
<hr> <hr>
<p> <p>
@ -61,19 +61,19 @@
<hr> <hr>
<p>You can optionally enter some tags! Tags will allow others to find your site based on your interests, or your site's theme. <b>Separate multiple tags with commas</b>. Don't think too hard about this, you can change them later. You can have a maximum of ten tags, and there is a two word per tag maximum (extra words in a tag will be removed).</p> <p>You can optionally enter some tags! Tags will allow others to find your site based on your interests, or your site's theme. <b>Separate multiple tags with commas</b>. Don't think too hard about this, you can change them later. You can have a maximum of five tags, and tags can only contain letters (A-Z) and numbers (0-9). There is a two word per tag maximum.</p>
<h5>Tags</h5> <h5>Tags</h5>
<input class="input-Area" name="tags" type="text" style="width: 400px; max-width:100%" placeholder="pokemon, video games, bulbasaur" value="<%= params[:tags] %>" autocapitalize="off" autocorrect="off"> <input class="input-Area" name="tags" type="text" style="width: 400px; max-width:100%" placeholder="pokemon, video games, bulbasaur" value="<%= params[:tags] %>" autocapitalize="off" autocorrect="off">
<hr> <hr>
<p><strong>The site you are creating will be free, forever.</strong> We will never charge you for your web site.</p> <p><strong>The site you are creating will be free, forever.</strong> We will never charge you for your web site.</p>
<p><a href="/donate" target="_blank">Neocities has to pay the bills though</a>, and we like the idea of being able to work on the site full-time someday. So if you would like to help us reach this goal, we have created the <strong>Supporter Plan</strong>! <p><a href="/donate" target="_blank">Neocities has to pay the bills though</a>, and we like the idea of being able to work on the site full-time someday. So if you would like to help us reach this goal, we have created the <strong>Supporter Plan</strong>!
<p>Right now, the <strong>Supporter Plan</strong> is the same as the free plan, except that <strong>Supporter Plan members get 200MB</strong> of web space. You will also be listed as a supporter on our contributors page, and on your site profile page.</p> <p>Right now, the <strong>Supporter Plan</strong> is the same as the free plan, except that <strong>Supporter Plan members get 200MB</strong> of web space. You will also be listed as a supporter on our contributors page, and on your site profile page.</p>
<p>The base plan is $12 ($1/month) billed once per year, which is the cost of <a href="/img/yafagrillmenu.jpg" target="_blank">a delicious Yafa Combo with a lousy tip</a>. If you ever decide to cancel, you get to keep the extra space. Thanks for helping us run this site!</p> <p>The base plan is $12 ($1/month) billed once per year, which is the cost of <a href="/img/yafagrillmenu.jpg" target="_blank">a delicious Yafa Combo with a lousy tip</a>. If you ever decide to cancel, you get to keep the extra space. Thanks for helping us run this site!</p>
<div> <div>
<input type="radio" name="plan" value="free" <%= params[:plan].nil? || params[:plan] == 'free' ? 'checked' : '' %>> <input type="radio" name="plan" value="free" <%= params[:plan].nil? || params[:plan] == 'free' ? 'checked' : '' %>>
<span><strong>Free Plan (<%= Site::FREE_MAXIMUM_IN_MEGABYTES %>MB)</strong></span> <span><strong>Free Plan (<%= Site::FREE_MAXIMUM_IN_MEGABYTES %>MB)</strong></span>
@ -83,7 +83,7 @@
<input id="supporter" type="radio" name="plan" value="supporter" <%= params[:plan] == 'supporter' ? 'checked' : '' %>> <input id="supporter" type="radio" name="plan" value="supporter" <%= params[:plan] == 'supporter' ? 'checked' : '' %>>
<span><strong>Supporter Plan (<%= Site::SUPPORTER_MAXIMUM_IN_MEGABYTES %>MB)</strong></span> <span><strong>Supporter Plan (<%= Site::SUPPORTER_MAXIMUM_IN_MEGABYTES %>MB)</strong></span>
</div> </div>
<div id="plan_container" style="margin-top:20px; display: none"> <div id="plan_container" style="margin-top:20px; display: none">
<input id="stripe_token" name="stripe_token" type="hidden" value="<%= params[:stripe_token] %>"> <input id="stripe_token" name="stripe_token" type="hidden" value="<%= params[:stripe_token] %>">
@ -99,7 +99,7 @@
<option value="plan_five">$60/year ($5/month)</option> <option value="plan_five">$60/year ($5/month)</option>
</select> </select>
</p> </p>
<% if params[:stripe_token] %> <% if params[:stripe_token] %>
<p>Billing information has been saved, thank you!</p> <p>Billing information has been saved, thank you!</p>
<% else %> <% else %>
@ -108,30 +108,30 @@
CVC: <input type="text" size="4" maxlength="4" data-stripe="cvc" style="width: 60px"> CVC: <input type="text" size="4" maxlength="4" data-stripe="cvc" style="width: 60px">
</p> </p>
<p> <p>
Expiration: Expiration:
<input type="text" size="2" data-stripe="exp-month" placeholder="MM" maxlength="2" style="width: 50px"> <input type="text" size="2" data-stripe="exp-month" placeholder="MM" maxlength="2" style="width: 50px">
<input type="text" size="4" data-stripe="exp-year" placeholder="YYYY" maxlength="4" style="width: 60px"> <input type="text" size="4" data-stripe="exp-year" placeholder="YYYY" maxlength="4" style="width: 60px">
</p> </p>
<% end %> <% end %>
<p><strong>We accept Bitcoin!</strong> If you would prefer to use Bitcoin, choose the <strong>Free Plan</strong>, and then upgrade in the <strong>Settings</strong> page once your account is created.</p> <p><strong>We accept Bitcoin!</strong> If you would prefer to use Bitcoin, choose the <strong>Free Plan</strong>, and then upgrade in the <strong>Settings</strong> page once your account is created.</p>
</div> </div>
<hr> <hr>
<p><b>Last thing!</b> Enter these two words correctly (with spaces) so we know you're not a robot (don't worry robots, we still love you).</p> <p><b>Last thing!</b> Enter these two words correctly (with spaces) so we know you're not a robot (don't worry robots, we still love you).</p>
<div class="recaptcha"> <div class="recaptcha">
<%== recaptcha_tag :challenge, ssl: request.ssl? %> <%== recaptcha_tag :challenge, ssl: request.ssl? %>
</div> </div>
<hr> <hr>
<h3>You're done. Just click the button below!</h3> <h3>You're done. Just click the button below!</h3>
<input class="btn-Action" type="submit" value="Create Home Page"> <input class="btn-Action" type="submit" value="Create Home Page">
</form> </form>
</div> </div>
<script> <script>
window.onload = function() { window.onload = function() {
$('#signupform').find(':submit').prop('disabled', false) $('#signupform').find(':submit').prop('disabled', false)
@ -139,7 +139,7 @@
if($('#signupform input:radio[name="plan"]:checked').val() == 'free') { if($('#signupform input:radio[name="plan"]:checked').val() == 'free') {
return true return true
} }
if($('#stripe_token').val() != '') if($('#stripe_token').val() != '')
return true return true
@ -163,11 +163,11 @@
}) })
return false return false
}) })
$('#signupform input:radio[name="plan"]').change(function(){ $('#signupform input:radio[name="plan"]').change(function(){
showPlanIfSelected() showPlanIfSelected()
}) })
function showPlanIfSelected() { function showPlanIfSelected() {
var planContainer = $('#plan_container') var planContainer = $('#plan_container')
if($('#signupform input:radio[name="plan"]:checked').val() == 'supporter') if($('#signupform input:radio[name="plan"]:checked').val() == 'supporter')
@ -176,4 +176,4 @@
} }
showPlanIfSelected() showPlanIfSelected()
} }
</script> </script>