From b3941980593369312295525ddce820134a14b852 Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Wed, 10 Sep 2014 20:43:57 -0400 Subject: [PATCH 01/17] Add a note scaffolding --- app/controllers/notes_controller.rb | 74 +++++++++++++++++++++++ app/models/note.rb | 5 ++ app/models/user.rb | 1 + app/views/notes/_form.html.erb | 25 ++++++++ app/views/notes/edit.html.erb | 6 ++ app/views/notes/index.html.erb | 29 +++++++++ app/views/notes/index.json.jbuilder | 4 ++ app/views/notes/new.html.erb | 5 ++ app/views/notes/show.html.erb | 14 +++++ app/views/notes/show.json.jbuilder | 1 + config/routes.rb | 2 + db/migrate/20140911002456_create_notes.rb | 10 +++ 12 files changed, 176 insertions(+) create mode 100644 app/controllers/notes_controller.rb create mode 100644 app/models/note.rb create mode 100644 app/views/notes/_form.html.erb create mode 100644 app/views/notes/edit.html.erb create mode 100644 app/views/notes/index.html.erb create mode 100644 app/views/notes/index.json.jbuilder create mode 100644 app/views/notes/new.html.erb create mode 100644 app/views/notes/show.html.erb create mode 100644 app/views/notes/show.json.jbuilder create mode 100644 db/migrate/20140911002456_create_notes.rb diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb new file mode 100644 index 0000000..d9d139e --- /dev/null +++ b/app/controllers/notes_controller.rb @@ -0,0 +1,74 @@ +class NotesController < ApplicationController + before_action :set_note, only: [:show, :edit, :update, :destroy] + + # GET /notes + # GET /notes.json + def index + @notes = Note.all + end + + # GET /notes/1 + # GET /notes/1.json + def show + end + + # GET /notes/new + def new + @note = Note.new + end + + # GET /notes/1/edit + def edit + end + + # POST /notes + # POST /notes.json + def create + @note = Note.new(note_params) + + respond_to do |format| + if @note.save + format.html { redirect_to @note, notice: 'Note was successfully created.' } + format.json { render action: 'show', status: :created, location: @note } + else + format.html { render action: 'new' } + format.json { render json: @note.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /notes/1 + # PATCH/PUT /notes/1.json + def update + respond_to do |format| + if @note.update(note_params) + format.html { redirect_to @note, notice: 'Note was successfully updated.' } + format.json { head :no_content } + else + format.html { render action: 'edit' } + format.json { render json: @note.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /notes/1 + # DELETE /notes/1.json + def destroy + @note.destroy + respond_to do |format| + format.html { redirect_to notes_url } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_note + @note = Note.find(params[:id]) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def note_params + params.require(:note).permit(:value, :user_id) + end +end diff --git a/app/models/note.rb b/app/models/note.rb new file mode 100644 index 0000000..8b15928 --- /dev/null +++ b/app/models/note.rb @@ -0,0 +1,5 @@ +class Note < ActiveRecord::Base + belongs_to :user + + validates :value, presence: true +end diff --git a/app/models/user.rb b/app/models/user.rb index 3e108eb..4092e95 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,5 @@ class User < ActiveRecord::Base + has_many :notes # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :omniauthable, diff --git a/app/views/notes/_form.html.erb b/app/views/notes/_form.html.erb new file mode 100644 index 0000000..338ed1f --- /dev/null +++ b/app/views/notes/_form.html.erb @@ -0,0 +1,25 @@ +<%= form_for(@note) do |f| %> + <% if @note.errors.any? %> +
+

<%= pluralize(@note.errors.count, "error") %> prohibited this note from being saved:

+ + +
+ <% end %> + +
+ <%= f.label :value %>
+ <%= f.text_field :value %> +
+
+ <%= f.label :user_id %>
+ <%= f.number_field :user_id %> +
+
+ <%= f.submit %> +
+<% end %> diff --git a/app/views/notes/edit.html.erb b/app/views/notes/edit.html.erb new file mode 100644 index 0000000..b72a83e --- /dev/null +++ b/app/views/notes/edit.html.erb @@ -0,0 +1,6 @@ +

Editing note

+ +<%= render 'form' %> + +<%= link_to 'Show', @note %> | +<%= link_to 'Back', notes_path %> diff --git a/app/views/notes/index.html.erb b/app/views/notes/index.html.erb new file mode 100644 index 0000000..6884d3b --- /dev/null +++ b/app/views/notes/index.html.erb @@ -0,0 +1,29 @@ +

Listing notes

+ + + + + + + + + + + + + + <% @notes.each do |note| %> + + + + + + + + <% end %> + +
ValueUser
<%= note.value %><%= note.user_id %><%= link_to 'Show', note %><%= link_to 'Edit', edit_note_path(note) %><%= link_to 'Destroy', note, method: :delete, data: { confirm: 'Are you sure?' } %>
+ +
+ +<%= link_to 'New Note', new_note_path %> diff --git a/app/views/notes/index.json.jbuilder b/app/views/notes/index.json.jbuilder new file mode 100644 index 0000000..a7f871c --- /dev/null +++ b/app/views/notes/index.json.jbuilder @@ -0,0 +1,4 @@ +json.array!(@notes) do |note| + json.extract! note, :value, :user_id + json.url note_url(note, format: :json) +end diff --git a/app/views/notes/new.html.erb b/app/views/notes/new.html.erb new file mode 100644 index 0000000..7c6b790 --- /dev/null +++ b/app/views/notes/new.html.erb @@ -0,0 +1,5 @@ +

New note

