Commit da5d87f3 by Truong Ba Dieu

2.2 User management feature, 2.3 Item posting feature

parent f6cdd883
......@@ -54,6 +54,8 @@ gem "thin"
gem 'figaro', '1.1.1'
gem 'vacuum'
gem "breadcrumbs_on_rails"
gem 'momentjs-rails', '>= 2.8.1'
gem 'bootstrap3-datetimepicker-rails', '~> 4.7.14'
group :test do
# gem 'capybara' # Integration test tool to simulate a user on a website.
# gem 'capybara_minitest_spec' # MiniTest::Spec expectations for Capybara node matchers.
......
......@@ -47,6 +47,8 @@ GEM
bootstrap-sass (3.3.4.1)
autoprefixer-rails (>= 5.0.0.1)
sass (>= 3.2.19)
bootstrap3-datetimepicker-rails (4.7.14)
momentjs-rails (>= 2.8.1)
breadcrumbs_on_rails (2.3.0)
builder (3.2.2)
byebug (5.0.0)
......@@ -117,6 +119,8 @@ GEM
mime-types (2.6.1)
mini_portile (0.6.2)
minitest (5.7.0)
momentjs-rails (2.10.3)
railties (>= 3.1)
multi_json (1.11.2)
multi_xml (0.5.5)
mysql2 (0.3.18)
......@@ -225,6 +229,7 @@ PLATFORMS
DEPENDENCIES
bootstrap-sass (= 3.3.4.1)
bootstrap3-datetimepicker-rails (~> 4.7.14)
breadcrumbs_on_rails
byebug
coffee-rails (~> 4.1.0)
......@@ -239,6 +244,7 @@ DEPENDENCIES
jbuilder (~> 2.0)
jquery-rails
kaminari (= 0.16.3)
momentjs-rails (>= 2.8.1)
mysql2
rails (= 4.2.1)
rspec
......
......@@ -13,4 +13,6 @@
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
//= require moment
//= require bootstrap-datetimepicker
//= require_tree ./components
$(document).on 'ready page:load', ->
$('.datetimepicker').datetimepicker()
\ No newline at end of file
.mar-top-20{
margin-top: 20px;
margin-top: 20px!important;
}
.mar-bot-20{
margin-bottom: 20px;
margin-bottom: 20px!important;
}
.mar-r-10{
margin-right: 10px;
margin-right: 10px!important;
}
.text-center{
text-align: center;
text-align: center!important;
}
.mar-0{
margin: 0!important;
}
.pad-0{
padding: 0;
padding: 0!important;
}
.mar-l-0{
margin-left: 0!important;
}
\ No newline at end of file
......@@ -2,8 +2,24 @@ class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
layout :detect_layout
before_filter :configure_permitted_parameters, if: :devise_controller?
def get_categories
@categories = Category.all
end
def detect_layout
if devise_controller?
"devise"
else
"application"
end
end
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up).push(:name)
devise_parameter_sanitizer.for(:account_update).push(:name)
end
end
......@@ -2,6 +2,10 @@ class CategoriesController < ApplicationController
before_filter :get_categories
def show
params[:per_page] ||= 5
params[:page] ||= 1
@category = Category.find(params[:id])
@products = @category.products.page(params[:page]).per(params[:per_page])
end
end
\ No newline at end of file
......@@ -3,4 +3,24 @@ class ProductsController < ApplicationController
def show
@product = Product.find(params[:id])
end
def new
@product = Product.new
end
def create
@product = Product.new(new_product_params)
if @product.save
redirect_to category_path(@product.category)
else
render 'new'
end
end
private
def new_product_params
params[:product][:release_date] = DatetimeService.strptime(params[:product][:release_date], "%m/%d/%Y %H:%M %p")
params[:product][:public_date] = DatetimeService.strptime(params[:product][:public_date], "%m/%d/%Y %H:%M %p")
params.require(:product).permit(:stock, :pid, :title, :author, :publisher, :studio, :price, :currency, :category_id, :image, :release_date, :public_date, :recommend)
end
end
\ No newline at end of file
......@@ -2,4 +2,9 @@ module ApplicationHelper
def currency_number(price=0, currency="usd")
"#{currency}#{price}"
end
def categories_options
Category.pluck(:name, :id)
end
end
......@@ -2,9 +2,11 @@ class Product < ActiveRecord::Base
belongs_to :category
belongs_to :user
dragonfly_accessor :image
dragonfly_accessor :image do
# default 'public/images/product_default.jpg'
end
validates :pid, :title, :price, :category_id, presence: true
validates :pid, :title, :price, :category_id, :image, :stock, :release_date, :public_date, presence: true
validates :pid, uniqueness: true
scope :recommend, -> {where(recommend: true)}
......
......@@ -5,4 +5,6 @@ class User < ActiveRecord::Base
:recoverable, :rememberable, :trackable, :validatable
has_many :products
validates :name, presence: true
end
......@@ -6,4 +6,5 @@ class DatetimeService
DateTime.now
end
end
end
\ No newline at end of file
#categories
- if @products.present?
.products
- @products.each do |product|
= render "products/item", product: product
.text-center
= paginate @products
\ No newline at end of file
......@@ -12,13 +12,13 @@ nav.navbar.navbar-inverse
= image_tag "logo.png"
'Venshop
.collapse.navbar-collapse
-#ul.nav.navbar-nav
-# = render 'layouts/navigation_links'
ul.nav.navbar-nav
= render 'layouts/navigation_links'
ul.nav.navbar-nav.navbar-right
- if current_user.present?
li
a= current_user.email
= link_to (current_user.name || current_user.email), edit_user_registration_path
li
= link_to "Logout", destroy_user_session_path, method: 'delete'
- else
......
li
= link_to "Link 1", "#"
li
= link_to "Link 2", "#"
- if current_user.present?
li
= link_to "New product", new_product_path
......@@ -21,9 +21,9 @@ html
= render 'shared/search_bar'
= render_breadcrumbs :separator => ' / '
.row.mar-top-20
.col-sm-4
.col-sm-3
= render 'shared/categories'
.col-sm-8
.col-sm-9
= yield
.clearfix
= render 'layouts/footer'
doctype html
html
head
meta[name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"]
title
= @title || "Venshop"
= favicon_link_tag 'favicon.ico'
= favicon_link_tag 'apple-touch-icon.png', rel: 'apple-touch-icon', type: 'image/png'
= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true
= javascript_include_tag "application", "data-turbolinks-track" => true
= csrf_meta_tags
body
#wrap
header
= render 'layouts/navigation'
.container
.row.mar-top-20
.col-sm-12
= yield
.clearfix
= render 'layouts/footer'
.product-form
= form_for @product, html:{class: "form-horizontal"} do |f|
- if @product.errors.any?
#error_explanation
h3= "#{pluralize(@product.errors.count, "error")} prohibited this product from being saved:"
ul
- @product.errors.full_messages.each do |msg|
li= msg
= f.hidden_field :currency, value: '£'
.form-group
= f.label :pid, class:"control-label col-sm-3"
.col-sm-9
= f.text_field :pid, class: "form-control"
.form-group
= f.label :title, class:"control-label col-sm-3"
.col-sm-9
= f.text_field :title, class: "form-control"
.form-group
= f.label :stock, class:"control-label col-sm-3"
.col-sm-9
= f.number_field :stock, class: "form-control"
.form-group
= f.label :author, class:"control-label col-sm-3"
.col-sm-9
= f.text_field :author, class: "form-control"
.form-group
= f.label :publisher, class:"control-label col-sm-3"
.col-sm-9
= f.text_field :publisher, class: "form-control"
.form-group
= f.label :studio, class:"control-label col-sm-3"
.col-sm-9
= f.text_field :studio, class: "form-control"
.form-group
= f.label :price, class:"control-label col-sm-3"
.col-sm-9
= f.number_field :price, class: "form-control"
.form-group
= f.label :category_id, class:"control-label col-sm-3"
.col-sm-9
= f.select :category_id, options_for_select(categories_options, @product.category_id), {}, class: "form-control"
.form-group
= f.label "Image", class:"control-label col-sm-3", for: "product_image"
.col-sm-9
- if !@product.new_record? && @product.image.present?
= image_tag @product.image.thumb('200x200#')
= f.file_field :image
.form-group
= f.label :release_date, class:"control-label col-sm-3"
.col-sm-9
.input-group.date.datetimepicker
input(type='text' class="form-control" name="product[release_date]")
span.input-group-addon
span.glyphicon.glyphicon-calendar
.form-group
= f.label :public_date, class:"control-label col-sm-3"
.col-sm-9
.input-group.date.datetimepicker
input(type='text' class="form-control" name="product[public_date]")
span.input-group-addon
span.glyphicon.glyphicon-calendar
.form-group
= f.label :recommend, class:"control-label col-sm-3"
.col-sm-9
.checkbox
= f.check_box :recommend, class:'mar-l-0'
.form-group
.col-sm-offset-3.col-sm-9
= f.submit "Save", class: "btn btn-primary"
.row.mar-bot-20
.col-lg-7
.col-lg-9
.wrap-img.mar-r-10
= image_tag product.image.thumb('51x32#').url
.title= link_to product.title, product_path(product)
.col-lg-5
.col-lg-3
= "Price: #{currency_number(product.currency, product.price)}"
h1 New Product
= render "form"
\ No newline at end of file
ul.list-group
- @categories.each do |cate|
= link_to cate.name, category_path(cate), class: 'list-group-item'
\ No newline at end of file
= link_to cate.name, category_path(cate), class: "list-group-item #{@category.try(:id)==cate.id ? 'active' : ''}"
\ No newline at end of file
#search-bar
= form_tag search_path, class: "form-horizontal", method: "GET" do |f|
.row
.col-sm-9
.col-sm-10
= text_field_tag :keyword, params[:keyword], placeholder: "Keyword", class: "form-control"
.col-sm-3
.col-sm-2
= submit_tag "Search", class: "btn btn-primary"
......@@ -4,6 +4,10 @@ h2
= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f|
= devise_error_messages!
.field
= f.label :name
br
= f.text_field :name, autofocus: true
.field
= f.label :email
br
= f.email_field :email, autofocus: true
......
......@@ -3,9 +3,13 @@ h2
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
= devise_error_messages!
.field
= f.label :name
br
= f.text_field :name, autofocus: true
.field
= f.label :email
br
= f.email_field :email, autofocus: true
= f.email_field :email
.field
= f.label :password
- if @validatable
......
......@@ -205,7 +205,7 @@ Devise.setup do |config|
# Turn scoped views on. Before rendering "sessions/new", it will first check for
# "users/sessions/new". It's turned off by default because it's slower if you
# are using only default views.
# config.scoped_views = false
config.scoped_views = true
# Configure the default scope given to Warden. By default it's the first
# devise role declared in your routes (usually :user).
......
......@@ -8,7 +8,7 @@ Rails.application.routes.draw do
get '/search' => "home#search", as: :search
resources :categories, :only => [:show]
resources :products, :only => [:show]
resources :products, :only => [:new, :create, :show]
# Example of regular route:
# get 'products/:id' => 'catalog#view'
......
class AddNameToUsers < ActiveRecord::Migration
def change
add_column :users, :name, :string
end
end
class AddStockToProducts < ActiveRecord::Migration
def change
add_column :products, :stock, :integer, default: 10
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150715033939) do
ActiveRecord::Schema.define(version: 20150715091023) do
create_table "categories", force: :cascade do |t|
t.string "name", limit: 255
......@@ -31,6 +31,7 @@ ActiveRecord::Schema.define(version: 20150715033939) do
t.datetime "release_date"
t.datetime "public_date"
t.boolean "recommend", limit: 1, default: false
t.integer "stock", limit: 4, default: 10
end
create_table "users", force: :cascade do |t|
......@@ -46,6 +47,7 @@ ActiveRecord::Schema.define(version: 20150715033939) do
t.string "last_sign_in_ip", limit: 255
t.datetime "created_at"
t.datetime "updated_at"
t.string "name", limit: 255
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment