Commit 9ce0dc764fd5347f985bb36017e4468d93d3f9b8
Exists in
master
and in
1 other branch
Merge pull request #289
Showing
10 changed files
with
182 additions
and
34 deletions
Show diff stats
app/assets/javascripts/apps.show.js
1 | 1 | $(function() { |
2 | + | |
2 | 3 | $("#watchers_toggle").click(function() { |
3 | 4 | $("#watchers_div").slideToggle("slow"); |
4 | 5 | }); |
6 | + | |
5 | 7 | $("#repository_toggle").click(function() { |
6 | 8 | $("#repository_div").slideToggle("slow"); |
7 | 9 | }); |
10 | + | |
8 | 11 | $("#deploys_toggle").click(function() { |
9 | 12 | $("#deploys_div").slideToggle("slow"); |
10 | 13 | }); | ... | ... |
... | ... | @@ -0,0 +1,27 @@ |
1 | +class WatchersController < ApplicationController | |
2 | + respond_to :html | |
3 | + | |
4 | + expose(:app) do | |
5 | + App.find(params[:app_id]) | |
6 | + end | |
7 | + | |
8 | + expose(:watcher) do | |
9 | + app.watchers.where(:user_id => params[:id]).first | |
10 | + end | |
11 | + | |
12 | + before_filter :require_watcher_edit_priviledges, :only => [:destroy] | |
13 | + | |
14 | + def destroy | |
15 | + app.watchers.delete(watcher) | |
16 | + flash[:success] = "That's sad. #{watcher.label} is no longer watcher." | |
17 | + redirect_to root_path | |
18 | + end | |
19 | + | |
20 | + private | |
21 | + | |
22 | + def require_watcher_edit_priviledges | |
23 | + redirect_to(root_path) unless current_user == watcher.user || current_user.admin? | |
24 | + end | |
25 | + | |
26 | +end | |
27 | + | ... | ... |
app/views/apps/show.html.haml
1 | 1 | - content_for :title, app.name |
2 | 2 | - content_for :head do |
3 | - = auto_discovery_link_tag :atom, app_path(app, User.token_authentication_key => current_user.authentication_token, :format => "atom"), :title => "Errbit notices for #{app.name} at #{request.host}" | |
3 | + = auto_discovery_link_tag :atom, app_path(app, User.token_authentication_key => current_user.authentication_token, :format => "atom"), :title => t('.atom_title', :name => app.name, :host => request.host) | |
4 | 4 | - content_for :meta do |
5 | - %strong Errors Caught: | |
5 | + %strong=t('.errors_caught') | |
6 | 6 | = app.problems.count |
7 | - %strong Deploy Count: | |
7 | + %strong=t('.deploy_count') | |
8 | 8 | = app.deploys.count |
9 | - %strong API Key: | |
9 | + %strong=t('.api_key') | |
10 | 10 | = app.api_key |
11 | 11 | - content_for :action_bar do |
12 | 12 | - if current_user.admin? |
13 | - = link_to 'edit', edit_app_path(app), :class => 'button' | |
13 | + = link_to t('.edit'), edit_app_path(app), :class => 'button' | |
14 | 14 | - if all_errs |
15 | - = link_to 'unresolved errs', app_path(app), :class => 'button' | |
15 | + = link_to t('.unresolved_errs'), app_path(app), :class => 'button' | |
16 | 16 | - else |
17 | - = link_to 'all errs', app_path(app, :all_errs => true), :class => 'button' | |
17 | + = link_to t('.all_errs'), app_path(app, :all_errs => true), :class => 'button' | |
18 | 18 | |
19 | + - if current_user.watching?(app) | |
20 | + = link_to t('.unwatch'), app_watcher_path({:app_id => app, :id => current_user.id}), :method => :delete, :class => 'button', :confirm => t('.are_you_sure') | |
19 | 21 | %h3#watchers_toggle |
20 | - Watchers | |
21 | - %span.click_span (show/hide) | |
22 | + =t('.watchers') | |
23 | + %span.click_span=t('.show_hide') | |
22 | 24 | #watchers_div |
23 | 25 | - if app.notify_all_users |
24 | 26 | %table.watchers |
25 | 27 | %thead |
26 | 28 | %tr |
27 | - %th All users will be notified when something happens. | |
29 | + %th=t('.all_users_notified') | |
28 | 30 | - else |
29 | 31 | %table.watchers |
30 | 32 | %thead |
31 | 33 | %tr |
32 | - %th User or Email | |
34 | + %th=t('.user_or_email') | |
33 | 35 | %tbody |
34 | 36 | - app.watchers.each do |watcher| |
35 | 37 | %tr |
... | ... | @@ -37,35 +39,35 @@ |
37 | 39 | - if app.watchers.none? |
38 | 40 | %tr |
39 | 41 | %td |
40 | - %em Sadly, no one is watching this app | |
42 | + %em= t('.no_watcher') | |
41 | 43 | |
42 | 44 | - if app.github_repo? |
43 | 45 | %h3#repository_toggle |
44 | - Repository | |
45 | - %span.click_span (show/hide) | |
46 | + =t('.repository') | |
47 | + %span.click_span=t('.show_hide') | |
46 | 48 | #repository_div |
47 | 49 | %table.repository |
48 | 50 | %thead |
49 | 51 | %tr |
50 | - %th GitHub Repo | |
52 | + %th=t('.github_repo') | |
51 | 53 | %tbody |
52 | 54 | %tr |
53 | 55 | %td= link_to(app.github_repo, app.github_url, :target => '_blank') |
54 | 56 | |
55 | 57 | %h3#deploys_toggle |
56 | - Latest Deploys | |
57 | - %span.click_span (show/hide) | |
58 | + =t('.latest_deploys') | |
59 | + %span.click_span=t('.show_hide') | |
58 | 60 | #deploys_div |
59 | 61 | - if deploys.any? |
60 | 62 | %table.deploys |
61 | 63 | %thead |
62 | 64 | %tr |
63 | - %th When | |
64 | - %th Environment | |
65 | - %th Who | |
66 | - %th Message | |
67 | - %th Repository | |
68 | - %th Revision | |
65 | + %th=t('.when') | |
66 | + %th=t('.environment') | |
67 | + %th=t('.who') | |
68 | + %th=t('.message') | |
69 | + %th=t('.repository') | |
70 | + %th=t('.revision') | |
69 | 71 | |
70 | 72 | %tbody |
71 | 73 | - deploys.each do |deploy| |
... | ... | @@ -76,20 +78,20 @@ |
76 | 78 | %td.message #{deploy.message} |
77 | 79 | %td.repository #{deploy.repository} |
78 | 80 | %td.revision #{deploy.short_revision} |
79 | - = link_to "All Deploys (#{app.deploys.count})", app_deploys_path(app), :class => 'button' | |
81 | + = link_to t('.all_deploys', :count => app.deploys.count), app_deploys_path(app), :class => 'button' | |
80 | 82 | - else |
81 | - %h3 No deploys | |
83 | + %h3=t('.no_deploys') | |
82 | 84 | |
83 | 85 | - if app.problems.any? |
84 | - %h3.clear Errors | |
86 | + %h3.clear=t('.errors') | |
85 | 87 | %section |
86 | 88 | = form_tag search_problems_path(:all_errs => all_errs, :app_id => app.id), :method => :get, :remote => true do |
87 | - = text_field_tag :search, params[:search], :placeholder => 'Search for issues' | |
89 | + = text_field_tag :search, params[:search], :placeholder => t('.search_placeholder') | |
88 | 90 | %br |
89 | 91 | %section |
90 | 92 | .problem_table{:id => 'problem_table'} |
91 | 93 | = render 'problems/table', :problems => problems |
92 | 94 | - else |
93 | - %h3.clear No errs have been caught yet, make sure you setup your app | |
95 | + %h3.clear=t('.no_error_yet') | |
94 | 96 | = render 'configuration_instructions', :app => app |
95 | 97 | ... | ... |
app/views/devise/sessions/new.html.haml
config/locales/en.yml
... | ... | @@ -65,6 +65,9 @@ en: |
65 | 65 | omniauth_callbacks: |
66 | 66 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"." |
67 | 67 | success: "Successfully authenticated from %{kind} account." |
68 | + sessions: | |
69 | + new: | |
70 | + sign_in: "Sign in" | |
68 | 71 | |
69 | 72 | apps: |
70 | 73 | index: |
... | ... | @@ -78,3 +81,32 @@ en: |
78 | 81 | new_app: Add a New App |
79 | 82 | no_apps: 'No apps here.' |
80 | 83 | click_to_create: 'Click here to create your first one' |
84 | + show: | |
85 | + all_deploys: "All Deploys (%{count})" | |
86 | + all_errs: all errs | |
87 | + all_users_notified: "All users will be notified when something happens." | |
88 | + api_key: "API Key:" | |
89 | + are_you_sure: 'Are you sure?' | |
90 | + atom_title: "Errbit notices for %{name} at %{host}" | |
91 | + deploy_count: "Deploy Count:" | |
92 | + edit: edit | |
93 | + environment: Environment | |
94 | + errors: Errors | |
95 | + errors_caught: "Errors Caught:" | |
96 | + github_repo: GitHub Repo | |
97 | + latest_deploys: Latest Deploys | |
98 | + message: Message | |
99 | + no_deploys: No deploys | |
100 | + no_error_yet: "No errs have been caught yet, make sure you setup your app" | |
101 | + no_watcher: "Sadly, no one is watching this app" | |
102 | + repository: Repository | |
103 | + repository: Repository | |
104 | + revision: Revision | |
105 | + search_placeholder: 'Search for issues' | |
106 | + show_hide: "(show/hide)" | |
107 | + unresolved_errs: unresolved errs | |
108 | + unwatch: unwatch | |
109 | + user_or_email: User or Email | |
110 | + watchers: Watchers | |
111 | + when: When | |
112 | + who: Who | ... | ... |
config/routes.rb
spec/acceptance/sign_in_with_github_spec.rb
... | ... | @@ -0,0 +1,23 @@ |
1 | +require 'acceptance/acceptance_helper' | |
2 | + | |
3 | +feature 'A user can watch and unwatch an application' do | |
4 | + | |
5 | + let!(:app) { Fabricate(:app) } | |
6 | + let!(:user) do | |
7 | + user = Fabricate(:user) | |
8 | + app.watchers.create!( | |
9 | + :user_id => user.id | |
10 | + ) | |
11 | + user.reload | |
12 | + end | |
13 | + | |
14 | + scenario 'log in watch a project and unwatch it' do | |
15 | + visit '/' | |
16 | + fill_in :user_email, :with => user.email | |
17 | + fill_in :user_password, :with => 'password' | |
18 | + click_on I18n.t('devise.sessions.new.sign_in') | |
19 | + click_on I18n.t('apps.show.unwatch') | |
20 | + expect(page).to have_content(I18n.t('apps.index.no_apps') | |
21 | + end | |
22 | + | |
23 | +end | ... | ... |
... | ... | @@ -0,0 +1,36 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe WatchersController do | |
4 | + let(:app) do | |
5 | + a = Fabricate(:app) | |
6 | + Fabricate(:user_watcher, :app => a) | |
7 | + a | |
8 | + end | |
9 | + | |
10 | + describe "DELETE /apps/:app_id/watchers/:id/destroy" do | |
11 | + | |
12 | + context "with admin user" do | |
13 | + before(:each) do | |
14 | + sign_in Fabricate(:admin) | |
15 | + end | |
16 | + | |
17 | + context "successful watcher deletion" do | |
18 | + let(:problem) { Fabricate(:problem_with_comments) } | |
19 | + let(:watcher) { app.watchers.first } | |
20 | + | |
21 | + before(:each) do | |
22 | + delete :destroy, :app_id => app.id, :id => watcher.user.id.to_s | |
23 | + problem.reload | |
24 | + end | |
25 | + | |
26 | + it "should delete the watcher" do | |
27 | + app.watchers.detect{|w| w.id.to_s == watcher.id }.should == nil | |
28 | + end | |
29 | + | |
30 | + it "should redirect to index page" do | |
31 | + response.should redirect_to(root_path) | |
32 | + end | |
33 | + end | |
34 | + end | |
35 | + end | |
36 | +end | ... | ... |
spec/views/apps/show.html.haml_spec.rb
... | ... | @@ -2,17 +2,20 @@ require 'spec_helper' |
2 | 2 | |
3 | 3 | describe "apps/show.html.haml" do |
4 | 4 | let(:app) { stub_model(App) } |
5 | + let(:user) { stub_model(User) } | |
6 | + | |
7 | + let(:action_bar) do | |
8 | + view.content_for(:action_bar) | |
9 | + end | |
10 | + | |
5 | 11 | before do |
6 | 12 | view.stub(:app).and_return(app) |
7 | 13 | view.stub(:all_errs).and_return(false) |
8 | 14 | view.stub(:deploys).and_return([]) |
9 | - controller.stub(:current_user) { stub_model(User) } | |
15 | + controller.stub(:current_user) { user } | |
10 | 16 | end |
11 | 17 | |
12 | 18 | describe "content_for :action_bar" do |
13 | - def action_bar | |
14 | - view.content_for(:action_bar) | |
15 | - end | |
16 | 19 | |
17 | 20 | it "should confirm the 'cancel' link" do |
18 | 21 | render |
... | ... | @@ -28,5 +31,26 @@ describe "apps/show.html.haml" do |
28 | 31 | rendered.should match(/No errs have been/) |
29 | 32 | end |
30 | 33 | end |
34 | + | |
35 | + context "with user watch application" do | |
36 | + before do | |
37 | + user.stub(:watching?).with(app).and_return(true) | |
38 | + end | |
39 | + it 'see the unwatch button' do | |
40 | + render | |
41 | + expect(action_bar).to include(I18n.t('apps.show.unwatch')) | |
42 | + end | |
43 | + end | |
44 | + | |
45 | + context "with user not watch application" do | |
46 | + before do | |
47 | + user.stub(:watching?).with(app).and_return(false) | |
48 | + end | |
49 | + it 'not see the unwatch button' do | |
50 | + render | |
51 | + expect(action_bar).to_not include(I18n.t('apps.show.unwatch')) | |
52 | + end | |
53 | + end | |
54 | + | |
31 | 55 | end |
32 | 56 | ... | ... |