+ +<%= render 'form' %> + +<%= link_to 'Back', notes_path %> diff --git a/app/views/notes/show.html.erb b/app/views/notes/show.html.erb new file mode 100644 index 0000000..bc02d93 --- /dev/null +++ b/app/views/notes/show.html.erb @@ -0,0 +1,14 @@ +

<%= notice %>

+ +

+ Value: + <%= @note.value %> +

+ +

+ User: + <%= @note.user_id %> +

+ +<%= link_to 'Edit', edit_note_path(@note) %> | +<%= link_to 'Back', notes_path %> diff --git a/app/views/notes/show.json.jbuilder b/app/views/notes/show.json.jbuilder new file mode 100644 index 0000000..d98bdeb --- /dev/null +++ b/app/views/notes/show.json.jbuilder @@ -0,0 +1 @@ +json.extract! @note, :value, :user_id, :created_at, :updated_at diff --git a/config/routes.rb b/config/routes.rb index ab0efd8..a713bce 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,6 @@ Carbuncle::Application.routes.draw do + resources :notes + resources :products get 'fader' => 'paintings#fader' delete 'image_batch_destroy' => 'paintings#batch_destroy' diff --git a/db/migrate/20140911002456_create_notes.rb b/db/migrate/20140911002456_create_notes.rb new file mode 100644 index 0000000..1fb8d0f --- /dev/null +++ b/db/migrate/20140911002456_create_notes.rb @@ -0,0 +1,10 @@ +class CreateNotes < ActiveRecord::Migration + def change + create_table :notes do |t| + t.string :value + t.integer :user_id + + t.timestamps + end + end +end From f2028d49459c4e55323dd3260fb301a439709140 Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Wed, 10 Sep 2014 22:29:15 -0400 Subject: [PATCH 02/17] Refactor notes index/show/edit/create --- app/controllers/notes_controller.rb | 97 +++++++++++++------------ app/models/note.rb | 17 +++++ app/presenters/note_presenter.rb | 12 +++ app/views/layouts/application.html.erb | 1 + app/views/notes/_form.html.erb | 25 ------- app/views/notes/_list.html.haml | 14 ++++ app/views/notes/_notes_table.html.haml | 15 ++++ app/views/notes/edit.html.erb | 6 -- app/views/notes/form.html.haml | 24 ++++++ app/views/notes/index.html.erb | 29 -------- app/views/notes/index.html.haml | 43 +++++++++++ app/views/notes/new.html.erb | 5 -- app/views/notes/show.html.erb | 14 ---- app/views/notes/show.html.haml | 13 ++++ db/development.sqlite3 | Bin 26624 -> 26624 bytes db/schema.rb | 9 ++- db/test.sqlite3 | Bin 11264 -> 12288 bytes spec/factories/notes.rb | 5 ++ spec/models/note_spec.rb | 72 ++++++++++++++++++ 19 files changed, 276 insertions(+), 125 deletions(-) create mode 100644 app/presenters/note_presenter.rb delete mode 100644 app/views/notes/_form.html.erb create mode 100644 app/views/notes/_list.html.haml create mode 100644 app/views/notes/_notes_table.html.haml delete mode 100644 app/views/notes/edit.html.erb create mode 100644 app/views/notes/form.html.haml delete mode 100644 app/views/notes/index.html.erb create mode 100644 app/views/notes/index.html.haml delete mode 100644 app/views/notes/new.html.erb delete mode 100644 app/views/notes/show.html.erb create mode 100644 app/views/notes/show.html.haml create mode 100644 spec/factories/notes.rb create mode 100644 spec/models/note_spec.rb diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index d9d139e..4de1a61 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -1,74 +1,81 @@ class NotesController < ApplicationController - before_action :set_note, only: [:show, :edit, :update, :destroy] - - # GET /notes - # GET /notes.json + before_action :setup_sorting_variables, only: [:index] + before_action :find_note, except: [:index] + def index - @notes = Note.all + sort_key = [:value, :email, :created, :updated][@sort] + direction = (@asc == 1) ? :asc : :desc + + @notes = Note.similar_notes(params[:search]). + ordered_by(sort_key, direction).page(@page).per_page(10) end - # GET /notes/1 - # GET /notes/1.json def show end - # GET /notes/new def new - @note = Note.new + setup_form end - # GET /notes/1/edit def edit + setup_form end - # POST /notes - # POST /notes.json def create - @note = Note.new(note_params) - - respond_to do |format| - if @note.save - format.html { redirect_to @note, notice: 'Note was successfully created.' } - format.json { render action: 'show', status: :created, location: @note } - else - format.html { render action: 'new' } - format.json { render json: @note.errors, status: :unprocessable_entity } - end - end + save_form end - # PATCH/PUT /notes/1 - # PATCH/PUT /notes/1.json def update - respond_to do |format| - if @note.update(note_params) - format.html { redirect_to @note, notice: 'Note was successfully updated.' } - format.json { head :no_content } - else - format.html { render action: 'edit' } - format.json { render json: @note.errors, status: :unprocessable_entity } - end - end + save_form end - # DELETE /notes/1 - # DELETE /notes/1.json def destroy - @note.destroy - respond_to do |format| - format.html { redirect_to notes_url } - format.json { head :no_content } + if @note.nil? + flash[:error] = "Can't find note" + elsif @note.new_record? + flash[:error] = "Can't destroy new note" + else + flash[:notice] = "You destroyed #{@note.value}" + @note.destroy end + + redirect_to notes_path end private - # Use callbacks to share common setup or constraints between actions. - def set_note - @note = Note.find(params[:id]) + def find_note + @note = if params[:id].blank? + Note.new + else + Note.where(id: params[:id]).first + end + end + + def setup_form + render :form + end + + def save_form + @note.attributes = note_params + if @note.save + flash[:notice] = "Successfully saved #{@note.value}" + redirect_to notes_url + else + setup_form + end end - # Never trust parameters from the scary internet, only allow the white list through. def note_params - params.require(:note).permit(:value, :user_id) + params.require(:note).permit(:value, :user) + end + + def view_content + render params[:action] + end + + def setup_sorting_variables + @sort = params[:sort].blank? ? 0 : params[:sort].to_i + @asc = params[:asc].blank? ? 0 : params[:asc].to_i + @page = params[:page].blank? ? 1 : params[:page].to_i end end diff --git a/app/models/note.rb b/app/models/note.rb index 8b15928..4be831e 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -2,4 +2,21 @@ class Note < ActiveRecord::Base belongs_to :user validates :value, presence: true + + scope :similar_notes, -> (partial) { partial.blank? ? all : where{ value =~ "%#{partial}%" } } + + def self.ordered_by(sort, asc) + case sort + when :value + order{ value.send(asc) } + when :email + joins{ user.outer }.order{ user.email.send(asc) } + when :created + order{ created_at.send(asc) } + when :updated + order{ updated_at.send(asc) } + else + all + end + end end diff --git a/app/presenters/note_presenter.rb b/app/presenters/note_presenter.rb new file mode 100644 index 0000000..b09a451 --- /dev/null +++ b/app/presenters/note_presenter.rb @@ -0,0 +1,12 @@ +class NotePresenter < BasePresenter + presents :note + + delegate :value, :user, :created_at, :updated_at, to: :note + + def creator + unless note.user.nil? + note.user.email + end + end + # Other presenter methods to help show user information +end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 38ed3a1..5e6610b 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -14,6 +14,7 @@
<%= link_to "Dashboard", root_path, {class: 'btn btn-primary'} %> <%= link_to "Users", administration_manage_users_path, {class: 'btn btn-primary'} %> + <%= link_to "Notes", notes_path, {class: 'btn btn-primary'} %> <%= link_to "Images", paintings_path, {class: 'btn btn-primary'} %> <%= link_to "Image Fader", fader_path, {class: 'btn btn-primary'} %> <%= link_to "Products", products_path, {class: 'btn btn-primary'} %> diff --git a/app/views/notes/_form.html.erb b/app/views/notes/_form.html.erb deleted file mode 100644 index 338ed1f..0000000 --- a/app/views/notes/_form.html.erb +++ /dev/null @@ -1,25 +0,0 @@ -<%= form_for(@note) do |f| %> - <% if @note.errors.any? %> -
-

