diff --git a/.gitignore b/.gitignore
index 6a502e9..f7a9080 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,4 @@
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
+/public/uploads/*
diff --git a/Gemfile b/Gemfile
index fba3b4e..d0da616 100644
--- a/Gemfile
+++ b/Gemfile
@@ -26,6 +26,18 @@ gem 'sdoc', '~> 0.4.0', group: :doc
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring', group: :development
+
+gem 'devise'
+gem 'bootstrap-sass'
+
+
+gem 'carrierwave'
+gem "mini_magick"
+
+
+gem 'simple_form'
+
+
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
diff --git a/Gemfile.lock b/Gemfile.lock
index 53538d9..c4b6dbb 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -28,7 +28,15 @@ GEM
thread_safe (~> 0.1)
tzinfo (~> 1.1)
arel (5.0.1.20140414130214)
+ bcrypt (3.1.7)
+ bootstrap-sass (3.2.0.0)
+ sass (~> 3.2)
builder (3.2.2)
+ carrierwave (0.10.0)
+ activemodel (>= 3.2.0)
+ activesupport (>= 3.2.0)
+ json (>= 1.7)
+ mime-types (>= 1.16)
coffee-rails (4.0.1)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.0)
@@ -36,6 +44,12 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.7.0)
+ devise (3.2.4)
+ bcrypt (~> 3.0)
+ orm_adapter (~> 0.1)
+ railties (>= 3.2.6, < 5)
+ thread_safe (~> 0.1)
+ warden (~> 1.2.3)
erubis (2.7.0)
execjs (2.2.0)
hike (1.2.3)
@@ -51,8 +65,11 @@ GEM
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.25.1)
+ mini_magick (3.7.0)
+ subexec (~> 0.2.1)
minitest (5.3.4)
multi_json (1.10.1)
+ orm_adapter (0.5.0)
polyglot (0.3.5)
rack (1.5.2)
rack-test (0.6.2)
@@ -84,6 +101,9 @@ GEM
sdoc (0.4.0)
json (~> 1.8)
rdoc (~> 4.0, < 5.0)
+ simple_form (3.0.2)
+ actionpack (~> 4.0)
+ activemodel (~> 4.0)
spring (1.1.3)
sprockets (2.11.0)
hike (~> 1.2)
@@ -95,6 +115,7 @@ GEM
activesupport (>= 3.0)
sprockets (~> 2.8)
sqlite3 (1.3.9)
+ subexec (0.2.3)
thor (0.19.1)
thread_safe (0.3.4)
tilt (1.4.1)
@@ -108,17 +129,24 @@ GEM
uglifier (2.5.0)
execjs (>= 0.3.0)
json (>= 1.8.0)
+ warden (1.2.3)
+ rack (>= 1.0)
PLATFORMS
ruby
DEPENDENCIES
+ bootstrap-sass
+ carrierwave
coffee-rails (~> 4.0.0)
+ devise
jbuilder (~> 2.0)
jquery-rails
+ mini_magick
rails (= 4.1.0)
sass-rails (~> 4.0.3)
sdoc (~> 0.4.0)
+ simple_form
spring
sqlite3
turbolinks
diff --git a/app/assets/javascripts/admin/products.js.coffee b/app/assets/javascripts/admin/products.js.coffee
new file mode 100644
index 0000000..24f83d1
--- /dev/null
+++ b/app/assets/javascripts/admin/products.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index d6925fa..6ef63a6 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -14,3 +14,5 @@
//= require jquery_ujs
//= require turbolinks
//= require_tree .
+//= require bootstrap
+
diff --git a/app/assets/stylesheets/admin/products.css.scss b/app/assets/stylesheets/admin/products.css.scss
new file mode 100644
index 0000000..da8969d
--- /dev/null
+++ b/app/assets/stylesheets/admin/products.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the admin::products controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index a443db3..bcdb41c 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -12,4 +12,5 @@
*
*= require_tree .
*= require_self
+ *= require bootstrap
*/
diff --git a/app/controllers/admin/products_controller.rb b/app/controllers/admin/products_controller.rb
new file mode 100644
index 0000000..4308066
--- /dev/null
+++ b/app/controllers/admin/products_controller.rb
@@ -0,0 +1,55 @@
+class Admin::ProductsController < ApplicationController
+
+ before_action :authenticate_user!
+ before_action :admin_required
+
+
+ def index
+ @products = Product.all
+ end
+
+ def new
+ @product = Product.new
+ end
+
+ def show
+ @product = Product.find(params[:id])
+ end
+
+ def edit
+ @product = Product.find(params[:id])
+ end
+
+ def update
+ @product = Product.find(params[:id])
+ if @product.update(product_params)
+ redirect_to admin_products_path
+ else
+ render :edit
+ end
+ end
+
+
+ def destroy
+ @product = Product.find(params[:id])
+ @product.destroy!
+ redirect_to admin_products_path
+ end
+
+ def create
+ @product = Product.new(product_params)
+ if @product.save
+ redirect_to admin_products_path
+ else
+ render :new
+ end
+ end
+
+ private
+
+ def product_params
+ params.require(:product).permit(:title,:description,:quantity, :price, :image)
+ end
+
+
+end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index d83690e..7c1f1cb 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -2,4 +2,9 @@ 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
+
+ def admin_required
+ current_user.is_admin?
+ end
+
end
diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb
new file mode 100644
index 0000000..eda8b4e
--- /dev/null
+++ b/app/controllers/products_controller.rb
@@ -0,0 +1,13 @@
+class ProductsController < ApplicationController
+
+
+ def index
+ @products = Product.all
+ end
+
+ def show
+ @product = Product.find(params[:id])
+ end
+
+
+end
diff --git a/app/helpers/admin/products_helper.rb b/app/helpers/admin/products_helper.rb
new file mode 100644
index 0000000..977a242
--- /dev/null
+++ b/app/helpers/admin/products_helper.rb
@@ -0,0 +1,2 @@
+module Admin::ProductsHelper
+end
diff --git a/app/models/product.rb b/app/models/product.rb
new file mode 100644
index 0000000..9afd99e
--- /dev/null
+++ b/app/models/product.rb
@@ -0,0 +1,5 @@
+class Product < ActiveRecord::Base
+ mount_uploader :image , ImageUploader
+
+
+end
diff --git a/app/models/user.rb b/app/models/user.rb
new file mode 100644
index 0000000..83dc315
--- /dev/null
+++ b/app/models/user.rb
@@ -0,0 +1,12 @@
+class User < ActiveRecord::Base
+ # Include default devise modules. Others available are:
+ # :confirmable, :lockable, :timeoutable and :omniauthable
+ devise :database_authenticatable, :registerable,
+ :recoverable, :rememberable, :trackable, :validatable
+
+ def is_admin?
+ is_admin
+ end
+
+
+end
diff --git a/app/uploaders/image_uploader.rb b/app/uploaders/image_uploader.rb
new file mode 100644
index 0000000..4e4691d
--- /dev/null
+++ b/app/uploaders/image_uploader.rb
@@ -0,0 +1,67 @@
+# encoding: utf-8
+
+class ImageUploader < CarrierWave::Uploader::Base
+
+ # Include RMagick or MiniMagick support:
+ # include CarrierWave::RMagick
+ include CarrierWave::MiniMagick
+
+ # Choose what kind of storage to use for this uploader:
+ storage :file
+ # storage :fog
+
+ # Override the directory where uploaded files will be stored.
+ # This is a sensible default for uploaders that are meant to be mounted:
+ def store_dir
+ "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
+ end
+
+
+
+
+ # Provide a default URL as a default if there hasn't been a file uploaded:
+ # def default_url
+ # # For Rails 3.1+ asset pipeline compatibility:
+ # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
+ #
+ # "/images/fallback/" + [version_name, "default.png"].compact.join('_')
+ # end
+
+ # Process files as they are uploaded:
+ # process :scale => [200, 300]
+ #
+ # def scale(width, height)
+ # # do something
+ # end
+
+ # Create different versions of your uploaded files:
+ # version :thumb do
+ # process :resize_to_fit => [150, 150]
+ # end
+
+ version :md do
+ process resize_to_fit: [700, 500]
+ end
+
+ version :sm, from_version: :md do
+ process resize_to_fit: [300, 300]
+ end
+
+ version :square, from_version: :sm do
+ process resize_to_fill: [220, 220]
+ end
+
+ # Add a white list of extensions which are allowed to be uploaded.
+ # For images you might use something like this:
+ def extension_white_list
+ %w(jpg jpeg gif png)
+ end
+
+ # Override the filename of the uploaded files:
+ # Avoid using model.id or version_name here, see uploader/store.rb for details.
+ def filename
+ "image.jpg" if original_filename
+ end
+
+
+end
diff --git a/app/views/admin/products/edit.html.erb b/app/views/admin/products/edit.html.erb
new file mode 100644
index 0000000..a24c343
--- /dev/null
+++ b/app/views/admin/products/edit.html.erb
@@ -0,0 +1,9 @@
+<%= simple_form_for [:admin, @product] do |form| %>
+ <%= form.input :title,required: true,input_html: { class: 'form-control' },label:'標題' %>
+ <%= form.input :description,required: true,label:'敘述',input_html: { class: 'form-control' } %>
+ <%= form.input :quantity,required: true,input_html: { class: 'form-control',size: 20 },label:'數量' %>
+ <%= form.input :price,required: true,input_html: { class: 'form-control' },label:'價格' %>
+ <%= form.input :image,label:'上傳'%>
+
+ <%= form.submit "更新", :disable_with=> 'Submiting....', class: 'btn btn-info'%>
+<%end%>
\ No newline at end of file
diff --git a/app/views/admin/products/index.html.erb b/app/views/admin/products/index.html.erb
new file mode 100644
index 0000000..944fa2d
--- /dev/null
+++ b/app/views/admin/products/index.html.erb
@@ -0,0 +1,21 @@
+<%= link_to "新增產品",new_admin_product_path, class: "btn btn-warning" , style: 'margin-left: 14px;' %>
+
+<%@products.each do |product| %>
+
<%= product.description %>
+數量: <%= product.quantity %>
+價格: <%= product.price %>
+ <%= link_to "修改",edit_admin_product_path(product),:class=>'btn btn-primary' %> + <%= link_to "刪除",admin_product_path(product),:method=> :delete,:class=>'btn btn-danger' ,:confirm=> 'are you Sure!' %> +Welcome <%= @email %>!
+ +You can confirm your account email through the link below:
+ +<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>
diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb new file mode 100644 index 0000000..f667dc1 --- /dev/null +++ b/app/views/devise/mailer/reset_password_instructions.html.erb @@ -0,0 +1,8 @@ +Hello <%= @resource.email %>!
+ +Someone has requested a link to change your password. You can do this through the link below.
+ +<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>
+ +If you didn't request this, please ignore this email.
+Your password won't change until you access the link above and create a new one.
diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb new file mode 100644 index 0000000..41e148b --- /dev/null +++ b/app/views/devise/mailer/unlock_instructions.html.erb @@ -0,0 +1,7 @@ +Hello <%= @resource.email %>!
+ +Your account has been locked due to an excessive number of unsuccessful sign in attempts.
+ +Click the link below to unlock your account:
+ +<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>
diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb new file mode 100644 index 0000000..5535098 --- /dev/null +++ b/app/views/devise/passwords/edit.html.erb @@ -0,0 +1,16 @@ +Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>
+ +<%= link_to "Back", :back %> diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb new file mode 100644 index 0000000..234de91 --- /dev/null +++ b/app/views/devise/registrations/new.html.erb @@ -0,0 +1,18 @@ +