From ce442af995f39734dd3d9d827b634b586c476fcd Mon Sep 17 00:00:00 2001 From: Jared Pace Date: Thu, 5 Aug 2010 08:59:32 -0500 Subject: [PATCH] Add full management support for projects --- app/controllers/projects_controller.rb | 38 ++++++++++++++++++++++++++++++++++++++ app/models/project.rb | 5 ++++- app/views/errs/_table.html.haml | 6 +++++- app/views/layouts/application.html.haml | 1 + app/views/projects/_configuration_instructions.html.haml | 21 +++++++++++++++++++++ app/views/projects/_fields.html.haml | 10 ++++++++++ app/views/projects/edit.html.haml | 8 ++++++++ app/views/projects/index.html.haml | 1 + app/views/projects/new.html.haml | 8 ++++++++ app/views/projects/show.html.haml | 20 +++++++++++++++++++- public/stylesheets/application.css | 11 +++++++++++ spec/controllers/projects_controller_spec.rb | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 app/views/projects/_configuration_instructions.html.haml create mode 100644 app/views/projects/_fields.html.haml create mode 100644 app/views/projects/edit.html.haml create mode 100644 app/views/projects/new.html.haml diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index a0bb87d..5ccf717 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -9,4 +9,42 @@ class ProjectsController < ApplicationController @errs = @project.errs.paginate end + def new + @project = Project.new + @project.watchers.build + end + + def edit + @project = Project.find(params[:id]) + @project.watchers.build if @project.watchers.none? + end + + def create + @project = Project.new(params[:project]) + + if @project.save + flash[:success] = 'Great success! Configure your project with the API key below' + redirect_to project_path(@project) + else + render :new + end + end + + def update + @project = Project.find(params[:id]) + + if @project.update_attributes(params[:project]) + flash[:success] = "Good news everyone! '#{@project.name}' was successfully updated." + redirect_to project_path(@project) + else + render :edit + end + end + + def destroy + @project = Project.find(params[:id]) + @project.destroy + flash[:success] = "'#{@project.name}' was successfully destroyed." + redirect_to projects_path + end end diff --git a/app/models/project.rb b/app/models/project.rb index cf6d89c..cd6665b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -8,13 +8,16 @@ class Project embeds_many :watchers embeds_many :deploys - references_many :errs + references_many :errs, :dependent => :destroy before_validation :generate_api_key, :on => :create validates_presence_of :name, :api_key validates_uniqueness_of :name, :api_key, :allow_blank => true + accepts_nested_attributes_for :watchers, + :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } } + def self.find_by_api_key!(key) where(:api_key => key).first || raise(Mongoid::Errors::DocumentNotFound.new(self,key)) end diff --git a/app/views/errs/_table.html.haml b/app/views/errs/_table.html.haml index 6628366..574f320 100644 --- a/app/views/errs/_table.html.haml +++ b/app/views/errs/_table.html.haml @@ -20,4 +20,8 @@ %em= err.where %td.latest #{time_ago_in_words(err.last_notice_at)} ago %td.deploy= err.project.last_deploy_at ? err.project.last_deploy_at.to_date.to_s(:micro) : 'n/a' - %td.count= err.notices.count \ No newline at end of file + %td.count= err.notices.count + - if errs.none? + %tr + %td{:colspan => (@project ? 5 : 6)} + %em No errors have been caught, yet \ No newline at end of file diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 21b044a..0eec155 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -5,6 +5,7 @@ Hypnotoad — = yield(:page_title).present? ? yield(:page_title) : yield(:title) %meta{ :content => "text/html; charset=utf-8", "http-equiv" => "content-type" }/ + = csrf_meta_tag = javascript_include_tag :defaults = stylesheet_link_tag 'reset', 'application' = yield :head diff --git a/app/views/projects/_configuration_instructions.html.haml b/app/views/projects/_configuration_instructions.html.haml new file mode 100644 index 0000000..f5e9ee0 --- /dev/null +++ b/app/views/projects/_configuration_instructions.html.haml @@ -0,0 +1,21 @@ +%pre + %code + :preserve + + # Require the hoptoad_notifier gem in you App. + # + # Rails 3 - In your Gemfile + # gem 'hoptoad_notifier' + # + # Rails 2 - In environment.rb + # config.gem 'hoptoad_notifier' + # + # Then add the following to config/initializers/hoptoad.rb + HoptoadNotifier.configure do |config| + config.api_key = '#{project.api_key}' + config.host = '#{request.host}' + config.port = #{request.port} + # Note: Deployment notifications only work on port 80 + end + + \ No newline at end of file diff --git a/app/views/projects/_fields.html.haml b/app/views/projects/_fields.html.haml new file mode 100644 index 0000000..617880d --- /dev/null +++ b/app/views/projects/_fields.html.haml @@ -0,0 +1,10 @@ +%div.required + = f.label :name + = f.text_field :name + +%fieldset + %legend Watchers + - f.fields_for :watchers do |w| + %div + = w.label :email + = w.text_field :email \ No newline at end of file diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml new file mode 100644 index 0000000..7e489fb --- /dev/null +++ b/app/views/projects/edit.html.haml @@ -0,0 +1,8 @@ +- content_for :title, 'Edit Project' +- content_for :action_bar, link_to('cancel', project_path(@project)) + += form_for @project do |f| + + = render 'fields', :f => f + + %div= f.submit 'Update' \ No newline at end of file diff --git a/app/views/projects/index.html.haml b/app/views/projects/index.html.haml index 2237e5b..6d37564 100644 --- a/app/views/projects/index.html.haml +++ b/app/views/projects/index.html.haml @@ -1,4 +1,5 @@ - content_for :title, 'Projects' +- content_for :action_bar, link_to('new project', new_project_path) %table.projects %thead diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml new file mode 100644 index 0000000..3b46e18 --- /dev/null +++ b/app/views/projects/new.html.haml @@ -0,0 +1,8 @@ +- content_for :title, 'Add Project' +- content_for :action_bar, link_to('cancel', projects_path) + += form_for @project do |f| + + = render 'fields', :f => f + + %div= f.submit 'Add' \ No newline at end of file diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index c127405..98b74e1 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -7,7 +7,25 @@ - content_for :action_bar do = link_to 'edit', edit_project_path(@project) | - = link_to 'destroy', project_path(@project), :method => :destroy, :confirm => 'Seriously?' + = link_to 'destroy', project_path(@project), :method => :delete, :confirm => 'Seriously?' + +- if @project.errs.none? + %h3 Setup your app + = render 'configuration_instructions', :project => @project + +%h3 Watchers +%table.watchers + %thead + %tr + %th Email + %tbody + - @project.watchers.each do |watcher| + %tr + %td= watcher.email + - if @project.watchers.none? + %tr + %td + %em Sadly, no one is watching this project %h3 Errors = render 'errs/table', :errs => @errs \ No newline at end of file diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index b5ceec7..480fa7a 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -151,6 +151,17 @@ table th { background-color: #E2E2E2; font-weight: bold; text-transform: upperca table tbody tr:nth-child(odd) td { background-color: #F9F9F9; } table .main { width: 100%; } +/* Code */ +pre { + padding: 0.8em; + margin-bottom: 1em; + color: #f0f0f0; + background-color: #222; + border: 1px solid #444; + font-family: monaco, courier, monospace; + font-size: 1.1em; +} + /* HTML Styling */ .html { padding-left: 1em; border-left: 2px solid #C6C6C6;} .html h1, .html h2, .html h3, .html h4, .html h5, .html h6 { diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index f55abc5..8451b70 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -19,4 +19,110 @@ describe ProjectsController do end end + describe "GET /projects/new" do + it 'instantiates a new project with a prebuilt watcher' do + get :new + assigns(:project).should be_a(Project) + assigns(:project).should be_new_record + assigns(:project).watchers.should_not be_empty + end + end + + describe "GET /projects/:id/edit" do + it 'finds the correct project' do + project = Factory(:project) + get :edit, :id => project.id + assigns(:project).should == project + end + end + + describe "POST /projects" do + before do + @project = Factory(:project) + Project.stub(:new).and_return(@project) + end + + context "when the create is successful" do + before do + @project.should_receive(:save).and_return(true) + end + + it "should redirect to the project page" do + post :create, :project => {} + response.should redirect_to(project_path(@project)) + end + + it "should display a message" do + post :create, :project => {} + request.flash[:success].should match(/success/) + end + end + + context "when the create is unsuccessful" do + it "should render the new page" do + @project.should_receive(:save).and_return(false) + post :create, :project => {} + response.should render_template(:new) + end + end + end + + describe "PUT /projects/:id" do + before do + @project = Factory(:project) + Project.stub(:find).with(@project.id).and_return(@project) + end + + context "when the update is successful" do + before do + @project.should_receive(:update_attributes).and_return(true) + end + + it "should redirect to the project page" do + put :update, :id => @project.id, :project => {} + response.should redirect_to(project_path(@project)) + end + + it "should display a message" do + put :update, :id => @project.id, :project => {} + request.flash[:success].should match(/success/) + end + end + + context "when the update is unsuccessful" do + it "should render the edit page" do + @project.should_receive(:update_attributes).and_return(false) + put :update, :id => @project.id, :project => {} + response.should render_template(:edit) + end + end + end + + describe "DELETE /projects/:id" do + before do + @project = Factory(:project) + Project.stub(:find).with(@project.id).and_return(@project) + end + + it "should find the project" do + delete :destroy, :id => @project.id + assigns(:project).should == @project + end + + it "should destroy the project" do + @project.should_receive(:destroy) + delete :destroy, :id => @project.id + end + + it "should display a message" do + delete :destroy, :id => @project.id + request.flash[:success].should match(/success/) + end + + it "should redirect to the projects page" do + delete :destroy, :id => @project.id + response.should redirect_to(projects_path) + end + end + end -- libgit2 0.21.2