<%= pluralize(@note.errors.count, "error") %> prohibited this note from being saved:

- -
    - <% @note.errors.full_messages.each do |msg| %> -
  • <%= msg %>
  • - <% end %> -
-
- <% end %> - -
- <%= f.label :value %>
- <%= f.text_field :value %> -
-
- <%= f.label :user_id %>
- <%= f.number_field :user_id %> -
-
- <%= f.submit %> -
-<% end %> diff --git a/app/views/notes/_list.html.haml b/app/views/notes/_list.html.haml new file mode 100644 index 0000000..d222089 --- /dev/null +++ b/app/views/notes/_list.html.haml @@ -0,0 +1,14 @@ += will_paginate @notes + += hidden_field_tag :sort, params[:sort] += hidden_field_tag :page, params[:page] + +%table.table.table-striped + %tr + - ["Value", "User", "Created", "Modified"].each_with_index do |title, index| + %th= sortable index, title + %th + %th + %th + + = render partial: 'notes_table' diff --git a/app/views/notes/_notes_table.html.haml b/app/views/notes/_notes_table.html.haml new file mode 100644 index 0000000..6fddd76 --- /dev/null +++ b/app/views/notes/_notes_table.html.haml @@ -0,0 +1,15 @@ +- @notes.each do |note| + - present note do |n| + %tr + %td= n.value + %td + - if n.user.nil? + No User + - else + = n.user.email + + %td= n.created_at.strftime('%D') + %td= n.updated_at.strftime('%D') + %td= link_to "Show", n.note + %td= link_to 'Edit', edit_note_path(n.note) + %td= link_to 'Destroy', n.note, method: :delete, data: { confirm: "Are you sure?" } \ No newline at end of file diff --git a/app/views/notes/edit.html.erb b/app/views/notes/edit.html.erb deleted file mode 100644 index b72a83e..0000000 --- a/app/views/notes/edit.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -

Editing note

- -<%= render 'form' %> - -<%= link_to 'Show', @note %> | -<%= link_to 'Back', notes_path %> diff --git a/app/views/notes/form.html.haml b/app/views/notes/form.html.haml new file mode 100644 index 0000000..2a79e18 --- /dev/null +++ b/app/views/notes/form.html.haml @@ -0,0 +1,24 @@ +%h1= (@note.new_record?) ? 'Create note' : 'Edit note' + +- if @note.errors.any? + #error_explanation + %h2= pluralize(@note.errors.count, t(:error)).html_safe + t(:_prohibited_this_note_from_being_saved) + %ul + - @note.errors.full_messages.each do |msg| + %li= msg + +.elem.generic_form + = form_for @note, as: :note, url: "/notes/#{@note.id}" do |f| + .elem + .labels + = f.label :value + = f.text_field :value + + .btn-group.submit_field + - if @note.new_record? + = f.submit 'Create', class: 'btn btn-success' + - else + = f.submit 'Update', class: 'btn btn-success' + = link_to 'Show', @note, { class: 'btn btn-default' } + + = link_to 'Back', notes_path, { class: 'btn btn-default' } diff --git a/app/views/notes/index.html.erb b/app/views/notes/index.html.erb deleted file mode 100644 index 6884d3b..0000000 --- a/app/views/notes/index.html.erb +++ /dev/null @@ -1,29 +0,0 @@ -

