From e02b7a85e71d0e046a2a1741b599321f5abebbff Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Wed, 27 Jan 2016 14:12:49 +0100 Subject: [PATCH] More things --- app/controllers/badges.rb | 30 ++++++++++++++---- app/controllers/changes.rb | 26 ++++++++++----- app/helpers/badges_helper.rb | 8 ++--- app/views/badges/_form.haml | 44 ++++++++++++-------------- app/views/badges/edit.haml | 4 ++- app/views/badges/index.haml | 7 ++++ app/views/badges/new.haml | 4 ++- app/views/badges/show.haml | 36 +++++++++++++++++++-- app/views/changes/_form.haml | 39 +++++++++-------------- app/views/changes/new.haml | 6 +++- app/views/static/index.haml | 6 ++++ db/migrate/003_create_badge_changes.rb | 1 + db/schema.rb | 1 + models/badge.rb | 17 +++++++--- models/badge_change.rb | 35 +++++++++++++++++--- 15 files changed, 183 insertions(+), 81 deletions(-) diff --git a/app/controllers/badges.rb b/app/controllers/badges.rb index c01774e..970dd7e 100644 --- a/app/controllers/badges.rb +++ b/app/controllers/badges.rb @@ -10,6 +10,17 @@ end end + get :new do + if is_logged_in? + @badge = Badge.new + render :new + else + status 401 + flash[:error] = "You need to log in to create a badge." + redirect(url(:static, :index)) + end + end + get :show, with: :id, map: '/badges' do @badge = Badge.find_by_id(params[:id]) if @badge @@ -28,6 +39,7 @@ end get :github, map: '/v1/:username/:repo/:branch/:package', provides: :svg, cache: true do + expires 43200 # Cache for 12 hours cache_key { [params[:username], params[:repo], params[:branch], params[:package]].join('$') } main_key = [params[:username], params[:repo], params[:branch]].join('$') @@ -133,14 +145,18 @@ end end - get :new do - if is_logged_in? - @badge = Badge.new - render :new + put :update, with: :id do + @badge = Badge.find(params[:id]) + if @badge + if @badge.update_attributes(params[:badge]) + redirect(url(:badges, :index)) + else + flash.now[:error] = "Failed to update" + render 'badges/edit' + end else - status 401 - flash[:error] = "You need to log in to create a badge." - redirect(url(:static, :index)) + flash[:warning] = "Does not exist" + halt 404 end end end diff --git a/app/controllers/changes.rb b/app/controllers/changes.rb index 9e6eec5..577688a 100644 --- a/app/controllers/changes.rb +++ b/app/controllers/changes.rb @@ -11,15 +11,25 @@ end end - post :create do - @info = BadgeChange.new(params[:badge]) - @info.user = current_user + post :create, map: '/badges/:id/change/' do + if is_logged_in? + @change = BadgeChange.new(params[:badge_change]) + @badge = Badge.find params[:id] + @change.badge = @badge + @change.user = current_user - if @info.save - redirect(url(:badges, :show, id: @info.badge.id)) - else - flash.now[:error] = "Nope" - render 'changes/new' + if @change.save + redirect(url(:badges, :show, id: @change.badge.id)) + else + flash.now[:error] = "Nope" + render 'changes/new' + end end end + + put :accept, map: '/badges/:badge_id/change/:change_id/accept' do + end + + put :reject, map: '/badges/:badge_id/change/:change_id/reject' do + end end diff --git a/app/helpers/badges_helper.rb b/app/helpers/badges_helper.rb index 77c5550..d40de8d 100644 --- a/app/helpers/badges_helper.rb +++ b/app/helpers/badges_helper.rb @@ -29,16 +29,16 @@ def badge_config params end def version_string object - if object[:start] && SemanticRange.valid(object[:start]) + if object[:start].present? && SemanticRange.valid(object[:start]) str = object[:start] - if object[:end] && SemanticRange.valid(object[:end]) && SemanticRange.lt(object[:start], object[:end]) + if object[:end].present? && SemanticRange.valid(object[:end]) && SemanticRange.lt(object[:start], object[:end]) str += ' - ' + object[:end] - elsif object[:end] && (!SemanticRange.valid(object[:end]) || !SemanticRange.lt(object[:start], object[:end])) + elsif object[:end].present? && (!SemanticRange.valid(object[:end]) || !SemanticRange.lt(object[:start], object[:end])) str = 'Invalid' else str += '+' end - elsif object[:range] && SemanticRange.valid_range(object[:range]) + elsif object[:range].present? && SemanticRange.valid_range(object[:range]) str = SemanticRange.valid_range object[:range] else str = 'Invalid' diff --git a/app/views/badges/_form.haml b/app/views/badges/_form.haml index c6f2e43..5955da9 100644 --- a/app/views/badges/_form.haml +++ b/app/views/badges/_form.haml @@ -1,24 +1,22 @@ -= flash_tag(:error) -= form_for badge, url(:badges, :create), id: 'new_badge' do |f| - = f.error_messages - %div.form-group - = f.label :label, caption: "Badge label" - = f.text_field :label, placeholder: 'ember-versions', class: 'form-control' - %div.form-group - = f.label :title, caption: "Title of your page (for later identification)" - = f.text_field :title, placeholder: 'Amazing article about Ember.js', class: 'form-control' - %div.form-group - = f.label :url, caption: "URL this badge will appear on" - = f.text_field :url, placeholder: 'http://myblog.com/ember-js-rocks', class: 'form-control' - %div.form-group - = f.label :version_start - = f.text_field :version_start, class: 'form-control' - %div.form-group - = f.label :version_end - = f.text_field :version_end, class: 'form-control' - %div.form-group - = f.label :version_range - = f.text_field :version_range, class: 'form-control' += f.error_messages +%div.form-group + = f.label :label, caption: "Badge label" + = f.text_field :label, placeholder: 'ember-versions', class: 'form-control' +%div.form-group + = f.label :title, caption: "Title of your page (for later identification)" + = f.text_field :title, placeholder: 'Amazing article about Ember.js', class: 'form-control' +%div.form-group + = f.label :url, caption: "URL this badge will appear on" + = f.url_field :url, placeholder: 'http://myblog.com/ember-js-rocks', class: 'form-control' +%div.form-group + = f.label :version_start + = f.text_field :version_start, class: 'form-control' +%div.form-group + = f.label :version_end + = f.text_field :version_end, class: 'form-control' +%div.form-group + = f.label :version_range + = f.text_field :version_range, class: 'form-control' - %div.form-group - = f.submit "Submit", class: 'btn btn-default' +%div.form-group + = f.submit "Submit", class: 'btn btn-default' diff --git a/app/views/badges/edit.haml b/app/views/badges/edit.haml index ed2a46d..e9a881f 100644 --- a/app/views/badges/edit.haml +++ b/app/views/badges/edit.haml @@ -1,2 +1,4 @@ %h2 Edit badge -= partial 'badges/form', locals: {badge: @badge} += flash_tag(:error) += form_for @badge, url(:badges, :update, id: @badge.id), id: 'update_badge', method: :put do |f| + = partial 'badges/form', locals: {f: f} diff --git a/app/views/badges/index.haml b/app/views/badges/index.haml index 5f9a5dd..80e5906 100644 --- a/app/views/badges/index.haml +++ b/app/views/badges/index.haml @@ -18,6 +18,8 @@ %th ID %th Link %th Badge + %th Last Updated + %th Actions %tbody - @badges.each do |badge| %tr @@ -27,6 +29,11 @@ %td %a{href: url(:badges, :show, id: badge.id)} %img{src: "/b/#{badge.id}.svg"} + %td + = time_ago_in_words badge.updated_at + %td + %a{href: url(:badges, :edit, id: badge.id)} + Edit - else %p You currently don't have any badges. diff --git a/app/views/badges/new.haml b/app/views/badges/new.haml index 8426a35..9b00400 100644 --- a/app/views/badges/new.haml +++ b/app/views/badges/new.haml @@ -1,2 +1,4 @@ %h2 New Badge -= partial 'badges/form', locals: {badge: @badge} += flash_tag(:error) += form_for @badge, url(:badges, :create), id: 'new_badge' do |f| + = partial 'badges/form', locals: {f: f} diff --git a/app/views/badges/show.haml b/app/views/badges/show.haml index 3d4cc1e..da5c773 100644 --- a/app/views/badges/show.haml +++ b/app/views/badges/show.haml @@ -14,7 +14,11 @@ It is used in = link_to @badge.title, @badge.url, rel: 'nofollow' %p - Think this information is incorrect? Propose a change! + Think this badge is incorrect? + - if @badge.user == current_user + %a{href: url(:badges, :edit, id: @badge.id)} Edit the badge! + - else + %a{href: url(:changes, :new, id: @badge.id)} Propose a change! %h3 Embed %p Embed this badge in your site: @@ -23,9 +27,37 @@ %h3 Proposed changes +- if @badge.badge_changes.proposed.length > 0 + %table.table + %thead + %tr + %th Badge + %th Author + %th Comment + %th Time + %th + %tbody + - @badge.badge_changes.proposed.each do |change| + %tr + %td + %img{src: url(:badges, :static, start: change.version_start, end: change.version_end, range: change.version_end, format: :svg)} + %td + = change.user.handle + %td + = change.comment + %td + = time_ago_in_words change.created_at + ago + %td + - if is_logged_in? && change.user != current_user + %button.btn.btn-xs.btn-primary +1 + - if is_logged_in? && @badge.user == current_user + %button.btn.btn-success.btn-xs Apply + %button.btn.btn-danger.btn-xs Reject -The author will be notified of your proposed change to this badge. They can then either accept or reject your change. Other users can vote for your change. Once a proposed change has reached 3 votes it will be automatically accepted. +- else + There are currently no proposed changes to this badge. - if is_logged_in? %hr diff --git a/app/views/changes/_form.haml b/app/views/changes/_form.haml index 28fee8b..c02b47d 100644 --- a/app/views/changes/_form.haml +++ b/app/views/changes/_form.haml @@ -1,25 +1,16 @@ -= flash_tag(:error) -= form_for badge, url(:badge_infos, :create), id: 'new_badge' do |f| - = f.error_messages - %div.form-group - = f.label :label, caption: "Badge label" - = f.text_field :label, placeholder: 'ember-versions', class: 'form-control' - %div.form-group - = f.label :title, caption: "Title of your page (for later identification)" - = f.text_field :title, placeholder: 'Amazing article about Ember.js', class: 'form-control' - %div.form-group - = f.label :url, caption: "URL this badge will appear on" - = f.text_field :url, placeholder: 'http://myblog.com/ember-js-rocks', class: 'form-control' - = f.fields_for :badge_infos do |bi| - %div.form-group - = bi.label :version_start - = bi.text_field :version_start, class: 'form-control' - %div.form-group - = bi.label :version_end - = bi.text_field :version_end, class: 'form-control' - %div.form-group - = bi.label :version_range - = bi.text_field :version_range, class: 'form-control' += f.error_messages +%div.form-group + = f.label :version_start + = f.text_field :version_start, class: 'form-control' +%div.form-group + = f.label :version_end + = f.text_field :version_end, class: 'form-control' +%div.form-group + = f.label :version_range + = f.text_field :version_range, class: 'form-control' +%div.form-group + = f.label :comment + = f.text_area :comment, class: 'form-control' - %div.form-group - = f.submit "Submit", :class => 'btn btn-default' +%div.form-group + = f.submit "Submit", class: 'btn btn-default' diff --git a/app/views/changes/new.haml b/app/views/changes/new.haml index 8fc8dce..3ebc299 100644 --- a/app/views/changes/new.haml +++ b/app/views/changes/new.haml @@ -1,2 +1,6 @@ %h2 Propose Change -= partial 'badge_infos/form', locals: {badge: @badge} += flash_tag(:error) += form_for @change, url(:changes, :create, id: @badge.id), id: 'new_change' do |f| + = partial 'changes/form', locals: {f: f} + +%a{href: url(:badges, :show, id: @badge.id)} Back to badge diff --git a/app/views/static/index.haml b/app/views/static/index.haml index 7cd1f91..ae99437 100644 --- a/app/views/static/index.haml +++ b/app/views/static/index.haml @@ -31,6 +31,12 @@ Optionally you can also pass an optional label GET-parameter that will replace the label shown on the badge. +Embadge heavily caches badges generated for Github repositories. It is therefore recommended to +%a{href: "https://developer.github.com/webhooks/creating/"} set up a webhook +to invalidate our cache and update your badge: + +%pre https://embadge.io/v1/webhook + %h2#static Static Badges %p In case you want to use a static badge and specify version information yourself, you can use the embadge.io API. It supports four different parameters. diff --git a/db/migrate/003_create_badge_changes.rb b/db/migrate/003_create_badge_changes.rb index 0322d40..d472bf6 100644 --- a/db/migrate/003_create_badge_changes.rb +++ b/db/migrate/003_create_badge_changes.rb @@ -7,6 +7,7 @@ def self.up t.string :version_end t.string :version_range t.string :status, default: 'proposed' + t.text :comment t.timestamps end end diff --git a/db/schema.rb b/db/schema.rb index 9b07be4..e257486 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -20,6 +20,7 @@ t.string "version_end" t.string "version_range" t.string "status", default: "proposed" + t.text "comment" t.datetime "created_at" t.datetime "updated_at" end diff --git a/models/badge.rb b/models/badge.rb index c23dd79..bf80a32 100644 --- a/models/badge.rb +++ b/models/badge.rb @@ -13,11 +13,18 @@ class Badge < ActiveRecord::Base def definition { - start: version_start.blank? ? nil : version_start, - end: version_end.blank? ? nil : version_end, - range: version_range.blank? ? nil : version_range, - label: self.label, - id: self.id + start: version_start, + end: version_end, + range: version_range, + label: label, + id: id } end + + def apply! change + self.version_start = change.version_start + self.version_end = change.version_end + self.version_range = change.version_range + self.save! + end end diff --git a/models/badge_change.rb b/models/badge_change.rb index e1ccb4a..9ddbae3 100644 --- a/models/badge_change.rb +++ b/models/badge_change.rb @@ -1,11 +1,36 @@ class BadgeChange < ActiveRecord::Base + has_many :votes + belongs_to :badge + belongs_to :user - validates_presence_of :version_start, if: -> { self.version_range.blank? } - validates_presence_of :version_range, if: -> { self.version_start.blank? } + validates :version_start, presence: true, if: -> { self.version_range.blank? } + validates :version_range, presence: true, if: -> { self.version_start.blank? } validates :badge, presence: true validates :user, presence: true - has_many :votes - belongs_to :badge - belongs_to :user + VALID_STATUSES = %w(proposed rejected accepted) + validates :status, inclusion: { in: VALID_STATUSES, + message: "%{value} is not a valid status" } + + VALID_STATUSES.each do |status_name| + scope status_name, -> { where(status: status_name) } + + define_method("#{status_name}?") do + status == status_name + end + end + + # Sets status to accepted. + # Rejects all other changes. + # Copies attributes over to badge + def accept! + badge.apply! self + self.status = :accepted + self.save + end + + def reject! + self.status = :rejected + self.save! + end end