Listing notes

- - - - - - - - - - - - - - <% @notes.each do |note| %> - - - - - - - - <% end %> - -
ValueUser
<%= note.value %><%= note.user_id %><%= link_to 'Show', note %><%= link_to 'Edit', edit_note_path(note) %><%= link_to 'Destroy', note, method: :delete, data: { confirm: 'Are you sure?' } %>
- -
- -<%= link_to 'New Note', new_note_path %> diff --git a/app/views/notes/index.html.haml b/app/views/notes/index.html.haml new file mode 100644 index 0000000..56f13da --- /dev/null +++ b/app/views/notes/index.html.haml @@ -0,0 +1,43 @@ +%h1 Listing Notes + +%br/ + +.elem + = form_tag notes_path, method: :get, id: "note_search" do + = text_field_tag :search, params[:search], placeholder: "Search notes" + = submit_tag "Search", name: nil + +- unless @notes.empty? + .elem{ id: 'notes_table' } + = render partial: 'list' +- else + .elem + - if params[:search].blank? + No notes exist + - else + No notes match your search criteria + + +%br/ +%br/ + +.white_link.small_margin + = link_to "New note", new_note_path, class: 'btn btn-default' + + +:javascript + // Add click event to each of the headers of the notes table, and pagination + $(function () { + $('#notes_table th a, #notes_table .pagination a').on('click', ↵ + function () { + $.getScript(this.href); + return false; + } + ); + + // Search form. + $('#note_search').submit(function () { + $.get(this.action, $(this).serialize(), null, 'script'); + return false; + }); + }); \ No newline at end of file diff --git a/app/views/notes/new.html.erb b/app/views/notes/new.html.erb deleted file mode 100644 index 7c6b790..0000000 --- a/app/views/notes/new.html.erb +++ /dev/null @@ -1,5 +0,0 @@ -

New note

- -<%= render 'form' %> - -<%= link_to 'Back', notes_path %> diff --git a/app/views/notes/show.html.erb b/app/views/notes/show.html.erb deleted file mode 100644 index bc02d93..0000000 --- a/app/views/notes/show.html.erb +++ /dev/null @@ -1,14 +0,0 @@ -

<%= notice %>

- -

- Value: - <%= @note.value %> -

- -

- User: - <%= @note.user_id %> -

- -<%= link_to 'Edit', edit_note_path(@note) %> | -<%= link_to 'Back', notes_path %> diff --git a/app/views/notes/show.html.haml b/app/views/notes/show.html.haml new file mode 100644 index 0000000..8484cc5 --- /dev/null +++ b/app/views/notes/show.html.haml @@ -0,0 +1,13 @@ +.elem.small_margin.btn-group + = link_to 'Edit', edit_note_path(@note), { class: 'btn btn-default' } + = link_to 'Back', notes_path, { class: 'btn btn-default' } + +.elem + .label + Title: + = @note.value +.elem + .label + - unless @note.user.nil? + User: + = @note.user.email \ No newline at end of file diff --git a/db/development.sqlite3 b/db/development.sqlite3 index e180fc65db9a9ec5882d965c4fcccec6d4f64af3..01e83d3e1279d19bd8bd9dfba24d57f4c43e7240 100644 GIT binary patch literal 26624 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 F765IgJF)-( delta 101 zcmZojXo#2~Ey%{ez`zZ}Fu*xc$C#0AW5N<<9v0>u49xGC?=YWY-mzJbX9e@*9qc|p v(XAlS+sr4Jw*p0%GH>3>?JvT|%J7 Date: Thu, 11 Sep 2014 17:30:41 -0400 Subject: [PATCH 03/17] Fix typo --- app/controllers/products_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 393047d..5b5000f 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -3,7 +3,7 @@ class ProductsController < ApplicationController before_action :find_product, except: [:index] def index - sort_key = [:name, :descritpion, :cost, :created, :updated][@sort] + sort_key = [:name, :description, :cost, :created, :updated][@sort] direction = (@asc == 1) ? :asc : :desc @products = Product.similar_names(params[:search]). From 4580d1718140c2ce61ba96d4d8428b4b323bc712 Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Thu, 11 Sep 2014 17:31:44 -0400 Subject: [PATCH 04/17] Add a user email text field which triggers a partial user email search to be able to either fill out the email, or click on an email from the list shown. --- app/controllers/notes_controller.rb | 9 ++++- app/views/layouts/_user_list.html.haml | 6 +++ app/views/notes/form.html.haml | 54 +++++++++++++++++++++++++- config/routes.rb | 1 + 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 app/views/layouts/_user_list.html.haml diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index 4de1a61..9e0c1e5 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -10,6 +10,13 @@ def index ordered_by(sort_key, direction).page(@page).per_page(10) end + def search_users + @users = User.similar_emails(params[:partial_email]). + ordered_by(:email, :asc).limit(10) + + render partial: "/layouts/user_list" + end + def show end @@ -66,7 +73,7 @@ def save_form end def note_params - params.require(:note).permit(:value, :user) + params.require(:note).permit(:value, :user_id) end def view_content diff --git a/app/views/layouts/_user_list.html.haml b/app/views/layouts/_user_list.html.haml new file mode 100644 index 0000000..d0fd02b --- /dev/null +++ b/app/views/layouts/_user_list.html.haml @@ -0,0 +1,6 @@ +- unless @users.empty? + .elem + Select from similar users with similar emails + - @users.each do |u| + .selection{ id: u.id } + = u.email \ No newline at end of file diff --git a/app/views/notes/form.html.haml b/app/views/notes/form.html.haml index 2a79e18..83b9f0d 100644 --- a/app/views/notes/form.html.haml +++ b/app/views/notes/form.html.haml @@ -12,8 +12,16 @@ .elem .labels = f.label :value - = f.text_field :value - + = f.text_field :value, class: "form-control" + + = f.hidden_field :user_id + + .elem + .labels + = label_tag :user_email + = text_field_tag :user_email, f.object.user.nil? ? "" : f.object.user.email, "data-bind" => "value: email, valueUpdate: 'afterkeydown'", class: "form-control" + .results.well + .btn-group.submit_field - if @note.new_record? = f.submit 'Create', class: 'btn btn-success' @@ -22,3 +30,45 @@ = link_to 'Show', @note, { class: 'btn btn-default' } = link_to 'Back', notes_path, { class: 'btn btn-default' } + +:javascript + $('.results').hide(); + + var initial_user = $('#user_email').val(), + viewModel = { email: ko.observable(initial_user || '') }; + + viewModel.email.subscribe(function (partial) { + if (partial === '') { + $('#note_user_id').val(''); + } else { + var posting = {partial_email: ko.unwrap(partial)}; + $.ajax({ + url: '#{search_users_path}', + method: 'post', + data: posting, + success: function (results) { + $('.results').html(results); + + if (results.match(/selection/) === null) { + $('.results').show(); + $('#note_user_id').val(''); + $('.results'). + html("User email doesn't match records. Updating will clear this note's user"); + } else { + $('.results').show(); + + $('.selection').on('click', function (e) { + $('#note_user_id').val(e.currentTarget.id); + $('#user_email').val(e.currentTarget.innerText); + $('.results').hide(); + }); + } + }, + error: function (jqXHR, textStatus, errorThrown) { + alert(jqXHR.responseText); + } + }); + } + }); + + ko.applyBindings(viewModel); \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index a713bce..de54fe4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,6 @@ Carbuncle::Application.routes.draw do resources :notes + post 'search_users' => 'notes#search_users' resources :products get 'fader' => 'paintings#fader' From 81f43230e6ca1e96b6b8ee8cb2fd34f4192013f2 Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Thu, 11 Sep 2014 20:14:17 -0400 Subject: [PATCH 05/17] If a user email has been typed in but not clicked on, update the hidden user_id before the form submits --- app/views/notes/form.html.haml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/views/notes/form.html.haml b/app/views/notes/form.html.haml index 83b9f0d..c443a7a 100644 --- a/app/views/notes/form.html.haml +++ b/app/views/notes/form.html.haml @@ -71,4 +71,17 @@ } }); + //Before form submits check if the user id can be updated + $('#edit_note').submit(function () { + if ($('.selection:visible').length > 0) { + var current_partial_email = $('#user_email').val(); + + $('.selection').each(function (i, selection) { + if (selection.innerText === current_partial_email) { + $('#note_user_id').val(selection.id); + } + }); + } + }); + ko.applyBindings(viewModel); \ No newline at end of file From 498aa7a711457c4c9c220a3edf52f2707e30e9b2 Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Thu, 11 Sep 2014 20:49:09 -0400 Subject: [PATCH 06/17] Use the note presenter function instead of adding the logic to the page --- app/views/notes/_notes_table.html.haml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/views/notes/_notes_table.html.haml b/app/views/notes/_notes_table.html.haml index 6fddd76..559eb2a 100644 --- a/app/views/notes/_notes_table.html.haml +++ b/app/views/notes/_notes_table.html.haml @@ -2,12 +2,7 @@ - present note do |n| %tr %td= n.value - %td - - if n.user.nil? - No User - - else - = n.user.email - + %td= n.creator || "No user" %td= n.created_at.strftime('%D') %td= n.updated_at.strftime('%D') %td= link_to "Show", n.note From b42f808aa028c4ddf4d3fa18796a28dd9dc69582 Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Thu, 11 Sep 2014 20:49:27 -0400 Subject: [PATCH 07/17] Remove some useless scripts --- app/helpers/application_helper.rb | 2 +- app/views/administration/manage_users/index.html.haml | 8 -------- app/views/notes/index.html.haml | 7 ------- app/views/products/index.html.haml | 7 ------- 4 files changed, 1 insertion(+), 23 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index c369bd5..30fa72a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,7 +1,7 @@ module ApplicationHelper def sortable(column, title = nil) title ||= column.titleize - css_class = (column == @sort) ? "current ↵ #{(@asc == 1) ? 'asc' : 'desc'}" : nil + css_class = (column == @sort) ? "current #{(@asc == 1) ? 'asc' : 'desc'}" : nil direction = (column == @sort && @asc == 1) ? 0 : 1 #link_to title, {:sort => column, :direction => direction}, {:class => css_class} link_to title, params.merge(sort: column, asc: direction, page: nil), {:class => css_class} diff --git a/app/views/administration/manage_users/index.html.haml b/app/views/administration/manage_users/index.html.haml index 28feb30..2fa2c5a 100644 --- a/app/views/administration/manage_users/index.html.haml +++ b/app/views/administration/manage_users/index.html.haml @@ -17,7 +17,6 @@ - else No users match your search criteria - %br/ %br/ @@ -28,13 +27,6 @@ :javascript // Add click event to each of the headers of the products table, and pagination $(function () { - $('#users_table th a, #users_table .pagination a').on('click', ↵ - function () { - $.getScript(this.href); - return false; - } - ); - // Search form. $('#user_search').submit(function () { $.get(this.action, $(this).serialize(), null, 'script'); diff --git a/app/views/notes/index.html.haml b/app/views/notes/index.html.haml index 56f13da..40d0f13 100644 --- a/app/views/notes/index.html.haml +++ b/app/views/notes/index.html.haml @@ -28,13 +28,6 @@ :javascript // Add click event to each of the headers of the notes table, and pagination $(function () { - $('#notes_table th a, #notes_table .pagination a').on('click', ↵ - function () { - $.getScript(this.href); - return false; - } - ); - // Search form. $('#note_search').submit(function () { $.get(this.action, $(this).serialize(), null, 'script'); diff --git a/app/views/products/index.html.haml b/app/views/products/index.html.haml index adc8147..43d11fd 100644 --- a/app/views/products/index.html.haml +++ b/app/views/products/index.html.haml @@ -28,13 +28,6 @@ :javascript // Add click event to each of the headers of the products table, and pagination $(function () { - $('#products_table th a, #products_table .pagination a').on('click', ↵ - function () { - $.getScript(this.href); - return false; - } - ); - // Search form. $('#product_search').submit(function () { $.get(this.action, $(this).serialize(), null, 'script'); From 04446a7d8d66b71448bcc30d34a8a249c87c3732 Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Thu, 11 Sep 2014 20:55:19 -0400 Subject: [PATCH 08/17] Fix wording a bit --- app/views/layouts/_user_list.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/_user_list.html.haml b/app/views/layouts/_user_list.html.haml index d0fd02b..9b81656 100644 --- a/app/views/layouts/_user_list.html.haml +++ b/app/views/layouts/_user_list.html.haml @@ -1,6 +1,6 @@ - unless @users.empty? .elem - Select from similar users with similar emails + Select from users with similar emails - @users.each do |u| .selection{ id: u.id } = u.email \ No newline at end of file From 63273333ff32eebc7fdfcb2df53a4ce6a529c56e Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Thu, 11 Sep 2014 21:25:12 -0400 Subject: [PATCH 09/17] Remove more useless scripts --- app/views/administration/manage_users/index.html.haml | 11 ----------- app/views/notes/index.html.haml | 11 ----------- app/views/notes/show.html.haml | 8 ++++---- app/views/products/index.html.haml | 11 ----------- 4 files changed, 4 insertions(+), 37 deletions(-) diff --git a/app/views/administration/manage_users/index.html.haml b/app/views/administration/manage_users/index.html.haml index 2fa2c5a..8949746 100644 --- a/app/views/administration/manage_users/index.html.haml +++ b/app/views/administration/manage_users/index.html.haml @@ -22,14 +22,3 @@ .white_link.small_margin = link_to "New User", new_administration_manage_user_path, class: 'btn btn-default' - - -:javascript - // Add click event to each of the headers of the products table, and pagination - $(function () { - // Search form. - $('#user_search').submit(function () { - $.get(this.action, $(this).serialize(), null, 'script'); - return false; - }); - }); \ No newline at end of file diff --git a/app/views/notes/index.html.haml b/app/views/notes/index.html.haml index 40d0f13..6686bec 100644 --- a/app/views/notes/index.html.haml +++ b/app/views/notes/index.html.haml @@ -23,14 +23,3 @@ .white_link.small_margin = link_to "New note", new_note_path, class: 'btn btn-default' - - -:javascript - // Add click event to each of the headers of the notes table, and pagination - $(function () { - // Search form. - $('#note_search').submit(function () { - $.get(this.action, $(this).serialize(), null, 'script'); - return false; - }); - }); \ No newline at end of file diff --git a/app/views/notes/show.html.haml b/app/views/notes/show.html.haml index 8484cc5..4365de7 100644 --- a/app/views/notes/show.html.haml +++ b/app/views/notes/show.html.haml @@ -4,10 +4,10 @@ .elem .label - Title: + Note: = @note.value -.elem - .label - - unless @note.user.nil? +- unless @note.user.nil? + .elem + .label User: = @note.user.email \ No newline at end of file diff --git a/app/views/products/index.html.haml b/app/views/products/index.html.haml index 43d11fd..a0722c9 100644 --- a/app/views/products/index.html.haml +++ b/app/views/products/index.html.haml @@ -23,14 +23,3 @@ .white_link.small_margin = link_to "New Product", new_product_path, class: 'btn btn-default' - - -:javascript - // Add click event to each of the headers of the products table, and pagination - $(function () { - // Search form. - $('#product_search').submit(function () { - $.get(this.action, $(this).serialize(), null, 'script'); - return false; - }); - }); \ No newline at end of file From 02c1a73377b3fefe7fd531bcf480eff92a1c3672 Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Fri, 12 Sep 2014 12:50:54 -0400 Subject: [PATCH 10/17] Make the before create a validation so that bulk image uploading will create valid paintings --- app/models/painting.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/painting.rb b/app/models/painting.rb index 985702c..2eb8575 100644 --- a/app/models/painting.rb +++ b/app/models/painting.rb @@ -4,7 +4,7 @@ class Painting < ActiveRecord::Base mount_uploader :image, ImageUploader - before_create :default_title + before_validation :default_title def default_title self.title ||= File.basename(image.filename, '.*').titleize if image From 61289b600ce8f1bd5cc1d8a266d4f58376e887fe Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Mon, 15 Sep 2014 19:03:42 -0400 Subject: [PATCH 11/17] Fix manage user url --- app/controllers/administration/manage_users_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/administration/manage_users_controller.rb b/app/controllers/administration/manage_users_controller.rb index 1b6f685..a4af5fe 100644 --- a/app/controllers/administration/manage_users_controller.rb +++ b/app/controllers/administration/manage_users_controller.rb @@ -43,7 +43,7 @@ def destroy @user.destroy end - redirect_to administration_users_path + redirect_to administration_manage_users_path end private @@ -63,7 +63,7 @@ def save_form @user.attributes = user_params if @user.save flash[:notice] = "Successfully saved #{@user.email}" - redirect_to administration_users_url + redirect_to administration_manage_users_url else setup_form end From b396f68d2e0ed5c0a9887413cabb59a59947fcc6 Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Mon, 15 Sep 2014 19:44:26 -0400 Subject: [PATCH 12/17] Fix issue with replacing email text in FF --- app/views/notes/form.html.haml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/notes/form.html.haml b/app/views/notes/form.html.haml index c443a7a..9149261 100644 --- a/app/views/notes/form.html.haml +++ b/app/views/notes/form.html.haml @@ -58,8 +58,9 @@ $('.results').show(); $('.selection').on('click', function (e) { - $('#note_user_id').val(e.currentTarget.id); - $('#user_email').val(e.currentTarget.innerText); + var selection_id = e.currentTarget.id + $('#note_user_id').val(selection_id); + $('#user_email').val($('#' + selection_id).text()); $('.results').hide(); }); } From 2f8570400c884a29f476909e4a2fb8727375cdcb Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Mon, 15 Sep 2014 22:12:28 -0400 Subject: [PATCH 13/17] Use a json request instead of html to get the data back. Add a knockout template binding to the page so that when the view model's list of emails are updated, the emails will appear on the page as clickable. --- app/assets/stylesheets/carbuncle.css | 4 ++ app/controllers/notes_controller.rb | 5 +- app/views/notes/form.html.haml | 56 ++++++++++------------ app/views/notes/search_users.json.jbuilder | 3 ++ 4 files changed, 35 insertions(+), 33 deletions(-) create mode 100644 app/views/notes/search_users.json.jbuilder diff --git a/app/assets/stylesheets/carbuncle.css b/app/assets/stylesheets/carbuncle.css index 0fc4080..ffc980f 100644 --- a/app/assets/stylesheets/carbuncle.css +++ b/app/assets/stylesheets/carbuncle.css @@ -105,4 +105,8 @@ div div.elem:last-of-type .submit_field{ padding-top: 15px; +} + +.clickable { + cursor: pointer; } \ No newline at end of file diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index 9e0c1e5..8799316 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -14,7 +14,10 @@ def search_users @users = User.similar_emails(params[:partial_email]). ordered_by(:email, :asc).limit(10) - render partial: "/layouts/user_list" + respond_to do |format| + format.html { render partial: "/layouts/user_list" } + format.json { render :search_users } + end end def show diff --git a/app/views/notes/form.html.haml b/app/views/notes/form.html.haml index 9149261..ac84642 100644 --- a/app/views/notes/form.html.haml +++ b/app/views/notes/form.html.haml @@ -14,13 +14,20 @@ = f.label :value = f.text_field :value, class: "form-control" - = f.hidden_field :user_id + = f.hidden_field :user_id, "data-bind" => "value: userId" .elem .labels = label_tag :user_email = text_field_tag :user_email, f.object.user.nil? ? "" : f.object.user.email, "data-bind" => "value: email, valueUpdate: 'afterkeydown'", class: "form-control" - .results.well + + .results.well{ "data-bind" => "visible: showUserResults" } + %h5 + Please select from the list below (If the user is not found, then no user will be set) + %span{ "data-bind" => "template: { name: 'users', foreach: emailList }" } + + %script{ "id" => "users", "type" => "text/html" } + .clickable{ "data-bind" => "text: email, click: $parent.selectUser" } .btn-group.submit_field - if @note.new_record? @@ -32,38 +39,31 @@ = link_to 'Back', notes_path, { class: 'btn btn-default' } :javascript - $('.results').hide(); var initial_user = $('#user_email').val(), - viewModel = { email: ko.observable(initial_user || '') }; + initial_user_id = $('#note_user_id').val(), + viewModel = { email: ko.observable(initial_user || ''), + userId: ko.observable(initial_user_id || ''), + showUserResults: ko.observable(false), + emailList: ko.observableArray() }; viewModel.email.subscribe(function (partial) { if (partial === '') { - $('#note_user_id').val(''); + viewModel.userId(''); } else { var posting = {partial_email: ko.unwrap(partial)}; $.ajax({ url: '#{search_users_path}', + dataType: 'json', method: 'post', data: posting, success: function (results) { - $('.results').html(results); - - if (results.match(/selection/) === null) { - $('.results').show(); - $('#note_user_id').val(''); - $('.results'). - html("User email doesn't match records. Updating will clear this note's user"); + if (results.length === 1 && results[0].email === partial) { + viewModel.showUserResults(false); } else { - $('.results').show(); - - $('.selection').on('click', function (e) { - var selection_id = e.currentTarget.id - $('#note_user_id').val(selection_id); - $('#user_email').val($('#' + selection_id).text()); - $('.results').hide(); - }); + viewModel.showUserResults(true); } + viewModel.emailList(results); }, error: function (jqXHR, textStatus, errorThrown) { alert(jqXHR.responseText); @@ -72,17 +72,9 @@ } }); - //Before form submits check if the user id can be updated - $('#edit_note').submit(function () { - if ($('.selection:visible').length > 0) { - var current_partial_email = $('#user_email').val(); - - $('.selection').each(function (i, selection) { - if (selection.innerText === current_partial_email) { - $('#note_user_id').val(selection.id); - } - }); - } - }); + viewModel.selectUser = function (data) { + viewModel.email(data.email); + viewModel.userId(data.id); + }; ko.applyBindings(viewModel); \ No newline at end of file diff --git a/app/views/notes/search_users.json.jbuilder b/app/views/notes/search_users.json.jbuilder new file mode 100644 index 0000000..d1d43a3 --- /dev/null +++ b/app/views/notes/search_users.json.jbuilder @@ -0,0 +1,3 @@ +json.array!(@users) do |user| + json.extract! user, :id, :email +end From 25d7f61130fcc9ee17b8cf53fa188f1da5b9a86d Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Mon, 15 Sep 2014 22:36:02 -0400 Subject: [PATCH 14/17] Update the hidden user id only before the form submits instead of clicking on the selection list to allow users to just type the email and click update or tab to update. --- app/views/notes/form.html.haml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/views/notes/form.html.haml b/app/views/notes/form.html.haml index ac84642..155eecf 100644 --- a/app/views/notes/form.html.haml +++ b/app/views/notes/form.html.haml @@ -58,6 +58,7 @@ method: 'post', data: posting, success: function (results) { + // If the only result is the partial, then hide results if (results.length === 1 && results[0].email === partial) { viewModel.showUserResults(false); } else { @@ -74,7 +75,15 @@ viewModel.selectUser = function (data) { viewModel.email(data.email); - viewModel.userId(data.id); }; + //Before form submits check if the user id can be updated + $('#edit_note').submit(function () { + if ($('.results .clickable:hidden').length === 1) { + if (viewModel.emailList()[0].email === viewModel.email()) { + viewModel.userId(viewModel.emailList()[0].id); + } + } + }); + ko.applyBindings(viewModel); \ No newline at end of file From 64377bcc755dfb411234b3125a07cc52e8839816 Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Tue, 16 Sep 2014 17:21:36 -0400 Subject: [PATCH 15/17] Destroy notes when the associated user is destroyed. Show flash 'alert' as error. Setup a default host for development emails. setup the devise email that is the 'sender' when someone tries to reset their password --- app/models/user.rb | 2 +- app/views/layouts/application.html.erb | 6 ++++++ config/environments/development.rb | 2 ++ config/initializers/devise.rb | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 4092e95..9516456 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,5 @@ class User < ActiveRecord::Base - has_many :notes + has_many :notes, dependent: :destroy # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :omniauthable, diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 5e6610b..b3e5323 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -35,6 +35,12 @@
+ <% unless flash[:alert].blank? %> +
+ <%= flash[:alert] %> +
+ <% end %> + <% unless flash[:notice].blank? %>
<%= flash[:notice] %> diff --git a/config/environments/development.rb b/config/environments/development.rb index fbd2468..90e0c6d 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -13,6 +13,8 @@ config.consider_all_requests_local = true config.action_controller.perform_caching = false + config.action_mailer.default_url_options = { :host => "http://localhost:3000" } + # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 848d9a6..3667272 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -10,7 +10,7 @@ # Configure the e-mail address which will be shown in Devise::Mailer, # note that it will be overwritten if you use your own mailer class # with default "from" parameter. - config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com' + config.mailer_sender = 'adamdboudreau@hotmail.co.uk' # Configure the class responsible to send e-mails. # config.mailer = 'Devise::Mailer' From 39e1f3fd29752bbd0be940e048868b0a06fa1b5e Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Tue, 16 Sep 2014 17:43:11 -0400 Subject: [PATCH 16/17] Fix painting validation test failures (actually creating a new painting with just a title works) --- app/models/painting.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/painting.rb b/app/models/painting.rb index 2eb8575..6644872 100644 --- a/app/models/painting.rb +++ b/app/models/painting.rb @@ -7,7 +7,7 @@ class Painting < ActiveRecord::Base before_validation :default_title def default_title - self.title ||= File.basename(image.filename, '.*').titleize if image + self.title ||= File.basename(image.filename.to_s, '.*').titleize if image end def self.ordered_by(sort, asc) From 8ea85871ea61ebaf9b41d6a535d184c6f91417a3 Mon Sep 17 00:00:00 2001 From: Adam Boudreau Date: Tue, 16 Sep 2014 18:05:31 -0400 Subject: [PATCH 17/17] wrap the navigation links in a nav tag. Fix notes ordered by their user emails --- app/views/layouts/application.html.erb | 17 +++++++++-------- spec/models/note_spec.rb | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index b3e5323..d070a27 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -12,14 +12,15 @@
- <%= link_to "Dashboard", root_path, {class: 'btn btn-primary'} %> - <%= link_to "Users", administration_manage_users_path, {class: 'btn btn-primary'} %> - <%= link_to "Notes", notes_path, {class: 'btn btn-primary'} %> - <%= link_to "Images", paintings_path, {class: 'btn btn-primary'} %> - <%= link_to "Image Fader", fader_path, {class: 'btn btn-primary'} %> - <%= link_to "Products", products_path, {class: 'btn btn-primary'} %> - <%= link_to "Knockout test", knockout_test_path, {class: 'btn btn-primary'} %> - +
<% if user_signed_in? %> diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 8af95dc..64cecc9 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -57,8 +57,8 @@ end context "email" do - let(:u1) { FactoryGirl.create(:user) } - let(:u2) { FactoryGirl.create(:user) } + let(:u1) { FactoryGirl.create(:user, email: 'acdc@test.com') } + let(:u2) { FactoryGirl.create(:user, email: 'zztop@test.com') } before do u1.notes << notes[1] u2.notes << notes[2]